调整支付
This commit is contained in:
parent
0cdce6446b
commit
50493a570a
@ -13,7 +13,26 @@
|
||||
</view>
|
||||
|
||||
<view class="scrollable-content">
|
||||
<web-view :src="payUrl"></web-view>
|
||||
<!-- H5环境下的处理 -->
|
||||
<view v-if="isH5" class="h5-payment-container">
|
||||
<view class="payment-info">
|
||||
<view class="payment-title">支付信息</view>
|
||||
<view class="payment-url">{{ payUrl }}</view>
|
||||
</view>
|
||||
<view class="payment-actions">
|
||||
<button class="open-payment-btn" @click="openPaymentUrl">打开支付页面</button>
|
||||
<button class="copy-url-btn" @click="copyPaymentUrl">复制支付链接</button>
|
||||
</view>
|
||||
<view class="payment-tips">
|
||||
<text>提示:</text>
|
||||
<text>1. 点击"打开支付页面"按钮在新窗口打开支付</text>
|
||||
<text>2. 支付完成后请返回此页面</text>
|
||||
<text>3. 如无法打开,请复制链接到浏览器中打开</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 非H5环境使用web-view -->
|
||||
<web-view v-else :src="payUrl" @error="handleWebViewError" class="payment-webview"></web-view>
|
||||
</view>
|
||||
|
||||
<!-- 底部支付区域 -->
|
||||
@ -34,6 +53,228 @@ const { getCurXs, initWs, setWsCallback } = useUserStore();
|
||||
const { getData } = useDataStore();
|
||||
|
||||
const payUrl = ref("");
|
||||
const isH5 = ref(false);
|
||||
let webViewObserver: any = null;
|
||||
|
||||
// 检测是否为H5环境
|
||||
const checkPlatform = () => {
|
||||
// #ifdef H5
|
||||
isH5.value = true;
|
||||
// #endif
|
||||
};
|
||||
|
||||
// 打开支付URL
|
||||
const openPaymentUrl = () => {
|
||||
if (payUrl.value) {
|
||||
// 在新窗口打开支付页面
|
||||
window.open(payUrl.value, '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
// 复制支付URL
|
||||
const copyPaymentUrl = () => {
|
||||
if (payUrl.value) {
|
||||
// #ifdef H5
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(payUrl.value).then(() => {
|
||||
uni.showToast({
|
||||
title: '链接已复制',
|
||||
icon: 'success'
|
||||
});
|
||||
}).catch(() => {
|
||||
// 降级处理
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = payUrl.value;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
uni.showToast({
|
||||
title: '链接已复制',
|
||||
icon: 'success'
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 降级处理
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = payUrl.value;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
uni.showToast({
|
||||
title: '链接已复制',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
};
|
||||
|
||||
// web-view错误处理
|
||||
const handleWebViewError = (e: any) => {
|
||||
console.error('web-view加载错误:', e);
|
||||
uni.showModal({
|
||||
title: '加载失败',
|
||||
content: '支付页面加载失败,请检查网络连接或联系客服',
|
||||
showCancel: false
|
||||
});
|
||||
};
|
||||
|
||||
// 检查并修复z-index冲突
|
||||
const fixZIndexConflicts = () => {
|
||||
// #ifdef H5
|
||||
const iframes = document.querySelectorAll('iframe');
|
||||
iframes.forEach((iframe) => {
|
||||
if (iframe.src && iframe.src.includes('payweb')) {
|
||||
// 确保iframe有最高z-index
|
||||
(iframe as HTMLElement).style.zIndex = '999999';
|
||||
|
||||
// 查找所有可能覆盖iframe的元素
|
||||
const allElements = document.querySelectorAll('*');
|
||||
allElements.forEach((element) => {
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
const zIndex = parseInt(computedStyle.zIndex);
|
||||
if (zIndex >= 999999 && element !== iframe) {
|
||||
(element as HTMLElement).style.zIndex = '1';
|
||||
console.log('修复z-index冲突:', element.tagName, element.className);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
};
|
||||
|
||||
// 修复web-view样式
|
||||
const fixWebViewStyle = () => {
|
||||
// #ifdef H5
|
||||
setTimeout(() => {
|
||||
const iframes = document.querySelectorAll('iframe');
|
||||
iframes.forEach((iframe) => {
|
||||
if (iframe.src && iframe.src.includes('payweb')) {
|
||||
// 由于iframe被提升到body层级,我们需要计算正确的位置和尺寸
|
||||
const appElement = document.getElementById('app');
|
||||
const countdownSection = document.querySelector('.countdown-section');
|
||||
const paymentFooter = document.querySelector('.payment-footer');
|
||||
|
||||
if (appElement && countdownSection && paymentFooter) {
|
||||
const appRect = appElement.getBoundingClientRect();
|
||||
const countdownRect = countdownSection.getBoundingClientRect();
|
||||
const footerRect = paymentFooter.getBoundingClientRect();
|
||||
|
||||
// 考虑安全区域和状态栏
|
||||
const safeAreaTop = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--status-bar-height') || '0');
|
||||
const safeAreaBottom = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--window-bottom') || '0');
|
||||
|
||||
// 计算iframe应该的位置和尺寸
|
||||
const top = countdownRect.bottom + safeAreaTop;
|
||||
const left = appRect.left;
|
||||
const width = appRect.width;
|
||||
const height = footerRect.top - countdownRect.bottom - safeAreaBottom;
|
||||
|
||||
// 设置iframe样式,确保最高层级
|
||||
iframe.style.position = 'fixed';
|
||||
iframe.style.top = `${top}px`;
|
||||
iframe.style.left = `${left}px`;
|
||||
iframe.style.width = `${width}px`;
|
||||
iframe.style.height = `${Math.max(height, 100)}px`; // 确保最小高度
|
||||
iframe.style.border = 'none';
|
||||
iframe.style.margin = '0';
|
||||
iframe.style.padding = '0';
|
||||
iframe.style.zIndex = '999999'; // 使用更高的z-index
|
||||
iframe.style.backgroundColor = '#fff';
|
||||
iframe.style.pointerEvents = 'auto';
|
||||
|
||||
// 强制设置iframe为最高层级
|
||||
iframe.style.zIndex = '999999';
|
||||
|
||||
// 检查并降低其他可能覆盖的元素层级
|
||||
const potentialOverlays = document.querySelectorAll('.payment-footer, .countdown-section, .payment-page, [style*="z-index"]');
|
||||
potentialOverlays.forEach((element) => {
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
const currentZIndex = parseInt(computedStyle.zIndex) || 0;
|
||||
if (currentZIndex >= 999999) {
|
||||
(element as HTMLElement).style.zIndex = '1';
|
||||
console.log('降低元素z-index:', element.tagName, element.className);
|
||||
}
|
||||
});
|
||||
|
||||
// 确保iframe可见
|
||||
iframe.style.display = 'block';
|
||||
iframe.style.visibility = 'visible';
|
||||
iframe.style.opacity = '1';
|
||||
|
||||
console.log('已修复web-view样式,定位到正确区域', {
|
||||
top, left, width, height,
|
||||
zIndex: iframe.style.zIndex,
|
||||
display: iframe.style.display,
|
||||
visibility: iframe.style.visibility
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 额外检查z-index冲突
|
||||
fixZIndexConflicts();
|
||||
}, 100);
|
||||
// #endif
|
||||
};
|
||||
|
||||
// 监听DOM变化,持续修复web-view样式
|
||||
const observeWebView = () => {
|
||||
// #ifdef H5
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.type === 'childList') {
|
||||
mutation.addedNodes.forEach((node) => {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const element = node as Element;
|
||||
if (element.tagName === 'IFRAME') {
|
||||
setTimeout(() => {
|
||||
fixWebViewStyle();
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
// 监听窗口大小变化
|
||||
const handleResize = () => {
|
||||
setTimeout(() => {
|
||||
fixWebViewStyle();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
// 定期检查z-index冲突
|
||||
const checkZIndexConflicts = () => {
|
||||
fixZIndexConflicts();
|
||||
};
|
||||
|
||||
// 每2秒检查一次z-index冲突
|
||||
const zIndexInterval = setInterval(checkZIndexConflicts, 2000);
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener('orientationchange', handleResize);
|
||||
|
||||
return {
|
||||
observer,
|
||||
cleanup: () => {
|
||||
observer.disconnect();
|
||||
window.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener('orientationchange', handleResize);
|
||||
clearInterval(zIndexInterval);
|
||||
}
|
||||
};
|
||||
// #endif
|
||||
};
|
||||
|
||||
setWsCallback((type: string, res: any) => {
|
||||
console.log('收到WebSocket消息:', type, res.data);
|
||||
// 将data从字符串转为对象
|
||||
@ -109,12 +350,25 @@ const cancelRegistration = () => {
|
||||
};
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
// 检测平台
|
||||
checkPlatform();
|
||||
|
||||
if (options.payUrl) {
|
||||
payUrl.value = decodeURIComponent(options.payUrl);
|
||||
const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
|
||||
seconds = res.result;
|
||||
initWs();
|
||||
startCountdown();
|
||||
|
||||
// 修复web-view样式
|
||||
if (!isH5.value) {
|
||||
setTimeout(() => {
|
||||
fixWebViewStyle();
|
||||
}, 500);
|
||||
|
||||
// 启动DOM监听
|
||||
webViewObserver = observeWebView();
|
||||
}
|
||||
} else {
|
||||
uni.showToast({ title: '缺少支付地址', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
@ -157,17 +411,41 @@ onBeforeUnmount(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
|
||||
// 清理DOM监听器
|
||||
if (webViewObserver) {
|
||||
if (webViewObserver.cleanup) {
|
||||
webViewObserver.cleanup();
|
||||
} else {
|
||||
webViewObserver.disconnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.payment-page {
|
||||
min-height: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
// 确保布局正确
|
||||
.countdown-section {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.scrollable-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.payment-footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 可滚动内容区域样式
|
||||
@ -176,11 +454,126 @@ onBeforeUnmount(() => {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// web-view样式修复
|
||||
.payment-webview {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
position: relative !important;
|
||||
border: none !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
z-index: 1;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
// 确保web-view容器正确显示
|
||||
.scrollable-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
|
||||
// 当显示web-view时,隐藏其他内容
|
||||
&:has(.payment-webview) {
|
||||
.h5-payment-container {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// web-view容器样式
|
||||
.payment-webview {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
// H5支付容器样式
|
||||
.h5-payment-container {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
margin: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.payment-info {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.payment-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.payment-url {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
word-break: break-all;
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.open-payment-btn {
|
||||
background-color: #2879ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.copy-url-btn {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.payment-tips {
|
||||
background-color: #fff7e6;
|
||||
border: 1px solid #ffd591;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #d46b08;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 5px;
|
||||
|
||||
&:first-child {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.countdown-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
background-color: #2879ff;
|
||||
z-index: 1; // 确保不会覆盖iframe
|
||||
|
||||
.countdown-icon {
|
||||
margin-right: 10px;
|
||||
@ -204,6 +597,82 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// H5支付容器样式
|
||||
.h5-payment-container {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
margin: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.payment-info {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.payment-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.payment-url {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
word-break: break-all;
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.open-payment-btn {
|
||||
background-color: #2879ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.copy-url-btn {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.payment-tips {
|
||||
background-color: #fff7e6;
|
||||
border: 1px solid #ffd591;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
|
||||
text {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #d46b08;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 5px;
|
||||
|
||||
&:first-child {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.payment-footer {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
@ -212,6 +681,7 @@ onBeforeUnmount(() => {
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||
z-index: 1; // 确保不会覆盖iframe
|
||||
|
||||
.total-amount {
|
||||
display: flex;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user