import router from '@/routers' import { LOGIN_URL } from '@/config' import { type RouteRecordRaw } from 'vue-router' import { ElNotification } from 'element-plus' import { useUserStore } from '@/stores/modules/user' import { useAuthStore } from '@/stores/modules/auth' // 引入 views 文件夹下所有 vue 文件 const modules = import.meta.glob('@/views/**/*.vue') let isInitializing = false /** * 清除已有的动态路由 */ const clearDynamicRoutes = () => { const routes = router.getRoutes() routes.forEach(route => { if (route.name && route.name !== 'layout' && route.name !== 'login' && route.name !== 'testScriptAdd') { router.removeRoute(route.name) } }) } /** * 根据 component 路径查找对应的模块 * @param path 组件路径 */ const resolveComponentModule = async (path: string) => { // 规范化路径,去除首尾斜杠 let normalizedPath = path.trim() if (!normalizedPath.startsWith('/')) { normalizedPath = '/' + normalizedPath } if (normalizedPath.endsWith('.vue')) { normalizedPath = normalizedPath.slice(0, -4) } const fullPath = `/src/views${normalizedPath}.vue` return modules[fullPath] } /** * @description 初始化动态路由 */ export const initDynamicRouter = async () => { if (isInitializing) return Promise.reject(new Error('Dynamic router initialization in progress')) isInitializing = true const userStore = useUserStore() const authStore = useAuthStore() try { // 1. 获取菜单列表 && 按钮权限列表 await authStore.getAuthMenuList() await authStore.getAuthButtonList() // 2. 判断当前用户有没有菜单权限 if (!authStore.authMenuListGet.length) { ElNotification({ title: '无权限访问', message: '当前账号无任何菜单权限,请联系系统管理员!', type: 'warning', duration: 3000 }) userStore.setAccessToken('') userStore.setRefreshToken('') userStore.setExp(0) await router.replace(LOGIN_URL) return Promise.reject('No permission') } // 3. 清理之前的动态路由 clearDynamicRoutes() // 4. 添加动态路由 for (const item of authStore.flatMenuListGet) { // 删除 children 避免冗余嵌套 if (item.children) delete item.children // 处理组件映射 if (item.component && typeof item.component === 'string') { const moduleLoader = await resolveComponentModule(item.component) if (moduleLoader) { item.component = moduleLoader } else { console.warn(`未能找到组件: ${item.component}`) continue } } // 类型守卫:确保满足 RouteRecordRaw 接口要求 if ( typeof item.path === 'string' && (typeof item.component === 'function' || typeof item.redirect === 'string') ) { const routeItem = item as unknown as RouteRecordRaw if (item.meta.isFull) { router.addRoute(routeItem) } else { router.addRoute('layout', routeItem) } } else { console.warn('Invalid route item:', item) } } } catch (error) { // 当按钮 || 菜单请求出错时,重定向到登陆页 userStore.setAccessToken('') userStore.setRefreshToken('') userStore.setExp(0) await router.replace(LOGIN_URL) return Promise.reject(error) } finally { isInitializing = false } }