2026-06-26 15:30:37 +08:00
# 界面与流程结构
2026-06-26 16:09:09 +08:00
> 桌面工具,无前端路由。用 **5 Tab GUI( PySide6 `QMainWindow` + `QTabWidget`) + 流水线** 约定界面职责与导航。
2026-06-26 15:30:37 +08:00
## Tab 顺序与职责(工作流优先)
```
2026-07-07 14:58:54 +08:00
① 导入采集 │ ② AI生成 │ ③ 更新蝦皮 │ ④ 账号管理 │ ⑤ 设置
2026-06-26 15:30:37 +08:00
```
| Tab | 职责 | 风险 |
| --- | --- | --- |
| ① 导入采集 | 导入多个 Excel;任务列表;**采集**商品当前的旧标题/旧封面(只读),封面图下载本地;回写 Excel 旧字段 | 只读,低 |
2026-07-02 15:17:11 +08:00
| ② AI生成 | 左侧标题/封面**提示词**;右侧按批次/店铺/商品ID/状态筛选任务列表;AI 生成新标题,并按本轮开关可选生成新封面;已生成任务可本地微调新标题;双击看新旧封面 | 不触线上,中 |
2026-07-07 14:58:54 +08:00
| ③ 更新蝦皮 | 对**已生成**任务点击「开始更新」后弹窗确认;确认后打开编辑页换标题+封面并逐条点「更新」提交;结果回写 Excel | **写线上,高** |
2026-07-06 15:01:50 +08:00
| ④ 账号管理 | Shopee 账号(账号名/别名/数据目录/端口/密码本地明文仅参考/登录状态);启动登录、检测登录、生成快捷方式;启动登录必须复用已打开的同账号 Chrome,避免重复开窗口;检测登录遇到 `accounts.shopee.tw/seller/login` 必须显示未登录 | 中 |
2026-07-07 14:58:54 +08:00
| ⑤ 设置 | cmhub 网关/API Key、生文/生图别名、生成参数、本地图片目录、Chrome 路径、默认端口、蝦皮更新安全开关等 | — |
2026-06-26 15:30:37 +08:00
2026-07-07 14:58:54 +08:00
任务的**阶段状态**贯穿各 Tab: `imported → collected → generated → applied` (或 `failed/skipped` )。② 不设逐条人工确认阶段;③ 无常驻提交开关,但点击「开始更新」后必须先通过 ⑤ 的蝦皮更新安全开关,再弹窗确认当前筛选范围和任务数量。各 Tab 聚焦各自阶段的列与按钮,但操作同一批任务(同一 batch)。
2026-06-26 15:30:37 +08:00
2026-06-27 10:30:45 +08:00
## 全局 Tab 栏可用性
5 个主 Tab 是高频导航入口,不能使用 Qt 默认的紧凑宽度。`MainWindow` 必须为 `QTabWidget/QTabBar` 设置基础样式:
- 每个 Tab 设置稳定最小宽度和足够左右 padding,避免文字贴边或窄到误点。
- Tab 之间保留明显间距,当前 Tab 有清晰背景/边框高亮。
- 样式只影响顶层主 Tab,不改变各业务表格、弹窗和后续 Tab 内部布局。
- 新增业务 Tab 内容时不得缩小主 Tab 栏点击区域。
2026-07-07 15:30:04 +08:00
## 全局状态栏反馈
2026-07-07 15:42:19 +08:00
左下角状态栏用于低打扰反馈,T-543 已统一由 `MainWindow.show_status(message, level)` 控制语义色:
2026-07-07 15:30:04 +08:00
- 普通/导航/就绪:muted 或系统默认,例如「就绪」「当前:② AI生成」。
- 信息/进行中:info,例如「正在生成标题」「检测登录中」。
- 成功:success,例如「设置已保存」「已回写 Excel」。
- 警告/需用户处理:warning,例如「当前筛选结果没有待生成任务」「请先到①完成旧数据采集」「请先配置 cmhub」。
- 错误/阻断:danger,例如「更新失败」「账号未登录」「数据目录不可写」「点数不足」。
状态栏只改变文字色,不做大面积背景;它不能替代弹窗、空状态、运行日志、按钮禁用和任务状态列。普通提示必须重置状态栏颜色,避免上一条错误或成功颜色残留。
2026-06-26 15:30:37 +08:00
## 首次使用引导保护
2026-07-07 14:58:54 +08:00
- ① 导入采集 与 ③ 更新蝦皮 都依赖**账号已配置且已登录**(在 ④ 账号管理)。
2026-06-27 14:37:58 +08:00
- 当无账号 / 对应账号 Chrome 未启动 / 账号未登录时:相关执行按钮**禁用或在执行前汇总拦截**,并提示「请先到『账号管理』配置账号并登录」。
2026-07-01 08:35:46 +08:00
- ③ 点击「开始更新」后必须检查当前筛选结果涉及的账号;只要有账号 Chrome 未启动、CDP 端口不可访问或 Shopee 未登录,就弹窗列出账号并中止本轮更新,不创建真实更新 worker,不提交任何商品。
2026-07-06 15:01:50 +08:00
- 可以提供「打开账号管理」或「启动登录」入口辅助用户处理当前账号;不要无提示批量启动所有账号 Chrome,避免开错账号或启动过多浏览器进程。用户主动点击④「启动登录」时也必须先检查该账号 CDP 端口,已打开则复用现有 Chrome 并打开/激活卖家中心 tab,不重复 `Popen` 新窗口。
2026-06-26 15:30:37 +08:00
- 老用户账号已就绪则无感。
## ① 导入采集
```
┌ 导入采集 ─────────────────────────────────────────────────────┐
│ [导入 Excel…] [移除] [清空] │
│ ▸ 3 文件 · 128 行 · 有效125/无效3 · 匹配123 · 未匹配5⚠ │ ← 导入汇总栏
│ 匹配明细:女装店60 · my主店40 · 饰品店23 │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 账号名 别名 商品ID 阶段 旧标题 旧封面 │ │
│ │ 主店A 女装店 51100639510 待采集 — — │ │
│ └───────────────────────────────────────────────────────────┘ │
│ [▶ 采集旧标题/旧封面] [■停止] [回写旧数据到 Excel] │
2026-06-29 17:49:45 +08:00
│ 日志:逐条 文件→匹配账号、采集步骤、失败原因 │
2026-06-26 15:30:37 +08:00
└───────────────────────────────────────────────────────────────┘
```
- 导入:openpyxl 解析**输入列**(账号名/别名/商品id)入 SQLite。
- **导入汇总栏**(导入后即时刷新,跑采集前的校验关口):显示 文件数、解析行数(原始数据量)、有效/无效行、匹配账号行数(按账号细分)、未匹配行数。未匹配/无效数字标红可点,点击在列表筛出便于定位纠错。
2026-07-07 14:12:32 +08:00
- 采集:用该账号已启动并登录的 Chrome 只读打开商品页,读旧标题、下载旧封面到 `data/images/<batch_id>/<slug>/<task_id>_<item_id>_old.jpg` ,写 `old_title/old_cover_path` , stage=collected。若程序为采集自动新建商品页 tab,采集结束后自动关闭;若复用用户原本打开的 tab,则不关闭。
2026-07-02 21:46:32 +08:00
- 若商品 ID 已失效、无权限或店铺不匹配,Shopee 可能只弹出短暂错误 toast;采集失败时界面日志应显示捕获到的 toast 文案,并把 toast HTML/URL 写入本地诊断日志,避免用户手动抢复制。只有明确捕获商品失效/商品不存在/无权限类 toast 时,①列表“阶段”列显示“商品失效”;其他商品页打开失败仍显示“失败”。如果失败发生在 `open_product()` 内部,本轮自动新建的商品 tab 必须关闭,复用用户已有 tab 不关闭。
2026-07-02 17:32:51 +08:00
2026-06-27 14:37:58 +08:00
- 回写:采集完成后自动把旧标题/旧封面路径批量回写原 Excel;保留「回写旧数据到 Excel」作为手动重试入口(原文件被锁→提示关闭后重试/另存)。
2026-07-07 14:12:32 +08:00
- 别名未匹配账号 / 账号未登录 → 该行 skipped 并记原因。`T-207` 接入后,① 采集会像③更新一样写 `run_logs/run_log_events` ,并把完整脱敏 traceback 写入本地 `data/logs/` ,用于定位失败卡在哪个步骤。
2026-06-26 15:30:37 +08:00
2026-07-07 14:58:54 +08:00
- 「删除批次」位于①批次筛选旁,只能对当前选中的具体批次执行,不能在“全部批次”下执行;运行中禁用。删除是软删除:写本地批次删除标记,不物理删除 DB 记录,不删除原 Excel,不回滚蝦皮。删除后该批次不再出现在①/②/③任何批次下拉、任务列表、筛选、采集、生成、更新、回写入口中。确认框必须显示任务数、已上线任务数,并提示软删除只隐藏本地批次、不会回滚线上修改。
2026-06-26 15:30:37 +08:00
## ② AI生成
左右布局:左侧约 1/4 放提示词,右侧放筛选 + 任务列表。
```
┌ AI生成 ───────────────────────────────────────────────────────┐
│ ┌─左 ~1/4─┐ ┌──────────────── 右 3/4 ──────────────────────┐ │
2026-06-29 17:49:45 +08:00
│ │标题提示词│ │ 批次[本次▼] 店铺[全部▼] 商品ID[____] 状态[全部▼] [筛选] │ │
2026-06-26 15:30:37 +08:00
│ │[ ]│ │ ┌──────────────────────────────────────────┐ │ │
│ │[ ]│ │ │ 店铺名 商品id 旧标题 新标题 状态 │ │ │
│ │ │ │ │ 女装店 511..639 …T恤 …百搭 已生成 │ │ │
│ │封面提示词│ │ │ 女装店 511..640 … — 待生成 │ │ │
│ │[ ]│ │ └──────────────────────────────────────────┘ │ │
│ │[ ]│ │ (双击某行 → 弹窗看 旧封面 | 新封面) │ │
2026-06-29 17:49:45 +08:00
│ │ │ │ 运行日志:逐条记录标题/封面生成步骤与失败原因 │ │
2026-06-26 15:30:37 +08:00
│ └──────────┘ └───────────────────────────────────────────────┘ │
2026-07-02 15:17:11 +08:00
│ [ ] 生成封面图片(成本较高) 进度:标题30/30 · 图片0/0 · 失败1 [▶ 开始生成][■停止][重置生成结果] │
2026-06-26 15:30:37 +08:00
└───────────────────────────────────────────────────────────────┘
```
- 左侧(提示词管理,上下两块):
2026-07-07 14:12:32 +08:00
- **标题提示词**:多行输入 + 「保存」(写 `data/title_prompt.txt` );启动时自动加载回显。
- **封面提示词**:模板下拉(读 `data/prompts/cover/*.txt` )+ 图标工具栏(新建/保存/另存为/重命名/删除)+ 多行输入 + 「插入标题」(插 `{新标题}` ) /「预览」(变量替换后查看)。
2026-06-26 15:30:37 +08:00
- 变量:`{旧标题}` /`{新标题}` /`{商品id}` /`{店铺}` ,生成前按任务替换。
2026-06-29 17:49:45 +08:00
- 右上:按导入批次 / 店铺 / 商品ID / 状态筛选任务;商品ID输入框按包含匹配 `item_id` ,清空表示全部。
2026-07-01 14:30:49 +08:00
- 右下:任务列表(店铺名、商品id、旧标题、新标题、状态)+ AI生成运行日志;已生成、未提交线上、非运行中的任务可双击「新标题」列本地微调,写回 `tasks.new_title` ,清空 `last_error` 并回到可更新;双击其他列弹窗展示旧封面 | 新封面(纯查看)。
2026-07-02 15:17:11 +08:00
- 底部**单个「开始生成」+「停止」**,并增加「生成封面图片(成本较高)」复选框:默认不勾选,只生成标题;勾选后才在标题完成后按 `image_concurrency` 并发生成封面。该开关状态持久化到 `config.json` 的 `ai.generate_cover` ,但入口放在②,便于用户在每轮生成前做成本判断。
2026-07-04 17:59:23 +08:00
- 生成参数(标题/图片并发数、失败重试、分辨率、jpg 质量、cmhub 网关/Key/别名)在 ** ⑤ 设置**;②只暴露“本轮是否生成封面”的成本开关。
2026-07-07 14:12:32 +08:00
- 标题-only 模式标题成功即写库并进入 `generated` , `new_cover_path` 留空;标题+封面模式图片成功后写入本地新封面路径。两种模式都写 `run_type=generate` 的 `run_logs/run_log_events` 和用户可读滚动日志;未勾选生成封面时日志明确显示“本轮仅生成标题”。点击「开始生成」时先清空②界面可见日志并写入本轮开始摘要,运行中只追加本轮日志;不删除历史 `run_logs/run_log_events` 或本地 `data/logs/` 。进入页面默认可显示“本轮日志会在开始运行后显示”,历史日志不自动混入当前运行界面。「停止」取消未开始项,可再次「开始生成」对剩余继续。
2026-07-07 14:58:54 +08:00
- 「重置生成结果」仅作用当前选中单条,运行中禁用;确认后只改本地 DB,清空 `new_title/new_cover_path/last_error` 并退回 `collected/success` 供重新生成,默认不删除本地新封面文件。若该记录已提交过线上,必须在确认框提示本地重置不回滚蝦皮。
2026-07-01 14:30:49 +08:00
- **无逐条人工审核环节**;新标题默认直接用 AI 输出,但允许对已生成且未提交线上的单行做本地微调;可选对单行 `重生成` 。生成完即可进入 ③,③ 开始更新前会做批量确认。
2026-06-26 15:30:37 +08:00
2026-07-07 14:58:54 +08:00
## ③ 更新蝦皮
2026-06-26 15:30:37 +08:00
```
2026-07-07 14:58:54 +08:00
┌ 更新蝦皮 ───────────────────────────────────────────────────┐
2026-06-29 17:49:45 +08:00
│ 批次[本次▼] 店铺[全部▼] 商品ID[____] 状态[已生成▼] [筛选] │
2026-06-29 09:18:03 +08:00
│ ⚠ 点击「开始更新」后先过安全开关,再确认【当前筛选结果】并提交 │
2026-06-26 15:30:37 +08:00
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 店铺 商品ID 新标题 新封面 阶段 结果 │ │
│ └───────────────────────────────────────────────────────────┘ │
2026-07-01 14:30:49 +08:00
│ 运行日志:检查/真实更新逐条留痕 │
│ [检查本轮更新] [▶ 开始更新] [■停止] [回写结果到 Excel] │
2026-06-26 15:30:37 +08:00
└───────────────────────────────────────────────────────────────┘
```
2026-06-29 17:49:45 +08:00
- 顶部**按批次 / 店铺 / 商品ID / 状态筛选**(与 ①②一致);商品ID输入框按包含匹配 `item_id` ,清空表示全部;「开始更新」作用于**当前筛选结果**,是一道范围控制。
2026-06-26 15:30:37 +08:00
- 店铺筛选:建议**逐店铺更新**(每店铺需先启动其 Chrome 并登录)。
- 状态筛选:`已生成` 只跑未更新的;`失败` 用于**失败重试**; `已更新成功/略过` 仅查看。
2026-07-01 14:30:49 +08:00
- 「检查本轮更新」只读取当前筛选结果并写运行日志,不打开 Shopee、不提交、不改任务状态;弹窗/日志展示总任务数、店铺分布、会更新标题/封面、略过原因、每批最大条数和预计批次数。
- 点击「开始更新」先读取 ⑤ `shopee_update` 安全设置:未允许真实提交,或包含新封面但未允许封面更新时,直接弹警告并阻断;拦截弹窗必须写明具体未开启的设置项,并提供「前往设置」跳到 ⑤;普通正式更新不再以测试商品 ID 限制当前筛选结果,允许当前筛选结果包含多个真实商品 ID;`max_items_per_run` 作为**每批最大更新条数**,当前筛选总数超过该值时不阻断,而是自动分批执行。
2026-07-01 08:35:46 +08:00
- 安全开关通过后,弹窗展示本次筛选条件、任务总数、每批最大条数、预计批次数、安全设置和“将提交线上”的风险提示;用户点「是/确认」才开始,点「否/取消」不执行。
- 真实更新第一条商品前做账号就绪预检:按当前筛选结果汇总需要的账号;无账号、Chrome 未启动、CDP 端口不可访问、未登录或端口冲突时,弹窗列出具体账号/原因并中止本轮,不自动调用「启动登录」或静默打开 Chrome。
2026-06-30 11:50:49 +08:00
- 对确认后的**已生成(generated)任务**执行:打开编辑页换标题+换封面 → 点页面「更新」 → 如 Shopee 弹出“確定您要更新商品嗎?”确认框(`.eds-modal__content` / `.eds-modal__box` ),则只点弹窗主按钮「更新」提交,不点「立即優化」。
2026-07-02 21:46:32 +08:00
- 打开编辑页失败时,如果 Shopee 弹出错误 toast(如商品 ID 不正确、商品不存在、无权限),③运行日志和任务失败原因必须显示该 toast 文案;同时把 toast HTML/URL/时间写入本地诊断日志。用户不需要手动复制瞬时 toast 的 HTML。
2026-07-02 17:32:51 +08:00
2026-07-01 08:35:46 +08:00
- 更新封面时统一按替换第一张执行:删除第一张前必须已有该任务的本地旧封面备份(①采集得到的 `old_cover_path` 且文件存在);备份缺失时阻断该条更新并提示先采集/修复备份,不盲删线上图片。
2026-06-29 10:25:09 +08:00
- 默认串行、单条失败继续;⑤ 可开启多账号并行,不同账号同时执行,同一账号内仍串行;真实更新前若本轮账号调试端口冲突则阻断。
2026-07-01 14:30:49 +08:00
- 「检查本轮更新」只写运行日志与检查汇总,不打开 Shopee、不调用 `editor.apply_task()` 、不写任务状态、不回写 Excel。
2026-07-07 14:12:32 +08:00
- 真实更新每条立即写回 SQLite( committed/状态/error),失败不阻塞后续任务;检查和真实更新都会写 `run_logs/run_log_events` 。点击「检查本轮更新」或「开始更新」时先清空③界面可见日志并写入本轮检查/更新开始摘要,运行中只追加本轮日志;不删除历史 `run_logs/run_log_events` 或本地 `data/logs/` ,历史日志不自动混入当前运行界面。
2026-07-01 08:35:46 +08:00
- 分批更新时「停止」为协作式停止:已开始的当前商品跑到安全边界并写库后停止,不再开始新商品、不进入下一批;未开始任务保持原状态,下次可继续。
- 更新前做账号就绪预检:无账号、对应账号 Chrome 未启动、CDP 端口不可访问或未登录时整体阻断并引导去④账号管理,不进入逐条提交,也不自动打开账号 Chrome。
2026-07-02 21:46:32 +08:00
- 若 ⑤ 开启“成功后关闭本次新开编辑页”,则仅关闭本轮程序自动新开且成功提交的商品页;确认后跳回我的商品列表页时,关闭前等待 2 秒;已进入编辑页后的失败任务和用户原本打开的 tab 不关闭。但如果失败发生在 `open_product()` 内部,程序自动新开的无效商品页 tab 要关闭,避免 Chrome 残留空错误页。
2026-07-01 14:30:49 +08:00
- 「开始更新」是③的主操作按钮,视觉上必须强于其他批处理按钮。
2026-07-07 14:58:54 +08:00
- 「重置更新状态」从底部批处理按钮移到任务表右键菜单/高级入口,仅作用当前选中单条,运行中禁用;保留 `new_title/new_cover_path` ,只把本地状态退回可更新,用于重复测试上传/提交。若 `committed=1` ,确认框必须提示线上已提交过、本地重置不回滚蝦皮、重复更新会再次提交;不得静默清除 committed 历史事实。
2026-06-27 17:28:33 +08:00
- 更新完成后自动回写原 Excel:写入新标题、新封面图片路径、更新状态;原文件被锁时提示关闭后点击「回写结果到 Excel」手动重试。
- 自动回写完成后弹窗汇总成功/失败/略过数量与 Excel 回写文件/行数。
2026-06-26 15:30:37 +08:00
## ④ 账号管理
```
┌ 账号管理 ─────────────────────────────────────────────────────┐
│ 账号名 别名 地区 端口 登录状态 备注 │
│ 主店A 女装店 seller.shopee.tw 9222 ●已登录 │
│ [+新增][✎编辑][🗑删除] [▶启动并登录][🔄检测登录][⧉快捷方式] │
└───────────────────────────────────────────────────────────────┘
```
2026-06-29 10:05:16 +08:00
账号弹窗字段:账号名、别名(唯一,Excel 用它匹配)、地区域名、调试端口、密码(本地明文仅参考,保存/变更时提示,UI 打码,不自动登录)、备注;配置目录按别名生成 slug 只读显示。
2026-06-26 15:30:37 +08:00
## ⑤ 设置
2026-07-06 11:32:02 +08:00
- 设置页整体布局:内容区居中,左右留白已从 T-506 初始实现缩短到约 40%;实现上用最大内容宽度 + 自适应 margin,而不是写死窗口像素。所有设置组默认响应式 3 列表单:短字段占 1 格,URL/API Key/路径等长字段跨 2 格或 3 格;窄窗口自动降为 2 列/1 列。点击「保存设置」成功后,状态栏显示“设置已保存”,并弹出轻量提示框。T-531 已完成:保存成功会清除未保存标记;保存失败时保留未保存标记并阻止离开。
2026-07-06 10:56:42 +08:00
- cmhub 网关配置(T-529 后普通用户唯一 AI 入口):⑤设置页不再显示「AI 后端」label 或 direct/cmhub 下拉,直接展示 cmhub 网关 Base URL、API Key、生文别名、生图别名、连接超时、刷新别名、测试连接/查余额;Base URL 输入框旁提示“只填网关根,如 https://host”,保存/刷新前会规整掉 `/api` 、`/api/v1` 或其它路径。刷新别名/测试连接使用当前输入框内容发起请求,但不自动保存 URL/API Key,成功文案需提醒“记得点保存设置持久化”。
2026-07-06 15:56:28 +08:00
- T-532 需求:测试连接/查余额成功时,如果 cmhub `/balance` 返回账号名、用户名或邮箱等可识别信息,成功提示应显示 `cmhub 账号「<账号名>」连接成功:...` ,让用户确认当前 API Key 属于哪个 cmhub 账号;当前接口结构兼容 `{ "user": "cmhub_user", "points_balance": 88, "account": { "username": "cmhub_user", "display_name": "主账号" } }` ,优先显示 `account.display_name` ,没有时再用 `account.username` / `user` 等兜底;邮箱需脱敏,没有账号信息时保留 `cmhub 连接成功:...` 兜底文案。
2026-07-07 14:12:32 +08:00
- API Key 存在 `data/config/cmhub.json` ,本地明文保存;保存/变更时提示;UI 使用密码框打码显示,不进入日志/导出。
2026-07-04 17:59:23 +08:00
- 生文/生图别名来自 `GET /api/v1/models` 动态下拉,过滤未定价别名并展示单价/需原图提示;网关临时不可达时保留已存别名。
- 保存设置固定写 `ai.backend=cmhub` 。允许先保存不完整 cmhub 配置,②真正生成时如果缺 Base URL/API Key/别名,会提示去⑤补配置,不静默回退 direct。
2026-07-06 11:32:02 +08:00
- T-531 已完成:⑤设置页任意可编辑控件变更都进入未保存状态,保存按钮旁显示“● 未保存更改”;切换到其它 Tab 或关闭窗口时弹出保存/放弃/取消。放弃会重新从本地配置文件回填控件,避免未保存的 URL/API Key 留在界面上;程序化回填、保存后重载和刷新别名填充下拉不会误触发未保存状态。
2026-07-07 14:12:32 +08:00
- direct 模型清单和 `data/config/ai_models.json` 代码路径保留为内部兼容/手工回滚,不在普通 UI 暴露。
2026-07-04 17:59:23 +08:00
- AI 生成参数:标题并发、图片并发、失败重试、分辨率、返回超时、jpg 质量等短字段按三列排列。
2026-06-29 08:58:39 +08:00
- 分辨率为 `512 / 1k / 2k / 4k` ;返回超时只读展示 `resolution_timeouts[resolution]` ,不单独编辑。
2026-07-04 17:59:23 +08:00
- 保存写入 `config.json` 的 `ai` 段,供 ② AI生成复用;标题/图片模型角色下拉随 direct UI 一起隐藏。
2026-07-07 15:24:08 +08:00
- 路径与端口(T-501b/T-506/T-539 已接入):组件组改为 3 个组件一组;普通设置页只显示 Chrome 路径、默认端口、端口起止、CDP 就绪超时。T-538 后账号数据根目录、图片目录、DB 路径固定解析到 `data/` 下,普通 UI 不再提供输入框,避免用户误改后数据分裂;`config.json` 中 `user_data_root` / `image_dir` / `db_path` 字段继续作为内部兼容字段保留,手工配置值仍会被读取和保存。
2026-07-07 14:58:54 +08:00
- 蝦皮更新安全(T-501c/T-506 已接入):组件组改为 3 个组件一组;允许真实提交、允许更新封面、每批最大更新条数、成功后关闭本次新开编辑页等短字段三列排列;「多账号并行更新」与「最大并行账号数」必须合并为同一个横向组件,最大并行账号数紧跟在多账号并行更新后面,不允许换到下一行;测试商品 ID 仅作为历史/调试兼容字段保留,不参与普通正式更新安全检查,普通设置页已隐藏该入口。
2026-07-01 08:35:46 +08:00
- 默认关闭真实提交和封面更新,每批最大更新条数默认 1。
2026-06-29 09:18:03 +08:00
- ③ 点击「开始更新」会读取这些设置,先拦截不符合条件的更新,再弹确认框。
2026-07-01 14:30:49 +08:00
- 更新执行模式(T-504/T-506 已接入):⑤ 只保留多账号并行更新、最大并行账号数等执行设置;“dry-run”不再作为用户可见开关,改到③成为「检查本轮更新」按钮。
2026-07-01 08:35:46 +08:00
- 默认多账号并行关闭;开启多账号并行后同一账号内仍串行。
2026-06-26 15:30:37 +08:00
## 流程导航
```text
2026-07-06 15:01:50 +08:00
④ 账号管理:配账号 + 启动登录(首次必做;重复点击应复用已打开 Chrome)
2026-06-26 15:30:37 +08:00
│
2026-06-27 14:37:58 +08:00
① 导入采集:导入 Excel → 采集旧标题/旧封面 → 自动回写旧字段(失败可手动重试)
2026-06-26 15:30:37 +08:00
│
2026-07-02 15:17:11 +08:00
② AI生成:提示词 → 生成新标题/可选生成新封面(无逐条审核)
2026-06-26 15:30:37 +08:00
│
2026-07-07 14:58:54 +08:00
⑤ 设置:配置蝦皮更新安全、每批最大更新条数和执行模式
2026-06-29 09:18:03 +08:00
│
2026-07-07 14:58:54 +08:00
③ 更新蝦皮:对已生成任务点击开始更新 → 安全开关检查 → 弹窗确认 → 账号就绪预检(未启动/未登录则中止) → 换标题/允许时换封面 → 点「更新」提交 → 回写结果 → 弹窗汇总
2026-06-26 15:30:37 +08:00
```
2026-07-01 08:35:46 +08:00
- 未配账号 / Chrome 未启动 / 未登录:① ③ 的执行按钮禁用或执行前提示去 ④;③ 不静默启动缺失账号 Chrome。
2026-06-29 09:18:03 +08:00
- 已生成的任务即可进 ③;③ 通过 ⑤ 安全开关并经用户确认批量弹窗后提交线上,无常驻提交开关。
2026-06-26 15:30:37 +08:00
- 任意步骤失败:记入该任务、日志标明,不影响其他任务。
2026-06-26 16:09:09 +08:00
## 组件建议(PySide6)
2026-06-26 15:30:37 +08:00
| 组件 | 归属 | 说明 |
| --- | --- | --- |
2026-06-26 16:09:09 +08:00
| `MainWindow(QMainWindow)` | 根窗口 | 持有 `QTabWidget` 、状态栏、全局消息 |
| `CollectTab(QWidget)` | ① | 导入、任务表、采集、回写 |
2026-07-02 15:17:11 +08:00
| `GenerateTab(QWidget)` | ② | 左提示词管理 + 右筛选/任务列表;双击看新旧封面;开始生成/停止/进度;本轮「生成封面图片(成本较高)」开关接入 `GenerateWorker` |
2026-07-07 14:58:54 +08:00
| `ApplyTab(QWidget)` | ③ | 已生成任务筛选 +「检查本轮更新」+ 蝦皮更新安全拦截 + 分批开始更新确认 + 检查/真实更新运行日志 + 结果回写与结束汇总 |
2026-07-02 22:38:08 +08:00
| `AccountsTab(QWidget)` | ④ | 账号增删改、启动登录、检测登录、生成快捷方式;登录检测把 Shopee accounts 登录页判为未登录 |
2026-07-07 15:24:08 +08:00
| `SettingsTab(QWidget)` | ⑤ | cmhub 网关配置 + 响应式三列设置表单 + 生成参数 + Chrome/端口配置 + 蝦皮更新安全;数据路径字段隐藏但保留配置兼容 |
2026-06-26 16:09:09 +08:00
| `TaskTableModel(QAbstractTableModel)` | ①②③ | 任务表格数据模型,供 `QTableView` 使用 |
| `BaseWorker(QObject)` | 后台 | 定义 `progress/log/row_updated/failed/finished/cancelled` signals |
2026-07-01 14:30:49 +08:00
| `ApplyWorker(BaseWorker)` | ③ | 账号就绪预检、检查本轮更新、按每批最大条数分批、按账号并行或串行调用 `editor.apply_task(..., close_success_tab=...)` 、逐条 `set_applied()` ,失败继续,写运行日志 |
2026-06-29 08:45:04 +08:00
| `AIModelTestWorker(BaseWorker)` | ⑤ | 后台调用 `appconfig.test_ai_model()` 测试模型连接 |
2026-06-27 17:28:33 +08:00
| `WriteBackWorker(BaseWorker)` | ①③ | ①回写旧字段;③回写新标题/新封面/更新状态 |
2026-06-26 15:30:37 +08:00
2026-06-26 16:09:09 +08:00
> 采集、生成、更新都是耗时操作,使用 `QObject` worker + `QThread`。Worker 不直接操作 QWidget,只通过 signal 通知主线程刷新 UI。