Files
deep_research/.agent/skills/pdf-reportlab/SKILL.md
T

9.0 KiB
Raw Blame History

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

  • 同 h2keepWithNext=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_subtitle
  • manifest.confidentiality (如 "机密 | 仅供迈威生物内部决策使用")
  • manifest.author / manifest.date / manifest.version

七、页眉页脚(简洁化)

页眉

左边:报告简称(从 manifest.report_title 取前 15 字) 右边:章节名(动态,从当前 h1 内容取) 底线:#e5e7eb 浅灰分隔线

页脚

居中:页码(格式 — X — 字号:8pt#9ca3af 浅灰

特殊页

  • 封面:无页眉页脚
  • 免责声明:无页眉,仅页脚
  • 其他(摘要/术语表/目录/正文/附录/参考文献):有页眉页脚

八、报告结构(11 件套)

ReportLab 按以下顺序组装:

  1. 封面cover PageTemplate
  2. 免责声明normal PageTemplate,单页)
  3. Executive Summary / 执行摘要summary PageTemplate1-2 页)
  4. Abstract / 摘要normal,单页)
  5. Glossary / 术语表normal
  6. Table of Contents / 目录TOC,自动生成)
  7. 正文各章normal,每章 h1 强制分页)
  8. 结论与建议(正文的一部分)
  9. 附录normal
  10. 参考文献bibliography PageTemplatefootnote 样式)
  11. 版本信息normal,单页)

九、Markdown 支持范围

Markdown ReportLab 渲染
# 第 X 章 ... h1(新起一页,深蓝色)
## X.Y ... h2(节,蓝色,不分页)
### X.Y.Z ... h3(小节,深灰)
**粗体** inline <b>
*斜体* inline <i>
`代码` 等宽字体
> 引文 quote 样式(楷体,浅底色)
- 项 / 1. 项 项目符号列表
表格 | | | Table,自动列宽 + splitByRow
![caption](path) 图片 + 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-12020-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) 图片引用
   - 验证每个 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 再润色一轮。