From 3b2b376787131b515d1f8900a41ee95a9078d668 Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Tue, 2 Dec 2025 12:53:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=B1=82=E4=B8=8E=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/SystemParametersController.cs | 115 ++++++++++++++++++ .../Commands/CreateSystemParameterCommand.cs | 35 ++++++ .../Commands/DeleteSystemParameterCommand.cs | 14 +++ .../Commands/UpdateSystemParameterCommand.cs | 40 ++++++ .../Dto/SystemParameterDto.cs | 57 +++++++++ .../CreateSystemParameterCommandHandler.cs | 64 ++++++++++ .../DeleteSystemParameterCommandHandler.cs | 33 +++++ .../GetSystemParameterByIdQueryHandler.cs | 35 ++++++ .../SearchSystemParametersQueryHandler.cs | 69 +++++++++++ .../UpdateSystemParameterCommandHandler.cs | 66 ++++++++++ .../Queries/GetSystemParameterByIdQuery.cs | 9 ++ .../Queries/SearchSystemParametersQuery.cs | 41 +++++++ .../CreateSystemParameterCommandValidator.cs | 21 ++++ .../SearchSystemParametersQueryValidator.cs | 21 ++++ .../UpdateSystemParameterCommandValidator.cs | 22 ++++ .../ISystemParameterRepository.cs | 47 +++++++ .../DictionaryServiceCollectionExtensions.cs | 2 + .../EfSystemParameterRepository.cs | 80 ++++++++++++ 18 files changed, 771 insertions(+) create mode 100644 src/Api/TakeoutSaaS.AdminApi/Controllers/SystemParametersController.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs create mode 100644 src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs create mode 100644 src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs diff --git a/src/Api/TakeoutSaaS.AdminApi/Controllers/SystemParametersController.cs b/src/Api/TakeoutSaaS.AdminApi/Controllers/SystemParametersController.cs new file mode 100644 index 0000000..045d649 --- /dev/null +++ b/src/Api/TakeoutSaaS.AdminApi/Controllers/SystemParametersController.cs @@ -0,0 +1,115 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using TakeoutSaaS.Application.App.SystemParameters.Commands; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Application.App.SystemParameters.Queries; +using TakeoutSaaS.Module.Authorization.Attributes; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Results; +using TakeoutSaaS.Shared.Web.Api; + +namespace TakeoutSaaS.AdminApi.Controllers; + +/// +/// 系统参数管理。 +/// +/// +/// 提供参数的新增、修改、查询与删除。 +/// +[ApiVersion("1.0")] +[Authorize] +[Route("api/admin/v{version:apiVersion}/system-parameters")] +public sealed class SystemParametersController(IMediator mediator) : BaseApiController +{ + /// + /// 创建系统参数。 + /// + [HttpPost] + [PermissionAuthorize("system-parameter:create")] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] + public async Task> Create([FromBody] CreateSystemParameterCommand command, CancellationToken cancellationToken) + { + var result = await mediator.Send(command, cancellationToken); + return ApiResponse.Ok(result); + } + + /// + /// 查询系统参数列表。 + /// + [HttpGet] + [PermissionAuthorize("system-parameter:read")] + [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)] + public async Task>> List( + [FromQuery] string? keyword, + [FromQuery] bool? isEnabled, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20, + [FromQuery] string? sortBy = null, + [FromQuery] bool sortDesc = true, + CancellationToken cancellationToken = default) + { + var result = await mediator.Send(new SearchSystemParametersQuery + { + Keyword = keyword, + IsEnabled = isEnabled, + Page = page, + PageSize = pageSize, + SortBy = sortBy, + SortDescending = sortDesc + }, cancellationToken); + + return ApiResponse>.Ok(result); + } + + /// + /// 获取系统参数详情。 + /// + [HttpGet("{parameterId:long}")] + [PermissionAuthorize("system-parameter:read")] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] + public async Task> Detail(long parameterId, CancellationToken cancellationToken) + { + var result = await mediator.Send(new GetSystemParameterByIdQuery(parameterId), cancellationToken); + return result == null + ? ApiResponse.Error(ErrorCodes.NotFound, "系统参数不存在") + : ApiResponse.Ok(result); + } + + /// + /// 更新系统参数。 + /// + [HttpPut("{parameterId:long}")] + [PermissionAuthorize("system-parameter:update")] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] + public async Task> Update(long parameterId, [FromBody] UpdateSystemParameterCommand command, CancellationToken cancellationToken) + { + if (command.ParameterId == 0) + { + command = command with { ParameterId = parameterId }; + } + + var result = await mediator.Send(command, cancellationToken); + return result == null + ? ApiResponse.Error(ErrorCodes.NotFound, "系统参数不存在") + : ApiResponse.Ok(result); + } + + /// + /// 删除系统参数。 + /// + [HttpDelete("{parameterId:long}")] + [PermissionAuthorize("system-parameter:delete")] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] + public async Task> Delete(long parameterId, CancellationToken cancellationToken) + { + var success = await mediator.Send(new DeleteSystemParameterCommand { ParameterId = parameterId }, cancellationToken); + return success + ? ApiResponse.Success() + : ApiResponse.Error(ErrorCodes.NotFound, "系统参数不存在"); + } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs new file mode 100644 index 0000000..c5f332c --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/CreateSystemParameterCommand.cs @@ -0,0 +1,35 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; + +namespace TakeoutSaaS.Application.App.SystemParameters.Commands; + +/// +/// 创建系统参数命令。 +/// +public sealed class CreateSystemParameterCommand : IRequest +{ + /// + /// 参数键。 + /// + public string Key { get; set; } = string.Empty; + + /// + /// 参数值。 + /// + public string Value { get; set; } = string.Empty; + + /// + /// 描述。 + /// + public string? Description { get; set; } + + /// + /// 排序值。 + /// + public int SortOrder { get; set; } = 100; + + /// + /// 是否启用。 + /// + public bool IsEnabled { get; set; } = true; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs new file mode 100644 index 0000000..6f49ad8 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/DeleteSystemParameterCommand.cs @@ -0,0 +1,14 @@ +using MediatR; + +namespace TakeoutSaaS.Application.App.SystemParameters.Commands; + +/// +/// 删除系统参数命令。 +/// +public sealed record DeleteSystemParameterCommand : IRequest +{ + /// + /// 参数 ID。 + /// + public long ParameterId { get; init; } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs new file mode 100644 index 0000000..86bbfa7 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Commands/UpdateSystemParameterCommand.cs @@ -0,0 +1,40 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; + +namespace TakeoutSaaS.Application.App.SystemParameters.Commands; + +/// +/// 更新系统参数命令。 +/// +public sealed record UpdateSystemParameterCommand : IRequest +{ + /// + /// 参数 ID。 + /// + public long ParameterId { get; init; } + + /// + /// 参数键。 + /// + public string Key { get; init; } = string.Empty; + + /// + /// 参数值。 + /// + public string Value { get; init; } = string.Empty; + + /// + /// 描述。 + /// + public string? Description { get; init; } + + /// + /// 排序值。 + /// + public int SortOrder { get; init; } = 100; + + /// + /// 是否启用。 + /// + public bool IsEnabled { get; init; } = true; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs new file mode 100644 index 0000000..8305ae4 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Dto/SystemParameterDto.cs @@ -0,0 +1,57 @@ +using System.Text.Json.Serialization; +using TakeoutSaaS.Shared.Abstractions.Serialization; + +namespace TakeoutSaaS.Application.App.SystemParameters.Dto; + +/// +/// 系统参数 DTO。 +/// +public sealed class SystemParameterDto +{ + /// + /// 参数 ID。 + /// + [JsonConverter(typeof(SnowflakeIdJsonConverter))] + public long Id { get; init; } + + /// + /// 租户 ID。 + /// + [JsonConverter(typeof(SnowflakeIdJsonConverter))] + public long TenantId { get; init; } + + /// + /// 参数键。 + /// + public string Key { get; init; } = string.Empty; + + /// + /// 参数值。 + /// + public string Value { get; init; } = string.Empty; + + /// + /// 描述。 + /// + public string? Description { get; init; } + + /// + /// 排序值。 + /// + public int SortOrder { get; init; } + + /// + /// 是否启用。 + /// + public bool IsEnabled { get; init; } + + /// + /// 创建时间。 + /// + public DateTime CreatedAt { get; init; } + + /// + /// 最近更新时间。 + /// + public DateTime? UpdatedAt { get; init; } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs new file mode 100644 index 0000000..64ab3c1 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/CreateSystemParameterCommandHandler.cs @@ -0,0 +1,64 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using TakeoutSaaS.Application.App.SystemParameters.Commands; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Domain.SystemParameters.Entities; +using TakeoutSaaS.Domain.SystemParameters.Repositories; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Exceptions; + +namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; + +/// +/// 创建系统参数命令处理器。 +/// +public sealed class CreateSystemParameterCommandHandler( + ISystemParameterRepository repository, + ILogger logger) + : IRequestHandler +{ + private readonly ISystemParameterRepository _repository = repository; + private readonly ILogger _logger = logger; + + /// + public async Task Handle(CreateSystemParameterCommand request, CancellationToken cancellationToken) + { + // 1. 唯一性校验 + var existing = await _repository.FindByKeyAsync(request.Key, cancellationToken); + if (existing != null) + { + throw new BusinessException(ErrorCodes.Conflict, "系统参数键已存在"); + } + + // 2. 构建实体 + var parameter = new SystemParameter + { + Key = request.Key.Trim(), + Value = request.Value.Trim(), + Description = request.Description?.Trim(), + SortOrder = request.SortOrder, + IsEnabled = request.IsEnabled + }; + + // 3. 持久化 + await _repository.AddAsync(parameter, cancellationToken); + await _repository.SaveChangesAsync(cancellationToken); + _logger.LogInformation("创建系统参数 {Key}", parameter.Key); + + // 4. 映射返回 + return MapToDto(parameter); + } + + private static SystemParameterDto MapToDto(SystemParameter parameter) => new() + { + Id = parameter.Id, + TenantId = parameter.TenantId, + Key = parameter.Key, + Value = parameter.Value, + Description = parameter.Description, + SortOrder = parameter.SortOrder, + IsEnabled = parameter.IsEnabled, + CreatedAt = parameter.CreatedAt, + UpdatedAt = parameter.UpdatedAt + }; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs new file mode 100644 index 0000000..cda2c42 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/DeleteSystemParameterCommandHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using TakeoutSaaS.Application.App.SystemParameters.Commands; +using TakeoutSaaS.Domain.SystemParameters.Repositories; + +namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; + +/// +/// 删除系统参数命令处理器。 +/// +public sealed class DeleteSystemParameterCommandHandler( + ISystemParameterRepository repository, + ILogger logger) + : IRequestHandler +{ + private readonly ISystemParameterRepository _repository = repository; + private readonly ILogger _logger = logger; + + /// + public async Task Handle(DeleteSystemParameterCommand request, CancellationToken cancellationToken) + { + var existing = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); + if (existing == null) + { + return false; + } + + await _repository.RemoveAsync(existing, cancellationToken); + await _repository.SaveChangesAsync(cancellationToken); + _logger.LogInformation("删除系统参数 {Key}", existing.Key); + return true; + } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs new file mode 100644 index 0000000..c2bc53a --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/GetSystemParameterByIdQueryHandler.cs @@ -0,0 +1,35 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Application.App.SystemParameters.Queries; +using TakeoutSaaS.Domain.SystemParameters.Repositories; + +namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; + +/// +/// 获取系统参数详情查询处理器。 +/// +public sealed class GetSystemParameterByIdQueryHandler(ISystemParameterRepository repository) + : IRequestHandler +{ + private readonly ISystemParameterRepository _repository = repository; + + /// + public async Task Handle(GetSystemParameterByIdQuery request, CancellationToken cancellationToken) + { + var parameter = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); + return parameter == null ? null : MapToDto(parameter); + } + + private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() + { + Id = parameter.Id, + TenantId = parameter.TenantId, + Key = parameter.Key, + Value = parameter.Value, + Description = parameter.Description, + SortOrder = parameter.SortOrder, + IsEnabled = parameter.IsEnabled, + CreatedAt = parameter.CreatedAt, + UpdatedAt = parameter.UpdatedAt + }; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs new file mode 100644 index 0000000..678b55c --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/SearchSystemParametersQueryHandler.cs @@ -0,0 +1,69 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Application.App.SystemParameters.Queries; +using TakeoutSaaS.Domain.SystemParameters.Repositories; +using TakeoutSaaS.Shared.Abstractions.Results; + +namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; + +/// +/// 系统参数列表查询处理器。 +/// +public sealed class SearchSystemParametersQueryHandler(ISystemParameterRepository repository) + : IRequestHandler> +{ + private readonly ISystemParameterRepository _repository = repository; + + /// + public async Task> Handle(SearchSystemParametersQuery request, CancellationToken cancellationToken) + { + var parameters = await _repository.SearchAsync(request.Keyword, request.IsEnabled, cancellationToken); + + var sorted = ApplySorting(parameters, request.SortBy, request.SortDescending); + var paged = sorted + .Skip((request.Page - 1) * request.PageSize) + .Take(request.PageSize) + .ToList(); + + var items = paged.Select(MapToDto).ToList(); + return new PagedResult(items, request.Page, request.PageSize, parameters.Count); + } + + private static IOrderedEnumerable ApplySorting( + IReadOnlyCollection parameters, + string? sortBy, + bool sortDescending) + { + return sortBy?.ToLowerInvariant() switch + { + "key" => sortDescending + ? parameters.OrderByDescending(x => x.Key) + : parameters.OrderBy(x => x.Key), + "sortorder" => sortDescending + ? parameters.OrderByDescending(x => x.SortOrder) + : parameters.OrderBy(x => x.SortOrder), + "updatedat" => sortDescending + ? parameters.OrderByDescending(x => x.UpdatedAt ?? x.CreatedAt) + : parameters.OrderBy(x => x.UpdatedAt ?? x.CreatedAt), + "isenabled" => sortDescending + ? parameters.OrderByDescending(x => x.IsEnabled) + : parameters.OrderBy(x => x.IsEnabled), + _ => sortDescending + ? parameters.OrderByDescending(x => x.CreatedAt) + : parameters.OrderBy(x => x.CreatedAt) + }; + } + + private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() + { + Id = parameter.Id, + TenantId = parameter.TenantId, + Key = parameter.Key, + Value = parameter.Value, + Description = parameter.Description, + SortOrder = parameter.SortOrder, + IsEnabled = parameter.IsEnabled, + CreatedAt = parameter.CreatedAt, + UpdatedAt = parameter.UpdatedAt + }; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs new file mode 100644 index 0000000..6ba3104 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Handlers/UpdateSystemParameterCommandHandler.cs @@ -0,0 +1,66 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using TakeoutSaaS.Application.App.SystemParameters.Commands; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Domain.SystemParameters.Repositories; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Exceptions; + +namespace TakeoutSaaS.Application.App.SystemParameters.Handlers; + +/// +/// 更新系统参数命令处理器。 +/// +public sealed class UpdateSystemParameterCommandHandler( + ISystemParameterRepository repository, + ILogger logger) + : IRequestHandler +{ + private readonly ISystemParameterRepository _repository = repository; + private readonly ILogger _logger = logger; + + /// + public async Task Handle(UpdateSystemParameterCommand request, CancellationToken cancellationToken) + { + // 1. 读取已有参数 + var existing = await _repository.FindByIdAsync(request.ParameterId, cancellationToken); + if (existing == null) + { + return null; + } + + // 2. 唯一性校验 + var duplicate = await _repository.FindByKeyAsync(request.Key, cancellationToken); + if (duplicate != null && duplicate.Id != existing.Id) + { + throw new BusinessException(ErrorCodes.Conflict, "系统参数键已存在"); + } + + // 3. 更新字段 + existing.Key = request.Key.Trim(); + existing.Value = request.Value.Trim(); + existing.Description = request.Description?.Trim(); + existing.SortOrder = request.SortOrder; + existing.IsEnabled = request.IsEnabled; + + // 4. 持久化 + await _repository.UpdateAsync(existing, cancellationToken); + await _repository.SaveChangesAsync(cancellationToken); + _logger.LogInformation("更新系统参数 {Key}", existing.Key); + + return MapToDto(existing); + } + + private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new() + { + Id = parameter.Id, + TenantId = parameter.TenantId, + Key = parameter.Key, + Value = parameter.Value, + Description = parameter.Description, + SortOrder = parameter.SortOrder, + IsEnabled = parameter.IsEnabled, + CreatedAt = parameter.CreatedAt, + UpdatedAt = parameter.UpdatedAt + }; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs new file mode 100644 index 0000000..09c6b70 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/GetSystemParameterByIdQuery.cs @@ -0,0 +1,9 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; + +namespace TakeoutSaaS.Application.App.SystemParameters.Queries; + +/// +/// 获取系统参数详情查询。 +/// +public sealed record GetSystemParameterByIdQuery(long ParameterId) : IRequest; diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs new file mode 100644 index 0000000..d6e0238 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Queries/SearchSystemParametersQuery.cs @@ -0,0 +1,41 @@ +using MediatR; +using TakeoutSaaS.Application.App.SystemParameters.Dto; +using TakeoutSaaS.Shared.Abstractions.Results; + +namespace TakeoutSaaS.Application.App.SystemParameters.Queries; + +/// +/// 系统参数列表查询。 +/// +public sealed class SearchSystemParametersQuery : IRequest> +{ + /// + /// 关键字(匹配 Key/Description)。 + /// + public string? Keyword { get; init; } + + /// + /// 启用状态过滤。 + /// + public bool? IsEnabled { get; init; } + + /// + /// 页码。 + /// + public int Page { get; init; } = 1; + + /// + /// 每页条数。 + /// + public int PageSize { get; init; } = 20; + + /// + /// 排序字段(key/sortOrder/createdAt/updatedAt/isEnabled)。 + /// + public string? SortBy { get; init; } + + /// + /// 是否倒序。 + /// + public bool SortDescending { get; init; } = true; +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs new file mode 100644 index 0000000..a624833 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/CreateSystemParameterCommandValidator.cs @@ -0,0 +1,21 @@ +using FluentValidation; +using TakeoutSaaS.Application.App.SystemParameters.Commands; + +namespace TakeoutSaaS.Application.App.SystemParameters.Validators; + +/// +/// 创建系统参数命令验证器。 +/// +public sealed class CreateSystemParameterCommandValidator : AbstractValidator +{ + /// + /// 初始化验证规则。 + /// + public CreateSystemParameterCommandValidator() + { + RuleFor(x => x.Key).NotEmpty().MaximumLength(128); + RuleFor(x => x.Value).NotEmpty(); + RuleFor(x => x.Description).MaximumLength(512); + RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); + } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs new file mode 100644 index 0000000..83586ab --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/SearchSystemParametersQueryValidator.cs @@ -0,0 +1,21 @@ +using FluentValidation; +using TakeoutSaaS.Application.App.SystemParameters.Queries; + +namespace TakeoutSaaS.Application.App.SystemParameters.Validators; + +/// +/// 系统参数列表查询验证器。 +/// +public sealed class SearchSystemParametersQueryValidator : AbstractValidator +{ + /// + /// 初始化验证规则。 + /// + public SearchSystemParametersQueryValidator() + { + RuleFor(x => x.Page).GreaterThan(0); + RuleFor(x => x.PageSize).InclusiveBetween(1, 200); + RuleFor(x => x.Keyword).MaximumLength(256); + RuleFor(x => x.SortBy).MaximumLength(64); + } +} diff --git a/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs new file mode 100644 index 0000000..831ad11 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/App/SystemParameters/Validators/UpdateSystemParameterCommandValidator.cs @@ -0,0 +1,22 @@ +using FluentValidation; +using TakeoutSaaS.Application.App.SystemParameters.Commands; + +namespace TakeoutSaaS.Application.App.SystemParameters.Validators; + +/// +/// 更新系统参数命令验证器。 +/// +public sealed class UpdateSystemParameterCommandValidator : AbstractValidator +{ + /// + /// 初始化验证规则。 + /// + public UpdateSystemParameterCommandValidator() + { + RuleFor(x => x.ParameterId).GreaterThan(0); + RuleFor(x => x.Key).NotEmpty().MaximumLength(128); + RuleFor(x => x.Value).NotEmpty(); + RuleFor(x => x.Description).MaximumLength(512); + RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0); + } +} diff --git a/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs b/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs new file mode 100644 index 0000000..c222342 --- /dev/null +++ b/src/Domain/TakeoutSaaS.Domain/SystemParameters/Repositories/ISystemParameterRepository.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using TakeoutSaaS.Domain.SystemParameters.Entities; + +namespace TakeoutSaaS.Domain.SystemParameters.Repositories; + +/// +/// 系统参数仓储接口:提供基础 CRUD 与查询能力。 +/// +public interface ISystemParameterRepository +{ + /// + /// 根据标识获取系统参数。 + /// + Task FindByIdAsync(long id, CancellationToken cancellationToken = default); + + /// + /// 根据键获取系统参数(当前租户)。 + /// + Task FindByKeyAsync(string key, CancellationToken cancellationToken = default); + + /// + /// 查询系统参数列表。 + /// + Task> SearchAsync(string? keyword, bool? isEnabled, CancellationToken cancellationToken = default); + + /// + /// 新增系统参数。 + /// + Task AddAsync(SystemParameter parameter, CancellationToken cancellationToken = default); + + /// + /// 删除系统参数。 + /// + Task RemoveAsync(SystemParameter parameter, CancellationToken cancellationToken = default); + + /// + /// 更新系统参数。 + /// + Task UpdateAsync(SystemParameter parameter, CancellationToken cancellationToken = default); + + /// + /// 持久化更改。 + /// + Task SaveChangesAsync(CancellationToken cancellationToken = default); +} diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs index c680f1e..41cc530 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs @@ -10,6 +10,7 @@ using TakeoutSaaS.Infrastructure.Dictionary.Persistence; using TakeoutSaaS.Infrastructure.Dictionary.Repositories; using TakeoutSaaS.Infrastructure.Dictionary.Services; using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Domain.SystemParameters.Repositories; namespace TakeoutSaaS.Infrastructure.Dictionary.Extensions; @@ -31,6 +32,7 @@ public static class DictionaryServiceCollectionExtensions services.AddPostgresDbContext(DatabaseConstants.DictionaryDataSource); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddOptions() diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs new file mode 100644 index 0000000..1ec7868 --- /dev/null +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfSystemParameterRepository.cs @@ -0,0 +1,80 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using TakeoutSaaS.Domain.SystemParameters.Entities; +using TakeoutSaaS.Domain.SystemParameters.Repositories; +using TakeoutSaaS.Infrastructure.Dictionary.Persistence; + +namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories; + +/// +/// 系统参数 EF Core 仓储实现。 +/// +public sealed class EfSystemParameterRepository(DictionaryDbContext context) : ISystemParameterRepository +{ + /// + public Task FindByIdAsync(long id, CancellationToken cancellationToken = default) + { + return context.SystemParameters + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + } + + /// + public Task FindByKeyAsync(string key, CancellationToken cancellationToken = default) + { + var normalizedKey = key.Trim(); + return context.SystemParameters + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Key == normalizedKey, cancellationToken); + } + + /// + public async Task> SearchAsync(string? keyword, bool? isEnabled, CancellationToken cancellationToken = default) + { + var query = context.SystemParameters.AsNoTracking(); + + if (!string.IsNullOrWhiteSpace(keyword)) + { + var normalized = keyword.Trim(); + query = query.Where(x => x.Key.Contains(normalized) || (x.Description != null && x.Description.Contains(normalized))); + } + + if (isEnabled.HasValue) + { + query = query.Where(x => x.IsEnabled == isEnabled.Value); + } + + var parameters = await query + .OrderBy(x => x.SortOrder) + .ThenBy(x => x.Key) + .ToListAsync(cancellationToken); + + return parameters; + } + + /// + public Task AddAsync(SystemParameter parameter, CancellationToken cancellationToken = default) + { + return context.SystemParameters.AddAsync(parameter, cancellationToken).AsTask(); + } + + /// + public Task RemoveAsync(SystemParameter parameter, CancellationToken cancellationToken = default) + { + context.SystemParameters.Remove(parameter); + return Task.CompletedTask; + } + + /// + public Task UpdateAsync(SystemParameter parameter, CancellationToken cancellationToken = default) + { + context.SystemParameters.Update(parameter); + return Task.CompletedTask; + } + + /// + public Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + return context.SaveChangesAsync(cancellationToken); + } +}