283 lines
8.7 KiB
TypeScript
283 lines
8.7 KiB
TypeScript
import { clearBackendAuthTokens, loadBackendAuthTokens, loadBackendBaseUrl } from '../../utils/backendAuth'
|
|
import { finishSession, getEntryHome, type BackendCardResult, type BackendEntryHomeResult } from '../../utils/backendApi'
|
|
import { reportBackendClientLog } from '../../utils/backendClientLogs'
|
|
import { setGlobalMockDebugBridgeEnabled } from '../../utils/globalMockDebugBridge'
|
|
import { clearSessionRecoverySnapshot, loadSessionRecoverySnapshot } from '../../game/core/sessionRecovery'
|
|
import { getBackendSessionContextFromLaunchEnvelope, prepareMapPageUrlForRecovery } from '../../utils/gameLaunch'
|
|
|
|
const DEFAULT_CHANNEL_CODE = 'mini-demo'
|
|
const DEFAULT_CHANNEL_TYPE = 'wechat_mini'
|
|
|
|
type HomePageData = {
|
|
loading: boolean
|
|
statusText: string
|
|
userNameText: string
|
|
tenantText: string
|
|
channelText: string
|
|
ongoingSessionText: string
|
|
recentSessionText: string
|
|
ongoingRuntimeText: string
|
|
recentRuntimeText: string
|
|
ongoingActionHintText: string
|
|
showOngoingPanel: boolean
|
|
canRecoverOngoing: boolean
|
|
canAbandonOngoing: boolean
|
|
cards: BackendCardResult[]
|
|
}
|
|
|
|
function formatSessionSummary(session?: BackendEntryHomeResult['ongoingSession'] | null): string {
|
|
if (!session) {
|
|
return '无'
|
|
}
|
|
|
|
const title = session.eventName || session.eventDisplayName || session.eventId || session.id || session.sessionId
|
|
const status = session.status || session.sessionStatus || '--'
|
|
const route = session.routeCode || session.variantName || '默认赛道'
|
|
return `${title} / ${status} / ${route}`
|
|
}
|
|
|
|
function formatRuntimeSummary(session?: BackendEntryHomeResult['ongoingSession'] | null): string {
|
|
if (!session || !session.runtime) {
|
|
return '运行对象 --'
|
|
}
|
|
|
|
const runtime = session.runtime
|
|
const placeText = runtime.placeName || runtime.placeId || '--'
|
|
const mapText = runtime.mapName || runtime.mapId || '--'
|
|
const variantText = runtime.courseVariantId || session.variantName || session.variantId || '--'
|
|
return `地点 ${placeText} / 地图 ${mapText} / 赛道 ${variantText}`
|
|
}
|
|
|
|
function requireAuthToken(): string | null {
|
|
const app = getApp<IAppOption>()
|
|
const tokens = app.globalData && app.globalData.backendAuthTokens
|
|
? app.globalData.backendAuthTokens
|
|
: loadBackendAuthTokens()
|
|
return tokens && tokens.accessToken ? tokens.accessToken : null
|
|
}
|
|
|
|
function getRecoverySnapshotSessionId(): string {
|
|
const snapshot = loadSessionRecoverySnapshot()
|
|
if (!snapshot) {
|
|
return ''
|
|
}
|
|
const context = getBackendSessionContextFromLaunchEnvelope(snapshot.launchEnvelope)
|
|
return context && context.sessionId ? context.sessionId : ''
|
|
}
|
|
|
|
Page({
|
|
data: {
|
|
loading: false,
|
|
statusText: '准备加载首页',
|
|
userNameText: '--',
|
|
tenantText: '--',
|
|
channelText: '--',
|
|
ongoingSessionText: '无',
|
|
recentSessionText: '无',
|
|
ongoingRuntimeText: '运行对象 --',
|
|
recentRuntimeText: '运行对象 --',
|
|
ongoingActionHintText: '当前没有可恢复的进行中对局',
|
|
showOngoingPanel: false,
|
|
canRecoverOngoing: false,
|
|
canAbandonOngoing: false,
|
|
cards: [],
|
|
} as HomePageData,
|
|
|
|
onLoad() {
|
|
this.loadEntryHome()
|
|
},
|
|
|
|
onShow() {
|
|
this.loadEntryHome()
|
|
},
|
|
|
|
async loadEntryHome() {
|
|
const accessToken = requireAuthToken()
|
|
if (!accessToken) {
|
|
wx.redirectTo({ url: '/pages/login/login' })
|
|
return
|
|
}
|
|
|
|
this.setData({
|
|
loading: true,
|
|
statusText: '正在加载首页聚合',
|
|
})
|
|
|
|
try {
|
|
const result = await getEntryHome({
|
|
baseUrl: loadBackendBaseUrl(),
|
|
accessToken,
|
|
channelCode: DEFAULT_CHANNEL_CODE,
|
|
channelType: DEFAULT_CHANNEL_TYPE,
|
|
})
|
|
this.applyEntryHomeResult(result)
|
|
} catch (error) {
|
|
const message = error && (error as { message?: string }).message ? (error as { message: string }).message : '未知错误'
|
|
this.setData({
|
|
loading: false,
|
|
statusText: `首页加载失败:${message}`,
|
|
})
|
|
}
|
|
},
|
|
|
|
applyEntryHomeResult(result: BackendEntryHomeResult) {
|
|
const ongoingSession = result.ongoingSession || null
|
|
const recoverySnapshotSessionId = getRecoverySnapshotSessionId()
|
|
const canRecoverOngoing = !!ongoingSession && !!recoverySnapshotSessionId
|
|
&& ongoingSession.id === recoverySnapshotSessionId
|
|
const canAbandonOngoing = canRecoverOngoing
|
|
const ongoingActionHintText = !ongoingSession
|
|
? '当前没有可恢复的进行中对局'
|
|
: canRecoverOngoing
|
|
? '检测到本机仍保留这局的恢复记录,你可以继续恢复或主动放弃。'
|
|
: '检测到后端存在进行中对局,但本机当前没有匹配的恢复快照。'
|
|
reportBackendClientLog({
|
|
level: 'info',
|
|
category: 'entry-home',
|
|
message: 'entry home loaded',
|
|
details: {
|
|
ongoingSessionId: result.ongoingSession && result.ongoingSession.id ? result.ongoingSession.id : '',
|
|
ongoingEventId: result.ongoingSession && result.ongoingSession.eventId ? result.ongoingSession.eventId : '',
|
|
recentSessionId: result.recentSession && result.recentSession.id ? result.recentSession.id : '',
|
|
recentEventId: result.recentSession && result.recentSession.eventId ? result.recentSession.eventId : '',
|
|
cardEventIds: (result.cards || []).map((item) => (item.event && item.event.id ? item.event.id : '')),
|
|
hasOngoingSession: !!ongoingSession,
|
|
recoverySnapshotSessionId,
|
|
canRecoverOngoing,
|
|
},
|
|
})
|
|
this.setData({
|
|
loading: false,
|
|
statusText: '首页加载完成',
|
|
userNameText: result.user.nickname || result.user.publicId || result.user.id,
|
|
tenantText: `${result.tenant.name} (${result.tenant.code})`,
|
|
channelText: `${result.channel.displayName} / ${result.channel.code}`,
|
|
ongoingSessionText: formatSessionSummary(result.ongoingSession),
|
|
recentSessionText: formatSessionSummary(result.recentSession),
|
|
ongoingRuntimeText: formatRuntimeSummary(result.ongoingSession),
|
|
recentRuntimeText: formatRuntimeSummary(result.recentSession),
|
|
ongoingActionHintText,
|
|
showOngoingPanel: !!ongoingSession,
|
|
canRecoverOngoing,
|
|
canAbandonOngoing,
|
|
cards: result.cards || [],
|
|
})
|
|
},
|
|
|
|
handleRefresh() {
|
|
this.loadEntryHome()
|
|
},
|
|
|
|
handleOpenCard(event: WechatMiniprogram.TouchEvent) {
|
|
const eventId = event.currentTarget.dataset.eventId as string | undefined
|
|
if (!eventId) {
|
|
wx.showToast({
|
|
title: '该卡片暂无活动入口',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
wx.navigateTo({
|
|
url: `/pages/event/event?eventId=${encodeURIComponent(eventId)}`,
|
|
})
|
|
},
|
|
|
|
handleOpenRecentResult() {
|
|
wx.navigateTo({
|
|
url: '/pages/results/results',
|
|
})
|
|
},
|
|
|
|
handleOpenEventList() {
|
|
wx.navigateTo({
|
|
url: '/pages/events/events',
|
|
})
|
|
},
|
|
|
|
handleOpenExperienceMaps() {
|
|
wx.navigateTo({
|
|
url: '/pages/experience-maps/experience-maps',
|
|
})
|
|
},
|
|
|
|
handleResumeOngoing() {
|
|
const snapshot = loadSessionRecoverySnapshot()
|
|
if (!snapshot) {
|
|
wx.showToast({
|
|
title: '本机未找到恢复快照',
|
|
icon: 'none',
|
|
})
|
|
this.loadEntryHome()
|
|
return
|
|
}
|
|
|
|
wx.navigateTo({
|
|
url: prepareMapPageUrlForRecovery(snapshot.launchEnvelope),
|
|
})
|
|
},
|
|
|
|
handleAbandonOngoing() {
|
|
const snapshot = loadSessionRecoverySnapshot()
|
|
if (!snapshot) {
|
|
wx.showToast({
|
|
title: '本机未找到恢复快照',
|
|
icon: 'none',
|
|
})
|
|
this.loadEntryHome()
|
|
return
|
|
}
|
|
|
|
const sessionContext = getBackendSessionContextFromLaunchEnvelope(snapshot.launchEnvelope)
|
|
if (!sessionContext) {
|
|
clearSessionRecoverySnapshot()
|
|
wx.showToast({
|
|
title: '已清理本机恢复记录',
|
|
icon: 'none',
|
|
})
|
|
this.loadEntryHome()
|
|
return
|
|
}
|
|
|
|
wx.showModal({
|
|
title: '放弃进行中的游戏',
|
|
content: '放弃后,这局游戏会记为已取消,且不会再出现在“进行中”。',
|
|
confirmText: '确认放弃',
|
|
cancelText: '先保留',
|
|
success: (result) => {
|
|
if (!result.confirm) {
|
|
return
|
|
}
|
|
|
|
finishSession({
|
|
baseUrl: loadBackendBaseUrl(),
|
|
sessionId: sessionContext.sessionId,
|
|
sessionToken: sessionContext.sessionToken,
|
|
status: 'cancelled',
|
|
summary: {},
|
|
}).catch(() => {
|
|
wx.showToast({
|
|
title: '取消上报失败,请稍后重试',
|
|
icon: 'none',
|
|
})
|
|
}).finally(() => {
|
|
clearSessionRecoverySnapshot()
|
|
this.loadEntryHome()
|
|
})
|
|
},
|
|
})
|
|
},
|
|
|
|
handleLogout() {
|
|
clearBackendAuthTokens()
|
|
setGlobalMockDebugBridgeEnabled(false)
|
|
const app = getApp<IAppOption>()
|
|
if (app.globalData) {
|
|
app.globalData.backendAuthTokens = null
|
|
}
|
|
wx.redirectTo({
|
|
url: '/pages/login/login',
|
|
})
|
|
},
|
|
})
|