Files
cmr-mini/doc/config/线上业务接入边界方案.md

344 lines
7.9 KiB
Markdown
Raw 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.0
> 最后更新2026-04-02 08:28:05
## 1. 目的
本文档定义小程序接入线上业务 API 时的架构边界,确保以下原则始终成立:
- 游戏玩法仍然完全由配置驱动
- 线上 API 只负责业务编排,不负责定义或污染玩法
- 地图引擎和规则运行时可以继续独立于业务系统运行
- 本地 demo、离线配置、线上赛事三种入口可以共存
本文档适用于以下接入范围:
- 用户管理
- 登录与鉴权
- 首页卡片
- 赛事详情
- 地图详情
- Event 详情
- 报名
- launch 启动
- 后续 session 上报与查询
## 2. 核心结论
线上接入后,系统仍保持两层结构:
- 业务层:决定“用户是谁、能进什么、当前启动什么”
- 游戏层:决定“地图怎么画、规则怎么跑、控制点怎么判定、体验怎么表现”
两层之间只允许通过一个明确的启动模型通信,不允许业务 API 对游戏规则对象做直接写入。
一句话定义:
> API 负责发放启动上下文,配置负责定义游戏本身。
## 3. 分层原则
### 3.1 业务层职责
业务层负责:
- 登录与 token 管理
- 用户资料与身体数据
- 卡片、赛事、地图、Event 列表与详情
- 报名资格校验
- launch 启动资格与 session 凭证发放
- 后续成绩、轨迹、历史记录上传与查询
业务层可以决定:
- 是否允许用户启动
- 当前应启动哪个 Event
- 当前应加载哪份配置或 manifest
- 当前启动绑定的 `session_id``session_token`
业务层不可以决定:
- 控制点布局
- 游戏规则
- 打卡判定
- 跳点规则
- 引导、音效、表现策略
- 游戏内内容卡的结构和行为定义
### 3.2 游戏层职责
游戏层负责:
- 地图资源加载
- KML / course / 配置解析
- `GameDefinition` 构建
- 规则插件运行
- 传感器接入
- HUD、反馈、结果页、本地统计
- 游戏内 session 生命周期
游戏层只认配置和本地运行态,不认业务 API 对象。
游戏层不应该直接出现以下业务字段:
- `competition_id`
- `registration_status`
- `access_token`
- `refresh_token`
- `Authorization`
- `user_id`
业务字段可以存在于页面壳层或业务服务层,但不进入规则层。
## 4. 唯一允许的层间模型
业务层和游戏层之间,统一通过 `GameLaunchEnvelope` 通信。
建议结构如下:
```ts
interface GameLaunchEnvelope {
config: {
configUrl: string
configLabel: string
configChecksumSha256?: string | null
releaseId?: string | null
routeCode?: string | null
}
business: {
source: 'demo' | 'competition' | 'direct-event' | 'custom'
competitionId?: string | null
eventId?: string | null
launchRequestId?: string | null
participantId?: string | null
sessionId?: string | null
sessionToken?: string | null
sessionTokenExpiresAt?: string | null
realtimeEndpoint?: string | null
realtimeToken?: string | null
} | null
}
```
解释:
- `config` 是游戏层真正消费的输入
- `business` 是业务壳保留的上下文
- 地图页可以同时拿到两者,但地图引擎只读取 `config`
## 5. 推荐启动链路
### 5.1 Demo 启动
适用于本地调试、离线测试、玩法验证。
流程:
1. 页面构建 demo `GameLaunchEnvelope`
2. `config.configUrl` 指向 demo 配置
3. `business.source = 'demo'`
4. 跳转地图页
5. 地图页加载配置并启动引擎
特点:
- 不依赖业务 API
- 不依赖登录
- 不依赖 session
### 5.2 线上赛事启动
适用于正式业务入口。
流程:
1. 业务页请求赛事 / Event 详情
2. 用户在业务页完成登录、资格校验、报名确认
3. 用户点击开始,业务页调用 `launch`
4. 后端返回 `session_id``session_token``release_id``manifest_url``route_code`
5. 业务层把上述信息转换为 `GameLaunchEnvelope`
6. 地图页只根据 `config` 载入配置
7. 业务壳层保存 `business` 上下文供后续上报使用
注意:
- `launch` 是业务启动,不等于规则层 `startSession`
- 规则层本地开始游戏,仍由引擎按配置驱动
### 5.3 线上直入地图启动
适用于地图详情或 Event 直入。
流程与赛事入口基本一致,区别仅在于:
- 入口页不同
- 资格校验更轻
- `business.source = 'direct-event'`
## 6. manifest 的角色
后端提供的 `manifest_url` 不应直接变成规则层对象。
推荐做法:
- 业务层或适配层下载 manifest
- 将 manifest 解析并映射到当前配置体系
- 输出为当前引擎已支持的配置入口
manifest 是“线上发布描述”,不是“规则运行对象”。
建议把 manifest 适配理解为一个编译过程:
- 输入:后端发布描述
- 输出:当前配置驱动引擎可识别的配置资源
## 7. 目录建议
建议按三层组织代码:
```text
miniprogram/
services/
http.ts
client-api.ts
auth.ts
business/
launch/
launchBuilder.ts
launchStore.ts
manifestAdapter.ts
utils/
gameLaunch.ts
pages/
login/
home/
competition-detail/
event-detail/
map/
```
说明:
- `services` 只处理 API 通信
- `business/launch` 只做业务到配置的适配
- `utils/gameLaunch.ts` 定义启动模型和页面跳转协议
- `pages/map` 只做配置加载和游戏承载
## 8. 代码边界约束
### 8.1 允许进入地图页的内容
允许进入地图页:
- `GameLaunchEnvelope`
- `configUrl`
- `configLabel`
- `releaseId`
- `routeCode`
- `sessionToken`
但地图页内部还要继续区分:
- 引擎可读:`config`
- 业务壳可读:`business`
### 8.2 不允许进入引擎的内容
以下内容禁止进入 `MapEngine``GameRuntime``GameDefinition`
- 用户信息
- 登录态 token
- 报名状态
- 业务接口返回原始对象
- 赛事详情原始 JSON
- Event 详情原始 JSON
### 8.3 上报也走旁路
后续若接 `punches``finish``session-uploads`,建议流程如下:
1. 游戏层产生本地事件
2. 页面壳层或业务 service 订阅这些事件
3. 由业务层决定是否调用 API
不要在规则层里直接 `wx.request`
## 9. 当前项目的落地点
当前项目已具备以下基础:
- 地图页是配置驱动入口
- `remoteMapConfig.ts` 负责远程配置加载
- `MapEngine` 负责本地规则与表现运行
- 已新增 `utils/gameLaunch.ts` 作为启动边界模型
当前建议继续保持:
- `MapEngine` 只接 `RemoteMapConfig`
- 地图页只从 `GameLaunchEnvelope.config` 获取配置入口
- 业务上下文保留在地图页外层或页面壳层
## 10. 分阶段落地建议
### 阶段一:边界固化
目标:
- 地图页彻底改为只接 `GameLaunchEnvelope`
- demo 启动与线上启动走同一套入口协议
验收标准:
- 不再依赖页面内硬编码 URL 作为唯一启动方式
- 业务字段不进入引擎
### 阶段二:业务壳接入
目标:
- 接入登录、首页卡片、赛事详情、Event 详情、报名、launch
验收标准:
- 能从业务页成功进入地图页
- 地图仍由配置驱动启动
### 阶段三manifest 适配
目标:
- 将后端 `manifest_url` 适配为当前配置体系可消费的输入
验收标准:
- 同一个 Event 的线上发布内容可稳定映射为游戏配置入口
### 阶段四session 下游联通
目标:
- 补充上报、完成、结果、历史查询
验收标准:
- 业务链路打通
- 规则层仍不直接依赖业务 API
## 11. 必须长期坚持的规则
- 业务 API 不定义玩法
- 配置文件不承载用户态
- 引擎不依赖登录状态
- 引擎不依赖报名状态
- 业务页不直接修改 `GameDefinition`
- 规则层不直接请求业务 API
如果后续出现需求需要绕过这几条规则,应视为架构变更,不应当作普通功能迭代处理。
## 12. 一句话总结
线上系统负责“把用户送进正确的一局游戏”,配置系统负责“定义这局游戏是什么”。