--- id: T-648 title: 商品套图已有成功历史时确认新一轮生成 phase: 7 deps: [T-643, T-646] status: DONE created: 2026-07-17 --- ## 问题 / 背景 ⑥「商品套图」当前每次正常点击「生成套图」都会新建一个 `generation_round_key`。即使该商品已经有成功生成的套图,用户仍可能在未意识到已有可用结果的情况下再次提交生图并产生新的费用。 现有的本轮费用确认只能说明即将发起的请求,不能说明该商品是否已有成功历史。用户需要在开始一轮正常新生成前,明确看到已有结果,并能先查看历史、继续创建新一轮,或取消操作。 单张失败图片的「重试」、恢复未完成任务和仅失败/已取消的历史不应触发该提醒;它们不是用户主动开始一轮全新生成的场景。 ## 方案 ### 1. 以 SQLite 生成历史作为唯一判据 在 `app/image_studio.py` 或与现有生成轮次查询相邻的服务层增加结构化查询/摘要能力: - 按当前 `project_id` 查询是否存在至少一轮有成功输出的历史;“成功”以持久化 job / asset / 轮次终态事实判断,不扫描 `generated` 目录、文件名、创建时间或缩略图数量; - 摘要至少提供成功历史轮数、成功图片数和最近成功时间,供确认框显示;兼容已有的旧版历史记录,只要可确认存在成功输出就纳入提醒; - 只有失败、取消、未开始或没有有效成功输出的历史不提醒;软删除项目不进入普通生成流程; - 查询不得修改当前轮标记、job、asset、项目、文件或生成状态,也不能把历史图片重新提升为当前结果。 ### 2. 正常生成前增加一次明确决策 修改 `ProductSuiteTab.start_generation()` 及必要的对话框协作逻辑: - 只在用户发起的正常整轮生成(非 `retry_job_id` 单槽位重试、非恢复未完成任务、非运行中的停止操作)中检查成功历史; - 在已完成当前项目、原图、提示词、规格等基础校验后、既有本轮费用确认前,显示中文模态框: - 标题为「已有套图生成记录」; - 正文显示当前店铺/商品、已成功轮数和图片数,并明确“继续会创建新一轮生成,历史结果会保留”; - 操作固定为「查看历史」「继续生成新一轮」「取消」,默认焦点和关闭行为为「取消」; - 选择「查看历史」时打开/聚焦 T-646 的全局历史窗口,并临时启用“仅当前商品”筛选;不启动生成 worker、不创建新轮次,也不改变顶部「历史生成」按钮默认查看全部商品的行为; - 选择「继续生成新一轮」后才进入现有费用确认。确认费用后沿用现有流程生成新的 `generation_round_key`;历史轮次、当前已有结果、job 和 asset 必须保留; - 取消、关闭确认框、查看历史后关闭窗口均不得启动生成;继续路径必须有显式的一次性意图/回调控制,不能依赖按钮文字或产生重复提醒、重复费用确认、重复轮次; - 所有用户可见文案使用中文,不显示完整图片路径、接口 URL、模型别名、Key 或上游错误。 ### 3. 保持既有生成和历史边界 - 当前正常生成的规格校验、费用确认、并发、取消、任务恢复、计费、图片保存和最终状态语义保持不变; - 单张失败后点击「重试」继续沿用原轮次与槽位,绝不因为本任务被拦截为“新一轮”; - 「查看历史」只读,不提供从历史直接重跑、恢复历史为当前轮、删除历史或修改历史资产的能力; - 同步更新 `docs/04-architecture.md`、`docs/api.md`、`docs/routes.md` 中生成轮次与历史入口的交互语义。 ## 验收要点 - [ ] 当前商品存在至少一轮成功套图历史时,正常点击「生成套图」会先出现中文确认框。 - [ ] 确认框准确显示当前商品与成功历史摘要,并说明继续会创建新轮次且保留旧结果。 - [ ] 点击「查看历史」打开全局历史窗口且仅当前商品筛选生效;此路径不创建轮次、不提交 cmhub 请求。 - [ ] 点击「继续生成新一轮」后仍出现原有本轮费用确认;最终确认后创建新的 `generation_round_key`,旧轮次及图片保持可查看和可导出。 - [ ] 点击取消、关闭框或从查看历史返回后,不启动 worker、不扣点、不创建 job/asset/轮次。 - [ ] 单张失败重试、恢复未完成任务、仅失败或仅取消的历史不会触发该确认框。 - [ ] 反复点击继续或快速操作不会重复弹框、重复费用确认、重复创建轮次或并发启动多个同轮 worker。 - [ ] 不影响 AI帮写、提示词、商品原图、全局历史、导出、cmhub 调用、Shopee CDP、采集、AI生成、更新蝦皮、账号管理或设置。 ## 测试 - `tests/test_image_studio.py`: - 成功正常轮次和可确认成功的旧版历史会返回成功历史摘要; - 仅失败、仅取消、空历史、软删除项目不触发摘要; - 摘要不会依赖或扫描本地生成目录。 - `tests/test_product_suite_gui.py`: - 正常生成会按条件显示确认框,重试/恢复不会显示; - 查看历史启用当前商品筛选且不创建任务; - 继续后只进入一次既有费用确认,最终使用新轮次;取消不启动 worker; - 旧轮次、当前结果和导出入口仍可用。 - 运行: ```bash py -3.10 -m unittest tests.test_image_studio tests.test_product_suite_gui tests.test_workers 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、asset 或图片。 - 不新增历史重跑、批量生成确认、历史删除、恢复历史轮为当前轮或直接更新蝦皮功能。 - 不修改 cmhub API、模型别名、图片下载、轮询、超时、并发、计费或 Shopee CDP 流程。 ## 执行记录 - 2026-07-17:根据“已有成功套图时先提醒再新建一轮”的产品讨论创建任务。待实现。 - 2026-07-17:新增 `get_successful_generation_history_summary()`,仅按未软删除项目的 SQLite 有效 job 汇总成功轮数、成功图片数与最近成功时间;正常轮次按稳定槽位的最新尝试统计,NULL 旧版轮次整体兼容为一轮,目录与图片文件不参与判断。 - 2026-07-17:常规「生成套图」在原有费用确认前增加“已有套图生成记录”三选一确认;查看历史仅打开并临时筛选当前商品,继续才进入既有费用确认并创建新 UUID 轮次,取消不写入任务。单张失败重试继续绕过该流程。 - 2026-07-17:全局历史窗口增加受控的当前商品筛选设置,普通「历史生成」入口保持全局默认视图;同步更新架构、API 和流程文档。 - 验证通过:`py -3.10 -m unittest discover -s tests`(569 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。