using YD_Event.Application.Auth; using YD_Event.Application.Menu.Dtos; using Microsoft.OpenApi; namespace YD_Event.Application.Menu; /// /// 系统菜单管理 /// public class SysMenuService : BaseService, ITransient { private readonly ISqlSugarRepository _sysMenuRepository; private readonly IEasyCachingProvider _easyCachingProvider; private readonly AuthManager _authManager; public SysMenuService(ISqlSugarRepository sysMenuRepository, IEasyCachingProvider easyCachingProvider, AuthManager authManager) : base(sysMenuRepository) { _sysMenuRepository = sysMenuRepository; _easyCachingProvider = easyCachingProvider; _authManager = authManager; } /// /// 菜单列表查询 /// /// /// [DisplayName("菜单列表查询")] [HttpGet] public async Task> Page([FromQuery] string name) { if (_authManager.IsSuperAdmin) { var q1 = _sysMenuRepository.AsQueryable() .OrderBy(x => x.Sort) .OrderBy(x => x.Id); if (!string.IsNullOrWhiteSpace(name)) { var list = await q1.Where(x => x.Name.Contains(name)).ToListAsync(); return list.Adapt>(); } var menus = await q1.ToTreeAsync(x => x.Children, x => x.ParentId, null); return menus.Adapt>(); } else { long userId = _authManager.UserId; var q2 = _sysMenuRepository.AsQueryable().InnerJoin((menu, roleMenu) => menu.Id == roleMenu.MenuId) .InnerJoin((menu, roleMenu, role) => roleMenu.RoleId == role.Id) .InnerJoin((menu, roleMenu, role, userRole) => role.Id == userRole.RoleId) .Where((menu, roleMenu, role, userRole) => role.Status == AvailabilityStatus.Enable && userRole.UserId == userId); if (!string.IsNullOrWhiteSpace(name)) { var list = await q2.Where(menu => menu.Name.Contains(name)).Distinct().OrderBy(menu => menu.Sort).OrderBy(menu => menu.Id).ToListAsync(); return list.Adapt>(); } var menuIdList = await q2.Select(menu => menu.Id).ToListAsync(); var array = menuIdList.Select(x => x as object).ToArray(); var menus = await _sysMenuRepository.AsQueryable() .Where(x => x.Status == AvailabilityStatus.Enable) .OrderBy(x => x.Sort) .OrderBy(x => x.Id) .ToTreeAsync(x => x.Children, x => x.ParentId, null, array); return menus.Adapt>(); } } /// /// 添加菜单/按钮 /// /// [DisplayName("添加菜单/按钮")] [HttpPost("add")] public async Task AddMenu(AddSysMenuInput dto) { SysMenu sysMenu = dto.Adapt(); if (sysMenu.Type == MenuType.Button) { sysMenu.Link = sysMenu.Icon = sysMenu.Component = sysMenu.Path = sysMenu.Redirect = sysMenu.RouteName = null; } else { if (await _sysMenuRepository.IsAnyAsync(x => x.RouteName.ToLower() == dto.RouteName.ToLower())) { throw Oops.Bah("路由名称已存在"); } sysMenu.Code = null; } await _sysMenuRepository.InsertAsync(sysMenu); await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey); } /// /// 修改菜单/按钮 /// /// /// [DisplayName("更新菜单/按钮")] [HttpPut("edit")] public async Task UpdateMenu(UpdateSysMenuInput dto) { SysMenu sysMenu = await _sysMenuRepository.GetByIdAsync(dto.Id); if (sysMenu == null) { throw Oops.Bah("无线参数"); } if (dto.Type != MenuType.Button && await _sysMenuRepository.IsAnyAsync(x => x.RouteName.ToLower() == dto.RouteName.ToLower() && x.Id != dto.Id)) { throw Oops.Bah("路由名称已存在"); } //检查菜单父子关系是否存在循环引用 if (dto.ParentId.HasValue && dto.ParentId != sysMenu.ParentId) { List list = await _sysMenuRepository.AsQueryable().ToChildListAsync(x => x.Children, dto.Id); if (list.Any(x => x.Id == dto.ParentId)) { throw Oops.Bah($"请勿将当前{dto.Type.Description()}的父级菜单设置为它的子级"); } } dto.Adapt(sysMenu); if (sysMenu.Type == MenuType.Button) { sysMenu.Link = sysMenu.Icon = sysMenu.Component = sysMenu.Path = sysMenu.Redirect = sysMenu.RouteName = null; } else { sysMenu.Code = null; } await _sysMenuRepository.UpdateAsync(sysMenu); await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey); } /// /// 根据菜单Id获取系统菜单详情 /// /// /// [DisplayName("系统菜单详情")] [HttpGet] public async Task Detail([FromQuery] long id) { return await _sysMenuRepository.AsQueryable().Where(x => x.Id == id) .Select(x => new SysMenuDetailOutput { Id = x.Id, Name = x.Name, ParentId = x.ParentId, Status = x.Status, Code = x.Code, Sort = x.Sort, Component = x.Component, Icon = x.Icon, IsFixed = x.IsFixed, IsIframe = x.IsIframe, IsKeepAlive = x.IsKeepAlive, IsVisible = x.IsVisible, Link = x.Link, Remark = x.Remark, Path = x.Path, Redirect = x.Redirect, RouteName = x.RouteName, Type = x.Type }).FirstAsync(); } /// /// 菜单下拉树 /// /// [DisplayName("菜单下拉树")] [HttpGet] public async Task> TreeSelect() { var list = await _sysMenuRepository.AsQueryable() .OrderBy(x => x.Sort) .OrderBy(x => x.Id) .WithCache() .ToTreeAsync(x => x.Children, x => x.ParentId, null); return list.Adapt>(); } /// /// 删除菜单/按钮 /// /// /// [DisplayName("删除菜单/按钮"), HttpDelete("delete")] public override async Task Delete(KeyDto dto) { await base.Delete(dto); await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey); } /// /// 修改菜单/按钮状态 /// /// /// [DisplayName("修改菜单/按钮状态"), HttpPut("setStatus")] public override async Task SetStatus(AvailabilityDto dto) { await base.SetStatus(dto); await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey); } /// /// 获取当前登录用户可用菜单 /// /// [DisplayName("获取当前登录用户可用菜单")] [HttpGet] public async Task> PermissionMenus() { long userId = _authManager.UserId; var value = await _easyCachingProvider.GetAsync($"{CacheConst.PermissionMenuKey}{userId}", async () => { var queryable = _sysMenuRepository.AsQueryable() .Where(x => x.Status == AvailabilityStatus.Enable) .OrderBy(x => x.Sort) .OrderBy(x => x.Id); List list; if (_authManager.IsSuperAdmin) { list = await queryable .Where(x => x.Type != MenuType.Button) .ToTreeAsync(x => x.Children, x => x.ParentId, null); } else { List menuIdList = await _sysMenuRepository.AsSugarClient().Queryable().InnerJoin((role, userRole) => userRole.RoleId == role.Id) .InnerJoin((role, userRole, roleMenu) => role.Id == roleMenu.RoleId) .InnerJoin((role, userRole, roleMenu, menu) => roleMenu.MenuId == menu.Id) .Where((role, userRole, roleMenu, menu) => role.Status == AvailabilityStatus.Enable && userRole.UserId == userId && menu.Status == AvailabilityStatus.Enable) .Select((role, userRole, roleMenu) => roleMenu.MenuId).ToListAsync(); var array = menuIdList.Select(x => x as object).ToArray(); list = await queryable .ToTreeAsync(x => x.Children, x => x.ParentId, null, array); RemoveButton(list); } return list.Adapt>(); }, TimeSpan.FromDays(1)); return value.Value ?? new List(); } /// /// 菜单按钮树 /// /// [DisplayName("菜单按钮树")] [HttpGet] public async Task> TreeMenuButton() { long userId = _authManager.UserId; List menus; if (_authManager.IsSuperAdmin)//超级管理员 { menus = await _sysMenuRepository.AsQueryable().ToTreeAsync(x => x.Children, x => x.ParentId, null); } else { menus = await _sysMenuRepository.AsQueryable() .InnerJoin((menu, roleMenu) => menu.Id == roleMenu.MenuId) .InnerJoin((menu, roleMenu, role) => roleMenu.RoleId == role.Id) .InnerJoin((menu, roleMenu, role, userRole) => role.Id == userRole.RoleId) .Where((menu, roleMenu, role, userRole) => menu.Status == AvailabilityStatus.Enable && role.Status == AvailabilityStatus.Enable && userRole.UserId == userId) .Select(menu => menu) .ToTreeAsync(x => x.Children, x => x.ParentId, null); } return menus.Adapt>(); } /// /// 校验权限 /// /// 权限标识 /// [NonAction] public async Task CheckPermission(string code) { if (_authManager.IsSuperAdmin) return true; var cache = await GetAuthButtonCodeList(_authManager.UserId); var output = cache.FirstOrDefault(x => x.Code.Contains(code, StringComparison.CurrentCultureIgnoreCase)); return output?.Access ?? true; } /// /// 获取指定用户的访问权限集合 /// /// 系统用户id /// [NonAction] public async Task> GetAuthButtonCodeList(long userId) { var cache = await _easyCachingProvider.GetAsync($"{CacheConst.PermissionButtonCodeKey}{userId}", async () => { var queryable = _sysMenuRepository.AsSugarClient().Queryable() .InnerJoin((role, userRole) => role.Id == userRole.RoleId) .InnerJoin((role, userRole, roleMenu) => role.Id == roleMenu.RoleId) .Where(role => role.Status == AvailabilityStatus.Enable) .Select((role, userRole, roleMenu) => roleMenu); var list = await _sysMenuRepository.AsQueryable().LeftJoin(queryable, (menu, roleMenu) => menu.Id == roleMenu.MenuId) .Where(menu => menu.Type == MenuType.Button) .Select((menu, roleMenu) => new CheckPermissionOutput { Code = menu.Code, Access = SqlFunc.IIF(SqlFunc.IsNull(roleMenu.Id, 0) > 0 || menu.Status == AvailabilityStatus.Disable, true, false) }).ToListAsync(); return list.Distinct().ToList(); }, TimeSpan.FromDays(1)); return cache.Value; } /// /// 移除菜单中的按钮 /// /// void RemoveButton(List menus) { for (int i = menus.Count - 1; i >= 0; i--) { if (menus[i].Type == MenuType.Button) { menus.Remove(menus[i]); continue; } if (menus[i].Children.Any()) { RemoveButton(menus[i].Children); } } } }