# 配置驱动应用的后台管理方案建议
> 文档版本：v1.0
> 最后更新：2026-04-02 08:28:05


本文用于整理当前这类“配置驱动型地图游戏应用”的后台管理建议，面向：

- PostgreSQL 数据库
- Go 中间层
- 后台管理系统
- 客户端静态配置发布

目标是解决一个核心问题：

**配置文件会越来越大，如何在后台可维护、可复用、可审核、可发布、可回滚。**

---

## 1. 总体原则

最稳的方案不是“数据库直接存一大份 `game.json` 给客户端读”，而是：

**数据库管理编辑态，发布时编译成运行态静态配置文件。**

也就是两套形态：

### 编辑态
- 存在 PostgreSQL
- 适合后台表单编辑
- 支持版本管理
- 支持对象复用
- 支持审核、比对、回滚

### 运行态
- 由 Go 中间层装配生成
- 输出为静态 JSON
- 上传到 OSS/CDN
- 客户端只读取发布后的静态配置

这条路线最适合当前项目。

---

## 2. 不建议的做法

不建议把后台做成：

- 一张表里存一个超大的 `jsonb`
- 后台直接编辑整份 `game.json`
- 客户端通过 API 动态拼装所有配置

这样后面会遇到这些问题：

- 配置复用困难
- diff 难看
- 回滚困难
- 审核困难
- 局部编辑体验差
- 客户端运行态不稳定

---

## 3. 推荐的核心对象

建议后台和数据库先固定这 5 个核心对象：

### `Map`
地图底座。

负责：
- 瓦片资源
- meta 信息
- 磁偏角
- 初始视角

### `Playfield`
玩法空间对象定义。

负责：
- KML 来源
- 控制点覆盖信息
- 区域对象
- 危险区
- 采集物
- 起终点信息

说明：
- `Playfield` 是上位概念
- `course` 只是其中一种特化形式

### `GameMode`
玩法模板。

负责：
- 顺序赛
- 积分赛
- 后续幽灵赛、迷雾赛、金币赛等

也就是：
- `game.mode`
- `session`
- `punch`
- `scoring`
- `guidance`
- `visibility`
- `finish`
- `telemetry`
- `feedback`

### `ResourcePack`
资源包。

负责：
- 音效 profile
- 文创内容
- 图标
- HUD 主题
- 动效 profile

### `Event`
最终活动实例。

负责引用：
- 一个 `Map`
- 一个 `Playfield`
- 一个 `GameMode`
- 一个 `ResourcePack`

并允许少量活动级覆盖。

一句话：

**Event = Map + Playfield + GameMode + ResourcePack + EventOverrides**

---

## 4. 数据库建模建议

建议每个核心对象都分成：

- 主表
- version 表

### 4.1 主表

主表存稳定元信息：

- `id`
- `slug`
- `name`
- `status`
- `current_version_id`
- `created_at`
- `updated_at`

### 4.2 version 表

version 表存每个版本的具体内容：

- `id`
- `parent_id`
- `version_no`
- `schema_version`
- `content_jsonb`
- `created_by`
- `created_at`
- `change_note`

### 4.3 推荐表

建议至少有：

- `maps`
- `map_versions`
- `playfields`
- `playfield_versions`
- `game_modes`
- `game_mode_versions`
- `resource_packs`
- `resource_pack_versions`
- `events`
- `event_versions`

---

## 5. 为什么要做版本表

版本表的价值非常大：

- 支持草稿
- 支持发布版
- 支持 diff
- 支持回滚
- 支持审计
- 支持多人协作

如果没有版本表，后面后台管理一定会越来越难维护。

---

## 6. JSONB 的使用建议

推荐策略是：

- 稳定字段结构化
- 变化快的配置内容放 `jsonb`

例如主表中：
- `slug`
- `name`
- `status`

放结构化列。

而玩法具体配置、资源清单、覆盖字段，放在 `content_jsonb`。

这样兼顾：
- 查询效率
- 结构灵活性
- 配置扩展性

---

## 7. 后台编辑方式建议

后台不要直接给运营一个大 JSON 编辑框作为主要方式。

推荐做法：

- 地图编辑页
- Playfield 编辑页
- 玩法规则页
- 资源包页
- 活动编排页

按模块表单化编辑。

最后由 Go 中间层负责装配成最终配置 JSON。

也就是：

**后台是“编辑结构化对象”，不是“手工拼最终运行文件”。**

---

## 8. 发布机制建议

发布时建议按下面流程：

1. 后台选定某个 `Event Version`
2. Go 中间层读取它引用的：
   - `Map Version`
   - `Playfield Version`
   - `GameMode Version`
   - `ResourcePack Version`
3. 做装配
4. 做校验
5. 生成最终运行态 JSON
6. 上传 OSS/CDN
7. 记录一条 release

客户端只读：
- 已发布的静态配置 URL

不要让客户端直接查数据库 API 动态拼。

---

## 9. 推荐增加 Release 层

建议增加：

- `event_releases`

字段例如：

- `id`
- `event_id`
- `event_version_id`
- `release_no`
- `manifest_url`
- `published_by`
- `published_at`
- `status`

它的作用：

- 一键回滚
- 客户端锁定某次 release
- 管理历史发布记录
- 灰度验证

---

## 10. Go 中间层建议职责

Go 中间层不要只做 CRUD。

建议它至少承担这 4 类职责：

### 10.1 校验
- schema 校验
- 引用存在校验
- 字段完整性校验
- 规则约束校验

### 10.2 装配
把：
- `Map`
- `Playfield`
- `GameMode`
- `ResourcePack`
- `Event Overrides`

装配成最终配置结构。

### 10.3 发布
- 生成最终静态 JSON
- 上传到 OSS/CDN
- 记录 release

### 10.4 对比与预览
- 给后台显示 diff
- 给发布前做预览

一句话：

**Go 中间层本质上是配置编译器。**

---

## 11. 校验建议

建议尽量做强校验。

至少包括：

- schemaVersion 合法
- 引用对象存在
- KML 路径存在
- 地图 meta 存在
- 玩法字段完整

以及玩法特定约束，例如：

- 顺序赛必须有 start / finish
- 积分赛 control set 需要 score 或可派生 score
- `punch.radiusMeters > 0`
- `skip.radiusMeters > punch.radiusMeters`

这样能把很多错误挡在发布前。

---

## 12. 和当前静态目录的关系

当前你已经有类似目录：

- `map/`
- `kml/`
- `event/`

这很好，可以继续保留。

建议把它理解成：

- 数据库 = 编辑态
- 这些目录 = 发布产物态

也就是后台发布后，Go 中间层继续生成：

- `event/classic-sequential.json`
- `event/score-o.json`
- `map/...`
- `kml/...`

客户端保持现有读取方式不变。

---

## 13. 推荐的后续实施顺序

建议按这个顺序落地：

### 第一步
先建 5 个核心对象模型：
- `Map`
- `Playfield`
- `GameMode`
- `ResourcePack`
- `Event`

### 第二步
为每个对象补版本表。

### 第三步
Go 中间层实现“装配成最终 JSON”。

### 第四步
实现“发布到 OSS/CDN”。

### 第五步
后台逐步从 JSON 编辑过渡到模块化表单编辑。

---

## 14. 一句话总结

这类配置驱动应用最稳的后台方案是：

**PostgreSQL 管结构化、可版本化的编辑态对象；Go 中间层负责校验、装配和发布；客户端只消费发布后的静态 JSON。**

这样才能做到：

- 可复用
- 可扩展
- 可审核
- 可回滚
- 可稳定运行



