From 9166cb701069f4ee298e683e69aa5f815ce28433 Mon Sep 17 00:00:00 2001 From: chengma Date: Fri, 17 Jul 2026 10:35:13 +0800 Subject: [PATCH] docs(task): add suite generation safeguards --- docs/tasks/T-648.md | 93 +++++++++++++++++++++++++++++++++++++++++++++ docs/tasks/T-649.md | 87 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 docs/tasks/T-648.md create mode 100644 docs/tasks/T-649.md diff --git a/docs/tasks/T-648.md b/docs/tasks/T-648.md new file mode 100644 index 0000000..c119697 --- /dev/null +++ b/docs/tasks/T-648.md @@ -0,0 +1,93 @@ +--- +id: T-648 +title: 商品套图已有成功历史时确认新一轮生成 +phase: 7 +deps: [T-643, T-646] +status: TODO +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:根据“已有成功套图时先提醒再新建一轮”的产品讨论创建任务。待实现。 diff --git a/docs/tasks/T-649.md b/docs/tasks/T-649.md new file mode 100644 index 0000000..7116965 --- /dev/null +++ b/docs/tasks/T-649.md @@ -0,0 +1,87 @@ +--- +id: T-649 +title: 商品套图历史店铺下拉筛选和结果目录入口精简 +phase: 7 +deps: [T-646] +status: TODO +created: 2026-07-17 +--- + +## 问题 / 背景 + +T-646 的全局「历史生成」窗口目前使用自由文本输入框按店铺/账号模糊筛选。账号名和别名可能相近,模糊匹配会让用户难以确认当前筛选对象,也无法清楚表达已从账号管理中删除、但历史记录仍应可查看的店铺。 + +⑥顶部另有「打开结果文件夹」入口,直接打开内部生成目录。该目录可能包含中间文件、失败输出或内部存储结构,不适合作为正式用户导出路径;用户已经可以在历史窗口按轮次导出成功结果。 + +## 方案 + +### 1. 历史店铺改为结构化下拉筛选 + +修改全局历史查询和 `ProductSuiteGlobalHistoryDialog`: + +- 将「店铺」自由文本框替换为 `QComboBox`,首项固定为「全部店铺」;商品 ID 关键字输入和「仅当前商品」筛选保留,三者可叠加; +- 下拉项展示当前账号管理中可用账号,标签使用「账号名(账号别名)」;实际筛选值始终使用稳定的 `account_alias`,不能依赖显示文字反查; +- 同时从未软删除的历史商品项目中收集账号别名。若某历史别名已不在账号管理列表,仍须保留为可选项,标签明确标为「历史店铺:别名(账号已删除)」;不伪造账号名,也不丢失历史查询能力; +- 新增或扩展结构化查询参数(如 `account_alias`),在 SQLite 查询层使用精确匹配 `projects.account_alias = ?`;不再把下拉选择转换为 `LIKE` 模糊文本;如保留旧 `account_query` 参数,必须仅作为兼容入口并有明确优先级; +- 打开窗口、刷新、筛选或加载更多时保持稳定排序和分页;刷新下拉列表时尽量保留当前仍存在的选择,否则回退到「全部店铺」;不能一次把所有原图加载进内存; +- 顶部「历史生成」仍默认查看全部商品和全部店铺。T-648 从生成确认框打开历史时可单独启用“仅当前商品”,不能改变此默认行为。 + +### 2. 移除直接打开内部结果目录的正式入口 + +修改⑥「商品套图」顶部上下文区: + +- 移除可见的「打开结果文件夹」按钮、信号连接、可用状态和相关 GUI 测试断言; +- 不删除内部 `generated` 目录、已有图片、项目文件、导出能力、预览能力或历史窗口中的「导出本轮」; +- 用户需要取得图片时,统一从历史窗口选择某一轮后使用「导出本轮」,由用户选择外部目标目录并只复制成功且存在的输出图; +- 若保留无 UI 引用的内部辅助方法,必须不再能通过普通用户界面直接访问原始目录,且不得影响现有内部调用;优先清理确定无引用的死代码。 + +### 3. 文档与交互一致性 + +- 所有下拉项、空态、筛选提示和导出引导使用中文,不显示完整本地路径、接口 URL、模型别名、Key 或上游错误; +- 同步更新 `docs/04-architecture.md`、`docs/api.md`、`docs/routes.md`,说明历史店铺的精确别名筛选、历史账号兼容和结果导出入口; +- 如顶部区域布局或历史筛选 UI 需要更新效果图,保存到 `docs/ui/` 并在 `docs/ui/README.md` 登记。 + +## 验收要点 + +- [ ] 全局历史窗口的店铺筛选为下拉框,首项是「全部店铺」;不再提供店铺自由文本模糊输入。 +- [ ] 当前账号显示为「账号名(账号别名)」,选择后按精确 `account_alias` 查询,不会把相近别名、账号名或商品 ID 误匹配进来。 +- [ ] 已删除账号但仍有未软删除历史项目的别名可被选择,且标签明确标识为历史店铺。 +- [ ] 店铺、商品 ID 和仅当前商品筛选可正确叠加,刷新/分页后排序与结果稳定。 +- [ ] 顶部「历史生成」初次打开仍默认全局视图,不会被上一商品或生成确认路径永久改变。 +- [ ] ⑥顶部不再显示「打开结果文件夹」;历史窗口的「导出本轮」仍能把成功图片复制到用户选择的目录。 +- [ ] 不删除或修改内部生成图片、历史轮次、job、asset、项目或导出数据。 +- [ ] 不影响套图生成、单图重试、历史预览、AI帮写、cmhub 调用、Shopee CDP、采集、AI生成、更新蝦皮、账号管理或设置。 + +## 测试 + +- `tests/test_image_studio.py`: + - `account_alias` 精确筛选、全部店铺、商品 ID 与当前项目组合筛选; + - 相近别名不误匹配;历史别名可返回;软删除项目继续被排除; + - 分页与稳定排序不回归,兼容参数的优先级明确。 +- `tests/test_product_suite_gui.py`: + - 下拉项的显示标签和 `itemData` 正确,当前账号与历史店铺均可选; + - 切换店铺、商品 ID、仅当前商品后刷新结果正确; + - 历史窗口默认全局,外部指定当前项目的路径只影响该次窗口状态; + - 顶部不存在「打开结果文件夹」入口,历史导出入口和中文空态仍可用。 +- 运行: + +```bash +py -3.10 -m unittest tests.test_image_studio tests.test_product_suite_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 +``` + +- 人工建立至少两个当前账号、一个已删除账号的历史项目和相近别名测试数据,检查 Windows 100% / 125% / 150% 缩放下下拉框、筛选、分页和导出路径。 + +## 边界(不改什么) + +- 不删除账号、项目、轮次、job、asset、图片或任何历史记录。 +- 不实现批量导出、全部历史导出、历史删除、历史重跑、从历史恢复当前轮或直接更新蝦皮。 +- 不修改 cmhub API、模型别名、图片理解、生图、下载、轮询、超时、并发或计费逻辑。 +- 不修改 Shopee CDP、商品采集、AI生成、更新蝦皮、账号登录或设置模块。 + +## 执行记录 + +- 2026-07-17:根据全局历史筛选和结果目录入口精简的产品讨论创建任务。待实现。