import { loadBackendAuthTokens, loadBackendBaseUrl } from '../../utils/backendAuth' import { getSessionResult } from '../../utils/backendApi' import type { MapEngineResultSnapshot } from '../../engine/map/mapEngine' import type { GameLaunchEnvelope } from '../../utils/gameLaunch' type ResultPageData = { sessionId: string statusText: string sessionTitleText: string sessionSubtitleText: string rows: Array<{ label: string; value: string }> } function getAccessToken(): string | null { const app = getApp() const tokens = app.globalData && app.globalData.backendAuthTokens ? app.globalData.backendAuthTokens : loadBackendAuthTokens() return tokens && tokens.accessToken ? tokens.accessToken : null } function formatValue(value: unknown): string { if (value === null || value === undefined || value === '') { return '--' } return String(value) } function formatRouteSummary(input: { variantName?: string | null routeCode?: string | null }): string { if (input.variantName && input.routeCode) { return `${input.variantName} / ${input.routeCode}` } if (input.variantName) { return input.variantName } if (input.routeCode) { return input.routeCode } return '默认赛道' } function formatRuntimeValue(...candidates: Array): string { for (let index = 0; index < candidates.length; index += 1) { const value = candidates[index] if (typeof value === 'string' && value.trim().length > 0) { return value.trim() } } return '--' } function appendRuntimeRows( rows: Array<{ label: string; value: string }>, options: { runtime?: { runtimeBindingId?: string | null placeId?: string | null placeName?: string | null mapId?: string | null mapName?: string | null tileReleaseId?: string | null courseSetId?: string | null courseVariantId?: string | null routeCode?: string | null } | null variantName?: string | null routeCode?: string | null }, ) { if (!options.runtime) { return rows } return rows.concat([ { label: '运行绑定', value: formatRuntimeValue(options.runtime.runtimeBindingId) }, { label: '地点', value: formatRuntimeValue(options.runtime.placeName, options.runtime.placeId) }, { label: '地图', value: formatRuntimeValue(options.runtime.mapName, options.runtime.mapId) }, { label: '赛道集', value: formatRuntimeValue(options.runtime.courseSetId) }, { label: '赛道版本', value: formatRuntimeValue(options.runtime.courseVariantId, options.variantName) }, { label: 'RouteCode', value: formatRuntimeValue(options.runtime.routeCode, options.routeCode) }, { label: '瓦片版本', value: formatRuntimeValue(options.runtime.tileReleaseId) }, ]) } function loadPendingResultLaunchEnvelope(): GameLaunchEnvelope | null { const app = getApp() return app.globalData && app.globalData.pendingResultLaunchEnvelope ? app.globalData.pendingResultLaunchEnvelope : null } Page({ data: { sessionId: '', statusText: '准备加载结果', sessionTitleText: '结果页', sessionSubtitleText: '未加载', rows: [], } as ResultPageData, onLoad(query: { sessionId?: string }) { const sessionId = query && query.sessionId ? decodeURIComponent(query.sessionId) : '' this.setData({ sessionId }) this.applyPendingResultSnapshot() if (sessionId) { this.loadSingleResult(sessionId) return } this.setData({ statusText: '未提供单局会话,已跳转历史结果', }) wx.redirectTo({ url: '/pages/results/results', }) }, applyPendingResultSnapshot() { const app = getApp() const snapshot = app.globalData && app.globalData.pendingResultSnapshot ? app.globalData.pendingResultSnapshot as MapEngineResultSnapshot : null if (!snapshot) { return } const pendingLaunchEnvelope = loadPendingResultLaunchEnvelope() this.setData({ statusText: '正在加载结果', sessionTitleText: snapshot.title, sessionSubtitleText: snapshot.subtitle, rows: appendRuntimeRows([ { label: snapshot.heroLabel, value: snapshot.heroValue }, ...snapshot.rows.map((row) => ({ label: row.label, value: row.value, })), ], { runtime: pendingLaunchEnvelope && pendingLaunchEnvelope.runtime ? pendingLaunchEnvelope.runtime : null, variantName: pendingLaunchEnvelope && pendingLaunchEnvelope.variant ? pendingLaunchEnvelope.variant.variantName : null, routeCode: pendingLaunchEnvelope && pendingLaunchEnvelope.variant ? pendingLaunchEnvelope.variant.routeCode : null, }), }) if (app.globalData) { app.globalData.pendingResultSnapshot = null } }, async loadSingleResult(sessionId: string) { const accessToken = getAccessToken() if (!accessToken) { wx.redirectTo({ url: '/pages/login/login' }) return } this.setData({ statusText: '正在加载单局结果', }) try { const result = await getSessionResult({ baseUrl: loadBackendBaseUrl(), accessToken, sessionId, }) const pendingLaunchEnvelope = loadPendingResultLaunchEnvelope() this.setData({ statusText: '单局结果加载完成', sessionTitleText: result.session.eventName || result.session.eventDisplayName || result.session.eventId || result.session.id || result.session.sessionId, sessionSubtitleText: `${result.session.status || result.session.sessionStatus} / ${result.result.status} / ${formatRouteSummary(result.session)}`, rows: appendRuntimeRows([ { label: '赛道版本', value: formatRouteSummary(result.session) }, { label: '最终得分', value: formatValue(result.result.finalScore) }, { label: '最终用时(秒)', value: formatValue(result.result.finalDurationSec) }, { label: '完成点数', value: formatValue(result.result.completedControls) }, { label: '总点数', value: formatValue(result.result.totalControls) }, { label: '累计里程(m)', value: formatValue(result.result.distanceMeters) }, { label: '平均速度(km/h)', value: formatValue(result.result.averageSpeedKmh) }, { label: '最大心率', value: formatValue(result.result.maxHeartRateBpm) }, ], { runtime: result.session.runtime || (pendingLaunchEnvelope && pendingLaunchEnvelope.runtime ? pendingLaunchEnvelope.runtime : null), variantName: result.session.variantName || (pendingLaunchEnvelope && pendingLaunchEnvelope.variant ? pendingLaunchEnvelope.variant.variantName : null), routeCode: result.session.routeCode || (pendingLaunchEnvelope && pendingLaunchEnvelope.variant ? pendingLaunchEnvelope.variant.routeCode : null), }), }) const app = getApp() if (app.globalData) { app.globalData.pendingResultLaunchEnvelope = null } } catch (error) { const message = error && (error as { message?: string }).message ? (error as { message: string }).message : '未知错误' this.setData({ statusText: `结果加载失败:${message}`, }) } }, handleBackToList() { wx.redirectTo({ url: '/pages/results/results', }) }, })