Files
cmshoppe/docs/routes.md
T
chengma 04ff06a2e3 feat: 完成T-402确认后串行更新
③更新shopee在开始更新确认后创建ApplyWorker,按当前筛选结果串行调用editor.apply_task并逐条set_applied落库。

新增更新前账号就绪预检:无账号、Chrome未启动或未登录时整体阻断并引导到④账号管理,未确认或预检失败均不调用apply。

补充GUI开始/停止/进度刷新以及成功、失败、未匹配账号继续处理的单元测试,同步任务看板、API、流程和当前状态文档。
2026-06-27 17:13:18 +08:00

13 KiB
Raw Blame History

界面与流程结构

桌面工具,无前端路由。用 5 Tab GUI(PySide6 QMainWindow + QTabWidget)+ 流水线 约定界面职责与导航。

Tab 顺序与职责(工作流优先)

① 导入采集 │ ② AI生成 │ ③ 更新shopee │ ④ 账号管理 │ ⑤ 设置
Tab 职责 风险
① 导入采集 导入多个 Excel;任务列表;采集商品当前的旧标题/旧封面(只读),封面图下载本地;回写 Excel 旧字段 只读,低
② AI生成 左侧标题/封面提示词;右侧按批次/店铺筛选任务列表;AI 生成新标题/新封面;双击看新旧封面 不触线上,中
③ 更新shopee 对已生成任务点击「开始更新」后弹窗确认;确认后打开编辑页换标题+封面并逐条点「更新」提交;结果回写 Excel 写线上,高
④ 账号管理 Shopee 账号(账号名/别名/数据目录/端口/密码本地明文仅参考/登录状态);启动登录、检测登录、生成快捷方式 中
⑤ 设置 AI 模型/API Key、本地图片目录、Chrome 路径、默认端口等 —

任务的阶段状态贯穿各 Tab:imported → collected → generated → applied(或 failed/skipped)。② 不设逐条人工确认阶段;③ 无常驻提交开关,但点击「开始更新」后必须弹窗确认当前筛选范围和任务数量。各 Tab 聚焦各自阶段的列与按钮,但操作同一批任务(同一 batch)。

全局 Tab 栏可用性

5 个主 Tab 是高频导航入口,不能使用 Qt 默认的紧凑宽度。MainWindow 必须为 QTabWidget/QTabBar 设置基础样式:

  • 每个 Tab 设置稳定最小宽度和足够左右 padding,避免文字贴边或窄到误点。
  • Tab 之间保留明显间距,当前 Tab 有清晰背景/边框高亮。
  • 样式只影响顶层主 Tab,不改变各业务表格、弹窗和后续 Tab 内部布局。
  • 新增业务 Tab 内容时不得缩小主 Tab 栏点击区域。

首次使用引导保护

  • ① 导入采集 与 ③ 更新shopee 都依赖账号已配置且已登录(在 ④ 账号管理)。
  • 当无账号 / 对应账号 Chrome 未启动 / 账号未登录时:相关执行按钮禁用或在执行前汇总拦截,并提示「请先到『账号管理』配置账号并登录」。
  • 可以提供「打开账号管理」或「启动登录」入口辅助用户处理当前账号;不要无提示批量启动所有账号 Chrome,避免开错账号或启动过多浏览器进程。
  • 老用户账号已就绪则无感。

① 导入采集

