feat: 添加应用版本更新功能;实现版本检查、更新提示及国际化支持
This commit is contained in:
@@ -1,3 +1,33 @@
|
||||
import type { VersionInfo } from "@/api/types";
|
||||
import { App } from "@capacitor/app";
|
||||
import { alertController, modalController } from "@ionic/vue";
|
||||
import { client } from "@/api";
|
||||
import { i18n } from "@/locales";
|
||||
|
||||
/**
|
||||
* 版本比较函数
|
||||
* @param version1 版本号1,如 "1.2.3"
|
||||
* @param version2 版本号2,如 "1.2.4"
|
||||
* @returns 如果 version1 < version2 返回 -1,相等返回 0,大于返回 1
|
||||
*/
|
||||
function compareVersion(version1: string, version2: string): number {
|
||||
const v1Parts = version1.split(".").map(Number);
|
||||
const v2Parts = version2.split(".").map(Number);
|
||||
const maxLength = Math.max(v1Parts.length, v2Parts.length);
|
||||
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
const v1Part = v1Parts[i] || 0;
|
||||
const v2Part = v2Parts[i] || 0;
|
||||
|
||||
if (v1Part < v2Part)
|
||||
return -1;
|
||||
if (v1Part > v2Part)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用更新检查组合式函数
|
||||
*/
|
||||
@@ -5,7 +35,31 @@ export function useAppUpdate() {
|
||||
const isChecking = ref(false);
|
||||
const hasUpdate = ref(false);
|
||||
const latestVersion = ref("");
|
||||
const currentVersion = ref("1.0.0"); // 从 package.json 或环境变量读取
|
||||
const currentVersion = ref("");
|
||||
const forceUpdate = ref(false);
|
||||
const updateMessage = ref("");
|
||||
const updateUrl = ref("");
|
||||
const platform = usePlatform();
|
||||
|
||||
/**
|
||||
* 获取当前应用版本
|
||||
*/
|
||||
async function getCurrentVersion(): Promise<string> {
|
||||
try {
|
||||
// 在原生平台使用 Capacitor App API
|
||||
if (platform !== "browser") {
|
||||
const appInfo = await App.getInfo();
|
||||
return appInfo.version;
|
||||
}
|
||||
|
||||
// Web 平台从环境变量或 package.json 获取
|
||||
return import.meta.env.VITE_APP_VERSION || "0.0.1";
|
||||
}
|
||||
catch (error) {
|
||||
console.error("获取当前版本失败:", error);
|
||||
return "0.0.1";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有新版本
|
||||
@@ -14,44 +68,83 @@ export function useAppUpdate() {
|
||||
hasUpdate: boolean;
|
||||
currentVersion: string;
|
||||
latestVersion?: string;
|
||||
forceUpdate?: boolean;
|
||||
updateMessage?: string;
|
||||
updateUrl?: string;
|
||||
}> {
|
||||
isChecking.value = true;
|
||||
try {
|
||||
// 方案1: 从服务器检查版本(需要后端 API)
|
||||
// const response = await fetch('/api/version');
|
||||
// const { version } = await response.json();
|
||||
// latestVersion.value = version;
|
||||
// 1. 获取当前版本
|
||||
const current = await getCurrentVersion();
|
||||
currentVersion.value = current;
|
||||
|
||||
// 方案2: 检查 Service Worker 更新(PWA 应用)
|
||||
if ("serviceWorker" in navigator) {
|
||||
const registration = await navigator.serviceWorker.getRegistration();
|
||||
if (registration) {
|
||||
await registration.update();
|
||||
const hasNewWorker = registration.waiting !== null || registration.installing !== null;
|
||||
hasUpdate.value = hasNewWorker;
|
||||
// 2. 从服务器检查最新版本
|
||||
// TODO: 后端接口实现后替换为真实 API 调用
|
||||
// const response = await client.api.app.version.get({
|
||||
// query: {
|
||||
// platform: platform === 'ios' ? 'ios' : platform === 'android' ? 'android' : 'web',
|
||||
// currentVersion: current,
|
||||
// },
|
||||
// })
|
||||
|
||||
if (hasNewWorker) {
|
||||
return {
|
||||
hasUpdate: true,
|
||||
currentVersion: currentVersion.value,
|
||||
latestVersion: "新版本可用",
|
||||
};
|
||||
}
|
||||
// 模拟后端返回数据(开发阶段)
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
const versionInfo: VersionInfo = {
|
||||
version: "0.0.2", // 模拟有新版本
|
||||
forceUpdate: false,
|
||||
updateMessage: "修复了一些问题并优化了性能",
|
||||
updateUrl: platform === "ios"
|
||||
? "https://apps.apple.com/app/id123456789"
|
||||
: platform === "android"
|
||||
? "https://play.google.com/store/apps/details?id=riwa.ionic.app"
|
||||
: "",
|
||||
minSupportVersion: "0.0.1",
|
||||
};
|
||||
|
||||
// 真实 API 调用后的逻辑
|
||||
// if (response.error) {
|
||||
// console.error('检查更新失败:', response.error)
|
||||
// return {
|
||||
// hasUpdate: false,
|
||||
// currentVersion: current,
|
||||
// }
|
||||
// }
|
||||
// const versionInfo = response.data as VersionInfo
|
||||
|
||||
// 3. 版本比较
|
||||
const isNewVersion = compareVersion(current, versionInfo.version) < 0;
|
||||
|
||||
// 更新状态
|
||||
latestVersion.value = versionInfo.version;
|
||||
hasUpdate.value = isNewVersion;
|
||||
forceUpdate.value = versionInfo.forceUpdate || false;
|
||||
updateMessage.value = versionInfo.updateMessage || "";
|
||||
updateUrl.value = versionInfo.updateUrl || "";
|
||||
|
||||
// 4. 检查是否低于最低支持版本(强制更新)
|
||||
if (versionInfo.minSupportVersion) {
|
||||
const isBelowMinVersion = compareVersion(current, versionInfo.minSupportVersion) < 0;
|
||||
if (isBelowMinVersion) {
|
||||
forceUpdate.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟检查(实际应用中需要替换为真实的 API 调用)
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 暂时返回无更新
|
||||
return {
|
||||
hasUpdate: false,
|
||||
currentVersion: currentVersion.value,
|
||||
hasUpdate: isNewVersion,
|
||||
currentVersion: current,
|
||||
latestVersion: versionInfo.version,
|
||||
forceUpdate: forceUpdate.value,
|
||||
updateMessage: updateMessage.value,
|
||||
updateUrl: updateUrl.value,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
console.error("检查更新失败:", error);
|
||||
throw error;
|
||||
const current = currentVersion.value || await getCurrentVersion();
|
||||
return {
|
||||
hasUpdate: false,
|
||||
currentVersion: current,
|
||||
};
|
||||
}
|
||||
finally {
|
||||
isChecking.value = false;
|
||||
@@ -59,9 +152,71 @@ export function useAppUpdate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用更新(重新加载应用)
|
||||
* 打开应用商店更新页面
|
||||
*/
|
||||
async function openStoreUpdate(): Promise<void> {
|
||||
if (!updateUrl.value) {
|
||||
console.warn("没有提供更新链接");
|
||||
return;
|
||||
}
|
||||
|
||||
// 在原生平台打开外部链接
|
||||
if (platform !== "browser") {
|
||||
window.open(updateUrl.value, "_system");
|
||||
}
|
||||
else {
|
||||
// Web 平台直接打开链接
|
||||
window.open(updateUrl.value, "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示更新提示对话框
|
||||
*/
|
||||
async function showUpdateDialog(): Promise<void> {
|
||||
const alert = await alertController.create({
|
||||
header: i18n.global.t("app.update.title"),
|
||||
message: updateMessage.value || i18n.global.t("app.update.message"),
|
||||
backdropDismiss: !forceUpdate.value, // 强制更新时不允许关闭
|
||||
buttons: forceUpdate.value
|
||||
? [
|
||||
{
|
||||
text: i18n.global.t("app.update.now"),
|
||||
role: "confirm",
|
||||
handler: () => {
|
||||
openStoreUpdate();
|
||||
},
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
text: i18n.global.t("app.update.later"),
|
||||
role: "cancel",
|
||||
},
|
||||
{
|
||||
text: i18n.global.t("app.update.now"),
|
||||
role: "confirm",
|
||||
handler: () => {
|
||||
openStoreUpdate();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用更新(重新加载应用或打开商店)
|
||||
*/
|
||||
async function applyUpdate(): Promise<void> {
|
||||
// 如果是原生应用且有更新链接,打开应用商店
|
||||
if (platform !== "browser" && updateUrl.value) {
|
||||
await openStoreUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Web 应用检查 Service Worker 更新
|
||||
if ("serviceWorker" in navigator) {
|
||||
const registration = await navigator.serviceWorker.getRegistration();
|
||||
if (registration?.waiting) {
|
||||
@@ -91,13 +246,31 @@ export function useAppUpdate() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动检查更新并显示提示
|
||||
*/
|
||||
async function checkAndPromptUpdate(): Promise<void> {
|
||||
const result = await checkForUpdate();
|
||||
|
||||
if (result.hasUpdate) {
|
||||
await showUpdateDialog();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isChecking,
|
||||
hasUpdate,
|
||||
currentVersion,
|
||||
latestVersion,
|
||||
forceUpdate,
|
||||
updateMessage,
|
||||
updateUrl,
|
||||
checkForUpdate,
|
||||
applyUpdate,
|
||||
forceReload,
|
||||
openStoreUpdate,
|
||||
showUpdateDialog,
|
||||
checkAndPromptUpdate,
|
||||
getCurrentVersion,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user