重构PWA状态管理

This commit is contained in:
jxxghp
2025-07-07 14:05:11 +08:00
parent 73d7eb65b8
commit 0cf3342449
8 changed files with 489 additions and 975 deletions

View File

@@ -1,4 +1,5 @@
import type { ComputedRef, Ref } from 'vue'
import { useTabStateRestore } from '@/composables/useStateRestore'
// 动态标签页相关类型
interface DynamicHeaderTabButton {
@@ -38,7 +39,17 @@ export function useDynamicHeaderTab() {
items: DynamicHeaderTabItem[] | ComputedRef<DynamicHeaderTabItem[]> | Ref<DynamicHeaderTabItem[]>
modelValue: Ref<string>
appendButtons?: DynamicHeaderTabButton[]
enableStateRestore?: boolean
}) => {
// 集成PWA状态恢复功能
const enablePWARestore = config.enableStateRestore !== false // 默认启用
const pwaTabState = enablePWARestore ? useTabStateRestore(config.modelValue.value) : null
// 如果启用了PWA状态恢复先尝试恢复状态
if (pwaTabState && pwaTabState.activeTab.value) {
config.modelValue.value = pwaTabState.activeTab.value
}
const tabConfig: DynamicHeaderTabConfig = {
items: Array.isArray(config.items) ? config.items : config.items.value,
modelValue: config.modelValue.value,
@@ -46,12 +57,34 @@ export function useDynamicHeaderTab() {
routePath: route.path,
onUpdateModelValue: (value: string) => {
config.modelValue.value = value
// 同步到PWA状态
if (pwaTabState && value) {
pwaTabState.activeTab.value = value
}
},
}
// 如果启用了PWA状态恢复监听PWA状态变化并同步到modelValue
if (pwaTabState) {
watch(pwaTabState.activeTab, newTab => {
if (newTab && newTab !== config.modelValue.value) {
config.modelValue.value = newTab
// 更新tabConfig并重新注册
tabConfig.modelValue = newTab
if (registerDynamicHeaderTab) {
registerDynamicHeaderTab(tabConfig)
}
}
})
}
// 监听modelValue变化并更新配置
watch(config.modelValue, newValue => {
tabConfig.modelValue = newValue
// 同步到PWA状态
if (pwaTabState && newValue) {
pwaTabState.activeTab.value = newValue
}
// 重新注册以更新值
if (registerDynamicHeaderTab) {
registerDynamicHeaderTab(tabConfig)

View File

@@ -1,7 +1,6 @@
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useDisplay } from 'vuetify'
import { checkPWAStatus, isPWADisplayMode } from '@/@core/utils/navigator'
import type { PWAState } from '@/utils/pwaStateManager'
// 全局PWA状态确保只初始化一次
const globalPwaStatus = ref<{
@@ -72,142 +71,6 @@ export function usePWA() {
appMode,
pwaStatus,
loading: globalLoading,
// 保留手动初始化方法以防需要
initializePWA: initializePWAGlobally,
}
}
// PWA状态管理 composable
export function usePWAState() {
const isStateRestored = ref(false)
const stateRestoreCount = ref(0)
const lastRestoredState = ref<PWAState | null>(null)
const isPWAMode = ref(false)
// 检查PWA模式 - 使用统一的检测方式
const checkPWAMode = async () => {
// 确保全局PWA状态已初始化
if (globalPwaStatus.value === null) {
await initializePWAGlobally()
}
// 获取PWA状态
const status = globalPwaStatus.value
if (status) {
isPWAMode.value = status.isPWAEnvironment
} else {
// 如果状态获取失败,使用同步检测作为后备
isPWAMode.value = isPWADisplayMode()
}
}
// 保存当前状态
const saveCurrentState = async () => {
if (window.pwaStateController) {
await window.pwaStateController.saveCurrentState()
}
}
// 手动触发状态恢复检查
const checkStateRestore = async () => {
if (window.pwaStateController) {
// 静默检查
}
}
// 监听状态恢复事件
const handleStateRestored = (event: Event) => {
const customEvent = event as CustomEvent<{ state: PWAState }>
isStateRestored.value = true
stateRestoreCount.value++
lastRestoredState.value = customEvent.detail.state
}
// 重置状态恢复标志
const resetStateRestored = () => {
isStateRestored.value = false
lastRestoredState.value = null
}
// 检查状态管理器是否可用
const isStateManagerAvailable = () => {
return !!window.pwaStateController
}
onMounted(() => {
checkPWAMode()
// 监听状态恢复事件
window.addEventListener('pwaStateRestored', handleStateRestored)
// 监听PWA模式变化
const mediaQuery = window.matchMedia('(display-mode: standalone)')
const handleDisplayModeChange = (e: MediaQueryListEvent) => {
isPWAMode.value = e.matches
// 同步更新全局PWA状态
if (globalPwaStatus.value) {
globalPwaStatus.value.isStandaloneMode = e.matches
globalPwaStatus.value.isPWAEnvironment = globalPwaStatus.value.hasPWAFeatures || e.matches
globalPwaStatus.value.isFullPWA = globalPwaStatus.value.hasPWAFeatures && e.matches
}
}
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener('change', handleDisplayModeChange)
} else {
mediaQuery.addListener(handleDisplayModeChange)
}
onUnmounted(() => {
if (mediaQuery.removeEventListener) {
mediaQuery.removeEventListener('change', handleDisplayModeChange)
} else {
mediaQuery.removeListener(handleDisplayModeChange)
}
})
})
onUnmounted(() => {
window.removeEventListener('pwaStateRestored', handleStateRestored)
})
return {
// 响应式状态
isPWAMode,
isStateRestored,
stateRestoreCount,
lastRestoredState,
// 方法
saveCurrentState,
checkStateRestore,
resetStateRestored,
isStateManagerAvailable,
checkPWAMode,
}
}
// 全局PWA状态管理器
export function useGlobalPWAState() {
// 检查是否在PWA环境中 - 使用统一的检测方式
const isPWAEnvironment = () => {
return globalPwaStatus.value?.isPWAEnvironment ?? isPWADisplayMode()
}
// 获取存储的状态
const getStoredState = () => {
return localStorage.getItem('mp-pwa-app-state')
}
// 清除存储的状态
const clearStoredState = () => {
localStorage.removeItem('mp-pwa-app-state')
sessionStorage.removeItem('mp-pwa-session-state')
}
return {
isPWAEnvironment,
getStoredState,
clearStoredState,
}
}

View File

@@ -0,0 +1,192 @@
/**
* PWA状态恢复组合式API
* 提供2个专门的hooks路由、标签页
*/
import { ref, onMounted, onUnmounted, watch, inject } from 'vue'
import { useRoute } from 'vue-router'
import type { StateRestore } from '@/plugins/stateRestore'
// =============================================================================
// 1. 动态标签页状态恢复
// =============================================================================
/**
* 动态标签页状态恢复Hook
* 自动保存和恢复v-tabs的当前激活标签
*/
export function useTabStateRestore(defaultTab?: string) {
const route = useRoute()
const stateRestore = inject<StateRestore>('stateRestore')
const activeTab = ref<string>(defaultTab || '')
// 保存标签页状态
const saveTabState = (tab: string) => {
if (stateRestore && tab) {
stateRestore.tab.saveTabState(route.path, tab)
}
}
// 恢复标签页状态
const restoreTabState = () => {
if (stateRestore) {
const savedTab = stateRestore.tab.getTabState(route.path)
if (savedTab) {
activeTab.value = savedTab
console.log(`恢复标签页状态: ${route.path} -> ${savedTab}`)
return true
}
}
return false
}
// 监听activeTab变化自动保存
watch(activeTab, newTab => {
if (newTab) {
saveTabState(newTab)
}
})
// 组件挂载时恢复状态
onMounted(() => {
// 先尝试恢复,如果没有保存的状态则使用默认值
if (!restoreTabState() && defaultTab) {
activeTab.value = defaultTab
}
})
// 监听全局恢复事件
const handleRestore = () => {
restoreTabState()
}
onMounted(() => {
window.addEventListener('pwa-state-restore', handleRestore)
})
onUnmounted(() => {
window.removeEventListener('pwa-state-restore', handleRestore)
})
return {
activeTab,
saveTabState,
restoreTabState,
}
}
// =============================================================================
// 2. 路由状态恢复
// =============================================================================
/**
* 路由状态恢复Hook
* 获取路由恢复信息,主要用于调试和监控
*/
export function useRouteStateRestore() {
const stateRestore = inject<StateRestore>('stateRestore')
const lastRestoredRoute = ref<any>(null)
// 获取上次保存的路由
const getLastSavedRoute = () => {
if (stateRestore) {
return stateRestore.route.restoreRoute()
}
return null
}
// 手动保存当前路由
const saveCurrentRoute = () => {
if (stateRestore) {
stateRestore.route.saveCurrentRoute()
}
}
// 清除路由状态
const clearRouteState = () => {
if (stateRestore) {
stateRestore.route.clearRoute()
}
}
// 监听全局恢复事件
const handleRestore = (event: Event) => {
const customEvent = event as CustomEvent
if (customEvent.detail?.route) {
lastRestoredRoute.value = customEvent.detail.route
}
}
onMounted(() => {
window.addEventListener('pwa-state-restore', handleRestore)
})
onUnmounted(() => {
window.removeEventListener('pwa-state-restore', handleRestore)
})
return {
lastRestoredRoute,
getLastSavedRoute,
saveCurrentRoute,
clearRouteState,
}
}
// =============================================================================
// 3. 全量状态恢复Hook
// =============================================================================
/**
* 全量状态恢复Hook
* 用于清理所有状态或获取统计信息
*/
export function useStateRestore() {
const stateRestore = inject<StateRestore>('stateRestore')
// 清除所有状态
const clearAllStates = () => {
if (stateRestore) {
stateRestore.clearAllStates()
console.log('已清除所有PWA状态')
}
}
// 获取状态统计
const getStateStats = () => {
if (!stateRestore) return null
return {
hasRoute: !!stateRestore.route.restoreRoute(),
// 可以扩展更多统计信息
}
}
return {
clearAllStates,
getStateStats,
stateRestore,
}
}
// =============================================================================
// 4. 快捷Hook组合
// =============================================================================
/**
* 页面级状态恢复Hook
* 组合路由和标签页状态恢复功能,适用于有标签页的页面
*/
export function usePageStateRestore(defaultTab?: string) {
const tabs = defaultTab ? useTabStateRestore(defaultTab) : null
const route = useRouteStateRestore()
const global = useStateRestore()
return {
tabs,
route,
global,
}
}