docs: 完善身份模块文档注释与字段说明

This commit is contained in:
2025-12-12 11:08:39 +08:00
parent 715cbb3d36
commit 641598de86
36 changed files with 409 additions and 37 deletions

View File

@@ -7,6 +7,13 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record AssignUserRolesCommand : IRequest<bool>
{
/// <summary>
/// 用户 ID。
/// </summary>
public long UserId { get; init; }
/// <summary>
/// 角色 ID 集合。
/// </summary>
public long[] RoleIds { get; init; } = Array.Empty<long>();
}

View File

@@ -7,7 +7,18 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record BindRolePermissionsCommand : IRequest<bool>
{
/// <summary>
/// 角色 ID。
/// </summary>
public long RoleId { get; init; }
/// <summary>
/// 租户 ID可选空则取当前上下文
/// </summary>
public long? TenantId { get; init; }
/// <summary>
/// 权限 ID 集合。
/// </summary>
public long[] PermissionIds { get; init; } = Array.Empty<long>();
}

View File

@@ -9,18 +9,73 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record CreateMenuCommand : IRequest<MenuDefinitionDto>
{
/// <summary>
/// 父级菜单 ID。
/// </summary>
public long ParentId { get; init; }
/// <summary>
/// 菜单名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 路由路径。
/// </summary>
public string Path { get; init; } = string.Empty;
/// <summary>
/// 前端组件路径。
/// </summary>
public string Component { get; init; } = string.Empty;
/// <summary>
/// 显示标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 图标。
/// </summary>
public string? Icon { get; init; }
/// <summary>
/// 是否外链。
/// </summary>
public bool IsIframe { get; init; }
/// <summary>
/// 外链地址。
/// </summary>
public string? Link { get; init; }
/// <summary>
/// 是否缓存。
/// </summary>
public bool KeepAlive { get; init; }
/// <summary>
/// 排序序号。
/// </summary>
public int SortOrder { get; init; }
/// <summary>
/// 访问所需权限。
/// </summary>
public IReadOnlyCollection<string> RequiredPermissions { get; init; } = [];
/// <summary>
/// 元信息权限。
/// </summary>
public IReadOnlyCollection<string> MetaPermissions { get; init; } = [];
/// <summary>
/// 元信息角色。
/// </summary>
public IReadOnlyCollection<string> MetaRoles { get; init; } = [];
/// <summary>
/// 按钮权限集合。
/// </summary>
public IReadOnlyCollection<MenuAuthItemDto> AuthList { get; init; } = [];
}

View File

@@ -8,10 +8,33 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record CreatePermissionCommand : IRequest<PermissionDto>
{
/// <summary>
/// 父级权限 ID。
/// </summary>
public long ParentId { get; init; } = 0;
/// <summary>
/// 排序序号。
/// </summary>
public int SortOrder { get; init; } = 0;
/// <summary>
/// 权限类型group/leaf
/// </summary>
public string Type { get; init; } = "leaf";
/// <summary>
/// 权限名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 权限编码。
/// </summary>
public string Code { get; init; } = string.Empty;
/// <summary>
/// 描述。
/// </summary>
public string? Description { get; init; }
}

View File

@@ -13,7 +13,18 @@ public sealed record CreateRoleCommand : IRequest<RoleDto>
/// </summary>
public long? TenantId { get; init; }
/// <summary>
/// 角色名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 角色编码。
/// </summary>
public string Code { get; init; } = string.Empty;
/// <summary>
/// 描述。
/// </summary>
public string? Description { get; init; }
}

View File

@@ -7,5 +7,8 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record DeleteMenuCommand : IRequest<bool>
{
/// <summary>
/// 菜单 ID。
/// </summary>
public long Id { get; init; }
}

View File

@@ -7,5 +7,8 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record DeletePermissionCommand : IRequest<bool>
{
/// <summary>
/// 权限 ID。
/// </summary>
public long PermissionId { get; init; }
}

View File

