开发者指南
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:
- 从
config.json 提取封面字段 → 生成 ExactReplaceRule
- 遍历
project.json 的 structure → 生成各类 Rule
- 校验所有必填字段,缺失时抛出
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: 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 步骤
- 从
GJB438C全套模版/ 选取目标模板,转为 .docx
- 创建
skills/word-fillter-438c-XX/ 目录结构
- 复制
strict_word_filler/ 引擎(或复用已有)
- 编写
template_rules.py:
- 提取模板中的锚点文本 →
IDENTITY_LINE_ANCHORS
- 确定动态章节规则 →
INSERTION_PARENT_RULES
- 编写
config.json 和 project.json 模板
- 编写
SKILL.md 定义触发关键词和工作流
- 测试
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. 贡献流程
- Fork 项目仓库
- 创建特性分支 (
git checkout -b feature/new-template)
- 提交变更 (
git commit -m 'feat: 添加 [XX] 模板支持')
- 推送到分支 (
git push origin feature/new-template)
- 创建 Pull Request
提交信息格式:feat: / fix: / docs: / refactor: / chore: