# 故障恢复机制
> 文档版本：v1.0
> 最后更新：2026-04-02 08:28:05


本文档用于说明当前客户端在“游戏进行中非正常退出”场景下的恢复机制。

目标：

- 明确当前恢复能力边界
- 说明恢复快照保存什么、不保存什么
- 说明恢复流程、清理流程和测试方法

---

## 1. 设计原则

当前恢复机制采用：

`轻量快照恢复，而不是页面状态回放`

原则如下：

- 只恢复核心运行态
- 不恢复瞬时 UI
- 恢复后由规则层和展示层重新计算派生状态
- 恢复失败时允许直接降级回正常开局
- 不为了恢复体验牺牲主流程性能

---

## 2. 当前恢复范围

### 2.1 会恢复的内容

- 当前配置入口
- 当前对局核心状态
- 已完成点 / 已跳过点
- 当前分数
- 开赛时间 / 结束时间 / 结束原因
- 模式状态 `modeState`
- 遥测累计值
- 最后 GPS 点与精度
- 地图基础视口
- GPS 锁定状态

### 2.2 不恢复的内容

- 白色内容卡
- 答题卡中间态
- 黑底引导提示条
- 彩色短反馈条
- 待查看内容入口
- 临时动画和过渡效果
- 各类计时器、定时器、提示队列

说明：

这些内容都属于派生 UI 或瞬时体验，恢复后会重新按当前运行态计算，不直接持久化。

---

## 3. 快照结构

当前恢复快照定义在：

- [sessionRecovery.ts](D:/dev/cmr-mini/miniprogram/game/core/sessionRecovery.ts)

结构分为 4 块：

1. 快照元信息
- `schemaVersion`
- `savedAt`

2. 配置身份
- `launchEnvelope`
- `configAppId`
- `configVersion`

3. 对局核心状态
- `gameState`

4. 运行态附属状态
- `telemetry`
- `viewport`
- `currentGpsPoint`
- `currentGpsAccuracyMeters`
- `currentGpsInsideMap`
- `bonusScore`
- `quizCorrectCount`
- `quizWrongCount`
- `quizTimeoutCount`

---

## 4. 保存时机

当前 V1 保存时机如下：

- 对局进入 `running` 时先保存一次
- 对局进行中按低频节流定时保存
- 页面 `onHide` 时保存一次
- 页面 `onUnload` 时保存一次

当前默认节流周期：

- `5` 秒

说明：

- 不做每帧保存
- 不在所有 GPS 更新时保存
- 只做低频检查点式持久化

---

## 5. 恢复流程

当前恢复流程如下：

1. 页面进入时先解析启动入口
2. 如果没有显式新启动参数，则检查是否存在恢复快照
3. 若存在恢复快照，则优先使用快照中的 `launchEnvelope`
4. 配置加载完成后校验快照身份
5. 若快照属于当前配置，则弹出“继续恢复 / 放弃”确认
6. 用户确认恢复后：
- 先恢复系统设置运行态
- 再恢复 `GameRuntime` 核心状态
- 再恢复 `TelemetryRuntime`
- 再恢复地图视口与 GPS 锁定态
- 最后重新计算 HUD、按钮和提示

恢复相关落点：

- [map.ts](D:/dev/cmr-mini/miniprogram/pages/map/map.ts)
- [mapEngine.ts](D:/dev/cmr-mini/miniprogram/engine/map/mapEngine.ts)
- [gameRuntime.ts](D:/dev/cmr-mini/miniprogram/game/core/gameRuntime.ts)
- [telemetryRuntime.ts](D:/dev/cmr-mini/miniprogram/game/telemetry/telemetryRuntime.ts)

---

## 6. 清理规则

以下情况会清除恢复快照：

- 正常完赛
- 超时结束
- 主动退出
- 用户在恢复确认框中选择“放弃”
- 快照配置身份与当前配置不匹配
- 恢复失败

说明：

恢复快照只服务“未正常结束的进行中对局”。

---

## 7. 当前实现边界

当前 V1 的明确边界是：

- 支持续局
- 不支持恢复答题进行中
- 不支持恢复内容卡浏览进行中
- 不支持恢复弹层堆栈
- 不支持恢复临时 FX 状态

这不是缺陷，而是当前版本的刻意收敛。

---

## 8. 性能策略

当前恢复机制的性能策略如下：

- 快照只存小而必要的结构
- 不重复存整份远端配置 JSON
- 不存派生展示状态
- 不做高频写入
- 恢复后尽量走现有规则重算链

所以这套恢复机制更接近：

`保存运行核心状态 + 重新生成界面`

而不是：

`保存整个页面现场`

---

## 9. 测试建议

### 9.1 基础恢复

1. 开一局并至少完成 1 个点
2. 不正常结束，直接退后台并杀掉程序
3. 再次进入地图页
4. 确认出现恢复提示
5. 点击“继续恢复”
6. 确认分数、已完成点、计时和地图状态都能续上

### 9.2 放弃恢复

1. 重复上面步骤进入恢复提示
2. 点击“放弃”
3. 确认回到正常初始状态
4. 再次进入时不应重复提示

### 9.3 正常结束清理

分别验证：

- 正常打终点结束
- 主动退出
- 超时结束

结果都应为：

- 不再保留恢复快照
- 再次进入不再提示恢复

---

## 10. 后续演进方向

后续如果要继续增强，建议顺序如下：

1. 先补恢复链的 smoke tests
2. 再考虑恢复更多遥测累计细节
3. 最后才考虑是否恢复答题态或内容态

不建议一开始就追求全量 UI 恢复。

---

## 11. 一句话结论

当前故障恢复机制的定位是：

**保证玩家在异常退出后可以继续当前对局，但不承担恢复所有临时界面状态。**


