Merge remote-tracking branch 'upstream/main'

This commit is contained in:
轻风2016 2024-09-01 09:50:56 +08:00
commit 48d785e6cb
30 changed files with 1028 additions and 115 deletions

View File

@ -65,4 +65,9 @@ public class ClaimConst
/// 登录模式PC、APP
/// </summary>
public const string LoginMode = "LoginMode";
/// <summary>
/// 最新密码修改时间
/// </summary>
public const string LastChangePasswordTime = "LastChangePasswordTime";
}

View File

@ -81,6 +81,11 @@ public class ConfigConst
/// </summary>
public const string SysRegionSyncLevel = "sys_region_sync_level";
/// <summary>
/// 开启强制修改密码
/// </summary>
public const string SysForceChangePassword = "sys_force_change_password";
/// <summary>
/// Default 分组
/// </summary>

View File

@ -312,4 +312,35 @@ public partial class SysUser : EntityTenant
[SugarColumn(ColumnDescription = "电子签名", Length = 512)]
[MaxLength(512)]
public string? Signature { get; set; }
/// <summary>
/// 最新密码修改时间
/// </summary>
[SugarColumn(ColumnDescription = "最新密码修改时间")]
public DateTime? LastChangePasswordTime { get; set; }
/// <summary>
/// 验证超级管理员类型,若账号类型为超级管理员则报错
/// </summary>
/// <param name="errorMsg">自定义错误消息</param>
public void ValidateIsSuperAdminAccountType(ErrorCodeEnum? errorMsg = ErrorCodeEnum.D1014)
{
if (AccountType == AccountTypeEnum.SuperAdmin)
{
throw Oops.Oh(errorMsg);
}
}
/// <summary>
/// 验证用户Id是否相同若用户Id相同则报错
/// </summary>
/// <param name="userId">用户Id</param>
/// <param name="errorMsg">自定义错误消息</param>
public void ValidateIsUserId(long userId, ErrorCodeEnum? errorMsg = ErrorCodeEnum.D1001)
{
if (Id == userId)
{
throw Oops.Oh(errorMsg);
}
}
}

View File

