Jelajahi Sumber

perf: 优化websocket连接

1. 文档引用添加左侧图片
2. 文档引用底部点击可打开
3. 优化websocket连接,处理错误
zhupei 1 tahun lalu
induk
melakukan
05b2d82eed

+ 102 - 15
src/components/DialogWrap.vue

@@ -131,7 +131,7 @@
             <section>
               <div v-for="(knowledge, knowledgeIndex) in item.reference" :key="knowledgeIndex">
                 <a-popover :title="knowledge.doc_name" position="left">
-                  <div>
+                  <div @click="openDocuementPage(knowledge)">
                     <span>{{ knowledgeIndex + 1 }}</span>
                     <span>{{ knowledge.doc_name }}</span>
                   </div>
@@ -268,13 +268,16 @@ export default defineComponent({
     let dialogIndex = dialogList.length;
     const dialogScroll = ref("");
     const dialogConfig = ref({});
+
     const scrollToEnd = async () => {
       await nextTick();
       if (dialogScroll.value) {
         dialogScroll.value.scrollTop = dialogScroll.value.scrollHeight;
       }
     };
+
     let answerInterval = null;
+
     const stopWriting = () => {
       window.clearInterval(answerInterval);
       emit("set-readonly", false);
@@ -286,21 +289,25 @@ export default defineComponent({
       scrollToEnd();
       dialogIndex += 1;
     };
+
     const addData = (data) => {
       dialogList.splice(dialogIndex, 1, data);
       randomKey.value = Math.random();
       scrollToEnd();
     };
+
     const saveAnswer = (index) => {
       if (!props.readonly) {
         menuList[index].save = !menuList[index].save;
       }
     };
+
     const openCapacity = (index) => {
       if (!props.readonly) {
         menuList[index].open = !menuList[index].open;
       }
     };
+
     const openDocument = (index, documentIndex) => {
       if (menuList[index].documentOpenIndex === documentIndex) {
         menuList[index].documentOpenIndex = -1;
@@ -324,11 +331,13 @@ export default defineComponent({
 
       }
     };
+
     const copyAnswer = (text) => {
       if (!props.readonly) {
         helper.copyText(text, "复制成功");
       }
     };
+
     const reQuestion = (text) => {
       if (!props.readonly) {
         setTimeout(() => {
@@ -336,9 +345,21 @@ export default defineComponent({
         }, 200);
       }
     };
+
     const goKnowledge = () => {
-      emit("go-document");
+      // emit("go-document");
     };
+    // 点击文档,打开新页面
+    const openDocuementPage = (knowledge) => {
+      const doc_name = knowledge.doc_name;
+      const doc_id =  knowledge.id;
+
+      const pdf_url = `http://192.168.20.119:11080/v1/document/get/${doc_id}`;
+
+      window.open(pdf_url);
+    }
+
+
     const addLoading = (data) => {
       const mockData = DOCUMENT_RESULT;
       data.capacity = {
@@ -393,6 +414,7 @@ export default defineComponent({
       helper.webSocket.close();
     });
 
+
     onMounted(() => {
       scrollToEnd();
       /**
@@ -400,20 +422,70 @@ export default defineComponent({
        * 答案中 引用图标(感叹号)点击时,浮层显示引用内容
        */
       applyRefferencePopover(props.list);
-      // 如果是智能数据,则拿缓存里的数据开启对话
-      if (helper.read("sendData") && helper.read("sendData").agent_id == 'basic_excel_talk') {
-        const data = helper.read("sendData");
-        helper.webSocket = ajax.message.create(helper.read("token"), data.agent_id, data.chat_id, props.type);
-        // 创建对话之后清空缓存
-        helper.write('sendData', {});
-      } else {
-        helper.webSocket = ajax.message.create(helper.read("token"), props.agentId, props.dialogId, props.type);
+
+
+      // socket 消息队列
+      let msg_list = [];
+
+      function createSocket(){
+        const token = helper.read("token");
+        // 如果是智能数据,则拿缓存里的数据开启对话
+        if (helper.read("sendData") && helper.read("sendData").agent_id == 'basic_excel_talk') {
+          const data = helper.read("sendData");
+
+          helper.webSocket = ajax.message.create(token, data.agent_id, data.chat_id, props.type);
+
+          // 创建对话之后清空缓存
+          helper.write('sendData', {});
+        } else {
+          helper.webSocket = ajax.message.create(token, props.agentId, props.dialogId, props.type);
+        }
+
+        // 监听socket开启事件
+        // 当socket开启后,遍历消息,并发送
+        helper.webSocket.onopen = function(event){
+          msg_list.forEach(item => {
+            helper.webSocket.send(item);
+          });
+
+          // 所有消息发送完成后,清空消息队列
+          msg_list = [];
+        }
+      }
+
+      // 发送socket数据
+      function sendSocketMsg(dt){
+        // 判断socket是否开启
+        // 如果开启,则直接发送,如果没有开启,则将数据推入消息队列 
+        if(helper.webSocket.readyState === 0){
+          msg_list.push(dt);
+        }
+        if(helper.webSocket.readyState === 1){
+          helper.webSocket.send(dt);
+        }
+        if(helper.webSocket.readyState === 2){
+          // 正在关闭
+        }
+        if(helper.webSocket.readyState === 3){
+          msg_list.push(dt);
+
+          // 已关闭: 重新开启socket
+          createSocket();
+        }
       }
 
+      // 创建socket链接
+      createSocket();
+
+      
+
       helper.webSocket.onmessage = (event) => {
         const { type, reference, step_message, files } = JSON.parse(event.data);
+
         let { message } = JSON.parse(event.data);
+
         if (!loadingData.value) return;
+
         if (type === "stream") {
           // 没解析完就一直loading
           if (step_message == '文件上传完成,开始解析') {
@@ -428,9 +500,11 @@ export default defineComponent({
             addData(loadingData.value);
           } else {
             answerData.value += step_message ? getHTML(step_message) + "</br>" : message
+
             if (answerData.value && !isLoaded.value) {
               answerLoaded();
             }
+
             addAnswer(loadingData.value);
           }
         }
@@ -463,26 +537,28 @@ export default defineComponent({
             if (image_url) {
               imageUrl.value = `http://${window.location.hostname}${port}${image_url}`
             }
+
             if (excel_url) {
               const file = {
                 file_url: `http://${window.location.hostname}${port}${excel_url}`,
                 file_name: `${excel_name}.xlsx` || '点击下载',
               }
+
               answerFile.value = file
             }
+
             if (code) answerCode.value = getHTML(code);
-            if (sql) answerSql.value = getHTML(sql);
 
+            if (sql) answerSql.value = getHTML(sql);
           }
 
           if (answerData.value && !isLoaded.value) {
             answerLoaded();
           }
+
           addAnswer(loadingData.value);
         }
 
-
-
         if (type === "close") {
           if (!answerData.value) {
             answerLoaded();
@@ -494,6 +570,7 @@ export default defineComponent({
           isLoaded.value = false;
         }
       };
+
       helper.$bus.on("send-message", (value) => {
         dialogConfig.value = helper.dialogConfig;
         const question = props.type === "report" ? value.inputs.report_name : value;
@@ -505,18 +582,26 @@ export default defineComponent({
             : {
               message: value
             };
+
         if (props.type === 'doc') {
           sendData.doc_ids = [helper.read('docId')];
         }
-        helper.webSocket.send(JSON.stringify(sendData));
+
+        const dt = JSON.stringify(sendData);
+
+        // 发送socket数据
+        sendSocketMsg(dt)
       });
+
       helper.$bus.on("clear-message", () => {
         dialogList.splice(0);
       });
+
       helper.$bus.on("stop-writing", () => {
         stopWriting();
       });
     });
+
     return {
       goKnowledge,
       randomKey,
@@ -538,7 +623,9 @@ export default defineComponent({
       knowledgeList,
       dialogConfig,
       userName,
-      downloadFile
+      downloadFile,
+
+      openDocuementPage
     };
   }
 });

+ 1 - 1
src/components/pdf-viewer/PDFViewer.vue

@@ -148,7 +148,7 @@ onMounted(() => {
                 });
             }
 
-            box.value.appendChild(canvas);
+            box.value && box.value.appendChild(canvas);
         }
 
         // 所有页面都加载完毕,结束加载状态

+ 40 - 0
src/components/refference-effect/AsideImage.vue

@@ -0,0 +1,40 @@
+<template>
+    <a-popover>
+        <div class="image-aisde-btn-container">
+            <img :src="src" class="image-aside-btn" />
+        </div>
+        
+        <template #content>
+            <img :src="src" class="image-large-view" />
+        </template>
+    </a-popover>
+</template>
+<script setup>
+import {ref, computed} from 'vue';
+
+const props = defineProps({
+    src: String
+});
+</script>
+
+<style scoped>
+.image-aisde-btn-container{
+    width: 120px;
+    max-height: 120px;
+    flex-shrink: 0;
+    overflow: hidden;
+
+    margin-right: 5px;
+}
+
+.image-aside-btn{
+    width: 120px;
+    max-height: 120px;
+
+}
+
+.image-large-view{
+    max-width: 540px;
+    max-height: 540px;
+}
+</style>

+ 27 - 4
src/components/refference-effect/RefferenceFlag.vue

@@ -5,11 +5,18 @@
 
             <template #title></template>
             <template #content>
-                <div class="ref-text-content">
-                    {{text}}
-                </div>
+                <div class="refference-content">
+                    <AsideImage :src="img_url"/>
+
+                    <div class="refference-description">
+                        <div class="ref-text-content">
+                            {{text}}
+                        </div>
 
-                <FileNameDisplay @click="handleClick" :file_name="doc_name" :file_id="doc_id" />
+                        <FileNameDisplay @click="handleClick" :file_name="doc_name" :file_id="doc_id" />
+                    </div>
+                </div>
+                
             </template>
         </a-popover>
 
@@ -27,6 +34,7 @@ import { defineComponent, inject, ref, useTemplateRef } from "vue";
 
 import PDFViewer from '../pdf-viewer/PDFViewer.vue';
 
+import AsideImage from './AsideImage.vue';
 import FileNameDisplay from '../file/FileNameDisplay.vue';
 
 /**
@@ -36,6 +44,7 @@ import FileNameDisplay from '../file/FileNameDisplay.vue';
 
 const props = defineProps({
     img: String, // 图片链接
+    image_id: String,
     text: String, // 文本地址
     doc_id: String,
     doc_name: String,
@@ -47,6 +56,11 @@ const DOC_WIDTH = window.innerWidth/2;
 
 // http://192.168.20.119:11080/v1/document/get/
 const pdf_url = ref(`http://192.168.20.119:11080/v1/document/get/${props.doc_id}`);
+const img_url = ref(`http://192.168.20.119:11080/v1/document/image/${props.image_id}`);
+
+console.log(props.image_id, '图片ID');
+
+// /v1/document/image/81b160609be811ef9da00242ac160006-0841c05bca1ef27bfc98711406e4e6d9
 
 const visible = ref(false);
 
@@ -68,6 +82,15 @@ const handleCancel = () => {
 </script>
 
 <style scoped>
+.refference-content{
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+}
+.refference-description{
+    flex-grow: 1;
+}
+
 .ref-text-content{
     max-width: 460px;
     max-height: 340px;

+ 2 - 1
src/components/refference-effect/RefferenceRoot.vue

@@ -1,5 +1,5 @@
 <template>
-    <RefferenceFlag :img="img" :text="text" :doc_id="doc_id" :doc_name="doc_name" :positions="positions"/>
+    <RefferenceFlag :img="img" :text="text" :doc_id="doc_id" :doc_name="doc_name" :positions="positions" :image_id="image_id"/>
 </template>
 
 <script setup>
@@ -7,6 +7,7 @@ import RefferenceFlag from './RefferenceFlag.vue'
 
 const props = defineProps({
     img: String, // 图片链接
+    image_id: String,
     text: String, // 文本地址
     doc_id: String,
     doc_name: String,

+ 1 - 0
src/components/refference-effect/refference-flag.js

@@ -28,6 +28,7 @@ export default function dynamicRegRefFlag(mount_element, propsObject = {}) {
      */
     const app = createApp(RefferenceRoot, {
         img: propsObject.refference.img_id || '',
+        image_id: propsObject.refference.img_id,
         text: propsObject.refference.content_with_weight || '',
         doc_id: propsObject.refference.doc_id,
         doc_name: propsObject.refference.docnm_kwd,

+ 6 - 1
src/views/Home.vue

@@ -65,6 +65,7 @@
                     <span>{{ item.variable_name }}</span>
                   </p>
                 </div>
+
                 <div>
                   <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`" allow-clear @change="(event) => {
                     customChange(event, item.node_id, item.variable_name);
@@ -313,10 +314,14 @@ export default defineComponent({
           });
         }
       }
+      
       // 如果不是历史记录对话模式,则创建对话
       if (!historyMode.value) {
         const data = await ajax.message.createDialog(selectId.value);
-        dialogId.value = data.chat_id;
+
+        if(data){
+          dialogId.value = data.chat_id;
+        }
       }
       dialogList.value = [];
       showDialog.value = true;