using System.Linq.Expressions; using Fake.Application; using Microsoft.AspNetCore.Mvc; using Oms.Application.Dtos.Shared; using Oms.Application.Dtos.System; using Oms.Application.Shared; using Oms.Domain.SystemAggregate.Entities; using Oms.Domain.SystemAggregate.Repositories; namespace Oms.Application.Services.System; /// /// 字典 API 服务。 /// [ApiExplorerSettings(GroupName = "OMS-System")] public class DictService : ApplicationService { private IDictRepository DictRepository => LazyServiceProvider.GetRequiredService(); /// /// 查询字典列表。 /// /// 入参:字典分页查询条件。 /// 字典分页结果,包含字典列表与总记录数。 /// /// 核心业务逻辑: /// 1. 根据字典类型和关键词拼装筛选条件。 /// 2. 按排序值升序、主键降序返回分页结果。 /// 3. 供系统配置页直接展示和编辑。 /// [HttpGet("/system/dict/list")] public async Task> GetListAsync([FromQuery] DictListInput input) { var predicate = BuildListPredicate(input); var pageIndex = OmsDocHelper.NormalizePage(input.Page); var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize); var items = await DictRepository.GetPagedListAsync( predicate, pageIndex, pageSize, new Dictionary { [nameof(Dict.DictSort)] = true, [nameof(Dict.Id)] = false }); var total = await DictRepository.CountAsync(predicate); return new OmsPageResult { Items = items.Select(MapDictOutput).ToList(), Total = total }; } /// /// 新增字典。 /// /// 入参:字典新增参数。 /// 无返回体,仅完成新增字典。 /// /// 核心业务逻辑: /// 1. 校验类型、编码、名称等基础字段。 /// 2. 检查同类型下编码唯一性。 /// 3. 写入字典主数据供系统配置复用。 /// [HttpPost("/system/dict/create")] public async Task CreateAsync(DictCreateInput input) { await ValidateDictInputAsync(input.DictType, input.DictCode, input.DictName, null); await DictRepository.InsertAsync(new Dict { DictType = input.DictType.Trim(), DictSort = input.DictSort, DictCode = input.DictCode.Trim(), DictName = input.DictName.Trim() }); } /// /// 更新字典。 /// /// 入参:字典更新参数。 /// 无返回体,仅完成更新字典。 /// /// 核心业务逻辑: /// 1. 查询并校验目标字典是否存在。 /// 2. 检查更新后的类型与编码组合唯一性。 /// 3. 保存排序、编码和名称等最新配置。 /// [HttpPost("/system/dict/update")] public async Task UpdateAsync(DictUpdateInput input) { var entity = await GetDictOrThrowAsync(input.Id); await ValidateDictInputAsync(input.DictType, input.DictCode, input.DictName, entity.Id); entity.DictType = input.DictType.Trim(); entity.DictSort = input.DictSort; entity.DictCode = input.DictCode.Trim(); entity.DictName = input.DictName.Trim(); await DictRepository.UpdateAsync(entity); } /// /// 删除字典。 /// /// 入参:目标主键。 /// 无返回体,仅完成删除字典。 /// /// 核心业务逻辑: /// 1. 查询并校验目标字典是否存在。 /// 2. 走框架删除通道保留软删语义。 /// 3. 让下游列表自动隐藏已删除记录。 /// [HttpPost("/system/dict/delete")] public async Task DeleteAsync(IdInput input) { var entity = await GetDictOrThrowAsync(input.Id); await DictRepository.DeleteAsync(entity); } private static Expression> BuildListPredicate(DictListInput input) { var dictType = input.DictType?.Trim(); var keyword = input.Keyword?.Trim(); return x => (string.IsNullOrWhiteSpace(dictType) || x.DictType == dictType) && (string.IsNullOrWhiteSpace(keyword) || x.DictCode.Contains(keyword) || x.DictName.Contains(keyword)); } private async Task GetDictOrThrowAsync(int id) { var entity = await DictRepository.FirstOrDefaultAsync(x => x.Id == id); if (entity == null) { throw new BusinessException("字典不存在"); } return entity; } private async Task ValidateDictInputAsync(string dictType, string dictCode, string dictName, int? excludeId) { if (string.IsNullOrWhiteSpace(dictType)) { throw new BusinessException("字典类型不能为空"); } if (string.IsNullOrWhiteSpace(dictCode)) { throw new BusinessException("字典编码不能为空"); } if (string.IsNullOrWhiteSpace(dictName)) { throw new BusinessException("字典名称不能为空"); } var existed = await DictRepository.GetByTypeAndCodeAsync(dictType.Trim(), dictCode.Trim()); if (existed != null && existed.Id != excludeId) { throw new BusinessException("同类型下字典编码已存在"); } } private static DictOutput MapDictOutput(Dict entity) { return new DictOutput { Id = entity.Id, DictType = entity.DictType, DictSort = entity.DictSort, DictCode = entity.DictCode, DictName = entity.DictName, CreateTime = entity.CreateTime, UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime) }; } }