优化地图交互与文档方案
This commit is contained in:
416
backend-config-management-proposal.md
Normal file
416
backend-config-management-proposal.md
Normal file
@@ -0,0 +1,416 @@
|
||||
# 配置驱动应用的后台管理方案建议
|
||||
|
||||
本文用于整理当前这类“配置驱动型地图游戏应用”的后台管理建议,面向:
|
||||
|
||||
- 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。**
|
||||
|
||||
这样才能做到:
|
||||
|
||||
- 可复用
|
||||
- 可扩展
|
||||
- 可审核
|
||||
- 可回滚
|
||||
- 可稳定运行
|
||||
Reference in New Issue
Block a user