Files
cmshoppe/docs/tasks/T-552.md
T

5.2 KiB
Raw Blame History

id, title, phase, deps, status, created
id title phase deps status created
T-552 任务失败原因带上失败步骤(①②③ 阶段/状态列可见) 7
T-207
T-523
DONE 2026-07-08

问题 / 背景

①导入采集(及②③)列表里任务失败时,阶段/状态列只显示「失败」,操作员看不出卡在哪一步(打开商品页 / 页面就绪 / 读标题 / 读封面 / 下载封面 / 写库 / 回写Excel)。

  • 失败步骤信息其实已被采集:T-207 把 step=preflight/open_product/wait_ready/read_title/read_cover/download_cover/db_write/excel_write_back 记进了 run_log_events。
  • 但 db.mark_failed(task_id, phase, error) 里 phase 只是粗粒度(collect/generate/apply),error 只是原始消息;tasks.last_error 不含步骤。
  • ① 阶段列的 tooltip 已经在显示 last_error,但只有消息、没有步骤 → 要知道哪步得去翻「采集运行日志」逐条对,摩擦大。

这是"数据有、但没暴露在失败发生处"的可见性问题,不是要重新采集数据。

方案(P0:prepend 步骤到 last_error,最小改动)

让失败的 last_error 带上中文步骤,例如「读封面失败:图片超过大小上限」「打开商品页失败:CDP 端口无响应」。

  • worker(app/gui/workers.py 的 CollectWorker,及②③对应 worker):失败时 worker 已知当前 step(T-207 在逐任务追踪),把该 step 传给失败写库。
  • db(app/db.py mark_failed):把中文步骤 prepend 到 last_error(不改 schema),存成 「<步骤中文>失败:<原因>」;step 已是中文/已知失败步骤时避免重复前缀。
  • step→中文映射(放一处共用,如 worker 或 db helper):preflight→预检 / open_product→打开商品页 / wait_ready→页面就绪 / read_title→读标题 / read_cover→读封面 / download_cover→下载封面 / db_write→写库 / excel_write_back→回写Excel;未知 step 用原值兜底。
  • 展示:①②③ 的阶段/状态列 tooltip 已显示 last_error(含步骤后即自动可见);阶段列文案可选显示「失败·<步骤>」(能从 last_error 派生就派生,不额外加列)。
  • 三个模块共用同一套 step→中文 + prepend 逻辑,一次覆盖①②③"失败看不出哪步"。

备注:更结构化的做法是新增 tasks.last_error_step 字段(便于阶段列内联显示/上色),但需 schema 迁移;本任务按 P0 走 prepend,last_error_step 作为后续可选增强,双击看完整步骤链(run_log_events 按 task_id 过滤)也作为后续 P1。

验收要点

  • 采集/生成/更新任一步失败后,tasks.last_error 以「<中文步骤>失败:<原因>」开头。
  • ①②③ 失败行悬停 tooltip 能看到"是哪一步失败 + 原因",无需翻运行日志。
  • step→中文映射覆盖上述所有步骤,未知 step 不崩、用原值。
  • 已带步骤前缀的 error 不重复加前缀。
  • 单测:tests/test_db.py 断言 mark_failed 带 step 时 last_error 前缀正确、无 step 时保持原样;tests/test_gui.py 断言失败行 tooltip 含步骤文案(至少①覆盖,②③视改动补充)。

边界(不改什么)

只改 mark_failed 的 step 前缀 + worker 传 step + 模型 tooltip/阶段文案 + 单测;不改采集/生成/更新执行流程、run_log_events 结构(T-207 保留)、CDP/Shopee 交互、Excel、DB schema(P0 不加字段)。

执行记录

  • 2026-07-08:完成 T-552。
  • 代码:app/db.py 新增 FAILURE_STEP_LABELS、failure_step_label()、format_failure_error();mark_failed() 与 set_applied() 增加可选 step 参数,带 step 时把 last_error 统一保存为「<中文步骤>失败:<原因>」,无 step 时保持旧行为,已带步骤前缀时不重复添加。
  • 代码:①CollectWorker 采集失败时把当前 step 传给 mark_failed,并立即向 GUI 发出带步骤前缀的 last_error;②app/ai.py 的生成失败写库传入当前 title/cover step;③ApplyWorker 更新失败和异常失败传入当前 step 给 set_applied,默认归因为 apply_task,真实编辑器步骤仍由 on_step 覆盖。
  • 展示:①②③ 表格模型原本 tooltip 已读取 last_error,因此失败行悬停可直接看到失败步骤与原因;未新增列、不改 DB schema、不改 run_log_events。
  • 测试:tests/test_db.py 覆盖 mark_failed 带 step 前缀、未知 step 兜底、重复前缀不叠加、无 step 保持原样,以及 set_applied 更新失败 step 前缀;tests/test_gui.py 覆盖①②③失败行 tooltip 显示步骤与原因,并更新③ worker 失败原因断言。
  • 验证:py -3.10 -m unittest discover -s tests -p "test_db.py" 通过(9 tests);py -3.10 -m unittest discover -s tests -p "test_gui.py" 通过(104 tests);py -3.10 -m unittest discover -s tests -p "test_ai.py" 通过(40 tests);python -m ruff check app tests main.py 通过;python -m ruff check scripts\gen_task_board.py tests\test_task_board.py 通过;py -3.10 -m compileall app main.py 通过;py -3.10 -m py_compile scripts/gen_task_board.py 通过;git diff --check 通过;py -3.10 -m unittest discover -s tests 通过(257 tests)。