import router from './router' import { ElMessage } from 'element-plus' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { getToken } from '@/utils/auth' import { isHttp, isPathMatch } from '@/utils/validate' import { isRelogin } from '@/utils/request' import useUserStore from '@/store/modules/user' import useLockStore from '@/store/modules/lock' import useSettingsStore from '@/store/modules/settings' import usePermissionStore from '@/store/modules/permission' import useNoticeStore from '@/store/modules/notice' import useTagsViewStore from '@/store/modules/tagsView' // 全局变量,用于控制公告弹窗只显示一次 let hasShownNoticePopup = false NProgress.configure({ showSpinner: false }) const whiteList = ['/login', '/register'] const isWhiteList = (path) => { return whiteList.some(pattern => isPathMatch(pattern, path)) } router.beforeEach(async (to, from) => { NProgress.start() if (getToken()) { to.meta.title && useSettingsStore().setTitle(to.meta.title) const isLock = useLockStore().isLock if (to.path === '/login') { NProgress.done() return { path: '/' } } if (isWhiteList(to.path)) { return true } if (isLock && to.path !== '/lock') { NProgress.done() return { path: '/lock' } } if (!isLock && to.path === '/lock') { NProgress.done() return { path: '/' } } if (useUserStore().roles.length === 0) { isRelogin.show = true try { await useUserStore().getInfo() isRelogin.show = false const accessRoutes = await usePermissionStore().generateRoutes() accessRoutes.forEach(route => { if (!isHttp(route.path)) { if (!router.hasRoute(route.name)) { try { router.addRoute(route) } catch (e) { // 路由名重复时跳过,不影响其他路由加载 console.warn('路由添加跳过(名称重复):', route.name, e.message) } } } }) useNoticeStore().startPolling() useTagsViewStore().loadPersistedViews() return { ...to, replace: true } } catch (err) { console.error('路由加载失败:', err) await useUserStore().logOut() ElMessage.error(err.message || '登录已过期') return { path: '/login' } } } // 铁律: 路由权限校验 — 目标路由必须在已注册的路由中存在 // 防止切换账户后,通过旧标签或直接输入 URL 访问无权限页面 const resolved = router.resolve(to) if (resolved.matched.length === 0 || resolved.name === 'NotFound') { // 路由不存在(未注册),拒绝导航 ElMessage.warning('无权访问该页面') return { path: '/' } } return true } else { if (isWhiteList(to.path)) { return true } NProgress.done() return `/login?redirect=${to.fullPath}` } }) router.afterEach(() => { NProgress.done() // 登录成功后显示公告弹窗(仅限非登录页面且未显示过) const token = getToken() const isLoginPage = router.currentRoute.value.path === '/login' if (token && !isLoginPage && !hasShownNoticePopup) { setTimeout(() => { showNoticePopupGlobally() hasShownNoticePopup = true }, 1500) } }) // 全局函数:显示公告弹窗 function showNoticePopupGlobally() { try { const layouts = document.querySelectorAll('.app-wrapper') for (const layout of layouts) { const noticePopupRef = layout.__vue_app__?.config.globalProperties.$refs?.noticePopupRef if (noticePopupRef && noticePopupRef.showNotice) { noticePopupRef.showNotice() return } } window.dispatchEvent(new CustomEvent('show-notice-popup')) } catch (error) { console.error('显示公告弹窗失败:', error) } }