feat: 开发编辑工作台

This commit is contained in:
R524809
2026-08-14 18:27:45 +08:00
parent b27e42dc75
commit c18d70017e
50 changed files with 5496 additions and 57 deletions
+83 -48
View File
@@ -12,17 +12,21 @@
四个组成部分,各自独立可用、通过明确契约衔接:
| # | 部分 | 形态 | 状态 | 职责 |
|---|---|---|---|---|
| ① | **工具台 v1** | 静态页(原生 JS + Tailwind CDN | ✅ 在用 | 计价、上品登记、水印、俄文文案。**冻结维护,不重构** |
| | **采集插件** | Chrome MV3 扩展 | 🔨 待开发 | Ozon/1688 商品页采集 → 落本地文件夹 |
| | **发布工作台** | Web 应用 | 📋设计 | 导入本地文件夹 → 编辑/图片处理 → 提交发布 |
| | **服务端** | FastAPI | 🔨 部分就绪 | AI 文案、图片处理、Ozon API 代理、凭证保管 |
| # | 部分 | 形态 | 状态 | 职责 |
| --- | ---------- | ------------------------- | ------- | ---------------------------- |
| | **工具台 v1** | 静态页(原生 JS + Tailwind CDN | ✅ 在用 | 计价、上品登记、水印、俄文文案。**冻结维护,不重构** |
| | **采集插件** | Chrome MV3 扩展 | 🔨开发 | Ozon/1688 商品页采集 → 落本地文件夹 |
| | **发布工作台** | Web 应用 | 📋 待设计 | 导入本地文件夹 → 编辑/图片处理 → 提交发布 |
| ④ | **服务端** | FastAPI | 🔨 部分就绪 | AI 文案、图片处理、Ozon API 代理、凭证保管 |
**关键边界**:① 与 ③ 并存不互相替代。① 是已验证好用的轻量工具,③ 是面向"整商品发布"的新流程;③ 成熟后 ① 的计价器可能被吸收,但那是以后的事。
---
## 2. 目录结构
```
@@ -74,7 +78,7 @@ ozon-seller-kit/
代价:`start.command``docs/deployment.md` 里的启动路径要改,`.env` 加载路径 `parents[1]` 要跟着调。Python 内部 import 全是 `from api import ...` 这类顶层相对形式,只要工作目录切到 `server/` 就不受影响。
**这是唯一有破坏性的改动,建议在动 `studio/` 之前一次做完,不要拖到中途。** 如果你想零风险,也可以让后端留在根目录——架构其余部分不依赖这个决定。
**这是唯一有破坏性的改动,建议在动** `studio/` **之前一次做完,不要拖到中途。** 如果你想零风险,也可以让后端留在根目录——架构其余部分不依赖这个决定。
### 2.2 为什么 `web/` 不改名
@@ -84,6 +88,8 @@ ozon-seller-kit/
---
## 3. 核心数据契约:商品文件夹
**这是整个架构最重要的一个决定。** 四个部分之间不直接调用彼此的代码,只认一个约定:磁盘上的「商品文件夹」。
@@ -113,23 +119,27 @@ ozon-seller-kit/
2. **中间产物可见可改**。采集结果就是普通文件夹,能用 Finder 看、能手动补图、能备份、能在两台机器间拷。
3. **跨平台合并天然成立**。Ozon 采完,切到 1688 采同类商品,选同一个文件夹继续写入——就是往同一目录追加文件,不需要任何服务端参与。
### 3.1 product.json
结构对齐 Ozon `ProductAPI_ImportProductsV3`,但**不等于**它的请求体。区别在于采集阶段拿不到的字段留空,由工作台补齐:
| 字段 | 采集阶段 | 工作台补齐 |
|---|---|---|
| `name` / `description` | ✅ 原文(可能是俄文) | 改写/翻译 |
| `images` | 本地相对路径 | 上传图床后换成公网 URL |
| `offer_id` | ❌ 空 | **必须填自己的货号**(跟卖场景下不能沿用竞品的) |
| `description_category_id` | ❌ 空 | 类目选择/推荐 |
| `attributes[].id` | ❌ 空 | 类目属性字典映射 |
| 尺寸重量 | 参数表里有就带上 | 校验补全 |
| `price` / `old_price` | 采到竞品价,仅供参考 | 计价器算出 |
| 字段 | 采集阶段 | 工作台补齐 |
| ------------------------- | ----------- | -------------------------- |
| `name` / `description` | ✅ 原文(可能是俄文) | 改写/翻译 |
| `images` | 本地相对路径 | 上传图床后换成公网 URL |
| `offer_id` | ❌ 空 | **必须填自己的货号**(跟卖场景下不能沿用竞品的) |
| `description_category_id` | ❌ 空 | 类目选择/推荐 |
| `attributes[].id` | ❌ 空 | 查类目属性字典映射 |
| 尺寸重量 | 参数表里有就带上 | 校验补全 |
| `price` / `old_price` | 采到竞品价,仅供参考 | 计价器算出 |
所以 product.json 有个 `_meta.stage` 字段标明它处在哪个阶段:`collected``edited``published`
契约细节见 [`docs/contracts/product-json.md`](./contracts/product-json.md)。
契约细节见 `[docs/contracts/product-json.md](./contracts/product-json.md)`
### 3.2 契约真源与双语言实现
@@ -148,8 +158,12 @@ server/schemas/product.py (Pydantic)
---
## 4. 各部分职责与边界
### ① 工具台 v1`web/`
**冻结。** 只修 bug,不加功能、不重构、不迁技术栈。它当前的价值是「已经好用」,任何改动都是风险。
@@ -162,7 +176,7 @@ server/schemas/product.py (Pydantic)
不做:LLM 调用、图片处理、Ozon API、持有任何密钥。
一期只支持 Ozon(跟卖是第一优先级),1688 二期。详见 [`docs/extension/plan.md`](./extension/plan.md)。
一期只支持 Ozon(跟卖是第一优先级),1688 二期。详见 `[docs/extension/plan.md](./extension/plan.md)`
### ③ 发布工作台(`studio/`
@@ -172,6 +186,8 @@ server/schemas/product.py (Pydantic)
- **图片处理**:水印、白底、图内翻译、图生图 —— 重活走服务端
- **发布**:提交 Ozon 草稿,回填 `product_id`
### ④ 服务端(`server/`
唯一持有密钥的地方。当前有 `/api/ai/*`(文案);待补 `/api/image/*``/api/ozon/*`
@@ -180,6 +196,8 @@ server/schemas/product.py (Pydantic)
---
## 5. 端到端数据流
```
@@ -204,38 +222,50 @@ server/schemas/product.py (Pydantic)
---
## 6. 技术栈
| 部分 | 技术栈 | 说明 |
|---|---|---|
| ① web | 原生 JS + Tailwind CDN | 不动 |
| ② extension | WXT + React + TS strict | WXT 比 Plasmo 活跃 |
| ③ studio | 待定(见 §8 | |
| server | FastAPI + Pydantic | 已有 |
| 共享 | pnpm workspace | 只为 `packages/schema` 共享,不上 turborepo |
| 部分 | 技术栈 | 说明 |
| ----------- | ----------------------- | ------------------------------------ |
| ① web | 原生 JS + Tailwind CDN | 不动 |
| ② extension | WXT + React + TS strict | WXT 比 Plasmo 活跃 |
| studio | 待定(见 §8 | |
| ④ server | FastAPI + Pydantic | 已有 |
| 共享 | pnpm workspace | 只为 `packages/schema` 共享,不上 turborepo |
pnpm workspace 的唯一目的是让插件和 studio 共用契约类型。`pnpm-workspace.yaml` 三行搞定,不引入构建编排复杂度。
---
## 7. 服务端演进
当前是无状态的:只有 AI 文案代理,没有数据库。按需要逐步加,不要一次上齐:
| 阶段 | 触发条件 | 要加什么 |
|---|---|---|
| 现在 | — | 无状态,`/api/ai/*` |
| S1 | studio 要处理图片 | `/api/image/*`(水印/白底/翻译),仍无状态:收图返图 |
| S2 | 要发布到 Ozon | `/api/ozon/*` + 图床 + 类目字典缓存(SQLite 够用) |
| S3 | 图片处理变慢(图生图、视频) | 任务队列 + `/api/job/:id` 轮询 |
| S4 | 想要跨设备同步 | 商品库落库,本地文件夹降级为导入导出格式 |
| 阶段 | 触发条件 | 要加什么 |
| --- | -------------- | -------------------------------------- |
| 现在 | — | 无状态,`/api/ai/*` |
| S1 | studio 要处理图片 | `/api/image/*`(水印/白底/翻译),仍无状态:收图返图 |
| S2 | 要发布到 Ozon | `/api/ozon/*` + 图床 + 类目字典缓存(SQLite 够用) |
| S3 | 图片处理变慢(图生图、视频) | 任务队列 + `/api/job/:id` 轮询 |
| S4 | 想要跨设备同步 | 商品库落库,本地文件夹降级为导入导出格式 |
**S1、S2 都不需要数据库**,类目字典用文件缓存即可。S4 是个大改动,只在真的有多设备需求时才做——本地文件夹方案的一个优点就是单机场景下完全不需要它。
---
## 8. 已定决策
### D1 · 后端迁入 `server/` ✅
代价是改 `start.command``settings.py``.env` 路径、`deployment.md`。Python 内部 import 不受影响(工作目录切到 `server/` 即可)。**这是唯一有破坏性的改动,在开工 studio 前一次做完。**
@@ -250,10 +280,12 @@ studio 的核心是"几十个字段的结构化表单 + 图片批处理",正
File System Access 在 side panel(扩展页面上下文)可用,`showDirectoryPicker()` 拿到的 handle 存进 IndexedDB 后**跨会话免重复授权**,正好支撑"Ozon 采完切 1688 追加到同一文件夹"。`chrome.downloads` 保留为降级路径(用户拒绝授权时)。
细节见 [`docs/extension/plan-revision.md`](./extension/plan-revision.md) R1。
细节见 `[docs/extension/plan-revision.md](./extension/plan-revision.md)` R1。
---
## 9. 迁移计划
一次性做完,中途不要停在半路:
@@ -285,26 +317,29 @@ File System Access 在 side panel(扩展页面上下文)可用,`showDirect
⑥ web/ 加 README 标注 v1 冻结
```
`reference/1688-extension/` 要不要进 git:它是反编译产物,约 40 个 bundle。建议**加进 `.gitignore`**,保留在本地即可——设计结论已经写进 `docs/extension/plan.md` §2,原始 bundle 只在需要再次查证时才用。
`reference/1688-extension/` 要不要进 git:它是反编译产物,约 40 个 bundle。建议**加进** `.gitignore`,保留在本地即可——设计结论已经写进 `docs/extension/plan.md` §2,原始 bundle 只在需要再次查证时才用。
---
## 10. 里程碑(已调整优先级)
**插件先行:1688/淘宝 → Ozon**。理由见 [`docs/extension/1688-taobao-implementation.md`](./extension/1688-taobao-implementation.md)。
**插件先行:1688/淘宝 → Ozon**。理由见 `[docs/extension/1688-taobao-implementation.md](./extension/1688-taobao-implementation.md)`
| # | 内容 | 依赖 | 产出 | 工作量 |
|---|---|---|---|---|
| **M0** | 目录迁移 + 文档集中 | — | ✅ 已完成,服务正常起 | — |
| **M1** | 插件:1688 采集引擎 | M0 | Console 里能跑 `scanCurrentPage()` | 4h |
| **M2** | 插件:淘宝 profile | M1 | 淘宝页面同样可用 | 1h |
| **M3** | 插件:Side Panel + File System Access | M2 | 生成完整商品文件夹到本地 | 4h |
| **M4** | 插件:sources.json 去重 | M3 | 二次采集追加不重复 | 1h |
| **M5** | 契约真源:product.json Pydantic | M0 | `server/schemas/product.py` | 2h |
| **M6** | 插件:Ozon profile 实测 | M4 | Ozon 选择器验证(需真实页面链接) | 2h |
| **M7** | studio:导入文件夹 + 表单编辑 | M5 | 能改能存 | 8h |
| **M8** | studio + server:图片处理 | M7 | 水印/白底可用 | 6h |
| **M9** | serverOzon 发布 | M8 | 草稿进 Ozon 后台 | 4h |
**M4 结束时插件功能完整**,可以采集 1688/淘宝商品到本地文件夹,跨平台追加不重复。M9 结束时全链路跑通。
| # | 内容 | 依赖 | 产出 | 工作量 |
| ------ | ---------------------------------- | --- | ------------------------------- | --- |
| **M0** | 目录迁移 + 文档集中 | — | ✅ 已完成,服务正常起 | — |
| **M1** | 插件:1688 采集引擎 | M0 | Console 里能跑 `scanCurrentPage()` | 4h |
| **M2** | 插件:淘宝 profile | M1 | 淘宝页面同样可用 | 1h |
| **M3** | 插件:Side Panel + File System Access | M2 | 生成完整商品文件夹到本地 | 4h |
| **M4** | 插件:sources.json 去重 | M3 | 二次采集追加不重复 | 1h |
| **M5** | 契约真源:product.json Pydantic | M0 | `server/schemas/product.py` | 2h |
| **M6** | 插件:Ozon profile 实测 | M4 | Ozon 选择器验证(需真实页面链接) | 2h |
| **M7** | studio:导入文件夹 + 表单编辑 | M5 | 能改能存 | 8h |
| **M8** | studio + server:图片处理 | M7 | 水印/白底可用 | 6h |
| **M9** | serverOzon 发布 | M8 | 草稿进 Ozon 后台 | 4h |
**M4 结束时插件功能完整**,可以采集 1688/淘宝商品到本地文件夹,跨平台追加不重复。M9 结束时全链路跑通。