完成进入会话消息自动已读
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/main/java/com/bao/dating/pojo/dto/ChatCursorPageDTO.java
Normal file
21
src/main/java/com/bao/dating/pojo/dto/ChatCursorPageDTO.java
Normal 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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 < #{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>
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user