添加消息相关表

This commit is contained in:
zk
2026-04-28 12:13:05 +08:00
parent 0c61b89736
commit 6dec0db9fa
11 changed files with 421 additions and 5 deletions
@@ -0,0 +1,58 @@
package org.jiayunet.controller;
import lombok.AllArgsConstructor;
import org.jiayunet.pojo.PageResult;
import org.jiayunet.pojo.dto.message.MessageDto;
import org.jiayunet.pojo.dto.message.MessageUnreadCountDto;
import org.jiayunet.pojo.param.message.MessageQueryParam;
import org.jiayunet.service.MessageQueryService;
import org.jiayunet.service.MessageService;
import org.jiayunet.tool.UserSecurityTool;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 站内信消息接口
*
* @author zk
*/
@RestController
@RequestMapping("/message")
@AllArgsConstructor
public class MessageController {
private final MessageQueryService messageQueryService;
private final MessageService messageService;
/**
* 分页查询消息列表
*/
@GetMapping("/list")
public PageResult<MessageDto> listMessages(@Validated MessageQueryParam param) {
return messageQueryService.listMessages(param, UserSecurityTool.getUserId());
}
/**
* 查询未读消息数
*/
@GetMapping("/unread-count")
public Long countUnread() {
return messageQueryService.countUnread(UserSecurityTool.getUserId());
}
/**
* 按类型查询未读消息数
*/
@GetMapping("/unread-count-by-type")
public MessageUnreadCountDto countUnreadByType() {
return messageQueryService.countUnreadByType(UserSecurityTool.getUserId());
}
/**
* 标记消息已读
*/
@PostMapping("/read/{messageId}")
public void markRead(@PathVariable Long messageId) {
messageService.markRead(messageId, UserSecurityTool.getUserId());
}
}
@@ -0,0 +1,37 @@
package org.jiayunet.pojo.dto.message;
import lombok.Data;
import java.time.Instant;
/**
* 消息列表出参
*
* @author zk
*/
@Data
public class MessageDto {
private Long id;
/** 消息类型 1=系统消息 2=运营消息 3=订单消息 */
private Integer type;
/** 消息标题 */
private String title;
/** 消息内容 */
private String content;
/** 关联业务类型 */
private String bizType;
/** 关联业务ID */
private Long bizId;
/** 是否已读 */
private Boolean read;
/** 创建时间 */
private Instant createTime;
}
@@ -0,0 +1,24 @@
package org.jiayunet.pojo.dto.message;
import lombok.Data;
/**
* 各类型消息未读数出参
*
* @author zk
*/
@Data
public class MessageUnreadCountDto {
/** 总未读数 */
private Long total;
/** 系统消息未读数 */
private Long system;
/** 运营消息未读数 */
private Long operation;
/** 订单消息未读数 */
private Long order;
}
@@ -0,0 +1,18 @@
package org.jiayunet.pojo.param.message;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.jiayunet.pojo.PageParam;
/**
* 消息分页查询入参
*
* @author zk
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class MessageQueryParam extends PageParam {
/** 消息类型筛选,null=全部 */
private Integer type;
}
@@ -0,0 +1,90 @@
package org.jiayunet.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jiayunet.mapper.MessageMapper;
import org.jiayunet.mapper.MessageReadMapper;
import org.jiayunet.pojo.PageResult;
import org.jiayunet.pojo.dto.message.MessageDto;
import org.jiayunet.pojo.dto.message.MessageUnreadCountDto;
import org.jiayunet.pojo.param.message.MessageQueryParam;
import org.jiayunet.pojo.po.Message;
import org.jiayunet.pojo.po.MessageRead;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* C端消息查询服务
* <p>提供用户消息分页列表和未读数查询</p>
* <p>依赖:MessageMapper、MessageReadMapper</p>
* <p>使用表:bg_message(查询消息)、bg_message_read(查询已读状态)</p>
*
* @author zk
*/
@Service
public class MessageQueryService {
@Autowired
private MessageMapper messageMapper;
@Autowired
private MessageReadMapper messageReadMapper;
/**
* 分页查询用户消息列表
* <p>1. 查询用户可见消息(指定用户+全员)分页 2. 批量查已读状态 3. 组装DTO返回</p>
*/
public PageResult<MessageDto> listMessages(MessageQueryParam param, Long userId) {
Page<Message> page = messageMapper.selectPage(param.toPage(), new LambdaQueryWrapper<Message>()
.and(w -> w.eq(Message::getUserId, userId).or().eq(Message::getTargetType, 2))
.eq(param.getType() != null, Message::getType, param.getType()).orderByDesc(Message::getCreateTime));
List<Long> messageIds = page.getRecords().stream().map(Message::getId).collect(Collectors.toList());
// 批量查已读状态
Set<Long> readIds = messageIds.isEmpty() ? Set.of() : messageReadMapper.selectList(new LambdaQueryWrapper<MessageRead>().eq(MessageRead::getUserId, userId).in(MessageRead::getMessageId, messageIds)).stream().map(MessageRead::getMessageId).collect(Collectors.toSet());
List<MessageDto> dtoList = page.getRecords().stream().map(msg -> {
MessageDto dto = new MessageDto();
BeanUtils.copyProperties(msg, dto);
dto.setRead(readIds.contains(msg.getId()));
return dto;
}).collect(Collectors.toList());
return new PageResult<>(page.getCurrent(), page.getSize(), page.getTotal(), dtoList);
}
/**
* 查询未读消息数
*/
public Long countUnread(Long userId) {
Long totalCount = messageMapper.selectCount(new LambdaQueryWrapper<Message>().and(w -> w.eq(Message::getUserId, userId).or().eq(Message::getTargetType, 2)));
Long readCount = messageReadMapper.selectCount(new LambdaQueryWrapper<MessageRead>().eq(MessageRead::getUserId, userId));
return Math.max(0, totalCount - readCount);
}
/**
* 按类型查询未读消息数
* <p>分别统计系统消息(1)、运营消息(2)、订单消息(3)的未读数量</p>
*/
public MessageUnreadCountDto countUnreadByType(Long userId) {
Set<Long> readIds = messageReadMapper.selectList(new LambdaQueryWrapper<MessageRead>().eq(MessageRead::getUserId, userId).select(MessageRead::getMessageId)).stream().map(MessageRead::getMessageId).collect(Collectors.toSet());
Map<Integer, Long> unreadMap = messageMapper.selectList(new LambdaQueryWrapper<Message>()
.and(w -> w.eq(Message::getUserId, userId).or().eq(Message::getTargetType, 2)).select(Message::getId, Message::getType))
.stream().filter(msg -> !readIds.contains(msg.getId())).collect(Collectors.groupingBy(Message::getType, Collectors.counting()));
MessageUnreadCountDto dto = new MessageUnreadCountDto();
dto.setSystem(unreadMap.getOrDefault(1, 0L));
dto.setOperation(unreadMap.getOrDefault(2, 0L));
dto.setOrder(unreadMap.getOrDefault(3, 0L));
dto.setTotal(dto.getSystem() + dto.getOperation() + dto.getOrder());
return dto;
}
}