@ -4,6 +4,8 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using AngleSharp.Common;
namespace Admin.NET.Core;
/// <summary>
@ -14,87 +16,89 @@ namespace Admin.NET.Core;
public class EnumToDictJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IJsonSerializerProvider _jsonSerializer;
private const int OrderOffset = 10;
private const string DefaultTagType = "info";
public EnumToDictJob(IServiceScopeFactory scopeFactory, IJsonSerializerProvider jsonSerializer)
public EnumToDictJob(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
_jsonSerializer = jsonSerializer;
}
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
using var serviceScope = _scopeFactory.CreateScope();
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
// 获取数据库连接
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
// 获取枚举类型列表
var enumTypeList = sysEnumService.GetEnumTypeList();
var enumCodeList = enumTypeList.Select(u => u.TypeName);
var sysDictTypeCodeList = await db.Queryable<SysDictType>().Where(u => enumCodeList.Contains(u.Code)).Select(u => u.Code).ToListAsync(stoppingToken);
// 查询数据库中已存在的枚举类型代码
var sysDictTypeList = await db.Queryable<SysDictType>()
.Includes(d => d.Children)
.Where(d => enumCodeList.Contains(d.Code))
.ToListAsync(stoppingToken);
// 更新的枚举转换字典
var uEnumType = enumTypeList.Where(u => sysDictTypeCodeList.Contains(u.TypeName)).ToList();
var waitUpdateSysDictType = await db.Queryable<SysDictType>().Where(u => uEnumType.Any(a => a.TypeName == u.Code)).ToListAsync(stoppingToken);
var waitUpdateSysDictTypeDict = waitUpdateSysDictType.ToDictionary(u => u.Code, u => u);
var waitUpdateSysDictData = await db.Queryable<SysDictData>().Where(u => uEnumType.Any(a => a.TypeName == u.DictType.Code)).ToListAsync(stoppingToken);
var uSysDictType = new List<SysDictType>();
var uSysDictData = new List<SysDictData>();
if (uEnumType.Count > 0)
{
uEnumType.ForEach(e =>
{
if (waitUpdateSysDictTypeDict.TryGetValue(e.TypeName, out SysDictType value))
{
var uDictType = value;
uDictType.Name = e.TypeDescribe;
uDictType.Remark = e.TypeRemark;
var uDictData = waitUpdateSysDictData.Where(u => u.DictTypeId == uDictType.Id).ToList();
if (uDictData.Count > 0)
{
uDictData.ForEach(dictData =>
{
var enumData = e.EnumEntities.Where(u => dictData.Code == u.Name).FirstOrDefault();
if (enumData != null)
{
dictData.Value = enumData.Value.ToString();
dictData.Code = enumData.Name;
dictData.OrderNo = enumData.Value + 10;
dictData.Name = enumData.Describe;
dictData.TagType = enumData.Theme != "" ? enumData.Theme : dictData.TagType != "" ? dictData.TagType : "info";
uSysDictData.Add(dictData);
}
});
}
if (!uSysDictType.Any(u => u.Id == uDictType.Id))
uSysDictType.Add(uDictType);
}
});
try
{
db.BeginTran();
if (uSysDictType.Count > 0)
await db.Updateable(uSysDictType).ExecuteCommandAsync(stoppingToken);
if (uSysDictData.Count > 0)
await db.Updateable(uSysDictData).ExecuteCommandAsync(stoppingToken);
db.CommitTran();
}
catch (Exception error)
{
db.RollbackTran();
Log.Error($"{context.Trigger.Description}更新枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
throw new Exception($"{context.Trigger.Description}更新枚举转换字典入库错误");
}
}
var updatedEnumCodes = sysDictTypeList.Select(u => u.Code);
var updatedEnumType = enumTypeList.Where(u => updatedEnumCodes.Contains(u.TypeName)).ToList();
var sysDictTypeDict = sysDictTypeList.ToDictionary(u => u.Code, u => u);
var (updatedDictTypes, updatedDictDatas) = GetUpdatedDicts(updatedEnumType, sysDictTypeDict);
// 新增的枚举转换字典
var iEnumType = enumTypeList.Where(u => !sysDictTypeCodeList.Contains(u.TypeName)).ToList();
if (iEnumType.Count > 0)
var newEnumType = enumTypeList.Where(u => !updatedEnumCodes.Contains(u.TypeName)).ToList();
var (newDictTypes, newDictDatas) = GetNewSysDicts(newEnumType);
// 执行数据库操作
try
{
db.BeginTran();
if (updatedDictTypes.Count > 0)
await db.Updateable(updatedDictTypes).ExecuteCommandAsync(stoppingToken);
if (updatedDictDatas.Count > 0)
await db.Updateable(updatedDictDatas).ExecuteCommandAsync(stoppingToken);
if (newDictTypes.Count > 0)
await db.Insertable(newDictTypes).ExecuteCommandAsync(stoppingToken);
if (newDictDatas.Count > 0)
await db.Insertable(newDictDatas).ExecuteCommandAsync(stoppingToken);
db.CommitTran();
}
catch (Exception error)
{
db.RollbackTran();
Log.Error($"系统枚举转换字典操作错误:{error.Message}\n堆栈跟踪{error.StackTrace}", error);
throw;
}
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
Console.ForegroundColor = originColor;
}
/// <summary>
/// 获取需要新增的字典列表
/// </summary>
/// <param name="addEnumType"></param>
/// <returns>
/// 一个元组,包含以下元素:
/// <list type="table">
/// <item><term>SysDictTypes</term><description>字典类型列表</description></item>
/// <item><term>SysDictDatas</term><description>字典数据列表</description></item>
/// </list>
/// </returns>
private (List<SysDictType>, List<SysDictData>) GetNewSysDicts(List<EnumTypeOutput> addEnumType)
{
var newDictType = new List<SysDictType>();
var newDictData = new List<SysDictData>();
if (addEnumType.Count > 0)
{
// 新增字典类型
var iDictType = iEnumType.Select(u => new SysDictType
newDictType = addEnumType.Select(u => new SysDictType
{
Id = YitIdHelper.NextId(),
Code = u.TypeName,
@ -102,49 +106,70 @@ public class EnumToDictJob : IJob
Remark = u.TypeRemark,
Status = StatusEnum.Enable
}).ToList();
// 新增字典数据
var dictData = iEnumType.Join(iDictType, t1 => t1.TypeName, t2 => t2.Code, (t1, t2) => new
newDictData = addEnumType.Join(newDictType, t1 => t1.TypeName, t2 => t2.Code, (t1, t2) => new
{
data = t1.EnumEntities.Select(u => new SysDictData
Data = t1.EnumEntities.Select(u => new SysDictData
{
Id = YitIdHelper.NextId(), // 性能优化使用BulkCopyAsync必须手动获取Id
Id = YitIdHelper.NextId(),
DictTypeId = t2.Id,
Name = u.Describe,
Value = u.Value.ToString(),
Code = u.Name,
Remark = t2.Remark,
OrderNo = u.Value + 10,
TagType = u.Theme != "" ? u.Theme : "info"
OrderNo = u.Value + OrderOffset,
TagType = u.Theme != "" ? u.Theme : DefaultTagType,
}).ToList()
}).ToList();
var iDictData = new List<SysDictData>();
dictData.ForEach(item =>
{
iDictData.AddRange(item.data);
});
try
{
db.BeginTran();
}).SelectMany(x => x.Data).ToList();
}
return (newDictType, newDictData);
}
if (iDictType.Count > 0)
await db.Insertable(iDictType).ExecuteCommandAsync(stoppingToken);
if (iDictData.Count > 0)
await db.Insertable(iDictData).ExecuteCommandAsync(stoppingToken);
db.CommitTran();
}
catch (Exception error)
/// <summary>
/// 获取需要更新的字典列表
/// </summary>
/// <param name="updatedEnumType"></param>
/// <param name="sysDictTypeDict"></param>
/// <returns>
/// 一个元组,包含以下元素:
/// <list type="table">
/// <item><term>SysDictTypes</term><description>字典类型列表</description>
/// </item>
/// <item><term>SysDictDatas</term><description>字典数据列表</description>
/// </item>
/// </list>
/// </returns>
private (List<SysDictType>, List<SysDictData>) GetUpdatedDicts(List<EnumTypeOutput> updatedEnumType, Dictionary<string, SysDictType> sysDictTypeDict)
{
var updatedSysDictTypes = new List<SysDictType>();
var updatedSysDictData = new List<SysDictData>();
foreach (var e in updatedEnumType)
{
if (sysDictTypeDict.TryGetValue(e.TypeName, out var value))
{
db.RollbackTran();
Log.Error($"{context.Trigger.Description}新增枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
throw new Exception($"{context.Trigger.Description}新增枚举转换字典入库错误");
var updatedDictType = value;
updatedDictType.Name = e.TypeDescribe;
updatedDictType.Remark = e.TypeRemark;
updatedSysDictTypes.Add(updatedDictType);
var updatedDictData = updatedDictType.Children.Where(u => u.DictTypeId == updatedDictType.Id).ToList();
// 遍历需要更新的字典数据
foreach (var dictData in updatedDictData)
{
var enumData = e.EnumEntities.Where(u => dictData.Code == u.Name).FirstOrDefault();
if (enumData != null)
{
dictData.Value = enumData.Value.ToString();
dictData.OrderNo = enumData.Value + OrderOffset;
dictData.Name = enumData.Describe;
dictData.TagType = enumData.Theme != "" ? enumData.Theme : dictData.TagType != "" ? dictData.TagType : DefaultTagType;
updatedSysDictData.Add(dictData);
}
}
}
}
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
Console.ForegroundColor = originColor;
return (updatedSysDictTypes, updatedSysDictData);
}
}

View File

@ -33,6 +33,8 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
new SysConfig{ Id=1300000000211, Name="域登录验证", Code=ConfigConst.SysDomainLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000221, Name="数据校验日志", Code=ConfigConst.SysValidationLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否数据校验日志", OrderNo=130, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000231, Name="行政区域同步层级", Code=ConfigConst.SysRegionSyncLevel, Value="3", SysFlag=YesNoEnum.Y, Remark="行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级", OrderNo=140, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000241, Name="开启强制修改密码", Code=ConfigConst.SysForceChangePassword, Value="True", SysFlag=YesNoEnum.Y, Remark="开启强制修改密码", OrderNo=150, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000301, Name="系统主标题", Code=ConfigConst.SysWebTitle, Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统主标题", OrderNo=300, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000311, Name="系统副标题", Code=ConfigConst.SysWebViceTitle, Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统副标题", OrderNo=310, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000321, Name="系统描述", Code=ConfigConst.SysWebViceDesc, Value="站在巨人肩膀上的 .NET 通用权限开发框架", SysFlag=YesNoEnum.Y, Remark="系统描述", OrderNo=320, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },

View File

@ -230,6 +230,7 @@ public class SysAuthService : IDynamicApiController, ITransient
{ ClaimConst.OrgName, user.SysOrg?.Name },
{ ClaimConst.OrgType, user.SysOrg?.Type },
{ ClaimConst.LoginMode, loginMode },
{ ClaimConst.LastChangePasswordTime, user.LastChangePasswordTime },
}, tokenExpire);
// 生成刷新Token令牌

