793 lines
22 KiB
Vue
793 lines
22 KiB
Vue
<template>
|
||
<view class="container">
|
||
<!-- 全屏web-view容器 -->
|
||
<web-view :src="currentUrl" :style="webViewStyle" ref="webview" @message="handleMessage" @error="handleError"
|
||
@loading="handleLoading">
|
||
</web-view>
|
||
|
||
<!-- 加载状态 -->
|
||
<view v-if="loading" class="loading-container">
|
||
<view class="loading-spinner"></view>
|
||
<text class="loading-text">加载中...</text>
|
||
</view>
|
||
|
||
<!-- 错误状态 -->
|
||
<view v-if="error" class="error-container">
|
||
<text class="error-text">{{ error }}</text>
|
||
<button @click="reloadPage" class="reload-btn">重新加载</button>
|
||
<button @click="switchToFallback" class="fallback-btn">使用备用地址</button>
|
||
<button @click="clearTimeout" class="clear-btn">清除超时</button>
|
||
</view>
|
||
|
||
<!-- 调试信息(仅在调试模式下显示) -->
|
||
<view v-if="config.appConfig.debug" class="debug-info">
|
||
<text>当前URL: {{ currentUrl }}</text>
|
||
<text>加载状态: {{ loading ? '加载中' : '已加载' }}</text>
|
||
<text>navBarHeight: {{ navBarHeight }}</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import config from '@/config.js';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
config: config,
|
||
currentUrl: '', // 初始化为空字符串
|
||
loading: false,
|
||
error: '',
|
||
loadingTimer: null,
|
||
messageQueue: []
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.initApp();
|
||
},
|
||
onShow() {
|
||
this.resumeMessageQueue();
|
||
},
|
||
onHide() {
|
||
console.log('WebView页面隐藏');
|
||
},
|
||
onUnload() {
|
||
this.cleanup();
|
||
},
|
||
computed: {
|
||
navBarHeight() {
|
||
return (this.getSafeAreaHeight().navBarHeight || 44) + 'px'
|
||
},
|
||
webViewStyle() {
|
||
const safeArea = this.getSafeAreaHeight();
|
||
return {
|
||
position: 'absolute',
|
||
top: safeArea.navBarHeight + 'px',
|
||
left: '0px',
|
||
right: '0px',
|
||
bottom: '0px',
|
||
width: '100%',
|
||
height: `calc(100vh - ${safeArea.navBarHeight}px)`,
|
||
zIndex: 1
|
||
};
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
// 获取初始URL
|
||
getInitialUrl() {
|
||
console.log('获取初始URL,config:', this.config);
|
||
if (this.config && this.config.appConfig && this.config.appConfig.useTestPage) {
|
||
return this.config.webConfig.testUrl;
|
||
}
|
||
return this.config.webConfig.mainUrl;
|
||
},
|
||
|
||
// 初始化应用
|
||
initApp() {
|
||
console.log('UniApp: 开始初始化应用');
|
||
// 设置初始URL
|
||
this.currentUrl = this.getInitialUrl();
|
||
console.log('UniApp: 设置URL:', this.currentUrl);
|
||
|
||
this.setupLoadingTimeout();
|
||
this.initMessageHandler();
|
||
|
||
// 立即尝试注入桥接代码
|
||
console.log('UniApp: 立即注入桥接代码');
|
||
this.injectBridgeCode();
|
||
},
|
||
|
||
// 设置加载超时
|
||
setupLoadingTimeout() {
|
||
// 清除之前的定时器
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
}
|
||
|
||
// 检查是否启用超时检测
|
||
if (!this.config.appConfig.enableTimeout) {
|
||
console.log('超时检测已禁用');
|
||
return;
|
||
}
|
||
|
||
if (this.config.appConfig.loadingTimeout > 0) {
|
||
console.log('设置加载超时:', this.config.appConfig.loadingTimeout + 'ms');
|
||
this.loadingTimer = setTimeout(() => {
|
||
if (this.loading) {
|
||
console.warn('页面加载超时,当前状态:', this.loading);
|
||
this.handleTimeout();
|
||
}
|
||
}, this.config.appConfig.loadingTimeout);
|
||
}
|
||
},
|
||
|
||
// 处理加载超时
|
||
handleTimeout() {
|
||
console.warn('触发页面加载超时处理');
|
||
this.error = '页面加载超时,请检查网络连接';
|
||
this.loading = false;
|
||
// 清除定时器
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
this.loadingTimer = null;
|
||
}
|
||
},
|
||
|
||
// 初始化消息处理器
|
||
initMessageHandler() {
|
||
console.log('UniApp: 初始化消息处理器');
|
||
// 监听来自web-view的消息
|
||
window.addEventListener('message', (event) => {
|
||
console.log('UniApp: 收到window.message事件:', event.data);
|
||
this.handleIframeMessage(event);
|
||
});
|
||
},
|
||
|
||
// 设置WebView桥接
|
||
setupWebViewBridge() {
|
||
// 向web-view注入通信桥接代码
|
||
this.injectBridgeCode();
|
||
},
|
||
|
||
// 注入桥接代码
|
||
injectBridgeCode() {
|
||
console.log('UniApp: 开始注入桥接代码');
|
||
|
||
const bridgeCode = `
|
||
// UniApp WebView 桥接代码
|
||
console.log('开始注入UniApp桥接代码...');
|
||
|
||
// 检查是否已经存在桥接
|
||
if (window.uniAppBridge) {
|
||
console.log('UniApp桥接已存在,跳过注入');
|
||
return;
|
||
}
|
||
|
||
window.uniAppBridge = {
|
||
// 发送消息到UniApp
|
||
postMessage: function(type, data) {
|
||
console.log('UniApp桥接发送消息:', type, data);
|
||
window.parent.postMessage({
|
||
type: type,
|
||
data: data,
|
||
timestamp: Date.now()
|
||
}, '*');
|
||
},
|
||
|
||
// 获取用户信息
|
||
getUserInfo: function() {
|
||
console.log('UniApp桥接: 请求用户信息');
|
||
this.postMessage('getUserInfo', {});
|
||
},
|
||
|
||
// 获取设备信息
|
||
getDeviceInfo: function() {
|
||
console.log('UniApp桥接: 请求设备信息');
|
||
this.postMessage('getDeviceInfo', {});
|
||
},
|
||
|
||
// 显示Toast
|
||
showToast: function(message, duration = 2000) {
|
||
console.log('UniApp桥接: 显示Toast', message, duration);
|
||
this.postMessage('toast', { message, duration });
|
||
},
|
||
|
||
// 显示Alert
|
||
showAlert: function(title, content) {
|
||
console.log('UniApp桥接: 显示Alert', title, content);
|
||
this.postMessage('alert', { title, content });
|
||
},
|
||
|
||
// 显示Confirm
|
||
showConfirm: function(title, content) {
|
||
console.log('UniApp桥接: 显示Confirm', title, content);
|
||
this.postMessage('confirm', { title, content });
|
||
},
|
||
|
||
// 分享
|
||
share: function(data) {
|
||
console.log('UniApp桥接: 分享', data);
|
||
this.postMessage('share', data);
|
||
},
|
||
|
||
// 支付
|
||
payment: function(data) {
|
||
console.log('UniApp桥接: 支付', data);
|
||
this.postMessage('payment', data);
|
||
},
|
||
|
||
// 页面导航
|
||
navigate: function(url) {
|
||
console.log('UniApp桥接: 导航', url);
|
||
this.postMessage('navigate', { url });
|
||
},
|
||
|
||
// 自定义消息
|
||
sendCustomMessage: function(type, data) {
|
||
console.log('UniApp桥接: 自定义消息', type, data);
|
||
this.postMessage(type, data);
|
||
},
|
||
|
||
// 页面准备就绪
|
||
notifyPageReady: function(data) {
|
||
console.log('UniApp桥接: 页面准备就绪', data);
|
||
this.postMessage('pageReady', data);
|
||
}
|
||
};
|
||
|
||
// 监听来自UniApp的消息
|
||
window.addEventListener('message', function(event) {
|
||
console.log('UniApp桥接收到消息:', event.data);
|
||
if (event.data && event.data.type) {
|
||
// 触发自定义事件
|
||
const customEvent = new CustomEvent('uniAppMessage', {
|
||
detail: event.data
|
||
});
|
||
window.dispatchEvent(customEvent);
|
||
}
|
||
});
|
||
|
||
console.log('UniApp桥接代码注入成功');
|
||
|
||
// 通知UniApp页面已加载完成
|
||
window.parent.postMessage({
|
||
type: 'pageLoaded',
|
||
data: { url: window.location.href },
|
||
timestamp: Date.now()
|
||
}, '*');
|
||
`;
|
||
|
||
// 立即尝试注入
|
||
console.log('UniApp: 立即注入桥接代码');
|
||
this.evalJS(bridgeCode);
|
||
|
||
// 延迟再次注入,确保注入成功
|
||
setTimeout(() => {
|
||
console.log('UniApp: 延迟500ms后再次注入');
|
||
this.evalJS(bridgeCode);
|
||
}, 500);
|
||
|
||
// 再次延迟注入,作为备用方案
|
||
setTimeout(() => {
|
||
console.log('UniApp: 延迟1000ms后备用注入');
|
||
this.evalJS(bridgeCode);
|
||
}, 1000);
|
||
},
|
||
|
||
// 执行JavaScript代码
|
||
evalJS(code) {
|
||
console.log('UniApp: 执行JavaScript代码');
|
||
console.log('UniApp: 当前平台:', uni.getSystemInfoSync().platform);
|
||
|
||
const webview = this.$refs.webview;
|
||
console.log('UniApp: webview引用:', webview);
|
||
|
||
// 检查是否在App环境下
|
||
// #ifdef APP-PLUS
|
||
if (webview && webview.evalJS) {
|
||
try {
|
||
webview.evalJS(code);
|
||
console.log('UniApp: JavaScript代码执行成功 (App环境)');
|
||
} catch (error) {
|
||
console.error('UniApp: JavaScript代码执行失败:', error);
|
||
}
|
||
} else {
|
||
console.warn('UniApp: webview或evalJS方法不存在 (App环境)');
|
||
// 尝试备用方案
|
||
this.tryAlternativeInjection(code);
|
||
}
|
||
// #endif
|
||
|
||
// #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
|
||
console.log('UniApp: 小程序环境,使用备用注入方案');
|
||
this.tryAlternativeInjection(code);
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
console.log('UniApp: H5环境,使用备用注入方案');
|
||
this.tryAlternativeInjection(code);
|
||
// #endif
|
||
},
|
||
|
||
// 备用注入方案
|
||
tryAlternativeInjection(code) {
|
||
console.log('UniApp: 尝试备用注入方案');
|
||
try {
|
||
// 方案1: 直接通过postMessage发送代码
|
||
window.postMessage({
|
||
type: 'injectCode',
|
||
data: { code: code },
|
||
timestamp: Date.now()
|
||
}, '*');
|
||
console.log('UniApp: 备用方案1执行成功');
|
||
} catch (error) {
|
||
console.error('UniApp: 备用方案1失败:', error);
|
||
|
||
// 方案2: 通过web-view的message事件
|
||
try {
|
||
const webview = this.$refs.webview;
|
||
if (webview && webview.postMessage) {
|
||
webview.postMessage({
|
||
type: 'injectCode',
|
||
data: { code: code }
|
||
});
|
||
console.log('UniApp: 备用方案2执行成功');
|
||
} else {
|
||
console.error('UniApp: 备用方案2失败 - webview.postMessage不存在');
|
||
}
|
||
} catch (error2) {
|
||
console.error('UniApp: 备用方案2失败:', error2);
|
||
}
|
||
}
|
||
},
|
||
|
||
// 处理web-view组件的消息
|
||
handleMessage(event) {
|
||
console.log('收到web-view消息:', event.detail);
|
||
try {
|
||
const data = event.detail.data;
|
||
if (data && data.type) {
|
||
this.processMessage(data);
|
||
}
|
||
} catch (error) {
|
||
console.error('处理消息失败:', error);
|
||
}
|
||
},
|
||
|
||
// 处理iframe消息
|
||
handleIframeMessage(event) {
|
||
console.log('收到iframe消息:', event.data);
|
||
try {
|
||
if (event.data && event.data.type) {
|
||
// 处理页面加载完成消息
|
||
if (event.data.type === 'pageLoaded') {
|
||
console.log('收到页面加载完成消息:', event.data.data);
|
||
// 清除超时定时器
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
this.loadingTimer = null;
|
||
}
|
||
// 更新加载状态
|
||
this.loading = false;
|
||
this.processMessageQueue();
|
||
return;
|
||
}
|
||
|
||
this.processMessage(event.data);
|
||
}
|
||
} catch (error) {
|
||
console.error('处理iframe消息失败:', error);
|
||
}
|
||
},
|
||
|
||
// 处理消息
|
||
processMessage(data) {
|
||
console.log('UniApp处理消息:', data.type, data);
|
||
|
||
switch (data.type) {
|
||
case this.config.communication.messageTypes.GET_USER_INFO:
|
||
console.log('UniApp: 处理获取用户信息请求');
|
||
this.sendUserInfo();
|
||
break;
|
||
case this.config.communication.messageTypes.GET_DEVICE_INFO:
|
||
console.log('UniApp: 处理获取设备信息请求');
|
||
this.sendDeviceInfo();
|
||
break;
|
||
case this.config.communication.messageTypes.NAVIGATE:
|
||
console.log('UniApp: 处理导航请求');
|
||
this.handleNavigation(data);
|
||
break;
|
||
case this.config.communication.messageTypes.SHARE:
|
||
console.log('UniApp: 处理分享请求');
|
||
this.handleShare(data);
|
||
break;
|
||
case this.config.communication.messageTypes.PAYMENT:
|
||
console.log('UniApp: 处理支付请求');
|
||
this.handlePayment(data);
|
||
break;
|
||
case this.config.communication.messageTypes.TOAST:
|
||
console.log('UniApp: 处理Toast请求');
|
||
this.handleToast(data);
|
||
break;
|
||
case this.config.communication.messageTypes.ALERT:
|
||
console.log('UniApp: 处理Alert请求');
|
||
this.handleAlert(data);
|
||
break;
|
||
case this.config.communication.messageTypes.CONFIRM:
|
||
console.log('UniApp: 处理Confirm请求');
|
||
this.handleConfirm(data);
|
||
break;
|
||
case 'pageReady':
|
||
console.log('UniApp: 处理页面准备就绪消息');
|
||
// 可以在这里处理页面准备就绪的逻辑
|
||
break;
|
||
default:
|
||
console.log('UniApp: 未知消息类型:', data.type);
|
||
}
|
||
},
|
||
|
||
// 发送用户信息到iframe
|
||
sendUserInfo() {
|
||
console.log('UniApp: 发送用户信息');
|
||
const userInfo = {
|
||
type: 'userInfo',
|
||
data: this.config.userConfig.defaultUser
|
||
};
|
||
this.sendMessageToIframe(userInfo);
|
||
},
|
||
|
||
// 发送设备信息到iframe
|
||
sendDeviceInfo() {
|
||
console.log('UniApp: 发送设备信息');
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
const deviceInfo = {
|
||
type: 'deviceInfo',
|
||
data: {
|
||
platform: systemInfo.platform,
|
||
model: systemInfo.model,
|
||
version: systemInfo.version,
|
||
appVersion: this.config.appConfig.version,
|
||
appName: this.config.appConfig.appName,
|
||
screenWidth: systemInfo.screenWidth,
|
||
screenHeight: systemInfo.screenHeight,
|
||
statusBarHeight: systemInfo.statusBarHeight
|
||
}
|
||
};
|
||
this.sendMessageToIframe(deviceInfo);
|
||
},
|
||
|
||
// 处理导航
|
||
handleNavigation(data) {
|
||
if (data.url) {
|
||
console.log('导航到:', data.url);
|
||
// 可以在这里处理页面跳转逻辑
|
||
}
|
||
},
|
||
|
||
// 处理分享
|
||
handleShare(data) {
|
||
console.log('UniApp: 处理分享请求', data);
|
||
uni.share({
|
||
provider: 'weixin',
|
||
scene: 'WXSceneSession',
|
||
type: 0,
|
||
href: data.url || this.currentUrl,
|
||
title: data.title || this.config.appConfig.appName,
|
||
summary: data.summary || '分享内容',
|
||
success: (res) => {
|
||
console.log('UniApp: 分享成功:', res);
|
||
this.sendToIframe('shareResult', { success: true });
|
||
},
|
||
fail: (err) => {
|
||
console.error('UniApp: 分享失败:', err);
|
||
this.sendToIframe('shareResult', { success: false, error: err });
|
||
}
|
||
});
|
||
},
|
||
|
||
// 处理支付
|
||
handlePayment(data) {
|
||
console.log('UniApp: 处理支付请求', data);
|
||
// 这里可以集成具体的支付功能
|
||
// 模拟支付成功
|
||
setTimeout(() => {
|
||
this.sendToIframe('paymentResult', {
|
||
success: true,
|
||
orderId: data.orderId || 'order123'
|
||
});
|
||
}, 1000);
|
||
},
|
||
|
||
// 处理Toast
|
||
handleToast(data) {
|
||
console.log('UniApp: 处理Toast请求', data);
|
||
uni.showToast({
|
||
title: data.message,
|
||
icon: 'none',
|
||
duration: data.duration || 2000
|
||
});
|
||
},
|
||
|
||
// 处理Alert
|
||
handleAlert(data) {
|
||
console.log('UniApp: 处理Alert请求', data);
|
||
uni.showModal({
|
||
title: data.title || '提示',
|
||
content: data.content,
|
||
showCancel: false
|
||
});
|
||
},
|
||
|
||
// 处理Confirm
|
||
handleConfirm(data) {
|
||
console.log('UniApp: 处理Confirm请求', data);
|
||
uni.showModal({
|
||
title: data.title || '确认',
|
||
content: data.content,
|
||
success: (res) => {
|
||
console.log('UniApp: Confirm结果:', res);
|
||
this.sendToIframe('confirmResult', {
|
||
confirmed: res.confirm
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
// 发送消息到iframe
|
||
sendMessageToIframe(message) {
|
||
this.messageQueue.push(message);
|
||
this.processMessageQueue();
|
||
},
|
||
|
||
// 处理消息队列
|
||
processMessageQueue() {
|
||
console.log('UniApp: 处理消息队列, 队列长度:', this.messageQueue.length, '加载状态:', this.loading);
|
||
if (this.messageQueue.length > 0 && !this.loading) {
|
||
const message = this.messageQueue.shift();
|
||
console.log('UniApp: 发送消息到iframe:', message);
|
||
this.evalJS(`
|
||
window.postMessage(${JSON.stringify(message)}, '*');
|
||
`);
|
||
}
|
||
},
|
||
|
||
// 恢复消息队列处理
|
||
resumeMessageQueue() {
|
||
this.processMessageQueue();
|
||
},
|
||
|
||
// 向iframe发送消息的通用方法
|
||
sendToIframe(type, data) {
|
||
const message = {
|
||
type: type,
|
||
data: data,
|
||
timestamp: Date.now()
|
||
};
|
||
this.sendMessageToIframe(message);
|
||
},
|
||
|
||
// 处理加载状态
|
||
handleLoading(event) {
|
||
console.log('WebView加载状态变化:', event.detail);
|
||
const newLoadingState = event.detail.loading;
|
||
console.log('加载状态从', this.loading, '变为', newLoadingState);
|
||
|
||
this.loading = newLoadingState;
|
||
|
||
if (!this.loading) {
|
||
// 页面加载完成
|
||
console.log('页面加载完成,清除超时定时器');
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
this.loadingTimer = null;
|
||
}
|
||
|
||
// 页面加载完成后立即注入桥接代码
|
||
this.injectBridgeCode();
|
||
|
||
this.processMessageQueue();
|
||
} else {
|
||
// 开始加载,设置超时
|
||
console.log('页面开始加载,设置超时检测');
|
||
this.setupLoadingTimeout();
|
||
}
|
||
},
|
||
|
||
// 处理错误
|
||
handleError(event) {
|
||
console.error('WebView错误:', event.detail);
|
||
this.error = '页面加载失败,请检查网络连接';
|
||
this.loading = false;
|
||
clearTimeout(this.loadingTimer);
|
||
},
|
||
|
||
// 重新加载页面
|
||
reloadPage() {
|
||
this.error = '';
|
||
this.loading = true;
|
||
this.setupLoadingTimeout();
|
||
|
||
const webview = this.$refs.webview;
|
||
if (webview) {
|
||
webview.reload();
|
||
}
|
||
},
|
||
|
||
// 切换到备用地址
|
||
switchToFallback() {
|
||
this.currentUrl = this.config.webConfig.fallbackUrl;
|
||
this.reloadPage();
|
||
},
|
||
|
||
// 清除超时
|
||
clearTimeout() {
|
||
console.log('手动清除超时');
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
this.loadingTimer = null;
|
||
}
|
||
this.error = '';
|
||
this.loading = false;
|
||
console.log('超时已清除');
|
||
},
|
||
|
||
// 获取安全区域高度
|
||
getSafeAreaHeight() {
|
||
|
||
try {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
console.log('UniApp: 系统信息:', systemInfo);
|
||
|
||
// 安全区域信息
|
||
const safeArea = systemInfo.safeArea || {};
|
||
const safeAreaInsets = systemInfo.safeAreaInsets || {};
|
||
|
||
console.log('UniApp: 安全区域:', safeArea);
|
||
console.log('UniApp: 安全区域边距:', safeAreaInsets);
|
||
|
||
// 状态栏高度
|
||
const statusBarHeight = systemInfo.statusBarHeight || 0;
|
||
console.log('UniApp: 状态栏高度:', statusBarHeight);
|
||
|
||
// 计算顶部安全区域高度
|
||
let topSafeAreaHeight = statusBarHeight;
|
||
|
||
// 如果有安全区域边距信息,优先使用它
|
||
if (safeAreaInsets.top !== undefined) {
|
||
topSafeAreaHeight = safeAreaInsets.top;
|
||
console.log('UniApp: 使用safeAreaInsets.top:', topSafeAreaHeight);
|
||
} else if (safeArea.top !== undefined) {
|
||
topSafeAreaHeight = safeArea.top;
|
||
console.log('UniApp: 使用safeArea.top:', topSafeAreaHeight);
|
||
} else {
|
||
// 根据平台和设备类型计算
|
||
topSafeAreaHeight = this.calculatePlatformSafeArea(statusBarHeight, systemInfo);
|
||
}
|
||
|
||
// 返回完整的安全区域信息
|
||
const safeAreaInfo = {
|
||
top: topSafeAreaHeight,
|
||
bottom: safeAreaInsets.bottom || safeArea.bottom || 0,
|
||
left: safeAreaInsets.left || safeArea.left || 0,
|
||
right: safeAreaInsets.right || safeArea.right || 0,
|
||
statusBarHeight: statusBarHeight,
|
||
navBarHeight: 44, // 导航栏高度通常是44px
|
||
platform: systemInfo.platform,
|
||
model: systemInfo.model,
|
||
system: systemInfo.system,
|
||
screenWidth: systemInfo.screenWidth,
|
||
screenHeight: systemInfo.screenHeight
|
||
};
|
||
|
||
return safeAreaInfo;
|
||
|
||
} catch (error) {
|
||
console.error('UniApp: 获取安全区域信息失败:', error);
|
||
|
||
// 返回默认值
|
||
return {
|
||
top: 44,
|
||
bottom: 0,
|
||
left: 0,
|
||
right: 0,
|
||
statusBarHeight: 44,
|
||
navBarHeight: 44,
|
||
platform: 'unknown',
|
||
model: 'unknown',
|
||
system: 'unknown',
|
||
screenWidth: 375,
|
||
screenHeight: 667
|
||
};
|
||
}
|
||
},
|
||
|
||
// 根据平台计算安全区域
|
||
calculatePlatformSafeArea(statusBarHeight, systemInfo) {
|
||
const platform = systemInfo.platform.toLowerCase();
|
||
const model = systemInfo.model || '';
|
||
const screenHeight = systemInfo.screenHeight;
|
||
const screenWidth = systemInfo.screenWidth;
|
||
|
||
console.log('UniApp: 平台信息:', { platform, model, screenHeight, screenWidth });
|
||
|
||
// iOS设备
|
||
if (platform === 'ios') {
|
||
// iPhone X及以后的设备(刘海屏)
|
||
if (screenHeight >= 812 || screenWidth >= 812) {
|
||
console.log('UniApp: 检测到iPhone X及以后设备');
|
||
return 44; // iPhone X状态栏高度
|
||
}
|
||
// 传统iPhone设备
|
||
else {
|
||
console.log('UniApp: 检测到传统iPhone设备');
|
||
return statusBarHeight || 20;
|
||
}
|
||
}
|
||
// Android设备
|
||
else if (platform === 'android') {
|
||
// 高分辨率设备可能是刘海屏
|
||
if (screenHeight >= 800 || screenWidth >= 800) {
|
||
console.log('UniApp: 检测到高分辨率Android设备');
|
||
return Math.max(statusBarHeight, 24); // 至少24px
|
||
}
|
||
// 传统Android设备
|
||
else {
|
||
console.log('UniApp: 检测到传统Android设备');
|
||
return statusBarHeight || 24;
|
||
}
|
||
}
|
||
// 其他平台
|
||
else {
|
||
console.log('UniApp: 其他平台设备');
|
||
return statusBarHeight || 20;
|
||
}
|
||
},
|
||
|
||
// 动态设置web-view高度
|
||
setWebViewHeight(height) {
|
||
console.log('设置web-view高度:', height);
|
||
if (this.$refs.webview) {
|
||
// 方法1: 通过style直接设置
|
||
this.$refs.webview.$el.style.height = height + 'px';
|
||
|
||
// 方法2: 通过class设置
|
||
this.$refs.webview.$el.className = 'webview custom-height';
|
||
|
||
// 方法3: 强制重新计算样式
|
||
this.$nextTick(() => {
|
||
this.$refs.webview.$el.style.setProperty('height', height + 'px', 'important');
|
||
});
|
||
}
|
||
},
|
||
|
||
// 设置web-view为全屏
|
||
setWebViewFullscreen() {
|
||
const safeArea = this.getSafeAreaHeight();
|
||
const fullHeight = uni.getSystemInfoSync().windowHeight;
|
||
console.log('设置web-view全屏,高度:', fullHeight);
|
||
this.setWebViewHeight(fullHeight);
|
||
},
|
||
|
||
// 设置web-view为部分高度
|
||
setWebViewPartialHeight(percentage = 0.8) {
|
||
const safeArea = this.getSafeAreaHeight();
|
||
const windowHeight = uni.getSystemInfoSync().windowHeight;
|
||
const partialHeight = windowHeight * percentage;
|
||
console.log('设置web-view部分高度:', partialHeight, '百分比:', percentage);
|
||
this.setWebViewHeight(partialHeight);
|
||
},
|
||
|
||
// 清理资源
|
||
cleanup() {
|
||
if (this.loadingTimer) {
|
||
clearTimeout(this.loadingTimer);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
@import url("index.css");
|
||
</style> |