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 = null let onlyOneChild: Nullable = 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) } } }