- Split dr-chief-editor (Phase 3 read-only) vs new dr-editor-in-chief (Opus, Phase 4 lead) - New dr-translator (en->zh) and new humanizer-cn / output-hygiene / en-zh-translation skills - Switch to English working language (Phase 2-3), final Chinese translation (Phase 4) - /dr-init: add report title proposals + word budget mode - /dr-frame: bilingual framework - /dr-finalize: new chain editor->translator->polisher->reporter - report-template.py: widows/orphans/keepWithNext, 3-color hierarchy, confidentiality banner - dr-reporter: mandatory citations backfill + output hygiene check - dr-pm: batch-level context compression via manifest.batches_summary - mckinsey-method: SCQA only for Executive Summary + chapter intros (no explicit labels) - length-budget: 4 word-budget modes + en/zh 1:1.4 ratio
9.0 KiB
9.0 KiB
name, description
| name | description |
|---|---|
| pdf-reportlab | 用 ReportLab 生成专业中文 PDF 研究报告。集中样式管理、紧凑分页(widows/orphans/keepWithNext)、颜色层次、封面保密标识、页眉页脚简洁化。基于 9MW1911 综合战略报告的编排参考。 |
ReportLab 中文 PDF 模板使用指南(v0.5)
一、为什么是 ReportLab
- 完全可控:每个字号、行距、颜色由代码说了算,不被引擎意外改动
- 中文字体一次搞定:
pdfmetrics.registerFont注册后全局可用,子集嵌入 PDF,无授权问题 - 分页规则精确:支持 widows/orphans、keepWithNext、splitByRow 等避免孤行/寡行
- 图表嵌入高质量:matplotlib 300 DPI PNG,速度快
- 样式集中在 StyleSheet:避免字号不一
二、模板入口
脚本:.opencode/templates/report-template.py
调用:
uv run python .opencode/templates/report-template.py \
--input projects/<slug>/phase4/final.md \
--manifest projects/<slug>/manifest.json \
--output projects/<slug>/phase4/final.pdf \
--fonts-dir .opencode/templates/fonts
首次使用前:
bash .opencode/templates/fonts/download-fonts.sh
三、字体注册(7 个字重)
SrcSerif-Regular 思源宋体 Regular 正文
SrcSerif-Bold 思源宋体 Bold 正文粗体
SrcSans-Light 思源黑体 Light 页眉页脚
SrcSans-Medium 思源黑体 Medium 三级标题/图表
SrcSans-Bold 思源黑体 Bold 一二级标题
SrcSans-Heavy 思源黑体 Heavy 封面大标题
Kai 霞鹜文楷 Regular 摘要/引文
四、样式表(StyleSheet,集中管理)
| 样式名 | 字体 | 字号 | 行高 | 颜色 | 备注 |
|---|---|---|---|---|---|
body |
SrcSerif | 10.5 | 18 | #1a1a1a |
正文,首行缩进 21pt |
body-bold |
SrcSerif-Bold | 10.5 | 18 | #1a1a1a |
行内加粗 |
h1 |
SrcSans-Bold | 18 | 28 | #1e3a8a |
章标题,前强制分页 |
h2 |
SrcSans-Bold | 14 | 22 | #2c5282 |
节标题 |
h3 |
SrcSans-Medium | 12 | 18 | #374151 |
小节标题 |
quote |
Kai | 10.5 | 18 | #4b5563 |
引文 |
caption |
SrcSans-Medium | 9 | 13 | #6b7280 |
图表标题 |
footnote |
SrcSerif | 9 | 13 | #374151 |
脚注/参考文献 |
header-footer |
SrcSans-Light | 8 | 12 | #9ca3af |
页眉页脚 |
cover-title |
SrcSans-Heavy | 28 | 40 | #0f172a |
封面主标题 |
cover-subtitle |
SrcSans-Medium | 15 | 24 | #475569 |
封面副标题 |
cover-confidential |
SrcSans-Bold | 11 | 16 | #dc2626 |
封面保密标识(红色) |
cover-meta |
SrcSerif | 11 | 18 | #334155 |
封面元信息 |
summary |
SrcSerif | 11 | 20 | #1a1a1a |
执行摘要 |
五、分页规则(关键升级点)
章(h1)
pageBreakBefore=1(每章新起一页)keepWithNext=1(标题和下一段不分离)
节(h2)
- 禁止单独触发分页
keepWithNext=1(标题紧跟内容)
小节(h3)
- 同 h2,
keepWithNext=1
段落
widows=2, orphans=2(避免寡行/孤行)- 每段之间
spaceBefore=6, spaceAfter=6
表格
TableStyle中启用splitByRow=True(长表格按行分页)repeatRows=1(表头在分页后重复)- 单元格 padding 统一 4-6pt
摘要/术语表/目录/参考文献
- 每个独占起始页(用
PageBreak)
六、封面模板(参考 9MW1911)
封面独立一页,无页眉页脚,布局:
(上 30% 空白)
主标题(cover-title,黑色,居中)
副标题(cover-subtitle,深灰,居中)
(中部 40% 空白)
[机密 | 仅供 XX 内部决策使用] (cover-confidential,红色,居中)
(下部 20%)
类型:研究类
作者:Deep Research 系统 / <公司名>
编制日期:YYYY 年 M 月
版本:v1.0
字段来源:
manifest.report_title/report_subtitlemanifest.confidentiality(如 "机密 | 仅供迈威生物内部决策使用")manifest.author/manifest.date/manifest.version
七、页眉页脚(简洁化)
页眉
左边:报告简称(从 manifest.report_title 取前 15 字)
右边:章节名(动态,从当前 h1 内容取)
底线:#e5e7eb 浅灰分隔线
页脚
居中:页码(格式 — X —)
字号:8pt,#9ca3af 浅灰
特殊页
- 封面:无页眉页脚
- 免责声明:无页眉,仅页脚
- 其他(摘要/术语表/目录/正文/附录/参考文献):有页眉页脚
八、报告结构(11 件套)
ReportLab 按以下顺序组装:
- 封面(cover PageTemplate)
- 免责声明(normal PageTemplate,单页)
- Executive Summary / 执行摘要(summary PageTemplate,1-2 页)
- Abstract / 摘要(normal,单页)
- Glossary / 术语表(normal)
- Table of Contents / 目录(TOC,自动生成)
- 正文各章(normal,每章 h1 强制分页)
- 结论与建议(正文的一部分)
- 附录(normal)
- 参考文献(bibliography PageTemplate,footnote 样式)
- 版本信息(normal,单页)
九、Markdown 支持范围
| Markdown | ReportLab 渲染 |
|---|---|
# 第 X 章 ... |
h1(新起一页,深蓝色) |
## X.Y ... |
h2(节,蓝色,不分页) |
### X.Y.Z ... |
h3(小节,深灰) |
**粗体** |
inline <b> |
*斜体* |
inline <i> |
`代码` |
等宽字体 |
> 引文 |
quote 样式(楷体,浅底色) |
- 项 / 1. 项 |
项目符号列表 |
表格 | | | |
Table,自动列宽 + splitByRow |
 |
