From ff0ae974a1c561eaf2915988dac63cd066af189f Mon Sep 17 00:00:00 2001 From: yinbangzhong <zhongbangyin@126.com> Date: 星期四, 12 九月 2024 09:23:44 +0800 Subject: [PATCH] bug fix --- src/views/sessionManager/index.vue | 505 ++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 384 insertions(+), 121 deletions(-) diff --git a/src/views/sessionManager/index.vue b/src/views/sessionManager/index.vue index 6654627..6dfc3d0 100644 --- a/src/views/sessionManager/index.vue +++ b/src/views/sessionManager/index.vue @@ -78,61 +78,172 @@ /> </template> <template #content> - <div :class="{ chartUserText: theme === 'light' }" - >{{ sessionDetail.content }} + <div :class="{ chartUserText: theme === 'light' }"> + {{ sessionDetail.content }} + <!-- <a-input + :style="{ width: '100%' }" + v-model="sessionDetail.content" + v-if="isEdit" + /> + + <div v-else> + {{ sessionDetail.content }} + </div> --> </div> + <!-- <div v-if="!isEdit"> + <span + class="action" + v-if="index != 0" + @click="copy(sessionDetail.content)" + > + <icon-copy /> 澶嶅埗 + </span> + <span class="action" @click="edit()"> + <icon-pen /> 缂栬緫 + </span> + </div> + <a-space v-else> + <a-button type="outline" size="mini" @click="cancelEdit(1)" + >鍙栨秷</a-button + > + <a-button type="primary" size="mini" @click="cancelEdit(2)" + >纭畾</a-button + > + </a-space> --> </template> </a-comment> <a-comment v-else-if="sessionDetail.role === 'assistant'"> <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 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)" + <a-card v-if="isExistTip(sessionDetail.content)" style="padding: 10px"> + <div + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + v-for="(breakContent, breakIndex) in breakLine( + sessionDetail.content + )" > - <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 + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + v-if="isExistTip(breakContent)" + > + <div + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + v-for="(item, tipIndex) in tipMatch(breakContent)" + > + <span v-if="tipIndex == 0"> + {{ breakContent.substring(0, item.index) }} + <a-tooltip + background-color="#3491FA" + :content=" + getTipContent(messagenList.reference, index) + " + > + <img + style="width: 15px; height: 15px" + :src="tipImage" + /> + </a-tooltip> + <span v-if="tipIndex == item.len - 1"> + {{ breakContent.substring(item.index + 5) }} + </span> + </span> + <span v-else-if="tipIndex == item.len - 1"> + {{ + breakContent.substring( + item.preIndex + item.item.length, + item.index + ) + }} + <a-tooltip + background-color="#3491FA" + :content=" + getTipContent(messagenList.reference, index) + " + > + <img + style="width: 15px; height: 15px" + :src="tipImage" + /> + </a-tooltip> + {{ breakContent.substring(item.index + 5) }} + </span> + <span v-else> + {{ + breakContent.substring( + item.preIndex + item.item.length, + item.index + ) + }} + <a-tooltip + background-color="#3491FA" + :content=" + getTipContent(messagenList.reference, index) + " + > + <img + style="width: 15px; height: 15px" + :src="tipImage" + /> + </a-tooltip> + </span> + </div> + </div> + <div v-else> + {{ breakContent }} + </div> </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 v-else> + <a-textarea + readonly + auto-size + :default-value="chartText(sessionDetail.content)" + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + > + </a-textarea> </a-card> + <!-- <div class="prompt"> + <ul> + <li class="prompt-item" @click="copyText('43234')"> + <span> + 344343klsdjkjksdjkjksdjk灏卞紑濮嬪ぇ瀹剁湅鏁版嵁搴撶櫥璁板崱鍙楁墦鍑诲嚡鎾掔櫥璁板崱鍙楁墦鍑诲嚡鎾掔櫥璁板崱鍙楁墦鍑诲嚡鎾掔殑43</span + > + <span style="margin-left: 20px"> + <icon-right /> + </span> + </li> + </ul> + </div> --> </template> - <!-- <div>{{ sessionDetail.role === 'assistant' }}</div> --> + <template #actions> - <!-- <div - v-for="(item, leng) in messagenList.reference" - :key="leng" - > --> + <div> <div> <template @@ -168,38 +279,36 @@ > <icon-refresh /> 閲嶆柊鐢熸垚 </span> + <!-- <span class="action"><icon-to-bottom />涓嬭浇 </span> --> </template> </a-comment> <a-comment v-else-if="sessionDetail.role === 'last'"> <template #avatar> <img class="icon-user-jpg" - src="../../assets/images/icon-chart.png" + src="../../assets/images/icon-picture.png" alt="鏈湴鍥剧墖" /> </template> <template #content> - <a-textarea - readonly - auto-size - v-model="displayedText" - :class="{ chatItemAnswer: theme === 'light' }" - :style="{ - backgroundColor: - theme === 'light' ? '#ffffff' : '#000000', - }" - style="border: none" - > - </a-textarea> + <a-spin :loading="chartLoading" dot style="width: 100%"> + <a-textarea + readonly + auto-size + v-model="displayedText" + :class="{ chatItemAnswer: theme === 'light' }" + :style="{ + backgroundColor: + theme === 'light' ? '#ffffff' : '#000000', + }" + style="border: none" + > + </a-textarea> + </a-spin> </template> <template #actions> - <!-- <div class="icon-box"> - <div> - <img :src="getIconByExtension('pdf')" alt="" /> - </div> - <div class="icon-text"> 鏂囦欢绫诲瀷 </div> - </div> --> + <div class="action" @click="stopChat" @@ -215,24 +324,12 @@ </template> </a-comment> </div> - <!-- <div class="chartStart" v-if="isStart" @click="startChat" - >鍋滄鐢熸垚</div - > - <div class="chartStart v-else" @click="stopChat">閲嶆柊鐢熸垚</div> --> + </a-scrollbar> <div class="chat_bottom"> <div class="center-bottom"> - <!-- <a-textarea - v-model="inputMsg" - @keydown.shift.enter="sendMessage" - style="height: 180px" - placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝Shift+Enter鍙戦��" - :max-length="500" - allow-clear - show-word-limit - > - </a-textarea> --> + <a-textarea v-model="inputMsg" @keydown.shift.enter="handleShiftEnter" @@ -261,12 +358,15 @@ display: flex; justify-content: space-between; " + class="uploadFileDis" > <updataFile ref="fileInput" :sessionId="activeSessionId" + :hide="hide_upload" @selectFileCallback="selectFileCallback" ></updataFile> + <a-button :disabled="chatDis" @click="sentClick" @@ -354,7 +454,18 @@ ></smartAi> </div> </a-col> + <a-col :span="23" v-show="agentType == '5'"> + <div class="center"> + <seniorAgentSession :modalObj="agentObj"></seniorAgentSession> + </div> + </a-col> </a-row> + <a-modal title=" " v-model:visible="fileVisible" :footer="false" fullscreen> + <docx v-if="documenttype == 'docx'" :previewSrc="previewSrc"></docx> + <excel v-if="documenttype == ('xlsx' || 'xls')" :previewSrc="previewSrc"></excel> + <Pdf v-if="documenttype == 'pdf'" :previewSrc="previewSrc"></Pdf> + <txt v-if="documenttype == 'txt'" :previewSrc="previewSrc"></txt> + </a-modal> <a-modal v-model:visible="visible" title="淇敼鍚嶇О" @@ -383,7 +494,7 @@ </div> </template> <script setup lang="ts"> - import { useAppStore, useUserStore } from '@/store'; + import { useAppStore, userModelState, useUserStore } from '@/store'; import { computed, nextTick, @@ -401,9 +512,11 @@ import chatMenu from '@/views/sessionManager/components/chatMenu.vue'; import AddSession from '@/views/sessionManager/components/addSession.vue'; import agentSession from '@/views/sessionManager/components/agentSession.vue'; + import seniorAgentSession from '@/views/sessionManager/components/seniorAgentSession.vue'; import historySession from '@/views/sessionManager/components/historySession.vue'; import smartAi from '@/views/sessionManager/components/smartAi.vue'; import updataFile from '@/views/sessionManager/components/updataFile.vue'; + import EventBus from '@/utils/EventBus'; import { addSessionApi, @@ -412,6 +525,9 @@ getSessionDetailsApi, sessionListApi, uploadWithoutKb, + uploadAndParse, + chatInfos, + chatRm, } from '@/api/session'; import { getAuthorization } from '@/utils/auth'; import { queryCanvasList } from '@/api/Agent'; @@ -423,7 +539,13 @@ import pdfImg4 from '@/assets/session/icon-txt.png'; import pdfImg5 from '@/assets/session/txt.png'; import tipImage from '@/assets/session/tip.png'; - import { number } from "@intlify/core-base"; + + import docx from '@/views/dmx/knowledgeLib/components/docx.vue'; + import excel from '@/views/dmx/knowledgeLib/components/excel.vue'; + import Pdf from '@/views/dmx/knowledgeLib/components/Pdf.vue'; + import txt from '@/views/dmx/knowledgeLib/components/txt.vue'; + import { is } from 'immutable'; + import uploadFile from './components/uploadFile.vue'; // const url = ref('../../assets/session/PDF.png'); @@ -438,6 +560,7 @@ const modalObj = reactive({ add: false }); const dialogId = ref(''); const chatDis = ref(false); + const chartLoading = ref(false); const loading = ref(false); const agentType = ref('1'); const agentTitle = ref('鏈懡鍚嶄細璇�'); @@ -445,13 +568,14 @@ let from = reactive({ name: '鏈懡鍚嶄細璇�', }); - const isStopChat = ref(false); + const currIndex = ref(0); const displayedText = ref(''); // 姝e湪鏄剧ず鐨勬枃瀛� let timer: number | null = null; const streamStr = ref(''); const inputMsg = ref(''); const activeSessionId = ref(''); + const hide_upload=ref(2); const fieldNames = { value: 'id', label: 'name' }; const dialogs = ref([]); const dialogObj = reactive({}); @@ -464,10 +588,16 @@ const uploadRef = ref(); const files = ref([]); const file = ref(''); - const fileInput = ref(null); + const fileInput = ref(); 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: [ @@ -482,41 +612,69 @@ if (errors) return; let chatData = { id: chatObj.id, - conversation_id: chatObj.id, - name: from.name, + dialog_id: chatObj.dialog_id, + conversation_desc: from.name, }; const { code, data } = await addSessionApi(chatData); if (data) { Message.success('淇敼鎴愬姛'); handleCancel(); + if (data?.id) { + activeSessionId.value = data.id; + } queryNewSessionDetail(activeSessionId.value); } }; let dataItem = []; - const isExistTip=(message:string):boolean=>{ + const isExistTip = (message: string): boolean => { if (/##[0-9]\$\$/.test(message)) { return true; } else { return false; } - } + }; - const tipMatch = (session: any): any[] => { + const breakLine = (message: string): string[] => { + //鎸塡n鍒嗗壊瀛楃涓� + let arr = message.split('\n'); + return arr; + }; + + const chartText = (message: string): string => { + //鍘婚櫎鎵�鏈夌殑#鍜�** + let arr = message.replace(/\*\*|\#\#\#/g, ''); + return arr; + }; + + const tipMatch = (msg: string): 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 }); + let preTip = 0; + let matches = msg.match(/##([0-9]+)\$\$/g); + matches?.map((item) => { + let i = msg.indexOf(item); + indexs.push({ + index: i, + item: item, + preIndex: preTip, + len: matches.length, + }); preTip = i; }); return indexs; - } + }; const getTxt = (data, role, message, index) => { if (isExistTip(message)) { if (role == 'assistant' && index) { let i = index / 2 - 1 > 0 ? index / 2 - 1 : 0; + if (data.length == 1) { + i = 0; + } + if (data.length == i) { + i = data.length-1; + } dataItem = data[i].doc_aggs; } } else { @@ -527,26 +685,28 @@ }; const getTipContent = (data, index): string => { - let maxSimilarityContent = ""; + let maxSimilarityContent = ''; let i = index / 2 - 1 > 0 ? index / 2 - 1 : 0; + if (data.length == 1) { + i = 0; + } + if (data.length == i) { + i = data.length-1; + } let maxSimilarity = 0; data[i].chunks.forEach((chunk) => { - if (chunk.similarity > maxSimilarity) { - maxSimilarity = chunk.similarity; - maxSimilarityContent = chunk.content_with_weight; - } + if (chunk.similarity > maxSimilarity) { + maxSimilarity = chunk.similarity; + maxSimilarityContent = chunk.content_with_weight; } - ); + }); return maxSimilarityContent; }; - const clickHref = (item) => { - // return Message.warning('鏆傛棤娉曟煡鐪�'); - // window.open(`/api/v1/document/get/${item.doc_id}`, '_blank'); - downloadFile({ - url: `/api/v1/document/get/${item.doc_id}`, - filename: item.doc_name, - }); + const clickHref = async (item) => { + documenttype.value = item.doc_name.split('.').pop(); + previewSrc.value = httpUrl + `/api/v1/document/get/${item.doc_id}`+"?t="+new Date().getTime(); + fileVisible.value = true; }; const downloadFile = ({ @@ -608,9 +768,29 @@ // formRef.value.resetFields(); }; - const selectFileCallback = (data) => { - console.log(data, 'selectFileCallback'); - uploaditemList.value = data; + const selectFileCallback = (data,conversation_id) => { + uploaditemList.value = [...uploaditemList.value, ...data]; + activeSessionId.value = conversation_id; + }; + + + //涓婁紶鎴愬姛瑙f瀽getinfo + const getInfo = async (id) => { + const { code, data } = await chatInfos({ + doc_ids: activeSessionId.value, + }); + if (code === 200) { + uploaditemList.value = data; + } + }; + //鍒犻櫎涓婁紶鏂囨。 + const deleteUpload = async (id) => { + const { code, data } = await chatRm({ + doc_id: id, + }); + if (code === 200) { + getInfo(); + } }; let onFileSelectedLoading = ref(false); @@ -618,11 +798,25 @@ const deleteFile = (item) => { console.log(uploaditemList.value); uploaditemList.value.splice(item.index, 1); + // EventBus.emit('queryAgent', item); }; const { toClipboard } = useClipboard(); const copy = async (text) => { await toClipboard(text); //鍙傛暟涓鸿澶嶅埗鐨勬枃鏈� + }; + + const isEdit = ref(false); + const edit = () => { + isEdit.value = !isEdit.value; + }; + const cancelEdit = (val) => { + if (val == 1) { + isEdit.value = !isEdit.value; + } else { + //缂栬緫淇濆瓨 + isEdit.value = !isEdit.value; + } }; const DialogList = async () => { @@ -694,7 +888,9 @@ // 鍙戦�� const sentClick = () => { + displayedText.value=""; sendMessage('click'); + uploaditemList.value = []; }; // 閲嶆柊鐢熸垚 const reGenerate = () => { @@ -720,7 +916,6 @@ //鏂板缓浼氳瘽 // 濡傛灉鏈変細璇漣d console.log(inputMsg.value, '鏂板缓浼氳瘽鍚嶇О'); - const res = await addSessionApi({ dialog_id: '', conversation_desc: inputMsg.value, @@ -729,9 +924,15 @@ if (res.code == 200) { // console.log(res.data.conversation_id); activeSessionId.value = res.data?.conversation_id; - startChat(inputMsg.value); - inputMsg.value = ''; - // queryNewSessionDetail(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('鍒涘缓浼氳瘽澶辫触锛岃閲嶈瘯'); } @@ -746,10 +947,14 @@ } }; + let message_stop = []; + let message_id = ""; const startChat = async (valMsg) => { chatDis.value = true; loading.value = true; toStop = false; + displayedText.value = ''; + chartLoading.value = true; sessionDetailList.value.push({ content: valMsg, role: 'user', @@ -778,6 +983,7 @@ currIndex.value = 0; while (true) { if (toStop) { + message_stop.push(message_id); displayedText.value = ''; setChatDataMeg(chatDataMeg); break; @@ -789,9 +995,20 @@ try { const val = JSON.parse(value?.data || ''); const d = val?.data; + if (message_id != d.message_id) { + message_id = d.message_id; + message_stop = []; + } else { + //message_stop涓煡鎵緈essage_id + const index = message_stop.findIndex(item => item === message_id); + if (index > -1) { + break; + } + } if (typeof d !== 'boolean') { // console.info("data:", d); streamStr.value = d.content; + chartLoading.value = false; startDisplayStr(); } } catch (e) { @@ -800,12 +1017,9 @@ if (done) { console.info('done'); displayedText.value = ''; - if (isStopChat.value) { - setChatDataMeg(chatDataMeg); - } else { - queryNewSessionDetail(activeSessionId.value); - EventBus.emit('queryAppUsageList'); - } + chartLoading.value = false; + queryNewSessionDetail(activeSessionId.value); + EventBus.emit('queryAppUsageList'); break; } } @@ -816,14 +1030,8 @@ }; const stopChat = async () => { - // const { code, data } = await stopChatApi(activeSessionId.value); - // if (code === 200) { - // Message.success("宸插仠姝�"); - // queryNewSessionDetail(activeSessionId.value); - // } loading.value = false; chatDis.value = false; - isStopChat.value = true; toStop = true; console.log('stopChat'); console.log(displayedText.value, 'displayedText'); @@ -844,10 +1052,11 @@ 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); + if (chatObj?.message) { + chatObj.message = chatObj.message.concat(lastArr); + } Object.assign(chatDataMeg, { id: chatObj.id, conversation_id: chatObj.id, @@ -877,11 +1086,12 @@ agentTitle.value = data.name; from.name = data.name; refreshScroll(); //鍒锋柊婊氬姩鏉′綅缃� - isStopChat.value = false; } }; const changeAgentType = (val, session) => { + hide_upload.value = hide_upload.value+1; + uploaditemList.value=[]; agentType.value = val; console.log(val, 'val'); }; @@ -892,6 +1102,7 @@ from.name = session.name; const { code, data } = await getSessionDetailsApi(session.id); if (code === 200) { + Object.assign(chatObj, data); sessionDetailList.value = data.message; messagenList.value = data; refreshScroll(); //鍒锋柊婊氬姩鏉′綅缃� @@ -943,12 +1154,16 @@ activeSessionId.value = ''; }); onMounted(() => { + document.getElementsByTagName; let container = document.getElementById('container'); container.addEventListener('click', () => { - fileInput.value.cancel(); + // fileInput.value.cancel(); }); EventBus.on('newChat', () => { + uploaditemList.value = []; agentType.value = '1'; + chatObj = {}; + hide_upload.value = hide_upload.value+1; // createSession(''); activeSessionId.value = ''; sessionDetailList.value = [ @@ -1048,6 +1263,33 @@ font-size: 12px; padding-left: 10px; } + } + } + } + // .uploadFileDis { + // :deep(.arco-upload-list-type-text) { + // display: none; + // } + // } + .prompt { + ul { + margin: 0; + padding: 0; + display: flex; + } + ul > li { + list-style-type: none; + } + .prompt-item { + display: flex; + justify-content: space-between; + background-color: #fff; + cursor: pointer; + border-radius: 8px; + padding: 10px; + border: #e5e5e5; + &:hover { + background-color: #eee; } } } @@ -1184,6 +1426,11 @@ } } } + .uploadFileDis { + :deep(.arco-upload-list-type-text) { + display: none; + } + } .chat-item { padding: 10px 0; @@ -1193,6 +1440,19 @@ font-size: 14px; color: #333; margin-top: 4px; + } + :deep(.arco-card-body) { + padding: 0; + border-radius: 10px; + } + :deep(.arco-textarea) { + padding-top: 10px !important; + } + :deep(.arco-comment-inner-content) { + border-radius: 10px; + } + :deep(.arco-card-bordered) { + border-radius: 10px; } .icon-user-jpg { @@ -1212,6 +1472,9 @@ margin-left: 10px; } } + :deep(.arco-spin-loading .arco-spin-mask-icon) { + left: 10%; + } } .right { -- Gitblit v1.8.0