修改router 刷新404

This commit is contained in:
shaoleiliu-netizen123 2026-08-04 12:41:32 +08:00
parent c44622cad6
commit c83470087e
2 changed files with 90 additions and 85 deletions

View File

@ -1,5 +1,6 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import type { MenuInfo } from '@/api/auth'
import { useUserStore } from '@/stores/user'
//import type { MenuInfo } from '@/api/auth'
// 动态导入所有页面组件
const modules = import.meta.glob('/src/views/**/*.vue')
@ -34,7 +35,7 @@ const routes: RouteRecordRaw[] = [
component: () => import('@/views/dashboard/index.vue'),
meta: { title: '首页', icon: 'HomeOutline' }
},
// 个人中心
{
path: 'profile',
@ -216,11 +217,16 @@ const routes: RouteRecordRaw[] = [
}
]
},
// {
// path: '/:pathMatch(.*)',
// name: 'NotFound',
// component: () => import('@/views/error/404.vue'),
// meta: { title: '404', requiresAuth: false }
// }
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
path: '/:pathMatch(.*)',
component: () => import('@/views/error/404.vue'),
meta: { title: '404', requiresAuth: false }
// meta: { title: '404', requiresAuth: false }
}
]
@ -232,47 +238,34 @@ const router = createRouter({
// 已添加的动态路由
const addedRouteNames = new Set<string>()
// 动态路由是否已初始化
let dynamicRoutesInitialized = false
/**
*
*/
export function addDynamicRoutes(menus: MenuInfo[]) {
console.log('[动态路由] 开始处理菜单:', menus)
// 获取 Layout 路由的现有子路由路径
const getLayoutChildPaths = () => {
const layoutRoute = router.getRoutes().find(r => r.name === 'Layout')
if (layoutRoute && layoutRoute.children) {
return new Set(layoutRoute.children.map(c => c.path))
}
return new Set<string>()
}
const addRoutes = (menuList: MenuInfo[]) => {
export function addDynamicRoutes(menus: any) { //MenuInfo[]
//console.log('[动态路由] 开始处理菜单:', menus)
const addRoutes = (menuList: any) => { //MenuInfo[]
for (const menu of menuList) {
// 只处理菜单类型(type=2),且有 path
if (menu.type === 2 && menu.path) {
const routeName = 'Dynamic-' + menu.id
// 规范化路径,去掉开头的 /
// 检查是否已经有同路径的静态路由
const existingRoutes = router.getRoutes()
const menuPath = menu.path.startsWith('/') ? menu.path.slice(1) : menu.path
// 检查是否已经有同路径的路由(检查 Layout 的子路由)
const layoutChildPaths = getLayoutChildPaths()
const pathExists = layoutChildPaths.has(menuPath) || layoutChildPaths.has('/' + menuPath)
const pathExists = existingRoutes.some(r => r.path === '/' + menuPath || r.path === menuPath)
if (pathExists) {
console.log(`[动态路由] 跳过(已存在): ${menuPath}`)
// console.log(`[动态路由] 跳过(已存在): ${menuPath}`)
continue
}
if (addedRouteNames.has(routeName)) {
console.log(`[动态路由] 跳过(已添加): ${menuPath}`)
//console.log(`[动态路由] 跳过(已添加): ${menuPath}`)
continue
}
// 判断是否是外链菜单
if (menu.isFrame === 1 && menu.component) {
// 外链菜单,使用 iframe 组件
@ -292,36 +285,11 @@ export function addDynamicRoutes(menus: MenuInfo[]) {
} else if (menu.component) {
// 普通菜单,加载组件
const componentName = menu.component.startsWith('/') ? menu.component.slice(1) : menu.component
// 组件路径映射表解决菜单component与实际文件路径不匹配的问题
const componentMapping: Record<string, string> = {
'biz/toolUsage': 'biz/tool/usage/index',
'biz/toolUsage/index': 'biz/tool/usage/index',
'biz/tool/usage': 'biz/tool/usage/index',
}
// 查找映射关系
const mappedComponent = componentMapping[componentName] || componentName
// 尝试多种路径加载组件
let component = null
const possiblePaths = [
`/src/views/${mappedComponent}.vue`,
`/src/views/${mappedComponent}/index.vue`,
`/src/views/${componentName}.vue`,
`/src/views/${componentName}/index.vue`,
]
for (const path of possiblePaths) {
if (modules[path]) {
component = modules[path]
console.log(`[动态路由] 找到组件: ${path}`)
break
}
}
console.log(`[动态路由] 处理: path=${menuPath}, componentName=${componentName}, mappedComponent=${mappedComponent}, 组件存在=${!!component}`)
const componentPath = `/src/views/${componentName}.vue`
const component = modules[componentPath]
//console.log(`[动态路由] 处理: path=${menuPath}, component=${componentPath}, 组件存在=${!!component}`)
if (component) {
router.addRoute('Layout', {
path: menuPath,
@ -334,23 +302,22 @@ export function addDynamicRoutes(menus: MenuInfo[]) {
}
})
addedRouteNames.add(routeName)
console.log(`[动态路由] ✓ 添加成功: ${menuPath}`)
//console.log(`[动态路由] ✓ 添加成功: ${menuPath}`)
} else {
console.warn(`[动态路由] ✗ 组件不存在: ${componentName}`)
//console.warn(`[动态路由] ✗ 组件不存在: ${componentPath}`)
}
}
}
// 递归处理子菜单
if (menu.children && menu.children.length > 0) {
addRoutes(menu.children)
}
}
}
addRoutes(menus)
dynamicRoutesInitialized = true
console.log('[动态路由] 当前所有路由:', router.getRoutes().map(r => r.path))
//console.log('[动态路由] 当前所有路由:', router.getRoutes().map(r => r.path))
}
/**
@ -363,16 +330,15 @@ export function resetRouter() {
}
})
addedRouteNames.clear()
dynamicRoutesInitialized = false
}
// 路由守卫
router.beforeEach(async (to, _from, next) => {
const { useUserStore } = await import('@/stores/user')
console.log('路由测试');
const userStore = useUserStore()
document.title = `${to.meta.title || ''} - mes Admin`
//document.title = `${to.meta.title || ''} - CSY Admin`
if (to.meta.requiresAuth === false) {
next()
return
@ -383,25 +349,47 @@ router.beforeEach(async (to, _from, next) => {
return
}
if (!userStore.user || !dynamicRoutesInitialized) {
if (userStore.init) {
try {
if (!userStore.user) {
await userStore.getInfo()
}
await userStore.getInfo()
// 添加动态路由(只添加新的,不影响已有的)
addDynamicRoutes(userStore.menus)
console.log('[路由守卫] 动态路由已添加,重新导航到:', to.path)
userStore.setinit(false)
// userStore.init = false
next({ ...to, replace: true })
return
//return
} catch (error) {
console.error('[路由守卫] 获取用户信息失败:', error)
userStore.logout()
//userStore.init = false
userStore.setinit(true)
next({ name: 'Login' })
return
//return
}
}else{
next()
}
next()
// if (!userStore.user) {
// try {
// await userStore.getInfo()
// // 添加动态路由(只添加新的,不影响已有的)
// addDynamicRoutes(userStore.menus)
// next({ ...to, replace: true })
// return
// } catch (error) {
// userStore.logout()
// next({ name: 'Login' })
// return
// }
// }
// if (to.meta.requiresAuth === false) {
// next()
// return
// }
})
export default router

View File

@ -1,6 +1,7 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { authApi, type LoginParams, type UserInfo, type MenuInfo } from '@/api/auth'
import router, { resetRouter } from '@/router'
export const useUserStore = defineStore('user', () => {
// 状态
@ -10,11 +11,21 @@ export const useUserStore = defineStore('user', () => {
const permissions = ref<string[]>([])
const menus = ref<MenuInfo[]>([])
const init = ref<any>(true)
// 计算属性
const isLogin = computed(() => !!token.value)
const nickname = computed(() => user.value?.nickname || user.value?.username || '')
const avatar = computed(() => user.value?.avatar || '')
const postNames = computed(() => user.value?.postNames || '')
const userid = computed(() => user.value?.id || '')
function setinit(v:any) {
init.value = v
}
// 登录
async function login(params: LoginParams) {
const res = await authApi.login(params)
@ -45,6 +56,11 @@ export const useUserStore = defineStore('user', () => {
permissions.value = []
menus.value = []
init.value = true
// 重置路由
resetRouter()
// 只有之前有 token 时才发送 logout 请求
if (hadToken) {
try {
@ -54,9 +70,6 @@ export const useUserStore = defineStore('user', () => {
}
}
// 动态导入 router 避免循环依赖
const { default: router, resetRouter } = await import('@/router')
resetRouter()
router.push('/login')
}
@ -82,6 +95,10 @@ export const useUserStore = defineStore('user', () => {
isLogin,
nickname,
avatar,
init,
postNames,
userid,
setinit,
login,
getInfo,
logout,
@ -90,7 +107,7 @@ export const useUserStore = defineStore('user', () => {
}
}, {
persist: {
key: 'mes-user',
key: 'mars-user',
paths: ['token']
}
})