# 配置频繁变更场景下的后台管理方案 本文用于整理一套更适合“配置项变化很频繁”的后台方案。 适用前提: - 配置驱动型应用 - 游戏规则和字段会持续变化 - PostgreSQL 作为主数据库 - Go 作为中间层 - 客户端最终读取静态 JSON 核心目标是: **在保证后端稳定的前提下,让前端和玩法配置可以持续快速迭代。** --- ## 1. 核心原则 这版方案的核心思想只有一句: **后端管理“容器、版本、引用、发布”,不要深度管理每个细字段。** 也就是说: - 后端负责管理对象关系 - 后端负责管理版本和发布 - 后端负责做基础校验 - 后端尽量不要写死每个玩法里的所有字段细节 --- ## 2. 总体结构 推荐分成 3 层: ### 2.1 编辑层 后台管理系统面向的是“对象”,不是最终运行文件。 建议核心对象仍然是: - `Map` - `Playfield` - `GameMode` - `ResourcePack` - `Event` ### 2.2 装配层 Go 中间层负责: - 读取对象 - 合并引用 - 基础校验 - 生成最终运行态配置 ### 2.3 发布层 装配完成后,生成静态 JSON 上传到 OSS/CDN。 客户端只读取: - 已发布的静态配置 --- ## 3. 数据库存什么 数据库建议只存两类数据: ### 3.1 稳定元信息 结构化列保存: - `id` - `slug` - `name` - `status` - `current_version_id` - `created_at` - `updated_at` ### 3.2 易变配置内容 使用 `jsonb` 保存: - `content_jsonb` 也就是说,每个对象都建议拆成: - 主表 - version 表 例如: - `maps` / `map_versions` - `playfields` / `playfield_versions` - `game_modes` / `game_mode_versions` - `resource_packs` / `resource_pack_versions` - `events` / `event_versions` 这套结构最适合承接频繁变化的配置字段。 --- ## 4. 为什么要用 version 表 配置频繁变化时,版本表非常重要: - 支持草稿 - 支持当前版 - 支持发布版 - 支持历史回滚 - 支持 diff - 支持审计 如果没有版本表,配置演进到后面会越来越难控。 --- ## 5. 后端真正该负责的内容 后端建议强管理下面这 4 件事: ### 5.1 对象关系 例如: - Event 引用哪个 Map - Event 引用哪个 Playfield - Event 引用哪个 GameMode - Event 引用哪个 ResourcePack ### 5.2 版本机制 例如: - 草稿 - 当前版本 - 发布版本 - 回滚历史 ### 5.3 基础校验 只做真正稳定的校验: - 顶层结构是否合法 - 引用是否存在 - schemaVersion 是否兼容 - 必填对象是否齐全 ### 5.4 发布装配 把编辑态对象装配成最终运行态 JSON。 --- ## 6. 后端不要过度负责的内容 后端不要把下面这些写死: - 每个玩法的小规则字段 - 每个 HUD 开关 - 每个实验性参数 - 每个视觉细节配置 - 每次快速迭代里新增的小配置项 这些变化太频繁,应该优先放在 `jsonb` 内容里,由前端消费。 一句话: **后端不要成为“所有细字段的业务解释器”。** --- ## 7. 配置校验的推荐分层 建议分成 3 层校验。 ### 7.1 通用结构校验 所有配置都校验: - `schemaVersion` - `map` - `playfield` - `game` ### 7.2 公共字段校验 只校验稳定公共字段,例如: - `game.mode` 必须存在 - `game.punch.radiusMeters > 0` ### 7.3 玩法校验器 按 `game.mode` 分发,例如: - `classic-sequential` validator - `score-o` validator 但这里有个重要原则: **未识别字段默认允许透传。** 也就是说: - 不要因为多了一个新字段就发布失败 - 只有破坏基础结构或关键规则时才拦截 --- ## 8. 后台编辑策略 后台不要追求“一开始把所有字段都做成完美表单”。 建议分成两类: ### 8.1 稳定字段 做正式表单: - 名称 - 状态 - 模式 - 地图引用 - Playfield 引用 - 资源包引用 - 关键半径 - 是否必须起点/终点 ### 8.2 易变字段 先保留模块化 JSON 编辑区: - `game.sequence` - `game.guidance` - `game.visibility` - `game.feedback` - `playfield.controlOverrides` - 其他试验性字段 等这些字段稳定后,再逐步升级成正式表单。 这会比一开始硬做全表单更现实。 --- ## 9. 推荐的发布模型 建议增加一层: - `event_releases` 推荐字段: - `id` - `event_id` - `event_version_id` - `release_no` - `manifest_url` - `published_by` - `published_at` - `status` 发布流程: 1. 后台选择某个 `event_version` 2. Go 层装配最终配置 3. Go 层校验 4. 上传 OSS/CDN 5. 写入 release 记录 客户端只消费: - 某次 release 对应的静态 JSON --- ## 10. Go 中间层的职责 Go 中间层建议承担 4 类职责: ### 10.1 装配器 负责把: - `Map` - `Playfield` - `GameMode` - `ResourcePack` - `Event Overrides` 装配成最终运行态配置。 ### 10.2 校验器 负责: - 通用校验 - 公共字段校验 - 按玩法分发的插件式校验 ### 10.3 发布器 负责: - 生成静态 JSON - 上传 OSS/CDN - 写入 release ### 10.4 预览 / Diff 负责: - 给后台看发布前的预览 - 对比不同版本差异 一句话: **Go 中间层本质上是配置编译器,不只是 CRUD 服务。** --- ## 11. 这套方案为什么适合当前项目 因为当前项目的真实情况就是: - 配置字段变化快 - 玩法在持续演进 - 前端经常需要新增规则项 - 客户端更适合消费静态配置 如果后端每次都跟着细字段改表、改结构、改接口,成本会非常高。 这套方案可以避免: - 频繁 migration - 后端字段爆炸 - 每次小字段变更都改很多 Go 代码 --- ## 12. 推荐你现在就定死的原则 ### 原则 1 **数据库结构稳定,配置内容灵活。** ### 原则 2 **后端强管理对象关系,不强管理每个细字段。** ### 原则 3 **未知字段默认允许透传。** ### 原则 4 **客户端消费细规则,后端负责发布与校验。** ### 原则 5 **最终运行态永远是静态 JSON。** --- ## 13. 和当前目录结构的关系 如果当前静态目录是: - `map/` - `kml/` - `event/` 这套可以继续保留。 理解方式是: - 数据库 = 编辑态 - Go 装配 = 发布态转换 - OSS 目录 = 运行态产物 也就是说后台发布后,继续生成: - `event/classic-sequential.json` - `event/score-o.json` - `map/...` - `kml/...` 客户端现有读取逻辑无需推翻。 --- ## 14. 推荐实施顺序 建议按下面顺序推进: ### 第一步 先建 5 个核心对象: - `Map` - `Playfield` - `GameMode` - `ResourcePack` - `Event` ### 第二步 为每个对象补 version 表。 ### 第三步 Go 中间层先做最小装配功能。 ### 第四步 实现发布到 OSS/CDN。 ### 第五步 后台逐步把稳定字段表单化。 ### 第六步 把易变字段继续保留为 JSON 编辑区。 --- ## 15. 一句话总结 这套更适合频繁变化配置项的后台方案是: **PostgreSQL 存“版本化对象 + jsonb 内容”,Go 中间层做“装配 + 校验 + 发布”,客户端只读静态发布结果。**