feat(gui): hide AI studio tab
This commit is contained in:
@@ -166,6 +166,7 @@ class MainWindow(QMainWindow):
|
||||
ai_models_path=self.ai_models_path,
|
||||
status_callback=self.show_status,
|
||||
)
|
||||
if title == "⑥ AI工场":
|
||||
return ImageStudioTab(
|
||||
db_path=self.db_path,
|
||||
config=self.config,
|
||||
@@ -173,6 +174,7 @@ class MainWindow(QMainWindow):
|
||||
status_callback=self.show_status,
|
||||
prompts_dir=appconfig.image_studio_prompts_dir(self.config),
|
||||
)
|
||||
raise ValueError(f"未知主界面模块:{title}")
|
||||
|
||||
def refresh_task_tabs(self):
|
||||
for index in range(self.tabs.count()):
|
||||
|
||||
@@ -60,7 +60,6 @@ TAB_TITLES = [
|
||||
"③ 更新蝦皮",
|
||||
"④ 账号管理",
|
||||
"⑤ 设置",
|
||||
"⑥ AI工场",
|
||||
]
|
||||
|
||||
TAB_STYLE = """
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
## 一句话定位
|
||||
|
||||
蝦皮圈優化助手(代号 cmshopee)是一个 Windows 本地桌面自动化工具(PySide6,6 Tab),让运营管理多个 Shopee 账号,并用 CDP 驱动 Chrome + AI 批量改商品标题、换商品封面,同时提供 AI工场图片候选生成工作区。
|
||||
蝦皮圈優化助手(代号 cmshopee)是一个 Windows 本地桌面自动化工具(PySide6,当前正式界面显示 5 个工作流 Tab),让运营管理多个 Shopee 卖家账号,并用 CDP 驱动 Chrome + AI 批量改商品标题、换商品封面。AI工场图片候选工作区的代码与数据能力保留,但当前暂不在主界面展示入口。
|
||||
|
||||
主流水线(工作流优先顺序):
|
||||
**① 导入采集 → ② AI生成 → ③ 更新蝦皮 → ④ 账号管理 → ⑤ 设置**;**⑥ AI工场** 是图片项目/照片池/cmhub 托管生图工作区,不自动上传蝦皮。
|
||||
**① 导入采集 → ② AI生成 → ③ 更新蝦皮 → ④ 账号管理 → ⑤ 设置**。⑥ AI工场是保留的图片项目/照片池/cmhub 托管生图工作区,当前隐藏主界面入口且不自动上传蝦皮。
|
||||
|
||||
目标闭环:④ 配账号并登录 → ① 导入 Excel(按“别名”列关联账号)、采集旧标题/旧封面并回写 → ② 用提示词 AI 生成新标题/新封面(不设逐条确认阶段)→ ③ 对已生成任务点击「开始更新」,弹窗确认后批量改标题+换封面并点「更新」提交 → 结果实时存 SQLite、批量回写原 Excel。
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
## 当前阶段
|
||||
|
||||
当前项目处于:**V0 单账号流程已验证,正在实现 V1 多账号 + Excel + AI + 6 Tab GUI 工作台**。
|
||||
当前项目处于:**V0 单账号流程已验证,正在实现 V1 多账号 + Excel + AI 的 5 Tab GUI 工作台;AI工场入口暂时隐藏**。
|
||||
|
||||
优先路径:
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
**V1 当前 coding 目标**:
|
||||
|
||||
- 6 Tab 工作台:① 导入采集 → ② AI生成 → ③ 更新蝦皮 → ④ 账号管理 → ⑤ 设置;⑥ AI工场用于图片候选生成,不自动提交线上。
|
||||
- 当前正式界面为 5 Tab 工作台:① 导入采集 → ② AI生成 → ③ 更新蝦皮 → ④ 账号管理 → ⑤ 设置;⑥ AI工场的代码与本地数据保留,但主界面入口暂时隐藏,不自动提交线上。
|
||||
- GUI 固定为 PySide6;后台采集/生成/更新用 `QObject` worker + `QThread` + signal 回传进度。
|
||||
- 多账号管理;账号以独立 user-data-dir 隔离。③ 更新默认串行,提供「检查本轮更新」按钮;⑤ 可开启按账号并行和设置每批最大更新条数。
|
||||
- Excel 导入/回写 + SQLite 实时落库 + 本地图片目录。
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
## 一、系统结构
|
||||
|
||||
Windows 本地桌面自动化工具,无后端服务,6 Tab GUI 驱动一条流水线与一个 AI工场图片工作区。
|
||||
Windows 本地桌面自动化工具,无后端服务。当前正式 GUI 显示 5 个工作流 Tab;AI工场图片工作区的代码、数据库与本地资产能力保留,但主界面入口暂时隐藏。
|
||||
|
||||
```text
|
||||
运营(人)
|
||||
|
|
||||
v
|
||||
GUI(PySide6 QTabWidget,6 Tab)
|
||||
① 导入采集 ② AI生成 ③ 更新蝦皮 ④ 账号管理 ⑤ 设置 ⑥ AI工场
|
||||
GUI(PySide6 QTabWidget,当前显示 5 Tab)
|
||||
① 导入采集 ② AI生成 ③ 更新蝦皮 ④ 账号管理 ⑤ 设置
|
||||
|
|
||||
v
|
||||
核心模块(Python)
|
||||
@@ -39,7 +39,7 @@ Shopee 卖家中心页面 / 本地图片目录
|
||||
|
||||
真实组件:
|
||||
|
||||
- GUI 入口:根目录 `main.py` 调用 `app/gui/` 包(PySide6 + `QMainWindow` + `QTabWidget`,6 Tab);包入口 `app/gui/__init__.py` 提供 `main()` 并兼容 `from app import gui` / `from app.gui import MainWindow`;也支持 `python -m app`。
|
||||
- GUI 入口:根目录 `main.py` 调用 `app/gui/` 包(PySide6 + `QMainWindow` + `QTabWidget`,当前正式界面显示 5 Tab);包入口 `app/gui/__init__.py` 提供 `main()` 并兼容 `from app import gui` / `from app.gui import MainWindow`;也支持 `python -m app`。`ImageStudioTab` 及其服务层仍保留在代码和发布包中,但当前不加入顶层 `QTabWidget`。
|
||||
- 核心模块统一放在正式代码包 `app/`:`appconfig.py`、`db.py`、`excel.py`、`config.py`、`accounts.py`、`chrome.py`、`editor.py`、`workers.py`、`ai.py`、`prompts.py`、`image_studio.py`、`image_studio_images.py`、`image_studio_generation.py`、`image_studio_export.py`;CDP 底座迁入 `app/cdp.py`(当前根目录 `cdp.py` 为已验证来源)。
|
||||
- 已验证脚本(重构进模块):`prototypes/demo.py`、`prototypes/set_title.py`、`prototypes/set_cover.py`、`prototypes/get_title.py`、`prototypes/cookies.py`、`prototypes/inspect_images.py`、`prototypes/grab.py`。
|
||||
- 外部依赖:本机 Google Chrome;Shopee;AI 服务(文本+图像;普通产品默认 cmhub 网关,由 `data/config.json` 的 `ai.cmhub` + `data/config/cmhub.json` 配置;direct 直连模型清单仅作为内部兼容/手工回滚路径保留);`openpyxl`。
|
||||
@@ -63,7 +63,7 @@ imported → collected → generated → applied
|
||||
|
||||
## 三、职责划分
|
||||
|
||||
**GUI(6 Tab)**:见 [routes.md](routes.md)。只做交互与预览,不写业务逻辑;耗时操作走 PySide6 `QObject` worker + `QThread`,用 signal 回主线程刷新 UI。**① 采集点击后会为本轮匹配到的账号自动确保 Chrome 就绪:已打开则复用,未打开才启动;随后只检测登录态,未登录账号的任务跳过并汇总提示去 ④人工登录。③ 更新蝦皮仍是线上提交高风险链路:执行前只检测账号 Chrome/CDP/登录态,不自动启动缺失账号 Chrome。⑥ AI工场只读拉图、下载图片和 cmhub 托管生成都走 worker,不自动上传蝦皮。**
|
||||
**GUI(当前显示 5 Tab)**:见 [routes.md](routes.md)。只做交互与预览,不写业务逻辑;耗时操作走 PySide6 `QObject` worker + `QThread`,用 signal 回主线程刷新 UI。**① 采集点击后会为本轮匹配到的账号自动确保 Chrome 就绪:已打开则复用,未打开才启动;随后只检测登录态,未登录账号的任务跳过并汇总提示去 ④人工登录。③ 更新蝦皮仍是线上提交高风险链路:执行前只检测账号 Chrome/CDP/登录态,不自动启动缺失账号 Chrome。⑥ AI工场入口当前隐藏;其只读拉图、下载图片和 cmhub 托管生成代码仍保留,且不会自动上传蝦皮。**
|
||||
|
||||
**核心模块**
|
||||
|
||||
|
||||
+6
-5
@@ -1,11 +1,11 @@
|
||||
# 界面与流程结构
|
||||
|
||||
> 桌面工具,无前端路由。用 **6 Tab GUI(PySide6 `QMainWindow` + `QTabWidget`)+ 流水线** 约定界面职责与导航。
|
||||
> 桌面工具,无前端路由。当前正式界面用 **5 Tab GUI(PySide6 `QMainWindow` + `QTabWidget`)+ 流水线** 约定界面职责与导航;AI工场代码与数据保留,但主界面入口暂时隐藏。
|
||||
|
||||
## Tab 顺序与职责(工作流优先)
|
||||
|
||||
```
|
||||
① 导入采集 │ ② AI生成 │ ③ 更新蝦皮 │ ④ 账号管理 │ ⑤ 设置 │ ⑥ AI工场
|
||||
① 导入采集 │ ② AI生成 │ ③ 更新蝦皮 │ ④ 账号管理 │ ⑤ 设置
|
||||
```
|
||||
|
||||
| Tab | 职责 | 风险 |
|
||||
@@ -15,13 +15,14 @@
|
||||
| ③ 更新蝦皮 | 对**已生成**任务点击「开始更新」后弹窗确认;确认后打开编辑页换标题+封面并逐条点「更新」提交;结果回写 Excel | **写线上,高** |
|
||||
| ④ 账号管理 | Shopee 账号(账号名/别名/数据目录/端口/密码本地明文仅参考/登录状态);启动登录、检测登录、生成快捷方式;启动登录必须复用已打开的同账号 Chrome,避免重复开窗口;检测登录遇到 `accounts.shopee.tw/seller/login` 必须显示未登录 | 中 |
|
||||
| ⑤ 设置 | cmhub 网关/API Key、生文/生图别名、托管档位提示、生成参数、Chrome 路径、默认端口、蝦皮更新执行参数等 | — |
|
||||
| ⑥ AI工场 | 按账号+商品建立图片项目;只读拉取蝦皮原主图 URL;单击原图下载进入照片池;选择源图后用 cmhub 托管模型生成多张主图/详情图候选;管理 AI工场完整提示词模板;终选拖放与导出由后续任务接入 | 不触线上,中 |
|
||||
|
||||
⑥ AI工场原有代码、SQLite项目与图片资产继续保留,但当前不加入主窗口Tab栏;后续重新开放入口需另立任务。隐藏入口不会删除或迁移用户已有AI工场数据。
|
||||
|
||||
任务的**阶段状态**贯穿各 Tab:`imported → collected → generated → applied`(或 `failed/skipped`)。② 不设逐条人工确认阶段;③ 无常驻提交开关,点击「开始更新」后必须弹窗确认当前筛选范围、任务数量和线上提交风险。各 Tab 聚焦各自阶段的列与按钮,但操作同一批任务(同一 batch)。
|
||||
|
||||
## 全局 Tab 栏可用性
|
||||
|
||||
6 个主 Tab 是高频导航入口,不能使用 Qt 默认的紧凑宽度。`MainWindow` 必须为 `QTabWidget/QTabBar` 设置基础样式:
|
||||
当前 5 个主 Tab 是高频导航入口,不能使用 Qt 默认的紧凑宽度。`MainWindow` 必须为 `QTabWidget/QTabBar` 设置基础样式:
|
||||
|
||||
- 每个 Tab 设置稳定最小宽度和足够左右 padding,避免文字贴边或窄到误点。
|
||||
- Tab 之间保留明显间距,当前 Tab 有清晰背景/边框高亮。
|
||||
@@ -174,7 +175,7 @@
|
||||
- ③「更新内容」默认只更新标题,每批最大更新条数默认 1,同时更新蝦皮账号默认 1。
|
||||
- ③ 点击「开始更新」会先按「更新内容」校验缺失内容,再弹确认框。
|
||||
|
||||
## ⑥ AI工场
|
||||
## ⑥ AI工场(入口暂时隐藏)
|
||||
|
||||
```
|
||||
┌ AI工场 ──────────────────────────────────────────────────────┐
|
||||
|
||||
+5
-2
@@ -3,7 +3,7 @@ id: T-614
|
||||
title: 暂时隐藏主界面的AI工场Tab
|
||||
phase: 7
|
||||
deps: [T-613]
|
||||
status: TODO
|
||||
status: DONE
|
||||
created: 2026-07-13
|
||||
---
|
||||
|
||||
@@ -49,4 +49,7 @@ git diff --check
|
||||
|
||||
## 执行记录
|
||||
|
||||
(完成后记录实现、验证命令与结果。)
|
||||
- 2026-07-13:从顶层 `TAB_TITLES` 移除「⑥ AI工场」,主窗口只创建①导入采集、②AI生成、③更新蝦皮、④账号管理和⑤设置五个正式Tab;前五个Tab顺序、跳转索引、设置离开确认、状态栏和③警示图标保持不变。
|
||||
- 2026-07-13:保留 `ImageStudioTab`、AI工场服务层、worker、SQLite schema/迁移及用户已有项目和图片;直接构造AI工场组件的既有测试继续执行,发布包代码不做裁剪。
|
||||
- 2026-07-13:同步编程入口、架构和界面流程文档,明确AI工场入口暂时隐藏但能力与数据保留。
|
||||
- 验证:在干净worktree运行 `python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`py -3.10 -m unittest discover -s tests`(391项通过)和任务范围 `git diff --check`,均通过。未启动真实桌面窗口做人工视觉验收。
|
||||
|
||||
+10
-3
@@ -478,11 +478,12 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.addCleanup(window.close)
|
||||
|
||||
self.assertEqual(gui.display_name(), window.windowTitle())
|
||||
self.assertEqual(6, window.tabs.count())
|
||||
self.assertEqual(5, window.tabs.count())
|
||||
self.assertEqual(
|
||||
TAB_TITLES,
|
||||
[window.tabs.tabText(index) for index in range(window.tabs.count())],
|
||||
)
|
||||
self.assertNotIn("⑥ AI工场", TAB_TITLES)
|
||||
self.assertEqual("就绪", window.statusBar().currentMessage())
|
||||
self.assertEqual(gui.BUTTON_BASE_STYLE, window.styleSheet())
|
||||
self.assertEqual(TAB_STYLE, window.tabs.styleSheet())
|
||||
@@ -495,8 +496,14 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertIsInstance(window.tabs.widget(0), CollectTab)
|
||||
self.assertIsInstance(window.tabs.widget(1), GenerateTab)
|
||||
self.assertIsInstance(window.tabs.widget(2), ApplyTab)
|
||||
self.assertIsInstance(window.tabs.widget(3), AccountsTab)
|
||||
self.assertIsInstance(window.tabs.widget(4), SettingsTab)
|
||||
self.assertIsInstance(window.tabs.widget(5), ImageStudioTab)
|
||||
self.assertFalse(
|
||||
any(
|
||||
isinstance(window.tabs.widget(index), ImageStudioTab)
|
||||
for index in range(window.tabs.count())
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
"回写旧数据到 Excel",
|
||||
window.tabs.widget(0).write_back_button.text(),
|
||||
@@ -541,7 +548,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.addCleanup(tab.close)
|
||||
|
||||
self.assertEqual("imageStudioTab", tab.objectName())
|
||||
self.assertEqual("⑥ AI工场", TAB_TITLES[5])
|
||||
self.assertNotIn("⑥ AI工场", TAB_TITLES)
|
||||
self.assertGreaterEqual(tab.account_combo.count(), 1)
|
||||
self.assertEqual("alias-a", tab.account_combo.itemData(0))
|
||||
self.assertNotIn(
|
||||
|
||||
Reference in New Issue
Block a user