diff --git a/Appbuild/pages/index/index.vue b/Appbuild/pages/index/index.vue index 6be33682..2802f6bc 100644 --- a/Appbuild/pages/index/index.vue +++ b/Appbuild/pages/index/index.vue @@ -44,7 +44,11 @@ export default { backButtonCount: 0, backButtonTimer: null, canExit: false, - lastBackTime: 0 + lastBackTime: 0, + // 返回键状态管理 + iframeCanGoBack: false, + backTimeoutId: null, + isProcessingBack: false } }, onLoad() { @@ -231,6 +235,10 @@ export default { console.log('UniApp桥接: 处理返回键', action); switch(action) { + case 'tryBack': + // 尝试iframe内部返回 + this.tryIframeBack(); + break; case 'showExitConfirm': // 在 web-view 内显示退出确认 if (confirm('确定要退出应用吗?')) { @@ -244,6 +252,35 @@ export default { } }, + // 尝试iframe内部返回 + tryIframeBack: function() { + console.log('UniApp桥接: 尝试iframe内部返回'); + + try { + // 检查是否可以返回 + if (window.history && window.history.length > 1) { + console.log('iframe可以返回,执行返回操作'); + window.history.back(); + + // 通知UniApp返回成功 + this.postMessage('backSuccess', { canGoBack: true }); + } else { + console.log('iframe无法返回,通知UniApp'); + this.postMessage('backFailed', { + canGoBack: false, + reason: 'no_history' + }); + } + } catch (error) { + console.error('iframe返回操作失败:', error); + this.postMessage('backFailed', { + canGoBack: false, + reason: 'error', + error: error.message + }); + } + }, + // 监听返回键事件 listenBackButton: function() { // 监听浏览器的后退事件 @@ -259,6 +296,38 @@ export default { this.postMessage('backButton', { action: 'keydown' }); } }); + + // 监听页面可见性变化 + document.addEventListener('visibilitychange', (event) => { + console.log('UniApp桥接: 页面可见性变化', document.hidden); + if (!document.hidden) { + // 页面重新可见时,检查是否可以返回 + this.checkBackStatus(); + } + }); + + // 监听页面加载完成 + window.addEventListener('load', (event) => { + console.log('UniApp桥接: 页面加载完成'); + this.checkBackStatus(); + }); + }, + + // 检查返回状态 + checkBackStatus: function() { + try { + const canGoBack = window.history && window.history.length > 1; + console.log('UniApp桥接: 检查返回状态, canGoBack:', canGoBack); + + // 通知UniApp当前返回状态 + this.postMessage('backStatus', { + canGoBack: canGoBack, + historyLength: window.history ? window.history.length : 0, + currentUrl: window.location.href + }); + } catch (error) { + console.error('UniApp桥接: 检查返回状态失败:', error); + } } }; @@ -455,6 +524,18 @@ export default { console.log('UniApp: 处理返回键消息'); this.handleBackButtonMessage(data); break; + case 'backSuccess': + console.log('UniApp: 处理iframe返回成功消息'); + this.handleBackSuccess(data); + break; + case 'backFailed': + console.log('UniApp: 处理iframe返回失败消息'); + this.handleBackFailed(data); + break; + case 'backStatus': + console.log('UniApp: 处理iframe返回状态消息'); + this.handleBackStatus(data); + break; case 'exitApp': console.log('UniApp: 处理退出应用消息'); this.handleExitApp(); @@ -761,7 +842,7 @@ export default { const now = Date.now(); const timeDiff = now - this.lastBackTime; - console.log('处理返回键事件, 时间差:', timeDiff, 'ms'); + console.log('处理返回键事件, 时间差:', timeDiff, 'ms, iframeCanGoBack:', this.iframeCanGoBack); // 重置计数器 if (timeDiff > 2000) { @@ -771,9 +852,21 @@ export default { this.backButtonCount++; this.lastBackTime = now; + // 如果正在处理返回,忽略新的返回键 + if (this.isProcessingBack) { + console.log('正在处理返回,忽略新的返回键'); + return; + } + // 第一次按返回键 if (this.backButtonCount === 1) { - this.showExitConfirm(); + // 如果iframe可以返回,先尝试iframe返回 + if (this.iframeCanGoBack) { + this.tryIframeBack(); + } else { + // 如果iframe不能返回,直接显示退出确认 + this.showExitConfirm(); + } } // 第二次按返回键,直接退出 else if (this.backButtonCount >= 2) { @@ -781,6 +874,63 @@ export default { } }, + // 尝试iframe内部返回 + tryIframeBack() { + console.log('尝试iframe内部返回'); + + // 设置处理状态 + this.isProcessingBack = true; + + // 清除之前的超时 + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + } + + // 方法1: 通过桥接发送返回消息到iframe + this.sendBackButtonMessage('tryBack'); + + // 方法2: 直接执行JavaScript尝试返回 + this.evalJS(` + try { + // 检查是否可以返回 + if (window.history && window.history.length > 1) { + console.log('iframe可以返回,执行返回操作'); + window.history.back(); + + // 通知UniApp返回成功 + window.parent.postMessage({ + type: 'backSuccess', + data: { canGoBack: true }, + timestamp: Date.now() + }, '*'); + } else { + console.log('iframe无法返回,通知UniApp'); + window.parent.postMessage({ + type: 'backFailed', + data: { canGoBack: false, reason: 'no_history' }, + timestamp: Date.now() + }, '*'); + } + } catch (error) { + console.error('iframe返回操作失败:', error); + window.parent.postMessage({ + type: 'backFailed', + data: { canGoBack: false, reason: 'error', error: error.message }, + timestamp: Date.now() + }, '*'); + } + `); + + // 设置超时,如果iframe没有响应,则显示退出确认 + this.backTimeoutId = setTimeout(() => { + if (this.backButtonCount === 1 && this.isProcessingBack) { + console.log('iframe返回超时,显示退出确认'); + this.isProcessingBack = false; + this.showExitConfirm(); + } + }, 1500); // 1.5秒超时 + }, + // 显示退出确认 showExitConfirm() { console.log('显示退出确认'); @@ -864,6 +1014,46 @@ export default { // #endif }, + // 处理iframe返回成功消息 + handleBackSuccess(data) { + console.log('处理iframe返回成功消息:', data); + this.isProcessingBack = false; + this.iframeCanGoBack = true; + this.backButtonCount = 0; // 重置返回键计数 + this.lastBackTime = 0; // 重置最后按下时间 + + // 清除超时 + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } + }, + + // 处理iframe返回失败消息 + handleBackFailed(data) { + console.log('处理iframe返回失败消息:', data); + this.isProcessingBack = false; + this.iframeCanGoBack = false; + this.backButtonCount = 0; // 重置返回键计数 + this.lastBackTime = 0; // 重置最后按下时间 + + // 清除超时 + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } + + // 显示退出确认 + this.showExitConfirm(); + }, + + // 处理iframe返回状态消息 + handleBackStatus(data) { + console.log('处理iframe返回状态消息:', data); + this.iframeCanGoBack = data.data.canGoBack; + console.log('更新iframe返回状态:', this.iframeCanGoBack); + }, + // 恢复返回键监听 resumeBackButtonListener() { console.log('恢复返回键监听'); @@ -905,6 +1095,10 @@ export default { if (this.loadingTimer) { clearTimeout(this.loadingTimer); } + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } this.removeBackButtonListener(); } } diff --git a/Appbuild/unpackage/dist/dev/app-plus/app-service.js b/Appbuild/unpackage/dist/dev/app-plus/app-service.js index a4399776..91c6a5b3 100644 --- a/Appbuild/unpackage/dist/dev/app-plus/app-service.js +++ b/Appbuild/unpackage/dist/dev/app-plus/app-service.js @@ -122,7 +122,11 @@ if (uni.restoreGlobal) { backButtonCount: 0, backButtonTimer: null, canExit: false, - lastBackTime: 0 + lastBackTime: 0, + // 返回键状态管理 + iframeCanGoBack: false, + backTimeoutId: null, + isProcessingBack: false }; }, onLoad() { @@ -134,7 +138,7 @@ if (uni.restoreGlobal) { this.resumeBackButtonListener(); }, onHide() { - formatAppLog("log", "at pages/index/index.vue:59", "WebView页面隐藏"); + formatAppLog("log", "at pages/index/index.vue:63", "WebView页面隐藏"); this.pauseBackButtonListener(); }, onUnload() { @@ -144,7 +148,7 @@ if (uni.restoreGlobal) { methods: { // 获取初始URL getInitialUrl() { - formatAppLog("log", "at pages/index/index.vue:70", "获取初始URL,config:", this.config); + formatAppLog("log", "at pages/index/index.vue:74", "获取初始URL,config:", this.config); if (this.config && this.config.appConfig && this.config.appConfig.useTestPage) { return this.config.webConfig.testUrl; } @@ -152,12 +156,12 @@ if (uni.restoreGlobal) { }, // 初始化应用 initApp() { - formatAppLog("log", "at pages/index/index.vue:79", "UniApp: 开始初始化应用"); + formatAppLog("log", "at pages/index/index.vue:83", "UniApp: 开始初始化应用"); this.currentUrl = this.getInitialUrl(); - formatAppLog("log", "at pages/index/index.vue:82", "UniApp: 设置URL:", this.currentUrl); + formatAppLog("log", "at pages/index/index.vue:86", "UniApp: 设置URL:", this.currentUrl); this.setupLoadingTimeout(); this.initMessageHandler(); - formatAppLog("log", "at pages/index/index.vue:88", "UniApp: 立即注入桥接代码"); + formatAppLog("log", "at pages/index/index.vue:92", "UniApp: 立即注入桥接代码"); this.injectBridgeCode(); }, // 设置加载超时 @@ -166,14 +170,14 @@ if (uni.restoreGlobal) { clearTimeout(this.loadingTimer); } if (!this.config.appConfig.enableTimeout) { - formatAppLog("log", "at pages/index/index.vue:101", "超时检测已禁用"); + formatAppLog("log", "at pages/index/index.vue:105", "超时检测已禁用"); return; } if (this.config.appConfig.loadingTimeout > 0) { - formatAppLog("log", "at pages/index/index.vue:106", "设置加载超时:", this.config.appConfig.loadingTimeout + "ms"); + formatAppLog("log", "at pages/index/index.vue:110", "设置加载超时:", this.config.appConfig.loadingTimeout + "ms"); this.loadingTimer = setTimeout(() => { if (this.loading) { - formatAppLog("warn", "at pages/index/index.vue:109", "页面加载超时,当前状态:", this.loading); + formatAppLog("warn", "at pages/index/index.vue:113", "页面加载超时,当前状态:", this.loading); this.handleTimeout(); } }, this.config.appConfig.loadingTimeout); @@ -181,7 +185,7 @@ if (uni.restoreGlobal) { }, // 处理加载超时 handleTimeout() { - formatAppLog("warn", "at pages/index/index.vue:118", "触发页面加载超时处理"); + formatAppLog("warn", "at pages/index/index.vue:122", "触发页面加载超时处理"); this.error = "页面加载超时,请检查网络连接"; this.loading = false; if (this.loadingTimer) { @@ -191,9 +195,9 @@ if (uni.restoreGlobal) { }, // 初始化消息处理器 initMessageHandler() { - formatAppLog("log", "at pages/index/index.vue:130", "UniApp: 初始化消息处理器"); + formatAppLog("log", "at pages/index/index.vue:134", "UniApp: 初始化消息处理器"); window.addEventListener("message", (event) => { - formatAppLog("log", "at pages/index/index.vue:133", "UniApp: 收到window.message事件:", event.data); + formatAppLog("log", "at pages/index/index.vue:137", "UniApp: 收到window.message事件:", event.data); this.handleIframeMessage(event); }); }, @@ -203,21 +207,21 @@ if (uni.restoreGlobal) { }, // 注入桥接代码 injectBridgeCode() { - formatAppLog("log", "at pages/index/index.vue:146", "UniApp: 开始注入桥接代码"); + formatAppLog("log", "at pages/index/index.vue:150", "UniApp: 开始注入桥接代码"); const bridgeCode = ` // UniApp WebView 桥接代码 - __f__('log','at pages/index/index.vue:150','开始注入UniApp桥接代码...'); + __f__('log','at pages/index/index.vue:154','开始注入UniApp桥接代码...'); // 检查是否已经存在桥接 if (window.uniAppBridge) { - __f__('log','at pages/index/index.vue:154','UniApp桥接已存在,跳过注入'); + __f__('log','at pages/index/index.vue:158','UniApp桥接已存在,跳过注入'); return; } window.uniAppBridge = { // 发送消息到UniApp postMessage: function(type, data) { - __f__('log','at pages/index/index.vue:161','UniApp桥接发送消息:', type, data); + __f__('log','at pages/index/index.vue:165','UniApp桥接发送消息:', type, data); window.parent.postMessage({ type: type, data: data, @@ -227,69 +231,73 @@ if (uni.restoreGlobal) { // 获取用户信息 getUserInfo: function() { - __f__('log','at pages/index/index.vue:171','UniApp桥接: 请求用户信息'); + __f__('log','at pages/index/index.vue:175','UniApp桥接: 请求用户信息'); this.postMessage('getUserInfo', {}); }, // 获取设备信息 getDeviceInfo: function() { - __f__('log','at pages/index/index.vue:177','UniApp桥接: 请求设备信息'); + __f__('log','at pages/index/index.vue:181','UniApp桥接: 请求设备信息'); this.postMessage('getDeviceInfo', {}); }, // 显示Toast showToast: function(message, duration = 2000) { - __f__('log','at pages/index/index.vue:183','UniApp桥接: 显示Toast', message, duration); + __f__('log','at pages/index/index.vue:187','UniApp桥接: 显示Toast', message, duration); this.postMessage('toast', { message, duration }); }, // 显示Alert showAlert: function(title, content) { - __f__('log','at pages/index/index.vue:189','UniApp桥接: 显示Alert', title, content); + __f__('log','at pages/index/index.vue:193','UniApp桥接: 显示Alert', title, content); this.postMessage('alert', { title, content }); }, // 显示Confirm showConfirm: function(title, content) { - __f__('log','at pages/index/index.vue:195','UniApp桥接: 显示Confirm', title, content); + __f__('log','at pages/index/index.vue:199','UniApp桥接: 显示Confirm', title, content); this.postMessage('confirm', { title, content }); }, // 分享 share: function(data) { - __f__('log','at pages/index/index.vue:201','UniApp桥接: 分享', data); + __f__('log','at pages/index/index.vue:205','UniApp桥接: 分享', data); this.postMessage('share', data); }, // 支付 payment: function(data) { - __f__('log','at pages/index/index.vue:207','UniApp桥接: 支付', data); + __f__('log','at pages/index/index.vue:211','UniApp桥接: 支付', data); this.postMessage('payment', data); }, // 页面导航 navigate: function(url) { - __f__('log','at pages/index/index.vue:213','UniApp桥接: 导航', url); + __f__('log','at pages/index/index.vue:217','UniApp桥接: 导航', url); this.postMessage('navigate', { url }); }, // 自定义消息 sendCustomMessage: function(type, data) { - __f__('log','at pages/index/index.vue:219','UniApp桥接: 自定义消息', type, data); + __f__('log','at pages/index/index.vue:223','UniApp桥接: 自定义消息', type, data); this.postMessage(type, data); }, // 页面准备就绪 notifyPageReady: function(data) { - __f__('log','at pages/index/index.vue:225','UniApp桥接: 页面准备就绪', data); + __f__('log','at pages/index/index.vue:229','UniApp桥接: 页面准备就绪', data); this.postMessage('pageReady', data); }, // 处理返回键 handleBackButton: function(action) { - __f__('log','at pages/index/index.vue:231','UniApp桥接: 处理返回键', action); + __f__('log','at pages/index/index.vue:235','UniApp桥接: 处理返回键', action); switch(action) { + case 'tryBack': + // 尝试iframe内部返回 + this.tryIframeBack(); + break; case 'showExitConfirm': // 在 web-view 内显示退出确认 if (confirm('确定要退出应用吗?')) { @@ -303,27 +311,88 @@ if (uni.restoreGlobal) { } }, + // 尝试iframe内部返回 + tryIframeBack: function() { + __f__('log','at pages/index/index.vue:257','UniApp桥接: 尝试iframe内部返回'); + + try { + // 检查是否可以返回 + if (window.history && window.history.length > 1) { + __f__('log','at pages/index/index.vue:262','iframe可以返回,执行返回操作'); + window.history.back(); + + // 通知UniApp返回成功 + this.postMessage('backSuccess', { canGoBack: true }); + } else { + __f__('log','at pages/index/index.vue:268','iframe无法返回,通知UniApp'); + this.postMessage('backFailed', { + canGoBack: false, + reason: 'no_history' + }); + } + } catch (error) { + __f__('error','at pages/index/index.vue:275','iframe返回操作失败:', error); + this.postMessage('backFailed', { + canGoBack: false, + reason: 'error', + error: error.message + }); + } + }, + // 监听返回键事件 listenBackButton: function() { // 监听浏览器的后退事件 window.addEventListener('popstate', (event) => { - __f__('log','at pages/index/index.vue:251','UniApp桥接: 检测到 popstate 事件'); + __f__('log','at pages/index/index.vue:288','UniApp桥接: 检测到 popstate 事件'); this.postMessage('backButton', { action: 'popstate' }); }); // 监听键盘事件 document.addEventListener('keydown', (event) => { if (event.key === 'Backspace' || event.keyCode === 8) { - __f__('log','at pages/index/index.vue:258','UniApp桥接: 检测到返回键'); + __f__('log','at pages/index/index.vue:295','UniApp桥接: 检测到返回键'); this.postMessage('backButton', { action: 'keydown' }); } }); + + // 监听页面可见性变化 + document.addEventListener('visibilitychange', (event) => { + __f__('log','at pages/index/index.vue:302','UniApp桥接: 页面可见性变化', document.hidden); + if (!document.hidden) { + // 页面重新可见时,检查是否可以返回 + this.checkBackStatus(); + } + }); + + // 监听页面加载完成 + window.addEventListener('load', (event) => { + __f__('log','at pages/index/index.vue:311','UniApp桥接: 页面加载完成'); + this.checkBackStatus(); + }); + }, + + // 检查返回状态 + checkBackStatus: function() { + try { + const canGoBack = window.history && window.history.length > 1; + __f__('log','at pages/index/index.vue:320','UniApp桥接: 检查返回状态, canGoBack:', canGoBack); + + // 通知UniApp当前返回状态 + this.postMessage('backStatus', { + canGoBack: canGoBack, + historyLength: window.history ? window.history.length : 0, + currentUrl: window.location.href + }); + } catch (error) { + __f__('error','at pages/index/index.vue:329','UniApp桥接: 检查返回状态失败:', error); + } } }; // 监听来自UniApp的消息 window.addEventListener('message', function(event) { - __f__('log','at pages/index/index.vue:267','UniApp桥接收到消息:', event.data); + __f__('log','at pages/index/index.vue:336','UniApp桥接收到消息:', event.data); if (event.data && event.data.type) { // 触发自定义事件 const customEvent = new CustomEvent('uniAppMessage', { @@ -333,7 +402,7 @@ if (uni.restoreGlobal) { } }); - __f__('log','at pages/index/index.vue:277','UniApp桥接代码注入成功'); + __f__('log','at pages/index/index.vue:346','UniApp桥接代码注入成功'); // 通知UniApp页面已加载完成 window.parent.postMessage({ @@ -345,47 +414,47 @@ if (uni.restoreGlobal) { // 初始化返回键监听 window.uniAppBridge.listenBackButton(); `; - formatAppLog("log", "at pages/index/index.vue:291", "UniApp: 立即注入桥接代码"); + formatAppLog("log", "at pages/index/index.vue:360", "UniApp: 立即注入桥接代码"); this.evalJS(bridgeCode); setTimeout(() => { - formatAppLog("log", "at pages/index/index.vue:296", "UniApp: 延迟500ms后再次注入"); + formatAppLog("log", "at pages/index/index.vue:365", "UniApp: 延迟500ms后再次注入"); this.evalJS(bridgeCode); }, 500); setTimeout(() => { - formatAppLog("log", "at pages/index/index.vue:302", "UniApp: 延迟1000ms后备用注入"); + formatAppLog("log", "at pages/index/index.vue:371", "UniApp: 延迟1000ms后备用注入"); this.evalJS(bridgeCode); }, 1e3); }, // 执行JavaScript代码 evalJS(code) { - formatAppLog("log", "at pages/index/index.vue:309", "UniApp: 执行JavaScript代码"); - formatAppLog("log", "at pages/index/index.vue:310", "UniApp: 当前平台:", uni.getSystemInfoSync().platform); + formatAppLog("log", "at pages/index/index.vue:378", "UniApp: 执行JavaScript代码"); + formatAppLog("log", "at pages/index/index.vue:379", "UniApp: 当前平台:", uni.getSystemInfoSync().platform); const webview = this.$refs.webview; - formatAppLog("log", "at pages/index/index.vue:313", "UniApp: webview引用:", webview); + formatAppLog("log", "at pages/index/index.vue:382", "UniApp: webview引用:", webview); if (webview && webview.evalJS) { try { webview.evalJS(code); - formatAppLog("log", "at pages/index/index.vue:320", "UniApp: JavaScript代码执行成功 (App环境)"); + formatAppLog("log", "at pages/index/index.vue:389", "UniApp: JavaScript代码执行成功 (App环境)"); } catch (error) { - formatAppLog("error", "at pages/index/index.vue:322", "UniApp: JavaScript代码执行失败:", error); + formatAppLog("error", "at pages/index/index.vue:391", "UniApp: JavaScript代码执行失败:", error); } } else { - formatAppLog("warn", "at pages/index/index.vue:325", "UniApp: webview或evalJS方法不存在 (App环境)"); + formatAppLog("warn", "at pages/index/index.vue:394", "UniApp: webview或evalJS方法不存在 (App环境)"); this.tryAlternativeInjection(code); } }, // 备用注入方案 tryAlternativeInjection(code) { - formatAppLog("log", "at pages/index/index.vue:344", "UniApp: 尝试备用注入方案"); + formatAppLog("log", "at pages/index/index.vue:413", "UniApp: 尝试备用注入方案"); try { window.postMessage({ type: "injectCode", data: { code }, timestamp: Date.now() }, "*"); - formatAppLog("log", "at pages/index/index.vue:352", "UniApp: 备用方案1执行成功"); + formatAppLog("log", "at pages/index/index.vue:421", "UniApp: 备用方案1执行成功"); } catch (error) { - formatAppLog("error", "at pages/index/index.vue:354", "UniApp: 备用方案1失败:", error); + formatAppLog("error", "at pages/index/index.vue:423", "UniApp: 备用方案1失败:", error); try { const webview = this.$refs.webview; if (webview && webview.postMessage) { @@ -393,34 +462,34 @@ if (uni.restoreGlobal) { type: "injectCode", data: { code } }); - formatAppLog("log", "at pages/index/index.vue:364", "UniApp: 备用方案2执行成功"); + formatAppLog("log", "at pages/index/index.vue:433", "UniApp: 备用方案2执行成功"); } else { - formatAppLog("error", "at pages/index/index.vue:366", "UniApp: 备用方案2失败 - webview.postMessage不存在"); + formatAppLog("error", "at pages/index/index.vue:435", "UniApp: 备用方案2失败 - webview.postMessage不存在"); } } catch (error2) { - formatAppLog("error", "at pages/index/index.vue:369", "UniApp: 备用方案2失败:", error2); + formatAppLog("error", "at pages/index/index.vue:438", "UniApp: 备用方案2失败:", error2); } } }, // 处理web-view组件的消息 handleMessage(event) { - formatAppLog("log", "at pages/index/index.vue:376", "收到web-view消息:", event.detail); + formatAppLog("log", "at pages/index/index.vue:445", "收到web-view消息:", event.detail); try { const data = event.detail.data; if (data && data.type) { this.processMessage(data); } } catch (error) { - formatAppLog("error", "at pages/index/index.vue:383", "处理消息失败:", error); + formatAppLog("error", "at pages/index/index.vue:452", "处理消息失败:", error); } }, // 处理iframe消息 handleIframeMessage(event) { - formatAppLog("log", "at pages/index/index.vue:389", "收到iframe消息:", event.data); + formatAppLog("log", "at pages/index/index.vue:458", "收到iframe消息:", event.data); try { if (event.data && event.data.type) { if (event.data.type === "pageLoaded") { - formatAppLog("log", "at pages/index/index.vue:394", "收到页面加载完成消息:", event.data.data); + formatAppLog("log", "at pages/index/index.vue:463", "收到页面加载完成消息:", event.data.data); if (this.loadingTimer) { clearTimeout(this.loadingTimer); this.loadingTimer = null; @@ -432,63 +501,75 @@ if (uni.restoreGlobal) { this.processMessage(event.data); } } catch (error) { - formatAppLog("error", "at pages/index/index.vue:409", "处理iframe消息失败:", error); + formatAppLog("error", "at pages/index/index.vue:478", "处理iframe消息失败:", error); } }, // 处理消息 processMessage(data) { - formatAppLog("log", "at pages/index/index.vue:415", "UniApp处理消息:", data.type, data); + formatAppLog("log", "at pages/index/index.vue:484", "UniApp处理消息:", data.type, data); switch (data.type) { case this.config.communication.messageTypes.GET_USER_INFO: - formatAppLog("log", "at pages/index/index.vue:419", "UniApp: 处理获取用户信息请求"); + formatAppLog("log", "at pages/index/index.vue:488", "UniApp: 处理获取用户信息请求"); this.sendUserInfo(); break; case this.config.communication.messageTypes.GET_DEVICE_INFO: - formatAppLog("log", "at pages/index/index.vue:423", "UniApp: 处理获取设备信息请求"); + formatAppLog("log", "at pages/index/index.vue:492", "UniApp: 处理获取设备信息请求"); this.sendDeviceInfo(); break; case this.config.communication.messageTypes.NAVIGATE: - formatAppLog("log", "at pages/index/index.vue:427", "UniApp: 处理导航请求"); + formatAppLog("log", "at pages/index/index.vue:496", "UniApp: 处理导航请求"); this.handleNavigation(data); break; case this.config.communication.messageTypes.SHARE: - formatAppLog("log", "at pages/index/index.vue:431", "UniApp: 处理分享请求"); + formatAppLog("log", "at pages/index/index.vue:500", "UniApp: 处理分享请求"); this.handleShare(data); break; case this.config.communication.messageTypes.PAYMENT: - formatAppLog("log", "at pages/index/index.vue:435", "UniApp: 处理支付请求"); + formatAppLog("log", "at pages/index/index.vue:504", "UniApp: 处理支付请求"); this.handlePayment(data); break; case this.config.communication.messageTypes.TOAST: - formatAppLog("log", "at pages/index/index.vue:439", "UniApp: 处理Toast请求"); + formatAppLog("log", "at pages/index/index.vue:508", "UniApp: 处理Toast请求"); this.handleToast(data); break; case this.config.communication.messageTypes.ALERT: - formatAppLog("log", "at pages/index/index.vue:443", "UniApp: 处理Alert请求"); + formatAppLog("log", "at pages/index/index.vue:512", "UniApp: 处理Alert请求"); this.handleAlert(data); break; case this.config.communication.messageTypes.CONFIRM: - formatAppLog("log", "at pages/index/index.vue:447", "UniApp: 处理Confirm请求"); + formatAppLog("log", "at pages/index/index.vue:516", "UniApp: 处理Confirm请求"); this.handleConfirm(data); break; case "pageReady": - formatAppLog("log", "at pages/index/index.vue:451", "UniApp: 处理页面准备就绪消息"); + formatAppLog("log", "at pages/index/index.vue:520", "UniApp: 处理页面准备就绪消息"); break; case "backButton": - formatAppLog("log", "at pages/index/index.vue:455", "UniApp: 处理返回键消息"); + formatAppLog("log", "at pages/index/index.vue:524", "UniApp: 处理返回键消息"); this.handleBackButtonMessage(data); break; + case "backSuccess": + formatAppLog("log", "at pages/index/index.vue:528", "UniApp: 处理iframe返回成功消息"); + this.handleBackSuccess(data); + break; + case "backFailed": + formatAppLog("log", "at pages/index/index.vue:532", "UniApp: 处理iframe返回失败消息"); + this.handleBackFailed(data); + break; + case "backStatus": + formatAppLog("log", "at pages/index/index.vue:536", "UniApp: 处理iframe返回状态消息"); + this.handleBackStatus(data); + break; case "exitApp": - formatAppLog("log", "at pages/index/index.vue:459", "UniApp: 处理退出应用消息"); + formatAppLog("log", "at pages/index/index.vue:540", "UniApp: 处理退出应用消息"); this.handleExitApp(); break; default: - formatAppLog("log", "at pages/index/index.vue:463", "UniApp: 未知消息类型:", data.type); + formatAppLog("log", "at pages/index/index.vue:544", "UniApp: 未知消息类型:", data.type); } }, // 发送用户信息到iframe sendUserInfo() { - formatAppLog("log", "at pages/index/index.vue:469", "UniApp: 发送用户信息"); + formatAppLog("log", "at pages/index/index.vue:550", "UniApp: 发送用户信息"); const userInfo = { type: "userInfo", data: this.config.userConfig.defaultUser @@ -497,7 +578,7 @@ if (uni.restoreGlobal) { }, // 发送设备信息到iframe sendDeviceInfo() { - formatAppLog("log", "at pages/index/index.vue:479", "UniApp: 发送设备信息"); + formatAppLog("log", "at pages/index/index.vue:560", "UniApp: 发送设备信息"); const systemInfo = uni.getSystemInfoSync(); const deviceInfo = { type: "deviceInfo", @@ -517,12 +598,12 @@ if (uni.restoreGlobal) { // 处理导航 handleNavigation(data) { if (data.url) { - formatAppLog("log", "at pages/index/index.vue:500", "导航到:", data.url); + formatAppLog("log", "at pages/index/index.vue:581", "导航到:", data.url); } }, // 处理分享 handleShare(data) { - formatAppLog("log", "at pages/index/index.vue:507", "UniApp: 处理分享请求", data); + formatAppLog("log", "at pages/index/index.vue:588", "UniApp: 处理分享请求", data); uni.share({ provider: "weixin", scene: "WXSceneSession", @@ -531,18 +612,18 @@ if (uni.restoreGlobal) { title: data.title || this.config.appConfig.appName, summary: data.summary || "分享内容", success: (res) => { - formatAppLog("log", "at pages/index/index.vue:516", "UniApp: 分享成功:", res); + formatAppLog("log", "at pages/index/index.vue:597", "UniApp: 分享成功:", res); this.sendToIframe("shareResult", { success: true }); }, fail: (err) => { - formatAppLog("error", "at pages/index/index.vue:520", "UniApp: 分享失败:", err); + formatAppLog("error", "at pages/index/index.vue:601", "UniApp: 分享失败:", err); this.sendToIframe("shareResult", { success: false, error: err }); } }); }, // 处理支付 handlePayment(data) { - formatAppLog("log", "at pages/index/index.vue:528", "UniApp: 处理支付请求", data); + formatAppLog("log", "at pages/index/index.vue:609", "UniApp: 处理支付请求", data); setTimeout(() => { this.sendToIframe("paymentResult", { success: true, @@ -552,7 +633,7 @@ if (uni.restoreGlobal) { }, // 处理Toast handleToast(data) { - formatAppLog("log", "at pages/index/index.vue:541", "UniApp: 处理Toast请求", data); + formatAppLog("log", "at pages/index/index.vue:622", "UniApp: 处理Toast请求", data); uni.showToast({ title: data.message, icon: "none", @@ -561,7 +642,7 @@ if (uni.restoreGlobal) { }, // 处理Alert handleAlert(data) { - formatAppLog("log", "at pages/index/index.vue:551", "UniApp: 处理Alert请求", data); + formatAppLog("log", "at pages/index/index.vue:632", "UniApp: 处理Alert请求", data); uni.showModal({ title: data.title || "提示", content: data.content, @@ -570,12 +651,12 @@ if (uni.restoreGlobal) { }, // 处理Confirm handleConfirm(data) { - formatAppLog("log", "at pages/index/index.vue:561", "UniApp: 处理Confirm请求", data); + formatAppLog("log", "at pages/index/index.vue:642", "UniApp: 处理Confirm请求", data); uni.showModal({ title: data.title || "确认", content: data.content, success: (res) => { - formatAppLog("log", "at pages/index/index.vue:566", "UniApp: Confirm结果:", res); + formatAppLog("log", "at pages/index/index.vue:647", "UniApp: Confirm结果:", res); this.sendToIframe("confirmResult", { confirmed: res.confirm }); @@ -589,10 +670,10 @@ if (uni.restoreGlobal) { }, // 处理消息队列 processMessageQueue() { - formatAppLog("log", "at pages/index/index.vue:582", "UniApp: 处理消息队列, 队列长度:", this.messageQueue.length, "加载状态:", this.loading); + formatAppLog("log", "at pages/index/index.vue:663", "UniApp: 处理消息队列, 队列长度:", this.messageQueue.length, "加载状态:", this.loading); if (this.messageQueue.length > 0 && !this.loading) { const message = this.messageQueue.shift(); - formatAppLog("log", "at pages/index/index.vue:585", "UniApp: 发送消息到iframe:", message); + formatAppLog("log", "at pages/index/index.vue:666", "UniApp: 发送消息到iframe:", message); this.evalJS(` window.postMessage(${JSON.stringify(message)}, '*'); `); @@ -613,12 +694,12 @@ if (uni.restoreGlobal) { }, // 处理加载状态 handleLoading(event) { - formatAppLog("log", "at pages/index/index.vue:609", "WebView加载状态变化:", event.detail); + formatAppLog("log", "at pages/index/index.vue:690", "WebView加载状态变化:", event.detail); const newLoadingState = event.detail.loading; - formatAppLog("log", "at pages/index/index.vue:611", "加载状态从", this.loading, "变为", newLoadingState); + formatAppLog("log", "at pages/index/index.vue:692", "加载状态从", this.loading, "变为", newLoadingState); this.loading = newLoadingState; if (!this.loading) { - formatAppLog("log", "at pages/index/index.vue:617", "页面加载完成,清除超时定时器"); + formatAppLog("log", "at pages/index/index.vue:698", "页面加载完成,清除超时定时器"); if (this.loadingTimer) { clearTimeout(this.loadingTimer); this.loadingTimer = null; @@ -626,13 +707,13 @@ if (uni.restoreGlobal) { this.injectBridgeCode(); this.processMessageQueue(); } else { - formatAppLog("log", "at pages/index/index.vue:629", "页面开始加载,设置超时检测"); + formatAppLog("log", "at pages/index/index.vue:710", "页面开始加载,设置超时检测"); this.setupLoadingTimeout(); } }, // 处理错误 handleError(event) { - formatAppLog("error", "at pages/index/index.vue:636", "WebView错误:", event.detail); + formatAppLog("error", "at pages/index/index.vue:717", "WebView错误:", event.detail); this.error = "页面加载失败,请检查网络连接"; this.loading = false; clearTimeout(this.loadingTimer); @@ -654,18 +735,18 @@ if (uni.restoreGlobal) { }, // 清除超时 clearTimeout() { - formatAppLog("log", "at pages/index/index.vue:662", "手动清除超时"); + formatAppLog("log", "at pages/index/index.vue:743", "手动清除超时"); if (this.loadingTimer) { clearTimeout(this.loadingTimer); this.loadingTimer = null; } this.error = ""; this.loading = false; - formatAppLog("log", "at pages/index/index.vue:669", "超时已清除"); + formatAppLog("log", "at pages/index/index.vue:750", "超时已清除"); }, // 动态设置web-view高度 setWebViewHeight(height) { - formatAppLog("log", "at pages/index/index.vue:674", "设置web-view高度:", height); + formatAppLog("log", "at pages/index/index.vue:755", "设置web-view高度:", height); if (this.$refs.webview) { this.$refs.webview.$el.style.height = height + "px"; this.$refs.webview.$el.className = "webview custom-height"; @@ -677,28 +758,28 @@ if (uni.restoreGlobal) { // 设置web-view为全屏 setWebViewFullscreen() { const fullHeight = uni.getSystemInfoSync().windowHeight; - formatAppLog("log", "at pages/index/index.vue:692", "设置web-view全屏,高度:", fullHeight); + formatAppLog("log", "at pages/index/index.vue:773", "设置web-view全屏,高度:", fullHeight); this.setWebViewHeight(fullHeight); }, // 设置web-view为部分高度 setWebViewPartialHeight(percentage = 0.8) { const windowHeight = uni.getSystemInfoSync().windowHeight; const partialHeight = windowHeight * percentage; - formatAppLog("log", "at pages/index/index.vue:700", "设置web-view部分高度:", partialHeight, "百分比:", percentage); + formatAppLog("log", "at pages/index/index.vue:781", "设置web-view部分高度:", partialHeight, "百分比:", percentage); this.setWebViewHeight(partialHeight); }, // 初始化返回键监听 initBackButtonListener() { - formatAppLog("log", "at pages/index/index.vue:706", "初始化返回键监听"); + formatAppLog("log", "at pages/index/index.vue:787", "初始化返回键监听"); try { uni.addInterceptor("navigateBack", { invoke(e) { - formatAppLog("log", "at pages/index/index.vue:713", "拦截到返回事件:", e); + formatAppLog("log", "at pages/index/index.vue:794", "拦截到返回事件:", e); return false; } }); } catch (error) { - formatAppLog("warn", "at pages/index/index.vue:718", "addInterceptor 失败:", error); + formatAppLog("warn", "at pages/index/index.vue:799", "addInterceptor 失败:", error); } this.setupPhysicalBackButton(); this.setupWebViewBackListener(); @@ -707,21 +788,21 @@ if (uni.restoreGlobal) { setupPhysicalBackButton() { try { plus.key.addEventListener("backbutton", (e) => { - formatAppLog("log", "at pages/index/index.vue:735", "检测到物理返回键事件:", e); + formatAppLog("log", "at pages/index/index.vue:816", "检测到物理返回键事件:", e); this.handleBackButton(); }); } catch (error) { - formatAppLog("warn", "at pages/index/index.vue:739", "物理返回键监听失败:", error); + formatAppLog("warn", "at pages/index/index.vue:820", "物理返回键监听失败:", error); } }, // 设置 web-view 内返回监听 setupWebViewBackListener() { window.addEventListener("popstate", (event) => { - formatAppLog("log", "at pages/index/index.vue:748", "检测到 popstate 事件:", event); + formatAppLog("log", "at pages/index/index.vue:829", "检测到 popstate 事件:", event); this.handleBackButton(); }); window.addEventListener("beforeunload", (event) => { - formatAppLog("log", "at pages/index/index.vue:754", "检测到 beforeunload 事件:", event); + formatAppLog("log", "at pages/index/index.vue:835", "检测到 beforeunload 事件:", event); this.handleBackButton(); }); }, @@ -729,21 +810,75 @@ if (uni.restoreGlobal) { handleBackButton() { const now = Date.now(); const timeDiff = now - this.lastBackTime; - formatAppLog("log", "at pages/index/index.vue:764", "处理返回键事件, 时间差:", timeDiff, "ms"); + formatAppLog("log", "at pages/index/index.vue:845", "处理返回键事件, 时间差:", timeDiff, "ms, iframeCanGoBack:", this.iframeCanGoBack); if (timeDiff > 2e3) { this.backButtonCount = 0; } this.backButtonCount++; this.lastBackTime = now; + if (this.isProcessingBack) { + formatAppLog("log", "at pages/index/index.vue:857", "正在处理返回,忽略新的返回键"); + return; + } if (this.backButtonCount === 1) { - this.showExitConfirm(); + if (this.iframeCanGoBack) { + this.tryIframeBack(); + } else { + this.showExitConfirm(); + } } else if (this.backButtonCount >= 2) { this.exitApp(); } }, + // 尝试iframe内部返回 + tryIframeBack() { + formatAppLog("log", "at pages/index/index.vue:879", "尝试iframe内部返回"); + this.isProcessingBack = true; + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + } + this.sendBackButtonMessage("tryBack"); + this.evalJS(` + try { + // 检查是否可以返回 + if (window.history && window.history.length > 1) { + __f__('log','at pages/index/index.vue:897','iframe可以返回,执行返回操作'); + window.history.back(); + + // 通知UniApp返回成功 + window.parent.postMessage({ + type: 'backSuccess', + data: { canGoBack: true }, + timestamp: Date.now() + }, '*'); + } else { + __f__('log','at pages/index/index.vue:907','iframe无法返回,通知UniApp'); + window.parent.postMessage({ + type: 'backFailed', + data: { canGoBack: false, reason: 'no_history' }, + timestamp: Date.now() + }, '*'); + } + } catch (error) { + __f__('error','at pages/index/index.vue:915','iframe返回操作失败:', error); + window.parent.postMessage({ + type: 'backFailed', + data: { canGoBack: false, reason: 'error', error: error.message }, + timestamp: Date.now() + }, '*'); + } + `); + this.backTimeoutId = setTimeout(() => { + if (this.backButtonCount === 1 && this.isProcessingBack) { + formatAppLog("log", "at pages/index/index.vue:927", "iframe返回超时,显示退出确认"); + this.isProcessingBack = false; + this.showExitConfirm(); + } + }, 1500); + }, // 显示退出确认 showExitConfirm() { - formatAppLog("log", "at pages/index/index.vue:786", "显示退出确认"); + formatAppLog("log", "at pages/index/index.vue:936", "显示退出确认"); uni.showModal({ title: "退出确认", content: "确定要退出应用吗?", @@ -759,11 +894,11 @@ if (uni.restoreGlobal) { }, // 退出应用 exitApp() { - formatAppLog("log", "at pages/index/index.vue:809", "退出应用"); + formatAppLog("log", "at pages/index/index.vue:959", "退出应用"); try { plus.runtime.quit(); } catch (error) { - formatAppLog("error", "at pages/index/index.vue:816", "退出应用失败:", error); + formatAppLog("error", "at pages/index/index.vue:966", "退出应用失败:", error); } this.sendBackButtonMessage("exitApp"); }, @@ -777,50 +912,81 @@ if (uni.restoreGlobal) { timestamp: Date.now() }); } catch (error) { - formatAppLog("error", "at pages/index/index.vue:835", "发送返回键消息失败:", error); + formatAppLog("error", "at pages/index/index.vue:985", "发送返回键消息失败:", error); } } }, // 处理返回键消息 handleBackButtonMessage(data) { - formatAppLog("log", "at pages/index/index.vue:842", "处理返回键消息:", data); + formatAppLog("log", "at pages/index/index.vue:992", "处理返回键消息:", data); switch (data.action) { case "popstate": case "keydown": this.handleBackButton(); break; default: - formatAppLog("log", "at pages/index/index.vue:850", "未知的返回键动作:", data.action); + formatAppLog("log", "at pages/index/index.vue:1000", "未知的返回键动作:", data.action); } }, // 处理退出应用 handleExitApp() { - formatAppLog("log", "at pages/index/index.vue:856", "处理退出应用"); + formatAppLog("log", "at pages/index/index.vue:1006", "处理退出应用"); try { plus.runtime.quit(); } catch (error) { - formatAppLog("error", "at pages/index/index.vue:862", "退出应用失败:", error); + formatAppLog("error", "at pages/index/index.vue:1012", "退出应用失败:", error); } }, + // 处理iframe返回成功消息 + handleBackSuccess(data) { + formatAppLog("log", "at pages/index/index.vue:1019", "处理iframe返回成功消息:", data); + this.isProcessingBack = false; + this.iframeCanGoBack = true; + this.backButtonCount = 0; + this.lastBackTime = 0; + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } + }, + // 处理iframe返回失败消息 + handleBackFailed(data) { + formatAppLog("log", "at pages/index/index.vue:1034", "处理iframe返回失败消息:", data); + this.isProcessingBack = false; + this.iframeCanGoBack = false; + this.backButtonCount = 0; + this.lastBackTime = 0; + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } + this.showExitConfirm(); + }, + // 处理iframe返回状态消息 + handleBackStatus(data) { + formatAppLog("log", "at pages/index/index.vue:1052", "处理iframe返回状态消息:", data); + this.iframeCanGoBack = data.data.canGoBack; + formatAppLog("log", "at pages/index/index.vue:1054", "更新iframe返回状态:", this.iframeCanGoBack); + }, // 恢复返回键监听 resumeBackButtonListener() { - formatAppLog("log", "at pages/index/index.vue:869", "恢复返回键监听"); + formatAppLog("log", "at pages/index/index.vue:1059", "恢复返回键监听"); this.backButtonCount = 0; this.lastBackTime = 0; }, // 暂停返回键监听 pauseBackButtonListener() { - formatAppLog("log", "at pages/index/index.vue:876", "暂停返回键监听"); + formatAppLog("log", "at pages/index/index.vue:1066", "暂停返回键监听"); this.backButtonCount = 0; }, // 移除返回键监听 removeBackButtonListener() { - formatAppLog("log", "at pages/index/index.vue:882", "移除返回键监听"); + formatAppLog("log", "at pages/index/index.vue:1072", "移除返回键监听"); try { plus.key.removeEventListener("backbutton"); uni.removeInterceptor("navigateBack"); } catch (error) { - formatAppLog("warn", "at pages/index/index.vue:892", "移除返回键监听失败:", error); + formatAppLog("warn", "at pages/index/index.vue:1082", "移除返回键监听失败:", error); } if (this.backButtonTimer) { clearTimeout(this.backButtonTimer); @@ -832,6 +998,10 @@ if (uni.restoreGlobal) { if (this.loadingTimer) { clearTimeout(this.loadingTimer); } + if (this.backTimeoutId) { + clearTimeout(this.backTimeoutId); + this.backTimeoutId = null; + } this.removeBackButtonListener(); } } diff --git a/nkebao/src/pages/mobile/scenarios/list/index.module.scss b/nkebao/src/pages/mobile/scenarios/list/index.module.scss index b371a294..d200fddb 100644 --- a/nkebao/src/pages/mobile/scenarios/list/index.module.scss +++ b/nkebao/src/pages/mobile/scenarios/list/index.module.scss @@ -35,9 +35,12 @@ min-height: 100vh; padding: 0 0 60px 0; } -.scene-page-content { - padding: 16px; - text-align: center; +.error { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 50px 30px; } // 错误提示 .error-notice {