# 教材自带 PPT → 网页课件（学生版）改造与上线方法总结

> 适用对象：出版社/教材配套 PPT（每章一个 .pptx，10×5.62 英寸 16:9）
> 已跑通：第 1 章（61 页）、第 2 章（87 页），并已上线到腾讯云 `http://111.231.0.226:2345/lecture1|lecture2/`
> 工具：`soffice`（LibreOffice）、`pdftoppm`、Python（python-pptx / Pillow / lxml）、`vision-identify` 识图

---

## 一、总原则（三条，别再走偏）

1. **只换图，不动 PPT 主体配色**。课件原有蓝色系是设计基调，改它属于改版；要"配合整体色彩"，调的是**替换进去的新图**。
2. **逐页还原，不做重编**。页数必须等于源 PPT 页数；文字、备注、图片全部保留，矢量图形（自选图形/线条/组合）用**原页高清渲染图**承载，避免用 HTML 重画导致走形。
3. **学生版只展示内容**。不出现"原页/叠字/纯文字"模式切换、不出现文字稿/素材侧栏；问题页答案采用**同页折叠**。

---

## 二、换图流程（把别校元素换成我校）

### 1. 找出"含他校元素"的图片
- **按媒体哈希比对最快**：同一套出版社模板跨章共用同一张图。第 1 章确认过的两张同济图，在第 2 章里哈希完全相同：
  - `858ef6afb2`＝同济大学校名石碑照片（章节页整幅照片，10.0×4.7 in）
  - `5b14042c7a`＝同济校园照片（版式"封面2"整页背景，用于结束页）
- **新章节仍需抽查**：导出该章所有"大面积图片"（≥45% 版心）＋少量 jpeg，用识图确认内容（第 2 章抽查了 4 张，均为内容图表/历史照片，非他校照片）。
- 命令要点：`python-pptx` 遍历组合内图片 → 取 `shape.image.blob` → sha1 前 10 位建索引 → 与"已知他校图"哈希比对；同时统计 `ppt/media/*` 与 `ppt/slideLayouts|slideMasters` 的引用关系。

### 2. 生成替换图（cover 裁切 + 调色）
1. **等比放大**：横幅源图（广金官网 `https://www.gduf.edu.cn/images/47.jpg`，1920×500，站点最大尺寸）放大到恰好盖满目标框（一般 2.00×）。
2. **横向裁切**（不拉伸、不留模糊延伸）：裁切窗口按主体位置给 `bias`（广金主体建筑偏右，取 0.53–0.56）。
3. **反锐化**：`UnsharpMask(radius=2, percent=85)`，补回插值造成的发虚。
4. **调色对齐原图**：先量原图的 HSV 均值（饱和度/明度/色相），再对新图做
   `Color(目标饱和/当前饱和)` → `Brightness(目标明度/当前明度)`，并叠加 18% 模板主蓝 `#1F4E79` 使其融入蓝色调。
   - 实测目标：`image20/image14` 饱和 0.25、明度 0.70；`image1` 饱和 0.27、明度 0.58。
5. **写回 pptx**：**只替换 `ppt/media/<名>` 的字节**，其余条目原样复制。校验方式：逐 XML 比对颜色值，差异必须为 **0**。

### 3. 踩过的坑
- 图片部件在包内是**共享 part**：多个版式引用同一张图，边遍历边替换会漏掉后续引用 —— 先登记、再统一替换。
- 只改颜色不改图＝错：曾把同济石碑照片"染红"，被一眼看穿；**该换就换**。

---

## 三、逐页转写网页流程

```bash
# 1) 每页渲染成图（150 DPI → 1500×844；如需更清晰可提高 -r）
soffice --headless --convert-to pdf --outdir _conv "课件PPT-GDUF版/ChN-xxx-GDUF版.pptx"
pdftoppm -r 150 -png "_conv/ChN-xxx-GDUF版.pdf" "_conv/assets/page/slide"
# 2) 抽取每页文字（含位置、字号、粗体）与全部媒体
python _conv_work/_extract.py "课件PPT-GDUF版/ChN-xxx-GDUF版.pptx" _conv
# 3) 生成学生版网页（页数=源页数；问题页答案同页折叠；目录页含关键词搜索）
python _conv_work/_build_student.py _conv "_deploy/stmt-lectureN" \
  "软件测试课程设计" "第 N 章 xxx" _conv/_answers.json
```

