feat: 方案设计、数据库和接口设计基本完成

This commit is contained in:
R524809
2026-09-02 14:47:18 +08:00
parent a3fe066a5f
commit 04c94e75db
30 changed files with 3305 additions and 122 deletions
+13 -13
View File
@@ -14,18 +14,18 @@
### 2.1 注册
注册页字段只有手机号和密码,均为必填:
注册页字段只有邮箱和密码,均为必填:
| 字段 | 规则 |
|---|---|
| 手机号 | 使用国家区号 + 手机号的标准化格式保存;同一手机号只能注册一个账户。首期注册页默认中国区号,但数据模型和界面需支持后续扩展。 |
| 邮箱 | 去除首尾空格后以不区分大小写的形式保存;同一邮箱只能注册一个账户。首期仅校验基本邮箱格式,不发送验证邮件。 |
| 密码 | 由后续安全设计确定最终长度与复杂度;页面需要二次输入密码并提示规则。密码只可安全散列存储,绝不回显。 |
首期注册成功即可登录使用。短信验证和风控验证不在首期流程执行,但要预留“手机号是否已验证”和“注册/登录风控结果”的状态,未来加功能时不改变账户主流程。
首期注册成功即可登录使用。邮箱验证和注册/登录风控不在首期流程执行,但数据模型预留 `email_verified_at`;后续可增加邮箱验证。手机号、短信验证、短信登录也不在首期范围,未来通过新增可选手机号凭据和验证流程扩展,不影响邮箱账户主流程。
### 2.2 登录与会话
用户用手机号和密码登录。登录成功进入默认工作空间与首页;若后续一个账户拥有多个工作空间,再增加切换入口。首期需要提供退出登录;忘记密码、短信登录、第三方登录、设备管理和多因素认证均不在本轮范围。
用户用邮箱和密码登录。登录成功进入默认工作空间与首页;若后续一个账户拥有多个工作空间,再增加切换入口。首期需要提供退出登录;忘记密码、短信登录、第三方登录、设备管理和多因素认证均不在本轮范围。
### 2.3 全局平台与当前店铺上下文
@@ -78,9 +78,9 @@
- 店铺名称:只读,不可修改。
- 水印:下拉列表,包含当前账户可用的水印模板,也可以选择“暂不绑定”。
- 确认后,该店铺后续上架商品时默认使用此模板处理商品图片;已有图片不会被自动重写。
- 确认后,该店铺保存一个推荐水印模板;已有图片不会被自动重写。首期它不在发布时自动处理商品图片,用户须在商品编辑页对具体图片的“编辑 → 添加水印”中主动选择模板并生成派生图。
一个店铺首期只可绑定一个默认水印;同一水印模板可以绑定给多个店铺。
一个店铺首期只可绑定一个推荐水印;同一水印模板可以绑定给多个店铺。后期可将它用作图片弹窗的默认预选、批量添加或自动添加策略,但这些自动行为不属于首期。
### 3.4 编辑与删除
@@ -133,20 +133,20 @@
“查看效果”使用模板当前配置和固定演示底图打开预览。
### 4.3 上架时的默认加水印规则
### 4.3 商品编辑时主动加水印规则
当用户选择的目标店铺已经绑定水印模板时,点击“上架至 Ozon”后,系统在上传每张商品图片前生成一份带水印的派生图,并把派生图上传给 Ozon;未绑定模板则上传原选图。规则如下:
用户在商品编辑页的已选图片上悬浮,点击“编辑 → 添加水印”,在弹窗选择一个工作空间水印模板。确认后系统对这张图片生成一份带水印的派生图,并以派生图替换此 SKU 当前图片位置。规则如下:
- 商品级图片与每个 SKU 已选图片都适用,最终以实际要提交给 Ozon 的图片集合为准。
- 原始图片和编辑页已选图片不被改写;水印处理产物是一次独立的、可追溯的上传副本。
- 上传任务固化水印模板版本、位置、缩放/字体和不透明度;模板后续编辑不影响已上架商品。
- 用户在具体上架任务中应能查看“将应用的水印模板”;是否允许该次上架临时取消或更换模板,留待发布流程需求确认。
- 商品级候选图片与每个 SKU 已选图片都可处理;最终仅提交用户明确选中的图片集合。
- 原始图片不被改写;水印处理产物是独立、可追溯的派生素材,用户可在编辑弹窗恢复使用原图。
- 派生任务固化水印模板版本、位置、缩放/字体和不透明度;模板后续编辑不影响已生成的派生图。
- 首期不在上架任务中自动加水印,也不允许发布时临时替换;后续另行支持绑定水印的默认预选、批量添加或自动添加。
## 5. 本轮待确认事项
1. 商品限额的 Ozon 数据来源与刷新频率仍待平台接口/真实店铺联调确认;在此之前固定显示 `—`。
2. 账户是否从首期就允许多人共享同一工作空间/协作店铺?如果不做,首期仍按“一个账户一个工作空间”使用,但架构会保留扩展空间。
3. 上架任务是否允许临时取消或替换门店默认水印?
3. 后续“推荐水印”是仅在图片弹窗中预选,还是支持批量/自动生成派生图?
## 6. 非功能性约束
@@ -0,0 +1,132 @@
# 采集箱与在线商品需求
> 状态:已确认核心规则,待补充具体 PostgreSQL 表和 API 契约。采集插件入口和来源多 SKU 规则见 [`collector-browser-extension.md`](./collector-browser-extension.md)。
## 1. 领域边界
采集箱是工作空间共用的商品工作池:插件的“采集商品”“编辑上架”以及手动创建商品,都先创建或复用一条采集箱记录。采集时没有目标平台和门店。用户进入 ERP 编辑时使用页头当前平台;系统为该商品取得或创建这个平台的发布配置,并预选该平台默认门店。门店可以为这次及后续未上架 SKU 修改,但采集箱商品本身不属于任何门店。
**上架成功不会把商品移出采集箱。** 采集箱保留该商品,以便继续查看和编辑 Atlas 草稿;某个已成功提交到平台的 SKU 不能再次提交上架,但同一 SPU 下仍未上架的 SKU 可以首次上架。采集箱状态随**当前页头平台**变化:商品在 A 平台上架后,切换到 B 平台仍是未上架。在线商品是另一份“目标店铺在平台上实际存在什么商品”的同步视图,不能只由 Atlas 的发布记录推断。
```text
来源采集 / 手动创建
→ 采集箱(持续保留、可编辑;已成功上架 SKU 不可再次上架)
→ 发布任务 / Ozon 当前状态
→ 在线商品(店铺级平台同步视图,含非 Atlas 创建商品)
```
## 2. 采集箱列表
默认按更新时间倒序显示当前工作空间内所有未删除的采集箱商品;已上架商品仍显示。
| 列 | 展示与规则 |
|---|---|
| 复选框 | 用于批量删除。 |
| 图片 | 首张已就绪主图;素材转存中显示占位进度,失败显示占位和提示。 |
| 产品名称 | 来源标题或手动填写标题;尚未填写时显示“未命名商品”。 |
| 采集价格 | 单 SKU 显示来源价格;多 SKU 显示最小值–最大值,始终保留来源币种。它不是目标店铺售价。 |
| SKU 数量 | 来源确认的真实 SKU 数;无可靠组合时是默认 SKU `1`,并带“待确认”提示。 |
| 采集来源 | Ozon、1688、淘宝、天猫或手动创建;这是**来源平台**,不是目标发布平台。 |
| 备注 | 工作空间内管理备注,不发送给平台。 |
| 上架状态 | 按页头当前平台显示 `未上架`、`已部分上架` 或 `已上架`,口径见第 3 节。 |
| 创建时间 | 采集箱记录首次创建时间。 |
| 更新时间 | 采集补全、素材转存、编辑保存、发布任务或同步结果更新的时间。 |
| 操作 | 未上架:`编辑上架`、`删除`;已上架:`编辑`、`删除`。 |
顶部功能:
- 按产品标题模糊查询;
- 按采集来源平台筛选;
- 按上架状态筛选;
- `手动创建商品`;
- 容量进度条:`当前有效采集箱商品数 / 1000`;
- `批量删除`、`清空采集箱`。
容量按采集箱商品数计算,不按 SKU 数计算。一条采集箱记录即使含多个 SKU,也只计 1 个。由于已上架商品仍保留在采集箱,它同样占用当前 1000 条临时上限;已删除记录不计入。重复采集命中工作空间内同一 `source_platform + source_item_key` 时复用原记录,不增加额度。
## 3. 当前平台的上架状态和失败原因
列表按当前平台汇总该 SPU 下未删除 SKU 的**首次导入结果**;它不是 Ozon 前台可见性。Ozon 库存由卖家后续在 Ozon 后台设置,`visible`、库存、审核等实际状态在在线商品中查看。主状态有三种:
| 主状态 | 判定 |
|---|---|
| `未上架` | 当前平台没有任何 SKU 导入成功;包括未选择门店、尚未提交、提交处理中或所有已提交 SKU 均失败。 |
| `已部分上架` | 至少一个 SKU 已导入成功,且仍有未删除 SKU 未导入成功或正在处理。 |
| `已上架` | 当前平台下全部未删除 SKU 均已导入成功。若删除所有未上架 SKU、只留下已上架 SKU,状态随即变为此值。 |
“未上架”不能只给笼统结果。状态列的第二行或悬浮详情应展示状态说明:
- `未选择目标平台`;
- `等待发布`;
- `导入处理中` / `审核中`;
- `已导入,库存由 Ozon 后台维护`;
- `审核拒绝:{最近原因}`;
- `上架失败:{最近失败原因}`;
- `已归档或已下架`。
失败原因优先取最近 Atlas 发布任务保存的结构化错误;同步后若 Ozon 返回更准确的 `errors`、`status.decline_reasons` 或 `status.state_description`,以 Ozon 同步结果更新展示。处理/审核中不应误标为失败。
已成功上架的 SKU 没有“重新上架”或“更新平台商品”路径:编辑仅保存 Atlas 草稿,不向 Ozon 提交接口请求。未上架 SKU 可以在同一 SPU 中继续首次上架。若未来需要修改 Ozon 已有商品,应从在线商品的 SKU 行进入专门的“编辑在线商品”流程,并单独设计可修改字段、审核及发布规则;不能复用采集箱的上架按钮。首次发布仍为每个 SKU 保存独立不可变快照和任务记录。
## 4. 编辑、手动创建与删除
### 4.1 编辑上架
点击后进入 ERP 编辑入口:
1. 读取页头当前平台(首期默认 Ozon),取得或创建该商品的当前平台发布配置;
2. 服务端预选该工作空间在此平台的默认店铺,用户可在编辑页改为该平台的另一已授权门店;无门店则提示前往店铺管理;
3. 用户可编辑 SKU、媒体、定价、动态类目属性;已成功上架的 SKU 仅能保存 Atlas 侧编辑,未上架 SKU 可被选择并提交首次上架;
4. 发布成功或失败后均返回/保留采集箱记录,状态和原因随任务、同步更新。
### 4.2 手动创建
“手动创建商品”创建来源为 `manual` 的工作空间级采集箱草稿,并立即打开同一编辑入口。它不因为是手动创建而绕过采集箱、目标平台绑定、发布校验或任务快照。
### 4.3 删除与清空
- 删除只删除 Atlas 中的采集箱记录及其未被其他记录引用的素材关系;不删除来源站商品。
- 已上架采集箱记录也允许删除,但二次确认必须说明:**不会删除或下架 Ozon 商品,也不会从在线商品同步列表移除。**
- 删除时取消未执行的素材任务;已转存文件在确认没有任何引用后延迟物理清理。
- “清空采集箱”清理当前工作空间所有未删除的采集箱记录(包括已上架记录),必须展示数量并二次确认;不影响任何平台商品和在线商品记录。
## 5. 在线商品
在线商品是店铺级的 Ozon 实际商品镜像:既包含通过 Atlas 发布的商品,也包含卖家此前直接在 Ozon 后台或其他工具创建的商品。它是**平台 + 门店独有**的数据,不能跨平台或跨门店复用;即使某行关联到采集箱 SKU,它仍是 Ozon 店铺中的独立事实记录。**列表粒度为 Ozon `product_id` / `offer_id` 对应的一条商品 SKU 行,不按 Atlas 采集箱 SPU 聚合展示。** 一个采集箱 SPU 有多个 SKU 时,在线商品中应显示为多行;外部同步商品同样按这个粒度展示。
### 5.1 Ozon API 能力确认
现有 Ozon Seller API 资料已确认以下同步链路:
1. `POST /v3/product/list`:按 `last_id` 游标分页拉取店铺商品,支持 `ALL`、`VISIBLE`、`INVISIBLE`、`EMPTY_STOCK` 筛选;每项返回 `product_id` 与 `offer_id`,单页最多 1000 条。
2. `POST /v3/product/info/list`:按 `product_id`、`offer_id` 或 `sku` 批量读取详情,每批最多 100 条;返回名称、价格、图片、属性、库存、`visible`、审核状态、失败/拒绝原因和可见性详情。
因此可以使用 `Client-Id + Api-Key` 完成同步,不需要浏览器 Cookie。依据见 [商品列表 API](../integrations/ozon-seller-api/06-product-list.md) 与 [商品信息 API](../integrations/ozon-seller-api/05-product-info.md)。
### 5.2 同步任务
在线商品页提供“同步 Ozon 商品”入口;后台也可按后续确定的频率自动执行。同步必须是 BullMQ 异步任务:
```text
创建 store_online_product_sync 任务
→ /v3/product/list 分页获得全部 product_id + offer_id
→ /v3/product/info/list 每批最多 100 条补全详情
→ 以 store_id + ozon_product_id(或同店 offer_id)upsert 在线商品 SKU 镜像
→ 将 Atlas SKU 映射到匹配的 Ozon 商品;非 Atlas 商品保持“外部同步”来源
→ 成功完成全量分页后,处理本轮未见项目为疑似已删除/已归档,不直接物理删除
→ 保存同步时间、游标、统计、失败原因和原始响应摘要
```
同步中的并发、分页、重试、限流和异常应由 Worker 控制。同步失败保留上一轮成功镜像,并在在线商品页显示“最近同步失败”;不把失败当作平台商品已下架。
### 5.3 与采集箱的关联
通过 Atlas 发布的 SKU,使用 `store_id + offer_id` 和发布回填的 Ozon `product_id` 建立稳定映射。在线商品的每一 SKU 行可显示其 Atlas 来源链接;采集箱 SPU 的当前平台上架状态由首次导入映射汇总,**不**由在线商品的当前可见性派生。外部同步得到的 Ozon 商品也可出现在在线商品,但初始没有采集箱记录或 Atlas 商品关联;后续如需纳入编辑,另行设计“认领/导入在线商品”流程。
## 6. 待补充
1. 采集箱草稿已绑定目标后,是否允许换平台/换店铺及其迁移规则;
2. 在线商品列表的字段、筛选、详情、编辑入口和“认领外部商品”流程;
3. 自动同步频率、手动同步冷却时间、单店并发和限流参数;
4. 采集箱容量 1000 的最终套餐口径及超限提示;
5. 采集箱“首次导入成功”的用户文案,以及在线商品“实际可见/库存”的用户文案;二者必须区分,不能把 `visible=true` 当作采集箱上架状态。
@@ -11,17 +11,18 @@
浏览器插件让用户在来源商品详情页一键把商品导入 Atlas。它必须:
1. 采集商品原始文本、参数、媒体、规格轴和真实 SKU 组合;
2. 把记录写入登录用户当前工作空间的**当前默认店铺**;
2. 把记录写入登录用户当前工作空间共用的采集箱;采集时不关联目标平台或门店;
3. 让用户选择“只进入采集箱”或“导入后直接编辑上架”;
4. 保存来源证据和素材转存任务,确保后续可以修正、重试、审计;
5. 尽可能保留真实多 SKU,不凭名称、图片或笛卡尔积猜测不存在的组合。
5. 尽可能保留真实多 SKU,不凭名称、图片或笛卡尔积猜测不存在的组合;
6. 一期提供 Ozon Seller 网页增强采集:在用户浏览器的现有登录会话中调用第 7.3 节列出的四个接口,保存经过净化的观察结果。
首期来源站点与旧采集插件相同:Ozon(`ozon.ru`、`ozon.kz`、`ozon.by`)、1688、淘宝、天猫。
### 1.2 非目标
- 插件内不展示采集详情、商品字段编辑、AI 智能规划、AI 文案、AI 生图、套图生成、图片导出或定价;这些工作均在 Atlas ERP 页面完成。
- 插件不直接调用 Atlas 的正式发布接口,不直接创建 Ozon offer,也不保存 Ozon Seller Cookie。
- 插件不直接调用 Atlas 的正式发布接口,不直接创建 Ozon offer,也不提取完整、上传或持久化 Ozon Seller Cookie。
- 插件不以网页上的规格名称、SKU 图片或“所有颜色 × 所有尺码”的笛卡尔积推测真实 SKU。
- Ozon Seller 网页内部接口仅用于可观察的实验性采集,不能成为生产发布、库存或定价的唯一数据源。
@@ -38,10 +39,9 @@
| 状态 | 悬浮窗内容 | 行为 |
|---|---|---|
| 未登录或令牌失效 | `登录 Atlas ERP` | 新标签打开 Atlas 登录页。完成授权后,插件自动刷新为已登录状态。 |
| 已登录但没有默认店铺 | `前往 ERP 设置默认店铺` | 打开店铺管理页;不允许导入,避免采集记录落到不确定的店铺。 |
| 已登录且存在当前默认店铺 | `编辑上架`、`采集商品`、`进入 ERP` | 按下面的操作规则执行。 |
| 已登录 | `编辑上架`、`采集商品`、`进入 ERP` | 允许采集;采集箱记录只归属工作空间,不要求已有目标店铺。 |
首期不在悬浮窗中选择店铺。服务端从插件授权身份解析工作空间,并使用该工作空间的当前默认店铺;默认店铺切换在 ERP 中完成。
首期不在悬浮窗中选择平台或店铺。服务端从插件授权身份只解析工作空间,创建未绑定目标平台/门店的采集记录和商品基础草稿。用户进入 Atlas ERP 编辑页时,页面使用页头当前选中的平台;首期页头默认选择 Ozon,服务端取得该平台发布配置并预选默认店铺。若当前平台没有可用门店,允许保留采集箱记录,但不能进入该平台的商品编辑/发布流程,应引导用户在店铺管理中添加门店。
推荐采用扩展专用的短期授权码流程:插件打开 Atlas 登录/授权页,登录页完成后向 `chrome-extension://{extension-id}/...` 回传一次性 code,插件交换短期 access token 与可轮换 refresh token。令牌只放 Chrome 扩展专属存储,后台请求统一携带 `Authorization: Bearer`。不得像参考插件一样直接读取 ERP 网页 localStorage 中的长期 Token。
@@ -49,26 +49,27 @@
| 操作 | 流程 | 成功结果 |
|---|---|---|
| 编辑上架 | 扫描当前页 → 上报采集记录 → 创建/复用商品草稿 → 打开编辑页 | 新标签打开 `/products/{productId}/editor`;素材继续后台转存,编辑页显示状态。 |
| 编辑上架 | 扫描当前页 → 上报采集记录 → 创建/复用未绑定目标的商品基础草稿 → 打开 ERP 编辑入口 | 新标签打开 `/collection-items/{collectionItemId}/edit`;ERP 按页头当前平台取得发布配置并预选门店后进入 `/products/{productId}/editor`,素材继续后台转存。 |
| 采集商品 | 扫描当前页 → 上报采集记录 | 停留来源页,提示“已进入采集箱”;用户以后从采集箱编辑。 |
| 进入 ERP | 不扫描、不上报 | 新标签打开 Atlas ERP 首页。 |
“上报成功”定义为:数据库事务已创建或复用采集记录、商品草稿、SKU 草稿和素材转存任务。它不等待所有图片下载完成;各素材的 `pending/downloading/ready/failed` 状态在采集箱和编辑页可见,失败可单独重试。
“上报成功”定义为:数据库事务已创建或复用工作空间级采集记录、未绑定目标的商品草稿、SKU 草稿和素材转存任务。它不等待所有图片下载完成;各素材的 `pending/downloading/ready/failed` 状态在采集箱和编辑页可见,失败可单独重试。
## 3. 端到端流程与状态
```text
来源商品详情页
→ 插件认证、确认当前默认店铺
→ 插件认证、确认当前工作空间
→ 平台采集器(原始证据 + 规范化结果)
→ 扩展后台统一上报
→ Atlas API:幂等创建采集记录、SPU 草稿、真实 SKU 草稿、素材任务
→ Atlas API:幂等创建工作空间级采集记录、未绑定平台/门店的 SPU 基础草稿、真实 SKU 草稿、素材任务
→ Redis/BullMQ Worker:下载、校验、去重、转存到 MinIO/Kodo
→ 采集箱
├─ 继续编辑:商品编辑页
→ 工作空间共用采集箱(无目标平台/门店;上架后仍保留)
├─ 当前平台下未上架 SKU:编辑并首次上架;已上架 SKU:仅编辑 Atlas 草稿,不能再次上架
└─ 删除/归档/重试
→ 文案、SKU 媒体、定价、AI 生图、发布校验
→ 发布快照 → 官方 Ozon Seller API 导入、轮询、库存设置、上线状态
→ 发布快照 → 官方 Ozon Seller API 导入、轮询;库存由用户在 Ozon 后台设置
→ 在线商品:异步同步店铺全部 Ozon 商品(含非 Atlas 发布商品)
```
建议的采集状态:
@@ -83,7 +84,13 @@
| `failed` | 采集请求或关键记录创建失败;保留可诊断错误。 |
| `archived` | 用户不再处理的采集记录。 |
同一默认店铺内,以 `source_platform + source_item_key` 进行幂等。重复“采集商品”应返回已有采集记录;重复“编辑上架”打开同一商品草稿。只有用户在 ERP 中明确选择“重新采集并合并/创建副本”时,才允许覆盖或复制。
同一工作空间内,以 `source_platform + source_item_key` 进行幂等。重复“采集商品”应返回已有采集记录;重复“编辑上架”打开同一未绑定目标的商品草稿或其已绑定的编辑入口。只有用户在 ERP 中明确选择“重新采集并合并/创建副本”时,才允许覆盖或复制。
### 3.1 采集箱与目标店铺的绑定时点
采集来源平台与目标发布平台是不同概念:例如从 1688 采集的商品可以在后续发布到 Ozon,也可能未来发布到其他平台。因此采集箱和刚创建的商品草稿只携带 `workspace_id`、来源平台及来源证据,`target_platform_id`、`target_store_id` 均为未设置状态。
用户从采集箱点击“编辑”时,ERP 读取页头当前平台。服务端验证该平台存在于当前系统配置中,并取得/创建该商品在这个平台的发布配置,预选该工作空间在该平台的默认店铺;用户可在编辑页改选门店。A 平台与 B 平台的发布配置和 SKU 上架状态相互独立。扩展不能传入、指定或覆盖这个选择。
## 4. 统一采集数据模型
@@ -243,12 +250,12 @@ interface CollectedVariant {
### 7.1 目的与边界
毛子 ERP 在公开 Ozon 商品页采集外,还要求浏览器打开已登录的 `seller.ozon.ru`,并通过跨标签消息调用 Seller 网页的内部接口。Atlas 可以在 Ozon 采集插件中实现一个**可选、显式开启、只用于观察结果**的实验模式。
毛子 ERP 在公开 Ozon 商品页采集外,还要求浏览器打开已登录的 `seller.ozon.ru`,并通过跨标签消息调用 Seller 网页的内部接口。Atlas **一期即实现**第 7.3 节四个接口的浏览器本地观察模式;用户须在插件设置中显式开启。
实验模式目标是把公开页面发现的来源 SKU 与 Seller 网页返回的补充数据并排保存,帮助评估是否值得采用;它不得:
- 自动修改 Atlas 商品、价格、包装规格、库存或发布数据;
- 读取、保存、上传或记录 Seller Cookie、`company_id` 以外的会话凭据;
- 提取完整 Cookie、保存/上传 Cookie,或将 Cookie 写入日志、数据库、队列和扩展持久化存储;
- 替代官方 `Client-Id + Api-Key` Seller API 的正式发布、库存和状态同步;
- 将返回的销量/浏览等数据表述为“当前店铺数据”,除非 Ozon 未来提供可验证的官方契约。
@@ -270,7 +277,9 @@ interface CollectedVariant {
→ 毛子 ERP 加密后上传自己的后端
```
Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技术结构。实验结果进入 `source_evidence` 或独立 `seller_enrichment_observations`,保存原始响应的净化副本、字段清单、接口名、时间、当前来源 SKU、解析版本和错误信息。
Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技术结构。四个请求由浏览器扩展在 Seller 同源标签的页面上下文执行,`credentials: include` 仅让浏览器自动附带现有会话 Cookie;Atlas 不取得 Cookie 正文。请求所需的 `company_id` 仅在本次浏览器会话内从已登录 Seller 页面状态或 `sc_company_id` Cookie 取得,不上传为会话凭据、不写入扩展持久化存储。
实验结果进入 `source_evidence` 或独立 `seller_enrichment_observations`,保存**净化后的**响应副本、字段清单、接口名、采集时间、当前来源 SKU、解析版本和错误信息。`company_id` 如确有诊断必要,只能保存不可逆摘要或单独受控的店铺匹配标记,不能保存完整 Cookie。
### 7.3 四个接口与已观察到的用途
@@ -291,40 +300,54 @@ Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技
验证方法:使用两个不同店铺账户,对同一个不属于任一店铺的公开 SKU 对比响应;再和当前店铺已上架 SKU 的官方 Seller API 数据对比。只有在口径、权限和稳定性得到确认后,才能决定是否建设独立“选品洞察”功能。
### 7.5 Atlas 实验流程与安全控制
### 7.5 一期 Atlas 本地观察流程与安全控制
1. 用户在插件设置中显式打开“采集 Ozon Seller 网页观察数据(实验)”。默认关闭。
2. 用户自行在浏览器登录 `seller.ozon.ru`;插件只检测标签页和请求可用性,不显示、不导出、不持久化 Cookie。
3. 标准公开页面采集先完成。对每一个发现的 `sourceVariantKey`,后台按低并发、有限数量发起四个观察请求。
1. 用户在插件设置中显式打开“采集 Ozon Seller 网页观察数据(实验)”;默认关闭。该开关和第 7.3 节四接口能力均在一期交付。
2. 用户自行在浏览器登录 `seller.ozon.ru` 并保留一个有效 Seller 标签页;插件只检测标签页和请求可用性,不显示、不导出、不持久化 Cookie。
3. 标准公开页面采集先完成。对每一个发现的 `sourceVariantKey`,扩展后台按低并发、有限数量,通过 Seller 标签页依次发起四个观察请求。
4. 回传前清除请求/响应中可能存在的会话字段、用户信息、店铺名称、授权头等无关信息;服务器再次执行结构化白名单与脱敏。
5. 结果写入工作空间隔离的观察记录。采集箱展示“公开页数据 / Seller 网页观察数据”的字段差异,但不会自动覆盖草稿。
6. 请求失败、账号无权、没有 Seller 标签页或内部接口变更时,只记录 `unavailable` 原因;“编辑上架”和“采集商品”仍正常完成。
### 7.6 Cookie 能力分级与毛子 ERP 调研结论
“不持久化 Cookie”不等于“不使用用户浏览器的现有登录态”。浏览器在 Seller 同源 `fetch(..., { credentials: 'include' })` 时会自动附带该站 Cookie;Cookie 不需要、也不应离开浏览器才能完成一期四接口观察。
已核对的毛子 ERP 插件行为:它具有 Chrome `cookies` 权限;其本地跨标签请求会读取 `sc_company_id` 并使用 `credentials: 'include'` 调用四个接口;此外,用户点击“绑定 Cookie”后,它会读取完整 Seller Cookie 列表并提交给毛子后端的 `/api.shop/set_cookies`。该后端后续具体调用范围无法仅凭插件产物证明。
| 级别 | Cookie 位置与用途 | 能力边界 | Atlas 决策 |
|---|---|---|---|
| **一级:浏览器本地观察** | 用户浏览器管理 Cookie;扩展仅在已登录 Seller 标签页同源发请求,不读取完整 Cookie 值。 | 一期调用第 7.3 节四接口,保存净化结果;用户需保持浏览器 Seller 登录态。 | **一期实现。** |
| 二级:加密保存 Cookie(实验) | 用户显式授权后,浏览器将会话 Cookie 加密上传;云端 Worker 在白名单内调用网页接口。 | 可在用户未打开浏览器时执行已验证的补充查询或定时刷新;不自动获得任何未经验证的新业务能力。 | **预留,不实现。** |
| 三级:Cookie 驱动业务自动化 | 云端以会话身份调用具有写入副作用的网页接口。 | 可能涉及发布、改价、库存、广告等高风险操作;接口稳定性、账号权限、平台规则均未确认。 | **不纳入当前规划。** |
二级若未来立项,必须逐接口白名单、独立风险评审和用户再次授权;按门店验证 `company_id` 匹配;Cookie 只做信封加密保存,队列仅传 `secret_id`;不得记录明文、不得返回前端,支持立即撤销、过期检测和完整审计。无论任何级别,正式商品发布、库存和状态同步仍以官方 `Client-Id + Api-Key` Seller API 为准。
## 8. Atlas API、任务与存储
### 8.1 插件接口建议
| 接口 | 用途 |
|---|---|
| `GET /api/extension/session` | 返回登录状态、工作空间、当前默认店铺是否可用;不返回敏感门店凭据。 |
| `GET /api/extension/session` | 返回登录状态和工作空间是否可用;不返回平台、目标店铺或敏感门店凭据。 |
| `POST /api/extension/auth/exchange` | 用一次性授权码交换扩展短期令牌。 |
| `POST /api/extension/materials` | 接收 `CollectedProductPayload`;服务端解析当前身份与默认店铺,实施幂等创建。 |
| `POST /api/extension/materials` | 接收 `CollectedProductPayload`;服务端仅解析当前工作空间,实施幂等创建未绑定目标平台/门店的采集记录和草稿。 |
| `GET /api/collection-items/{id}` | 查询采集记录、SKU 发现数、素材转存状态和警告。 |
| `POST /api/collection-items/{id}/retry-assets` | 重新投递失败素材。 |
| `POST /api/collection-items/{id}/seller-enrichment-observations` | 仅实验开关启用时接收已净化的 Ozon Seller 网页观察数据。 |
| `POST /api/collection-items/{id}/seller-enrichment-observations` | 一期的本地观察开关启用时,接收已净化的四接口结果;不接收 Cookie。 |
不得让插件在请求体中随意指定 `workspace_id` 或 `store_id`。服务端从令牌确定工作空间,读取该工作空间的当前默认店铺,并在事务中应用 PostgreSQL RLS。
不得让插件在请求体中随意指定 `workspace_id`、`platform_id` 或 `store_id`。服务端从令牌确定工作空间并在事务中应用 PostgreSQL RLS;目标平台和店铺仅在 ERP 编辑入口按第 3.1 节规则绑定。
### 8.2 素材转存
- 插件上报来源 URL、Referer origin、MIME/类型、组别、排序和媒体关系;不把二进制图片塞进常规 JSON。
- Worker 用受控请求下载来源素材,进行 MIME、大小、尺寸、哈希校验,再写入私有 MinIO/Kodo 对象存储。
- Worker 用受控请求下载来源素材,进行 MIME、大小、尺寸、哈希校验,再写入私有 MinIO/Kodo 对象存储;资产记录保存 `storage_provider + bucket + object_key`,不保存转存后文件的长期访问 URL。
- 下载受来源防盗链、过期 URL 或风控影响而失败时,保留来源 URL 和错误;用户可重新采集或在编辑页手动上传。
- 同一工作空间内用内容哈希和来源规范化 URL 去重,但同一资产可在多个商品/SKU 媒体关系中复用。
### 8.3 可恢复性
采集记录、素材任务、Ozon Seller 网页实验请求和未来发布任务都应先写 PostgreSQL,再经 outbox 投递 BullMQ。重试必须有幂等键、次数上限、指数退避和可见错误。浏览器关闭、Worker 重启或 Redis 重建都不能造成已创建商品草稿重复或素材关系丢失。
采集记录、素材任务和未来发布任务都应先写 PostgreSQL,再经 outbox 投递 BullMQ。第 7.3 节四接口请求必须在用户浏览器的 Seller 同源标签完成,不能投递给云端 Worker;扩展将结果或 `unavailable` 原因提交服务端后再落库。浏览器关闭、Worker 重启或 Redis 重建都不能造成已创建商品草稿重复或素材关系丢失。
## 9. 旧实现与参考实现的取舍
@@ -348,10 +371,10 @@ Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技
### 10.1 分期
1. **采集基础**:扩展认证、小浮窗、默认店铺检查、统一载荷、采集箱入库、素材转存、幂等和“编辑上架/采集商品”。
1. **采集基础与 Seller 本地观察**:扩展认证、小浮窗、工作空间检查、统一载荷、无目标平台/门店的采集箱入库、素材转存、幂等和“编辑上架/采集商品”;同时实现第 7.3 节四接口的跨标签同源调用、净化存储、`unavailable` 回退和字段差异展示。
2. **真实多 SKU**:1688 `skuMapOriginal`、淘宝/天猫 `skuId + propPath`、Ozon 公开 `sku` 变体遍历;完善 SKU 媒体继承与采集箱警告。
3. **Ozon Seller 网页观察实验**:四个接口的同源调用、净化存储、字段差异观察页与双店铺验证;不接入正式发布链路。
4. **编辑与发布闭环**:动态属性、AI 文案/媒体、定价快照、发布校验、官方 Ozon Seller API 导入、轮询和库存设置。
3. **观察数据验证**:用双店铺账户完成字段字典、口径、权限范围和稳定性对照;不接入正式发布链路,也不升级为 Cookie 云端保存。
4. **编辑与发布闭环**:动态属性、AI 文案/媒体/类目、定价快照、发布校验、官方 Ozon Seller API 导入和轮询;库存由用户在 Ozon 后台设置。
### 10.2 验收样本矩阵
@@ -366,17 +389,17 @@ Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技
| 无 SKU 图 | 真实 SKU 均存在并继承父商品默认图。 |
| 个别变体详情/素材失败 | 保留发现的 SKU 和错误;可单独重试。 |
| 重复点击采集 | 复用同一采集记录和商品草稿。 |
| 无默认店铺/令牌过期 | 只显示正确的登录或设置引导,不写入数据。 |
| Ozon Seller 实验无权限 | 标准公开采集成功,观察实验单独失败且不阻塞。 |
| 无目标店铺/令牌过期 | 没有 Ozon 默认店铺时仍可采集;进入 Ozon 编辑时提示设置默认店铺。令牌过期时只显示登录引导,不写入数据。 |
| Ozon Seller 本地观察无权限、未登录或无 Seller 标签页 | 标准公开采集成功,四接口观察分别记录 `unavailable` 且不阻塞。 |
## 11. 待确认与后续文档
本文件已确认插件入口、默认店铺、多 SKU 基本原则和 Ozon Seller 网页观察实验的边界。实施前仍需补充:
本文件已确认插件入口、工作空间共用采集箱、目标平台/门店绑定时点、多 SKU 基本原则和 Ozon Seller 网页观察实验的边界。实施前仍需补充:
1. `CollectedProductPayload` 的 OpenAPI/JSON Schema 与 PostgreSQL 表、迁移和 RLS 细节;
2. 当前默认店铺的服务端选择、切换和删除规则;
2. ERP 页头当前平台、该平台默认店铺的选择、切换和删除规则,以及采集草稿已绑定目标后的换平台策略;
3. 各来源真实页面快照测试集与解析器版本策略;
4. Ozon Seller 网页四接口实验的字段字典、双店铺对照结果、数据保留期和是否继续投入;
4. Ozon Seller 网页四接口的字段字典、双店铺对照结果、数据保留期和是否具备建设独立选品洞察的价值;
5. 采集箱列表、详情、重新采集、合并与归档的页面需求;
6. 正式 Ozon 发布任务的状态机、请求/响应审计与库存策略。
+3 -3
View File
@@ -82,10 +82,10 @@
| 分组 | 字段 | 规则 |
|---|---|---|
| 目标市场 | 履约模式、当前平台商品类目 | 当前平台和当前店铺从页头读取;店铺自动带入币种和默认定价方案。平台商品类目和平台佣金类目均强绑定当前平台;履约模式首期预留 FBS/FBO,实际可用项由该平台的佣金规则决定。 |
| 目标市场 | 履约模式、当前平台商品类目 | 当前平台和当前店铺从页头读取;店铺带入默认计价币种和定价方案。市场不是门店字段:首期使用当前平台默认市场 `RU`,未来多市场时由顶部全局上下文选择或使用平台默认值。平台商品类目和平台佣金类目均强绑定当前平台;履约模式首期预留 FBS/FBO,实际可用项由该平台的佣金规则决定。 |
| 商品与包裹 | 采购成本、包裹实重、长/宽/高 | 采购成本首期以 CNY 输入;重量以 g、尺寸以 cm 或 mm 输入。体积由三边自动计算,不能只存一个孤立体积值。允许显示并在必要时人工确认体积重。 |
| 定价目标 | 期望加价率、划线折扣率、广告费占比、其他占比 | 所有比例必须明确单位为 `%`。期望加价率与划线折扣率的计算口径见第 7 节。 |
| 费用与物流 | 跨境物流商、运输方式、国内运费+代贴单、尾程(Ozon 代理费)、提现费、汇率 | 默认选择 CEL 并同时勾选其可用运输方式;用户可比较全部方式。国内运费+代贴单为固定金额;尾程、提现费为比例;汇率必须显示来源、值和更新时间,允许本次覆盖。 |
| 费用与物流 | 跨境物流商、运输方式、国内运费+代贴单、尾程(Ozon 代理费)、提现费、汇率 | 默认选择 CEL 并同时勾选其可用运输方式;用户可比较全部方式。国内运费+代贴单为固定金额;尾程、提现费为比例;系统汇率首期使用 CBR 的 CNY→RUB 官方参考汇率,必须显示来源、适用日期、值和抓取时间,允许本次覆盖。详见 [`../architecture/exchange-rates.md`](../architecture/exchange-rates.md)。 |
“其他”可先作为单一百分比输入,展示名称为“其他(提醒、货损等)”。规则模型必须支持将来拆成多项费用,例如货损、退款准备金、保险、税费,而不改变最终报价结构。
@@ -111,7 +111,7 @@
### 4.3 缺失与异常
- 缺少类目佣金、有效运价、汇率、采购成本或有效包裹数据时,不输出建议售价,指出缺失项。
- 缺少类目佣金、有效运价、系统汇率、采购成本或有效包裹数据时,不输出建议售价,指出缺失项;用户可按权限选择定价方案固定汇率或本次覆盖。若系统 CBR 汇率超过 72 小时未更新,须醒目标记“可能过期”,不得伪装为最新数据。
- 包裹尺寸不适用于某个运输方式、超过重量/尺寸上限或无法得到计费重时,该方式单独标为不可报价,不影响其他方式。
- 临时覆盖的佣金、汇率或运价必须以醒目标记,并且保存结果时固化为快照。