巴青农资商城

我的服务技术方案.md 18KB

我的服务 — 技术方案(C 端)

依据: 《我的服务功能需求.md》v1.1
关联: 平台《会员管理技术方案.md》v1.3、《商户入驻审核技术方案.md》v1.2、《商城入驻协议技术方案.md》v1.0、《关联需求分析.md》v1.6;C 端《会员注册登录技术方案.md》v1.3(登录前置)
范围: C 端 个人资料、修改密码、收货地址、商家入驻申请 的后端落位、表结构、接口契约;不含 前端页面与平台审核实现细节(平台审核见入驻审核专册)。
v1.4: 已有商户管理员 仅开店铺 入驻:GET /api/merchant/entry/contextsubmitApply shopOnly 分支。
原则: 账号复用 sys_usermember_id = user_id);鉴权 TokenService + MemberAuthInterceptor;入驻 form_json 快照 + 平台审核链。


1. 技术架构

选型
基础框架 RuoYi v3.9.2springboot2 分支)
数据库 MySQL 5.7.39
ORM / 响应 MyBatis;AjaxResultcodemsgdata
密码 BCrypt(SecurityUtils.encryptPassword / matchesPassword
C 端鉴权 MemberWebConfigMemberAuthInterceptorTokenService.getLoginUserMemberContext.setMemberId
文件上传 RuoYi 通用上传(头像、证件照等);URL 写入表单字段
入驻校验 EntryApplyFormValidator + IMerchantEntryAgreementFacade

1.1 模块落位

baqing-shop/src/main/java/com/ruoyi/web/modules/
├── account/                              # 资料 · 地址
│   ├── controller/MemberAppController.java
│   ├── service/impl/MemberAppServiceImpl.java
│   ├── service/impl/MemberAddressServiceImpl.java
│   ├── domain/BizMember.java、BizMemberAddress.java
│   ├── vo/MemberAddressVO.java
│   ├── config/MemberWebConfig.java
│   └── support/MemberAuthInterceptor.java、MemberContext.java
├── entry/                                # 商家入驻
│   ├── controller/MerchantEntryApplyAppController.java
│   ├── service/impl/MerchantEntryApplyServiceImpl.java
│   ├── dto/EntryApplySubmitDTO.java
│   ├── vo/EntryApplyMyVO.java、EntryApplyContextVO.java
│   └── support/EntryApplyFormValidator.java、EntryApplyFormMapper.java
└── content/                              # 入驻协议(只读)
    └── controller/MerchantEntryAgreementAppController.java

sql/
├── biz_member.sql                        # biz_member + biz_member_address
├── biz_merchant_entry_apply.sql
├── biz_merchant_entry_agreement.sql
└── biz_merchant_entry_form_json说明.sql  # form_json 字段对照

1.2 业务链

【资料 / 密码 / 地址】
MemberAuthInterceptor
    → MemberAppController / MemberAddressService
        → sys_user(nick_name、avatar、email、sex、password…)
        → biz_member(member_id、扩展统计)
        → biz_member_address(1:N)

【商家入驻】
GET /api/merchant/entry/agreement(匿名)
GET /api/merchant/entry/context(会员 · 是否仅开店铺)
    → 新主体:填写 subject/biz/shop
    → 已有商户管理员:仅填写 shop
    → POST /api/merchant/entry/apply
        → biz_merchant_entry_apply(form_json + 冗余检索列)
            → 平台审核 / 公示 / 建档(entry 模块 · 平台 Controller)
                → biz_merchant + biz_shop + biz_merchant_account
                → biz_member_message(审核结果通知)
关联模块 协作
会员注册登录 登录 Token;本模块 全部须鉴权(协议接口除外)
平台会员管理 共用表;平台 只读 资料/地址
商户入驻审核 C 端 写申请;平台 approve/reject/completePublicity
商城入驻协议 assertAccepted 提交前校验
订单(待建设) 结算页 biz_member_address;本模块 不写订单

1.3 鉴权范围

路径 鉴权
/api/member/register/login/serviceAgreement/** 匿名(会员注册登录专册
/api/member/profile/address/** 会员 Token
/api/member/password(建议) 会员 Token
/api/merchant/entry/agreement/status @Anonymous
/api/merchant/entry/context/apply/my 会员 TokenMemberWebConfig/api/merchant/entry/**,排除 agreement/status)

MemberWebConfig 拦截范围(摘要):

.addPathPatterns("/api/member/**", "/api/merchant/entry/**",
        "/api/shop/*/follow", "/api/cart/**", "/api/checkout/**", "/api/order/**")
.excludePathPatterns("/api/member/register", "/api/member/login", "/api/member/sms/send",
        "/api/member/serviceAgreement", "/api/member/serviceAgreement/**",
        "/api/merchant/entry/agreement", "/api/merchant/entry/status");

/api/member/login 不在拦截器内;登录成功后客户端 带 Token 访问 /context 等接口,由 MemberAuthInterceptor 注入 MemberContext

Header:Authorization: Bearer {token}(与平台 TokenService 一致)。


2. 数据库设计

不新建会员主表;权威 DDL 见 sql/ 目录。下列为 本模块读写 表摘要。

2.1 账号与资料(复用)

本模块用途 关键字段
sys_user 资料、密码 user_id(= member_id)、nick_nameemailsexavatarpassword
biz_member 会员扩展 member_id(= user_id)、register_time、消费统计

字段映射(C 端展示):

产品字段 存储 可编辑
用户 ID member_id
会员名称 user_name 否(功能需求资料页未列;改名称 非本期
手机号 phonenumber
昵称 nick_name
头像 avatar
邮箱 email
性别 sex(0男 1女 2未知)
密码 password PUT /password

更新口径: BizMemberMapper.updateAccountmember_id 更新 sys_userWHERE user_id = #{memberId});不写入 biz_member

2.2 收货地址 biz_member_address

字段 类型 说明
address_id bigint PK 自增
member_id bigint FK → biz_member.member_id
consignee_name varchar(64) 收货人
mobile varchar(20) 联系电话
region_code varchar(64) 省市区编码(区县级 code)
region_name varchar(128) 省市区名称(省/市/区 / 拼接)
detail_address varchar(256) 详细地址
is_default char(1) 01 是;同会员 至多一条 为 1
del_flag char(1) 0 存在 2 逻辑删除
create_time / update_time datetime 排序用

索引: idx_member (member_id, del_flag)

列表排序(已实现): ORDER BY is_default DESC, update_time DESC(默认置顶;其余按最近更新倒序)。

2.3 入驻申请 biz_merchant_entry_apply

字段 类型 说明
apply_id bigint PK
apply_no varchar(32) UK 业务单号
apply_status char(1) 0 待审 1 已完成 2 未通过 3 公示中
merchant_type char(1) 1 个人 2 企业
member_id bigint 申请人
member_code varchar(64) 会员名称冗余
subject_label varchar(128) 列表摘要(姓名/企业名)
contact_name / contact_phone varchar 联系人
id_card_no / credit_code varchar(32) 唯一性校验
merchant_name / shop_name varchar(128) 唯一性校验
form_json longtext { subject, biz, shop, agreementAccepted, shopOnlyMode?, existingMerchantId? } 快照
reject_reason varchar(500) 驳回原因
merchant_id / shop_id bigint 公示完成回填
apply_time datetime 提交时间
publicity_start_time / publicity_end_time datetime 公示期
del_flag char(1) 0/2

索引: idx_member_status (member_id, apply_status) — 阻塞重复提交(status in 0,3)。

2.4 协作表(只读 / 下游写入)

关系
biz_merchant_entry_agreement C 端读协议;enable_flag=1 才开放申请
biz_member_message 审核/公示/完成时 entry 模块写入
biz_merchantbiz_shopbiz_merchant_account 公示完成 后由平台 Service 创建

2.5 ER(本模块视角)

sys_user ──1:1── biz_member ──1:N── biz_member_address
                    │
                    └──1:N── biz_merchant_entry_apply ──►(审核后)biz_merchant / biz_shop

3. 接口设计

统一响应:AjaxResult;登录接口 token 在根级(见会员注册登录专册)。
基路径: 资料/地址 /api/member;入驻 /api/merchant/entry

3.1 个人资料

GET /api/member/profile

说明
鉴权 会员 Token
响应 data 建议 MemberProfileAppVO
字段 说明
memberId 用户 ID(只读)
mobile 手机号(只读)
memberCode 会员名称(只读,登录账号)
nickName 昵称
avatar 头像 URL
email 邮箱
sex 性别

已实现: MemberProfileAppVOupdateAccountsys_user(email/sex)。

PUT /api/member/profile

Body 可写字段
nickName、avatar、email、sex 更新 sys_useruser_id = member_id
不可写 memberId、mobile、password
校验 说明
nickName 非空
email 格式(可空)

Service: MemberAppServiceImpl.updateProfileBizMemberMapper.updateAccountsys_user:nick_name、avatar、email、sex)。


3.2 修改密码

PUT /api/member/password(建议独立接口)

Body 必填
oldPassword
newPassword
confirmPassword

| 流程 | | |------|--| | 1 | matchesPassword(oldPassword, sys_user.password) | | 2 | newPassword === confirmPassword | | 3 | encryptPassword(newPassword) 更新 sys_user.password |

| 失败 msg(示例) | | |----------------|--| | 旧密码错误 | | | 两次输入的密码不一致 | |

现状: 密码可通过 PUT /profilepassword 字段更新 且无旧密码校验须迁移 至本接口以满足功能需求 MS-W1。


3.3 收货地址

方法 路径 说明 状态
GET /address/list 当前会员地址列表 已实现
POST /address 新增 已实现
PUT /address 修改(Body 含 addressId) 已实现
DELETE /address/{addressId} 逻辑删除 已实现
PUT /address/{addressId}/default 设默认 已实现

GET /api/member/address/list

响应 dataMemberAddressVO[]

字段 说明
addressId
consigneeName、mobile
regionCode、regionName、detailAddress
isDefault 0/1
fullAddress regionName(去 /)+ 详细地址

POST /api/member/address / PUT /api/member/address

Body 字段 必填
addressId PUT 必填
consigneeName、mobile
regionCode、regionName 是;须 成对 非空
detailAddress
isDefault 否;为 1 时 同事务 clearDefault

事务规则:

isDefault = 1  →  UPDATE 同 member 其他行 is_default = 0  →  写当前行

3.4 商家入驻协议(只读)

方法 路径 鉴权 说明
GET /api/merchant/entry/agreement 匿名 协议标题、版本、正文、entryOpen
GET /api/merchant/entry/status 匿名 entryOpen 开关

3.5 入驻上下文(v1.4)

GET /api/merchant/entry/context

说明
鉴权 会员 Token
响应 EntryApplyContextVO
字段 说明
shopOnlyMode 是否已是商户管理员
canShopOnlyApply 是否可仅填店铺提交
blockReason 不可时的原因
merchantId、merchantType、subjectLabel、merchantName 展示用
subject、biz 只读快照(BizMerchant 结构)

canShopOnlyApply=true 条件: 商户 cert_status=正常biz_complete=1

状态: 已实现


3.6 提交入驻申请

POST /api/merchant/entry/apply

说明
鉴权 会员 Token
Body EntryApplySubmitDTO
{
  "subject": { },
  "biz": { },
  "shop": { "shopName", "shopAvatar", "shopPhone", "shopDesc" },
  "agreementAccepted": true
}

仅开店铺(v1.4): Body 可仅含 shop + agreementAccepted;后端 buildSubmitFromExistingMerchant 合并 DB 商户快照;form_json 写入 shopOnlyMode=trueexistingMerchantId

  • subject / biz 结构同 BizMerchant;字段清单见 sql/biz_merchant_entry_form_json说明.sql
  • merchant_typeEntryApplyFormValidator.resolveMerchantType 从表单推断(1 个人 / 2 企业);仅开店铺时取自已有商户。
校验 实现
协议勾选 IMerchantEntryAgreementFacade.assertAccepted
待审/公示中 countBlockingByMemberId(status in 0,3)
完整字段 新主体:validateMobileSubmit;仅开店铺:validateShopOnlySubmit
唯一性 证件/信用代码/merchant_name/shop_name(仅开店铺 exclude existingMerchantId
会员昵称 绑定经营账号路径须 nick_name 非空
商户就绪 仅开店铺:assertMerchantEligibleForShopOnly(正常 + biz_complete=1)

成功 data

{
  "applyId": 1,
  "applyNo": "EA202605260001",
  "applyStatus": "0"
}

状态: 已实现


3.7 我的入驻申请

GET /api/member/entry/my → 实际路径 GET /api/merchant/entry/my

说明
鉴权 会员 Token
响应 EntryApplyMyVO[](按 apply_time 降序)
字段 说明
applyId、applyNo
applyStatus 0/1/2/3
applyTime、auditTime
rejectReason status=2 时有值
publicityStartTime、publicityEndTime status=3/1 时 建议扩展 VO
merchantId、shopId status=1 回填

状态: 已实现(公示时间字段 可补 至 VO)。


3.8 错误码(业务 msg 示例)

场景 msg
未登录 请先登录(401)
会员不存在 会员不存在
地址不存在 地址不存在
待审申请已存在 常量 MSG_PENDING_EXISTS
协议未勾选 Facade 统一文案
旧密码错误 旧密码错误
证件/店名重复 对应唯一性提示
商户经营未完善 商户经营信息未完善,请联系平台完善后再申请开店
商户冻结/注销 对应 MSG_MERCHANT_FROZEN / MSG_MERCHANT_CANCELLED

4. Service 要点

4.1 资料

getProfile(memberId)
    → BizMemberMapper.selectById(JOIN sys_user)
    → 脱敏 password;组装 VO(含 email/sex)

updateProfile(memberId, dto)
    → 校验 nickName 等
    → updateAccount(sys_user:nick_name, avatar, email, sex)

4.2 修改密码

changePassword(memberId, old, new, confirm)
    → 校验 confirm
    → matchesPassword(old)
    → updateAccount(password=encrypt(new))

4.3 地址

addAddress / updateAddress / setDefaultAddress
    @Transactional
    → validateAddress
    → 若 isDefault=1 → clearDefault(memberId)
    → insert / update / setDefault

4.4 入驻提交

submitApply(memberId, dto)
    @Transactional
    → agreementFacade.assertAccepted
    → countBlockingByMemberId == 0
    → requireMember(nick_name 非空)
    → findMerchantByMemberAdmin
        ├── 有:validateShopOnlySubmit + buildSubmitFromExistingMerchant + assertUnique(exclude merchantId)
        └── 无:validateMobileSubmit + assertUnique
    → insert biz_merchant_entry_apply(form_json + shopOnlyMode/existingMerchantId)

5. 与平台方案协作

平台文档 C 端本模块关系
《会员管理技术方案》§4 共用 /api/member/profile/address/**;平台 /agri/member 只读
《商户入驻审核技术方案》§4 C 端 3.5~3.7 对应其 4.0~4.2;审核 4.6~4.8 仅平台
《商城入驻协议技术方案》 3.4 读配置;enable_flag=0apply 阻断
《关联需求分析》§2.1 用户链账号 经营账号;completePublicity 后 bindAccountOnMerchantCreate

入驻状态 C 端只读流转:

0 待审 ──平台 approve──► 3 公示中 ──期满 complete──► 1 已完成
  └──平台 reject──► 2 未通过(C 端展示 rejectReason,可再 submit 新单)

6. 实现状态

能力 状态 备注
鉴权 MemberAuthInterceptor + TokenService 已实现
GET/PUT /profile(含 email/sex) 已实现 MemberProfileAppVO
PUT /password(旧密码校验) 已实现
地址 CRUD + 默认互斥 已实现
入驻协议 GET 已实现
GET /context、POST /apply shopOnly 已实现 v1.4
POST /apply、GET /my 已实现 含公示时间
C 端前端 已实现(见《我的服务前端技术方案.md》v1.4,含 shopOnly 分步)

7. 非本期

说明
手机号换绑
资料页改会员名称 功能需求未列
待审申请撤销/改资料 驳回后重提
GET /api/member/message/list 消息列表另册
入驻表单草稿保存

8. 修订记录

版本 说明
v1.4.1 MemberWebConfig 统一拦截 /api/merchant/entry/**/login 不设置 MemberContext
v1.4 入驻 仅开店铺GET /contextvalidateShopOnlySubmitform_json.shopOnlyMode
v1.3 biz_member_addressprovince/city/districtregion_code/region_name
v1.2 移除 birthday(个人资料不含出生日期)
v1.1 email/sex 存 sys_userPUT /passwordMemberProfileAppVO
v1.0 首版

文档版本:v1.4.1 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《我的服务功能需求.md》v1.2