From a4ca216c5b215f323b3c439b2f445dad72bbfce1 Mon Sep 17 00:00:00 2001 From: zhangxiao <898441624@qq.com> Date: 星期一, 26 八月 2024 16:44:31 +0800 Subject: [PATCH] fix: 修改bug --- src/views/sessionManager/index.vue | 465 ++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 273 insertions(+), 192 deletions(-) diff --git a/src/views/sessionManager/index.vue b/src/views/sessionManager/index.vue index 09650bd..d140f21 100644 --- a/src/views/sessionManager/index.vue +++ b/src/views/sessionManager/index.vue @@ -1,5 +1,5 @@ <template> - <div class="container"> + <div class="container" id="container"> <!-- <AddSession--> <!-- :modalObj="modalObj"--> <!-- @addSession="addSession"--> @@ -23,8 +23,16 @@ <!-- <span class="title">{{ agentTitle }}</span>--> <a-popover position="bottom" trigger="click"> - <a-button border - >{{ agentTitle }} + <a-button border> + <span + style=" + width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + " + >{{ from.name }}</span + > <icon-down style="margin-left: 4px" /> </a-button> <template #content> @@ -49,12 +57,13 @@ ref="scrollbar" id="home" class="chat-list" - style=" - width: 80%; - overflow: auto; - height: calc(100vh - 380px); - margin: 0px auto 20px; - " + style="width: 80%; overflow: auto; margin: 0px auto 20px" + :style="{ + height: + uploaditemList.length > 0 + ? 'calc(100vh - 480px)' + : 'calc(100vh - 380px)', + }" > <div class="chat-item" @@ -78,30 +87,68 @@ <template #avatar> <img class="icon-user-jpg" - src="../../assets/images/icon-chart.png" + src="../../assets/images/icon-picture.png" alt="鏈湴鍥剧墖" /> </template> <template #content> - <!-- <a-card :class="{ chatItemAnswer: theme === 'light' }">--> - <!-- <div--> - <!-- :class="{ light: theme === 'light' }"--> - <!-- v-html="sessionDetail.content.replace(/\n/g, '<br/>')"--> - <!-- >--> - <!-- </div>--> - <!-- </a-card>--> - <a-textarea - readonly - auto-size - v-model="sessionDetail.content" - :class="{ chatItemAnswer: theme === 'light' }" - :style="{ - backgroundColor: - theme === 'light' ? '#ffffff' : '#000000', - }" - style="border: none" - > - </a-textarea> + <a-card v-if="isExistTip(sessionDetail.content)"> + <div + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none; display: inline" + v-for="(item, tipIndex) in tipMatch(sessionDetail)" + > + <span v-if="tipIndex == 0"> + {{ sessionDetail.content.substring(0, item.index) }} + <a-tooltip + background-color="#3491FA" + :content=" + getTipContent(messagenList.reference, index) + " + > + <img + style="width: 20px; height: 20px" + :src="tipImage" + /> + </a-tooltip> + </span> + <span v-else> + {{ + sessionDetail.content.substring( + item.preIndex + item.item.length, + item.index + ) + }} + <a-tooltip + background-color="#3491FA" + :content=" + getTipContent(messagenList.reference, index) + " + > + <img + style="width: 20px; height: 20px" + :src="tipImage" + /> + </a-tooltip> + </span> + </div> + </a-card> + <a-card v-else> + <div + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + > + {{ sessionDetail.content }} + </div> + </a-card> </template> <!-- <div>{{ sessionDetail.role === 'assistant' }}</div> --> <template #actions> @@ -150,7 +197,7 @@ <template #avatar> <img class="icon-user-jpg" - src="../../assets/images/icon-chart.png" + src="../../assets/images/icon-picture.png" alt="鏈湴鍥剧墖" /> </template> @@ -213,7 +260,11 @@ v-model="inputMsg" @keydown.shift.enter="handleShiftEnter" @keydown.enter="sendMessage" - placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝Shift+Enter鎹㈣锛孍nter鍙戦��" + :placeholder=" + uploaditemList.length > 0 + ? '鏁寸悊杩欎簺鏂囦欢鐨勬牳蹇冨唴瀹�' + : '杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝Shift+Enter鎹㈣锛孍nter鍙戦��' + " allow-clear show-word-limit :disabled="chatDis" @@ -227,8 +278,18 @@ maxRows: 5, }" /> - - <div class="btn-send"> + <div + style=" + width: 100%; + display: flex; + justify-content: space-between; + " + > + <updataFile + ref="fileInput" + :sessionId="activeSessionId" + @selectFileCallback="selectFileCallback" + ></updataFile> <a-button :disabled="chatDis" @click="sentClick" @@ -240,54 +301,26 @@ </a-button> </div> </div> - <!-- <div style="margin-top: 0px">--> - <!-- <a-upload--> - <!-- ref="uploadRef"--> - <!-- :file-list="uploadList"--> - <!-- :limit="1"--> - <!-- multiple--> - <!-- :custom-request="customRequest"--> - <!-- style="font-size: 24px;margin-bottom: 10px;position: relative;width: 200px">--> - <!-- <template #upload-button>--> - <!-- <icon-attachment style="color: #0960bd;position: absolute;top:-50px;left: 20px;z-index: 10000"/>--> - <!-- </template>--> - <!-- </a-upload>--> - <!-- </div>--> - <span - style=" - position: absolute; - top: 94px; - left: 20px; - z-index: 999; - cursor: pointer; - " - > - <icon-attachment - size="28" - @click="selectFile" - style="color: #0960bd" - /> - <input - ref="fileInput" - type="file" - style="display: none" - @change="onFileSelected" - /> - </span> - <div class="uploadFileList"> + <div class="uploadFileList" v-if="uploaditemList.length > 0"> <div class="files" v-for="(item, index) in uploaditemList" :key="index" - style="position: relative; width: 200px; margin-top: 10px" + style=" + position: relative; + width: 200px; + margin-top: 10px; + margin-right: 20px; + " > <a-comment :author="item.name" - :content="item.size + ''" + :content="item.size" style=" background: var(--color-bg-2); padding: 10px; border-radius: 10px; + font-size: 12px; " > <template #avatar> @@ -300,9 +333,10 @@ </template> </a-spin> <!-- <a-button type="text" :loading="onFileSelectedLoading" v-if="onFileSelectedLoading"></a-button>--> - <a-avatar v-if="!onFileSelectedLoading"> - <icon-file style="color: #0960bd" /> - </a-avatar> + <!-- <a-avatar v-if="!onFileSelectedLoading">--> + <!-- <icon-file style="color: #0960bd" />--> + <!-- </a-avatar>--> + <img :src="getIconByExtension(item.name)" alt="" /> </template> </a-comment> <icon-close-circle-fill @@ -344,6 +378,12 @@ </div> </a-col> </a-row> + <a-modal title=" " v-model:visible="fileVisible" :footer="false" fullscreen> + <!-- <docx previewSrc="http://192.168.20.116:1080/v1/document/get/405c3efa4d8c11ef97560242ac120006"></docx>--> + <docx v-if="documenttype == 'docx'" :previewSrc="previewSrc"></docx> + <excel v-if="documenttype == 'excel'" :previewSrc="previewSrc"></excel> + <txtPdf v-if="documenttype == 'txtPdf'" :previewSrc="previewSrc"></txtPdf> + </a-modal> <a-modal v-model:visible="visible" title="淇敼鍚嶇О" @@ -352,14 +392,9 @@ :footer="false" title-align="start" > - <a-form - ref="formRef" - :rules="rules" - :model="chatObj" - @submit="handleSubmit" - > + <a-form ref="formRef" :rules="rules" :model="from" @submit="handleSubmit"> <a-form-item field="name" label="鍚嶇О"> - <a-input v-model="agentTitle" placeholder="璇疯緭鍏ュ悕绉�" /> + <a-input v-model="from.name" placeholder="璇疯緭鍏ュ悕绉�" /> </a-form-item> <a-form-item> <div style="width: 100%; text-align: right"> @@ -377,12 +412,7 @@ </div> </template> <script setup lang="ts"> - import { - IconClose, - IconSearch, - IconTiktokColor, - } from '@arco-design/web-vue/es/icon'; - import { useAppStore, useUserStore } from '@/store'; + import { useAppStore, userModelState, useUserStore } from '@/store'; import { computed, nextTick, @@ -402,7 +432,7 @@ import agentSession from '@/views/sessionManager/components/agentSession.vue'; import historySession from '@/views/sessionManager/components/historySession.vue'; import smartAi from '@/views/sessionManager/components/smartAi.vue'; - import setName from '@/views/sessionManager/components/setName.vue'; + import updataFile from '@/views/sessionManager/components/updataFile.vue'; import EventBus from '@/utils/EventBus'; import { addSessionApi, @@ -421,10 +451,20 @@ import pdfImg3 from '@/assets/session/execl.png'; import pdfImg4 from '@/assets/session/icon-txt.png'; import pdfImg5 from '@/assets/session/txt.png'; + import tipImage from '@/assets/session/tip.png'; + + import docx from '@/views/dmx/knowledgeLib/components/docx.vue'; + import excel from '@/views/dmx/knowledgeLib/components/excel.vue'; + import txtPdf from '@/views/dmx/knowledgeLib/components/txtPdf.vue'; // const url = ref('../../assets/session/PDF.png'); - const sessionDetailList = ref([]); //鏍规嵁浼氳瘽id鍑烘潵鐨勪細璇濊鎯� + const sessionDetailList = ref([ + { + content: '浣犲ソ锛� 鎴戞槸浣犵殑鍔╃悊锛屾湁浠�涔堝彲浠ュ府鍒颁綘鐨勫悧锛�', + role: 'assistant', + }, + ]); //鏍规嵁浼氳瘽id鍑烘潵鐨勪細璇濊鎯� const messagenList = ref({}); const sessionList = ref([]); //浼氳瘽鍒楄〃 const modalObj = reactive({ add: false }); @@ -434,6 +474,9 @@ const agentType = ref('1'); const agentTitle = ref('鏈懡鍚嶄細璇�'); let chatObj = reactive({}); + let from = reactive({ + name: '鏈懡鍚嶄細璇�', + }); const isStopChat = ref(false); const currIndex = ref(0); const displayedText = ref(''); // 姝e湪鏄剧ず鐨勬枃瀛� @@ -456,6 +499,13 @@ const fileInput = ref(null); const chatDataMeg = reactive({}); const visible = ref(false); + const fileVisible = ref(false); + let toStop = false; + let documenttype = ref('docx'); + let previewSrc = ref(''); + + const modelStore = userModelState(); + const httpUrl = modelStore.hrefUrl; const rules = { name: [ @@ -468,12 +518,10 @@ const handleSubmit = async ({ values, errors }) => { if (errors) return; - // chatObj.name = agentTitle.value; - // chatObj.conversation_id = chatObj.id; let chatData = { id: chatObj.id, conversation_id: chatObj.id, - name: agentTitle.value, + name: from.name, }; const { code, data } = await addSessionApi(chatData); if (data) { @@ -483,14 +531,31 @@ } }; let dataItem = []; + const isExistTip = (message: string): boolean => { + if (/##[0-9]\$\$/.test(message)) { + return true; + } else { + return false; + } + }; + + const tipMatch = (session: any): any[] => { + //match session.content涓殑##[0-9]$$鐨勭储寮� + let indexs: any[] = []; + let preTip = 0; + session.content.match(/##([0-9]+)\$\$/g)?.map((item) => { + let i = session.content.indexOf(item); + indexs.push({ index: i, item: item, preIndex: preTip }); + preTip = i; + }); + return indexs; + }; + const getTxt = (data, role, message, index) => { - if (/##0\$\$/.test(message)) { + if (isExistTip(message)) { if (role == 'assistant' && index) { - data.forEach((item) => { - if (Object.keys(item).length !== 0 && item?.doc_aggs.length > 0) { - dataItem = item.doc_aggs; - } - }); + let i = index / 2 - 1 > 0 ? index / 2 - 1 : 0; + dataItem = data[i].doc_aggs; } } else { dataItem = []; @@ -499,9 +564,47 @@ return dataItem; }; - const clickHref = (item) => { - return Message.warning('鏆傛棤娉曟煡鐪�'); - window.open(`/api/v1/document/get/${item.doc_id}`, '_blank'); + const getTipContent = (data, index): string => { + let maxSimilarityContent = ''; + let i = index / 2 - 1 > 0 ? index / 2 - 1 : 0; + let maxSimilarity = 0; + data[i].chunks.forEach((chunk) => { + if (chunk.similarity > maxSimilarity) { + maxSimilarity = chunk.similarity; + maxSimilarityContent = chunk.content_with_weight; + } + }); + return maxSimilarityContent; + }; + + const clickHref = async (item) => { + documenttype.value = item.doc_name.split('.').pop(); + previewSrc.value = httpUrl + `/api/v1/document/get/${item.doc_id}`; + fileVisible.value = true; + }; + + const downloadFile = ({ + url, + filename, + target, + }: { + url: string; + filename?: string; + target?: string; + }) => { + const downloadElement = document.createElement('a'); + downloadElement.style.display = 'none'; + downloadElement.href = url; + if (target) { + downloadElement.target = '_blank'; + } + downloadElement.rel = 'noopener noreferrer'; + if (filename) { + downloadElement.download = filename; + } + document.body.appendChild(downloadElement); + downloadElement.click(); + document.body.removeChild(downloadElement); }; const getIconByExtension = computed(() => (extension) => { @@ -539,74 +642,21 @@ // formRef.value.resetFields(); }; - const selectFile = () => { - fileInput.value.click(); + const selectFileCallback = (data) => { + console.log(data, 'selectFileCallback'); + uploaditemList.value = [...uploaditemList.value, ...data]; }; let onFileSelectedLoading = ref(false); - const onFileSelected = (event) => { - const file = event.target.files[0]; - uploaditemList.value = [ - { - name: file.name, - size: file.size, - }, - ]; - if (file) { - onFileSelectedLoading.value = true; - const formData = new FormData(); - formData.append('file', file); - formData.append('conversation_id', activeSessionId.value); - uploadWithoutKb(formData).then((res) => { - // console.log(res); - if (res.code == 200) { - console.log(res); - console.log(uploaditemList.value); - onFileSelectedLoading.value = false; - fileInput.value.value = ''; - uploaditemList.value = []; - Message.success('涓婁紶鎴愬姛'); - } else { - Message.error('涓婁紶澶辫触'); - } - }); - } - }; const deleteFile = (item) => { console.log(uploaditemList.value); - uploaditemList.value = []; + uploaditemList.value.splice(item.index, 1); }; const { toClipboard } = useClipboard(); const copy = async (text) => { await toClipboard(text); //鍙傛暟涓鸿澶嶅埗鐨勬枃鏈� - }; - - const onChange = (fileList) => { - // files.value = fileList; - }; - - // 涓婁紶鏂囦欢 - const customRequest = async (option) => { - const { onProgress, onError, onSuccess, fileItem, name } = option; - fileItem.status = 'ready'; - if (fileItem.file) { - const formData = new FormData(); - formData.append('file', fileItem.file); - formData.append('conversation_id', activeSessionId.value); - uploadWithoutKb(formData).then((res) => { - // console.log(res); - if (res.code == 200) { - console.log(res); - console.log(uploadList.value); - fileItem.status = 'done'; - // uploadList.value = []; - } else { - fileItem.status = 'error'; - } - }); - } }; const DialogList = async () => { @@ -675,26 +725,6 @@ event.preventDefault(); inputMsg.value += '\n'; }; - const dialogChange = (val) => { - // 鍒ゆ柇褰撳墠鏄櫤鑳戒綋鎴朼gent - // console.log(val, 'val'); - dialogId.value = val; - dialogs.value.forEach((item) => { - if (item.id === val) { - Object.assign(dialogObj, item); - } - }); - console.log(dialogObj.type, 'dialogObj'); - if (dialogObj.type == 1) { - agentType.value = '1'; - querySessionList(); - } else { - agentType.value = '2'; - queryAgentSessionList(); - } - - // querySessionList(); - }; // 鍙戦�� const sentClick = () => { @@ -715,21 +745,39 @@ event.preventDefault(); // 闃绘榛樿琛屼负锛屽嵆涓嶆崲琛� } - // if (!activeSessionId.value) { - // Message.warning("璇烽�夋嫨浼氳瘽"); - // chatDis.value = false; - // loading.value = false; - // return; - // } - // if (displayedText.value) { // querySessionList(); // } if (inputMsg.value) { - startChat(inputMsg.value); - - inputMsg.value = ''; + if (!activeSessionId.value) { + //鏂板缓浼氳瘽 + // 濡傛灉鏈変細璇漣d + console.log(inputMsg.value, '鏂板缓浼氳瘽鍚嶇О'); + const res = await addSessionApi({ + dialog_id: '', + conversation_desc: inputMsg.value, + }); + // console.log(res, "res"); + if (res.code == 200) { + // console.log(res.data.conversation_id); + activeSessionId.value = res.data?.conversation_id; + const { code, data } = await getSessionDetailsApi( + res.data?.conversation_id + ); + if (code === 200) { + console.log(data, '鏂板缓浼氳瘽璇︽儏'); + Object.assign(chatObj, data); + startChat(inputMsg.value); + inputMsg.value = ''; + } + } else { + Message.error('鍒涘缓浼氳瘽澶辫触锛岃閲嶈瘯'); + } + } else { + startChat(inputMsg.value); + inputMsg.value = ''; + } } else { Message.warning('娑堟伅涓嶈兘涓虹┖'); } @@ -740,6 +788,7 @@ const startChat = async (valMsg) => { chatDis.value = true; loading.value = true; + toStop = false; sessionDetailList.value.push({ content: valMsg, role: 'user', @@ -767,6 +816,11 @@ .getReader(); currIndex.value = 0; while (true) { + if (toStop) { + displayedText.value = ''; + setChatDataMeg(chatDataMeg); + break; + } const x = await reader?.read(); if (x) { const { done, value } = x; @@ -809,6 +863,7 @@ loading.value = false; chatDis.value = false; isStopChat.value = true; + toStop = true; console.log('stopChat'); console.log(displayedText.value, 'displayedText'); console.log(sessionDetailList.value, 'sessionDetailList'); @@ -828,7 +883,6 @@ sessionDetailList.value = sessionDetailList.value .splice(0, sessionDetailList.value.length - 2) .concat(lastArr); - console.log(sessionDetailList.value, 'sessionDetailList2'); console.log(chatObj, 'chatObj瀵硅薄'); chatObj.message = chatObj.message.concat(lastArr); @@ -859,6 +913,7 @@ sessionDetailList.value = data.message; messagenList.value = data; agentTitle.value = data.name; + from.name = data.name; refreshScroll(); //鍒锋柊婊氬姩鏉′綅缃� isStopChat.value = false; } @@ -872,6 +927,7 @@ const querySessionDetail = async (session) => { sectionList.value = session; activeSessionId.value = session.id; + from.name = session.name; const { code, data } = await getSessionDetailsApi(session.id); if (code === 200) { sessionDetailList.value = data.message; @@ -922,14 +978,24 @@ querySessionList(); }; onBeforeMount(() => { - // DialogList(); - //鏂板缓浼氳瘽 - createSession(''); + activeSessionId.value = ''; }); onMounted(() => { + let container = document.getElementById('container'); + container.addEventListener('click', () => { + fileInput.value.cancel(); + }); EventBus.on('newChat', () => { agentType.value = '1'; - createSession(''); + // createSession(''); + activeSessionId.value = ''; + sessionDetailList.value = [ + { + content: '浣犲ソ锛� 鎴戞槸浣犵殑鍔╃悊锛屾湁浠�涔堝彲浠ュ府鍒颁綘鐨勫悧锛�', + role: 'assistant', + }, + ]; + from.name = '鏈懡鍚嶄細璇�'; }); }); onBeforeUnmount(() => { @@ -1288,4 +1354,19 @@ :deep(.arco-upload-list-item-operation) { //display: none; } + .uploadFileList { + width: 100%; + max-height: 140px; + overflow-y: auto; + padding: 10px; + display: flex; + flex-wrap: wrap; + :deep(.arco-comment-author) { + width: 100px; + display: inline-block; + overflow: hidden; /* 闅愯棌瓒呭嚭鐨勫唴瀹� */ + text-overflow: ellipsis; /* 浣跨敤鐪佺暐鍙锋潵浠f浛琚殣钘忕殑鏂囧瓧 */ + white-space: nowrap; /* 涓嶆崲琛岋紝浣垮唴瀹瑰湪涓�琛屽唴鏄剧ず */ + } + } </style> -- Gitblit v1.8.0