frontEnd.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { RouteRecordRaw } from 'vue-router';
  2. import { storeToRefs } from 'pinia';
  3. import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index';
  4. import pinia from '/@/stores';
  5. import { Session } from '/@/utils/storage';
  6. import { useUserInfo } from '/@/stores/userInfo';
  7. import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
  8. import { useRoutesList } from '/@/stores/routesList';
  9. import { NextLoading } from '/@/utils/loading';
  10. import {adminRoutes,notFoundAndNoPower, staticRoutes} from '/@/router/route';
  11. // 前端控制路由
  12. /**
  13. * 前端控制路由:初始化方法,防止刷新时路由丢失
  14. * @method NextLoading 界面 loading 动画开始执行
  15. * @method useUserInfo(pinia).setUserInfos() 触发初始化用户信息 pinia
  16. * @method setAddRoute 添加动态路由
  17. * @method setFilterMenuAndCacheTagsViewRoutes 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
  18. */
  19. export async function initFrontEndControlRoutes() {
  20. // 界面 loading 动画开始执行
  21. if (window.nextLoading === undefined) NextLoading.start();
  22. // 无 token 停止执行下一步
  23. if (!Session.get('token')) return false;
  24. // 触发初始化用户信息 pinia
  25. // https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
  26. // await useUserInfo(pinia).setUserInfos();
  27. // 无登录权限时,添加判断
  28. // https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
  29. //TODO 角色过滤替换为权限过滤
  30. // if (useUserInfo().userInfos.roles.length <= 0) return Promise.resolve(true);
  31. // 添加动态路由
  32. // await setAddRoute();
  33. // 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
  34. await setFilterMenuAndCacheTagsViewRoutes();
  35. }
  36. /**
  37. * 添加动态路由
  38. * @method router.addRoute
  39. * @description 此处循环为 dynamicRoutes(/@/router/route)第一个顶级 children 的路由一维数组,非多级嵌套
  40. * @link 参考:https://next.router.vuejs.org/zh/api/#addroute
  41. */
  42. export async function setAddRoute() {
  43. // console.log("添加路由",adminRoutes)
  44. await setFilterRouteEnd().forEach((route: RouteRecordRaw) => {
  45. // console.log("添加路由:",route)
  46. router.addRoute(route);
  47. });
  48. }
  49. /**
  50. * 获取有当前用户权限标识的路由数组,进行对原路由的替换
  51. * @description 替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
  52. * @returns 返回替换后的路由数组
  53. */
  54. export function setFilterRouteEnd() {
  55. /*
  56. let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(adminRoutes));
  57. // notFoundAndNoPower 防止 404、401 不在 layout 布局中,不设置的话,404、401 界面将全屏显示
  58. // 关联问题 No match found for location with path 'xxx'
  59. filterRouteEnd[0].children = [...setFilterRoute(filterRouteEnd[0].children), ...notFoundAndNoPower];
  60. return filterRouteEnd;*/
  61. let filterRouteEnd: any =[];
  62. filterRouteEnd.push(adminRoutes[0])
  63. let adminRouteList: RouteRecordRaw[] | undefined = adminRoutes[0].children;
  64. // @ts-ignore
  65. adminRouteList.forEach((item:RouteRecordRaw)=>{
  66. filterRouteEnd.push(item)
  67. if(item.children&&item.children.length>0){
  68. item.children.forEach((childItem:RouteRecordRaw)=>{
  69. filterRouteEnd.push(childItem)
  70. })
  71. }
  72. })
  73. return filterRouteEnd;
  74. }
  75. /**
  76. * 获取当前用户权限标识去比对路由表(未处理成多级嵌套路由)
  77. * @description 这里主要用于动态路由的添加,router.addRoute
  78. * @link 参考:https://next.router.vuejs.org/zh/api/#addroute
  79. * @param chil dynamicRoutes(/@/router/route)第一个顶级 children 的下路由集合
  80. * @returns 返回有当前用户权限标识的路由数组
  81. */
  82. export function setFilterRoute(chil: any) {
  83. const stores = useUserInfo(pinia);
  84. const { userInfos } = storeToRefs(stores);
  85. let filterRoute: any = [];
  86. chil.forEach((route: any) => {
  87. if (route.meta.roles) {
  88. route.meta.roles.forEach((metaRoles: any) => {
  89. userInfos.value.roles.forEach((roles: any) => {
  90. if (metaRoles === roles) filterRoute.push({ ...route });
  91. });
  92. });
  93. }
  94. });
  95. return filterRoute;
  96. }
  97. /**
  98. * 缓存多级嵌套数组处理后的一维数组
  99. * @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
  100. */
  101. export function setCacheTagsViewRoutes() {
  102. // 获取有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
  103. const stores = useUserInfo(pinia);
  104. const tagsViewRoutes = useTagsViewRoutes(pinia);
  105. const { userInfos } = storeToRefs(stores);
  106. let permMenus = setFilterHasPermsMenu(staticRoutes, userInfos.value.permList);
  107. // 添加到 pinia setTagsViewRoutes 中
  108. let cachetagsViewRoutes = formatTwoStageRoutes(formatFlatteningRoutes(permMenus))[0].children
  109. // console.log("piana tagsViewRoutes>>>",cachetagsViewRoutes)
  110. tagsViewRoutes.setTagsViewRoutes(cachetagsViewRoutes);
  111. }
  112. /**
  113. * 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
  114. * @description 用于左侧菜单、横向菜单的显示
  115. * @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
  116. */
  117. export function setFilterMenuAndCacheTagsViewRoutes() {
  118. const stores = useUserInfo(pinia);
  119. const storesRoutesList = useRoutesList(pinia);
  120. const { userInfos } = storeToRefs(stores);
  121. //管理后台路由设置
  122. // debugger
  123. let routes = [...staticRoutes]
  124. // console.log("设置后台菜单>>>",adminRoutes,userInfos.value.permList)
  125. let menuList = setFilterHasPermsMenu(adminRoutes, userInfos.value.permList);
  126. console.log("设置后台菜单>>>",menuList)
  127. storesRoutesList.setRoutesList(menuList);
  128. setCacheTagsViewRoutes();
  129. }
  130. /**
  131. * 判断路由 `meta.roles` 中是否包含当前登录用户权限字段
  132. * @param roles 用户权限标识,在 userInfos(用户信息)的 roles(登录页登录时缓存到浏览器)数组
  133. * @param route 当前循环时的路由项
  134. * @returns 返回对比后有权限的路由项
  135. */
  136. export function hasRoles(roles: any, route: any) {
  137. if (route.meta && route.meta.roles) return roles.some((role: any) => route.meta.roles.includes(role));
  138. else return true;
  139. }
  140. export function hasMenuPermission(permList: any, route: any) {
  141. if (route.meta && route.meta.perm) return permList.some((perm: any) => route.meta.perm.includes(perm));
  142. else return true;
  143. }
  144. /**
  145. * 获取当前用户权限标识去比对路由表,设置递归过滤有权限的路由
  146. * @param routes 当前路由 children
  147. * @param permList 用户权限标识,(登录页登录时缓存到浏览器)权限数组
  148. * @returns 返回有权限的路由数组 `meta.roles` 中控制
  149. */
  150. export function setFilterHasPermsMenu(routes: any, permList:Array<string>=[]) {
  151. const menuList: any = [];
  152. routes.forEach((route: any) => {
  153. const item = { ...route };
  154. if (hasMenuPermission(permList, item)) {
  155. if (item.children) item.children = setFilterHasPermsMenu(item.children, permList);
  156. // console.log(item)
  157. menuList.push(item);
  158. }
  159. });
  160. return menuList;
  161. }