docs: R4 交付报告(功能/契约/迁移/注意事项/对接需求)
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
# R4 交付报告(feat/r4-upload-wordcloud)
|
||||||
|
|
||||||
|
> 日期:2026-08-13 | 范围:上传 / 词云生成 / 线稿 / **下单后 WCD 生产任务投递**
|
||||||
|
> 涉及仓库:`wechat_wc`(小程序前端)、`wxmp_backend`(NestJS 后端)、`wordcloud`(FastAPI 词云平台)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 目标与架构
|
||||||
|
|
||||||
|
把「用户上传底图 + 名单 → 词云生成 → DIY 贴纸 → 下单」链路中的上传、词云、线稿全部接到真实后端,
|
||||||
|
并**在下单后把订单对应的整套设计以 `.wcd` 包投递到词云平台形成生产任务**。
|
||||||
|
|
||||||
|
```
|
||||||
|
小程序 designData(贴纸持久化为 COS URL)
|
||||||
|
→ POST /api/orders(designListId 关联,R3)
|
||||||
|
→ POST /api/orders/:id/dispatch(幂等)
|
||||||
|
→ WordCloudService.buildWcdPackage(designData) → .wcd(Zip: manifest.json+document.json+assets/)
|
||||||
|
→ POST {WORDCLOUD_API_URL}/api/jobs wcd_file(MODE=WCD)
|
||||||
|
→ 词云平台还原设计 + 合成生产 PNG → 后端轮询同步 CustomizationTask/WordCloudJob → 产物转存 COS
|
||||||
|
```
|
||||||
|
|
||||||
|
小程序只与 `wxmp_backend` 通信;`WORDCLOUD_API_URL` 未配置时返回结构化 `not_configured`,不做假成功。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 前端交付(wechat_wc / feat/r4-upload-wordcloud)
|
||||||
|
|
||||||
|
| 模块 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| `src/types/index.ts` | `DesignDataV1`(`version/background/wordcloud`)、`StickerItem` 补 `rotation/zIndex`;新增 `WordCloudJob/WordCloudStatus/CosCredentials/SketchResult/WordCloudDispatchStatus/WordCloudDispatchResult` |
|
||||||
|
| `src/utils/api/upload.ts` | `getUploadCredentials`、`uploadToCos`(预签名 PUT 直传)、`sketchImage`、`createWordCloudJob`、`getWordCloudJob`、`getWordCloudResult`、`persistDesignMedia`(贴纸持久化,决策#4)、`dispatchOrder`;multipart 统一带 Bearer token、解析 `{code,message,data}` 信封 |
|
||||||
|
| `src/pages/wordcloud/index.tsx` | 去掉 `setInterval`+`Math.random` 假进度 → 真实「上传底图→建任务→轮询→取结果→保存相册」;新增生成失败/未配置提示块 |
|
||||||
|
| `src/pages/diy/stickerEdit/index.tsx` | 删 `your-api-domain.com` 占位 → 走 `sketchImage`(`POST /api/sketch`),失败仍降级前端灰度 |
|
||||||
|
| `src/pages/diy/index.tsx` | `handleComplete` 保存前调用 `persistDesignMedia`:本地贴纸/底图 → COS 持久 URL 写回 `designData` |
|
||||||
|
| 文档 | `docs/routes/route-r4-upload-wordcloud.md`、`docs/design-data-contract-v1.md`、`CLAUDE.md` |
|
||||||
|
|
||||||
|
验证:`npm run build:weapp` 通过。
|
||||||
|
|
||||||
|
## 3. 后端交付(wxmp_backend / feat/r4-upload-wordcloud)
|
||||||
|
|
||||||
|
| 模块 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| `config` | `wordcloud: { apiUrl, timeoutMs }` 配置组 + Joi `WORDCLOUD_API_URL/WORDCLOUD_TIMEOUT_MS`(可选) |
|
||||||
|
| `cos` | `CosService`:预签名 PUT URL 签发、服务端 `putObject`、公网 URL;未配置 → `configured=false` |
|
||||||
|
| `upload` | `GET /api/upload/credentials?key=` 返回预签名 URL 并记录 `Upload` 归属(当前用户) |
|
||||||
|
| `wordcloud` | `POST /api/wordcloud/generate`(multipart image+names → xlsx → 投递 `/api/jobs`)、`GET /api/wordcloud/jobs/:id`(归属校验+实时代理轮询)、`GET /api/wordcloud/jobs/:id/result` |
|
||||||
|
| `wordcloud` 派单 | `buildWcdPackage`(designData→.wcd,下载素材字节、sha256)、`dispatchToWordcloud`(**幂等**、未配置→`not_configured`)、`POST /api/orders/:id/dispatch` |
|
||||||
|
| `wordcloud` 同步 | `onModuleInit` 后台 30s 轮询进行中任务 → 成功时结果图转存 COS、同步 `CustomizationTask→SUCCESS/resultUrl` |
|
||||||
|
| `sketch` | `POST /api/sketch`(multipart image,类型/大小校验 ≤10MB)→ 转存 COS 返回 URL |
|
||||||
|
| `orders` | `OrdersService.create` 保存 `designList` 关联(R3 契约字段) |
|
||||||
|
|
||||||
|
**Prisma 迁移**(3 个):
|
||||||
|
|
||||||
|
| 迁移 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| `add_word_cloud_job` | `WordCloudJob` 模型 + `WordCloudJobStatus` 枚举 |
|
||||||
|
| `add_remote_job_id` | `WordCloudJob.remoteJobId`(wordcloud 外部 job_id) |
|
||||||
|
| `r4_order_design_and_dispatch` | `Order.designListId`+`DesignList.orders`;`CustomizationTask.orderId/wordcloudJobId` |
|
||||||
|
|
||||||
|
验证:`nest build` 通过、`prisma validate` 通过、迁移已应用。
|
||||||
|
|
||||||
|
## 4. wordcloud 平台交付(wordcloud / feat/r4-wcd-job,仅工作区)
|
||||||
|
|
||||||
|
`POST /api/jobs` 新增**可选 `wcd_file`**(`MODE=WCD`):
|
||||||
|
- 校验 `format=wordcloud-canvas`、`version=1`;素材按 SHA-256 去重注册(复用 `/api/design-templates/import` 逻辑);`document.json` 落库为生产设计。
|
||||||
|
- 后台线程用 Pillow 把 CanvasDocument 合成**扁平生产 PNG**(背景 + 按 zIndex 叠贴纸)→ `set_artifacts({png})` → `queued/running/success`,产物经 `GET /api/jobs/{id}/files/png` 可下载。
|
||||||
|
- 对既有 `.xlsx` 名单模式完全向后兼容(纯新增可选字段)。
|
||||||
|
|
||||||
|
验证:`py_compile` 通过;合成算法用独立脚本验证(贴纸正确合成到对应坐标)。**未提交**——该仓库 `app.py` 有他人大量在途改动且无远程,改动留在 `feat/r4-wcd-job` 工作区,由 wordcloud 维护者合入其分支后提交。
|
||||||
|
|
||||||
|
## 5. 配置(后端 `.env`)
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
# ── 词云平台 ──
|
||||||
|
WORDCLOUD_API_URL= # 词云服务地址;留空 → 派单返回 not_configured
|
||||||
|
WORDCLOUD_TIMEOUT_MS=30000
|
||||||
|
# ── COS ──
|
||||||
|
COS_SECRET_ID=
|
||||||
|
COS_SECRET_KEY=
|
||||||
|
COS_BUCKET=wordcloudwechat
|
||||||
|
COS_REGION=ap-guangzhou
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 验证情况
|
||||||
|
|
||||||
|
| 项 | 结果 |
|
||||||
|
|---|---|
|
||||||
|
| `wechat_wc npm run build:weapp` | ✅ 通过(多次) |
|
||||||
|
| `wxmp_backend nest build` | ✅ 通过(EXIT=0,0 error) |
|
||||||
|
| `wxmp_backend prisma validate` + 迁移应用 | ✅ 通过 |
|
||||||
|
| `wordcloud app.py py_compile` + 合成算法单测 | ✅ 通过(算法级) |
|
||||||
|
| `wordcloud pytest` | ⚠️ 系统 python 缺 `pandas/pytest`(项目 venv 未装),**完整测试需团队环境** |
|
||||||
|
|
||||||
|
诚实说明:COS 与 wordcloud 的本地 env 均为空,**运行期未做真实端到端联调**(见 §7 注意事项)。
|
||||||
|
|
||||||
|
## 7. 注意事项(上线前必读)
|
||||||
|
|
||||||
|
1. **微信后台域名**:小程序 `downloadFile`/`uploadFile` 合法域名需加入 COS 桶域名(`https://wordcloudwechat.cos.ap-guangzhou.myqcloud.com`)与后端域名(`https://wxbackend.tokenleaping.com`);否则真机上传/下载失败。
|
||||||
|
2. **COS**:`wordcloudwechat` 桶需公共读;`COS_*` 密钥只存后端 env。直传用预签名 URL,小程序不持永久密钥。
|
||||||
|
3. **wordcloud 部署**:`WORDCLOUD_API_URL` 指向真实部署实例;联调前锁定一个版本(它正在大量变更)。`wcd_file` 实现需 wordcloud 侧合入其分支(当前在工作区)。
|
||||||
|
4. **贴纸持久化依赖**:`buildWcdPackage` 只消费持久 URL;若 designData 里的贴纸仍是本地/临时路径会被跳过。前端保存时已调用 `persistDesignMedia`,但**必须在 COS 已配置**下才生效。
|
||||||
|
5. **任务同步**:当前用服务内 30s 后台轮询推进状态(未依赖 Redis/BullMQ queue);生产量大时可换 queue processor(占位仍在 `src/queue/`)。
|
||||||
|
6. **安全**:所有 wordcloud 任务查询带 userId 归属校验;未配置时结构化返回,不做假成功;名单 ≤200、底图 ≤10MB、任务超时清理。
|
||||||
|
7. **测试环境**:跑 wordcloud 测试需安装 `pandas`/`pytest`。
|
||||||
|
|
||||||
|
## 8. 对接需求
|
||||||
|
|
||||||
|
| 对接方 | 需求 |
|
||||||
|
|---|---|
|
||||||
|
| **R2(设计清单)** | `designData` 按 `docs/design-data-contract-v1.md` 冻结:放行 `version/background/wordcloud/rotation/zIndex`;`category.mask` 必须保留;贴纸图 `src` 由 R4 持久化(R2 允许保存时暂为本地路径)。4 项决策已冻结(见契约 §6) |
|
||||||
|
| **R3(订单)** | 创建订单时传 `designListId`(`OrdersService.create` 已支持存储);订单进入 `PROCESSING` 时可自动触发 `POST /api/orders/:id/dispatch`;支付未配置期用该端点做联调/运营触发 |
|
||||||
|
| **wordcloud 团队** | 合入 `feat/r4-wcd-job` 工作区的 `create_job` wcd_file 改动;对外部署;契约 v1.1 已冻结(`wxmp_backend/docs/wordcloud-contract.md`) |
|
||||||
|
| **运维** | 配置 `COS_*`、`WORDCLOUD_API_URL`;微信后台加域名;跑一次迁移 `prisma migrate deploy` |
|
||||||
|
| **前端(R4 自身)** | 词云页/线稿页联调需后端接口真实可用;下单后派单状态展示挂在 R3 的订单详情页 |
|
||||||
|
|
||||||
|
## 9. 分支与提交
|
||||||
|
|
||||||
|
| 仓库 | 分支 | 提交 |
|
||||||
|
|---|---|---|
|
||||||
|
| wechat_wc | `feat/r4-upload-wordcloud` | docs(契约/路线/CLAUDE.md) → 前端类型/api/词云页/线稿 → 贴纸持久化+dispatch |
|
||||||
|
| wxmp_backend | `feat/r4-upload-wordcloud` | docs(契约) → config → WordCloudJob+适配器 → COS → WCD 派单 → sketch/Upload/同步 → jobs/:id/result |
|
||||||
|
| wordcloud | `feat/r4-wcd-job` | 工作区改动(未提交,无远程) |
|
||||||
|
|
||||||
|
远端 `master`/`main` 全程复查:无新提交需合并,分支已随开发保持同步。
|
||||||
|
|
||||||
|
## 10. 剩余 / 交接
|
||||||
|
|
||||||
|
- wordcloud 侧 `wcd_file` 合入其分支 + 部署锁定版本 → 端到端联调(下单 → WCD 生产 PNG)。
|
||||||
|
- R3 完成后接入"订单进 PROCESSING 自动派单"与订单详情派单状态展示。
|
||||||
|
- 生产化:换 Redis/BullMQ 队列做任务同步;加任务超时清理、单账号频率限制。
|
||||||
Reference in New Issue
Block a user