# 多赛道 Variant 五层设计草案 > 文档版本:v0.1 > 最后更新:2026-04-02 18:24:00 本文档用于定义“一个活动对应多版 KML / 多条赛道”时的推荐架构。 目标: - 不从页面交互倒推系统结构 - 先把多赛道能力按平台层次拆清 - 让前端、后端、后台、恢复、结果页都围绕同一套事实工作 - 为后续“手动选择 / 随机指定 / 后端指定”留出统一伸缩空间 说明: - 本文档是设计草案,不是最终接口契约 - 本文档优先定义分层、边界、事实和约束 - 具体页面表现、后台表单细节、字段命名可在后续实现阶段微调 --- ## 1. 背景与核心判断 当前项目里,一场活动后续可能不止一版 KML。 常见需求包括: - 同一活动下有 A / B / C 多条赛道 - 准备阶段允许玩家手动选择 - 准备阶段由系统随机分配 - 后续可能由后台或裁判端直接指定 这里最关键的判断是: **赛道版本不是页面临时状态,而是 session 级事实。** 也就是说,一旦某局比赛绑定了某个赛道版本,这个事实必须贯穿: - 准备阶段 - launch - session start / finish - 故障恢复 - result - ongoing session - 历史结果 如果这一点不先定住,后面多端、多页面、多恢复链会很快乱掉。 --- ## 2. 总体原则 多赛道能力建议固定遵守下面 6 条原则: 1. 一局比赛只绑定一个赛道版本 2. 前端可以参与选择,但最终绑定以后端 session 为准 3. 客户端不应各自实现不同的随机分配规则 4. 恢复链必须记住赛道版本 5. 结果页、历史结果和 ongoing 摘要必须可追溯赛道版本 6. 扩展新分配模式时,不破坏现有分层 一句话总结: **前端负责交互,后端负责最终绑定,session 负责真实落账。** --- ## 3. 五层模型 多赛道能力建议拆成 5 层。 ### 3.1 资源层 职责: - 只定义赛道素材本身 - 不讨论谁来选,不讨论 session 典型内容: - KML 文件 - 赛道元数据 - 可选地图资源 - 可选赛道封面、说明图 这一层回答的是: - 这个赛道版本本身是什么 - 它的原始素材和元信息是什么 建议约束: - 每个赛道版本都应有稳定的 `variantId` - 每个赛道版本都应能独立定位到自己的 KML / manifest 入口 - 资源层不应混入“本局随机到谁”这种运行时逻辑 ### 3.2 活动编排层 职责: - 定义一个活动下有哪些赛道版本可用 - 定义这些版本如何被分配 典型内容: - `assignmentMode` - `courseVariants[]` - 权重 - 可选分组规则 - 可选活动级覆盖 这一层回答的是: - 当前活动允许哪些赛道版本 - 当前活动按什么模式分配赛道 推荐至少支持 3 种模式: 1. `manual` - 用户手选 2. `random` - 系统随机指定 3. `server-assigned` - 后端预先指定,前端只展示 后续可扩展模式: - 按分组分配 - 按批次轮换 - 团队共用赛道 - 避免重复赛道 ### 3.3 会话绑定层 职责: - 真正决定“这局比赛到底绑定哪条赛道” - 作为跨端、跨页面、跨恢复的一致事实 这一层回答的是: - 当前 session 最终绑定的是哪个 `variantId` - 这个绑定是手选、随机还是后端直接指定 这一层必须落账的最小事实建议包括: - `sessionId` - `eventId` - `variantId` - `assignmentMode` - `assignedAt` - 可选的 `assignmentSource` 核心约束: - `variantId` 一旦绑定,不应在本局内漂移 - launch、恢复、结果、排行榜都要引用同一 `variantId` - 客户端本地恢复快照必须保存 `variantId` ### 3.4 客户端呈现层 职责: - 负责向玩家展示可选项或绑定结果 - 负责发起用户选择 - 负责消费最终绑定后的赛道配置 这一层回答的是: - 准备页要不要展示赛道列表 - 是否允许点击手选 - 是否显示“本局随机分配结果” - 地图页加载哪一个 manifest 推荐规则: - `manual`:准备页展示赛道列表,允许选择 - `random`:准备页展示“随机分配”结果,不允许随意更改 - `server-assigned`:准备页只展示最终结果,不提供选择 强约束: - 客户端不能把“页面选择结果”当成最终事实 - 客户端必须以后端返回的 `variantId` 为准 - 地图页只消费最终绑定后的 manifest / runtime profile ### 3.5 后台运营层 职责: - 管理赛道版本 - 管理活动编排 - 管理发布与审计 这一层回答的是: - 活动有哪些赛道版本 - 每个版本的素材、说明和发布状态是什么 - 当前活动采用哪种分配策略 - 某局最终是怎么绑定出来的 后台层建议逐步承担: - 赛道版本管理 - 活动绑定多个 variant - 权重配置 - 发布检查 - 历史审计 --- ## 4. 多端协作边界 多赛道能力一旦牵涉多端,最容易出问题的地方是边界不清。 建议固定边界如下: ### 4.1 前端负责 - 展示赛道选择或展示赛道结果 - 发起选择请求或发起随机请求 - 消费 launch 返回的赛道绑定结果 - 在地图、恢复、结果页中显示当前 `variantId` 或赛道名 ### 4.2 后端负责 - 最终确认本局绑定哪个 `variantId` - 将 `variantId` 写入 session - 确保 launch 返回的 release / manifest 与 `variantId` 对应 - 确保 result / ongoing / recovery 均能反查 `variantId` ### 4.3 后台负责 - 管理活动可用的 variants - 管理 assignment mode - 管理发布、上下线和审计 约束: - 不允许前端自己定义“随机分配算法”后直接当成最终结果 - 不允许某端私自改 `variantId` 但不落 session - 不允许恢复链丢失 `variantId` --- ## 5. 配置与发布建议 多赛道不是只改一个 `kmlUrl`。 它建议进入活动编排配置,而不是页面临时字段。 推荐抽象: - 活动级: - `assignmentMode` - `courseVariants[]` - variant 级: - `id` - `name` - `kmlUrl` - `weight` - `overrides` 如果某些版本不仅 KML 不同,连分值、样式、规则也不同,推荐允许 variant 带局部覆盖。 推荐覆盖顺序: `系统默认值 -> 玩法默认值 -> 活动默认值 -> variant 覆盖 -> 单点覆盖` 这样未来不会因为多赛道把既有继承体系打乱。 --- ## 6. 恢复、结果与摘要约束 ### 6.1 故障恢复 恢复快照中必须加入: - `variantId` - 可选 `variantName` 恢复原则: - 恢复的是这局绑定的赛道事实 - 不重新随机 - 不重新询问选择 ### 6.2 结果页 结果页建议至少展示: - 活动名 - 赛道版本名或 `variantId` - 本局结果摘要 ### 6.3 ongoing / recent / 历史成绩 这些摘要建议都能反映: - 本局属于哪个赛道版本 否则后续: - 用户无法判断自己玩的哪版 - 运营无法解释同活动下不同赛道差异 - 排名、复盘、申诉都困难 --- ## 7. 推荐实施顺序 这块不建议一上来就做全套复杂功能。 推荐分三期: ### 第一期:架构定型 目标: - 定义 `courseVariants` - 定义 `assignmentMode` - 定义 session 绑定 `variantId` - 明确恢复、结果、launch 必须带上 `variantId` ### 第二期:前后端最小闭环 目标: - 支持 `manual` - 支持 `random` - 准备页可展示赛道选择或随机结果 - launch 能消费最终绑定结果 ### 第三期:运营扩展 目标: - 接后台编排 - 增加 `server-assigned` - 扩展更多分配模式 - 做更完整的审计、排行榜和统计 --- ## 8. 六层检查在多赛道能力中的应用 后续只要多赛道相关配置或契约有变更,建议继续执行当前约定的六层检查: 1. 文档 2. 配置源 3. 解析层 4. 编译层 5. 消费层 6. 发布与联调层 具体到多赛道能力,检查点通常包括: - 文档是否同步 `assignmentMode / variants / variantId` - 配置源是否新增或调整 variant 结构 - 解析层是否能读取多赛道结构 - 编译层是否能生成最终绑定后的 runtime profile - 地图、结果页、恢复链是否都消费了 `variantId` - launch / release / manifest 是否和最终 variant 绑定一致 --- ## 9. 当前建议结论 当前阶段,建议把“多 KML / 多赛道”先当成**平台能力设计**,而不是页面功能。 当前最重要的不是先做某个选择 UI,而是先定住以下 4 个事实: 1. 一个活动可以有多个 variants 2. 一个 session 只能绑定一个 `variantId` 3. 最终绑定以后端 session 为准 4. 恢复、结果、ongoing、历史结果都必须能追溯该 `variantId` --- ## 10. 一句话总结 **多赛道能力建议固定采用“资源层、活动编排层、会话绑定层、客户端呈现层、后台运营层”五层模型,先把 `variantId` 做成 session 级事实,再去实现准备页手选、随机分配和后台指定等具体交互。**