wangrong
2026-08-30 4c949c0dc9bcae785c281c9d8125295f09810b15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { isExternal } from '@/utils/validate'
import { cloneDeep } from 'lodash'
import { XpackComponent } from '@/components/plugin'
const modules = import.meta.glob('../views/**/*.vue')
export const Layout = () => import('@/layout/index.vue')
const xpackComName = 'components/plugin'
export const LayoutTransition = () => import('@/layout/components/LayoutTransition.vue')
// 后端控制路由生成
export const generateRoutesFn2 = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => {
  const res: AppRouteRecordRaw[] = []
 
  for (const router of routes) {
    let route = { ...router }
 
    if (route.top && route.inLayout) {
      route = decorate(route)
    }
 
    if (route.plugin) {
      const jsName = route.component
      route.component = xpackComName
      route.props = {
        jsname: jsName,
        inLayout: route.inLayout
      }
    }
 
    const data: AppRouteRecordRaw = {
      path: route.path,
      hidden: route.hidden,
      name: route.name,
      redirect: route.redirect,
      meta: route.meta,
      props: route.props as Recordable
    }
 
    if (route.component) {
      let comModule = null
      if (route.component === xpackComName) {
        comModule = XpackComponent
      } else if (!route.component.startsWith('Layout')) {
        comModule = modules[`../views/${route.component}/index.vue`]
      }
 
      if (route.component === 'Layout') {
        data.component = Layout
      } else if (route.component === 'LayoutTransition') {
        data.component = LayoutTransition
      } else if (!comModule) {
      } else {
        data.component = comModule
      }
    }
    if (route.children) {
      data.children = generateRoutesFn2(route.children)
    }
    res.push(data as AppRouteRecordRaw)
  }
 
  return res
}
 
export const formatRoute = (arr: AppCustomRouteRecordRaw[]): AppCustomRouteRecordRaw[] => {
  return arr.map(ele => {
    const router = cloneDeep(ele)
    const { path, children = [] } = router
 
    if (children?.length === 1 && router.path !== '/data') {
      const [route] = children
      router.path = `${path}/${route.path}`
      router.children = []
    }
    return router
  })
}
 
// 包装一层父级目录
export const decorate = (router: AppCustomRouteRecordRaw): AppCustomRouteRecordRaw => {
  const { path, meta, children = [], inLayout, hidden } = router
  const parent = {
    path,
    meta,
    inLayout,
    component: 'Layout',
    children,
    hidden
  }
 
  const current = { ...router }
  current.inLayout = false
  if (!children?.length) {
    current.path = 'index'
    parent.children = [current]
  }
  return parent
}
 
export const resolvePath = (item: AppRouteRecordRaw) => {
  // 如果是首页,就返回重定向路由
  if (item.path === '/') {
    return item.redirect as string
  }
 
  // 如果有子项,默认跳转第一个子项路由
  let path = ''
  /**
   * item 路由子项
   * parent 路由父项
   */
  const getDefaultPath = (ele, parent?) => {
    // 如果path是个外部链接(不建议),直接返回链接,存在个问题:如果是外部链接点击跳转后当前页内容还是上一个路由内容
    if (isExternal(ele.path)) {
      path = ele.path
      return
    }
    // 第一次需要父项路由拼接,所以只是第一个传parent
    if (parent) {
      path += parent.path + '/' + ele.path
    } else {
      path += '/' + ele.path
    }
    // 如果还有子项,继续递归
    if (ele.children) {
      getDefaultPath(ele.children[0])
    }
  }
 
  if (item.children) {
    getDefaultPath(item.children[0], item)
    return path
  }
 
  return item.path
}