图片 + caption 样式 |
[src_001] |
上标引用 |
--- |
分页符 |
不支持:HTML 标签、数学公式、代码块高亮。
十、图表嵌入
不用 ReportLab 原生绘图,全部预渲染为 PNG:
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
font_path = '.opencode/templates/fonts/SourceHanSansSC-Medium.otf'
fm.fontManager.addfont(font_path)
plt.rcParams['font.family'] = 'Source Han Sans SC'
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize=(6, 4), dpi=300)
# ...
plt.savefig('projects/<slug>/phase4/figures/fig_01_XXX.png', dpi=300, bbox_inches='tight')
Markdown 中引用:![图 1-1:2020-2025 GLP-1 市场规模(数据来源:[src_042])](figures/fig_01_XXX.png)
十一、manifest 必需字段
{
"slug": "...",
"report_title": "自研 O-糖苷酶立项可行性研究报告",
"report_subtitle": "对标 NEB 与 Merck 经典产品的技术路径、IP 壁垒与差异化战略",
"confidentiality": "机密 | 仅供内部决策使用",
"author": "Deep Research 系统",
"date": "2026-04-21",
"version": "1.0",
"type": "研究类",
"disclaimer": "本报告基于公开信息与 AI 辅助研究生成,仅供参考..."
}
十二、常见坑与对策
| 坑 | 对策 |
|---|---|
| 中文字号不一 | 集中 StyleSheet,不在 Paragraph 里 inline 改 fontSize |
| 行距太挤 | 行高 = 字号 × 1.5~1.7 |
| 换行断错 | wordWrap='CJK' 必设 |
| 表格被截断 | splitByRow=True, repeatRows=1 |
| 标题孤行(页末一个标题后直接新页) | keepWithNext=1 |
| 段落寡行(末段只剩一行在下页) | widows=2, orphans=2 |
| 图片变形 | 先 matplotlib 出 300 DPI PNG,再 Image(path, width=..., kind="proportional") |
| 生成慢 | matplotlib 图表预渲染,不要在 PDF 生成阶段现算 |
| 参考文献丢失 | dr-reporter 出稿前检查:读 citations.md,确认内容已写入 final.md |
十三、dr-reporter 调用流程
1. 环境检查
- 字体 ≥6 个 OTF 文件
- final.md 存在
- manifest.json 有必需字段
2. 回填参考文献(关键步骤,修复 v0.4 的 bug)
- 读 citations.md 内容
- 在 final.md 中找到"## 参考文献"段落
- 如果段落内容是占位符(如 "[由 dr-reporter 自动生成]" 或为空)
→ 替换为 citations.md 的完整内容
- 写回 final.md
3. 图表检查
- 扫描 final.md 中所有  图片引用
- 验证每个 path 在 figures/ 目录下存在
- 缺失图片 → 警告并继续,但汇报中注明
4. 生成 PDF
uv run python .opencode/templates/report-template.py \
--input projects/<slug>/phase4/final.md \
--manifest projects/<slug>/manifest.json \
--output projects/<slug>/phase4/final.pdf \
--fonts-dir .opencode/templates/fonts
5. 生成 DOCX(可选)
pandoc projects/<slug>/phase4/final.md \
--from markdown --to docx \
--output projects/<slug>/phase4/final.docx \
--toc --toc-depth=3
6. 验证
- PDF 文件大小 > 500KB(太小说明字体没嵌)
- PDF 页数合理(按字数估算)
- "参考文献"章节存在且非空
7. 汇报
十四、输出卫生检查(必跑)
生成 PDF 前:
# 加载 skill:output-hygiene
python3 .opencode/templates/hygiene_check.py projects/<slug>/phase4/final.md
禁止词残留 → 抛回 dr-polisher 再润色一轮。