162 lines
10 KiB
Markdown
162 lines
10 KiB
Markdown
# V2.1 商品试算页方案(studio /trial/:id)
|
||
|
||
> 状态:Phase A 前端开发中(本次交付前端,服务端接口见 api.md)
|
||
> 参照:`web/ozonSeller.html` + `web/js/app.js`(v1 工具台,冻结只读)。试算页 = v1 流水线的 studio 化 + 数据落库。
|
||
> 前端代码:`studio/src/pages/trial/`
|
||
|
||
---
|
||
|
||
## 1. 定位与入口
|
||
|
||
商品试算页是 V2.1 的**主工作流页面**:采集落库后的一切加工都在这里完成——
|
||
核对商品信息 → 价格试算 → 俄文文案 → 图片/AI 生图 → 入库 → 导出 CSV/组合码 → 人工上 Ozon 后台。
|
||
|
||
入口:
|
||
1. **插件采集后自动打开**(Phase C):`/trial/{product_id}` 新标签页;
|
||
2. **采集箱「试算」按钮**(Phase A 已加):每行操作列;
|
||
3. URL 直达 / 从商品编辑页切换。
|
||
|
||
商品编辑页(`/product/:id`)保留,定位降级为「Ozon 结构化字段的长期储备」;试算页不依赖它。
|
||
|
||
## 2. 页面结构
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────┬────────────┐
|
||
│ 标题(中文/俄文) · stage 标签 · 保存状态 · 来源链接 · 去编辑页 │ 区域导航 │
|
||
├──────────────────────────────────────────────────────┤ (锚点滚动) │
|
||
│ 01 商品信息 标题/采集价/品牌/销量/店铺/重量/尺寸/货号/ │ │
|
||
│ 采买地址/参数表/描述(可编辑,onBlur 落库) │ │
|
||
│ 02 价格试算 进货价/净利率/贴单费/物流等级/预留折扣/汇率 → │ │
|
||
│ 结果卡(物流费→实收价/净利润→完全成本/总抽成→ │ │
|
||
│ 销售价¥/₽/预留价) + 三类告警 │ │
|
||
│ 03 俄文文案 商品资料 → 模型选择 → 生成标题/简介/标签 → 回填 │ │
|
||
│ 04 图片与AI生图 采集图片(分组勾选/上传/AI生图) + 出图方案(规划/ │ │
|
||
│ 风格/要求/模型/一键生成+进度) + 生成结果(导出) │ → image-suite.md │
|
||
│ 05 入库与导出 入库状态 + 导出本商品CSV + 批量导出CSV + 组合码 │ │
|
||
└──────────────────────────────────────────────────────┴────────────┘
|
||
```
|
||
|
||
## 3. 01 商品信息
|
||
|
||
编辑即落库(onBlur/onChange → `PATCH /api/products/{id}`,与编辑页一致的自动保存模式)。
|
||
|
||
| 字段 | 落库位置 | 说明 |
|
||
|---|---|---|
|
||
| 标题(中文) | `raw.title_zh`(回退展示 `raw.title`) | 采集原标题写入 `raw.title`,人工整理后的中文名写 `title_zh` |
|
||
| 俄文标题 | `name` | 文案生成回填,也可手改 |
|
||
| 采集价 / 品牌 / 销量 / 店铺 | `raw.price` / `raw.brand` / `raw.sales` / `raw.shop` | 只读展示 |
|
||
| 重量 g | `weight`(`weight_unit='g'`) | 采集已自动 kg→g;试算计价直接用 |
|
||
| 长×宽×高 cm | `depth/width/height`(`dimension_unit='mm'`,cm×10 落库) | 计价与尺寸校验用 |
|
||
| 货号(SKU) | `offer_id` | 对齐 v1「型号-后缀」,v2.1 用单字段;CSV/组合码的主键 |
|
||
| 采买地址 | `raw.purchase_url` | 1688/淘宝采集时默认取 `source_url`;可改;导出 CSV 列 |
|
||
| 参数表 | `raw.params`(`[{key,value}]`) | 只读折叠展示;供文案/生图上下文 |
|
||
| 描述 | `raw.desc` | 可编辑;供文案/生图上下文 |
|
||
|
||
## 4. 02 价格试算(公式从 web/js/app.js 移植,单位口径不变)
|
||
|
||
输入参数(存 `product.pricing` JSON):`purchasePrice` 进货价¥(默认30)、`profitRate` 净利率%(默认100)、
|
||
`tdPrice` 贴单费¥(默认3)、`logisticsLevel` low/high/high2(默认 low)、`lineMultiplier` 划线价倍数%(默认100,0-500)、
|
||
`fxRate` 汇率(`product.fx_rate` 快照,无则 `GET /api/fx` 拉取)。重量/尺寸取自 01 区块。
|
||
|
||
> 划线价口径(v2.1 调整):原 v1 的「预留折扣空间」(划线价 = 销售价 ÷ (1-折扣%))在 >95% 区间发散且 ≥100% 无解,
|
||
> 改为「划线价倍数」:`划线价 = 销售价 × (1 + 倍数%)`。倍数 100% → 划线价 = 2× 销售价;50% → 1.5×。线性、全程可算。
|
||
|
||
**物流费**(`baseLogisticsFee` 已在 `studio/src/pricing/pricing.ts`):
|
||
|
||
| 等级 | 条件 | 公式 | 规则文案 |
|
||
|---|---|---|---|
|
||
| low | ≤500g | `3.12 + 0.026×重量` | low:3.12 + 0.026×重量 |
|
||
| low | >500g | `23.92 + 0.01768×重量` | low:23.92 + 0.01768×重量 |
|
||
| high2 | ≤5000g | `22.88 + 0.026×重量` | 高2:22.88 + 0.026×重量 |
|
||
| high2 | >5000g | `64.48 + 0.024×重量` | 高2:64.48 + 0.024×重量 |
|
||
| high | ≤2000g | `16.64 + 0.026×重量` | 普通:16.64 + 0.026×重量 |
|
||
| high | >2000g | `37.44 + 0.01768×重量` | 普通:37.44 + 0.01768×重量 |
|
||
|
||
最后 `+ 贴单费`(规则文案追加「 + 通递价」)。
|
||
|
||
**计价链**(与 web/app.js:1035-1053 逐行一致):
|
||
|
||
```
|
||
实收价 = 进货价 × (1 + 净利率%)
|
||
净利润 = 进货价 × 净利率%
|
||
净得率 = low→0.845,其余→0.785
|
||
销售价¥ = (实收价 + 物流费) / 净得率
|
||
平台佣金 = 销售价 × 12%(low)/ 18%(其余) ← 展示用
|
||
平台总抽成 = 销售价 × (1 - 净得率) = 15.5% / 21.5% ← 含佣金及约3.5%其它费
|
||
完全成本 = 进货价 + 物流费 + 平台总抽成
|
||
预留后¥ = 销售价 × (1 + 划线价倍数%)(即划线价);差额 = 划线价 - 销售价
|
||
销售价₽ = 销售价¥ × 汇率;划线₽ = 划线价¥ × 汇率
|
||
```
|
||
|
||
**校验**(v2.1 新增移植到 `pricing.ts`:`validateDimensions` / `validateLogisticsLevelCny` / `validatePriceRange`,注意等级/区间建议用的销售价单位是 **CNY**,与 v1 一致):
|
||
|
||
| 校验 | 规则 | 表现 |
|
||
|---|---|---|
|
||
| 尺寸硬校验 | low≤500g:三边和≤90 且最长边≤60;low>500g:≤150/≤60;high≤2000g:≤150/≤60;high>2000g:≤250/≤150(high2 按 high 档执行,v1 即如此) | 红色错误,结果卡显示 `--`,不落计价结果 |
|
||
| 物流等级建议 | 销售价>140¥ 且 low → 建议高等级;<135¥ 且非 low → 建议低等级 | 橙色提示 |
|
||
| 价格区间 | 销售价 ∈ [135,140]¥ → 汇率波动风险 | 橙色提示 |
|
||
|
||
**落库**:参数或结果任一变化即重算并保存(对齐编辑页 PriceInfoPanel 模式):
|
||
|
||
```jsonc
|
||
// product.pricing(PriceInfoPanel 字段的超集,向后兼容)
|
||
{
|
||
"purchasePrice": 30, "profitRate": 100, "logisticsLevel": "low", "tdPrice": 3,
|
||
"lineMultiplier": 100, "fxRate": 11.5, "weightG": 600, "dims": { "l": 20, "w": 15, "h": 10 },
|
||
"logisticsFee": 22.12, "receivedPrice": 60, "profitPrice": 30, "commission": 11.63,
|
||
"fullCommission": 15.02, "totalCost": 67.14,
|
||
"sellingPriceCny": 77.51, "linePriceCny": 155.02,
|
||
"sellingPriceRub": 891.4, "linePriceRub": 1782.7,
|
||
"calculatedAt": "2026-08-26T12:00:00Z"
|
||
}
|
||
// 同时回填:price=销售价CNY,old_price=划线价CNY,currency_code=CNY,fx_rate=汇率
|
||
```
|
||
|
||
## 5. 03 俄文文案
|
||
|
||
直接复用编辑页 CopyPanel(`studio/src/pages/product/CopyPanel.tsx`)与服务端 `/api/ai/models`、`/api/ai/copy`:
|
||
- 输入区预填 `raw.title_zh + raw.params + raw.desc + 卖点`;
|
||
- 生成 2 个推荐标题(俄+中对照)、俄文简介、标签芯片;
|
||
- 「回填」标题写 `name + raw.title_zh`,简介写 `description`,结果另存 `product.copy`(后续服务端可加,前端先回填字段)。
|
||
|
||
## 6. 04 图片与 AI 生图
|
||
|
||
详见 [`image-suite.md`](./image-suite.md)。前端(Phase A)已实现完整交互:
|
||
采集图片分组展示与勾选、上传(`POST /api/materials/bytes`,已可用)、每张图「AI 生图」弹窗、
|
||
套图方案(默认/AI 规划/数量微调)、5 套风格 + 可编辑风格提示词、生图要求、10 个生图模型、
|
||
一键生成 + 进度轮询 + 结果网格 + 导出 ZIP、下载采集图片。
|
||
套图相关服务端接口 Phase B 提供,前端先行按 api.md 契约调用。
|
||
|
||
## 7. 05 入库与导出
|
||
|
||
**入库**:无独立「录入」按钮——01/02/03 区块的每次编辑都自动落库(v1 的 localStorage 登记表 → products 表)。
|
||
本区块显示入库状态(计价时间 `pricing.calculatedAt`、货号、来源)。
|
||
|
||
**CSV(对齐 web/app.js:1376-1424 的 16 列,UTF-8 BOM + RFC 转义)**:
|
||
|
||
```
|
||
货号(sku=offer_id)、商品名(title_zh)、进货价、物流费、平台总抽成、实收价、完全成本、
|
||
销售价、净利润、净利率、卢布销价、重量(g)、尺寸(cm L×W×H)、状态(stage 中文)、
|
||
Ozon地址(https://www.ozon.ru/product/<sku>)、采买地址(raw.purchase_url)
|
||
```
|
||
|
||
- **导出本商品 CSV**:当前商品一行,立即下载;
|
||
- **批量导出 CSV**:拉取商品列表(有 `pricing.calculatedAt` 的)逐个取详情拼装(Phase A 前端拼装,Phase D 可换 `GET /api/export/trial-csv`);
|
||
- **组合码**:`货号 预留₽价(两位小数)` 每行一条(无预留₽回退销售价₽),弹窗展示 + 一键复制,用于 Ozon 后台批量改价(对齐 v1「上品组合码」)。
|
||
|
||
## 8. 前端文件清单(Phase A)
|
||
|
||
| 文件 | 职责 |
|
||
|---|---|
|
||
| `studio/src/pages/trial/TrialPage.tsx` | 页面骨架:加载商品+素材、自动保存、区块导航 |
|
||
| `studio/src/pages/trial/TrialInfoPanel.tsx` | 01 商品信息 |
|
||
| `studio/src/pages/trial/TrialPricingPanel.tsx` | 02 价格试算 |
|
||
| `studio/src/pages/product/CopyPanel.tsx` | 03 俄文文案(复用,不新建) |
|
||
| `studio/src/pages/trial/TrialSuitePanel.tsx` | 04 图片与 AI 生图(素材/方案/生成/结果) |
|
||
| `studio/src/pages/trial/AiImageGenModal.tsx` | 单张 AI 生图弹窗 |
|
||
| `studio/src/pages/trial/TrialExportPanel.tsx` | 05 入库与导出 |
|
||
| `studio/src/services/suite.ts` | 套图/生图/导出 服务层(按 api.md 契约) |
|
||
| `studio/src/pricing/pricing.ts` | 追加 validateDimensions 等三个校验 + 规则文案 |
|
||
| `studio/src/utils/file.ts` | CSV 转义 / blob 下载 / 文件名清理 |
|
||
| `studio/src/router/index.tsx` + `layouts/menuConfig.tsx` + `CollectionPage.tsx` | 路由 `/trial/:id`、页头信息、采集箱「试算」入口 |
|