Files
hermes-skills/skills/legal/contract-editor/references/review-opinion-font-enforcement.md
T

4.4 KiB

审查意见文档字体强制设置

背景(2026-07-02 肃言+恭兴合同返工)

review-rules.md 规定审查意见文档:中文统一仿宋体,英文Times New Roman。

问题:模板文件(朱家角 审查意见【模板】.docx)的表头行有显式eastAsia=仿宋,但新建的数据行字体设置不一致:

  • 恭兴审查意见:editor给数据行设了 ascii=仿宋 hAnsi=仿宋(错:英文也变仿宋了)
  • 肃言审查意见:editor压根没给数据行设ascii/hAnsi(只有eastAsia=仿宋)

根因:LLM每次独立session生成代码,字体设置逻辑不稳定。

强制修复代码(生成审查意见后必跑)

from docx import Document
from docx.oxml.ns import qn
from docx.oxml import OxmlElement

def enforce_review_opinion_fonts(doc_path, save=True):
    """审查意见文档生成后强制设置所有run的字体。
    中文=仿宋, 英文=Times New Roman
    """
    doc = Document(doc_path)
    fixed = 0
    
    # Fix all table cells
    for table in doc.tables:
        for row in table.rows:
            for cell in row.cells:
                for p in cell.paragraphs:
                    for run in p.runs:
                        fixed += _fix_run_font(run._element)
    
    # Fix all paragraphs outside tables
    for p in doc.paragraphs:
        for run in p.runs:
            fixed += _fix_run_font(run._element)
    
    if save:
        doc.save(doc_path)
    return fixed

def _fix_run_font(run_element):
    """Ensure run has eastAsia=仿宋, ascii/hAnsi=Times New Roman"""
    rPr = run_element.find(qn('w:rPr'))
    if rPr is None:
        rPr = OxmlElement('w:rPr')
        run_element.insert(0, rPr)
    
    rFonts = rPr.find(qn('w:rFonts'))
    if rFonts is None:
        rFonts = OxmlElement('w:rFonts')
        rPr.insert(0, rFonts)
    
    changed = False
    
    # eastAsia must be 仿宋
    if rFonts.get(qn('w:eastAsia')) != '仿宋':
        rFonts.set(qn('w:eastAsia'), '仿宋')
        changed = True
    
    # ascii must be Times New Roman (NOT 仿宋)
    if rFonts.get(qn('w:ascii')) != 'Times New Roman':
        rFonts.set(qn('w:ascii'), 'Times New Roman')
        changed = True
    
    # hAnsi must be Times New Roman (NOT 仿宋)
    if rFonts.get(qn('w:hAnsi')) != 'Times New Roman':
        rFonts.set(qn('w:hAnsi'), 'Times New Roman')
        changed = True
    
    return 1 if changed else 0

验证方法

def verify_review_opinion_fonts(doc_path):
    """验证审查意见文档字体全部正确"""
    from docx import Document
    from docx.oxml.ns import qn
    doc = Document(doc_path)
    errors = []
    for table in doc.tables:
        for i, row in enumerate(table.rows):
            for j, cell in enumerate(row.cells):
                for p in cell.paragraphs:
                    for run in p.runs:
                        rpr = run._element.find(qn('w:rPr'))
                        if rpr is None:
                            errors.append(f'Row{i}Col{j}: no rPr')
                            continue
                        rf = rpr.find(qn('w:rFonts'))
                        if rf is None:
                            errors.append(f'Row{i}Col{j}: no rFonts')
                            continue
                        ea = rf.get(qn('w:eastAsia'))
                        ascii_f = rf.get(qn('w:ascii'))
                        hAnsi = rf.get(qn('w:hAnsi'))
                        if ea != '仿宋':
                            errors.append(f'Row{i}Col{j}: eastAsia={ea} (should be 仿宋)')
                        if ascii_f != 'Times New Roman':
                            errors.append(f'Row{i}Col{j}: ascii={ascii_f} (should be TNR)')
                        if hAnsi != 'Times New Roman':
                            errors.append(f'Row{i}Col{j}: hAnsi={hAnsi} (should be TNR)')
    return errors

常见错误

错误 后果 根因
ascii/hAnsi=仿宋 英文/数字渲染用仿宋(无西文字形,显示异常) LLM把"统一仿宋"理解为所有属性都设仿宋
数据行无ascii/hAnsi 英文回退系统默认字体(可能是宋体/黑体) 只设了eastAsia,忘设西文字体
只有表头有字体 数据行全部回退默认 模板限制:只有表头行有显式字体

预防方案

最佳方案:修改模板文件的Normal样式或Table Grid样式定义,预设完整字体。但模板可能被多场景共用,最稳妥还是生成后强制设置。