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().ToArray() ?? []; - if (seedData.Length == 0) - { - Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 没有种子数据"); - return default; + if (seedData.Length == 0) + { + Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 没有种子数据"); + return default; } // 若实体包含Id字段,则设置为当前租户Id递增1 @@ -510,4 +513,89 @@ public static class SqlSugarExtension } #endregion 视图操作 + + #region 简称操作 + /// + /// 包含缩写特性的类型属性缓存表 + /// + private static readonly ConcurrentDictionary?> _textAbbrPropCache = new(); + + /// + /// 系统通用服务 + /// + private static readonly Lazy _lazySysCommonService = new(() => App.GetService()); + + /// + /// 初始化文本简称数据 + /// + /// + public static async Task InitTextAbbDataAsync(this SqlSugarScopeProvider dbProvider) + { + // 表数据为空,则导入数据 + if (await dbProvider.Queryable().CountAsync() == 0) + { + var totalWatch = Stopwatch.StartNew(); // 开始总计时 + var message = "尝试初始化简称表数据,"; + var path = AppDomain.CurrentDomain.BaseDirectory + "pinyin.csv"; + using var reader = new StreamReader(path); + await using var csv = new CsvFile(reader.BaseStream); + var lines = csv.ReadAll().Select(u => new SysTextAbbr + { + Word = u[0], + FullName = u[1] + }).ToList(); + var count = await dbProvider.Storageable(lines).WhereColumns(u => new { u.Word, u.FullName }).ExecuteCommandAsync(); + message += $"成功导入 {count} 条,总耗时:{totalWatch.ElapsedMilliseconds} ms"; + Console.WriteLine(message); + } + } + + /// + /// 自动注入文本缩写到绑定字段 + /// + /// + public static void SetTextAbbrProperty(this DataFilterModel entityInfo) + { + // 仅处理新增/更新操作 + if (entityInfo.OperationType is DataFilterType.InsertByObject or DataFilterType.UpdateByObject) + { + var entityValue = entityInfo.EntityValue; + var entityType = entityValue.GetType(); + + // 仅在目标属性值为空时触发自动生成 + if (entityValue.GetValue(entityInfo.PropertyName) == null) + { + // 获取或创建类型属性缓存(原子化操作避免竞争条件) + var propDict = _textAbbrPropCache.GetOrAdd(entityType, type => + { + // 反射获取带[BindTextAbbr]特性的属性,预存属性元数据 + var props = type.GetProperties() + .Where(p => p.IsDefined(typeof(BindTextAbbrAttribute))) + .Select(p => (p, p.GetCustomAttribute()!)) + .ToDictionary(t => t.p.Name, t => (t.p, t.Item2)); + + return props.Any() ? props : null; + }); + + // 无绑定属性或当前属性不匹配时提前结束 + if (propDict == null || !propDict.TryGetValue(entityInfo.PropertyName, out var propData)) return; + + // 解构预存的属性和特性信息 + var (_, attribute) = propData; + var value = entityValue.GetValue(attribute.PropertyName)?.ToString(); + + // 源文本非空时生成缩写 + if (!string.IsNullOrWhiteSpace(value)) + { + // 使用线程安全的延迟初始化服务实例获取文本缩写 + var abbrValue = _lazySysCommonService.Value + .GetNameAbbr(new() { Text = value, All = attribute.SaveFullAbbr }) + .GetAwaiter() + .GetResult(); + entityInfo.SetValue(abbrValue); + } + } + } + } + #endregion } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs index 1aee446c..7233ea0b 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs @@ -283,6 +283,9 @@ public static class SqlSugarSetup entityInfo.SetValue(App.User?.FindFirst(ClaimConst.RealName)?.Value); } + // 设置绑定简称字段数据 + entityInfo.SetTextAbbrProperty(); + //// 自定义数据审计 //SqlSugarDataExecuting.Execute(oldValue, entityInfo); }; @@ -364,6 +367,9 @@ public static class SqlSugarSetup // 初始化种子数据 if (config.SeedSettings.EnableInitSeed) InitSeedData(dbProvider, config.SeedSettings.EnableIncreSeed); + + // 初始化文本简称表数据 + _ = dbProvider.InitTextAbbDataAsync(); } /// diff --git a/Web/src/api-services/system/apis/sys-common-api.ts b/Web/src/api-services/system/apis/sys-common-api.ts index 00056587..bd039dd1 100644 --- a/Web/src/api-services/system/apis/sys-common-api.ts +++ b/Web/src/api-services/system/apis/sys-common-api.ts @@ -23,6 +23,7 @@ import { AdminNETResultListString } from '../models'; import { AdminNETResultSmKeyPairOutput } from '../models'; import { AdminNETResultStressTestHarnessResult } from '../models'; import { AdminNETResultString } from '../models'; +import { NameAbbrInput } from '../models'; import { StressTestInput } from '../models'; /** * SysCommonApi - axios parameter creator @@ -325,6 +326,54 @@ export const SysCommonApiAxiosParamCreator = function (configuration?: Configura options: localVarRequestOptions, }; }, + /** + * 获取文本简称 + * @summary 获取文本简称 + * @param {NameAbbrInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysCommonNameAbbrPost: async (body?: NameAbbrInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysCommon/nameAbbr`; + // 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 国密SM2解密字符串 🔖 @@ -608,6 +657,20 @@ export const SysCommonApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * 获取文本简称 + * @summary 获取文本简称 + * @param {NameAbbrInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysCommonNameAbbrPost(body?: NameAbbrInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysCommonApiAxiosParamCreator(configuration).apiSysCommonNameAbbrPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 国密SM2解密字符串 🔖 @@ -733,6 +796,16 @@ export const SysCommonApiFactory = function (configuration?: Configuration, base async apiSysCommonMachineSerialKeyGet(options?: AxiosRequestConfig): Promise> { return SysCommonApiFp(configuration).apiSysCommonMachineSerialKeyGet(options).then((request) => request(axios, basePath)); }, + /** + * 获取文本简称 + * @summary 获取文本简称 + * @param {NameAbbrInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysCommonNameAbbrPost(body?: NameAbbrInput, options?: AxiosRequestConfig): Promise> { + return SysCommonApiFp(configuration).apiSysCommonNameAbbrPost(body, options).then((request) => request(axios, basePath)); + }, /** * * @summary 国密SM2解密字符串 🔖 @@ -849,6 +922,17 @@ export class SysCommonApi extends BaseAPI { public async apiSysCommonMachineSerialKeyGet(options?: AxiosRequestConfig) : Promise> { return SysCommonApiFp(this.configuration).apiSysCommonMachineSerialKeyGet(options).then((request) => request(this.axios, this.basePath)); } + /** + * 获取文本简称 + * @summary 获取文本简称 + * @param {NameAbbrInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysCommonApi + */ + public async apiSysCommonNameAbbrPost(body?: NameAbbrInput, options?: AxiosRequestConfig) : Promise> { + return SysCommonApiFp(this.configuration).apiSysCommonNameAbbrPost(body, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 国密SM2解密字符串 🔖 diff --git a/Web/src/api-services/system/models/add-user-input.ts b/Web/src/api-services/system/models/add-user-input.ts index c7d462c0..522b7590 100644 --- a/Web/src/api-services/system/models/add-user-input.ts +++ b/Web/src/api-services/system/models/add-user-input.ts @@ -99,6 +99,22 @@ export interface AddUserInput { */ tenantId?: number | null; + /** + * 姓名简拼 + * + * @type {string} + * @memberof AddUserInput + */ + pinyin?: string | null; + + /** + * 姓名全拼 + * + * @type {string} + * @memberof AddUserInput + */ + allPinyin?: string | null; + /** * 昵称 * diff --git a/Web/src/api-services/system/models/index.ts b/Web/src/api-services/system/models/index.ts index 655e7cfe..e328d991 100644 --- a/Web/src/api-services/system/models/index.ts +++ b/Web/src/api-services/system/models/index.ts @@ -332,6 +332,7 @@ export * from './mqtt-client-status'; export * from './mqtt-protocol-version'; export * from './mqtt-session-status'; export * from './mzb-input'; +export * from './name-abbr-input'; export * from './navigate'; export * from './network-info'; export * from './network-interface-statistics'; diff --git a/Web/src/api-services/system/models/name-abbr-input.ts b/Web/src/api-services/system/models/name-abbr-input.ts new file mode 100644 index 00000000..ff61b63a --- /dev/null +++ b/Web/src/api-services/system/models/name-abbr-input.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * 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 NameAbbrInput + */ +export interface NameAbbrInput { + + /** + * 文本 + * + * @type {string} + * @memberof NameAbbrInput + */ + text?: string | null; + + /** + * 是否全称 + * + * @type {boolean} + * @memberof NameAbbrInput + */ + all?: boolean; +} diff --git a/Web/src/api-services/system/models/sys-user.ts b/Web/src/api-services/system/models/sys-user.ts index 4abe2d6a..d60ce2c3 100644 --- a/Web/src/api-services/system/models/sys-user.ts +++ b/Web/src/api-services/system/models/sys-user.ts @@ -114,6 +114,22 @@ export interface SysUser { */ realName?: string | null; + /** + * 姓名简拼 + * + * @type {string} + * @memberof SysUser + */ + pinyin?: string | null; + + /** + * 姓名全拼 + * + * @type {string} + * @memberof SysUser + */ + allPinyin?: string | null; + /** * 昵称 * diff --git a/Web/src/api-services/system/models/update-user-input.ts b/Web/src/api-services/system/models/update-user-input.ts index c16ed302..3b172991 100644 --- a/Web/src/api-services/system/models/update-user-input.ts +++ b/Web/src/api-services/system/models/update-user-input.ts @@ -99,6 +99,22 @@ export interface UpdateUserInput { */ tenantId?: number | null; + /** + * 姓名简拼 + * + * @type {string} + * @memberof UpdateUserInput + */ + pinyin?: string | null; + + /** + * 姓名全拼 + * + * @type {string} + * @memberof UpdateUserInput + */ + allPinyin?: string | null; + /** * 昵称 * diff --git a/Web/src/api-services/system/models/user-output.ts b/Web/src/api-services/system/models/user-output.ts index 383a7837..38790081 100644 --- a/Web/src/api-services/system/models/user-output.ts +++ b/Web/src/api-services/system/models/user-output.ts @@ -114,6 +114,22 @@ export interface UserOutput { */ realName?: string | null; + /** + * 姓名简拼 + * + * @type {string} + * @memberof UserOutput + */ + pinyin?: string | null; + + /** + * 姓名全拼 + * + * @type {string} + * @memberof UserOutput + */ + allPinyin?: string | null; + /** * 昵称 * diff --git a/Web/src/i18n/pages/system/zh-CN.ts b/Web/src/i18n/pages/system/zh-CN.ts index 0e5d6416..fd28d5e7 100644 --- a/Web/src/i18n/pages/system/zh-CN.ts +++ b/Web/src/i18n/pages/system/zh-CN.ts @@ -84,6 +84,8 @@ export default { messageDetail: '消息详情', account: '账号', realName: '姓名', + pinyin: '簡拼', + allPinyin: '全拼', jobTitle: '职位名称', phoneNumber: '手机号码', resetPassword: '重置密码', diff --git a/Web/src/i18n/pages/system/zh-HK.ts b/Web/src/i18n/pages/system/zh-HK.ts index c5f66782..4556330f 100644 --- a/Web/src/i18n/pages/system/zh-HK.ts +++ b/Web/src/i18n/pages/system/zh-HK.ts @@ -80,6 +80,8 @@ export default { messageDetail: '消息詳情', account: '賬號', realName: '姓名', + pinyin: '簡拼', + allPinyin: '全拼', jobTitle: '職位名稱', phoneNumber: '手機號碼', resetPassword: '重置密碼', diff --git a/Web/src/i18n/pages/system/zh-TW.ts b/Web/src/i18n/pages/system/zh-TW.ts index 57202266..20efb0a5 100644 --- a/Web/src/i18n/pages/system/zh-TW.ts +++ b/Web/src/i18n/pages/system/zh-TW.ts @@ -80,6 +80,8 @@ export default { messageDetail: '訊息詳細', account: '帳號', realName: '姓名', + pinyin: '简拼', + allPinyin: '全拼', jobTitle: '職稱', phoneNumber: '手機號碼', resetPassword: '重設密碼', diff --git a/Web/src/utils/commonFunction.ts b/Web/src/utils/commonFunction.ts index 0dcc2304..1c7590bb 100644 --- a/Web/src/utils/commonFunction.ts +++ b/Web/src/utils/commonFunction.ts @@ -3,6 +3,9 @@ import useClipboard from 'vue-clipboard3'; import { ElMessage } from 'element-plus'; import { formatDate } from '/@/utils/formatTime'; import { useI18n } from 'vue-i18n'; +import {debounce} from "lodash-es"; +import {getAPI} from "/@/utils/axios-utils"; +import {SysCommonApi} from "/@/api-services/system"; export default function () { const { t } = useI18n(); @@ -83,6 +86,18 @@ export default function () { .join('&'); return `${url}${url.includes('?') ? '&' : '?'}${queryString}`; }; + // 获取简称 + const getNameAbbr = (text: string, callback?: (abbr: any) => void) => { + if (!text) return ElMessage.error('获取简称文本不能为空'); + try { + return getAPI(SysCommonApi).apiSysCommonNameAbbrPost({ text: text }).then(res => { + if (callback) callback(res.data.result); + return res.data.result; + }) + } catch (e) { + ElMessage.error('获取失败'); + } + }; return { percentFormat, dateFormatYMD, @@ -96,5 +111,6 @@ export default function () { removeHtml, getEnumDesc, appendQueryParams, + getNameAbbr, }; } diff --git a/Web/src/views/system/user/index.vue b/Web/src/views/system/user/index.vue index 650b0aaa..6d54b96b 100644 --- a/Web/src/views/system/user/index.vue +++ b/Web/src/views/system/user/index.vue @@ -159,6 +159,9 @@ const options = useVxeTable( { field: 'nickName', title: t('message.list.nickname'), minWidth: 120, showOverflow: 'tooltip' }, { field: 'realName', title: t('message.list.realName'), minWidth: 120, showOverflow: 'tooltip' }, + { field: 'pinyin', title: t('message.list.pinyin'), minWidth: 120, showOverflow: 'tooltip' }, + { field: 'allPinyin', title: t('message.list.allPinyin'), minWidth: 120, showOverflow: 'tooltip' }, + { field: 'phone', title: t('message.list.phoneNumber'), minWidth: 120, showOverflow: 'tooltip' }, { field: 'birthday', title: t('message.list.birthDate'), minWidth: 100, showOverflow: 'tooltip', formatter: ({ cellValue }: any) => XEUtils.toDateString(cellValue, 'yyyy-MM-dd') },