# 定时任务 — 模板填充「源数据抽取」手工测试清单 > 覆盖功能:定时任务「模板数据转换器」内置 agent —— 把用户传入的源数据转换成 HTML > 模板的 `DATA` 结构并填充生成可预览页面。**重点测「源数据抽取」**:源可能是 > ① 纯 JSON、② 含 JSON 的文本、③ 纯文本,三种形态都要正确处理。 > > 测试环境:后端 `http://localhost:8001`(`make dev`),前端 `http://localhost:5174`(`pnpm dev`)。 > 相关代码:`deerflow/runtime/scheduler/template_fill.py`(`extract_embedded_json`)、 > `service.py`(`_run_template_fill_attempt` / `_build_conversion_prompt`)、 > `pages/ScheduledTasksPage.tsx`。 --- ## 前置 — 进入表单 | # | 步骤 | 预期结果 | |---|------|----------| | 0.1 | 任务管理 → 新建定时任务 | 弹出「新建定时任务」对话框 | | 0.2 | 「执行智能体」下拉选择 **模板数据转换器** | 表单出现「HTML 模板」下拉;「必须生成 HTML/Markdown」两个开关隐藏 | | 0.3 | 「HTML 模板」下拉选择 **no.1** | 下方出现「上传 .json」按钮 + 源数据文本框;说明含「未提供源 JSON 时,将直接展示该模板的默认数据」| --- ## T1 — 源形态①:纯 JSON | # | 步骤 / 输入 | 预期结果 | |---|------|----------| | 1.1 | 在源数据框粘贴纯 JSON(示例见下「样例 A」) | 文本框正常接收,无报错 | | 1.2 | 保存任务 → 「立即执行」 | 执行记录新增一条,状态最终 succeeded | | 1.3 | 打开执行记录 → HTML 预览 | 渲染出 no.1 大屏,**总览指标/各列表数据来自粘贴的 JSON**(而非模板默认值)| | 1.4 | 执行记录正文 | 文案为「已根据源数据填充模板「no.1」生成页面」| ## T2 — 源形态②:含 JSON 的文本(抽取重点) | # | 步骤 / 输入 | 预期结果 | |---|------|----------| | 2.1 | 粘贴「样例 B」(前后是中文说明,中间夹一段 JSON) | 文本框正常接收 | | 2.2 | 保存 → 立即执行 → 查看 HTML | 页面数据以**夹带的 JSON 为准**填充;正文里的补充说明(如「重点突出 X」)被一并参考 | | 2.3 | 验证抽取正确性:JSON 字符串值里含 `}`(如 `"备注": "进度 80%}尚未完成"`) | 不会被误判为 JSON 块提前结束,整段 JSON 被完整抽取 | ## T3 — 源形态③:纯文本(无 JSON) | # | 步骤 / 输入 | 预期结果 | |---|------|----------| | 3.1 | 粘贴「样例 C」(一段纯中文描述,无任何 JSON) | 文本框正常接收 | | 3.2 | 保存 → 立即执行 → 查看 HTML | 智能体**理解文本语义**后据实填充模板,产出完整可预览页面(数据可能较稀疏但结构完整)| | 3.3 | 不应报「未返回 JSON」类硬失败(除非模型彻底失败重试耗尽)| 状态 succeeded | ## T4 — 空源 → 模板默认数据 | # | 步骤 | 预期结果 | |---|------|----------| | 4.1 | 源数据框留空,保存 → 立即执行 | **不调用模型**,直接用 no.1 模板自带的默认数据生成 | | 4.2 | 执行记录正文 | 「未提供源数据,已用模板「no.1」的默认数据生成页面」| | 4.3 | HTML 预览 | 展示模板内置的默认大屏 | ## T5 — 上传 .json 文件 | # | 步骤 | 预期结果 | |---|------|----------| | 5.1 | 点击「上传 .json 文件」,选一个合法 `.json` | 文件内容被读入源数据文本框 | | 5.2 | 上传一个非法 JSON 内容的文件 | toast 提示「文件不是合法 JSON,已填入文本框请检查」,内容仍填入(可手改)| | 5.3 | 连续上传同一个文件两次 | 第二次仍能触发读取(input 已被重置 value)| ## T6 — no.2(只展示模板) | # | 步骤 | 预期结果 | |---|------|----------| | 6.1 | 「HTML 模板」下拉选 **no.2** | **隐藏**上传按钮与源数据文本框;显示「该模板暂为直接展示已有数据,无需填写」| | 6.2 | 即使之前填过源数据,保存 → 立即执行 | 忽略源数据,**原样输出** no.2 现有页面 | | 6.3 | 执行记录正文 | 「已展示模板「no.2」的现有数据」| ## T7 — 编辑回显 | # | 步骤 | 预期结果 | |---|------|----------| | 7.1 | 对已保存的模板任务点「编辑」 | 「执行智能体」「HTML 模板」「源数据」均正确回显 | | 7.2 | 把模板从 no.1 改成 no.2 再保存 | 切到 no.2 时源数据区即时隐藏;保存后执行走只展示分支 | --- ## 样例数据(可直接复制粘贴到源数据框) ### 样例 A — 纯 JSON ```json { "overview": { "核心指标": [ { "名称": "综合区域", "数值": 7, "单位": "区", "说明": "测试数据" }, { "名称": "组织与单位", "数值": 188, "单位": "个", "说明": "测试数据" } ] }, "regions": [ { "name": "测试区域甲", "scope": "本岛西岸" } ], "equipment": [ { "name_zh": "测试装备X", "category": "无人系统", "status": "列装" } ] } ``` > 预期:总览第一项「综合区域」显示 **7**,「组织与单位」显示 **188**,区域/装备出现「测试区域甲」「测试装备X」。 ### 样例 B — 含 JSON 的文本 ``` 这是本月台海态势数据,请据此填充大屏,重点突出离岛防卫: {"overview": {"核心指标": [{"名称": "综合区域", "数值": 9, "单位": "区", "说明": "含离岛"}]}, "regions": [{"name": "离岛防区", "scope": "外岛", "备注": "进度 80%}尚未完成"}]} 以上数据来自 6 月例会,务必准确,不要臆造未提供的字段。 ``` > 预期:① 数据以中间 JSON 为准(综合区域=9、出现「离岛防区」);② 字符串里的 `}`(`进度 80%}`)不破坏抽取;③ 前后的「重点突出离岛防卫」「务必准确」作为补充说明被模型参考。 ### 样例 C — 纯文本 ``` 请整理一份台湾滨海防卫概览:覆盖本岛沿岸 9 个综合区域,组织与单位约 280 个, 装备条目近百项(含无人系统、防空、海军平台等类别),并列出若干关键节点与近期演习。 数据以离线知识为准,没有的字段留空即可。 ``` > 预期:智能体理解语义后据实填充,产出结构完整的页面(具体数值取决于模型,可较稀疏),不报硬失败。 --- ## 后端单元测试(自动化补充) ```bash # 在 offline-backend-20260512/backend/ 下运行 PYTHONPATH=. uv run --no-sync pytest tests/test_template_fill.py -v # 引擎:抽取/校验/填充/注册表 PYTHONPATH=. uv run --no-sync pytest tests/test_template_fill_attempt.py -v # 调度器执行分支:三形态/默认/只展示/重试 PYTHONPATH=. uv run --no-sync pytest tests/test_template_builder_seed.py -v # 内置 agent 种子 ``` 抽取相关关键用例: - `test_extract_embedded_json_pure_object` / `_pure_array` —— 纯 JSON。 - `test_extract_embedded_json_text_with_json` / `_fenced` —— 含 JSON 的文本 / ```json 围栏。 - `test_extract_embedded_json_plain_text_returns_none` —— 纯文本返回 None。 - `test_extract_embedded_json_ignores_braces_in_strings` —— 引号内 `}` 不误判。 - `test_text_with_embedded_json_surfaced_in_prompt` —— 转换 prompt 单独标注「识别到的结构化数据」。 - `test_plain_text_source_converts` —— 纯文本仍照常转换。 - `test_empty_source_uses_template_default` —— 空源用模板默认数据。 - `test_display_only_template_renders_as_is` —— no.2 原样输出。 三个文件应全部通过(0 failed)。