完成进入会话消息自动已读

This commit is contained in:
KilLze
2026-01-07 00:47:38 +08:00
parent 1d179da910
commit 0bb69075f7
8 changed files with 132 additions and 34 deletions

View File

@@ -4,12 +4,15 @@ import com.bao.dating.common.Result;
import com.bao.dating.common.ResultCode; import com.bao.dating.common.ResultCode;
import com.bao.dating.common.result.PageResult; import com.bao.dating.common.result.PageResult;
import com.bao.dating.context.UserContext; import com.bao.dating.context.UserContext;
import com.bao.dating.pojo.dto.ChatCursorPageDTO;
import com.bao.dating.pojo.vo.ChatRecordsVO; import com.bao.dating.pojo.vo.ChatRecordsVO;
import com.bao.dating.service.ChatService; import com.bao.dating.service.ChatService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
/** /**
* 聊天控制器 * 聊天控制器
* @author lenovo * @author lenovo
@@ -24,16 +27,20 @@ public class ChatController {
/** /**
* 获取聊天记录 * 获取聊天记录
* @param targetUserId 目标用户ID * @param targetUserId 目标用户ID
* @param page 页码 * @param pageDTO 分页参数
* @param size 页大小 * @return 聊天记录列表
*/ */
@GetMapping("/history/{targetUserId}") @GetMapping("/history/{targetUserId}")
public Result<PageResult<ChatRecordsVO>> getChatHistory( public Result<List<ChatRecordsVO>> getChatHistory(
@PathVariable Long targetUserId, @PathVariable Long targetUserId,
@RequestParam(defaultValue = "1") Integer page, ChatCursorPageDTO pageDTO){
@RequestParam(defaultValue = "50") Integer size){
Long currentUserId = UserContext.getUserId(); Long currentUserId = UserContext.getUserId();
PageResult<ChatRecordsVO> history = chatService.getChatHistory(currentUserId, targetUserId, page, size); chatService.markChatMessagesAsRead(currentUserId, targetUserId);
List<ChatRecordsVO> history = chatService.getChatHistory(
currentUserId,
targetUserId,
pageDTO.getCursor(),
pageDTO.getSize());
return Result.success(ResultCode.SUCCESS, "获取聊天记录成功", history); return Result.success(ResultCode.SUCCESS, "获取聊天记录成功", history);
} }

View File

@@ -5,6 +5,7 @@ import com.bao.dating.pojo.entity.ChatRecords;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@Mapper @Mapper
@@ -17,8 +18,19 @@ public interface ChatRecordsMapper {
/** /**
* 根据用户ID和接收方用户ID查询聊天记录 * 根据用户ID和接收方用户ID查询聊天记录
*/ */
List<ChatRecords> selectChatWindowHistory( List<ChatRecords> selectChatHistoryByCursor(
@Param("currentUserId") Long currentUserId, @Param("currentUserId") Long currentUserId,
@Param("targetUserId") Long targetUserId @Param("targetUserId") Long targetUserId,
@Param("cursor") LocalDateTime cursor,
@Param("size") Integer size
);
/**
* 标记消息为已读
*/
int markMessagesAsRead(
@Param("senderUserId") Long senderUserId,
@Param("receiverUserId") Long receiverUserId,
@Param("readTime") LocalDateTime readTime
); );
} }

View File

@@ -36,4 +36,11 @@ public interface ChatSessionsMapper {
*/ */
int updateSessionForReceiver(ChatSessions chatSessions); int updateSessionForReceiver(ChatSessions chatSessions);
/**
* 清空会话未读数
*/
int clearUnreadCount(
@Param("userId") Long userId,
@Param("targetUserId") Long targetUserId
);
} }

View File

@@ -0,0 +1,21 @@
package com.bao.dating.pojo.dto;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class ChatCursorPageDTO {
/**
* 时间游标:最后一条消息的发送时间
*/
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime cursor;
/**
* 拉取条数
*/
private Integer size;
}

View File

@@ -4,6 +4,9 @@ import com.bao.dating.common.result.PageResult;
import com.bao.dating.pojo.dto.ChatRecordSendDTO; import com.bao.dating.pojo.dto.ChatRecordSendDTO;
import com.bao.dating.pojo.vo.ChatRecordsVO; import com.bao.dating.pojo.vo.ChatRecordsVO;
import java.time.LocalDateTime;
import java.util.List;
/** /**
* 聊天服务 * 聊天服务
* @author lenovo * @author lenovo
@@ -21,9 +24,17 @@ public interface ChatService {
* 获取聊天记录 * 获取聊天记录
* @param currentUserId 当前用户ID * @param currentUserId 当前用户ID
* @param targetUserId 目标用户ID * @param targetUserId 目标用户ID
* @param page 页码 * @param cursor 时间游标
* @param size 页大小 * @param size 页大小
* @return 聊天记录列表 * @return 聊天记录列表
*/ */
PageResult<ChatRecordsVO> getChatHistory(Long currentUserId, Long targetUserId, Integer page, Integer size); List<ChatRecordsVO> getChatHistory(Long currentUserId, Long targetUserId, LocalDateTime cursor, Integer size);
/**
* 标记聊天记录为已读
* @param currentUserId 当前用户ID
* @param targetUserId 目标用户ID
*/
void markChatMessagesAsRead(Long currentUserId, Long targetUserId);
} }

