docs: 落 T-622 ⑥商品套图替换AI工场(迁移套餐模块)+ 效果图

- 新增 docs/tasks/T-622.md:需求定稿+落地事实(全原生PySide6、复用image_studio后端与异步生图、绑账号+商品ID、去详情图、原生重写不引WebView)
- 新增 docs/ui/tab6-suite-package-v1.svg:家风效果图(顶部账号+商品ID、6图上传、2×2下拉去label、卖点框加高、结构3类、生成按钮toggle、可滚动区、右侧结果+进度)
- docs/ui/README.md 登记该效果图

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
chengma
2026-07-13 15:20:42 +08:00
co-authored by Claude Opus 4.8
parent a86e2bb162
commit e2fbae2ee1
3 changed files with 234 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
---
id: T-622
title: ⑥用「商品套图」模块替换现有 AI工场(迁移电商图生成器套餐模块)
phase: 7
deps: [T-564]
status: TODO
created: 2026-07-13
---
## 问题 / 背景
顾客不满意最新代码里的 ⑥「AI工场」模块(现有原生 PySide6 实现,后端表 `image_studio_*`)。要求把 `/mnt/d/chengma/虾皮圈电商图生成器源码` 项目里的「商品套图(商品套餐)」模块交互迁移过来,替换现有 ⑥「AI工场」。
已核实的现状事实(落地依据,来自读码):
- cmshopee **全原生 PySide6**,未引入 `QtWebEngine / QWebChannel`;迁移源是 QWebChannel + WebView 单页应用(`web/index.html` + `web/app.js` + `web/style.css`)。
- 现有 ⑥「AI工场」后端分层已完整,可复用:`app/image_studio.py`(领域 Project/Asset/Job/Selection)、`app/image_studio_generation.py`(异步生图)、`app/image_studio_export.py`(导出)、`app/image_studio_images.py`(图片处理)、`app/image_paths.py`;DB 表 `image_studio_projects/assets/jobs/selections`(`app/db.py:293+`);提示词目录 `data/prompts/image_studio/`(`app/appconfig.py:256`)。
- 现有 AI工场 **project 强绑定「账号别名 + 商品ID」**(`app/image_studio.py:148`「缺少账号别名」、`:291`「缺少商品ID」)——顾客不满的是交互/UI,后端契约(绑账号+商品ID、异步生图)保留。
- 异步生图已接:`POST /api/v1/generate/image/tasks` + `Idempotency-Key` + `task_id` 轮询(`app/ai.py:1104+`,T-564 已落地)。
UI 已定稿:`docs/ui/tab6-suite-package-v1.svg`(本仓库家风:`#2b3a55` 头栏 / `#2f6fed` 蓝 / 微软雅黑;已在 `docs/ui/README.md` 登记)。
## 需求定稿(以 SVG 为准)
**整体**
- ⑥ 单一图片类型(**去掉「详情图」**,与套图合并;详情类目可用「自定义分类」加回)。
- 保留**多任务并行**(顶部「套图任务 1 / 2 / +」标签,互不阻塞)。
- **顶部上下文条**:`账号` 下拉 + `商品ID` 输入 + `拉取蝦皮主图` 按钮(右靠、与「打开文件夹」同右边缘);每个套图任务绑定一个账号+商品ID,切换任务随之切换。
- 采用**原生 PySide6 重写 UI**,复用上述 `image_studio_*` 后端与异步生图管线;**不引入 QtWebEngine**。
**左侧配置面板(可滚动区 + 底部固定按钮)**
- 商品原图上传:两行共 **6 张缩略图**(主图 / 参考1..5)+ 添加;支持点击/拖拽/粘贴,或「拉取蝦皮主图」带入;第 1 张为主图,最多 16 张。
- 生成设置:**4 个可切换下拉**(平台=Shopee / 国家地区=中国台湾 / 语言=繁体中文 / 比例=1:1),**不显示 label**(靠位置辨识);+ 复选框「每张上传图分别作为主图生成」。
- 平台/国家/语言当前后端为固定单值,做成下拉是为将来多平台扩展;**选中值须透传进生成提示词上下文**,不得只做装饰。
- 商品卖点与要求:多行输入框(较高)+「✧ AI 帮写」按钮。
- 套图结构配置:默认仅 **3 类**「白底图 / 场景图 / 卖点图」,各带 `− 数量 +` 计数器;`+ 添加自定义分类`(可改名 / 删除)。
- 底部固定「▶ 生成套图(N)」按钮(**在滚动区外,不随滚动**);点击后**同一按钮切换为「■ 停止生成」**(建议危险色);**取消独立「停止」按钮**。按钮下方 label:`建议填写产品名称、核心卖点、目标人群、使用场景与禁用元素`。
- 除「生成套图」按钮外,其余组件同属一个**竖直滚动区**。
**右侧结果区**
- 工具栏:`生成结果` + `共 N 张·成功 M 张` 徽标 + `历史生成` + `打开文件夹`。
- 结果网格:每张卡片显示图片/生成中骨架/失败(带「重试」);右键单图可 预览 / 复制路径 / 重新生成。
- 底部一行(与左侧「生成套图」按钮同高):进度条 + `套图 X/Y(秒)· 失败 N` 汇总。
## 待决 / 选型(实现前确认)
1. **技术栈**:推荐**原生 PySide6 重写 UI**、复用现有 `image_studio_*` 后端;已排除内嵌 WebView(避免 QtWebEngine 打包体积与依赖)。若坚持搬 WebView 需另评估。
2. 平台/国家/语言下拉的选中值如何进入生成上下文(提示词模板变量 or 生成请求参数),需与 `image_studio_generation` 对齐。
3. 效果图当前为「滚动区裁剪」呈现;如需一屏展示全部配置项,属实现期布局细节。
## 验收要点
- ⑥ 标签由「AI工场」交互替换为「商品套图」布局,功能对齐 SVG;旧 AI工场入口不再暴露。
- 顶部账号+商品ID 生效:切换任务/账号/商品ID 正确带入;「拉取蝦皮主图」把线上主图拉进「商品原图」。
- 套图结构 3 类默认 + 自定义分类增删改;数量计数正确,合计张数与「生成套图(N)」一致。
- 生成走异步管线(复用 T-564):提交→轮询→逐张落盘;单张失败可重试;「生成⇄停止」toggle 正常;多任务并行互不阻塞。
- 平台/国家/语言/比例选中值确实进入生成上下文(非装饰)。
- 复用现有 `image_studio_*` 表与目录,不新造并行后端;不引入 QtWebEngine。
- 验证:`py -3.10 -m unittest`(相关模块)、`python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check` 全绿。
## 边界(不改什么)
- 不改动 `image_studio.py / image_studio_generation.py / image_studio_export.py` 的后端数据契约与异步生图协议(仅按需扩展字段)。
- 不动 ①~⑤ 既有标签与流程。
- 不引入 `QtWebEngine`(采纳原生重写方案时)。
- 安全红线:不写真实凭证到代码/文档/日志;`config.json`、`cmshopee.db`、`images/` 等不提交;不绕过 Shopee 风控;生成/导出等本地操作不触碰 ③ 的线上提交边界。
+1
View File
@@ -14,5 +14,6 @@
| [tab6-image-studio.svg](tab6-image-studio.svg) | ⑥ 图片精修(提案·初版):商品列表、原主图九宫、照片池、生成控制、终选排序 | | [tab6-image-studio.svg](tab6-image-studio.svg) | ⑥ 图片精修(提案·初版):商品列表、原主图九宫、照片池、生成控制、终选排序 |
| [tab6-image-studio-v2.svg](tab6-image-studio-v2.svg) | ⑥ 图片精修(提案·重排):细图标轨、照片池放大、提示词中心整列、全宽出片盘 | | [tab6-image-studio-v2.svg](tab6-image-studio-v2.svg) | ⑥ 图片精修(提案·重排):细图标轨、照片池放大、提示词中心整列、全宽出片盘 |
| [tab6-ai-studio-v3.svg](tab6-ai-studio-v3.svg) | ⑥ AI工场(需求定稿·v3):合并提示词、完整模板 CRUD、异步任务照片池、部分导出与终选排序 | | [tab6-ai-studio-v3.svg](tab6-ai-studio-v3.svg) | ⑥ AI工场(需求定稿·v3):合并提示词、完整模板 CRUD、异步任务照片池、部分导出与终选排序 |
| [tab6-suite-package-v1.svg](tab6-suite-package-v1.svg) | ⑥ 商品套图(迁移提案·v1):从「虾皮圈电商图生成器」商品套餐模块迁移,替换 AI工场;已去掉「详情图」(与套图合并为单一图片类型)。采用本仓库既有模块风格(#2b3a55 头栏 / #2f6fed 蓝 / 微软雅黑)。多任务标签页、左侧配置面板(商品原图上传、生成设置、AI 帮写、套图结构配置:白底/场景/模特/细节/卖点+自定义分类计数)、右侧生成结果网格、底部进度与生成/停止 |
> 仅为线框效果图,最终样式以实现为准。带 `-T584`/`-v2` 等后缀的为**改版提案**,未定稿。界面职责与流程见 [../routes.md](../routes.md)。 > 仅为线框效果图,最终样式以实现为准。带 `-T584`/`-v2` 等后缀的为**改版提案**,未定稿。界面职责与流程见 [../routes.md](../routes.md)。
+167
View File
@@ -0,0 +1,167 @@
<svg xmlns="http://www.w3.org/2000/svg" width="940" height="620" viewBox="0 0 940 620" font-family="'Segoe UI','Microsoft YaHei',sans-serif">
<!-- ⑥ 商品套图(迁移自「虾皮圈电商图生成器」商品套餐模块,替换原 AI工场;已去掉「详情图」,与套图合并为单一图片类型;顶部绑定账号+商品ID,复用现有 image_studio 后端)-->
<defs>
<style>
.win{fill:#f4f6f9;stroke:#d3d9e2}.hd{fill:#2b3a55}.title{fill:#fff;font-size:14px;font-weight:600}
.tab{fill:#e8ebf0}.tabA{fill:#f4f6f9}.tabT{fill:#5c6573;font-size:13px}.tabTA{fill:#2f6fed;font-size:13px;font-weight:600}
.sec{fill:#1f2733;font-size:13px;font-weight:600}.mut{fill:#8a92a0;font-size:11px}
.cell{fill:#2a2f3a;font-size:12px}.th{fill:#5c6573;font-size:12px;font-weight:600}
.btnP{fill:#2f6fed}.btnPT{fill:#fff;font-size:13px;font-weight:600}
.btn{fill:#fff;stroke:#c5ccd6}.btnT{fill:#3a4150;font-size:12px}
.panel{fill:#fff;stroke:#e2e6ec}.inp{fill:#fff;stroke:#c5ccd6}.ta{fill:#fbfcfe;stroke:#c5ccd6}
.img{fill:#e3ebf7;stroke:#d6ddea}.card{fill:#fff;stroke:#e2e6ec}
.row{fill:#fbfcfe;stroke:#eef0f5}.cnt{fill:#eef2fb}.cntT{fill:#2f6fed;font-size:12px}
.chip{fill:#eef2fb;stroke:#cdd8ef}.chipA{fill:#fff;stroke:#2f6fed}
.sel{fill:#fff;stroke:#c5ccd6}.selT{fill:#2a2f3a;font-size:11px}
</style>
<clipPath id="leftScroll"><rect x="2" y="6" width="260" height="426" rx="6"/></clipPath>
</defs>
<rect class="win" x="0.5" y="0.5" width="939" height="619" rx="8"/>
<rect class="hd" x="0.5" y="0.5" width="939" height="40" rx="8"/><rect class="hd" x="0.5" y="20" width="939" height="21"/>
<text class="title" x="18" y="26">蝦皮圈優化助手 · 商品套图生成</text>
<circle cx="888" cy="20" r="6" fill="#f5bf4f"/><circle cx="910" cy="20" r="6" fill="#5ac26a"/><circle cx="866" cy="20" r="6" fill="#e0e4ea"/>
<!-- tab bar (⑥ active) -->
<rect class="tab" x="0.5" y="41" width="939" height="38"/>
<rect class="tabA" x="590" y="45" width="150" height="38"/><rect x="590" y="45" width="150" height="3" fill="#2f6fed"/>
<text class="tabT" x="24" y="68">① 导入采集</text>
<text class="tabT" x="150" y="68">② AI生成</text>
<text class="tabT" x="256" y="68">③ 更新蝦皮</text>
<text class="tabT" x="386" y="68">④ 账号管理</text>
<text class="tabT" x="516" y="68">⑤ 设置</text>
<text class="tabTA" x="604" y="68">⑥ 商品套图</text>
<!-- top context bar: 套图任务标签 + 账号选择 + 商品ID(每个任务绑定一个账号+商品ID)-->
<rect class="chipA" x="18" y="90" width="112" height="26" rx="6"/>
<circle cx="34" cy="103" r="4" fill="#2f6fed"/><text class="cell" x="44" y="107">套图任务 1</text><text class="mut" x="116" y="107">×</text>
<rect class="chip" x="136" y="90" width="112" height="26" rx="6"/>
<circle cx="152" cy="103" r="4" fill="#20a464"/><text class="cell" x="162" y="107" fill="#5c6573">套图任务 2</text><text class="mut" x="234" y="107">×</text>
<rect class="btn" x="254" y="90" width="30" height="26" rx="6"/><text class="btnT" x="264" y="108">+</text>
<!-- account + item id(整组右靠边,账号下拉紧邻商品ID)-->
<text class="cell" x="532" y="107" fill="#5c6573">账号</text>
<rect class="sel" x="560" y="91" width="104" height="24" rx="5"/><text class="selT" x="568" y="107">女装店</text><text class="selT" x="652" y="107" fill="#8a92a0">▾</text>
<text class="cell" x="668" y="107" fill="#5c6573">商品ID</text>
<rect class="inp" x="724" y="91" width="90" height="24" rx="5"/><text class="cell" x="730" y="107" font-size="11">51100639510</text>
<rect class="btn" x="838" y="90" width="100" height="26" rx="6"/><text class="btnT" x="854" y="108">拉取蝦皮主图</text>
<!-- ===================== LEFT CONFIG PANEL ===================== -->
<g transform="translate(18,126)">
<rect class="panel" x="0" y="0" width="264" height="488" rx="6"/>
<!-- 可滚动内容区(clip 到可视窗口,超出部分靠滚动查看)-->
<g clip-path="url(#leftScroll)">
<!-- 商品原图:两行共 6 张缩略图 + 添加 -->
<text class="sec" x="14" y="18">商品原图</text>
<text class="mut" x="250" y="18" text-anchor="end">6 / 16</text>
<!-- row 1 -->
<rect class="img" x="14" y="24" width="46" height="40" rx="6"/>
<rect class="btnP" x="14" y="50" width="26" height="12" rx="4"/><text x="27" y="59" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">主图</text>
<rect class="img" x="72" y="24" width="46" height="40" rx="6"/>
<rect x="72" y="50" width="32" height="12" rx="4" fill="#8a92a0"/><text x="88" y="59" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">参考1</text>
<rect class="img" x="130" y="24" width="46" height="40" rx="6"/>
<rect x="130" y="50" width="32" height="12" rx="4" fill="#8a92a0"/><text x="146" y="59" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">参考2</text>
<rect x="188" y="24" width="46" height="40" rx="6" fill="#f7f9fd" stroke="#c5ccd6" stroke-dasharray="3 3"/>
<text x="211" y="44" font-size="14" fill="#2f6fed" text-anchor="middle">+</text><text x="211" y="57" font-size="8" fill="#8a92a0" text-anchor="middle">添加</text>
<!-- row 2 (新增 3 张) -->
<rect class="img" x="14" y="68" width="46" height="40" rx="6"/>
<rect x="14" y="94" width="32" height="12" rx="4" fill="#8a92a0"/><text x="30" y="103" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">参考3</text>
<rect class="img" x="72" y="68" width="46" height="40" rx="6"/>
<rect x="72" y="94" width="32" height="12" rx="4" fill="#8a92a0"/><text x="88" y="103" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">参考4</text>
<rect class="img" x="130" y="68" width="46" height="40" rx="6"/>
<rect x="130" y="94" width="32" height="12" rx="4" fill="#8a92a0"/><text x="146" y="103" font-size="8" font-weight="600" fill="#fff" text-anchor="middle">参考5</text>
<text class="mut" x="14" y="122">点击 / 拖拽 / 粘贴,或「拉取蝦皮主图」带入;第 1 张为主图,最多 16 张</text>
<!-- 生成设置:平台/国家/语言/比例(2×2 可切换下拉,已去 4 个 label)+ 每张主图 -->
<text class="sec" x="14" y="142">生成设置</text>
<rect class="sel" x="14" y="148" width="108" height="22" rx="5"/><text class="selT" x="22" y="163">Shopee</text><text class="selT" x="112" y="163" fill="#8a92a0">▾</text>
<rect class="sel" x="132" y="148" width="108" height="22" rx="5"/><text class="selT" x="140" y="163">中国台湾</text><text class="selT" x="230" y="163" fill="#8a92a0">▾</text>
<rect class="sel" x="14" y="174" width="108" height="22" rx="5"/><text class="selT" x="22" y="189">繁体中文</text><text class="selT" x="112" y="189" fill="#8a92a0">▾</text>
<rect class="sel" x="132" y="174" width="108" height="22" rx="5"/><text class="selT" x="140" y="189">1:1</text><text class="selT" x="230" y="189" fill="#8a92a0">▾</text>
<rect x="14" y="206" width="14" height="14" rx="3" fill="#2f6fed"/><path d="M17 213 l2.6 2.6 4.4-4.4" fill="none" stroke="#fff" stroke-width="1.6"/>
<text class="cell" x="34" y="217" font-size="11">每张上传图分别作为主图生成</text>
<!-- 商品卖点与要求(去掉 4 个 label 省下的高度并入,输入框更高)-->
<text class="sec" x="14" y="240">商品卖点与要求</text>
<rect x="168" y="227" width="82" height="20" rx="5" fill="#eef2fb" stroke="#cdd8ef"/><text class="cntT" x="209" y="241" text-anchor="middle">✧ AI 帮写</text>
<rect class="ta" x="14" y="246" width="236" height="118" rx="6"/>
<text x="22" y="264" fill="#98a1b0" font-size="11">降噪蓝牙耳机,40 小时续航,亲肤皮革</text>
<text x="22" y="280" fill="#98a1b0" font-size="11">耳罩,适合通勤与办公场景…</text>
<!-- 套图结构配置 (仅 3 个默认) -->
<text class="sec" x="14" y="384">套图结构配置</text>
<text class="mut" x="250" y="384" text-anchor="end">合计 5 张</text>
<g font-size="12">
<rect class="row" x="14" y="390" width="236" height="22" rx="6"/>
<text class="cell" x="22" y="405" font-size="11">白底图</text>
<g transform="translate(176,391)"><rect class="cnt" x="0" y="0" width="18" height="18" rx="5"/><text class="cntT" x="9" y="14" text-anchor="middle">−</text><text class="cell" x="37" y="14" text-anchor="middle" font-weight="600">1</text><rect class="cnt" x="56" y="0" width="18" height="18" rx="5"/><text class="cntT" x="65" y="14" text-anchor="middle">+</text></g>
<rect class="row" x="14" y="416" width="236" height="22" rx="6"/>
<text class="cell" x="22" y="431" font-size="11">场景图</text>
<g transform="translate(176,417)"><rect class="cnt" x="0" y="0" width="18" height="18" rx="5"/><text class="cntT" x="9" y="14" text-anchor="middle">−</text><text class="cell" x="37" y="14" text-anchor="middle" font-weight="600">2</text><rect class="cnt" x="56" y="0" width="18" height="18" rx="5"/><text class="cntT" x="65" y="14" text-anchor="middle">+</text></g>
<rect class="row" x="14" y="442" width="236" height="22" rx="6"/>
<text class="cell" x="22" y="457" font-size="11">卖点图</text>
<g transform="translate(176,443)"><rect class="cnt" x="0" y="0" width="18" height="18" rx="5"/><text class="cntT" x="9" y="14" text-anchor="middle">−</text><text class="cell" x="37" y="14" text-anchor="middle" font-weight="600">2</text><rect class="cnt" x="56" y="0" width="18" height="18" rx="5"/><text class="cntT" x="65" y="14" text-anchor="middle">+</text></g>
</g>
<rect x="14" y="470" width="236" height="22" rx="6" fill="#fff" stroke="#c5ccd6" stroke-dasharray="3 3"/>
<text x="132" y="485" font-size="11" font-weight="600" fill="#2f6fed" text-anchor="middle">+ 添加自定义分类(可改名 / 删除)</text>
</g>
<!-- 竖直滚动条:除“生成套图”按钮外,上方所有组件同属一个可滚动区 -->
<rect x="255" y="8" width="4" height="424" rx="2" fill="#eef0f5"/>
<rect x="255" y="8" width="4" height="300" rx="2" fill="#c5ccd6"/>
<line x1="8" y1="432" x2="256" y2="432" stroke="#eef0f5"/>
<!-- 生成套图 button (fixed at bottom, OUTSIDE scroll area; toggles to 停止生成) -->
<rect class="btnP" x="14" y="438" width="236" height="36" rx="6"/><text class="btnPT" x="132" y="461" text-anchor="middle">▶ 生成套图(5)</text>
<text x="14" y="483" font-size="9.5" fill="#8a92a0">建议填写产品名称、核心卖点、目标人群、使用场景与禁用元素</text>
</g>
<!-- ===================== RIGHT: RESULTS ===================== -->
<g transform="translate(298,126)">
<!-- toolbar -->
<text class="sec" x="0" y="20">生成结果</text>
<rect x="76" y="6" width="120" height="20" rx="5" fill="#eef2fb"/><text class="cntT" x="136" y="20" text-anchor="middle" font-size="11">共 5 张 · 成功 3 张</text>
<rect class="btn" x="470" y="4" width="72" height="24" rx="6"/><text class="btnT" x="484" y="20">历史生成</text>
<rect class="btn" x="550" y="4" width="90" height="24" rx="6"/><text class="btnT" x="562" y="20">打开文件夹</text>
<!-- cards grid (card 144x136, img 128x96) -->
<g>
<!-- r1c1 done 白底图 -->
<rect class="card" x="0" y="36" width="144" height="136" rx="8"/><rect class="img" x="8" y="44" width="128" height="96" rx="6"/>
<circle cx="128" cy="52" r="7" fill="#20a464"/><path d="M125 52 l2 2 4-4" fill="none" stroke="#fff" stroke-width="1.6"/>
<text class="cell" x="10" y="160" font-size="11">白底图</text><text class="mut" x="136" y="160" text-anchor="end">×</text>
<!-- r1c2 done 场景图1 -->
<rect class="card" x="156" y="36" width="144" height="136" rx="8"/><rect class="img" x="164" y="44" width="128" height="96" rx="6"/>
<circle cx="284" cy="52" r="7" fill="#20a464"/><path d="M281 52 l2 2 4-4" fill="none" stroke="#fff" stroke-width="1.6"/>
<text class="cell" x="166" y="160" font-size="11">场景图 1</text><text class="mut" x="292" y="160" text-anchor="end">×</text>
<!-- r1c3 generating 场景图2 -->
<rect class="card" x="312" y="36" width="144" height="136" rx="8"/><rect x="320" y="44" width="128" height="96" rx="6" fill="#f2f5fb" stroke="#dfe4ee"/>
<circle cx="384" cy="84" r="12" fill="none" stroke="#2f6fed" stroke-width="3" stroke-dasharray="50 24"/>
<text class="cntT" x="384" y="116" text-anchor="middle" font-size="11">生成中…</text>
<text class="cell" x="322" y="160" font-size="11">场景图 2</text>
<!-- r1c4 failed 卖点图1 -->
<rect class="card" x="468" y="36" width="144" height="136" rx="8"/>
<rect x="476" y="44" width="128" height="96" rx="6" fill="#fdecea" stroke="#f3c0bb"/>
<circle cx="540" cy="80" r="12" fill="#f7d3ce"/><text x="540" y="85" font-size="14" font-weight="700" fill="#c2473d" text-anchor="middle">!</text>
<rect class="btn" x="508" y="102" width="64" height="20" rx="5" stroke="#c2473d"/><text x="540" y="116" font-size="11" font-weight="600" fill="#c2473d" text-anchor="middle">重试</text>
<text class="cell" x="478" y="160" font-size="11">卖点图 1</text>
<!-- r2c1 done 卖点图2 -->
<rect class="card" x="0" y="184" width="144" height="136" rx="8"/><rect class="img" x="8" y="192" width="128" height="96" rx="6"/>
<circle cx="128" cy="200" r="7" fill="#20a464"/><path d="M125 200 l2 2 4-4" fill="none" stroke="#fff" stroke-width="1.6"/>
<text class="cell" x="10" y="308" font-size="11">卖点图 2</text><text class="mut" x="136" y="308" text-anchor="end">×</text>
<!-- r2c2 ghost -->
<rect x="156" y="184" width="144" height="136" rx="8" fill="#fff" stroke="#e6ebf3" stroke-dasharray="4 4"/>
<rect x="164" y="192" width="128" height="96" rx="6" fill="#f8fafd"/>
<text x="228" y="234" font-size="10" fill="#aab2c0" text-anchor="middle">右键单图:预览 /</text>
<text x="228" y="250" font-size="10" fill="#aab2c0" text-anchor="middle">复制路径 / 重新生成</text>
</g>
<!-- progress + summary(整行下移,与左侧“生成套图”按钮同一行)-->
<rect x="0" y="440" width="612" height="7" rx="3.5" fill="#e6edfb"/>
<rect x="0" y="440" width="490" height="7" rx="3.5" fill="#2f6fed"/>
<text class="cell" x="0" y="466" font-size="12">套图 4 / 5(38 秒)·</text>
<text x="130" y="466" font-size="12" fill="#c2473d">失败 1</text>
<text class="mut" x="612" y="466" text-anchor="end">每张完成即落盘 · 失败可单张重试</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB