# 模板 03：生成器 _build.py 模板（一键重建整门课）

> 职责：读取各课内容模块 → 生成 首页 / 每课目录 / 每页幻灯片 / 占位页；内容改动后只需重跑 `python3 _build.py`。
> 完整可抄版本：`引用文件/_build.py`（含 52 页第 1 课的实例，把 `LECTURES` 换成你自己的即可）。

## 一、核心数据与函数（约定）

```python
LECTURES = [ dict(no=1, title='…', week='第1周', desc='…', status='done'|'todo'), … ]
# status='done' 走真实内容模块；'todo' 生成占位页

def slide_page(no, i, total, title, body, prev, next, label):
    # 产出单页 html；若 body 含 class="quiz"/quiz-opt/data-action 自动追加 <script src="../quiz.js">
def build_lecture1(): …  # 第 1 课：SLIDES = _content1.SLIDES + _content2.SLIDES（或 _contentN）
def build_placeholders(): …  # 未制作大课 → 最小占位页（未开放观看＋返回）
def build_home(): …  # 课程主页卡片
GROUPS = [('一、封面·导学', 1, 4), …]  # 每课目录的分组（起止页号）
```

## 二、⚠ "页数变了"必须同步的三处（血的教训）

| 改动 | 要改的地方 |
|---|---|
| 插入/删除/拆分页 | ① 内容模块顺序；② `assert total == N`；③ `GROUPS` 分组起止；④ 首页卡片"查看全部 N 页"；⑤ 目录 subtitle 自动取 total 无需改 |
| 改课程名/教师/考核口径 | home 常量（HOME_TITLE/HOME_SUB/ HOME_PILL）与各课 label，别漏讲师行 |
| 新增交互页 | 自动（生成器检测 quiz 标记注入 quiz.js），无需手工 |

## 三、生成器自检（每次 build 后跑）

```bash
ls lecture1/1.*.html | wc -l                   # == 总页数
grep -c "quiz.js" lecture1/1.13.html           # 交互页应 =1
python3 -c "from _content1 import SLIDES; print(len(SLIDES))"   # 内容条数与页数一致
```

## 四、换新课程的最小改动清单

1. 复制 `引用文件/_build.py` → 改 `LECTURES`（16 课的标题/周次/简介按你的教学日历）；
2. 改 `HOME_TITLE`/`HOME_SUB`/`HOME_PILL`（课程名/院系/学时学分考核）；
3. 建立 `_contentN.py`（模板 02），第 1 课先做、其余 status='todo'；
4. 运行 `python3 _build.py` → 检查 `assert` 通过、页数与目录一致 → 发布（模板 06）。

## 五、扩展点

- 页内 `<style>`：个别页压缩标题/内边距腾空间给大图（见第 2 章 1.31/1.47 实例）；
- 占位页文案：只允许"未开放观看＋返回"，无其他内容；
- 新增题型：改 `quiz.js` 一处即可全站生效。