mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-26 01:51:41 +08:00
7.0 KiB
7.0 KiB
PWA状态管理功能实现说明
概述
本次实现为您的MoviePilot项目添加了完整的PWA状态管理功能,专门解决iOS设备上PWA后台被杀导致状态丢失的问题。
已实现的功能
1. 核心状态管理器 (src/utils/pwaStateManager.ts)
- ✅ 多层存储策略:localStorage + sessionStorage + IndexedDB + Service Worker缓存
- ✅ 智能状态恢复:基于时间、URL、设备方向的智能决策
- ✅ 生命周期监听:自动监听页面可见性、焦点变化、卸载事件
- ✅ 表单状态保存:自动保存和恢复表单数据
- ✅ 滚动位置恢复:精确恢复页面滚动位置
- ✅ UI状态管理:保存侧边栏、主题等界面状态
2. Service Worker增强 (src/service-worker.ts)
- ✅ 状态缓存端点:虚拟的
/api/pwa-state端点用于状态存储 - ✅ 消息通信:支持与主应用的双向状态同步
- ✅ 缓存管理:专用的状态缓存空间
- ✅ 错误处理:完善的错误处理和降级策略
3. Vue集成 (src/main.ts)
- ✅ 自动初始化:PWA模式下自动启动状态管理
- ✅ 环境检测:智能检测PWA运行环境
- ✅ 全局可用:状态管理器绑定到全局对象
- ✅ 事件监听:监听状态恢复事件并处理
4. Vue组合式API (src/composables/usePWAState.ts)
- ✅ 响应式状态:提供响应式的状态管理接口
- ✅ 便捷方法:封装常用的状态操作方法
- ✅ 类型安全:完整的TypeScript类型支持
- ✅ 组件友好:易于在Vue组件中使用
5. 类型声明 (src/types/pwa.d.ts)
- ✅ 类型扩展:扩展Window和Navigator接口
- ✅ 自定义事件:定义状态恢复事件类型
- ✅ TypeScript支持:完整的类型安全保障
6. 演示组件 (src/components/PWAStateDemo.vue)
- ✅ 功能演示:展示所有状态管理功能
- ✅ 测试界面:提供测试表单和操作按钮
- ✅ 状态监控:实时显示状态管理器状态
使用方法
在Vue组件中使用
<script setup lang="ts">
import { usePWAState } from '@/composables/usePWAState'
const {
isPWAMode,
isStateRestored,
saveCurrentState,
resetStateRestored
} = usePWAState()
// 手动保存状态
const handleImportantAction = async () => {
await saveCurrentState()
// 执行重要操作
}
</script>
<template>
<div>
<VAlert v-if="isStateRestored" type="success">
状态已恢复!
</VAlert>
<VBtn @click="handleImportantAction">
执行重要操作
</VBtn>
</div>
</template>
手动操作状态
// 在浏览器控制台中
window.pwaStateController.saveCurrentState() // 保存当前状态
工作原理
1. 状态保存时机
- 🔄 页面隐藏时:
visibilitychange事件触发 - 🔄 失去焦点时:
blur事件延迟1秒触发 - 🔄 页面卸载时:
beforeunload事件触发 - 🔄 定期保存:每30秒自动保存一次
- 🔄 手动触发:调用API手动保存
2. 状态恢复时机
- 🔄 应用启动时:自动检查并恢复状态
- 🔄 页面显示时:
visibilitychange事件触发 - 🔄 获得焦点时:清除延迟保存定时器
3. 存储策略
localStorage (主要状态)
↓
sessionStorage (临时状态)
↓
IndexedDB (大量数据)
↓
Service Worker缓存 (跨页面共享)
4. 恢复决策
状态恢复需要同时满足:
- ✅ 状态未过期(默认30分钟内)
- ✅ URL路径匹配
- ✅ 设备方向未显著变化
配置选项
修改状态保存间隔
// 在 PWAStateController 中修改
private setupPeriodicSave(): void {
setInterval(() => {
if (!document.hidden) {
this.saveCurrentState()
}
}, 60000) // 改为60秒保存一次
}
修改状态过期时间
// 在 StateRestoreDecision 中修改
export class StateRestoreDecision {
private maxStateAge = 60 * 60 * 1000 // 改为60分钟
}
自定义状态内容
// 在 PWAStateController 中添加自定义状态
private getAppSpecificState(): any {
return {
// 现有状态...
// 添加自定义状态
customData: {
userPreferences: this.getUserPreferences(),
currentMedia: this.getCurrentMedia(),
searchHistory: this.getSearchHistory()
}
}
}
调试和监控
控制台调试
// 检查状态管理器是否可用
console.log('状态管理器:', window.pwaStateController)
// 查看当前保存的状态
console.log('本地状态:', localStorage.getItem('mp-pwa-app-state'))
// 手动保存状态
window.pwaStateController?.saveCurrentState()
// 清除所有状态
localStorage.removeItem('mp-pwa-app-state')
sessionStorage.removeItem('mp-pwa-session-state')
监听状态事件
// 监听状态恢复事件
window.addEventListener('pwaStateRestored', (event) => {
console.log('状态已恢复:', event.detail.state)
})
注意事项
iOS特殊性
- PWA不与Safari共享存储空间
- 后台执行时间有限(约30秒-5分钟)
- 内存压力时会被强制清理
- Service Worker可能会被暂停
存储限制
- localStorage: 约5-10MB
- sessionStorage: 约5-10MB
- IndexedDB: 较大但可能被清理
- Service Worker缓存: 约50MB
性能考虑
- 避免保存过大的状态对象
- 使用防抖技术避免频繁保存
- 异步处理状态操作
- 定期清理过期状态
测试方法
1. 基本功能测试
- 将应用添加到iOS桌面
- 打开PWA,填写测试表单
- 切换到其他应用
- 等待几分钟后重新打开PWA
- 检查表单数据和滚动位置是否恢复
2. 状态管理测试
- 在PWA中访问演示页面:
/pwa-state-demo - 观察状态管理器状态
- 测试手动保存和恢复功能
- 验证状态恢复通知
3. 长时间测试
- 保持PWA在后台运行几小时
- 使用其他应用增加内存压力
- 重新打开PWA检查状态恢复
- 重启设备后测试状态持久性
故障排除
状态未恢复
- 检查是否在PWA模式运行
- 确认状态管理器已初始化
- 检查控制台错误信息
- 验证存储权限和配额
性能问题
- 减少状态保存频率
- 优化状态对象大小
- 检查内存使用情况
- 考虑延迟初始化
兼容性问题
- 检查iOS版本支持
- 验证Service Worker注册
- 测试不同设备和浏览器
- 检查网络连接状态
后续优化建议
- 智能压缩:对大型状态对象进行压缩
- 增量保存:只保存变化的状态部分
- 云端同步:结合服务器实现跨设备状态同步
- 用户偏好:允许用户自定义状态保存策略
- 性能监控:添加状态管理性能指标
- A/B测试:测试不同的状态管理策略效果
通过这套完整的解决方案,您的MoviePilot PWA应该能够在iOS设备上提供更好的用户体验,显著减少因后台被杀而导致的状态丢失问题。