完善刷新页面展示bug

This commit is contained in:
2026-03-14 14:52:36 +08:00
parent 5914104851
commit 500160df11
3 changed files with 131 additions and 6 deletions

View File

@@ -14,6 +14,25 @@ import {
import { addView, activeFullPath, visitedViews } from './tagsViewStore.uts'
import { hasAdminModuleAccess } from '@/layouts/admin/utils/role.uts'
// ============================================
// Tabs 持久化 keys使用 sessionStorage与 token 策略一致)
// sessionStorage 在同一标签页 F5 刷新后保留,关闭标签页后自动清除
// ============================================
const TAB_STORAGE_KEY = 'admin_opened_tabs'
const ACTIVE_ROUTE_KEY = 'admin_active_route'
const LAST_SUB_STORAGE_KEY = 'admin_last_sub_by_menu'
/** 将当前 tabs / activeRouteId / lastSubIdByMenu 写入 sessionStorage */
function persistNavState(): void {
// #ifdef H5
try {
sessionStorage.setItem(TAB_STORAGE_KEY, JSON.stringify(tabs.value))
sessionStorage.setItem(ACTIVE_ROUTE_KEY, activeRouteId.value)
sessionStorage.setItem(LAST_SUB_STORAGE_KEY, JSON.stringify(lastSubIdByMenu.value))
} catch (_) {}
// #endif
}
/**
* 标签页类型
*/
@@ -120,6 +139,9 @@ export function openRoute(routeId: string, addTab: boolean = true): void {
// 添加到标签页
if (addTab) {
addTabItem(route)
} else {
// 即使不新增 tabactiveRouteId 变化了也要持久化
persistNavState()
}
}
@@ -150,6 +172,9 @@ function addTabItem(route: RouteRecord): void {
// 更新新版 TagsViewStore
addView(route, route.path)
activeFullPath.value = route.path
// 持久化到 sessionStorage
persistNavState()
}
/**
@@ -178,6 +203,8 @@ export function closeTab(tabId: string): void {
}
tabs.value.splice(index, 1)
// 持久化
persistNavState()
}
/**
@@ -192,6 +219,8 @@ export function closeOtherTabs(keepTabId: string): void {
if (!stillExists) {
openRoute(keepTabId, false)
}
// 持久化
persistNavState()
}
/**
@@ -205,6 +234,8 @@ export function closeAllTabs(): void {
if (homeTab) {
openRoute(homeTab.id, false)
}
// 持久化
persistNavState()
}
/**
@@ -222,7 +253,7 @@ export function toggleSubSider(): void {
}
/**
* 初始化导航状态
* 初始化导航状态(首次进入 / 恢复失败时的兜底)
* 在 AdminLayout 组件 onMounted 时调用
*/
export function initNavState(): void {
@@ -244,6 +275,86 @@ export function initNavState(): void {
openRoute('home_index', false)
}
/**
* 从 sessionStorage 恢复导航状态F5刷新后调用
* - 校验每个缓存 tab 的路由是否仍然存在
* - 校验是否仍有权限
* - 过滤无效项后重建 tabs
* - 恢复 activeRouteId 和菜单高亮
* @returns true=恢复成功false=无有效缓存或恢复失败(调用方应走 initNavState 兜底)
*/
export function restoreNavState(): boolean {
// #ifdef H5
try {
const rawTabs = sessionStorage.getItem(TAB_STORAGE_KEY)
if (!rawTabs) return false
const savedTabs = JSON.parse(rawTabs) as TabItem[]
if (!Array.isArray(savedTabs) || savedTabs.length === 0) return false
// 校验并过滤:路由必须存在且有权限
const validTabs = savedTabs.filter(tab => {
const route = findRouteById(tab.id)
if (!route) return false // 路由已不存在(文件删除或路由表变更)
const moduleId = route.parentId ?? tab.id.split('_')[0]
return hasAdminModuleAccess(moduleId) // 检查权限
})
// 首页 tab 始终保留(防止全部被过滤后无处可去)
const homeRoute = findRouteById('home_index')
if (homeRoute && !validTabs.some(t => t.id === 'home_index')) {
validTabs.unshift({
id: homeRoute.id,
title: homeRoute.title,
path: homeRoute.path,
isAffix: homeRoute.isAffix || false
})
}
if (validTabs.length === 0) return false
// 重建 tabs
tabs.value = validTabs
validTabs.forEach(tab => {
const route = findRouteById(tab.id)
if (route) addView(route, route.path)
})
// 恢复 lastSubIdByMenu
try {
const rawLast = sessionStorage.getItem(LAST_SUB_STORAGE_KEY)
if (rawLast) {
lastSubIdByMenu.value = JSON.parse(rawLast) as Record<string, string>
}
} catch (_) {}
// 恢复 activeRouteId
const savedActive = sessionStorage.getItem(ACTIVE_ROUTE_KEY)
const activeIsValid = savedActive != null &&
findRouteById(savedActive) != null &&
validTabs.some(t => t.id === savedActive)
const targetId = activeIsValid ? savedActive! : validTabs[0].id
activeRouteId.value = targetId
activeFullPath.value = findRouteById(targetId)?.path ?? ''
const activeRoute = findRouteById(targetId)
if (activeRoute?.parentId) {
activeTopMenuId.value = activeRoute.parentId
} else {
activeTopMenuId.value = targetId.split('_')[0]
}
console.log('[AdminNav] 已从缓存恢复导航状态, tabs:', validTabs.length, 'active:', targetId)
return true
} catch (e) {
console.warn('[AdminNav] 恢复导航状态失败,将走默认初始化:', e)
return false
}
// #endif
return false
}
/**
* 根据 currentPage 同步状态
* 用于页面组件传入 currentPage prop 时的状态同步