# 法律文书：脚注、同源模板成稿、Doro 编辑后字体修复

contract-editor 库（zipfile+lxml）在**新成稿文书**（非修订态）上的复用。2026-06-23-24 邹家《情况反映》制作中验证。配套 `litigation-doc-tracked-changes.md`（那篇讲修订态；本篇讲脚注+新建文书+字体规范化，都不是 tracked-changes）。

## 1. 法条原文脚注——从同案"姊妹文书"克隆脚注样式（铁律：脚注样式不要凭空造）

需求场景：Doro 把正文里的法条引用（"《民事诉讼法》第七十一条之规定"）要求改成**脚注呈现法条全文**，且"脚注格式和申请书一样"。

正确做法是从**同案已有带脚注的文书**（如同目录的《民事诉讼监督申请书》v9）克隆脚注体例，而不是自己拼 footnotes.xml：

**脚注的两个组成**（先从姊妹文书读出样式模板）：
- 正文里的**引用标**：一个 `<w:r>`，rPr 带 `<w:rStyle w:val="affb"/>` + Times New Roman + 与正文同字号（sz24），内含 `<w:footnoteReference w:id="N"/>`。`affb` 是 Word 默认的 FootnoteReference 字符样式 id（不同文档可能不同，**从姊妹文书正文的 footnoteReference 承载 run 实测，别硬编码**）。
- footnotes.xml 里的**脚注正文**：separator/continuationSeparator 两个特殊脚注（id=-1/0，原样复制）+ 内容脚注（id≥1）。内容脚注段落 spacing line=240，run 字号是**脚注体例 sz18（9pt，小于正文）**，法名加粗（`<w:b/>`）、条号与原文不加粗。

```python
# 从姊妹文书 sqs_v9.docx 取模板
fn_sqs = etree.fromstring(z_sqs.read('word/footnotes.xml'))
special = {ft: deepcopy(f) for f in fn_sqs.iter(qn('footnote'))
           for ft in [f.get(qn('type'))] if ft in ('separator','continuationSeparator')}
content_tmpl_p = deepcopy([f.find(qn('p')) for f in fn_sqs.iter(qn('footnote'))
                           if f.get(qn('id'))=='1'][0])
# 从模板段落抽三种 rPr：mark(带rStyle affb)、bold(法名)、plain(原文)
# 正文引用标 rPr 则从姊妹文书 document.xml 里 footnoteReference 承载 run 抓
```

**目标 docx 必须已支持脚注**：`word/_rels/document.xml.rels` 有 footnotes 关系、`[Content_Types].xml` 有 `footnotes+xml`、styles.xml 有 `affb` 样式。若目标是从同源文书演化来的（本例情况反映以申请书为母版），这三样天然齐全；若从零新建则要补。

## 2. 脚注标定位的坑：锚点跨 run 时 footnoteReference 会插错位置（本会话实犯）

把脚注标插在"第五十一条第二款"之后时，第一版用"找锚点子串→定位锚点所在 run→run 后插标"，结果 ³ 插到了下游的"承办部门"后面——因为锚点文字**跨多个 run**，按 run 粒度定位会落到错误的 run。

**正解：字符流定位 + 必要时拆 run**。把全段所有 `w:t` 拼成字符流，建立 `每个字符→(t元素, 字符在t内的索引)` 映射，找到锚点**结束字符**的精确位置；若结束字符在某 run 中间，**split 该 run**（head 留原 run，tail 进新 run），脚注引用 run 插在 head 和 tail 之间。这样标精确落在"…第二款【标】所定…"。

验证只能靠 OnlyOffice x2t 渲染后看页脚——vision 一眼就抓出"³ 标在承办部门后"，肉眼读 XML 容易漏。体例统一：四个脚注一律"法条号正后方"挂注（不要有的挂句末有的挂条号后）。

## 3. 用同案文书做"母版"新建文书——保证两份同源同体例

新建《情况反映》时，以同案《民事诉讼监督申请书》v9 为母版克隆，确保字体/字号/页边距/样式完全一致（Doro/Maggie 两份并排看不会有体例差）：
- 从母版抽各类段落模板：title(居中bold sz30)、body(首行缩进480 sz24)、recip(顶格bold 机关名)、sign(右对齐)、date、attachment-title、attachment-item。`mk(tmpl_key, text, bold=, no_indent=)` 克隆模板段→清空 run/numPr/ins/del→重设仿宋+Times→填文字。
- 用母版的整个 docx 做容器（保留 sectPr 页面设置、styles、numbering），只重写 body 的段落序列 + 清掉 `<w:trackRevisions/>`。
- **清掉母版页眉**：母版页眉可能是另一种文书的抬头（本例申请书页眉"申请监督案号/受理法院"套在情况反映上不对）。清页眉要两步：①删页眉段所有 run 文字；②**删页眉段 pPr 的 `<w:pBdr>`**（页眉那条横线来自段落下边框，只删文字会留一条孤线）。OnlyOffice 渲染确认顶部纯白到标题。

## 4. ⚠️Doro 用编辑器改过的 docx 会丢显式 eastAsia 字体属性——每轮都要补（本会话两轮各犯一次）

**现象**：Doro 在他本机编辑器改过 docx 后回传，正文中文 run 的 `rFonts` **没有显式 eastAsia 字体名**（本会话两轮分别 1283、1243 个中文字符 `eastAsia=None`，docDefaults 也空）。OnlyOffice 靠底层回退仍渲染成仿宋、肉眼看正常，但**显式字体属性缺失不符合交付标准**（我们要求中文显式仿宋）。

**判别**：交付前扫一遍——
```python
for r in root.iter(qn('r')):
    rf = r.find(qn('rPr/rFonts'))
    ea = rf.get(qn('eastAsia')) if rf is not None else None
    # 统计含中文 run 里 ea is None 的数量；>0 就要补
```

**修复（格式规范化，不改字形/文字/Doro 内容）**：每个含文字的 run，rFonts 显式设 `eastAsia=仿宋`，缺 ascii/hAnsi 的补 `Times New Roman`；再给 `docDefaults/rPrDefault/rPr/rFonts` 补 `eastAsia=仿宋` 兜底。改完目标：CJK 全仿宋、英数全 Times。**这是和合同字体规范化同类的操作，但要点在"每次 Doro 回传都要重做一遍"**——他的编辑器每改一次就再剥一次，不是一次性问题。改完必须 OnlyOffice 重渲染确认无字形回退（字体属性动过就要重验）。

## 5. 附件/正文 Doro 自己加的内容：修错别字但不擅改实质

Doro 自己在附件加了"检查监督申请书"——①错别字"检**查**"→"检**察**"院的监督，规范名应是与正式文件名一致的《民事诉讼监督申请书》（改）；②但若附件项之间有实质区分缺失（如两份《质证通知书》一份标了"3日期限版"另一份没标"15日期限版"），那是 Doro 定的内容，**只提示不擅改**。附件清单常是自动编号（numId），Doro 删手敲序号是对的，自动会续 1-6。

## 一句话
脚注从同案姊妹文书克隆样式（rStyle affb + sz18 脚注体、法名加粗）、标位置用字符流+拆run精确落在条号后；新建文书拿同案文书做母版保同源（清页眉含删 pBdr）；**Doro 编辑器回传的 docx 每轮都丢显式 eastAsia，每次交付前都要全局补仿宋再渲染**。
