巴青农资商城

会员管理技术方案.md 17KB

会员管理 — 技术方案

依据: 《会员管理功能需求.md》v1.0
关联: 《订单管理功能需求.md》v1.0.1、《商品管理功能需求.md》v1.3.3、《店铺管理功能需求.md》v1.3.2、《关联需求分析.md》v1.2
范围: 本文以 会员主数据、收货地址、平台端查询/启用订单只读聚合 为主;biz_order 由订单模块维护,本文给出 ER、Facade 契约与会员侧接口;C 端注册/登录接口单列 §4(与平台共用表)。
原则: 会员与 biz_merchant_account 分表;手机号 del_flag=0 唯一;消费统计 O11 与订单一致。


1. 技术架构

选型
基础框架 RuoYi v3.9.2springboot2 分支)
数据库 MySQL 5.7.39
ORM / 权限 / 响应 MyBatis;@PreAuthorizeAjaxResult / TableDataInfo
密码 C 端 SecurityUtils.encryptPassword(BCrypt);存于 sys_user.password
账号 sys_user 复用member_id = user_id;会员角色 role_key=member
脱敏 列表手机号中间 4 位 *(如 177****9136
日志 启用状态变更 @Log

1.1 模块落位

baqing-shop/src/main/java/com/ruoyi/web/modules/account/
├── controller/MemberController.java           # 平台 /agri/member
├── controller/MemberAppController.java        # C 端 /api/member
├── service/impl/MemberServiceImpl.java
├── service/impl/MemberAppServiceImpl.java
├── service/impl/MemberAddressServiceImpl.java
├── support/MemberRegistrationSupport.java     # C 端注册 + 平台添加(共用)
├── support/MemberSysUserSupport.java          # 解析 role_key=member
├── domain/BizMember.java、BizMemberAddress.java
└── mapper/BizMemberMapper.xml、BizMemberAddressMapper.xml

resources/mapper/account/BizMemberMapper.xml   # JOIN sys_user;列表过滤 member 角色
sql/biz_member.sql                             # biz_member 扩展表 + member 角色初始化

1.2 业务链

sys_user(账号:user_name/phonenumber/nick_name/password/avatar/status)
    └── biz_member(member_id = user_id;等级/消费统计/注册时间)
            ├── biz_member_address(1:N)
            │
            ├── IMemberFacade ──► 订单模块
            └── biz_order.member_id
字段映射 sys_user biz_member(业务层别名)
主键 user_id member_id
手机号 phonenumber mobile
会员名称 user_name memberCode
昵称 nick_name nickName
密码 password password
头像 avatar avatar
状态 status(0正常 1停用) status

注册(事务): insertUser(角色 member)→ insert biz_membermember_id = userId)。

模块 表/职责
会员(本文) biz_memberbiz_member_address;平台列表/详情/启用
订单管理 v1.0 biz_order 等;履约写操作;向会员回写消费汇总
商户/店铺/商品 无会员表;经营账号 不关联 member_id

1.3 跨模块 Facade

