Files
wechat_wc/docs/r4-delivery-report.md
T

137 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# R4 交付报告(feat/r4-upload-wordcloud
> 日期:2026-08-13 | 范围:上传 / 词云生成 / 线稿 / **下单后 WCD 生产任务投递**
> 涉及仓库:`wechat_wc`(小程序前端)、`wxmp_backend`NestJS 后端)、`wordcloud`FastAPI 词云平台)
---
## 1. 目标与架构
把「用户上传底图 + 名单 → 词云生成 → DIY 贴纸 → 下单」链路中的上传、词云、线稿全部接到真实后端,
并**在下单后把订单对应的整套设计以 `.wcd` 包投递到词云平台形成生产任务**。
```
小程序 designData(贴纸持久化为 COS URL
→ POST /api/ordersdesignListId 关联,R3
→ POST /api/orders/:id/dispatch(幂等)
→ WordCloudService.buildWcdPackage(designData) → .wcdZip: manifest.json+document.json+assets/
→ POST {WORDCLOUD_API_URL}/api/jobs wcd_fileMODE=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` 名单模式完全向后兼容(纯新增可选字段)。
**生产订单列表**(补充,回应需求"wordcloud 侧订单列表"):
- `_create_wcd_job` 从 WCD 的 `manifest.meta.orderNo`(或 `order-{orderNo}` 命名)登记生产订单到 `service_orders/`(新增存储目录 + `_order_dir/_read_order/_write_order` 辅助)。
- 新增 `GET /api/orders`(生产订单列表,回填对应 job 最新状态)与 `GET /api/orders/{order_no}`(详情),便于 wordcloud/运营侧查看下方单的生产任务。
- **注意**`order` 目录含 `order.json``list_orders` 需直接遍历 `ORDERS_DIR`(不能复用只认 `meta/template/project.json``_list_dirs`)。
验证:`py_compile` 通过;用 venv FastAPI 真实调用 `_create_wcd_job` + 轮询任务 + `list_orders`/`get_order` + 产物访问,**端到端通过**(订单登记、状态=success、产物 PNG 可访问)。**未提交**——该仓库 `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=00 error |
| `wxmp_backend prisma validate` + 迁移应用 | ✅ 通过 |
| `wordcloud app.py py_compile` | ✅ 通过 |
| `wordcloud` WCD/订单列表端到端 | ✅ 用 venv FastAPI(0.136.3) 真实调用:建 WCD job → success → `GET /api/orders` 登记订单 → 产物 PNG 可访问 |
| `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 改动 + **订单列表(`GET /api/orders`**;对外部署;契约 v1.1 已冻结(`wxmp_backend/docs/wordcloud-contract.md`);新订单列表为运营侧查看,wxmp_backend 不消费 |
| **运维** | 配置 `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 队列做任务同步;加任务超时清理、单账号频率限制。