FEAT => 本次更新项目为:

存一半
This commit is contained in:
超级老白兔
2025-07-31 18:18:01 +08:00
parent 101676cef3
commit 02d0031079
4 changed files with 541 additions and 85 deletions

View File

@@ -38,20 +38,30 @@ export default {
loading: false,
error: '',
loadingTimer: null,
messageQueue: []
messageQueue: [],
// 返回键监听相关
backButtonListener: null,
backButtonCount: 0,
backButtonTimer: null,
canExit: false,
lastBackTime: 0
}
},
onLoad() {
this.initApp();
this.initBackButtonListener();
},
onShow() {
this.resumeMessageQueue();
this.resumeBackButtonListener();
},
onHide() {
console.log('WebView页面隐藏');
this.pauseBackButtonListener();
},
onUnload() {
this.cleanup();
this.removeBackButtonListener();
},
methods: {
@@ -214,6 +224,41 @@ export default {
notifyPageReady: function(data) {
console.log('UniApp桥接: 页面准备就绪', data);
this.postMessage('pageReady', data);
},
// 处理返回键
handleBackButton: function(action) {
console.log('UniApp桥接: 处理返回键', action);
switch(action) {
case 'showExitConfirm':
// 在 web-view 内显示退出确认
if (confirm('确定要退出应用吗?')) {
this.postMessage('exitApp', {});
}
break;
case 'exitApp':
// 通知 UniApp 退出应用
this.postMessage('exitApp', {});
break;
}
},
// 监听返回键事件
listenBackButton: function() {
// 监听浏览器的后退事件
window.addEventListener('popstate', (event) => {
console.log('UniApp桥接: 检测到 popstate 事件');
this.postMessage('backButton', { action: 'popstate' });
});
// 监听键盘事件
document.addEventListener('keydown', (event) => {
if (event.key === 'Backspace' || event.keyCode === 8) {
console.log('UniApp桥接: 检测到返回键');
this.postMessage('backButton', { action: 'keydown' });
}
});
}
};
@@ -237,6 +282,9 @@ export default {
data: { url: window.location.href },
timestamp: Date.now()
}, '*');
// 初始化返回键监听
window.uniAppBridge.listenBackButton();
`;
// 立即尝试注入
@@ -403,6 +451,14 @@ export default {
console.log('UniApp: 处理页面准备就绪消息');
// 可以在这里处理页面准备就绪的逻辑
break;
case 'backButton':
console.log('UniApp: 处理返回键消息');
this.handleBackButtonMessage(data);
break;
case 'exitApp':
console.log('UniApp: 处理退出应用消息');
this.handleExitApp();
break;
default:
console.log('UniApp: 未知消息类型:', data.type);
}
@@ -645,11 +701,211 @@ export default {
this.setWebViewHeight(partialHeight);
},
// 初始化返回键监听
initBackButtonListener() {
console.log('初始化返回键监听');
// 方法1: 使用 uni.addInterceptor 拦截返回事件
// #ifdef APP-PLUS
try {
uni.addInterceptor('navigateBack', {
invoke(e) {
console.log('拦截到返回事件:', e);
return false; // 阻止默认返回行为
}
});
} catch (error) {
console.warn('addInterceptor 失败:', error);
}
// #endif
// 方法2: 监听物理返回键
this.setupPhysicalBackButton();
// 方法3: 监听 web-view 内的返回事件
this.setupWebViewBackListener();
},
// 设置物理返回键监听
setupPhysicalBackButton() {
// #ifdef APP-PLUS
try {
// 监听安卓物理返回键
plus.key.addEventListener('backbutton', (e) => {
console.log('检测到物理返回键事件:', e);
this.handleBackButton();
});
} catch (error) {
console.warn('物理返回键监听失败:', error);
}
// #endif
},
// 设置 web-view 内返回监听
setupWebViewBackListener() {
// 监听 web-view 内的 popstate 事件
window.addEventListener('popstate', (event) => {
console.log('检测到 popstate 事件:', event);
this.handleBackButton();
});
// 监听 web-view 内的 beforeunload 事件
window.addEventListener('beforeunload', (event) => {
console.log('检测到 beforeunload 事件:', event);
this.handleBackButton();
});
},
// 处理返回键事件
handleBackButton() {
const now = Date.now();
const timeDiff = now - this.lastBackTime;
console.log('处理返回键事件, 时间差:', timeDiff, 'ms');
// 重置计数器
if (timeDiff > 2000) {
this.backButtonCount = 0;
}
this.backButtonCount++;
this.lastBackTime = now;
// 第一次按返回键
if (this.backButtonCount === 1) {
this.showExitConfirm();
}
// 第二次按返回键,直接退出
else if (this.backButtonCount >= 2) {
this.exitApp();
}
},
// 显示退出确认
showExitConfirm() {
console.log('显示退出确认');
// 方法1: 使用 uni.showModal
// #ifdef APP-PLUS
uni.showModal({
title: '退出确认',
content: '确定要退出应用吗?',
confirmText: '退出',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.exitApp();
}
}
});
// #endif
// 方法2: 通过桥接发送消息到 web-view
this.sendBackButtonMessage('showExitConfirm');
},
// 退出应用
exitApp() {
console.log('退出应用');
// 方法1: 使用 plus.runtime.quit
// #ifdef APP-PLUS
try {
plus.runtime.quit();
} catch (error) {
console.error('退出应用失败:', error);
}
// #endif
// 方法2: 通过桥接发送退出消息
this.sendBackButtonMessage('exitApp');
},
// 发送返回键消息到 web-view
sendBackButtonMessage(action) {
if (this.$refs.webview) {
try {
// 通过 postMessage 发送消息
this.$refs.webview.postMessage({
type: 'backButton',
action: action,
timestamp: Date.now()
});
} catch (error) {
console.error('发送返回键消息失败:', error);
}
}
},
// 处理返回键消息
handleBackButtonMessage(data) {
console.log('处理返回键消息:', data);
switch (data.action) {
case 'popstate':
case 'keydown':
this.handleBackButton();
break;
default:
console.log('未知的返回键动作:', data.action);
}
},
// 处理退出应用
handleExitApp() {
console.log('处理退出应用');
// #ifdef APP-PLUS
try {
plus.runtime.quit();
} catch (error) {
console.error('退出应用失败:', error);
}
// #endif
},
// 恢复返回键监听
resumeBackButtonListener() {
console.log('恢复返回键监听');
this.backButtonCount = 0;
this.lastBackTime = 0;
},
// 暂停返回键监听
pauseBackButtonListener() {
console.log('暂停返回键监听');
this.backButtonCount = 0;
},
// 移除返回键监听
removeBackButtonListener() {
console.log('移除返回键监听');
// #ifdef APP-PLUS
try {
// 移除物理返回键监听
plus.key.removeEventListener('backbutton');
// 移除拦截器
uni.removeInterceptor('navigateBack');
} catch (error) {
console.warn('移除返回键监听失败:', error);
}
// #endif
// 清除定时器
if (this.backButtonTimer) {
clearTimeout(this.backButtonTimer);
this.backButtonTimer = null;
}
},
// 清理资源
cleanup() {
if (this.loadingTimer) {
clearTimeout(this.loadingTimer);
}
this.removeBackButtonListener();
}
}
}

View File

@@ -116,25 +116,35 @@ if (uni.restoreGlobal) {
loading: false,
error: "",
loadingTimer: null,
messageQueue: []
messageQueue: [],
// 返回键监听相关
backButtonListener: null,
backButtonCount: 0,
backButtonTimer: null,
canExit: false,
lastBackTime: 0
};
},
onLoad() {
this.initApp();
this.initBackButtonListener();
},
onShow() {
this.resumeMessageQueue();
this.resumeBackButtonListener();
},
onHide() {
formatAppLog("log", "at pages/index/index.vue:51", "WebView页面隐藏");
formatAppLog("log", "at pages/index/index.vue:59", "WebView页面隐藏");
this.pauseBackButtonListener();
},
onUnload() {
this.cleanup();
this.removeBackButtonListener();
},
methods: {
// 获取初始URL
getInitialUrl() {
formatAppLog("log", "at pages/index/index.vue:60", "获取初始URLconfig:", this.config);
formatAppLog("log", "at pages/index/index.vue:70", "获取初始URLconfig:", this.config);
if (this.config && this.config.appConfig && this.config.appConfig.useTestPage) {
return this.config.webConfig.testUrl;
}
@@ -142,12 +152,12 @@ if (uni.restoreGlobal) {
},
// 初始化应用
initApp() {
formatAppLog("log", "at pages/index/index.vue:69", "UniApp: 开始初始化应用");
formatAppLog("log", "at pages/index/index.vue:79", "UniApp: 开始初始化应用");
this.currentUrl = this.getInitialUrl();
formatAppLog("log", "at pages/index/index.vue:72", "UniApp: 设置URL:", this.currentUrl);
formatAppLog("log", "at pages/index/index.vue:82", "UniApp: 设置URL:", this.currentUrl);
this.setupLoadingTimeout();
this.initMessageHandler();
formatAppLog("log", "at pages/index/index.vue:78", "UniApp: 立即注入桥接代码");
formatAppLog("log", "at pages/index/index.vue:88", "UniApp: 立即注入桥接代码");
this.injectBridgeCode();
},
// 设置加载超时
@@ -156,14 +166,14 @@ if (uni.restoreGlobal) {
clearTimeout(this.loadingTimer);
}
if (!this.config.appConfig.enableTimeout) {
formatAppLog("log", "at pages/index/index.vue:91", "超时检测已禁用");
formatAppLog("log", "at pages/index/index.vue:101", "超时检测已禁用");
return;
}
if (this.config.appConfig.loadingTimeout > 0) {
formatAppLog("log", "at pages/index/index.vue:96", "设置加载超时:", this.config.appConfig.loadingTimeout + "ms");
formatAppLog("log", "at pages/index/index.vue:106", "设置加载超时:", this.config.appConfig.loadingTimeout + "ms");
this.loadingTimer = setTimeout(() => {
if (this.loading) {
formatAppLog("warn", "at pages/index/index.vue:99", "页面加载超时,当前状态:", this.loading);
formatAppLog("warn", "at pages/index/index.vue:109", "页面加载超时,当前状态:", this.loading);
this.handleTimeout();
}
}, this.config.appConfig.loadingTimeout);
@@ -171,7 +181,7 @@ if (uni.restoreGlobal) {
},
// 处理加载超时
handleTimeout() {
formatAppLog("warn", "at pages/index/index.vue:108", "触发页面加载超时处理");
formatAppLog("warn", "at pages/index/index.vue:118", "触发页面加载超时处理");
this.error = "页面加载超时,请检查网络连接";
this.loading = false;
if (this.loadingTimer) {
@@ -181,9 +191,9 @@ if (uni.restoreGlobal) {
},
// 初始化消息处理器
initMessageHandler() {
formatAppLog("log", "at pages/index/index.vue:120", "UniApp: 初始化消息处理器");
formatAppLog("log", "at pages/index/index.vue:130", "UniApp: 初始化消息处理器");
window.addEventListener("message", (event) => {
formatAppLog("log", "at pages/index/index.vue:123", "UniApp: 收到window.message事件:", event.data);
formatAppLog("log", "at pages/index/index.vue:133", "UniApp: 收到window.message事件:", event.data);
this.handleIframeMessage(event);
});
},
@@ -193,21 +203,21 @@ if (uni.restoreGlobal) {
},
// 注入桥接代码
injectBridgeCode() {
formatAppLog("log", "at pages/index/index.vue:136", "UniApp: 开始注入桥接代码");
formatAppLog("log", "at pages/index/index.vue:146", "UniApp: 开始注入桥接代码");
const bridgeCode = `
// UniApp WebView 桥接代码
__f__('log','at pages/index/index.vue:140','开始注入UniApp桥接代码...');
__f__('log','at pages/index/index.vue:150','开始注入UniApp桥接代码...');
// 检查是否已经存在桥接
if (window.uniAppBridge) {
__f__('log','at pages/index/index.vue:144','UniApp桥接已存在跳过注入');
__f__('log','at pages/index/index.vue:154','UniApp桥接已存在跳过注入');
return;
}
window.uniAppBridge = {
// 发送消息到UniApp
postMessage: function(type, data) {
__f__('log','at pages/index/index.vue:151','UniApp桥接发送消息:', type, data);
__f__('log','at pages/index/index.vue:161','UniApp桥接发送消息:', type, data);
window.parent.postMessage({
type: type,
data: data,
@@ -217,68 +227,103 @@ if (uni.restoreGlobal) {
// 获取用户信息
getUserInfo: function() {
__f__('log','at pages/index/index.vue:161','UniApp桥接: 请求用户信息');
__f__('log','at pages/index/index.vue:171','UniApp桥接: 请求用户信息');
this.postMessage('getUserInfo', {});
},
// 获取设备信息
getDeviceInfo: function() {
__f__('log','at pages/index/index.vue:167','UniApp桥接: 请求设备信息');
__f__('log','at pages/index/index.vue:177','UniApp桥接: 请求设备信息');
this.postMessage('getDeviceInfo', {});
},
// 显示Toast
showToast: function(message, duration = 2000) {
__f__('log','at pages/index/index.vue:173','UniApp桥接: 显示Toast', message, duration);
__f__('log','at pages/index/index.vue:183','UniApp桥接: 显示Toast', message, duration);
this.postMessage('toast', { message, duration });
},
// 显示Alert
showAlert: function(title, content) {
__f__('log','at pages/index/index.vue:179','UniApp桥接: 显示Alert', title, content);
__f__('log','at pages/index/index.vue:189','UniApp桥接: 显示Alert', title, content);
this.postMessage('alert', { title, content });
},
// 显示Confirm
showConfirm: function(title, content) {
__f__('log','at pages/index/index.vue:185','UniApp桥接: 显示Confirm', title, content);
__f__('log','at pages/index/index.vue:195','UniApp桥接: 显示Confirm', title, content);
this.postMessage('confirm', { title, content });
},
// 分享
share: function(data) {
__f__('log','at pages/index/index.vue:191','UniApp桥接: 分享', data);
__f__('log','at pages/index/index.vue:201','UniApp桥接: 分享', data);
this.postMessage('share', data);
},
// 支付
payment: function(data) {
__f__('log','at pages/index/index.vue:197','UniApp桥接: 支付', data);
__f__('log','at pages/index/index.vue:207','UniApp桥接: 支付', data);
this.postMessage('payment', data);
},
// 页面导航
navigate: function(url) {
__f__('log','at pages/index/index.vue:203','UniApp桥接: 导航', url);
__f__('log','at pages/index/index.vue:213','UniApp桥接: 导航', url);
this.postMessage('navigate', { url });
},
// 自定义消息
sendCustomMessage: function(type, data) {
__f__('log','at pages/index/index.vue:209','UniApp桥接: 自定义消息', type, data);
__f__('log','at pages/index/index.vue:219','UniApp桥接: 自定义消息', type, data);
this.postMessage(type, data);
},
// 页面准备就绪
notifyPageReady: function(data) {
__f__('log','at pages/index/index.vue:215','UniApp桥接: 页面准备就绪', data);
__f__('log','at pages/index/index.vue:225','UniApp桥接: 页面准备就绪', data);
this.postMessage('pageReady', data);
},
// 处理返回键
handleBackButton: function(action) {
__f__('log','at pages/index/index.vue:231','UniApp桥接: 处理返回键', action);
switch(action) {
case 'showExitConfirm':
// 在 web-view 内显示退出确认
if (confirm('确定要退出应用吗?')) {
this.postMessage('exitApp', {});
}
break;
case 'exitApp':
// 通知 UniApp 退出应用
this.postMessage('exitApp', {});
break;
}
},
// 监听返回键事件
listenBackButton: function() {
// 监听浏览器的后退事件
window.addEventListener('popstate', (event) => {
__f__('log','at pages/index/index.vue:251','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桥接: 检测到返回键');
this.postMessage('backButton', { action: 'keydown' });
}
});
}
};
// 监听来自UniApp的消息
window.addEventListener('message', function(event) {
__f__('log','at pages/index/index.vue:222','UniApp桥接收到消息:', event.data);
__f__('log','at pages/index/index.vue:267','UniApp桥接收到消息:', event.data);
if (event.data && event.data.type) {
// 触发自定义事件
const customEvent = new CustomEvent('uniAppMessage', {
@@ -288,7 +333,7 @@ if (uni.restoreGlobal) {
}
});
__f__('log','at pages/index/index.vue:232','UniApp桥接代码注入成功');
__f__('log','at pages/index/index.vue:277','UniApp桥接代码注入成功');
// 通知UniApp页面已加载完成
window.parent.postMessage({
@@ -296,48 +341,51 @@ if (uni.restoreGlobal) {
data: { url: window.location.href },
timestamp: Date.now()
}, '*');
// 初始化返回键监听
window.uniAppBridge.listenBackButton();
`;
formatAppLog("log", "at pages/index/index.vue:243", "UniApp: 立即注入桥接代码");
formatAppLog("log", "at pages/index/index.vue:291", "UniApp: 立即注入桥接代码");
this.evalJS(bridgeCode);
setTimeout(() => {
formatAppLog("log", "at pages/index/index.vue:248", "UniApp: 延迟500ms后再次注入");
formatAppLog("log", "at pages/index/index.vue:296", "UniApp: 延迟500ms后再次注入");
this.evalJS(bridgeCode);
}, 500);
setTimeout(() => {
formatAppLog("log", "at pages/index/index.vue:254", "UniApp: 延迟1000ms后备用注入");
formatAppLog("log", "at pages/index/index.vue:302", "UniApp: 延迟1000ms后备用注入");
this.evalJS(bridgeCode);
}, 1e3);
},
// 执行JavaScript代码
evalJS(code) {
formatAppLog("log", "at pages/index/index.vue:261", "UniApp: 执行JavaScript代码");
formatAppLog("log", "at pages/index/index.vue:262", "UniApp: 当前平台:", uni.getSystemInfoSync().platform);
formatAppLog("log", "at pages/index/index.vue:309", "UniApp: 执行JavaScript代码");
formatAppLog("log", "at pages/index/index.vue:310", "UniApp: 当前平台:", uni.getSystemInfoSync().platform);
const webview = this.$refs.webview;
formatAppLog("log", "at pages/index/index.vue:265", "UniApp: webview引用:", webview);
formatAppLog("log", "at pages/index/index.vue:313", "UniApp: webview引用:", webview);
if (webview && webview.evalJS) {
try {
webview.evalJS(code);
formatAppLog("log", "at pages/index/index.vue:272", "UniApp: JavaScript代码执行成功 (App环境)");
formatAppLog("log", "at pages/index/index.vue:320", "UniApp: JavaScript代码执行成功 (App环境)");
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:274", "UniApp: JavaScript代码执行失败:", error);
formatAppLog("error", "at pages/index/index.vue:322", "UniApp: JavaScript代码执行失败:", error);
}
} else {
formatAppLog("warn", "at pages/index/index.vue:277", "UniApp: webview或evalJS方法不存在 (App环境)");
formatAppLog("warn", "at pages/index/index.vue:325", "UniApp: webview或evalJS方法不存在 (App环境)");
this.tryAlternativeInjection(code);
}
},
// 备用注入方案
tryAlternativeInjection(code) {
formatAppLog("log", "at pages/index/index.vue:296", "UniApp: 尝试备用注入方案");
formatAppLog("log", "at pages/index/index.vue:344", "UniApp: 尝试备用注入方案");
try {
window.postMessage({
type: "injectCode",
data: { code },
timestamp: Date.now()
}, "*");
formatAppLog("log", "at pages/index/index.vue:304", "UniApp: 备用方案1执行成功");
formatAppLog("log", "at pages/index/index.vue:352", "UniApp: 备用方案1执行成功");
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:306", "UniApp: 备用方案1失败:", error);
formatAppLog("error", "at pages/index/index.vue:354", "UniApp: 备用方案1失败:", error);
try {
const webview = this.$refs.webview;
if (webview && webview.postMessage) {
@@ -345,34 +393,34 @@ if (uni.restoreGlobal) {
type: "injectCode",
data: { code }
});
formatAppLog("log", "at pages/index/index.vue:316", "UniApp: 备用方案2执行成功");
formatAppLog("log", "at pages/index/index.vue:364", "UniApp: 备用方案2执行成功");
} else {
formatAppLog("error", "at pages/index/index.vue:318", "UniApp: 备用方案2失败 - webview.postMessage不存在");
formatAppLog("error", "at pages/index/index.vue:366", "UniApp: 备用方案2失败 - webview.postMessage不存在");
}
} catch (error2) {
formatAppLog("error", "at pages/index/index.vue:321", "UniApp: 备用方案2失败:", error2);
formatAppLog("error", "at pages/index/index.vue:369", "UniApp: 备用方案2失败:", error2);
}
}
},
// 处理web-view组件的消息
handleMessage(event) {
formatAppLog("log", "at pages/index/index.vue:328", "收到web-view消息:", event.detail);
formatAppLog("log", "at pages/index/index.vue:376", "收到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:335", "处理消息失败:", error);
formatAppLog("error", "at pages/index/index.vue:383", "处理消息失败:", error);
}
},
// 处理iframe消息
handleIframeMessage(event) {
formatAppLog("log", "at pages/index/index.vue:341", "收到iframe消息:", event.data);
formatAppLog("log", "at pages/index/index.vue:389", "收到iframe消息:", event.data);
try {
if (event.data && event.data.type) {
if (event.data.type === "pageLoaded") {
formatAppLog("log", "at pages/index/index.vue:346", "收到页面加载完成消息:", event.data.data);
formatAppLog("log", "at pages/index/index.vue:394", "收到页面加载完成消息:", event.data.data);
if (this.loadingTimer) {
clearTimeout(this.loadingTimer);
this.loadingTimer = null;
@@ -384,55 +432,63 @@ if (uni.restoreGlobal) {
this.processMessage(event.data);
}
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:361", "处理iframe消息失败:", error);
formatAppLog("error", "at pages/index/index.vue:409", "处理iframe消息失败:", error);
}
},
// 处理消息
processMessage(data) {
formatAppLog("log", "at pages/index/index.vue:367", "UniApp处理消息:", data.type, data);
formatAppLog("log", "at pages/index/index.vue:415", "UniApp处理消息:", data.type, data);
switch (data.type) {
case this.config.communication.messageTypes.GET_USER_INFO:
formatAppLog("log", "at pages/index/index.vue:371", "UniApp: 处理获取用户信息请求");
formatAppLog("log", "at pages/index/index.vue:419", "UniApp: 处理获取用户信息请求");
this.sendUserInfo();
break;
case this.config.communication.messageTypes.GET_DEVICE_INFO:
formatAppLog("log", "at pages/index/index.vue:375", "UniApp: 处理获取设备信息请求");
formatAppLog("log", "at pages/index/index.vue:423", "UniApp: 处理获取设备信息请求");
this.sendDeviceInfo();
break;
case this.config.communication.messageTypes.NAVIGATE:
formatAppLog("log", "at pages/index/index.vue:379", "UniApp: 处理导航请求");
formatAppLog("log", "at pages/index/index.vue:427", "UniApp: 处理导航请求");
this.handleNavigation(data);
break;
case this.config.communication.messageTypes.SHARE:
formatAppLog("log", "at pages/index/index.vue:383", "UniApp: 处理分享请求");
formatAppLog("log", "at pages/index/index.vue:431", "UniApp: 处理分享请求");
this.handleShare(data);
break;
case this.config.communication.messageTypes.PAYMENT:
formatAppLog("log", "at pages/index/index.vue:387", "UniApp: 处理支付请求");
formatAppLog("log", "at pages/index/index.vue:435", "UniApp: 处理支付请求");
this.handlePayment(data);
break;
case this.config.communication.messageTypes.TOAST:
formatAppLog("log", "at pages/index/index.vue:391", "UniApp: 处理Toast请求");
formatAppLog("log", "at pages/index/index.vue:439", "UniApp: 处理Toast请求");
this.handleToast(data);
break;
case this.config.communication.messageTypes.ALERT:
formatAppLog("log", "at pages/index/index.vue:395", "UniApp: 处理Alert请求");
formatAppLog("log", "at pages/index/index.vue:443", "UniApp: 处理Alert请求");
this.handleAlert(data);
break;
case this.config.communication.messageTypes.CONFIRM:
formatAppLog("log", "at pages/index/index.vue:399", "UniApp: 处理Confirm请求");
formatAppLog("log", "at pages/index/index.vue:447", "UniApp: 处理Confirm请求");
this.handleConfirm(data);
break;
case "pageReady":
formatAppLog("log", "at pages/index/index.vue:403", "UniApp: 处理页面准备就绪消息");
formatAppLog("log", "at pages/index/index.vue:451", "UniApp: 处理页面准备就绪消息");
break;
case "backButton":
formatAppLog("log", "at pages/index/index.vue:455", "UniApp: 处理返回键消息");
this.handleBackButtonMessage(data);
break;
case "exitApp":
formatAppLog("log", "at pages/index/index.vue:459", "UniApp: 处理退出应用消息");
this.handleExitApp();
break;
default:
formatAppLog("log", "at pages/index/index.vue:407", "UniApp: 未知消息类型:", data.type);
formatAppLog("log", "at pages/index/index.vue:463", "UniApp: 未知消息类型:", data.type);
}
},
// 发送用户信息到iframe
sendUserInfo() {
formatAppLog("log", "at pages/index/index.vue:413", "UniApp: 发送用户信息");
formatAppLog("log", "at pages/index/index.vue:469", "UniApp: 发送用户信息");
const userInfo = {
type: "userInfo",
data: this.config.userConfig.defaultUser
@@ -441,7 +497,7 @@ if (uni.restoreGlobal) {
},
// 发送设备信息到iframe
sendDeviceInfo() {
formatAppLog("log", "at pages/index/index.vue:423", "UniApp: 发送设备信息");
formatAppLog("log", "at pages/index/index.vue:479", "UniApp: 发送设备信息");
const systemInfo = uni.getSystemInfoSync();
const deviceInfo = {
type: "deviceInfo",
@@ -461,12 +517,12 @@ if (uni.restoreGlobal) {
// 处理导航
handleNavigation(data) {
if (data.url) {
formatAppLog("log", "at pages/index/index.vue:444", "导航到:", data.url);
formatAppLog("log", "at pages/index/index.vue:500", "导航到:", data.url);
}
},
// 处理分享
handleShare(data) {
formatAppLog("log", "at pages/index/index.vue:451", "UniApp: 处理分享请求", data);
formatAppLog("log", "at pages/index/index.vue:507", "UniApp: 处理分享请求", data);
uni.share({
provider: "weixin",
scene: "WXSceneSession",
@@ -475,18 +531,18 @@ if (uni.restoreGlobal) {
title: data.title || this.config.appConfig.appName,
summary: data.summary || "分享内容",
success: (res) => {
formatAppLog("log", "at pages/index/index.vue:460", "UniApp: 分享成功:", res);
formatAppLog("log", "at pages/index/index.vue:516", "UniApp: 分享成功:", res);
this.sendToIframe("shareResult", { success: true });
},
fail: (err) => {
formatAppLog("error", "at pages/index/index.vue:464", "UniApp: 分享失败:", err);
formatAppLog("error", "at pages/index/index.vue:520", "UniApp: 分享失败:", err);
this.sendToIframe("shareResult", { success: false, error: err });
}
});
},
// 处理支付
handlePayment(data) {
formatAppLog("log", "at pages/index/index.vue:472", "UniApp: 处理支付请求", data);
formatAppLog("log", "at pages/index/index.vue:528", "UniApp: 处理支付请求", data);
setTimeout(() => {
this.sendToIframe("paymentResult", {
success: true,
@@ -496,7 +552,7 @@ if (uni.restoreGlobal) {
},
// 处理Toast
handleToast(data) {
formatAppLog("log", "at pages/index/index.vue:485", "UniApp: 处理Toast请求", data);
formatAppLog("log", "at pages/index/index.vue:541", "UniApp: 处理Toast请求", data);
uni.showToast({
title: data.message,
icon: "none",
@@ -505,7 +561,7 @@ if (uni.restoreGlobal) {
},
// 处理Alert
handleAlert(data) {
formatAppLog("log", "at pages/index/index.vue:495", "UniApp: 处理Alert请求", data);
formatAppLog("log", "at pages/index/index.vue:551", "UniApp: 处理Alert请求", data);
uni.showModal({
title: data.title || "提示",
content: data.content,
@@ -514,12 +570,12 @@ if (uni.restoreGlobal) {
},
// 处理Confirm
handleConfirm(data) {
formatAppLog("log", "at pages/index/index.vue:505", "UniApp: 处理Confirm请求", data);
formatAppLog("log", "at pages/index/index.vue:561", "UniApp: 处理Confirm请求", data);
uni.showModal({
title: data.title || "确认",
content: data.content,
success: (res) => {
formatAppLog("log", "at pages/index/index.vue:510", "UniApp: Confirm结果:", res);
formatAppLog("log", "at pages/index/index.vue:566", "UniApp: Confirm结果:", res);
this.sendToIframe("confirmResult", {
confirmed: res.confirm
});
@@ -533,10 +589,10 @@ if (uni.restoreGlobal) {
},
// 处理消息队列
processMessageQueue() {
formatAppLog("log", "at pages/index/index.vue:526", "UniApp: 处理消息队列, 队列长度:", this.messageQueue.length, "加载状态:", this.loading);
formatAppLog("log", "at pages/index/index.vue:582", "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:529", "UniApp: 发送消息到iframe:", message);
formatAppLog("log", "at pages/index/index.vue:585", "UniApp: 发送消息到iframe:", message);
this.evalJS(`
window.postMessage(${JSON.stringify(message)}, '*');
`);
@@ -557,12 +613,12 @@ if (uni.restoreGlobal) {
},
// 处理加载状态
handleLoading(event) {
formatAppLog("log", "at pages/index/index.vue:553", "WebView加载状态变化:", event.detail);
formatAppLog("log", "at pages/index/index.vue:609", "WebView加载状态变化:", event.detail);
const newLoadingState = event.detail.loading;
formatAppLog("log", "at pages/index/index.vue:555", "加载状态从", this.loading, "变为", newLoadingState);
formatAppLog("log", "at pages/index/index.vue:611", "加载状态从", this.loading, "变为", newLoadingState);
this.loading = newLoadingState;
if (!this.loading) {
formatAppLog("log", "at pages/index/index.vue:561", "页面加载完成,清除超时定时器");
formatAppLog("log", "at pages/index/index.vue:617", "页面加载完成,清除超时定时器");
if (this.loadingTimer) {
clearTimeout(this.loadingTimer);
this.loadingTimer = null;
@@ -570,13 +626,13 @@ if (uni.restoreGlobal) {
this.injectBridgeCode();
this.processMessageQueue();
} else {
formatAppLog("log", "at pages/index/index.vue:573", "页面开始加载,设置超时检测");
formatAppLog("log", "at pages/index/index.vue:629", "页面开始加载,设置超时检测");
this.setupLoadingTimeout();
}
},
// 处理错误
handleError(event) {
formatAppLog("error", "at pages/index/index.vue:580", "WebView错误:", event.detail);
formatAppLog("error", "at pages/index/index.vue:636", "WebView错误:", event.detail);
this.error = "页面加载失败,请检查网络连接";
this.loading = false;
clearTimeout(this.loadingTimer);
@@ -598,18 +654,18 @@ if (uni.restoreGlobal) {
},
// 清除超时
clearTimeout() {
formatAppLog("log", "at pages/index/index.vue:606", "手动清除超时");
formatAppLog("log", "at pages/index/index.vue:662", "手动清除超时");
if (this.loadingTimer) {
clearTimeout(this.loadingTimer);
this.loadingTimer = null;
}
this.error = "";
this.loading = false;
formatAppLog("log", "at pages/index/index.vue:613", "超时已清除");
formatAppLog("log", "at pages/index/index.vue:669", "超时已清除");
},
// 动态设置web-view高度
setWebViewHeight(height) {
formatAppLog("log", "at pages/index/index.vue:618", "设置web-view高度:", height);
formatAppLog("log", "at pages/index/index.vue:674", "设置web-view高度:", height);
if (this.$refs.webview) {
this.$refs.webview.$el.style.height = height + "px";
this.$refs.webview.$el.className = "webview custom-height";
@@ -621,21 +677,162 @@ if (uni.restoreGlobal) {
// 设置web-view为全屏
setWebViewFullscreen() {
const fullHeight = uni.getSystemInfoSync().windowHeight;
formatAppLog("log", "at pages/index/index.vue:636", "设置web-view全屏高度:", fullHeight);
formatAppLog("log", "at pages/index/index.vue:692", "设置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:644", "设置web-view部分高度:", partialHeight, "百分比:", percentage);
formatAppLog("log", "at pages/index/index.vue:700", "设置web-view部分高度:", partialHeight, "百分比:", percentage);
this.setWebViewHeight(partialHeight);
},
// 初始化返回键监听
initBackButtonListener() {
formatAppLog("log", "at pages/index/index.vue:706", "初始化返回键监听");
try {
uni.addInterceptor("navigateBack", {
invoke(e) {
formatAppLog("log", "at pages/index/index.vue:713", "拦截到返回事件:", e);
return false;
}
});
} catch (error) {
formatAppLog("warn", "at pages/index/index.vue:718", "addInterceptor 失败:", error);
}
this.setupPhysicalBackButton();
this.setupWebViewBackListener();
},
// 设置物理返回键监听
setupPhysicalBackButton() {
try {
plus.key.addEventListener("backbutton", (e) => {
formatAppLog("log", "at pages/index/index.vue:735", "检测到物理返回键事件:", e);
this.handleBackButton();
});
} catch (error) {
formatAppLog("warn", "at pages/index/index.vue:739", "物理返回键监听失败:", error);
}
},
// 设置 web-view 内返回监听
setupWebViewBackListener() {
window.addEventListener("popstate", (event) => {
formatAppLog("log", "at pages/index/index.vue:748", "检测到 popstate 事件:", event);
this.handleBackButton();
});
window.addEventListener("beforeunload", (event) => {
formatAppLog("log", "at pages/index/index.vue:754", "检测到 beforeunload 事件:", event);
this.handleBackButton();
});
},
// 处理返回键事件
handleBackButton() {
const now = Date.now();
const timeDiff = now - this.lastBackTime;
formatAppLog("log", "at pages/index/index.vue:764", "处理返回键事件, 时间差:", timeDiff, "ms");
if (timeDiff > 2e3) {
this.backButtonCount = 0;
}
this.backButtonCount++;
this.lastBackTime = now;
if (this.backButtonCount === 1) {
this.showExitConfirm();
} else if (this.backButtonCount >= 2) {
this.exitApp();
}
},
// 显示退出确认
showExitConfirm() {
formatAppLog("log", "at pages/index/index.vue:786", "显示退出确认");
uni.showModal({
title: "退出确认",
content: "确定要退出应用吗?",
confirmText: "退出",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
this.exitApp();
}
}
});
this.sendBackButtonMessage("showExitConfirm");
},
// 退出应用
exitApp() {
formatAppLog("log", "at pages/index/index.vue:809", "退出应用");
try {
plus.runtime.quit();
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:816", "退出应用失败:", error);
}
this.sendBackButtonMessage("exitApp");
},
// 发送返回键消息到 web-view
sendBackButtonMessage(action) {
if (this.$refs.webview) {
try {
this.$refs.webview.postMessage({
type: "backButton",
action,
timestamp: Date.now()
});
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:835", "发送返回键消息失败:", error);
}
}
},
// 处理返回键消息
handleBackButtonMessage(data) {
formatAppLog("log", "at pages/index/index.vue:842", "处理返回键消息:", data);
switch (data.action) {
case "popstate":
case "keydown":
this.handleBackButton();
break;
default:
formatAppLog("log", "at pages/index/index.vue:850", "未知的返回键动作:", data.action);
}
},
// 处理退出应用
handleExitApp() {
formatAppLog("log", "at pages/index/index.vue:856", "处理退出应用");
try {
plus.runtime.quit();
} catch (error) {
formatAppLog("error", "at pages/index/index.vue:862", "退出应用失败:", error);
}
},
// 恢复返回键监听
resumeBackButtonListener() {
formatAppLog("log", "at pages/index/index.vue:869", "恢复返回键监听");
this.backButtonCount = 0;
this.lastBackTime = 0;
},
// 暂停返回键监听
pauseBackButtonListener() {
formatAppLog("log", "at pages/index/index.vue:876", "暂停返回键监听");
this.backButtonCount = 0;
},
// 移除返回键监听
removeBackButtonListener() {
formatAppLog("log", "at pages/index/index.vue:882", "移除返回键监听");
try {
plus.key.removeEventListener("backbutton");
uni.removeInterceptor("navigateBack");
} catch (error) {
formatAppLog("warn", "at pages/index/index.vue:892", "移除返回键监听失败:", error);
}
if (this.backButtonTimer) {
clearTimeout(this.backButtonTimer);
this.backButtonTimer = null;
}
},
// 清理资源
cleanup() {
if (this.loadingTimer) {
clearTimeout(this.loadingTimer);
}
this.removeBackButtonListener();
}
}
};

View File

@@ -35,7 +35,10 @@
min-height: 100vh;
padding: 0 0 60px 0;
}
.scene-page-content {
padding: 16px;
text-align: center;
}
// 错误提示
.error-notice {
margin-bottom: 12px;

View File

@@ -65,7 +65,7 @@ const Scene: React.FC = () => {
navigate("/scenarios/new");
};
if (error && scenarios.length === 0) {
if (!(error && scenarios.length === 0)) {
return (
<Layout
header={