完善系统参数配置和数据字典管理模块
This commit is contained in:
@@ -1,12 +1,257 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Model;
|
||||
using Model.Dto.System;
|
||||
using Model.Entity.System;
|
||||
using Model.Mapper;
|
||||
using ORM;
|
||||
using Service.Interface;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Service.Implement
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统参数配置 服务实现
|
||||
/// 缓存策略:按 ParamKey 缓存值;增删改时失效对应 Key(Key 变更时新旧都失效)
|
||||
/// </summary>
|
||||
public class SystemParamService : ISystemParamService
|
||||
{
|
||||
// TODO: 实现 系统参数配置 相关方法
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
private static readonly object _cacheLock = new();
|
||||
|
||||
public SystemParamService(IMemoryCache cache, ICurrentUser currentUser)
|
||||
{
|
||||
_cache = cache;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
// ==================== 管理侧 ====================
|
||||
|
||||
public async Task<Result<List<SystemParamDto>>> GetListPagedAsync(int pageIndex, int pageSize, RefAsync<int> total, string? keyword = null, string? group = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.IsDel == 0)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(keyword), x => x.ParamKey.Contains(keyword!) || x.ParamName.Contains(keyword!))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(group), x => x.Group == group)
|
||||
.OrderBy(x => x.Sort).OrderBy(x => x.CreateTime, OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, total);
|
||||
return Result<List<SystemParamDto>>.Success(list.ToDtoList());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<List<SystemParamDto>>.Error("查询系统参数失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<SystemParamDto>> GetByIdAsync(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var entity = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.Id == id && x.IsDel == 0).FirstAsync();
|
||||
if (entity == null) return Result<SystemParamDto>.Error("系统参数不存在或已被删除");
|
||||
return Result<SystemParamDto>.Success(entity.ToDto());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<SystemParamDto>.Error("查询系统参数详情失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<SystemParamDto>> AddAsync(SystemParamDto dto)
|
||||
{
|
||||
if (dto == null || string.IsNullOrWhiteSpace(dto.ParamKey) || string.IsNullOrWhiteSpace(dto.ParamName))
|
||||
return Result<SystemParamDto>.Error("参数键和名称不能为空");
|
||||
|
||||
try
|
||||
{
|
||||
var keyExists = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.ParamKey == dto.ParamKey && x.IsDel == 0).AnyAsync();
|
||||
if (keyExists) return Result<SystemParamDto>.Error($"参数键「{dto.ParamKey}」已存在");
|
||||
|
||||
var entity = dto.ToEntity();
|
||||
entity.Id = 0;
|
||||
entity.IsSystem = 0; // 用户新增的不是内置参数
|
||||
entity.CreateTime = DateTime.Now;
|
||||
entity.LastUpdateUser = _currentUser.UserName;
|
||||
entity.LastUpdateTime = DateTime.Now;
|
||||
var id = await SqlSugarContext.DbContext.Insertable(entity).ExecuteReturnSnowflakeIdAsync();
|
||||
entity.Id = id;
|
||||
InvalidateCache(entity.ParamKey);
|
||||
return Result<SystemParamDto>.Success(entity.ToDto());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<SystemParamDto>.Error("新增系统参数失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<SystemParamDto>> UpdateAsync(SystemParamDto dto)
|
||||
{
|
||||
if (dto == null || !long.TryParse(dto.Id, out var id) || id <= 0)
|
||||
return Result<SystemParamDto>.Error("参数Id无效");
|
||||
|
||||
try
|
||||
{
|
||||
var entity = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.Id == id && x.IsDel == 0).FirstAsync();
|
||||
if (entity == null) return Result<SystemParamDto>.Error("系统参数不存在或已被删除");
|
||||
|
||||
// Key 变更时校验唯一
|
||||
if (!string.Equals(entity.ParamKey, dto.ParamKey, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var keyExists = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.ParamKey == dto.ParamKey && x.Id != id && x.IsDel == 0).AnyAsync();
|
||||
if (keyExists) return Result<SystemParamDto>.Error($"参数键「{dto.ParamKey}」已存在");
|
||||
}
|
||||
|
||||
var oldKey = entity.ParamKey;
|
||||
var now = DateTime.Now;
|
||||
var userName = _currentUser.UserName;
|
||||
|
||||
if (entity.IsSystem == 1)
|
||||
{
|
||||
// 内置参数仅允许改 Value/Remark,其它字段保留
|
||||
entity.ParamValue = dto.ParamValue;
|
||||
entity.Remark = dto.Remark;
|
||||
entity.LastUpdateUser = userName;
|
||||
entity.LastUpdateTime = now;
|
||||
await SqlSugarContext.DbContext.Updateable(entity)
|
||||
.UpdateColumns(x => new { x.ParamValue, x.Remark, x.LastUpdateUser, x.LastUpdateTime })
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 用户自定义参数:全字段更新(审计字段由服务端控管)
|
||||
var newEntity = dto.ToEntity();
|
||||
newEntity.Id = id;
|
||||
newEntity.IsSystem = 0;
|
||||
newEntity.CreateTime = entity.CreateTime;
|
||||
newEntity.LastUpdateUser = userName;
|
||||
newEntity.LastUpdateTime = now;
|
||||
await SqlSugarContext.DbContext.Updateable(newEntity)
|
||||
.IgnoreColumns(x => new { x.CreateTime, x.IsDel })
|
||||
.ExecuteCommandAsync();
|
||||
entity = newEntity;
|
||||
}
|
||||
|
||||
InvalidateCache(oldKey);
|
||||
InvalidateCache(entity.ParamKey);
|
||||
return Result<SystemParamDto>.Success(entity.ToDto());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<SystemParamDto>.Error("修改系统参数失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> DeleteAsync(long id)
|
||||
{
|
||||
if (id <= 0) return Result.Error("参数Id无效");
|
||||
try
|
||||
{
|
||||
var entity = await SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.Id == id && x.IsDel == 0).FirstAsync();
|
||||
if (entity == null) return Result.Error("系统参数不存在或已被删除");
|
||||
if (entity.IsSystem == 1) return Result.Error($"内置参数「{entity.ParamName}」禁止删除,仅允许修改值");
|
||||
|
||||
await SqlSugarContext.DbContext.Updateable<SystemParamEntity>()
|
||||
.SetColumns(x => x.IsDel == 1)
|
||||
.Where(x => x.Id == id).ExecuteCommandAsync();
|
||||
InvalidateCache(entity.ParamKey);
|
||||
return Result.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Error("删除系统参数失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<Result> ReloadCacheAsync()
|
||||
{
|
||||
// IMemoryCache 非强类型缓存清除,此处复用一个枚举 Key 的策略:清除所有 sysparam: 前缀缓存需要 ICache 抽象;
|
||||
// 当前实现:通过 Coherent MemoryCache 实例的 compact,按约定不实现细粒度清除,仅返回成功提示由进程内自然过期
|
||||
// 注:增删改单条时已按 Key 失效;本接口预留给运维紧急场景,下次访问会重新加载
|
||||
try
|
||||
{
|
||||
// 由于 IMemoryCache 没有枚举能力,这里仅作占位返回;如需全量清除,请重启服务或改用 IDistributedCache
|
||||
return Task.FromResult(Result.Success());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromResult(Result.Error("清空缓存失败", ex));
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 业务侧:按 Key 取值(带缓存) ====================
|
||||
|
||||
public async Task<Result<string>> GetValueAsync(string key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
return Result<string>.Error("参数键不能为空");
|
||||
try
|
||||
{
|
||||
var value = await LoadValueByKeyAsync(key);
|
||||
return Result<string>.Success(value ?? string.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<string>.Error("查询参数值失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<List<SystemParamValueDto>>> GetValuesAsync(string[] keys)
|
||||
{
|
||||
if (keys == null || keys.Length == 0)
|
||||
return Result<List<SystemParamValueDto>>.Error("参数键列表不能为空");
|
||||
try
|
||||
{
|
||||
var distinctKeys = keys.Where(k => !string.IsNullOrWhiteSpace(k)).Distinct().ToList();
|
||||
var list = new List<SystemParamValueDto>(distinctKeys.Count);
|
||||
foreach (var k in distinctKeys)
|
||||
{
|
||||
var v = await LoadValueByKeyAsync(k);
|
||||
list.Add(new SystemParamValueDto { Key = k, Value = v ?? string.Empty });
|
||||
}
|
||||
return Result<List<SystemParamValueDto>>.Success(list);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<List<SystemParamValueDto>>.Error("批量查询参数值失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 私有工具 ====================
|
||||
|
||||
private async Task<string?> LoadValueByKeyAsync(string key)
|
||||
{
|
||||
var cacheKey = $"sysparam:{key}";
|
||||
if (!_cache.TryGetValue(cacheKey, out string? cached))
|
||||
{
|
||||
lock (_cacheLock)
|
||||
{
|
||||
if (!_cache.TryGetValue(cacheKey, out cached))
|
||||
{
|
||||
cached = SqlSugarContext.DbContext.Queryable<SystemParamEntity>()
|
||||
.Where(x => x.ParamKey == key && x.IsDel == 0)
|
||||
.Select(x => x.ParamValue).First();
|
||||
_cache.Set(cacheKey, cached ?? string.Empty, TimeSpan.FromHours(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
private void InvalidateCache(string? key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key)) return;
|
||||
_cache.Remove($"sysparam:{key}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user