From 429d4fb747d3c535caf2785b2976ad19cfdcde11 Mon Sep 17 00:00:00 2001
From: MSuMshk <2039814060@qq.com>
Date: Sun, 23 Nov 2025 12:47:29 +0800
Subject: [PATCH] =?UTF-8?q?chore:=20=E6=8F=90=E4=BA=A4=E5=BD=93=E5=89=8D?=
=?UTF-8?q?=E5=8F=98=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Document/10_TODO.md | 6 +-
.../Controllers/DictionaryController.cs | 126 +++++++
src/Api/TakeoutSaaS.AdminApi/Program.cs | 9 +-
.../TakeoutSaaS.AdminApi.csproj | 1 +
src/Api/TakeoutSaaS.MiniApi/Program.cs | 7 +-
src/Api/TakeoutSaaS.UserApi/Program.cs | 7 +-
.../Abstractions/IDictionaryAppService.cs | 26 ++
.../Abstractions/IDictionaryCache.cs | 27 ++
.../Contracts/CreateDictionaryGroupRequest.cs | 34 ++
.../Contracts/CreateDictionaryItemRequest.cs | 48 +++
.../Contracts/DictionaryBatchQueryRequest.cs | 15 +
.../Contracts/DictionaryGroupQuery.cs | 19 +
.../Contracts/UpdateDictionaryGroupRequest.cs | 26 ++
.../Contracts/UpdateDictionaryItemRequest.cs | 36 ++
.../DictionaryServiceCollectionExtensions.cs | 20 +
.../Dictionary/Models/DictionaryGroupDto.cs | 23 ++
.../Dictionary/Models/DictionaryItemDto.cs | 23 ++
.../Services/DictionaryAppService.cs | 344 ++++++++++++++++++
.../Entities/IMultiTenantEntity.cs | 12 +
.../Tenancy/ITenantContextAccessor.cs | 12 +
.../Tenancy/ITenantProvider.cs | 6 +-
.../Tenancy/TenantConstants.cs | 12 +
.../Tenancy/TenantContext.cs | 45 +++
.../Security/TenantHttpContextExtensions.cs | 31 ++
.../Dictionary/Entities/DictionaryGroup.cs | 61 ++++
.../Dictionary/Entities/DictionaryItem.cs | 69 ++++
.../Dictionary/Enums/DictionaryScope.cs | 17 +
.../Repositories/IDictionaryRepository.cs | 68 ++++
.../Identity/Entities/IdentityUser.cs | 6 +-
.../Identity/Entities/MiniUser.cs | 8 +-
.../Persistence/TenantAwareDbContext.cs | 89 +++++
.../DictionaryServiceCollectionExtensions.cs | 44 +++
.../Options/DictionaryCacheOptions.cs | 12 +
.../Persistence/DictionaryDbContext.cs | 63 ++++
.../Repositories/EfDictionaryRepository.cs | 105 ++++++
.../Services/DistributedDictionaryCache.cs | 56 +++
.../Persistence/IdentityDataSeeder.cs | 16 +
.../Identity/Persistence/IdentityDbContext.cs | 11 +-
.../Identity/Services/JwtTokenService.cs | 12 +-
.../Extensions/DictionaryModuleExtensions.cs | 22 ++
.../TakeoutSaaS.Module.Dictionary.csproj | 3 +-
.../TenantServiceCollectionExtensions.cs | 34 ++
.../TenantContextAccessor.cs | 34 ++
.../TenantProvider.cs | 35 +-
.../TenantResolutionMiddleware.cs | 191 ++++++++++
.../TenantResolutionOptions.cs | 56 +++
46 files changed, 1864 insertions(+), 63 deletions(-)
create mode 100644 src/Api/TakeoutSaaS.AdminApi/Controllers/DictionaryController.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryAppService.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Abstractions/IDictionaryCache.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryGroupRequest.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/CreateDictionaryItemRequest.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryBatchQueryRequest.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/DictionaryGroupQuery.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryGroupRequest.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Contracts/UpdateDictionaryItemRequest.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryGroupDto.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Models/DictionaryItemDto.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs
create mode 100644 src/Core/TakeoutSaaS.Shared.Abstractions/Entities/IMultiTenantEntity.cs
create mode 100644 src/Core/TakeoutSaaS.Shared.Abstractions/Tenancy/ITenantContextAccessor.cs
create mode 100644 src/Core/TakeoutSaaS.Shared.Abstractions/Tenancy/TenantConstants.cs
create mode 100644 src/Core/TakeoutSaaS.Shared.Abstractions/Tenancy/TenantContext.cs
create mode 100644 src/Core/TakeoutSaaS.Shared.Web/Security/TenantHttpContextExtensions.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Entities/DictionaryGroup.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Entities/DictionaryItem.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Enums/DictionaryScope.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Dictionary/Repositories/IDictionaryRepository.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Common/Persistence/TenantAwareDbContext.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Extensions/DictionaryServiceCollectionExtensions.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Options/DictionaryCacheOptions.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Persistence/DictionaryDbContext.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Repositories/EfDictionaryRepository.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/Services/DistributedDictionaryCache.cs
create mode 100644 src/Modules/TakeoutSaaS.Module.Dictionary/Extensions/DictionaryModuleExtensions.cs
create mode 100644 src/Modules/TakeoutSaaS.Module.Tenancy/Extensions/TenantServiceCollectionExtensions.cs
create mode 100644 src/Modules/TakeoutSaaS.Module.Tenancy/TenantContextAccessor.cs
create mode 100644 src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionMiddleware.cs
create mode 100644 src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionOptions.cs
diff --git a/Document/10_TODO.md b/Document/10_TODO.md
index 9190463..ddb4c41 100644
--- a/Document/10_TODO.md
+++ b/Document/10_TODO.md
@@ -17,9 +17,9 @@
- [x] 登录防刷限流(MiniApi)
## C. 多租户与参数字典
-- [ ] 多租户中间件:从 Header/域名解析租户(Shared.Web + Tenancy)
-- [ ] EF Core 全局查询过滤(tenant_id)
-- [ ] 参数字典模块(系统参数/业务参数)CRUD 与缓存(Dictionary 模块)
+- [x] 多租户中间件:从 Header/域名解析租户(Shared.Web + Tenancy)
+- [x] EF Core 全局查询过滤(tenant_id)
+- [x] 参数字典模块(系统参数/业务参数)CRUD 与缓存(Dictionary 模块)
## D. 数据访问与多数据源
- [ ] EF Core 10 基础上下文、实体基类、审计字段
diff --git a/src/Api/TakeoutSaaS.AdminApi/Controllers/DictionaryController.cs b/src/Api/TakeoutSaaS.AdminApi/Controllers/DictionaryController.cs
new file mode 100644
index 0000000..7232ed2
--- /dev/null
+++ b/src/Api/TakeoutSaaS.AdminApi/Controllers/DictionaryController.cs
@@ -0,0 +1,126 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using TakeoutSaaS.Application.Dictionary.Abstractions;
+using TakeoutSaaS.Application.Dictionary.Contracts;
+using TakeoutSaaS.Application.Dictionary.Models;
+using TakeoutSaaS.Module.Authorization.Attributes;
+using TakeoutSaaS.Shared.Abstractions.Results;
+using TakeoutSaaS.Shared.Web.Api;
+
+namespace TakeoutSaaS.AdminApi.Controllers;
+
+///
+/// 参数字典管理。
+///
+[ApiVersion("1.0")]
+[Authorize]
+[Route("api/admin/v{version:apiVersion}/dictionaries")]
+public sealed class DictionaryController : BaseApiController
+{
+ private readonly IDictionaryAppService _dictionaryAppService;
+
+ ///
+ /// 初始化字典控制器。
+ ///
+ /// 字典服务
+ public DictionaryController(IDictionaryAppService dictionaryAppService)
+ {
+ _dictionaryAppService = dictionaryAppService;
+ }
+
+ ///
+ /// 查询字典分组。
+ ///
+ [HttpGet]
+ [PermissionAuthorize("dictionary:group:read")]
+ [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)]
+ public async Task>> GetGroups([FromQuery] DictionaryGroupQuery query, CancellationToken cancellationToken)
+ {
+ var groups = await _dictionaryAppService.SearchGroupsAsync(query, cancellationToken);
+ return ApiResponse>.Ok(groups);
+ }
+
+ ///
+ /// 创建字典分组。
+ ///
+ [HttpPost]
+ [PermissionAuthorize("dictionary:group:create")]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ public async Task> CreateGroup([FromBody] CreateDictionaryGroupRequest request, CancellationToken cancellationToken)
+ {
+ var group = await _dictionaryAppService.CreateGroupAsync(request, cancellationToken);
+ return ApiResponse.Ok(group);
+ }
+
+ ///
+ /// 更新字典分组。
+ ///
+ [HttpPut("{groupId:guid}")]
+ [PermissionAuthorize("dictionary:group:update")]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ public async Task> UpdateGroup(Guid groupId, [FromBody] UpdateDictionaryGroupRequest request, CancellationToken cancellationToken)
+ {
+ var group = await _dictionaryAppService.UpdateGroupAsync(groupId, request, cancellationToken);
+ return ApiResponse.Ok(group);
+ }
+
+ ///
+ /// 删除字典分组。
+ ///
+ [HttpDelete("{groupId:guid}")]
+ [PermissionAuthorize("dictionary:group:delete")]
+ [ProducesResponseType(typeof(ApiResponse