8.7 KiB
id, title, phase, deps, status, created
| id | title | phase | deps | status | created | ||||
|---|---|---|---|---|---|---|---|---|---|
| T-612 | AI工场生图运行态分级,保留当前项目非冲突操作 | 7 |
|
DONE | 2026-07-13 |
问题 / 背景
⑥ AI工场点击「开始生成」或「继续查询任务」后,ImageStudioTab.start_generation() / resume_generation_jobs() 都经由通用 _start_worker() 进入 _set_running(True)。当前 _set_running() 会同时禁用商品列表、蝦皮原主图、照片池、主图/详情图终选、提示词模板、提示词编辑、生成参数、开始/继续查询、导出和项目操作,只留下「取消」。
这不是 cmhub 网络等待导致 GUI 卡死:网络工作在 QThread 中。它是早期把所有 AI工场 worker 当作同一种“全页互斥操作”的保守实现,用来避免:
- 在单一
_running_worker/_running_thread模型下同时启动两个耗时 worker; - 生成回调按
current_project刷新时,用户同时删除项目或开始另一项写操作; - 用户误以为生成中的提示词或源图变更会影响已经提交给 cmhub 的本轮任务。
但图片生成/继续查询通常持续数分钟,全页变灰妨碍运营在当前商品内浏览照片池、整理终选、修改下一轮提示词。T-608 已经为单张蝦皮原图下载拆除了全页禁用,生图仍沿用旧的全局锁定策略,体验不一致。
方案
1. 区分操作类型,保留“单一耗时 worker”边界
在 app/gui/tabs/image_studio.py 中把通用运行态从单一布尔值扩展为明确的操作类型,例如:generate、resume、pull_images、export。运行期间仍只允许一个由 _start_worker() 管理的耗时 worker,不能借“局部可用”引入两个生成、轮询、拉图或导出 worker 并发。
ImageStudioGenerateJobsWorker与ImageStudioResumeJobsWorker使用“生成运行态”;- 拉取蝦皮主图、导出终选维持现有较严格的互斥范围;
- T-608 的单张原图下载队列继续使用专用路径,不回退到
_start_worker(),不受本任务破坏; - 线程引用仍只在
thread.finished后释放,继续遵守 T-604 的生命周期修复。
2. 生图期间只禁用冲突操作
处于“生成运行态”时:
- 必须禁用:开始生成、继续查询任务、拉取蝦皮主图、导出终选、删除项目、会启动完整原图下载的原图区操作;这些操作会再启动 worker、改变线上主图快照、移动导出文件或删除当前 worker 仍在写入的项目。
- 保持可用:当前项目的照片池浏览、源图选择、主图/详情图终选排序、提示词模板切换/编辑/保存、类型/数量/比例的下一轮设置,以及打开当前项目文件夹。
- 当前这一轮的源图、提示词、类型、数量、比例在创建
ImageStudioGenerateJobsWorker时已经快照传入;运行中修改上述控件只影响下一轮,不得改变已提交或正在轮询的 cmhub job。 - 在生成设置区显示中文轻量提示,例如「本轮任务已固定;此处修改将在下一轮生成时生效」,避免用户误解。
- 第一版不开放切换商品项目。项目切换会重置缩略图缓存、
current_project、selected_source_asset_id和列表内容,且现有完成/进度回调仍依赖当前 tab 状态;保留禁用项目列表可避免旧项目的余额、进度或刷新事件显示到新项目。后续若要支持跨项目浏览,必须先让全部回调按启动时捕获的project_id隔离,再单独立任务。
取消按钮继续始终可用;点击后只请求 worker 在安全边界停止,控件在 worker 正常完成、失败或停止并完成清理后恢复。
3. 回调与状态恢复保持幂等
_finish_worker()、worker.failed、worker.finished以及thread.finished的顺序不得导致控件提前恢复或重复恢复;继续复用 T-604 的_worker_error_handled与线程引用清理规则。- 生成部分成功、部分失败、用户停止、cmhub 轮询失败和导出/拉图失败后,都按各自操作类型恢复对应控件,而不是无条件套用“生成态”或“全局空闲态”。
- 不在 GUI 主线程等待 cmhub,也不在后台线程直接操作 Qt 控件。
4. 文档同步
更新 docs/routes.md 中⑥ AI工场的生成运行口径:生图期间禁止新建冲突 worker,但可继续整理当前项目的下一轮设置与终选;原图下载、项目切换、拉取、导出和删除的边界保持明确。
验收要点
- 点击「开始生成」或「继续查询任务」后,取消按钮可用,开始/继续查询/拉取/导出/删除项目/原图区下载操作不可用。
- 生图期间,照片池、主图终选、详情图终选、提示词模板、提示词编辑和下一轮类型/数量/比例控件不再整体变灰,可正常操作。
- 运行中修改提示词或参数后,本轮已创建的 worker 仍使用启动时的快照;下一轮生成才读取新值。
- 生图期间不能启动第二个耗时 worker,不能切换或删除项目,不能从原图区触发新的完整原图下载。
- 停止、完成、部分失败和 worker 异常后,控件按空闲态正确恢复;不会出现 QThread 提前释放、重复错误弹窗或残留禁用状态。
- T-608 的单张原图下载仍只局部更新,不会因为本任务重新把 AI工场全页变灰。
- 不改 cmhub submit/poll/download、计费、job 持久化、SQLite schema、CDP、Chrome、蝦皮读取/更新或①至⑤模块。
测试要求
更新或新增 tests/test_gui.py:
- 覆盖生成运行态下各控件的精确启用/禁用清单;特别断言照片池、终选、提示词和参数可用,而开始/继续查询/拉取/导出/删除/原图区下载不可用。
- 覆盖运行中修改 prompt/参数不会改变已构造 worker 的参数,只影响下一次
start_generation()。 - 覆盖取消、成功、失败、
finished(ok=False)与thread.finished各顺序下,运行态和线程引用均正确恢复且错误只处理一次。 - 覆盖原图下载专用队列不受生成运行态重构影响。
验证命令:
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
人工验收:启动一轮等待时间较长的生图,在等待期间编辑下一轮提示词、调整数量、拖动已有候选图到终选并点击取消;确认本轮任务参数不变、下一轮使用新设置,且没有生成第二个后台 worker。
边界(不改什么)
- 不实现多项目并行生成、跨项目浏览、多个全局 worker 并发或后台静默重提交流程。
- 不改变单张原图下载的最大并发、重试、项目隔离和关闭清理规则。
- 不改变照片池中失败任务卡的展示语义;该问题由 T-613 单独处理。
- 不增加 cmhub API 字段、重试次数、超时、计费规则、数据库字段或新的设置入口。
- 不改变任何 CDP、Shopee、Chrome 登录或上传逻辑。
执行记录
- 2026-07-13:完成 AI工场生图运行态分级。
app/gui/tabs/image_studio.py:为通用 worker 增加operation_kind,区分生成/继续查询、拉主图、导出等操作;生成/继续查询期间保留照片池、终选、提示词模板/编辑和下一轮参数,仍禁用项目切换、原图区下载、拉图、开始/继续查询、导出、删除。app/gui/tabs/image_studio.py:生成 worker 创建时固定使用当时的源图、提示词和参数;界面显示「本轮任务已固定;此处修改将在下一轮生成时生效」。打开项目文件夹在生成期间仍可用。app/gui/tabs/image_studio.py:_start_worker()在上一 QThread 尚未发出thread.finished时拒绝启动下一 worker;拉图、生成、继续查询、导出、删除和移除照片增加运行中保护,避免程序化调用绕过禁用按钮。docs/routes.md:更新⑥ AI工场的生成运行态边界。tests/test_gui.py:新增生成态控件清单/参数快照测试,以及线程收尾前禁止启动下一 worker 的测试。
- 验证:
- 主工作区定向 GUI 测试通过:4 项,覆盖生成运行态、参数快照和线程生命周期。
- 主工作区
python -m ruff check app tests main.py、py -3.10 -m compileall app main.py、git diff --check通过。 - 主工作区全量 unittest 因既有未提交默认提示词文件变更失败 3 项(
papa1被乱码默认模板替代),不属于本任务。 - 干净 worktree
D:\chengma\cmshopee-t612-verify仅应用本任务差异后通过:python -m ruff check app tests main.py、py -3.10 -m compileall app main.py、py -3.10 -m unittest discover -s tests(389 项)及git diff --check。