|
@@ -15,7 +15,8 @@
|
|
|
<div class="message-avatar ai-avatar" v-else-if="message.role === 'assistant'">
|
|
<div class="message-avatar ai-avatar" v-else-if="message.role === 'assistant'">
|
|
|
<i class="el-icon-s-opportunity"></i>
|
|
<i class="el-icon-s-opportunity"></i>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="message-text" v-html="message.content">
|
|
|
|
|
|
|
+ <div class="message-text">
|
|
|
|
|
+ <div v-html="formatMessageContent(message.content)"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="message-completed" v-if="message.role === 'assistant' && message.completed">
|
|
<div class="message-completed" v-if="message.role === 'assistant' && message.completed">
|
|
|
<i class="el-icon-check"></i>
|
|
<i class="el-icon-check"></i>
|
|
@@ -51,7 +52,7 @@
|
|
|
<i class="el-icon-s-opportunity"></i>
|
|
<i class="el-icon-s-opportunity"></i>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="message-text">
|
|
<div class="message-text">
|
|
|
- <div v-html="currentStreamingText"></div>
|
|
|
|
|
|
|
+ <div v-html="formatMessageContent(currentStreamingText)"></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -97,7 +98,8 @@
|
|
|
<!-- <i class="el-icon-s-opportunity"></i> -->
|
|
<!-- <i class="el-icon-s-opportunity"></i> -->
|
|
|
<img src="@/assets/icons/ai.png" alt="Custom Icon" class="custom-icon">
|
|
<img src="@/assets/icons/ai.png" alt="Custom Icon" class="custom-icon">
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="message-text" v-html="message.content">
|
|
|
|
|
|
|
+ <div class="message-text">
|
|
|
|
|
+ <div v-html="formatMessageContent(message.content)"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="message-completed" v-if="message.role === 'assistant' && message.completed">
|
|
<div class="message-completed" v-if="message.role === 'assistant' && message.completed">
|
|
|
<i class="el-icon-check"></i>
|
|
<i class="el-icon-check"></i>
|
|
@@ -133,7 +135,7 @@
|
|
|
<img src="@/assets/icons/ai.png" alt="Custom Icon" class="custom-icon">
|
|
<img src="@/assets/icons/ai.png" alt="Custom Icon" class="custom-icon">
|
|
|
</div>
|
|
</div>
|
|
|
<div class="message-text">
|
|
<div class="message-text">
|
|
|
- <div v-html="currentStreamingText"></div>
|
|
|
|
|
|
|
+ <div v-html="formatMessageContent(currentStreamingText)"></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -294,49 +296,109 @@ export default {
|
|
|
const lines = buffer.split('\n');
|
|
const lines = buffer.split('\n');
|
|
|
buffer = lines.pop() || ''; // 最后一行可能不完整,保存到buffer
|
|
buffer = lines.pop() || ''; // 最后一行可能不完整,保存到buffer
|
|
|
|
|
|
|
|
- // 变量来跟踪当前事件类型和数据
|
|
|
|
|
- let currentEvent = 'agent_message'; // 默认为agent_message事件类型
|
|
|
|
|
- let currentData = '';
|
|
|
|
|
-
|
|
|
|
|
- for (let i = 0; i < lines.length; i++) {
|
|
|
|
|
- const line = lines[i].trim();
|
|
|
|
|
|
|
+ for (const line of lines) {
|
|
|
|
|
+ // 跳过完全空的行(SSE 协议中的分隔符)
|
|
|
|
|
+ if (line === '') continue;
|
|
|
|
|
|
|
|
- // 空行表示一个事件的结束
|
|
|
|
|
- if (line === '') {
|
|
|
|
|
- if (currentData) {
|
|
|
|
|
- // 如果有数据,处理当前事件
|
|
|
|
|
- this.handleEvent(currentEvent, currentData);
|
|
|
|
|
- currentData = '';
|
|
|
|
|
- }
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 事件类型行
|
|
|
|
|
|
|
+ // 解析 SSE 格式
|
|
|
if (line.startsWith('event:')) {
|
|
if (line.startsWith('event:')) {
|
|
|
- currentEvent = line.slice(6).trim();
|
|
|
|
|
|
|
+ // event: message - 忽略,只处理 data 行
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 数据行
|
|
|
|
|
if (line.startsWith('data:')) {
|
|
if (line.startsWith('data:')) {
|
|
|
- const dataContent = line.slice(5).trim();
|
|
|
|
|
- if (dataContent) {
|
|
|
|
|
- // 初始化或追加数据
|
|
|
|
|
- if (currentData) {
|
|
|
|
|
- currentData += '\n' + dataContent;
|
|
|
|
|
- } else {
|
|
|
|
|
- currentData = dataContent;
|
|
|
|
|
|
|
+ // 提取 data: 后面的内容
|
|
|
|
|
+ let data = line.substring(5).trim();
|
|
|
|
|
+
|
|
|
|
|
+ // 跳过 ping 事件
|
|
|
|
|
+ if (data === 'ping' || data.includes('"ping"')) continue;
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试解析 JSON 格式的数据
|
|
|
|
|
+ if (data.startsWith('{')) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const jsonData = JSON.parse(data);
|
|
|
|
|
+
|
|
|
|
|
+ // 调试日志:简化输出
|
|
|
|
|
+ console.log('解析JSON - event:', jsonData.event, 'answer长度:', jsonData.answer ? jsonData.answer.length : 0);
|
|
|
|
|
+
|
|
|
|
|
+ // 处理 MESSAGE_END 事件
|
|
|
|
|
+ if (jsonData.event === 'message_end' || jsonData.eventType === 'MESSAGE_END') {
|
|
|
|
|
+ console.log('收到 MESSAGE_END 事件,流式结束');
|
|
|
|
|
+ this.messageId = jsonData.message_id || jsonData.id;
|
|
|
|
|
+ this.finishStreaming();
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理包含 answer 字段的消息
|
|
|
|
|
+ if (jsonData.answer !== undefined && jsonData.answer !== null) {
|
|
|
|
|
+ this.messageId = jsonData.message_id || jsonData.id;
|
|
|
|
|
+ this.taskId = jsonData.task_id;
|
|
|
|
|
+
|
|
|
|
|
+ let answer = jsonData.answer.toString();
|
|
|
|
|
+
|
|
|
|
|
+ // 调试日志:查看 answer 内容
|
|
|
|
|
+ console.log('收到answer,长度:', answer.length, '前50字符:', answer.substring(0, Math.min(50, answer.length)));
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否包含完整的 Thinking 块(从开始到结束)
|
|
|
|
|
+ if (answer.includes('<details') && answer.includes('</details>')) {
|
|
|
|
|
+ console.log('检测到完整的Thinking块,提取后续内容');
|
|
|
|
|
+ const detailsEndIndex = answer.indexOf('</details>');
|
|
|
|
|
+ answer = answer.substring(detailsEndIndex + '</details>'.length);
|
|
|
|
|
+ this.isThinking = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 检查是否是 Thinking 开始
|
|
|
|
|
+ else if (answer.includes('<details') && answer.includes('<summary>')) {
|
|
|
|
|
+ console.log('检测到Thinking开始,跳过此块');
|
|
|
|
|
+ this.isThinking = true;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 检查是否是 Thinking 结束
|
|
|
|
|
+ else if (answer.includes('</details>')) {
|
|
|
|
|
+ console.log('检测到Thinking结束,提取后续内容');
|
|
|
|
|
+ const detailsEndIndex = answer.indexOf('</details>');
|
|
|
|
|
+ answer = answer.substring(detailsEndIndex + '</details>'.length);
|
|
|
|
|
+ this.isThinking = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果在 Thinking 模式中,跳过
|
|
|
|
|
+ if (this.isThinking) {
|
|
|
|
|
+ console.log('当前在Thinking模式,跳过');
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 普通消息内容,添加到队列
|
|
|
|
|
+ if (answer) {
|
|
|
|
|
+ console.log('添加到队列,长度:', answer.length);
|
|
|
|
|
+ this.messageQueue.push(answer);
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.isProcessingQueue) {
|
|
|
|
|
+ this.processMessageQueue();
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.log('answer为空,跳过');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('JSON解析错误:', e.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 非 JSON 格式的纯文本数据
|
|
|
|
|
+ console.log('纯文本数据,长度:', data.length);
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.isThinking) {
|
|
|
|
|
+ this.messageQueue.push(data);
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.isProcessingQueue) {
|
|
|
|
|
+ this.processMessageQueue();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- continue;
|
|
|
|
|
|
|
+ }else{
|
|
|
|
|
+ this.handleMessageData(line)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 处理缓冲区中可能剩余的完整事件
|
|
|
|
|
- if (currentData) {
|
|
|
|
|
- this.handleEvent(currentEvent, currentData);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// 继续读取流
|
|
// 继续读取流
|
|
|
readStream();
|
|
readStream();
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -360,29 +422,48 @@ export default {
|
|
|
this.finishStreaming();
|
|
this.finishStreaming();
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
|
|
+ // 处理消息数据(添加到队列)
|
|
|
|
|
+ handleMessageData(text) {
|
|
|
|
|
+ if (!text) return;
|
|
|
|
|
+ // 将文本按字符添加到队列
|
|
|
|
|
+ for (let char of text) {
|
|
|
|
|
+ this.messageQueue.push(char);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.isProcessingQueue) {
|
|
|
|
|
+ this.processMessageQueue();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
processMessageQueue() {
|
|
processMessageQueue() {
|
|
|
this.isProcessingQueue = true;
|
|
this.isProcessingQueue = true;
|
|
|
|
|
|
|
|
const processNextChunk = () => {
|
|
const processNextChunk = () => {
|
|
|
if (this.messageQueue.length > 0) {
|
|
if (this.messageQueue.length > 0) {
|
|
|
- // 每次只处理一小部分文本,以实现打字机效果
|
|
|
|
|
|
|
+ // 取出队列中的文本块
|
|
|
const chunk = this.messageQueue.shift();
|
|
const chunk = this.messageQueue.shift();
|
|
|
|
|
|
|
|
- // 处理内容 - 不需要类型检查,直接添加内容到当前流式文本
|
|
|
|
|
|
|
+ // 调试日志:查看队列中的数据
|
|
|
|
|
+ // console.log('处理队列数据,长度:', chunk.length, '内容预览:', chunk.substring(0, 50));
|
|
|
|
|
+
|
|
|
|
|
+ // 直接添加整个文本块到当前流式文本(保留换行符)
|
|
|
this.currentStreamingText += chunk;
|
|
this.currentStreamingText += chunk;
|
|
|
|
|
|
|
|
// 滚动到底部
|
|
// 滚动到底部
|
|
|
this.scrollToBottom();
|
|
this.scrollToBottom();
|
|
|
|
|
|
|
|
- // 使用setTimeout延迟处理下一个块,创造打字机效果
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- processNextChunk();
|
|
|
|
|
- }, 10); // 调整延迟时间可以控制打字速度
|
|
|
|
|
|
|
+ // 立即处理下一个块(不需要打字机效果的延迟)
|
|
|
|
|
+ if (this.messageQueue.length > 0) {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ processNextChunk();
|
|
|
|
|
+ }, 5); // 很短的延迟,只是为了不阻塞UI
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.isProcessingQueue = false;
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
this.isProcessingQueue = false;
|
|
this.isProcessingQueue = false;
|
|
|
|
|
+ // 检查是否有新数据到达
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
- if (this.messageQueue.length > 0) {
|
|
|
|
|
|
|
+ if (this.messageQueue.length > 0 && !this.isProcessingQueue) {
|
|
|
this.processMessageQueue();
|
|
this.processMessageQueue();
|
|
|
}
|
|
}
|
|
|
}, 20);
|
|
}, 20);
|
|
@@ -397,9 +478,21 @@ export default {
|
|
|
this.isStreaming = false;
|
|
this.isStreaming = false;
|
|
|
this.isThinking = false;
|
|
this.isThinking = false;
|
|
|
|
|
|
|
|
|
|
+ console.log('finishStreaming 被调用,队列长度:', this.messageQueue.length, '当前文本长度:', this.currentStreamingText.length);
|
|
|
|
|
+
|
|
|
|
|
+ // 先处理完队列中剩余的所有消息
|
|
|
|
|
+ if (this.messageQueue.length > 0) {
|
|
|
|
|
+ console.log('队列中还有数据,先处理完...');
|
|
|
|
|
+ const remainingText = this.messageQueue.join('');
|
|
|
|
|
+ this.currentStreamingText += remainingText;
|
|
|
|
|
+ this.messageQueue = [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 等待所有消息处理完毕
|
|
// 等待所有消息处理完毕
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
if (this.currentStreamingText) {
|
|
if (this.currentStreamingText) {
|
|
|
|
|
+ console.log('保存消息到历史记录,总长度:', this.currentStreamingText.length);
|
|
|
|
|
+
|
|
|
// 创建消息对象
|
|
// 创建消息对象
|
|
|
const assistantMessage = {
|
|
const assistantMessage = {
|
|
|
role: "assistant",
|
|
role: "assistant",
|
|
@@ -420,11 +513,12 @@ export default {
|
|
|
this.isLoading = false;
|
|
this.isLoading = false;
|
|
|
this.messageQueue = [];
|
|
this.messageQueue = [];
|
|
|
this.aiThought = "";
|
|
this.aiThought = "";
|
|
|
|
|
+ this.isProcessingQueue = false;
|
|
|
console.log("this.sessionId:结束",this.sessionId);
|
|
console.log("this.sessionId:结束",this.sessionId);
|
|
|
|
|
|
|
|
// 最终滚动到底部确保内容可见
|
|
// 最终滚动到底部确保内容可见
|
|
|
this.scrollToBottom();
|
|
this.scrollToBottom();
|
|
|
- }, 200); // 短暂延迟确保所有内容已处理完毕
|
|
|
|
|
|
|
+ }, 100); // 缩短延迟时间
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// 获取建议问题
|
|
// 获取建议问题
|
|
@@ -511,10 +605,23 @@ export default {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 处理空数据
|
|
|
|
|
+ if (!eventData || !eventData.trim()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
// 尝试解析JSON数据
|
|
// 尝试解析JSON数据
|
|
|
const data = JSON.parse(eventData);
|
|
const data = JSON.parse(eventData);
|
|
|
|
|
|
|
|
|
|
+ // 过滤掉 MESSAGE_END 等元数据事件
|
|
|
|
|
+ if (data.eventType === 'MESSAGE_END' || data.event === 'message_end') {
|
|
|
|
|
+ console.log('收到 MESSAGE_END 事件,流式结束');
|
|
|
|
|
+ this.messageId = data.id;
|
|
|
|
|
+ this.finishStreaming();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
switch (eventName) {
|
|
switch (eventName) {
|
|
|
case 'agent_message':
|
|
case 'agent_message':
|
|
|
// 处理agent_message事件
|
|
// 处理agent_message事件
|
|
@@ -523,7 +630,7 @@ export default {
|
|
|
this.messageId = data.id; // 保存消息ID
|
|
this.messageId = data.id; // 保存消息ID
|
|
|
this.taskId = data.task_id; // 保存任务ID用于停止响应
|
|
this.taskId = data.task_id; // 保存任务ID用于停止响应
|
|
|
const answer = data.answer.toString();
|
|
const answer = data.answer.toString();
|
|
|
- if (answer.trim()) {
|
|
|
|
|
|
|
+ if (answer) {
|
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
|
this.messageQueue.push(answer);
|
|
this.messageQueue.push(answer);
|
|
|
|
|
|
|
@@ -538,7 +645,7 @@ export default {
|
|
|
// 处理message事件
|
|
// 处理message事件
|
|
|
if (data && data.answer !== undefined) {
|
|
if (data && data.answer !== undefined) {
|
|
|
const answer = data.answer.toString();
|
|
const answer = data.answer.toString();
|
|
|
- if (answer.trim()) {
|
|
|
|
|
|
|
+ if (answer) {
|
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
|
this.messageQueue.push(answer);
|
|
this.messageQueue.push(answer);
|
|
|
|
|
|
|
@@ -546,37 +653,18 @@ export default {
|
|
|
this.processMessageQueue();
|
|
this.processMessageQueue();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } else if (data && data.eventType === 'MESSAGE_END') {
|
|
|
|
|
- console.log("Message end event received");
|
|
|
|
|
- this.finishStreaming();
|
|
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case 'message_end':
|
|
case 'message_end':
|
|
|
// 消息结束事件,完成流式处理
|
|
// 消息结束事件,完成流式处理
|
|
|
- // console.log("Message end event received:", data);
|
|
|
|
|
this.finishStreaming();
|
|
this.finishStreaming();
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case 'agent_thought':
|
|
case 'agent_thought':
|
|
|
// 处理思考过程
|
|
// 处理思考过程
|
|
|
if (data && data.thought && data.thought.trim() !== '') {
|
|
if (data && data.thought && data.thought.trim() !== '') {
|
|
|
- // console.log("AI思考:", data.thought);
|
|
|
|
|
-
|
|
|
|
|
- // 格式化思考内容,添加前缀
|
|
|
|
|
- // const formattedThought = `<strong>AI思考:</strong><br>${data.thought.replace(/\n/g, '<br>')}`;
|
|
|
|
|
-
|
|
|
|
|
- // 更新思考内容并显示思考状态
|
|
|
|
|
- // this.aiThought = formattedThought;
|
|
|
|
|
this.isThinking = true;
|
|
this.isThinking = true;
|
|
|
-
|
|
|
|
|
- // 确保滚动到可见区域
|
|
|
|
|
- // this.$nextTick(() => {
|
|
|
|
|
- // const thinkingElement = document.querySelector('.thinking-message');
|
|
|
|
|
- // if (thinkingElement) {
|
|
|
|
|
- // thinkingElement.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
|
|
|
|
- // }
|
|
|
|
|
- // });
|
|
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
@@ -596,7 +684,7 @@ export default {
|
|
|
// 其他事件类型,尝试提取answer字段
|
|
// 其他事件类型,尝试提取answer字段
|
|
|
if (data && data.answer !== undefined) {
|
|
if (data && data.answer !== undefined) {
|
|
|
const answer = data.answer.toString();
|
|
const answer = data.answer.toString();
|
|
|
- if (answer.trim()) {
|
|
|
|
|
|
|
+ if (answer) {
|
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
this.isThinking = false; // 收到回答,关闭思考状态
|
|
|
this.messageQueue.push(answer);
|
|
this.messageQueue.push(answer);
|
|
|
|
|
|
|
@@ -607,26 +695,28 @@ export default {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- // 如果解析JSON失败,尝试直接使用原始数据
|
|
|
|
|
- console.error("Error parsing event data:", error);
|
|
|
|
|
|
|
+ // 如果解析JSON失败,说明是纯文本数据
|
|
|
|
|
+ console.log("非JSON数据,直接处理:", eventData);
|
|
|
|
|
+
|
|
|
if (eventName === 'message_end') {
|
|
if (eventName === 'message_end') {
|
|
|
this.finishStreaming();
|
|
this.finishStreaming();
|
|
|
} else if (eventName === 'agent_thought') {
|
|
} else if (eventName === 'agent_thought') {
|
|
|
- // 尝试处理可能的非JSON格式的思考内容
|
|
|
|
|
- if (typeof eventData === 'string' && eventData.trim()) {
|
|
|
|
|
- this.aiThought = eventData;
|
|
|
|
|
|
|
+ // 思考内容,跳过显示
|
|
|
|
|
+ this.isThinking = true;
|
|
|
|
|
+ } else if (eventName !== 'error' && eventName !== 'ping') {
|
|
|
|
|
+ // 检查是否是 Thinking 内容(包含 <details> 标签)
|
|
|
|
|
+ if (eventData.includes('<details') && eventData.includes('<summary>')) {
|
|
|
|
|
+ // 跳过 Thinking 内容,不显示
|
|
|
this.isThinking = true;
|
|
this.isThinking = true;
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- } else if (eventName !== 'error') {
|
|
|
|
|
- // 非控制类事件,直接添加到消息队列
|
|
|
|
|
- if (typeof eventData === 'string' && eventData.trim()) {
|
|
|
|
|
- this.isThinking = false; // 收到回答,关闭思考状态
|
|
|
|
|
- // 将原始文本添加到队列
|
|
|
|
|
- this.messageQueue.push(eventData);
|
|
|
|
|
-
|
|
|
|
|
- if (!this.isProcessingQueue) {
|
|
|
|
|
- this.processMessageQueue();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 普通消息内容,直接添加到队列
|
|
|
|
|
+ this.isThinking = false;
|
|
|
|
|
+ this.messageQueue.push(eventData);
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.isProcessingQueue) {
|
|
|
|
|
+ this.processMessageQueue();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -661,6 +751,13 @@ export default {
|
|
|
handleSuggestionClick(suggestion) {
|
|
handleSuggestionClick(suggestion) {
|
|
|
this.userInput = suggestion;
|
|
this.userInput = suggestion;
|
|
|
// this.sendMessage();
|
|
// this.sendMessage();
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 格式化消息内容,将换行符转换为 <br> 标签
|
|
|
|
|
+ formatMessageContent(content) {
|
|
|
|
|
+ if (!content) return '';
|
|
|
|
|
+ // 将换行符转换为 <br> 标签
|
|
|
|
|
+ return content.replace(/\n/g, '<br>');
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|