feat(product-suite): add original image batch management

This commit is contained in:
chengma
2026-07-14 15:35:59 +08:00
parent 21d2dd5253
commit e86b9189ab
8 changed files with 759 additions and 37 deletions
+1 -1
View File
@@ -431,7 +431,7 @@ data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.<ext> # AI 生成的新
- 任一组件生成后 `stage=generated`;**不设逐条人工审核阶段**。若只有标题,③可选择只更新标题;若只有封面,③可选择只更新封面,②标题状态仍为待生成,后续补标题会保留已有封面且不重复生图。双击任务弹窗查看旧封面、新封面和历史候选图;T-577 后弹窗内「重置图片」只清当前任务 `new_cover_path` 并归档旧图,不启动单条 `GenerateWorker`,用户退出后用状态筛选「待生成」批量补生成封面。②「重置生成结果」提供标题/封面/全部的多选或当前筛选范围重置,默认不删除本地新封面文件;已生成且未提交线上的新标题可在②表格本地微调。
- 并发数、重试、分辨率、jpg 质量、模型/Key 均来自 ⑤ 设置(`data/config.json` 的 `ai` 段;Key 存 `data/config/cmhub.json` 或 direct 兼容清单)。T-547 后标题并发和图片并发都限制为 1..5,失败重试次数限制为 0..10;旧 `config.json` 或手工配置的超限值会在加载/保存时夹紧。⑤仍只展示一个「图片并发」设置;cmhub 模式下②运行日志显示“图片并发 X,cmhub实际生图并发 Y,下载并发 Y”。
- ⑥商品套图固定使用⑤保存的 cmhub 生图 alias;平台、国家地区、输出语言、比例、分类、商品ID、参考图序号和卖点文本由 `product_suite.build_suite_prompt()` 组成每个 job 的完整提示词。比例同时传入 `image_studio_generation.run_jobs(aspect_ratio=...)`,最终进入 cmhub 请求与输出资产元数据。
- `image_studio_projects.suite_settings_json` 持久化套图设置,旧数据库由 `db.init_db()` 原位补列,默认 `{}`;`draft_prompt` 继续保存卖点文本。`image_studio_assets` 中有效商品原图最多16张,历史 missing 记录不占有效名额;手工原图不会因再次同步蝦皮 URL 被误标 missing。
- `image_studio_projects.suite_settings_json` 持久化套图设置,旧数据库由 `db.init_db()` 原位补列,默认 `{}`;`draft_prompt` 继续保存卖点文本。`image_studio_assets` 中有效商品原图最多16张,历史 missing 记录不占有效名额;手工原图不会因再次同步蝦皮 URL 被误标 missing。⑥原图列表的批量勾选只保存在当前 `SuiteTaskState` 对应的界面上下文,不写库;批量移除由 `remove_original_assets_if_unused()` 一次校验项目归属、原图类型和 job/终选引用,并在单个 SQLite 事务中删除资产行、连续重排 `source_order`。服务不删除本地文件或蝦皮线上图片,任一资产校验失败时整批回滚。
- 第六 Tab 的多个 `SuiteTaskState` 各自保留 generation/pull/import/AI/download worker 与线程引用;切换任务不取消任务。多个任务可并行,但 `image_studio_generation` 使用进程级 semaphore 保证所有套图任务合计最多5个 cmhub 在途 job。线程还在运行时关闭任务只请求协作式停止,模块级引用保留到 `QThread.finished`,不得提前销毁线程对象;下载前后均检查停止信号,停止后的临时文件不入资产库。
提示词管理:
+2
View File
@@ -373,6 +373,7 @@ update_project_suite_settings(project_id, settings, path=None) -> ImageStudioPro
sync_original_asset_urls(project_id, image_urls, path=None) -> list[ImageStudioAsset]
list_assets(project_id, kind=None, include_missing=True, path=None) -> list[ImageStudioAsset]
reorder_original_assets(project_id, asset_ids, path=None) -> list[ImageStudioAsset]
remove_original_assets_if_unused(project_id, asset_ids, path=None) -> list[ImageStudioAsset]
create_job(project_id, source_asset_id=None, job_type="main", prompt="", ...) -> ImageStudioJob
list_jobs(project_id, statuses=None, path=None) -> list[ImageStudioJob]
list_resumable_jobs(project_id=None, include_failed_downloads=False, path=None) -> list[ImageStudioJob]
@@ -408,6 +409,7 @@ export_project_selection(project_id, parent_dir, existing_mode="fail", path=None
- `image_studio_projects.suite_settings_json` 保存平台/国家/语言/比例/逐图主图/分类数量;`draft_prompt` 保存商品卖点。有效原图上限16张,missing 历史不占名额。
- 拉取蝦皮原主图只读:复用 `editor.open_product(..., bring_to_front=False)` 和 `editor.read_product_image_urls()`,不上传、不拖拽、不点击更新。
- 原图下载走 `image_studio_images` 的公网 URL、大小、Content-Type、重定向和 PIL 解码校验;只在用户单击时落盘。
- `remove_original_assets_if_unused()` 会先校验整批原图的项目归属、资产类型及 job/终选引用,再在单个事务中删除资产行并连续重排 `source_order`;任一图片不可删除时整批不变,本地源文件和蝦皮线上图片始终保留。
- cmhub 托管生图每张都是独立 job:保存 `task_key/task_id/status/call_id/points_cost/points_balance`;已有 `task_id` 时只 poll/download,不重复 submit。商品套图把平台/国家/语言/比例等上下文写入每个 job prompt,并把比例实参传到 cmhub;界面不展示 Provider URL、OpenAI Key 或上游接口路径。
- `include_failed_downloads=True` 允许 failed 但已有 `task_id`、无输出 asset 的任务继续查询,用于下载失败或本地保存失败恢复。
- 终选顺序由 `replace_selections()` 事务替换,主图/详情图同类别去重、跨类别可复用。
+4 -2
View File
@@ -186,7 +186,8 @@
┌ 套图任务1 │ 套图任务2 │ + ───────────────────────────────────┐
│ [历史生成][打开结果文件夹][添加图片] 账号[▼] 商品ID[____][拉取主图] │
├ 左侧配置(滚动)────────────┬ 右侧生成结果 ─────────────────────┤
│ 商品原图:主图/参考1..5/添加 │ 共N张·成功M张 │
│ 商品原图 N/16 已选N张[全选][反选]│ 共N张·成功M张 │
│ 主图/参考图按宽度换行自然展开 │ │
│ 平台 站点 语言 比例(同行) │ [结果卡][结果卡][失败卡·重试] │
│ 每张上传图分别作为主图生成 │ │
│ 商品卖点与要求 [AI帮写/取消] │ │
@@ -198,7 +199,8 @@
- 每个顶部任务标签持有独立账号、商品ID、设置、原图、当前 job 集合和 worker;任务可并行生成。切换任务不停止后台操作;关闭运行中任务先确认并协作式取消,线程引用保留到真正结束,避免 `QThread: Destroyed while thread is still running`。
- 二级套图任务标签使用独立紧凑样式,不继承主模块 Tab 的大尺寸点击区。上下文栏左侧集中「历史生成 / 打开结果文件夹 / 添加图片」,右侧集中账号、商品 ID 和拉取入口;常见 11~13 位商品 ID 不得裁切,长账号可通过 tooltip 查看完整名称。
- 项目仍以 `账号别名 + 商品ID` 唯一,复用 `image_studio_projects/assets/jobs`。`suite_settings_json` 保存平台、国家地区、语言、比例、逐图主图模式和分类数量;卖点文本继续使用 `draft_prompt`。
- 商品原图最多16张。前6个槽位固定显示主图与参考1~5;支持文件选择、外部拖入、剪贴板粘贴和列表内排序。历史失效远程图不占有效名额;第1张是主参考图。
- 商品原图最多16张。前6个槽位固定显示主图与参考1~5;列表关闭内部滚动条,按可用宽度换行并自然向下展开,由左侧配置区统一滚动。支持文件选择、外部拖入、剪贴板粘贴和列表内排序。历史失效远程图不占有效名额;第1张是主参考图。
- 每张真实原图左上角提供独立勾选框,标题行显示「已选 N 张 / 全选 / 反选」;添加占位图不参与选择。勾选只在当前任务界面内临时保留,普通刷新和排序按资产 ID 保留,切换任务或删除成功后清空。右键或 Delete 可批量移除,确认框说明准确数量、主图变化及非破坏性边界;生成中或勾选项仍在下载时整批阻断。移除只删除当前项目的本地资产记录,不删除本地源文件或蝦皮线上图片。
- 「拉取蝦皮主图」复用只读 CDP,读取 URL 后由最多2个下载 worker 后台落盘;不改标题/封面、不拖拽、不点击更新。拉取、下载期间其余界面和其他任务仍可操作。
- 套图只有一个图片类型,不再展示详情图、终选盘或模板 CRUD。默认分类为白底图1、场景图2、卖点图2;自定义分类名称非空、无空格、最多10字且不可重名。逐图主图开启后,白底图只生成一次,其余分类按每张有效原图展开。
- 平台、国家地区、语言和比例以四个带独立标签的同行下拉展示,选项只显示真实值;四项都写进每个 job 的完整提示词,比例还透传到 cmhub 生图请求,不是装饰字段。已有项目保存自己的完整设置;未绑定商品的新任务在重启后采用 `config.json` 的最近四项选择。生成仍走 `image_studio_generation.run_jobs()` 的 submit → poll → download 管线。
+12 -1
View File
@@ -3,7 +3,7 @@ id: T-631
title: 商品套图原图自适应展示与批量选择删除
phase: 7
deps: [T-627]
status: TODO
status: DONE
created: 2026-07-14
---
@@ -95,3 +95,14 @@ created: 2026-07-14
- 不修改 cmhub 生图提交、轮询、下载、并发、重试或计费逻辑,不修改生成结果/历史结果删除语义。
- 不把原图勾选状态持久化,不新增 SQLite 字段;只扩展现有图片资产服务的事务级批量操作。
- 不修改①~⑤模块 UI,不修改主窗口全局样式。
## 执行记录
- 2026-07-14 完成。
- ⑥商品原图列表已关闭横向/纵向内部滚动条,按当前可用宽度、固定缩略图尺寸和最多16张原图动态计算行数与高度;最少6个展示位保持不变,图片区自然向下展开并由外层 `suiteConfigScroll` 统一滚动。
- 每张真实原图通过自定义 delegate 显示独立复选框,添加占位图不参与选择。标题栏新增「已选 N 张 / 全选 / 反选」;普通刷新和拖拽排序按 `asset_id` 保留勾选,任务切换及删除成功后清空。复选框点击不会触发下载或预览,缩略图单击、双击、拖拽和悬停单张删除保持原语义。
- 右键菜单和 Delete/Backspace 已统一支持单张或勾选集合删除。确认框显示准确数量,包含主图变化、本地源文件保留、蝦皮线上图片不删除及重新拉取可能恢复的说明;生成中或任一选中图片仍在后台下载时整批阻断。
- `app/image_studio.py` 新增 `remove_original_assets_if_unused()`:一次校验项目、原图类型、job/终选引用,在同一个 SQLite 事务中删除资产行并连续重排 `source_order`;任一 ID 无效或被引用时整批不变,本地文件始终保留。
- 已同步 `docs/04-architecture.md`、`docs/api.md` 与 `docs/routes.md`。新增 GUI 和服务层测试,覆盖 0/6/7/16 张及宽度变化、选择状态、任务切换、点击/键盘/右键路由、运行与下载阻断、跨项目/非原图/不存在/job/终选引用的事务回滚。
- 离屏界面检查通过:1180×760 下16张图片为3列6行,内部滚动范围为0、外层滚动正常;960×640 的 Windows 125% / 150% 缩放模拟下标题栏操作不重叠,复选框不遮挡缩略图文字或右上角单张删除入口。
- 当前工作区全量测试仅有任务开始前已存在的默认封面提示词重命名导致3个旧 `papa1` 断言失败;在只包含 T-631 暂存内容的干净验证工作树中运行 `py -3.10 -m unittest discover -s tests`,479项全部通过。`python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check` 全部通过。