😎 feat(文本简称): 增加文本简称功能并应用到用户姓名

- 新增 BindTextAbbrAttribute 特性用于绑定文本简称字段
- 创建 SysTextAbbr 表存储文字简称数据
- 在 SysUser 表中添加姓名简称相关字段
- 实现 GetNameAbbr 方法获取文本简称
- 在数据初始化时导入简称数据
- 在数据审计操作中智能设置带[BindTextAbbr]特性字段值
This commit is contained in:
喵你个汪呀 2025-08-12 17:36:28 +08:00
parent 776d4f195a
commit d9e56baeb9
20 changed files with 468 additions and 43 deletions

View File

@ -0,0 +1,28 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 绑定文本简称字段特性
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class BindTextAbbrAttribute : Attribute
{
public string PropertyName { get; }
public bool SaveFullAbbr { get; }
/// <summary>
/// 初始化绑定文本简称字段特性
/// </summary>
/// <param name="propertyName">关联的属性名称</param>
/// <param name="saveFullAbbr">是否保存全称</param>
public BindTextAbbrAttribute(string propertyName, bool saveFullAbbr = false)
{
PropertyName = propertyName;
SaveFullAbbr = saveFullAbbr;
}
}

View File

@ -0,0 +1,29 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 系统文字简称表
/// </summary>
[SugarTable(null, "系统文字简称表")]
[SysTable]
public partial class SysTextAbbr : EntityBaseId
{
/// <summary>
/// 文字
/// </summary>
[MaxLength(1)]
[SugarColumn(ColumnDescription = "文字", Length = 1)]
public virtual string Word { get; set; }
/// <summary>
/// 文字全称
/// </summary>
[MaxLength(8)]
[SugarColumn(ColumnDescription = "文字全称", Length = 8)]
public virtual string FullName { get; set; }
}

View File

@ -38,6 +38,22 @@ public partial class SysUser : EntityTenant
[MaxLength(32)]
public virtual string RealName { get; set; }
/// <summary>
/// 姓名简拼
/// </summary>
[BindTextAbbr(nameof(RealName))]
[SugarColumn(ColumnDescription = "简拼", Length = 32)]
[MaxLength(32)]
public virtual string? Pinyin { get; set; }
/// <summary>
/// 姓名全拼
/// </summary>
[BindTextAbbr(nameof(RealName), true)]
[SugarColumn(ColumnDescription = "姓名全拼", Length = 32)]
[MaxLength(32)]
public virtual string? AllPinyin { get; set; }
/// <summary>
/// 昵称
/// </summary>

View File

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

View File

@ -17,13 +17,18 @@ namespace Admin.NET.Core.Service;
[AllowAnonymous]
public class SysCommonService : IDynamicApiController, ITransient
{
private readonly SqlSugarRepository<SysTextAbbr> _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<SysTextAbbr> 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;
}
/// <summary>
/// 获取文本简称
/// </summary>
[HttpPost]
[DisplayName("获取文本简称")]
[ApiDescriptionSettings(Order = 1, Description = "获取文本简称")]
public async Task<string> 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 ? " " : "");
}
}

View File

