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;
}
}