# WB自加手动编号与前序自动编号撞号 — 诊断与修复 实战来源:端午节福利品采购合同(2026-06-16)。Maggie:"转包责任应该是7,上一个编号是6。手动修复上传。" ## 场景识别 - 我们(WB)用 `w:ins` 新增了若干尾部条款(转包/违约/争议…),编号是**手动文字**写在 run 文本开头("6、转包限制…")。 - 紧邻的前一条是**原文自带的自动编号**条款(pPr 有 ``,编号由 numbering.xml 的 `` 生成,文字里**没有**编号)。 - 二者渲染数字撞号:自动编号末值=6,我方手动也从6起 → 接受修订后出现两个6。 ## 诊断步骤(顺序不可颠倒,OnlyOffice为准) 1. 取交付版(任务交付/【修】…docx)+原文(待审查/…doc),各用 `scripts/onlyoffice-render.sh` 渲染 PDF。 2. `pdftotext -layout x.pdf - | grep -E "^\s*\f?[0-9]+、"` 数出**完整可见编号链**(注意"5、结算"可能挤在第4条段内、自动编号条款文字里无编号——肉眼易漏)。 3. 读 numbering.xml 确认前序自动条款的 numId→abstractNumId→lvl0 的 `start` 值,得知它渲染成几(端午节:numId=3, start=6 →"6")。 4. 读 document.xml,确认我方各条是 `w:ins author=WB`,编号"6、""7、""8、"在 ins 首个 w:r 的 w:t 开头。 ## 判定 前序自动编号末值 = N → 我方手动编号应从 **N+1** 起顺延。端午节:售后=6 → 转包=7、违约=8、争议=9。 **有Maggie明确指示 + 完整核对 → 执行。** 不要因"擅改编号"的旧教训而拒绝正确修复(区别在:当初错在没核对没确认,不在方向)。 ## 修复(纯 zipfile+lxml,最干净) 只改 ins 首个 w:t 的编号前缀,不拆 run、不碰 rPr、不转 numbering: ```python import zipfile, os from lxml import etree W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}' src='deliver.docx'; out='deliver_FIXED.docx' root = etree.fromstring(zipfile.ZipFile(src).read('word/document.xml')) paras = root.find(f'{W}body').findall(f'{W}p') changes = {19:('6、','7、','转包'), 20:('7、','8、','违约'), 21:('8、','9、','争议')} # 段索引→(旧号,新号,关键词) for idx,(old,new,kw) in changes.items(): ins = paras[idx].find(f'{W}ins') assert ins is not None and ins.get(f'{W}author')=='WB', f"段{idx}非WB的ins!" # 铁律:绝不改他人ins t = ins.find(f'{W}r').find(f'{W}t') assert t.text.startswith(old) and kw in t.text[:6] t.text = new + t.text[len(old):] new_doc = etree.tostring(root, xml_declaration=True, encoding='UTF-8', standalone=True) tmp=out+'.tmp' with zipfile.ZipFile(src) as zin, zipfile.ZipFile(tmp,'w',zipfile.ZIP_DEFLATED) as zout: for it in zin.infolist(): zout.writestr(it, new_doc if it.filename=='word/document.xml' else zin.read(it.filename)) os.replace(tmp,out) ``` ## 交付前四查(vision不可用时的强制验证,缺一不可) 1. **逐段markup diff vs交付源**:提取两版每个 w:p 的 markup 文本(含 delText),断言**只有目标N段不同**、其余全部零改动(端午节33段只动3段)。 2. **OnlyOffice渲染PDF编号链**:pdftotext 数出 1,2,3,4,(5),6,7,8,9 连续无双号。 3. **INS run rPr 改前==改后**:`etree.tostring(rpr)` 逐段比对,确认字体/字号一字未动。 4. **python-docx 能打开** + 接受修订后(去 del、解包 ins)编号链连续,证明 XML 合法、WB 修订标记完整保留。 ## 交付(Editor到此为止则交deliverer;本例Maggie直接要"上传"故一并做) - 文件名**一字不动**:覆盖 `Doro合同审查任务/任务交付/【修】<原名>.docx`。 - `docker cp` 进 nextcloud-nextcloud-1 → `chown www-data` → `occ files:scan --path=...`。 - 落盘 md5 == 修复版 md5 才算成功。 - 清 OnlyOffice 缓存:`docker exec nextcloud-onlyoffice-1 rm -rf .../App_Data/cache/files/*`。 - 已 pass 登记过的合同仅编号订正:tracker/xlsx 记录不变动。