9.9 KiB
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 后台。
入口:
- 插件采集后自动打开(Phase C):
/trial/{product_id}新标签页; - 采集箱「试算」按钮(Phase A 已加):每行操作列;
- 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)、discountReserve 预留折扣%(默认50,≤95)、
fxRate 汇率(product.fx_rate 快照,无则 GET /api/fx 拉取)。重量/尺寸取自 01 区块。
物流费(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 模式):
// product.pricing(PriceInfoPanel 字段的超集,向后兼容)
{
"purchasePrice": 30, "profitRate": 100, "logisticsLevel": "low", "tdPrice": 3,
"discountReserve": 50, "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, "reservedPriceCny": 155.02,
"sellingPriceRub": 891.4, "reservedPriceRub": 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。前端(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、页头信息、采集箱「试算」入口 |