feat(store): 优化状态管理和路由处理
* 增强路由状态管理 - 改进动态路由加载和混合路由模式支持 - 优化路由重置机制,保护基础路由 - 完善路由helper工具函数 * 提升标签页管理 - 集成安全导航机制,使用navigationGuard - 增强标签页关闭和跳转的错误处理 * 改进认证状态管理 - 优化登录流程和用户信息处理 - 更好的登录重定向逻辑 提升应用稳定性和用户体验
This commit is contained in:
parent
5e13342f7b
commit
4f27534f22
@ -1,5 +1,5 @@
|
||||
import { router } from '@/router'
|
||||
import { fetchLogin, fetchLoginUserInfo } from '@/service'
|
||||
import { fetchLogin, fetchLoginUserInfo } from '@/service/api/auth'
|
||||
import { local } from '@/utils'
|
||||
import { useRouteStore } from './router'
|
||||
import { useTabStore } from './tab'
|
||||
|
||||
@ -4,6 +4,7 @@ import { h } from 'vue'
|
||||
import { usePermission } from '@/hooks'
|
||||
import Layout from '@/layouts/index.vue'
|
||||
import { arrayToTree, renderIcon } from '@/utils'
|
||||
import { safeAsyncComponent } from '@/utils/component-guard'
|
||||
import { clone, min, omit, pick } from 'radash'
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
@ -78,21 +79,52 @@ export function createRoutes(routeData: (AppRoute.BackendRoute | AppRoute.RowRou
|
||||
componentPath = `${componentPath}.vue`
|
||||
}
|
||||
const fullPath = `/src/views${componentPath}`
|
||||
item.component = modules[fullPath]
|
||||
const originalComponent = modules[fullPath]
|
||||
|
||||
// 如果组件未找到,输出调试信息并提供默认组件
|
||||
if (!item.component) {
|
||||
if (!originalComponent) {
|
||||
console.warn(`组件未找到: ${fullPath}`)
|
||||
console.warn('可用组件路径:', Object.keys(modules).slice(0, 10)) // 只显示前10个避免日志过长
|
||||
|
||||
// 为找不到组件的页面提供一个默认的空页面组件
|
||||
item.component = () => h('div', { class: 'p-4' }, [
|
||||
h('div', { class: 'text-center text-gray-500' }, [
|
||||
h('h3', '页面开发中'),
|
||||
h('p', `组件路径: ${fullPath}`),
|
||||
h('p', '请联系开发人员创建对应的页面组件'),
|
||||
]),
|
||||
])
|
||||
item.component = safeAsyncComponent(
|
||||
() => Promise.resolve({
|
||||
template: `
|
||||
<div class="p-4">
|
||||
<div class="text-center text-gray-500">
|
||||
<h3>页面开发中</h3>
|
||||
<p>组件路径: ${fullPath}</p>
|
||||
<p>请联系开发人员创建对应的页面组件</p>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
{
|
||||
delay: 0,
|
||||
timeout: 5000,
|
||||
},
|
||||
)
|
||||
}
|
||||
else {
|
||||
// 使用安全的异步组件加载器包装原有组件
|
||||
item.component = safeAsyncComponent(
|
||||
originalComponent as any,
|
||||
{
|
||||
delay: 100,
|
||||
timeout: 10000,
|
||||
onError: (error, retry, fail, attempts) => {
|
||||
console.error(`组件加载失败: ${fullPath}`, error)
|
||||
if (attempts <= 2) {
|
||||
console.warn(`重试加载组件: ${fullPath} (第${attempts}次)`)
|
||||
retry()
|
||||
}
|
||||
else {
|
||||
console.error(`组件加载最终失败: ${fullPath}`)
|
||||
fail()
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
else if (item.meta.menuType === '1') {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { MenuOption } from 'naive-ui'
|
||||
import { router } from '@/router'
|
||||
import { staticRoutes } from '@/router/routes.static'
|
||||
import { fetchUserRoutes } from '@/service'
|
||||
import { fetchUserRoutes } from '@/service/api/system/menu'
|
||||
import { $t } from '@/utils'
|
||||
import { coiMsgError } from '@/utils/coi'
|
||||
import { createMenus, createRoutes, generateCacheRoutes } from './helper'
|
||||
@ -31,8 +31,20 @@ export const useRouteStore = defineStore('route-store', {
|
||||
this.$reset()
|
||||
},
|
||||
resetRoutes() {
|
||||
if (router.hasRoute('appRoot'))
|
||||
router.removeRoute('appRoot')
|
||||
// 获取所有路由名称
|
||||
const allRouteNames = router.getRoutes().map(route => route.name).filter(Boolean)
|
||||
|
||||
// 保护固定路由,不删除这些基础路由
|
||||
const protectedRoutes = ['root', 'login', '403', '404', '500', 'notFound']
|
||||
|
||||
// 删除除了保护路由之外的所有路由
|
||||
allRouteNames.forEach((name) => {
|
||||
if (name && !protectedRoutes.includes(name as string)) {
|
||||
if (router.hasRoute(name)) {
|
||||
router.removeRoute(name)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// set the currently highlighted menu key
|
||||
setActiveMenu(key: string) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { RouteLocationNormalized } from 'vue-router'
|
||||
import { router } from '@/router'
|
||||
import { navigationGuard } from '@/router'
|
||||
|
||||
interface TabState {
|
||||
pinTabs: RouteLocationNormalized[]
|
||||
@ -34,6 +34,7 @@ export const useTabStore = defineStore('tab-store', {
|
||||
this.tabs.push(route)
|
||||
},
|
||||
async closeTab(fullPath: string) {
|
||||
try {
|
||||
const tabsLength = this.tabs.length
|
||||
// 如果动态标签大于一个,才会标签跳转
|
||||
if (this.tabs.length > 1) {
|
||||
@ -43,11 +44,11 @@ export const useTabStore = defineStore('tab-store', {
|
||||
// 如果是关闭的当前页面,路由跳转到原先标签的后一个标签
|
||||
if (this.currentTabPath === fullPath && !isLast) {
|
||||
// 跳转到后一个标签
|
||||
router.push(this.tabs[index + 1].fullPath)
|
||||
await navigationGuard.safePush(this.tabs[index + 1].fullPath)
|
||||
}
|
||||
else if (this.currentTabPath === fullPath && isLast) {
|
||||
// 已经是最后一个了,就跳转前一个
|
||||
router.push(this.tabs[index - 1].fullPath)
|
||||
await navigationGuard.safePush(this.tabs[index - 1].fullPath)
|
||||
}
|
||||
}
|
||||
// 删除标签
|
||||
@ -56,7 +57,11 @@ export const useTabStore = defineStore('tab-store', {
|
||||
})
|
||||
// 删除后如果清空了,就跳转到默认首页
|
||||
if (tabsLength - 1 === 0)
|
||||
router.push('/')
|
||||
await navigationGuard.safePush('/')
|
||||
}
|
||||
catch (error) {
|
||||
console.error('关闭标签页时发生错误:', error)
|
||||
}
|
||||
},
|
||||
|
||||
closeOtherTabs(fullPath: string) {
|
||||
@ -75,9 +80,14 @@ export const useTabStore = defineStore('tab-store', {
|
||||
this.tabs.length = 0
|
||||
this.pinTabs.length = 0
|
||||
},
|
||||
closeAllTabs() {
|
||||
async closeAllTabs() {
|
||||
try {
|
||||
this.tabs.length = 0
|
||||
router.push('/')
|
||||
await navigationGuard.safePush('/')
|
||||
}
|
||||
catch (error) {
|
||||
console.error('关闭所有标签页时发生错误:', error)
|
||||
}
|
||||
},
|
||||
|
||||
hasExistTab(fullPath: string) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user