View File

@ -165,14 +165,9 @@ public class SysUserService : IDynamicApiController, ITransient
[DisplayName("删除用户")]
public virtual async Task DeleteUser(DeleteUserInput input)
{
var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id);
if (user == null)
return;
if (user.AccountType == AccountTypeEnum.SuperAdmin)
throw Oops.Oh(ErrorCodeEnum.D1014);
if (user.Id == _userManager.UserId)
throw Oops.Oh(ErrorCodeEnum.D1001);
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
user.ValidateIsSuperAdminAccountType();
user.ValidateIsUserId(_userManager.UserId);
// 若账号为租户默认账号则禁止删除
var isTenantUser = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().IsAnyAsync(u => u.UserId == input.Id);
@ -206,7 +201,7 @@ public class SysUserService : IDynamicApiController, ITransient
[DisplayName("查看用户基本信息")]
public virtual async Task<SysUser> GetBaseInfo()
{
return await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
return await _sysUserRep.GetByIdAsync(_userManager.UserId);
}
/// <summary>
@ -226,15 +221,15 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[DisplayName("设置用户状态")]
public virtual async Task<int> SetStatus(UserInput input)
{
if (_userManager.UserId == input.Id)
throw Oops.Oh(ErrorCodeEnum.D1026);
var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
if (user.AccountType == AccountTypeEnum.SuperAdmin)
throw Oops.Oh(ErrorCodeEnum.D1015);
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
user.ValidateIsSuperAdminAccountType(ErrorCodeEnum.D1015);
if (!Enum.IsDefined(typeof(StatusEnum), input.Status))
throw Oops.Oh(ErrorCodeEnum.D3005);
@ -285,7 +280,7 @@ public class SysUserService : IDynamicApiController, ITransient
input.PasswordOld = CryptogramUtil.SM2Decrypt(input.PasswordOld);
input.PasswordNew = CryptogramUtil.SM2Decrypt(input.PasswordNew);
var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
var user = await _sysUserRep.GetByIdAsync(_userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString())
{
if (user.Password != MD5Encryption.Encrypt(input.PasswordOld))
@ -323,7 +318,7 @@ public class SysUserService : IDynamicApiController, ITransient
[DisplayName("重置用户密码")]
public virtual async Task<string> ResetPwd(ResetPwdUserInput input)
{
var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
user.Password = CryptogramUtil.Encrypt(password);
await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();
@ -343,7 +338,7 @@ public class SysUserService : IDynamicApiController, ITransient
[DisplayName("解除登录锁定")]
public virtual async Task UnlockLogin(UnlockLoginInput input)
{
var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
// 清空密码错误次数
var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}";

View File

@ -106,4 +106,44 @@ public class DeleteMessageTemplateInput
/// </summary>
[Required(ErrorMessage = "订阅模板Id不能为空")]
public string TemplateId { get; set; }
}
public class UploadAvatarInput
{
/// <summary>
/// 小程序用户身份标识
/// </summary>
[Required(ErrorMessage = "OpenId不能为空")]
public string OpenId { get; set; }
/// <summary>
/// 文件
/// </summary>
[Required]
public IFormFile File { get; set; }
/// <summary>
/// 文件类型
/// </summary>
public string FileType { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string Path { get; set; }
}
public class SetNickNameInput
{
/// <summary>
/// 小程序用户身份标识
/// </summary>
[Required(ErrorMessage = "OpenId不能为空")]
public string OpenId { get; set; }
/// <summary>
/// 昵称
/// </summary>
[Required(ErrorMessage = "昵称不能为空")]
public string NickName { get; set; }
}

View File

@ -15,14 +15,17 @@ public class SysWxOpenService : IDynamicApiController, ITransient
private readonly SqlSugarRepository<SysOAuthUser> _sysOAuthUserRep;
private readonly SysConfigService _sysConfigService;
private readonly WechatApiClient _wechatApiClient;
private readonly SysFileService _sysFileService;
public SysWxOpenService(SqlSugarRepository<SysOAuthUser> sysOAuthUserRep,
SysConfigService sysConfigService,
WechatApiClientFactory wechatApiClientFactory)
WechatApiClientFactory wechatApiClientFactory,
SysFileService sysFileService)
{
_sysOAuthUserRep = sysOAuthUserRep;
_sysConfigService = sysConfigService;
_wechatApiClient = wechatApiClientFactory.CreateWxOpenClient();
_sysFileService = sysFileService;
}
/// <summary>
@ -131,6 +134,57 @@ public class SysWxOpenService : IDynamicApiController, ITransient
};
}
/// <summary>
/// 上传小程序头像
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[AllowAnonymous]
[DisplayName("上传小程序头像")]
public async Task<SysFile> UploadAvatar([FromForm] UploadAvatarInput input)
{
var wxUser = await _sysOAuthUserRep.GetFirstAsync(u => u.OpenId == input.OpenId);
if (wxUser == null)
throw Oops.Oh("未找到用户上传失败");
var res = await _sysFileService.UploadFile(new FileUploadInput { File = input.File, FileType = input.FileType, Path = input.Path });
wxUser.Avatar = res.Url;
await _sysOAuthUserRep.AsUpdateable(wxUser).IgnoreColumns(true).ExecuteCommandAsync();
return res;
}
/// <summary>
/// 设置小程序用户昵称
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public async Task SetNickName(SetNickNameInput input)
{
var wxUser = await _sysOAuthUserRep.GetFirstAsync(u => u.OpenId == input.OpenId);
if (wxUser == null)
throw Oops.Oh("未找到用户信息设置失败");
wxUser.NickName = input.NickName;
await _sysOAuthUserRep.AsUpdateable(wxUser).IgnoreColumns(true).ExecuteCommandAsync();
return;
}
/// <summary>
/// 获取小程序用户信息
/// </summary>
/// <param name="openid"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task<dynamic> GetUserInfo(string openid)
{
var wxUser = await _sysOAuthUserRep.GetFirstAsync(u => u.OpenId == openid);
if (wxUser == null)
throw Oops.Oh("未找到用户信息获取失败");
return new { nickName = wxUser.NickName, avator = wxUser.Avatar };
}
/// <summary>
/// 验证签名 🔖
/// </summary>

View File

@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Admin.NET.Plugin.ReZero", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Admin.NET.Plugin.ApprovalFlow", "Plugins\Admin.NET.Plugin.ApprovalFlow\Admin.NET.Plugin.ApprovalFlow.csproj", "{4124E31B-EA94-4EE3-9EC6-A565F1420AEA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Admin.NET.Plugin.K3Cloud", "Plugins\Admin.NET.Plugin.K3Cloud\Admin.NET.Plugin.K3Cloud.csproj", "{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -64,6 +66,10 @@ Global
{4124E31B-EA94-4EE3-9EC6-A565F1420AEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4124E31B-EA94-4EE3-9EC6-A565F1420AEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4124E31B-EA94-4EE3-9EC6-A565F1420AEA}.Release|Any CPU.Build.0 = Release|Any CPU
{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -73,6 +79,7 @@ Global
{F6A002AD-CF7F-4771-8597-F12A50A93DAA} = {76F70D22-8D53-468E-A3B6-1704666A1D71}
{04AB2E76-DE8B-4EFD-9F48-F8D4C0993106} = {76F70D22-8D53-468E-A3B6-1704666A1D71}
{4124E31B-EA94-4EE3-9EC6-A565F1420AEA} = {76F70D22-8D53-468E-A3B6-1704666A1D71}
{9EB9C39E-E14F-443E-9AA3-EE417ABCBC1D} = {76F70D22-8D53-468E-A3B6-1704666A1D71}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5CD801D7-984A-4F5C-8FA2-211B7A5EA9F3}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<NoWarn>1701;1702;1591;8632</NoWarn>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<Copyright>Admin.NET</Copyright>
<Description>Admin.NET 通用权限开发平台</Description>
</PropertyGroup>
<ItemGroup>
<None Update="Configuration\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Admin.NET.Core\Admin.NET.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
{
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
"K3Cloud": {
// ERP
"Url": "http://127.0.0.1/k3cloud/",
// Id(ID)
"AcctID": "XXXXXXXXX",
// Id
"AppId": "XXXXXXXX",
//
"AppKey": "XXX",
//
"UserName": "XXX",
//
"UserPassword": "XXXX@2024",
//
"LanguageCode": "2052"
}
}

