feat: 商品试算页

This commit is contained in:
R524809
2026-08-26 17:38:44 +08:00
parent 6027d8f8d7
commit ac4ab22ac2
18 changed files with 3055 additions and 3 deletions
+110
View File
@@ -0,0 +1,110 @@
# V2.1 API 契约(新增 + 复用)
> 状态:前端服务层已按本文开发(Phase A);服务端 Phase B 按 本文实现。
> 通用:鉴权 `Authorization: Bearer <JWT>`studio 走 axios 拦截器自动附带);错误统一 FastAPI `detail`。
---
## 1. 复用的现有接口(Phase A 即可用)
| 接口 | 用途(试算页) |
|---|---|
| `GET /api/products/{id}``PATCH /api/products/{id}` | 商品详情 / 试算页自动保存(raw/pricing/copy/price/weight/... 全字段) |
| `GET /api/products/{id}/assets` | 素材列表(分组/规格/状态/stored_url |
| `GET /api/products?stage&q&page&page_size` | 批量 CSV / 组合码导出的数据源 |
| `POST /api/materials/bytes` | 试算页「上传图片」(FormData:`product_id, group_key=upload, file`)→ `{asset_id, status}` |
| `GET /api/fx` | 汇率 `{rate, source, ts}` |
| `GET /api/ai/models``POST /api/ai/copy` | 俄文文案(模型白名单 / 生成) |
| `POST /api/image/edit` | 智能修图页保留,不在试算页主链路 |
## 2. 套图规划 `POST /api/suite/plan`Phase B
**Req**
```jsonc
{
"product_id": "uuid", // 可选:便于日志与上下文缓存
"texts": [ { "kind": "title|price|params|selling_point|desc|brand|sales|shop",
"content": "…", "pairs": [ { "key": "…", "value": "…" } ] } ],
"sku_variants": ["粉色", "蓝色"],
"image_stats": { "main": 8, "sku": 6, "detail": 12 },
"platform": "ozon",
"requirements": "…|null" // 用户强制要求,最高优先级
}
```
**Res** `{ "summary": "一句话方案说明", "items": [ { "kind": "white_bg", "title": "白底主图", "detail": "…", "prompt_hint": "…", "count": 2, "variant_name": "粉色|null" } ] }`
实现要点:DeepSeek 单行紧凑 JSONkind 白名单清洗;count 钳 0-3;幻觉 variant 丢弃绑定;总数建议 8-15。同步接口(数秒级)。
## 3. 一键生成 `POST /api/suite/generate`Phase B
**Req**
```jsonc
{
"product_id": "uuid",
"texts": [ ],
"images": [ { "url": "…", "group_key": "main|sku|detail|upload", "variant_name": "粉色|null" } ], // 勾选参考底图
"style_set": 1,
"style_prompt": "…|null", // 用户改写的风格提示词,覆盖后端模板
"requirements": "…|null",
"plan": [ PlanItemcount>0 ],
"platform": "ozon",
"model": "gpt-image-2-vip",
"watermark": { "enabled": true, "type": "image|text", "text": "xiongmaoyx", "opacity": 30 } // 关闭时缺省
}
```
**Res** `{ "suite_id": "…" }`
实现要点:方案按 count 展开逐张 job;内存任务表 + 全局串行队列;逐张 build_prompt(模型家族分册)→ 参考图解析(variant 精确匹配→main 第 1 张;≤2 张)→ 生图 → 水印 → 落 storage;生成图追加 `product_assets(group_key='generated')`
## 4. 任务查询 `GET /api/suites/{id}`Phase B
**Res**
```jsonc
{
"id": "…", "status": "pending|running|done|partial|failed",
"style_set": 1, "platform": "ozon", "lang": "俄文", "ratio": "3:4", "provider": "rightapi",
"total": 8, // 计划总张数(images 逐张追加,过程中 length < total
"images": [ { "type_id": "white_bg", "name": "白底主图-01.png", "url": "/media/suites/…png",
"status": "ok|failed", "error": null } ],
"error": null
}
```
前端 3s 轮询;`done/partial/failed` 终态;后端重启后 404,前端提示重新生成。
## 5. 结果导出 `GET /api/suites/{id}/zip`Phase B
`application/zip` blob(按方案标题命名内部文件)。404/失败返回 `detail` JSON。
## 6. 单张 AI 生图 `POST /api/suite/image-edit`Phase B
**Req**
```jsonc
{
"product_id": "uuid",
"image_url": "…", // stored_url 或 source_url(服务端代下绕防盗链)
"prompt": "把背景换成纯白色摄影棚", // 必填
"model": "nano-banana-2",
"append": true // true:结果追加 product_assets(generated)
}
```
**Res** `{ "url": "/media/suites/….png", "asset_id": "uuid|null" }`
同步接口(单张 5s-5min,前端 axios 超时 120s+;gpt 系列偶发超时由前端重试提示兜底)。
实现要点:复用 §3 的 provider 层与 prompt 家族;参考图 = 传入单图;Ozon 规格(俄文 3:4)。
## 7. 导出与代理(Phase B / D
| 接口 | 方法 | Req | Res |
|---|---|---|---|
| `/api/export/images` | POST | `{ "title": "…", "images": [{ "url", "groupName", "variantName", "key" }] }` | zip blob(分组建文件夹) |
| `/api/proxy-image?url=` | GET | 源站图片 URL | 图片字节(带站点 Referer 代下,绕防盗链) |
| `/api/export/trial-csv` | GET | query`stage?` | csv blob16 列,见 trial-page.md §7Phase D 服务端化,替代前端拼装) |
## 8. 采集相关(Phase C 使用,均已实现)
- `POST /api/materials`:插件上传采集结果;**响应含 `product_id`**(插件用于打开 `/trial/{id}`)。
- `GET /api/collected?platform=&itemId=`:采集前查重。
## 9. 冻结接口(不投入,保留代码)
`/api/publish/*``/api/shops/*``/api/categories/*`——Ozon API 直传链路(D1)。