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

96 lines
8.8 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.
---
id: T-628
title: 采集当前记录阶段与单条耗时指示器
phase: 2
deps: [T-620]
status: DONE
created: 2026-07-14
---
## 问题 / 背景
①「导入采集」处理商品详情页时,打开页面、等待加载和下载封面都可能持续较长时间。当前页面只有静态的「批次进度」汇总、底部状态栏和运行日志,用户在一条记录长时间未结束时难以判断采集是否仍在执行。
已核实的现状:
- `collectBatchProgressOverview` 是根据 SQLite 任务快照生成的汇总 label,`refresh_tasks()` 时会整体重写文本,本身没有运行计时语义。
- `CollectWorker.progress` 主要在一条记录结束后发出,不能反映当前记录正在执行哪个步骤。
- `row_updated(status=running)` 在单条记录登录状态检查之后才发出;若以它作为计时起点,会漏掉前置检查和本条登录检查耗时。
- `editor.collect()` 已有 `open_product / wait_ready / read_title / read_cover / download_cover` 等步骤回调,可作为结构化阶段来源。
顾客希望在「批次进度」同行右侧增加动态计时,并在每条记录开始时重置,让用户能看到当前采集任务仍处于运行状态。
计时数字持续变化只能证明 GUI 计时器仍在运行,不能证明 CDP 一定在继续推进。因此本任务把需求优化为「**当前阶段 + 当前记录耗时**」指示器:阶段显示最后一次已知进展,秒数显示该记录已经等待多久,不向用户承诺任务一定健康。
## 方案
### 1. 批次进度同行增加独立运行指示器
- 在现有「批次进度」右侧增加独立 label,不把计时字符串拼入 `batch_progress_label`,避免 `refresh_tasks()` 重写批次汇总时覆盖计时内容。
- 两个 label 放入同一水平布局:批次汇总占可伸缩区域,运行指示器靠右并按最长合理文案预留稳定宽度,秒数变化不得造成布局抖动。
- 运行中推荐文案:`正在采集 3/20 · 等待商品页加载 · 本条 00:18`。
- 窗口空间不足时,允许批次汇总自然换行;运行状态、序号和时间必须保持可见,完整商品 ID / 账号可放在中文 tooltip 中,不在紧凑 label 内强行堆叠。
- 不使用纯装饰性转圈或闪烁动画;每秒变化的计时和明确的「正在采集」文字即为运行反馈。
### 2. 使用结构化 Worker 活动信号
- 为 `CollectWorker` 增加专用结构化活动信号,例如 `activity: Signal(dict)`;不得通过解析用户日志文本推断当前任务或步骤。
- 活动 payload 至少支持:
- `preflight_started`:开始检查账号和 Chrome;
- `task_started`:一条 eligible 记录开始处理;
- `task_step`:当前记录进入新步骤;
- `task_finished`:当前记录成功、失败或略过。
- payload 使用稳定字段,如 `state / index / total / task_id / item_id / alias / step / result`,不得把账号密码、Cookie、token 或未脱敏异常放入信号。
- `task_started` 应在进入每条记录处理循环后尽早发出,覆盖本条账号匹配、登录检查和后续采集耗时;不得等到 `db.mark_running()` 后才开始计时。
- `editor.collect()` 的步骤回调继续用于日志,同时把步骤作为结构化 `task_step` 发给 GUI。阶段映射集中维护并全部显示中文,至少覆盖:检查账号、打开商品页、等待商品页加载、读取标题、读取封面、下载封面、保存采集结果。
- 结构化活动信号只增加可观察性,不改变原有 `progress / row_updated / log / failed / finished / cancelled` 的业务语义。
- 本轮正常完成、停止和前置阻断继续以现有 `finished / cancelled` 信号及 summary 中的 `blocked` 字段为唯一终态来源,不在 `activity` 中复制一套终态协议。
### 3. 计时口径与生命周期
- GUI 使用父对象为 `CollectTab` 的 `QTimer`,每 1000ms 刷新一次;真实耗时通过 `time.monotonic()` 计算,不通过简单 `seconds += 1` 累加。
- 点击「采集旧标题/旧封面」并成功创建 Worker 后,记录批次开始时间,显示 `正在检查账号 · 00:00`。
- 收到 `task_started` 时重置当前记录起点并开始显示 `本条 00:00`;收到 `task_step` 只更新阶段文字,不重置本条计时。
- 下一条记录开始时重新从 `00:00` 计时;成功、失败或略过可短暂冻结本条耗时,随后由下一条 `task_started` 覆盖。
- 用户点击「停止」后,指示器立即改为 `正在停止 · 本条 00:18`,在当前不可中断步骤退出前继续显示等待时间;收到 `cancelled` 后再冻结为终态,不能提前伪装成已经停止。
- 正常完成、前置检查阻断、用户停止、Worker 异常及线程释放路径都必须停止 QTimer、清理当前任务引用并冻结最终文字,不能在采集结束后继续走秒。
- 本轮终态文案应区分:
- 正常完成:`采集完成 · 总用时 08:32`;
- 用户停止:`采集已停止 · 总用时 03:10`;
- 前置阻断:`采集未开始 · 检查未通过`;
- 异常结束:`采集已结束 · 请查看运行日志`。
- 计时只用于本次 GUI 显示,不写入 SQLite 或 Excel;现有逐条诊断日志中的 `elapsed_ms` 保持不变。
### 4. 状态语义与视觉边界
- 运行中使用现有信息色/进行中色,并保留「正在采集」文字,不能只靠颜色表达状态。
- 完成、停止、阻断和异常沿用项目既有状态语义色;不增加“卡死”自动判定。页面加载和图片下载可能合法地持续较久,仅凭固定秒数变色会产生误报。
- 用户看到持续增加的本条耗时,应理解为“该记录尚未结束”;阶段长时间不变化时可据此决定查看日志或停止,但 UI 不显示“运行正常”等未经验证的结论。
## 验收要点
- 有批次任务但未运行时,批次汇总显示正常,右侧运行指示器不误报正在采集。
- 点击采集后,在首条记录开始前显示中文前置检查状态和持续计时;GUI 保持可响应。
- 第一条记录开始时显示 `1/N` 并从 `00:00` 计时;步骤变化时阶段文字变化、本条计时不重置。
- 第二条记录开始时显示 `2/N`,本条时间重新从 `00:00` 开始。
- 成功、失败和略过记录都能进入正确的下一条计时;不会因为某条失败而停止整轮指示器。
- 正常完成、前置阻断、用户停止、Worker 异常和线程收尾后计时全部停止,等待数秒后界面秒数不再变化。
- 批次进度汇总刷新不会覆盖运行指示器;运行指示器更新也不会改变批次阶段统计。
- 运行状态 label 宽度稳定,在最小支持窗口及 Windows 100% / 125% / 150% 显示缩放下无重叠和明显布局跳动。
- 单测使用可控 `time.monotonic()` 或注入时间验证,不通过真实 `sleep()` 拉长测试。
- 自动验证:`py -3.10 -m unittest discover -s tests`、`python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check` 全绿。
## 边界(不改什么)
- 不修改 CDP 选择器、商品页打开/关闭策略、Chrome 前后台切换、登录判定或采集重试策略。
- 不修改任务 `stage/status`、SQLite schema、Excel schema、回写流程或批次统计口径。
- 不把计时器放进 Worker 线程,不让 GUI 每秒查询 SQLite,也不把每秒 tick 写入运行日志。
- 不改变②AI生成、③更新蝦皮及⑥商品套图的计时显示。
## 执行记录
- 2026-07-14:`CollectWorker` 新增独立 `activity` 结构化信号,在前置检查、每条记录开始、采集步骤变化及单条结束时发送稳定 payload;每条记录进入循环即发 `task_started`,登录检查和 `editor.collect()` 步骤只更新阶段,不改变原有进度、日志、状态写库和终态信号。
- 2026-07-14:①「导入采集」在批次进度同行右侧新增固定宽度运行指示器,显示前置检查、`N/总数`、当前中文阶段和本条 `MM:SS`;基于 `time.monotonic()` 每秒刷新,每条开始重置,步骤变化不重置,停止请求期间继续显示实际等待,完成、阻断、停止和异常后冻结中文终态。
- 2026-07-14:新增 Worker 活动事件顺序和 GUI 计时生命周期测试,覆盖三条记录的成功/略过事件、步骤不重置、下一条归零、停止等待、终态冻结、小时格式及中文 tooltip;用户可见终态不展示底层英文异常。
- 验证:当前工作区全套 GUI 测试除任务开始前已存在的默认封面提示词 `papa1.txt` 改名造成的 2 项旧断言外,采集相关测试全部通过;在仅覆盖 T-628 四个文件的隔离 worktree 中运行 `python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`py -3.10 -m unittest discover -s tests`(461 项通过)及 `git diff --check`,结果全部通过。