View File

@ -0,0 +1,8 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
global using Furion;
global using Furion.ConfigurableOptions;

View File

@ -0,0 +1,45 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.K3Cloud;
public sealed class K3CloudOptions : IConfigurableOptions
{
/// <summary>
/// ERP业务站点地址
/// </summary>
public string Url { get; set; }
/// <summary>
/// 帐套Id(数据中心ID)
/// </summary>
public string AcctID { get; set; }
/// <summary>
/// 应用Id
/// </summary>
public string AppId { get; set; }
/// <summary>
/// 应用密钥
/// </summary>
public string AppKey { get; set; }
/// <summary>
/// 用户名称
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 用户密码
/// </summary>
public string UserPassword { get; set; }
/// <summary>
/// 语言代码
/// </summary>
public string LanguageCode { get; set; }
}

View File

@ -0,0 +1,23 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.K3Cloud.Service;
/// <summary>
/// ERP基础入参
/// </summary>
public class K3CloudBaeInput<T>
{
/// <summary>
/// 表单Id
/// </summary>
public string formid { get; set; }
/// <summary>
/// 数据包
/// </summary>
public T data { get; set; }
}

View File

@ -0,0 +1,12 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.K3Cloud.Service;
public class K3CloudLoginInput
{
public List<string> parameters { get; set; }
}

