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

87 lines
6.2 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-659
title: 更新蝦皮批次内容预检改为剔除跳过不中止整批
status: DONE
phase: 7
deps: []
created: 2026-07-17
---
# T-659 更新蝦皮批次内容预检改为剔除跳过不中止整批
## 问题 / 背景
③「更新蝦皮」选定批次点「开始更新」时,若批次内有个别记录的新标题或新封面生成失败(内容为空),当前会弹窗「更新内容未生成」并中止**整批**更新——1~2 条失败记录拦下其余全部合格记录。
代码链路(`app/gui/tabs/apply.py`):
1. `_start_update()`(:243)按当前筛选收集候选任务:`_is_update_candidate_task()`(:390)只看 `stage == "generated"` 且 `status ∈ {success, pending, failed}`,**生成失败的记录也在候选内**;
2. `_update_content_error()`(:584)按更新模式检查候选:模式含标题要求 `new_title` 非空、含封面要求 `new_cover_path` 非空,**任何一条缺失**即返回完整错误文案;
3. :256-260 预检非空 → `QMessageBox.warning("更新内容未生成", ...)` → `return`,一条都不执行。
该预检的原始意图是拦「更新模式选错」的整体性错误(如批次只生成了标题、用户却选了标题+封面),但没有区分「全部缺失(模式错)」与「个别缺失(个别生成失败)」。执行层 `ApplyWorker` 本身支持逐条跳过(汇总格式含「略过{skipped}」,:697),预检比执行器更严格,属于门槛过度。
## 需求定稿
预检从「一票中止」改为「剔除 + 知情确认」:
1. 缺少本轮所需内容(按更新模式判定新标题/新封面)的记录,从本轮任务中**剔除**,不进 `ApplyWorker`;
2. 确认弹窗(保留,符合 ③ 开始更新前弹窗确认的红线)中新增跳过说明:缺标题/缺封面的条数与示例商品ID,让用户知情后再确认;
3. 仅当**剔除后无任务可执行**(整批缺失,大概率模式选错)时,保留现有「更新内容未生成」警告中止,并沿用回②生成或调整更新内容的引导文案;
4. 被剔除记录的库内状态、stage、Excel 回写均不变——它们不算本轮失败也不算略过,修复(②补生成)后下轮自然重新入选。
## 实现方案
- `_update_content_error()` 重构为返回结构化结果(如「可执行任务列表 + 缺标题列表 + 缺封面列表」),或新增并列函数;不再以「有缺失」为中止条件。
- `_start_update()`:
- 剔除后可执行任务 > 0:把跳过统计并入 `_confirmation_message()`(新增行如「跳过 N 条缺少新标题(示例商品ID:…)」),確認后仅以可执行任务创建 `ApplyWorker`;
- 剔除后为 0:维持现「更新内容未生成」`QMessageBox.warning` 中止,文案不变;
- 「检查本轮更新」(dry_run)与正式更新走同一套剔除逻辑,两者展示一致的跳过说明。
- 状态栏摘要同步:本轮开始时记录「本轮 N 条,跳过 M 条(缺标题 x / 缺封面 y)」。
- 不修改 `ApplyWorker`、CDP 流程、批次/店铺筛选、Excel 回写和 `_is_update_candidate_task()` 的候选口径(failed 状态保留在候选中是为了重试上轮更新失败的记录,与本问题无关)。
## 验收标准
- [ ] 批次内 1~2 条缺新标题/新封面时,点「开始更新」不再中止:确认弹窗列出跳过条数与示例商品ID,确认后其余记录正常执行。
- [ ] 跳过的记录不进入本轮执行,也不被计为本轮失败或略过;其库内状态与 Excel 不受本轮影响。
- [ ] 整批全部缺失所需内容时,仍弹「更新内容未生成」警告并中止,引导文案与现版一致。
- [ ] 「检查本轮更新」(dry_run)与正式更新的剔除与提示行为一致。
- [ ] 更新模式为「只更新标题」时只按新标题剔除;「只更新封面」只按新封面剔除;「标题和封面」按两者分别统计并都剔除。
- [ ] 确认弹窗仍在执行前出现(③ 红线不变);取消则不执行任何任务。
- [ ] 被跳过记录在②补生成后,下轮筛选自动重新入选并可正常更新。
- [ ] CDP 执行、批次筛选、店铺筛选、停止/重置更新、Excel 回写行为不变。
## 测试要求
- `tests/test_gui.py`(既有「更新内容未生成」用例所在文件)覆盖:部分缺标题、部分缺封面、两者混合、全部缺失中止、剔除后确认文案内容、dry_run 一致性、三种更新模式的剔除口径。
- 断言跳过记录未进入 worker 任务列表、状态与 stage 未被改动。
- 回归:无缺失时确认文案与现版一致(不出现跳过行)。
## 文档同步
- 实现时更新 `docs/04-architecture.md` 中 ③ 更新前置校验的描述(如有);不修改冻结的 `docs/06-tasks.md`。
## 验证
```bash
py -3.10 -m unittest tests.test_gui
py -3.10 -m unittest discover -s tests
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check
```
## 非目标
- 不修改 ②AI生成的失败重试机制,不在③内触发补生成。
- 不修改 `ApplyWorker` 执行语义、并发、批次大小与账号就绪检查。
- 不改动「账号未就绪」中止逻辑(那是另一类整体性前置条件)。
- 不引入按记录勾选/排除的手动选择 UI。
## 执行记录
- 2026-07-17:`ApplyTab` 新增按更新模式划分可执行任务、缺少新标题任务和缺少新封面任务的预检;有可执行任务时只将其交给 `ApplyWorker`,缺失记录不改 SQLite、Excel 或运行状态。
- 2026-07-17:正式更新和「检查本轮更新」共用该预检;确认框显示跳过条数、缺失类型和示例商品ID,状态栏与本轮日志显示可执行/跳过摘要。全部任务都缺失时仍沿用「更新内容未生成」弹窗中止。
- 2026-07-17:补充三种更新模式的剔除口径、正式更新部分跳过和检查模式部分跳过回归测试;同步架构、API 和界面流程文档。
- 验证通过:`py -3.10 -m unittest tests.test_gui`(190 项)、`py -3.10 -m unittest discover -s tests`(591 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。离屏 GUI 测试有 Qt 字体/插件告警,但无测试失败。