商户通知管理模块提供通知统计、通知列表查询等功能,支持系统通知、订单提醒等多种通知类型。
GET /notice/getNoticeStatistics| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| receiverId | String | 是 | 接收人ID(商户ID,格式如:store_18241052019) |
GET /notice/getNoticeStatistics?receiverId=store_18241052019
{
"code": 200,
"success": true,
"data": {
"systemNotice": {
"id": "12345",
"senderId": "system",
"receiverId": "store_18241052019",
"businessId": 102,
"title": "店铺审核通知",
"context": "您的店铺已通过审核",
"noticeType": 1,
"isRead": 0,
"createdTime": "2025-11-12 14:30:00",
"systemNum": 5
},
"orderNotice": {
"id": "12346",
"senderId": "system",
"receiverId": "store_18241052019",
"businessId": 2001,
"title": "新订单提醒",
"context": "您有一笔新订单",
"noticeType": 2,
"isRead": 0,
"createdTime": "2025-11-12 15:20:00",
"orderNum": 3
}
},
"msg": "查询成功"
}
| 字段名 | 类型 | 说明 |
|---|---|---|
| systemNotice | Object/String | 系统通知对象或字符串"null" |
| systemNotice.systemNum | Long | 系统通知未读数量 |
| orderNotice | Object/String | 订单提醒对象或字符串"null" |
| orderNotice.orderNum | Long | 订单提醒未读数量 |
GET /notice/getNoticeList| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| pageNum | int | 是 | - | 页码(从1开始) |
| pageSize | int | 是 | - | 每页条数 |
| receiverId | String | 是 | - | 接收人ID(商户ID) |
| noticeType | int | 否 | 0 | 通知类型(0-系统通知和订单提醒之外的类型,1-系统通知,2-订单提醒) |
GET /notice/getNoticeList?receiverId=store_18241052019&pageNum=1&pageSize=10¬iceType=0
{
"code": 200,
"success": true,
"data": {
"records": [
{
"id": "12347",
"senderId": "user_13800138000",
"receiverId": "store_18241052019",
"businessId": 301,
"title": "新评论通知",
"context": "用户对您的店铺进行了评论",
"noticeType": 0,
"isRead": 0,
"userName": "张三",
"userImage": "https://example.com/avatar.jpg",
"platformType": "1",
"createdTime": "2025-11-12 16:00:00"
}
],
"total": 50,
"size": 10,
"current": 1,
"pages": 5
},
"msg": null
}
| 字段名 | 类型 | 说明 |
|---|---|---|
| records | Array | 当前页通知列表 |
| records[].id | String | 通知ID |
| records[].senderId | String | 发送人ID |
| records[].receiverId | String | 接收人ID |
| records[].businessId | Integer | 业务ID |
| records[].title | String | 通知标题 |
| records[].context | String | 通知内容 |
| records[].noticeType | Integer | 通知类型 |
| records[].isRead | Integer | 是否已读(0-未读,1-已读) |
| records[].userName | String | 发送用户名称 |
| records[].userImage | String | 发送用户头像 |
| records[].platformType | String | 平台类型(1-默认平台,2-其他) |
| records[].createdTime | String | 创建时间 |
| total | Long | 总记录数 |
| size | Integer | 每页条数 |
| current | Integer | 当前页码 |
| pages | Integer | 总页数 |
| noticeType | 说明 |
|---|---|
| 0 | 系统通知和订单提醒之外的类型(如评论、关注、举报等) |
| 1 | 系统通知(店铺审核、违规处理等) |
| 2 | 订单提醒(新订单、订单核销等) |
平台类型 platformType 用于标识通知来源平台:
"1":默认平台(本平台)"2":其他平台判断规则:
businessId 为空 → 默认平台reportContextType 为 1、2、3(商户、用户、动态) → 默认平台通知中的 senderId 格式:
"system""store_手机号"(如:store_18241052019)"user_手机号"(如:user_13800138000)系统会自动查询并关联发送人的 userName 和 userImage。
文件路径:alien-store-platform/src/main/java/shop/alien/storeplatform/controller/NoticeController.java
@ApiOperation("获取系统通知和订单提醒统计")
@GetMapping("/getNoticeStatistics")
public R<JSONObject> getNoticeStatistics(@RequestParam("receiverId") String receiverId) {
// ...
}
@ApiOperation("获取通知列表")
@GetMapping("/getNoticeList")
public R<IPage<LifeNoticeVo>> getNoticeList(@RequestParam("pageNum") int pageNum,
@RequestParam("pageSize") int pageSize,
@RequestParam("receiverId") String receiverId,
@RequestParam(value = "noticeType", defaultValue = "0") int noticeType) {
// ...
}
文件路径:alien-store-platform/src/main/java/shop/alien/storeplatform/service/NoticeService.java
JSONObject getNoticeStatistics(String receiverId);
IPage<LifeNoticeVo> getNoticeList(int pageNum, int pageSize, String receiverId, int noticeType);
文件路径:alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/NoticeServiceImpl.java
@Override
public IPage<LifeNoticeVo> getNoticeList(int pageNum, int pageSize, String receiverId, int noticeType) {
// 1. 查询通知列表
LambdaQueryWrapper<LifeNotice> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(LifeNotice::getReceiverId, receiverId);
queryWrapper.eq(LifeNotice::getNoticeType, noticeType);
queryWrapper.eq(LifeNotice::getDeleteFlag, 0);
queryWrapper.orderByDesc(LifeNotice::getCreatedTime);
List<LifeNotice> lifeNoticeList = lifeNoticeMapper.selectList(queryWrapper);
// 2. 解析 senderId,分组为 store 和 user
Map<String, List<String>> senderIdMap = lifeNoticeList.stream()
.map(LifeNotice::getSenderId)
.filter(item -> item != null && !"system".equals(item) && item.contains("_"))
.collect(Collectors.groupingBy(
item -> item.split("_")[0], // 按 store 或 user 分组
Collectors.mapping(
item -> item.split("_")[1], // 提取手机号
Collectors.toList()
)));
// 3. 查询违规举报信息(用于判断平台类型)
List<Integer> businessIdList = lifeNoticeList.stream()
.map(LifeNotice::getBusinessId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
List<LifeUserViolation> lifeUserViolationList =
lifeUserViolationMapper.selectBatchIds(businessIdList);
Map<Integer, String> lifeUserViolationMap = lifeUserViolationList.stream()
.filter(item -> item.getReportContextType() != null)
.collect(Collectors.toMap(
LifeUserViolation::getId,
LifeUserViolation::getReportContextType,
(existing, replacement) -> existing
));
// 4. 查询用户信息(商户和普通用户)
String storePhones = senderIdMap.containsKey("store") ?
"'" + String.join("','", senderIdMap.get("store")) + "'" : "''";
String userPhones = senderIdMap.containsKey("user") ?
"'" + String.join("','", senderIdMap.get("user")) + "'" : "''";
List<LifeMessageVo> userList =
lifeMessageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
// 5. 组装 LifeNoticeVo,关联用户信息
List<LifeNoticeVo> noticeVoList = new ArrayList<>();
lifeNoticeList.forEach(item -> {
LifeNoticeVo noticeVo = new LifeNoticeVo();
BeanUtils.copyProperties(item, noticeVo);
// 设置用户信息(如果不是系统通知)
if (!"system".equals(noticeVo.getSenderId())) {
LifeMessageVo userinfo = userList.stream()
.filter(user -> user.getPhoneId().equals(item.getSenderId()))
.findFirst()
.orElse(null);
if (userinfo != null) {
noticeVo.setUserName(userinfo.getUserName());
noticeVo.setUserImage(userinfo.getUserImage());
}
}
noticeVoList.add(noticeVo);
});
// 6. 设置平台类型标识
for (LifeNoticeVo lifeNoticeVo : noticeVoList) {
// businessId 为空时,设置为默认平台
if (lifeNoticeVo.getBusinessId() == null) {
lifeNoticeVo.setPlatformType("1");
}
// 店铺审核通知设置为默认平台
if ("店铺审核通知".equals(lifeNoticeVo.getTitle())) {
lifeNoticeVo.setPlatformType("1");
}
// 根据举报类型判断平台类型
if (lifeNoticeVo.getBusinessId() != null &&
lifeUserViolationMap.containsKey(lifeNoticeVo.getBusinessId())) {
String reportContextType = lifeUserViolationMap.get(lifeNoticeVo.getBusinessId());
if ("1,2,3".contains(reportContextType)) {
lifeNoticeVo.setPlatformType("1");
}
}
}
// 7. 手动分页
List<LifeNoticeVo> pageList = noticeVoList.stream()
.skip((long) (pageNum - 1) * pageSize)
.limit(pageSize)
.collect(Collectors.toList());
// 8. 构建分页结果
IPage<LifeNoticeVo> result = new Page<>();
result.setRecords(pageList);
result.setTotal(noticeVoList.size());
result.setPages((int) Math.ceil(noticeVoList.size() / (double) pageSize));
result.setSize(pageSize);
result.setCurrent(pageNum);
return result;
}
private final LifeNoticeMapper lifeNoticeMapper; // 通知Mapper
private final LifeMessageMapper lifeMessageMapper; // 消息Mapper(用于查询用户信息)
private final LifeUserViolationMapper lifeUserViolationMapper; // 违规举报Mapper
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import shop.alien.entity.store.LifeNotice;
import shop.alien.entity.store.LifeUserViolation;
import shop.alien.entity.store.vo.LifeMessageVo;
import shop.alien.entity.store.vo.LifeNoticeVo;
import shop.alien.mapper.LifeMessageMapper;
import shop.alien.mapper.LifeNoticeMapper;
import shop.alien.mapper.LifeUserViolationMapper;
import java.util.*;
import java.util.stream.Collectors;
| 项目 | 原接口 | 新接口 |
|---|---|---|
| 服务 | alien-store(app端) | alien-store-platform(web端) |
| 路径 | /alienStore/notice/getSystemAndOrderNoticeSum | /notice/getNoticeStatistics |
| 方法名 | getSystemAndOrderNoticeSum | getNoticeStatistics |
| 项目 | 原接口 | 新接口 |
|---|---|---|
| 服务 | alien-store(app端) | alien-store-platform(web端) |
| 路径 | /alienStore/notice/getNoticeByPhoneId | /notice/getNoticeList |
| 方法名 | getNoticeList | getNoticeList |
| Controller | LifeNoticeController | NoticeController |
| Service | LifeNoticeService | NoticeService |
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | String | 主键ID |
| sender_id | String | 发送人ID |
| receiver_id | String | 接收人ID |
| business_id | Integer | 业务ID |
| title | String | 通知标题 |
| context | String | 通知内容 |
| notice_type | Integer | 通知类型(0/1/2) |
| is_read | Integer | 是否已读(0-未读,1-已读) |
| delete_flag | Integer | 删除标记(0-未删除,1-已删除) |
| created_time | Date | 创建时间 |
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键ID |
| report_context_type | String | 举报内容分类(0-商户,1-用户,2-动态,3-评论,4-二手商品,5-二手用户) |
| violation_type | String | 违规类型 |
| processing_status | String | 处理状态(0-未处理,1-违规,2-未违规) |
{
"code": 500,
"success": false,
"data": null,
"msg": "查询失败:数据库连接异常"
}
调用 getNoticeStatistics 获取未读数量,在首页显示通知角标。
调用 getNoticeList 获取通知列表,展示不同类型的通知:
noticeType=0:其他通知(评论、关注等)noticeType=1:系统通知noticeType=2:订单提醒通过 WebSocket 或定时轮询更新通知数量和列表。
接口一(通知统计):
接口二(通知列表):
-- 查询商户的通知统计
SELECT
notice_type,
COUNT(*) AS total_count,
SUM(CASE WHEN is_read = 0 THEN 1 ELSE 0 END) AS unread_count,
MAX(created_time) AS latest_time
FROM life_notice
WHERE receiver_id = 'store_18241052019'
AND notice_type IN (1, 2)
AND delete_flag = 0
GROUP BY notice_type;
-- 查询通知列表
SELECT
id, sender_id, receiver_id, business_id, title, context,
notice_type, is_read, created_time
FROM life_notice
WHERE receiver_id = 'store_18241052019'
AND notice_type = 0
AND delete_flag = 0
ORDER BY created_time DESC
LIMIT 10 OFFSET 0;
store_ + 手机号(如:store_18241052019)delete_flag 字段"null" 而非 null 对象接口一(通知统计):
NoticeController,添加 getNoticeStatistics 接口NoticeService,添加方法定义NoticeServiceImpl,实现统计逻辑接口二(通知列表):
getNoticeList 接口getNoticeList 方法定义LifeMessageMapper 和 LifeUserViolationMapper