From 0bcad8ba7eb09e6f548b8d9aa8517e8c1aedef0f Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Fri, 30 Jan 2026 07:53:25 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2=E5=92=8C?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 获取租户角色列表:GET /api/admin/v1/tenants/{tenantId}/roles - 删除租户角色:DELETE /api/admin/v1/tenants/{tenantId}/roles/{roleId} Co-Authored-By: Claude Opus 4.5 --- .../Controllers/TenantRolesController.cs | 60 +++++++++++++++++++ .../Commands/DeleteTenantRoleCommand.cs | 19 ++++++ .../DeleteTenantRoleCommandHandler.cs | 33 ++++++++++ .../Handlers/ListTenantRolesQueryHandler.cs | 48 +++++++++++++++ .../Identity/Queries/ListTenantRolesQuery.cs | 31 ++++++++++ 5 files changed, 191 insertions(+) create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteTenantRoleCommand.cs create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteTenantRoleCommandHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ListTenantRolesQueryHandler.cs create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/ListTenantRolesQuery.cs diff --git a/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs b/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs index 4cc8315..963929b 100644 --- a/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs +++ b/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs @@ -19,6 +19,41 @@ namespace TakeoutSaaS.AdminApi.Controllers; [Route("api/admin/v{version:apiVersion}/tenants/{tenantId:long}/roles")] public sealed class TenantRolesController(IMediator mediator) : BaseApiController { + /// + /// 获取租户角色列表。 + /// + /// 租户 ID。 + /// 关键字(角色名称/编码)。 + /// 页码(从 1 开始)。 + /// 每页条数。 + /// 取消标记。 + /// 角色分页列表。 + [HttpGet] + [PermissionAuthorize("identity:role:read")] + [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)] + public async Task>> List( + long tenantId, + [FromQuery] string? keyword, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20, + CancellationToken cancellationToken = default) + { + // 1. 构造查询 + var query = new ListTenantRolesQuery + { + TenantId = tenantId, + Keyword = keyword, + Page = page, + PageSize = pageSize + }; + + // 2. 执行查询 + var result = await mediator.Send(query, cancellationToken); + + // 3. 返回分页结果 + return ApiResponse>.Ok(result); + } + /// /// 创建租户角色。 /// @@ -125,4 +160,29 @@ public sealed class TenantRolesController(IMediator mediator) : BaseApiControlle // 3. 返回更新结果 return ApiResponse.Ok(result); } + + /// + /// 删除租户角色。 + /// + /// 租户 ID。 + /// 角色 ID。 + /// 取消标记。 + /// 删除结果。 + [HttpDelete("{roleId:long}")] + [PermissionAuthorize("identity:role:delete")] + [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] + public async Task> Delete( + long tenantId, + long roleId, + CancellationToken cancellationToken) + { + // 1. 构造命令 + var command = new DeleteTenantRoleCommand { TenantId = tenantId, RoleId = roleId }; + + // 2. 执行删除 + var result = await mediator.Send(command, cancellationToken); + + // 3. 返回删除结果 + return ApiResponse.Ok(result); + } } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteTenantRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteTenantRoleCommand.cs new file mode 100644 index 0000000..9c18368 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteTenantRoleCommand.cs @@ -0,0 +1,19 @@ +using MediatR; + +namespace TakeoutSaaS.Application.Identity.Commands; + +/// +/// 删除租户角色命令。 +/// +public sealed record DeleteTenantRoleCommand : IRequest +{ + /// + /// 租户 ID(由路由绑定)。 + /// + public long TenantId { get; init; } + + /// + /// 角色 ID(由路由绑定)。 + /// + public long RoleId { get; init; } +} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteTenantRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteTenantRoleCommandHandler.cs new file mode 100644 index 0000000..b55db20 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteTenantRoleCommandHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using TakeoutSaaS.Application.Identity.Commands; +using TakeoutSaaS.Domain.Identity.Enums; +using TakeoutSaaS.Domain.Identity.Repositories; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Exceptions; + +namespace TakeoutSaaS.Application.Identity.Handlers; + +/// +/// 删除租户角色命令处理器。 +/// +public sealed class DeleteTenantRoleCommandHandler(IRoleRepository roleRepository) + : IRequestHandler +{ + /// + public async Task Handle(DeleteTenantRoleCommand request, CancellationToken cancellationToken) + { + // 1. 校验角色存在 + var role = await roleRepository.FindByIdAsync(PortalType.Tenant, request.TenantId, request.RoleId, cancellationToken); + if (role is null) + { + throw new BusinessException(ErrorCodes.NotFound, "角色不存在"); + } + + // 2. 执行软删除 + await roleRepository.DeleteAsync(PortalType.Tenant, request.TenantId, request.RoleId, cancellationToken); + await roleRepository.SaveChangesAsync(cancellationToken); + + // 3. 返回成功 + return true; + } +} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListTenantRolesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListTenantRolesQueryHandler.cs new file mode 100644 index 0000000..51c10fe --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListTenantRolesQueryHandler.cs @@ -0,0 +1,48 @@ +using MediatR; +using TakeoutSaaS.Application.Identity.Contracts; +using TakeoutSaaS.Application.Identity.Queries; +using TakeoutSaaS.Domain.Identity.Enums; +using TakeoutSaaS.Domain.Identity.Repositories; +using TakeoutSaaS.Shared.Abstractions.Results; + +namespace TakeoutSaaS.Application.Identity.Handlers; + +/// +/// 获取租户角色列表查询处理器。 +/// +public sealed class ListTenantRolesQueryHandler(IRoleRepository roleRepository) + : IRequestHandler> +{ + /// + public async Task> Handle(ListTenantRolesQuery request, CancellationToken cancellationToken) + { + // 1. 查询租户下所有角色 + var roles = await roleRepository.SearchAsync(PortalType.Tenant, request.TenantId, request.Keyword, cancellationToken); + + // 2. 计算分页参数 + var totalCount = roles.Count; + var page = Math.Max(1, request.Page); + var pageSize = Math.Clamp(request.PageSize, 1, 100); + + // 3. 应用分页 + var pagedRoles = roles + .OrderBy(r => r.Code) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToArray(); + + // 4. 映射 DTO + var dtos = pagedRoles.Select(role => new RoleDto + { + Portal = role.Portal, + Id = role.Id, + TenantId = role.TenantId, + Code = role.Code, + Name = role.Name, + Description = role.Description + }).ToArray(); + + // 5. 返回分页结果 + return new PagedResult(dtos, page, pageSize, totalCount); + } +} diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/ListTenantRolesQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/ListTenantRolesQuery.cs new file mode 100644 index 0000000..256f635 --- /dev/null +++ b/src/Application/TakeoutSaaS.Application/Identity/Queries/ListTenantRolesQuery.cs @@ -0,0 +1,31 @@ +using MediatR; +using TakeoutSaaS.Application.Identity.Contracts; +using TakeoutSaaS.Shared.Abstractions.Results; + +namespace TakeoutSaaS.Application.Identity.Queries; + +/// +/// 获取租户角色列表查询。 +/// +public sealed record ListTenantRolesQuery : IRequest> +{ + /// + /// 租户 ID。 + /// + public long TenantId { get; init; } + + /// + /// 关键字(角色名称/编码)。 + /// + public string? Keyword { get; init; } + + /// + /// 页码(从 1 开始)。 + /// + public int Page { get; init; } = 1; + + /// + /// 每页条数。 + /// + public int PageSize { get; init; } = 20; +}