routerHelper.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import { createRouter, createWebHashHistory } from 'vue-router'
  2. import type { Router, RouteLocationNormalized, RouteRecordNormalized, RouteMeta } from 'vue-router'
  3. import { isUrl } from '@/utils/is'
  4. import { useCache } from '@/hooks/web/useCache'
  5. import { useAppStoreWithOut } from '@/store/modules/app'
  6. import { omit, cloneDeep } from 'lodash-es'
  7. const appStore = useAppStoreWithOut()
  8. const { wsCache } = useCache()
  9. const modules = import.meta.glob('../../views/**/*.{vue,tsx}')
  10. /* Layout */
  11. export const Layout = () => import('@/layout/Layout.vue')
  12. export const getParentLayout = () => {
  13. return () =>
  14. new Promise((resolve) => {
  15. resolve({
  16. name: 'ParentLayout'
  17. })
  18. })
  19. }
  20. export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
  21. if (!route) return route
  22. const { matched, ...opt } = route
  23. return {
  24. ...opt,
  25. matched: (matched
  26. ? matched.map((item) => ({
  27. meta: item.meta,
  28. name: item.name,
  29. path: item.path
  30. }))
  31. : undefined) as RouteRecordNormalized[]
  32. }
  33. }
  34. // 前端控制路由生成
  35. export const generateRoutesFn1 = (
  36. routes: AppRouteRecordRaw[],
  37. basePath = '/'
  38. ): AppRouteRecordRaw[] => {
  39. const res: AppRouteRecordRaw[] = []
  40. for (const route of routes) {
  41. const meta = route.meta as RouteMeta
  42. // skip some route
  43. if (meta.hidden && !meta.showMainRoute) {
  44. continue
  45. }
  46. let data: Nullable<AppRouteRecordRaw> = null
  47. let onlyOneChild: Nullable<string> = null
  48. if (route.children && route.children.length === 1 && !meta.alwaysShow) {
  49. onlyOneChild = (
  50. isUrl(route.children[0].path)
  51. ? route.children[0].path
  52. : pathResolve(pathResolve(basePath, route.path), route.children[0].path)
  53. ) as string
  54. }
  55. // 权限过滤,通过获取登录信息里面的角色权限,动态的渲染菜单。
  56. const list = wsCache.get(appStore.getUserInfo).checkedNodes
  57. // 开发者可以根据实际情况进行扩展
  58. for (const item of list) {
  59. // 通过路径去匹配
  60. if (isUrl(item.path) && (onlyOneChild === item.path || route.path === item.path)) {
  61. data = Object.assign({}, route)
  62. } else {
  63. const routePath = pathResolve(basePath, onlyOneChild || route.path)
  64. if (routePath === item.path || meta.followRoute === item.path) {
  65. data = Object.assign({}, route)
  66. }
  67. }
  68. }
  69. // recursive child routes
  70. if (route.children && data) {
  71. data.children = generateRoutesFn1(route.children, pathResolve(basePath, data.path))
  72. }
  73. if (data) {
  74. res.push(data as AppRouteRecordRaw)
  75. }
  76. }
  77. return res
  78. }
  79. // 后端控制路由生成
  80. export const generateRoutesFn2 = (routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] => {
  81. const res: AppRouteRecordRaw[] = []
  82. for (const route of routes) {
  83. const data: AppRouteRecordRaw = {
  84. path: route.path,
  85. name: route.name,
  86. redirect: route.redirect,
  87. meta: route.meta
  88. }
  89. if (route.component) {
  90. const comModule =
  91. modules[`../../${route.component}.vue`] || modules[`../../${route.component}.tsx`]
  92. if (comModule) {
  93. // 动态加载路由文件,可根据实际情况进行自定义逻辑
  94. const component = route.component as string
  95. data.component =
  96. component === '#' ? Layout : component.includes('##') ? getParentLayout() : comModule
  97. } else {
  98. console.error(`未找到${route.component}.vue文件或${route.component}.tsx文件,请创建`)
  99. }
  100. }
  101. // recursive child routes
  102. if (route.children) {
  103. data.children = generateRoutesFn2(route.children)
  104. }
  105. res.push(data as AppRouteRecordRaw)
  106. }
  107. return res
  108. }
  109. export const pathResolve = (parentPath: string, path: string) => {
  110. const childPath = path.startsWith('/') || !path ? path : `/${path}`
  111. return `${parentPath}${childPath}`
  112. }
  113. // 路由降级
  114. export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
  115. const modules: AppRouteRecordRaw[] = cloneDeep(routes)
  116. for (let index = 0; index < modules.length; index++) {
  117. const route = modules[index]
  118. if (!isMultipleRoute(route)) {
  119. continue
  120. }
  121. promoteRouteLevel(route)
  122. }
  123. return modules
  124. }
  125. // 层级是否大于2
  126. const isMultipleRoute = (route: AppRouteRecordRaw) => {
  127. if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
  128. return false
  129. }
  130. const children = route.children
  131. let flag = false
  132. for (let index = 0; index < children.length; index++) {
  133. const child = children[index]
  134. if (child.children?.length) {
  135. flag = true
  136. break
  137. }
  138. }
  139. return flag
  140. }
  141. // 生成二级路由
  142. const promoteRouteLevel = (route: AppRouteRecordRaw) => {
  143. let router: Router | null = createRouter({
  144. routes: [route as unknown as RouteRecordNormalized],
  145. history: createWebHashHistory()
  146. })
  147. const routes = router.getRoutes()
  148. addToChildren(routes, route.children || [], route)
  149. router = null
  150. route.children = route.children?.map((item) => omit(item, 'children'))
  151. }
  152. // 添加所有子菜单
  153. const addToChildren = (
  154. routes: RouteRecordNormalized[],
  155. children: AppRouteRecordRaw[],
  156. routeModule: AppRouteRecordRaw
  157. ) => {
  158. for (let index = 0; index < children.length; index++) {
  159. const child = children[index]
  160. const route = routes.find((item) => item.name === child.name)
  161. if (!route) {
  162. continue
  163. }
  164. routeModule.children = routeModule.children || []
  165. if (!routeModule.children.find((item) => item.name === route.name)) {
  166. routeModule.children?.push(route as unknown as AppRouteRecordRaw)
  167. }
  168. if (child.children?.length) {
  169. addToChildren(routes, child.children, routeModule)
  170. }
  171. }
  172. }