Files
TakeoutSaaS.TenantApi/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs
MSuMshk 5a26f82628 refactor: 将 Permission 和 MenuDefinition 改为系统级实体
- Permission 和 MenuDefinition 改为继承 AuditableEntityBase(移除 TenantId)
- 添加 PortalType 枚举区分平台端/租户端
- Repository 使用 IgnoreQueryFilters() 查询系统级数据
- 更新所有相关 Handler 和 DTO,移除 TenantId 引用
- 与 AdminApi 保持一致的设计

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 14:49:27 +08:00

75 lines
2.5 KiB
C#

using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
/// <summary>
/// 权限树查询处理器。
/// </summary>
public sealed class PermissionTreeQueryHandler(
IPermissionRepository permissionRepository,
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. 获取租户上下文并查询权限
var tenantId = tenantProvider.GetCurrentTenantId();
var permissions = await permissionRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
// 2. 构建节点映射与父子分组
var nodeMap = permissions.ToDictionary(
x => x.Id,
x => new PermissionTreeDto
{
Id = x.Id,
ParentId = x.ParentId,
SortOrder = x.SortOrder,
Type = x.Type,
Name = x.Name,
Code = x.Code,
Description = x.Description,
Children = Array.Empty<PermissionTreeDto>()
});
var childrenLookup = permissions
.GroupBy(x => x.ParentId)
.ToDictionary(g => g.Key, g => g.OrderBy(c => c.SortOrder).ThenBy(c => c.Id).Select(c => c.Id).ToList());
// 3. 递归组装树,确保子节点引用最新
List<PermissionTreeDto> Build(long parentId)
{
if (!childrenLookup.TryGetValue(parentId, out var childIds))
{
return [];
}
var result = new List<PermissionTreeDto>(childIds.Count);
foreach (var childId in childIds)
{
if (!nodeMap.TryGetValue(childId, out var child))
{
continue;
}
var withChildren = child with { Children = Build(child.Id) };
result.Add(withChildren);
}
return result;
}
// 4. 返回根节点集合
var roots = Build(0);
return roots;
}
}