diff --git a/Admin.NET/Admin.NET.Core/Attribute/BindTextAbbrAttribute.cs b/Admin.NET/Admin.NET.Core/Attribute/BindTextAbbrAttribute.cs
new file mode 100644
index 00000000..435de57d
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Attribute/BindTextAbbrAttribute.cs
@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 绑定文本简称字段特性
+///
+[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
+public class BindTextAbbrAttribute : Attribute
+{
+ public string PropertyName { get; }
+ public bool SaveFullAbbr { get; }
+
+ ///
+ /// 初始化绑定文本简称字段特性
+ ///
+ /// 关联的属性名称
+ /// 是否保存全称
+ public BindTextAbbrAttribute(string propertyName, bool saveFullAbbr = false)
+ {
+ PropertyName = propertyName;
+ SaveFullAbbr = saveFullAbbr;
+ }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Entity/SysTextAbbr.cs b/Admin.NET/Admin.NET.Core/Entity/SysTextAbbr.cs
new file mode 100644
index 00000000..324a8a97
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Entity/SysTextAbbr.cs
@@ -0,0 +1,29 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 系统文字简称表
+///
+[SugarTable(null, "系统文字简称表")]
+[SysTable]
+public partial class SysTextAbbr : EntityBaseId
+{
+ ///
+ /// 文字
+ ///
+ [MaxLength(1)]
+ [SugarColumn(ColumnDescription = "文字", Length = 1)]
+ public virtual string Word { get; set; }
+
+ ///
+ /// 文字全称
+ ///
+ [MaxLength(8)]
+ [SugarColumn(ColumnDescription = "文字全称", Length = 8)]
+ public virtual string FullName { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Entity/SysUser.cs b/Admin.NET/Admin.NET.Core/Entity/SysUser.cs
index 7b434a4e..a0899b3f 100644
--- a/Admin.NET/Admin.NET.Core/Entity/SysUser.cs
+++ b/Admin.NET/Admin.NET.Core/Entity/SysUser.cs
@@ -38,6 +38,22 @@ public partial class SysUser : EntityTenant
[MaxLength(32)]
public virtual string RealName { get; set; }
+ ///
+ /// 姓名简拼
+ ///
+ [BindTextAbbr(nameof(RealName))]
+ [SugarColumn(ColumnDescription = "简拼", Length = 32)]
+ [MaxLength(32)]
+ public virtual string? Pinyin { get; set; }
+
+ ///
+ /// 姓名全拼
+ ///
+ [BindTextAbbr(nameof(RealName), true)]
+ [SugarColumn(ColumnDescription = "姓名全拼", Length = 32)]
+ [MaxLength(32)]
+ public virtual string? AllPinyin { get; set; }
+
///
/// 昵称
///
diff --git a/Admin.NET/Admin.NET.Core/Service/Common/Dto/NameAbbrInput.cs b/Admin.NET/Admin.NET.Core/Service/Common/Dto/NameAbbrInput.cs
new file mode 100644
index 00000000..6bd32dff
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Common/Dto/NameAbbrInput.cs
@@ -0,0 +1,23 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+///
+/// 获取文本简称
+///
+public class NameAbbrInput
+{
+ ///
+ /// 文本
+ ///
+ public string Text { get; set; }
+
+ ///
+ /// 是否全称
+ ///
+ public bool All { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs
index 473e2e71..8290a6b0 100644
--- a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs
@@ -17,13 +17,18 @@ namespace Admin.NET.Core.Service;
[AllowAnonymous]
public class SysCommonService : IDynamicApiController, ITransient
{
+ private readonly SqlSugarRepository _sysTextAbbrRep;
private readonly IApiDescriptionGroupCollectionProvider _apiProvider;
private readonly SysCacheService _sysCacheService;
private readonly IHttpRemoteService _httpRemoteService;
- public SysCommonService(IApiDescriptionGroupCollectionProvider apiProvider, SysCacheService sysCacheService, IHttpRemoteService httpRemoteService)
+ public SysCommonService(IApiDescriptionGroupCollectionProvider apiProvider,
+ SysCacheService sysCacheService,
+ SqlSugarRepository sysTextAbbrRep,
+ IHttpRemoteService httpRemoteService)
{
_apiProvider = apiProvider;
+ _sysTextAbbrRep = sysTextAbbrRep;
_sysCacheService = sysCacheService;
_httpRemoteService = httpRemoteService;
}
@@ -285,4 +290,22 @@ public class SysCommonService : IDynamicApiController, ITransient
.SetJsonContent(input.JsonContent)));
return stressTestHarnessResult;
}
+
+ ///
+ /// 获取文本简称
+ ///
+ [HttpPost]
+ [DisplayName("获取文本简称")]
+ [ApiDescriptionSettings(Order = 1, Description = "获取文本简称")]
+ public async Task GetNameAbbr(NameAbbrInput input)
+ {
+ if (string.IsNullOrWhiteSpace(input.Text)) return "";
+ var map = (await _sysTextAbbrRep.GetListAsync(u => input.Text.Contains(u.Word)))
+ ?.ToDictionary(u => u.Word, u => u.FullName);
+ return map == null || map.Count == 0 ? input.Text : input.Text.Select(c =>
+ {
+ var val = map.GetValueOrDefault(c.ToString(), c.ToString());
+ return input.All ? val : val[..1].ToLower();
+ }).Join(input.All ? " " : "");
+ }
}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs b/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
index 25b6dbcd..2781d4d2 100644
--- a/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
@@ -57,7 +57,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("获取用户分页列表")]
+ [DisplayName("获取用户分页列表")]
public virtual async Task> Page(PageUserInput input)
{
// 获取用户拥有的机构集合
@@ -82,7 +82,7 @@ public class SysUserService : IDynamicApiController, ITransient
.Where(u => u.AccountType != AccountTypeEnum.SuperAdmin)
.WhereIF(orgList != null || extOrgUserIdList != null, u => orgList.Contains(u.OrgId) || extOrgUserIdList.Contains(u.Id))
.WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account))
- .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
+ .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName) || u.Pinyin.Contains(input.RealName) || u.AllPinyin.Replace(" ", "").Contains(input.RealName))
.WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName))
.WhereIF(!string.IsNullOrWhiteSpace(input.Phone), u => u.Phone.Contains(input.Phone))
.OrderBy(u => new { u.OrderNo, u.Id })
@@ -103,18 +103,18 @@ public class SysUserService : IDynamicApiController, ITransient
///
[UnitOfWork]
[ApiDescriptionSettings(Name = "Add"), HttpPost]
- [DisplayName("增加用户")]
+ [DisplayName("增加用户")]
public virtual async Task AddUser(AddUserInput input)
- {
- // 是否有权操作此账号
+ {
+ // 是否有权操作此账号
if (!_userManager.SuperAdmin && input.AccountType is AccountTypeEnum.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D1033);
var query = _sysUserRep.AsQueryable().ClearFilter();
if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
-
+
// 若没有设置密码则取默认密码
- var password = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPassword);
+ var password = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPassword);
var user = input.Adapt();
user.Password = CryptogramHelper.Encrypt(password);
var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
@@ -139,22 +139,22 @@ public class SysUserService : IDynamicApiController, ITransient
///
[UnitOfWork]
[ApiDescriptionSettings(Name = "Update"), HttpPost]
- [DisplayName("更新用户")]
+ [DisplayName("更新用户")]
public virtual async Task UpdateUser(UpdateUserInput input)
- {
+ {
var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.Id != input.Id);
if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
- if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
-
- // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新
+ if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
+
+ // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新
var user = await _sysUserRep.GetByIdAsync(input.Id);
var roleIds = await _sysUserRoleService.GetUserRoleIdList(input.Id);
if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u)))
{
// 强制下线账号和失效Token
await OfflineAndExpireToken(user);
- }
-
+ }
+
// 更新用户
await _sysUserRep.AsUpdateable(input.Adapt()).IgnoreColumns(true).IgnoreColumns(u => new { u.Password, u.Status, u.TenantId }).ExecuteCommandAsync();
@@ -190,7 +190,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
[UnitOfWork]
[ApiDescriptionSettings(Name = "Delete"), HttpPost]
- [DisplayName("删除用户")]
+ [DisplayName("删除用户")]
public virtual async Task DeleteUser(DeleteUserInput input)
{
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
@@ -231,7 +231,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// 查看用户基本信息 🔖
///
///
- [DisplayName("查看用户基本信息")]
+ [DisplayName("查看用户基本信息")]
public virtual async Task GetBaseInfo()
{
return await _sysUserRep.GetByIdAsync(_userManager.UserId);
@@ -242,7 +242,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
[ApiDescriptionSettings(Name = "UpdateBaseInfo"), HttpPost]
- [DisplayName("更新用户基本信息")]
+ [DisplayName("更新用户基本信息")]
public virtual async Task UpdateBaseInfo(SysUser user)
{
return await _sysUserRep.AsUpdateable(user)
@@ -255,7 +255,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
[UnitOfWork]
- [DisplayName("设置用户状态")]
+ [DisplayName("设置用户状态")]
public virtual async Task SetStatus(BaseStatusInput input)
{
if (_userManager.UserId == input.Id)
@@ -288,7 +288,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
[UnitOfWork]
- [DisplayName("授权用户角色")]
+ [DisplayName("授权用户角色")]
public async Task GrantRole(UserRoleInput input)
{
var user = await _sysUserRep.GetByIdAsync(input.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
@@ -311,7 +311,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("修改用户密码")]
+ [DisplayName("修改用户密码")]
public virtual async Task ChangePwd(ChangePwdInput input)
{
// 国密SM2解密(前端密码传输SM2加密后的)
@@ -376,7 +376,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("重置用户密码")]
+ [DisplayName("重置用户密码")]
public virtual async Task ResetPwd(ResetPwdUserInput input)
{
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
@@ -404,7 +404,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// 验证密码有效期 🔖
///
///
- [DisplayName("验证密码有效期")]
+ [DisplayName("验证密码有效期")]
public async Task VerifyPwdExpirationTime()
{
var sysConfig = await _sysConfigService.GetConfig(ConfigConst.SysPasswordExpirationTime);
@@ -424,7 +424,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("解除登录锁定")]
+ [DisplayName("解除登录锁定")]
public virtual async Task UnlockLogin(BaseIdInput input)
{
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
@@ -442,7 +442,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("获取用户拥有角色集合")]
+ [DisplayName("获取用户拥有角色集合")]
public async Task GetOwnRoleList(long userId)
{
// 获取当前用户已分配角色
@@ -461,7 +461,7 @@ public class SysUserService : IDynamicApiController, ITransient
///
///
///
- [DisplayName("获取用户扩展机构集合")]
+ [DisplayName("获取用户扩展机构集合")]
public async Task> GetOwnExtOrgList(long userId)
{
return await _sysUserExtOrgService.GetUserExtOrgList(userId);
diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs
index 87044fd6..319519a8 100644
--- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs
+++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs
@@ -5,6 +5,9 @@
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System.Text.Json;
+using Minio.DataModel;
+using NewLife.IO;
+using NewLife.Reflection;
namespace Admin.NET.Core;
@@ -173,8 +176,8 @@ public static class SqlSugarExtension
foreach (var filter in filters)
{
- Expression bExpresionFilter;
-
+ Expression bExpresionFilter;
+
if (Enum.IsDefined(typeof(FilterLogicEnum), filter.Logic))
{
if (filter.Filters is null) throw new ArgumentException("The Filters attribute is required when declaring a logic");
@@ -384,37 +387,37 @@ public static class SqlSugarExtension
{
if (entityType.GetCustomAttribute() == null &&
(entityType.GetCustomAttribute() != null ||
- entityType.GetCustomAttribute() != null))
- {
+ entityType.GetCustomAttribute() != null))
+ {
Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非SysTable 与 (LogTable 或 Tenant)表");
- return default;
+ return default;
}
}
else if (config.ConfigId.ToString() == SqlSugarConst.LogConfigId) // 日志库
{
- if (entityType.GetCustomAttribute() == null)
- {
- Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非LogTable表");
- return default;
+ if (entityType.GetCustomAttribute() == null)
+ {
+ Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非LogTable表");
+ return default;
}
}
else
{
var att = entityType.GetCustomAttribute(); // 自定义的库
- if (att == null || att.configId.ToString() != config.ConfigId.ToString())
- {
- Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非Tenant表");
- return default;
+ if (att == null || att.configId.ToString() != config.ConfigId.ToString())
+ {
+ Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非Tenant表");
+ return default;
}
}
var instance = Activator.CreateInstance(seedType);
var hasDataMethod = seedType.GetMethod("HasData");
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast