PlatformMenuHelper.cs 3.18 KB
using FoodLabeling.Application.Services.DbModels;

namespace FoodLabeling.Application.Helpers;

/// <summary>
/// 平台端菜单判定(与 ThSaasMenuPermissionCatalog.IsPlatformOnlyMenu 一致,避免 Application 依赖 Th 程序集)
/// </summary>
public static class PlatformMenuHelper
{
    /// <summary>
    /// 是否为仅平台端菜单(不可分配给公司)
    /// </summary>
    public static bool IsPlatformOnlyMenu(MenuDbEntity? menu)
    {
        if (menu == null)
        {
            return true;
        }

        var code = menu.PermissionCode?.Trim() ?? string.Empty;
        if (code.StartsWith("menu.platform", StringComparison.OrdinalIgnoreCase))
        {
            return true;
        }

        var router = menu.Router?.Trim() ?? string.Empty;
        return router.StartsWith("/platform", StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 从全量菜单中保留平台菜单及其祖先节点,以便组装菜单树
    /// </summary>
    public static List<MenuDbEntity> FilterPlatformMenusWithAncestors(IReadOnlyList<MenuDbEntity> allMenus)
    {
        if (allMenus.Count == 0)
        {
            return new List<MenuDbEntity>();
        }

        var byId = allMenus
            .GroupBy(m => m.Id, StringComparer.OrdinalIgnoreCase)
            .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);

        var keepIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        foreach (var menu in allMenus.Where(IsPlatformOnlyMenu))
        {
            IncludeWithAncestors(menu.Id, byId, keepIds);
        }

        return allMenus.Where(m => keepIds.Contains(m.Id)).ToList();
    }

    private static void IncludeWithAncestors(
        string menuId,
        IReadOnlyDictionary<string, MenuDbEntity> byId,
        HashSet<string> keepIds)
    {
        if (!byId.TryGetValue(menuId, out var current))
        {
            return;
        }

        if (!keepIds.Add(current.Id))
        {
            return;
        }

        var parentId = current.ParentId?.Trim() ?? "0";
        if (parentId == "0" || parentId == Guid.Empty.ToString())
        {
            return;
        }

        IncludeWithAncestors(parentId, byId, keepIds);
    }

    /// <summary>
    /// 仅保留公司已开通菜单及其祖先节点(租户业务库 menu 表可能含 Seed 全量菜单)。
    /// </summary>
    public static List<MenuDbEntity> FilterCompanyMenusWithAncestors(
        IReadOnlyList<MenuDbEntity> allMenus,
        IReadOnlySet<string> enabledMenuIds)
    {
        if (allMenus.Count == 0 || enabledMenuIds.Count == 0)
        {
            return new List<MenuDbEntity>();
        }

        var byId = allMenus
            .Where(m => !m.IsDeleted && !IsPlatformOnlyMenu(m))
            .GroupBy(m => m.Id, StringComparer.OrdinalIgnoreCase)
            .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);

        var keepIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        foreach (var menuId in enabledMenuIds)
        {
            IncludeWithAncestors(menuId?.Trim() ?? string.Empty, byId, keepIds);
        }

        return allMenus.Where(m => keepIds.Contains(m.Id)).ToList();
    }
}