// 导入自定义布局 import LoginLayout from './layouts/LoginLayout.vue' // 导入默认布局(必须保留,否则其他页面会404) import DefaultLayout from '@vuepress/theme-default/layouts/Layout.vue' import { defineClientConfig } from 'vuepress/client' import { createPinia } from 'pinia' // 1. 补全所有缺失的核心导入(适配docs根目录的store/utils) import { useUserStore } from './store/modules/user' import { showToast, getUserInfo } from '../utils/request' // 新增getUserInfo // 核心修改:导入全局常量SITE_BASE import { SITE_BASE } from './constants.js'; // 原有组件导入(位置不变,无需修改) import WithAuth from './components/WithAuth.vue' import Login from './components/Login.vue' import helperHTML from './components/helperHTML.vue' import longPic from './components/longPic.vue' export default defineClientConfig({ // 新增:注册布局 layouts: { Layout: DefaultLayout, // 默认布局 LoginLayout: LoginLayout // 登录页布局 }, // 2. 解构出router(路由守卫必须用) enhance({ app, router }) { const pinia = createPinia() app.use(pinia) // 全局注册组件(原有逻辑,无问题) app.component('WithAuth', WithAuth) app.component('Login', Login) app.component('helperHTML', helperHTML) app.component('longPic', longPic) // 权限指令v-auth:修复this指向+Pinia实例化问题 app.directive('auth', { mounted(el, binding) { // 3. Pinia仓库必须执行实例化(核心修复) const userStore = useUserStore() const requiredRoles = binding.value if (!requiredRoles) return // 未登录/无权限直接隐藏 if (!userStore.isLogin) { el.style.display = 'none' return } let hasPermission = false if (typeof requiredRoles === 'string') { hasPermission = userStore.hasRole(requiredRoles) } else if (Array.isArray(requiredRoles)) { hasPermission = requiredRoles.some(role => userStore.hasRole(role)) } if (!hasPermission) el.style.display = 'none' }, updated(el, binding) { // 4. 修复this指向问题:直接复用mounted逻辑,不用this this.mounted.call(this, el, binding) } }) // 全局路由守卫:VuePress 2.x 适配版(白名单+未登录跳登录) const whiteList = ['/login.html'] // 无需登录的页面 // 隐藏登录功能 // router.beforeEach(async (to, from, next) => { // const userStore = useUserStore() // const isLogin = userStore.isLogin // // // 白名单页面,直接放行 // if (whiteList.includes(to.path)) { // next() // return // } // // // 未登录:跳登录页并记录跳转前地址(适配base: /dma_handbook/) // // 替换client.js中路由守卫的未登录跳转代码 // if (!isLogin) { // showToast('请先登录后访问') // // 核心修复:直接使用to.fullPath(已包含SITE_BASE),无需手动拼接 // let redirectPath = to.fullPath // // 兜底校验:极端情况若fullPath未带SITE_BASE,手动拼接(防止地址栏手动修改) // if (!redirectPath.startsWith(SITE_BASE)) { // redirectPath = `${SITE_BASE}${redirectPath.replace(/^\//, '')}` // 去掉开头的/,避免双斜杠 // } // // 编码后拼接登录页地址 // const redirect = encodeURIComponent(redirectPath) // window.location.href = `${SITE_BASE}login.html?redirect=${redirect}` // return // } // // 核心修改:仅【已登录 + 未拉取过用户信息】时,才调用接口 // if (!userStore.isUserInfoFetched) { // await getUserInfo(userStore) // // 拉取成功后,更新标记为true(本次会话不再重复调用) // userStore.setUserInfoFetched(true) // } // // 已登录,正常放行 // next() // }) // 全局退出登录方法:6. 挂载到window,所有环境(Markdown/组件)都能调用 window.$logout = () => { const userStore = useUserStore() userStore.resetStore() // 清除Pinia+localStorage状态 showToast('退出登录成功') window.location.href = `${SITE_BASE}login.html` } }, setup() {}, })