平安校园
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

264 líneas
11 KiB

  1. //
  2. namespace SafeCampus.System;
  3. /// <summary>
  4. /// <inheritdoc cref="IMenuService"/>
  5. /// </summary>
  6. public class MenuService : DbRepository<SysResource>, IMenuService
  7. {
  8. private readonly ILogger<MenuService> _logger;
  9. private readonly IResourceService _resourceService;
  10. private readonly IRelationService _relationService;
  11. public MenuService(ILogger<MenuService> logger, IResourceService resourceService, IRelationService relationService)
  12. {
  13. _logger = logger;
  14. _resourceService = resourceService;
  15. _relationService = relationService;
  16. }
  17. /// <inheritdoc/>
  18. public List<SysResource> ConstructMenuTrees(List<SysResource> resourceList, long? parentId = 0)
  19. {
  20. //找下级资源ID列表
  21. var resources = resourceList.Where(it => it.ParentId == parentId).OrderBy(it => it.SortCode).ToList();
  22. if (resources.Count > 0)//如果数量大于0
  23. {
  24. var data = new List<SysResource>();
  25. foreach (var item in resources)//遍历资源
  26. {
  27. item.Children = ConstructMenuTrees(resourceList, item.Id);//添加子节点
  28. data.Add(item);//添加到列表
  29. }
  30. return data;//返回结果
  31. }
  32. return new List<SysResource>();
  33. }
  34. /// <inheritdoc />
  35. public async Task<List<SysResource>> Tree(MenuTreeInput input, bool showDisabled = true)
  36. {
  37. //获取所有菜单
  38. var sysResources = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
  39. sysResources = sysResources.WhereIF(input.Module != null, it => it.Module.Value == input.Module.Value)//根据模块查找
  40. .WhereIF(!showDisabled, it => it.Status == CommonStatusConst.ENABLE)//是否显示禁用的
  41. .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title == input.SearchKey)//根据关键字查找
  42. .ToList();
  43. //构建菜单树
  44. var tree = ConstructMenuTrees(sysResources);
  45. return tree;
  46. }
  47. /// <inheritdoc />
  48. public async Task<List<SysResource>> ShortcutTree(List<SysResource> sysResources = null)
  49. {
  50. if (sysResources == null)
  51. //获取所有菜单
  52. sysResources = (await _resourceService.GetAllModuleAndMenuAndSpaList())
  53. .Where(it => it.Status == CommonStatusConst.ENABLE).ToList();
  54. // //获取所有单页
  55. // var sysSpas = (await _resourceService.GetConfigsByCategory(CateGoryConst.RESOURCE_SPA))
  56. // .Where(it => it.Status == CommonStatusConst.ENABLE).ToList();
  57. sysResources.ForEach(it =>
  58. {
  59. if (it.MenuType == SysResourceConst.CATALOG)
  60. it.ParentId = it.Module.Value;//目录的父级ID设置为模块ID
  61. });
  62. //构建菜单树
  63. var tree = ConstructMenuTrees(sysResources, null);
  64. //将单页的排前面根据排序码排序
  65. tree = tree.OrderByDescending(it => it.Category == CateGoryConst.RESOURCE_SPA).ThenBy(it => it.SortCode).ToList();
  66. return tree;
  67. }
  68. /// <inheritdoc />
  69. public async Task Add(MenuAddInput input)
  70. {
  71. await CheckInput(input);//检查参数
  72. var sysResource = input.Adapt<SysResource>();//实体转换
  73. if (await InsertAsync(sysResource))//插入数据
  74. await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//刷新菜单缓存
  75. }
  76. /// <inheritdoc />
  77. public async Task Edit(MenuEditInput input)
  78. {
  79. var resource = await CheckInput(input);//检查参数
  80. var sysResource = input.Adapt<SysResource>();//实体转换
  81. var updatePath = resource.Path != input.Path;//是否更新路径
  82. var permissions = new List<SysRelation>();
  83. if (updatePath)
  84. {
  85. //获取所有角色和用户的权限关系
  86. var rolePermissions = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION);
  87. var userPermissions = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);
  88. //找到所有匹配的权限
  89. rolePermissions = rolePermissions.Where(it => it.TargetId.Contains(resource.Path)).ToList();
  90. userPermissions = userPermissions.Where(it => it.TargetId.Contains(resource.Path)).ToList();
  91. //更新路径
  92. rolePermissions.ForEach(it => it.TargetId = it.TargetId.Replace(resource.Path, input.Path));
  93. userPermissions.ForEach(it => it.TargetId = it.TargetId.Replace(resource.Path, input.Path));
  94. //添加到权限列表
  95. permissions.AddRange(rolePermissions);
  96. permissions.AddRange(userPermissions);
  97. }
  98. //事务
  99. var result = await Tenant.UseTranAsync(async () =>
  100. {
  101. await UpdateAsync(sysResource);//更新数据
  102. if (permissions.Count > 0)//如果权限列表大于0就更新
  103. {
  104. await Context.Updateable(permissions)
  105. .ExecuteCommandAsync();//更新关系表
  106. }
  107. });
  108. if (result.IsSuccess)//如果成功了
  109. {
  110. await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//刷新菜单缓存
  111. //刷新关系表缓存
  112. if (updatePath)
  113. {
  114. await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION);
  115. await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);
  116. }
  117. }
  118. }
  119. /// <inheritdoc />
  120. public async Task Delete(BaseIdListInput input)
  121. {
  122. //获取所有ID
  123. var ids = input.Ids;
  124. if (ids.Count > 0)
  125. {
  126. //获取所有菜单和按钮
  127. var resourceList = await _resourceService.GetListAsync(new List<string> { CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_BUTTON });
  128. //找到要删除的菜单
  129. var sysResources = resourceList.Where(it => ids.Contains(it.Id)).ToList();
  130. //查找内置菜单
  131. var system = sysResources.Where(it => it.Code == SysResourceConst.SYSTEM).FirstOrDefault();
  132. if (system != null)
  133. throw Oops.Bah($"不可删除系统菜单:{system.Title}");
  134. //需要删除的资源ID列表
  135. var resourceIds = new List<long>();
  136. //遍历菜单列表
  137. sysResources.ForEach(it =>
  138. {
  139. //获取菜单所有子节点
  140. var child = _resourceService.GetChildListById(resourceList, it.Id, false);
  141. //将子节点ID添加到删除资源ID列表
  142. resourceIds.AddRange(child.Select(it => it.Id).ToList());
  143. resourceIds.Add(it.Id);//添加到删除资源ID列表
  144. });
  145. ids.AddRange(resourceIds);//添加到删除ID列表
  146. //事务
  147. var result = await Tenant.UseTranAsync(async () =>
  148. {
  149. await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除菜单和按钮
  150. await Context.Deleteable<SysRelation>()//关系表删除对应SYS_ROLE_HAS_RESOURCE
  151. .Where(it => it.Category == CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE && resourceIds.Contains(SqlFunc.ToInt64(it.TargetId)))
  152. .ExecuteCommandAsync();
  153. });
  154. if (result.IsSuccess)//如果成功了
  155. {
  156. await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//资源表菜单刷新缓存
  157. await _resourceService.RefreshCache(CateGoryConst.RESOURCE_BUTTON);//资源表按钮刷新缓存
  158. await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE);//关系表刷新缓存
  159. }
  160. else
  161. {
  162. //写日志
  163. _logger.LogError(result.ErrorMessage, result.ErrorException);
  164. throw Oops.Oh(ErrorCodeEnum.A0002);
  165. }
  166. }
  167. }
  168. /// <inheritdoc />
  169. public async Task<SysResource> Detail(BaseIdInput input)
  170. {
  171. var sysResources = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
  172. var resource = sysResources.Where(it => it.Id == input.Id).FirstOrDefault();
  173. return resource;
  174. }
  175. /// <inheritdoc />
  176. public async Task ChangeModule(MenuChangeModuleInput input)
  177. {
  178. var sysResource = await Detail(new BaseIdInput { Id = input.Id });
  179. if (sysResource != null)
  180. {
  181. if (sysResource.Module == input.Module)//如果模块ID没变直接返回
  182. return;
  183. if (sysResource.ParentId != 0)
  184. throw Oops.Bah("非顶级菜单不可修改所属模块");
  185. //获取所有菜单和模块
  186. var resourceList = await _resourceService.GetListAsync(new List<string> { CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_MODULE });
  187. if (!resourceList.Any(it => it.Category == CateGoryConst.RESOURCE_MODULE && it.Id == input.Module.Value))
  188. throw Oops.Bah("不存在的模块");
  189. //获取所有菜单
  190. var menuList = resourceList.Where(it => it.Category == CateGoryConst.RESOURCE_MENU).ToList();
  191. //获取需要改变模块菜单的所有子菜单
  192. var childList = _resourceService.GetChildListById(menuList, input.Id);
  193. childList.ForEach(it => it.Module = input.Module);
  194. //更新数据
  195. await UpdateRangeAsync(childList);
  196. //刷新菜单缓存
  197. await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);
  198. }
  199. }
  200. #region 方法
  201. /// <summary>
  202. /// 检查输入参数
  203. /// </summary>
  204. /// <param name="sysResource"></param>
  205. private async Task<SysResource> CheckInput(SysResource sysResource)
  206. {
  207. //获取所有菜单列表
  208. var menList = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
  209. //判断是否有同级且同名的菜单
  210. if (menList.Any(it => it.ParentId == sysResource.ParentId && it.Title == sysResource.Title && it.Id != sysResource.Id))
  211. throw Oops.Bah($"存在重复的菜单名称:{sysResource.Title}");
  212. if (sysResource.ParentId != 0)
  213. {
  214. //获取父级,判断父级ID正不正确
  215. var parent = menList.Where(it => it.Id == sysResource.ParentId).FirstOrDefault();
  216. if (parent != null)
  217. {
  218. if (parent.Module != sysResource.Module)//如果父级的模块和当前模块不一样
  219. throw Oops.Bah("模块与上级菜单不一致");
  220. if (parent.Id == sysResource.Id)
  221. throw Oops.Bah("上级菜单不能选择自己");
  222. }
  223. else
  224. {
  225. throw Oops.Bah($"上级菜单不存在:{sysResource.ParentId}");
  226. }
  227. }
  228. //如果ID大于0表示编辑
  229. if (sysResource.Id > 0)
  230. {
  231. var resource = menList.Where(it => it.Id == sysResource.Id).FirstOrDefault();
  232. if (resource == null)
  233. throw Oops.Bah($"菜单不存在:{sysResource.Id}");
  234. return resource;
  235. }
  236. return null;
  237. }
  238. #endregion 方法
  239. }