update 客户端:根据当前用户邮箱查询聊天室 和查询七天内的记录 接口修改,新增用户邮箱参数

This commit is contained in:
yyb 2025-04-30 17:36:43 +08:00
parent 934be40c8b
commit bea674e93c
15 changed files with 99 additions and 55 deletions

View File

@ -34,6 +34,7 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Resource @Resource
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* 注册 Stomp的端点 可以注册多个端点 * 注册 Stomp的端点 可以注册多个端点
* addEndpoint添加STOMP协议的端点客户端访问地址 * addEndpoint添加STOMP协议的端点客户端访问地址

View File

@ -14,6 +14,7 @@ public enum ExceptionEnum {
MAX_LIMIT_CONNECT(1021, "服务器websocket连接数已达上限,服务器拒绝链接"), MAX_LIMIT_CONNECT(1021, "服务器websocket连接数已达上限,服务器拒绝链接"),
SET_PRINCIPAL_FAIL(1022, "websocket链接异常,用户身份设置失败"), SET_PRINCIPAL_FAIL(1022, "websocket链接异常,用户身份设置失败"),
GET_PRINCIPAL_FAIL(1023, "websocket链接异常,用户信息邮箱获取失败"), GET_PRINCIPAL_FAIL(1023, "websocket链接异常,用户信息邮箱获取失败"),
ACCOUNT_HAS_CONNECTED(1024, "当前登录用户在其他地方链接"),
; ;
private final int code; private final int code;

View File

@ -34,9 +34,8 @@ public class ChatMessageController {
@PostMapping("/find/recently/message") @PostMapping("/find/recently/message")
@ApiOperation(value = "查询七天内的记录", notes = "根据ID查询七天内的记录") @ApiOperation(value = "查询七天内的记录", notes = "根据ID查询七天内的记录")
@RequiresLogin
public R<List<ChatMessageDto>> findRecentlyMessage(@RequestBody MessagePageVo pageVo) { public R<List<ChatMessageDto>> findRecentlyMessage(@RequestBody MessagePageVo pageVo) {
return chatMessageService.findRecentlyMessage(pageVo.getId(), pageVo.getPageNum(), pageVo.getRoomId()); return chatMessageService.findRecentlyMessage(pageVo.getEmail(),pageVo.getId(), pageVo.getPageNum(), pageVo.getRoomId());
} }
@GetMapping("/delete/message") @GetMapping("/delete/message")

View File

@ -4,6 +4,7 @@ import com.m2pool.chat.dto.ChatRoomDto;
import com.m2pool.chat.service.ChatRoomService; import com.m2pool.chat.service.ChatRoomService;
import com.m2pool.chat.vo.CharRoomVo; import com.m2pool.chat.vo.CharRoomVo;
import com.m2pool.chat.vo.RoomPageVo; import com.m2pool.chat.vo.RoomPageVo;
import com.m2pool.chat.vo.RoomVo;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.web.page.TableDataInfo; import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.RequiresLogin; import com.m2pool.common.security.annotation.RequiresLogin;
@ -35,11 +36,10 @@ public class ChatRoomController {
return chatRoomService.findRoomList(roomPageVo); return chatRoomService.findRoomList(roomPageVo);
} }
@GetMapping("/find/room/by/userid") @PostMapping("/find/room/by/userid")
@ApiOperation(value = "客户端:根据当前用户邮箱查询聊天室") @ApiOperation(value = "客户端:根据当前用户邮箱查询聊天室")
@RequiresLogin public R<ChatRoomDto> findRoomByUserid(@RequestBody RoomVo roomVo) {
public R<ChatRoomDto> findRoomByUserid() { return chatRoomService.findRoomByUserid(roomVo);
return chatRoomService.findRoomByUserid();
} }

View File

@ -28,9 +28,9 @@ public class ChatRoomDto {
@ApiModelProperty(value = "聊天室id", example = "1") @ApiModelProperty(value = "聊天室id", example = "1")
private String id; private String id;
/** /**
* 聊天对象id * 聊天对象id一般为客服
*/ */
@ApiModelProperty(value = "聊天对象id", example = "1") @ApiModelProperty(value = "聊天对象id:一般为客服", example = "1")
private String userEmail; private String userEmail;
/** /**
* 聊天室重要程度 * 聊天室重要程度
@ -56,4 +56,10 @@ public class ChatRoomDto {
*/ */
@ApiModelProperty(value = "客服回复时间", example = "2025-10-01 12:32:01") @ApiModelProperty(value = "客服回复时间", example = "2025-10-01 12:32:01")
private LocalDateTime lastCustomerSendTime; private LocalDateTime lastCustomerSendTime;
/**
* 聊天发起者id 一般为游客或登录用户
*/
@ApiModelProperty(value = "聊天发起者id :一般为游客或登录用户", example = "1")
private String selfEmail;
} }

