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

100 lines
5.9 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-567
title: ②封面画廊基础:候选图查看、单选保存、原图弹窗
phase: 7
deps: [T-566]
status: DONE
created: 2026-07-09
---
## 问题 / 背景
运营需要在软件内对比同一商品多次 AI 生图的候选,并把其中一张设为当前生效封面。当前②列表双击打开的「封面对照」弹窗只显示旧封面 + 当前新封面各一张,无法看到历史候选,也不能保存选中的历史图。
T-566 已提供数据层能力:重置封面时归档旧图、`db.update_generated_cover()` 切换当前封面指针、`image_paths.list_task_cover_candidates()` 枚举候选图。本任务只做 GUI 第一阶段:画廊查看 + 单选保存 + 原图弹窗。
## 方案(改哪个文件、改成什么)
### `app/gui/tabs/generate.py` — 重构封面对照弹窗
- 将现有 `show_task_images` 改为封面画廊弹窗(可拆成独立 `QDialog` 类,如 `CoverGalleryDialog`)。
- 布局:
- 左侧保留「旧封面」参照,推荐缩略图约 `300x300`;
- 右侧为候选画廊:横向 `QScrollArea`,每个候选项包含缩略图、`QRadioButton`、时间/当前标记;
- 底部按钮第一阶段只保留「保存」「取消」;不做「重新生成」「上一条/下一条」。
- 尺寸:
- 默认 `resize(min(960x580, 屏幕 availableGeometry 的 90%))`;
- 不用 `setFixedSize()`,拉伸增量给画廊区域;
- 小屏下窗口标题栏必须完整可见。
### 候选加载与默认选中
- 打开弹窗时调用 T-566 `list_task_cover_candidates(image_root, task, account)` 现场扫目录。
- 默认选中 = DB 当前 `task.new_cover_path` 指向的文件;不是无条件选最新。
- 如果 DB 当前路径不存在但候选列表不空:
- 默认不自动改库;
- 画廊显示候选但不预选,状态 label 提示“当前生效封面文件不存在,请选择一张后保存”。
- 如果无候选图:
- 右侧显示空状态“暂无生成封面图片”;
- 「保存」置灰。
- 缩略图加载必须用 `QImage` 读入内存后转 `QPixmap`,不长期持有文件句柄,避免后续重置/重生时 Windows 文件锁影响归档改名。
### 保存
- 选中项与 DB 当前 `new_cover_path` 相同:直接关闭。
- 选中项不同:调用 `db.update_generated_cover(task_id, selected_path)`;刷新②列表该行;关闭弹窗。
- 若该任务 `committed=1` 或 `stage='applied'`,保存前必须弹确认:
- 文案说明“本地换封面不会回滚蝦皮,重复更新会再次提交线上”;
- 用户取消则不写库、不关闭。
- 保存失败(文件不存在、DB 错误等)应弹中文错误并保留弹窗,不吞异常。
### 原图弹窗
- 双击任一候选缩略图打开原图弹窗:
- `QDialog + QScrollArea` 展示原始尺寸图片;
- 窗口最大不超过屏幕 availableGeometry 的 90%,超出可滚动;
- 标题显示图片文件名和原始分辨率,如 `1024x1024`。
## 验收要点
- 双击②任务列表仍能打开封面查看入口;旧封面仍作为参照显示。
- 画廊列出该任务全部 `_new*` 候选,不显示 `_old`。
- 默认选中 DB 当前 `new_cover_path`;DB 当前路径缺失时不自动改库。
- 选择另一张并保存会调用 `db.update_generated_cover()`,②列表新封面路径刷新;未变更直接关闭。
- 已提交线上任务保存前弹二次确认;取消不写库。
- 双击缩略图可打开原图弹窗,超出屏幕可滚动,标题含分辨率。
- 缩略图加载不持文件句柄;Windows 下打开画廊后仍可重命名候选文件。
- 验证命令(unittest,不引入 pytest):
- `py -3.10 -m unittest tests.test_gui tests.test_db tests.test_image_paths`
- `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`
## 边界(不改什么)
- 不做单任务重新生成(T-568)。
- 不做上一条/下一条切换和未保存三态拦截(T-569)。
- 不改 T-566 的数据层契约。
- 不改 `GenerateWorker`、`generate_batch`、cmhub 请求链路。
- 不改 ③更新/Excel 回写/CDP/Shopee。
## 执行记录
- 2026-07-09 完成 T-567。
- 修改 `app/gui/tabs/generate.py`:
- 将②任务列表双击封面查看入口重构为 `CoverGalleryDialog`,左侧显示旧封面参照,右侧横向滚动画廊显示该任务全部 `_new*.jpg` 候选。
- 画廊打开时调用 T-566 的 `image_paths.list_task_cover_candidates()` 现场扫描目录;默认选中 DB 当前 `new_cover_path`,当前路径缺失时不自动改库并提示选择后保存;无候选时显示空状态并禁用保存。
- 保存时未变更直接关闭;变更时调用 `db.update_generated_cover()`,保存成功后刷新②任务列表。已提交线上任务保存前弹中文二次确认,说明本地换封面不会回滚蝦皮、重复更新会再次提交线上。
- 缩略图和旧封面预览统一用 `QImage` 读入内存后转 `QPixmap`,不长期持有文件句柄;候选缩略图双击打开 `OriginalImageDialog` 原图弹窗,标题显示文件名与原始分辨率,超出屏幕时可滚动。
- 修改 `app/gui/widgets.py`:补充 `QImage`、`QButtonGroup`、`QRadioButton` 聚合导入,供画廊弹窗使用。
- 修改 `tests/test_gui.py`:
- 覆盖候选图展示和 `_old` 过滤、当前封面默认选中、打开画廊后候选文件可重命名、保存切换当前封面、已提交任务取消确认不写库、当前路径缺失/无候选提示和禁用保存、原图弹窗分辨率标题。
- 验证通过:
- `py -3.10 -m unittest tests.test_gui`
- `py -3.10 -m unittest tests.test_gui tests.test_db tests.test_image_paths`
- `python -m ruff check app tests main.py`
- `py -3.10 -m compileall app main.py`
- `py -3.10 -m unittest discover -s tests`(290 tests;PySide6 字体目录警告不影响结果)
- `git diff --check`