From ff2d01588d4e69d3bf1ad856e8e225b7f6a3c0f2 Mon Sep 17 00:00:00 2001 From: zhaowei <zhaowei> Date: 星期一, 26 八月 2024 11:01:48 +0800 Subject: [PATCH] 1、基本实现电子说明书页面布局及功能 2、基本实现语言大模型页面与后端数据联动 --- src/views/ai/LanguageModel.vue | 517 +++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 356 insertions(+), 161 deletions(-) diff --git a/src/views/ai/LanguageModel.vue b/src/views/ai/LanguageModel.vue index e2d3666..36c4eb6 100644 --- a/src/views/ai/LanguageModel.vue +++ b/src/views/ai/LanguageModel.vue @@ -1,11 +1,15 @@ <template> <div class="page-container"> <div class="outer-container"> + <!--宸︿晶鍘嗗彶浼氳瘽鍖哄煙--> <div class="left-container"> + <!--logo鍖哄煙--> <div class="logo-container"><img src="@/assets/page/languageModel/logo.png"></div> + + <!--鍔熻兘鎸夐敭鍖哄煙--> <div class="manage-history-container"> <div @click="createNewConversation" - :class="[isAtNewConversation?'create-history-container-active':'',isDeletingBatch?'fold-create-history-container':'expand-create-history-container']" + :class="[isAtNewConversation?'create-history-container-active':'',isDeletingBatch?'fold-create-history-container':'expand-create-history-container',isModelResponding?'disable-expand':'']" class="create-new-conversation"> <a-icon type="plus"></a-icon> <span v-if="!isDeletingBatch">鏂板浼氳瘽</span> @@ -38,7 +42,7 @@ </div> </template> <div @click="deleteBatchConversation" id="delete-batch-button" - :class="[checkedConversationIdList.length?'able-delete-button':'disable-delete-button']"> + :class="[checkedConversationIdList.length&&!isModelResponding?'able-delete-button':'disable-delete-button']"> <a-icon type="delete"/> <div>鍒犻櫎</div> </div> @@ -52,9 +56,18 @@ </template> </div> </div> + + <!--鍘嗗彶浼氳瘽鍒楄〃鍖哄煙--> <div class="chat-history-container"> + <template v-if="!chatHistoryList.length"> + <a-empty> + <span slot="description">鏃犲巻鍙蹭細璇�</span> + </a-empty + > + </template> + <div v-for="(item,index) in chatHistoryList" :key="item.id" - :class="[item.id===activeHistoryIndex?'single-history-active':'',item.inputVisible?'input-visible-class':'']" + :class="[item.id===activeHistoryIndex?'single-history-active':'',item.inputVisible?'input-visible-class':'',isModelResponding?'disable-switch':'']" @click="switchToCurrentConversation(item,$event)" @mouseenter="item.iconVisible=true" @mouseleave="item.iconVisible=false"> @@ -65,7 +78,6 @@ <span class="check-mark"></span> </label> - <a-popover placement="top" :visible="item.deletePopVisible" trigger="click" :getPopupContainer="node=>node.parentNode"> <template slot="content"> @@ -73,13 +85,14 @@ <div>鍒犻櫎鍚庢棤娉曟仮澶嶏紝鏄惁缁х画鍒犻櫎锛�</div> <div> <button class="cancel-delete-button" @click="cancelDeleteConversation(item,$event)">鍙栨秷</button> - <button @click="confirmDeleteConversation(item,index)" id="delete-conversation-button">鍒犻櫎</button> + <button @click.stop="confirmDeleteConversation(item,index)" id="delete-conversation-button">鍒犻櫎 + </button> </div> </div> </template> <template v-if="!item.inputVisible"> - <div class="conversation-title">{{item.title}}</div> - <div class="icon-container hover-icon-container" v-show="!isDeletingBatch"> + <div class="conversation-title">{{item.problem.slice(0,15)}}</div> + <div class="icon-container hover-icon-container" v-show="!isDeletingBatch&&!isModelResponding"> <a-icon type="edit" @click.stop="editConversationTitle(item)"/> <a-icon type="delete" @click.stop="deleteConversation(item)" @blur="cancelDeleteConversation(item,$event)"/> @@ -102,28 +115,33 @@ </div> </div> + <!--鍙充晶浼氳瘽鍐呭鍖哄煙--> <div class="right-container"> + <!--浼氳瘽鍐呭鍒楄〃鍖哄煙--> <div class="conversation-container"> <div v-for="item in currentConversation.messages" class="single-conversation" :id="'id'+item.index"> <div v-if="item.role==='user'" class="user-question"> <div class="avatar"> <a-avatar :src="getAvatar()"/> </div> - <div class="content">{{item.content}}</div> + <div class="conversation-content">{{item.content}}</div> </div> <div v-else class="assistant-answer"> <div class="avatar"> <img src="@/assets/page/languageModel/ai-avatar.png"/> </div> - <div class="content">{{item.content}}</div> + <div class="conversation-content" v-html="item.content.replace(/\n/g,'<br>')"></div> </div> </div> </div> + + <!--鎻愰棶杈撳叆鍖哄煙--> <div class="input-container" :class="[textareaFocused?'input-container-active':'']"> <textarea v-model="inputQuestion" :placeholder="textareaPlaceholder" @keydown.enter="sendQuestion($event)" @focus="textareaFocused=true" @blur="textareaFocused=false"></textarea> - <img src="@/assets/page/languageModel/send-message.png" @click="sendQuestion($event)" v-if="!isResponding"> + <img src="@/assets/page/languageModel/send-message.png" @click="sendQuestion($event)" + v-if="!isModelResponding"> <a-icon type="loading" class="loading-icon" v-else/> </div> </div> @@ -136,6 +154,16 @@ import { mapGetters } from 'vuex' import { message } from 'ant-design-vue' import { randomUUID } from '@/utils/util' + import { + addNewConversationApi, + getChatHistoryListApi, + getCurrentConversationApi, + deleteSingleChatHistoryApi, + askToLanguageModelApi + } from '@/api/ai' + import { EventSourcePolyfill } from 'event-source-polyfill' + import Vue from 'vue' + import { ACCESS_TOKEN, TENANT_ID } from '@/store/mutation-types' message.config({ maxCount: 1, @@ -151,62 +179,22 @@ checkedConversationIdList: [], deleteBatchPopVisible: false, currentConversation: { - id: '683a65fd-8feb-4446-ad32-714c4785f667', - messages: [ - { - 'role': 'user', - 'content': '浣犳槸璋侊紵浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋�' - }, - { - 'role': 'assistant', - 'content': '鎴戞槸26涓敓娑寚瀵煎笀灏忕埍' - }, - { - 'role': 'user', - 'content': '浣犻兘鑳藉仛浜涗粈涔堬紵' - }, - { - 'role': 'assistant', - 'content': '鎴戣兘绔欏湪鏈潵瑙嗚甯姪鍚屽浠仛濂界敓娑鍒掓寚瀵笺��' - }, - { - 'role': 'user', - 'content': '浠婂ぉ澶╂皵濡備綍锛�' - }, - { - 'role': 'assistant', - 'content': '鎴戞槸26涓敓娑寚瀵煎笀灏忕埍' - }, - { - 'role': 'user', - 'content': '浣犻兘鑳藉仛浜涗粈涔堬紵' - }, - { - 'role': 'assistant', - 'content': '鎴戣兘绔欏湪鏈潵瑙嗚甯姪鍚屽浠仛濂界敓娑鍒掓寚瀵笺��' - } - ], - stream: false, - max_tokens: 500, - iconVisible: false, - inputVisible: false, - deletePopVisible: false + id: '', + messages: [], + stream: true, + max_tokens: 500 }, - // currentConversation: {}, isAtNewConversation: false, isDeletingBatch: false, activeHistoryIndex: null, editingHistoryIndex: null, deletingHistoryIndex: null, - iconVisible: false, - inputVisible: false, editedConversationTitle: '', - deletePopVisible: false, conversationContainer: null, inputQuestion: '', - textareaPlaceholder: 'Enter鍙戦�侊紝Shift+Enter鎹㈣', + textareaPlaceholder: '', textareaFocused: false, - isResponding: false + isModelResponding: false } }, @@ -219,40 +207,265 @@ document.removeEventListener('click', this.handleDocumentClick) } } + }, + isAtNewConversation: { + handler(val) { + if (val) { + this.textareaPlaceholder = '璇峰皾璇曢棶鎴戯細浣犳槸璋侊紵' + } else { + this.textareaPlaceholder = 'Enter鍙戦�侊紝Shift+Enter鎹㈣' + } + }, + immediate: true } }, + created() { + this.getChatHistoryListByApi() + }, mounted() { - this.getConversationByApi() this.conversationContainer = document.querySelector('.conversation-container') }, methods: { ...mapGetters(['avatar']), - /* 璋冪敤鎺ュ彛鑾峰彇褰撳墠浼氳瘽璁板綍 */ - getConversationByApi() { - this.currentConversation.title = this.currentConversation.messages[0].content.slice(0, 15) - this.chatHistoryList.push(this.currentConversation) - this.activeHistoryIndex = this.chatHistoryList[0].id - if (!this.chatHistoryList.length) this.textareaPlaceholder = '璇峰皾璇曢棶鎴戯細浣犳槸璋侊紵' + getChatHistoryListByApi() { + // TODO 璋冪敤鎺ュ彛鑾峰彇鍘嗗彶浼氳瘽鍒楄〃,濡傛灉鍘嗗彶浼氳瘽涓嶄负绌哄垯璺宠浆鑷崇涓�鏉″巻鍙蹭細璇濆唴瀹逛腑 + getChatHistoryListApi() + .then(res => { + console.log('res', res) + if (res.success && res.result && res.result.length > 0) { + this.chatHistoryList = res.result.map(item => { + return { + ...item, + iconVisible: false, + inputVisible: false, + deletePopVisible: false + } + }) + if (!this.activeHistoryIndex) this.switchToCurrentConversation(this.chatHistoryList[0]) + if (this.isDeletingBatch) this.singleHistoryCheckedChange() + } else { + this.chatHistoryList = [] + this.createNewConversation() + } + }) + .catch(err => { + this.chatHistoryList = [] + this.createNewConversation() + console.log('err', err) + }) }, - /* 鍒涘缓涓�涓柊浼氳瘽 */ + /* 鐐瑰嚮鏂板浼氳瘽鍚庤Е鍙� */ createNewConversation() { if (this.isAtNewConversation) this.$message.info('褰撳墠宸叉槸鏈�鏂板璇�') + if (this.isModelResponding) return // 妯″瀷鍥炵瓟鏈熼棿绂佹鏂板浼氳瘽 this.isAtNewConversation = true this.currentConversation = { - id: randomUUID(), - title: '', + id: '', messages: [], stream: true, - max_tokens: 500, - iconVisible: false, - inputVisible: false, - deletePopVisible: false + max_tokens: 500 } // 鏂板缓浼氳瘽鏃跺彇娑堝師鍏堣閫変腑鐨勫巻鍙插璇濓紝鏇存竻鏅板憡璇夌敤鎴风幇鍦ㄧ晫闈㈠浜庢柊寤哄璇濅腑 if (this.activeHistoryIndex !== null) this.activeHistoryIndex = null - this.textareaPlaceholder = '璇峰皾璇曢棶鎴戯細浣犳槸璋侊紵' + }, + + /* 璋冪敤鎺ュ彛鑾峰彇褰撳墠浼氳瘽璁板綍 */ + getConversationByApi(id) { + // TODO 鏍规嵁鐐瑰嚮鐨勫巻鍙蹭細璇滻D鑾峰彇瀵瑰簲鍘嗗彶浼氳瘽鐨勫璇濊褰曞垪琛� + getCurrentConversationApi({ id }) + .then(res => { + console.log('currentRes', res) + if (res.success && res.result) { + this.currentConversation.messages = res.result.map(item => { + return { + id: item.id, + role: item.aiType === 2 ? 'user' : 'assistant', + content: item.aiType === 2 ? item.problem : item.answer + } + }) + this.scrollToConversationContainerBottom() + this.currentConversation.id = res.result[0].parentId + if (this.isModelResponding) this.isModelResponding = false + if (res.result[res.result.length - 1].aiType === 2) { + console.log('瑙﹀彂鍚戞ā鍨嬫彁闂�', res.result) + this.askToLanguageModel() + } + } + }) + }, + + addNewConversationByApi(params) { + this.inputQuestion = '' + // TODO 璋冪敤鍚庣鎺ュ彛淇濆瓨褰撳墠闂涓斿垱寤轰竴鏉″巻鍙蹭細璇濊褰曪紝鐒跺悗鍐嶉噸鏂拌皟鐢ㄨ幏鍙栧巻鍙茶褰曞垪琛ㄦ帴鍙e埛鏂板垪琛� + addNewConversationApi(params) + .then(res => { + if (res.success) { + switch (+params.aiType) { + case 1: + this.getChatHistoryListByApi() + this.$message.success('浼氳瘽鍒楄〃璁板綍' + res.message) + break + case 2: + this.getConversationByApi(this.activeHistoryIndex) + this.$message.success('鏂板浼氳瘽鍐呭闂璁板綍' + res.message) + break + case 3: + this.getConversationByApi(this.activeHistoryIndex) + // this.currentConversation.messages[this.currentConversation.messages.length - 1].content += '\n' + '瀵硅瘽缁撴潫' + this.$message.success('鏂板浼氳瘽鍐呭绛旀璁板綍' + res.message) + break + } + } else { + this.$message.error(res.message) + } + }) + }, + + /* 鍚戞ā鍨嬫彁闂� */ + sendQuestion(event) { + //鐩戞祴鏄惁鎸変笅shift閿� + if (!event.shiftKey) { + event.preventDefault() + if (this.isModelResponding) { + this.$message.error('璇风瓑寰呮満鍣ㄤ汉鍥炲鍚庡啀鍙戦�佸摝~') + return + } + if (!this.inputQuestion) { + this.$message.error('浣犳病鏈夎緭鍏ュ唴瀹瑰摝') + return + } + + const params = { + problem: this.inputQuestion, + aiType: '' + } + if (this.isAtNewConversation) { + params.aiType = 1 + params.parentId = '' + } else { + params.aiType = 2 + params.parentId = this.activeHistoryIndex + } + this.addNewConversationByApi(params) + } + }, + + askToLanguageModel() { + const messages = JSON.parse(JSON.stringify(this.currentConversation)) + const answer = { + id: '', + role: 'assistant', + content: '' + } + this.currentConversation.messages.push(answer) + let lastElement + this.$nextTick(() => { + const elementArr = document.querySelectorAll('.single-conversation') + lastElement = elementArr[elementArr.length - 1] + console.log('elementArr', elementArr) + }) + console.log('beforeAnswerConversation', messages) + console.log('this.currentConversation', this.currentConversation) + this.isModelResponding = true + // 鍙戦�丳OST璇锋眰鍒版ā鍨嬶紝鑾峰彇鍝嶅簲娴� + askToLanguageModelApi(messages) + .then(async (response) => { + if (!response.body) return + + const reader = response.body.pipeThrough(new TextDecoderStream()).getReader() + // const decoder = new TextDecoder() + // console.log(reader) + let discontinuousJsonArray = [] + let isContinuous = null + + while (true) { + const { value, done } = await reader.read() + if (done) { + const params = { + parentId: this.activeHistoryIndex, + answer: this.currentConversation.messages.find(item => !item.id && item.role === 'assistant').content, + aiType: 3 + } + this.addNewConversationByApi(params) + break + } + + this.scrollToConversationContainerBottom() + const objectArray = parsePack(value) + // console.log('objectArray', objectArray) + if (Array.isArray(objectArray) && objectArray.length > 0) { + if (discontinuousJsonArray.length === 2) discontinuousJsonArray = [] + objectArray.forEach(json => { + if (!json.choices || json.choices.length === 0) { + return + } + const text = json.choices[0].delta.content + this.currentConversation.messages.find(item => !item.id && item.role === 'assistant').content += text + }) + if (isContinuous) { + discontinuousJsonArray = [] + isContinuous = null + } + } + } + + // 閫掑綊鎵惧埌DOM涓嬫渶鍚庝竴涓厓绱犺妭鐐� + function parsePack(str) { + const pattern = /data:\s*(?!\[DONE\])(\{.*?\})\s*\n/g + const result = [] + let match + while ((match = pattern.exec(str)) !== null) { + const jsonStr = match[1] + console.log('jsonStr', jsonStr) + try { + const object = JSON.parse(jsonStr) + if (object) result.push(object) + } catch (err) { + console.log('err', err) + } + } + + // 姝ゅ垽鏂鐞嗚繑鍥炵殑涓嶅畬鏁寸殑鏁扮粍 + if (match = pattern.exec(str) === null) { + isContinuous = false + // console.log('str', str) + // 姝ゅ涓哄睆钄借繑鍥炲甫鏈塸ing瀛楃涓� + if (!str.includes('ping')) { + discontinuousJsonArray.push(str) + // 鍒ゆ柇鏉′欢涓�2鏄敱浜庝笉瀹屾暣鏁扮粍浠呯粡杩�2娆¤繑鍥炲�煎氨鍙互鎷兼帴瀹屾暣锛屼絾杩樻槸涓嶅簲璇ョ敤鏁板瓧浣滀负鍒ゆ柇鏉′欢锛屼互闃蹭笉姝�2娆� + if (discontinuousJsonArray.length === 2) { + // console.log('discontinuousJsonArray', discontinuousJsonArray[0], '---', discontinuousJsonArray[1]) + const discontinuousMatch = pattern.exec(discontinuousJsonArray[0] + discontinuousJsonArray[1]) + discontinuousJsonArray = [JSON.parse(discontinuousMatch[1])] + isContinuous = true + return discontinuousJsonArray + } + } + } + return result + } + }) + .catch(error => { + console.error('璇锋眰澶辫触:', error) + }) + }, + + /* 鍒囨崲鑷冲綋鍓嶇偣鍑讳細璇� */ + switchToCurrentConversation(record, event = {}) { + if (record.id === this.activeHistoryIndex) return // 閬垮厤閲嶅鐐瑰嚮 + if (event.target && event.target.type === 'checkbox') return //鐐瑰嚮澶氶�夋寜閽伩鍏嶄紶閫掔粰姝や簨浠� + if (record.inputVisible) return // 褰撴潯浼氳瘽姝e湪琚慨鏀规椂鍐嶆鐐瑰嚮鏈潯浼氳瘽鏃犲弽棣� + // 鍏抽棴鐐瑰嚮缂栬緫鎸夐挳鍚庣殑杈撳叆妗� + if (this.editingHistoryIndex !== null && this.editingHistoryIndex !== record.id) this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex)) + // 鍏抽棴鎵�鏈夌‘璁ゅ垹闄ゅ脊绐� + if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex)) + if (this.isAtNewConversation) this.isAtNewConversation = false // 濡傛灉鍦ㄥ垱寤烘柊瀵硅瘽鐣岄潰鍒欏皢鏂板璇濈晫闈㈠叧闂� + if (this.isModelResponding) return // 妯″瀷鍥炵瓟鏈熼棿绂佹鍒囨崲浼氳瘽 + + this.activeHistoryIndex = record.id + this.getConversationByApi(record.id) }, /* 鐐瑰嚮鍏ㄩ�夋寜閽悗鏀瑰彉鍕鹃�夊悗瑙﹀彂 */ @@ -263,7 +476,7 @@ } else { this.checkedConversationIdList = [] } - console.log('瑙﹀彂鍏ㄩ��', event.target.checked) + console.log('瑙﹀彂鍏ㄩ��', this.checkedConversationIdList) }, /* 鐐瑰嚮鍘嗗彶璁板綍涓閫夋鏀瑰彉鍕鹃�夊悗瑙﹀彂 */ @@ -298,6 +511,7 @@ /* 鐐瑰嚮绾㈣壊鍥炬爣鎵归噺鍒犻櫎鎸夐挳鍚庤Е鍙� */ deleteBatchConversation() { if (!this.checkedConversationIdList.length) return + if (this.isModelResponding) return // 妯″瀷鍥炵瓟鏈熼棿绂佹鍒犻櫎浼氳瘽 this.deleteBatchPopVisible = !this.deleteBatchPopVisible }, @@ -326,23 +540,6 @@ this.checkedConversationIdList = [] }, - /* 鍒囨崲鑷冲綋鍓嶇偣鍑讳細璇� */ - switchToCurrentConversation(record, event = {}) { - if (event.target && event.target.type === 'checkbox') return //鐐瑰嚮澶氶�夋寜閽伩鍏嶄紶閫掔粰姝や簨浠� - if (record.inputVisible) return // 褰撴潯浼氳瘽姝e湪琚慨鏀规椂鍐嶆鐐瑰嚮鏈潯浼氳瘽鏃犲弽棣� - // 鍏抽棴鐐瑰嚮缂栬緫鎸夐挳鍚庣殑杈撳叆妗� - if (this.editingHistoryIndex !== null && this.editingHistoryIndex !== record.id) this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex)) - // 鍏抽棴鎵�鏈夌‘璁ゅ垹闄ゅ脊绐� - if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex)) - - this.activeHistoryIndex = record.id - this.currentConversation = this.chatHistoryList.find(item => item.id === record.id) - this.isAtNewConversation = false - - // 鍒囨崲瀵硅瘽鏃舵洿鏀规彁闂緭鍏ユ鎻愮ず鏂囧瓧 - if (record.messages.length > 0) this.textareaPlaceholder = 'Enter鍙戦�侊紝Shift+Enter鎹㈣' - }, - /* 鐐瑰嚮缂栬緫浼氳瘽鏍囬鎸夐挳鏃惰Е鍙� */ editConversationTitle(record) { // 浠呭紑鍚渶鍚庝竴娆$偣鍑荤紪杈戞寜閽悗鐨勮緭鍏ユ @@ -352,7 +549,7 @@ this.editingHistoryIndex = record.id record.inputVisible = true - this.editedConversationTitle = record.title + this.editedConversationTitle = record.problem this.$nextTick(() => document.getElementById('edit-input').focus()) }, @@ -365,42 +562,49 @@ } // 浠呭彲浣跨敤鏈�鍚庝竴娆$偣鍑诲垹闄ゆ寜閽殑鍔熻兘 if (this.deletingHistoryIndex !== null && this.deletingHistoryIndex !== record.id) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex)) - + if (this.isModelResponding) return // 妯″瀷鍥炵瓟鏈熼棿绂佹鍒犻櫎浼氳瘽 record.deletePopVisible = !record.deletePopVisible this.deletingHistoryIndex = record.id }, /* 纭缂栬緫浼氳瘽鏍囬 */ confirmEditConversationTitle(record, event) { + // TODO 璋冪敤缂栬緫浼氳瘽鎺ュ彛骞堕噸鏂拌幏鍙栧巻鍙蹭細璇濇暟鎹� record.title = this.editedConversationTitle this.cancelEditConversationTitle(record, event) }, /* 纭鍒犻櫎浼氳瘽鏃惰Е鍙� */ confirmDeleteConversation(record, index) { - this.chatHistoryList = this.chatHistoryList.filter(item => item.id !== this.deletingHistoryIndex) - - if (this.chatHistoryList.length > 0) { - // 鍒ゆ柇褰撳墠浼氳瘽鏄笉鏄鍒犻櫎鐨勪細璇� - if (this.activeHistoryIndex === record.id) { - if (this.chatHistoryList[index]) { - console.log('鍒犻櫎闈炴渶鍚庝竴鏉�') - this.currentConversation = this.chatHistoryList[index] - this.activeHistoryIndex = this.chatHistoryList[index].id - } else { - console.log('鍒犻櫎鏈�鍚庝竴鏉�') - this.currentConversation = this.chatHistoryList[this.chatHistoryList.length - 1] - this.activeHistoryIndex = this.chatHistoryList[this.chatHistoryList.length - 1].id + deleteSingleChatHistoryApi({ id: record.id }) + .then(res => { + if (res.success) { + if (this.chatHistoryList.length !== 1) { + // 鍒ゆ柇褰撳墠浼氳瘽鏄笉鏄鍒犻櫎鐨勪細璇� + console.log('record', record) + console.log('activeHistoryIndex', this.activeHistoryIndex) + if (this.activeHistoryIndex === record.id) { + if (index !== 0) { + console.log('鍒犻櫎闈炵涓�鏉¤褰�') + this.switchToCurrentConversation(this.chatHistoryList[index - 1]) + } else { + console.log('鍒犻櫎绗竴鏉¤褰�') + this.switchToCurrentConversation(this.chatHistoryList[index + 1]) + } + } + } else { + console.log('鍒犻櫎鏈�鍚庝竴鏉¤褰�') + this.activeHistoryIndex = null + } + record.deletePopVisible = false + this.deletingHistoryIndex = null + this.getChatHistoryListByApi() + this.$message.success(res.message) } - } - } else { - console.log('鍒犻櫎鍓嶅彧鏈変竴鏉�') - this.activeHistoryIndex = null - this.createNewConversation() - } - record.deletePopVisible = false - this.deletingHistoryIndex = null - this.$message.success('鍒犻櫎鎴愬姛锛�') + }) + .catch(err => { + this.$message.error(err.message) + }) }, /* 鍙栨秷缂栬緫浼氳瘽鏍囬鏃惰Е鍙� */ @@ -414,7 +618,7 @@ /* 鍙栨秷鍒犻櫎浼氳瘽鏃惰Е鍙� */ cancelDeleteConversation(record, event) { // 澶卞幓鐒︾偣浜嬩欢鏃惰嫢鐐瑰嚮鐨勫厓绱犳槸纭鍒犻櫎鎸夐挳鍒欎笉杩涜澶卞幓鐒︾偣浜嬩欢锛岀洿鎺ヨ繘鍏ョ‘璁ゅ垹闄や簨浠� - if (event.relatedTarget && event.relatedTarget.id === 'delete-conversation-button') return + if (event && event.relatedTarget && event.relatedTarget.id === 'delete-conversation-button') return record.deletePopVisible = false this.deletingHistoryIndex = null }, @@ -424,55 +628,20 @@ return getFileAccessHttpUrl(this.avatar()) }, - /* 鍚戞ā鍨嬫彁闂� */ - sendQuestion(e) { - //鐩戞祴鏄惁鎸変笅shift閿� - if (!e.shiftKey) { - e.preventDefault() - if (this.isResponding) { - this.$message.error('璇风瓑寰呮満鍣ㄤ汉鍥炲鍚庡啀鍙戦�佸摝~') - return - } - if (!this.inputQuestion) { - this.$message.error('浣犳病鏈夎緭鍏ュ唴瀹瑰摝') - return - } - - const newQuestion = { - role: 'user', - content: this.inputQuestion - } - this.currentConversation.messages.push(newQuestion) - - // 褰撴柊寤哄璇濇椂闇�鍏堟彁闂啀璁插璇濆姞鍏ュ埌鍘嗗彶璁板綍涓� - if (this.currentConversation.messages.length === 1) { - this.currentConversation.title = newQuestion.content.slice(0, 15) - this.chatHistoryList.unshift(this.currentConversation) - if (this.isDeletingBatch) this.singleHistoryCheckedChange() - this.switchToCurrentConversation(this.currentConversation) - } - - this.isResponding = true - const response = { - role: 'assistant', - content: '杩欎釜闂鎴戜篃涓嶅お娓呮' - } - setTimeout(() => { - this.currentConversation.messages.push(response) - this.inputQuestion = '' - this.isResponding = false - this.$nextTick(() => { - this.conversationContainer.scrollTo({ top: 9999999999999999999999999999, behavior: 'smooth' }) - }) - }, 1000) - } + scrollToConversationContainerBottom(scrollBehavior = 'auto') { + this.$nextTick(() => { + this.conversationContainer.scrollTo({ + top: this.conversationContainer.scrollHeight, + behavior: scrollBehavior + }) + }) } } } </script> <style scoped lang="less"> - @main-container-background: rgba(255, 255, 255, .8); + @main-container-background: rgba(255, 255, 255, .7); @container-border-radius: 12px; @container-padding: 10px; @single-history-edit-border: 3px solid #ABC0CC; @@ -564,6 +733,13 @@ margin-right: 10px; } } + + &.disable-expand { + cursor: not-allowed; + &:hover { + box-shadow: none; + } + } } .delete-batch-container { @@ -633,7 +809,14 @@ flex: 1; overflow: auto; - & > div { + .ant-empty { + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + } + + & > div:not(.ant-empty) { border: 3px solid transparent; border-radius: 10px; padding: 10px 20px; @@ -714,6 +897,14 @@ } } + } + + &.disable-switch { + cursor: not-allowed; + + &:not(.single-history-active):hover { + background-color: transparent; + } } } } @@ -866,16 +1057,20 @@ &.user-question { align-items: flex-end; - .content { + .conversation-content { background-color: @user-question-background; + text-align: justify; + text-align-last: left; } } &.assistant-answer { align-items: flex-start; - .content { + .conversation-content { background-color: @assistant-answer-background; + text-align: justify; + text-align-last: left; } } @@ -889,7 +1084,7 @@ } } - .content { + .conversation-content { max-width: 80%; box-shadow: @conversation-content-container-box-shadow; border-radius: @container-border-radius; -- Gitblit v1.9.3