user_handbook/docs/.vuepress/client.js

154 lines
5.9 KiB
JavaScript
Raw Normal View History

2026-03-30 10:23:03 +08:00
// 导入自定义布局
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'
import FaqList from './components/FaqList.vue'
import LongPicSplit from './components/LongPicSplit.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)
app.component('FaqList', FaqList)
app.component('LongPicSplit', LongPicSplit)
// 权限指令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'] // 无需登录的页面
// 上线做处理
if (typeof window == 'undefined') {
return
}
// 隐藏登录功能
// router.beforeEach(async (to, from, next) => {
// const userStore = useUserStore()
// const isLogin = userStore.isLogin
//
// // 白名单页面,直接放行
// if (whiteList.includes(to.path)) {
// next()
// return
// }
// if (typeof window == 'undefined') {
// 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()
// })
// ==============================================
// 【唯一正确】等待页面完全加载完再滚动锚点
// 解决:图片/长图未加载完 → 滚动错位、自动上飘
// ==============================================
// ==============================================
// 【VuePress 正确】监听页面完全加载完毕
// 100% 解决:图片未加载完 → 滚动错位、往上飘
// ==============================================
router.afterEach(async (to) => {
if (!to.hash) return
// ======================================
// 【这里就是:等待页面完全加载完成】
// ======================================
await new Promise(resolve => setTimeout(resolve, 200)) // 等待DOM渲染
// 等待【所有图片】加载完成
await Promise.allSettled(
Array.from(document.images).map(img => {
return new Promise(resolve => {
if (img.complete) resolve()
img.onload = resolve
img.onerror = resolve
})
})
)
await new Promise(resolve => setTimeout(resolve, 200)) // 等待高度稳定
console.log('12321==')
// ======================================
// 【到这里:页面才算 100% 加载完成】
// 现在再滚动,绝对不会飘!
// ======================================
// const target = document.querySelector(to.hash)
// if (!target) return
//
// const top = target.offsetTop - 60
// window.scrollTo(0, top)
})
},
setup() {},
})