routerHelper.ts 5.4 KB

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