SysMenuService.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. using Infrastructure.Attribute;
  2. using Infrastructure.Extensions;
  3. using SqlSugar;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using ZR.Common;
  8. using ZR.Model.System;
  9. using ZR.Model.System.Dto;
  10. using ZR.Model.System.Vo;
  11. using ZR.Service.System.IService;
  12. namespace ZR.Service
  13. {
  14. /// <summary>
  15. /// 菜单
  16. /// </summary>
  17. [AppService(ServiceType = typeof(ISysMenuService), ServiceLifetime = LifeTime.Transient)]
  18. public class SysMenuService : BaseService<SysMenu>, ISysMenuService
  19. {
  20. public ISysRoleService SysRoleService;
  21. public SysMenuService(ISysRoleService sysRoleService)
  22. {
  23. SysRoleService = sysRoleService;
  24. }
  25. /// <summary>
  26. /// 获取所有菜单数(菜单管理)
  27. /// </summary>
  28. /// <returns></returns>
  29. public List<SysMenu> SelectTreeMenuList(MenuQueryDto menu, long userId)
  30. {
  31. List<SysMenu> menuList;
  32. if (SysRoleService.IsAdmin(userId))
  33. {
  34. menuList = SelectTreeMenuList(menu);
  35. }
  36. else
  37. {
  38. var userRoles = SysRoleService.SelectUserRoles(userId);
  39. menuList = SelectTreeMenuListByRoles(menu, userRoles);
  40. }
  41. return menuList ?? new List<SysMenu>();
  42. }
  43. /// <summary>
  44. /// 获取所有菜单列表
  45. /// </summary>
  46. /// <returns></returns>
  47. public List<SysMenu> SelectMenuList(MenuQueryDto menu, long userId)
  48. {
  49. List<SysMenu> menuList;
  50. if (SysRoleService.IsAdmin(userId))
  51. {
  52. menuList = SelectAllMenuList(menu);
  53. }
  54. else
  55. {
  56. var userRoles = SysRoleService.SelectUserRoles(userId);
  57. menuList = SelectMenuListByRoles(menu, userRoles);
  58. }
  59. return menuList;
  60. }
  61. /// <summary>
  62. /// 获取菜单详情
  63. /// </summary>
  64. /// <param name="menuId"></param>
  65. /// <returns></returns>
  66. public SysMenu GetMenuByMenuId(int menuId)
  67. {
  68. return GetFirst(it => it.MenuId == menuId);
  69. }
  70. /// <summary>
  71. /// 根据菜单id获取菜单列表
  72. /// </summary>
  73. /// <param name="menuId"></param>
  74. /// <param name="userId"></param>
  75. /// <returns></returns>
  76. public List<SysMenu> GetMenusByMenuId(int menuId, long userId)
  77. {
  78. var menuExpression = Expressionable.Create<SysMenu>();
  79. menuExpression.And(c => c.ParentId == menuId);
  80. if (!SysRoleService.IsAdmin(userId))
  81. {
  82. var userRoles = SysRoleService.SelectUserRoles(userId);
  83. var roleMenus = Context.Queryable<SysRoleMenu>()
  84. .Where(r => userRoles.Contains(r.Role_id)).Select(s => s.Menu_id).ToList();
  85. menuExpression.And(c => roleMenus.Contains(c.MenuId));
  86. }
  87. var list = GetList(menuExpression.ToExpression()).OrderBy(f => f.OrderNum).ToList();
  88. Context.ThenMapper(list, item =>
  89. {
  90. item.SubNum = Context.Queryable<SysMenu>().SetContext(x => x.ParentId, () => item.MenuId, item).Count;
  91. });
  92. return list;
  93. }
  94. /// <summary>
  95. /// 添加菜单
  96. /// </summary>
  97. /// <param name="menu"></param>
  98. /// <returns></returns>
  99. public int AddMenu(SysMenu menu)
  100. {
  101. menu.Create_time = DateTime.Now;
  102. return InsertReturnIdentity(menu);
  103. }
  104. /// <summary>
  105. /// 编辑菜单
  106. /// </summary>
  107. /// <param name="menu"></param>
  108. /// <returns></returns>
  109. public int EditMenu(SysMenu menu)
  110. {
  111. menu.Icon = string.IsNullOrEmpty(menu.Icon) ? "" : menu.Icon;
  112. return Update(menu, false);
  113. }
  114. /// <summary>
  115. /// 删除菜单管理信息
  116. /// </summary>
  117. /// <param name="menuId"></param>
  118. /// <returns></returns>
  119. public int DeleteMenuById(int menuId)
  120. {
  121. return Delete(menuId);
  122. }
  123. /// <summary>
  124. /// 校验菜单名称是否唯一
  125. /// </summary>
  126. /// <param name="menu"></param>
  127. /// <returns></returns>
  128. public string CheckMenuNameUnique(SysMenu menu)
  129. {
  130. long menuId = menu.MenuId == 0 ? -1 : menu.MenuId;
  131. SysMenu info = GetFirst(it => it.MenuName == menu.MenuName && it.ParentId == menu.ParentId);
  132. //if (info != null && menuId != info.menuId && menu.menuName.Equals(info.menuName))
  133. //{
  134. // return UserConstants.NOT_UNIQUE;
  135. //}
  136. if (info != null && info.MenuId != menu.MenuId)
  137. {
  138. return UserConstants.NOT_UNIQUE;
  139. }
  140. return UserConstants.UNIQUE;
  141. }
  142. /// <summary>
  143. /// 菜单排序
  144. /// </summary>
  145. /// <param name="menuDto"></param>
  146. /// <returns></returns>
  147. public int ChangeSortMenu(MenuDto menuDto)
  148. {
  149. return Update(new SysMenu() { MenuId = menuDto.MenuId, OrderNum = menuDto.OrderNum }, it => new { it.OrderNum });
  150. }
  151. /// <summary>
  152. /// 是否存在菜单子节点
  153. /// </summary>
  154. /// <param name="menuId"></param>
  155. /// <returns></returns>
  156. public bool HasChildByMenuId(long menuId)
  157. {
  158. return Count(it => it.ParentId == menuId) > 0;
  159. }
  160. /// <summary>
  161. /// 获取左边导航栏菜单树
  162. /// </summary>
  163. /// <param name="userId"></param>
  164. /// <returns></returns>
  165. public List<SysMenu> SelectMenuTreeByUserId(long userId)
  166. {
  167. MenuQueryDto dto = new() { Status = "0", MenuTypeIds = "M,C" };
  168. if (SysRoleService.IsAdmin(userId))
  169. {
  170. return SelectTreeMenuList(dto);
  171. }
  172. else
  173. {
  174. List<long> roleIds = SysRoleService.SelectUserRoles(userId);
  175. return SelectTreeMenuListByRoles(dto, roleIds);
  176. }
  177. }
  178. /// <summary>
  179. /// 查询精确到按钮的操作权限
  180. /// </summary>
  181. /// <param name="userId"></param>
  182. /// <returns></returns>
  183. public List<string> SelectMenuPermsByUserId(long userId)
  184. {
  185. var menus = Context.Queryable<SysMenu, SysRoleMenu, SysUserRole, SysRole>((m, rm, ur, r) => new JoinQueryInfos(
  186. JoinType.Left, m.MenuId == rm.Menu_id,
  187. JoinType.Left, rm.Role_id == ur.RoleId,
  188. JoinType.Left, ur.RoleId == r.RoleId
  189. ))
  190. .Where((m, rm, ur, r) => m.Status == "0" && r.Status == "0" && ur.UserId == userId)
  191. .Select((m, rm, ur, r) => m).ToList();
  192. var menuList = menus.Where(f => !string.IsNullOrEmpty(f.Perms));
  193. return menuList.Select(x => x.Perms).Distinct().ToList();
  194. }
  195. /// <summary>
  196. /// 根据用户查询系统菜单列表
  197. /// </summary>
  198. /// <param name="menu"></param>
  199. /// <param name="roles">用户角色集合</param>
  200. /// <returns></returns>
  201. private List<SysMenu> SelectTreeMenuListByRoles(MenuQueryDto menu, List<long> roles)
  202. {
  203. var roleMenus = Context.Queryable<SysRoleMenu>()
  204. .Where(r => roles.Contains(r.Role_id))
  205. .Select(f => f.Menu_id).Distinct().ToList();
  206. return Queryable()
  207. .Where(c => roleMenus.Contains(c.MenuId))
  208. .WhereIF(!string.IsNullOrEmpty(menu.MenuName), (c) => c.MenuName.Contains(menu.MenuName))
  209. .WhereIF(!string.IsNullOrEmpty(menu.Visible), (c) => c.Visible == menu.Visible)
  210. .WhereIF(!string.IsNullOrEmpty(menu.Status), (c) => c.Status == menu.Status)
  211. .WhereIF(!string.IsNullOrEmpty(menu.MenuTypeIds), c => menu.MenuTypeIdArr.Contains(c.MenuType))
  212. .OrderBy((c) => new { c.ParentId, c.OrderNum })
  213. .Select(c => c)
  214. .ToTree(it => it.Children, it => it.ParentId, 0);
  215. }
  216. /// <summary>
  217. /// 获取所有菜单
  218. /// </summary>
  219. /// <returns></returns>
  220. private List<SysMenu> SelectAllMenuList(MenuQueryDto menu)
  221. {
  222. return Queryable()
  223. .WhereIF(!string.IsNullOrEmpty(menu.MenuName), it => it.MenuName.Contains(menu.MenuName))
  224. .WhereIF(!string.IsNullOrEmpty(menu.Visible), it => it.Visible == menu.Visible)
  225. .WhereIF(!string.IsNullOrEmpty(menu.Status), it => it.Status == menu.Status)
  226. .WhereIF(menu.ParentId != null, it => it.ParentId == menu.ParentId)
  227. .OrderBy(it => new { it.ParentId, it.OrderNum })
  228. .ToList();
  229. }
  230. /// <summary>
  231. /// 根据用户查询系统菜单列表
  232. /// </summary>
  233. /// <param name="sysMenu"></param>
  234. /// <param name="roles">用户角色集合</param>
  235. /// <returns></returns>
  236. private List<SysMenu> SelectMenuListByRoles(MenuQueryDto sysMenu, List<long> roles)
  237. {
  238. var roleMenus = Context.Queryable<SysRoleMenu>()
  239. .Where(r => roles.Contains(r.Role_id));
  240. return Queryable()
  241. .InnerJoin(roleMenus, (c, j) => c.MenuId == j.Menu_id)
  242. .Where((c, j) => c.Status == "0")
  243. .WhereIF(!string.IsNullOrEmpty(sysMenu.MenuName), (c, j) => c.MenuName.Contains(sysMenu.MenuName))
  244. .WhereIF(!string.IsNullOrEmpty(sysMenu.Visible), (c, j) => c.Visible == sysMenu.Visible)
  245. .OrderBy((c, j) => new { c.ParentId, c.OrderNum })
  246. .Select(c => c)
  247. .ToList();
  248. }
  249. /// <summary>
  250. /// 获取所有菜单(菜单管理)
  251. /// </summary>
  252. /// <returns></returns>
  253. public List<SysMenu> SelectTreeMenuList(MenuQueryDto menu)
  254. {
  255. int parentId = menu.ParentId != null ? (int)menu.ParentId : 0;
  256. var list = Queryable()
  257. .WhereIF(!string.IsNullOrEmpty(menu.MenuName), it => it.MenuName.Contains(menu.MenuName))
  258. .WhereIF(!string.IsNullOrEmpty(menu.Visible), it => it.Visible == menu.Visible)
  259. .WhereIF(!string.IsNullOrEmpty(menu.Status), it => it.Status == menu.Status)
  260. .WhereIF(!string.IsNullOrEmpty(menu.MenuTypeIds), it => menu.MenuTypeIdArr.Contains(it.MenuType))
  261. .WhereIF(menu.ParentId != null, it => it.ParentId == menu.ParentId)
  262. .OrderBy(it => new { it.ParentId, it.OrderNum })
  263. .ToTree(it => it.Children, it => it.ParentId, parentId);
  264. return list;
  265. }
  266. #region 方法
  267. ///// <summary>
  268. ///// 根据父节点的ID获取所有子节点
  269. ///// </summary>
  270. ///// <param name="list">分类表</param>
  271. ///// <param name="parentId">传入的父节点ID</param>
  272. ///// <returns></returns>
  273. //public List<SysMenu> GetChildPerms(List<SysMenu> list, int parentId)
  274. //{
  275. // List<SysMenu> returnList = new List<SysMenu>();
  276. // var data = list.FindAll(f => f.parentId == parentId);
  277. // foreach (var item in data)
  278. // {
  279. // RecursionFn(list, item);
  280. // returnList.Add(item);
  281. // }
  282. // return returnList;
  283. //}
  284. /// <summary>
  285. /// 递归列表
  286. /// </summary>
  287. /// <param name="list"></param>
  288. /// <param name="t"></param>
  289. private void RecursionFn(List<SysMenu> list, SysMenu t)
  290. {
  291. //得到子节点列表
  292. List<SysMenu> childList = GetChildList(list, t);
  293. t.Children = childList;
  294. foreach (var item in childList)
  295. {
  296. if (GetChildList(list, item).Count() > 0)
  297. {
  298. RecursionFn(list, item);
  299. }
  300. }
  301. }
  302. /// <summary>
  303. /// 递归获取子菜单
  304. /// </summary>
  305. /// <param name="list">所有菜单</param>
  306. /// <param name="sysMenu"></param>
  307. /// <returns></returns>
  308. private List<SysMenu> GetChildList(List<SysMenu> list, SysMenu sysMenu)
  309. {
  310. return list.Where(p => p.ParentId == sysMenu.MenuId).ToList();
  311. }
  312. /// <summary>
  313. /// 获取路由侧边栏,动态生成
  314. /// </summary>
  315. /// <param name="menus"></param>
  316. /// <returns></returns>
  317. public List<RouterVo> BuildMenus(List<SysMenu> menus)
  318. {
  319. List<RouterVo> routers = new List<RouterVo>();
  320. foreach (var menu in menus)
  321. {
  322. RouterVo router = new()
  323. {
  324. Hidden = "1".Equals(menu.Visible),
  325. Name = GetRouteName(menu),
  326. Path = GetRoutePath(menu),
  327. Component = GetComponent(menu),
  328. Meta = new Meta(menu.MenuName, menu.Icon, "1".Equals(menu.IsCache), menu.MenuNameKey, menu.Path)
  329. };
  330. List<SysMenu> cMenus = menu.Children;
  331. //是目录并且有子菜单
  332. if (cMenus != null && cMenus.Count > 0 && (UserConstants.TYPE_DIR.Equals(menu.MenuType)))
  333. {
  334. router.AlwaysShow = true;
  335. router.Redirect = "noRedirect";
  336. router.Children = BuildMenus(cMenus);
  337. }
  338. else if (IsMeunFrame(menu))
  339. {
  340. router.Meta = null;
  341. List<RouterVo> childrenList = new();
  342. RouterVo children = new()
  343. {
  344. Path = menu.Path,
  345. Component = menu.Component,
  346. Name = string.IsNullOrEmpty(menu.Path) ? "" : menu.Path.ToLower(),
  347. Meta = new Meta(menu.MenuName, menu.Icon, "1".Equals(menu.IsCache), menu.MenuNameKey, menu.Path)
  348. };
  349. childrenList.Add(children);
  350. router.Children = childrenList;
  351. }
  352. else if (menu.ParentId == 0 && IsInnerLink(menu))
  353. {
  354. router.Meta = new Meta(menu.MenuName, menu.Icon);
  355. router.Path = "/";
  356. List<RouterVo> childrenList = new();
  357. RouterVo children = new();
  358. string routerPath = InnerLinkReplaceEach(menu.Path);
  359. children.Path = routerPath;
  360. children.Component = UserConstants.INNER_LINK;
  361. children.Name = routerPath.ToLower();
  362. children.Meta = new Meta(menu.MenuName, menu.Icon, menu.Path);
  363. childrenList.Add(children);
  364. router.Children = childrenList;
  365. }
  366. routers.Add(router);
  367. }
  368. return routers;
  369. }
  370. /// <summary>
  371. /// 构建前端所需要下拉树结构
  372. /// </summary>
  373. /// <param name="menus">菜单列表</param>
  374. /// <returns>下拉树结构列表</returns>
  375. public List<SysMenu> BuildMenuTree(List<SysMenu> menus)
  376. {
  377. List<SysMenu> returnList = new List<SysMenu>();
  378. List<long> tempList = menus.Select(f => f.MenuId).ToList();
  379. foreach (var menu in menus)
  380. {
  381. // 如果是顶级节点, 遍历该父节点的所有子节点
  382. if (!tempList.Contains(menu.ParentId))
  383. {
  384. RecursionFn(menus, menu);
  385. returnList.Add(menu);
  386. }
  387. }
  388. if (!returnList.Any())
  389. {
  390. returnList = menus;
  391. }
  392. return returnList;
  393. }
  394. /// <summary>
  395. /// 构建前端所需要下拉树结构
  396. /// </summary>
  397. /// <param name="menus"></param>
  398. /// <returns></returns>
  399. public List<TreeSelectVo> BuildMenuTreeSelect(List<SysMenu> menus)
  400. {
  401. List<SysMenu> menuTrees = BuildMenuTree(menus);
  402. List<TreeSelectVo> treeMenuVos = new List<TreeSelectVo>();
  403. foreach (var item in menuTrees)
  404. {
  405. treeMenuVos.Add(new TreeSelectVo(item));
  406. }
  407. return treeMenuVos;
  408. }
  409. /// <summary>
  410. /// 获取路由名称
  411. /// </summary>
  412. /// <param name="menu">菜单信息</param>
  413. /// <returns>路由名称</returns>
  414. public string GetRouteName(SysMenu menu)
  415. {
  416. string routerName = menu.Path.ToLower();
  417. // 非外链并且是一级目录(类型为目录)
  418. if (IsMeunFrame(menu))
  419. {
  420. routerName = string.Empty;
  421. }
  422. return routerName;
  423. }
  424. /// <summary>
  425. /// 获取路由路径
  426. /// </summary>
  427. /// <param name="menu">菜单信息</param>
  428. /// <returns>路由地址</returns>
  429. public string GetRoutePath(SysMenu menu)
  430. {
  431. string routerPath = menu.Path;
  432. // 内链打开外网方式
  433. if (menu.ParentId != 0 && IsInnerLink(menu))
  434. {
  435. routerPath = InnerLinkReplaceEach(routerPath);
  436. }
  437. // 非外链并且是一级目录(类型为目录)
  438. if (0 == menu.ParentId && UserConstants.TYPE_DIR.Equals(menu.MenuType)
  439. && UserConstants.NO_FRAME.Equals(menu.IsFrame))
  440. {
  441. routerPath = "/" + menu.Path;
  442. }
  443. else if (IsMeunFrame(menu))// 非外链并且是一级目录(类型为菜单)
  444. {
  445. routerPath = "/";
  446. }
  447. return routerPath;
  448. }
  449. /// <summary>
  450. /// 获取组件名称
  451. /// </summary>
  452. /// <param name="menu"></param>
  453. /// <returns></returns>
  454. public string GetComponent(SysMenu menu)
  455. {
  456. string component = UserConstants.LAYOUT;
  457. if (!string.IsNullOrEmpty(menu.Component) && !IsMeunFrame(menu))
  458. {
  459. component = menu.Component;
  460. }
  461. else if (menu.Component.IsEmpty() && menu.ParentId != 0 && IsInnerLink(menu))
  462. {
  463. component = UserConstants.INNER_LINK;
  464. }
  465. else if (string.IsNullOrEmpty(menu.Component) && IsParentView(menu))
  466. {
  467. component = UserConstants.PARENT_VIEW;
  468. }
  469. return component;
  470. }
  471. /// <summary>
  472. /// 是否为菜单内部跳转
  473. /// </summary>
  474. /// <param name="menu">菜单信息</param>
  475. /// <returns></returns>
  476. public bool IsMeunFrame(SysMenu menu)
  477. {
  478. return menu.ParentId == 0 && UserConstants.TYPE_MENU.Equals(menu.MenuType)
  479. && menu.IsFrame.Equals(UserConstants.NO_FRAME);
  480. }
  481. /// <summary>
  482. /// 是否为内链组件
  483. /// </summary>
  484. /// <param name="menu">菜单信息</param>
  485. /// <returns>结果</returns>
  486. public bool IsInnerLink(SysMenu menu)
  487. {
  488. return menu.IsFrame.Equals(UserConstants.NO_FRAME) && Tools.IsUrl(menu.Path);
  489. }
  490. ///
  491. /// <summary>
  492. /// 是否为parent_view组件
  493. /// </summary>
  494. /// <param name="menu">菜单信息</param>
  495. /// <returns></returns>
  496. public bool IsParentView(SysMenu menu)
  497. {
  498. return menu.ParentId != 0 && UserConstants.TYPE_DIR.Equals(menu.MenuType);
  499. }
  500. /// <summary>
  501. /// 内链域名特殊字符替换
  502. /// </summary>
  503. /// <param name = "path" ></ param >
  504. /// < returns ></ returns >
  505. public string InnerLinkReplaceEach(string path)
  506. {
  507. return path.IsNotEmpty() ? path
  508. .Replace(UserConstants.HTTP, "")
  509. .Replace(UserConstants.HTTPS, "")
  510. .Replace(UserConstants.WWW, "")
  511. .Replace(".", "/") : path;
  512. }
  513. #endregion
  514. }
  515. }