Files
cmr-mini/backend/docs/核心流程.md

309 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 核心流程
> 文档版本v1.3
> 最后更新2026-04-03 18:16:19
## 1. 总流程
```mermaid
flowchart LR
A["Entry Resolve"] --> B["Auth"]
B --> C["Home / Cards"]
C --> D["Event Play"]
D --> E["Resolve Release"]
E --> F["Launch Session"]
F --> G["Client Load Manifest"]
G --> H["Session Start / Finish"]
H --> I["Result / History"]
```
补充说明:
- 这条主流程既服务当前小程序,也要服务未来 APP
- 终端差异主要体现在登录方式、设备能力和运行时 UI不应拆成两套业务流程
## 2. 入口解析
入口层先解决:
- 用户从哪个渠道进来
- 当前归属哪个 `tenant`
- 当前品牌壳和首页卡片应该加载什么
当前对应接口:
- `GET /entry/resolve`
- `GET /home`
- `GET /cards`
- `GET /me/entry-home`
## 3. 登录流程
### 3.1 APP
APP 当前主链是手机号验证码:
1. `POST /auth/sms/send`
2. `POST /auth/login/sms`
3. 返回 `access_token + refresh_token`
说明:
- APP 是未来更强接入端,后端设计必须预留身体资料、设备绑定、遥测摘要等扩展空间
### 3.2 微信小程序
微信小程序当前主链是:
1. 客户端 `wx.login`
2. `POST /auth/login/wechat-mini`
3. 后端换取 `openid`
4. 返回 `access_token + refresh_token`
开发环境也支持 `dev-` 前缀 code。
### 3.3 绑定与合并
当小程序用户后续绑定手机号时:
1. 先发 `bind_mobile` 场景验证码
2. `POST /auth/bind/mobile`
3. 如果手机号已属于别的用户,则合并到手机号主账号
当前策略是:
- 手机号账号优先
- 微信轻账号并入手机号账号
## 4. 首页流程
首页不是固定首页,而是“入口上下文首页”。
当前聚合接口:
- `GET /me/entry-home`
它会返回:
- 当前用户
- 当前 tenant
- 当前 channel
- 当前 cards
- 继续中的 session
- 最近一局 session
## 5. Event Play 流程
活动详情页或开始前准备页不应该只拿 `event`
它还必须拿到:
- 当前是否可启动
- 当前会落到哪份 `release`
- 当前是否存在多赛道 `variant` 编排
- 是否有 ongoing session
- 当前推荐动作是什么
补充规则:
- `play.canLaunch` 不是“有 event 就能进”
- 它当前表示“当前发布 release 已完整可启动”
- 最小要求为:
- 已发布 release 存在
- manifest 存在
- runtime 已绑定
- presentation 已绑定
- content bundle 已绑定
当前聚合接口:
- `GET /events/{eventPublicID}/play`
它会返回:
- `event`
- `release`
- `resolvedRelease`
- `currentPresentation`
- `currentContentBundle`
- `play.assignmentMode`
- `play.courseVariants[]`
- `play.canLaunch`
- `play.primaryAction`
- `play.launchSource`
- `play.ongoingSession`
- `play.recentSession`
当前多赛道第一阶段约束:
- `play.assignmentMode` 只先支持最小口径:
- `manual`
- `random`
- `server-assigned`
- `play.courseVariants[]` 只先返回准备页必需字段:
- `id`
- `name`
- `description`
- `routeCode`
- `selectable`
## 6. Launch 流程
### 6.1 当前原则
启动一局游戏时,不是“启动一个 event”。
而是:
> 基于 event 当前可启动的 release创建一条固化 release 的 session。
### 6.2 当前接口
- `POST /events/{eventPublicID}/launch`
当前请求体支持:
- `releaseId`
- `variantId`
- `clientType`
- `deviceKey`
当前返回会带:
- `launch.source`
- `launch.resolvedRelease`
- `launch.variant`
- `launch.presentation`
- `launch.contentBundle`
- `launch.config`
- `launch.business.sessionId`
- `launch.business.sessionToken`
补充约束:
- `launch` 是统一业务启动入口,不应因为 APP / 小程序差异复制两套接口
- 终端差异通过 `clientType``deviceKey`、后续能力声明字段处理
### 6.3 客户端应如何使用
客户端进入游戏前,应以返回中的这几项为准:
- `launch.resolvedRelease.releaseId`
- `launch.resolvedRelease.manifestUrl`
- `launch.resolvedRelease.manifestChecksumSha256`
- `launch.variant.id`
- `launch.variant.assignmentMode`
活动运营域第二阶段第二刀新增建议消费摘要:
- `launch.presentation.presentationId`
- `launch.contentBundle.contentBundleId`
补充说明:
- 如果活动声明了多赛道 variant`launch` 会返回本局最终绑定的 `variant`
- 前端可以发起选择,但最终绑定以后端 `launch` 返回为准
- 故障恢复不重新分配 variant
而不是再拿 `event` 自己去猜。
## 7. Session 流程
### 7.1 当前接口
- `GET /sessions/{sessionPublicID}`
- `POST /sessions/{sessionPublicID}/start`
- `POST /sessions/{sessionPublicID}/finish`
- `GET /me/sessions`
### 7.2 鉴权模型
查询接口:
-`access_token`
局内动作接口:
-`sessionToken`
这保证了业务登录态和一局游戏运行态是分开的。
### 7.3 当前状态语义
- `launched`:已创建一局,客户端尚未正式开始
- `running`:客户端已开始本局
- `finished`:正常完成
- `failed`:超时或规则失败
- `cancelled`:主动退出或放弃恢复
补充约束:
- `cancelled``failed` 都不再作为 ongoing session 返回
- “放弃恢复”当前正式收口为 `finish(cancelled)`
- 同一局旧 `sessionToken``finish(cancelled)` 场景允许继续使用
- 第一阶段若活动声明了多赛道session 会固化:
- `assignmentMode`
- `variantId`
- `variantName`
- `routeCode`
### 7.4 幂等要求
- `start` 幂等:
- `launched` -> `running`
- 重复 `start` 不应报错
- `finish` 幂等:
- 第一次进入终态后,重复 `finish` 直接返回当前结果
- 这个约束同时服务小程序故障恢复和未来 APP 重试补报
## 8. 结果流程
### 8.1 当前接口
- `GET /sessions/{sessionPublicID}/result`
- `GET /me/results`
### 8.2 当前 finish payload
`finish` 当前支持上传结果摘要:
- `finalDurationSec`
- `finalScore`
- `completedControls`
- `totalControls`
- `distanceMeters`
- `averageSpeedKmh`
- `maxHeartRateBpm`
### 8.3 结果页约束
结果页应该基于 session 结果查看,不应该回头去查当前 event 当前 release。
因为:
- 一个 event 未来可能发布新版本
- 历史结果必须追溯到当时真实跑过的那份 release
- 如果一场活动存在多个 variant结果与历史摘要也必须能追溯本局 `variantId`
## 9. 当前最应该坚持的流程约束
业务主线应始终保持为:
`entry -> auth -> event play -> resolve release -> launch -> session -> result`
不要退回成:
`event -> launch -> game`
也不要走成:
`mini event -> mini launch -> mini game`
或:
`app event -> app launch -> app game`
业务接口必须保持统一,终端差异只进入上下文,不进入对象模型分叉。