📓开发指南

开发者指南

GJB438C-DocSkill 开发与扩展指南

1. 开发环境配置

1.1 系统要求

要求 说明
Python 3.10+(使用 from __future__ import annotations
操作系统 Windows / macOS / Linux

1.2 依赖安装

1
pip install python-docx>=1.1.0

1.3 项目结构(以 [10] 为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
skills/word-fillter-438c-srs/
├── SKILL.md # Skill 定义(触发关键词、约束、工作流)
├── documents/
│ └── [10][SRS] 软件需求规格说明-438C-2021.docx
├── templates/
│ ├── config.json # 封面信息配置
│ └── project.json # 章节内容配置
└── scripts/
├── main.py # CLI 入口(调用 pipeline.main)
├── process.py # 免参数入口(硬编码路径)
└── strict_word_filler/ # 核心引擎
├── __init__.py
├── models.py # 不可变数据模型
├── loader.py # JSON → BuildPlan
├── docx_ops.py # Word 文档操作
├── template_rules.py # 模板锚点常量
├── errors.py # 异常类型
└── pipeline.py # CLI 参数解析

2. 核心模块详解

2.1 models.py — 数据模型

所有数据类均使用 @dataclass(frozen=True) 确保不可变性。

通用模型([10] 和 [11] 共享)

模型 用途
ExactReplaceRule 精确文本替换(封面信息)
ParagraphReplaceRule 段落锚点替换(正文内容)
DynamicSectionItem 动态章节子项(section_id + title + body)
DynamicSectionRule 动态章节规则(克隆原型段落生成子节)
TableFillRule 表格填充(locator_rows + rows)
BuildPlan 构建计划(所有规则的不可变容器)

[11] 专属模型

模型 用途
CSCISectionItem CSCI 子项(9 个字段)
CSCISectionRule CSCI 章节规则(13 个锚点)

2.2 loader.py — 构建计划

build_plan(config_data, project_data) 解析两个 JSON 并构建 BuildPlan

  1. config.json 提取封面字段 → 生成 ExactReplaceRule
  2. 遍历 project.jsonstructure → 生成各类 Rule
  3. 校验所有必填字段,缺失时抛出 StrictDataError

关键校验:

  • _require_content() — 确保字段存在且非空
  • _require_int() — 确保整数字段合法
  • _sorted_section_items() — 按数字排序章节 ID

2.3 docx_ops.py — 文档操作

核心函数:

函数 说明
apply_plan() 总入口,按顺序执行所有规则
apply_exact_replacement() 精确匹配替换,验证命中数量
apply_paragraph_replacement() 包含匹配替换,支持多行展开
apply_dynamic_section() 克隆原型段落生成动态子章节
apply_csci_sections() [11] 克隆整个 CSCI 原型块
apply_table_fill() 定位表格 + 克隆行 + 填充数据
apply_caption_numbering() 自动编号 表X-X / 图X-X
mark_toc_for_update() 设置 Word updateFields 标记

辅助函数:

函数 说明
iter_all_paragraphs() 遍历所有段落(含页眉页脚、表格内嵌)
iter_body_non_toc_paragraphs() 遍历正文段落(跳过 TOC 样式)
set_paragraph_text() 保留 run 格式设置文本
set_paragraphs_from_text() 多行文本展开为新段落
find_single_body_paragraph() 查找唯一匹配段落(精确/包含模式)
_clone_after() 深拷贝段落 XML 并插入锚点之后

2.4 template_rules.py — 模板常量

常量 说明
IDENTITY_LINE_ANCHORS 文档标识行的锚点文本
PATTERN_OVERRIDES 覆盖特定章节的 replacement_pattern
INSERTION_PARENT_RULES [10] 动态章节的插入规则
CSCI_SECTION_RULE [11] CSCI 章节的 13 个锚点

2.5 errors.py — 异常

异常 基类 触发场景
StrictTemplateError RuntimeError 模板结构与预期不匹配
StrictDataError RuntimeError 输入 JSON 数据不完整或非法

2.6 pipeline.py — CLI 入口

1
2
3
4
5
6
7
8
def main(argv=None) -> int:
# 解析 --template, --config, --project, --output
config_data = load_json(config_path)
project_data = load_json(project_path)
plan = build_plan(config_data, project_data)
doc = Document(str(template_path))
apply_plan(doc, plan)
doc.save(str(output_path))

3. 添加新 Skill

3.1 步骤

  1. GJB438C全套模版/ 选取目标模板,转为 .docx
  2. 创建 skills/word-fillter-438c-XX/ 目录结构
  3. 复制 strict_word_filler/ 引擎(或复用已有)
  4. 编写 template_rules.py
    • 提取模板中的锚点文本 → IDENTITY_LINE_ANCHORS
    • 确定动态章节规则 → INSERTION_PARENT_RULES
  5. 编写 config.jsonproject.json 模板
  6. 编写 SKILL.md 定义触发关键词和工作流
  7. 测试

3.2 提取锚点的技巧

1
2
3
4
5
6
7
# 遍历模板段落找到锚点文本
from docx import Document

doc = Document("template.docx")
for i, para in enumerate(doc.paragraphs):
if para.text.strip():
print(f"[{i}] ({para.style.name}) {para.text[:80]}")

3.3 提取表格定位行

1
2
3
for table in doc.tables:
header = [cell.text.strip() for cell in table.rows[0].cells]
print(header)

4. 调试技巧

4.1 查看 docx 内部 XML

1
2
unzip document.docx -d document_extracted/
cat document_extracted/word/document.xml | xmllint --format -

4.2 JSON 格式化

1
2
import json
print(json.dumps(data, indent=2, ensure_ascii=False))

4.3 验证 BuildPlan

1
2
3
4
5
6
7
8
9
10
from strict_word_filler.loader import build_plan, load_json
from pathlib import Path

config = load_json(Path("config.json"))
project = load_json(Path("project.json"))
plan = build_plan(config, project)
print(f"精确替换: {len(plan.exact_replacements)}")
print(f"段落替换: {len(plan.paragraph_replacements)}")
print(f"动态章节: {len(plan.dynamic_sections)}")
print(f"表格填充: {len(plan.tables)}")

5. 贡献流程

  1. Fork 项目仓库
  2. 创建特性分支 (git checkout -b feature/new-template)
  3. 提交变更 (git commit -m 'feat: 添加 [XX] 模板支持')
  4. 推送到分支 (git push origin feature/new-template)
  5. 创建 Pull Request

提交信息格式:feat: / fix: / docs: / refactor: / chore: