feat(ai-chat): 实现AI聊天对话与会话消息记录功能

新增AI聊天对话接口和会话消息记录查询接口,支持SSE流式响应处理。
在sendMessage组件中集成真实SE调用逻辑,替换原有模拟实现,
并完善conversationId的获取与保存机制。新增sseHelper工具类用于统一处理SSE连接和数据解析。
This commit is contained in:
陈昱达
2025-09-24 14:26:37 +08:00
parent be411ec72d
commit 483b57f667
4 changed files with 128 additions and 139 deletions

View File

@@ -19,7 +19,7 @@
</template>
<script>
// import { aiChat } from '@/api/boe/aiChat.js'
import { aiChat } from '@/api/boe/aiChat.js'
export default {
name: 'SendMessage',
@@ -55,7 +55,7 @@ export default {
methods: {
handleSend() {
if (!this.inputContent.trim() || this.disabled) return
console.log(1);
// 添加用户消息到列表
const userMessage = {
isBot: false,
@@ -73,128 +73,7 @@ export default {
this.inputContent = ''
},
// 调用AI聊天接口
callAIChat(question) {
// 创建新的AI消息对象
const aiMessage = {
isBot: true,
text: '',
thinkText: '',
caseRefers: [], // 添加caseRefers字段
textCompleted: false // 添加文字处理完成状态默认为false
};
this.messageList.push(aiMessage);
// 模拟SSE流式响应
this.simulateSSE(question, aiMessage);
},
// 模拟SSE流式响应
simulateSSE(question, aiMessage) {
// 模拟AI思考过程包含think标签内容
const fullResponse =
"<think>" +
"让我思考一下如何更好地回答用户的问题。首先需要分析问题的关键点,然后查找相关的知识库内容。\n" +
"用户询问的是关于" + question + "的问题,我需要提供准确且有用的信息。\n" +
"</think>" +
"正在分析问题:" + question + "\n" +
"检索相关案例...\n" +
"匹配最佳解决方案...\n" +
"您好,我已经收到您的问题:\"" + question + "\"。\n" +
"正在分析相关内容...\n" +
"根据我的知识库,我为您提供以下解答:\n" +
"首先,我们需要了解问题的背景和关键点。\n" +
"在这个案例中,我们可以采用以下步骤来解决:\n" +
"1. 确认问题的具体表现和影响范围\n" +
"2. 分析可能的原因和影响因素\n" +
"3. 制定针对性的解决方案\n" +
"4. 实施并验证解决方案的有效性\n" +
"如果您还有其他相关问题,欢迎继续提问!";
let index = 0;
let inThinkTag = false;
let thinkContent = '';
let mainContent = '';
this.suggestions = [1,2,3]
this.$emit('update-suggestions', [1,2,3]);
// 模拟打字机效果
const typeNextCharacter = () => {
if (index < fullResponse.length) {
const char = fullResponse.charAt(index);
// 处理<think>标签
if (fullResponse.substring(index, index + 7) === '<think>') {
inThinkTag = true;
index += 7; // 跳过<think>标签
setTimeout(typeNextCharacter, 10);
return;
}
// 处理</think>标签
if (fullResponse.substring(index, index + 8) === '</think>') {
inThinkTag = false;
aiMessage.thinkText = thinkContent;
index += 8; // 跳过</think>标签
// 更新父组件的messageList
this.$emit('update-message', aiMessage);
setTimeout(typeNextCharacter, 10);
return;
}
// 根据当前状态添加字符
if (inThinkTag) {
thinkContent += char;
aiMessage.thinkText = thinkContent;
} else {
mainContent += char;
aiMessage.text = mainContent;
}
index++;
setTimeout(typeNextCharacter, 30);
// 实时更新父组件的messageList
this.$emit('update-message', aiMessage);
} else {
// 设置文字处理完成状态为true
aiMessage.textCompleted = true;
// 模拟status 0的caseRefers数据
// 在消息完成后添加引用案例
setTimeout(() => {
aiMessage.caseRefers = [
{
caseId: "case_001",
title: "案例1标题",
authorName: "张三",
keywords: ["关键词1", "关键词2"],
content: "这是案例1的内容摘要..."
},
{
caseId: "case_002",
title: "案例2标题",
authorName: "李四",
keywords: ["关键词3", "关键词4"],
content: "这是案例2的内容摘要..."
}
];
this.$emit('update-message', aiMessage);
}, 500);
// 所有内容完成
this.$emit('loading', false);
}
};
// 开始打字机效果
setTimeout(typeNextCharacter, 100);
},
/*
// 真实的SSE实现暂时注释掉
callAIChat(question) {
// 创建新的AI消息对象
@@ -213,19 +92,8 @@ export default {
query: question
};
// 使用fetch API处理SSE
const url = process.env.VUE_APP_BOE_BASE_API + '/xboe/m/boe/case/ai/chat';
const token = this.$store.getters.token;
// 创建POST请求
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
[this.$ajax.tokenName]: token
},
body: JSON.stringify(requestData)
}).then(response => {
aiChat(requestData).then(response => {
// 处理流式响应
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
@@ -266,6 +134,10 @@ export default {
// 更新父组件的messageList
this.$emit('update-message', aiMessage);
}
// 从响应中获取并保存conversationId
if (jsonData.data.conversationId) {
this.conversationId = jsonData.data.conversationId;
}
break;
case 1: // 流式对话内容
@@ -296,6 +168,10 @@ export default {
aiMessage.textCompleted = true;
// 更新父组件的messageList
this.$emit('update-message', aiMessage);
// 从响应中获取并保存conversationId
if (jsonData.data.conversationId) {
this.conversationId = jsonData.data.conversationId;
}
break;
case 3: // 返回建议
@@ -305,6 +181,10 @@ export default {
break;
case 4: // 交互完成
// 从响应中获取并保存conversationId
if (jsonData.data.conversationId) {
this.conversationId = jsonData.data.conversationId;
}
this.$emit('loading', false);
break;
}
@@ -339,7 +219,6 @@ export default {
this.$emit('update-message', aiMessage);
});
},
*/
handleNewConversation() {
this.$emit('new-conversation')
}