aslan-h5/src/utils/versionChecker.js

222 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/utils/versionChecker.js
// 版本检查工具
import { imageCacheManager } from '@/utils/imageCacheManager'
const PERSISTENT_KEYS = [
'preferred-language', // 语言设置
'userProfile', // 用户资料
'teamInfo', // 团队信息
'lastImgUrl', // 最后图片URL
'applyInfo', // 申请资料
'gamesKing', // 游戏王每日弹窗查看状态
]
export class VersionChecker {
constructor() {
this.currentVersion = import.meta.env.VITE_APP_VERSION || Date.now().toString() //app版本号
this.storageKey = 'h5_app_version' //本地存储的版本号key
this.serverVersionKey = 'app_server_version' //服务器版本号key
this.enableCheck = import.meta.env.VITE_ENABLE_VERSION_CHECK === 'true' //是否开启检测app版本号
}
// 检查版本(开发环境:本地.env文件生产环境构建脚本生成的version.json文件
async checkServerVersion() {
if (!this.enableCheck) {
return false
}
try {
let versionInfo //版本更新信息
// 开发环境:使用本地.env文件环境变量
if (import.meta.env.MODE === 'development') {
versionInfo = {
version: import.meta.env.VITE_APP_VERSION,
type: import.meta.env.VITE_VERSION_TYPE || 'patch',
}
}
// 生产环境从服务器获取version.json文件
else {
const response = await fetch(`/version.json?t=${Date.now()}`)
if (!response.ok) {
console.warn('无法获取服务器版本信息')
return false
}
const contentType = response.headers.get('content-type')
if (!contentType || !contentType.includes('application/json')) {
console.warn('服务器返回的不是JSON格式')
return false
}
versionInfo = await response.json() //获取服务器版本信息
}
const serverVersion = versionInfo.version //最新生成的服务器版本号
const versionType = versionInfo.type || 'patch' // 版本更新类型
const storedServerVersion = localStorage.getItem(this.serverVersionKey) //网页缓存的版本号
// 更新服务器版本信息
localStorage.setItem(this.serverVersionKey, serverVersion)
// 比较版本
if (storedServerVersion && storedServerVersion !== serverVersion) {
console.log(`检测到${versionType}版本更新: ${storedServerVersion} -> ${serverVersion}`)
// 返回版本类型信息
return {
shouldUpdate: true,
versionType: versionType,
}
}
return { shouldUpdate: false }
} catch (error) {
console.warn('版本检查失败:', error.message)
return { shouldUpdate: false }
}
}
// 初始化网页首次检查版本
async checkVersion() {
// 获取最新版本信息
const versionResult = await this.checkServerVersion()
// 判断是否需要更新
if (versionResult.shouldUpdate) {
await this.handleVersionUpdate(versionResult.versionType)
return true
}
// 检查本地版本是否匹配
const storedLocalVersion = localStorage.getItem(this.storageKey)
if (storedLocalVersion !== this.currentVersion) {
// 本地版本变化,可能是首次加载或本地版本升级
localStorage.setItem(this.storageKey, this.currentVersion)
console.log(`本地版本更新到: ${this.currentVersion}`)
}
return false
}
// 处理版本更新
async handleVersionUpdate(updateType = 'major') {
console.log(`检测到${updateType}版本更新,正在清理缓存...`)
// 根据更新类型决定清除策略
switch (updateType) {
case 'major':
// 重大更新:清除所有缓存(不管图片版本号是否更新)
await this.clearCache()
break
case 'minor':
case 'patch':
// minor或patch更新检查图片版本号是否更新
// 如果图片版本号更新则按imageCacheVersion中的cacheType清除缓存
// 如果图片版本号未更新,则不做任何缓存清除处理
await imageCacheManager.checkVersionAndUpdate()
this.clearSessionData() // 清除 session 数据
break
default:
// 默认:清除所有缓存
await this.clearCache()
}
localStorage.setItem(this.storageKey, this.currentVersion)
localStorage.setItem(this.serverVersionKey, this.currentVersion)
// 直接刷新页面
this.forceReload()
}
// 清除所有会话存储数据sessionStorage
clearSessionData() {
try {
// localStorage和Cache API不受影响
const preservedData = {}
PERSISTENT_KEYS.forEach((key) => {
const value = localStorage.getItem(key)
if (value !== null) {
preservedData[key] = value
}
})
// 清除 sessionStorage
sessionStorage.clear()
// 恢复保留的数据
Object.keys(preservedData).forEach((key) => {
localStorage.setItem(key, preservedData[key])
})
} catch (error) {
console.warn('清理 session 数据失败:', error)
}
}
async clearCache() {
// 清除范围:
// localStorage所有本地存储数据
// sessionStorage所有会话存储数据
// Cache API所有缓存包括非图片缓存
// Service Worker注销所有注册
// 保留数据:保留 PERSISTENT_KEYS 中定义的白名单数据
try {
// 保存需要保留的数据
const preservedData = {}
PERSISTENT_KEYS.forEach((key) => {
const value = localStorage.getItem(key)
if (value !== null) {
preservedData[key] = value
}
})
// 清除所有localStorage
localStorage.clear()
// 恢复保留的数据
Object.keys(preservedData).forEach((key) => {
localStorage.setItem(key, preservedData[key])
})
// 清除sessionStorage
sessionStorage.clear()
// 清除所有缓存
if ('caches' in window) {
const cacheNames = await caches.keys()
await Promise.all(cacheNames.map((name) => caches.delete(name)))
}
// 注销Service Worker如果存在
if ('serviceWorker' in navigator) {
const registrations = await navigator.serviceWorker.getRegistrations()
await Promise.all(registrations.map((reg) => reg.unregister()))
}
} catch (error) {
console.warn('清除缓存失败:', error)
}
}
// 强制刷新页面
forceReload() {
// 直接刷新当前页面,不跳转到其他页面
try {
window.location.reload(true)
} catch (error) {
// 备用方案
window.location.href = window.location.href
}
}
// 获取当前版本
getCurrentVersion() {
return this.currentVersion
}
}
// 导出单例
export const versionChecker = new VersionChecker()