┌ 导入采集 ─────────────────────────────────────────────────────┐
│ [导入 Excel…] [移除] [清空]                                    │
│ ▸ 3 文件 · 128 行 · 有效125/无效3 · 匹配123 · 未匹配5⚠         │ ← 导入汇总栏
│   匹配明细:女装店60 · my主店40 · 饰品店23                      │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 账号名  别名     商品ID       阶段        旧标题  旧封面    │ │
│ │ 主店A  女装店  51100639510  待采集       —      —          │ │
│ └───────────────────────────────────────────────────────────┘ │
│ [▶ 采集旧标题/旧封面]  [■停止]      [回写旧数据到 Excel]       │
│ 日志:逐条 文件→匹配账号、采集结果                             │
└───────────────────────────────────────────────────────────────┘
  • 导入:openpyxl 解析输入列(账号名/别名/商品id)入 SQLite。
  • 导入汇总栏(导入后即时刷新,跑采集前的校验关口):显示 文件数、解析行数(原始数据量)、有效/无效行、匹配账号行数(按账号细分)、未匹配行数。未匹配/无效数字标红可点,点击在列表筛出便于定位纠错。
  • 采集:用该账号已启动并登录的 Chrome 只读打开商品页,读旧标题、下载旧封面到本地图片目录,写 old_title/old_cover_path,stage=collected。若程序为采集自动新建商品页 tab,采集结束后自动关闭;若复用用户原本打开的 tab,则不关闭。
  • 回写:采集完成后自动把旧标题/旧封面路径批量回写原 Excel;保留「回写旧数据到 Excel」作为手动重试入口(原文件被锁→提示关闭后重试/另存)。
  • 别名未匹配账号 / 账号未登录 → 该行 skipped 并记原因。

② AI生成

左右布局:左侧约 1/4 放提示词,右侧放筛选 + 任务列表。

