# 分卷制作规范 v1.1

本文件说明如何把一个新的历史时期做成「分卷」，接入全史壳层，并通过验收。目标是把新增时期的成本压到**只写数据与配置**，不改主壳。

---

## 1. 分卷是什么

```
全史壳层（index.html）
   └── 分卷（volumes/<年份范围>/）
          ├── index.html      该时期的独立地图页
          ├── data/core.js    时期主数据（帝王/事件/政权/疆域）
          └── data/prefs.js   州府两级界线（可选）
```

- 壳层负责：时期目录、总览地图、长时序轴、详情卡、深链。
- 分卷负责：该时期的逐年地图、事件、政权面板、检索与州府层。
- 一个分卷目录可以单独拷走，双击 `index.html` 离线打开；不依赖壳层。

**非目标**：P1 不追求「一个通用渲染引擎」。916–1279 的 viewer 是参考实现，包含该时期的朝代切换、年号表、州府图层等专属逻辑。新增分卷可以复用它，但需要按新时期的政权结构做配置级适配；通用引擎化列为 P2。

---

## 2. 新建一卷：五步

### 第 1 步 · 建元数据

复制模板：

```bash
cp -r periods/_template periods/<period-id>
```

编辑 `periods/<period-id>/period.json`：

- `status` 先写 `planned`，`entry` 写 `null`。
- `anchor` 选一个**与其他卷不重叠**的代表性都城，用于总览地图。
- `bands` 写全史时间轴上的分段；`row=0` 中原王朝，`row=1` 并立政权。
- `highlights` 先放 2–3 条最确定的事件，必须有来源。

此时运行 `node tools/build.mjs`，壳层就会自动出现这一卷的入口（待补状态），**不需要改主壳**。

### 第 2 步 · 准备数据包

按 [`DATA-SCHEMA.md`](DATA-SCHEMA.md) 写：

- `events.json`：事件、地点、来源、置信度。
- `regimes.json`：政权、都城、疆域快照、注记点。
- `sources.json`：史料源清单；事件来源必须在此登记。
- `places.json`：地名索引（P2 规范化用）。
- `prefectures.json`：州府两级界线（没有就整层隐藏，不要拿别期数据冒充）。

**硬性要求**

- 每个事件都有 `year`、`place.lon/lat`、`source`、`confidence`。
- 没有来源的内容不得进入正式数据；不确定的坐标标 `approx`，不确定的结论标 `low` 并写 `note`。
- 疆域快照必须是**史实年份的离散快照**，相邻快照未变时不要硬造插值。
- 边界不得钳到视口边缘拉出假边界；跨出视口的西境做裁剪。

### 第 3 步 · 校验

```bash
node tools/validate_period.mjs <period-id>
```

任何 `✗` 都必须修掉；`!` 是待补提醒，需在 README 的「待补内容」中登记。校验通过后再进入下一步。

### 第 4 步 · 生成运行包

```bash
node tools/build_volume.mjs <period-id> <volume-dir>
# 例：node tools/build_volume.mjs liao-song 916-1279
```

生成 `volumes/<volume-dir>/data/core.js` 与 `prefs.js`。这两个文件是 classic script（`window.PERIOD_DATA` / `window.PERIOD_PREFS`），**不能用 fetch / ESM**，否则 `file://` 双击会失败。

分卷的 `index.html` 可以是：

- 参考实现：复制 `volumes/916-1279/index.html`，保留其 `<script src="data/core.js">` 装载顺序；
- 或自写 viewer，但必须满足第 6 节的验收清单。

### 第 5 步 · 接上入口

1. 把 `period.json.status` 改为 `ready`，`entry` 写 `volumes/<volume-dir>/index.html`。
2. `stats` 填真实条数（校验器会核对）。
3. 运行：

```bash
node tools/build.mjs
node tools/validate_period.mjs
node tools/check.mjs
node tools/test_shell.mjs
```

4. 打开壳层，确认该卷出现在左栏与时间轴，点击可进入分卷；返回总览不残留该卷数据。

---

## 3. 分卷 viewer 的最小契约

如果复用 916–1279 的参考实现，确认以下行为仍然成立：

| 能力 | 验收点 |
|---|---|
| 离线 | `file://` 双击打开，无网络请求 |
| 数据装载 | 先 `data/prefs.js`、再 `data/core.js`，最后主脚本 |
| 时间轴 | 年份变化后，地图、事件点、政权面板、左栏同步 |
| 切换时期 | 不残留上一时期的政权、事件、年份 |
| 地图 | 无白边、无黑块；缩放后文字不糊、标记不重叠 |
| 移动端 | 控件不溢出；左栏可开合；时间轴可拖动 |
| 来源 | 每条事件都能看到出处；无来源不显示 |
| 回退 | 分卷目录可单独打包；原版本保留 |

