From c4ea08aedbcb4f43467f7ff84d6751305af7e39b Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期一, 27 四月 2026 21:32:03 +0800
Subject: [PATCH] fix:分享页自动打开APP修复

---
 tcm-training-admin-backend/src/main/resources/static/app-download/index.html |  107 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/tcm-training-admin-backend/src/main/resources/static/app-download/index.html b/tcm-training-admin-backend/src/main/resources/static/app-download/index.html
index 0d73a94..63dab49 100644
--- a/tcm-training-admin-backend/src/main/resources/static/app-download/index.html
+++ b/tcm-training-admin-backend/src/main/resources/static/app-download/index.html
@@ -267,6 +267,8 @@
         bindTicketLoading: false,
         openAppUrl: '',
         autoOpenTimer: 0,
+        resumeWatchTimer: 0,
+        openConfirmTimer: 0,
         openingApp: false,
         pendingResumeOpen: false
     }
@@ -274,6 +276,9 @@
     const PENDING_OPEN_STORAGE_KEY = 'appInvitePendingOpen'
     const AUTO_DOWNLOAD_DELAY_MS = 1600
     const RESUME_AUTO_OPEN_DELAY_MS = 500
+    const OPEN_CONFIRM_DELAY_MS = 1200
+    const RESUME_WATCH_INTERVAL_MS = 1200
+    const RESUME_WATCH_DURATION_MS = 15000
 
     /**
      * 页面初始化。
@@ -378,11 +383,13 @@
         if (!openAppUrl) {
             return
         }
+        const pendingOpen = readPendingOpen()
+        const shouldOnlyOpenApp = !fromResume && pendingOpen && pendingOpen.inviteCode === state.inviteCode && pendingOpen.resumeAttempted
         persistPendingOpen()
         tryOpenApp(openAppUrl)
-        if (fromResume) {
-            clearPendingOpen()
+        if (fromResume || shouldOnlyOpenApp) {
             showStatus('正在尝试打开 APP,如未打开请点击按钮重试')
+            scheduleOpenFallbackConfirm()
             return
         }
         scheduleDownloadFallback()
@@ -459,6 +466,10 @@
             document.getElementById('flowTip').textContent = '安装完成后返回本页,页面会自动打开 APP 继续注册。'
             document.getElementById('primaryActionBtn').textContent = '安装完成后自动打开中...'
             showStatus('未检测到 APP,正在为您下载对应安装包')
+            persistPendingOpen({
+                downloadStartedAt: Date.now(),
+                resumeAttempted: false
+            })
             window.location.href = downloadUrl
         }, AUTO_DOWNLOAD_DELAY_MS)
     }
@@ -495,13 +506,14 @@
     /**
      * 记录安装后返回页面需要继续打开 APP。
      */
