Files
track/track-uniapp/src/App.vue
duxingchen d32a3dce49 chore: UniApp OTA静默更新 + 项目分析报告
1. UniApp OTA更新优化
   - 移除进度条和下载中Toast(静默后台下载)
   - 安装成功后3秒自动重启,无用户感知
   - 失败时仅console.error,不弹窗打扰用户

2. 项目分析报告
   - 新增PROJECT_ANALYSIS_REPORT.md
   - 涵盖技术栈、数据模型、核心业务流程、潜在痛点和架构建议
2026-08-12 12:04:51 +08:00

181 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script>
import { getNotifications } from "./api/notification";
export default {
onLaunch() {
console.log("生产流转 T1.0.2 启动");
// 🚦 路由守卫:首页已是 scan未登录才跳登录页零闪烁
const token = uni.getStorageSync("access_token") || uni.getStorageSync("refresh_token");
const user = uni.getStorageSync("user");
if (!token || !user) {
uni.reLaunch({ url: "/pages/login/login" });
}
// 已登录 → 原地渲染 scan 页,不需任何跳转
// 🚀 OTA 热更新检测(仅 App 端生效)
// #ifdef APP-PLUS
this.checkUpdate();
// #endif
},
onShow() {
console.log("App 显示");
this.updateTabBarBadge();
// 🚀 每次回到前台也检查更新,用户无需杀后台就能感知新版本
// #ifdef APP-PLUS
this.checkUpdate();
// #endif
},
onHide() {
console.log("App 隐藏");
},
methods: {
// ==========================================================
// OTA 热更新雷达 — 版本检测 + WGT 下载 + 静默安装
// ==========================================================
checkUpdate() {
// 🚀 节流5分钟内不重复检查避免 onShow 频繁触发弹窗骚扰
const now = Date.now();
if (this._lastUpdateCheck && now - this._lastUpdateCheck < 5 * 60 * 1000) {
console.log("[OTA] 距上次检查不足5分钟跳过");
return;
}
this._lastUpdateCheck = now;
// 🔧 appWgtVersion 跟随 WGT 更新,解析算法: major*100 + lastNum
// "T1.0.1"→101, "T1.0.10"→110, "T1.0.99"→199
const sysInfo = uni.getSystemInfoSync();
const wgtVer = sysInfo.appWgtVersion || sysInfo.appVersion || "0";
const currentVersionCode = this.parseVersionCode(wgtVer);
const baseUrl = uni.getStorageSync("env_base_url") || "http://track_back.iris-rs.cn/api/v1";
console.log("[OTA] 本地版本:", wgtVer, "→ 数字:", currentVersionCode);
uni.request({
url: `${baseUrl}/app/check-update`,
method: "GET",
timeout: 8000,
success: (res) => {
if (res.statusCode !== 200) return;
const data = res.data;
if (!data || !data.wgt_url) {
console.log("[OTA] 服务端无可用更新包");
return;
}
const serverVersionCode = data.version_code || 0;
console.log("[OTA] 服务端版本:", data.version, "| 数字版本:", serverVersionCode);
// 客户端自行对比:服务端 > 本地 = 需要更新
if (serverVersionCode <= currentVersionCode) {
console.log("[OTA] 已是最新版本,无需更新");
return;
}
console.log("[OTA] 发现新版本:", data.version);
this.downloadAndInstall(data.wgt_url, data.version, data.description);
},
fail: () => {
console.log("[OTA] 版本检测网络失败,跳过");
},
});
},
/** 版本号→数字: "T1.0.10" → 1*100+10 = 110 */
parseVersionCode(v) {
if (!v) return 0;
const nums = v.match(/\d+/g);
if (!nums || nums.length < 2) return 0;
return parseInt(nums[0], 10) * 100 + parseInt(nums[nums.length - 1], 10);
},
downloadAndInstall(wgtUrl, newVersion, description) {
if (!wgtUrl) {
console.log("[OTA] 无 WGT 下载地址");
return;
}
const content = description
? `发现新版本 ${newVersion}\n\n${description}\n\n是否立即更新`
: `发现新版本 ${newVersion},是否立即更新?`;
uni.showModal({
title: "版本更新",
content,
confirmText: "立即更新",
cancelText: "稍后再说",
success: (modalRes) => {
if (!modalRes.confirm) return;
// 🚀 静默更新:无进度条、无 toast、不监听 onProgressUpdate
uni.downloadFile({
url: wgtUrl,
success: (downloadRes) => {
if (downloadRes.statusCode !== 200) {
console.error("[OTA] 下载失败, statusCode:", downloadRes.statusCode);
return;
}
plus.runtime.install(
downloadRes.tempFilePath,
{ force: true },
() => {
console.log("[OTA] 安装成功3秒后自动重启");
setTimeout(() => {
plus.runtime.restart();
}, 3000);
},
(err) => {
console.error("[OTA] 安装失败:", err.message);
}
);
},
fail: (err) => {
console.error("[OTA] 下载失败:", err.errMsg);
},
});
},
});
},
// ==========================================================
// TabBar 消息红点
// ==========================================================
async updateTabBarBadge() {
try {
let user = uni.getStorageSync("user");
if (typeof user === "string" && user) {
try { user = JSON.parse(user); } catch (e) { user = null; }
}
const userId = user?.username || user?.id || "";
if (!userId) return;
const res = await getNotifications(userId, 0, 1);
const unreadCount = res.unread_count || 0;
if (unreadCount > 0) {
uni.setTabBarBadge({
index: 2,
text: unreadCount > 99 ? "99+" : String(unreadCount),
});
} else {
uni.removeTabBarBadge({ index: 2 });
}
} catch {
// 静默失败
}
},
},
};
</script>
<style>
page {
background-color: #f3f4f6;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 14px;
color: #1f2937;
}
</style>