Files
cmshoppe/docs/03-tech-stack.md
T

95 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 技术栈(Tech Stack)
> “用什么”的统一速查表。选型与理由在此集中维护;“怎么把它们搭起来”见 [架构设计](04-architecture.md)。
> 未定项必须标为待定,不要让 agent 在代码里自行决定。
## 一、技术栈一览
| 维度 | 选型 | 状态 | 理由 / 说明 |
| --- | --- | --- | --- |
| 语言 | Python 3.10(正式打包固定);CI 使用 3.11 | 已定 | 发布构建固定使用 `py -3.10`;源码曾验证可在 3.7.9 运行,但不作为发布打包基线 |
| 运行平台 | Windows(生产);WSL 可用于开发 | 已定 | Chrome 与各 user-data-dir 在 Windows;GUI 与 Chrome 同机,CDP 走 `localhost` |
| 浏览器自动化 | 自研 CDP 客户端 `app/cdp.py` | 已定 | 基于 websocket-client + requests 手写;不引入 playwright/selenium,规避代理与 Origin 坑 |
| WebSocket | `websocket-client`(import `websocket`) | 已定 | 讲 CDP 协议;用 `suppress_origin=True` 绕过 403 |
| HTTP | `requests` | 已定 | 读 `/json` 拿 tab 列表;`trust_env=False` 忽略代理 |
| 浏览器 | Google Chrome(已安装) | 已定 | 带 `--remote-debugging-port` 启动 |
| GUI 框架 | PySide6(Qt for Python,`QTabWidget` 5 Tab) | 已定 | 当前环境已安装 PySide6;V1 需要表格、图片预览、后台任务进度、确认弹窗,Qt 的 signal/slot + QThread 更适合 |
| 应用配置 | `data/config.json`(JSON,stdlib) | 已定 | 少量应用级设置:Chrome 路径、目录根、端口、DB 路径等 |
| 业务数据 | SQLite(stdlib `sqlite3`,`data/cmshopee.db`) | 已定 | 账号、任务、结果:成行增长、要查询/统计/导出 |
| Excel 读写 | `openpyxl` | 已定 | 导入任务、回写结果;stdlib 读不了 .xlsx |
| AI 模型注册 | `data/config/cmhub.json` 网关 Key + `data/config/ai_models.json` direct 兼容清单 | 已接入 | 普通产品默认 cmhub,使用 `data/config.json` 的 Base URL/别名 + `data/config/cmhub.json` 单 Key;direct 模型清单保留为内部兼容/手工回滚路径,普通⑤设置页不暴露后端切换 |
| AI 文本生成 | `app/ai.py` 默认 cmhub `POST /api/v1/generate/title`,保留 direct chat JSON 兼容分支 | 已接入 | 提示词+旧标题→新标题;返回值不变;cmhub 计费 metadata 通过事件回调上报 |
| AI 图像生成 | `app/ai.py` 默认 cmhub `POST /api/v1/generate/image`,保留 direct chat/images_edits 兼容分支 | 已接入 | 提示词+旧封面→新封面;cmhub 拿 `image_url` 后安全下载并转本地 JPEG;生图读超时不自动重发 |
| 并发 | 标准库 `concurrent.futures.ThreadPoolExecutor` | 已定 | 标题/图片分别按并发数并行;③ 可按账号并行更新;可停止、可重试 |
| 运行日志 | SQLite `run_logs` / `run_log_events` | 已定 | ③ dry-run 与真实更新都留痕;结构化内容走脱敏 |
| 图片处理 | `requests`(下载)+ `Pillow`(按分辨率/jpg质量存盘) | 部分待定 | 下载旧封面;新封面按 resolution 生成、jpg_quality 存盘 |
| 测试 | `python -m compileall app main.py` + `unittest` + 手动 CDP/AI 验证 | 已定(分层) | 配置/DB/Excel/prompts 用单测;CDP/Shopee 与真实 AI 属集成验证或 mock |
| 打包分发 | PyInstaller onedir(`cmshopee.spec`) | 已定 | 产出 Windows 免安装文件夹;不内置配置、DB、图片、日志、Chrome 登录态或提示词等本地数据;运行时统一写入程序同级 `data/` |
## 二、决策记录与演进
- **CDP 自研而非 playwright**:当前已验证根目录 `cdp.py`,正式代码迁入 `app/cdp.py`;它零重依赖、完全可控,并已在开发环境绕开了代理(`*_proxy` 指向本地 :1080)和 Chrome 的 Origin 403 两个坑。未来若交互复杂度大幅上升,再评估 playwright。
- **GUI 选 PySide6**:V1 是 5 Tab 运营工作台,包含任务表格、筛选、图片预览、后台采集/生成/更新、进度与停止。当前环境已安装 PySide6,且 Tkinter 不可用;Qt 的 `QThread`/signal-slot 比 Tkinter 手动 queue/after 更适合长任务回传 UI。
- **存储拆两层**:应用设置进 `data/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)。
- **快捷方式生成用 PowerShell(无额外依赖)**:用 `WScript.Shell.CreateShortcut` 生成 `.lnk`,不引入 `pywin32` 等依赖。
- **AI 服务商收口到 cmhub 网关**:T-301 的 `data/config/ai_models.json` direct 通用 HTTP 接入仍保留为内部兼容/手工回滚路径;T-526~T-529 后普通产品默认 `backend=cmhub`,⑤设置页只展示 cmhub Base URL + 生文/生图别名 + `data/config/cmhub.json` 单 Key,不再暴露 AI 后端切换。
- **AI 模型 category 是硬约束**:`data/config/ai_models.json` 每个模型必须有 `category=text` 或 `category=image`;启动时报 “AI 模型 category 必须是 text 或 image” 时,按 [常见问题排查](troubleshooting.md) 修复本地配置,不删除或提交含 Key 的配置文件。
- **敏感信息不加密但强提示与脱敏**:密码与 AI Key 只在本机 SQLite / `data/config/ai_models.json` / `data/config/cmhub.json` 明文保存;保存/变更时弹窗提示,UI 打码,日志/导出必须脱敏,相关本地文件必须 gitignore。
- **AI 产出无逐条审核**:生成的新标题/新封面经 ③ 批量确认后提交线上;无常驻提交开关,本地留档 + 回写 Excel 供追溯。
- **T-504 更新执行增强**:③ 支持 dry-run 预览、运行日志和按账号并行;默认 dry-run 关闭、并行关闭,不引入新依赖。
- **不引入数据库(指外部 DB)**:用 stdlib SQLite 足够;不引入 Postgres/MySQL 等。
- **生产在 Windows 直跑**:开发期我们用过 WSL→Windows 的 `netsh portproxy`(9333→9222)连 CDP;但 GUI 与 Chrome 都在 Windows 时,直接连 `127.0.0.1:9222`,无需 portproxy。
- **PyInstaller 使用 onedir 免安装包**:T-524 先做 `dist/cmshopee/` onedir,不做自动更新器;T-540 后当前打包依赖锁定 PyInstaller 6.11.1,产物必须是 `cmshopee.exe` + `_internal/` 集中依赖布局。T-538 后打包版不再 `chdir` 到 exe 目录,用户本地配置、DB、图片、日志、登录态和提示词统一保留在 exe 同级 `data/` 子目录,更新时覆盖程序文件并保留 `data/`。`app/version.py` 是唯一版本源,打包脚本固定使用 `py -3.10`,并把 `dist/cmshopee/` 组装为 `release/cmshopee-<APP_VERSION>/` 与 `release/cmshopee-<APP_VERSION>-portable.zip`。
## 三、构建与运行命令
| 用途 | 命令 |
| --- | --- |
| 安装依赖 | `py -3.10 -m pip install -r requirements.txt` |
| 检查 PySide6 | `python -c "import PySide6; print(PySide6.__version__)"` |
| 语法检查 | `py -3.10 -m compileall app main.py` |
| 启动 GUI | `py -3.10 main.py` / `py -3.10 -m app` |
| 单元测试(T-006 后) | `py -3.10 -m unittest discover -s tests` |
| CI 自动验证 | GitHub Actions `.github/workflows/tests.yml`(Windows + Python 3.11 + `QT_QPA_PLATFORM=offscreen`) |
| 安装打包依赖 | `py -3.10 -m pip install -r requirements-build.txt` |
| 打包 exe | `powershell -ExecutionPolicy Bypass -File scripts\\build_exe.ps1` |
| 跑单账号演示 | `python prototypes/demo.py`(分步)/ `set AUTO=1 && python prototypes/demo.py`(自动) |
| 提交更新(真改线上) | `set UPDATE=1 && python prototypes/demo.py` |
| 读取某账号 Cookie(调试) | `python prototypes/cookies.py` |
Windows PowerShell 下设置环境变量与 cmd 不同:
```powershell
# PowerShell
$env:AUTO=1; python prototypes/demo.py
$env:UPDATE=1; python prototypes/demo.py
```
```cmd
:: cmd
set AUTO=1 && python prototypes/demo.py
```
## 四、依赖纪律
- 运行时第三方依赖统一写入根目录 `requirements.txt` 并锁定版本;换机或 CI 使用 `python -m pip install -r requirements.txt` 安装。
- 打包依赖只写入 `requirements-build.txt`;PyInstaller 不属于运行时依赖,不写进 `requirements.txt`。
- 当前直接依赖锁定:PySide6 6.5.3、openpyxl 3.1.3、requests 2.31.0、websocket-client 1.6.1、Pillow 9.5.0。
- 新增第三方依赖前,先在本文说明用途、替代方案和维护成本,并同步更新 `requirements.txt`。
- GUI 框架固定为 PySide6,不允许混入 Tkinter/PyQt/Web 形成两套 UI。
- 不引入第二套浏览器自动化方案(不要 `app/cdp.py` 之外再混入 selenium/playwright)。
- 不确定的技术选型先更新本文,再进入代码。
## 五、测试分层
| 层级 | 覆盖对象 | 验证方式 |
| --- | --- | --- |
| 语法 | 正式代码包与入口 | `python -m compileall app main.py` |
| 单元 | `appconfig/db/excel/prompts/config/chrome` 的纯逻辑 | T-006 建立 `tests/` 后运行 `python -m unittest discover -s tests`,使用临时目录/临时 SQLite/样例 Excel |
| GUI 轻测 | PySide6 主窗口可创建、Tab 数量、worker signal 基本行为 | 可用 unittest 构造 `QApplication`,不连真实 Shopee |
| CI | push / pull_request 自动跑语法 + 全量 unittest | `.github/workflows/tests.yml` 安装 `requirements.txt`,运行 `python -m compileall app main.py` 与 `python -m unittest discover -s tests`;不连真实 Shopee/AI |
| 集成 | CDP/editor 操作 Shopee 测试商品 | 手动跑 `prototypes/demo.py` 或后续专用集成脚本 |
| 外部 AI | 模型连接、文本/图像生成 | 默认 mock;真实调用只在手动验证时跑,避免成本和限流 |