feat: 初始化项目,项目需求、方案文档

This commit is contained in:
R524809
2026-09-01 17:35:48 +08:00
commit 5b77ba72b5
23 changed files with 5173 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# 商品 AI 编辑页
> 状态:已确认的产品需求与领域设计,尚未实施。它是 Atlas Seller Kit 的商品工作流规范。
## 目标
商品 AI 编辑页以一个商品(SPU)和多个可售 SKU 表达采集商品。它提供通用信息、SKU 媒体与规格编辑、SKU 定价、AI 文案、AI 套图和后续平台发布的统一入口。
页面不依赖旧项目的本地试算页;新产品应先满足多租户、云端存储和国际化架构要求。
## 已确认规则
| 主题 | 规则 |
|---|---|
| SKU | 每个商品至少有一条 SKU;单规格商品也使用默认 SKU。 |
| Ozon | 每个 SKU 对应独立 offer/import item;不依赖 Ozon 自动合并前台变体。 |
| 动态属性 | 基于当前平台商品类目 schema 动态渲染,不能把类目属性写死成列。 |
| 属性归属 | `is_aspect=true` 的平台属性默认是 SKU 属性;其他默认通用,但允许业务上改为 SKU 属性。 |
| 双规格 | 实物规格用于展示、文案和尺寸图;包装物流规格用于定价、物流和发布,二者绝不混用。 |
| 字段继承 | SKU 可继承父商品默认规格/定价参数;字段为空只表示未覆盖父默认值,不表示 SKU 不存在。 |
| 媒体 | 商品级候选素材和 SKU 已选媒体分离,以稳定 asset/SKU ID 关联,不按名称或 URL 猜测。 |
## 分册
- [页面与交互](./product-ai-editor.md)
- [数据库领域模型](./data-model.md)
- [服务端 API 契约](./api.md)
+42
View File
@@ -0,0 +1,42 @@
# 商品编辑 API 契约
> 接口前缀与鉴权细节待基础架构确认。所有请求由当前用户、工作空间、门店上下文授权;客户端不能跨租户指定 ID。
## 1. 采集与读取
| 接口 | 用途 |
|---|---|
| `POST /api/stores/{store_id}/materials` | 上报采集商品与可选 SKU 数组;无 SKU 数组时创建默认 SKU。 |
| `GET /api/products/{product_id}/editor` | 返回编辑页所需商品、SKU、属性 schema、媒体和草稿版本。 |
| `GET /api/products/{product_id}/validation` | 返回父商品和逐 SKU 的本地发布校验。 |
采集变体按 `platform + source_item_key + source_variant_key` 幂等。只有来源明确给出 SKU—图片关联时才能绑定 SKU;其他图片进入商品候选池。未知口径的规格保留原文并标为 `ambiguous`。
## 2. 草稿、SKU 与属性
| 接口 | 用途 |
|---|---|
| `PUT /api/products/{product_id}/editor-draft` | 原子保存商品、SKU、属性、排序和媒体选择;使用 ETag/版本号冲突控制。 |
| `POST /api/products/{product_id}/variants` | 创建或复制 SKU。 |
| `PATCH /api/products/{product_id}/variants/{variant_id}` | 修改 SKU;可继承字段传 `null` 恢复默认值。 |
| `DELETE /api/products/{product_id}/variants/{variant_id}` | 软删除未发布 SKU;已发布 SKU 改停用并留给发布流程处理。 |
| `GET /api/products/{product_id}/attribute-schema` | 按门店平台和当前类目返回动态属性 schema/字典。 |
schema 适配器对 Ozon 调用 `/v1/description-category/attribute` 和字典值接口,读取 `type`、`is_required`、`is_collection`、`max_value_count`、`dictionary_id`、`is_aspect`。对其他平台提供同一内部 schema 形状。
## 3. 定价、媒体和 AI
| 接口 | 用途 |
|---|---|
| `POST /api/products/{product_id}/variants/{variant_id}/pricing/quote` | 用服务端有效包装规格计算预览,不落价。 |
| `POST /api/products/{product_id}/variants/{variant_id}/pricing/confirm` | 重新计算、校验、保存快照并回填售价/划线价。 |
| `GET/PUT /api/products/{product_id}/variants/{variant_id}/media` | 读取候选媒体/保存 SKU 已选媒体及顺序。 |
| `POST /api/products/{product_id}/ai/copy` | 生成父商品的多语言标题、标签、简介等候选草稿。 |
| `POST /api/products/{product_id}/ai/suite-plans` | 创建显式绑定目标 SKU 的套图规划。 |
| `POST /api/products/{product_id}/variants/{variant_id}/ai/dimension-image` | 创建单 SKU 尺寸图任务,并固化实物规格快照。 |
确认定价失败(缺失/待确认/无效包装规格或物流校验失败)返回 `422`,不改写现有价格。AI 返回候选结果,不能未经用户确认覆盖手工内容。
## 4. 后续发布
未来平台适配器接受“父商品 + 单 SKU”规范化对象。Ozon 实现将每个启用 SKU 转换为一个 `/v3/product/import.items[]`:复制通用标题、简介、类目和通用属性;填入 SKU offer、价格、包装规格、图片和变体属性。批量按平台限制分组,结果按 SKU 独立保存。
+44
View File
@@ -0,0 +1,44 @@
# 商品与 SKU 数据模型
> 目标数据库:PostgreSQL。单位统一存储为毫米(`mm`)和克(`g`)。所有租户数据必须拥有或可追溯至 `workspace_id`。
## 1. 云端租户层
```text
users ── workspace_memberships ── workspaces
└─ stores ── platform_connections
```
`stores` 保存平台标识、市场/国家、默认 locale、默认币种和连接状态。敏感凭据经加密后保存在专用连接密钥记录中,绝不放进前端、日志或商品 JSON。
## 2. 商品领域
```text
stores 1 ── N products (SPU) 1 ── N product_variants (SKU)
├── product_attributes
├── product_assets ── variant_media
└── pricing_defaults ── variant_pricing_snapshots
```
每个父商品至少有一条 SKU。`products` 保存通用标题、简介、型号、条形码、采买地址、货源备注、目标市场/类目引用、富内容、默认规格及默认计价参数。可翻译内容不能只存一列,应以 `product_translations`(语言/市场、字段、值、来源、状态)或等价模型保存。
`product_variants` 保存:稳定来源键、展示名、启用/排序、SKU 货号、采购价、售价、划线价、币种、SKU 规格、包装物流规格、实物规格、发布映射和时间戳。`offer_id` 对同一门店/平台连接必须唯一。
## 3. 双规格和继承
父商品可提供默认的实物/包装规格;SKU 可以逐字段覆盖:
- 实物:`physical_length_mm`、`physical_width_mm`、`physical_height_mm`、`net_weight_g`;用于规格展示、文案和尺寸图。
- 包装物流:`package_length_mm`、`package_width_mm`、`package_height_mm`、`shipping_weight_g`;用于定价、物流校验和平台发布。
值按“SKU 覆盖 → 父商品默认”合并;两组规格独立合并。`null` 表示该字段继承,不是零,也不是 SKU 不存在。每组须有来源、原始文本、状态(`confirmed`/`ambiguous`/`missing`)和确认时间;口径未知的数据不能落入任一规格组。
## 4. 动态属性和媒体
`product_attributes` 使用结构化行保存 `scope`(common/variant)、本地 key、平台属性 ID、复杂属性 ID、JSON 值、语言、来源与确认状态。平台 schema 驱动类型、必填、字典、多值和 `is_aspect`;`is_aspect=true` 默认 variant scope,但允许业务覆盖。
`product_assets` 保存资产事实和对象存储 URL;`variant_media` 保存 SKU 对资产的图片/视频/封面选择与顺序。资产归属一律用稳定 ID;采集平台无法稳定给 SKU 归属时,只作为商品级候选池。
## 5. 定价、任务和发布
`variant_pricing_snapshots` 保存确认时的输入、合并后的包装规格、公式版本、汇率、结果、告警和时间;导出/发布时服务端重新校验,不能信任浏览器结果。所有 AI、媒体、导出和发布任务保存 `workspace_id`、`product_id` 与可空/必填的 `variant_id`,可重试、可恢复并隔离租户。
+42
View File
@@ -0,0 +1,42 @@
# 商品 AI 编辑页:页面与交互
## 1. 页面定位
页面编辑一个父商品及其 SKU 集合。通用信息只维护一次;每个 SKU 是独立可售单元。单规格商品也显示一张默认 SKU 卡片,因而定价、媒体、货号与发布没有特殊分支。
```text
页头:返回 · 商品标题 · 草稿状态 · 来源
├─ 商品通用信息
│ ├─ 类目、标题、品牌、型号、主题标签、简介、JSON 富内容
│ ├─ 条形码、采买地址、货源备注
│ └─ 当前平台/市场类目的动态属性
├─ SKU 商品:卡片(默认)/ 紧凑列表
│ └─ N 个 SKU
└─ 固定操作栏
├─ 左:AI 标题/标签/描述 · AI 套图生成
└─ 右:取消并关闭 · 保存草稿 · 上架至平台(后续)
```
## 2. 保存和校验
页面以编辑草稿工作,不采用字段失焦即写库。保存草稿需原子提交父商品、SKU、属性和媒体顺序;存在未保存修改时关闭页面须二次确认。SKU 定价确认是例外:它会即时持久化该 SKU 的价格与定价快照。
前端根据平台商品类目 schema 渲染属性控件、必填提示、字典选择、多值限制及变体属性。`is_aspect=true` 默认显示在 SKU 区;采购业务确有需要时,用户可把非 aspect 属性(如容量)改为 SKU 属性。类目变更后,失配属性保留为未映射草稿,不能自动进入发布请求。
## 3. SKU 卡片和列表
卡片默认展示:序号、SKU 名称、启用状态、最多 3 张图片缩略图(可切换为 5)、视频封面/视频、货号、采购价、售价、划线价、定价按钮、两组规格与变体属性。列表仅是紧凑视图,字段和数据完全相同。
SKU 名称只用于展示;采集 SKU 用稳定 `source_variant_key` 关联,手工 SKU 用本地 UUID。规格字段 `null` 仅表示没有覆盖父商品默认值,绝不能据此判断是否单规格或缺少 SKU。
## 4. 定价弹窗
点击 SKU 的“定价”打开弹窗,显示该 SKU 合并后的包装物流规格,并允许调整采购价、利润率、贴单费、物流等级、划线价倍数和汇率。服务端计算预览、尺寸校验和告警;确认后保存不可变快照,并回填 SKU 销售价和划线价。
包装规格缺失、口径待确认、数值无效或不符合物流限制时不得确认。实物规格不进入物流计算;它缺失时仅禁用尺寸图。
## 5. 媒体与 AI
SKU 图片编辑弹窗左侧是该 SKU 的已选图片(排序/移除),右侧分组展示 AI 生图记录、采集主图、采集 SKU 图和采集详情图。商品级素材可被多个 SKU 选择;明确有稳定来源关联的 SKU 图只展示给对应 SKU。
AI 文案针对父商品生成候选标题、标签、简介与富内容,用户选择后写入草稿。AI 套图由左侧抽屉承载,必须显式选择目标 SKU;尺寸图一 SKU 一任务,并保存实物规格快照。