feat: 采集插件需求和方案
This commit is contained in:
+7
-6
@@ -15,9 +15,10 @@
|
||||
## 当前阅读顺序
|
||||
|
||||
1. [`project/HANDOFF.md`](./project/HANDOFF.md):项目边界和已经确认的商品规则。
|
||||
2. [`requirements/account-store-watermark.md`](./requirements/account-store-watermark.md):账户、门店和水印需求。
|
||||
3. [`requirements/pricing-tool.md`](./requirements/pricing-tool.md):独立试算、SKU 定价方案和物流规则需求。
|
||||
4. [`requirements/cel-ozon-rfbs-rates-review.md`](./requirements/cel-ozon-rfbs-rates-review.md):从 CEL Ozon-rFBS 资费表提取的待审核规则。
|
||||
5. [`architecture/foundation-data-model.md`](./architecture/foundation-data-model.md):基础模块数据模型和 PostgreSQL DDL。
|
||||
6. [`architecture/technology-and-deployment.md`](./architecture/technology-and-deployment.md):已确认的 NestJS、PostgreSQL、Redis/BullMQ、MinIO、七牛 Kodo 与部署策略。
|
||||
7. 需求确认后,才创建对应的接口和开发方案文档。
|
||||
2. [`requirements/collector-browser-extension.md`](./requirements/collector-browser-extension.md):来源商品采集、采集箱、多 SKU、插件认证和 Ozon Seller 网页观察实验。
|
||||
3. [`requirements/account-store-watermark.md`](./requirements/account-store-watermark.md):账户、门店和水印需求。
|
||||
4. [`requirements/pricing-tool.md`](./requirements/pricing-tool.md):独立试算、SKU 定价方案和物流规则需求。
|
||||
5. [`requirements/cel-ozon-rfbs-rates-review.md`](./requirements/cel-ozon-rfbs-rates-review.md):从 CEL Ozon-rFBS 资费表提取的待审核规则。
|
||||
6. [`architecture/foundation-data-model.md`](./architecture/foundation-data-model.md):基础模块数据模型和 PostgreSQL DDL。
|
||||
7. [`architecture/technology-and-deployment.md`](./architecture/technology-and-deployment.md):已确认的 NestJS、PostgreSQL、Redis/BullMQ、MinIO、七牛 Kodo 与部署策略。
|
||||
8. 需求确认后,才创建对应的接口和开发方案文档。
|
||||
|
||||
@@ -31,7 +31,7 @@ SKU 名称只用于展示;采集 SKU 用稳定 `source_variant_key` 关联,
|
||||
|
||||
## 4. 定价弹窗
|
||||
|
||||
点击 SKU 的“定价”打开弹窗,显示该 SKU 合并后的包装物流规格,并允许调整采购价、利润率、贴单费、物流等级、划线价倍数和汇率。服务端计算预览、尺寸校验和告警;确认后保存不可变快照,并回填 SKU 销售价和划线价。
|
||||
点击 SKU 的“定价”打开弹窗,显示该 SKU 合并后的包装物流规格,并允许调整采购价、期望加价率、贴单费、物流方式、划线折扣率和汇率。服务端计算预览、尺寸校验和告警;确认后保存不可变快照,并回填 SKU 销售价和划线价。划线价统一按 `划线价 = 销售价 ÷ (1 − 划线折扣率)` 计算,不使用或兼容“划线价倍数”。
|
||||
|
||||
包装规格缺失、口径待确认、数值无效或不符合物流限制时不得确认。实物规格不进入物流计算;它缺失时仅禁用尺寸图。
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
| 尺寸图 | 必须逐 SKU 生成,任务保存 SKU ID 和实物规格快照。 |
|
||||
| 定价 | SKU 上点“定价”打开弹窗,以有效包装数据计算;用户确认后回填 SKU 销售价和划线价。 |
|
||||
| 编辑体验 | 新商品 AI 编辑页取代旧商品编辑页;旧试算页不再追加多 SKU 功能。 |
|
||||
| 媒体 | 采集主图/详情图是商品候选池;只有来源有稳定关联时才把图片绑定 SKU。1688、淘宝、天猫暂不假设能可靠采集 SKU 图片。 |
|
||||
| 发布 | 本期只设计“上架至平台”按钮与数据边界,不实现真正发布。 |
|
||||
| 采集插件 | 采集 Ozon、1688、淘宝、天猫详情页;未登录只显示登录入口,已登录显示“编辑上架 / 采集商品 / 进入 ERP”。采集记录始终写入当前工作空间的默认店铺。详情见 [`requirements/collector-browser-extension.md`](../requirements/collector-browser-extension.md)。 |
|
||||
| 采集 SKU | 只有来源给出稳定 SKU/组合证据时创建多个 SKU;不能把规格轴做笛卡尔积。没有专属 SKU 图时,真实 SKU 继承父商品默认图而不复制资产。 |
|
||||
| 媒体 | 采集主图/详情图是商品候选池;来源明确给出 SKU、或可靠的规格轴值(如颜色)与图片关系时才自动绑定。其余素材由编辑页人工选择。 |
|
||||
| 发布 | 商品采集、编辑、定价、AI 媒体和发布至 Ozon 后台并上线是核心闭环。正式发布使用官方 Seller API,按一 SKU 一 import item/offer 执行、轮询结果并设置库存。 |
|
||||
|
||||
## 3. Ozon 已核对结论
|
||||
|
||||
@@ -39,6 +41,7 @@
|
||||
4. 本地素材使用 MinIO;共享测试和生产素材使用七牛 Kodo,不使用应用服务器本地目录作为持久存储。
|
||||
5. AI、生图、导出、采集转存和发布使用 Redis + BullMQ 队列/Worker,任务可重试、可恢复且携带工作空间与 SKU 上下文。
|
||||
6. 用户界面语言、采集源语言、商品编辑语言和发布目标语言相互独立;文案及属性值需要支持多语言版本。
|
||||
7. Ozon Seller 网页内部接口可以在插件中作为显式开启的观察性实验采集;不得保存 Cookie、不得阻塞标准采集、不得替代官方 Seller API 发布或把未验证经营数据视为本店事实。
|
||||
|
||||
建议的核心层级:
|
||||
|
||||
@@ -51,13 +54,14 @@ User → Workspace → Membership / Role
|
||||
|
||||
## 5. 下一步建议
|
||||
|
||||
在开始前端或商品模块前,先形成以下文档并获得确认:
|
||||
在开始实施前,以下内容需要继续细化并获得确认:
|
||||
|
||||
1. 云端多租户、认证、权限与门店模型;
|
||||
2. PostgreSQL schema、迁移策略和租户隔离策略;
|
||||
3. 平台适配器接口(先 Ozon,后续可接其他平台);
|
||||
4. 多语言/市场/币种的数据模型;
|
||||
5. 对象存储、任务队列、密钥加密和部署方案。
|
||||
6. 浏览器采集载荷、采集箱页面、真实多 SKU 解析测试集,以及 Ozon Seller 网页观察实验的字段口径,见 [`requirements/collector-browser-extension.md`](../requirements/collector-browser-extension.md)。
|
||||
|
||||
之后再按 `docs/product/` 的商品编辑页、数据库和 API 契约实现产品功能。
|
||||
|
||||
@@ -67,4 +71,5 @@ User → Workspace → Membership / Role
|
||||
- [编辑页交互设计](../product/product-ai-editor.md)
|
||||
- [商品/SKU 数据模型](../product/data-model.md)
|
||||
- [商品编辑 API 契约](../product/api.md)
|
||||
- [浏览器采集插件需求与技术方案](../requirements/collector-browser-extension.md)
|
||||
- [技术栈、异步任务与部署方案](../architecture/technology-and-deployment.md)
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
# 浏览器采集插件:需求与技术方案
|
||||
|
||||
> 状态:已确认核心方向,待实施。本文是 Atlas Seller Kit 从来源商品详情页进入采集箱、商品编辑与后续 Ozon 上线的采集入口规范。
|
||||
>
|
||||
> 本文取代旧 `ozon-seller-kit` 采集插件的产品定位,但只复用经验证的页面采集思路,不复用旧项目的本地数据库、无鉴权接口、`/trial/:id` 页面、AI 套图或生图流程。
|
||||
|
||||
## 1. 目标、范围与非目标
|
||||
|
||||
### 1.1 目标
|
||||
|
||||
浏览器插件让用户在来源商品详情页一键把商品导入 Atlas。它必须:
|
||||
|
||||
1. 采集商品原始文本、参数、媒体、规格轴和真实 SKU 组合;
|
||||
2. 把记录写入登录用户当前工作空间的**当前默认店铺**;
|
||||
3. 让用户选择“只进入采集箱”或“导入后直接编辑上架”;
|
||||
4. 保存来源证据和素材转存任务,确保后续可以修正、重试、审计;
|
||||
5. 尽可能保留真实多 SKU,不凭名称、图片或笛卡尔积猜测不存在的组合。
|
||||
|
||||
首期来源站点与旧采集插件相同:Ozon(`ozon.ru`、`ozon.kz`、`ozon.by`)、1688、淘宝、天猫。
|
||||
|
||||
### 1.2 非目标
|
||||
|
||||
- 插件内不展示采集详情、商品字段编辑、AI 智能规划、AI 文案、AI 生图、套图生成、图片导出或定价;这些工作均在 Atlas ERP 页面完成。
|
||||
- 插件不直接调用 Atlas 的正式发布接口,不直接创建 Ozon offer,也不保存 Ozon Seller Cookie。
|
||||
- 插件不以网页上的规格名称、SKU 图片或“所有颜色 × 所有尺码”的笛卡尔积推测真实 SKU。
|
||||
- Ozon Seller 网页内部接口仅用于可观察的实验性采集,不能成为生产发布、库存或定价的唯一数据源。
|
||||
|
||||
## 2. 用户体验
|
||||
|
||||
### 2.1 出现位置与外观
|
||||
|
||||
在受支持来源站的**商品详情页**右下角显示一个小型矩形悬浮窗。它应使用 Shadow DOM 隔离来源站 CSS,布局接近参考插件:品牌图标/名称、收起按钮和纵向操作按钮。非商品页或 URL 软导航到非商品页时隐藏。
|
||||
|
||||
插件不使用旧版的全高 iframe Side Panel。点击操作时仅显示短暂的加载、成功或失败状态;复杂信息回到 ERP 页面展示。
|
||||
|
||||
### 2.2 登录态
|
||||
|
||||
| 状态 | 悬浮窗内容 | 行为 |
|
||||
|---|---|---|
|
||||
| 未登录或令牌失效 | `登录 Atlas ERP` | 新标签打开 Atlas 登录页。完成授权后,插件自动刷新为已登录状态。 |
|
||||
| 已登录但没有默认店铺 | `前往 ERP 设置默认店铺` | 打开店铺管理页;不允许导入,避免采集记录落到不确定的店铺。 |
|
||||
| 已登录且存在当前默认店铺 | `编辑上架`、`采集商品`、`进入 ERP` | 按下面的操作规则执行。 |
|
||||
|
||||
首期不在悬浮窗中选择店铺。服务端从插件授权身份解析工作空间,并使用该工作空间的当前默认店铺;默认店铺切换在 ERP 中完成。
|
||||
|
||||
推荐采用扩展专用的短期授权码流程:插件打开 Atlas 登录/授权页,登录页完成后向 `chrome-extension://{extension-id}/...` 回传一次性 code,插件交换短期 access token 与可轮换 refresh token。令牌只放 Chrome 扩展专属存储,后台请求统一携带 `Authorization: Bearer`。不得像参考插件一样直接读取 ERP 网页 localStorage 中的长期 Token。
|
||||
|
||||
### 2.3 三个操作
|
||||
|
||||
| 操作 | 流程 | 成功结果 |
|
||||
|---|---|---|
|
||||
| 编辑上架 | 扫描当前页 → 上报采集记录 → 创建/复用商品草稿 → 打开编辑页 | 新标签打开 `/products/{productId}/editor`;素材继续后台转存,编辑页显示状态。 |
|
||||
| 采集商品 | 扫描当前页 → 上报采集记录 | 停留来源页,提示“已进入采集箱”;用户以后从采集箱编辑。 |
|
||||
| 进入 ERP | 不扫描、不上报 | 新标签打开 Atlas ERP 首页。 |
|
||||
|
||||
“上报成功”定义为:数据库事务已创建或复用采集记录、商品草稿、SKU 草稿和素材转存任务。它不等待所有图片下载完成;各素材的 `pending/downloading/ready/failed` 状态在采集箱和编辑页可见,失败可单独重试。
|
||||
|
||||
## 3. 端到端流程与状态
|
||||
|
||||
```text
|
||||
来源商品详情页
|
||||
→ 插件认证、确认当前默认店铺
|
||||
→ 平台采集器(原始证据 + 规范化结果)
|
||||
→ 扩展后台统一上报
|
||||
→ Atlas API:幂等创建采集记录、SPU 草稿、真实 SKU 草稿、素材任务
|
||||
→ Redis/BullMQ Worker:下载、校验、去重、转存到 MinIO/Kodo
|
||||
→ 采集箱
|
||||
├─ 继续编辑:商品编辑页
|
||||
└─ 删除/归档/重试
|
||||
→ 文案、SKU 媒体、定价、AI 生图、发布校验
|
||||
→ 发布快照 → 官方 Ozon Seller API 导入、轮询、库存设置、上线状态
|
||||
```
|
||||
|
||||
建议的采集状态:
|
||||
|
||||
| 状态 | 含义 |
|
||||
|---|---|
|
||||
| `collecting` | 插件正在扫描来源页。 |
|
||||
| `received` | 服务端已接受原始结果并创建事务记录。 |
|
||||
| `materializing` | 素材下载、转存、哈希去重进行中。 |
|
||||
| `ready_for_edit` | 至少商品草稿可编辑;单个素材仍可能失败。 |
|
||||
| `needs_review` | SKU 组合、规格或媒体证据不足,需要人工确认。 |
|
||||
| `failed` | 采集请求或关键记录创建失败;保留可诊断错误。 |
|
||||
| `archived` | 用户不再处理的采集记录。 |
|
||||
|
||||
同一默认店铺内,以 `source_platform + source_item_key` 进行幂等。重复“采集商品”应返回已有采集记录;重复“编辑上架”打开同一商品草稿。只有用户在 ERP 中明确选择“重新采集并合并/创建副本”时,才允许覆盖或复制。
|
||||
|
||||
## 4. 统一采集数据模型
|
||||
|
||||
### 4.1 原始与规范化数据分层
|
||||
|
||||
采集结果不能直接当作已确认商品数据。至少保留三层:
|
||||
|
||||
1. **原始证据**:页面 URL、采集时间、来源页面状态片段/响应片段、字段路径、解析器版本、原始文本和来源素材 URL。
|
||||
2. **规范化采集结果**:解析出的通用字段、规格轴、SKU 组合、媒体关系和可信度。
|
||||
3. **商品草稿**:用户或 AI 确认后的 SPU/SKU、属性、媒体和价格;只有草稿能进入发布快照。
|
||||
|
||||
每个字段和媒体关系应携带 `source`、`confidence`、`raw_value`、`captured_at`。规格、重量或尺寸口径未知时保留原文并标记 `ambiguous`,不能直接写入实物或包装物流规格。
|
||||
|
||||
### 4.2 规范化载荷
|
||||
|
||||
```ts
|
||||
interface CollectedProductPayload {
|
||||
source: {
|
||||
platform: 'ozon' | '1688' | 'taobao' | 'tmall';
|
||||
itemKey: string;
|
||||
canonicalUrl: string;
|
||||
collectedAt: string;
|
||||
parserVersion: string;
|
||||
};
|
||||
common: {
|
||||
title?: CollectedValue;
|
||||
description?: CollectedValue;
|
||||
brand?: CollectedValue;
|
||||
sourcePrice?: MoneyValue;
|
||||
attributes: CollectedAttribute[];
|
||||
categories: SourceCategory[];
|
||||
};
|
||||
variantAxes: SourceVariantAxis[];
|
||||
variants: CollectedVariant[];
|
||||
assets: CollectedAsset[];
|
||||
evidence: SourceEvidence[];
|
||||
}
|
||||
|
||||
interface CollectedVariant {
|
||||
sourceVariantKey: string; // 来源稳定 ID;不可只用展示名称
|
||||
sourceSku?: string;
|
||||
selections: Array<{ axisKey: string; valueKey: string; valueName: string }>;
|
||||
displayName: string;
|
||||
sourcePrice?: MoneyValue;
|
||||
sourceStock?: number;
|
||||
physical?: RawMeasurementSet;
|
||||
package?: RawMeasurementSet;
|
||||
mediaBindings: VariantMediaBinding[];
|
||||
confidence: 'verified' | 'partial';
|
||||
evidenceRefs: string[];
|
||||
}
|
||||
```
|
||||
|
||||
`variantAxes` 描述颜色、尺码、容量等可选值;`variants` 只描述可售的真实组合。两者不能互相替代。
|
||||
|
||||
### 4.3 媒体关系与继承
|
||||
|
||||
| 关系 | 条件 | 编辑页/发布时的表现 |
|
||||
|---|---|---|
|
||||
| `variant_direct` | 来源明确给出这个 SKU 与素材的稳定关联 | 自动绑定给该 SKU。 |
|
||||
| `axis_value` | 例如颜色值有稳定图片,SKU 组合明确包含该颜色 | 该素材可作为包含该颜色的 SKU 默认图,保留“来自颜色轴”证据。 |
|
||||
| `product_candidate` | 主图、详情图或无法可靠关联的素材 | 进入商品候选池;用户可选给任一 SKU。 |
|
||||
| `inherited_product_default` | SKU 已验证存在但无专属图 | SKU 卡片与发布预览解析父商品默认图;不复制资产、不声称它是来源 SKU 图。 |
|
||||
|
||||
这允许“真实多 SKU 但没有 SKU 图”的商品继续进入编辑、定价和发布,同时不制造错误的来源关联。发布快照必须记录最终解析到的媒体 ID 与关系来源。
|
||||
|
||||
## 5. 多 SKU 通用规则
|
||||
|
||||
1. 创建多个 SKU 的前提是来源提供稳定组合记录、SKU ID、变体 SKU、`propPath` 等可验证证据;单独的“红色”“M 码”选项不够。
|
||||
2. `source_variant_key` 优先使用来源 SKU ID。不存在来源 ID 时,使用来源提供的属性 ID/值 ID 的有序组合,并记录构造规则与风险;不得只拼本地化展示名称。
|
||||
3. 同一 `source_variant_key` 重采集应更新其采集记录和候选素材,不应再创建一个 SKU。
|
||||
4. 只识别出规格轴但没有组合时,创建一个默认 SKU,状态为 `needs_review`;规格轴仍保留给编辑页辅助人工拆分。
|
||||
5. 不使用笛卡尔积构造 SKU。来源若只返回“颜色选项”和“尺码选项”而没有组合可售表,无法证明每种组合都存在。
|
||||
6. 来源价格、库存、重量、尺寸只作采集参考。发布前必须由用户确认有效包装规格、定价快照、目标店铺类目和目标语言内容。
|
||||
|
||||
## 6. 各平台详细方案
|
||||
|
||||
### 6.1 Ozon 公开商品页
|
||||
|
||||
#### 目标
|
||||
|
||||
按 Ozon 页面公开的真实 `sku` 发现同一前台变体组,并为每个发现的来源 SKU 建立 `CollectedVariant`。这里的来源 `sku` 是 Ozon 前台商品/变体标识,**不是 Atlas 目标店铺的 `offer_id`**;发布后每个 Atlas SKU 仍生成自己的 `offer_id`。
|
||||
|
||||
#### 采集步骤
|
||||
|
||||
1. 从当前商品页的白名单状态组件读取标题、价格、画廊、视频、参数、类目和当前来源 SKU。
|
||||
2. 从包含产品变体的页面状态(参考实现中的 `webProductsModal` / `aspects[].variants` 一类组件)提取每一条 `sku`、标题、价格、划线价、封面、规格文本和关联链接。旧采集插件只保留了 `webAspects` 的名称与图片,丢弃了 `sku`,新实现不得如此。
|
||||
3. 将当前 SKU 和发现到的关联 SKU 放入有界队列;按 `sku` 去重。对每个 SKU 加载该 SKU 的公开详情页面/页面 JSON,补齐图片、视频、描述与可能继续出现的关联 SKU。
|
||||
4. 队列达到固定上限(建议 100)或无新 SKU 时停止。记录 `discovered_count`、`hydrated_count`、失败项与页面证据。
|
||||
5. 每个成功补全的来源 SKU 创建一个 `CollectedVariant`;没有专属图片时设置 `inherited_product_default`,不丢弃变体。
|
||||
|
||||
#### 完整性边界
|
||||
|
||||
“采集完整”只表示当前公开页面明确暴露的同一变体组已经遍历完成,不能承诺获得 Ozon 系统中所有相似商品、其他卖家 offer、未在该组展示的变体,或受地区/库存/实验策略隐藏的内容。来源页面没有稳定 `sku` 的候选项不得创建 SKU。
|
||||
|
||||
#### 失败与回退
|
||||
|
||||
- 公开变体组不可读:只创建当前页面默认 SKU,并保留“未发现可验证关联 SKU”警告。
|
||||
- 个别变体详情失败:保留已经发现的 `sourceVariantKey`,状态为 `partial`;用户可在采集箱触发重新补全。
|
||||
- 页面内容延迟加载:先等待目标组件和有限滚动;不得抓取推荐、关联购买等非当前商品组件。
|
||||
|
||||
### 6.2 1688
|
||||
|
||||
#### 可复用的旧插件能力
|
||||
|
||||
旧项目的 `extensions/collector` 会通过 MAIN world bridge 读取 `window.context`,已能从中取得:
|
||||
|
||||
- `skuModel.skuProps`:规格轴和值,部分值带图片;
|
||||
- `skuMapOriginal`:SKU 级价格、库存和组合信息;
|
||||
- `pieceWeightScaleInfo`:部分 SKU 的长、宽、高和重量;
|
||||
- 主图、视频、标题、类目、店铺、参数和来源 `offerId`。
|
||||
|
||||
但旧实现把 SKU 信息扁平为“带规格名的 SKU 图片”,其最终 `ScanResult` 和 `/api/materials` 上报均未保留真实 SKU 记录,必须重构。
|
||||
|
||||
#### 新解析方案
|
||||
|
||||
1. 读取并保存规格轴:每个属性维度的来源属性 ID、名称、值 ID、值名称和图片 URL。
|
||||
2. 遍历 `skuMapOriginal` 的每个真实组合行。优先取行自身 SKU ID;若没有,读取行中完整的属性 ID/值 ID 组合生成 canonical key。
|
||||
3. 通过属性 ID/值 ID,而不是文字名称,将组合行映射到规格轴。这样“黑色”在两个维度重复出现也不会错配。
|
||||
4. 读取该组合行的价格、库存和可用状态;从 `pieceWeightScaleInfo` 以来源 SKU ID 或同一属性组合匹配重量/尺寸,保存原单位和证据路径。
|
||||
5. 若颜色/样式轴图片明确属于组合中的一个值,创建 `axis_value` 媒体关系;无可靠关系时只放候选池,SKU 继承父商品默认图。
|
||||
|
||||
#### 禁止的回退
|
||||
|
||||
参考毛子 ERP 的 1688 DOM 逻辑会把“规格选项 × SKU 详情”做笛卡尔积,再用父商品主图填充图片。父图回退本身可用,但笛卡尔积会制造不存在的组合,Atlas 禁止采用。缺少真实组合表时只保留规格轴并创建默认 SKU。
|
||||
|
||||
### 6.3 淘宝与天猫
|
||||
|
||||
#### 可复用的页面数据
|
||||
|
||||
旧插件读取 `__ICE_APP_CONTEXT__`、`__general_skupanel_cache_data` 和 `__ICE_DATA_LOADER__`,目前只能提取规格轴和值图片。毛子 ERP 的实现展示了真实组合应如何解析:
|
||||
|
||||
- `skuBase.props`:属性维度和值,包含 `pid`、`vid`、名称和部分图片;
|
||||
- `skuBase.skus`:每个真实可售组合的 `skuId` 和 `propPath`;
|
||||
- `skuCore.sku2info[skuId]`:该组合的价格等 SKU 级信息。
|
||||
|
||||
`propPath` 中的 `pid:vid` 列表是组合证据。新插件须将它映射回 `skuBase.props`,生成如“颜色=红、尺码=M”的选择集,使用 `skuId` 作为 `sourceVariantKey`。
|
||||
|
||||
#### 采集策略
|
||||
|
||||
1. 优先读取当前页面已经加载的状态数据,不主动调用签名 MTop 接口。
|
||||
2. 若状态中同时存在 `skuBase.skus` 与 `skuCore.sku2info`,按真实 `skuId` 创建多 SKU;价格缺失时标记 `partial`,不丢失组合。
|
||||
3. 若只存在 `skuBase.props`,只保存规格轴和颜色等值图片;创建默认 SKU 并要求人工确认。
|
||||
4. 颜色值图片可按 `axis_value` 关系继承给包含该颜色的真实组合;尺码、容量等无图片的组合继承父商品默认图。
|
||||
|
||||
毛子 ERP 会在某些场景直接携带浏览器登录态调用签名 MTop 详情接口,取得 `skuCore` 与详情描述。该做法可以作为独立的技术可行性研究,但不能成为首期生产依赖:它受签名算法、登录态、风控和来源站规则影响。若未来试验,必须显式开关、最小请求量、记录来源与失败原因,且不能把 Cookie 或签名凭据上传 Atlas。
|
||||
|
||||
### 6.4 平台能力与回退矩阵
|
||||
|
||||
| 平台 | 真实 SKU 组合证据 | 价格/库存 | SKU 图片策略 | 无组合时 |
|
||||
|---|---|---|---|---|
|
||||
| Ozon | 公开变体的 `sku` 与页面关联数据 | 逐 SKU 公开价格;库存通常不作为可信采集字段 | 逐 SKU封面,缺失时继承父图 | 当前页面默认 SKU。 |
|
||||
| 1688 | `skuMapOriginal` 行与属性 ID/值 ID 组合 | 可采集价格、库存 | 颜色/样式值图片按轴继承;其余父图继承 | 默认 SKU + 规格轴。 |
|
||||
| 淘宝/天猫 | `skuBase.skus.skuId + propPath` | `skuCore.sku2info` | 颜色轴图片按组合继承;其余父图继承 | 默认 SKU + 规格轴。 |
|
||||
|
||||
## 7. Ozon Seller 网页增强采集:观察性实验
|
||||
|
||||
### 7.1 目的与边界
|
||||
|
||||
毛子 ERP 在公开 Ozon 商品页采集外,还要求浏览器打开已登录的 `seller.ozon.ru`,并通过跨标签消息调用 Seller 网页的内部接口。Atlas 可以在 Ozon 采集插件中实现一个**可选、显式开启、只用于观察结果**的实验模式。
|
||||
|
||||
实验模式目标是把公开页面发现的来源 SKU 与 Seller 网页返回的补充数据并排保存,帮助评估是否值得采用;它不得:
|
||||
|
||||
- 自动修改 Atlas 商品、价格、包装规格、库存或发布数据;
|
||||
- 读取、保存、上传或记录 Seller Cookie、`company_id` 以外的会话凭据;
|
||||
- 替代官方 `Client-Id + Api-Key` Seller API 的正式发布、库存和状态同步;
|
||||
- 将返回的销量/浏览等数据表述为“当前店铺数据”,除非 Ozon 未来提供可验证的官方契约。
|
||||
|
||||
四个接口都属于 `seller.ozon.ru` 网页内部接口,不是公开 Seller API;官方公开文档未给出其稳定契约。接口变动、登录态不足或风控失败必须视为正常实验失败,而非商品采集失败。
|
||||
|
||||
### 7.2 参考插件的调用方式
|
||||
|
||||
毛子 ERP 的 background/content script 大致如下:
|
||||
|
||||
```text
|
||||
公开 Ozon 商品页发现 source SKU
|
||||
→ 检查是否有已登录 seller.ozon.ru 标签页
|
||||
→ 从当前浏览器会话取得 company_id
|
||||
→ 跨标签发消息给 seller.ozon.ru content script
|
||||
→ 在 seller.ozon.ru 同源上下文中 fetch 内部接口
|
||||
headers: x-o3-company-id / x-o3-language
|
||||
credentials: include
|
||||
→ 仅把响应数据(不含 Cookie)回传来源页
|
||||
→ 毛子 ERP 加密后上传自己的后端
|
||||
```
|
||||
|
||||
Atlas 只可借鉴“请求必须在已登录 Ozon 同源标签执行”的技术结构。实验结果进入 `source_evidence` 或独立 `seller_enrichment_observations`,保存原始响应的净化副本、字段清单、接口名、时间、当前来源 SKU、解析版本和错误信息。
|
||||
|
||||
### 7.3 四个接口与已观察到的用途
|
||||
|
||||
| 接口 | 参考请求形态 | 已观察到的用途 | Atlas 实验记录 |
|
||||
|---|---|---|---|
|
||||
| `/api/v1/search-variant-model` | `{ name: sourceSku, limit: 50 }` | 按来源 SKU/名称查找变体模型候选。 | 候选数量、候选 `variant_id`、是否存在精确 SKU。 |
|
||||
| `/api/v1/search` | `company_id` + SKU filter + `is_copy_allowed: false` | 以来源 SKU 查找内部变体记录,必要时取得 `variant_id`。 | 查询上下文、匹配项、选择理由。 |
|
||||
| `/api/site/seller-prototype/create-bundle-by-variant-id` | `company_id`、`variant_id`、`source: SOURCE_UI_COPY_MERGED` | 获得复制/创建商品 bundle;代码可见其中包含商品图片、包装长宽高和重量等。 | bundle 的净化原始 JSON、可解析字段、与公开页差异。 |
|
||||
| `/api/site/seller-analytics/what_to_sell/data/v3` | `company_id`、SKU、`period: monthly`、`stock: any_stock` | 参考插件读取销量/销售额相关字段、品牌、类目、浏览/点击/退款等指标;其他字段会透传到其后端。 | 全量字段名、数值、时间口径、账户差异、是否可重复。 |
|
||||
|
||||
前 3 个接口主要用于 SKU/变体定位和复制 bundle;经营指标主要来自第 4 个分析接口。截图中的 rFBS 佣金、跟卖列表和跟卖价在毛子 ERP 中还会通过其自身后端接口补充,不应误认为由这四个 Ozon 接口直接返回。
|
||||
|
||||
### 7.4 数据范围尚未确认的事项
|
||||
|
||||
`what_to_sell/data/v3` 请求需要 `company_id`,但仅从插件代码无法证明它返回“当前店铺指标”还是“平台/权限范围内的市场洞察”。毛子 ERP 会对公开来源商品的 SKU 发起请求,这说明它可能用于竞品/选品数据;但这不是可依赖的接口契约。
|
||||
|
||||
因此实验页面必须标注:`Ozon Seller 网页观察数据,范围与口径未确认,仅供研究`。
|
||||
|
||||
验证方法:使用两个不同店铺账户,对同一个不属于任一店铺的公开 SKU 对比响应;再和当前店铺已上架 SKU 的官方 Seller API 数据对比。只有在口径、权限和稳定性得到确认后,才能决定是否建设独立“选品洞察”功能。
|
||||
|
||||
### 7.5 Atlas 实验流程与安全控制
|
||||
|
||||
1. 用户在插件设置中显式打开“采集 Ozon Seller 网页观察数据(实验)”。默认关闭。
|
||||
2. 用户自行在浏览器登录 `seller.ozon.ru`;插件只检测标签页和请求可用性,不显示、不导出、不持久化 Cookie。
|
||||
3. 标准公开页面采集先完成。对每一个发现的 `sourceVariantKey`,后台按低并发、有限数量发起四个观察请求。
|
||||
4. 回传前清除请求/响应中可能存在的会话字段、用户信息、店铺名称、授权头等无关信息;服务器再次执行结构化白名单与脱敏。
|
||||
5. 结果写入工作空间隔离的观察记录。采集箱展示“公开页数据 / Seller 网页观察数据”的字段差异,但不会自动覆盖草稿。
|
||||
6. 请求失败、账号无权、没有 Seller 标签页或内部接口变更时,只记录 `unavailable` 原因;“编辑上架”和“采集商品”仍正常完成。
|
||||
|
||||
## 8. Atlas API、任务与存储
|
||||
|
||||
### 8.1 插件接口建议
|
||||
|
||||
| 接口 | 用途 |
|
||||
|---|---|
|
||||
| `GET /api/extension/session` | 返回登录状态、工作空间、当前默认店铺是否可用;不返回敏感门店凭据。 |
|
||||
| `POST /api/extension/auth/exchange` | 用一次性授权码交换扩展短期令牌。 |
|
||||
| `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 网页观察数据。 |
|
||||
|
||||
不得让插件在请求体中随意指定 `workspace_id` 或 `store_id`。服务端从令牌确定工作空间,读取该工作空间的当前默认店铺,并在事务中应用 PostgreSQL RLS。
|
||||
|
||||
### 8.2 素材转存
|
||||
|
||||
- 插件上报来源 URL、Referer origin、MIME/类型、组别、排序和媒体关系;不把二进制图片塞进常规 JSON。
|
||||
- Worker 用受控请求下载来源素材,进行 MIME、大小、尺寸、哈希校验,再写入私有 MinIO/Kodo 对象存储。
|
||||
- 下载受来源防盗链、过期 URL 或风控影响而失败时,保留来源 URL 和错误;用户可重新采集或在编辑页手动上传。
|
||||
- 同一工作空间内用内容哈希和来源规范化 URL 去重,但同一资产可在多个商品/SKU 媒体关系中复用。
|
||||
|
||||
### 8.3 可恢复性
|
||||
|
||||
采集记录、素材任务、Ozon Seller 网页实验请求和未来发布任务都应先写 PostgreSQL,再经 outbox 投递 BullMQ。重试必须有幂等键、次数上限、指数退避和可见错误。浏览器关闭、Worker 重启或 Redis 重建都不能造成已创建商品草稿重复或素材关系丢失。
|
||||
|
||||
## 9. 旧实现与参考实现的取舍
|
||||
|
||||
### 9.1 `ozon-seller-kit/extensions/collector`
|
||||
|
||||
可复用:WXT/TypeScript 扩展结构、Shadow DOM 注入、MAIN world bridge、来源素材分组、Ozon/1688/淘宝/天猫的基础页面识别、图片 URL 还原、详情图懒加载和后台代理请求。
|
||||
|
||||
不复用:全高 AI Side Panel、AI 规划/生图/导出、无鉴权 `POST /api/materials`、本地服务地址、单商品数据模型,以及把 `variantName` 当作 SKU 关系的做法。
|
||||
|
||||
### 9.2 `extension-v1` 与 `extension-v2`
|
||||
|
||||
两者的 `ProductJson` 都只有一个商品;`_images.sku[].variantName` 只是图片备注,不能表达真实多 SKU。v1 甚至只取淘宝/天猫第一条规格轴;v2 对 Ozon 仅保存变体名称和图片。它们只能作为页面选择器和素材采集参考。
|
||||
|
||||
### 9.3 毛子 ERP 插件
|
||||
|
||||
可借鉴:小悬浮窗和登录状态切换、淘宝/天猫 `skuId + propPath + sku2info` 的真实组合解析、Ozon 以公开 `sku` 发现变体并逐一补全详情、按 SKU 去重、无专属图时回退父商品图、Seller 网页内部接口的跨标签同源调用结构。
|
||||
|
||||
不复用:读取 ERP localStorage Token、长期保存访问令牌、上传 Cookie、依赖未公开 Seller 网页接口完成核心业务、1688 的规格轴与 SKU 明细笛卡尔积、将未证实的经营指标作为正式店铺事实。
|
||||
|
||||
## 10. 实施分期与验收
|
||||
|
||||
### 10.1 分期
|
||||
|
||||
1. **采集基础**:扩展认证、小浮窗、默认店铺检查、统一载荷、采集箱入库、素材转存、幂等和“编辑上架/采集商品”。
|
||||
2. **真实多 SKU**:1688 `skuMapOriginal`、淘宝/天猫 `skuId + propPath`、Ozon 公开 `sku` 变体遍历;完善 SKU 媒体继承与采集箱警告。
|
||||
3. **Ozon Seller 网页观察实验**:四个接口的同源调用、净化存储、字段差异观察页与双店铺验证;不接入正式发布链路。
|
||||
4. **编辑与发布闭环**:动态属性、AI 文案/媒体、定价快照、发布校验、官方 Ozon Seller API 导入、轮询和库存设置。
|
||||
|
||||
### 10.2 验收样本矩阵
|
||||
|
||||
每个平台至少准备以下可重复样本并保存允许使用的页面快照:
|
||||
|
||||
| 场景 | 断言 |
|
||||
|---|---|
|
||||
| 单 SKU 商品 | 创建一个默认 SKU,主图和参数完整。 |
|
||||
| 单规格轴、多 SKU | 创建来源实际出现的所有 SKU,不重复。 |
|
||||
| 颜色 × 尺码 | 只创建来源组合表实际列出的组合;不得出现笛卡尔积假组合。 |
|
||||
| 有颜色图、无尺码图 | 组合继承颜色轴图或父图,关系可追溯。 |
|
||||
| 无 SKU 图 | 真实 SKU 均存在并继承父商品默认图。 |
|
||||
| 个别变体详情/素材失败 | 保留发现的 SKU 和错误;可单独重试。 |
|
||||
| 重复点击采集 | 复用同一采集记录和商品草稿。 |
|
||||
| 无默认店铺/令牌过期 | 只显示正确的登录或设置引导,不写入数据。 |
|
||||
| Ozon Seller 实验无权限 | 标准公开采集成功,观察实验单独失败且不阻塞。 |
|
||||
|
||||
## 11. 待确认与后续文档
|
||||
|
||||
本文件已确认插件入口、默认店铺、多 SKU 基本原则和 Ozon Seller 网页观察实验的边界。实施前仍需补充:
|
||||
|
||||
1. `CollectedProductPayload` 的 OpenAPI/JSON Schema 与 PostgreSQL 表、迁移和 RLS 细节;
|
||||
2. 当前默认店铺的服务端选择、切换和删除规则;
|
||||
3. 各来源真实页面快照测试集与解析器版本策略;
|
||||
4. Ozon Seller 网页四接口实验的字段字典、双店铺对照结果、数据保留期和是否继续投入;
|
||||
5. 采集箱列表、详情、重新采集、合并与归档的页面需求;
|
||||
6. 正式 Ozon 发布任务的状态机、请求/响应审计与库存策略。
|
||||
|
||||
相关文档:[商品编辑页](../product/README.md)、[商品 API 草案](../product/api.md)、[技术与异步任务方案](../architecture/technology-and-deployment.md)、[Ozon Seller API 资料](../integrations/ozon-seller-api/README.md)。
|
||||
Reference in New Issue
Block a user