┌ AI生成 ───────────────────────────────────────────────────────┐
│ ┌─左 ~1/4─┐ ┌──────────────── 右 3/4 ──────────────────────┐ │
│ │标题提示词│ │ 批次[本次▼] 店铺[全部▼] 状态[全部▼] [筛选]    │ │
│ │[        ]│ │ ┌──────────────────────────────────────────┐ │ │
│ │[        ]│ │ │ 店铺名  商品id     旧标题    新标题  状态 │ │ │
│ │          │ │ │ 女装店 511..639  …T恤    …百搭  已生成 │ │ │
│ │封面提示词│ │ │ 女装店 511..640  …       —      待生成 │ │ │
│ │[        ]│ │ └──────────────────────────────────────────┘ │ │
│ │[        ]│ │  (双击某行 → 弹窗看 旧封面 | 新封面)         │ │
│ └──────────┘ └───────────────────────────────────────────────┘ │
│  进度:标题30/30 · 封面12/30 · 失败1       [▶ 开始生成] [■停止]  │
└───────────────────────────────────────────────────────────────┘
  • 左侧(提示词管理,上下两块):
    • 标题提示词:多行输入 + 「保存」(写 title_prompt.txt);启动时自动加载回显。
    • 封面提示词:模板下拉(读 prompts/cover/*.txt)+ 图标工具栏(新建/保存/另存为/重命名/删除)+ 多行输入 + 「插入标题」(插 {新标题})/「预览」(变量替换后查看)。
    • 变量:{旧标题}/{新标题}/{商品id}/{店铺},生成前按任务替换。
  • 右上:按导入批次 / 店铺 / 状态筛选任务。
  • 右下:任务列表(店铺名、商品id、旧标题、新标题、状态);双击某条 → 弹窗展示旧封面 | 新封面(纯查看)。
  • 底部单个「开始生成」+「停止」:开始生成 = 先按 title_concurrency 并发生成标题,接着按 image_concurrency 并发生成封面;进度实时显示 标题/封面/失败 计数。
  • 生成参数(标题/图片并发数、失败重试、分辨率、jpg 质量、模型/Key)在 ⑤ 设置,不在本 Tab 重复。
  • 每条/每张完成即写库;「停止」取消未开始项,可再次「开始生成」对剩余继续。
  • 无逐条人工审核环节;新标题直接用 AI 输出(不可编辑);可选对单行 重生成。生成完即可进入 ③,③ 开始更新前会做批量确认。

③ 更新shopee

┌ 更新shopee ───────────────────────────────────────────────────┐
│ 批次[本次▼] 店铺[全部▼] 状态[已生成▼] [筛选]                   │
│ ⚠ 点击「开始更新」后确认【当前筛选结果】,确认后改标题+换封面并提交 │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 店铺  商品ID       新标题      新封面   阶段    结果       │ │
│ └───────────────────────────────────────────────────────────┘ │
│ [▶ 开始更新] [■停止]                    [回写结果到 Excel]     │
└───────────────────────────────────────────────────────────────┘
  • 顶部按批次 / 店铺 / 状态筛选(与 ①②一致);「开始更新」作用于当前筛选结果,是一道范围控制。
    • 店铺筛选:建议逐店铺更新(每店铺需先启动其 Chrome 并登录)。
    • 状态筛选:已生成 只跑未更新的;失败 用于失败重试;已更新成功/略过 仅查看。
  • 点击「开始更新」后弹窗展示本次筛选条件、任务数量和“将提交线上”的风险提示;用户点「是/确认」才开始,点「否/取消」不执行。
  • 对确认后的已生成(generated)任务执行:打开编辑页换标题+换封面 → 点「更新」提交。
  • 串行、单条失败继续;每条立即写回 SQLite(committed/状态/error),失败不阻塞后续任务。
  • 更新前做账号就绪预检:无账号、对应账号 Chrome 未启动或未登录时整体阻断并引导去④账号管理,不进入逐条提交。
  • 更新结果回写原 Excel 与结束弹窗汇总留给 T-403。

④ 账号管理

┌ 账号管理 ─────────────────────────────────────────────────────┐
│ 账号名  别名     地区              端口  登录状态  备注        │
│ 主店A  女装店  seller.shopee.tw  9222  ●已登录                │
│ [+新增][✎编辑][🗑删除]  [▶启动并登录][🔄检测登录][⧉快捷方式] │
└───────────────────────────────────────────────────────────────┘

账号弹窗字段:账号名、别名(唯一,Excel 用它匹配)、地区域名、调试端口、密码(本地明文仅参考,UI 打码,不自动登录)、备注;配置目录按别名生成 slug 只读显示。

⑤ 设置

  • AI:服务商 / 文本模型 / 图像模型 / API Key(本地明文存,UI 打码,不入日志)。
  • AI 生成参数:标题并发数、图片并发数、失败重试次数、分辨率、jpg 质量。
  • 本地图片目录(旧封面下载、新封面生成的存放根目录)。
  • Chrome 路径、默认调试端口 / 端口范围、超时、DB 路径。

流程导航

④ 账号管理:配账号 + 启动登录(首次必做)
        │
① 导入采集:导入 Excel → 采集旧标题/旧封面 → 自动回写旧字段(失败可手动重试)
        │
② AI生成:提示词 → 生成新标题/新封面(无逐条审核)
        │
③ 更新shopee:对已生成任务点击开始更新 → 弹窗确认 → 换标题+封面 → 点「更新」提交 → T-403 回写结果
  • 未配账号 / Chrome 未启动 / 未登录:① ③ 的执行按钮禁用或执行前提示去 ④。
  • 已生成的任务即可进 ③;③ 用户确认批量弹窗后提交线上,无常驻提交开关。
  • 任意步骤失败:记入该任务、日志标明,不影响其他任务。

组件建议(PySide6)

组件 归属 说明
MainWindow(QMainWindow) 根窗口 持有 QTabWidget、状态栏、全局消息
CollectTab(QWidget) ① 导入、任务表、采集、回写
GenerateTab(QWidget) ② 左提示词管理 + 右筛选/任务列表;双击看新旧封面;开始生成/停止/进度已接入 GenerateWorker
ApplyTab(QWidget) ③ 已生成任务筛选 + 开始更新确认 + 确认后串行更新已接入;回写由 T-403 接入
AccountsTab(QWidget) ④ 账号增删改、启动登录、检测登录、生成快捷方式
SettingsTab(QWidget) ⑤ AI/目录/Chrome 配置
TaskTableModel(QAbstractTableModel) ①②③ 任务表格数据模型,供 QTableView 使用
BaseWorker(QObject) 后台 定义 progress/log/row_updated/failed/finished/cancelled signals
ApplyWorker(BaseWorker) ③ 账号就绪预检、串行调用 editor.apply_task()、逐条 set_applied(),失败继续

采集、生成、更新都是耗时操作,使用 QObject worker + QThread。Worker 不直接操作 QWidget,只通过 signal 通知主线程刷新 UI。