View File

@@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -116,36 +117,46 @@ public class ChatServiceImpl implements ChatService {
* @return 聊天记录列表 * @return 聊天记录列表
*/ */
@Override @Override
public PageResult<ChatRecordsVO> getChatHistory(Long currentUserId, Long targetUserId, Integer page, Integer size) { public List<ChatRecordsVO> getChatHistory(Long currentUserId, Long targetUserId, LocalDateTime cursor, Integer size) {
if (page == null || page < 1) {
page = 1;
}
if (size == null || size < 1 || size > 100) { if (size == null || size < 1 || size > 100) {
size = 50; size = 50;
} }
// 分页
PageHelper.startPage(page, size);
// 查询 // 查询
List<ChatRecords> recordsList = List<ChatRecords> records =
chatRecordsMapper.selectChatWindowHistory(currentUserId, targetUserId); chatRecordsMapper.selectChatHistoryByCursor(
currentUserId,
targetUserId,
cursor,
size
);
// 使用 PageInfo 封装查询结果 Collections.reverse(records);
PageInfo<ChatRecords> pageInfo = new PageInfo<>(recordsList);
// 转换为 VO return records.stream().map(record -> {
List<ChatRecordsVO> voList = recordsList.stream() ChatRecordsVO vo = new ChatRecordsVO();
.map(record -> { BeanUtils.copyProperties(record, vo);
ChatRecordsVO vo = new ChatRecordsVO(); return vo;
BeanUtils.copyProperties(record, vo); }).collect(Collectors.toList());
return vo; }
})
.collect(Collectors.toList());
// 使用 PageInfo 的信息创建 PageResult @Override
return new PageResult<>(pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPageSize(), voList); @Transactional(rollbackFor = Exception.class)
public void markChatMessagesAsRead(Long currentUserId, Long targetUserId) {
// 1. 更新 chat_records把对方发给我的未读消息设为已读
chatRecordsMapper.markMessagesAsRead(
targetUserId,
currentUserId,
LocalDateTime.now()
);
// 2. 更新 chat_sessions清空当前会话的未读数
chatSessionsMapper.clearUnreadCount(
currentUserId,
targetUserId
);
} }
} }

View File

@@ -32,18 +32,36 @@
</insert> </insert>
<!-- 根据两个用户ID查询聊天记录 (按发送时间倒序) - PageHelper 会自动处理分页 --> <!-- 根据两个用户ID查询聊天记录 (按发送时间倒序) - PageHelper 会自动处理分页 -->
<select id="selectChatWindowHistory" resultType="com.bao.dating.pojo.entity.ChatRecords"> <select id="selectChatHistoryByCursor" resultType="com.bao.dating.pojo.entity.ChatRecords">
SELECT SELECT
chat_id, sender_user_id, receiver_user_id, message_content, message_type, chat_id, sender_user_id, receiver_user_id, message_content, message_type,
read_status, read_time, send_time, message_status, created_at, updated_at read_status, read_time, send_time, message_status, created_at, updated_at
FROM chat_records FROM chat_records
WHERE WHERE
message_status = 1 message_status = 1
AND ( AND (
(sender_user_id = #{currentUserId} AND receiver_user_id = #{targetUserId}) (sender_user_id = #{currentUserId} AND receiver_user_id = #{targetUserId})
OR OR
(sender_user_id = #{targetUserId} AND receiver_user_id = #{currentUserId}) (sender_user_id = #{targetUserId} AND receiver_user_id = #{currentUserId})
) )
<if test="cursor != null">
AND send_time &lt; #{cursor}
</if>
ORDER BY send_time DESC ORDER BY send_time DESC
LIMIT #{size}
</select> </select>
<!-- 标记消息为已读 -->
<update id="markMessagesAsRead">
UPDATE chat_records
SET
read_status = 1,
read_time = #{readTime},
updated_at = NOW()
WHERE
sender_user_id = #{senderUserId}
AND receiver_user_id = #{receiverUserId}
AND read_status = 0
AND message_status = 1
</update>
</mapper> </mapper>

View File

@@ -59,4 +59,15 @@
AND target_user_id = #{targetUserId} AND target_user_id = #{targetUserId}
</update> </update>
<!-- 清空未读消息数 -->
<update id="clearUnreadCount">
UPDATE chat_sessions
SET
unread_count = 0,
updated_at = NOW()
WHERE
user_id = #{userId}
AND target_user_id = #{targetUserId}
AND session_status = 1
</update>
</mapper> </mapper>