Files
wechat_wc/docs/routes/route-r2-address-design.md
T

125 lines
6.5 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.
# R2 收货地址 + 设计清单(feat/r2-address-design
**Goal:** 把收货地址和设计清单从本地 Storage 切换到后端 CRUD,完成字段契约、接口权限、
默认地址事务、设计数据 JSON 与状态映射,让 R3 的订单闭环可以直接消费这两组能力。
**Architecture:** 前端 `api/address.ts``api/design.ts` 负责 HTTP 契约,本地
`store/address.ts``store/design.ts` 在联调期保留为兜底;后端补齐 addresses 与 design-list
的完整 CRUD、事务与本人数据校验;`checkout` 页归 R3 所有,R2 只定义接口不修改该页面。
**Tech Stack:** Taro 3.6 + React 18 + TypeScriptNestJS 11 + Prisma/PostgreSQL。
## 1. 本分支要开发的内容
### 前端 `wechat_wc`
| 文件 | 职责 |
|---|---|
| `src/utils/api/address.ts` | `fetchAddresses/createAddress/updateAddress/deleteAddress/setDefaultAddress`,负责 `region[]``province/city/district` 双向转换 |
| `src/utils/api/design.ts` | `fetchDesignList/createDesign/updateDesign/deleteDesigns` |
| `src/pages/address/index.tsx` | 列表、新增、编辑、删除、设为默认全部走 API;保留表单校验与区域 Picker |
| `src/pages/designList/index.tsx` | 列表、状态筛选、批量删除走 API;保留 LoginGuard |
| `src/types/index.ts` | AddressItem/DesignItem 与后端结构对齐,新增服务端 id、状态码、时间字段 |
| `src/utils/store/address.ts``design.ts` | 降级为“本地缓存/离线兜底”,API 调用成功后同步刷新 |
### 后端 `wxmp_backend`
| 模块 | 内容 |
|---|---|
| `addresses` | `GET/POST /api/addresses``PATCH /api/addresses/:id``PATCH /api/addresses/:id/default``DELETE /api/addresses/:id`;全部带 userId 归属校验 |
| `addresses` 事务 | 设置默认时事务内先清旧默认再设新默认;删除默认地址后自动指定最新一条为默认 |
| `design-list` | `GET/POST /api/design-list``PATCH /api/design-list/:id``DELETE /api/design-list/:id`、批量删除 |
| `design-list` 校验 | `items` JSON 结构与大小校验、状态机转换、本人专属查询 |
| `docs/api-contract-v1.md` | 地址字段映射、设计清单状态枚举、错误码 |
### 词云项目 `wordcloud`
不参与本分支,但 `designData` 中的本地贴纸图片路径问题会影响后续 R4,见风险一节。
## 2. 状态映射(必须先定死)
后端 `DesignListStatus` 目前是 `DRAFT/SUBMITTED/PROCESSING/DONE`,前端是
`undesigned/designing/ordered`。R2 不要在两边各造一套值,建议按显示语义映射:
| 前端显示 | 后端状态 | 前端状态码 |
|---|---|---|
| 待设计 | DRAFT | `undesigned` |
| 设计中 | SUBMITTED | `designing` |
| 生产中 | PROCESSING | `processing` |
| 已下单 | DONE | `ordered` |
“已下单”不要用独立状态表达,改为 `orderId != null` 派生;前端只显示,不提交这个状态。
状态码收口到 `docs/api-contract-v1.md`,后端校验状态迁移,前端不传自由字符串。
## 3. 字段契约
### 地址
后端 `province/city/district/detail` 对应前端 `region: [province, city, district] + detail`
转换只放在 `api/address.ts`,页面和 store 不得散落第二次转换。
### 设计数据
`DesignList.items` 是服务端 JSON,前端提交结构建议与当前 `DesignItem.designData` 对齐:
```ts
interface DesignData {
stickers?: StickerItem[]
category?: ProductCategory
imageSrc?: string
imagePos?: { x: number; y: number; scale: number }
}
```
服务端只做白名单字段校验,不修改业务 JSON 内容;单条设计数据建议限制在 1MB 以内。
## 4. 设计注意事项
### DO
- DO 地址的增删改查和默认切换全部要求登录态,401 时引导去个人中心登录。
- DO 所有按 id 操作的服务端路由同时带 `userId` 条件,404 与 403 区分清楚。
- DO 默认地址切换与删除补偿放在同一个 Prisma transaction 里。
- DO 前端继续沿用户已熟悉的表单校验,但最终校验提示以后端返回为准。
- DO 设计清单状态通过后端枚举返回,前端状态筛选基于返回的 `status` 计算。
- DO 批量删除设计条目提供单个接口或循环调用时保证部分失败可恢复;推荐后端一次批量删除。
- DO 本地 store 只在 API 失败时做降级读取,成功写回后以服务端数据为准。
### DON'T
- DON'T 把前端 `region` 数组原样 POST 给后端,后端契约是四个独立地址字段。
- DON'T 让前端直接写 `isDefault` 的两条规则,默认地址唯一性由后端事务保证。
- DON'T 在路由/service 层漏掉归属校验;这是本分支最容易出的越权洞。
- DON'T 新增前端自造状态 `ordered` 之外的字符串,状态值必须在契约文档里可枚举。
- DON'T 在本分支修改 `checkout/index.tsx`,地址选择器与下单集成留给 R3。
- DON'T 把 `wxfile://` 临时贴纸路径当作可持久化 URL 直接入库,R4 之前它只是本地预览。
- DON'T 用设计清单字段承载订单状态,`orderId` 派生展示即可。
## 5. 补充内容
### 验收标准
- 地址页与设计清单页在登录态下增删改查、默认切换、批量删除全部走真实后端并刷新。
- 后端所有变更接口带本人校验,越权访问返回 403,不存在资源返回 404。
- 默认地址永远唯一;删除默认地址后列表自动产生新的默认地址。
- 前端构建与后端构建通过;Swagger 涵盖地址与设计清单全部接口。
- 状态映射表在 `docs/api-contract-v1.md` 中落地,前端页面不再出现魔法字符串状态。
### 合并与依赖
- 分支名:前端与后端均为 `feat/r2-address-design`
- R2 依赖已有登录体系(已完成),不依赖 R1;可与 R1 并行开发。
- checkout 对地址 API 的调用在 R3 接入,R2 只需保证接口稳定即可。
### 风险
- 设计数据中的贴纸是本地临时路径,一旦真机重启或清理缓存,旧设计预览会裂图;在 R4 上传能力完成前,文档明确这是已知限制。
- 旧版本本地 `smart_design_list_<openid>` 数据与后端数据可能并存,首次切换登录时避免双写冲突;可做一次性“导入本地清单”或直接忽略旧数据。
- 批量删除接口若后端未实现,前端循环删除会遇到部分失败,联调时先约定失败语义。
### 测试要求
- 后端:地址 CRUD、默认地址唯一性事务、越权访问、设计清单状态迁移、超大 JSON 拒绝。
- 前端:地址新增/编辑/删除/默认切换、设计清单筛选/批量删除、断网降级提示、401 引导登录。