---

## 4. 主壳侧的唯一改动点

新增分卷**不应改** `index.html` / `shell.js` / `shell.css`，只需要：

```
periods/<period-id>/period.json  →  node tools/build.mjs  →  data/catalog.js
```

`catalog.js` 自动汇总：

- 左栏卷目与进度；
- 全史时间轴分段；
- 总览地图的时期锚点；
- 右栏详情卡。

若发现必须改壳层才能接入，说明 `period.json` 的契约缺字段，应先补规范，而不是在壳里加 if。

---

## 5. 分期推进顺序（建议）

| 批次 | 时期 | 目标 | 关键难点 |
|---|---|---|---|
| P1（已完成） | 辽宋夏金蒙 916–1279 | 参考实现 + 全史壳层 | 多政权并立、州府 14 档 |
| P2 | 秦汉、隋唐、明清 | 三个锚点时期，每期 30–50 事件 | 疆域分幅数字化、羁縻/都护府表达 |
| P3 | 魏晋南北朝、五代十国 | 分裂期政权图谱 | 政权碎、存续短、州郡滥多 |
| P4 | 先秦 | 都邑、战场、考古文化区 | 无逐年边界，需换表达方式 |
| P5 | 跨期搜索、政权对比、专题 | 平台化 | 索引与性能 |

---

## 6. 验收清单（每卷必须全过）

- [ ] `validate_period.mjs` 0 错误；待补提醒已登记。
- [ ] `check.mjs` 通过（数据量、年号、事件、几何、离线依赖）。
- [ ] `test_drag.mjs` 22 项全 OK（若复用参考 viewer）。
- [ ] 时期切换后地图、事件、政权面板、年份状态同步，无上一期残留。
- [ ] 地图无白边/黑块；缩放后文字与标记不糊、不重叠。
- [ ] 桌面端与移动端均可操作，控件不溢出。
- [ ] 每条事件可查来源；无来源内容未进入正式数据。
- [ ] 分卷可单独打包离线打开。
- [ ] 交付说明区分「已完成」与「占位/待补」。
- [ ] 截图（桌面 + 移动）与测试输出归档。

---

## 7. 性能与体积红线

- 单卷 `index.html` 应 < 1.5 MB；主数据与州府数据外置。
- 时期数据按卷加载，禁止全史一次性载入。
- 宏观层只用简化边界（总览快照当前约 8 KB / 478 顶点）；分卷才加载完整几何。
- 州府层按年份档懒构建；切回旧年份不重建。
- 移动端首屏不加载未选中的分卷数据。

---

## 8. 已知限制（P1）

1. **viewer 未完全引擎化**：916–1279 的朝代 tab、年号表、检索是专属逻辑；新卷需要配置级适配。
2. **地名规范化未完成**：120 条既有事件只有近似坐标，`place.name` 为空，P2 补。
3. **总览只有一张示例快照**：1141 年，其他时期只显示史实都城锚点，不绘制推测疆域。
4. **近现代未纳入**：本期范围止于清（1912），近现代入口不展示。
5. **地图合规**：当前底图为不含国界线的地形晕渲；公开发布前须按中国地图管理要求送审并使用合规底图。


---

## 9. v1.1 实践：八卷全部开放

八卷（先秦、秦汉、魏晋南北朝、隋唐五代、辽宋夏金蒙、元、明、清）已按本规范接入。新增能力：

- **通用 viewer 生成**：`tools/patch_viewer.py` 从 `tools/viewer_template.html` 生成分卷，朝代 tab、人物 tab、事件因果链、负年份、无年号提示、城市注记均由 `period.json` 配置。
- **通用疆域构建**：`tools/build_geo.mjs` 读取 `periods/<id>/geo.config.json`，从图集快照抽取政权与州府，按 `hidden`/`admin`/`minorPolities` 处理特殊政权。
- **通用内容合并**：`tools/build_content.mjs` 合并 `_src/events-*.mjs`、`figures-*.mjs`、`chains.mjs`，生成 `events.json`/`figures.json`/`sources.json`/`period.json`。
- **主页概略图**：`tools/build_overview_geo.mjs` 按每卷 `overview.year` 生成简化疆域，`tools/audit_shell.mjs` 逐卷核对标题、年代、链接、统计与大事。
- **分卷目录命名**：公元后卷用年段（`581-960`、`916-1279` 等）；公元前卷用 `pre-qin`、`qin-han`、`wei-jin`，避免双负号路径。

新增一卷的最小步骤：写 `geo.config.json` + `period.template.json` + `_src` 内容，跑上述五条命令，补 README 与测试。
