# 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 文件,用于定义文字替换规则。 - Story:Word 的逻辑文本区域,例如正文、页眉、页脚、批注、文本框等。 - Run:Word 在同一段落或容器内对连续文字进行的内部样式片段划分。视觉上连续的文字可能由多个 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 - 不得要求安装 Visio;Visio/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 [] [] [Job=] [File=""] [Rule=] ``` 字段说明如下: - `` - 可选值:`INFO`、`WARNING`、`ERROR` - `` - 含义:本地时间戳,精确到毫秒 - `` - 含义:事件编码 - `[Job=]` - 可选字段 - 含义:批处理任务或文件任务标识 - `[File=""]` - 可选字段 - 含义:相关文件绝对路径 - `[Rule=]` - 可选字段 - 含义:相关规则 ID - `` - 含义:日志正文 ### 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. 附录 E:BMP 差异文件编码规则 ### 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 - 输入文件路径 - 规则文件路径 - 执行时间 - 结果判定 - 失败原因 - 日志位置