View File

@ -0,0 +1,62 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.K3Cloud.Service;
public class K3CloudLoginOutput
{
public string Message { get; set; }
public string MessageCode { get; set; }
public ErpLoginResultType LoginResultType { get; set; }
}
public enum ErpLoginResultType
{
/// <summary>
/// 激活
/// </summary>
Activation = -7,
/// <summary>
/// 云通行证未绑定Cloud账号
/// </summary>
EntryCloudUnBind = -6,
/// <summary>
/// 需要表单处理
/// </summary>
DealWithForm = -5,
/// <summary>
/// 登录警告
/// </summary>
Wanning = -4,
/// <summary>
/// 密码验证不通过(强制的)
/// </summary>
PWInvalid_Required = -3,
/// <summary>
/// 密码验证不通过(可选的)
/// </summary>
PWInvalid_Optional = -2,
/// <summary>
/// 登录失败
/// </summary>
Failure = -1,
/// <summary>
/// 用户或密码错误
/// </summary>
PWError = 0,
/// <summary>
/// 登录成功
/// </summary>
Success = 1
}

View File

@ -0,0 +1,66 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Plugin.K3Cloud.Service;
public class K3CloudPushResultOutput
{
public ErpPushResultInfo Result { get; set; }
}
public class ErpPushResultInfo
{
/// <summary>
/// Id
/// </summary>
public object? Id { get; set; }
/// <summary>
/// 编码
/// </summary>
public string? Number { get; set; }
public ErpPushResultInfo_ResponseStatus ResponseStatus { get; set; }
}
public class ErpPushResultInfo_ResponseStatus
{
public bool IsSuccess { get; set; }
public int? ErrorCode { get; set; }
/// <summary>
/// 错误代码MsgCode说明
///0默认
///1上下文丢失 会话过期
///2没有权限
///3操作标识为空
///4异常
///5单据标识为空
///6数据库操作失败
///7许可错误
///8参数错误
///9指定字段/值不存在
///10未找到对应数据
///11验证失败
///12不可操作
///13网控冲突
///14调用限制
///15禁止管理员登录
/// </summary>
public int? MsgCode { get; set; }
/// <summary>
/// 如果失败,具体失败原因
/// </summary>
public List<ErpPushResultInfo_Errors> Errors { get; set; }
}
public class ErpPushResultInfo_Errors
{
public string FieldName { get; set; }
public string Message { get; set; }
public int DIndex { get; set; }
}

View File

