--- id: T-603 title: ②AI生成封面重置计数与商品ID警示色 phase: 7 deps: [T-511, T-534, T-554, T-566, T-577] status: DONE created: 2026-07-11 --- ## 问题 / 背景 ②AI生成模块里,用户可以通过顶部「重置生成结果」或封面画廊「重置图片」重置某条记录的封面。T-566 已经让重置封面时把旧 `new_cover_path` 归档,因此同一商品后续可能有多张生成图片候选可查看和恢复。 当前缺口是:`tasks` 表里没有“这条记录封面曾经重置过”的业务事实;②列表也只给「标题状态 / 图片状态」上色,商品ID列没有特殊颜色。用户回到列表后,不能直接判断哪些商品可能有多张候选图,需要双击逐条打开画廊确认。 本任务目标:**记录封面重置历史,并在②AI生成列表用商品ID列 warning 色提醒用户“这条商品封面重置过,可能有多张候选图”。** ## 方案 ### 1. DB 增加封面重置历史字段 在 `tasks` 表做兼容迁移,新增字段: - `cover_reset_count INTEGER NOT NULL DEFAULT 0` - `cover_reset_at TEXT` 同步更新: - `SCHEMA_SQL` - 旧库启动时的 ad-hoc 迁移 - `Task` dataclass - row → `Task` 映射 - DB 单测 字段语义: - `cover_reset_count > 0` 表示该商品封面曾经被人工重置过,可能存在多张封面候选图。 - `cover_reset_at` 记录最近一次封面重置时间,用于 tooltip 和诊断。 - 这不是失败状态,也不是待生成状态;它是“有重置历史/可重点查看候选图”的业务标记。 ### 2. 统一在 `db.reset_generated()` 里记录 只在 `reset_cover=True` 且重置前 `before.new_cover_path` 非空时记录封面重置历史: - `cover_reset_count = cover_reset_count + 1` - `cover_reset_at = now` 原因: - 顶部「重置生成结果」和封面画廊「重置图片」都会走 `db.reset_generated()`,统一在这里记录不会漏。 - 如果只重置标题(`reset_title=True, reset_cover=False`),不改 `cover_reset_count`,避免误导用户“有多张图片”。 - 如果任务本来没有 `new_cover_path`,即使传入 `reset_cover=True`,也不增加计数,避免空重置造成误标。 明确不清除: - `db.update_generated_cover()` 不清 `cover_reset_count`。用户从历史候选图保存回当前封面后,这条记录仍属于“曾经重置过/有候选图历史”。 - `db.set_generated()` 新生成封面成功后也不清 `cover_reset_count`。新图成功后更需要保留提示,方便用户知道可打开画廊比较多张候选图。 - 第一版不提供“清除重置历史”入口;后续如果用户需要,可另做独立任务。 ### 3. ②商品ID列语义色 在 `GenerateTaskTableModel.data()` 中增加商品ID列(列 1)的 `Qt.ForegroundRole`: - 若 `task.cover_reset_count > 0`,商品ID显示为 warning/琥珀色。 - 颜色复用 T-511/T-543 语义色板中的 `COLOR_WARNING`,不要新增硬编码颜色。 - 不使用红色;红色保留给失败。 - 不使用绿色;绿色保留给成功。 - 不刷整行背景,避免与失败、选中态、状态列颜色冲突。 tooltip: - 商品ID列若 `cover_reset_count > 0`,显示: - `该商品封面已重置 2 次,可能有多张候选图,双击可查看封面画廊` - 如果同一行还有 `last_error`,商品ID列优先显示封面重置提示;状态列/其它列继续保留原失败 tooltip 即可。 ### 4. 不用扫描候选图数量作为主判断 不要把 `image_paths.list_task_cover_candidates()` 或目录扫描结果作为商品ID变色的唯一依据。 原因: - 图片文件可能被用户移动、清理或被杀毒软件隔离。 - 旧版本路径兼容、归档文件名、业务目录迁移都可能影响扫描稳定性。 - “封面重置过”是业务事实,应该存在 SQLite 里。 可以在未来增强 tooltip 时辅助显示“当前扫描到 X 张候选图”,但本任务第一版只依赖 `cover_reset_count` 决定商品ID颜色。 ## 验收要点 - 重置某条封面后,刷新②AI生成列表,该行商品ID变成 warning/琥珀色。 - 批量重置封面时,多行商品ID都变色。 - 只重置标题时,商品ID不变色。 - 如果任务没有 `new_cover_path`,重置封面不增加 `cover_reset_count`,商品ID不误变色。 - 双击变色商品仍能进入封面画廊查看候选图。 - 从候选图里保存某张图为当前封面后,商品ID仍保持 warning 色,因为它仍有重置历史。 - 重新生成封面成功后,商品ID仍保持 warning 色,提示用户可打开画廊比较候选图。 - 程序重启后颜色仍保留。 - ③更新蝦皮逻辑不受影响;③列表不因为 `cover_reset_count` 改颜色。 - 失败行仍按现有状态列/图片状态列显示 danger;商品ID warning 只表示“封面重置历史”,不是失败。 ## 测试要求 - `tests/test_db.py` - 覆盖新字段 schema 和旧库迁移。 - 覆盖 `reset_generated(reset_cover=True)` 增加 `cover_reset_count/cover_reset_at`。 - 覆盖只重置标题不增加计数。 - 覆盖没有 `new_cover_path` 的空封面重置不增加计数。 - 覆盖 `update_generated_cover()` 和 `set_generated()` 不清除计数。 - `tests/test_gui.py` - 覆盖 `GenerateTaskTableModel` 商品ID列 `Qt.ForegroundRole` 返回 warning 色。 - 覆盖商品ID列 tooltip 显示重置次数和画廊提示。 - 覆盖标题状态/图片状态列原有颜色不回归。 验证命令: ```bash python -m ruff check app tests main.py py -3.10 -m compileall app main.py py -3.10 -m unittest discover -s tests git diff --check ``` ## 边界(不改什么) - 不改 AI/cmhub 请求、并发、重试、下载保存逻辑。 - 不改封面画廊候选图枚举规则。 - 不改 ③更新蝦皮/CDP/Shopee 流程。 - 不新增 Excel 字段,不把重置次数回写 Excel。 - 不新增“只看重置过”筛选。 - 不用目录扫描结果替代 SQLite 业务标记。 - 不让标题重置触发商品ID变色。 ## 执行记录 - 2026-07-11:已完成。 - 代码: - `app/db.py`:`tasks` 新增 `cover_reset_count INTEGER NOT NULL DEFAULT 0` 与 `cover_reset_at TEXT`,补 `init_db()` 兼容迁移、`Task` dataclass 字段和旧库迁移路径。 - `db.reset_generated()`:仅在 `reset_cover=True` 且重置前 `new_cover_path` 非空时累加 `cover_reset_count` 并写最近重置时间;只重置标题、空封面重置不计数。`update_generated_cover()` 与 `set_generated()` 不清除该历史。 - `app/gui/models.py`:② `GenerateTaskTableModel` 商品ID列在 `cover_reset_count > 0` 时使用 `COLOR_WARNING`,tooltip 显示“该商品封面已重置 X 次,可能有多张候选图,双击可查看封面画廊”;标题/图片状态列原有颜色不变。 - 测试: - `tests/test_db.py`:覆盖新字段初始化、旧库迁移、封面重置计数、只重置标题不计数、空封面重置不计数、选择候选图/重新生成后不清除计数。 - `tests/test_gui.py`:覆盖②商品ID列 warning 色、tooltip 和状态列颜色不回归。 - 验证: - 当前主工作区全量 unittest 会被既有未提交默认提示词文件影响(`papa1` 与 `默认.txt` 差异),该问题不属于 T-603。 - 在临时干净 worktree 中仅应用本任务 diff 后验证通过: - `python -m ruff check app tests main.py` - `py -3.10 -m compileall app main.py` - `py -3.10 -m unittest discover -s tests`(338 tests) - `git diff --check` - 主工作区定向验证通过: - `py -3.10 -m unittest tests.test_db` - `py -3.10 -m unittest tests.test_gui.GuiTests.test_generate_table_marks_cover_reset_history_on_item_id_column tests.test_gui.GuiTests.test_generate_table_splits_title_and_cover_statuses_and_widths`