# 专利交底书 .docx 输出格式规范

本文档是 `SKILL.md` 第五阶段格式规范的详细附录，来源于客户提供的《技术交底书模板.doc》。规范用于驱动 `scripts/md2docx.js` 生成符合代理人审阅习惯的 .docx 文档。

## 1. 页面参数

| 项 | 取值 |
| --- | --- |
| 纸张 | A4（宽 11906 DXA × 高 16838 DXA） |
| 上下页边距 | 1440 DXA（≈2.54 cm） |
| 左右页边距 | 1800 DXA（≈3.17 cm） |
| 页码 | 底部居中，9pt（sz=18），字体随正文 |
| 行号、装订线 | 不启用 |

## 2. 字体清单

| 角色 | 东亚字体（eastAsia） | 西文字体（ascii / hAnsi / cs） | 用途 |
| --- | --- | --- | --- |
| 正文 | 宋体 | Times New Roman | 段落、表格单元格、列表项 |
| 章节标题 | 楷体_GB2312 | Times New Roman | `#` / `##` / `###` / `####` |
| 大标题 | 楷体_GB2312 | Times New Roman | 文档首行「技术交底书」 |
| 头部字段 | 仿宋_GB2312 | Times New Roman | 交底书名称 / 发明人 / 联系人 / 电话 / E-MAIL |
| 代码 | 宋体（兜底） | Consolas | 行内 `` ` `` 与 ``` ``` |

> 字体名按模板原文写为 `宋体`、`楷体_GB2312`、`仿宋_GB2312`。Mac/Linux 缺字时可在 fontTable.xml 中追加 fallback，本规范不强制。

## 3. 字号

| 角色 | 字号 | docx-js `size`（半磅） | 行内字符 size |
| --- | --- | --- | --- |
| 大标题 | 18pt（二号） | 36 | — |
| 正文 / 标题 / 头部字段 | 10.5pt（五号） | 21 | — |
| 代码 | 10pt | 20 | — |
| 页码 | 9pt | 18 | — |

> 章节标题与正文同字号，仅"字体 + 加粗"区分；不要把章节标题做大字号，与模板不符。

## 4. 段落参数

| 段落 | 行距 | 对齐 | 首行缩进 | 段前 / 段后 |
| --- | --- | --- | --- | --- |
| 大标题 | line=420 exact | center | 无 | 240 / 240 |
| 头部字段 | line=360 auto（1.5x） | left | 无 | 0 / 0 |
| 章节标题 H1 | line=420 exact | left | 无 | 240 / 120 |
| 章节标题 H2 | line=420 exact | left | 无 | 160 / 80 |
| 章节标题 H3 | line=420 exact | left | 无 | 140 / 60 |
| 章节标题 H4 | line=420 exact | left | 无 | 120 / 60 |
| 正文 | line=360 auto（1.5x） | both（两端对齐） | 420 twips（2 字） | 0 / 0 |
| 列表项 | line=360 auto | both | 720 hanging 360 | 0 / 0 |
| 代码块行 | line=300 auto | left | 无 | 0 / 0；底色 `#F5F5F5` |

行距单位说明：在 docx-js 里 `spacing.line` 单位为二十分之一磅；`lineRule: "exact"` 表示固定行高，`"auto"` 表示倍数（240 = 1x，360 = 1.5x，420 = 21pt 固定）。

## 5. 颜色

| 角色 | RGB |
| --- | --- |
| 正文 / 标题 / 头部 / 表格 / 列表 / 代码 | `#000000`（黑） |
| 占位提示语（如「（请客观评价…）」） | `#0000FF`（模板蓝），仅出现在保留模板占位的场合 |
| 表格表头底色 | `#E7E6E6` |
| 代码块底色 | `#F5F5F5` |

> 正式交付的交底书中不应出现模板蓝；若文档中出现蓝色文字，说明仍残留模板占位语，需替换为真实内容。

## 6. 附图嵌入规范

代理人审阅交底书时需要直接看到附图，**不能**接受 `[![附图1 - 四遍扫描整体流程](media/doc1_fig1.png)]` 这类文本描述形式。生成 docx 时必须把图片真正嵌入到对应位置。

### 6.1 Markdown 写法

附图必须 **独立成行**：

```markdown
![附图1 - 四遍扫描整体流程](media/doc1_fig1.png)
```

不要把附图与正文混排在同一段；非独立行的 `![]()` 不会触发图片嵌入，仍按文本处理。

### 6.2 文件组织

- 推荐每篇交底书 md 的同目录下建立 `media/` 子目录，把附图放在里面
- 命名建议：`doc{交底书序号}_fig{图序}.png`，例如 `media/doc1_fig1.png`、`media/doc1_fig2.png`
- 路径解析以 md 文件所在目录为基准；只支持相对路径或绝对路径

