Explorar el Código

✨ feat(app): 支持全页面触发应用更新

Zimo hace 4 días
padre
commit
fc4c3c984a
Se han modificado 5 ficheros con 69 adiciones y 12 borrados
  1. 1 2
      App.vue
  2. 0 3
      pages/home/index.vue
  3. 0 2
      pages/user/login.vue
  4. 6 3
      utils/hot-update.js
  5. 62 2
      utils/upgrade.js

+ 1 - 2
App.vue

@@ -80,8 +80,7 @@ export default {
 		 *
 		 * 为什么放在 App.vue 的 onLaunch:
 		 * 1. 这是整个项目真正的应用启动入口,热更新要尽量早执行,就应该接在这里。
-		 * 2. 现有项目的旧升级逻辑写在页面组件里,只会在登录页 / 首页 mounted 后才触发,
-		 *    对“启动即检查热更新”这个目标来说太晚了。
+		 * 2. APK 与 WGT 更新都由全局更新服务处理,不依赖登录页、首页或其他业务页面挂载组件。
 		 * 3. 放在这里还能保证热更新和数据库初始化、scheme 监听这类“应用级逻辑”处于同一层级,
 		 *    后续维护时更容易看清启动链路。
 		 *

+ 0 - 3
pages/home/index.vue

@@ -436,8 +436,6 @@
         </view>
       </view>
     </view>
-    <!-- 升级提示 -->
-    <upgrade />
     <uni-popup
       ref="ruiDuReportPopup"
       type="bottom"
@@ -515,7 +513,6 @@
 import { getLoginUserInfo } from "@/api/login";
 import { getUnreadMessageCount } from "@/api/message";
 import { getOvertimeTaskList } from "@/api/task";
-import Upgrade from "@/components/upgrade.vue";
 import { useDeptStore } from "@/store/modules/dept";
 import { useDeviceStore } from "@/store/modules/device";
 import { messageNavigate } from "@/utils/navigate";

+ 0 - 2
pages/user/login.vue

@@ -48,7 +48,6 @@
 
     <!-- 引用语言选择组件 -->
     <language-popup ref="languagePopupRef" />
-    <upgrade ref="upgradeRef" />
   </view>
 </template>
 
@@ -71,7 +70,6 @@ import { saveUser } from "@/utils/appDb";
 import { setUserId, setToken, setDeptId, setUserInfo } from "@/utils/auth.js";
 import { useDataDictStore } from "@/store/modules/dataDict";
 // 引入组件
-import Upgrade from "@/components/upgrade.vue";
 import LanguagePopup from "@/components/language-popup.vue";
 
 // 引入钉钉JSAPI -- 仅在H5环境下使用

+ 6 - 3
utils/hot-update.js

@@ -1,4 +1,5 @@
 import config from "@/utils/config";
+import { runAppUpgrade } from "@/utils/upgrade";
 
 /**
  * 旧版本使用过的持久化锁 key,仅用于启动时清理遗留值。
@@ -207,7 +208,7 @@ const isApkPackageUrl = (url = "") => {
 
 /**
  * 启动时先检查整包更新。只有 Android 端存在比当前原生版本更新的 APK 时,
- * 才中止 WGT 流程并通知原有整包升级组件
+ * 才中止 WGT 流程并执行全局整包更新
  */
 const requestAppUpgradeInfo = () => {
   return new Promise((resolve, reject) => {
@@ -654,9 +655,11 @@ const executeWgtHotUpdate = async () => {
             plus.runtime.version
           )
         ) {
+          currentStage = "app-upgrade";
+          const appUpgradeResult = await runAppUpgrade(appUpgradeResponse.data);
           finalResult = {
-            status: "fallback-app-check-version",
-            message: "检测到新的 APK,优先执行整包更新",
+            status: appUpgradeResult.status,
+            message: "检测到新的 APK,已进入整包更新流程",
             data: appUpgradeResponse.data,
           };
           return finalResult;

+ 62 - 2
utils/upgrade.js

@@ -17,6 +17,66 @@ const compareVersion = (a = "", b = "") => {
 
   return 0;
 };
+
+let appUpgradePromise = null;
+
+/**
+ * 全局执行 APK 整包更新。
+ *
+ * App.vue / 页面全局 onShow 都可能触发更新检查,因此这里不能依赖某个页面
+ * 是否挂载了 upgrade 组件。使用 uni 的全局提示能力后,用户停留在任意页面
+ * 都能收到更新提示;模块内 Promise 同时避免重复弹窗和重复下载。
+ */
+export const runAppUpgrade = ({
+  appVersion: name,
+  note: content = "",
+  url,
+  forceUpdate = true,
+}) => {
+  if (appUpgradePromise) return appUpgradePromise;
+
+  appUpgradePromise = new Promise((resolve, reject) => {
+    uni.showModal({
+      title: `发现新版本 V${name}`,
+      content: content || "检测到新的应用版本,是否立即更新?",
+      showCancel: !forceUpdate,
+      confirmText: "立即更新",
+      cancelText: "稍后再说",
+      success: async ({ confirm }) => {
+        if (!confirm) {
+          resolve({ status: "cancelled" });
+          return;
+        }
+
+        try {
+          uni.showLoading({
+            title: "下载更新中",
+            mask: true,
+          });
+
+          const fileName = await downloadApp(url, (percent) => {
+            uni.showLoading({
+              title: `下载中 ${percent}%`,
+              mask: true,
+            });
+          });
+
+          uni.hideLoading();
+          installApp(fileName);
+          resolve({ status: "install-triggered" });
+        } catch (error) {
+          uni.hideLoading();
+          reject(error);
+        }
+      },
+      fail: reject,
+    });
+  }).finally(() => {
+    appUpgradePromise = null;
+  });
+
+  return appUpgradePromise;
+};
 
 /**
  * @description 检查app版本是否需要升级
@@ -33,8 +93,8 @@ export const checkVersion = async ({
   url, //下载链接
   forceUpdate, //是否强制升级
 }) => {
-  const currentAppVersion = plus.runtime.version;
-  if (compareVersion(code, currentAppVersion) > 0) {
+  const currentAppVersion = plus.runtime.version;
+  if (compareVersion(code, currentAppVersion) > 0) {
     let platform = uni.getSystemInfoSync().platform; //手机平台
     if (platform === "android") {
       uni.$emit("upgrade-app", {