193 lines
5.3 KiB
TypeScript
193 lines
5.3 KiB
TypeScript
import { createRouter, createWebHashHistory } from 'vue-router'
|
|
import type { Router, RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'
|
|
import { isUrl } from '@/utils/is'
|
|
import { useCache } from '@/hooks/web/useCache'
|
|
import { useAppStoreWithOut } from '@/store/modules/app'
|
|
import { omit, cloneDeep } from 'lodash-es'
|
|
|
|
const appStore = useAppStoreWithOut()
|
|
|
|
const { wsCache } = useCache()
|
|
|
|
const modules = import.meta.glob('../../views/**/*.{vue,tsx}')
|
|
|
|
/* Layout */
|
|
const Layout = () => import('@/layout/index.vue')
|
|
|
|
export const getParentLayout = () => {
|
|
return () =>
|
|
new Promise((resolve) => {
|
|
resolve({
|
|
name: 'ParentLayout'
|
|
})
|
|
})
|
|
}
|
|
|
|
export function getRoute(route: RouteLocationNormalized): RouteLocationNormalized {
|
|
if (!route) return route
|
|
const { matched, ...opt } = route
|
|
return {
|
|
...opt,
|
|
matched: (matched
|
|
? matched.map((item) => ({
|
|
meta: item.meta,
|
|
name: item.name,
|
|
path: item.path
|
|
}))
|
|
: undefined) as RouteRecordNormalized[]
|
|
}
|
|
}
|
|
|
|
// 前端控制路由生成
|
|
export function generateRoutesFn1(
|
|
routes: AppRouteRecordRaw[],
|
|
basePath = '/'
|
|
): AppRouteRecordRaw[] {
|
|
const res: AppRouteRecordRaw[] = []
|
|
|
|
for (const route of routes) {
|
|
// skip some route
|
|
if (route.meta && route.meta.hidden && !route.meta.showMainRoute) {
|
|
continue
|
|
}
|
|
|
|
let data: Nullable<AppRouteRecordRaw> = null
|
|
|
|
let onlyOneChild: Nullable<string> = null
|
|
|
|
if (route.children && route.children.length === 1 && !route.meta.alwaysShow) {
|
|
onlyOneChild = (
|
|
isUrl(route.children[0].path)
|
|
? route.children[0].path
|
|
: pathResolve(pathResolve(basePath, route.path), route.children[0].path)
|
|
) as string
|
|
}
|
|
|
|
// 权限过滤,通过获取登录信息里面的角色权限,动态的渲染菜单。
|
|
const list = wsCache.get(appStore.getUserInfo).checkedNodes
|
|
// 开发者可以根据实际情况进行扩展
|
|
for (const item of list) {
|
|
// 通过路径去匹配
|
|
if (isUrl(item.path) && (onlyOneChild === item.path || route.path === item.path)) {
|
|
data = Object.assign({}, route)
|
|
} else {
|
|
const routePath = pathResolve(basePath, onlyOneChild || route.path)
|
|
if (routePath === item.path || (route.meta && route.meta.followRoute === item.path)) {
|
|
data = Object.assign({}, route)
|
|
}
|
|
}
|
|
}
|
|
|
|
// recursive child routes
|
|
if (route.children && data) {
|
|
data.children = generateRoutesFn1(route.children, pathResolve(basePath, data.path))
|
|
}
|
|
if (data) {
|
|
res.push(data as AppRouteRecordRaw)
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
// 后端控制路由生成
|
|
export function generateRoutesFn2(routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] {
|
|
const res: AppRouteRecordRaw[] = []
|
|
|
|
for (const route of routes) {
|
|
const data: AppRouteRecordRaw = {
|
|
path: route.path,
|
|
name: route.name,
|
|
redirect: route.redirect,
|
|
meta: route.meta
|
|
}
|
|
if (route.component) {
|
|
// 动态加载路由文件,可根据实际情况进行自定义逻辑
|
|
const component = route.component as string
|
|
data.component =
|
|
component === '#'
|
|
? Layout
|
|
: component.includes('##')
|
|
? getParentLayout()
|
|
: modules[`../../${route.component}.vue`] || modules[`../../${route.component}.tsx`]
|
|
}
|
|
// recursive child routes
|
|
if (route.children) {
|
|
data.children = generateRoutesFn2(route.children)
|
|
}
|
|
res.push(data as AppRouteRecordRaw)
|
|
}
|
|
return res
|
|
}
|
|
|
|
export function pathResolve(parentPath: string, path: string) {
|
|
return `${parentPath}/${path}`
|
|
}
|
|
|
|
// 路由降级
|
|
export function flatMultiLevelRoutes(routes: AppRouteRecordRaw[]) {
|
|
const modules: AppRouteRecordRaw[] = cloneDeep(routes)
|
|
for (let index = 0; index < modules.length; index++) {
|
|
const route = modules[index]
|
|
if (!isMultipleRoute(route)) {
|
|
continue
|
|
}
|
|
promoteRouteLevel(route)
|
|
}
|
|
return modules
|
|
}
|
|
|
|
// 层级是否大于2
|
|
function isMultipleRoute(route: AppRouteRecordRaw) {
|
|
if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
|
|
return false
|
|
}
|
|
|
|
const children = route.children
|
|
|
|
let flag = false
|
|
for (let index = 0; index < children.length; index++) {
|
|
const child = children[index]
|
|
if (child.children?.length) {
|
|
flag = true
|
|
break
|
|
}
|
|
}
|
|
return flag
|
|
}
|
|
|
|
// 路由降级
|
|
function promoteRouteLevel(route: AppRouteRecordRaw) {
|
|
let router: Router | null = createRouter({
|
|
routes: [route as unknown as RouteRecordNormalized],
|
|
history: createWebHashHistory()
|
|
})
|
|
|
|
const routes = router.getRoutes()
|
|
addToChildren(routes, route.children || [], route)
|
|
router = null
|
|
|
|
route.children = route.children?.map((item) => omit(item, 'children'))
|
|
}
|
|
|
|
// 添加所有子菜单
|
|
function addToChildren(
|
|
routes: RouteRecordNormalized[],
|
|
children: AppRouteRecordRaw[],
|
|
routeModule: AppRouteRecordRaw
|
|
) {
|
|
for (let index = 0; index < children.length; index++) {
|
|
const child = children[index]
|
|
const route = routes.find((item) => item.name === child.name)
|
|
if (!route) {
|
|
continue
|
|
}
|
|
routeModule.children = routeModule.children || []
|
|
if (!routeModule.children.find((item) => item.name === route.name)) {
|
|
routeModule.children?.push(route as unknown as AppRouteRecordRaw)
|
|
}
|
|
if (child.children?.length) {
|
|
addToChildren(routes, child.children, routeModule)
|
|
}
|
|
}
|
|
}
|