From 2617e1786c3fddc43b18df31c8236b97ce4ee60f Mon Sep 17 00:00:00 2001
From: zjk <852185829@qq.com>
Date: 星期五, 31 七月 2026 16:26:20 +0800
Subject: [PATCH] feat: 添加应用更新进度显示与安装权限
---
components/admin/AdminConfigPanel.vue | 98 +++++++++++++++++++++++++++++++++++++------------
1 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/components/admin/AdminConfigPanel.vue b/components/admin/AdminConfigPanel.vue
index 53102ad..8e0864e 100644
--- a/components/admin/AdminConfigPanel.vue
+++ b/components/admin/AdminConfigPanel.vue
@@ -59,7 +59,7 @@
</view>
<view class="update-btn" @click="handleVersionUpdate">
<image :src="updateBtnIcon" class="banner-btn-icon" mode="aspectFit"></image>
- <text class="update-btn-text">{{ isUpdatingVersion ? '下载中...' : '立即更新' }}</text>
+ <text class="update-btn-text">{{ updateButtonText }}</text>
</view>
</view>
<view class="update-banner" v-else>
@@ -172,7 +172,7 @@
</template>
<script setup>
-import { onMounted, ref } from 'vue';
+import { computed, onMounted, ref } from 'vue';
import configPageIcon from '../../static/admin-pages/L2Nja.png';
import machineIcon from '../../static/admin-pages/n83u2.png';
import systemInfoIcon from '../../static/admin-pages/tLgNe.png';
@@ -190,7 +190,7 @@
import { syncEmployeeVerifyList } from '../../api/employee';
import { deactivateVisitMachine } from '../../api/device';
import { getLatestVersion } from '../../api/visitorRecord';
-import { clearRequestServerConfig, getRequestServerConfig, setRequestServerConfig } from '../../utils/request';
+import { buildBaseUrl, clearRequestServerConfig, getRequestServerConfig, setRequestServerConfig } from '../../utils/request';
import { syncAllPendingRecords } from '../../utils/syncEngine';
import { downloadRemoteFileToLocal } from '../../utils/fs';
@@ -203,12 +203,30 @@
const isLoggingOut = ref(false);
const isManualSyncing = ref(false);
const isUpdatingVersion = ref(false);
+const updateDownloadProgress = ref(-1);
+const isInstallingVersion = ref(false);
const logoutHoldTimer = ref(null);
const currentVersion = ref('v1.0.0');
const latestVersion = ref('');
const hasNewVersion = ref(false);
const latestVersionInfo = ref(null);
+
+const updateButtonText = computed(() => {
+ if (!isUpdatingVersion.value) {
+ return '立即更新';
+ }
+
+ if (isInstallingVersion.value) {
+ return '安装中...';
+ }
+
+ if (updateDownloadProgress.value >= 0) {
+ return `下载中 ${updateDownloadProgress.value}%`;
+ }
+
+ return '下载中...';
+});
const normalizeVersionNumber = (version = '') => {
return String(version || '').trim().replace(/^[vV]/, '');
@@ -366,6 +384,24 @@
});
};
+const resolvePackageDownloadUrl = (packageUrl = '') => {
+ const normalizedPackageUrl = String(packageUrl || '').trim();
+ if (!normalizedPackageUrl) {
+ return '';
+ }
+
+ if (/^https?:\/\//.test(normalizedPackageUrl)) {
+ return normalizedPackageUrl;
+ }
+
+ const baseUrl = buildBaseUrl(getRequestServerConfig());
+ if (!baseUrl) {
+ return '';
+ }
+
+ return `${baseUrl}${normalizedPackageUrl.startsWith('/') ? normalizedPackageUrl : `/${normalizedPackageUrl}`}`;
+};
+
const handleVersionUpdate = async () => {
if (isUpdatingVersion.value) {
return;
@@ -373,8 +409,9 @@
const packageUrl = latestVersionInfo.value?.packageUrl || '';
const packageName = latestVersionInfo.value?.packageName || 'visitor-update.apk';
+ const packageDownloadUrl = resolvePackageDownloadUrl(packageUrl);
- if (!hasNewVersion.value || !packageUrl) {
+ if (!hasNewVersion.value || !packageDownloadUrl) {
uni.showToast({
title: '未获取到更新包地址',
icon: 'none',
@@ -392,43 +429,56 @@
try {
isUpdatingVersion.value = true;
- uni.showLoading({
- title: '更新包下载中...',
- mask: true,
- });
+ updateDownloadProgress.value = 0;
+ isInstallingVersion.value = false;
+ let lastProgress = -1;
const fileNamePrefix = String(packageName || 'visitor-update')
.replace(/\.[^.]+$/, '')
.replace(/[^a-zA-Z0-9_-]/g, '-') || 'visitor-update';
- const localPackagePath = await downloadRemoteFileToLocal(packageUrl, {
+ const localPackagePath = await downloadRemoteFileToLocal(packageDownloadUrl, {
directoryName: 'apk-updates',
fileNamePrefix,
fallbackExtension: 'apk',
+ onProgress: ({ progress }) => {
+ const safeProgress = Math.max(0, Math.min(100, Number(progress || 0)));
+ if (safeProgress === lastProgress) {
+ return;
+ }
+ lastProgress = safeProgress;
+ updateDownloadProgress.value = safeProgress;
+ },
});
- uni.hideLoading();
+ updateDownloadProgress.value = 100;
+ isInstallingVersion.value = true;
+ uni.showToast({
+ title: '下载完成,正在拉起安装',
+ icon: 'none',
+ });
- plus.runtime.install(localPackagePath, {}, () => {
- uni.showToast({
- title: '安装包已打开,请按提示完成更新',
- icon: 'none',
- });
- }, (error) => {
- console.error('安装更新包失败:', error);
- uni.showToast({
- title: error?.message || '安装更新包失败',
- icon: 'none',
+ await new Promise((resolve, reject) => {
+ plus.runtime.install(localPackagePath, {}, () => {
+ uni.showToast({
+ title: '安装包已打开,请按提示完成更新',
+ icon: 'none',
+ });
+ resolve();
+ }, (error) => {
+ reject(error);
});
});
} catch (error) {
- console.error('下载更新包失败:', error);
+ const actionText = isInstallingVersion.value ? '安装更新包失败' : '下载更新包失败';
+ console.error(`${actionText}:`, error);
uni.showToast({
- title: error?.message || '下载更新包失败',
+ title: error?.message || actionText,
icon: 'none',
});
} finally {
- uni.hideLoading();
isUpdatingVersion.value = false;
+ updateDownloadProgress.value = -1;
+ isInstallingVersion.value = false;
}
};
@@ -439,7 +489,7 @@
try {
isManualSyncing.value = true;
-
+
// 强制触发员工档案全量同步,绕过缓存有效期
try {
await syncEmployeeVerifyList(true);
--
Gitblit v1.7.1