feat: 添加版本检查 API,支持从 Cloudflare Function 获取应用版本信息;更新相关配置文件
This commit is contained in:
101
functions/api/version.ts
Normal file
101
functions/api/version.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* Cloudflare Pages Function - 版本检查 API
|
||||||
|
* 访问路径: /api/version
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface VersionInfo {
|
||||||
|
version: string;
|
||||||
|
forceUpdate: boolean;
|
||||||
|
updateMessage: string;
|
||||||
|
updateUrl: string;
|
||||||
|
minSupportVersion: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Env {
|
||||||
|
// 可以在这里添加环境变量类型
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VersionConfig {
|
||||||
|
ios: VersionInfo;
|
||||||
|
android: VersionInfo;
|
||||||
|
web: VersionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 版本配置 - 直接在这里管理版本信息
|
||||||
|
const versionConfig: VersionConfig = {
|
||||||
|
ios: {
|
||||||
|
version: "0.0.1",
|
||||||
|
forceUpdate: false,
|
||||||
|
updateMessage: "修复了一些问题并优化了性能",
|
||||||
|
updateUrl: "https://apps.apple.com/app/id123456789",
|
||||||
|
minSupportVersion: "0.9.0",
|
||||||
|
},
|
||||||
|
android: {
|
||||||
|
version: "0.0.1",
|
||||||
|
forceUpdate: false,
|
||||||
|
updateMessage: "修复了一些问题并优化了性能",
|
||||||
|
updateUrl: "https://play.google.com/store/apps/details?id=riwa.ionic.app",
|
||||||
|
minSupportVersion: "0.9.0",
|
||||||
|
},
|
||||||
|
web: {
|
||||||
|
version: "0.0.1",
|
||||||
|
forceUpdate: false,
|
||||||
|
updateMessage: "修复了一些问题并优化了性能",
|
||||||
|
updateUrl: "",
|
||||||
|
minSupportVersion: "0.9.0",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onRequestGet: PagesFunction<Env> = async (context) => {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(context.request.url);
|
||||||
|
const platform = searchParams.get("platform") || "web";
|
||||||
|
const currentVersion = searchParams.get("currentVersion") || "0.0.1";
|
||||||
|
|
||||||
|
// 验证平台参数
|
||||||
|
if (!["ios", "android", "web"].includes(platform)) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({ error: "Invalid platform parameter" }),
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取对应平台的版本信息
|
||||||
|
const versionInfo = versionConfig[platform as keyof VersionConfig];
|
||||||
|
|
||||||
|
// 返回版本信息
|
||||||
|
return new Response(JSON.stringify(versionInfo), {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Cache-Control": "public, max-age=300", // 缓存5分钟
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error("Version check error:", error);
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({ error: "Internal server error" }),
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 支持 CORS 预检请求
|
||||||
|
export const onRequestOptions: PagesFunction<Env> = async () => {
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204,
|
||||||
|
headers: {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "Content-Type",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
17
functions/tsconfig.json
Normal file
17
functions/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"types": ["@cloudflare/workers-types"],
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -64,6 +64,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "catalog:",
|
"@antfu/eslint-config": "catalog:",
|
||||||
"@capacitor/cli": "catalog:",
|
"@capacitor/cli": "catalog:",
|
||||||
|
"@cloudflare/workers-types": "catalog:",
|
||||||
"@iconify-json/bx": "catalog:",
|
"@iconify-json/bx": "catalog:",
|
||||||
"@iconify-json/circle-flags": "catalog:",
|
"@iconify-json/circle-flags": "catalog:",
|
||||||
"@iconify-json/cryptocurrency-color": "catalog:",
|
"@iconify-json/cryptocurrency-color": "catalog:",
|
||||||
|
|||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -54,6 +54,9 @@ catalogs:
|
|||||||
'@capacitor/status-bar':
|
'@capacitor/status-bar':
|
||||||
specifier: 8.0.0
|
specifier: 8.0.0
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
|
'@cloudflare/workers-types':
|
||||||
|
specifier: ^4.20260113.0
|
||||||
|
version: 4.20260113.0
|
||||||
'@elysiajs/eden':
|
'@elysiajs/eden':
|
||||||
specifier: ^1.4.5
|
specifier: ^1.4.5
|
||||||
version: 1.4.5
|
version: 1.4.5
|
||||||
@@ -399,6 +402,9 @@ importers:
|
|||||||
'@capacitor/cli':
|
'@capacitor/cli':
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
|
'@cloudflare/workers-types':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 4.20260113.0
|
||||||
'@iconify-json/bx':
|
'@iconify-json/bx':
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 1.2.2
|
version: 1.2.2
|
||||||
@@ -521,7 +527,7 @@ importers:
|
|||||||
version: 7.4.0
|
version: 7.4.0
|
||||||
wrangler:
|
wrangler:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 4.54.0
|
version: 4.54.0(@cloudflare/workers-types@4.20260113.0)
|
||||||
|
|
||||||
packages/distribute:
|
packages/distribute:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1323,6 +1329,9 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@cloudflare/workers-types@4.20260113.0':
|
||||||
|
resolution: {integrity: sha512-CS2tUdGn1EMAV5GoFYYUfsZ4vwwXiYxwrUiI8ZRkxrJGqkHNGily/5Zf+vt/wh1HSoiCIChNYiuLEoCA/XUybw==}
|
||||||
|
|
||||||
'@cspotcode/source-map-support@0.8.1':
|
'@cspotcode/source-map-support@0.8.1':
|
||||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -10499,6 +10508,8 @@ snapshots:
|
|||||||
'@cloudflare/workerd-windows-64@1.20251210.0':
|
'@cloudflare/workerd-windows-64@1.20251210.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@cloudflare/workers-types@4.20260113.0': {}
|
||||||
|
|
||||||
'@cspotcode/source-map-support@0.8.1':
|
'@cspotcode/source-map-support@0.8.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.9
|
'@jridgewell/trace-mapping': 0.3.9
|
||||||
@@ -19654,7 +19665,7 @@ snapshots:
|
|||||||
'@cloudflare/workerd-linux-arm64': 1.20251210.0
|
'@cloudflare/workerd-linux-arm64': 1.20251210.0
|
||||||
'@cloudflare/workerd-windows-64': 1.20251210.0
|
'@cloudflare/workerd-windows-64': 1.20251210.0
|
||||||
|
|
||||||
wrangler@4.54.0:
|
wrangler@4.54.0(@cloudflare/workers-types@4.20260113.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@cloudflare/kv-asset-handler': 0.4.1
|
'@cloudflare/kv-asset-handler': 0.4.1
|
||||||
'@cloudflare/unenv-preset': 2.7.13(unenv@2.0.0-rc.24)(workerd@1.20251210.0)
|
'@cloudflare/unenv-preset': 2.7.13(unenv@2.0.0-rc.24)(workerd@1.20251210.0)
|
||||||
@@ -19665,6 +19676,7 @@ snapshots:
|
|||||||
unenv: 2.0.0-rc.24
|
unenv: 2.0.0-rc.24
|
||||||
workerd: 1.20251210.0
|
workerd: 1.20251210.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
'@cloudflare/workers-types': 4.20260113.0
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
catalogMode: prefer
|
|
||||||
shellEmulator: true
|
|
||||||
trustPolicy: no-downgrade
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- packages/*
|
- packages/*
|
||||||
|
|
||||||
catalog:
|
catalog:
|
||||||
'@riwa/api-types': http://192.168.1.7:9528/api/riwa-eden-0.0.138.tgz
|
'@antfu/eslint-config': ^6.6.1
|
||||||
'@capacitor-community/barcode-scanner': ^4.0.1
|
'@capacitor-community/barcode-scanner': ^4.0.1
|
||||||
'@capacitor-mlkit/barcode-scanning': ^8.0.0
|
'@capacitor-mlkit/barcode-scanning': ^8.0.0
|
||||||
'@capacitor/app': 8.0.0
|
'@capacitor/app': 8.0.0
|
||||||
'@capacitor/barcode-scanner': ^3.0.0
|
'@capacitor/barcode-scanner': ^3.0.0
|
||||||
'@capacitor/camera': ^8.0.0
|
'@capacitor/camera': ^8.0.0
|
||||||
|
'@capacitor/cli': 8.0.0
|
||||||
'@capacitor/clipboard': ^8.0.0
|
'@capacitor/clipboard': ^8.0.0
|
||||||
'@capacitor/core': 8.0.0
|
'@capacitor/core': 8.0.0
|
||||||
'@capacitor/file-transfer': ^2.0.0
|
'@capacitor/file-transfer': ^2.0.0
|
||||||
@@ -21,35 +18,8 @@ catalog:
|
|||||||
'@capacitor/keyboard': 8.0.0
|
'@capacitor/keyboard': 8.0.0
|
||||||
'@capacitor/share': ^8.0.0
|
'@capacitor/share': ^8.0.0
|
||||||
'@capacitor/status-bar': 8.0.0
|
'@capacitor/status-bar': 8.0.0
|
||||||
|
'@cloudflare/workers-types': ^4.20260113.0
|
||||||
'@elysiajs/eden': ^1.4.5
|
'@elysiajs/eden': ^1.4.5
|
||||||
'@ionic/vue': ^8.7.11
|
|
||||||
'@ionic/vue-router': ^8.7.11
|
|
||||||
'@tailwindcss/vite': ^4.1.18
|
|
||||||
'@vee-validate/zod': ^4.15.1
|
|
||||||
'@vueuse/core': ^14.1.0
|
|
||||||
'@vueuse/integrations': ^14.1.0
|
|
||||||
'@vueuse/router': ^14.1.0
|
|
||||||
'better-auth': ^1.4.6
|
|
||||||
'dayjs': ^1.11.19
|
|
||||||
'ethers': ^6.16.0
|
|
||||||
'html2canvas': ^1.4.1
|
|
||||||
'ionicons': ^8.0.13
|
|
||||||
'jsqr': ^1.4.0
|
|
||||||
'lightweight-charts': ^5.1.0
|
|
||||||
'lodash-es': ^4.17.21
|
|
||||||
'markdown-it': ^14.1.0
|
|
||||||
'pinia': ^3.0.4
|
|
||||||
'qr-scanner-wechat': ^0.1.3
|
|
||||||
'qrcode': ^1.5.4
|
|
||||||
'tailwindcss': ^4.1.18
|
|
||||||
'vconsole': ^3.15.1
|
|
||||||
'vee-validate': ^4.15.1
|
|
||||||
'vue': ^3.5.25
|
|
||||||
'vue-i18n': ^11.2.2
|
|
||||||
'vue-router': ^4.6.3
|
|
||||||
'zod': ^3.24.1
|
|
||||||
'@antfu/eslint-config': ^6.6.1
|
|
||||||
'@capacitor/cli': 8.0.0
|
|
||||||
'@iconify-json/bx': ^1.2.2
|
'@iconify-json/bx': ^1.2.2
|
||||||
'@iconify-json/circle-flags': ^1.2.10
|
'@iconify-json/circle-flags': ^1.2.10
|
||||||
'@iconify-json/cryptocurrency-color': ^1.2.4
|
'@iconify-json/cryptocurrency-color': ^1.2.4
|
||||||
@@ -62,32 +32,65 @@ catalog:
|
|||||||
'@iconify-json/tdesign': ^1.2.11
|
'@iconify-json/tdesign': ^1.2.11
|
||||||
'@iconify/vue': ^5.0.0
|
'@iconify/vue': ^5.0.0
|
||||||
'@ionic/cli': ^7.2.1
|
'@ionic/cli': ^7.2.1
|
||||||
|
'@ionic/vue': ^8.7.11
|
||||||
|
'@ionic/vue-router': ^8.7.11
|
||||||
|
'@riwa/api-types': http://192.168.1.7:9528/api/riwa-eden-0.0.138.tgz
|
||||||
|
'@tailwindcss/vite': ^4.1.18
|
||||||
'@types/lodash-es': ^4.17.12
|
'@types/lodash-es': ^4.17.12
|
||||||
'@types/node': ^24.10.2
|
'@types/node': ^24.10.2
|
||||||
'@types/qrcode': ^1.5.6
|
'@types/qrcode': ^1.5.6
|
||||||
|
'@vee-validate/zod': ^4.15.1
|
||||||
'@vitejs/plugin-basic-ssl': ^2.1.3
|
'@vitejs/plugin-basic-ssl': ^2.1.3
|
||||||
'@vitejs/plugin-legacy': ^7.2.1
|
'@vitejs/plugin-legacy': ^7.2.1
|
||||||
'@vitejs/plugin-vue': ^6.0.2
|
'@vitejs/plugin-vue': ^6.0.2
|
||||||
'@vitejs/plugin-vue-jsx': ^5.1.2
|
'@vitejs/plugin-vue-jsx': ^5.1.2
|
||||||
'@vue/eslint-config-typescript': ^14.6.0
|
'@vue/eslint-config-typescript': ^14.6.0
|
||||||
'@vue/test-utils': ^2.4.6
|
'@vue/test-utils': ^2.4.6
|
||||||
'cypress': ^15.7.1
|
'@vueuse/core': ^14.1.0
|
||||||
'dotenv': ^17.2.3
|
'@vueuse/integrations': ^14.1.0
|
||||||
'eslint': ^9.39.1
|
'@vueuse/router': ^14.1.0
|
||||||
'eslint-plugin-format': ^1.1.0
|
better-auth: ^1.4.6
|
||||||
'eslint-plugin-vue': ^10.6.2
|
cypress: ^15.7.1
|
||||||
'jiti': ^2.6.1
|
dayjs: ^1.11.19
|
||||||
'jsdom': ^27.3.0
|
dotenv: ^17.2.3
|
||||||
'lint-staged': ^16.2.7
|
eslint: ^9.39.1
|
||||||
'simple-git-hooks': ^2.13.1
|
eslint-plugin-format: ^1.1.0
|
||||||
'terser': ^5.44.1
|
eslint-plugin-vue: ^10.6.2
|
||||||
'typescript': ~5.9.3
|
ethers: ^6.16.0
|
||||||
'unplugin-auto-import': ^20.3.0
|
html2canvas: ^1.4.1
|
||||||
'unplugin-icons': ^22.5.0
|
ionicons: ^8.0.13
|
||||||
'unplugin-vue-components': ^30.0.0
|
jiti: ^2.6.1
|
||||||
'vite': ^7.2.7
|
jsdom: ^27.3.0
|
||||||
'vite-plugin-pwa': ^1.2.0
|
jsqr: ^1.4.0
|
||||||
'vitest': ^4.0.15
|
lightweight-charts: ^5.1.0
|
||||||
'vue-tsc': ^3.1.8
|
lint-staged: ^16.2.7
|
||||||
'workbox-window': ^7.4.0
|
lodash-es: ^4.17.21
|
||||||
'wrangler': ^4.54.0
|
markdown-it: ^14.1.0
|
||||||
|
pinia: ^3.0.4
|
||||||
|
qr-scanner-wechat: ^0.1.3
|
||||||
|
qrcode: ^1.5.4
|
||||||
|
simple-git-hooks: ^2.13.1
|
||||||
|
tailwindcss: ^4.1.18
|
||||||
|
terser: ^5.44.1
|
||||||
|
typescript: ~5.9.3
|
||||||
|
unplugin-auto-import: ^20.3.0
|
||||||
|
unplugin-icons: ^22.5.0
|
||||||
|
unplugin-vue-components: ^30.0.0
|
||||||
|
vconsole: ^3.15.1
|
||||||
|
vee-validate: ^4.15.1
|
||||||
|
vite: ^7.2.7
|
||||||
|
vite-plugin-pwa: ^1.2.0
|
||||||
|
vitest: ^4.0.15
|
||||||
|
vue: ^3.5.25
|
||||||
|
vue-i18n: ^11.2.2
|
||||||
|
vue-router: ^4.6.3
|
||||||
|
vue-tsc: ^3.1.8
|
||||||
|
workbox-window: ^7.4.0
|
||||||
|
wrangler: ^4.54.0
|
||||||
|
zod: ^3.24.1
|
||||||
|
|
||||||
|
catalogMode: prefer
|
||||||
|
|
||||||
|
shellEmulator: true
|
||||||
|
|
||||||
|
trustPolicy: off
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { VersionInfo } from "@/api/types";
|
import type { VersionInfo } from "@/api/types";
|
||||||
import { App } from "@capacitor/app";
|
import { App } from "@capacitor/app";
|
||||||
import { alertController } from "@ionic/vue";
|
import { alertController } from "@ionic/vue";
|
||||||
import { client } from "@/api";
|
|
||||||
import { i18n } from "@/locales";
|
import { i18n } from "@/locales";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,12 +27,6 @@ function compareVersion(version1: string, version2: string): number {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateUrls = {
|
|
||||||
ios: "https://apps.apple.com/app/id123456789",
|
|
||||||
android: "https://play.google.com/store/apps/details?id=riwa.ionic.app",
|
|
||||||
browser: "",
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用更新检查
|
* 应用更新检查
|
||||||
*/
|
*/
|
||||||
@@ -81,40 +74,53 @@ export function useAppUpdate() {
|
|||||||
updateUrl?: string;
|
updateUrl?: string;
|
||||||
}> {
|
}> {
|
||||||
state.isChecking = true;
|
state.isChecking = true;
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
const current = await getCurrentVersion();
|
||||||
|
// 开发环境下不检查更新
|
||||||
|
state.currentVersion = current;
|
||||||
|
state.hasUpdate = false;
|
||||||
|
state.latestVersion = current;
|
||||||
|
state.forceUpdate = false;
|
||||||
|
state.updateMessage = "";
|
||||||
|
state.updateUrl = "";
|
||||||
|
state.isChecking = false;
|
||||||
|
return {
|
||||||
|
hasUpdate: false,
|
||||||
|
currentVersion: current,
|
||||||
|
};
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// 1. 获取当前版本
|
// 1. 获取当前版本
|
||||||
const current = await getCurrentVersion();
|
const current = await getCurrentVersion();
|
||||||
state.currentVersion = current;
|
state.currentVersion = current;
|
||||||
// 2. 从服务器检查最新版本
|
|
||||||
// TODO: 后端接口实现后替换为真实 API 调用
|
|
||||||
// const response = await client.api.app.version.get({
|
|
||||||
// query: {
|
|
||||||
// platform: platform === 'ios' ? 'ios' : platform === 'android' ? 'android' : 'web',
|
|
||||||
// currentVersion: current,
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 模拟后端返回数据(开发阶段)
|
// 2. PWA 应用检查 Service Worker 更新
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
if (platform === "browser" && "serviceWorker" in navigator) {
|
||||||
const versionInfo: VersionInfo = {
|
const registration = await navigator.serviceWorker.getRegistration();
|
||||||
version: "0.0.1", // 模拟有新版本
|
if (registration) {
|
||||||
forceUpdate: false,
|
// 触发 Service Worker 更新检查
|
||||||
updateMessage: "修复了一些问题并优化了性能",
|
await registration.update();
|
||||||
updateUrl: updateUrls[platform] || "",
|
}
|
||||||
minSupportVersion: "0.0.1",
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// 真实 API 调用后的逻辑
|
// 3. 从 Cloudflare Function 检查最新版本
|
||||||
// if (response.error) {
|
const apiUrl = window.location.origin;
|
||||||
// console.error('检查更新失败:', response.error)
|
const response = await fetch(
|
||||||
// return {
|
`${apiUrl}/api/version?platform=${platform}¤tVersion=${current}`,
|
||||||
// hasUpdate: false,
|
{ cache: "no-cache" }, // 不使用缓存,确保获取最新版本信息
|
||||||
// currentVersion: current,
|
);
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// const versionInfo = response.data as VersionInfo
|
|
||||||
|
|
||||||
// 3. 版本比较
|
if (!response.ok) {
|
||||||
|
console.error("检查更新失败:", response.statusText);
|
||||||
|
return {
|
||||||
|
hasUpdate: false,
|
||||||
|
currentVersion: current,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionInfo: VersionInfo = await response.json();
|
||||||
|
|
||||||
|
// 4. 版本比较
|
||||||
const isNewVersion = compareVersion(current, versionInfo.version) < 0;
|
const isNewVersion = compareVersion(current, versionInfo.version) < 0;
|
||||||
|
|
||||||
// 更新状态
|
// 更新状态
|
||||||
@@ -186,7 +192,7 @@ export function useAppUpdate() {
|
|||||||
text: i18n.global.t("app.update.now"),
|
text: i18n.global.t("app.update.now"),
|
||||||
role: "confirm",
|
role: "confirm",
|
||||||
handler: () => {
|
handler: () => {
|
||||||
openStoreUpdate();
|
applyUpdate();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -199,7 +205,7 @@ export function useAppUpdate() {
|
|||||||
text: i18n.global.t("app.update.now"),
|
text: i18n.global.t("app.update.now"),
|
||||||
role: "confirm",
|
role: "confirm",
|
||||||
handler: () => {
|
handler: () => {
|
||||||
openStoreUpdate();
|
applyUpdate();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -218,22 +224,63 @@ export function useAppUpdate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web 应用检查 Service Worker 更新
|
// PWA 应用更新流程
|
||||||
if ("serviceWorker" in navigator) {
|
if (platform === "browser" && "serviceWorker" in navigator) {
|
||||||
const registration = await navigator.serviceWorker.getRegistration();
|
const registration = await navigator.serviceWorker.getRegistration();
|
||||||
if (registration?.waiting) {
|
|
||||||
// 通知 Service Worker 跳过等待,立即激活
|
|
||||||
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
||||||
|
|
||||||
// 等待 Service Worker 激活后重新加载页面
|
if (registration) {
|
||||||
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
// 检查是否有等待激活的 Service Worker
|
||||||
window.location.reload();
|
const waitingWorker = registration.waiting;
|
||||||
});
|
if (waitingWorker) {
|
||||||
return;
|
// 通知 Service Worker 跳过等待,立即激活
|
||||||
|
(waitingWorker as ServiceWorker).postMessage({ type: "SKIP_WAITING" });
|
||||||
|
|
||||||
|
// 等待控制器变更后重新加载
|
||||||
|
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
||||||
|
window.location.reload();
|
||||||
|
}, { once: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有正在安装的 Service Worker
|
||||||
|
if (registration.installing) {
|
||||||
|
const installingWorker = registration.installing;
|
||||||
|
installingWorker.addEventListener("statechange", () => {
|
||||||
|
if (installingWorker.state === "installed" && navigator.serviceWorker.controller) {
|
||||||
|
// 新的 Service Worker 已安装,通知它跳过等待
|
||||||
|
(installingWorker as ServiceWorker).postMessage({ type: "SKIP_WAITING" });
|
||||||
|
|
||||||
|
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
||||||
|
window.location.reload();
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手动触发更新检查
|
||||||
|
try {
|
||||||
|
await registration.update();
|
||||||
|
// 等待一小段时间让更新完成
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
|
// 如果有等待的 Service Worker,激活它
|
||||||
|
const waitingWorker = registration.waiting;
|
||||||
|
if (waitingWorker) {
|
||||||
|
(waitingWorker as ServiceWorker).postMessage({ type: "SKIP_WAITING" });
|
||||||
|
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
||||||
|
window.location.reload();
|
||||||
|
}, { once: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error("Service Worker 更新失败:", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有 Service Worker,直接重新加载
|
// 如果以上都没有执行,直接重新加载页面
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@@ -1,6 +1,7 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
/// <reference types="vite-plugin-pwa/client" />
|
/// <reference types="vite-plugin-pwa/client" />
|
||||||
/// <reference types="unplugin-icons/types/vue" />
|
/// <reference types="unplugin-icons/types/vue" />
|
||||||
|
/// <reference types="@cloudflare/workers-types" />
|
||||||
|
|
||||||
import type { MessageSchema } from "@/locales";
|
import type { MessageSchema } from "@/locales";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext", "DOM", "WebWorker"],
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
|
|||||||
Reference in New Issue
Block a user