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; /// /// 权限树查询处理器。 /// public sealed class PermissionTreeQueryHandler( IPermissionRepository permissionRepository, ITenantProvider tenantProvider) : IRequestHandler> { /// /// 构建权限树。 /// /// 查询参数。 /// 取消标记。 /// 权限树列表。 public async Task> 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, TenantId = x.TenantId, ParentId = x.ParentId, SortOrder = x.SortOrder, Type = x.Type, Name = x.Name, Code = x.Code, Description = x.Description, Children = Array.Empty() }); 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 Build(long parentId) { if (!childrenLookup.TryGetValue(parentId, out var childIds)) { return []; } var result = new List(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; } }