要点：
- **组合形状坐标变换**：`子坐标 → 页面坐标` 用组合的 `off/ext` 与 `chOff/chExt` 做仿射映射（`_extract.py` 的 `group_map`）。
- **媒体按内容去重**：同一张图在包内多处引用只导出一次，命名 `img-<sha1-10>.<ext>`。
- **答案配置外部化**：`_answers.json` 形如 `{"85": {"q": "思考题", "a": ["…","…"]}}`；**只传该章的配置**（曾因脚本内置默认值导致第 1 章答案串到第 2 章）。
- **JSON 里用全角引号**：答案文本含 ASCII 双引号会直接让 JSON 解析失败。
- **文件名补零对齐**：`pdftoppm` 产出 `slide-01.png`（2 位）而 HTML 引用 `slide-001.png`（3 位）→ 统一重命名，并做**文件存在性校验**（不是只查字符串）。
- 校验清单：页数＝源页数｜文字块数＝源文字块数｜资源引用全部落地（引用数 vs 缺失数）｜页面内 `data-mode` 计数为 0｜问题页含"查看参考答案"。

---

## 四、上线到云服务器

```bash
tar czf /tmp/stmt-lectureN.tar.gz stmt-lectureN
~/Downloads/scp_cloud.sh /tmp/stmt-lectureN.tar.gz /root/stmt-lectureN.tar.gz
~/Downloads/ssh_cloud.sh 'cd /var/www/stmt && cp -a lectureN _backup-lectureN-<日期> \
  && rm -rf /tmp/new && mkdir -p /tmp/new && tar xzf /root/stmt-lectureN.tar.gz -C /tmp/new \
  && rm -rf lectureN && mv /tmp/new/stmt-lectureN lectureN \
  && chown -R lighthouse:lighthouse lectureN && rm -f /root/stmt-lectureN.tar.gz'
```

- 站点：`stmt-web.service`（`python3 -m http.server 2345 --directory /var/www/stmt`），静态站，替换文件后**无需重启**。
- 首页 `index.html` 的入口本来就是 `lectureN/index.html`，替换目录即可，不用改主页。
- **先备份再替换**（服务器上保留 `_backup-lectureN-*`），出问题可一键回滚。
- 校验三段：服务器本机 `127.0.0.1:2345` → **公网** `111.231.0.226:2345` → 关键文件 md5 与本地一致。

---

## 五、命令速查（本章一键流程）

```bash
cd "/home/zyw/Downloads/dl-hub/25-软件测试方法和技术第4版OCR整理"

# ① 换图（第 2 章为例）
python _brand_work/_gduf_apply.py \
  "课件PPT-加校徽/Ch2-软件测试基本概念-STMT-2022.pptx" \
  "课件PPT-GDUF版/Ch2-软件测试基本概念-GDUF版.pptx" \
  "image14.jpg=2130x1000@0.56@0.70@0.25" "image1.jpg=1780x1000@0.53@0.58@0.27"

# ② 渲染 + 抽取 + 生成学生版
soffice --headless --convert-to pdf --outdir _conv2 "课件PPT-GDUF版/Ch2-软件测试基本概念-GDUF版.pptx"
pdftoppm -r 150 -png "_conv2/Ch2-软件测试基本概念-GDUF版.pdf" "_conv2/assets/page/slide"
python _conv_work/_extract.py "课件PPT-GDUF版/Ch2-软件测试基本概念-GDUF版.pptx" _conv2
python _conv_work/_build_student.py _conv2 "_deploy/stmt-lecture2" "软件测试课程设计" "第 2 章 软件测试基本概念" _conv2/_answers.json

# ③ 上线（见第四节命令）
```

---

## 六、已完成与待办

| 章 | 源页数 | 换图 | 学生版 | 云端 | 备注 |
|---|---|---|---|---|---|
| 第 1 章 引论 | 61 | image20.jpg / image1.jpg | ✅ 57、59 页折叠答案 | ✅ `/lecture1/` | 旧 40 页重编版已备份 |
| 第 2 章 软件测试基本概念 | 87 | image14.jpg / image1.jpg | ✅ 85 页折叠答案 | ✅ `/lecture2/` | 占位页已备份 |
| 第 3–15 章 | 待做 | 每章先比对哈希找同源同济图 | 每章按问题页配置 `_answers.json` | 替换 `lectureN/` | 流程已全部脚本化 |