View File

@ -43,7 +43,6 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
*/ */
private static final ConcurrentHashMap<String,String> ipConnectionCountMap = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String,String> ipConnectionCountMap = new ConcurrentHashMap<>();
/** /**
* 当前链接数 * 当前链接数
*/ */
@ -56,7 +55,9 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
public WebsocketChannelInterceptor(CustomWebSocketConfig customWebSocketConfig, ApplicationEventPublisher applicationEventPublisher) {
public WebsocketChannelInterceptor(CustomWebSocketConfig customWebSocketConfig,
ApplicationEventPublisher applicationEventPublisher) {
this.customWebSocketConfig = customWebSocketConfig; this.customWebSocketConfig = customWebSocketConfig;
this.applicationEventPublisher = applicationEventPublisher; this.applicationEventPublisher = applicationEventPublisher;
} }
@ -128,11 +129,14 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
} }
//本次链接为登录用户,并且已经链接.直接拒绝本次链接(多用户登录) //本次链接为登录用户,并且已经链接.直接拒绝本次链接(多用户登录)
if ( type == LOGIN_USER ) { if ( type == LOGIN_USER ) {
if(email.equals(hasConnectionEmail) || ipConnectionCountMap.containsValue(email)){ if(email.equals(hasConnectionEmail) ){
// StompPrincipal principal = new StompPrincipal(email, type, true); // StompPrincipal principal = new StompPrincipal(email, type, true);
// applicationEventPublisher.publishEvent(new IpLimitEvent(this, principal)); // applicationEventPublisher.publishEvent(new IpLimitEvent(this, principal));
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT)); throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
} }
if(ipConnectionCountMap.containsValue(email)){
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.ACCOUNT_HAS_CONNECTED));
}
} }
ipConnectionCountMap.put(ipAddr,email); ipConnectionCountMap.put(ipAddr,email);

View File

@ -1,6 +1,11 @@
package com.m2pool.chat.listener; package com.m2pool.chat.listener;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.chat.entity.ChatRoom;
import com.m2pool.chat.entity.StompPrincipal; import com.m2pool.chat.entity.StompPrincipal;
import com.m2pool.chat.mapper.ChatMessageMapper;
import com.m2pool.chat.mapper.ChatRoomMapper;
import com.m2pool.chat.service.impl.StompServiceImpl; import com.m2pool.chat.service.impl.StompServiceImpl;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -26,6 +31,12 @@ public class WebSocketEventListener implements ApplicationListener<SessionDiscon
@Resource @Resource
private StompServiceImpl stompService; private StompServiceImpl stompService;
@Resource
private ChatRoomMapper chatRoomMapper;
@Resource
private ChatMessageMapper chatMessageMapper;
@Override @Override
public void onApplicationEvent(SessionDisconnectEvent event) { public void onApplicationEvent(SessionDisconnectEvent event) {
StompPrincipal user = (StompPrincipal) event.getUser(); StompPrincipal user = (StompPrincipal) event.getUser();
@ -35,7 +46,8 @@ public class WebSocketEventListener implements ApplicationListener<SessionDiscon
//游客断开链接通知客服删除游客聊天室 //游客断开链接通知客服删除游客聊天室
stompService.customerCloseRoom(user.getName()); stompService.customerCloseRoom(user.getName());
// 删除数据库中游客数据 // 删除数据库中游客数据
chatRoomMapper.delete(new LambdaUpdateWrapper<ChatRoom>().eq(ChatRoom::getUserOneEmail, user.getName()));
chatMessageMapper.delete(new LambdaUpdateWrapper<ChatMessage>().eq(ChatMessage::getSendEmail, user.getName()));
} }
} }
} }

