RbacMenuAppService.cs 8.33 KB
using FoodLabeling.Application.Contracts.Dtos.RbacMenu;
using FoodLabeling.Application.Contracts.IServices;
using FoodLabeling.Application.Services.DbModels;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Yi.Framework.SqlSugarCore.Abstractions;

namespace FoodLabeling.Application.Services;

/// <summary>
/// 权限(Menu)管理(食品标签-美国版对外)
/// </summary>
public class RbacMenuAppService : ApplicationService, IRbacMenuAppService
{
    private readonly ISqlSugarDbContext _dbContext;

    public RbacMenuAppService(ISqlSugarDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    /// <inheritdoc />
    public async Task<List<RbacMenuGetListOutputDto>> GetListAsync([FromQuery] RbacMenuGetListInputVo input)
    {
        var query = _dbContext.SqlSugarClient.Queryable<MenuDbEntity>()
            .Where(x => x.IsDeleted == false)
            .WhereIF(!string.IsNullOrWhiteSpace(input.MenuName), x => x.MenuName.Contains(input.MenuName!.Trim()))
            .WhereIF(input.State is not null, x => x.State == input.State)
            .WhereIF(input.MenuSource is not null, x => x.MenuSource == input.MenuSource!.Value)
            .OrderBy(x => x.OrderNum, OrderByType.Desc);

        var entities = await query.ToListAsync();

        return entities.Select(x => new RbacMenuGetListOutputDto
        {
            Id = x.Id,
            ParentId = x.ParentId,
            MenuName = x.MenuName ?? string.Empty,
            RouterName = x.RouterName,
            Router = x.Router,
            PermissionCode = x.PermissionCode,
            MenuType = x.MenuType,
            MenuSource = x.MenuSource,
            OrderNum = x.OrderNum,
            State = x.State
        }).ToList();
    }

    /// <inheritdoc />
    public async Task<RbacMenuGetListOutputDto> GetAsync(string id)
    {
        var entity = await _dbContext.SqlSugarClient.Queryable<MenuDbEntity>()
            .Where(x => x.Id == id && x.IsDeleted == false)
            .SingleAsync();
        if (entity is null)
        {
            throw new UserFriendlyException("权限不存在");
        }

        return new RbacMenuGetListOutputDto
        {
            Id = entity.Id,
            ParentId = entity.ParentId,
            MenuName = entity.MenuName ?? string.Empty,
            RouterName = entity.RouterName,
            Router = entity.Router,
            PermissionCode = entity.PermissionCode,
            MenuType = entity.MenuType,
            MenuSource = entity.MenuSource,
            OrderNum = entity.OrderNum,
            State = entity.State
        };
    }

    /// <inheritdoc />
    public async Task<RbacMenuGetListOutputDto> CreateAsync([FromBody] RbacMenuCreateInputVo input)
    {
        var name = input.MenuName?.Trim();
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new UserFriendlyException("权限名称不能为空");
        }

        var entity = new MenuDbEntity
        {
            Id = GuidGenerator.Create().ToString(),
            MenuName = name,
            ParentId = string.IsNullOrWhiteSpace(input.ParentId) ? "0" : input.ParentId.Trim(),
            MenuType = input.MenuType,
            MenuSource = input.MenuSource,
            PermissionCode = input.PermissionCode?.Trim(),
            Router = input.Router?.Trim(),
            Component = input.Component?.Trim(),
            OrderNum = input.OrderNum,
            State = input.State,
            IsDeleted = false,
            CreationTime = DateTime.Now,
            IsCache = false,
            IsLink = false,
            IsShow = true,
            ConcurrencyStamp = string.Empty
        };
        await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync();
        return await GetAsync(entity.Id);
    }

    /// <inheritdoc />
    public async Task<RbacMenuGetListOutputDto> UpdateAsync(string id, [FromBody] RbacMenuUpdateInputVo input)
    {
        var entity = await _dbContext.SqlSugarClient.Queryable<MenuDbEntity>()
            .Where(x => x.Id == id && x.IsDeleted == false)
            .SingleAsync();
        if (entity is null)
        {
            throw new UserFriendlyException("权限不存在");
        }

        var name = input.MenuName?.Trim();
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new UserFriendlyException("权限名称不能为空");
        }

