6.5 KiB
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 + TypeScript;NestJS 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 对齐:
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 引导登录。