11 KiB
11 KiB
V2 总体架构
状态:方案设计(待确认) 上游:V2 总览 · V1
architecture.md前置阅读:建议先读capability-inventory.md了解现状资产。
1. 组件与职责
┌───────────────┐ Bearer Token ┌──────────────────────────────────────────────┐
│ Chrome 插件 │ ────────────────▶ │ 服务端 server/(FastAPI) │
│ extension-v2 │ POST /api/materials│ │
│ (Ozon/1688 采集)│ │ ├─ api/ 采集/商品/类目/店铺/发布/图片/汇率 │
└───────────────┘ │ ├─ services/ Ozon / DeepSeek / 套图 / 七牛 │
▲ │ ├─ models/ SQLAlchemy ORM + Alembic │
│ 远程配置 / 埋点 │ └─ jobs/ 异步:图下载转存 / 发布轮询 │
┌───────┴───────┐ │ │
│ 采集配置文件 │ └──────┬───────────────┬───────────────┬────────┘
│(可热更) │ │ │ │
└───────────────┘ ┌──────────▼──┐ ┌───────▼────────┐ ┌─────▼─────────┐
│ PostgreSQL │ │ 七牛对象存储 │ │ Ozon Seller API│
│ 商品/店铺/任务│ │ 源图/生成图/水印 │ │ Client-Id+Api-Key│
└─────────────┘ └────────────────┘ └───────────────┘
▲
│ REST /api/*
┌─────────────┴──────────────┐
│ studio/(React + Vite + antd)│
│ 采集箱 / 商品编辑 / 发布 / 店铺 / 导出 │
└────────────────────────────┘
四个部分与 V1 一致(插件 / studio / server / 采集配置),但 studio 的职责显著扩大(从单页图生图 → 完整工作台),server 从无状态代理 → 有状态业务中枢。
2. 核心边界(延续 V1,补充 V2)
- 密钥只放服务端:DeepSeek / DASHSCOPE / 七牛 / Ozon 店铺 Client-Id+Api-Key 全部只在 server 侧;插件和 studio 只持有一个长期 Bearer Token。
- 插件仍做纯采集:不调 LLM、不做图片处理、不碰 Ozon API;只是把「写本地文件夹」换成「上传落库」。
- 服务端是唯一出网口(对 Ozon/云厂商):插件 background 与服务端通信,studio 与服务端通信;谁都不直连 Ozon。
- 商品数据单点真源 =
products表:_前缀的本地扩展字段(_raw/_pricing/_images)仍保留在 JSONB 里,提交 Ozon 前按 V1 契约剥离。 - 图片一律七牛公网 URL:数据库里存七牛 URL,不存本地路径、不存源站 URL(源站 URL 仅存
product_assets.source_url做溯源)。
3. 技术栈
| 部分 | 技术栈 | 说明 |
|---|---|---|
| server | FastAPI + SQLAlchemy 2.0(async)+ Alembic + httpx | 沿用现状 FastAPI;ORM 用 SQLAlchemy 2.0 async |
| DB | PostgreSQL 16(腾讯云 CDB) | JSONB 存 attributes/raw/pricing |
| 任务 | 轻量:先 DB 轮询 + asyncio 后台任务;量大再上 Redis/Celery | 图下载转存、发布轮询都是 IO 密集 |
| 对象存储 | 七牛云 Kodo | 源图转存 + 生成图 + 水印结果 |
| 缓存 | 类目/属性字典 → PostgreSQL 表 + 内存 LRU;可选 Redis | 见 ozon-publish.md §3 |
| studio | React 19 + Vite 7 + antd 6 + react-router 7 | 沿用现状;加 react-query 或 zustand 管状态 |
| extension | WXT + React + TS | 沿用;改造 export → upload |
| 鉴权 | JWT(短期)+ Bearer Token;MVP 单用户,预留 users 表 |
见 §6 |
与 V1 的差异:唯一新增重依赖是 SQLAlchemy + Alembic 和 七牛 SDK(qiniu)。任务队列一期不引入 Redis/Celery,用「DB 状态机 + 后台协程」即可(单人自用规模)。
4. 目录结构(目标)
ozon-seller-kit/
├── server/
│ ├── main.py # 应用入口,挂载路由 + studio 静态
│ ├── api/ # 按域拆:collection / products / categories /
│ │ │ # shops / publish / export / image / ai / fx / auth
│ ├── services/ # ozon_client / deepseek / image_suite / qiniu / pricing
│ ├── models/ # SQLAlchemy 模型(见 database.md)
│ ├── schemas/ # Pydantic(接口契约真源)
│ ├── jobs/ # 后台协程:下载转存 / 发布轮询
│ ├── migrations/ # Alembic
│ └── config/ # settings.py + models.yaml(沿用)
├── studio/ # 工作台(多页)
│ └── src/
│ ├── pages/
│ │ ├── collection/ # 采集箱列表
│ │ ├── product/ # 商品编辑(核心)
│ │ │ └── components/ # PricingPanel / CopyPanel / ImagePanel /
│ │ │ # CategoryPicker / AttributeMapper / PublishPanel
│ │ ├── publish/ # 发布任务 / 状态
│ │ ├── shops/ # 店铺管理(Client-Id / Api-Key)
│ │ ├── export/ # CSV 导出
│ │ └── ai-image/ # 保留:智能修图(wanx2.1-imageedit,改名)
│ ├── services/ # 与 /api/* 对齐的客户端
│ ├── stores/ # zustand:商品编辑态 / 采集箱筛选
│ └── pricing/ # 从 v1 抄来的计价纯函数(不改原文件)
├── extension-v2/ # 采集插件(改造:上传落库)
│ └── src/
│ ├── messaging/ # 消息层(plan.md §9)
│ ├── api/ # 后端客户端(仅 background)
│ └── collector/ profiles/ # 沿用采集引擎
├── web/ # v1 工具台,冻结
├── docs/
│ ├── v2/ # ★ 本文档集
│ └── ...(V1 文档)
└── .env / .env.example
5. 状态机:商品生命周期
V1 是 collected → edited → published。V2 因为「落库 + 异步发布」,扩展为:
collected ──(进入编辑)──> editing ──(填写完整)──> ready ──(点发布)──> publishing
│
┌───────────────────────────────────────┤
▼ ▼
imported(成功) failed(失败,可改后重发)
│ ▲
└────── published ──(可归档)──> archived ─┘
collected 插件刚上传,只有素材与原文
editing 用户正在编辑(计价/文案/图片/类目)
ready 必填项齐全,可发布
publishing 已提交 ImportProductsV3,拿到 task_id,等待轮询
published 轮询 imported 成功,回填 product_id
failed 轮询返回 errors / 校验失败;可回到 editing 修复后重发
archived 手动归档(软删)
- 每步都落库,刷新/换设备不丢。
publishing由发布任务表(publish_tasks)驱动,服务端轮询/v1/product/import/info更新状态。- 状态定义详见
database.md§2.2。
6. 鉴权与多租户
MVP(单人自用):.env 里配一个 APP_TOKEN,插件 options 页和 studio 登录页填同一个值,请求头 Authorization: Bearer <APP_TOKEN>。服务端校验后签发短期 JWT,后续请求用 JWT。
预留升级路径(不影响 MVP):users 表 + shops.user_id 已留好外键,未来要做多用户 SaaS 只需补注册/登录 + 按 user_id 过滤查询,schema 不用改。
| 层 | MVP | 升级 |
|---|---|---|
| 身份 | 单个 APP_TOKEN |
users 表 + 密码哈希 |
| 会话 | 短期 JWT(Authorization: Bearer) |
同左,加刷新令牌 |
| 店铺归属 | 全部归当前用户 | 按 user_id 隔离 |
| 密钥保护 | 店铺 Api-Key 服务端 AES-GCM 加密落库 | 同左 |
7. 部署拓扑(腾讯云)
┌────────────── nginx (443) ──────────────┐
│ /api/* → uvicorn (127.0.0.1:8800) │
浏览器/插件 ─────▶ │ / → studio 静态资源(构建产物)│
│ /ozonSeller.html → web/(v1,可选保留) │
└─────────────────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
PostgreSQL(CDB) 七牛 Kodo(对象存储) 外部 API(Ozon/DeepSeek/DashScope)
- 单进程部署:FastAPI 同源托管 studio 构建产物(与 V1 托管 web/ 同思路),
/api走 nginx 反代到 uvicorn。 - 环境变量:
.env在服务器上维护(不入 git),新增APP_TOKEN/DATABASE_URL/QINIU_*/APP_BASE_URL。 - CORS:同源托管时
CORS_ORIGINS留空;开发期 studio 跑 8900 时用 Vite 代理/api,无需 CORS。 - 详见
migration.md§5。
8. 与 V1 的差异小结
| 维度 | V1 | V2 |
|---|---|---|
| 契约真源 | 磁盘「商品文件夹」 | products 表 + 七牛 |
| 插件出口 | File System Access 写盘 | POST /api/materials 落库 |
| studio | 单页图生图 | 多页工作台 |
| server | 无状态代理(ai/image) | 有状态业务中枢(DB/七牛/Ozon/任务) |
| 发布 | 预留 /api/ozon/* 占位 |
完整发布链路 + 任务轮询 |
| 图片 | 图生图(wanx2.1)+ 前端水印 | 智能修图 + 电商套图 + 七牛托管 |
| 数据导出 | v1 登记表 CSV(前端) | 服务端统一 CSV 导出 |
| 部署 | 本机 127.0.0.1 | 腾讯云公网 |