创建ChatRoom同步AI数据

This commit is contained in:
2025-12-23 17:31:34 +08:00
parent d2e141f17c
commit d3ef2f0d60
3 changed files with 135 additions and 40 deletions

View File

@@ -73,7 +73,7 @@ public class ChatController {
} }
} }
log.info("创建会话: agentId={}, title={}, userId={}, userType={}", chat.getAgentId(), chat.getTitle(), chat.getUserId()); log.info("创建会话: agentId={}, title={}, userId={}, userType={}", chat.getAgentId(), chat.getTitle(), chat.getUserId(), chat.getUserType());
return chatService.createChat(chat); return chatService.createChat(chat);
} }

View File

@@ -3,6 +3,7 @@ package org.xyzh.workcase.service;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -18,11 +19,15 @@ import org.xyzh.api.workcase.vo.ChatMemberVO;
import org.xyzh.api.workcase.vo.ChatRoomMessageVO; import org.xyzh.api.workcase.vo.ChatRoomMessageVO;
import org.xyzh.api.workcase.vo.ChatRoomVO; import org.xyzh.api.workcase.vo.ChatRoomVO;
import org.xyzh.api.workcase.vo.CustomerServiceVO; import org.xyzh.api.workcase.vo.CustomerServiceVO;
import org.xyzh.api.ai.dto.TbChat;
import org.xyzh.api.ai.dto.TbChatMessage;
import org.xyzh.api.ai.service.AgentChatService;
import org.xyzh.api.workcase.constant.WorkcaseConstant; import org.xyzh.api.workcase.constant.WorkcaseConstant;
import org.xyzh.common.core.domain.ResultDomain; import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain; import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam; import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.core.page.PageRequest; import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.utils.NonUtils;
import org.xyzh.common.utils.id.IdUtil; import org.xyzh.common.utils.id.IdUtil;
import org.xyzh.workcase.mapper.TbChatMessageMapper; import org.xyzh.workcase.mapper.TbChatMessageMapper;
import org.xyzh.workcase.mapper.TbChatRoomMapper; import org.xyzh.workcase.mapper.TbChatRoomMapper;
@@ -56,6 +61,9 @@ public class ChatRoomServiceImpl implements ChatRoomService {
@Autowired @Autowired
private RedisService redisService; private RedisService redisService;
@DubboReference(version = "1.0.0", group = "ai", timeout = 30000, retries = 0)
private AgentChatService agentChatService;
// ========================= 聊天室管理 ========================== // ========================= 聊天室管理 ==========================
@Override @Override
@@ -112,6 +120,10 @@ public class ChatRoomServiceImpl implements ChatRoomService {
updateRoom.setCurrentAgentId(assignResult.getData().getUserId()); updateRoom.setCurrentAgentId(assignResult.getData().getUserId());
chatRoomMapper.updateChatRoom(updateRoom); chatRoomMapper.updateChatRoom(updateRoom);
} }
// 从AI同步对话历史
if(NonUtils.isNotEmpty(chatRoom.getAiSessionId())){
syncAiChatMessages(chatRoom);
}
return ResultDomain.success("创建成功", chatRoom); return ResultDomain.success("创建成功", chatRoom);
} }
@@ -607,6 +619,87 @@ public class ChatRoomServiceImpl implements ChatRoomService {
// ========================= 私有方法 ========================== // ========================= 私有方法 ==========================
/**
* 从AI同步对话历史到聊天室
* @param chatRoom 聊天室信息包含aiSessionId和guestId
*/
private void syncAiChatMessages(TbChatRoomDTO chatRoom) {
try {
// 1. 构建查询条件获取AI对话消息列表
TbChat filter = new TbChat();
filter.setChatId(chatRoom.getAiSessionId());
filter.setUserId(chatRoom.getGuestId());
filter.setUserType(false); // 来客
ResultDomain<TbChatMessage> result = agentChatService.getChatMessageList(filter);
if (!Boolean.TRUE.equals(result.getSuccess()) || result.getDataList() == null) {
logger.warn("获取AI对话消息失败: aiSessionId={}, message={}",
chatRoom.getAiSessionId(), result.getMessage());
return;
}
List<TbChatMessage> aiMessages = result.getDataList();
if (aiMessages.isEmpty()) {
logger.info("AI对话消息为空: aiSessionId={}", chatRoom.getAiSessionId());
return;
}
// 2. 转换并存入聊天室消息表
int syncCount = 0;
long baseTime = System.currentTimeMillis() - aiMessages.size() * 1000L; // 保持消息顺序
for (int i = 0; i < aiMessages.size(); i++) {
TbChatMessage aiMsg = aiMessages.get(i);
TbChatRoomMessageDTO roomMsg = new TbChatRoomMessageDTO();
roomMsg.setMessageId(IdUtil.generateUUID());
roomMsg.setOptsn(IdUtil.getOptsn());
roomMsg.setRoomId(chatRoom.getRoomId());
roomMsg.setContent(aiMsg.getContent());
roomMsg.setMessageType("text");
roomMsg.setStatus("sent");
roomMsg.setFiles(aiMsg.getFiles());
roomMsg.setSendTime(new Date(baseTime + i * 1000L));
roomMsg.setIsAiMessage(true);
roomMsg.setAiMessageId(aiMsg.getMessageId());
roomMsg.setCreator(chatRoom.getGuestId());
// 根据角色设置发送者信息
if ("user".equals(aiMsg.getRole())) {
roomMsg.setSenderId(chatRoom.getGuestId());
roomMsg.setSenderName(chatRoom.getGuestName());
roomMsg.setSenderType("guest");
roomMsg.setIsAiMessage(false);
} else {
// AI回复
roomMsg.setSenderId("AI");
roomMsg.setSenderName("智能助手");
roomMsg.setSenderType("ai");
}
chatMessageMapper.insertChatMessage(roomMsg);
syncCount++;
}
// 3. 更新聊天室消息数和最后消息
if (syncCount > 0) {
TbChatMessage lastAiMsg = aiMessages.get(aiMessages.size() - 1);
TbChatRoomDTO updateRoom = new TbChatRoomDTO();
updateRoom.setRoomId(chatRoom.getRoomId());
updateRoom.setLastMessage(lastAiMsg.getContent());
updateRoom.setLastMessageTime(new Date());
updateRoom.setMessageCount(syncCount);
chatRoomMapper.updateChatRoom(updateRoom);
}
logger.info("AI对话同步完成: roomId={}, aiSessionId={}, syncCount={}",
chatRoom.getRoomId(), chatRoom.getAiSessionId(), syncCount);
} catch (Exception e) {
logger.error("同步AI对话失败: aiSessionId={}", chatRoom.getAiSessionId(), e);
}
}
private void publishMessageToRedis(TbChatRoomMessageDTO message) { private void publishMessageToRedis(TbChatRoomMessageDTO message) {
try { try {
String channel = WorkcaseConstant.REDIS_CHAT_PREFIX + message.getRoomId(); String channel = WorkcaseConstant.REDIS_CHAT_PREFIX + message.getRoomId();

View File

@@ -51,47 +51,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import type { ChatRoomVO } from '@/types/workcase' import { workcaseChatAPI } from '@/api'
import type { ChatRoomVO, TbChatRoomDTO, PageRequest } from '@/types'
// 导航栏 // 导航栏
const navPaddingTop = ref<number>(0) const navPaddingTop = ref<number>(0)
const navHeight = ref<number>(44) const navHeight = ref<number>(44)
const capsuleHeight = ref<number>(32) const capsuleHeight = ref<number>(32)
// 加载状态
const loading = ref<boolean>(false)
// 聊天室列表 // 聊天室列表
const chatRooms = ref<ChatRoomVO[]>([ const chatRooms = ref<ChatRoomVO[]>([])
{
roomId: 'room001',
roomName: '控制系统故障咨询',
guestId: '1',
guestName: '李经理',
status: 'active',
lastMessage: '好的,工程师会尽快联系您',
lastMessageTime: '2024-12-17 16:30:00',
unreadCount: 2,
workcaseId: 'TH20241217001'
},
{
roomId: 'room002',
roomName: '设备维修咨询',
guestId: '2',
guestName: '王工',
status: 'closed',
lastMessage: '问题已解决,感谢您的咨询',
lastMessageTime: '2024-12-16 14:20:00',
unreadCount: 0
},
{
roomId: 'room003',
roomName: '新设备安装咨询',
guestId: '3',
guestName: '张总',
status: 'waiting',
lastMessage: '您好,请问有什么可以帮助您的?',
lastMessageTime: '2024-12-17 10:15:00',
unreadCount: 0
}
])
// 生命周期 // 生命周期
onMounted(() => { onMounted(() => {
@@ -117,15 +89,45 @@ onMounted(() => {
}) })
// 加载聊天室列表 // 加载聊天室列表
function loadChatRooms() { async function loadChatRooms() {
console.log('加载聊天室列表') loading.value = true
// TODO: 调用 workcaseChatAPI.getChatRoomPage() 获取数据 try {
// 获取当前用户ID
const userId = uni.getStorageSync('userId') || ''
const pageRequest: PageRequest<TbChatRoomDTO> = {
filter: {
guestId: userId // 查询当前用户的聊天室
},
pageParam: {
pageNumber: 1,
pageSize: 50
}
} }
// 格式化时间 const res = await workcaseChatAPI.getChatRoomPage(pageRequest)
if (res.success && res.pageDomain?.dataList) {
chatRooms.value = res.pageDomain.dataList
}
} catch (error) {
console.error('加载聊天室列表失败:', error)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 格式化时间(兼容 iOS
function formatTime(time?: string): string { function formatTime(time?: string): string {
if (!time) return '' if (!time) return ''
const date = new Date(time) // iOS 不支持 "yyyy-MM-dd HH:mm:ss" 格式,需要转换为 "yyyy-MM-ddTHH:mm:ss"
const iosCompatibleTime = time.replace(' ', 'T')
const date = new Date(iosCompatibleTime)
if (isNaN(date.getTime())) return ''
const now = new Date() const now = new Date()
const diff = now.getTime() - date.getTime() const diff = now.getTime() - date.getTime()