平安校园
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

ResourceService.cs 17 KiB

il y a 4 mois
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. 
  2. //
  3. using System.ComponentModel;
  4. namespace SafeCampus.System;
  5. /// <inheritdoc cref="IResourceService"/>
  6. public class ResourceService : DbRepository<SysResource>, IResourceService
  7. {
  8. private readonly ISimpleCacheService _simpleCacheService;
  9. private readonly IRelationService _relationService;
  10. public ResourceService(ISimpleCacheService simpleCacheService, IRelationService relationService)
  11. {
  12. _simpleCacheService = simpleCacheService;
  13. _relationService = relationService;
  14. }
  15. /// <inheritdoc />
  16. public async Task<List<string>> GetCodeByIds(List<long> ids, string category)
  17. {
  18. //根据分类获取所有
  19. var sysResources = await GetListByCategory(category);
  20. //条件查询
  21. var result = sysResources.Where(it => ids.Contains(it.Id)).Select(it => it.Code).ToList();
  22. return result;
  23. }
  24. /// <inheritdoc/>
  25. public async Task<List<SysResource>> GetListAsync(List<string>? categoryList = null)
  26. {
  27. //定义结果
  28. var sysResources = new List<SysResource>();
  29. //定义资源分类列表,如果是空的则获取全部资源
  30. categoryList = categoryList != null
  31. ? categoryList
  32. : new List<string>
  33. {
  34. CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_BUTTON,
  35. CateGoryConst.RESOURCE_SPA, CateGoryConst.RESOURCE_MODULE
  36. };
  37. //遍历列表
  38. foreach (var category in categoryList)
  39. {
  40. //根据分类获取到资源列表
  41. var data = await GetListByCategory(category);
  42. //添加到结果集
  43. sysResources.AddRange(data);
  44. }
  45. return sysResources;
  46. }
  47. /// <inheritdoc/>
  48. public async Task<List<SysResource>> GetAllModuleAndMenuAndSpaList()
  49. {
  50. //获取所有的菜单和模块以及单页面列表,
  51. var sysResources = await GetListAsync(new List<string>
  52. {
  53. CateGoryConst.RESOURCE_MODULE, CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_SPA
  54. });
  55. if (sysResources != null)
  56. {
  57. //并按分类和排序码排序
  58. sysResources = sysResources.OrderBy(it => it.Category).ThenBy(it => it.SortCode).ToList();
  59. }
  60. return sysResources;
  61. }
  62. /// <inheritdoc/>
  63. public async Task<List<SysResource>> GetMenuAndSpaListByModuleId(long id)
  64. {
  65. //获取所有的菜单和模块以及单页面列表,
  66. var sysResources = await GetListAsync(new List<string> { CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_SPA });
  67. if (sysResources != null)
  68. {
  69. //并按分类和排序码排序
  70. sysResources = sysResources.Where(it => it.Category == CateGoryConst.RESOURCE_SPA || it.Module == id)//根据模块ID获取菜单
  71. .OrderBy(it => it.Category).ThenBy(it => it.SortCode).ToList();//排序
  72. }
  73. return sysResources;
  74. }
  75. /// <inheritdoc/>
  76. public async Task RefreshCache(string category = null)
  77. {
  78. //如果分类是空的
  79. if (category == null)
  80. {
  81. //删除全部key
  82. _simpleCacheService.DelByPattern(SystemConst.CACHE_SYS_RESOURCE);
  83. await GetListAsync();
  84. }
  85. else
  86. {
  87. //否则只删除一个Key
  88. _simpleCacheService.Remove(SystemConst.CACHE_SYS_RESOURCE + category);
  89. await GetListByCategory(category);
  90. }
  91. }
  92. /// <inheritdoc />
  93. public async Task<List<SysResource>> GetChildListById(long resId, bool isContainOneself = true)
  94. {
  95. //获取所有机构
  96. var sysResources = await GetListAsync();
  97. //查找下级
  98. var childList = GetResourceChildren(sysResources, resId);
  99. if (isContainOneself)//如果包含自己
  100. {
  101. //获取自己的机构信息
  102. var self = sysResources.Where(it => it.Id == resId).FirstOrDefault();
  103. if (self != null) childList.Insert(0, self);//如果机构不为空就插到第一个
  104. }
  105. return childList;
  106. }
  107. /// <inheritdoc />
  108. public List<SysResource> GetChildListById(List<SysResource> sysResources, long resId, bool isContainOneself = true)
  109. {
  110. //查找下级
  111. var childList = GetResourceChildren(sysResources, resId);
  112. if (isContainOneself)//如果包含自己
  113. {
  114. //获取自己的机构信息
  115. var self = sysResources.Where(it => it.Id == resId).FirstOrDefault();
  116. if (self != null) childList.Insert(0, self);//如果机构不为空就插到第一个
  117. }
  118. return childList;
  119. }
  120. /// <inheritdoc />
  121. public async Task<List<SysResource>> GetListByCategory(string category)
  122. {
  123. //先从Redis拿
  124. var sysResources = _simpleCacheService.Get<List<SysResource>>(SystemConst.CACHE_SYS_RESOURCE + category);
  125. if (sysResources == null)
  126. {
  127. //redis没有就去数据库拿
  128. sysResources = await base.GetListAsync(it => it.Category == category);
  129. if (sysResources.Count > 0)
  130. {
  131. //插入Redis
  132. _simpleCacheService.Set(SystemConst.CACHE_SYS_RESOURCE + category, sysResources);
  133. }
  134. }
  135. return sysResources;
  136. }
  137. /// <inheritdoc />
  138. public async Task<List<ResTreeSelector>> ResourceTreeSelector()
  139. {
  140. var resourceTreeSelectors = new List<ResTreeSelector>();//定义结果
  141. //获取模块列表
  142. var moduleList = await GetListByCategory(CateGoryConst.RESOURCE_MODULE);
  143. //遍历模块
  144. foreach (var module in moduleList)
  145. {
  146. //将实体转换为ResourceTreeSelectorOutPut获取基本信息
  147. var resourceTreeSelector = module.Adapt<ResTreeSelector>();
  148. resourceTreeSelector.Menu = await GetRoleGrantResourceMenus(module.Id);
  149. resourceTreeSelectors.Add(resourceTreeSelector);
  150. }
  151. return resourceTreeSelectors;
  152. }
  153. /// <inheritdoc />
  154. public List<PermissionTreeSelector> PermissionTreeSelector(List<string> routes)
  155. {
  156. var permissions = new List<PermissionTreeSelector>();//权限列表
  157. var controllerTypes =
  158. App.EffectiveTypes.Where(u =>
  159. !u.IsInterface && !u.IsAbstract && u.IsDefined(typeof(RolePermissionAttribute), false));
  160. foreach (var controller in controllerTypes)
  161. {
  162. var apiAttribute = controller.GetCustomAttribute<ApiDescriptionSettingsAttribute>();//获取接口描述特性
  163. var tag = apiAttribute.Tag;//获取标签
  164. //获取数据权限特性
  165. var routeAttributes = controller.GetCustomAttributes<RouteAttribute>().ToList();
  166. if (routeAttributes == null)
  167. continue;
  168. var route = routeAttributes[0];//取第一个值
  169. var routeName = GetRouteName(controller.Name, route.Template);//赋值路由名称
  170. //如果路由包含在路由列表中
  171. if (routes.Contains(routeName))
  172. {
  173. //获取所有方法
  174. var methods = controller.GetMethods();
  175. //遍历方法
  176. foreach (var method in methods)
  177. {
  178. //获取忽略数据权限特性
  179. var ignoreRolePermission = method.GetCustomAttribute<IgnoreRolePermissionAttribute>();
  180. if (ignoreRolePermission == null)//如果是空的代表需要数据权限
  181. {
  182. //获取接口描述
  183. var displayName = method.GetCustomAttribute<DisplayNameAttribute>();
  184. if (displayName != null)
  185. {
  186. //默认路由名称
  187. var apiRoute = StringHelper.FirstCharToLower(method.Name);
  188. //获取get特性
  189. var requestGet = method.GetCustomAttribute<HttpGetAttribute>();
  190. if (requestGet != null)//如果是get方法
  191. apiRoute = requestGet.Template;
  192. else
  193. {
  194. //获取post特性
  195. var requestPost = method.GetCustomAttribute<HttpPostAttribute>();
  196. if (requestPost != null)//如果是post方法
  197. apiRoute = requestPost.Template;
  198. }
  199. apiRoute = route.Template + $"/{apiRoute}";
  200. if (!apiRoute.StartsWith("/"))
  201. apiRoute = "/" + apiRoute;//如果路由地址不是/开头则加上/防止控制器没写
  202. var apiName = displayName.DisplayName;//如果描述不为空则接口名称用描述的名称
  203. //合并
  204. var permissionName = apiRoute + $"[{tag}-{apiName}]";
  205. //添加到权限列表
  206. permissions.Add(new PermissionTreeSelector
  207. {
  208. ApiName = apiName,
  209. ApiRoute = apiRoute,
  210. PermissionName = permissionName
  211. });
  212. }
  213. }
  214. }
  215. }
  216. }
  217. return permissions;
  218. }
  219. /// <inheritdoc />
  220. public async Task<List<SysResource>> GetResourcesByIds(List<long> ids, string category)
  221. {
  222. //获取所有菜单
  223. var menuList = await GetListByCategory(category);
  224. //获取菜单信息
  225. var menus = menuList.Where(it => ids.Contains(it.Id)).ToList();
  226. return menus;
  227. }
  228. /// <inheritdoc />
  229. public List<SysResource> GetResourceParent(List<SysResource> resourceList, long parentId)
  230. {
  231. //找上级资源ID列表
  232. var resources = resourceList.Where(it => it.Id == parentId).FirstOrDefault();
  233. if (resources != null)//如果数量大于0
  234. {
  235. var data = new List<SysResource>();
  236. var parents = GetResourceParent(resourceList, resources.ParentId.Value);
  237. data.AddRange(parents);//添加子节点;
  238. data.Add(resources);//添加到列表
  239. return data;//返回结果
  240. }
  241. return new List<SysResource>();
  242. }
  243. #region 方法
  244. /// <summary>
  245. /// 获取路由地址名称
  246. /// </summary>
  247. /// <param name="controllerName">控制器地址</param>
  248. /// <param name="template">路由名称</param>
  249. /// <returns></returns>
  250. private string GetRouteName(string controllerName, string template)
  251. {
  252. if (!template.StartsWith("/"))
  253. template = "/" + template;//如果路由名称不是/开头则加上/防止控制器没写
  254. if (template.Contains("[controller]"))
  255. {
  256. controllerName = controllerName.Replace("Controller", "");//去掉Controller
  257. controllerName = StringHelper.FirstCharToLower(controllerName);//转首字母小写写
  258. template = template.Replace("[controller]", controllerName);//替换[controller]
  259. }
  260. return template;
  261. }
  262. /// <summary>
  263. /// 获取资源所有下级
  264. /// </summary>
  265. /// <param name="resourceList">资源列表</param>
  266. /// <param name="parentId">父ID</param>
  267. /// <returns></returns>
  268. public List<SysResource> GetResourceChildren(List<SysResource> resourceList, long parentId)
  269. {
  270. //找下级资源ID列表
  271. var resources = resourceList.Where(it => it.ParentId == parentId).ToList();
  272. if (resources.Count > 0)//如果数量大于0
  273. {
  274. var data = new List<SysResource>();
  275. foreach (var item in resources)//遍历资源
  276. {
  277. var res = GetResourceChildren(resourceList, item.Id);
  278. data.AddRange(res);//添加子节点;
  279. data.Add(item);//添加到列表
  280. }
  281. return data;//返回结果
  282. }
  283. return new List<SysResource>();
  284. }
  285. /// <summary>
  286. /// 获取授权菜单
  287. /// </summary>
  288. /// <param name="moduleId">模块ID</param>
  289. /// <returns></returns>
  290. public async Task<List<ResTreeSelector.RoleGrantResourceMenu>> GetRoleGrantResourceMenus(long moduleId)
  291. {
  292. var roleGrantResourceMenus = new List<ResTreeSelector.RoleGrantResourceMenu>();//定义结果
  293. var allMenuList = (await GetListByCategory(CateGoryConst.RESOURCE_MENU)).Where(it => it.Module == moduleId).ToList();//获取所有菜单列表
  294. var allButtonList = await GetListByCategory(CateGoryConst.RESOURCE_BUTTON);//获取所有按钮列表
  295. var parentMenuList = allMenuList.Where(it => it.ParentId == SafeCampusConst.ZERO).ToList();//获取一级目录
  296. //遍历一级目录
  297. foreach (var parent in parentMenuList)
  298. {
  299. //如果是目录则去遍历下级
  300. if (parent.MenuType == SysResourceConst.CATALOG)
  301. {
  302. //获取所有下级菜单
  303. var menuList = GetChildListById(allMenuList, parent.Id, false);
  304. if (menuList.Count > 0)//如果有菜单
  305. {
  306. //遍历下级菜单
  307. foreach (var menu in menuList)
  308. {
  309. //如果菜单类型是菜单
  310. if (menu.MenuType is SysResourceConst.MENU or SysResourceConst.SUBSET)
  311. {
  312. //获取菜单下按钮集合并转换成对应实体
  313. var buttonList = allButtonList.Where(it => it.ParentId == menu.Id).ToList();
  314. var buttons = buttonList.Adapt<List<ResTreeSelector.RoleGrantResourceButton>>();
  315. roleGrantResourceMenus.Add(new ResTreeSelector.RoleGrantResourceMenu
  316. {
  317. Id = menu.Id,
  318. ParentId = parent.Id,
  319. ParentName = parent.Title,
  320. Module = moduleId,
  321. Title = GetRoleGrantResourceMenuTitle(menuList, menu),//菜单名称需要特殊处理因为有二级菜单
  322. Button = buttons
  323. });
  324. }
  325. else if (menu.MenuType == SysResourceConst.LINK || menu.MenuType == SysResourceConst.IFRAME)//如果是内链或者外链
  326. {
  327. //直接加到资源列表
  328. roleGrantResourceMenus.Add(new ResTreeSelector.RoleGrantResourceMenu
  329. {
  330. Id = menu.Id,
  331. ParentId = parent.Id,
  332. ParentName = parent.Title,
  333. Module = moduleId,
  334. Title = menu.Title
  335. });
  336. }
  337. }
  338. }
  339. else
  340. {
  341. //否则就将自己加到一级目录里面
  342. roleGrantResourceMenus.Add(new ResTreeSelector.RoleGrantResourceMenu
  343. {
  344. Id = parent.Id,
  345. ParentId = parent.Id,
  346. ParentName = parent.Title,
  347. Module = moduleId
  348. });
  349. }
  350. }
  351. else
  352. {
  353. //就将自己加到一级目录里面
  354. var roleGrantResourcesButtons = new ResTreeSelector.RoleGrantResourceMenu
  355. {
  356. Id = parent.Id,
  357. ParentId = parent.Id,
  358. ParentName = parent.Title,
  359. Module = moduleId,
  360. Title = parent.Title
  361. };
  362. //如果菜单类型是菜单
  363. if (parent.MenuType == SysResourceConst.MENU)
  364. {
  365. //获取菜单下按钮集合并转换成对应实体
  366. var buttonList = allButtonList.Where(it => it.ParentId == parent.Id).ToList();
  367. roleGrantResourcesButtons.Button = buttonList.Adapt<List<ResTreeSelector.RoleGrantResourceButton>>();
  368. }
  369. roleGrantResourceMenus.Add(roleGrantResourcesButtons);
  370. }
  371. }
  372. return roleGrantResourceMenus;
  373. }
  374. /// <inheritdoc />
  375. public string GetRoleGrantResourceMenuTitle(List<SysResource> menuList, SysResource menu)
  376. {
  377. //查找菜单上级
  378. var parentList = GetResourceParent(menuList, menu.ParentId.Value);
  379. //如果有父级菜单
  380. if (parentList.Count > 0)
  381. {
  382. var titles = parentList.Select(it => it.Title).ToList();//提取出父级的name
  383. var title = string.Join("- ", titles) + $"-{menu.Title}";//根据-分割,转换成字符串并在最后加上菜单的title
  384. return title;
  385. }
  386. return menu.Title;//原路返回
  387. }
  388. #endregion 方法
  389. }