Просмотр исходного кода

feat: 将AI回答的内容流式展示每次展示一行直至全部展示

zhouyuhao 6 месяцев назад
Родитель
Сommit
fef061d961
1 измененных файлов с 26 добавлено и 2 удалено
  1. 26 2
      src/views/AIRobotChat/src/AIRobotChat.vue

+ 26 - 2
src/views/AIRobotChat/src/AIRobotChat.vue

@@ -59,6 +59,7 @@ interface MessageItem {
   isAnswer?: boolean // 是否为用户问题的答案,是则才能展示反馈组件
   isError?: boolean // 是否为错误消息
   isCancel?: boolean // 是否为取消消息
+  html?: string // 渲染后的HTML内容
 }
 const messages = ref<MessageItem[]>([
   {
@@ -96,6 +97,28 @@ const progressStatus = {
 
 const isShowTips = ref(false) // 是否展示提示信息
 
+const parseHtmlString = (data) => {
+  const lines = data.split('\n')
+
+  function streamMarkdown() {
+    const lastMsg: any = messages.value[messages.value.length - 1]
+    let index = 0
+    lastMsg.content = '' // 清空上一个消息的内容
+    const timer = setInterval(() => {
+      if (index < lines.length) {
+        lastMsg.content += lines[index] + '\n'
+        lastMsg.html = renderedMessage(lastMsg.content) // ✅ 每次整段渲染
+        index++
+        scrollToBottom() // 滚动到底部
+      } else {
+        clearInterval(timer)
+      }
+    }, 150)
+  }
+
+  streamMarkdown()
+}
+
 const progressInterval = ref()
 const serial_no = ref()
 const aiChat = (question, isPresetQuestion) => {
@@ -118,12 +141,13 @@ const aiChat = (question, isPresetQuestion) => {
         messages.value[messages.value.length - 1] = {
           id: serial_no.value,
           type: 'robot',
-          content: data,
+          content: '',
           feedback: '',
           isShowFeedback: false,
           isAnswer: true
         }
 
+        parseHtmlString(data)
         scrollToBottom()
         loadingAnswer.value = false
         queryTime.value = -1
@@ -320,7 +344,7 @@ defineExpose({
           alt=""
         />
         <div style="display: inline-block; max-width: 100%">
-          <div v-html="renderedMessage(msg.content)" class="markdown-body"></div>
+          <div v-html="msg.html || renderedMessage(msg.content)" class="markdown-body"></div>
         </div>
         <LoadingDots
           v-if="index === messages.length - 1 && msg.isAnswer && loadingAnswer"