接口 提供方 调用方 方法
IMemberFacade 本模块 订单、C 端下单 getMemberisMemberEnabledexistsByMobilerefreshConsumption
IOrderFacade 订单(目标包 com.ruoyi.web.modules.order待实现 本模块 pageOrdersByMembergetOrderDetailhasUnfinishedOrdersByShop/Merchant(见《订单管理技术方案》§1.3)

订单未实现前:pageOrdersByMemberaccount.facade.DefaultOrderFacade 桩返回空页;实现后迁入 order.facade 并以《订单管理技术方案》v1.0.2 为准。

消费统计(O11)实现二选一(推荐 A):

方案 说明
A 冗余字段 biz_member.order_counttotal_amount;订单 已完成 时订单模块调用 IMemberFacade.refreshConsumption(memberId) 同事务
B 实时聚合 列表/详情每次 SUM biz_order;数据量大时再改 A

1.4 状态联动

事件 biz_member biz_order 商户/店铺
禁用会员 status=1 不变(M15) 不变
订单已完成 刷新 order_count/total_amount 状态→已完成
商户冻结/店停业 不变 仅禁 下单 各模块规则

2. 数据库设计

2.1 本模块表

表名 说明
biz_member C 端买家主档
biz_member_address 收货地址簿

2.2 关联表(订单模块,ER 引用)

表名 说明
biz_order member_id FK;DDL 见《订单管理技术方案.md》v1.0

2.3 biz_member + sys_user

权威 DDL:sql/biz_member.sql。账号列在 sys_user;查询通过 biz_member JOIN sys_user

biz_member(扩展表)

字段 类型 说明
member_id bigint PK = sys_user.user_id(非自增)
member_level tinyint 选填;字典 biz_member_level
order_count int 已完成订单笔数
total_amount decimal(12,2) 已完成实付合计
register_time datetime 注册时间
create_by/time, update_by/time, remark 审计

sys_user(账号,注册时写入)

字段 说明
user_name 会员名称(C 端可随机生成)
nick_name 昵称
phonenumber 手机号;del_flag=0 唯一
password BCrypt
avatar 头像 URL
status 0 启用 1 禁用
角色 注册时分配 role_key=member

2.4 biz_member_address

字段 类型 说明
address_id bigint PK
member_id bigint FK
consignee_name varchar(64) 收货人
mobile varchar(20) 联系电话
region_code varchar(64) 省市区编码(区县级 code)
region_name varchar(128) 省市区名称(省/市/区 / 拼接)
detail_address varchar(256) 详细地址
is_default char(1) 0 否 1 是;每会员至多一条默认
del_flag char(1) 0 存在 2 删除
create_time, update_time

2.5 索引与约束

索引/约束 说明
biz_member PRIMARY (member_id) member_id 非自增,= sys_user.user_id
biz_member KEY idx_register (register_time) 列表默认排序
sys_user 应用层 checkPhoneUnique phonenumberdel_flag='0' 时唯一(M2)
sys_user 应用层 checkUserNameUnique user_name(会员名称)唯一
sys_user_role 注册/平台添加时写入 role_idrole_key=member
biz_member_address PRIMARY、idx_member member_id, del_flag

2.6 DDL(权威脚本)

完整建表与 member 角色初始化sql/biz_member.sql
biz_membermobile/password/status 等账号列;查询通过 biz_member INNER JOIN sys_user

-- biz_member:仅扩展字段(账号在 sys_user)
CREATE TABLE `biz_member` (
  `member_id` bigint(20) NOT NULL COMMENT '与 sys_user.user_id 一致',
  `member_level` tinyint(4) DEFAULT NULL,
  `order_count` int(11) NOT NULL DEFAULT '0',
  `total_amount` decimal(12,2) NOT NULL DEFAULT '0.00',
  `register_time` datetime NOT NULL,
  `create_by` varchar(64) DEFAULT '',
  `create_time` datetime DEFAULT NULL,
  `update_by` varchar(64) DEFAULT '',
  `update_time` datetime DEFAULT NULL,
  `remark` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`member_id`),
  KEY `idx_register` (`register_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='C端会员扩展表';

唯一约束(应用层): sys_user.phonenumberdel_flag='0' 时不可重复(M2);MemberRegistrationSupport / ISysUserService.checkPhoneUnique

2.7 字典

dict_type 用途
biz_member_status status:0 启用 / 1 禁用
biz_member_level member_level(tinyint;如 0=普通;选填)

3. 平台端接口设计

基路径: /agri/member
权限前缀: agri:member

3.1 接口一览

方法 路径 权限 说明
GET /list list 会员分页列表
POST / add 平台添加会员(无需短信验证码)
GET /{memberId} query 会员详情(基本 + 地址列表)
PUT /{memberId}/status edit 启用/禁用
GET /{memberId}/orders query 该会员订单分页(只读
GET /{memberId}/orders/{orderId} query 订单详情(只读;校验 member_id

不提供 导入、改等级、余额积分(需求 §13)。

3.2a 新增 POST /

Body 说明
mobile 必填;11 位手机号
password 必填;BCrypt 入库
memberCode 选填;sys_user.user_name;未填则 8 位随机唯一名
nickName 选填;未填同会员名称
avatar 选填;sys_user.avatar
memberLevel 选填
status 选填;默认 0 启用
remark 选填

流程: 同事务 insertUser(角色 member)→ insert biz_membermember_id=user_id)。
成功: 返回 memberId

3.2 列表 GET /list

Query 说明
pageNum, pageSize 分页
keyword 可选;会员名称、昵称或手机号 模糊(M11)
status 可选;0/1

过滤: u.del_flag='0'EXISTS 子查询要求 sys_user_role + sys_role.role_key='member'MemberServiceImpl 注入 memberRoleKey,排除仅平台/商户账号)。
排序: biz_member.register_time DESC
实现: BizMemberMapper.selectListselectVo JOIN sys_usermemberRoleExists 片段。

rows:

字段 说明
memberId, memberCode, nickName memberCode 为会员名称
mobile 脱敏
memberLevel, memberLevelLabel memberLevel 为 tinyint 字典值,可空;label 为展示文案
status, statusLabel 字典
orderCount, totalAmount 来自冗余字段(与 O11 一致)
registerTime

3.3 详情 GET /{memberId}

{
  "memberId": 1,
  "memberCode": "用户A",
  "nickName": "用户A",
  "mobile": "17712349136",
  "memberLevel": null,
  "status": "0",
  "orderCount": 3,
  "totalAmount": 1280.50,
  "registerTime": "2026-05-01 10:00:00",
  "addressList": [
    {
      "addressId": 10,
      "consigneeName": "张三",
      "mobile": "17712349136",
      "regionCode": "540622",
      "regionName": "西藏自治区/那曲市/比如县",
      "detailAddress": "某某路1号",
      "isDefault": "1",
      "fullAddress": "西藏自治区那曲市比如县某某路1号"
    }
  ]
}
规则 说明
不存在 code!=200msg 会员不存在
手机号 平台 query 权限可看完整号(需求 §10 权限)

3.4 启用/禁用 PUT /{memberId}/status

{ "status": "1" }
校验 说明
status 0 / 1
禁用 记操作日志; 调订单关闭

3.5 会员订单列表 GET /{memberId}/orders

委托 IOrderFacade.pageOrdersByMember;Query 对齐需求 §6.3:

Query 说明
pageNum, pageSize
orderNo 订单编号
goodsName 商品名称
payType, payStatus 支付
shipStatus 发货/订单履约状态
consigneeName, consigneeMobile, address 收货
logisticsCompany 物流公司
beginTime, endTime 下单时间

rows: 与《订单管理》列表字段对齐子集;operateType=readonly(前端隐藏发货/关闭按钮,M6)。

3.6 会员订单详情 GET /{memberId}/orders/{orderId}

  • 校验 biz_order.member_id = memberId,否则 403/业务异常。
  • 含商品明细、物流节点时间轴; 写操作字段。

3.7 错误码(业务 msg 示例)

场景 msg
会员不存在 会员不存在
订单不属于该会员 无权查看该订单
禁用成功 操作成功

统一包装:AjaxResult / TableDataInfocodemsgdata/rows/total)。


4. C 端接口(已实现 · MemberAppController

C 端专册: 注册/登录见 《会员注册登录技术方案》 v1.2;本节保留摘要。

基路径: /api/member
鉴权: MemberWebConfig + MemberAuthInterceptorregister/login/sms/send/serviceAgreement/** 匿名且不经拦截器;其余须会员 Token → MemberContext.getMemberId()

MemberWebConfig 拦截 /api/member/**(排除 login/register 等)、/api/merchant/entry/**(排除 agreement/status)、购物车/结算/订单等;详见 C 端《会员注册登录技术方案》§3.1。

方法 路径 说明
POST /sms/send 发送验证码
POST /register 手机号+密码+确认密码;无验证码
POST /login 手机号或会员名称+密码;返回 Token
GET /profile 当前会员(密码脱敏)
PUT /profile user_name/nick_name/avatar/passwordupdateAccount
GET /address/list 地址列表
POST /address 新增地址
PUT /address 修改地址
DELETE /address/{addressId} 删除地址
PUT /address/{addressId}/default 设默认

协作接口(content 模块 · 同基路径前缀):

方法 路径 说明
GET /serviceAgreement 买家服务协议(MallServiceAgreementAppController
GET /serviceAgreement/status 注册/登录开放状态
规则 说明
M2 注册/添加前 countByMobile(JOIN sys_user
M4 sys_user.status=1 禁止登录
M7 校验 biz_merchant_account 绑定(分表、无 FK)
注册事务 insertUser(角色 member)→ insert biz_membermember_id=user_id

5. 与订单模块协作

5.1 biz_order 字段(权威 DDL)

完整定义见 sql/biz_order.sql 及《订单管理技术方案》§2(v1.0.1)。会员模块主要消费:

字段 说明
order_id, order_no 主键与展示编号
member_id 关联 biz_member.member_id
shop_id 店铺归属
order_status 3=已完成(O11 统计);0/1/2=未完成 O10
pay_amount 实付;O11 SUM 字段
del_flag 固定 0;删单用 order_status=5

明细、物流见 biz_order_itembiz_order_logistics_trace

5.2 消费汇总刷新(O11)

订单状态 → 已完成
    → IOrderFacade 内或监听
    → IMemberFacade.refreshConsumption(memberId)
    → UPDATE biz_member SET order_count=?, total_amount=?
          WHERE 统计条件 status=已完成 AND del_flag=0

refreshConsumption 建议 按 member_id 重算(避免并发漏加):

SELECT COUNT(1), IFNULL(SUM(pay_amount),0)
FROM biz_order
WHERE member_id = #{memberId} AND order_status = '3' AND del_flag = '0'

5.3 会员订单只读

平台 会员管理订单管理 共用 IOrderFacade.getOrderDetail;会员 Controller 禁止 暴露发货/关闭 URL(M6)。


6. 菜单与权限(RuoYi)

菜单 权限标识
会员管理 agri:member:list
添加会员 agri:member:add
查看详情 agri:member:query
启用/禁用 agri:member:edit

订单只读挂在 query;不写 agri:member:remove(本期无删会员需求,逻辑删除预留)。


7. 非本期(库表/接口不建)

说明
余额、积分、标签、导入 需求 §13
商家端查会员 不做
会员等级自动升级 member_level 展示

本期已实现: 平台 POST /agri/member 添加会员(无短信验证码);C 端注册/登录/资料/地址;列表仅 role_key=member 用户。


8. 源文档对照

需求规则 技术落点
M1~M3 买家、只读订单 §1.2、§3.5~3.6
M2 手机号唯一 sys_user.phonenumber + checkPhoneUnique / countByMobile
M4 启用 sys_user.status + IMemberFacade.isMemberEnabled
M5/O11 消费统计 biz_member.order_count/total_amount + §5.2
M6 订单不写 无发货类接口
M7 与经营账号隔离 分表、无 FK
M9 订单仅当前会员 member_id 强制过滤
M11 检索 keyword 匹配 user_name / nick_name / phonenumber(API 字段仍为 memberCode 等)
列表范围 role_key=membermemberRoleExists
M12 订单检索 §3.5 Query
M14 地址只读(平台) 详情 addressList;C 端 §4 维护

文档版本:v1.4 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 地址表 region_code/region_name · C 端注册/登录见《消费者APP/会员注册登录/会员注册登录技术方案.md》v1.2 · 关联《会员管理功能需求.md》v1.1、《会员管理测试用例.md》v1.1