        entity.MenuName = name;
        entity.ParentId = string.IsNullOrWhiteSpace(input.ParentId) ? "0" : input.ParentId.Trim();
        entity.MenuType = input.MenuType;
        entity.MenuSource = input.MenuSource;
        entity.PermissionCode = input.PermissionCode?.Trim();
        entity.Router = input.Router?.Trim();
        entity.Component = input.Component?.Trim();
        entity.OrderNum = input.OrderNum;
        entity.State = input.State;
        entity.LastModificationTime = DateTime.Now;

        await _dbContext.SqlSugarClient.Updateable(entity)
            .Where(x => x.Id == entity.Id)
            .ExecuteCommandAsync();
        return await GetAsync(entity.Id);
    }

    /// <inheritdoc />
    public async Task DeleteAsync([FromBody] List<string> ids)
    {
        var idList = ids?.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct().ToList() ?? new List<string>();
        if (idList.Count == 0)
        {
            return;
        }

        await _dbContext.SqlSugarClient.Updateable<MenuDbEntity>()
            .SetColumns(x => new MenuDbEntity { IsDeleted = true })
            .Where(x => idList.Contains(x.Id))
            .ExecuteCommandAsync();
    }

    /// <inheritdoc />
    public async Task<List<RbacMenuTreeDto>> GetTreeAsync()
    {
        // 返回所有字段,但过滤逻辑删除数据
        var menus = await _dbContext.SqlSugarClient.Queryable<MenuDbEntity>()
            .Where(x => x.IsDeleted == false)
            .OrderBy(x => x.OrderNum, OrderByType.Desc)
            .ToListAsync();

        var nodes = menus.Select(m => new RbacMenuTreeDto
        {
            Id = m.Id,
            IsDeleted = m.IsDeleted,
            CreationTime = m.CreationTime,
            CreatorId = m.CreatorId,
            LastModifierId = m.LastModifierId,
            LastModificationTime = m.LastModificationTime,
            OrderNum = m.OrderNum,
            State = m.State,
            MenuName = m.MenuName ?? string.Empty,
            RouterName = m.RouterName,
            MenuType = m.MenuType,
            PermissionCode = m.PermissionCode,
            ParentId = m.ParentId,
            MenuIcon = m.MenuIcon,
            Router = m.Router,
            IsLink = m.IsLink,
            IsCache = m.IsCache,
            IsShow = m.IsShow,
            Remark = m.Remark,
            Component = m.Component,
            MenuSource = m.MenuSource,
            Query = m.Query,
            ConcurrencyStamp = m.ConcurrencyStamp,
            Children = new List<RbacMenuTreeDto>()
        }).ToList();

        // TreeHelper 仅支持 Guid Id/ParentId,这里使用字符串 ParentId 自行构建树
        var nodeById = nodes
            .Where(x => !string.IsNullOrWhiteSpace(x.Id))
            .GroupBy(x => x.Id)
            .ToDictionary(g => g.Key, g => g.First());

        foreach (var node in nodes)
        {
            node.Children ??= new List<RbacMenuTreeDto>();
            var parentId = string.IsNullOrWhiteSpace(node.ParentId) ? "0" : node.ParentId.Trim();
            if (parentId == "0" || parentId == "00000000-0000-0000-0000-000000000000")
            {
                continue;
            }

            if (nodeById.TryGetValue(parentId, out var parent))
            {
                parent.Children ??= new List<RbacMenuTreeDto>();
                parent.Children.Add(node);
            }
        }

        var roots = nodes
            .Where(n =>
            {
                var pid = string.IsNullOrWhiteSpace(n.ParentId) ? "0" : n.ParentId.Trim();
                return pid == "0" || pid == "00000000-0000-0000-0000-000000000000" || !nodeById.ContainsKey(pid);
            })
            .ToList();

        SortTree(roots);
        return roots;
    }

    private static void SortTree(List<RbacMenuTreeDto> nodes)
    {
        nodes.Sort((a, b) => b.OrderNum.CompareTo(a.OrderNum));
        foreach (var node in nodes)
        {
            if (node.Children is { Count: > 0 })
            {
                SortTree(node.Children);
            }
        }
    }
}