-    function persistPendingOpen() {
+    function persistPendingOpen(extraData) {
         try {
-            window.localStorage.setItem(PENDING_OPEN_STORAGE_KEY, JSON.stringify({
+            const currentValue = readPendingOpen() || {}
+            window.localStorage.setItem(PENDING_OPEN_STORAGE_KEY, JSON.stringify(Object.assign({}, currentValue, {
                 inviteCode: state.inviteCode,
                 openAppUrl: state.openAppUrl,
                 createdAt: Date.now()
-            }))
+            }, extraData || {})))
         } catch (error) {
         }
     }
@@ -514,12 +526,19 @@
         if (!pendingOpen || pendingOpen.inviteCode !== state.inviteCode || state.pendingResumeOpen) {
             return
         }
+        if (pendingOpen.resumeAttempted) {
+            renderInstalledOpenFallback()
+            return
+        }
         state.pendingResumeOpen = true
         if (pendingOpen.openAppUrl) {
             state.openAppUrl = pendingOpen.openAppUrl
         }
         window.setTimeout(function () {
             if (!document.hidden) {
+                persistPendingOpen({
+                    resumeAttempted: true
+                })
                 void handlePrimaryAction(true)
             }
             state.pendingResumeOpen = false
@@ -532,12 +551,84 @@
     function bindResumeAutoOpenListeners() {
         window.addEventListener('pageshow', function () {
             scheduleResumeAutoOpen()
+            startResumeWatch()
+        })
+        window.addEventListener('focus', function () {
+            scheduleResumeAutoOpen()
+            startResumeWatch()
         })
         document.addEventListener('visibilitychange', function () {
             if (!document.hidden && !state.openingApp) {
                 scheduleResumeAutoOpen()
+                startResumeWatch()
             }
         })
+    }
+
+    /**
+     * 在安卓安装器返回浏览器后短时间轮询补偿事件丢失。
+     */
+    function startResumeWatch() {
+        const pendingOpen = readPendingOpen()
+        if (!pendingOpen || pendingOpen.inviteCode !== state.inviteCode || state.resumeWatchTimer) {
+            return
+        }
+        const watchStartedAt = Date.now()
+        state.resumeWatchTimer = window.setInterval(function () {
+            if (Date.now() - watchStartedAt > RESUME_WATCH_DURATION_MS) {
+                clearResumeWatch()
+                return
+            }
+            if (!document.hidden && !state.openingApp) {
+                scheduleResumeAutoOpen()
+            }
+        }, RESUME_WATCH_INTERVAL_MS)
+    }
+
+    /**
+     * 清理安卓返回检测轮询。
+     */
+    function clearResumeWatch() {
+        if (state.resumeWatchTimer) {
+            window.clearInterval(state.resumeWatchTimer)
+            state.resumeWatchTimer = 0
+        }
+    }
+
+    /**
+     * 自动拉起失败后保留用户点击兜底入口。
+     */
+    function scheduleOpenFallbackConfirm() {
+        clearOpenConfirmTimer()
+        state.openConfirmTimer = window.setTimeout(function () {
+            if (document.hidden) {
+                clearPendingOpen()
+                clearResumeWatch()
+                return
+            }
+            document.getElementById('flowTip').textContent = '若未自动打开,请点击下方按钮继续注册。'
+            document.getElementById('primaryActionBtn').textContent = '已安装,点此打开 APP'
+            showStatus('若未自动打开 APP,请点击按钮继续注册')
+        }, OPEN_CONFIRM_DELAY_MS)
+    }
+
+    /**
+     * 展示已安装后的手动打开兜底按钮态。
+     */
+    function renderInstalledOpenFallback() {
+        document.getElementById('flowTip').textContent = '安装完成后,请点击下方按钮打开 APP 继续注册。'
+        document.getElementById('primaryActionBtn').textContent = '已安装,点此打开 APP'
+        showStatus('若未自动打开 APP,请点击按钮继续注册')
+    }
+
+    /**
+     * 清理自动打开确认计时器。
+     */
+    function clearOpenConfirmTimer() {
+        if (state.openConfirmTimer) {
+            window.clearTimeout(state.openConfirmTimer)
+            state.openConfirmTimer = 0
+        }
     }
 
     /**
@@ -568,6 +659,7 @@
             window.localStorage.removeItem(PENDING_OPEN_STORAGE_KEY)
         } catch (error) {
         }
+        clearResumeWatch()
     }
 
     /**
@@ -586,6 +678,11 @@
     function updateButtonState() {
         const primaryActionBtn = document.getElementById('primaryActionBtn')
         primaryActionBtn.disabled = state.bindTicketLoading || (!state.androidDownloadUrl && !state.iosDownloadUrl)
+        const pendingOpen = readPendingOpen()
+        if (pendingOpen && pendingOpen.inviteCode === state.inviteCode && pendingOpen.resumeAttempted) {
+            primaryActionBtn.textContent = '已安装,点此打开 APP'
+            return
+        }
         primaryActionBtn.textContent = state.bindTicketLoading ? '正在准备注册信息...' : '打开 APP 继续注册'
     }
 

--
Gitblit v1.7.1