import config from '@/configs'; import store from '@/store'; import { createRouter, createWebHistory } from 'vue-router'; // 示例模块 import demoModule from './demo'; // 全局路由 export const globalRoutes = [ { path: '/login', name: 'Login', component: () => import('@/views/global/login.vue'), meta: { global: true, }, }, { path: '/404', name: '404', component: () => import('@/views/global/404.vue'), meta: { global: true, }, }, ]; export const demoRoutes = import.meta.env.MODE === 'development' ? demoModule : []; // 动态模块 export const dynamicRoutes = []; const modules = import.meta.globEager('./modules/*.js'); Object.values(modules).forEach((mod) => { dynamicRoutes.push(...mod.default); }); // 本地路由 export const routes = [ ...globalRoutes, { path: '/', name: 'App', redirect: { name: 'Home' }, component: () => import('@/layouts/default.vue'), meta: { layout: true, title: '首页', icon: 'home-fill', }, children: [ { path: '/home', name: 'Home', component: () => import('@/views/home/index.vue'), meta: { title: '首页', icon: 'home-fill', }, }, ], }, ...dynamicRoutes, ...demoRoutes, { path: '/:pathMatch(.*)*', redirect: '/404', name: 'NotFound', meta: { global: true, }, }, ]; const router = createRouter({ history: createWebHistory(), routes: config.useLocalRouter ? routes : globalRoutes, }); router.onError((error, to) => { console.info('[router] error', error, to); }); router.beforeEach(async (to, from, next) => { if (store.state.local.token) { if (!store.state.auth.permission.length) { await store.dispatch('auth/getUserInfo'); if (config.useLocalRouter) { store.commit('auth/setPermission', routes); } else { await store.dispatch('auth/getPermission'); } next({ ...to, replace: true }); } else { console.info(`[router] from ${from.name} to ${to.name}`); const deep = (route) => { let child = (route.children || []).find((item) => !item.meta?.hidden); return child?.children?.length ? deep(child?.children) : child?.name; }; let childName = deep([...to.matched].pop()); if (childName) { next({ name: childName }); } else { next(); store.commit('layout/setActiveAside', to.matched[0].name); store.commit('layout/setActiveMenu', to.name); store.commit('layout/setActiveTab', to.name); store.commit('layout/setBreakcrumbList', to.matched); store.commit('layout/addTab', to); } } } else if (to.meta.global) { next(); } else { next(false); store.dispatch('auth/logout', to.fullPath); } }); export default router; /** * 多级嵌套路由时,由于父级路由页面中没有router-view组件所以子级路由页面无法显示 * 所以需要将路由规则展平处理 * @param {*} routes * @param {*} parent */ const flatRoutes = (routes, parent = { path: '/', meta: {} }) => routes.flatMap((route) => { let res = []; if (!route.path.startsWith('/')) { if (!parent.path.endsWith('/')) { parent.path += '/'; } route.path = parent.path + route.path; } route.meta.menu = route.path.replaceAll(/\/:[^?]+\?/g, ''); let activeMenu = route.meta.activeMenu; if (!activeMenu && route.meta.hidden) { activeMenu = parent.meta.menu; } route.meta.activeMenu = activeMenu || route.meta.menu; const children = flatRoutes(route.children || [], route); route.redirect = children.find((item) => !item.meta.hidden)?.meta.menu; if (route.meta.layout) { route.children = children; res = [route]; } else { res = [route, ...children]; } return res; }); export const reset = (routes) => { router.getRoutes().forEach((item) => { router.removeRoute(item.name); }); if (!config.useLocalRouter) { routes = [ ...globalRoutes, ...routes, ...demoRoutes, { path: '/:pathMatch(.*)*', redirect: '/404', name: 'NotFound', meta: { global: true, }, }, ]; } flatRoutes(routes).forEach(router.addRoute); store.commit( 'layout/setNotKeepAliveList', router .getRoutes() .filter((item) => item.meta.keepAlive === false) .map((item) => item.name) ); console.info('[router] reset', router.getRoutes()); };