import { type H5BridgeMessage, type H5ExperienceRequest } from '../../game/experience/h5Experience' type ExperienceWebViewPageData = { pageTitle: string pageSubtitle: string presentation: 'sheet' | 'dialog' | 'fullscreen' webViewSrc: string webViewReady: boolean loadErrorText: string panelBodyHeightPx: number } let currentRequest: H5ExperienceRequest | null = null let currentEventChannel: WechatMiniprogram.EventChannel | null = null let pageResolved = false function appendQueryParam(url: string, key: string, value: string): string { const separator = url.indexOf('?') >= 0 ? '&' : '?' return `${url}${separator}${key}=${encodeURIComponent(value)}` } function buildWebViewSrc(request: H5ExperienceRequest): string { let nextUrl = request.url nextUrl = appendQueryParam(nextUrl, 'cmrBridge', request.bridgeVersion) nextUrl = appendQueryParam(nextUrl, 'cmrKind', request.kind) return nextUrl } function emitFallbackAndClose() { if (!currentRequest || !currentEventChannel) { return } if (!pageResolved) { pageResolved = true currentEventChannel.emit('fallback', currentRequest.fallback) } wx.navigateBack({ fail: () => {}, }) } function emitCloseAndBack(payload?: Record) { if (currentEventChannel && !pageResolved) { pageResolved = true currentEventChannel.emit('close', payload || {}) } wx.navigateBack({ fail: () => {}, }) } Page({ data: { pageTitle: '内容体验', pageSubtitle: '', presentation: 'sheet', webViewSrc: '', webViewReady: false, loadErrorText: '', panelBodyHeightPx: 420, }, onLoad() { const systemInfo = wx.getSystemInfoSync() const windowHeight = typeof systemInfo.windowHeight === 'number' ? systemInfo.windowHeight : 700 pageResolved = false currentRequest = null currentEventChannel = null this.setData({ pageTitle: '内容体验', pageSubtitle: '', presentation: 'sheet', webViewSrc: '', webViewReady: false, loadErrorText: '', panelBodyHeightPx: Math.max(420, Math.floor(windowHeight * 0.62)), }) try { currentEventChannel = this.getOpenerEventChannel() } catch { currentEventChannel = null } if (!currentEventChannel) { return } currentEventChannel.on('init', (request: H5ExperienceRequest) => { currentRequest = request const presentation = request.presentation || 'sheet' const panelHeightPx = presentation === 'dialog' ? Math.max(420, Math.floor(windowHeight * 0.7)) : presentation === 'fullscreen' ? Math.max(520, windowHeight - 24) : Math.max(420, Math.floor(windowHeight * 0.72)) const headerHeightPx = presentation === 'fullscreen' ? 84 : 76 this.setData({ pageTitle: request.title || '内容体验', pageSubtitle: request.subtitle || '', presentation, webViewSrc: buildWebViewSrc(request), webViewReady: true, loadErrorText: '', panelBodyHeightPx: Math.max(240, panelHeightPx - headerHeightPx), }) }) }, onUnload() { if (currentEventChannel && !pageResolved) { currentEventChannel.emit('close', {}) } pageResolved = false currentRequest = null currentEventChannel = null }, handleWebViewMessage(event: WechatMiniprogram.CustomEvent) { const dataList = event.detail && Array.isArray(event.detail.data) ? event.detail.data : [] const rawMessage = dataList.length ? dataList[dataList.length - 1] : null if (!rawMessage || typeof rawMessage !== 'object') { return } const message = rawMessage as H5BridgeMessage const action = message.action || message.type || '' if (!action) { return } if (action === 'close') { emitCloseAndBack(message.payload) return } if (action === 'submitResult') { if (currentEventChannel) { currentEventChannel.emit('submitResult', message.payload || {}) } return } if (action === 'fallback') { emitFallbackAndClose() } }, handleWebViewError() { this.setData({ loadErrorText: '页面打开失败,已回退原生内容', }) emitFallbackAndClose() }, handleCloseTap() { emitCloseAndBack({}) }, })