View File

@ -19,12 +19,13 @@ public interface ChatMessageService{
/** /**
* 游标分页 查询7天内数据 * 游标分页 查询7天内数据
* @param email 用户邮箱
* @param id 游标 * @param id 游标
* @param pageNum 每页条数 * @param pageNum 每页条数
* @param roomId 聊天室id * @param roomId 聊天室id
* @return * @return
*/ */
R<List<ChatMessageDto>> findRecentlyMessage(Long id,Integer pageNum,Long roomId); R<List<ChatMessageDto>> findRecentlyMessage(String email,Long id,Integer pageNum,Long roomId);
/** /**

View File

@ -5,6 +5,7 @@ import com.m2pool.chat.dto.ChatRoomDto;
import com.m2pool.chat.entity.ChatRoom; import com.m2pool.chat.entity.ChatRoom;
import com.m2pool.chat.vo.CharRoomVo; import com.m2pool.chat.vo.CharRoomVo;
import com.m2pool.chat.vo.RoomPageVo; import com.m2pool.chat.vo.RoomPageVo;
import com.m2pool.chat.vo.RoomVo;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.web.page.TableDataInfo; import com.m2pool.common.core.web.page.TableDataInfo;
@ -21,7 +22,7 @@ public interface ChatRoomService extends IService<ChatRoom> {
* 根据当前用户邮箱查询聊天室 * 根据当前用户邮箱查询聊天室
* @return * @return
*/ */
R<ChatRoomDto> findRoomByUserid(); R<ChatRoomDto> findRoomByUserid(RoomVo roomVo);
/** /**
* 修改聊天室信息 * 修改聊天室信息

View File

@ -41,8 +41,7 @@ public class ChatMessageServiceImpl implements ChatMessageService {
} }
@Override @Override
public R<List<ChatMessageDto>> findRecentlyMessage(Long id,Integer pageNum,Long roomId) { public R<List<ChatMessageDto>> findRecentlyMessage(String email,Long id,Integer pageNum,Long roomId) {
String email = SecurityUtils.getUsername();
ChatMessage chatMessage = chatMessageMapper.selectById(id); ChatMessage chatMessage = chatMessageMapper.selectById(id);
List<ChatMessageDto> recentlyMessage; List<ChatMessageDto> recentlyMessage;
if(chatMessage != null){ if(chatMessage != null){

View File

@ -10,6 +10,7 @@ import com.m2pool.chat.mapper.ChatRoomMapper;
import com.m2pool.chat.service.ChatRoomService; import com.m2pool.chat.service.ChatRoomService;
import com.m2pool.chat.vo.CharRoomVo; import com.m2pool.chat.vo.CharRoomVo;
import com.m2pool.chat.vo.RoomPageVo; import com.m2pool.chat.vo.RoomPageVo;
import com.m2pool.chat.vo.RoomVo;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.constant.HttpStatus; import com.m2pool.common.core.constant.HttpStatus;
import com.m2pool.common.core.utils.PageUtils; import com.m2pool.common.core.utils.PageUtils;
@ -75,9 +76,9 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
@Override @Override
@Transactional @Transactional
public R<ChatRoomDto> findRoomByUserid() { public R<ChatRoomDto> findRoomByUserid(RoomVo roomVo) {
//1.查询当前用户与对应用户是否已存在创建的聊天室 //1.查询当前用户与对应用户是否已存在创建的聊天室
String userEmail = SecurityUtils.getUsername(); String userEmail = roomVo.getEmail();
ChatRoomDto roomByUserEmail = chatRoomMapper.findRoomByUserEmail(userEmail); ChatRoomDto roomByUserEmail = chatRoomMapper.findRoomByUserEmail(userEmail);
if(roomByUserEmail != null){ if(roomByUserEmail != null){
return R.success(roomByUserEmail); return R.success(roomByUserEmail);
@ -93,7 +94,7 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
ChatRoom build = ChatRoom.builder().userOneEmail(userEmail).userTwoEmail(sysUser.getEmail()).build(); ChatRoom build = ChatRoom.builder().userOneEmail(userEmail).userTwoEmail(sysUser.getEmail()).build();
int insert = chatRoomMapper.insert(build); int insert = chatRoomMapper.insert(build);
if (insert > 0){ if (insert > 0){
return R.success(ChatRoomDto.builder().id(String.valueOf(build.getId())).userEmail(build.getUserTwoEmail()).build()); return R.success(ChatRoomDto.builder().id(String.valueOf(build.getId())).selfEmail(userEmail).userEmail(build.getUserTwoEmail()).build());
} }
return R.fail("聊天室不存在,并且创建聊天室失败"); return R.fail("聊天室不存在,并且创建聊天室失败");
} }

View File

@ -1,5 +1,6 @@
package com.m2pool.chat.service.impl; package com.m2pool.chat.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.m2pool.chat.config.CustomWebSocketConfig; import com.m2pool.chat.config.CustomWebSocketConfig;
import com.m2pool.chat.constant.Destination; import com.m2pool.chat.constant.Destination;
import com.m2pool.chat.dto.WebsocketMessageDto; import com.m2pool.chat.dto.WebsocketMessageDto;
@ -10,7 +11,6 @@ import com.m2pool.chat.mapper.ChatMessageMapper;
import com.m2pool.chat.mapper.ChatRoomMapper; import com.m2pool.chat.mapper.ChatRoomMapper;
import com.m2pool.chat.service.StompService; import com.m2pool.chat.service.StompService;
import com.m2pool.chat.vo.UserMessageVo; import com.m2pool.chat.vo.UserMessageVo;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult; import com.m2pool.common.core.web.Result.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
@ -24,7 +24,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import static com.m2pool.chat.constant.UserType.*; import static com.m2pool.chat.constant.UserType.CUSTOMER;
@Service @Service
public class StompServiceImpl implements StompService { public class StompServiceImpl implements StompService {
@ -49,10 +49,6 @@ public class StompServiceImpl implements StompService {
@Override @Override
public AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo) { public AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo) {
if(StringUtils.isEmpty(userMessageVo.getEmail())){
userMessageVo.setEmail(webSocketConfig.getDefaultCustomerEmail());
}
userRegistry.getUsers().forEach(user -> System.out.println(user.getName()));
Boolean isCreate = principal.getIsCreate(); Boolean isCreate = principal.getIsCreate();
WebsocketMessageDto build = WebsocketMessageDto.builder() WebsocketMessageDto build = WebsocketMessageDto.builder()
.type(userMessageVo.getType()) .type(userMessageVo.getType())
@ -66,44 +62,45 @@ public class StompServiceImpl implements StompService {
if (isCreate){ if (isCreate){
principal.setIsCreate(false); principal.setIsCreate(false);
} }
//获取当前聊天室对象 //获取当前聊天室对象
ChatRoom chatRoom = chatRoomMapper.selectById(userMessageVo.getRoomId()); ChatRoom chatRoom;
if (chatRoom != null ){
build.setRoomId(String.valueOf(userMessageVo.getRoomId()));
if(LOGIN_USER.equals(principal.getType())){
build.setClientReadNum(chatRoom.getServiceReadNum() + 1);
}else {
build.setClientReadNum(chatRoom.getClientReadNum() + 1);
}
}else{ if(!CUSTOMER.equals(principal.getType())){
build.setRoomId(TOURIST.equals(userMessageVo.getType()) ? userMessageVo.getEmail() : principal.getName()); chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
.eq(ChatRoom::getUserOneEmail, principal.getName())
.eq(ChatRoom::getUserTwoEmail, userMessageVo.getEmail()));
build.setRoomId(String.valueOf(userMessageVo.getRoomId()));
build.setClientReadNum(chatRoom.getServiceReadNum() + 1);
}else {
chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
.eq(ChatRoom::getUserOneEmail, userMessageVo.getEmail())
.eq(ChatRoom::getUserTwoEmail, principal.getName()));
build.setRoomId(String.valueOf(userMessageVo.getRoomId()));
build.setClientReadNum(chatRoom.getClientReadNum() + 1);
} }
boolean bool = checkOnline(userMessageVo); boolean bool = checkOnline(userMessageVo);
//在线用户才发送消息 //在线用户才发送消息
if (bool){ if (bool){
messagingTemplate.convertAndSendToUser(userMessageVo.getEmail(), Destination.QUEUE + "/" + userMessageVo.getEmail(),build); messagingTemplate.convertAndSendToUser(userMessageVo.getEmail(), Destination.QUEUE + "/" + userMessageVo.getEmail(),build);
} }
// 接收者和发送者 都不是游客才能存储消息 和修改聊天室信息后续可改为消息中间件解耦形式 // 消息存储
if (!TOURIST.equals(userMessageVo.getReceiveUserType()) && !TOURIST.equals(principal.getType()) && chatRoom != null){ transactionTemplate.execute(new TransactionCallbackWithoutResult() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override
@Override protected void doInTransactionWithoutResult(TransactionStatus status) {
protected void doInTransactionWithoutResult(TransactionStatus status) { try {
try { // 插入消息并获取 ID
// 插入消息并获取 ID insertMessage(principal,userMessageVo);
insertMessage(principal,userMessageVo); //聊天室已读未读数量更新
//聊天室已读未读数量更新 updateRoom(chatRoom,principal.getType(),bool);
updateRoom(chatRoom,principal.getType(),bool); } catch (Exception e) {
} catch (Exception e) { // 回滚事务
// 回滚事务 status.setRollbackOnly();
status.setRollbackOnly(); throw e;
throw e;
}
} }
}); }
} });
//可以用void
return AjaxResult.success("成功"); return AjaxResult.success("成功");
} }

View File

@ -25,6 +25,10 @@ public class MessagePageVo {
@ApiModelProperty(value = "用户类型 0 游客 1 登录用户 2 客服", example = "1",required = true) @ApiModelProperty(value = "用户类型 0 游客 1 登录用户 2 客服", example = "1",required = true)
private Integer userType; private Integer userType;
@ApiModelProperty(value = "当前登录用户邮箱;游客就是生成的唯一id", example = "54544@qq.com",required = true)
private String email;
public MessagePageVo() { public MessagePageVo() {
this.pageNum = 20; this.pageNum = 20;
} }

View File

@ -0,0 +1,18 @@
package com.m2pool.chat.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName RoomVo
* @Description TODO
* @Author yyb
* @Date 2025/4/30 16:27
*/
@Data
@ApiModel(description = "根据用户邮箱查询聊天室")
public class RoomVo {
@ApiModelProperty(value = "当前登录用户邮箱;游客就是生成的唯一id", example = "54544@qq.com",required = true)
private String email;
}

View File

@ -30,7 +30,7 @@
</select> </select>
<select id="findRoomByUserEmail" resultType="com.m2pool.chat.dto.ChatRoomDto"> <select id="findRoomByUserEmail" resultType="com.m2pool.chat.dto.ChatRoomDto">
SELECT SELECT
id,client_read_num AS clientReadNum ,user_two_email AS userEmail id,client_read_num AS clientReadNum ,user_one_email AS selfEmail,user_two_email AS userEmail
FROM FROM
chat_room chat_room
WHERE WHERE