@@ -7,6 +7,9 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record DeleteRoleCommand : IRequest<bool>
{
/// <summary>
/// 角色 ID。
/// </summary>
public long RoleId { get; init; }
/// <summary>

View File

@@ -9,19 +9,78 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record UpdateMenuCommand : IRequest<MenuDefinitionDto?>
{
/// <summary>
/// 菜单 ID。
/// </summary>
public long Id { get; init; }
/// <summary>
/// 父级菜单 ID。
/// </summary>
public long ParentId { get; init; }
/// <summary>
/// 菜单名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 路由路径。
/// </summary>
public string Path { get; init; } = string.Empty;
/// <summary>
/// 前端组件路径。
/// </summary>
public string Component { get; init; } = string.Empty;
/// <summary>
/// 显示标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 图标。
/// </summary>
public string? Icon { get; init; }
/// <summary>
/// 是否外链。
/// </summary>
public bool IsIframe { get; init; }
/// <summary>
/// 外链地址。
/// </summary>
public string? Link { get; init; }
/// <summary>
/// 是否缓存。
/// </summary>
public bool KeepAlive { get; init; }
/// <summary>
/// 排序序号。
/// </summary>
public int SortOrder { get; init; }
/// <summary>
/// 访问所需权限。
/// </summary>
public IReadOnlyCollection<string> RequiredPermissions { get; init; } = [];
/// <summary>
/// 元信息权限。
/// </summary>
public IReadOnlyCollection<string> MetaPermissions { get; init; } = [];
/// <summary>
/// 元信息角色。
/// </summary>
public IReadOnlyCollection<string> MetaRoles { get; init; } = [];
/// <summary>
/// 按钮权限集合。
/// </summary>
public IReadOnlyCollection<MenuAuthItemDto> AuthList { get; init; } = [];
}

View File

@@ -8,10 +8,33 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record UpdatePermissionCommand : IRequest<PermissionDto?>
{
/// <summary>
/// 权限 ID。
/// </summary>
public long PermissionId { get; init; }
/// <summary>
/// 父级权限 ID。
/// </summary>
public long ParentId { get; init; }
/// <summary>
/// 排序序号。
/// </summary>
public int SortOrder { get; init; }
/// <summary>
/// 权限类型group/leaf
/// </summary>
public string Type { get; init; } = "leaf";
/// <summary>
/// 权限名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 描述。
/// </summary>
public string? Description { get; init; }
}

View File

@@ -8,6 +8,9 @@ namespace TakeoutSaaS.Application.Identity.Commands;
/// </summary>
public sealed record UpdateRoleCommand : IRequest<RoleDto?>
{
/// <summary>
/// 角色 ID。
/// </summary>
public long RoleId { get; init; }
/// <summary>
@@ -15,6 +18,13 @@ public sealed record UpdateRoleCommand : IRequest<RoleDto?>
/// </summary>
public long? TenantId { get; init; }
/// <summary>
/// 角色名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 角色描述。
/// </summary>
public string? Description { get; init; }
}

View File

@@ -7,10 +7,16 @@ namespace TakeoutSaaS.Application.Identity.Contracts;
/// </summary>
public sealed class AdminLoginRequest
{
/// <summary>
/// 账号。
/// </summary>
[Required]
[MaxLength(64)]
public string Account { get; set; } = string.Empty;
/// <summary>
/// 密码。
/// </summary>
[Required]
[MaxLength(128)]
public string Password { get; set; } = string.Empty;

View File

@@ -7,6 +7,9 @@ namespace TakeoutSaaS.Application.Identity.Contracts;
/// </summary>
public sealed class RefreshTokenRequest
{
/// <summary>
/// 刷新令牌。
/// </summary>
[Required]
[MaxLength(256)]
public string RefreshToken { get; set; } = string.Empty;

View File

@@ -7,17 +7,32 @@ namespace TakeoutSaaS.Application.Identity.Contracts;
/// </summary>
public sealed class WeChatLoginRequest
{
/// <summary>
/// wx.login 返回的临时 code。
/// </summary>
[Required]
[MaxLength(128)]
public string Code { get; set; } = string.Empty;
/// <summary>
/// 用户昵称。
/// </summary>
[MaxLength(64)]
public string? Nickname { get; set; }
/// <summary>
/// 头像地址。
/// </summary>
[MaxLength(256)]
public string? Avatar { get; set; }
/// <summary>
/// 加密用户数据。
/// </summary>
public string? EncryptedData { get; set; }
/// <summary>
/// 加密向量。
/// </summary>
public string? Iv { get; set; }
}

View File

@@ -13,6 +13,12 @@ public sealed class AssignUserRolesCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<AssignUserRolesCommand, bool>
{
/// <summary>
/// 处理用户角色分配请求。
/// </summary>
/// <param name="request">分配命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(AssignUserRolesCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -13,6 +13,12 @@ public sealed class BindRolePermissionsCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<BindRolePermissionsCommand, bool>
{
/// <summary>
/// 处理角色权限绑定请求。
/// </summary>
/// <param name="request">绑定命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -15,6 +15,12 @@ public sealed class CreatePermissionCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<CreatePermissionCommand, PermissionDto>
{
/// <summary>
/// 处理创建权限请求。
/// </summary>
/// <param name="request">创建命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>创建后的权限 DTO。</returns>
public async Task<PermissionDto> Handle(CreatePermissionCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -17,6 +17,12 @@ public sealed class CreateRoleCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<CreateRoleCommand, RoleDto>
{
/// <summary>
/// 处理创建角色请求。
/// </summary>
/// <param name="request">创建命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>创建后的角色 DTO。</returns>
public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -13,6 +13,12 @@ public sealed class DeletePermissionCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<DeletePermissionCommand, bool>
{
/// <summary>
/// 处理删除权限请求。
/// </summary>
/// <param name="request">删除命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(DeletePermissionCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -13,6 +13,12 @@ public sealed class DeleteRoleCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<DeleteRoleCommand, bool>
{
/// <summary>
/// 处理删除角色请求。
/// </summary>
/// <param name="request">删除命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(DeleteRoleCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文

View File

@@ -10,6 +10,12 @@ namespace TakeoutSaaS.Application.Identity.Handlers;
public sealed class DeleteRoleTemplateCommandHandler(IRoleTemplateRepository roleTemplateRepository)
: IRequestHandler<DeleteRoleTemplateCommand, bool>
{
/// <summary>
/// 处理删除角色模板请求。
/// </summary>
/// <param name="request">删除命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(DeleteRoleTemplateCommand request, CancellationToken cancellationToken)
{
// 1. 查询模板

View File

@@ -9,6 +9,11 @@ namespace TakeoutSaaS.Application.Identity.Handlers;
/// </summary>
internal static class MenuMapper
{
/// <summary>
/// 将菜单实体映射为 DTO。
/// </summary>
/// <param name="entity">菜单实体。</param>
/// <returns>菜单定义 DTO。</returns>
public static MenuDefinitionDto ToDto(MenuDefinition entity)
{
// 1. 解析权限字段
@@ -42,6 +47,11 @@ internal static class MenuMapper
};
}
/// <summary>
/// 将 DTO 字段填充到实体。
/// </summary>
/// <param name="entity">菜单实体。</param>
/// <param name="dto">菜单 DTO。</param>
public static void FillEntity(MenuDefinition entity, MenuDefinitionDto dto)
{
// 1. 赋值基础字段
@@ -65,6 +75,14 @@ internal static class MenuMapper
: JsonSerializer.Serialize(dto.AuthList);
}
/// <summary>
/// 构建或更新菜单实体并返回 DTO。
/// </summary>
/// <param name="existing">已存在的菜单实体。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="name">菜单名称。</param>
/// <param name="payload">菜单 DTO 载荷。</param>
/// <returns>菜单定义 DTO。</returns>
public static MenuDefinitionDto FromCommand(MenuDefinition? existing, long tenantId, string name, MenuDefinitionDto payload)
{
// 1. 构造实体
@@ -81,11 +99,21 @@ internal static class MenuMapper
return ToDto(entity);
}
/// <summary>
/// 将权限/角色集合合并为存储字符串。
/// </summary>
/// <param name="codes">编码集合。</param>
/// <returns>逗号分隔字符串。</returns>
public static string JoinCodes(IEnumerable<string> codes)
{
return string.Join(',', codes.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct(StringComparer.OrdinalIgnoreCase));
}
/// <summary>
/// 将逗号分隔编码拆分为集合。
/// </summary>
/// <param name="codes">编码字符串。</param>
/// <returns>编码数组。</returns>
public static string[] SplitCodes(string? codes)
{
if (string.IsNullOrWhiteSpace(codes))

View File

@@ -14,6 +14,12 @@ public sealed class PermissionTreeQueryHandler(
ITenantProvider tenantProvider)
: IRequestHandler<PermissionTreeQuery, IReadOnlyList<PermissionTreeDto>>
{
/// <summary>
/// 构建权限树。
/// </summary>
/// <param name="request">查询参数。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>权限树列表。</returns>
public async Task<IReadOnlyList<PermissionTreeDto>> Handle(PermissionTreeQuery request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文并查询权限

View File

@@ -15,6 +15,12 @@ public sealed class SearchPermissionsQueryHandler(
ITenantProvider tenantProvider)
: IRequestHandler<SearchPermissionsQuery, PagedResult<PermissionDto>>
{
/// <summary>
/// 执行权限分页查询。
/// </summary>
/// <param name="request">查询参数。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<PagedResult<PermissionDto>> Handle(SearchPermissionsQuery request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文并查询权限

View File

@@ -15,6 +15,12 @@ public sealed class SearchRolesQueryHandler(
ITenantProvider tenantProvider)
: IRequestHandler<SearchRolesQuery, PagedResult<RoleDto>>
{
/// <summary>
/// 执行角色分页查询。
/// </summary>
/// <param name="request">查询参数。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<PagedResult<RoleDto>> Handle(SearchRolesQuery request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文并查询角色

View File

@@ -14,6 +14,12 @@ public sealed class UpdatePermissionCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<UpdatePermissionCommand, PermissionDto?>
{
/// <summary>
/// 执行权限更新。
/// </summary>
/// <param name="request">更新命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>更新后的权限 DTO 或 null。</returns>
public async Task<PermissionDto?> Handle(UpdatePermissionCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文并查询权限

View File

@@ -14,6 +14,12 @@ public sealed class UpdateRoleCommandHandler(
ITenantProvider tenantProvider)
: IRequestHandler<UpdateRoleCommand, RoleDto?>
{
/// <summary>
/// 执行角色更新。
/// </summary>
/// <param name="request">更新命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>更新后的角色 DTO 或 null。</returns>
public async Task<RoleDto?> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
{
// 1. 获取租户上下文并查询角色

View File

@@ -9,9 +9,24 @@ namespace TakeoutSaaS.Application.Identity.Queries;
/// </summary>
public sealed class SearchPermissionsQuery : IRequest<PagedResult<PermissionDto>>
{
/// <summary>
/// 搜索关键字。
/// </summary>
public string? Keyword { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页条数。
/// </summary>
public int PageSize { get; init; } = 20;
/// <summary>
/// 排序字段。
/// </summary>
public string? SortBy { get; init; }
/// <summary>
/// 是否降序。
/// </summary>
public bool SortDescending { get; init; } = true;
}

View File

@@ -14,9 +14,24 @@ public sealed class SearchRolesQuery : IRequest<PagedResult<RoleDto>>
/// </summary>
public long? TenantId { get; init; }
/// <summary>
/// 搜索关键字。
/// </summary>
public string? Keyword { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页条数。
/// </summary>
public int PageSize { get; init; } = 20;
/// <summary>
/// 排序字段。
/// </summary>
public string? SortBy { get; init; }
/// <summary>
/// 是否降序。
/// </summary>
public bool SortDescending { get; init; } = true;
}