@ -0,0 +1,52 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Furion.RemoteRequest;
namespace Admin.NET.Plugin.K3Cloud.Service;
/// <summary>
/// 金蝶云星空ERP接口
/// </summary>
[Client("K3Cloud")]
public interface IK3CloudApi : IHttpDispatchProxy
{
/// <summary>
/// 验证用户
/// </summary>
/// <param name="input"></param>
/// <param name="action"></param>
/// <returns></returns>
[Post("Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc")]
Task<K3CloudLoginOutput> ValidateUser([Body] K3CloudLoginInput input, [Interceptor(InterceptorTypes.Response)] Action<HttpClient, HttpResponseMessage> action = default);
/// <summary>
/// 保存表单
/// </summary>
/// <param name="input"></param>
/// <param name="action"></param>
/// <returns></returns>
[Post("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc")]
Task<K3CloudPushResultOutput> Save<T>([Body] K3CloudBaeInput<T> input, [Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);
/// <summary>
/// 提交表单
/// </summary>
/// <param name="input"></param>
/// <param name="action"></param>
/// <returns></returns>
[Post("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit.common.kdsvc")]
Task<K3CloudPushResultOutput> Submit<T>([Body] K3CloudBaeInput<T> input, [Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);
/// <summary>
/// 审核表单
/// </summary>
/// <param name="input"></param>
/// <param name="action"></param>
/// <returns></returns>
[Post("Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc")]
Task<K3CloudPushResultOutput> Audit<T>([Body] K3CloudBaeInput<T> input, [Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);
}

View File

@ -0,0 +1,31 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Admin.NET.Plugin.K3Cloud;
[AppStartup(100)]
public class Startup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddConfigurableOptions<K3CloudOptions>();
services.AddRemoteRequest(options =>
{
options.AddHttpClient("K3Cloud", u =>
{
u.BaseAddress = new Uri(App.GetConfig<K3CloudOptions>("K3Cloud", true).Url);
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2024.08.30",
"lastBuildTime": "2024.09.01",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -26,7 +26,7 @@
"@wangeditor/editor-for-vue": "^5.1.12",
"animate.css": "^4.1.1",
"async-validator": "^4.2.5",
"axios": "^1.7.5",
"axios": "^1.7.6",
"countup.js": "^2.8.0",
"cropperjs": "^1.6.2",
"echarts": "^5.5.1",
@ -70,7 +70,7 @@
"vue-router": "^4.4.3",
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.1.12",
"vxe-pc-ui": "^4.1.15",
"vxe-table": "^4.7.59",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.5",

View File

@ -20,10 +20,12 @@ import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } fr
import { AddSubscribeMessageTemplateInput } from '../models';
import { AdminResultGenerateQRImageOutput } from '../models';
import { AdminResultObject } from '../models';
import { AdminResultSysFile } from '../models';
import { AdminResultWxOpenIdOutput } from '../models';
import { AdminResultWxPhoneOutput } from '../models';
import { GenerateQRImageInput } from '../models';
import { SendSubscribeMessageInput } from '../models';
import { SetNickNameInput } from '../models';
import { WxOpenIdLoginInput } from '../models';
/**
* SysWxOpenApi - axios parameter creator
@ -218,6 +220,170 @@ export const SysWxOpenApiAxiosParamCreator = function (configuration?: Configura
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {SetNickNameInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysWxOpenSetNickNamePost: async (body?: SetNickNameInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysWxOpen/setNickName`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {string} [openId]
* @param {Blob} [file]
* @param {string} [fileType]
* @param {string} [path]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysWxOpenUploadAvatarPostForm: async (openId?: string, file?: Blob, fileType?: string, path?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysWxOpen/uploadAvatar`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
const localVarFormParams = new FormData();
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
if (openId !== undefined) {
localVarFormParams.append('OpenId', openId as any);
}
if (file !== undefined) {
localVarFormParams.append('File', file as any);
}
if (fileType !== undefined) {
localVarFormParams.append('FileType', fileType as any);
}
if (path !== undefined) {
localVarFormParams.append('Path', path as any);
}
localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = localVarFormParams;
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {string} openid
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysWxOpenUserInfoOpenidGet: async (openid: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'openid' is not null or undefined
if (openid === null || openid === undefined) {
throw new RequiredError('openid','Required parameter openid was null or undefined when calling apiSysWxOpenUserInfoOpenidGet.');
}
const localVarPath = `/api/sysWxOpen/userInfo/{openid}`
.replace(`{${"openid"}}`, encodeURIComponent(String(openid)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -506,6 +672,51 @@ export const SysWxOpenApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary
* @param {SetNickNameInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenSetNickNamePost(body?: SetNickNameInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await SysWxOpenApiAxiosParamCreator(configuration).apiSysWxOpenSetNickNamePost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary
* @param {string} [openId]
* @param {Blob} [file]
* @param {string} [fileType]
* @param {string} [path]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenUploadAvatarPostForm(openId?: string, file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysFile>>> {
const localVarAxiosArgs = await SysWxOpenApiAxiosParamCreator(configuration).apiSysWxOpenUploadAvatarPostForm(openId, file, fileType, path, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary
* @param {string} openid
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenUserInfoOpenidGet(openid: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
const localVarAxiosArgs = await SysWxOpenApiAxiosParamCreator(configuration).apiSysWxOpenUserInfoOpenidGet(openid, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -614,6 +825,39 @@ export const SysWxOpenApiFactory = function (configuration?: Configuration, base
async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
return SysWxOpenApiFp(configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {SetNickNameInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenSetNickNamePost(body?: SetNickNameInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysWxOpenApiFp(configuration).apiSysWxOpenSetNickNamePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {string} [openId]
* @param {Blob} [file]
* @param {string} [fileType]
* @param {string} [path]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenUploadAvatarPostForm(openId?: string, file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysFile>> {
return SysWxOpenApiFp(configuration).apiSysWxOpenUploadAvatarPostForm(openId, file, fileType, path, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {string} openid
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysWxOpenUserInfoOpenidGet(openid: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
return SysWxOpenApiFp(configuration).apiSysWxOpenUserInfoOpenidGet(openid, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -711,6 +955,42 @@ export class SysWxOpenApi extends BaseAPI {
public async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
return SysWxOpenApiFp(this.configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {SetNickNameInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysWxOpenApi
*/
public async apiSysWxOpenSetNickNamePost(body?: SetNickNameInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysWxOpenApiFp(this.configuration).apiSysWxOpenSetNickNamePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {string} [openId]
* @param {Blob} [file]
* @param {string} [fileType]
* @param {string} [path]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysWxOpenApi
*/
public async apiSysWxOpenUploadAvatarPostForm(openId?: string, file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysFile>> {
return SysWxOpenApiFp(this.configuration).apiSysWxOpenUploadAvatarPostForm(openId, file, fileType, path, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {string} openid
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysWxOpenApi
*/
public async apiSysWxOpenUserInfoOpenidGet(openid: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
return SysWxOpenApiFp(this.configuration).apiSysWxOpenUserInfoOpenidGet(openid, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖

View File

@ -399,6 +399,14 @@ export interface AddUserInput {
*/
signature?: string | null;
/**
*
*
* @type {Date}
* @memberof AddUserInput
*/
lastChangePasswordTime?: Date | null;
/**
*
*

View File

@ -301,6 +301,7 @@ export * from './search';
export * from './security-rule-set';
export * from './send-subscribe-message-input';
export * from './serialization-format';
export * from './set-nick-name-input';
export * from './signature-input';
export * from './sm-key-pair-output';
export * from './sms-verify-code-input';
@ -370,6 +371,7 @@ export * from './sys-schedule';
export * from './sys-user';
export * from './sys-user-ext-org';
export * from './sys-wechat-pay';
export * from './sys-wx-open-upload-avatar-body';
export * from './table-output';
export * from './tenant-id-input';
export * from './tenant-input';

View File

@ -0,0 +1,38 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface SetNickNameInput
*/
export interface SetNickNameInput {
/**
*
*
* @type {string}
* @memberof SetNickNameInput
*/
openId: string;
/**
*
*
* @type {string}
* @memberof SetNickNameInput
*/
nickName: string;
}

View File

@ -413,4 +413,12 @@ export interface SysUser {
* @memberof SysUser
*/
signature?: string | null;
/**
*
*
* @type {Date}
* @memberof SysUser
*/
lastChangePasswordTime?: Date | null;
}

View File

@ -0,0 +1,54 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface SysWxOpenUploadAvatarBody
*/
export interface SysWxOpenUploadAvatarBody {
/**
*
*
* @type {string}
* @memberof SysWxOpenUploadAvatarBody
*/
openId: string;
/**
*
*
* @type {Blob}
* @memberof SysWxOpenUploadAvatarBody
*/
file: Blob;
/**
*
*
* @type {string}
* @memberof SysWxOpenUploadAvatarBody
*/
fileType?: string;
/**
*
*
* @type {string}
* @memberof SysWxOpenUploadAvatarBody
*/
path?: string;
}

View File

@ -399,6 +399,14 @@ export interface UpdateUserInput {
*/
signature?: string | null;
/**
*
*
* @type {Date}
* @memberof UpdateUserInput
*/
lastChangePasswordTime?: Date | null;
/**
*
*

View File

@ -414,6 +414,14 @@ export interface UserOutput {
*/
signature?: string | null;
/**
*
*
* @type {Date}
* @memberof UserOutput
*/
lastChangePasswordTime?: Date | null;
/**
*
*

View File

@ -113,13 +113,13 @@
<el-tab-pane label="修改密码">
<el-form ref="ruleFormPasswordRef" :model="state.ruleFormPassword" label-width="auto">
<el-form-item label="当前密码" prop="passwordOld" :rules="[{ required: true, message: '当前密码不能为空', trigger: 'blur' }]">
<el-input v-model="state.ruleFormPassword.passwordOld" type="password" autocomplete="off" />
<el-input v-model="state.ruleFormPassword.passwordOld" type="password" autocomplete="off" show-password />
</el-form-item>
<el-form-item label="新密码" prop="passwordNew" :rules="[{ required: true, message: '新密码不能为空', trigger: 'blur' }]">
<el-input v-model="state.ruleFormPassword.passwordNew" type="password" autocomplete="off" />
<el-input v-model="state.ruleFormPassword.passwordNew" type="password" autocomplete="off" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="passwordNew2" :rules="[{ validator: validatePassword, required: true, trigger: 'blur' }]">
<el-input v-model="state.passwordNew2" type="password" autocomplete="off" />
<el-input v-model="state.passwordNew2" type="password" autocomplete="off" show-password />
</el-form-item>
<el-form-item>
<el-button icon="ele-Refresh" @click="resetPassword"> </el-button>