import { nextTick } from 'vue' import { createRouter, createWebHistory } from 'vue-router' import { useUserStore } from '@/stores/user' import { useMenuStore } from '@/stores/menu' import { useDictStore } from '@/stores/dict' import { getToken } from '@/utils/cookie' import NProgress from 'nprogress' import customSystemRouter from './custom-system-router' import { getCustomRouteData } from '@/utils/menu' import mainRouter from './mainRouter' import 'nprogress/nprogress.css' import req from '@/requset/axios' import utilMd5 from '@/utils/md5' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', redirect: { name: 'login' } }, { path: '/login', name: 'login', component: () => import('@/views/Login/index.vue'), meta: { requiresAuth: false } }, { path: '/platLayout', name: 'platLayout', component: () => import('@/components/Layout/index.vue'), children: [ // 自定义前台路由 ...customSystemRouter, // 业务系统菜单 ...mainRouter, // 404页面 { path: '/:catchAll(.*)', component: import('@/views/NotFound/index.vue') } ] }, // 404页面 { path: '/:catchAll(.*)', component: import('@/views/NotFound/index.vue') } ] }) // 配置NProgress NProgress.configure({ showSpinner: false }) let isRegisterRoute = false // 移除url后面的指定参数 const removeUrlParams = (param) => { const query = window.location.search.substring(1) if (!query) { return } const vars = query.split('&') const newVars = [] for (var i = 0; i < vars.length; i++) { var pair = vars[i].split('=') if (pair[0] != param) { newVars.push(vars[i]) } } console.log(newVars) setTimeout(() => { const path = `${window.location.pathname}${ newVars.length > 0 ? '?' : '' }${newVars.join('&')}` window.history.replaceState(null, null, path) }, 1000) } const tokenLogin = async (userInfo, next, routerName, pathInfo) => { const dictStore = useDictStore() const userStore = useUserStore() const menuStore = useMenuStore() const { loginStatus } = await userStore.userLogin(userInfo) if (loginStatus) { // 请求菜单 const firstMenuPath = (await menuStore.userMenuData()) as '' // 请求字典 dictStore.sysDictData() removeUrlParams('tokenKey') if (!firstMenuPath) { ElMessage.warning('抱歉,您暂无可访问菜单!') return } next({ path: firstMenuPath }) } else { window.location.href = 'https://scm-spwz.com/fvue/viewPlat/index' } } // 全局前置守卫 router.beforeEach(async (to, from, next) => { const menuStore = useMenuStore() const userStore = useUserStore() if (to.query.tokenKey) { try { const res = await req.post( window.config.API_BASE_URL + '/api/valid/' + to.query.tokenKey ) if (res.data.state) { let value = res.data.value await tokenLogin( { username: value.account, password: '', token: utilMd5.hexMD5(value.account + 'JDXT') }, next, to.query.routerName, to ) removeUrlParams('tokenKey') return // 关键:token登录完成后直接返回,不执行后续逻辑 } else { // token验证失败,跳转到登录页 next({ name: 'login' }) return } } catch (error) { console.error('Token验证失败:', error) next({ name: 'login' }) return } } NProgress.start() // 记录上一个路由的参数(排除登录页面) if ( from.name && from.name !== 'login' && (Object.keys(from.params).length > 0 || Object.keys(from.query).length > 0) ) { menuStore.recordRouteParams(from.name as string, from.params, from.query) } // 登录验证 if (to.meta.requiresAuth === false) { next() } else { const token = getToken() if (token && userStore.isLogin) { // 检查是否需要加载动态路由 const customRouter = menuStore.getCustomMenuData // const customRouter = getCustomRouteData(normalMenuData) if (customRouter.length > 0 && !isRegisterRoute) { // 添加自定义路由 customRouter.forEach((route) => { const { parentRoutePath, routeObj } = route if (!isRouteExists(routeObj.name, parentRoutePath, routeObj.path)) { // 使用 Vite 的 glob 导入来处理动态路径 const modules = import.meta.glob('@/views/**/*.vue') const component = modules[routeObj.componentUrl] if (!component) { console.error('组件路径不存在:', routeObj.componentUrl) } router.addRoute(parentRoutePath, { path: routeObj.path, name: routeObj.name, component }) } }) await nextTick() isRegisterRoute = true next({ ...to, replace: true }) // 强制刷新当前路由 } else { next() } } else { next({ name: 'login' }) } } }) const isRouteExists = (name: string, parentRoutePath: string, path: string): boolean => { const routes = router.getRoutes() // 检查路由name是否已存在 if (router.hasRoute(name)) return true // 检查完整路径是否已存在 const fullPath = `${parentRoutePath}/${path}`.replace(/\/+/g, '/') return routes.some((r) => r.path === fullPath) } // 全局后置钩子 router.afterEach(() => { NProgress.done() }) export default router