import pagesJson from 'virtual:pages-json' import type { Page } from '@uni-ku/pages-json/types' interface cousPage extends Page { islogin: boolean name?: string } function generateRoutes() { if (!pagesJson.pages) return [] const routes = pagesJson.pages.map((page) => { const newPath = `/${page.path}` return { ...page, path: newPath } }) as cousPage[] if (pagesJson.subPackages && pagesJson.subPackages.length > 0) { pagesJson.subPackages.forEach((subPackage) => { const subRoutes = subPackage.pages.map((page: any) => { const newPath = `/${subPackage.root}/${page.path}` return { ...page, path: newPath } }) routes.push(...subRoutes) }) } return routes } const router = createRouter({ routes: generateRoutes(), }) /** * 过滤出所有需要登录的name 返回不需要登录的name * */ function whitePathName() { return generateRoutes().filter(it => !it.islogin).map(it => it.name) } router.beforeEach((to, from, next) => { console.log('🚀 beforeEach 守卫触发:', { to, from }, '') const { token, redirectName } = storeToRefs(useUserStore()) if (to.name === 'smqjh-login') { redirectName.value = appendParamsToPath(String(from.path), from.params as any) console.log(redirectName.value, ' redirectName.value') } if (!whitePathName().includes(to.name) && !token.value) { const { confirm: showConfirm } = useGlobalMessage() return new Promise((resolve, reject) => { showConfirm({ title: '警告', msg: '检测到当前状态未登录,是否登录', confirmButtonText: '登录', cancelButtonText: '取消', success() { redirectName.value = String(to.path) // console.log('✅ 用户确认访问,允许导航') router.replace({ name: 'smqjh-login' }) // resolve() }, fail() { // console.log('❌ 用户取消访问,阻止导航') next(false) reject(new Error('用户取消访问')) }, }) }) } // 演示:基本的导航日志记录 if (to.path && from.path) { console.log(`📍 导航: ${from.path} → ${to.path}`) } // 继续导航 next() }) router.afterEach((to, from) => { console.log('🎯 afterEach 钩子触发:', { to, from }) // 演示:简单的页面切换记录 if (to.path) { console.log(`📄 页面切换完成: ${to.path}`) } }) export default router /** * 将 params 参数拼接到 path 路径后面 * 兼容扫码拉起小程序时 q 参数为编码后的 URL 的情况 * @param path 基础路径 * @param params 参数对象 * @returns 拼接后的完整路径 */ function appendParamsToPath(path: string, params: Record): string { if (!params || Object.keys(params).length === 0) { return path } const queryParams: string[] = [] Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { const strValue = String(value) // 处理扫码参数 q,可能是编码后的 URL if (key === 'q') { const extractedParams = extractParamsFromEncodedUrl(strValue) if (extractedParams) { // 将提取的参数合并到 queryParams Object.entries(extractedParams).forEach(([k, v]) => { queryParams.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`) }) return } } // 普通参数直接编码 const encodedKey = encodeURIComponent(key) const encodedValue = encodeURIComponent(strValue) queryParams.push(`${encodedKey}=${encodedValue}`) } }) const queryString = queryParams.join('&') return queryString ? `${path}?${queryString}` : path } /** * 从编码后的 URL 中提取查询参数 * @param encodedUrl 可能被编码的 URL 字符串 * @returns 解析后的查询参数对象,如果不是有效的 URL 则返回 null */ function extractParamsFromEncodedUrl(encodedUrl: string): Record | null { try { // 尝试解码 URL let decodedUrl = encodedUrl // 可能需要多次解码(处理多次编码的情况) while (decodedUrl.includes('%')) { const newDecoded = decodeURIComponent(decodedUrl) if (newDecoded === decodedUrl) break decodedUrl = newDecoded } // 检查是否是有效的 URL 格式 if (!decodedUrl.includes('http://') && !decodedUrl.includes('https://')) { return null } // 提取 ? 后面的查询参数 const questionIndex = decodedUrl.indexOf('?') if (questionIndex === -1) { return null } const queryString = decodedUrl.substring(questionIndex + 1) if (!queryString) { return null } // 解析查询参数 const params: Record = {} const pairs = queryString.split('&') pairs.forEach((pair) => { const equalIndex = pair.indexOf('=') if (equalIndex > 0) { const key = decodeURIComponent(pair.substring(0, equalIndex)) const val = decodeURIComponent(pair.substring(equalIndex + 1)) params[key] = val } else if (pair) { params[decodeURIComponent(pair)] = '' } }) return Object.keys(params).length > 0 ? params : null } catch { return null } }