Files
DCIT/srs.md
2026-07-13 10:04:36 +08:00

2821 lines
91 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WORD 文件信息替换与还原工具需求规格说明书
## 1. 文档目的
本文档用于明确“WORD 文件信息替换与还原工具”的功能范围、交互方式、数据格式、兼容性约束、运行约束与验收标准,作为开发、测试和验收的统一依据。
## 2. 产品目标
本工具用于对 Word 文件中的文字与图像信息进行批量替换,并生成可用于严格还原的差异文件;随后可基于替换后的文件和差异文件恢复出还原文件。
工具应满足以下总体目标:
- 同时支持 `*.doc``*.docx` 输入文件。
- 替换和恢复宿主机必须已安装支持 `*.docx` 的 Word 或 WPS除该明确前提外程序及其依赖应绿色离线交付。
- 所有依赖离线打包,目标环境无需联网下载。
- 替换和还原过程静默执行,不显示 Word 打开界面。
- 支持批量处理目录及子目录中的文件。
- 还原过程采用严格匹配,不允许模糊恢复。
说明:
- `*.docx` 是优先设计、优先优化、优先验证的格式。
- `*.doc` 作为兼容性支持对象,在复杂对象场景下以最终验收结果为准。
## 3. 术语定义
- 原始文件 `[A]`:待执行替换操作的 Word 文件。
- 替换后文件 `[B]`:执行替换操作后生成的新 Word 文件。
- 差异文件 `[C]`:记录替换过程所需恢复信息的数据文件。
- 还原文件 `[A']`:根据 `[B]``[C]` 还原生成的 Word 文件。
- 规则文件:后缀为 `*.rule` 的 JSON 文件,用于定义文字替换规则。
- StoryWord 的逻辑文本区域,例如正文、页眉、页脚、批注、文本框等。
- RunWord 在同一段落或容器内对连续文字进行的内部样式片段划分。视觉上连续的文字可能由多个 Run 组成。
## 4. 功能概述
系统包含以下三个页面:
- 替换
- 恢复
- 设置
系统主要能力包括:
- 选择原始文件目录并批量生成替换后文件与差异文件
- 基于替换后文件和差异文件生成还原文件
- 管理规则文件,配置文字替换规则
- 对规则进行合法性和兼容性检查
- 记录详细运行日志、会话配置和处理结果
## 5. 处理对象范围
### 5.1 总体范围
替换与恢复范围为全文范围,包含但不限于:
- 页眉
- 页脚
- 正文段落
- 正文中的表格
- 页眉和页脚中的表格
- 正文中的文本框
- 页眉和页脚中的文本框
- 批注
- 题注
- 超链接显示文字
- 目录显示结果
- 域显示结果
- 公式中的可解析文字内容
- 图表中的文本内容
- 图片对象
- 形状对象中的文字及可转换图形内容
### 5.2 图片对象范围
以下图片对象在替换与恢复范围内:
- 嵌入式图片
- 浮动图片
- 页眉页脚中的图片
- 表格单元格中的图片
- 文本框中的图片
### 5.3 表格支持范围
表格处理要求如下:
- 支持普通表格
- 支持合并单元格
- 支持表格单元格中的文字
- 支持表格单元格中的图片
- 不支持跨单元格匹配文字
### 5.4 明确不支持的处理方式
- 不支持跨段落匹配文字
- 不支持对加密文档进行处理
- 不支持对受保护文档进行处理
说明:
- 只读文档应支持处理。
- 对于不支持或无法打开的文档,系统应记录错误并跳过当前文件,继续处理后续文件。
## 6. 替换功能需求
### 6.1 功能描述
对原始文件 `[A]` 执行替换操作,输出:
- 替换后文件 `[B]`
- 差异文件 `[C]` 的 JSON 形式
- 差异文件 `[C]` 的 BMP 形式
### 6.2 处理模式
替换处理支持目录批处理:
- 以用户选择的原始文件夹为输入根目录
- 自动扫描该目录及其所有子目录下的 `*.doc``*.docx` 文件
- 用户可对扫描结果进行勾选控制
- 仅处理当前勾选的文件
### 6.3 输出目录与目录结构
替换输出应满足:
- 以用户选择的替换文件夹为输出根目录
- 相对于原始文件夹的目录树结构必须被完整保留
- 替换后文件与差异文件保存在替换文件夹下对应相对路径目录中
### 6.4 命名规则
替换模式下输出文件命名规则如下:
- 原始文件的文件基本名(不含目录与扩展名)必须纳入启用规则的匹配和替换范围
- 文件名匹配使用与正文文字一致的规则顺序、普通文本/正则模式、大小写开关、全字匹配开关和替换模板语义
- 目录路径与扩展名不参与文件名规则匹配和替换
- 若文件名未命中任何规则,则使用原始文件基本名
- 替换后文件名:`规则替换后的文件基本名-yyyyMMdd.原始后缀`
- 差异文件 JSON 名:`规则替换后的文件基本名-yyyyMMdd.diff`
- 差异文件 BMP 名:`规则替换后的文件基本名-yyyyMMdd.bmp`
- 差异文件必须在文档元数据中记录原始文件名与实际替换后文件名,用于恢复时还原文件名
- 当原始文件名与实际替换后文件名不一致时,差异文件的修改记录中必须记录一条文件名变更操作,用于审计文件名变化
- 若规则替换后的文件基本名为空或包含非法文件名字符,应阻断当前扫描/执行并在日志中记录源文件、规则结果和错误原因
若出现同名冲突:
- 不覆盖现有文件
- 自动在文件名后追加自增序号
- 同一源文件产生的替换文档、`*.diff``*.bmp` 中任一输出发生同名冲突时,三者必须使用相同的自增序号,确保恢复扫描可按同一文件基本名配对
示例:
- 原始文件 `示例.docx`,文件名规则将 `示例` 替换为 `样例`
- `样例-20260424.docx`
- `样例-20260424_1.docx`
- `样例-20260424.diff`
- `样例-20260424_1.diff`
- `样例-20260424.bmp`
- `样例-20260424_1.bmp`
## 7. 文字替换规则
### 7.1 基本规则
每条规则用于将文字片段 `alpha` 替换为 `beta`
规则按列表顺序依次执行。
前一条规则替换后的结果允许被后一条规则再次命中。
当多条规则命中同一位置时:
- 以规则顺序优先
### 7.2 规则文件格式
规则文件采用 JSON 格式保存:
- 文件后缀:`*.rule`
### 7.3 每条规则字段
每条规则至少包含以下字段:
- 规则 ID
- 规则名称
- 是否启用
- 匹配模式
- 是否区分大小写
- 是否全字匹配
- 原文本或正则表达式
- 新文本或替换模板
- 备注
字段说明:
- 规则 ID 必须唯一
- 匹配模式取值为:
- 普通文本
- 正则表达式
- 区分大小写默认值为:否
- 全字匹配默认值为:否
### 7.4 普通模式与正则模式
文字替换应支持:
- 普通文本模式
- 正则表达式模式
正则模式要求:
- 支持捕获组
- 支持捕获组回填
### 7.5 匹配边界要求
匹配应满足:
- 允许跨 Run 匹配
- 不允许跨段落匹配
- 不允许跨单元格匹配
说明:
- 在同一段落、同一文本框、同一单元格内部,视觉连续但被拆分为多个 Run 的文本,应允许被视为同一次匹配。
### 7.6 样式保持要求
文字替换后必须保持以下样式不变:
- 字体
- 字号
- 颜色
- 粗体、斜体、下划线等字符样式
- 缩进
- 行间距
- 段前距
- 段后距
- 编号格式
编号相关要求:
- 编号值不变
- 编号级别不变
- 缩进不变
- 制表位不变
- 自动编号行为不变
### 7.7 占位要求
文字替换后不得改变原有版式。
“占位”定义为:
- 屏幕显示字符宽度
若新文本显示宽度大于原文本:
- 应对新文本进行截断
若新文本显示宽度小于原文本:
- 允许采用适当空白填充或等效方式补齐
补齐规则要求:
- 只要能够保持原版式不变且支持完整恢复,具体空白实现方式不限
- 若“补齐宽度”和“版式稳定”冲突,以版式稳定为优先
### 7.8 可恢复性记录要求
每一处文字替换都必须写入差异文件,至少记录:
- 替换类型,标记为“文本替换”
- 规则 ID
- 规则名称
- 规则表达式或原文本
- 当前规则命中序号
- 位置起点
- 位置终点
- 被替换前文本
- 替换后文本
- 所属对象类型
### 7.9 自动提取生成规则要求
系统应支持从当前启用的文档集合自动提取候选规则。
该功能要求如下:
- 入口位于替换页面
- 提取对象为替换页面文件列表中复选框已勾选的全部文档
- 当文件列表未勾选任何文件时,自动提取不得执行
- 文件列表中的高亮选中状态不影响自动提取扫描范围
- 提取范围为全部勾选文档中纳入文字替换范围的可见文本内容
- 提取范围至少包括:
- 正文
- 页眉页脚
- 表格
- 文本框
- 批注
- 超链接显示文字
- 域结果
- 公式文字
- 图表文字
- 仅提取可见文本
- 不提取隐藏文字、域代码、修订删除内容和对象内部不可见元数据
- 提取内容至少包含:
- 关键字
- 高频词
- 高频句
- 提取类别应在设置页面中可配置,默认全选
- 自动提取不设置扫描页数或字符数上限,应对全部勾选文档全文分析
- 自动提取功能优先保证 `*.docx`,对 `*.doc` 以实际可解析文本范围为准
提取算法与筛选要求:
- 关键字提取应支持以下算法,并允许多选:
- 按词频
- `TF-IDF`
- `TextRank`
- 关键字提取算法默认全选
- 执行自动提取时,应对勾选文件范围按所选关键字算法各执行一轮,并对结果去重合并后进入预览
- 高频词提取应支持中文词项和英文单词两个统计选项,默认全选
- 高频句提取应支持中文句和英文句两个统计选项,默认全选
- 高频句的句子分隔符应在设置页面中可配置,默认启用常见中英文句末分隔符
- 单字和单词长度限制应在设置页面中可配置
- 中文词项最小长度默认值建议为 `1`
- 英文单词最小长度默认值建议为 `1`
- 邮箱地址默认参与提取
- 其他内容如纯数字、日期、编号序列、页码、URL 不默认排除
提取结果处理要求:
- 提取完成后,必须先展示提取结果预览,而不是直接追加
- 预览界面中,用户应可按条选择是否追加
- 预览结果应至少显示:
- 是否追加
- 提取类型
- 原文本
- 统计值
- 首次出现文档路径
- 首次出现顺序
- 提取结果应按首次出现顺序排序
- 同一原文本在同一次提取结果中去重后仅保留一次
- 用户确认后,每一条被选中的提取结果应追加为一条新规则
- 追加目标为当前会话内存中的规则列表
- 追加后应立即反映到设置页面的规则列表中
- 规则追加后,只有在用户执行“保存规则文件”后,才写入 `*.rule` 文件
自动生成规则的默认字段要求:
- 规则 ID系统自动生成且必须唯一
- 自动提取生成的规则 ID 应按提取类型使用前缀:
- 关键字:`AK`
- 高频词:`AW`
- 高频句:`AS`
- 规则名称:系统自动生成
- 自动提取生成的规则名称建议格式为:
- 关键字:`AUTO-KW-0001`
- 高频词:`AUTO-WORD-0001`
- 高频句:`AUTO-SENT-0001`
- 是否启用:是
- 匹配模式:普通文本
- 是否区分大小写:是
- 是否全字匹配:是
- 原文本或表达式:提取结果原文
- 新文本或替换模板:默认初始化为空字符串
- 备注:应标记为自动提取,并至少记录提取类型、统计值、首次出现文档路径和提取时间
补充要求:
- 自动提取规则的“规则生效”定义为规则启用状态为“是”
- 即使新文本或替换模板为空字符串,自动提取生成的规则仍必须默认处于启用状态
- 系统不得因自动提取规则的新文本为空而自动禁用、自动填充或阻止用户执行后续替换流程
- 对于原文本为空、纯空白或无效的提取结果,不得追加
- 对于与当前规则列表中原文本相同的普通文本规则,应视为重复项并避免追加
- 若现有人工规则与自动提取结果原文本相同,则必须保留人工规则并丢弃自动提取结果
- 即使现有规则的大小写选项或新文本不同,只要原文本相同,自动提取结果仍视为重复项
- 在用户确认追加前,应执行快速去重和冲突检查
- 在用户确认追加后,应对完整规则列表执行正式合法性和兼容性检查
- 提取过程中必须显示进度,并允许用户取消
- 提取过程中不允许用户编辑规则列表
- 用户取消提取后,不得修改当前规则列表
- 追加完成后,系统应自动切换到设置页面并定位到第一条新增规则
- 系统必须提供“撤销本次自动提取追加结果”的操作
- 撤销应仅回退最近一次自动提取成功追加的规则集合
- 若未提取到任何有效结果,必须弹窗提示“未提取到可用项”
- 提取完成后,系统应通过弹窗和日志给出提取总数、成功追加数、跳过数
- 自动提取失败时,不得破坏现有规则列表,并必须写入日志
## 8. 图片替换规则
### 8.1 位图图片范围
位图图片至少支持以下格式:
- BMP
- PNG
- JPG / JPEG
- TIFF
- GIF
### 8.2 非位图图片范围
非位图图片或对象至少支持以下类型:
- WMF
- EMF
- SVG
- Office 形状对象
- 图表对象
### 8.3 位图图片替换方式
对位图图片执行如下处理:
- 在原图基础上添加随机噪声形成新图
- 噪声类型包含:
- 点噪声
- 线噪声
- 块噪声
- 噪声应基本均匀分布于全图范围
- 被修改的像素数占比不得低于原图像素总数的 50%
### 8.4 非位图图片替换方式
对非位图对象执行如下处理:
- 先转换为位图
- 转换后保持原显示占位不变
- 再按位图图片替换方式处理
### 8.5 图片属性保持要求
图片替换后必须保持以下属性不变:
- 显示尺寸
- 页面位置
- 环绕方式
- 锚点位置
- 裁剪参数
- 旋转角度
### 8.6 随机性要求
图片替换要求如下:
- 默认每次执行时噪声应随机不同
- 系统应支持固定随机种子,以便相同输入可重复生成相同结果
- 噪声类型比例不提供用户配置项,由系统自动设置最优方案
### 8.7 非位图恢复要求
非位图对象在恢复时:
- 只恢复为位图形式
- 不要求恢复为原始非位图对象类型
### 8.8 图片差异记录要求
每一处图片替换都必须写入差异文件,至少记录:
- 替换类型,标记为“图像替换”
- 对象位置
- 原图数据
- 若原图为非位图,则记录转换后的位图数据
- 替换后新图数据
- 随机种子
- 原图尺寸
- 替换后尺寸
- 所属对象类型
## 9. 其他对象处理规则
### 9.1 超链接
超链接仅处理:
- 显示文字
不处理:
- 目标 URL
### 9.2 目录
目录处理要求:
- 替换时仅处理目录当前显示结果
- 替换完成后必须自动更新目录
- 恢复完成后必须自动更新目录
### 9.3 域
域处理要求:
- 仅处理域显示结果
- 不处理域代码
- 替换完成和恢复完成后必须刷新域,并验证文档显示结果中不得存在“错误!未找到引用源”等交叉引用或域结果错误
- 若验证发现交叉引用或域结果错误,应拒绝输出当前文件,并在日志中记录足够定位的 Story、容器、段落和上下文片段
### 9.4 公式
公式处理要求:
- 解析公式中的可解析文字内容进行替换
- 不将公式整体按图像处理
### 9.5 图表
图表中以下文本内容均在处理范围内:
- 标题
- 坐标轴标题
- 图例
- 数据标签
- 图表内嵌数据表文本
### 9.6 批注
批注处理要求:
- 仅修改批注内容
- 必须保留批注作者
- 必须保留批注时间
- 必须保留批注状态
## 10. 还原功能需求
### 10.1 功能描述
通过读取替换后文件 `[B]` 与差异文件 `[C]`,生成还原文件 `[A']`
### 10.2 还原匹配原则
还原过程采用严格匹配,不允许容错查找。
即:
- 必须按差异文件中记录的位置严格定位
- 必须按差异文件中记录的当前内容进行严格比对
- 任一关键匹配条件不成立时,该处恢复失败
### 10.3 位置模型
差异文件中的位置定义采用以下模型:
- Story 类型
- 容器路径
- 段落索引
- 起始 Run 索引
- 起始字符偏移
- 结束 Run 索引
- 结束字符偏移
说明:
- 文本对象使用上述位置模型定位
- 非文本对象应在上述逻辑容器基础上补充对象索引定位
### 10.4 恢复输入格式
恢复模式下,用户一次只能选择一种差异文件输入格式:
- `*.diff`
- `*.bmp`
若用户选择 `*.bmp`
- 程序应先自动解码得到与 JSON 差异数据逻辑等价的数据
- 然后按统一恢复逻辑执行恢复
程序不应在同一次批处理中自动混用两种差异文件格式。
### 10.5 恢复输出目录与命名
恢复模式输出要求:
- 以用户选择的恢复文件夹为输出根目录
- 相对于替换文件夹的目录树结构必须完整保留
- 恢复时必须优先读取差异文件中的 `sourceDocument.fileName`
恢复文件命名规则如下:
- 对于包含文件名元数据的新差异文件:恢复输出文件名应还原为原始文件名与原始扩展名
- 示例:`示例.docx` 经文件名规则替换输出为 `样例-20260424.docx`,恢复输出应为 `示例.docx`
- 对于缺少原始文件名元数据的旧差异文件,允许使用兼容命名:`替换后文件名-rcv.替换后后缀`
若发生同名冲突:
- 不覆盖
- 自动追加自增序号
### 10.6 异常处理
还原过程中:
- 单个文件失败不应导致整个批处理终止
- 系统应记录错误并继续处理后续文件
- 处理结束后必须给出汇总结果
## 11. 可逆性与一致性要求
### 11.1 文字一致性
恢复后的 `[A']` 必须在文字内容上与 `[A]` 完全一致。
文字内容一致的验收口径为:
- 按纯文本完全一致验收
### 11.2 排版一致性
恢复后的 `[A']` 必须在排版上与 `[A]` 一致。
排版一致的验收至少包括:
- 页数一致
- 分页位置一致
- 段落分页一致
- 表格分页一致
- 行数一致
### 11.3 插图一致性
恢复后的插图必须与原文件在视觉上保持一致。
插图一致性验收至少同时包括:
- 肉眼比对一致
- 尺寸和位置一致
- 像素相似度达到测试规范定义阈值
说明:
- 像素相似度阈值由测试规范另行定义。
## 12. 规则兼容性检查
### 12.1 检查时机
规则兼容性检查必须在以下时机执行:
- 保存规则文件时
- 执行替换前
### 12.2 检查内容
兼容性检查至少覆盖:
- 正则表达式非法
- 规则自身替换后再次命中自身
- 多条规则命中同一区域
- 规则间循环影响
- 规则前后覆盖关系
- 明显不可恢复风险
### 12.3 检查结果处理
当发现正则语法错误等致命错误时:
- 禁止保存规则文件
- 通过日志提示错误
- 日志必须能够定位规则位置
- 日志必须提供详细错误信息
当发现兼容性风险但不属于致命错误时:
- 允许用户继续执行
- 必须弹窗提示
- 必须写入日志
### 12.4 执行门槛
规则兼容性检查必须在执行前完成。
对于非致命风险:
- 允许用户确认后继续执行
## 13. 差异文件要求
### 13.1 总体要求
差异文件必须同时生成两种形式:
- JSON 形式
- BMP 形式
两种形式必须双向无损转换。
### 13.2 JSON 差异文件
JSON 差异文件要求如下:
- 文件后缀:`*.diff`
- 图片差异数据必须内嵌保存
- 不允许依赖外部图片文件进行恢复
- 差异文件必须包含完整恢复所需信息
### 13.3 JSON 加密选项
系统必须提供 JSON 差异文件加密选项:
- 可选值:加密 / 不加密
- 默认值:加密
该选项要求:
- 记录到会话配置文件中
- 影响后续生成的 `*.diff` 文件
说明:
- 由于系统同时必须生成不加密的 `*.bmp` 差异文件,`*.diff` 的加密能力仅适用于该文件自身的存储形式
-`*.bmp` 同时存在时,不应将 `*.diff` 加密视为整体差异数据的保密性保证
### 13.4 BMP 差异文件
BMP 差异文件要求如下:
- 文件后缀:`*.bmp`
- 与对应 `*.diff` 文件同名同目录生成
- 必须能够无损还原出逻辑等价的差异数据
- BMP 文件本身不加密
### 13.5 校验与安全性
差异文件必须具备:
- 完整性校验
- 防篡改能力
差异文件至少应记录以下校验与识别信息:
- 原始文件指纹
- 替换后文件指纹
- 规则文件指纹
- 程序版本
- 差异算法版本
若差异文件校验失败:
- 必须拒绝恢复
- 不允许强制继续
若恢复时发现替换后文件 `[B]` 与差异文件 `[C]` 不匹配:
- 必须拒绝恢复
- 记录明确错误原因
- 不允许强制继续
## 14. 人机界面要求
### 14.1 通用界面要求
系统界面固定为以下三个 Tab 页:
- 替换
- 恢复
- 设置
批处理期间界面要求:
- 不得卡死
- 状态必须持续刷新
- 日志必须持续刷新
- 进度条必须持续刷新
### 14.2 目录选择对话框要求
凡涉及文件夹路径选择,均应满足:
- 单击按钮后,弹出系统现代风格的目录选择对话框
- 对话框界面风格应与文件打开对话框一致,但选择目标为文件夹
- 不使用传统树形“浏览文件夹”对话框
- 用户点击“确定”后,关闭对话框,并将所选文件夹绝对路径填入对应文本框
- 用户点击“取消”后,关闭对话框,不更新对应文本框内容
### 14.3 替换页面
替换页面包含以下主要控件:
- 选择原始文件夹按钮
- 原始文件夹路径文本框
- 选择替换文件夹按钮
- 替换文件夹路径文本框
- 文件列表
- 自动提取按钮
- 开始替换按钮
- 停止按钮
- 总进度条
- 单文件进度条
交互要求:
- 当原始文件夹路径文本框或替换文件夹路径文本框失去输入焦点后,应自动异步扫描原始文件夹
- 自动加载目标目录及子目录下符合后缀的文件
- 扫描过程中界面不得无响应
- 文件列表默认全部勾选
- 支持单选和多选
- 支持批量勾选和批量取消勾选
- 支持右键批量操作
- 右键菜单至少应提供:删除、启用、不启用
- 右键菜单批量操作应作用于当前选中的一行或多行
- 支持按列排序
- 自动提取按钮用于对当前勾选启用的文件集合执行关键字、高频词、高频句提取
- 当文件列表未勾选任何文件时,自动提取按钮应禁用或给出明确提示
- 当文件列表勾选了一个或多个文件时,点击自动提取按钮后,应对全部勾选文档执行提取
- 文件列表的单选或多选状态仅用于界面交互,不影响自动提取的扫描范围
- 点击自动提取后,应先进入提取结果预览流程
- 自动提取过程中必须显示处理进度,并允许用户取消
- 自动提取过程中界面不得假死
- 自动提取过程中不允许编辑规则列表
- 预览界面中,用户应可选择性勾选要追加的候选项
- 用户确认追加后,提取结果应追加到当前规则列表,并立即反映到设置页面的规则列表中
- 追加完成后,应自动切换到设置页面并定位到第一条新增规则
- 系统应提供“撤销本次自动提取追加结果”操作
- 提取完成后,必须弹出结果摘要,并将提取数量、追加数量、跳过数量写入日志
- 若未提取到任何有效结果,必须弹窗提示“未提取到可用项”
文件列表至少包含以下列:
- 原始文件路径
- 替换后文件路径
- 差异文件路径
- 文本替换次数
- 图片替换次数
- 当前状态
停止按钮语义:
- 用户点击停止后,系统应尽量完成当前正在处理的文件
- 当前文件结束后再停止后续任务
状态显示至少包含:
- 未处理
- 处理中
- 成功
- 失败
- 已停止
颜色要求:
- 成功:绿色
- 失败:红色
- 处理中:蓝色
- 已停止:灰色
运行过程中必须显示:
- 当前正在处理的文件编号 / 总文件数
- 当前规则编号与规则名称
- 当前文件命中次数
- 累计命中次数
执行完成后:
- 必须弹出汇总结果对话框
### 14.4 恢复页面
恢复页面包含以下主要控件:
- 选择替换文件夹按钮
- 替换文件夹路径文本框
- 选择恢复文件夹按钮
- 恢复文件夹路径文本框
- 文件列表
- 开始恢复按钮
- 停止按钮
- 总进度条
- 单文件进度条
交互要求:
- 当相关路径文本框失去输入焦点后,应自动异步扫描
- 自动加载目标目录及子目录下可恢复的文件
- 单次批处理仅允许使用一种差异文件输入格式
- 支持右键批量操作
- 右键菜单至少应提供:删除、启用、不启用
- 右键菜单批量操作应作用于当前选中的一行或多行
文件列表至少包含以下列:
- 替换后文件路径
- 差异文件路径
- 恢复文件路径
- 文本恢复次数
- 图片恢复次数
- 当前状态
停止按钮语义与替换页面一致。
执行完成后:
- 必须弹出汇总结果对话框
### 14.5 设置页面
设置页面包含以下主要控件:
- 打开规则文件按钮
- 规则文件路径显示区
- 保存规则文件按钮
- 规则列表
- 自动提取设置区
- 规则新增按钮
- 规则删除按钮
- 规则上移按钮
- 规则下移按钮
规则列表至少包含以下字段列:
- 规则 ID
- 规则名称
- 是否启用(复选框)
- 匹配模式
- 是否区分大小写
- 是否全字匹配
- 原文本或表达式
- 新文本或替换模板
- 备注
设置页面要求:
- 仅保留“打开”和“保存”操作
- 不提供导入、导出、另存为等独立功能
- 规则列表支持单选和多选
- 规则列表支持右键批量操作
- 规则列表右键菜单至少应提供:删除、启用、不启用
- 规则列表右键批量操作应作用于当前选中的一行或多行
- 保存时必须执行规则合法性和兼容性检查
- 检查结果必须同时输出到弹窗和日志
- 替换页面自动提取追加的规则,必须立即显示在规则列表中
- 自动提取设置区至少应提供以下配置项:
- 提取类别选择:关键字、高频词、高频句,默认全选
- 关键字提取算法选择:按词频、`TF-IDF``TextRank`,支持多选,默认全选
- 关键字最大提取数量,默认 `10`
- 高频词最大提取数量,默认 `10`
- 高频句最大提取数量,默认 `10`
- 高频词统计选项:中文词项、英文单词,默认全选
- 高频句统计选项:中文句、英文句,默认全选
- 中文词项最小长度
- 英文单词最小长度
- 句子分隔符选项
- 是否排除邮箱地址,默认否
- 自动提取相关设置属于会话配置,重启后应从 `config.json` 恢复
## 15. 日志要求
### 15.1 日志显示与存储
系统必须同时提供:
- 界面日志框显示
- 日志文件落盘
界面日志框要求:
- 支持复制日志内容
- 支持右键菜单
- 右键菜单至少应提供:复制全部内容、清空日志
- “复制全部内容”应复制当前日志框中的全部文本内容
- “清空日志”仅清空界面日志框显示内容,不影响已落盘日志文件
日志编码固定为:
- UTF-8
日志文件要求:
- 保存于启动目录
- 采用按天追加写入方式
- 启动目录必须可写;若不可写,则视为运行环境不满足要求
日志文件命名规则:
- `session-yyyyMMdd.log`
### 15.2 日志级别与颜色
日志级别至少包括:
- INFO
- WARNING
- ERROR
显示颜色要求:
- INFO绿色
- WARNING橙色
- ERROR红色
- 一般过程信息:黑色
### 15.3 日志内容
日志至少记录:
- 文件操作记录
- 当前处理源文件
- 生成的替换文件路径
- 生成的 JSON 差异文件路径
- 生成的 BMP 差异文件路径
- 当前处理的规则编号与规则名称
- 匹配成功的原文本
- 匹配成功的起始位置和结束位置
- 当前文件序号与总文件数
- 当前规则序号与总规则数
- 当前规则命中序号
- 恢复记录
- 恢复失败原因
- 异常堆栈
- 规则兼容性检查结果及严重级别
- 图片替换时的随机种子
- 图片替换时的尺寸信息
- 批处理汇总信息
### 15.4 批处理汇总
批处理汇总日志至少包含:
- 成功文件数
- 失败文件数
- 跳过文件数
- 文本替换总次数
- 图片替换总次数
- 文本恢复总次数
- 图片恢复总次数
## 16. 会话配置要求
### 16.1 基本要求
系统应以 JSON 格式保存当前会话信息:
- 文件名:`config.json`
- 保存目录:启动目录
会话信息变化后应自动刷新配置文件。
启动时若存在 `config.json`,应自动加载。
### 16.2 配置项
会话配置至少包含:
- 当前规则文件路径
- 替换页面的原始文件夹路径
- 替换页面的替换文件夹路径
- 恢复页面的替换文件夹路径
- 恢复页面的恢复文件夹路径
- JSON 差异文件加密开关
## 17. 兼容性与运行环境要求
### 17.1 操作系统
系统必须兼容以下离线原生纯净系统:
- Windows 7 SP1 x64
- Windows 10 x64
- Windows 11 x64
- Windows Server 2022 x64
### 17.2 运行架构
- 仅支持 x64
- 程序应以普通用户权限运行
- 不依赖管理员权限
- 目标机不具有管理员权限
- 目标机不具有软件安装权限
### 17.3 依赖要求
- 所有依赖必须随程序离线打包
- 目标系统不应要求预装第三方运行时或工具;若 .NET Framework 4.8 无法真正自包含,应在交付风险中明确说明
- 允许程序首次启动时将内置组件解压到本地临时目录
- 替换和恢复宿主机必须已安装支持 `*.docx` 的 Word 或 WPS
- 不得要求安装 VisioVisio/OLE 等对象按可见位图表示处理
- 第三方库应选择免费授权的非商业第三方库,且可满足项目使用要求
### 17.4 交付形式
交付形式要求如下:
- 仅提供绿色版
- 不提供安装版
- 不要求桌面快捷方式、开始菜单或卸载项
若采用覆盖升级方式分发新版本,应保留:
- `config.json`
- 日志文件
- `*.rule` 规则文件
## 18. 性能与响应要求
### 18.1 目标性能指标
以下指标为单个文件处理的目标性能,不作为强制验收门槛:
- 替换处理 2000 页 Word 文件不超过 180 秒
- 还原处理 2000 页 Word 文件不超过 180 秒
- 替换处理 100 页 Word 文件不超过 10 秒
- 还原处理 100 页 Word 文件不超过 10 秒
说明:
- 目录扫描时间不计入上述指标
- 日志写入时间不计入上述指标
- BMP 差异文件生成时间不计入上述指标
### 18.2 大文件与多文件响应性
即使在大文件或多文件场景下,系统也必须满足:
- 不出现界面卡死
- 不出现状态不更新
- 不出现操作无响应
- 支持异步扫描
- 支持并行处理多个文件
并行处理要求:
- 并发度不提供用户配置项
- 由系统根据运行环境自动尽可能利用可用资源
## 19. 标准验收要求
### 19.1 标准验收样例集
项目必须提供标准验收样例集,至少覆盖:
- 页眉
- 页脚
- 文本框
- 表格
- 合并单元格
- 批注
- 目录
-
- 公式
- 图表
- 位图图片
- 非位图图片
- `*.doc`
- `*.docx`
### 19.2 验收输出物
项目应提供:
- 测试报告
- 验收报告模板
### 19.3 执行前门槛
执行替换前至少满足:
- 规则文件加载成功
- 规则合法性检查通过
- 规则兼容性检查已完成
- 输入路径有效
- 输出路径有效且可写
## 20. 异常防护与故障处理要求
### 20.1 总体原则
系统应满足以下总体故障处理原则:
- 单文件失败不影响后续文件继续处理
- 文件级错误必须在日志中完整记录
- 汇总结果必须明确显示成功、失败、跳过数量
- 停止操作应在当前文件尽量处理完成后生效
- 以“可恢复性”和“一致性”为最高优先级,不得为了继续执行而牺牲可逆性
### 20.2 路径与目录防护
执行前必须完成路径合法性检查。
以下情况应视为非法配置并阻止执行:
- 原始文件夹与替换文件夹相同
- 原始文件夹与恢复文件夹相同
- 替换文件夹与恢复文件夹相同
- 任意两个上述目录互为父子目录
- 输出目标路径与输入源路径重合
执行过程中还必须处理以下路径异常:
- 路径过长
- 文件名或路径包含非法字符
- 输出目录不存在
- 输出目录只读
- 输出目录无写权限
对于批处理根路径非法:
- 整个批处理不得启动
对于单文件目标路径异常:
- 当前文件失败
- 记录日志
- 继续处理后续文件
### 20.3 原子写入与半成品防护
每个文件的替换与恢复都必须采用原子提交策略。
执行要求如下:
- 正式输出文件 `[B]``*.diff``*.bmp``[A']` 必须先写入临时文件
- 仅当当前文件的全部必需输出均成功生成且校验通过后,才允许提交为正式文件
- 若其中任一输出生成失败、校验失败或写入失败,则该文件整体视为失败
失败时必须满足:
- 不保留正式半成品
- 尽可能清理当前文件产生的临时文件
- 日志中必须标明清理结果
### 20.4 文件占用与外部变更防护
系统必须检测并处理以下场景:
- 原始文件被其他进程占用
- 替换后文件目标被占用
- 差异文件目标被占用
- 恢复文件目标被占用
- 文件在扫描后至处理前被删除、移动或替换
- 文件在处理过程中被外部修改
处理要求如下:
- 当前文件失败
- 记录明确错误原因
- 继续处理后续文件
### 20.5 资源与环境异常防护
系统必须防护以下异常:
- 磁盘空间不足
- 临时目录不可写
- 启动目录不可写
- 内存不足
- 图片渲染失败
- 非位图转位图失败
- 并发过高导致系统无响应
处理要求如下:
- 启动目录不可写时,视为运行环境不满足要求,阻止执行
- 临时目录不可写时,视为当前批次运行环境不满足要求,阻止当前批次执行
- 单文件处理中出现资源类异常时,当前文件失败并继续后续文件
- 系统应在并发处理时自动控制资源使用,优先保证界面可响应
### 20.6 并发与重复处理防护
并发处理时必须满足:
- 同一源文件不得重复入队
- 同一输出目标路径不得被多个任务同时占用
- 扫描结果必须去重
- 同一差异文件目标不得被多个任务同时生成
- 同一恢复输出目标不得被多个任务同时生成
系统应采用互斥或等效机制保证上述约束。
### 20.7 规则执行异常防护
除规则兼容性检查外,执行期还必须防护以下问题:
- 零长度匹配导致死循环
- 正则灾难性回溯导致长时间卡死
- 非法捕获组回填引用
- 单条规则在单文件中的异常高频命中
- 规则链式替换导致处理次数异常膨胀
处理要求如下:
- 系统应设置内部安全阈值和超时保护
- 触发保护时,当前文件失败
- 日志中必须记录触发的规则、原因和触发位置
### 20.8 对象级异常处理策略
以下对象在解析、替换或恢复过程中若任一对象处理失败:
- 文本框
- 形状
- 图表
- 公式
- 表格
- 图片
- 批注
- 页眉页脚中的对象
则默认处理策略为:
- 跳过当前对象
- 继续处理当前文件中的后续对象
- 日志中必须记录对象类型、Story、容器路径、位置、操作 ID 和失败原因
- 文件级全局校验、打开、写入、完整性或指纹错误仍按当前文件失败处理
说明:
- 该策略用于在不破坏当前文件整体处理的前提下保留可诊断信息;不得静默隐藏局部失败
### 20.9 字体环境异常防护
系统必须在执行前进行字体环境检查。
检查目标包括:
- 当前处理文件中使用的字体是否在目标机可用
- 缺失字体是否可能影响排版一致性
由于目标环境可能离线且不具备字体安装权限,当发现缺失字体时:
- 不得尝试联网下载、更新或安装字体
- 当前文件继续执行替换或恢复
- 中文及东亚文字默认使用 `宋体` 兜底
- 英文、数字及拉丁文字默认使用 `Times New Roman` 兜底
- 日志中必须记录缺失字体清单、兜底字体和影响说明
### 20.10 差异文件错配与恢复防护
恢复前必须校验以下信息:
- 替换后文件 `[B]` 与差异文件 `[C]` 的指纹对应关系
- 差异文件的完整性校验值
- 差异文件的防篡改校验结果
- 差异文件所对应的规则文件指纹
- 差异文件所对应的程序版本和算法版本
当出现以下任一情况时:
- 指纹不匹配
- 校验失败
- 防篡改校验失败
- 关键版本信息不兼容
则:
- 必须拒绝恢复
- 不允许强制继续
- 日志中必须记录明确原因
### 20.11 停止、崩溃与中断恢复
用户点击停止时:
- 系统应尽量完成当前文件
- 当前文件结束后停止调度新的文件
- 尚未开始的文件标记为“已停止”
程序异常退出、系统崩溃或断电后:
- 下次启动时应自动检测上次遗留的临时文件
- 对可安全清理的临时文件自动清理
- 清理结果写入日志
对于无法安全判断是否可清理的遗留文件:
- 不得自动作为正式输出使用
- 必须提示用户并记录日志
### 20.12 配置与规则文件损坏防护
`config.json` 缺失时:
- 系统可按默认会话配置启动
- 首次保存配置时自动生成新的 `config.json`
- 写入日志
`config.json` 损坏或无法解析时:
- 系统必须提示用户配置文件已损坏
- 在用户确认重建默认配置或修复原配置前,禁止启动替换、恢复和自动提取等执行型任务
- 不得按损坏配置继续执行
- 写入日志
`*.rule` 文件损坏、缺失或无法解析时:
- 不允许启动替换任务
- 必须提示用户重新加载或修复规则文件
- 写入日志
### 20.13 日志异常防护
当批处理开始前日志文件无法创建或无法打开时:
- 不允许启动批处理任务
- 必须提示用户运行环境不满足要求
当批处理过程中日志文件追加写入失败时:
- 系统应优先保证当前文件处理流程可控结束
- 后续日志至少应继续保留在界面日志中
- 当前批次在当前文件结束后不得继续调度新的文件
- 必须提示用户日志落盘失败
## 21. 非功能性要求摘要
- 静默处理,不显示 Word 打开界面
- UI 在长时间处理过程中保持可响应
- 启动目录必须可写
- 差异文件必须可校验
- 差异文件 JSON 默认加密
- BMP 差异文件不加密
- 还原必须严格匹配,不允许模糊恢复
## 22. 附录 A规则文件 `*.rule` JSON 结构
### 22.1 顶层结构
规则文件采用 JSON 对象作为顶层结构,建议如下:
```json
{
"format": "dcit-rule",
"version": "1.0",
"savedAt": "2026-04-24T20:15:30+08:00",
"generator": {
"appName": "DCIT",
"appVersion": "1.0.0"
},
"rules": []
}
```
顶层字段定义如下:
- `format`
- 类型:`string`
- 必填:是
- 固定值:`dcit-rule`
- `version`
- 类型:`string`
- 必填:是
- 含义:规则文件结构版本
- `savedAt`
- 类型:`string`
- 必填:是
- 含义:规则文件保存时间,采用 ISO 8601 格式
- `generator`
- 类型:`object`
- 必填:否
- 含义:生成该规则文件的程序信息
- `rules`
- 类型:`array`
- 必填:是
- 含义:规则数组
### 22.2 规则数组执行语义
- `rules` 数组中的顺序即执行顺序
- 保存时必须保持用户界面中的当前排序
- 加载后必须按文件中的数组顺序恢复到界面
### 22.3 单条规则对象结构
每条规则对象结构如下:
```json
{
"id": "R001",
"name": "替换合同编号",
"enabled": true,
"matchMode": "plain",
"caseSensitive": false,
"wholeWord": false,
"pattern": "合同编号",
"replacement": "文件编号",
"note": "示例规则"
}
```
字段定义如下:
- `id`
- 类型:`string`
- 必填:是
- 要求:规则唯一标识,不可重复
- `name`
- 类型:`string`
- 必填:是
- 含义:规则名称
- `enabled`
- 类型:`boolean`
- 必填:是
- 含义:规则是否启用
- `matchMode`
- 类型:`string`
- 必填:是
- 可选值:
- `plain`
- `regex`
- `caseSensitive`
- 类型:`boolean`
- 必填:是
- 默认值:`false`
- `wholeWord`
- 类型:`boolean`
- 必填:是
- 默认值:`false`
- `pattern`
- 类型:`string`
- 必填:是
- 含义:普通文本模式下的匹配文本,或正则模式下的表达式
- `replacement`
- 类型:`string`
- 必填:是
- 含义:替换文本或正则回填模板
- `note`
- 类型:`string`
- 必填:否
- 含义:备注
### 22.4 规则文件约束
- 不定义作用范围字段
- 不定义图片替换参数字段
- 图片替换策略采用全局固定策略
-`matchMode``regex` 时,`pattern` 必须通过正则合法性检查
- 当正则语法非法时,不允许保存规则文件
### 22.5 规则文件示例
```json
{
"format": "dcit-rule",
"version": "1.0",
"savedAt": "2026-04-24T20:15:30+08:00",
"generator": {
"appName": "DCIT",
"appVersion": "1.0.0"
},
"rules": [
{
"id": "R001",
"name": "替换合同编号",
"enabled": true,
"matchMode": "plain",
"caseSensitive": false,
"wholeWord": false,
"pattern": "合同编号",
"replacement": "文件编号",
"note": "普通文本规则"
},
{
"id": "R002",
"name": "替换日期",
"enabled": true,
"matchMode": "regex",
"caseSensitive": false,
"wholeWord": false,
"pattern": "(20\\d{2})-(\\d{2})-(\\d{2})",
"replacement": "$1/$2/$3",
"note": "支持捕获组回填"
}
]
}
```
## 23. 附录 B差异文件 `*.diff` JSON 结构
### 23.1 总体结构
`*.diff` 文件采用 JSON 对象作为顶层结构。
当 JSON 差异文件不加密时,结构建议如下:
```json
{
"format": "dcit-diff",
"version": "1.0",
"createdAt": "2026-04-24T20:30:00+08:00",
"encrypted": false,
"app": {},
"algorithm": {},
"sourceDocument": {},
"replacedDocument": {},
"ruleFile": {},
"integrity": {},
"payload": {}
}
```
当 JSON 差异文件加密时,顶层结构建议如下:
```json
{
"format": "dcit-diff",
"version": "1.0",
"createdAt": "2026-04-24T20:30:00+08:00",
"encrypted": true,
"app": {},
"algorithm": {},
"sourceDocument": {},
"replacedDocument": {},
"ruleFile": {},
"integrity": {},
"encryption": {},
"payloadCiphertext": "Base64..."
}
```
说明:
- `payload` 表示明文差异数据载荷
- `payloadCiphertext` 表示加密后的差异数据载荷
- 两种模式下,`sourceDocument``replacedDocument``ruleFile``integrity` 的结构保持一致
- `*.bmp` 中承载的是逻辑等价的明文差异数据,不承载 `payloadCiphertext`
### 23.2 顶层公共字段
- `format`
- 类型:`string`
- 必填:是
- 固定值:`dcit-diff`
- `version`
- 类型:`string`
- 必填:是
- 含义:差异文件结构版本
- `createdAt`
- 类型:`string`
- 必填:是
- 含义:差异文件创建时间,采用 ISO 8601 格式
- `encrypted`
- 类型:`boolean`
- 必填:是
- 含义:当前 `*.diff` 是否加密存储
- `app`
- 类型:`object`
- 必填:是
- 含义:程序信息
- `algorithm`
- 类型:`object`
- 必填:是
- 含义:差异算法与 BMP 编码算法版本信息
- `sourceDocument`
- 类型:`object`
- 必填:是
- 含义:原始文件 `[A]` 的识别信息
- `replacedDocument`
- 类型:`object`
- 必填:是
- 含义:替换后文件 `[B]` 的识别信息
- `ruleFile`
- 类型:`object`
- 必填:是
- 含义:规则文件识别信息
- `integrity`
- 类型:`object`
- 必填:是
- 含义:完整性校验与防篡改信息
### 23.3 程序与算法信息结构
`app` 对象建议结构如下:
```json
{
"name": "DCIT",
"version": "1.0.0"
}
```
`algorithm` 对象建议结构如下:
```json
{
"diffVersion": "1.0",
"bmpCodecVersion": "1.0"
}
```
### 23.4 文档识别信息结构
`sourceDocument``replacedDocument` 对象建议结构如下:
```json
{
"fileName": "示例.docx",
"relativePath": "子目录/示例.docx",
"extension": ".docx",
"fingerprintAlgorithm": "SHA-256",
"fingerprint": "Base64..."
}
```
字段说明:
- `fileName`
- 含义:文件名
- `sourceDocument.fileName` 必须记录原始文件 `[A]` 的原始文件名
- `replacedDocument.fileName` 必须记录实际生成的替换后文件 `[B]` 文件名,包括文件名规则替换和同名自增后的最终结果
- `relativePath`
- 含义:相对根目录路径
- `extension`
- 含义:原始扩展名
- `fingerprintAlgorithm`
- 含义:文件指纹算法
- `fingerprint`
- 含义:文件指纹值
`ruleFile` 对象建议结构如下:
```json
{
"fileName": "default.rule",
"version": "1.0",
"fingerprintAlgorithm": "SHA-256",
"fingerprint": "Base64..."
}
```
### 23.5 完整性与防篡改结构
`integrity` 对象建议结构如下:
```json
{
"hashAlgorithm": "SHA-256",
"payloadHash": "Base64...",
"tamperProtectionAlgorithm": "HMAC-SHA256",
"tamperProtectionValue": "Base64..."
}
```
字段要求如下:
- `payloadHash` 用于校验明文载荷的一致性
- `tamperProtectionValue` 用于防篡改校验
- 恢复前必须先校验 `payloadHash``tamperProtectionValue`
### 23.6 加密结构
`encrypted = true` 时,必须包含 `encryption` 对象和 `payloadCiphertext` 字段。
`encryption` 对象建议结构如下:
```json
{
"algorithm": "implementation-defined",
"keyId": "default",
"nonce": "Base64...",
"tag": "Base64..."
}
```
字段说明:
- `algorithm`
- 含义:加密算法标识,具体实现可由程序定义
- `keyId`
- 含义:密钥标识
- `nonce`
- 含义:随机数或初始向量
- `tag`
- 含义:认证标签
- `payloadCiphertext`
- 含义:加密后的差异载荷,使用 Base64 编码
### 23.7 明文载荷 `payload` 结构
`encrypted = false` 时,`payload` 建议结构如下:
```json
{
"statistics": {
"textReplaceCount": 0,
"imageReplaceCount": 0
},
"operations": []
}
```
字段要求如下:
- `statistics`
- 含义:统计信息
- `operations`
- 类型:`array`
- 含义:按实际执行顺序记录的替换操作列表
- 当文件名发生变化时,必须包含一条文件名变更操作:`type = "fileName"``objectType = "documentFileName"``originalText` 为原始文件名,`writtenText` 为实际替换后文件名
### 23.8 位置对象结构
所有操作对象都必须包含 `position` 字段。
`position` 对象建议结构如下:
```json
{
"storyType": "main",
"containerPath": "/body/table[0]/row[1]/cell[2]",
"paragraphIndex": 3,
"startRunIndex": 1,
"startCharOffset": 4,
"endRunIndex": 2,
"endCharOffset": 7,
"objectIndex": null
}
```
字段说明:
- `storyType`
- 类型:`string`
- 示例值:
- `main`
- `header`
- `footer`
- `comment`
- `textbox`
- `shape`
- `chart`
- `equation`
- `containerPath`
- 类型:`string`
- 含义:逻辑容器路径
- `paragraphIndex`
- 类型:`integer`
- 含义:容器内段落索引
- `startRunIndex`
- 类型:`integer`
- 含义:起始 Run 索引
- `startCharOffset`
- 类型:`integer`
- 含义:起始字符偏移
- `endRunIndex`
- 类型:`integer`
- 含义:结束 Run 索引
- `endCharOffset`
- 类型:`integer`
- 含义:结束字符偏移
- `objectIndex`
- 类型:`integer | null`
- 含义:非文本对象或同容器内对象索引
### 23.9 文本替换操作对象结构
文本替换操作对象建议结构如下:
```json
{
"operationId": "T000001",
"type": "text",
"objectType": "paragraph",
"position": {},
"rule": {
"id": "R001",
"name": "替换合同编号",
"matchMode": "plain",
"pattern": "合同编号",
"hitIndex": 1
},
"originalText": "合同编号",
"replacementTemplateResult": "文件编号",
"writtenText": "文件编号 ",
"displayWidthOriginal": 8,
"displayWidthWritten": 8,
"truncated": false,
"paddingApplied": true
}
```
字段说明:
- `operationId`
- 类型:`string`
- 含义:操作唯一标识
- `type`
- 类型:`string`
- 固定值:`text`
- `objectType`
- 类型:`string`
- 示例值:
- `paragraph`
- `tableCell`
- `textbox`
- `comment`
- `hyperlinkDisplay`
- `fieldResult`
- `equationText`
- `chartText`
- `rule`
- 类型:`object`
- 含义:命中的规则信息
- `originalText`
- 类型:`string`
- 含义:替换前文本
- `replacementTemplateResult`
- 类型:`string`
- 含义:规则替换模板展开后的结果,尚未进行截断或补齐
- `writtenText`
- 类型:`string`
- 含义:实际写入 `[B]` 的文本
- `displayWidthOriginal`
- 类型:`integer`
- 含义:原文本显示宽度
- `displayWidthWritten`
- 类型:`integer`
- 含义:写入文本显示宽度
- `truncated`
- 类型:`boolean`
- 含义:是否发生截断
- `paddingApplied`
- 类型:`boolean`
- 含义:是否发生补齐
### 23.10 图像替换操作对象结构
图像替换操作对象建议结构如下:
```json
{
"operationId": "I000001",
"type": "image",
"objectType": "inlineImage",
"position": {},
"sourceKind": "bitmap",
"originalImage": {
"format": "png",
"widthPx": 800,
"heightPx": 600,
"data": "Base64..."
},
"convertedBitmapImage": null,
"newImage": {
"format": "png",
"widthPx": 800,
"heightPx": 600,
"data": "Base64..."
},
"seed": 123456789,
"noiseSummary": {
"modifiedPixelRatio": 0.53
},
"layout": {
"displayWidthEmu": 3657600,
"displayHeightEmu": 2743200,
"wrapMode": "inline",
"rotationDegree": 0
}
}
```
字段说明:
- `type`
- 固定值:`image`
- `objectType`
- 示例值:
- `inlineImage`
- `floatingImage`
- `headerImage`
- `textboxImage`
- `shapeImage`
- `sourceKind`
- 可选值:
- `bitmap`
- `convertedFromVector`
- `originalImage`
- 含义:原始图像数据
- `convertedBitmapImage`
- 含义:当原对象为非位图时,记录转换后的位图数据;位图源对象时为 `null`
- `newImage`
- 含义:替换后图像数据
- `seed`
- 含义:用于生成噪声的随机种子
- `noiseSummary.modifiedPixelRatio`
- 含义:修改像素比例,必须大于等于 `0.5`
- `layout`
- 含义:用于校验图像占位与布局属性未变化
### 23.11 `payload` 示例
```json
{
"statistics": {
"textReplaceCount": 1,
"imageReplaceCount": 1
},
"operations": [
{
"operationId": "T000001",
"type": "text",
"objectType": "paragraph",
"position": {
"storyType": "main",
"containerPath": "/body",
"paragraphIndex": 0,
"startRunIndex": 0,
"startCharOffset": 0,
"endRunIndex": 0,
"endCharOffset": 4,
"objectIndex": null
},
"rule": {
"id": "R001",
"name": "替换合同编号",
"matchMode": "plain",
"pattern": "合同编号",
"hitIndex": 1
},
"originalText": "合同编号",
"replacementTemplateResult": "文件编号",
"writtenText": "文件编号",
"displayWidthOriginal": 8,
"displayWidthWritten": 8,
"truncated": false,
"paddingApplied": false
},
{
"operationId": "I000001",
"type": "image",
"objectType": "inlineImage",
"position": {
"storyType": "main",
"containerPath": "/body",
"paragraphIndex": 2,
"startRunIndex": 0,
"startCharOffset": 0,
"endRunIndex": 0,
"endCharOffset": 0,
"objectIndex": 0
},
"sourceKind": "bitmap",
"originalImage": {
"format": "png",
"widthPx": 800,
"heightPx": 600,
"data": "Base64..."
},
"convertedBitmapImage": null,
"newImage": {
"format": "png",
"widthPx": 800,
"heightPx": 600,
"data": "Base64..."
},
"seed": 123456789,
"noiseSummary": {
"modifiedPixelRatio": 0.53
},
"layout": {
"displayWidthEmu": 3657600,
"displayHeightEmu": 2743200,
"wrapMode": "inline",
"rotationDegree": 0
}
}
]
}
```
## 24. 附录 C会话配置文件 `config.json` 结构
### 24.1 总体结构
`config.json` 采用 JSON 对象作为顶层结构,建议如下:
```json
{
"format": "dcit-config",
"version": "1.0",
"savedAt": "2026-04-24T21:00:00+08:00",
"settings": {
"ruleFilePath": "D:\\rules\\default.rule",
"jsonDiffEncryption": true,
"autoExtract": {
"enabledTypes": {
"keyword": true,
"highFrequencyWord": true,
"highFrequencySentence": true
},
"keywordAlgorithms": ["frequency", "tfIdf", "textRank"],
"maxKeywordCount": 10,
"maxHighFrequencyWordCount": 10,
"maxHighFrequencySentenceCount": 10,
"wordStatisticsOptions": {
"chineseToken": true,
"englishWord": true
},
"sentenceStatisticsOptions": {
"chineseSentence": true,
"englishSentence": true
},
"minChineseTokenLength": 1,
"minEnglishWordLength": 1,
"sentenceDelimiters": ["。", "", "", ".", "!", "?", "", ";"],
"excludeEmailAddress": false
}
},
"replacePage": {
"sourceFolder": "D:\\input",
"replaceFolder": "D:\\output_replace"
},
"restorePage": {
"replaceFolder": "D:\\output_replace",
"restoreFolder": "D:\\output_restore"
}
}
```
### 24.2 顶层字段定义
- `format`
- 类型:`string`
- 必填:是
- 固定值:`dcit-config`
- `version`
- 类型:`string`
- 必填:是
- 含义:配置文件结构版本
- `savedAt`
- 类型:`string`
- 必填:是
- 含义:配置保存时间,采用 ISO 8601 格式
- `settings`
- 类型:`object`
- 必填:是
- 含义:全局设置
- `replacePage`
- 类型:`object`
- 必填:是
- 含义:替换页面会话信息
- `restorePage`
- 类型:`object`
- 必填:是
- 含义:恢复页面会话信息
### 24.3 `settings` 对象结构
`settings` 对象建议结构如下:
```json
{
"ruleFilePath": "D:\\rules\\default.rule",
"jsonDiffEncryption": true,
"autoExtract": {
"enabledTypes": {
"keyword": true,
"highFrequencyWord": true,
"highFrequencySentence": true
},
"keywordAlgorithms": ["frequency", "tfIdf", "textRank"],
"maxKeywordCount": 10,
"maxHighFrequencyWordCount": 10,
"maxHighFrequencySentenceCount": 10,
"wordStatisticsOptions": {
"chineseToken": true,
"englishWord": true
},
"sentenceStatisticsOptions": {
"chineseSentence": true,
"englishSentence": true
},
"minChineseTokenLength": 1,
"minEnglishWordLength": 1,
"sentenceDelimiters": [
"。",
"",
"",
".",
"!",
"?",
"",
";"
],
"excludeEmailAddress": false
}
}
```
字段定义如下:
- `ruleFilePath`
- 类型:`string`
- 必填:否
- 含义:当前规则文件的绝对路径
- `jsonDiffEncryption`
- 类型:`boolean`
- 必填:是
- 含义:是否默认对 `*.diff` 采用加密存储
- `autoExtract`
- 类型:`object`
- 必填:否
- 含义:自动提取相关会话设置
`autoExtract` 对象字段定义如下:
- `enabledTypes`
- 类型:`object`
- 必填:是
- 含义:自动提取类别开关
- `keywordAlgorithms`
- 类型:`array`
- 必填:是
- 默认值:`["frequency", "tfIdf", "textRank"]`
- 允许值:`frequency``tfIdf``textRank`
- 含义:关键字提取算法集合,按配置顺序轮询执行
- `maxKeywordCount`
- 类型:`integer`
- 必填:是
- 默认值:`10`
- `maxHighFrequencyWordCount`
- 类型:`integer`
- 必填:是
- 默认值:`10`
- `maxHighFrequencySentenceCount`
- 类型:`integer`
- 必填:是
- 默认值:`10`
- `wordStatisticsOptions`
- 类型:`object`
- 必填:是
- 含义:高频词统计选项
- `sentenceStatisticsOptions`
- 类型:`object`
- 必填:是
- 含义:高频句统计选项
- `minChineseTokenLength`
- 类型:`integer`
- 必填:是
- 默认值:`1`
- `minEnglishWordLength`
- 类型:`integer`
- 必填:是
- 默认值:`1`
- `sentenceDelimiters`
- 类型:`array`
- 必填:是
- 含义:句子分隔符列表
- `excludeEmailAddress`
- 类型:`boolean`
- 必填:是
- 默认值:`false`
- 含义:是否在自动提取中排除邮箱地址
### 24.4 `replacePage` 对象结构
`replacePage` 对象建议结构如下:
```json
{
"sourceFolder": "D:\\input",
"replaceFolder": "D:\\output_replace"
}
```
字段定义如下:
- `sourceFolder`
- 类型:`string`
- 必填:否
- 含义:替换页面当前原始文件夹绝对路径
- `replaceFolder`
- 类型:`string`
- 必填:否
- 含义:替换页面当前替换文件夹绝对路径
### 24.5 `restorePage` 对象结构
`restorePage` 对象建议结构如下:
```json
{
"replaceFolder": "D:\\output_replace",
"restoreFolder": "D:\\output_restore"
}
```
字段定义如下:
- `replaceFolder`
- 类型:`string`
- 必填:否
- 含义:恢复页面当前替换文件夹绝对路径
- `restoreFolder`
- 类型:`string`
- 必填:否
- 含义:恢复页面当前恢复文件夹绝对路径
### 24.6 配置文件保存与加载约束
- `config.json` 必须使用 UTF-8 编码
- 所有路径字段均采用绝对路径
- 缺失字段按默认值处理
- 文件缺失时,系统可按默认会话配置启动,并在首次保存时生成
- 文件损坏或无法解析时,系统必须提示用户并阻止执行型任务,直到用户确认重建默认配置或修复原配置文件
## 25. 附录 D日志格式与日志样例
### 25.1 日志文件基本要求
日志文件采用纯文本格式:
- 编码UTF-8
- 行结束符CRLF
- 按天追加写入
- 保存于启动目录
### 25.2 单行日志格式
建议单行日志采用如下格式:
```text
[<LEVEL>] <yyyyMMdd:HHmmss.fff> [<EVENT_CODE>] [Job=<JOB_ID>] [File="<ABS_PATH>"] [Rule=<RULE_ID>] <MESSAGE>
```
字段说明如下:
- `<LEVEL>`
- 可选值:`INFO``WARNING``ERROR`
- `<yyyyMMdd:HHmmss.fff>`
- 含义:本地时间戳,精确到毫秒
- `<EVENT_CODE>`
- 含义:事件编码
- `[Job=<JOB_ID>]`
- 可选字段
- 含义:批处理任务或文件任务标识
- `[File="<ABS_PATH>"]`
- 可选字段
- 含义:相关文件绝对路径
- `[Rule=<RULE_ID>]`
- 可选字段
- 含义:相关规则 ID
- `<MESSAGE>`
- 含义:日志正文
### 25.3 事件编码建议
日志事件编码至少建议包含:
- `APP_START`
- `APP_EXIT`
- `CONFIG_LOAD`
- `CONFIG_SAVE`
- `RULE_LOAD`
- `RULE_SAVE`
- `RULE_CHECK_OK`
- `RULE_CHECK_WARN`
- `RULE_CHECK_ERROR`
- `EXTRACT_START`
- `EXTRACT_PREVIEW`
- `EXTRACT_APPEND`
- `EXTRACT_UNDO`
- `EXTRACT_CANCEL`
- `EXTRACT_EMPTY`
- `EXTRACT_DONE`
- `EXTRACT_SKIP`
- `SCAN_START`
- `SCAN_DONE`
- `FILE_START`
- `TEXT_MATCH`
- `TEXT_WRITE`
- `IMAGE_REPLACE`
- `DIFF_WRITE`
- `BMP_WRITE`
- `RESTORE_START`
- `RESTORE_APPLY`
- `FILE_SUCCESS`
- `FILE_FAIL`
- `FILE_STOPPED`
- `SUMMARY`
- `STACK`
### 25.4 异常堆栈记录格式
当需要记录异常堆栈时:
- 先输出一条主错误日志
- 再按堆栈行逐行输出 `STACK` 事件
示例:
```text
[ERROR] 20260424:210512.314 [FILE_FAIL] [Job=J0008] [File="D:\input\a.docx"] 文件处理失败:无法写入差异文件
[ERROR] 20260424:210512.315 [STACK] [Job=J0008] IOException: access denied
[ERROR] 20260424:210512.316 [STACK] [Job=J0008] at DiffWriter.Commit(...)
```
### 25.5 日志样例
普通启动样例:
```text
[INFO] 20260424:210000.102 [APP_START] 程序启动
[INFO] 20260424:210000.130 [CONFIG_LOAD] 配置加载成功
[INFO] 20260424:210001.004 [RULE_LOAD] [File="D:\rules\default.rule"] 规则文件加载成功,共 12 条规则
```
扫描样例:
```text
[INFO] 20260424:210005.217 [SCAN_START] [File="D:\input"] 开始扫描目录
[INFO] 20260424:210006.884 [SCAN_DONE] [File="D:\input"] 扫描完成,共发现 36 个文件
```
文字匹配样例:
```text
[INFO] 20260424:210015.011 [FILE_START] [Job=J0001] [File="D:\input\sample.docx"] 开始处理文件
[INFO] 20260424:210015.428 [TEXT_MATCH] [Job=J0001] [File="D:\input\sample.docx"] [Rule=R001] 命中位置=/body p=0 start=(0,0) end=(0,4) 原文="合同编号"
[INFO] 20260424:210015.431 [TEXT_WRITE] [Job=J0001] [File="D:\input\sample.docx"] [Rule=R001] 写入文本="文件编号"
```
图片替换样例:
```text
[INFO] 20260424:210016.223 [IMAGE_REPLACE] [Job=J0001] [File="D:\input\sample.docx"] 对象=/body p=2 obj=0 seed=123456789 modifiedPixelRatio=0.53
```
规则检查警告样例:
```text
[WARNING] 20260424:210020.044 [RULE_CHECK_WARN] [Rule=R008] 规则可能与后续规则重叠命中,允许用户确认后继续
```
批处理汇总样例:
```text
[INFO] 20260424:210530.992 [SUMMARY] 成功=34 失败=2 跳过=0 文本替换=1280 图片替换=96 文本恢复=0 图片恢复=0
```
## 26. 附录 EBMP 差异文件编码规则
### 26.1 目标
本附录定义如何将逻辑等价的明文差异数据无损编码为 `*.bmp` 文件,并确保能够从 `*.bmp` 无损恢复出逻辑等价的 JSON 差异数据。
### 26.2 编码输入
BMP 编码输入为“逻辑等价的明文差异数据”。
具体要求如下:
- 若当前 `*.diff` 文件为未加密形式,则以其规范化 JSON 结构作为输入
- 若当前 `*.diff` 文件为加密形式,则在内存中使用等价的明文差异数据作为输入
- `*.bmp` 不承载 `payloadCiphertext`
- `*.bmp` 不提供保密性,仅提供可逆承载能力
### 26.3 规范化 JSON 串行化规则
在编码为 BMP 之前,必须先将差异数据序列化为规范化 JSON 字节流。
规范化规则如下:
- 编码为 UTF-8
- 不写入 BOM
- 对象字段按本 SRS 定义顺序输出
- 数组元素顺序保持原始执行顺序
- 不输出无意义空白
- 字符串按 JSON 标准转义
说明:
- 只要解码后得到的差异数据在结构和语义上与原始差异数据等价,即视为满足要求
### 26.4 二进制封装结构
规范化 JSON 字节流在映射到像素前,必须先封装为二进制载荷。
二进制封装结构定义如下:
1. `Magic`
- 长度8 字节
- 固定 ASCII 内容:`DCITBMP1`
2. `HeaderVersion`
- 长度2 字节
- 类型:无符号整数,小端序
- 固定值:`1`
3. `Flags`
- 长度2 字节
- 类型:无符号整数,小端序
- 当前固定值:`0`
4. `PayloadLength`
- 长度8 字节
- 类型:无符号整数,小端序
- 含义:规范化 JSON 字节流长度
5. `PayloadSha256`
- 长度32 字节
- 含义:规范化 JSON 字节流的 SHA-256 值
6. `PayloadBytes`
- 长度:`PayloadLength`
- 含义:规范化 JSON 字节流本体
封装后的字节流记为 `BlobBytes`
### 26.5 像素映射规则
`BlobBytes` 必须映射为 8 位灰度 BMP 图像。
映射规则如下:
- BMP 使用 8 位灰度色板
- 色板中第 `i` 个颜色的 RGB 值必须为 `(i, i, i)`,其中 `i` 取值范围为 `0..255`
- `BlobBytes` 中每个字节值直接映射为一个像素灰度值
- 映射顺序为按行优先,从左到右、从上到下
### 26.6 图像宽高计算规则
为保证编码确定性BMP 宽高采用如下固定规则:
- `width = 1024`
- `height = ceil(length(BlobBytes) / 1024)`
`length(BlobBytes) = 0`,则:
- `width = 1024`
- `height = 1`
### 26.7 尾部填充规则
若最后一个像素行未被 `BlobBytes` 填满,则:
- 剩余像素全部填充为灰度值 `0`
说明:
- 这些尾部填充值不属于逻辑载荷
- 解码时必须依据 `PayloadLength` 精确截取有效数据
### 26.8 BMP 行对齐说明
BMP 文件行对齐所引入的字节填充属于 BMP 文件格式自身要求。
该部分:
- 不属于逻辑差异数据
- 解码时必须忽略 BMP 行对齐填充,仅按像素值恢复 `BlobBytes`
### 26.9 解码规则
`*.bmp` 恢复差异数据时,解码流程如下:
1. 读取 BMP 像素数据
2. 按行优先顺序恢复灰度字节流
3. 读取并校验 `Magic`
4. 读取 `HeaderVersion`
5. 读取 `Flags`
6. 读取 `PayloadLength`
7. 读取 `PayloadSha256`
8.`PayloadLength` 截取 `PayloadBytes`
9. 校验 `PayloadSha256`
10.`PayloadBytes` 按 UTF-8 解析为规范化 JSON
11. 反序列化为逻辑等价的差异数据对象
若任一步失败,则:
- 必须判定该 `*.bmp` 文件无效
- 必须拒绝恢复
- 必须写入日志
### 26.10 `*.bmp` 转 `*.diff` 输出规则
当系统需要根据 `*.bmp` 生成等价 `*.diff` 文件时:
- 输出内容应为规范化后的明文 JSON 差异数据
- 输出编码为 UTF-8
- 不写入 BOM
- 输出结构必须满足本 SRS 第 23 章定义
### 26.11 BMP 编码示意
编码过程示意如下:
```text
Diff Object
-> Canonical JSON UTF-8 Bytes
-> BlobBytes(Magic + Header + Payload)
-> 8-bit Grayscale Pixel Stream
-> BMP File
```
解码过程示意如下:
```text
BMP File
-> 8-bit Grayscale Pixel Stream
-> BlobBytes
-> Canonical JSON UTF-8 Bytes
-> Diff Object
```
## 27. 附录 F测试用例矩阵
### 27.1 目的与使用方式
本附录给出本项目的最小可执行测试用例矩阵,用于指导:
- 开发阶段联调验证
- 系统测试与回归测试
- 标准验收样例集执行
- 交付前功能覆盖检查
说明如下:
- `级别=必测` 表示应纳入正式测试与交付前回归
- `级别=建议` 表示建议覆盖,但不作为单独阻断项
- 若单个用例涉及多个对象类型,则应分别在 `*.docx``*.doc` 上至少各验证一组样例
- 所有涉及“恢复一致性”的用例,均应同时检查文本一致、对象一致性约束和日志记录完整性
### 27.2 核心替换功能测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-RPL-001 | 必测 | 正文普通文本替换 | `*.docx` 正文含普通段落文本,配置普通文本规则 | 成功命中并替换,生成 `[B]``*.diff``*.bmp`,日志记录命中次数 |
| TC-RPL-002 | 必测 | `*.doc` 基本文本替换 | `*.doc` 文档含普通段落文本,配置普通文本规则 | 成功完成替换,输出文件可打开,日志无未处理异常 |
| TC-RPL-003 | 必测 | 页眉文本替换 | 页眉内含普通文本 | 页眉文本成功替换,恢复后与原文一致 |
| TC-RPL-004 | 必测 | 页眉表格替换 | 页眉中含表格及单元格文字 | 表格内文字成功替换,表格结构保持不变 |
| TC-RPL-005 | 必测 | 文本框文字替换 | 正文和页眉中均含文本框文字 | 文本框内文字成功替换,文本框位置和尺寸不变 |
| TC-RPL-006 | 必测 | 合并单元格表格替换 | 表格存在横向或纵向合并单元格 | 合并单元格结构保持不变,允许跨 `Run` 匹配,不允许跨单元格匹配 |
| TC-RPL-007 | 必测 | 批注内容替换 | 文档存在批注文本 | 仅批注内容变化,作者、时间、状态保持不变 |
| TC-RPL-008 | 必测 | 超链接显示文字替换 | 文档含超链接 | 仅显示文字发生替换,目标 URL 保持不变 |
| TC-RPL-009 | 必测 | 目录项相关文本替换 | 文档含目录及其源标题文本 | 替换完成后自动更新目录,目录显示结果与正文一致 |
| TC-RPL-010 | 必测 | 域结果替换 | 文档含域结果显示文本 | 仅域结果参与替换,域代码不修改 |
| TC-RPL-011 | 必测 | 公式内文字替换 | 文档含可解析公式对象 | 公式中可解析文字成功替换,排版不明显异常 |
| TC-RPL-012 | 必测 | 图表文本替换 | 图表含标题、轴标题、图例、数据标签、数据表 | 所有已定义范围的图表文本均参与替换 |
| TC-RPL-013 | 必测 | 嵌入式位图替换 | 文档含 PNG、JPG、BMP、TIFF、GIF 等位图 | 图片完成噪声替换,尺寸、位置、环绕、锚点、裁剪、旋转保持不变 |
| TC-RPL-014 | 必测 | 浮动图片替换 | 文档含浮动位图图片 | 浮动属性保持不变,图片成功替换 |
| TC-RPL-015 | 必测 | 非位图对象图片替换 | 文档含 WMF、EMF、SVG、Office 形状或等价非位图对象 | 成功转换后按图片策略替换,并在恢复后达到视觉一致 |
| TC-RPL-016 | 必测 | 规则顺序执行 | 两条规则前后存在依赖关系 | 严格按列表顺序执行,后一条允许命中前一条替换结果 |
| TC-RPL-017 | 必测 | 区分大小写开关 | 同一原文大小写混合,规则开启或关闭大小写敏感 | 开启时仅命中大小写完全一致项,关闭时大小写无关命中 |
| TC-RPL-018 | 必测 | 全字匹配开关 | 规则原文为词边界敏感内容 | 开启时仅全字命中,关闭时允许部分命中 |
| TC-RPL-019 | 必测 | 正则捕获组回填 | 配置包含捕获组和替换模板的规则 | 正则命中成功,替换结果符合回填模板 |
| TC-RPL-020 | 必测 | 跨 `Run` 匹配 | 同一段落内视觉连续文本被拆成多个 `Run` | 应成功命中并替换 |
| TC-RPL-021 | 必测 | 不跨段落匹配 | 目标文本被分布在两个段落 | 不应命中,日志中不产生错误 |
| TC-RPL-022 | 必测 | 不跨单元格匹配 | 目标文本分布在两个不同单元格 | 不应命中,表格结构保持不变 |
| TC-RPL-023 | 必测 | 过长替换文本截断 | 新文本显示宽度大于原文本允许宽度 | 应按规则截断,且尽量保持版式不变 |
| TC-RPL-024 | 必测 | 过短替换文本补齐 | 新文本显示宽度小于原文本 | 应采用可逆方式补齐,恢复后可完全回到原文本 |
| TC-RPL-025 | 必测 | 页脚文本替换 | 页脚内含普通文本 | 页脚文本成功替换,恢复后与原文一致 |
| TC-RPL-026 | 必测 | 页脚表格替换 | 页脚中含表格及单元格文字 | 表格内文字成功替换,页脚表格结构保持不变 |
| TC-RPL-027 | 必测 | 页脚文本框替换 | 页脚中含文本框文字 | 文本框内文字成功替换,文本框位置和尺寸保持不变 |
| TC-RPL-028 | 必测 | 页眉页脚图片替换 | 页眉或页脚中含嵌入式或浮动图片 | 图片成功替换,尺寸、位置、环绕和锚点保持不变 |
| TC-RPL-029 | 必测 | 图片随机噪声默认变化 | 相同输入、未设置固定随机种子时执行两次替换 | 两次图片替换结果应存在噪声差异,且均可成功恢复 |
| TC-RPL-030 | 必测 | 固定随机种子可复现 | 对同一输入设置相同固定随机种子重复替换 | 图片替换结果保持一致,且恢复结果一致 |
| TC-RPL-031 | 必测 | 替换输出目录结构一致性 | 原始文件夹包含多级子目录并执行替换 | 替换后文件、`*.diff``*.bmp` 均保留相对目录树结构 |
| TC-RPL-032 | 必测 | 替换输出重名自动重命名 | 替换输出目录已存在同名目标文件 | 新输出采用自增序号重命名,不覆盖既有文件;同一源文件的替换文档、`*.diff``*.bmp` 自增序号一致 |
| TC-RPL-033 | 必测 | 文件名参与规则替换 | 原始文件名命中启用规则,正文可无命中 | 替换后文件、`*.diff``*.bmp` 均使用规则替换后的文件基本名加日期后缀保存;差异元数据和 `payload.operations` 均记录文件名变更 |
| TC-RPL-034 | 必测 | 文件名替换非法结果防护 | 文件名规则替换结果为空或包含非法文件名字符 | 系统阻断当前扫描/执行,日志记录源文件、替换后文件名结果和错误原因 |
| TC-RPL-035 | 必测 | 文件名变更修改记录 | 文件名因规则、日期后缀或同名自增导致最终输出名与原始文件名不同 | 差异文件 `payload.operations` 包含 `type=fileName``objectType=documentFileName` 的记录,原始文件名和实际替换后文件名准确 |
### 27.3 恢复与一致性测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-RST-001 | 必测 | 从 `*.diff` 恢复文本 | 使用替换输出的 `[B] + *.diff` | 成功恢复出 `[A']`,文本内容与原始 `[A]` 完全一致 |
| TC-RST-002 | 必测 | 从 `*.bmp` 恢复文本 | 使用替换输出的 `[B] + *.bmp` | 先解码为等价差异数据,再恢复成功 |
| TC-RST-003 | 必测 | 文本与图片同时恢复 | 文档同时包含文本替换和图片替换 | 文本和图片均恢复成功 |
| TC-RST-004 | 必测 | 严格位置匹配恢复 | 差异文件中的位置与当前文档严格一致 | 正常恢复,不启用容错查找 |
| TC-RST-005 | 必测 | 位置不匹配恢复失败 | 人工修改 `[B]` 后再执行恢复 | 恢复被拒绝,日志明确给出失败原因 |
| TC-RST-006 | 必测 | 目录自动更新 | 恢复后文档含目录 | 恢复完成后自动更新目录显示结果 |
| TC-RST-007 | 必测 | 交叉引用错误验证 | 恢复后文档显示结果中存在“错误!未找到引用源”或等价域错误文本 | 恢复输出被拒绝,日志记录 Story、容器、段落和上下文片段 |
| TC-RST-008 | 必测 | 编号段落一致性 | 原文包含多级编号列表 | 恢复后编号值、级别、缩进、制表位、自动编号行为均一致 |
| TC-RST-009 | 必测 | 表格与文本框一致性 | 原文含表格、页眉表格、文本框 | 恢复后结构、位置、内容与原文一致 |
| TC-RST-010 | 必测 | 图片视觉一致性 | 原文含位图和非位图对象 | 恢复后应满足肉眼一致、尺寸与位置一致,并满足像素相似度阈值要求 |
| TC-RST-011 | 必测 | 路径结构一致性 | 目录批处理替换后执行恢复 | 恢复输出目录保留原目录树结构 |
| TC-RST-012 | 必测 | 重名自动重命名 | 目标恢复目录已有同名输出 | 新输出采用自增序号重命名,不覆盖原文件 |
| TC-RST-013 | 建议 | 多轮替换后恢复验证 | 同一文件多次独立处理,存在多个版本输出 | 每组 `[B] + C` 仅对应恢复其本轮结果,不得串用 |
| TC-RST-014 | 必测 | 单批次差异文件格式不混用 | 同一恢复批次同时勾选 `*.diff``*.bmp` 两类输入 | 系统拒绝混合执行,提示用户单次批处理仅允许一种差异文件格式 |
| TC-RST-015 | 必测 | 规则文件指纹错配恢复失败 | `[B]` 与差异文件匹配,但差异文件中的规则文件指纹与当前恢复上下文不一致 | 恢复被拒绝,日志明确记录规则文件指纹错配 |
| TC-RST-016 | 必测 | 程序或算法版本不兼容恢复失败 | 差异文件中的程序版本或算法版本与当前程序不兼容 | 恢复被拒绝,日志明确记录版本不兼容原因 |
| TC-RST-017 | 必测 | 恢复原始文件名 | 原始文件名经规则替换后生成 `[B]`,差异文件记录 `sourceDocument.fileName` | 恢复输出使用原始文件名和原始扩展名;若同名冲突则自动追加自增序号 |
### 27.4 规则文件与差异文件测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-RULE-001 | 必测 | 打开规则文件 | 使用合法 `*.rule` 文件 | 成功加载全部规则,顺序与文件内一致 |
| TC-RULE-002 | 必测 | 保存规则文件 | 编辑后保存 `*.rule` | 成功保存为 UTF-8 JSON内容满足附录 A 定义 |
| TC-RULE-003 | 必测 | 非法正则禁止保存 | 规则中包含非法正则表达式 | 保存失败,弹窗提示,日志能定位规则位置和详细错误 |
| TC-RULE-004 | 必测 | 规则兼容性检查告警 | 存在重叠命中或重复命中风险 | 弹窗提示并写日志,允许用户继续 |
| TC-RULE-005 | 必测 | 规则兼容性检查阻断 | 存在无法解析或必然错误规则 | 禁止保存或禁止执行,并写日志 |
| TC-RULE-006 | 必测 | 差异文件 JSON 明文保存 | 会话配置为 `jsonDiffEncryption=false` | 输出明文 `*.diff`,结构符合附录 B |
| TC-RULE-007 | 必测 | 差异文件 JSON 加密保存 | 会话配置为 `jsonDiffEncryption=true` | 输出加密 `*.diff`,恢复时可正确解密 |
| TC-RULE-008 | 必测 | BMP 与 JSON 等价性 | 同一替换结果同时生成 `*.diff``*.bmp` | `*.bmp` 可无损还原出逻辑等价的明文差异数据 |
| TC-RULE-009 | 必测 | 差异文件完整性校验 | 人工篡改 `*.diff``*.bmp` | 校验失败,拒绝恢复,不允许强制继续 |
| TC-RULE-010 | 必测 | 指纹错配阻断 | 使用不匹配的 `[B]`、规则文件或差异文件组合 | 恢复失败,日志标明错配类型 |
| TC-RULE-011 | 必测 | 自动提取预览流程 | 在替换页面勾选一个或多个文件并点击自动提取 | 基于全部勾选文件生成关键字、高频词、高频句候选结果并展示预览,不直接写入规则列表 |
| TC-RULE-012 | 必测 | 自动提取选择性追加 | 在预览中仅勾选部分候选项 | 仅被勾选的候选项被追加为规则 |
| TC-RULE-013 | 必测 | 自动提取规则默认属性 | 执行自动提取并追加后检查新增规则字段 | 新增规则默认满足“启用=是、普通文本、区分大小写=是、全字匹配=是、原文本=提取结果、新文本为空字符串”,且系统不因新文本为空而自动禁用规则 |
| TC-RULE-014 | 必测 | 自动提取去重 | 当前规则列表中已存在相同原文本规则,再次执行自动提取 | 不重复追加,弹窗和日志给出跳过数量 |
| TC-RULE-015 | 必测 | 自动提取不覆盖人工规则 | 自动提取结果与人工规则原文本相同 | 自动提取结果被丢弃,人工规则保持不变 |
| TC-RULE-016 | 必测 | 自动提取命名与备注 | 执行自动提取并追加后检查新增规则的 ID、名称、备注 | ID 前缀、名称格式和备注内容满足 SRS 要求 |
| TC-RULE-017 | 必测 | 自动提取空结果提示 | 文档无有效候选项 | 弹窗提示“未提取到可用项”,不修改规则列表 |
| TC-RULE-018 | 必测 | 自动提取撤销 | 完成一次自动提取追加后执行撤销 | 最近一次自动提取新增的规则被整体回退 |
| TC-RULE-019 | 必测 | 自动提取关键字算法轮询 | 关键字算法同时勾选按词频、`TF-IDF``TextRank` | 系统按配置顺序对勾选文件范围各执行一轮,并对结果去重合并后进入预览 |
| TC-RULE-020 | 必测 | 自动提取邮箱与单字默认纳入 | 使用包含邮箱地址、单字、单词的勾选文件集合执行自动提取 | 邮箱地址参与提取,单字和单词按最小长度设置纳入统计 |
| TC-RULE-021 | 必测 | 执行前规则兼容性复检 | 规则文件已成功保存后,执行前再引入兼容性风险条件 | 启动执行前再次触发规则兼容性检查,弹窗和日志同时给出结果 |
| TC-RULE-022 | 必测 | 自动提取多文件跨文档去重 | 多个勾选文件中存在相同候选原文本 | 预览和追加结果中仅保留一条规则,并保留首次出现文档路径和顺序 |
| TC-RULE-023 | 必测 | 自动提取仅写入会话内存直到保存 | 自动提取追加规则后不执行保存规则文件,直接关闭或重新加载 | 内存规则变化不写入 `*.rule` 文件,原规则文件内容保持不变 |
| TC-RULE-024 | 必测 | 自动提取追加前后双阶段检查 | 自动提取结果中包含重复项和追加后才暴露的兼容性问题 | 追加前执行快速去重和冲突检查,追加后执行完整合法性和兼容性检查 |
| TC-RULE-025 | 必测 | BMP 文件命名与输出位置 | 执行替换并生成差异文件 | `*.bmp``*.diff` 同名同目录生成 |
| TC-RULE-026 | 必测 | 自动提取范围以勾选集为准 | 文件列表高亮选择与复选框勾选集合不一致 | 自动提取仅扫描勾选文件,高亮选中状态不影响结果 |
### 27.5 异常与防护测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-EXC-001 | 必测 | 不支持加密文档 | 输入为加密文档 | 当前文件失败并记录错误,后续文件继续 |
| TC-EXC-002 | 必测 | 不支持受保护文档 | 输入为受保护文档 | 当前文件失败并记录错误,后续文件继续 |
| TC-EXC-003 | 必测 | 支持只读文档 | 输入为只读文档 | 可正常读取并处理 |
| TC-EXC-004 | 必测 | 目录重叠阻断 | 原始目录与替换目录或恢复目录相同或互为父子目录 | 禁止执行,弹窗并写日志 |
| TC-EXC-005 | 必测 | 原子写入保护 | 生成 `[B]` 后、写入 `*.diff` 前制造故障 | 不保留正式半成品,仅允许保留临时文件用于清理 |
| TC-EXC-006 | 必测 | 输出文件被占用 | 目标输出文件被其他进程占用 | 当前文件失败并记录原因,后续文件继续 |
| TC-EXC-007 | 必测 | 源文件处理中被修改 | 处理过程中外部修改源文件 | 当前文件失败并记录错误,后续文件继续 |
| TC-EXC-008 | 必测 | 磁盘空间不足 | 输出盘或临时目录空间不足 | 当前文件失败,日志明确记录空间异常 |
| TC-EXC-009 | 必测 | 临时目录不可写 | 临时目录权限不足 | 当前批次禁止启动,提示并写日志 |
| TC-EXC-010 | 必测 | 字体缺失兜底 | 目标机缺少影响排版的关键字体 | 当前文件继续处理,中文/东亚字体使用宋体兜底,英文和数字使用 Times New Roman 兜底,日志记录缺失字体和兜底说明 |
| TC-EXC-011 | 必测 | 零长度匹配防护 | 正则规则可产生零长度命中 | 执行期被阻断或安全跳过,不发生死循环 |
| TC-EXC-012 | 必测 | 灾难性回溯防护 | 构造高风险正则输入 | 执行可控失败或超时终止,程序不假死 |
| TC-EXC-013 | 必测 | 命中次数异常上限防护 | 单规则在单文件内产生异常大量命中 | 触发防护并记录日志 |
| TC-EXC-014 | 必测 | 停止按钮行为 | 执行批处理过程中点击停止 | 尽量完成当前文件后停止,其余未开始文件标记为“已停止” |
| TC-EXC-015 | 必测 | 崩溃后临时文件清理 | 制造异常中断后重启程序 | 启动时发现并清理无效临时文件,日志记录清理过程 |
| TC-EXC-016 | 必测 | 重复入队防护 | 同一源文件因扫描或并发被重复加入任务队列 | 系统应去重,不重复处理同一源文件 |
| TC-EXC-017 | 必测 | 配置文件损坏处理 | `config.json` 内容损坏 | 禁止按损坏配置继续执行,提示并写日志,直到用户确认重建默认配置或修复原配置 |
| TC-EXC-018 | 必测 | 规则文件损坏处理 | `*.rule` 文件内容损坏 | 加载失败并提示,不得带病执行 |
| TC-EXC-019 | 必测 | 自动提取取消保护 | 自动提取过程中执行取消 | 当前规则列表保持不变,日志记录取消事件 |
| TC-EXC-020 | 必测 | 自动提取失败不破坏规则列表 | 自动提取过程中制造解析异常 | 现有规则列表保持不变,日志记录失败原因 |
| TC-EXC-021 | 必测 | 配置文件缺失处理 | 启动时不存在 `config.json` | 系统按默认会话配置启动,不阻断执行,首次保存时生成新的 `config.json` |
| TC-EXC-022 | 必测 | 批处理前日志文件不可创建 | 启动目录日志文件无法创建或打开 | 当前批处理不得启动,并提示运行环境不满足要求 |
| TC-EXC-023 | 必测 | 运行中日志落盘失败 | 批处理过程中日志文件追加写入失败 | 当前文件可控结束,界面日志继续保留,当前批次结束后不再调度新任务 |
| TC-EXC-024 | 必测 | 单文件失败后继续后续文件 | 批处理中首个文件失败,后续文件仍可正常处理 | 当前失败文件被记录,后续文件继续执行,汇总结果正确统计成功和失败数量 |
### 27.6 UI、日志与会话配置测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-UI-001 | 必测 | 三页签存在性 | 启动程序 | 存在“替换”“恢复”“设置”三个固定页签 |
| TC-UI-002 | 必测 | 现代目录选择对话框 | 点击目录选择按钮 | 弹出文件选择风格的目录选择对话框,而非老式树形浏览目录框 |
| TC-UI-003 | 必测 | 失焦自动扫描 | 修改原始目录输入框后移出焦点 | 自动异步扫描,不阻塞界面 |
| TC-UI-004 | 必测 | 文件列表排序 | 点击文件列表列头 | 列表按所选列排序 |
| TC-UI-005 | 必测 | 进度显示 | 批处理执行中 | 显示总进度条、单文件进度条、当前文件、已处理数量、累计命中数 |
| TC-UI-006 | 必测 | 当前规则显示 | 批处理执行中 | 显示当前规则 ID 和规则名称 |
| TC-UI-007 | 必测 | 行状态颜色 | 文件成功、失败、处理中、已停止 | 颜色分别符合绿色、红色、蓝色、灰色定义 |
| TC-UI-008 | 必测 | 完成汇总弹窗 | 替换或恢复批处理完成 | 弹出汇总结果,包含成功数、失败数、停止数及替换恢复统计 |
| TC-UI-009 | 必测 | 日志编码与内容 | 执行任一处理流程 | 日志文件为 UTF-8包含路径、规则 ID、事件码、失败原因等字段 |
| TC-UI-010 | 必测 | 异常堆栈日志 | 制造处理期异常 | 日志中先写主错误,再写 `STACK` 事件 |
| TC-UI-011 | 必测 | 会话配置持久化 | 修改 `jsonDiffEncryption` 等设置后重启程序 | 设置写入 `config.json` 并可正确恢复 |
| TC-UI-012 | 建议 | 长日志连续写入 | 长时间批处理大量文件 | 界面持续响应,日志正常追加,不出现明显卡死 |
| TC-UI-013 | 必测 | 自动提取按钮使能条件 | 文件列表分别处于未勾选、勾选一个、勾选多个状态 | 仅在至少勾选一个文件时允许执行自动提取,未勾选时禁用或明确提示 |
| TC-UI-014 | 必测 | 自动提取结果同步显示 | 在替换页面执行自动提取后切换到设置页面 | 新增规则应立即显示在规则列表中 |
| TC-UI-015 | 必测 | 自动提取进度与取消 | 执行大文档自动提取 | 界面显示提取进度,可取消,且界面保持响应 |
| TC-UI-016 | 必测 | 自动提取后自动定位 | 自动提取成功追加规则后 | 自动切换到设置页面并定位到第一条新增规则 |
| TC-UI-017 | 必测 | 自动提取期间禁止编辑规则 | 自动提取进行中尝试编辑规则列表 | 编辑入口被禁用或阻断 |
| TC-UI-018 | 必测 | 自动提取设置持久化 | 修改自动提取设置并重启程序 | 自动提取相关设置从 `config.json` 正确恢复 |
| TC-UI-019 | 必测 | 目录选择取消不修改路径 | 打开目录选择对话框后点击“取消” | 对应路径文本框内容保持不变 |
| TC-UI-020 | 必测 | 文件列表批量勾选与取消勾选 | 在替换页面文件列表执行批量勾选和批量取消勾选 | 复选框状态批量更新正确,自动提取和批处理范围随之变化 |
| TC-UI-021 | 必测 | 恢复页失焦自动扫描 | 修改恢复页相关路径输入框后移出焦点 | 自动异步扫描可恢复文件,不阻塞界面 |
| TC-UI-022 | 必测 | 自动提取预览字段完整性 | 执行自动提取进入预览界面 | 预览列表至少显示是否追加、提取类型、原文本、统计值、首次出现文档路径、首次出现顺序 |
| TC-UI-023 | 必测 | 会话配置自动刷新 | 修改会话配置项但不重启程序 | `config.json` 随配置变化自动刷新,内容与当前会话一致 |
| TC-UI-024 | 必测 | 日志框右键菜单 | 在日志框打开右键菜单并执行复制全部内容、清空日志 | 菜单项完整,复制操作覆盖全部日志文本,清空操作仅清空界面日志框 |
| TC-UI-025 | 必测 | 替换页文件列表右键批量操作 | 在替换页选择多行后执行删除、启用、不启用 | 所选行被批量删除或批量更新勾选状态,界面状态同步刷新 |
| TC-UI-026 | 必测 | 恢复页文件列表右键批量操作 | 在恢复页选择多行后执行删除、启用、不启用 | 所选行被批量删除或批量更新勾选状态,界面状态同步刷新 |
| TC-UI-027 | 必测 | 规则列表右键批量操作 | 在设置页规则列表选择多行后执行删除、启用、不启用 | 所选规则被批量删除或批量更新启用状态,规则列表与执行状态同步刷新 |
### 27.7 兼容性与运行环境测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-CMP-001 | 必测 | Win7 SP1 x64 兼容性 | 在 Win7 SP1 x64 环境运行绿色版 | 程序可启动、可执行基本替换与恢复流程 |
| TC-CMP-002 | 必测 | x64 平台约束 | 在 x64 目标机运行 | 程序可正常运行 |
| TC-CMP-003 | 必测 | 无管理员权限运行 | 目标机普通用户权限,无管理员权限 | 程序可正常启动并完成处理 |
| TC-CMP-004 | 必测 | 无软件安装权限运行 | 目标机禁止安装软件 | 绿色版可直接运行,不依赖安装流程 |
| TC-CMP-005 | 必测 | 启动目录可写要求 | 启动目录可写 | 程序可正常创建日志与配置文件 |
| TC-CMP-006 | 必测 | 启动目录不可写阻断 | 启动目录不可写 | 视为环境不满足,程序拒绝继续运行并提示原因 |
| TC-CMP-007 | 建议 | 首次启动解压内置组件 | 完全离线环境首次运行 | 可成功解压所需组件并进入可用状态 |
| TC-CMP-008 | 必测 | Word/WPS 宿主机前提 | 替换/恢复宿主机安装支持 docx 的 Word 或 WPS | 程序可调用宿主能力完成域刷新、doc/docx 转换或相关文档处理 |
| TC-CMP-009 | 必测 | 无 Visio 依赖 | 文档包含 Visio/OLE 对象且目标机未安装 Visio | 按可见位图处理和恢复,不要求安装 Visio |
### 27.8 响应性与目标性能测试矩阵
| 用例 ID | 级别 | 测试目标 | 输入或前置条件 | 预期结果 |
| --- | --- | --- | --- | --- |
| TC-PRF-001 | 建议 | 100 页替换目标性能 | 单个 100 页文档执行替换 | 目标值为不超过 10 秒;若未达到,不单独作为强制阻断项 |
| TC-PRF-002 | 建议 | 100 页恢复目标性能 | 单个 100 页文档执行恢复 | 目标值为不超过 10 秒;若未达到,不单独作为强制阻断项 |
| TC-PRF-003 | 必测 | 大文件界面响应性 | 单个大文件处理过程中观察界面 | 不得出现界面卡死、状态不更新、操作无响应 |
| TC-PRF-004 | 必测 | 多文件批处理响应性 | 多文件批处理执行过程中观察界面 | 不得出现界面卡死、状态不更新、操作无响应 |
| TC-PRF-005 | 建议 | 并发处理稳定性 | 开启多文件并行处理 | 应能利用环境资源并保持正确性,不出现重复处理、输出冲突或死锁 |
### 27.9 标准验收样例集覆盖要求
标准验收样例集至少应覆盖以下样例类别,并与本章测试矩阵建立一一映射关系:
- `*.docx` 正文、页眉、页脚
- `*.doc` 正文、页眉、页脚
- 文本框、批注、表格、合并单元格
- 超链接显示文字、目录、域结果
- 公式、图表
- 位图图片、非位图图片
- 嵌入式图片、浮动图片
- 自动提取关键字、高频词、高频句
- 规则顺序、正则、大小写、全字匹配、跨 `Run`
- 恢复严格匹配、差异错配、完整性校验失败
- 无管理员权限、无安装权限、启动目录可写与不可写场景
测试报告中至少应包含以下映射信息:
- 样例编号
- 对应用例 ID
- 输入文件路径
- 规则文件路径
- 执行时间
- 结果判定
- 失败原因
- 日志位置