SysMenuService.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using Furion.DatabaseAccessor.Extensions;
  2. using YBEE.EQM.Core;
  3. namespace YBEE.EQM.Application
  4. {
  5. /// <summary>
  6. /// 菜单服务
  7. /// </summary>
  8. public class SysMenuService : ISysMenuService, ITransient
  9. {
  10. private readonly IRepository<SysMenu> _menuRep;
  11. private readonly ISysRoleUserService _roleUserService;
  12. private readonly ISysRoleMenuService _roleMenuService;
  13. private readonly ICacheService _cacheService;
  14. public SysMenuService(IRepository<SysMenu> menuRep, ISysRoleUserService roleUserService, ISysRoleMenuService roleMenuService, ICacheService cacheService)
  15. {
  16. _menuRep = menuRep;
  17. _roleUserService = roleUserService;
  18. _roleMenuService = roleMenuService;
  19. _cacheService = cacheService;
  20. }
  21. #region 私有方法
  22. /// <summary>
  23. /// 创建Pids格式
  24. /// 如果pid是0顶级节点,pids就是 [0];
  25. /// 如果pid不是顶级节点,pids就是 pid菜单的 pids + [pid] + ,
  26. /// </summary>
  27. /// <param name="pid"></param>
  28. /// <returns></returns>
  29. private async Task<string> CreateNewPids(long pid)
  30. {
  31. if (pid == 0L)
  32. {
  33. return "[0],";
  34. }
  35. else
  36. {
  37. var pmenu = await _menuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == pid);
  38. return pmenu.Pids + "[" + pid + "],";
  39. }
  40. }
  41. /// <summary>
  42. /// 增加和编辑时检查参数
  43. /// </summary>
  44. /// <param name="input"></param>
  45. private static void CheckMenuParam(SysMenuInput input)
  46. {
  47. var type = input.MenuType;
  48. var router = input.Router;
  49. var permission = input.Permission;
  50. var openType = input.OpenType;
  51. if (type.Equals((int)MenuType.FOLDER))
  52. {
  53. if (string.IsNullOrEmpty(router)) { throw Oops.Oh(ErrorCode.E8102); }
  54. }
  55. else if (type.Equals((int)MenuType.MENU))
  56. {
  57. if (string.IsNullOrEmpty(router)) { throw Oops.Oh(ErrorCode.E8102); }
  58. if (string.IsNullOrEmpty(openType.ToString())) { throw Oops.Oh(ErrorCode.E8103); }
  59. }
  60. else if (type.Equals((int)MenuType.BUTTON))
  61. {
  62. if (string.IsNullOrEmpty(permission)) { throw Oops.Oh(ErrorCode.E8104); }
  63. if (!permission.Contains('.')) { throw Oops.Oh(ErrorCode.E8105); }
  64. // 判断该资源是否存在
  65. //permission = ":" + permission;
  66. //var urlSet = resourceCache.getAllResources();
  67. //if (!urlSet.Contains(permission.Replace(":","/")))
  68. // throw Oops.Oh(ErrorCode.meu1005);
  69. }
  70. }
  71. #endregion
  72. /// <summary>
  73. /// 添加菜单
  74. /// </summary>
  75. /// <param name="input"></param>
  76. /// <returns></returns>
  77. /// <exception cref="NotImplementedException"></exception>
  78. public async Task Add(AddSysMenuInput input)
  79. {
  80. var isExist = await _menuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code); // u.Name == input.Name
  81. if (isExist)
  82. {
  83. throw Oops.Oh(ErrorCode.E8101);
  84. }
  85. // 校验参数
  86. CheckMenuParam(input.Adapt<SysMenuInput>());
  87. var menu = input.Adapt<SysMenu>();
  88. menu.Pids = await CreateNewPids(input.Pid);
  89. menu.Status = CommonStatus.ENABLE;
  90. await menu.InsertAsync();
  91. // 清除缓存
  92. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
  93. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_PERMISSION);
  94. }
  95. /// <summary>
  96. /// 更新菜单
  97. /// </summary>
  98. /// <param name="input"></param>
  99. /// <returns></returns>
  100. /// <exception cref="NotImplementedException"></exception>
  101. public async Task Update(UpdateSysMenuInput input)
  102. {
  103. // Pid和Id不能一致,一致会导致无限递归
  104. if (input.Id == input.Pid)
  105. {
  106. throw Oops.Oh(ErrorCode.E8107);
  107. }
  108. var isExist = await _menuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code && u.Id != input.Id); // u.Name == input.Name
  109. if (isExist)
  110. {
  111. throw Oops.Oh(ErrorCode.E8101);
  112. }
  113. // 校验参数
  114. CheckMenuParam(input.Adapt<SysMenuInput>());
  115. // 如果是编辑,父id不能为自己的子节点
  116. var childIdList = await _menuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
  117. .Select(u => u.Id).ToListAsync();
  118. if (childIdList.Contains(input.Pid))
  119. throw Oops.Oh(ErrorCode.E8107);
  120. var oldMenu = await _menuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
  121. // 生成新的pids
  122. var newPids = await CreateNewPids(input.Pid);
  123. // 是否更新子节点的pids的标识
  124. var updateSubPidsFlag = input.Pid != oldMenu.Pid;
  125. // 开始更新所有子节点的配置
  126. if (updateSubPidsFlag)
  127. {
  128. // 查找所有叶子节点,包含子节点的子节点
  129. var menuList = await _menuRep.Where(u => EF.Functions.Like(u.Pids, $"%{oldMenu.Id}%")).ToListAsync();
  130. // 更新所有子节点的应用为当前菜单的应用
  131. if (menuList.Count > 0)
  132. {
  133. // 更新所有子节点的pids
  134. if (updateSubPidsFlag)
  135. {
  136. menuList.ForEach(u =>
  137. {
  138. // 子节点pids组成 = 当前菜单新pids + 当前菜单id + 子节点自己的pids后缀
  139. var oldParentCodesPrefix = oldMenu.Pids + "[" + oldMenu.Id + "],";
  140. var oldParentCodesSuffix = u.Pids[oldParentCodesPrefix.Length..];
  141. var menuParentCodes = newPids + "[" + oldMenu.Id + "]," + oldParentCodesSuffix;
  142. u.Pids = menuParentCodes;
  143. });
  144. }
  145. }
  146. }
  147. // 更新当前菜单
  148. oldMenu = input.Adapt<SysMenu>();
  149. oldMenu.Pids = newPids;
  150. await oldMenu.UpdateAsync(ignoreNullValues: true);
  151. // 清除缓存
  152. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
  153. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_PERMISSION);
  154. }
  155. /// <summary>
  156. /// 删除菜单
  157. /// </summary>
  158. /// <param name="input"></param>
  159. /// <returns></returns>
  160. /// <exception cref="NotImplementedException"></exception>
  161. public async Task Del(DeleteSysMenuInput input)
  162. {
  163. var childIdList = await _menuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
  164. .Select(u => u.Id).ToListAsync();
  165. childIdList.Add(input.Id);
  166. var menus = await _menuRep.Where(u => childIdList.Contains(u.Id)).ToListAsync();
  167. await _menuRep.DeleteAsync(menus);
  168. // 级联删除该菜单及子菜单对应的角色-菜单表信息
  169. //await _sysRoleMenuService.DeleteRoleMenuListByMenuIdList(childIdList);
  170. // 清除缓存
  171. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
  172. await _cacheService.DelByPatternAsync(CommonConst.CACHE_KEY_PERMISSION);
  173. }
  174. /// <summary>
  175. /// 获取菜单列表
  176. /// </summary>
  177. /// <returns></returns>
  178. public async Task<List<SysMenuOutput>> GetAllList()
  179. {
  180. var items = await _menuRep.DetachedEntities.Where(u => u.Status == CommonStatus.ENABLE)
  181. .OrderBy(u => u.Sort)
  182. .ProjectToType<SysMenuOutput>()
  183. .ToListAsync();
  184. return items;
  185. }
  186. /// <summary>
  187. /// 获取所有菜单(树形)
  188. /// </summary>
  189. /// <returns></returns>
  190. public async Task<List<SysMenuOutput>> GetAllTreeList()
  191. {
  192. var menus = await _menuRep.DetachedEntities.Where(u => u.Status == CommonStatus.ENABLE)
  193. .ProjectToType<SysMenuOutput>()
  194. .ToListAsync();
  195. return new TreeBuildUtil<SysMenuOutput>().Build(menus);
  196. }
  197. /// <summary>
  198. /// 获取用户权限(按钮权限标识集合)
  199. /// </summary>
  200. /// <param name="userId"></param>
  201. /// <returns></returns>
  202. public async Task<List<string>> GetLoginPermissionList(int userId)
  203. {
  204. var permissions = await _cacheService.GetPermission(userId); // 先从缓存里面读取
  205. if (permissions == null || permissions.Count < 1)
  206. {
  207. if (!CurrentSysUserInfo.IsSuperAdmin && userId != 0)
  208. {
  209. var roleIdList = await _roleUserService.GetUserRoleIdList(userId);
  210. var menuIdList = await _roleMenuService.GetRoleMenuIdList(roleIdList);
  211. permissions = await _menuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id))
  212. .Where(u => u.MenuType == MenuType.BUTTON)
  213. .Where(u => u.Status == CommonStatus.ENABLE)
  214. .Select(u => u.Permission).ToListAsync();
  215. }
  216. else
  217. {
  218. permissions = await _menuRep.DetachedEntities
  219. .Where(u => u.MenuType == MenuType.BUTTON)
  220. .Where(u => u.Status == CommonStatus.ENABLE)
  221. .Select(u => u.Permission).ToListAsync();
  222. }
  223. await _cacheService.SetPermission(userId, permissions); // 缓存结果
  224. }
  225. return permissions;
  226. }
  227. /// <summary>
  228. /// 获取所有权限(按钮权限标识集合)
  229. /// </summary>
  230. /// <returns></returns>
  231. public async Task<List<string>> GetAllPermissionList()
  232. {
  233. return await GetLoginPermissionList(0);
  234. }
  235. /// <summary>
  236. /// 获取前端可使用的菜单列表
  237. /// </summary>
  238. /// <param name="userId"></param>
  239. /// <returns></returns>
  240. public async Task<List<AntMenuOutput>> GetLoginAntMenus(int userId)
  241. {
  242. var items = await _cacheService.GetMenu(userId); // 先从缓存里面读取
  243. if (items == null || items.Count < 1)
  244. {
  245. var sysMenuList = new List<SysMenu>();
  246. // 管理员则展示所有系统菜单
  247. if (CurrentSysUserInfo.IsSuperAdmin)
  248. {
  249. sysMenuList = await _menuRep.DetachedEntities
  250. .Where(u => u.Status == CommonStatus.ENABLE && u.Visible == true)
  251. .Where(u => u.MenuType != MenuType.BUTTON)
  252. .OrderBy(u => u.Sort).ThenBy(u => u.Id).ToListAsync();
  253. }
  254. else
  255. {
  256. // 非管理员则获取自己角色所拥有的菜单集合
  257. var roleIdList = await _roleUserService.GetUserRoleIdList(userId);
  258. var menuIdList = await _roleMenuService.GetRoleMenuIdList(roleIdList);
  259. sysMenuList = await _menuRep.DetachedEntities
  260. .Where(u => menuIdList.Contains(u.Id))
  261. .Where(u => u.Status == CommonStatus.ENABLE && u.Visible == true)
  262. .Where(u => u.MenuType != MenuType.BUTTON)
  263. .OrderBy(u => u.Sort).ThenBy(u => u.Id).ToListAsync();
  264. }
  265. // 转换成登录菜单
  266. items = sysMenuList.Select(u => new AntMenuOutput
  267. {
  268. Id = u.Id,
  269. Pid = u.Pid,
  270. Path = u.OpenType == MenuOpenType.OUTER ? u.Link : u.Router,
  271. Name = u.Code,
  272. Component = u.Component,
  273. Title = u.Name,
  274. Icon = u.Icon,
  275. Visible = u.Visible,
  276. Link = u.Link,
  277. Target = u.OpenType == MenuOpenType.OUTER ? "_blank" : "",
  278. }).ToList();
  279. await _cacheService.SetMenu(userId, items); // 缓存结果
  280. }
  281. return items;
  282. }
  283. }
  284. }