2026-07-29-checkout-address-management-design.md 5.7 KB

Checkout 地址管理改造设计

背景

小程序商城购买流程中,checkout 页面当前使用了 consignees(收货人)系统来管理地址信息,但存在以下问题:

  1. 收货人系统无省市区字段consignees 表只有 name/phone/idCard/ethnicity/bloodType/address(纯文本),没有 province/city/district/street 结构化地址
  2. 身份证等字段混入地址管理:idCard/ethnicity/bloodType 属于商品维度的购买信息,不应与地址绑定
  3. 地址编辑后不保存:收货人编辑页面没有省市区选择器,输入的地址信息无法正确存储

现状分析

两个并存的系统

系统 有省市区 有默认地址 当前 checkout 使用
地址系统 user_address ✅ province/city/district/street ✅ isDefault
收货人系统 consignees ❌(只有 text address) ✅ isDefault

已有可用资源

  • 前端address-edit.vue 已有完整的省市区三级联动选择器 + 地址表单
  • 前端address.vue 已有地址列表 + 选择模式 + 编辑/删除/设为默认
  • 后端UserAddressController 提供完整 CRUD + setDefault
  • 后端ProductPurchaseFieldService 已实现按商品配置购买信息字段

设计

核心变更

checkout 页面从 consignees 系统切换到 user_address 系统,身份证等购买信息字段保持独立。

数据流

商品详情 → checkout
              │
              ├─ 地址区域 → 调用 /api/user/address/list
              │              ├─ 有地址 → 跳转 address/address.vue?selectMode=1
              │              │              ├─ 选择地址 → 回传 → checkout
              │              │              ├─ 编辑 → address-edit?addressId=X
              │              │              └─ 新增 → address-edit
              │              └─ 无地址 → 直接跳转 address-edit(新增)
              │
              ├─ 购买信息区域 → 保持 getProductRequiredFields 逻辑
              │                   身份证/民族/血型等按商品配置显示
              │
              └─ 提交订单 → 传 addressId(代替 consigneeId)

文件改动清单

1. checkout.vue(核心改动)

改动项 说明
loadDefaultConsignee()loadDefaultAddress() 调用 /api/user/address/list 加载地址列表,选中默认地址
地址卡片显示 改为显示 receiverName、phone、province+city+district+street、isDefault 标签
移除购买信息字段 地址卡片中不再显示 idCard、ethnicity、bloodType
openConsigneePicker()openAddressPicker() 跳转到 address/address.vue?selectMode=1
goAddConsignee()goAddAddress() 跳转到 address-edit/address-edit
提交订单 consigneeId → 改为 addressId,取选中地址的 id
onShow 生命周期 监听返回时重新加载地址列表,自动选中刚保存的地址
移除 consigneeList API 引用 改为调用 uni.request 直接访问 /api/user/address/list

2. address/address.vue(完善选择模式)

改动项 说明
选择模式回传 确保 onSelect 回传完整数据:{ id, receiverName, phone, province, city, district, street, isDefault }
回传机制 当前用 prevPage.selectedAddress = item 方式,确认 checkout 能正确读取

3. address-edit/address-edit.vue

无需改动。已有省市区联动选择器、详细地址、默认地址开关、保存逻辑。

4. 后端

无需改动。UserAddressController 已有完整 CRUD + setDefault。

购买信息字段的独立机制

身份证号、民族、血型、手签名等字段:

  • ProductPurchaseFieldService 管理,按商品维度配置
  • 管理端通过 product_purchase_fields 表配置每个商品需要哪些字段
  • 接口 /api/product/purchase_fields/required 返回该商品需要的字段列表
  • 预填来源:默认收货人 → 用户信息
  • 不在地址卡片中显示,仅在"购买信息"区域按需显示

交互流程

checkout 页面加载(onLoad/onShow)
  ├─ 调用 /api/user/address/list → 获取地址列表
  ├─ 有地址 → 选中默认地址(isDefault=1)或第一个地址
  └─ 无地址 → 显示"请选择地址"空状态

点击地址区域
  ├─ 有地址列表 → navigateTo address/address.vue?selectMode=1
  │                ├─ 点击地址卡片 → 回传选中地址数据 → navigateBack
  │                ├─ 点击编辑 → navigateTo address-edit?addressId=X
  │                └─ 点击新增 → navigateTo address-edit
  │
  └─ 无地址 → navigateTo address-edit(新增)
               └─ 保存成功 → navigateBack

checkout onShow 行为
  ├─ 每次页面显示时重新调用 /api/user/address/list 加载地址列表
  ├─ 如果当前未选中地址,自动选中默认地址(isDefault=1)或第一个
  └─ 如果已选中地址但列表有变化,保持选中状态不变

提交订单
  ├─ 验证:地址必选、购买信息字段必填校验
  ├─ 传参:{ addressId, items, remark, purchaseInfo, pointsUsed }
  └─ 成功 → 跳转支付

未改动部分

  • ProductPurchaseFieldServiceProductPurchaseField 实体
  • ConsigneeController / ConsigneeService / Consignee 实体(保留,但不再用于地址选择)
  • 后端 UserAddressController / UserAddressService
  • 数据库表结构
  • address-picker.vue 组件(备用,有四级地址选择)