推进活动系统最小成品闭环与游客体验

This commit is contained in:
2026-04-07 19:05:18 +08:00
parent 1a6008449e
commit 6cd16f08dd
102 changed files with 16087 additions and 3556 deletions

View File

@@ -1,7 +1,9 @@
import { clearBackendAuthTokens, loadBackendAuthTokens, loadBackendBaseUrl } from '../../utils/backendAuth'
import { getEntryHome, type BackendCardResult, type BackendEntryHomeResult } from '../../utils/backendApi'
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'
@@ -16,6 +18,10 @@ type HomePageData = {
recentSessionText: string
ongoingRuntimeText: string
recentRuntimeText: string
ongoingActionHintText: string
showOngoingPanel: boolean
canRecoverOngoing: boolean
canAbandonOngoing: boolean
cards: BackendCardResult[]
}
@@ -50,6 +56,15 @@ function requireAuthToken(): string | null {
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,
@@ -61,6 +76,10 @@ Page({
recentSessionText: '无',
ongoingRuntimeText: '运行对象 --',
recentRuntimeText: '运行对象 --',
ongoingActionHintText: '当前没有可恢复的进行中对局',
showOngoingPanel: false,
canRecoverOngoing: false,
canAbandonOngoing: false,
cards: [],
} as HomePageData,
@@ -102,6 +121,16 @@ Page({
},
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',
@@ -112,6 +141,9 @@ Page({
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({
@@ -124,6 +156,10 @@ Page({
recentSessionText: formatSessionSummary(result.recentSession),
ongoingRuntimeText: formatRuntimeSummary(result.ongoingSession),
recentRuntimeText: formatRuntimeSummary(result.recentSession),
ongoingActionHintText,
showOngoingPanel: !!ongoingSession,
canRecoverOngoing,
canAbandonOngoing,
cards: result.cards || [],
})
},
@@ -159,6 +195,79 @@ Page({
})
},
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)

View File

@@ -10,18 +10,31 @@
<view class="panel">
<view class="panel__title">当前状态</view>
<view class="summary">{{statusText}}</view>
<view class="summary">进行中:{{ongoingSessionText}}</view>
<view class="summary">进行中运行对象:{{ongoingRuntimeText}}</view>
<view wx:if="{{showOngoingPanel}}" class="summary">进行中:{{ongoingSessionText}}</view>
<view wx:if="{{showOngoingPanel}}" class="summary">进行中运行对象:{{ongoingRuntimeText}}</view>
<view wx:if="{{showOngoingPanel}}" class="summary">{{ongoingActionHintText}}</view>
<view class="summary">最近一局:{{recentSessionText}}</view>
<view class="summary">最近一局运行对象:{{recentRuntimeText}}</view>
<view class="actions">
<button class="btn btn--secondary" bindtap="handleRefresh">刷新首页</button>
<button class="btn btn--ghost" bindtap="handleOpenEventList">活动列表</button>
<button class="btn btn--ghost" bindtap="handleOpenExperienceMaps">地图体验</button>
<button class="btn btn--ghost" bindtap="handleOpenRecentResult">查看结果</button>
<button class="btn btn--ghost" bindtap="handleLogout">退出登录</button>
</view>
</view>
<view wx:if="{{showOngoingPanel}}" class="panel">
<view class="panel__title">进行中的游戏</view>
<view class="summary">{{ongoingSessionText}}</view>
<view class="summary">{{ongoingRuntimeText}}</view>
<view class="summary">{{ongoingActionHintText}}</view>
<view class="actions">
<button class="btn btn--secondary" bindtap="handleResumeOngoing" disabled="{{!canRecoverOngoing}}">恢复</button>
<button class="btn btn--ghost" bindtap="handleAbandonOngoing" disabled="{{!canAbandonOngoing}}">放弃</button>
</view>
</view>
<view class="panel">
<view class="panel__title">活动入口</view>
<view wx:if="{{!cards.length}}" class="summary">当前没有首页卡片</view>