diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md index 6a9fa97..724265a 100644 --- a/docs/00-ai-start-here.md +++ b/docs/00-ai-start-here.md @@ -4,7 +4,7 @@ ## 一句话定位 -cmshopee 是一个 Windows 本地桌面自动化工具(Tkinter,5 Tab),让运营管理多个 Shopee 账号,并用 CDP 驱动 Chrome + AI 批量改商品标题、换商品封面。 +cmshopee 是一个 Windows 本地桌面自动化工具(PySide6,5 Tab),让运营管理多个 Shopee 账号,并用 CDP 驱动 Chrome + AI 批量改商品标题、换商品封面。 5 Tab 流水线(工作流优先顺序): **① 导入采集 → ② AI生成 → ③ 更新shopee → ④ 账号管理 → ⑤ 设置** @@ -19,7 +19,7 @@ cmshopee 是一个 Windows 本地桌面自动化工具(Tkinter,5 Tab), 1. [`01-vision.md`](01-vision.md):为什么做、为谁做、什么不做。 2. [`02-requirements.md`](02-requirements.md):V1 要什么、怎么算达成。 -3. [`03-tech-stack.md`](03-tech-stack.md):既定技术选型(Python + 自研 CDP + Tkinter 待确认)。 +3. [`03-tech-stack.md`](03-tech-stack.md):既定技术选型(Python + 自研 CDP + PySide6)。 4. [`04-architecture.md`](04-architecture.md):模块职责、账号数据模型、**第七节 CDP 已验证事实(重点)**。 5. [`05-coding-rules.md`](05-coding-rules.md):写代码前必须遵守的规则。 6. [`06-tasks.md`](06-tasks.md):领取本轮唯一任务。 @@ -35,7 +35,7 @@ cmshopee 是一个 Windows 本地桌面自动化工具(Tkinter,5 Tab), 优先路径: 1. Phase 0:把已验证流程模块化(`editor.py`),建立 `config.json` 与 SQLite。 -2. Phase 1:账号绑定 user-data-dir、Chrome 启动、登录保活。 +2. Phase 1:账号绑定 user-data-dir、Chrome 启动、登录保活、PySide6 主窗口骨架。 3. Phase 2:导入 Excel、采集旧标题/旧封面并回写。 4. Phase 3:AI 生成新标题/新封面。 5. Phase 4:③ 批量确认后更新 Shopee 并回写结果。 @@ -65,6 +65,7 @@ cmshopee 是一个 Windows 本地桌面自动化工具(Tkinter,5 Tab), **V1 当前 coding 目标**: - 5 Tab 流水线:① 导入采集 → ② AI生成 → ③ 更新shopee → ④ 账号管理 → ⑤ 设置。 +- GUI 固定为 PySide6;后台采集/生成/更新用 `QObject` worker + `QThread` + signal 回传进度。 - 多账号管理,但执行更新仍串行;账号以独立 user-data-dir 隔离。 - Excel 导入/回写 + SQLite 实时落库 + 本地图片目录。 - AI 生成标题/封面,不设逐条确认阶段。 diff --git a/docs/02-requirements.md b/docs/02-requirements.md index 6991f6a..de7c437 100644 --- a/docs/02-requirements.md +++ b/docs/02-requirements.md @@ -108,5 +108,5 @@ - **第三方平台风险**:Shopee 页面结构、class 名、接口随时可能变;限流、风控、封号风险存在,禁止高频批量。 - **自动化边界风险**:③ 确认后会自动改标题、上传图片、拖拽并点「更新」提交线上;点「开始更新」并确认前需自行确保筛选范围、任务来源与 AI 产出可接受。 - **合规风险**:仅在自有/授权账号上操作;遵守 Shopee 卖家条款;不绕过任何平台限制。 -- **GUI 选型待确认**:默认 Tkinter(零依赖),是否改用 PySide/Web 由维护者确认,见 [技术栈](03-tech-stack.md)。 +- **GUI 选型**:V1 固定为 PySide6;后台任务通过 QThread/signal 回传进度,见 [技术栈](03-tech-stack.md) 与 [架构](04-architecture.md)。 - **多账号并行待确认**:V1 多账号串行;并行的端口分配与资源占用在 V2 评估。 diff --git a/docs/03-tech-stack.md b/docs/03-tech-stack.md index 96686c7..fa49b1a 100644 --- a/docs/03-tech-stack.md +++ b/docs/03-tech-stack.md @@ -13,7 +13,7 @@ | WebSocket | `websocket-client`(import `websocket`) | 已定 | 讲 CDP 协议;用 `suppress_origin=True` 绕过 403 | | HTTP | `requests` | 已定 | 读 `/json` 拿 tab 列表;`trust_env=False` 忽略代理 | | 浏览器 | Google Chrome(已安装) | 已定 | 带 `--remote-debugging-port` 启动 | -| GUI 框架 | Tkinter(标准库,`ttk.Notebook` 5 Tab) | 待定(推荐) | 零依赖、单机够用;如需更现代 UI 再评估 PySide6 / Web | +| GUI 框架 | PySide6(Qt for Python,`QTabWidget` 5 Tab) | 已定 | 当前环境已安装 PySide6;V1 需要表格、图片预览、后台任务进度、确认弹窗,Qt 的 signal/slot + QThread 更适合 | | 应用配置 | `config.json`(JSON,stdlib) | 已定 | 少量应用级设置:Chrome 路径、目录根、端口、DB 路径等 | | 业务数据 | SQLite(stdlib `sqlite3`,`cmshopee.db`) | 已定 | 账号、任务、结果:成行增长、要查询/统计/导出 | | Excel 读写 | `openpyxl` | 已定 | 导入任务、回写结果;stdlib 读不了 .xlsx | @@ -27,7 +27,7 @@ ## 二、决策记录与演进 - **CDP 自研而非 playwright**:当前手写 `cdp.py`,因为它零重依赖、完全可控,并已在开发环境绕开了代理(`*_proxy` 指向本地 :1080)和 Chrome 的 Origin 403 两个坑。未来若交互复杂度大幅上升,再评估 playwright。 -- **GUI 选 Tkinter**:V1 是单机配置 + 触发操作的轻量界面,Tkinter 零依赖即可。若后续需要表格、拖拽、复杂布局,再评估 PySide6。**该选型在动代码前需维护者确认。** +- **GUI 选 PySide6**:V1 是 5 Tab 运营工作台,包含任务表格、筛选、图片预览、后台采集/生成/更新、进度与停止。当前环境已安装 PySide6,且 Tkinter 不可用;Qt 的 `QThread`/signal-slot 比 Tkinter 手动 queue/after 更适合长任务回传 UI。 - **存储拆两层**:应用设置进 `config.json`,账号/任务/结果进 SQLite。判据:少量人改无需查询 → 配置文件;成行增长要查询/导出 → DB。同一事实只存一处,不重复。取代早期的 `accounts.json` 方案。 - **Excel 用 openpyxl**:运营用真实 .xlsx;stdlib 无法读写 xlsx,引入一个轻依赖比改用 CSV 更贴合用户习惯。 - **多账号隔离用独立 user-data-dir,不用 Chrome profile**:profile 共享同一 user-data-dir/进程/调试端口,无法每账号独立 CDP 与并行;独立 user-data-dir 才契合自动化。详见 [架构 3.0](04-architecture.md)。 @@ -41,7 +41,8 @@ | 用途 | 命令 | | --- | --- | -| 安装依赖 | `pip install websocket-client requests openpyxl` | +| 安装依赖 | `pip install websocket-client requests openpyxl pillow PySide6` | +| 检查 PySide6 | `python -c "import PySide6; print(PySide6.__version__)"` | | 语法检查 | `python -m py_compile *.py` | | 跑单账号演示 | `python prototypes/demo.py`(分步)/ `set AUTO=1 && python prototypes/demo.py`(自动) | | 提交更新(真改线上) | `set UPDATE=1 && python prototypes/demo.py` | @@ -63,6 +64,6 @@ set AUTO=1 && python prototypes/demo.py ## 四、依赖纪律 - 新增第三方依赖前,先在本文说明用途、替代方案和维护成本。 -- GUI 框架一旦确定(Tkinter 或其他),固定下来,不允许两套 UI 框架并存。 +- GUI 框架固定为 PySide6,不允许混入 Tkinter/PyQt/Web 形成两套 UI。 - 不引入第二套浏览器自动化方案(不要 cdp.py 之外再混入 selenium/playwright)。 - 不确定的技术选型先更新本文,再进入代码。 diff --git a/docs/04-architecture.md b/docs/04-architecture.md index b66bf22..9eca8f8 100644 --- a/docs/04-architecture.md +++ b/docs/04-architecture.md @@ -11,7 +11,7 @@ Windows 本地桌面自动化工具,无后端服务,5 Tab GUI 驱动一条 运营(人) | v -GUI(Tkinter ttk.Notebook,5 Tab) +GUI(PySide6 QTabWidget,5 Tab) ① 导入采集 ② AI生成 ③ 更新shopee ④ 账号管理 ⑤ 设置 | v @@ -34,7 +34,7 @@ Shopee 卖家中心页面 / 本地图片目录 真实组件: -- GUI 入口:`gui.py`(待建,Tkinter + `ttk.Notebook`,5 Tab)。 +- GUI 入口:`gui.py`(待建,PySide6 + `QMainWindow` + `QTabWidget`,5 Tab)。 - 核心模块:`appconfig.py`、`db.py`、`excel.py`、`config.py`、`chrome.py`、`editor.py`、`ai.py`(待建);CDP 底座 `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 服务(文本+图像,服务商待定);`openpyxl`。 @@ -58,7 +58,7 @@ imported → collected → generated → applied ## 三、职责划分 -**GUI(5 Tab)**:见 [routes.md](routes.md)。只做交互与预览,不写业务逻辑;耗时操作走后台线程。**首次未配账号/未登录时,① ③ 执行按钮禁用并提示去 ④。** +**GUI(5 Tab)**:见 [routes.md](routes.md)。只做交互与预览,不写业务逻辑;耗时操作走 PySide6 `QObject` worker + `QThread`,用 signal 回主线程刷新 UI。**首次未配账号/未登录时,① ③ 执行按钮禁用并提示去 ④。** **核心模块** @@ -226,6 +226,15 @@ images//_new. # AI 生成的新封面 ## 六、关键流程细节 +### 6.0 GUI 线程模型(PySide6) + +- 主线程只运行 `QApplication`、窗口、表格、弹窗和状态刷新;不得在主线程执行 CDP、AI、Excel 回写、图片下载等耗时任务。 +- 每类耗时流程封装为 `QObject` worker:`CollectWorker`、`GenerateWorker`、`ApplyWorker`、`ImportWorker`、`WriteBackWorker`。 +- Worker 通过 signal 向 GUI 汇报:`progress`、`row_updated`、`log`、`failed`、`finished`、`cancelled`;GUI 槽函数只做 UI 刷新和按钮状态切换。 +- Worker 不直接操作任何 Qt widget,不弹窗;需要用户确认的动作(如 ③ 开始更新确认)必须在主线程先完成,再启动 worker。 +- `停止` 使用协作式取消:GUI 调用 worker 的 cancel 标记;worker 在任务间/重试前检查,取消未开始项,正在执行的单条任务跑到安全边界后结束。 +- SQLite connection 不跨线程共享;每个 worker/线程按需创建自己的连接,写库后发 signal 通知 UI 刷新。 + ### 6.1 采集(① Tab,只读) - 用账号 Chrome 打开商品页,等就绪,读旧标题(标题输入框 value)。 @@ -306,6 +315,7 @@ cmshopee/ ├── title_prompt.txt # 标题提示词(单文件,启动回显) ├── prompts/cover/<名称>.txt # 封面提示词模板(多个) ├── appconfig.py / db.py / excel.py / config.py / chrome.py / editor.py / ai.py / prompts.py / gui.py # 待建 +├── workers.py # PySide6 worker/QThread 编排(可选拆分) ├── cdp.py # CDP 底座(正式模块,已有) └── prototypes/ # 已验证原型/探查脚本(demo/set_*/get_title/cookies/inspect_images/grab/1.py) # 逻辑待并入 editor.py 后清理;见 prototypes/README.md @@ -321,3 +331,4 @@ cmshopee/ - 密码与 AI Key 加密存、不外传、不写日志;不自动登录。 - AI 生成内容直接进入 ③ 更新候选;③ 批量确认后提交,新图本地留档 + 回写 Excel 以备追溯。 - 高风险模块先单独验证,再接入流水线。 +- GUI 只通过 signal/slot 接收 worker 进度;禁止后台线程直接操作 Qt widget 或共享 SQLite connection。 diff --git a/docs/05-coding-rules.md b/docs/05-coding-rules.md index b497651..4e18ff3 100644 --- a/docs/05-coding-rules.md +++ b/docs/05-coding-rules.md @@ -33,10 +33,11 @@ ## 4. 架构纪律 -- 技术栈以 `03-tech-stack.md` 为准;GUI 框架未确认前不要写大量 UI 代码。 -- 新增依赖前先说明理由;优先标准库(Tkinter、json、sqlite3、subprocess),Excel 用 openpyxl。 +- 技术栈以 `03-tech-stack.md` 为准;GUI 固定使用 PySide6,不引入第二套 UI 框架。 +- 新增依赖前先说明理由;优先标准库(json、sqlite3、subprocess),GUI 用 PySide6,Excel 用 openpyxl。 - 存储边界:应用设置进 `config.json`,账号/任务/结果进 SQLite,登录态只在 user-data-dir,同一事实只存一处。 - 模块职责以 `04-architecture.md` 为准:GUI 不写业务逻辑,业务在 `appconfig/db/excel/config/chrome/cdp/editor`。 +- PySide6 后台任务必须通过 worker/QThread/signal 回传 UI;后台线程不得直接操作 Qt widget,不共享 SQLite connection。 - 模块/CLI 合约以 `api.md` 为准。 ## 5. 代码规范 @@ -81,4 +82,4 @@ python prototypes/demo.py # 单账号闭环验证(不提交) ## 9. 拿不准就问 -问题要具体:说明卡在哪、有哪些选项、倾向哪个及原因。尤其 GUI 框架、端口分配、删图确认框结构这类影响后续的决策,先确认再写。 +问题要具体:说明卡在哪、有哪些选项、倾向哪个及原因。尤其端口分配、删图确认框结构这类影响后续的决策,先确认再写。 diff --git a/docs/06-tasks.md b/docs/06-tasks.md index 2edc18e..b26454a 100644 --- a/docs/06-tasks.md +++ b/docs/06-tasks.md @@ -33,7 +33,8 @@ | T-101 | `config` 生成 slug + 创建 `chrome_user_data_dir/` | T-003 | 别名→唯一 slug;目录按需建;路径绝对化 | TODO | | T-102 | `chrome.py` 启动器:拼参数并启动、探测端口 | T-101, T-002 | 含三参数;端口就绪可探测 | TODO | | T-103 | 首次登录保活 + 登录检测 `is_logged_in` | T-102, T-001 | 关闭再启动免重登;登录/未登录判断准确 | TODO | -| T-104 | 五 Tab 主窗口骨架(`ttk.Notebook`,5 Tab 空壳) | T-002 | 五个 Tab 按顺序可切换 | TODO | +| T-104 | PySide6 五 Tab 主窗口骨架(`QMainWindow` + `QTabWidget`,5 Tab 空壳) | T-002 | 五个 Tab 按顺序可切换;启动不阻塞;基础状态栏可用 | TODO | +| T-104b | PySide6 worker 基类与线程启动工具(`BaseWorker` + `QThread` 包装) | T-104 | signals: progress/log/row_updated/failed/finished/cancelled;取消标记可用;worker 不直接操作 QWidget | TODO | | T-105 | Tab④ 账号增删改(账号名/别名/端口/密码加密)+ 启动登录 + 检测登录 | T-104, T-101, T-103 | 增删改入库、建目录;密码加密默认打码;状态列刷新 | TODO | | T-106 | 可选:为账号生成桌面快捷方式 | T-102 | `.lnk` 目标含该账号参数;双击进对应账号 | TODO | @@ -42,9 +43,9 @@ | ID | 任务 | 依赖 | 验收要点 | 状态 | | --- | --- | --- | --- | --- | | T-201 | `excel.py` 导入:解析多文件输入列入库 | T-003 | 按模板解析账号名/别名/商品id;脏数据容错;写 tasks(batch_id) | TODO | -| T-202 | Tab① 任务列表 + 导入按钮 + 别名匹配标记 | T-201, T-105 | Treeview 显示账号/别名/商品id/阶段;未匹配标“略过” | TODO | +| T-202 | Tab① 任务列表 + 导入按钮 + 别名匹配标记 | T-201, T-105 | `QTableView` 显示账号/别名/商品id/阶段;未匹配标“略过” | TODO | | T-202b | Tab① 导入汇总栏 | T-202 | 导入后显示 文件数/解析行数/有效/无效/匹配(按账号)/未匹配;未匹配可点击筛出 | TODO | -| T-203 | 采集旧标题+旧封面(只读),下载图片,立即写库 | T-202, T-001 | 逐条 set_collected;旧封面下载到 `images//`;未登录/未匹配略过记原因 | TODO | +| T-203 | 采集旧标题+旧封面(只读),下载图片,立即写库 | T-202, T-001, T-104b | 通过 worker 执行;逐条 set_collected;旧封面下载到 `images//`;未登录/未匹配略过记原因 | TODO | | T-204 | 回写旧字段到原 Excel(含文件锁处理) | T-203, T-201 | 旧标题/旧封面回写原文件;被锁提示重试或 export_copy | TODO | | T-205 | 首次未配账号/未登录的引导保护 | T-105, T-203 | 无账号/未登录时 ① 执行按钮禁用并提示去④ | TODO | @@ -55,14 +56,14 @@ | T-301 | 确定 AI 服务商/模型并接入 `ai.py`(`gen_title`/`gen_cover`,带重试/分辨率/jpg质量) | T-002 | 可调;Key 加密读取;`gen_cover` 支持 resolution+jpg_quality;失败按 retry 重试;错误明确 | TODO | | T-302 | Tab② 左右布局:左提示词(标题/封面),右按批次/店铺/状态筛选 + 任务列表 | T-301, T-203 | 左 ~1/4 提示词多行;右筛选+列表(店铺/商品id/旧标题/新标题/状态) | TODO | | T-302p | `prompts.py` + Tab② 提示词管理 | T-302 | 标题保存/启动回显 title_prompt.txt;封面多模板(下拉+新建/保存/另存为/重命名/删除,存 prompts/cover/);插入 `{新标题}`;预览变量替换;render_prompt 接入生成 | TODO | -| T-303 | Tab② 开始生成(单按钮)+ 停止 + 进度:**先并发标题再并发图片** | T-302 | `generate_batch` 先 title_concurrency 并发标题、再 image_concurrency 并发图片;每条 set_generated 立即写库;停止可取消未开始项;进度 标题/封面/失败 计数;双击弹窗看新旧封面 | TODO | +| T-303 | Tab② 开始生成(单按钮)+ 停止 + 进度:**先并发标题再并发图片** | T-302, T-104b | `generate_batch` 先 title_concurrency 并发标题、再 image_concurrency 并发图片;worker/signal 回传进度;每条 set_generated 立即写库;停止可取消未开始项;进度 标题/封面/失败 计数;双击弹窗看新旧封面 | TODO | ## Phase 4 · 更新 shopee(③) | ID | 任务 | 依赖 | 验收要点 | 状态 | | --- | --- | --- | --- | --- | | T-401 | Tab③ 列出已生成任务 + 按批次/店铺/状态筛选 + 开始更新确认弹窗 | T-303 | 顶部批次/店铺/状态筛选;「开始更新」仅作用于当前筛选结果;弹窗显示筛选条件/任务数/线上提交风险;取消不执行;状态=失败可重试;无常驻提交开关 | TODO | -| T-402 | 串行执行 apply:批量确认后换标题+换封面+点更新提交,单条失败继续,立即写库 | T-401, T-001 | 确认后逐条 set_applied;失败继续;未登录引导保护;未确认时不调用 apply | TODO | +| T-402 | 串行执行 apply:批量确认后换标题+换封面+点更新提交,单条失败继续,立即写库 | T-401, T-001, T-104b | 确认后 worker 串行执行并逐条 set_applied;失败继续;未登录引导保护;未确认时不调用 apply | TODO | | T-403 | 回写结果到原 Excel(新标题/新封面/更新状态)+ 结束弹窗汇总 | T-402, T-204 | 回写原文件(锁处理);弹窗 成功/失败/略过 | TODO | ## Phase 5 · 设置与收尾 diff --git a/docs/README.md b/docs/README.md index ae3448a..5c72b0e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,7 @@ ## 一句话定位 -cmshopee 是一个给**电商运营**使用的 Windows 桌面自动化工具,用于**管理多个 Shopee 卖家账号、并用 CDP 驱动 Chrome 批量修改商品标题、替换商品封面图**。V0 已验证单账号「改标题 + 换封面」闭环;当前 V1 目标是 5 Tab 流水线:导入采集 → AI 生成 → 点击「开始更新」并确认后批量提交 → 回写结果。 +cmshopee 是一个给**电商运营**使用的 Windows PySide6 桌面自动化工具,用于**管理多个 Shopee 卖家账号、并用 CDP 驱动 Chrome 批量修改商品标题、替换商品封面图**。V0 已验证单账号「改标题 + 换封面」闭环;当前 V1 目标是 5 Tab 流水线:导入采集 → AI 生成 → 点击「开始更新」并确认后批量提交 → 回写结果。 ## 文档导航 diff --git a/docs/api.md b/docs/api.md index 89478ea..3f75bae 100644 --- a/docs/api.md +++ b/docs/api.md @@ -169,6 +169,33 @@ render_prompt(template_text, task) -> str - 生成封面时 `gen_cover` 的 prompt = `render_prompt(当前封面模板, task)`。 - 模板与 `title_prompt.txt` 均为可手改的纯文本文件。 +## gui / workers 模块(`gui.py` / `workers.py`,待建,PySide6) + +```python +# GUI 入口 +main() -> int # 创建 QApplication + MainWindow +class MainWindow(QMainWindow) # QTabWidget: ①②③④⑤ + +# worker 约定 +class BaseWorker(QObject): + progress = Signal(dict) # {"done": int, "total": int, ...} + row_updated = Signal(int, dict) # task_id, changed fields + log = Signal(str) + failed = Signal(int, str) # task_id, error + finished = Signal(dict) # summary + cancelled = Signal(dict) + def cancel(self) -> None: ... + +run_worker(worker: BaseWorker) -> QThread # 绑定 signals、启动、收尾 deleteLater +``` + +要点: + +- GUI 线程只操作 Qt widget;后台 worker 不直接访问 QWidget。 +- 采集、AI 生成、更新、Excel 回写都通过 worker 执行,用 signal 回传进度。 +- 每个 worker/线程按需创建自己的 SQLite connection,不跨线程共享连接。 +- ③ 的批量确认弹窗在 GUI 主线程完成;用户确认后才创建 `ApplyWorker`。 + ## CLI / 触发合约(现有脚本,过渡期保留) ```bash diff --git a/docs/current-state.md b/docs/current-state.md index 1b069fa..008cf3a 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -7,14 +7,14 @@ - 日期:2026-06-26 - 阶段:V0 单账号 CDP 流程已验证;V1 多账号管理 + 5 Tab GUI + Excel/AI 流水线为既定设计,尚未开始编码。 -- 技术栈:Python 3.10+,自研 CDP(websocket-client + requests),SQLite(sqlite3)+ `config.json` + openpyxl + AI(服务商待定),GUI Tkinter 5 Tab(待最终确认)。 -- 生产代码:尚无 `appconfig/db/excel/config/chrome/editor/gui`;现有为验证脚本 + `cdp.py`。 +- 技术栈:Python 3.10+,自研 CDP(websocket-client + requests),SQLite(sqlite3)+ `config.json` + openpyxl + AI(服务商待定),GUI PySide6 5 Tab(已定)。 +- 生产代码:尚无 `appconfig/db/excel/config/chrome/editor/gui/workers`;现有为验证脚本 + `cdp.py`。 - 测试:以 `py_compile` + 在测试商品上手动跑 `prototypes/demo.py` 为主,无自动化测试。 - 数据:无 `config.json`、`cmshopee.db`、`chrome_user_data_dir/`(待 Phase 0/1 建立)。 ## 既定设计要点(文档已定) -- GUI:**5 Tab 流水线**,顺序 ① 导入采集 → ② AI生成 → ③ 更新shopee → ④ 账号管理 → ⑤ 设置。 +- GUI:**PySide6 5 Tab 流水线**,顺序 ① 导入采集 → ② AI生成 → ③ 更新shopee → ④ 账号管理 → ⑤ 设置;后台任务用 worker/QThread/signal。 - 流水线阶段:imported → collected(采集旧标题/旧封面+下载+回写)→ generated(AI 提示词生成新标题/新封面)→ applied(③ 弹窗批量确认后改 Shopee 并提交)。**无 confirmed、无常驻提交开关。** - 存储:`config.json`(应用设置)+ `config/ai_models.json`(AI 模型清单与加密 Key)+ SQLite `cmshopee.db`(账号/任务/各阶段结果)+ openpyxl(Excel)+ 本地 `images/`(旧/新封面)。 - 多账号隔离:每账号独立 user-data-dir(非 profile)。 @@ -31,7 +31,7 @@ | `cdp.py` | 已有 | CDP 底座:连接/找 tab/开 tab/执行 JS/拖拽(正式模块,留根目录) | | `prototypes/` | 已有 | 已验证原型/探查脚本(demo/set_title/set_cover/get_title/cookies/inspect_images/grab/1.py),逻辑待并入 `editor.py` 后清理;见 `prototypes/README.md` | | `chrome-remote-debug-lan.md` | 已有 | WSL→Windows CDP 转发排查记录 | -| `appconfig.py` / `db.py` / `excel.py` / `config.py` / `chrome.py` / `editor.py` / `gui.py` | 待建 | Phase 0-3 产出 | +| `appconfig.py` / `db.py` / `excel.py` / `config.py` / `chrome.py` / `editor.py` / `gui.py` / `workers.py` | 待建 | Phase 0-3 产出 | | `config.json` / `cmshopee.db` / `chrome_user_data_dir/` | 待建 | 含配置/业务/凭证,须 gitignore | ## 已验证能力(单账号) @@ -68,6 +68,7 @@ set UPDATE=1 && python prototypes/demo.py - Chrome 已用某 user-data-dir 带 `--remote-debugging-port` + `--remote-allow-origins=*` 启动并登录 Shopee。 - 已 `pip install websocket-client requests`。 +- PySide6 当前环境已可导入(验证版本 6.5.3);GUI 实现固定使用 PySide6。 - 默认连 `127.0.0.1:9222`(开发期可用 `CDP_HOST` 指向 WSL 转发的 `192.168.0.224:9333`)。 ## 开始编码前检查 @@ -80,6 +81,6 @@ set UPDATE=1 && python prototypes/demo.py ## 维护规则 -- 新建 `config/chrome/editor/gui` 或改 CDP 选择器后,更新本文与 `04-architecture.md`。 +- 新建 `config/chrome/editor/gui/workers` 或改 CDP 选择器后,更新本文与 `04-architecture.md`。 - 任务状态变化同步 [`06-tasks.md`](06-tasks.md);执行记录追加 [`../progress.md`](../progress.md)。 - 本文只保留当前快照,不保留完整历史。 diff --git a/docs/routes.md b/docs/routes.md index fb752f4..cf121d7 100644 --- a/docs/routes.md +++ b/docs/routes.md @@ -1,6 +1,6 @@ # 界面与流程结构 -> 桌面工具,无前端路由。用 **5 Tab GUI(Tkinter `ttk.Notebook`)+ 流水线** 约定界面职责与导航。 +> 桌面工具,无前端路由。用 **5 Tab GUI(PySide6 `QMainWindow` + `QTabWidget`)+ 流水线** 约定界面职责与导航。 ## Tab 顺序与职责(工作流优先) @@ -132,15 +132,17 @@ - 已生成的任务即可进 ③;③ 用户确认批量弹窗后提交线上,无常驻提交开关。 - 任意步骤失败:记入该任务、日志标明,不影响其他任务。 -## 组件建议(Tkinter) +## 组件建议(PySide6) | 组件 | 归属 | 说明 | | --- | --- | --- | -| `MainNotebook` | 根窗口 | 5 个 Tab | -| `CollectTab` | ① | 导入、任务表、采集、回写 | -| `GenerateTab` | ② | 左提示词 + 右筛选/任务列表、双击看新旧封面、开始生成 | -| `ApplyTab` | ③ | 已生成任务、开始更新确认、换标题+封面+提交、回写 | -| `AccountsTab` | ④ | 账号增删改、启动登录 | -| `SettingsTab` | ⑤ | AI/目录/Chrome 配置 | +| `MainWindow(QMainWindow)` | 根窗口 | 持有 `QTabWidget`、状态栏、全局消息 | +| `CollectTab(QWidget)` | ① | 导入、任务表、采集、回写 | +| `GenerateTab(QWidget)` | ② | 左提示词 + 右筛选/任务列表、双击看新旧封面、开始生成 | +| `ApplyTab(QWidget)` | ③ | 已生成任务、开始更新确认、换标题+封面+提交、回写 | +| `AccountsTab(QWidget)` | ④ | 账号增删改、启动登录 | +| `SettingsTab(QWidget)` | ⑤ | AI/目录/Chrome 配置 | +| `TaskTableModel(QAbstractTableModel)` | ①②③ | 任务表格数据模型,供 `QTableView` 使用 | +| `BaseWorker(QObject)` | 后台 | 定义 `progress/log/row_updated/failed/finished/cancelled` signals | -> 采集、生成、更新都是耗时操作,放后台线程,避免界面卡死。 +> 采集、生成、更新都是耗时操作,使用 `QObject` worker + `QThread`。Worker 不直接操作 QWidget,只通过 signal 通知主线程刷新 UI。 diff --git a/progress.md b/progress.md index 69fa144..43bb1e2 100644 --- a/progress.md +++ b/progress.md @@ -169,4 +169,15 @@ - CDP 已验证事实统一引用 `docs/04-architecture.md` 第七节。 - 下一步:继续处理剩余全栈落地缺口,如 SQLite/Excel schema、GUI 线程模型、AI 接入任务依赖。 +## 【2026-06-26】决策 · GUI 框架改为 PySide6 + +- 状态:DONE(仅文档) +- 变更:更新 `docs/03-tech-stack.md`、`docs/04-architecture.md`、`docs/routes.md`、`docs/06-tasks.md`、`docs/api.md`、`docs/00-ai-start-here.md`、`docs/02-requirements.md`、`docs/05-coding-rules.md`、`docs/current-state.md`、`docs/README.md`。 +- 决策: + - V1 GUI 框架固定为 PySide6(Qt for Python),不再使用 Tkinter。 + - 理由:当前环境已安装 PySide6,Tkinter 不可导入;V1 需要表格、图片预览、后台任务进度、停止按钮、确认弹窗,Qt 的 `QThread` + signal/slot 更适合。 + - GUI 线程模型:主线程只操作 Qt widget;采集/生成/更新/回写使用 `QObject` worker + `QThread`;worker 通过 signal 回传 `progress/log/row_updated/failed/finished/cancelled`;worker 不直接操作 QWidget,不跨线程共享 SQLite connection。 + - 新增 `workers.py` 作为可选模块承载 PySide6 worker/QThread 编排。 +- 下一步:继续处理 SQLite/Excel schema 与 AI 接入任务依赖。 +