### 6.3 嵌入与缩放规则

| 项 | 取值 |
| --- | --- |
| 支持格式 | png / jpg / jpeg / gif / bmp / svg |
| 真实像素读取 | png：解析 IHDR 块拿真实宽高；其它格式：按 4:3 兜底 |
| 目标宽度 | 540 px（≈内容区宽度 8306 DXA，留少量边距） |
| 高度上限 | 720 px |
| 缩放 | 等比；高度超限时按高度反算宽度，绝不裁剪、绝不拉伸 |
| 图片段落对齐 | 居中 |
| 图片段落行距 | 1.5x（line=360 auto）；段前 120 / 段后 40 twips |

### 6.4 图注

`![alt](path)` 中的 `alt` 文字会自动生成图注段落紧跟在图片下方：

- 字体：宋体（东亚）+ Times New Roman（西文）
- 字号：10pt（sz=20）
- 字形：斜体
- 对齐：居中
- 行距：1.25x（line=300 auto），段后 120 twips

`alt` 为空时不输出图注段落。

### 6.5 容错

- 图片路径不存在：在文档中插入红色 `[图片缺失] alt (src)` 文本，**不**抛错中断转换
- 非 png 图片读取尺寸失败：按 4:3 兜底
- 跨平台路径分隔符：始终用 `path.resolve` 统一为绝对路径再读

### 6.6 docx-js API 关键写法

`ImageRun` 必须传 `type` 参数，且 `altText` 三字段全填：

```js
new ImageRun({
  type: "png",
  data: fs.readFileSync(absPath),
  transformation: { width: 540, height: 360 },
  altText: { title: "附图1", description: "附图1", name: "doc1_fig1.png" },
});
```

`scripts/md2docx.js` 已封装以上全部逻辑，调用脚本即可，无需手写 ImageRun。

## 7. 表格规范

- 宽度模式：`WidthType.DXA`（不要用百分比）
- 表格总宽 = 列宽之和 = 内容区宽度（A4 默认 8306 DXA）
- 单元格四周边框：`BorderStyle.SINGLE`，size=4，color=`808080`
- 单元格 padding：`{ top: 80, bottom: 80, left: 120, right: 120 }`
- 表头：底色 `#E7E6E6`，居中加粗
- 单元格段落行距：1.25x（line=300 auto）

## 8. 头部字段识别规则

满足以下任一正则的段落会被识别为"头部字段"，自动套用仿宋_GB2312 加粗：

```text
^\s*\*\*交底书名称[：:].*\*\*
^\s*\*\*本专利发明人[：:].*\*\*
^\s*\*\*技术问题联系人[：:].*\*\*
^\s*\*\*联系人电话[：:].*\*\*
^\s*\*\*E-?MAIL[：:].*\*\*
```

为避免相邻头部字段被合并为单段，tokenizer 在遇到 `**xxx：**` 形式的行时不与上下行合并。

## 9. 自检（生成后）

生成 docx 后，建议执行：

```bash
python scripts/office/unpack.py 专利交底书_X_20260318.docx tmp/
grep -oE 'w:eastAsia="[^"]+"' tmp/word/document.xml | sort | uniq -c
grep -oE 'w:color w:val="[A-F0-9]+"' tmp/word/document.xml | sort | uniq -c
ls tmp/word/media/ 2>/dev/null | wc -l   # 内嵌图片数
```

期望输出：

- `仿宋_GB2312` 恰好出现 **5** 次（五个头部字段）
- `楷体_GB2312` 出现次数 ≥ 章节标题数
- 其余东亚字体均为 `宋体`
- `w:color` 仅出现 `000000`（除非显式保留蓝色占位语）
- 内嵌图片数 = md 中独立行 `![alt](path)` 的个数（即 md 中 `grep -cE '^\s*!\[' *.md`）

任一项不满足，需检查 md 源文档结构与 `scripts/md2docx.js` 的常量配置。

## 10. 客户换模板的更新步骤

1. 转换为 .docx：`soffice --headless --convert-to docx 新模板.doc`
2. 解包：`python scripts/office/unpack.py 新模板.docx tmpl/`
3. 在 `tmpl/word/styles.xml` 中读取：
   - `<w:docDefaults>` → 默认 rFonts / sz（决定正文默认值）
   - `Heading1` / `Heading2` 等内置标题样式 → 章节标题字体、字号、行距
4. 在 `tmpl/word/document.xml` 中抽样几段实际文本，确认实际使用的 rPr 是否覆盖了 styles 默认值
5. 将差异写入本规范 § 2~7 表格，同时同步修改 `scripts/md2docx.js` 顶部常量
6. 重跑 § 9 自检
