巴青农资商城

站内消息技术方案.md 13KB

站内消息 — 技术方案(C 端)

依据: 《站内消息功能需求.md》v1.0
关联: 平台《商户入驻审核技术方案》v1.1、《商户入驻审核功能需求》v1.1、《会员管理技术方案》v1.3、《关联需求分析.md》v1.6;C 端《我的服务技术方案》v1.0
范围: C 端 /api/member/message/** 未读数、分页列表、详情(含 打开即已读);复用 既有 biz_member_message 与入驻审核 写入 链路;不含 前端页面、平台消息管理、短信/Push。
原则: 不新建表;写入 entry 模块 MemberEntryMessageSupport;本模块 只读 + 已读更新;按 member_id 严格隔离


1. 技术架构

选型
基础框架 RuoYi v3.9.2springboot2 分支)
数据库 MySQL 5.7.39
ORM / 响应 MyBatis;AjaxResultcodemsgdata);列表 TableDataInforowstotal
鉴权 MemberAuthInterceptorMemberWebConfig/api/member/**); @Anonymous
分页 PageHelper + startPage();Query pageNumpageSize
缓存 本期不做 Redis

1.1 模块落位

baqing-shop/src/main/java/com/ruoyi/web/modules/message/     # 新建 · C 端读
├── controller/MemberMessageAppController.java               # /api/member/message/**
├── service/IMemberMessageAppService.java
├── service/impl/MemberMessageAppServiceImpl.java
├── vo/
│   ├── MemberMessageListItemVO.java                         # 列表行
│   ├── MemberMessageDetailVO.java                           # 详情
│   └── MemberMessageUnreadVO.java                           # 未读数
└── constant/MemberMessageConstants.java                     # 文案/ bizType 常量(读侧)

entry/(已有 · 写入 · 协作)
├── domain/BizMemberMessage.java
├── mapper/BizMemberMessageMapper.java                       # 扩展 select/count/updateRead
├── support/MemberEntryMessageSupport.java                   # approve/reject/complete 写消息
└── constant/MerchantEntryApplyConstants.java                # BIZ_TYPE_ENTRY_AUDIT、标题常量

account/(已有 · 鉴权)
├── config/MemberWebConfig.java                              # /api/member/** 已覆盖 message
└── support/MemberContext.java、MemberAuthInterceptor.java

resources/mapper/entry/BizMemberMessageMapper.xml            # 扩展 SQL
sql/biz_member_message.sql                                   # 权威 DDL(已存在)

1.2 协作链

【写入 · 平台入驻审核 · 已实现】
    PUT /agri/merchantEntryApply/approve/{applyId}
        → MemberEntryMessageSupport.sendPublicity(...)
    PUT /agri/merchantEntryApply/completePublicity/{applyId}
    或 MerchantEntryPublicityTask.processExpiredPublicity()
        → MemberEntryMessageSupport.sendPass(...)
    PUT /agri/merchantEntryApply/reject
        → MemberEntryMessageSupport.sendReject(...)

【本模块 · C 端读】
    GET  /api/member/message/unread-count     → 红点/角标
    GET  /api/member/message/list             → 分页列表
    GET  /api/member/message/{messageId}      → 详情 + 标记已读

【前端跳转 · 协作】
    biz_type=ENTRY_AUDIT & biz_id=applyId
        → 我的入驻 GET /api/merchant/entry/my(按 applyId 定位详情页)
关联模块 协作
平台 · 商户入驻审核 唯一写入方(EA14);三类消息标题/正文与 MemberEntryMessageSupport 一致
平台 · 会员管理 禁用会员 无法登录 → 本模块不可用
C 端 · 我的服务 / 入驻 消息详情 跳转/api/merchant/entry/my 对应申请
C 端 · 订单/关注 订单/开业提醒类消息 非本期biz_type 预留扩展

1.3 职责边界

职责
MemberEntryMessageSupport insert 消息; 提供 C 端 API
MemberMessageAppService member_id 查询未读计数详情并 markRead
C 端 Controller 创建/删除/编辑消息接口(MM8)

2. 数据库设计

2.1 复用 · 会员站内消息 biz_member_message

DDL 见 sql/biz_member_message.sql本期不 ALTER

字段 类型 说明
message_id bigint PK 自增
member_id bigint 收件会员;列表/详情 WHERE 必带
biz_type varchar(32) 业务类型;本期 ENTRY_AUDIT
biz_id bigint 业务主键;入驻类 = apply_id
title varchar(128) 标题
content varchar(1000) 正文(含驳回原因、公示时间等)
read_flag char(1) 0 未读 / 1 已读;默认 0
create_time datetime 投递时间;列表 降序

索引(已有):

索引 用途
idx_member_time (member_id, create_time) 分页列表
PK (message_id) 详情

可选优化(非本期必做): idx_member_read (member_id, read_flag) — 未读数大时加速 COUNT

2.2 业务类型枚举(本期)

biz_type 含义 biz_id 写入时机
ENTRY_AUDIT 商户入驻审核 apply_id 公示中 / 入驻完成 / 审核驳回

标题常量(与 MerchantEntryApplyConstants 对齐):

场景 title
审核通过→公示 入驻审核通过,公示中
完成公示 入驻完成
审核驳回 入驻审核未通过

2.3 与关联表

关系
biz_merchant_entry_apply biz_idapply_id;跳转前 可选 校验申请是否存在
biz_member member_id → 收件人;与登录态 一致

3. C 端接口设计

基路径: /api/member/message
鉴权: 全部须 Authorization: Bearer {token};未登录 → 401「请先登录」
MemberWebConfig: /api/member/** 已拦截无需追加 path。

3.1 接口一览

方法 路径 说明
GET /api/member/message/unread-count 未读条数(红点)
GET /api/member/message/list 消息分页列表
GET /api/member/message/{messageId} 消息详情 + 标记已读

本期不提供:

说明
POST/PUT/DELETE 消息 C 端 不可 创建/编辑/删除(MM8)
分类 Tab / 搜索 / 批量已读 需求 非本期
平台 B 端查会员信箱

3.2 未读数 GET /api/member/message/unread-count

说明
数据范围 member_id = MemberContext.getMemberId()read_flag='0'
响应 AjaxResultdata

dataMemberMessageUnreadVO

字段 类型 说明
unreadCount int 未读条数;0 时前端 隐藏 红点

SQL 要点: SELECT COUNT(1) FROM biz_member_message WHERE member_id=? AND read_flag='0'

3.3 消息列表 GET /api/member/message/list

说明
Query pageNumpageSize(RuoYi 默认)
排序 create_time DESC
响应 TableDataInfo

rows[]MemberMessageListItemVO

字段 类型 说明
messageId long
title string
summary string content 截断(建议 ≤80 字,Service 层 StringUtils.abbreviate
readFlag string 0 / 1
createTime string yyyy-MM-dd HH:mm:ss
bizType string ENTRY_AUDIT
bizId long applyId

空列表: rows=[]total=0非异常

3.4 消息详情 GET /api/member/message/{messageId}

说明
数据范围 message_id=? AND member_id=当前会员
副作用 read_flag='0'更新为 1(MM2);已读 幂等
事务 @Transactional:查询 + 条件更新 同一事务

不存在或非本人: ServiceException「消息不存在」(404 或业务码,与项目统一)。

dataMemberMessageDetailVO

字段 类型 说明
messageId long
title string 完整标题
content string 完整正文
readFlag string 返回 1(本次打开后)
createTime string
bizType string
bizId long
linkType string 跳转类型;ENTRY_AUDITMERCHANT_ENTRY
linkAvailable boolean 关联 apply_id 是否存在false 时前端 仅展示正文

跳转约定(前端):

linkType 行为
MERCHANT_ENTRY 跳转 我的入驻 页,携带 applyId=bizId;数据来自 GET /api/merchant/entry/my

3.5 错误与响应格式

场景 code msg(示例)
未登录 401 请先登录
消息不存在 404 或 500 消息不存在
成功 200 操作成功

统一 AjaxResult / TableDataInfo,与 C 端其它模块一致。


4. Service 要点

4.1 getUnreadCount(memberId)

return mapper.countUnreadByMemberId(memberId)

4.2 listMessages(memberId)(Controller 内 startPage()

return mapper.selectListByMemberId(memberId)   # ORDER BY create_time DESC
→ 每行 content → summary 截断

4.3 getDetailAndMarkRead(memberId, messageId)@Transactional

msg = mapper.selectByIdAndMemberId(messageId, memberId)
if msg == null → throw「消息不存在」
if read_flag == '0' → mapper.updateReadFlag(messageId, memberId, '1')
if biz_type == ENTRY_AUDIT → linkAvailable = applyMapper.selectById(bizId) != null
assemble MemberMessageDetailVO

4.4 Mapper 扩展(BizMemberMessageMapper

方法 说明
insert 已有 · 写入
countUnreadByMemberId(Long memberId) 未读数
selectListByMemberId(Long memberId) 列表(PageHelper 分页)
selectByIdAndMemberId(messageId, memberId) 详情 + 隔离
updateReadFlag(messageId, memberId, readFlag) WHERE message_id AND member_id

5. 与平台入驻审核写入对齐

平台操作 消息方法 title content 要点
approve sendPublicity 入驻审核通过,公示中 申请编号 + 公示结束时间
completePublicity sendPass 入驻完成 申请编号 + 经营账号登录指引
reject sendReject 入驻审核未通过 申请编号 + 驳回原因

本模块不修改 上述写入逻辑;联调时核对 标题/正文 与《站内消息功能需求》§7 一致 即可。


6. 业务规则映射(MM)

编号 实现要点
MM0 MemberWebConfig + MemberContext
MM1 unread-countCOUNT read_flag=0
MM2 详情接口 同事务 更新 read_flag=1
MM3 写入在 entry;本模块 只读
MM4 content 与 MemberEntryMessageSupport 同源
MM5 所有 SQL 带 member_id
MM6 列表 create_time DESC + PageHelper
MM7 详情返回 linkType + bizId
MM8 写/删 API
MM9 代录入 insert → 本模块 此类消息
MM10 仅处理已写入的 ENTRY_AUDIT

7. 测试要点

用例 预期
未登录调 list 401
会员 A 读会员 B 的 messageId 「消息不存在」
未读详情后再调 unread-count 计数 -1
已读详情再次打开 read_flag 仍为 1
approve 后 list 新行 read_flag=0,title=公示中
reject 后 detail content rejectReason
空信箱 list rows=[], total=0

建议测试类: MemberMessageAppServiceTestMemberMessageAppControllerTest(MockMvc + Token)。


8. 非本期 / 扩展

说明
订单类 biz_type=ORDER_* 订单模块建设时 扩展 insert + linkType
店铺开业 SHOP_OPEN 关注模块 另册
PUT .../read-all 全部已读 可迭代
Redis 缓存未读数 量大时再考虑
平台消息管理后台

9. 修订记录

版本 说明
v1.0 首版:复用 biz_member_message/api/member/message 三接口;与入驻审核写入链协作

文档版本:v1.0 · 关联《站内消息功能需求.md》v1.0、《商户入驻审核技术方案.md》v1.1、《会员管理技术方案》v1.3 · 草稿保持不变。