122 lines
7.1 KiB
Markdown
122 lines
7.1 KiB
Markdown
# 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` | 素材列表(分组/规格/状态/current `stored_url`、`original_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 单行紧凑 JSON;kind 白名单清洗;count 钳 0-3;幻觉 variant 丢弃绑定;总张数 AI 自主(建议 8 张左右;安全上限:默认 15,生图要求指定「N 张」时按 N、最大 24)。同步接口(数秒级)。
|
||
|
||
## 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": [ …PlanItem(count>0)… ],
|
||
"platform": "ozon",
|
||
"model": "gpt-image-2-vip",
|
||
"watermark": { "enabled": true, "type": "image|text", "text": "xiongmaoyx", "opacity": 30 } // 关闭时缺省
|
||
}
|
||
```
|
||
**Res** `{ "suite_id": "…" }`
|
||
|
||
实现要点:方案按 count 展开为持久化逐图子任务;独立 Worker 领取子项并在完成后回写进度。Pcore、RightAPI 与通义万相的第三方任务 ID 会先写入数据库,重启后继续轮询同一个模型任务;完成后再水印、落 storage、追加 `product_assets(group_key='generated')`。
|
||
|
||
## 4. 任务查询 `GET /api/suites/{id}`(Phase B)
|
||
|
||
**Res**
|
||
```jsonc
|
||
{
|
||
"id": "…", "status": "queued|running|done|partial|failed|cancelled",
|
||
"style_set": 1, "platform": "ozon", "lang": "俄文", "ratio": "3:4", "provider": "rightapi",
|
||
"total": 8, "completed": 3, "failed": 1,
|
||
"images": [ { "type_id": "white_bg", "name": "白底主图-01.png", "url": "/media/suites/…png",
|
||
"status": "queued|waiting_provider|running|done|failed|cancelled", "error": null } ],
|
||
"error": null
|
||
}
|
||
```
|
||
前端采用“本次请求结束后再延迟下一次”的递归轮询(正常 3s、请求失败指数退避),并在切换任务、组件卸载时取消在途请求;`done/partial/failed/cancelled` 为终态。每条 `images` 项另含 `item_id`,用于按图重试。浏览器会暂存当前任务 ID,并从服务端查询商品的活动任务;Web 服务或 Worker 重启后仍可恢复任务状态。
|
||
|
||
辅助接口:`GET /api/products/{product_id}/suites?active_only=true` 恢复活动任务;`POST /api/suites/{id}/cancel` 取消任务;`POST /api/suites/{id}/retry` 重试全部失败子项;`POST /api/suites/{id}/items/{item_id}/retry` 只重试指定失败项。
|
||
|
||
## 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** `{ "suite_id": "…" }`
|
||
|
||
接口仅创建并提交统一图片任务,立即返回;前端通过 `GET /api/suites/{suite_id}` 查询状态和 `images[0].url`。完成后若 `append=true`,结果会回写为 `product_assets(group_key='generated')`。单张编辑优先级高于套图,提交模型后同样持久化第三方任务 ID;参考图 = 传入单图;Ozon 规格(俄文 3:4)。
|
||
|
||
## 7. 素材水印 `POST /api/assets/watermark` / `POST /api/assets/watermark/remove`
|
||
|
||
`POST /api/assets/watermark` 的请求体为 `{ "asset_ids": ["uuid"], "watermark": { "enabled": true, "type": "text|image", "text": "…", "opacity": 30 } }`,立即返回 `{ "job_id": "uuid", "total": n }`。Worker 对选中的采集图或生成图逐张应用水印,前端经 `GET /api/suites/{job_id}` 查看逐图进度和错误;`GET /api/products/{product_id}/watermark-jobs?active_only=true` 用于页面刷新后恢复。
|
||
|
||
`POST /api/assets/watermark/remove` 的请求体为 `{ "asset_ids": ["uuid"] }`,将选中图片恢复为无水印原图。
|
||
|
||
`POST /api/assets/watermark/remove` 当前仍为短时同步操作,返回 `{ "updated_ids": [], "failed": [] }`。两接口均只保留原图和当前展示版本:重新加水印会在数据库提交后删除旧水印文件;前端展示、单张下载与导出均使用 `stored_url`。
|
||
|
||
## 8. 导出与代理(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 blob(16 列,见 trial-page.md §7;Phase D 服务端化,替代前端拼装) |
|
||
|
||
图片资源上限:默认单张上传/远程下载 20 MB;一次导出最多 50 张,ZIP 内源图片总量与成品 ZIP 均最多 200 MB。超过限制返回 HTTP `413` 及可读错误提示;ZIP 超过 2 MB 自动写入临时磁盘,并以分块响应下载。
|
||
|
||
## 9. 采集相关(Phase C 使用,均已实现)
|
||
|
||
- `POST /api/materials`:插件上传采集结果;**响应含 `product_id`**(插件用于打开 `/trial/{id}`)。
|
||
- `GET /api/collected?platform=&itemId=`:采集前查重。
|
||
|
||
## 10. 冻结接口(不投入,保留代码)
|
||
|
||
`/api/publish/*`、`/api/shops/*`、`/api/categories/*`——Ozon API 直传链路(D1)。
|