@ -57,7 +57,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("获取用户分页列表")]
[DisplayName("获取用户分页列表")]
public virtual async Task<SqlSugarPagedList<UserOutput>> 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
/// <returns></returns>
[UnitOfWork]
[ApiDescriptionSettings(Name = "Add"), HttpPost]
[DisplayName("增加用户")]
[DisplayName("增加用户")]
public virtual async Task<long> 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<string>(ConfigConst.SysPassword);
var password = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValueByCode<string>(ConfigConst.SysPassword);
var user = input.Adapt<SysUser>();
user.Password = CryptogramHelper.Encrypt(password);
var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
@ -139,22 +139,22 @@ public class SysUserService : IDynamicApiController, ITransient
/// <returns></returns>
[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<SysUser>()).IgnoreColumns(true).IgnoreColumns(u => new { u.Password, u.Status, u.TenantId }).ExecuteCommandAsync();
@ -190,7 +190,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// <returns></returns>
[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
/// 查看用户基本信息 🔖
/// </summary>
/// <returns></returns>
[DisplayName("查看用户基本信息")]
[DisplayName("查看用户基本信息")]
public virtual async Task<SysUser> GetBaseInfo()
{
return await _sysUserRep.GetByIdAsync(_userManager.UserId);
@ -242,7 +242,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <returns></returns>
[ApiDescriptionSettings(Name = "UpdateBaseInfo"), HttpPost]
[DisplayName("更新用户基本信息")]
[DisplayName("更新用户基本信息")]
public virtual async Task<int> UpdateBaseInfo(SysUser user)
{
return await _sysUserRep.AsUpdateable(user)
@ -255,7 +255,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[DisplayName("设置用户状态")]
[DisplayName("设置用户状态")]
public virtual async Task<int> SetStatus(BaseStatusInput input)
{
if (_userManager.UserId == input.Id)
@ -288,7 +288,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// <param name="input"></param>
/// <returns></returns>
[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
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("修改用户密码")]
[DisplayName("修改用户密码")]
public virtual async Task<int> ChangePwd(ChangePwdInput input)
{
// 国密SM2解密前端密码传输SM2加密后的
@ -376,7 +376,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[DisplayName("重置用户密码")]
[DisplayName("重置用户密码")]
public virtual async Task<string> ResetPwd(ResetPwdUserInput input)
{
var user = await _sysUserRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
@ -404,7 +404,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// 验证密码有效期 🔖
/// </summary>
/// <returns></returns>
[DisplayName("验证密码有效期")]
[DisplayName("验证密码有效期")]
public async Task<bool> VerifyPwdExpirationTime()
{
var sysConfig = await _sysConfigService.GetConfig(ConfigConst.SysPasswordExpirationTime);
@ -424,7 +424,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[DisplayName("获取用户拥有角色集合")]
[DisplayName("获取用户拥有角色集合")]
public async Task<GrantRoleOutput> GetOwnRoleList(long userId)
{
// 获取当前用户已分配角色
@ -461,7 +461,7 @@ public class SysUserService : IDynamicApiController, ITransient
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[DisplayName("获取用户扩展机构集合")]
[DisplayName("获取用户扩展机构集合")]
public async Task<List<SysUserExtOrg>> GetOwnExtOrgList(long userId)
{
return await _sysUserExtOrgService.GetUserExtOrgList(userId);

View File

@ -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<SysTableAttribute>() == null &&
(entityType.GetCustomAttribute<LogTableAttribute>() != null ||
entityType.GetCustomAttribute<TenantAttribute>() != null))
{
entityType.GetCustomAttribute<TenantAttribute>() != 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<LogTableAttribute>() == null)
{
Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非LogTable表");
return default;
if (entityType.GetCustomAttribute<LogTableAttribute>() == null)
{
Console.WriteLine($" 忽略 {seedType.FullName,-58} ({dbProvider.CurrentConnectionConfig.ConfigId}) 原因: 非LogTable表");
return default;
}
}
else
{
var att = entityType.GetCustomAttribute<TenantAttribute>(); // 自定义的库
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<object>().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
/// <summary>
/// 包含缩写特性的类型属性缓存表
/// </summary>
private static readonly ConcurrentDictionary<Type, Dictionary<string, (PropertyInfo Prop, BindTextAbbrAttribute Attr)>?> _textAbbrPropCache = new();
/// <summary>
/// 系统通用服务
/// </summary>
private static readonly Lazy<SysCommonService> _lazySysCommonService = new(() => App.GetService<SysCommonService>());
/// <summary>
/// 初始化文本简称数据
/// </summary>
/// <param name="dbProvider"></param>
public static async Task InitTextAbbDataAsync(this SqlSugarScopeProvider dbProvider)
{
// 表数据为空,则导入数据
if (await dbProvider.Queryable<SysTextAbbr>().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);
}
}
/// <summary>
/// 自动注入文本缩写到绑定字段
/// </summary>
/// <param name="entityInfo"></param>
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<BindTextAbbrAttribute>()!))
.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
}

View File

@ -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();
}
/// <summary>

View File

@ -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<RequestArgs> => {
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<AxiosResponse<AdminNETResultString>>> {
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<AxiosResponse<AdminNETResultString>> {
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<AxiosResponse<AdminNETResultString>> {
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<AxiosResponse<AdminNETResultString>> {
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<AxiosResponse<AdminNETResultString>> {
return SysCommonApiFp(this.configuration).apiSysCommonNameAbbrPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary SM2解密字符串 🔖

View File

@ -99,6 +99,22 @@ export interface AddUserInput {
*/
tenantId?: number | null;
/**
*
*
* @type {string}
* @memberof AddUserInput
*/
pinyin?: string | null;
/**
*
*
* @type {string}
* @memberof AddUserInput
*/
allPinyin?: string | null;
/**
*
*

View File

@ -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';

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 NameAbbrInput
*/
export interface NameAbbrInput {
/**
*
*
* @type {string}
* @memberof NameAbbrInput
*/
text?: string | null;
/**
*
*
* @type {boolean}
* @memberof NameAbbrInput
*/
all?: boolean;
}

View File

@ -114,6 +114,22 @@ export interface SysUser {
*/
realName?: string | null;
/**
*
*
* @type {string}
* @memberof SysUser
*/
pinyin?: string | null;
/**
*
*
* @type {string}
* @memberof SysUser
*/
allPinyin?: string | null;
/**
*
*

View File

@ -99,6 +99,22 @@ export interface UpdateUserInput {
*/
tenantId?: number | null;
/**
*
*
* @type {string}
* @memberof UpdateUserInput
*/
pinyin?: string | null;
/**
*
*
* @type {string}
* @memberof UpdateUserInput
*/
allPinyin?: string | null;
/**
*
*

View File

@ -114,6 +114,22 @@ export interface UserOutput {
*/
realName?: string | null;
/**
*
*
* @type {string}
* @memberof UserOutput
*/
pinyin?: string | null;
/**
*
*
* @type {string}
* @memberof UserOutput
*/
allPinyin?: string | null;
/**
*
*

View File

@ -84,6 +84,8 @@ export default {
messageDetail: '消息详情',
account: '账号',
realName: '姓名',
pinyin: '簡拼',
allPinyin: '全拼',
jobTitle: '职位名称',
phoneNumber: '手机号码',
resetPassword: '重置密码',

View File

@ -80,6 +80,8 @@ export default {
messageDetail: '消息詳情',
account: '賬號',
realName: '姓名',
pinyin: '簡拼',
allPinyin: '全拼',
jobTitle: '職位名稱',
phoneNumber: '手機號碼',
resetPassword: '重置密碼',

View File

@ -80,6 +80,8 @@ export default {
messageDetail: '訊息詳細',
account: '帳號',
realName: '姓名',
pinyin: '简拼',
allPinyin: '全拼',
jobTitle: '職稱',
phoneNumber: '手機號碼',
resetPassword: '重設密碼',

View File

@ -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,
};
}

View File

@ -159,6 +159,9 @@ const options = useVxeTable<UserOutput>(
{ 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') },