From 08bdea262597d6beb49acf61f4b0b781aed7ae1d Mon Sep 17 00:00:00 2001 From: obroccolio Date: Wed, 12 Aug 2026 19:08:26 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=86=BB=E7=BB=93=20wordcloud=20WCD=20?= =?UTF-8?q?=E5=A5=91=E7=BA=A6=EF=BC=88v1.1=EF=BC=89=E4=B8=8E=20designData?= =?UTF-8?q?=20=E7=94=9F=E4=BA=A7=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-contract-v1.md | 44 +++++++++++++++++++++++++--- docs/wordcloud-contract.md | 59 +++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 21 deletions(-) diff --git a/docs/api-contract-v1.md b/docs/api-contract-v1.md index 14dd87e..0da33ca 100644 --- a/docs/api-contract-v1.md +++ b/docs/api-contract-v1.md @@ -162,16 +162,23 @@ unitPrice: number count: number designData?: { + version?: 1 + category?: { id: string; mask: object; tone?: number[] } + background?: { src: string; color?: string; pos?: { x: number; y: number; scale: number } } + wordcloud?: { jobId?: string; imageUrl: string; names: string[] } stickers?: unknown[] - category?: unknown - imageSrc?: string - imagePos?: { x: number; y: number; scale: number } + imageSrc?: string // 兼容旧版 + imagePos?: { x: number; y: number; scale: number } // 兼容旧版 } }[] } ``` -`items` 为服务端 JSON,需做结构白名单与大小校验(单条 ≤ 1MB)。 +> **designData 结构遵循 `wechat_wc/docs/design-data-contract-v1.md`(R2/R4 冻结契约)。** +> 该契约保证 R4 下单后能据此构造 `.wcd` 投递到词云平台。要点: +> 贴纸图 `src` 必须为 COS 持久 URL(禁止 `wxfile://`/`tmp`)、保留 `wordcloud` 分组、 +> 保留 `category.mask`;后端该 JSON 白名单须放行 `version/background/wordcloud/rotation/zIndex`。 +>`items` 为服务端 JSON,需做结构白名单与大小校验(单条 ≤ 1MB)。 ### PATCH /api/design-list/:id @@ -298,6 +305,35 @@ multipart 请求:`image`(底图)+ `names`(文本名单)+ `params?`。 multipart:`image`。返回处理后图片 URL;失败时前端降级本地灰度。 +### POST /api/orders/:id/dispatch(R4 新增,下单后 WCD 派单触发) + +幂等触发把订单对应设计的 `.wcd` 投递到词云平台形成生产任务。 + +请求体:`{}`(幂等键 `requestId` 可选)。 + +响应 `data`: + +```ts +{ + orderId: string + status: 'queued' | 'running' | 'success' | 'failed' | 'not_configured' + wordcloudJobId?: string + message?: string +} +``` + +- 同一订单重复调用只投递一次(以 `CustomizationTask.orderId` 唯一或状态约束)。 +- `WORDCLOUD_API_URL` 未配置时返回 `status: 'not_configured'` 与可读 `message`,不做假成功。 +- 常规路径:订单进入 `PROCESSING` 时由后端队列自动触发;本接口作为支付未配置期的联调/运营手段。 +- 词云平台侧契约见 `docs/wordcloud-contract.md`(`POST /api/jobs` 可选 `wcd_file`)。 + +### 环境变量(R4 新增) + +| 变量 | 必填 | 说明 | +|---|---|---| +| `WORDCLOUD_API_URL` | 否(为空视为未配置) | 词云平台(FastAPI)地址;未配置时派单返回 `not_configured` | +| `WORDCLOUD_TIMEOUT_MS` | 否 | 请求 wordcloud 超时(毫秒),默认 30000 | + ## 9. 契约维护规则 - 前端与后端同名分支成对开发:`feat/r1-catalog`、`feat/r2-address-design`、`feat/r3-order-pay`、`feat/r4-upload-wordcloud`。 diff --git a/docs/wordcloud-contract.md b/docs/wordcloud-contract.md index f63f69d..646a8bc 100644 --- a/docs/wordcloud-contract.md +++ b/docs/wordcloud-contract.md @@ -1,13 +1,14 @@ -# wordcloud 外部服务契约 v1 +# wordcloud 外部服务契约 v1.1 本文档冻结 `wxmp_backend` 与 `/Users/broccoli/Project/wordcloud` 之间依赖的最小接口。 wordcloud 项目内部仍在大量变更,但只要不违反本文档,`wxmp_backend` 的适配层不受影响。 ## 1. 版本与状态 -- 契约版本:`v1` -- 状态:*.xlsx 名单模式冻结;`names` 直接文本/JSON 模式为推荐扩展点,尚未冻结。 -- 服务地址:由 `wxmp_backend` 环境变量配置,禁止硬编码到代码或小程序前端。 +- 契约版本:`v1.1`(相对 v1 为**兼容扩展**,仅新增可选字段,未改任何既有字段语义)。 +- 状态:*.xlsx 名单模式冻结;`names` 直接文本/JSON 模式为推荐扩展点,尚未冻结; + **WCD 生产任务输入(`wcd_file`)已冻结(v1.1)**,wordcloud 侧实现可后置。 +- 服务地址:由 `wxmp_backend` 环境变量 `WORDCLOUD_API_URL` 配置,禁止硬编码到代码或小程序前端。 - 小程序前端永远不直接访问 wordcloud,只访问 `wxmp_backend`。 ## 2. 冻结接口 @@ -18,30 +19,44 @@ wordcloud 项目内部仍在大量变更,但只要不违反本文档,`wxmp_b | 字段 | 必填 | 说明 | |---|---|---| -| `name_list` | 是 | `.xlsx` 名单文件,v1 必填 | -| `mask_image` | IMAGE 模式必填 | `.png/.jpg/.jpeg` 掩膜 | +| `name_list` | 与 `wcd_file` 二选一 | `.xlsx` 名单文件,v1 必填 | +| `wcd_file` | 与 `name_list` 二选一 | `.wcd` 画布导入导出包(v1.1 新增)。存在时进入“还原设计 → 生产任务”模式 | +| `mask_image` | IMAGE 模式必填 | `.png/.jpg/.jpeg` 掩膜;`wcd_file` 模式下不要求 | | `font_file` | 否 | `.ttf/.ttc/.otf` 临时字体 | | `font_id` | 否 | 已上传字体 id | | `params` | 否 | JSON 字符串,顶层必须是对象 | -`params` 关键值: +`wcd_file` 模式下 `params` 关键值建议带: ```json { - "MODE": "IMAGE", - "DATA_COL_INDEX": 1, + "MODE": "WCD", "SEED": 42, - "N_REPETITIONS": 20, "ENABLE_STROKE_WEIGHTS": false, "FONT_COLOR": "#000000" } ``` -响应:`{ "job_id": "..." }`。 +响应与既有模式一致:`{ "job_id": "..." }`。 + +**WCD 包结构**(wxmp_backend 构造,校验逻辑对齐 wordcloud 现有 +`POST /api/design-templates/import`): + +``` +{wcd}.wcd +├── manifest.json // { format: "wordcloud-canvas", version: 1, canvas: {width,height,background}, +│ // assets: [{id,name,type,mimeType,sha256,size}], meta?: {...} } +├── document.json // CanvasDocument:{width,height,background,layers,layerFolders,elements} +└── assets/. // 每个 sticker/底图的图片字节 +``` + +- `document.elements[]` 中 `type == "sticker"` 的元素通过 `assetId` 引用包内临时 ID, + 导入后由 wordcloud 统一重映射为真实素材 ID。 +- 名单快照可放 `manifest.meta`,仅记录,不影响还原。 ### GET /api/jobs/{job_id} -返回: +返回(与 v1 一致): ```json { @@ -91,19 +106,29 @@ wordcloud 项目内部仍在大量变更,但只要不违反本文档,`wxmp_b ## 4. 错误语义 - 4xx:参数错误,错误信息在 `detail` 或 `message`。 + - `wcd_file` 非 `.wcd` / 非合法 Zip => 400。 + - `manifest.format != "wordcloud-canvas"` 或 `version != 1` => 400。 + - `name_list` 与 `wcd_file` 都缺失 => 400。 - 5xx:服务/任务异常,wxmp_backend 将任务标记 `failed` 并在超时后清理。 - wxmp_backend 适配层应设置请求超时(例如 30s),任务超时上限(例如 10 分钟)。 ## 5. 稳定性规则 -- 上述 4 个端点的路径、字段名、状态枚举、分页/轮询语义冻结为 v1。 +- 上述端点的路径、字段名、状态枚举、分页/轮询语义冻结。 +- `wcd_file` 为 v1.1 兼容扩展:对既有调用方完全向后兼容(纯新增可选字段)。 - wordcloud 内部重构、新增 canvas/assets/projects/templates 能力不影响本契约。 - 契约变更流程:定义 v2 -> 更新本文档 -> wxmp_backend 在 R4 分支升级适配器 -> 双版本并存一个发布周期。 -- 若 wordcloud 希望新增“直接传名字列表”能力,默认视为 v1 兼容扩展,字段必须是 optional。 ## 6. 集成要点 -- `wxmp_backend` 负责把小程序文本名单转换为 `.xlsx` 再调用 `POST /api/jobs`。 -- `wxmp_backend` 保存 `job_id -> userId` 映射,轮询与结果查询必须校验归属。 +- `wxmp_backend` 负责把小程序文本名单转换为 `.xlsx` 再调用 `POST /api/jobs`(名单模式)。 +- **`wxmp_backend` 负责在下单后把订单对应 `designData` 构造为 `.wcd` 再调用 + `POST /api/jobs`(WCD 模式,`MODE=WCD`)**,见 + `wechat_wc/docs/design-data-contract-v1.md`(数据结构)与 + `wechat_wc/docs/routes/route-r4-upload-wordcloud.md` §3(派单流程)。 +- `wxmp_backend` 保存 `job_id -> orderId/userId`(WCD 模式)或 `job_id -> userId`(名单模式)映射, + 轮询与结果查询必须校验归属。 - 结果图由 wxmp_backend 下载并转存 COS,返回给小程序的是 COS 公网 URL。 -- wordcloud 若对外暴露公网,需要加访问 token 或网络白名单,防止被直接刷任务。 +- `WORDCLOUD_API_URL` 未配置时,下单派单返回结构化“未配置”错误(状态字面量 + `not_configured`,见 `api-contract-v1.md` §8 的 `POST /api/orders/:id/dispatch`),不做假成功。 +- wordcloud 若对外暴露公网,需要加访问 token 或网络白名单,防止被直接刷任务。 \ No newline at end of file