docs: add product suite generation history tasks

This commit is contained in:
chengma
2026-07-16 21:08:29 +08:00
parent 75af87d441
commit c146c0b41d
2 changed files with 284 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
---
id: T-643
title: 商品套图持久化当前生成轮次
phase: 7
deps: [T-642]
status: TODO
created: 2026-07-16
---
## 问题 / 背景
⑥「商品套图」当前把 `SuiteTaskState.current_job_ids` 作为“本轮结果”的唯一依据。该字段只存在于 GUI 内存中:
- 软件重启、关闭任务后重新输入商品 ID,无法恢复上次正在使用的一轮生成结果;
- `image_studio_jobs` 只有单张生成 job,没有持久化的轮次和槽位字段;
- 「历史生成」当前只能把当前项目全部 job 混在同一个结果网格中,无法可靠区分整轮生成、单张失败重试和更早历史;
- 如果直接隐藏「历史生成」,已有项目重新打开后可能显示“还没有生成结果”,但数据库和本地图片实际仍然存在。
产品目标是:每个店铺商品项目在主界面默认只展示一轮“当前结果”,同时保留以前的 job、图片、错误和计费记录,供后续历史弹窗查看。不能通过创建时间间隔、文件夹名称或图片数量猜测轮次。
## 方案
### 1. 为生成 job 增加持久化轮次与槽位
修改 SQLite schema、迁移和 `app/image_studio.py` 数据模型:
- `image_studio_projects` 增加可空 `current_generation_round_key`,表示主界面当前使用的生成轮次;
- `image_studio_jobs` 增加 `generation_round_key`,同一次整轮生成创建的 job 使用同一个不可复用 UUID;
- `image_studio_jobs` 增加 `generation_slot_index`,按本轮生成规格顺序从 0 开始稳定编号;
- 为 `(project_id, generation_round_key, generation_slot_index, id)` 增加适合查询当前槽位和历史轮次的索引;
- 数据类、建库和增量迁移同步兼容旧数据库。
不把 GUI `run_token` 直接作为长期业务主键。轮次 key 可以在本轮开始时由 GUI 创建并传给 worker,但持久化语义是“生成轮次”,不承担迟到信号隔离职责。
### 2. 整轮生成创建新轮次
修改 `app/gui/tabs/product_suite.py`、`app/gui/workers.py` 和生成服务调用:
- 正常点击「生成套图」时创建新的 `generation_round_key`;
- worker 创建每条 job 时同时写入该轮次 key 和稳定槽位;
- 活动运行仍使用现有 `generation_run_token` 做线程/迟到信号隔离,不改变 T-639/T-640 的终态看门狗;
- 当前会话内继续用 `current_job_ids` 实时展示本轮 job,避免等待整轮完成后才显示;
- 本轮至少有一个成功结果时,把项目 `current_generation_round_key` 原子更新为新轮次;
- 本轮全部失败、全部取消或未创建有效结果时,保留原来的当前轮,失败轮仍进入历史记录;
- 部分成功时允许新轮成为当前轮,主界面保留成功和失败槽位,用户可继续按 T-640 单张重试。
切换当前轮不得删除、覆盖或改写旧轮次 job、计费、错误和输出资产。
### 3. 单张重试留在原轮次和原槽位
T-640 的单张失败重试继续新建 job,但必须:
- 继承原 job 的 `generation_round_key`;
- 继承原 job 的 `generation_slot_index`;
- 当前轮每个槽位默认取该轮次、该槽位最新创建的 job;
- 重试成功、再次失败或取消都只替换该槽位在主界面的当前版本,其他槽位和轮次不变;
- 原失败 job 和每次重试 job 全部保留,供历史详情和问题审计使用。
成功图片的主动“重新生成”若后续开放,也必须明确是替换当前槽位还是新增变体;本任务不扩大该入口。
### 4. 已有项目和旧版 job 兼容
旧数据库中的 job 没有可靠的轮次边界,不得按时间差或图片数量猜测:
- 迁移后旧 job 使用明确的 `legacy` 兼容轮次语义,或保持空值并由查询层统一映射为“旧版历史记录”;
- 若项目只有旧版 job、没有新格式当前轮,主界面可以临时展示“旧版历史记录”,避免用户误以为图片丢失;
- 用户完成下一次新格式整轮生成后,项目切换到新轮次,旧 job 只在历史记录中展示;
- 文件缺失时保留 job/asset 记录并显示不可用状态,不自动删除历史。
### 5. 当前结果查询与恢复
在 `app/image_studio.py` 提供结构化 API:
- 设置或读取项目当前轮次;
- 按项目列出生成轮次摘要;
- 按轮次和槽位读取当前有效 job;
- 按轮次读取全部尝试记录,供 T-644 历史弹窗使用。
商品项目绑定、草稿恢复、任务切换和软件重启后:
- 从项目持久化的当前轮次恢复 `current_job_ids`;
- 按槽位顺序展示,不使用 `updated_at` 排序打乱图片位置;
- 当前轮不存在、job 被软删除或图片文件缺失时给出稳定空态/缺失态,不抛出裸英文错误;
- `generation_job_ids` 仍只表示当前活动请求,不从历史轮次恢复。
### 6. 数据一致性和诊断
- 设置当前轮次、读取轮次槽位和单张重试替换必须校验 project/job 归属;
- 不允许把其他账号、商品项目或草稿项目的轮次设为当前轮;
- 当前轮 key、job 数量、成功/失败数量可写诊断日志,不记录提示词全文、图片 URL、密钥或 Cookie;
- schema 变化同步更新 `docs/04-architecture.md`、`docs/api.md` 和 `docs/routes.md`。
## 验收要点
- [ ] 商品完成一轮生成后,关闭软件并重新打开相同店铺和商品 ID,主结果区恢复同一轮、同一顺序的图片。
- [ ] 再生成一整轮后,主界面只展示新当前轮,旧轮 job、图片、错误和计费记录仍保留。
- [ ] 新轮全部失败或全部取消时,原当前轮继续显示;失败轮可以被历史查询读取。
- [ ] 新轮部分成功时切换为当前轮,成功和失败槽位均可见,失败槽位可继续单张重试。
- [ ] 单张失败重试沿用原轮次和槽位,其他当前图片不消失、不换序。
- [ ] 程序重启后重试结果仍占据原槽位,原失败 job 仍存在。
- [ ] 旧数据库可以自动迁移;旧 job 不被猜测性拆分、删除或覆盖。
- [ ] 当前轮和历史轮查询不会跨店铺、跨商品或跨项目串数据。
- [ ] 不影响生成停止、迟到信号隔离、恢复未完成 cmhub 任务和本地图片保存。
## 测试
- `tests/test_db.py`:
- 新建数据库字段与索引;
- 旧数据库增量迁移;
- 重复初始化幂等。
- `tests/test_image_studio.py`:
- 当前轮设置/读取和项目归属校验;
- 轮次摘要、槽位当前 job、全部尝试查询;
- 旧版 job 兼容。
- `tests/test_workers.py`:
- 整轮 job 写入相同轮次和稳定槽位;
- 单张重试继承轮次和槽位。
- `tests/test_product_suite_gui.py`:
- 项目重新绑定和重启恢复当前轮;
- 新轮成功、部分成功、全失败/取消时的当前轮切换;
- 单张重试跨重启保持槽位。
- 运行:
```bash
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
```
## 边界(不改什么)
- 不删除旧轮次 job、生成图片、错误、扣点或余额记录。
- 不通过扫描目录、文件名、时间差或图片数量猜测轮次。
- 不在本任务实现历史弹窗、历史图片删除或“恢复历史轮为当前轮”。
- 不修改 cmhub API、模型别名、提示词组装、并发、超时、轮询和下载协议。
- 不修改 CDP、蝦皮主图拉取、①导入采集、②AI生成、③更新蝦皮、④账号管理或⑤设置。
## 执行记录
- 待执行。