diff --git a/docs/r2-workflow.md b/docs/r2-workflow.md index 6bc43d6..b677702 100644 --- a/docs/r2-workflow.md +++ b/docs/r2-workflow.md @@ -149,7 +149,28 @@ `smart_design_list_` 与服务端并存的问题按路线文档风险节处理:忽略或提供 一次性导入,默认忽略)。 -### 阶段 5:联调与验收 +### 阶段 5:联调与验收 ✅(2026-09-12 核心收口) + +**已验证:** + +- 后端 35 项 API 测试全过(CRUD/默认地址事务/403/404/状态机/白名单/1MB/401); +- 前端 API 层 13 项断言全过(复跑于阶段 3/4 之后,确认无回归); +- 真机验收步骤 1-9、11-13 全过(清单链路/地址链路/登录态边界); +- **数据库直查验证 WCD 红线**:`category` 裁剪为 `{id, mask, tone}` 落库、`mask` 完整、 + 贴纸 `wxfile://` 路径按契约保留(`persistDesignMedia` 因 upload 占位静默降级); +- `build:weapp` / `nest build` 双端构建通过; +- 越权 403/404 由双账号 API 测试覆盖(真机步骤 #14 免测)。 + +**验收期间发现并修复的问题(非 R2 引入):** + +1. 后端缺 `PATCH /api/users/me` 路由(契约 §2 遗漏)→ 已补(后端提交 3fc65e5); +2. 本机缺 `.env`(`OSS_BASE_URL`)导致首页大图空白 → 环境问题,已记录到 + `docs/routes/R2/README.md` 公共注意第 6 条。 + +**未覆盖(低风险,可后补):** 断网降级真机步骤 #10(代码路径已实现,逻辑简单)。 + +**交接收口:** 跨线路注意事项见 `docs/routes/R2/README.md`(R3 的 checkout 切换与 +删除守卫、R4 的整包合并回写、R1 的 productId 校验等)。 按路线文档验收标准逐条过: diff --git a/docs/routes/R2/README.md b/docs/routes/R2/README.md new file mode 100644 index 0000000..7aaa7ee --- /dev/null +++ b/docs/routes/R2/README.md @@ -0,0 +1,59 @@ +# R2 交接收口说明(给其他线路) + +> R2(地址 + 设计清单服务端化)已于 2026-09-12 完成阶段 1-5 核心验收, +> 分支 `feat/r2-address-design`(前后端成对)。本文档记录**其他线路接入时必须知道**的 +> 事实与红线,避免重复踩坑。实现细节见 `docs/r2-workflow.md`。 + +## 已生效的事实(所有线路) + +1. **地址/设计清单的真数据源是服务端**(PostgreSQL),本地 `utils/store` 已降级为 + 「离线兜底缓存」:页面 API 成功回写缓存、失败读缓存、联网刷新以服务端为准覆盖, + **旧本地数据不自动合并**(用户反馈"我的设计没了"是预期行为,相关页面需要文案兜底)。 +2. **designData 是服务端持久化 JSON**(白名单 7 键:version/category/background/wordcloud/ + stickers/imageSrc/imagePos,单条 ≤1MB)。DIY 保存时 `category` 裁剪为 `{id, mask, tone}`, + `mask` 已验证完整落库(WCD 画布尺寸来源)。 +3. **真机验证**:贴纸 `src` 目前落库为 `wxfile://` 本地路径(`persistDesignMedia` 因后端 + upload 模块占位而静默降级保留本地图)——契约允许,但 **R4 的 COS 上传是派单前硬前置**。 +4. **后端补齐了 `PATCH /api/users/me`**(契约 §2 历史遗漏,service 早有 updateProfile 但 + controller 未注册路由,Profile 页保存资料曾 404)。 +5. 后端 JSON body 上限 2MB(≤1MB 受理 / 1MB~2MB → 400 / >2MB → 413), + **multipart 上传不走此限制**。 +6. 环境坑:前端 `.env`(`OSS_BASE_URL`)不入库。新机器 clone 后必须手动创建,否则 + `assetUrl('/img/...')` 退化为找包内本地文件 → **首页大图全空白**(大图 8 月已迁 OSS, + 包内不再携带)。 + +## 给 R3(订单 + 支付) + +1. **checkout 页现在必须切换服务端 id**:`POST /api/orders` 要传服务端 `designListId` / + `addressId`。checkout 目前仍读本地 store(R2 红线未动它);因 R2 会把服务端数据回写 + 缓存,过渡期读缓存能拿到服务端 id,但 R3 接入时应直接切 API。 +2. **状态触发权归 R3**:`PROCESSING`/`DONE` 由订单流程驱动(前端从不提交); + `ordered` 由 `orderId != null` 派生,只读。R2 已实现单向状态机 + `DRAFT→SUBMITTED→PROCESSING→DONE`(后端校验,回退 400)。 +3. **删除保护(R3 落地项)**:R2 的 DELETE/batch-delete **没有**做"有订单关联的清单 + 禁止删除"的守卫。R3 建 Order→DesignList 关联时必须同步加 delete-guard 或明确外键行为 + (SetNull),否则用户可删掉订单引用的设计快照。 +4. orders / orderDetail / profile 页仍读本地 store,R3 接入时一并切 API + (读的是 R2 回写的缓存,过渡期数据可用)。 +5. 金额重算:按契约用服务端 Product 真实价格 + `designList.items[0]` 快照, + 忽略客户端金额;下单带 `requestId` 幂等。 + +## 给 R4(上传 / 词云 / 派单) + +1. **回写 designData 必须整包合并提交**:PATCH 的 `items` 是全量替换。R4 写入 + `wordcloud` 分组或回写贴纸 COS URL 时,要先取服务端最新 designData、合并后再整包 + PATCH——**不能只传改动片段**,否则会冲掉其他字段(与 DIY 保存同一条红线, + 见 `docs/design-data-contract-v1.md` 约束#2)。 +2. `persistDesignMedia`(`utils/api/upload.ts`)已就位且真机验证为静默降级——R4 把 + upload 模块做实后,现有调用点无需改动即自动生效。 +3. 前端 `DesignDataV1.category` 类型已收窄为 `{id, mask, tone}`(契约 §2 冻结形状), + R4 不要往该字段塞完整 ProductCategory。 +4. DIY 贴纸目前不产生 `rotation`(无旋转手势)、`zIndex` 仅渲染层使用——两字段类型已 + 备好但值可能缺席,WCD 打包按 optional 处理(契约决策#2)。 + +## 给 R1(商品目录) + +1. R2 的 `productId` **不做存在性校验**(当时商品表未 seed 的阶段0 决策#7)。 + R1 落地后如需收紧,属于契约语义变更,需同步 `api-contract` 版本。 +2. `productIcon` 不入库(决策#3):设计清单页图标按 `PRODUCT_ICON_MAP[productId]` 兜底。 + R1 商品表有 `iconImg` 后可改为服务端 optional 下发(契约允许字段新增)。 diff --git a/docs/routes/README.md b/docs/routes/README.md index 21398e4..3211068 100644 --- a/docs/routes/README.md +++ b/docs/routes/README.md @@ -11,6 +11,10 @@ | [R3 订单 + 支付占位](route-r3-order-pay.md) | `feat/r3-order-pay` | 服务端下单、金额重算、订单状态机、支付未配置占位 | | [R4 上传 + 词云 + 线稿](route-r4-upload-wordcloud.md) | `feat/r4-upload-wordcloud` | COS 上传、wordcloud 契约冻结、sketch、任务轮询 | +**已收口路线的交接说明**(后续线路接入前必读): + +- [R2 交接收口说明](R2/README.md)——R3/R4/R1 接入服务端化地址与设计清单前的事实、红线与待办。 + ## 合并顺序与依赖 - R1 是交易链路的前置,优先合入。