From 50493a570a23b56a774009b2c58b0be236e40c2b Mon Sep 17 00:00:00 2001 From: ywyonui Date: Tue, 5 Aug 2025 12:41:14 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/base/course-selection/pay-wait.vue | 476 ++++++++++++++++++- 1 file changed, 473 insertions(+), 3 deletions(-) diff --git a/src/pages/base/course-selection/pay-wait.vue b/src/pages/base/course-selection/pay-wait.vue index 2a98c56..d13a0e9 100644 --- a/src/pages/base/course-selection/pay-wait.vue +++ b/src/pages/base/course-selection/pay-wait.vue @@ -13,7 +13,26 @@ - + + + + 支付信息 + {{ payUrl }} + + + + + + + 提示: + 1. 点击"打开支付页面"按钮在新窗口打开支付 + 2. 支付完成后请返回此页面 + 3. 如无法打开,请复制链接到浏览器中打开 + + + + + @@ -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(); + } + } });