init commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录菜单-AntDesign菜单类型
|
||||
/// </summary>
|
||||
public class AntDesignTreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父id
|
||||
/// </summary>
|
||||
public string Pid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由名称, 必须设置,且不能重名
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件
|
||||
/// </summary>
|
||||
public string Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重定向地址, 访问这个路由时, 自定进行重定向
|
||||
/// </summary>
|
||||
public string Redirect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由元信息(路由附带扩展信息)
|
||||
/// </summary>
|
||||
public Meta Meta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路径
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 控制路由和子路由是否显示在 sidebar
|
||||
/// </summary>
|
||||
public bool Hidden { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式
|
||||
/// </summary>
|
||||
public int OpenType { get; set; }
|
||||
|
||||
public string Application { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路由元信息内部类
|
||||
/// </summary>
|
||||
public class Meta
|
||||
{
|
||||
/// <summary>
|
||||
/// 路由标题, 用于显示面包屑, 页面标题 *推荐设置
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可见
|
||||
/// </summary>
|
||||
public bool Show { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 如需外部打开,增加:_blank
|
||||
/// </summary>
|
||||
public string Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内链打开http链接
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
}
|
||||
}
|
||||
148
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuInput.cs
Normal file
148
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuInput.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单参数
|
||||
/// </summary>
|
||||
public class MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public virtual string Pid { get; set; } = System.Guid.Empty.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||
/// </summary>
|
||||
public virtual int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由地址
|
||||
/// </summary>
|
||||
public virtual string Router { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件地址
|
||||
/// </summary>
|
||||
public virtual string Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限标识
|
||||
/// </summary>
|
||||
public virtual string Permission { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用分类(应用编码)
|
||||
/// </summary>
|
||||
public virtual string Application { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||
/// </summary>
|
||||
public virtual int OpenType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可见(Y-是,N-否)
|
||||
/// </summary>
|
||||
public bool Visible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内链地址
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重定向地址
|
||||
/// </summary>
|
||||
public string Redirect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权重(字典 1系统权重 2业务权重)
|
||||
/// </summary>
|
||||
public string Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定上级菜单显示
|
||||
/// </summary>
|
||||
public bool VisibleParent { get; set; }
|
||||
}
|
||||
|
||||
public class AddMenuInput : MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单类型不能为空")]
|
||||
public override int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "打开方式不能为空")]
|
||||
public override int OpenType { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteMenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateMenuInput : AddMenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>DeleteMenuInput
|
||||
[Required(ErrorMessage = "父级菜单Id不能为空")]
|
||||
public override string Pid { get; set; }
|
||||
}
|
||||
|
||||
public class QueryMenuInput : DeleteMenuInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ChangeAppMenuInput : MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用编码
|
||||
/// </summary>DeleteMenuInput
|
||||
[Required(ErrorMessage = "应用编码不能为空")]
|
||||
public override string Application { get; set; }
|
||||
}
|
||||
}
|
||||
36
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuOutput.cs
Normal file
36
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuOutput.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单树(列表形式)
|
||||
/// </summary>
|
||||
public class MenuOutput : MenuInput, ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<MenuOutput> Children { get; set; } = new List<MenuOutput>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return Pid;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<MenuOutput>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuTreeOutput.cs
Normal file
76
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuTreeOutput.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单树---授权、新增编辑时选择
|
||||
/// </summary>
|
||||
public class MenuTreeOutput : ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单类型
|
||||
/// </summary>
|
||||
public int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联显示父级
|
||||
/// </summary>
|
||||
public bool VisibleParent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限标识
|
||||
/// </summary>
|
||||
public string Permission { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序,越小优先级越高
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<MenuTreeOutput> Children { get; set; } = new List<MenuTreeOutput>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return ParentId;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<MenuTreeOutput>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
20220330_Vote/Ewide.Core/Service/Menu/ISysMenuService.cs
Normal file
22
20220330_Vote/Ewide.Core/Service/Menu/ISysMenuService.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysMenuService
|
||||
{
|
||||
Task AddMenu(AddMenuInput input);
|
||||
Task<List<AntDesignTreeNode>> ChangeAppMenu(ChangeAppMenuInput input);
|
||||
Task DeleteMenu(DeleteMenuInput input);
|
||||
Task<List<AntDesignTreeNode>> GetLoginMenusAntDesign(string userId, string appCode);
|
||||
Task<List<string>> GetLoginPermissionList(string userId);
|
||||
Task<dynamic> GetMenu(QueryMenuInput input);
|
||||
Task<dynamic> GetMenuList([FromQuery] MenuInput input);
|
||||
Task<dynamic> GetMenuTree([FromQuery] MenuInput input);
|
||||
Task<List<string>> GetUserMenuAppCodeList(string userId);
|
||||
Task<bool> HasMenu(string appCode);
|
||||
Task<dynamic> TreeForGrant([FromQuery] MenuInput input);
|
||||
Task UpdateMenu(UpdateMenuInput input);
|
||||
}
|
||||
}
|
||||
494
20220330_Vote/Ewide.Core/Service/Menu/SysMenuService.cs
Normal file
494
20220330_Vote/Ewide.Core/Service/Menu/SysMenuService.cs
Normal file
@@ -0,0 +1,494 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统菜单服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Menu", Order = 146)]
|
||||
public class SysMenuService : ISysMenuService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysMenu> _sysMenuRep; // 菜单表仓储
|
||||
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ISysCacheService _sysCacheService;
|
||||
private readonly ISysUserRoleService _sysUserRoleService;
|
||||
private readonly ISysRoleMenuService _sysRoleMenuService;
|
||||
|
||||
public SysMenuService(IRepository<SysMenu> sysMenuRep,
|
||||
IUserManager userManager,
|
||||
ISysCacheService sysCacheService,
|
||||
ISysUserRoleService sysUserRoleService,
|
||||
ISysRoleMenuService sysRoleMenuService)
|
||||
{
|
||||
_sysMenuRep = sysMenuRep;
|
||||
_userManager = userManager;
|
||||
_sysCacheService = sysCacheService;
|
||||
_sysUserRoleService = sysUserRoleService;
|
||||
_sysRoleMenuService = sysRoleMenuService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户权限(按钮权限标识集合)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<string>> GetLoginPermissionList(string userId)
|
||||
{
|
||||
var permissions = await _sysCacheService.GetPermission(userId); // 先从缓存里面读取
|
||||
if (permissions == null || permissions.Count < 1)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Type == (int)MenuType.FUNCTION)
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Select(u => u.Permission).ToListAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetPermission(userId, permissions); // 缓存结果
|
||||
#endif
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户AntDesign菜单集合
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<AntDesignTreeNode>> GetLoginMenusAntDesign(string userId, string appCode)
|
||||
{
|
||||
var antDesignTreeNodes = await _sysCacheService.GetMenu(userId, appCode); // 先从缓存里面读取
|
||||
if (antDesignTreeNodes == null || antDesignTreeNodes.Count < 1)
|
||||
{
|
||||
var sysMenuList = new List<SysMenu>();
|
||||
// 管理员则展示所有系统权重菜单,不能展示业务权重菜单
|
||||
if (_userManager.SuperAdmin)
|
||||
{
|
||||
sysMenuList = await _sysMenuRep.DetachedEntities
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Application == appCode)
|
||||
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||
.Where(u => u.Weight != (int)MenuWeight.DEFAULT_WEIGHT)
|
||||
.OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非管理员则获取自己角色所拥有的菜单集合
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
sysMenuList = await _sysMenuRep.DetachedEntities
|
||||
.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Application == appCode)
|
||||
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||
.OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
// 转换成登录菜单
|
||||
antDesignTreeNodes = sysMenuList.Select(u => new AntDesignTreeNode
|
||||
{
|
||||
Id = u.Id,
|
||||
Pid = u.Pid,
|
||||
Name = u.Code,
|
||||
Component = u.Component,
|
||||
Redirect = u.Redirect,
|
||||
Link = u.Link,
|
||||
OpenType = u.OpenType,
|
||||
Meta = new Meta
|
||||
{
|
||||
Title = u.Name,
|
||||
Icon = u.Icon,
|
||||
Show = u.Visible,
|
||||
Link = u.Link,
|
||||
Target = u.OpenType == (int)MenuOpenType.OUTER ? "_blank" : ""
|
||||
},
|
||||
Application = u.Application
|
||||
}).ToList();
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetMenu(userId, appCode, antDesignTreeNodes); // 缓存结果
|
||||
#endif
|
||||
}
|
||||
return antDesignTreeNodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户菜单所属的应用编码集合
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<string>> GetUserMenuAppCodeList(string userId)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
return await _sysMenuRep.DetachedEntities
|
||||
.Where(u => (u.Type == 2 && u.VisibleParent) || u.Type < 2)
|
||||
.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Select(u => u.Application).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统菜单列表(树表)
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/list")]
|
||||
public async Task<dynamic> GetMenuList([FromQuery] MenuInput input)
|
||||
{
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities.Where((application, u => u.Application == input.Application.Trim()),
|
||||
(name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.Select(u => u.Adapt<MenuOutput>())
|
||||
.ToListAsync();
|
||||
return new TreeBuildUtil<MenuOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Pids格式
|
||||
/// 如果pid是0顶级节点,pids就是 [0];
|
||||
/// 如果pid不是顶级节点,pids就是 pid菜单的 pids + [pid] + ,
|
||||
/// </summary>
|
||||
/// <param name="pid"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> CreateNewPids(string pid)
|
||||
{
|
||||
if (pid.Equals(System.Guid.Empty.ToString()))
|
||||
{
|
||||
return "[" + System.Guid.Empty + "],";
|
||||
}
|
||||
else
|
||||
{
|
||||
var pmenu = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == pid);
|
||||
return pmenu.Pids + "[" + pid + "],";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加和编辑时检查参数
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
private async Task CheckMenuParam(MenuInput input)
|
||||
{
|
||||
var type = input.Type;
|
||||
var router = input.Router;
|
||||
var permission = input.Permission;
|
||||
var openType = input.OpenType;
|
||||
var isVisibleParent = input.VisibleParent;
|
||||
|
||||
if (type.Equals((int)MenuType.DIR))
|
||||
{
|
||||
//if (string.IsNullOrEmpty(router))
|
||||
// throw Oops.Oh(ErrorCode.D4001);
|
||||
}
|
||||
else if (type.Equals((int)MenuType.MENU))
|
||||
{
|
||||
//if (string.IsNullOrEmpty(router))
|
||||
// throw Oops.Oh(ErrorCode.D4001);
|
||||
//if (string.IsNullOrEmpty(openType))
|
||||
// throw Oops.Oh(ErrorCode.D4002);
|
||||
}
|
||||
else if (type.Equals((int)MenuType.FUNCTION))
|
||||
{
|
||||
if (string.IsNullOrEmpty(permission))
|
||||
throw Oops.Oh(ErrorCode.D4003);
|
||||
if (!permission.Contains(":"))
|
||||
throw Oops.Oh(ErrorCode.D4004);
|
||||
// 判断该资源是否存在
|
||||
//permission = ":" + permission;
|
||||
//var urlSet = resourceCache.getAllResources();
|
||||
//if (!urlSet.Contains(permission.Replace(":","/")))
|
||||
// throw Oops.Oh(ErrorCode.meu1005);
|
||||
}
|
||||
|
||||
// 检查上级菜单的类型是否正确
|
||||
var pid = input.Pid;
|
||||
var flag = true;
|
||||
var empty = System.Guid.Empty.ToString();
|
||||
switch(type)
|
||||
{
|
||||
// 目录必须在顶级下
|
||||
case (int)MenuType.DIR:
|
||||
flag = pid.Equals(empty);
|
||||
break;
|
||||
// 菜单必须在顶级或目录下
|
||||
case (int)MenuType.MENU:
|
||||
if (!pid.Equals(empty))
|
||||
{
|
||||
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||
flag = parent.Type.Equals((int)MenuType.DIR);
|
||||
}
|
||||
break;
|
||||
// 功能必须在菜单下
|
||||
case (int)MenuType.FUNCTION:
|
||||
{
|
||||
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||
flag = parent == null ? false : parent.Type.Equals((int)MenuType.MENU);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
throw Oops.Oh("父级菜单类型错误");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/add")]
|
||||
public async Task AddMenu(AddMenuInput input)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(input.Code))
|
||||
{
|
||||
var isExist = await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code); // u.Name == input.Name
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D4000);
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
await CheckMenuParam(input);
|
||||
|
||||
var menu = input.Adapt<SysMenu>();
|
||||
menu.Pids = await CreateNewPids(input.Pid);
|
||||
menu.Status = (int)CommonStatus.ENABLE;
|
||||
await menu.InsertAsync();
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/delete")]
|
||||
[UnitOfWork]
|
||||
public async Task DeleteMenu(DeleteMenuInput input)
|
||||
{
|
||||
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
||||
.Select(u => u.Id).ToListAsync();
|
||||
childIdList.Add(input.Id);
|
||||
|
||||
var menus = await _sysMenuRep.Where(u => childIdList.Contains(u.Id)).ToListAsync();
|
||||
menus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
// 级联删除该菜单及子菜单对应的角色-菜单表信息
|
||||
await _sysRoleMenuService.DeleteRoleMenuListByMenuIdList(childIdList);
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/edit"),]
|
||||
public async Task UpdateMenu(UpdateMenuInput input)
|
||||
{
|
||||
// Pid和Id不能一致,一致会导致无限递归
|
||||
if (input.Id == input.Pid)
|
||||
throw Oops.Oh(ErrorCode.D4006);
|
||||
|
||||
if (!string.IsNullOrEmpty(input.Code))
|
||||
{
|
||||
var isExist = await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code && u.Id != input.Id); // u.Name == input.Name
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D4000);
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
await CheckMenuParam(input);
|
||||
// 如果是编辑,父id不能为自己的子节点
|
||||
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
||||
.Select(u => u.Id).ToListAsync();
|
||||
if (childIdList.Contains(input.Pid))
|
||||
throw Oops.Oh(ErrorCode.D4006);
|
||||
|
||||
var oldMenu = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
|
||||
// 生成新的pids
|
||||
var newPids = await CreateNewPids(input.Pid);
|
||||
|
||||
// 是否更新子应用的标识
|
||||
var updateSubAppsFlag = false;
|
||||
// 是否更新子节点的pids的标识
|
||||
var updateSubPidsFlag = false;
|
||||
|
||||
// 如果应用有变化
|
||||
if (input.Application != oldMenu.Application)
|
||||
{
|
||||
// 父节点不是根节点不能移动应用
|
||||
if (!oldMenu.Pid.Equals(System.Guid.Empty.ToString()))
|
||||
throw Oops.Oh(ErrorCode.D4007);
|
||||
updateSubAppsFlag = true;
|
||||
}
|
||||
// 父节点有变化
|
||||
if (input.Pid != oldMenu.Pid)
|
||||
updateSubPidsFlag = true;
|
||||
|
||||
// 开始更新所有子节点的配置
|
||||
if (updateSubAppsFlag || updateSubPidsFlag)
|
||||
{
|
||||
// 查找所有叶子节点,包含子节点的子节点
|
||||
var menuList = await _sysMenuRep.Where(u => EF.Functions.Like(u.Pids, $"%{oldMenu.Id}%")).ToListAsync();
|
||||
// 更新所有子节点的应用为当前菜单的应用
|
||||
if (menuList.Count > 0)
|
||||
{
|
||||
// 更新所有子节点的application
|
||||
if (updateSubAppsFlag)
|
||||
{
|
||||
menuList.ForEach(u =>
|
||||
{
|
||||
u.Application = input.Application;
|
||||
});
|
||||
}
|
||||
|
||||
// 更新所有子节点的pids
|
||||
if (updateSubPidsFlag)
|
||||
{
|
||||
menuList.ForEach(u =>
|
||||
{
|
||||
// 子节点pids组成 = 当前菜单新pids + 当前菜单id + 子节点自己的pids后缀
|
||||
var oldParentCodesPrefix = oldMenu.Pids + "[" + oldMenu.Id + "],";
|
||||
var oldParentCodesSuffix = u.Pids.Substring(oldParentCodesPrefix.Length);
|
||||
var menuParentCodes = newPids + "[" + oldMenu.Id + "]," + oldParentCodesSuffix;
|
||||
u.Pids = menuParentCodes;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新当前菜单
|
||||
oldMenu = input.Adapt<SysMenu>();
|
||||
oldMenu.Pids = newPids;
|
||||
await oldMenu.UpdateExcludeAsync(new[] { nameof(SysMenu.Type) }, ignoreNullValues: true);
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/detail")]
|
||||
public async Task<dynamic> GetMenu(QueryMenuInput input)
|
||||
{
|
||||
return await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单树,用于新增、编辑时选择上级节点
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/tree")]
|
||||
public async Task<dynamic> GetMenuTree([FromQuery] MenuInput input)
|
||||
{
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities
|
||||
.Where(application, u => u.Application == input.Application.Trim())
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Type == (int)MenuType.DIR || u.Type == (int)MenuType.MENU)
|
||||
.OrderBy(u => u.Sort)
|
||||
.Select(u => new MenuTreeOutput
|
||||
{
|
||||
Id = u.Id,
|
||||
ParentId = u.Pid,
|
||||
Value = u.Id.ToString(),
|
||||
Title = u.Name,
|
||||
Type = u.Type,
|
||||
VisibleParent = u.VisibleParent,
|
||||
Sort = u.Sort
|
||||
}).ToListAsync();
|
||||
return new TreeBuildUtil<MenuTreeOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单树,用于给角色授权时选择
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/treeForGrant")]
|
||||
public async Task<dynamic> TreeForGrant([FromQuery] MenuInput input)
|
||||
{
|
||||
var menuIdList = new List<string>();
|
||||
if (_userManager.SuperAdmin)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
|
||||
menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
}
|
||||
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities
|
||||
.Where(application, u => u.Application == input.Application.Trim())
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
|
||||
.OrderBy(u => u.Sort).Select(u => new MenuTreeOutput
|
||||
{
|
||||
Id = u.Id,
|
||||
ParentId = u.Pid,
|
||||
Value = u.Id.ToString(),
|
||||
Title = u.Name,
|
||||
Type = u.Type,
|
||||
VisibleParent = u.VisibleParent,
|
||||
Permission = u.Permission,
|
||||
Remark = u.Remark,
|
||||
Sort = u.Sort
|
||||
}).ToListAsync();
|
||||
return new TreeBuildUtil<MenuTreeOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据应用编码判断该机构下是否有状态为正常的菜单
|
||||
/// </summary>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<bool> HasMenu(string appCode)
|
||||
{
|
||||
return await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Application == appCode && u.Status != CommonStatus.DELETED);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据系统应用切换菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("/sysMenu/change")]
|
||||
public async Task<List<AntDesignTreeNode>> ChangeAppMenu(ChangeAppMenuInput input)
|
||||
{
|
||||
return await GetLoginMenusAntDesign(_userManager.UserId, input.Application);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user