| src/App.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/components/DownloadProgressMask.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/components/el-progress.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/config.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/login.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/message.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/mine.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/works.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/utils/versionUpgrade.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/App.vue
@@ -10,6 +10,7 @@ import { confirmMessage } from "@/api/login.js"; const showSplash = ref(true); onMounted(() => { setTimeout(() => { showSplash.value = false; src/components/DownloadProgressMask.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,83 @@ <template> <view v-if="state.show" class="dpm-mask" @touchmove.stop.prevent @tap.stop> <view class="dpm-card" @tap.stop> <view class="dpm-title">{{ state.title }}</view> <ElProgress :percentage="state.progress" :stroke-width="12" :show-text="true" color="#0D867F" /> </view> </view> </template> <script setup> import { reactive, onUnmounted } from "vue"; import bus from "@/plugins/bus"; import ElProgress from "@/components/el-progress.vue"; const state = reactive({ show: false, progress: 0, title: "æ´æ°å ä¸è½½ä¸...", }); const handle = (payload = {}) => { if (!payload || typeof payload !== "object") return; if (payload.show === false) { state.show = false; state.progress = 0; state.title = "æ´æ°å ä¸è½½ä¸..."; // ä¸è½½ç»æï¼æ¢å¤ tabBarï¼é¿å åºé¨ä¸å¯ç¹ try { uni.showTabBar({ animation: false }); } catch (e) {} return; } if (payload.show === true) state.show = true; if (typeof payload.progress === "number" && Number.isFinite(payload.progress)) { state.progress = Math.max(0, Math.min(100, Math.floor(payload.progress))); } if (payload.title) state.title = String(payload.title); // ä¸è½½è¿è¡ä¸ï¼éèåç tabBarï¼åçå±çº§é«äºé¡µé¢é®ç½©ï¼å¦åä»å¯ç¹å»ï¼ if (state.show) { try { uni.hideTabBar({ animation: false }); } catch (e) {} } }; // äºä»¶çå¬å¿ é¡»å°½æ©æ³¨åï¼setup é¶æ®µå°±æ³¨åï¼ï¼é¿å ä¸è½½å¼å§æ¶è¿æª mounted 导è´éè¿é¦æ¬¡ show äºä»¶ // bus.ts ååäºä»¶åªè½ç»å®ä¸æ¬¡ï¼å off å onï¼ç¡®ä¿å§ç»ææ try { bus.$off("versionUpgrade:downloadProgress"); } catch (e) {} try { bus.$on("versionUpgrade:downloadProgress", handle); } catch (e) {} onUnmounted(() => { try { bus.$off("versionUpgrade:downloadProgress"); } catch (e) {} }); </script> <style scoped lang="scss"> .dpm-mask { position: fixed; left: 0; top: 0; right: 0; bottom: 0; z-index: 9999; background: rgba(0, 0, 0, 0.45); display: flex; align-items: center; justify-content: center; } .dpm-card { width: 620rpx; padding: 28rpx 28rpx 22rpx; background: #ffffff; border-radius: 20rpx; box-shadow: 0 12rpx 36rpx rgba(0, 0, 0, 0.18); } .dpm-title { text-align: center; font-size: 32rpx; font-weight: 600; color: rgba(0, 0, 0, 0.85); margin-bottom: 18rpx; } </style> src/components/el-progress.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,56 @@ <template> <view class="el-progress"> <view class="el-progress-bar"> <view class="el-progress-bar__outer" :style="{ height: `${strokeWidth}px` }"> <view class="el-progress-bar__inner" :style="innerStyle" /> </view> </view> <view v-if="showText" class="el-progress__text">{{ text }}</view> </view> </template> <script setup> import { computed } from "vue"; const props = defineProps({ percentage: { type: Number, default: 0 }, strokeWidth: { type: Number, default: 10 }, showText: { type: Boolean, default: true }, color: { type: String, default: "#409EFF" }, }); const safePercent = computed(() => { const n = Number(props.percentage); if (!Number.isFinite(n)) return 0; return Math.max(0, Math.min(100, Math.floor(n))); }); const innerStyle = computed(() => ({ width: `${safePercent.value}%`, backgroundColor: props.color, })); const text = computed(() => `${safePercent.value}%`); </script> <style scoped> .el-progress { width: 100%; } .el-progress-bar__outer { background-color: rgba(0, 0, 0, 0.08); border-radius: 100px; overflow: hidden; } .el-progress-bar__inner { height: 100%; border-radius: 100px; transition: width 0.15s ease; } .el-progress__text { margin-top: 10rpx; text-align: center; font-size: 26rpx; color: rgba(0, 0, 0, 0.55); } </style> src/config.js
@@ -1,7 +1,7 @@ // åºç¨å ¨å±é ç½® const config = { baseUrl: 'http://1.15.17.182:9003', fileUrl: 'http://1.15.17.182:9003', baseUrl: "http://1.15.17.182:9003", fileUrl: "http://1.15.17.182:9002", // åºç¨ä¿¡æ¯ appInfo: { // åºç¨åç§° @@ -13,16 +13,17 @@ // 宿¹ç½ç« site_url: "http://ruoyi.vip", // æ¿çåè®® agreements: [{ agreements: [ { title: "éç§æ¿ç", url: "https://ruoyi.vip/protocol.html" url: "https://ruoyi.vip/protocol.html", }, { title: "ç¨æ·æå¡åè®®", url: "https://ruoyi.vip/protocol.html" } ] } } url: "https://ruoyi.vip/protocol.html", }, ], }, }; export default config export default config; src/pages/index.vue
@@ -197,6 +197,7 @@ <view class="bottom-space" /> </scroll-view> <DownloadProgressMask /> </view> </template> @@ -205,6 +206,7 @@ import { onShow } from "@dcloudio/uni-app"; import { analysisCustomerContractAmounts, getBusiness } from "@/api/viewIndex"; import { createVersionUpgradeChecker } from "@/utils/versionUpgrade"; import DownloadProgressMask from "@/components/DownloadProgressMask.vue"; const imgNum1 = "/static/images/index/num1.png"; const imgNum2 = "/static/images/index/num2.png"; src/pages/login.vue
@@ -264,18 +264,33 @@ // #ifdef APP-PLUS try { // #ifdef APP-PLUS // @ts-ignore if (plus?.runtime?.version) { if (plus?.runtime?.getProperty) { // @ts-ignore versionName.value = plus.runtime.version; const appid = plus.runtime.appid; // @ts-ignore plus.runtime.getProperty(appid, (info) => { const v = info?.version || info?.versionName || ""; if (v) { versionName.value = String(v); console.log("[login-version] å½åç¯å¢=APP-PLUSï¼çæ¬=", versionName.value); } else { console.log("[login-version] APP-PLUS è·åå°ççæ¬åæ®µä¸ºç©ºï¼ä½¿ç¨é»è®¤å¼:", versionName.value); } console.log("[login-version] æç»çæ¬å·:", versionName.value); }); } else { console.log("[login-version] APP-PLUS ç¯å¢ä¸ç¼ºå° getPropertyï¼ä½¿ç¨é»è®¤å¼:", versionName.value); console.log("[login-version] æç»çæ¬å·:", versionName.value); } // #endif } catch (e) { // è·å失败æ¶ä½¿ç¨é»è®¤å¼ console.log("[login-version] APP-PLUS è·åçæ¬å¤±è´¥:", e); console.log("[login-version] æç»çæ¬å·:", versionName.value); } // #endif console.log("[login-version] æç»çæ¬å·:", versionName.value); loadPassword(); getUserLoginFacotryList(); src/pages/message.vue
@@ -60,6 +60,8 @@ <text class="loading-more-text">å è½½æ´å¤...</text> </view> </scroll-view> <DownloadProgressMask /> </view> </template> @@ -68,6 +70,7 @@ import { onShow } from "@dcloudio/uni-app"; import { listNotice, confirmMessage, getNoticeCount } from "@/api/login.js"; import useUserStore from "@/store/modules/user"; import DownloadProgressMask from "@/components/DownloadProgressMask.vue"; // æ ç¾é¡µæ°æ® const tabList = [ src/pages/mine.vue
@@ -73,6 +73,12 @@ <view class="card-illu faq"></view> </view> </view> --> <view class="version-wrap"> <text class="version-text">çæ¬å·ï¼{{ version }}</text> </view> <DownloadProgressMask /> </view> </template> @@ -81,6 +87,7 @@ import config from '@/config.js' import { getUserProfile } from "@/api/system/user"; import useUserStore from '@/store/modules/user' import DownloadProgressMask from "@/components/DownloadProgressMask.vue"; const userStore = useUserStore() const name = userStore.name; const roleName = userStore.roleName; @@ -169,6 +176,19 @@ /* #endif */ } /* çæ¬å· */ .version-wrap { width: 100%; text-align: center; margin-top: 18px; padding-bottom: 14px; } .version-text { font-size: 12px; color: #999; } /* é¡¶é¨ä¸ªäººä¿¡æ¯å¡ */ .profile-card { display: flex; src/pages/works.vue
@@ -264,6 +264,8 @@ </up-grid> </view> </view> <DownloadProgressMask /> </view> </template> @@ -273,6 +275,7 @@ import { userLoginFacotryList } from "@/api/login"; import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting"; import { createVersionUpgradeChecker } from "@/utils/versionUpgrade"; import DownloadProgressMask from "@/components/DownloadProgressMask.vue"; import modal from "@/plugins/modal"; import useUserStore from "@/store/modules/user"; src/utils/versionUpgrade.js
@@ -1,5 +1,6 @@ import config from "@/config"; import { getAllVersion } from "@/api/viewIndex"; import bus from "@/plugins/bus"; function compareVersion(v1, v2) { const s1 = String(v1 || "").replace(/[^\d.]/g, "").split(".").map((n) => Number(n) || 0); @@ -23,7 +24,7 @@ return `${size}B`; } function getCurrentVersion(logPrefix) { async function getCurrentVersion(logPrefix) { let currentVersion = config?.appInfo?.version || "1.0.0"; console.log(`${logPrefix} å¼å§è·åå½åçæ¬ï¼é»è®¤å¼:`, currentVersion); // #ifdef MP-WEIXIN @@ -40,12 +41,23 @@ // #endif // #ifdef APP-PLUS try { // APP-PLUS ä¸ï¼plus.runtime.version 䏿¯ä¸å¡çæ¬å·ï¼ç»å¸¸æ¯è¿è¡æ¶/SDKçæ¬ï¼ï¼ // è¿éæ¹ç¨ getProperty åç³»ç»å±é¢ç app versionã // @ts-ignore if (plus?.runtime?.version) { if (plus?.runtime?.getProperty) { // @ts-ignore currentVersion = plus.runtime.version; const appid = plus.runtime.appid; const appInfo = await new Promise((resolve) => { // @ts-ignore plus.runtime.getProperty(appid, (info) => resolve(info || {})); }); const v = appInfo?.version || appInfo?.versionName || appInfo?.appVersion || ""; if (v) { currentVersion = String(v); console.log(`${logPrefix} å½åç¯å¢=APP-PLUSï¼çæ¬=`, currentVersion); return currentVersion; } console.log(`${logPrefix} APP-PLUS è·åå°ççæ¬åæ®µä¸ºç©ºï¼å°ä½¿ç¨é ç½®çæ¬:`, currentVersion); } } catch (e) { console.log(`${logPrefix} APP-PLUS è·åçæ¬å¤±è´¥:`, e); @@ -83,20 +95,46 @@ // #endif } function downloadVersionPackage(url, logPrefix) { console.log(`${logPrefix} å¼å§ä¸è½½æ´æ°å :`, url); uni.showLoading({ title: "æ´æ°å ä¸è½½ä¸..." }); uni.downloadFile({ url, function buildFullDownloadUrl(rawUrl) { const u = String(rawUrl || "").trim(); if (!u) return ""; // å·²ç»æ¯ç»å¯¹å°åï¼ç´æ¥è¿å if (/^https?:\/\//i.test(u)) return u; const base = String(config?.fileUrl || config?.baseUrl || "").replace(/\/+$/, ""); const path = u.startsWith("/") ? u : `/${u}`; return `${base}${path}`; } function emitDownloadProgress(payload, logPrefix) { try { bus.$emit("versionUpgrade:downloadProgress", payload); } catch (e) { console.log(`${logPrefix} downloadProgress äºä»¶æ´¾å失败:`, e); } } function downloadVersionPackage(url, logPrefix, fileSize) { const fullUrl = buildFullDownloadUrl(url); console.log(`${logPrefix} å¼å§ä¸è½½æ´æ°å :`, { rawUrl: url, fullUrl }); if (!fullUrl) { uni.showToast({ title: "æ´æ°éä»¶å°åæ æ", icon: "none" }); return; } const totalSize = Number(fileSize); const hasTotalSize = Number.isFinite(totalSize) && totalSize > 0; console.log(`${logPrefix} ä¸è½½å¤§å°ä¿¡æ¯:`, { fileSize, totalSize, hasTotalSize }); emitDownloadProgress({ show: true, progress: 0, title: "æ´æ°å ä¸è½½ä¸..." }, logPrefix); const task = uni.downloadFile({ url: fullUrl, success: (res) => { console.log(`${logPrefix} ä¸è½½ç»æ:`, res); uni.hideLoading(); emitDownloadProgress({ show: false }, logPrefix); if (res.statusCode !== 200 || !res.tempFilePath) { console.log(`${logPrefix} ä¸è½½å¤±è´¥ï¼ç¶æç æä¸´æ¶è·¯å¾å¼å¸¸`); uni.showToast({ title: "ä¸è½½å¤±è´¥ï¼è¯·ç¨åéè¯", icon: "none" }); return; } const lowerUrl = String(url || "").toLowerCase(); const lowerUrl = String(fullUrl || "").toLowerCase(); const isInstallPkg = lowerUrl.endsWith(".wgt") || lowerUrl.endsWith(".wgtu") || lowerUrl.endsWith(".apk"); console.log(`${logPrefix} æä»¶ç±»å夿:`, { lowerUrl, isInstallPkg }); if (isInstallPkg) { @@ -114,10 +152,31 @@ }, fail: (err) => { console.log(`${logPrefix} ä¸è½½è¯·æ±å¤±è´¥:`, err); uni.hideLoading(); emitDownloadProgress({ show: false }, logPrefix); uni.showToast({ title: "ä¸è½½å¤±è´¥ï¼è¯·æ£æ¥ç½ç»", icon: "none" }); }, }); // ä¸è½½è¿åº¦ï¼é¨å端ï¼APP/å°ç¨åºï¼æ¯æ onProgressUpdate try { if (task && typeof task.onProgressUpdate === "function") { task.onProgressUpdate((p) => { const downloadedSize = Number(p?.totalBytesWritten ?? p?.writtenBytes ?? p?.downloadedSize); const expectedSize = Number(p?.totalBytesExpectedToWrite ?? p?.totalBytesExpected ?? p?.totalSize); const denom = hasTotalSize ? totalSize : (Number.isFinite(expectedSize) && expectedSize > 0 ? expectedSize : 0); let progress = Number(p?.progress); if (!(Number.isFinite(progress) && progress >= 0 && progress <= 100) && denom > 0 && Number.isFinite(downloadedSize) && downloadedSize >= 0) { progress = (downloadedSize / denom) * 100; } if (!Number.isFinite(progress)) return; emitDownloadProgress({ show: true, progress, title: "æ´æ°å ä¸è½½ä¸..." }, logPrefix); }); } } catch (e) { console.log(`${logPrefix} onProgressUpdate ç»å®å¤±è´¥:`, e); } } async function checkAppVersionUpgrade(logPrefix, currentVersion) { @@ -170,7 +229,7 @@ return; } const firstFile = Array.isArray(first?.commonFileList) ? first.commonFileList[0] : null; const downloadUrl = firstFile?.url || ""; const downloadUrl = firstFile?.url || firstFile?.downloadUrl || ""; const fileSizeText = formatFileSize(firstFile?.fileSize); console.log(`${logPrefix} æ´æ°éä»¶ä¿¡æ¯:`, { downloadUrl, @@ -191,7 +250,7 @@ uni.showToast({ title: "æªæ¾å°æ´æ°éä»¶å°å", icon: "none" }); return; } downloadVersionPackage(downloadUrl, logPrefix); downloadVersionPackage(downloadUrl, logPrefix, firstFile?.fileSize); }, }); } catch (e) { @@ -204,7 +263,7 @@ const logPrefix = options.logPrefix || "[version]"; let lastVersionCheckAt = 0; const triggerVersionCheck = (from = "unknown") => { const triggerVersionCheck = async (from = "unknown") => { const now = Date.now(); if (now - lastVersionCheckAt < throttleMs) { console.log(`${logPrefix} è·³è¿é夿£æ¥ï¼æ¥æº=${from}`); @@ -212,8 +271,8 @@ } lastVersionCheckAt = now; console.log(`${logPrefix} 触åçæ¬æ£æ¥ï¼æ¥æº=${from}`); const currentVersion = getCurrentVersion(logPrefix); checkAppVersionUpgrade(logPrefix, currentVersion); const currentVersion = await getCurrentVersion(logPrefix); await checkAppVersionUpgrade(logPrefix, currentVersion); }; return { triggerVersionCheck };