Files
urbanLifeline/urbanLifelineServ/workcase/聊天室实现文档.md
2025-12-22 13:08:08 +08:00

10 KiB
Raw Blame History

聊天室实现文档

1. 业务规则

  • 一个工单只能创建一个聊天室,一个聊天室可以发起多次会议
  • 创建聊天室时自动添加来客和所有在线客服到成员表
  • 消息发送使用分布式锁保证时间戳递增,避免并发乱序

2. 核心文件结构

workcase/
├── src/main/java/org/xyzh/workcase/
│   ├── service/
│   │   ├── ChatRoomServiceImpl.java    # 聊天室服务实现
│   │   └── MeetServiceImpl.java        # 会议服务实现(伪代码)
│   ├── listener/
│   │   └── ChatMessageListener.java    # Redis消息监听器
│   ├── config/
│   │   ├── WebSocketConfig.java        # STOMP WebSocket配置
│   │   └── RedisSubscriberConfig.java  # Redis订阅配置
│   └── mapper/
│       ├── TbChatRoomMapper.java
│       ├── TbChatRoomMemberMapper.java
│       ├── TbChatMessageMapper.java
│       └── TbCustomerServiceMapper.java

apis/api-workcase/
├── src/main/java/org/xyzh/api/workcase/
│   ├── constant/
│   │   └── WorkcaseConstant.java       # 常量定义
│   ├── service/
│   │   ├── ChatRoomService.java        # 聊天室服务接口
│   │   └── MeetService.java            # 会议服务接口
│   ├── dto/
│   │   ├── TbChatRoomDTO.java
│   │   ├── TbChatRoomMemberDTO.java
│   │   └── TbChatMessageDTO.java
│   └── vo/
│       ├── ChatRoomVO.java
│       ├── ChatMemberVO.java
│       └── ChatMessageVO.java

3. Redis Key 设计

Key 说明 示例
chat:room:{roomId} 聊天室消息Pub/Sub频道 chat:room:abc123
chat:room:online:{roomId} 在线用户Set chat:room:online:abc123
chat:room:lock:{roomId} 消息发送锁 chat:room:lock:abc123
chat:room:lasttime:{roomId} 最后消息时间戳 chat:room:lasttime:abc123
chat:list:update 聊天室列表更新通知频道 chat:list:update

4. 消息流转架构

┌─────────────────────────────────────────────────────────────────┐
│                        消息发送流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  客户端 ──HTTP POST──> ChatRoomServiceImpl.sendMessage()        │
│                              │                                  │
│                              ▼                                  │
│                    ┌─────────────────┐                          │
│                    │ 获取分布式锁     │                          │
│                    │ chat:room:lock  │                          │
│                    └────────┬────────┘                          │
│                              │                                  │
│                              ▼                                  │
│                    ┌─────────────────┐                          │
│                    │ 递增时间戳保证   │                          │
│                    │ 消息顺序        │                          │
│                    └────────┬────────┘                          │
│                              │                                  │
│                              ▼                                  │
│                    ┌─────────────────┐                          │
│                    │ 保存到数据库     │                          │
│                    └────────┬────────┘                          │
│                              │                                  │
│                              ▼                                  │
│              redisService.publish("chat:room:{roomId}")         │
│                              │                                  │
│                              ▼                                  │
│              redisService.publish("chat:list:update")           │
│                              │                                  │
└──────────────────────────────┼──────────────────────────────────┘
                               │
┌──────────────────────────────┼──────────────────────────────────┐
│                        消息接收流程                              │
├──────────────────────────────┼──────────────────────────────────┤
│                              │                                  │
│       RedisSubscriberConfig (订阅 chat:room:*, chat:list:update)│
│                              │                                  │
│                              ▼                                  │
│              ChatMessageListener.onMessage()                    │
│                         ┌────┴────┐                             │
│                         │         │                             │
│                         ▼         ▼                             │
│   /topic/chat/{roomId}     /topic/chat/list-update              │
│   (聊天窗口消息)            (聊天室列表更新)                      │
│         │                       │                               │
│         ▼                       ▼                               │
│   聊天窗口订阅者            列表页面订阅者                        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

5. 用户类型常量

常量 说明
USER_TYPE_GUEST guest 来客
USER_TYPE_STAFF staff 客服
USER_TYPE_AI ai AI助手

6. 状态常量

聊天室状态

常量 说明
ROOM_STATUS_ACTIVE active 活跃
ROOM_STATUS_CLOSED closed 已关闭

成员状态

常量 说明
MEMBER_STATUS_ACTIVE active 活跃
MEMBER_STATUS_LEFT left 已离开
MEMBER_STATUS_REMOVED removed 被移除

消息状态

常量 说明
MESSAGE_STATUS_SENT sent 已发送
MESSAGE_STATUS_RECALLED recalled 已撤回

7. 并发消息处理

// 获取分布式锁
String lockKey = WorkcaseConstant.REDIS_CHAT_LOCK + roomId;
redisService.setIfAbsent(lockKey, "1", 5);  // 5秒过期

// 保证时间戳递增
String timeKey = WorkcaseConstant.REDIS_CHAT_LASTTIME + roomId;
long lastTime = redisService.get(timeKey);
if (currentTime <= lastTime) {
    currentTime = lastTime + 1;
}
message.setSendTime(new Date(currentTime));
redisService.set(timeKey, currentTime);

// 释放锁
redisService.delete(lockKey);

8. 前端WebSocket连接示例

// 连接WebSocket
const socket = new SockJS('/ws/chat');
const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
    // 1. 订阅聊天室消息(聊天窗口使用)
    stompClient.subscribe('/topic/chat/' + roomId, (message) => {
        const chatMessage = JSON.parse(message.body);
        // 处理收到的消息,添加到聊天窗口
        console.log('收到消息:', chatMessage);
    });

    // 2. 订阅聊天室列表更新(列表页面使用)
    stompClient.subscribe('/topic/chat/list-update', (message) => {
        const chatMessage = JSON.parse(message.body);
        // 根据roomId更新对应聊天室的lastMessage和lastMessageTime
        updateChatRoomInList(chatMessage.roomId, {
            lastMessage: chatMessage.content,
            lastMessageTime: chatMessage.sendTime,
            senderName: chatMessage.senderName
        });
    });
});

// 断开连接
stompClient.disconnect();

9. API接口

ChatRoomService

方法 说明
createChatRoom(dto) 创建聊天室,自动添加来客和客服
updateChatRoom(dto) 更新聊天室信息
closeChatRoom(roomId, closedBy) 关闭聊天室
deleteChatRoom(roomId) 删除聊天室
getChatRoomById(roomId) 获取聊天室详情
getChatRoomPage(pageRequest) 分页查询聊天室
addChatRoomMember(member) 添加成员
removeChatRoomMember(memberId) 移除成员
sendMessage(message) 发送消息(含并发处理)
getChatMessagePage(pageRequest) 分页查询消息
assignCustomerService(roomId) 分配所有客服到聊天室

MeetService伪代码

方法 说明
createMeeting(dto) 创建会议
startMeeting(meetingId) 开始会议
endMeeting(meetingId) 结束会议
joinMeeting(participant) 参与者加入
leaveMeeting(participantId) 参与者离开
generateMeetingJoinUrl(...) 生成Jitsi加入链接
addTranscription(dto) 添加转录记录