feat: 添加应用版本更新功能;实现版本检查、更新提示及国际化支持
This commit is contained in:
242
app.update.md
Normal file
242
app.update.md
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
# 应用版本更新使用示例
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
`useAppUpdate` 提供了完整的应用版本检查和更新功能,支持:
|
||||||
|
|
||||||
|
- ✅ 自动获取当前应用版本(原生/Web)
|
||||||
|
- ✅ 从后端 API 检查最新版本
|
||||||
|
- ✅ 版本号比较(语义化版本)
|
||||||
|
- ✅ 强制更新和可选更新
|
||||||
|
- ✅ 打开应用商店更新页面
|
||||||
|
- ✅ 国际化支持(中英文)
|
||||||
|
- ✅ Service Worker 更新(PWA)
|
||||||
|
|
||||||
|
## 基础使用
|
||||||
|
|
||||||
|
### 1. 在应用启动时检查更新
|
||||||
|
|
||||||
|
在 `App.vue` 或主布局组件中:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
|
||||||
|
const { checkAndPromptUpdate } = useAppUpdate()
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
// 应用启动 3 秒后检查更新
|
||||||
|
setTimeout(() => {
|
||||||
|
checkAndPromptUpdate()
|
||||||
|
}, 3000)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 手动触发检查更新
|
||||||
|
|
||||||
|
在设置页面添加"检查更新"按钮:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<ion-page>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>系统设置</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item button @click="handleCheckUpdate">
|
||||||
|
<ion-label>
|
||||||
|
<h2>检查更新</h2>
|
||||||
|
<p>当前版本: {{ currentVersion }}</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-spinner v-if="isChecking" slot="end" />
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-content>
|
||||||
|
</ion-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const {
|
||||||
|
isChecking,
|
||||||
|
currentVersion,
|
||||||
|
checkAndPromptUpdate,
|
||||||
|
} = useAppUpdate()
|
||||||
|
|
||||||
|
async function handleCheckUpdate() {
|
||||||
|
await checkAndPromptUpdate()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 自定义更新提示
|
||||||
|
|
||||||
|
如果不想使用默认对话框,可以自己处理:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
const {
|
||||||
|
hasUpdate,
|
||||||
|
latestVersion,
|
||||||
|
forceUpdate,
|
||||||
|
updateMessage,
|
||||||
|
checkForUpdate,
|
||||||
|
openStoreUpdate,
|
||||||
|
} = useAppUpdate()
|
||||||
|
|
||||||
|
async function checkUpdate() {
|
||||||
|
const result = await checkForUpdate()
|
||||||
|
|
||||||
|
if (result.hasUpdate) {
|
||||||
|
// 自定义提示逻辑
|
||||||
|
if (result.forceUpdate) {
|
||||||
|
// 强制更新 - 阻止用户继续使用
|
||||||
|
showForceUpdateModal()
|
||||||
|
} else {
|
||||||
|
// 可选更新 - 显示提示但允许跳过
|
||||||
|
showOptionalUpdateToast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 显示版本信息
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>
|
||||||
|
<h2>应用版本</h2>
|
||||||
|
<p>{{ currentVersion || '获取中...' }}</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-badge v-if="hasUpdate" color="danger">有更新</ion-badge>
|
||||||
|
</ion-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
|
||||||
|
const { currentVersion, hasUpdate, getCurrentVersion, checkForUpdate } = useAppUpdate()
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getCurrentVersion()
|
||||||
|
await checkForUpdate()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 参考
|
||||||
|
|
||||||
|
### 返回值
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
// 状态
|
||||||
|
isChecking: Ref<boolean> // 是否正在检查更新
|
||||||
|
hasUpdate: Ref<boolean> // 是否有新版本
|
||||||
|
currentVersion: Ref<string> // 当前版本号
|
||||||
|
latestVersion: Ref<string> // 最新版本号
|
||||||
|
forceUpdate: Ref<boolean> // 是否强制更新
|
||||||
|
updateMessage: Ref<string> // 更新提示信息
|
||||||
|
updateUrl: Ref<string> // 应用商店链接
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
getCurrentVersion(): Promise<string> // 获取当前版本
|
||||||
|
checkForUpdate(): Promise<UpdateResult> // 检查更新
|
||||||
|
checkAndPromptUpdate(): Promise<void> // 检查并显示提示
|
||||||
|
showUpdateDialog(): Promise<void> // 显示更新对话框
|
||||||
|
openStoreUpdate(): Promise<void> // 打开应用商店
|
||||||
|
applyUpdate(): Promise<void> // 应用更新
|
||||||
|
forceReload(): Promise<void> // 强制刷新
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### checkForUpdate 返回类型
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
hasUpdate: boolean // 是否有更新
|
||||||
|
currentVersion: string // 当前版本
|
||||||
|
latestVersion?: string // 最新版本
|
||||||
|
forceUpdate?: boolean // 是否强制更新
|
||||||
|
updateMessage?: string // 更新说明
|
||||||
|
updateUrl?: string // 更新链接
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 后端 API 接口
|
||||||
|
|
||||||
|
需要后端实现以下接口:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// GET /api/app/version
|
||||||
|
// Query Parameters:
|
||||||
|
{
|
||||||
|
platform: 'ios' | 'android' | 'web' // 平台类型
|
||||||
|
currentVersion: string // 当前版本号
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response:
|
||||||
|
{
|
||||||
|
version: string // 最新版本号
|
||||||
|
buildNumber?: number // 构建号
|
||||||
|
forceUpdate: boolean // 是否强制更新
|
||||||
|
updateMessage?: string // 更新说明(多语言)
|
||||||
|
updateUrl?: string // 下载链接
|
||||||
|
minSupportVersion?: string // 最低支持版本
|
||||||
|
releaseDate?: string // 发布时间
|
||||||
|
releaseNotes?: string[] // 更新日志
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境变量配置
|
||||||
|
|
||||||
|
在 `.env` 文件中添加:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 应用版本(可选,如果不设置会从 Capacitor 读取)
|
||||||
|
VITE_APP_VERSION=1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## 版本号规范
|
||||||
|
|
||||||
|
遵循语义化版本规范(Semantic Versioning):
|
||||||
|
|
||||||
|
- **主版本号**:不兼容的 API 修改
|
||||||
|
- **次版本号**:向下兼容的功能性新增
|
||||||
|
- **修订号**:向下兼容的问题修正
|
||||||
|
|
||||||
|
示例:`1.2.3`
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **原生应用更新**:iOS 和 Android 原生应用必须通过应用商店更新,不能绕过
|
||||||
|
2. **强制更新策略**:谨慎使用强制更新,避免影响用户体验
|
||||||
|
3. **版本检查频率**:建议应用启动时检查,避免频繁请求
|
||||||
|
4. **降级处理**:如果后端接口失败,应用仍能正常使用
|
||||||
|
5. **测试环境**:开发阶段接口返回模拟数据,生产环境需替换为真实 API
|
||||||
|
|
||||||
|
## 国际化文本
|
||||||
|
|
||||||
|
已添加的翻译键:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"app.update.title": "发现新版本 / New Version Available",
|
||||||
|
"app.update.message": "有新版本可用... / A new version is available...",
|
||||||
|
"app.update.now": "立即更新 / Update Now",
|
||||||
|
"app.update.later": "稍后再说 / Later",
|
||||||
|
"app.update.forceUpdate": "发现新版本,需要更新后才能继续使用"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 生产环境配置
|
||||||
|
|
||||||
|
1. **替换模拟数据**:在 [useAppUpdate.ts](../composables/useAppUpdate.ts#L80-L100) 中取消注释真实 API 调用
|
||||||
|
2. **配置应用商店链接**:后端返回正确的 App Store / Google Play 链接
|
||||||
|
3. **设置最低支持版本**:根据实际情况配置 `minSupportVersion`
|
||||||
@@ -65,3 +65,25 @@ export type UserDepositOrderBody = TreatyQuery<typeof client.api.deposit.orders.
|
|||||||
export type UserWithdrawOrderData = Treaty.Data<typeof client.api.withdraw.get>["data"][number];
|
export type UserWithdrawOrderData = Treaty.Data<typeof client.api.withdraw.get>["data"][number];
|
||||||
|
|
||||||
export type UserWithdrawOrderBody = TreatyQuery<typeof client.api.withdraw.get>;
|
export type UserWithdrawOrderBody = TreatyQuery<typeof client.api.withdraw.get>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用版本信息
|
||||||
|
*/
|
||||||
|
export interface VersionInfo {
|
||||||
|
/** 最新版本号,如 "1.2.3" */
|
||||||
|
version: string;
|
||||||
|
/** 构建号 */
|
||||||
|
buildNumber?: number;
|
||||||
|
/** 是否强制更新 */
|
||||||
|
forceUpdate: boolean;
|
||||||
|
/** 更新提示信息 */
|
||||||
|
updateMessage?: string;
|
||||||
|
/** 更新下载链接(App Store / Google Play) */
|
||||||
|
updateUrl?: string;
|
||||||
|
/** 最低支持版本,低于此版本必须更新 */
|
||||||
|
minSupportVersion?: string;
|
||||||
|
/** 发布时间 */
|
||||||
|
releaseDate?: string;
|
||||||
|
/** 更新内容 */
|
||||||
|
releaseNotes?: string[];
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 isChecking = ref(false);
|
||||||
const hasUpdate = ref(false);
|
const hasUpdate = ref(false);
|
||||||
const latestVersion = ref("");
|
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;
|
hasUpdate: boolean;
|
||||||
currentVersion: string;
|
currentVersion: string;
|
||||||
latestVersion?: string;
|
latestVersion?: string;
|
||||||
|
forceUpdate?: boolean;
|
||||||
|
updateMessage?: string;
|
||||||
|
updateUrl?: string;
|
||||||
}> {
|
}> {
|
||||||
isChecking.value = true;
|
isChecking.value = true;
|
||||||
try {
|
try {
|
||||||
// 方案1: 从服务器检查版本(需要后端 API)
|
// 1. 获取当前版本
|
||||||
// const response = await fetch('/api/version');
|
const current = await getCurrentVersion();
|
||||||
// const { version } = await response.json();
|
currentVersion.value = current;
|
||||||
// latestVersion.value = version;
|
|
||||||
|
|
||||||
// 方案2: 检查 Service Worker 更新(PWA 应用)
|
// 2. 从服务器检查最新版本
|
||||||
if ("serviceWorker" in navigator) {
|
// TODO: 后端接口实现后替换为真实 API 调用
|
||||||
const registration = await navigator.serviceWorker.getRegistration();
|
// const response = await client.api.app.version.get({
|
||||||
if (registration) {
|
// query: {
|
||||||
await registration.update();
|
// platform: platform === 'ios' ? 'ios' : platform === 'android' ? 'android' : 'web',
|
||||||
const hasNewWorker = registration.waiting !== null || registration.installing !== null;
|
// currentVersion: current,
|
||||||
hasUpdate.value = hasNewWorker;
|
// },
|
||||||
|
// })
|
||||||
|
|
||||||
if (hasNewWorker) {
|
// 模拟后端返回数据(开发阶段)
|
||||||
return {
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
hasUpdate: true,
|
const versionInfo: VersionInfo = {
|
||||||
currentVersion: currentVersion.value,
|
version: "0.0.2", // 模拟有新版本
|
||||||
latestVersion: "新版本可用",
|
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 {
|
return {
|
||||||
hasUpdate: false,
|
hasUpdate: isNewVersion,
|
||||||
currentVersion: currentVersion.value,
|
currentVersion: current,
|
||||||
|
latestVersion: versionInfo.version,
|
||||||
|
forceUpdate: forceUpdate.value,
|
||||||
|
updateMessage: updateMessage.value,
|
||||||
|
updateUrl: updateUrl.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error("检查更新失败:", error);
|
console.error("检查更新失败:", error);
|
||||||
throw error;
|
const current = currentVersion.value || await getCurrentVersion();
|
||||||
|
return {
|
||||||
|
hasUpdate: false,
|
||||||
|
currentVersion: current,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
isChecking.value = false;
|
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> {
|
async function applyUpdate(): Promise<void> {
|
||||||
|
// 如果是原生应用且有更新链接,打开应用商店
|
||||||
|
if (platform !== "browser" && updateUrl.value) {
|
||||||
|
await openStoreUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Web 应用检查 Service Worker 更新
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
const registration = await navigator.serviceWorker.getRegistration();
|
const registration = await navigator.serviceWorker.getRegistration();
|
||||||
if (registration?.waiting) {
|
if (registration?.waiting) {
|
||||||
@@ -91,13 +246,31 @@ export function useAppUpdate() {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动检查更新并显示提示
|
||||||
|
*/
|
||||||
|
async function checkAndPromptUpdate(): Promise<void> {
|
||||||
|
const result = await checkForUpdate();
|
||||||
|
|
||||||
|
if (result.hasUpdate) {
|
||||||
|
await showUpdateDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isChecking,
|
isChecking,
|
||||||
hasUpdate,
|
hasUpdate,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
latestVersion,
|
latestVersion,
|
||||||
|
forceUpdate,
|
||||||
|
updateMessage,
|
||||||
|
updateUrl,
|
||||||
checkForUpdate,
|
checkForUpdate,
|
||||||
applyUpdate,
|
applyUpdate,
|
||||||
forceReload,
|
forceReload,
|
||||||
|
openStoreUpdate,
|
||||||
|
showUpdateDialog,
|
||||||
|
checkAndPromptUpdate,
|
||||||
|
getCurrentVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,15 @@
|
|||||||
"transfer": "Transfer",
|
"transfer": "Transfer",
|
||||||
"balance": "Balance"
|
"balance": "Balance"
|
||||||
},
|
},
|
||||||
|
"app": {
|
||||||
|
"update": {
|
||||||
|
"title": "New Version Available",
|
||||||
|
"message": "A new version is available. Update now?",
|
||||||
|
"now": "Update Now",
|
||||||
|
"later": "Later",
|
||||||
|
"forceUpdate": "A new version is required to continue using the app"
|
||||||
|
}
|
||||||
|
},
|
||||||
"scanner": {
|
"scanner": {
|
||||||
"title": "Scan QR Code",
|
"title": "Scan QR Code",
|
||||||
"hint": "Align QR code within frame to scan",
|
"hint": "Align QR code within frame to scan",
|
||||||
|
|||||||
@@ -6,6 +6,15 @@
|
|||||||
"transfer": "转账",
|
"transfer": "转账",
|
||||||
"balance": "余额"
|
"balance": "余额"
|
||||||
},
|
},
|
||||||
|
"app": {
|
||||||
|
"update": {
|
||||||
|
"title": "发现新版本",
|
||||||
|
"message": "有新版本可用,是否立即更新?",
|
||||||
|
"now": "立即更新",
|
||||||
|
"later": "稍后再说",
|
||||||
|
"forceUpdate": "发现新版本,需要更新后才能继续使用"
|
||||||
|
}
|
||||||
|
},
|
||||||
"scanner": {
|
"scanner": {
|
||||||
"title": "扫描二维码",
|
"title": "扫描二维码",
|
||||||
"hint": "将二维码对准扫描框进行扫描",
|
"hint": "将二维码对准扫描框进行扫描",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { checkbox, close, contrastOutline, information, languageOutline, refresh
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useIonRouter();
|
const router = useIonRouter();
|
||||||
const { cacheSize, calculateCacheSize, clearCache } = useCacheSize();
|
const { cacheSize, calculateCacheSize, clearCache } = useCacheSize();
|
||||||
const { isChecking, checkForUpdate } = useAppUpdate();
|
const { isChecking, checkAndPromptUpdate } = useAppUpdate();
|
||||||
const { currentLanguage } = useLanguage();
|
const { currentLanguage } = useLanguage();
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const themeNames = {
|
const themeNames = {
|
||||||
@@ -27,48 +27,7 @@ function handleClearCache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleCheckUpdate() {
|
async function handleCheckUpdate() {
|
||||||
try {
|
checkAndPromptUpdate();
|
||||||
const result = await checkForUpdate();
|
|
||||||
|
|
||||||
if (result.hasUpdate) {
|
|
||||||
const alert = await alertController.create({
|
|
||||||
header: t("settings.updateAvailable"),
|
|
||||||
message: `${t("settings.currentVersion")}: ${result.currentVersion}\n${t("settings.latestVersion")}: ${result.latestVersion || t("settings.newVersion")}`,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: t("settings.cancel"),
|
|
||||||
role: "cancel",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: t("settings.updateNow"),
|
|
||||||
handler: () => {
|
|
||||||
window.location.reload();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
await alert.present();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const toast = await toastController.create({
|
|
||||||
message: t("settings.alreadyLatest"),
|
|
||||||
duration: 2000,
|
|
||||||
icon: checkbox,
|
|
||||||
position: "bottom",
|
|
||||||
color: "success",
|
|
||||||
});
|
|
||||||
await toast.present();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
const toast = await toastController.create({
|
|
||||||
message: t("settings.checkUpdateFailed"),
|
|
||||||
duration: 2000,
|
|
||||||
position: "bottom",
|
|
||||||
color: "danger",
|
|
||||||
});
|
|
||||||
await toast.present();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user