| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867 |
- <template>
- <div class="conversation-chat-container">
- <div class="conversation-chat-main" ref="chat_scrren_container">
- <div class="conversation-chat-main-left"></div>
- <div class="conversation-chat-main-content" :style="style_conversation_chat_content">
- <DialogHeader
- v-if="!show_welcome && !is_init_model"
- class="conversation-chat-header"
- :agent_name="current_agent_name"
- :style="style_header"
- />
- <div class="conversation-chat-content" :style="style_body">
- <div class="conversation-chat-main-container" :style="style_conversation_chat_main_container">
- <template v-if="show_welcome">
- <!-- 有会话ID 获取历史记录,显示加载中状态 -->
- <!-- <div v-if="session_id" class="conversation-chat-area history-list-loading"> -->
- <!-- <div class="scroll-left"></div> -->
- <!-- <div class="history-list-loading-container"><a-spin /></div> -->
- <!-- <div class="scroll-right"></div> -->
- <!-- </div> -->
- <!-- 无会话ID,直接对话,此时可现实欢迎消息:欢迎使用报表合并、欢迎使用文档智能、欢迎使用小数绘图 -->
- <!-- <DialogWelcome v-if="!session_id" class="conversation-chat-area" /> -->
- <DialogWelcome class="conversation-chat-area" />
- </template>
- <DialogList
- v-if="!show_welcome"
- ref="list_scroller"
- class="conversation-chat-area"
- :height="list_height"
- :width="chat_width / 2"
- :agent_id="agent_id"
- :list="chat_display_list"
- :suggestion="chat_suggestion"
- :answer_action_list="answer_action_list"
- :is_show_right_page="show_right"
- @share="handleChatShare"
- @edit="handleEditChat"
- @retry="handleRetryChat"
- @toSearchPage="toSearchPage"
- @toShowMindMap="toShowMindMap"
- @send="handleSendChat"
- @submit="handleSuggestSubmit"
- :style="style_conversation_chat_list"
- >
- <!-- <template v-slot:left>
- <div class="scroll-left"></div>
- </template>
- <template v-slot:right>
- <div class="scroll-right"></div>
- </template> -->
- </DialogList>
- </div>
- <DialogInput
- v-show="!is_init_model"
- ref="dialog_input"
- class="conversation-chat-input"
- :style="style_conversation_chat_list"
- :ask_input_text="ask_input_text"
- :disabled="input_disabled"
- :enable_text_input="enable_text_input"
- :enable_file_upload="enable_file_upload"
- :file_accept="file_accept"
- :agent_id="agent_id"
- @sizeChange="handleInputSizeChange"
- @actionConfigChange="handleActionConfigChange"
- @submit="handleInputSubmit"
- >
- <template v-if="show_input_others_opts" v-slot:top>
- <DialogInputTop
- :user_input_form="conversation_params.user_input_form"
- @initModel="initModel"
- ref="dialog_input_top"
- />
- </template>
- <template v-slot:top>
- <DialogStopSse v-if="show_stop_sse" @stopResponse="stopResponse"></DialogStopSse>
- </template>
- </DialogInput>
- <DialogCommonUsed
- v-if="show_welcome"
- :style="style_conversation_chat_list"
- @updateAskTxt="updatAskTxt"
- ></DialogCommonUsed>
- </div>
- <DialogFooter v-show="!is_init_model" class="conversation-chat-footer" :style="style_footer" />
- </div>
- <div class="conversation-chat-main-right" :style="style_conversation_chat_right">
- <div class="conversation-chat-expand" :style="style_conversation_chat_expand" v-if="is_show_right_page">
- <div class="conversation-chat-mind-map" ref="fullScreen_mindMap">
- <!-- 全屏时显示的退出按钮 -->
- <button v-if="isFullScreen" class="exit-button" @click="exitFullScreen">X</button>
- <MindMap
- v-if="show_mind_map"
- ref="mind_map"
- :content="mindMap_content"
- :box_style="box_style"
- :svg_style="svg_style"
- @extend="extendMindMap"
- ></MindMap>
- <div class="mind_map_error" v-if="mindMap_err.length">{{ mindMap_err }}</div>
- <div class="conversation-chat-mind-map-tools">
- <ConversationChatMindMapTools
- :isFullScreen="isFullScreen"
- @toZoomIn="zoomIn"
- @toZoomOut="zoomOut"
- @toZoomReset="zoomReset"
- @toDownload="downloadMap"
- @toFullScreen="toFullScreen"
- @toExitFullScreen="exitFullScreen"
- ></ConversationChatMindMapTools>
- </div>
- </div>
- <div class="conversation-chat-mind-map-spin" v-if="loading_mind_map">
- <a-spin tip="加载中..."></a-spin>
- </div>
- <div class="conversation-chat-web-page" v-if="show_web_page">
- <ConversationChatWebPage :search_list="search_list" @toClose="closeWebPage"></ConversationChatWebPage>
- </div>
- </div>
- <div class="conversation-chat-expand" v-if="show_word_viewer">
- <ConversationChatWordViewer :edit_txt="edit_txt_value" @close="closeChatWord"></ConversationChatWordViewer>
- </div>
- </div>
- </div>
- <ChatAsideExpandBtn v-if="show_right_page_btn" @toggleRight="toggleRight"></ChatAsideExpandBtn>
- </div>
- </template>
- <script setup>
- import { ref, onMounted, onUnmounted, watch, computed, nextTick } from 'vue';
- import { useI18n } from 'vue-i18n';
- import { marked } from 'marked';
- // import { Message } from '@arco-design/web-vue';
- import { Message } from '../../3rd-libs/arco-vue-libs';
- import { jsonStringify } from '../../utils/utils';
- import DialogHeader from '../../modules/conversation-chat/DialogHeader.vue';
- import DialogWelcome from '../../modules/conversation-chat/DialogWelcome.vue';
- import DialogList from '../../modules/conversation-chat/DialogList.vue';
- import DialogInput from '../../modules/conversation-chat/DialogInput.vue';
- // import DialogInputAttachedAttrs from '../../modules/conversation-chat/DialogInputAttachedAttrs.vue';
- import DialogInputTop from '../../modules/conversation-chat/DialogInputTop.vue';
- import DialogFooter from '../../modules/conversation-chat/DialogFooter.vue';
- import ChatAsideExpandBtn from '../../modules/conversation-aside/ChatAsideExpandBtn.vue';
- import MindMap from '../../components/MindMap.vue';
- import ConversationChatMindMapTools from '../../modules/conversation-aside/Conversation-chat-mind-tools.vue';
- import ConversationChatWebPage from '../../modules/conversation-aside/Conversation-chat-web-page.vue';
- import DialogCommonUsed from '../../modules/conversation-chat/DialogCommonUsed.vue';
- import DialogStopSse from '../../modules/conversation-chat/DialogStopSse.vue';
- import useWebSocketChat from '../../modules/conversation-dialog/use-websocket-chat';
- import useFetchEventSource from '../../modules/conversation-dialog/use-sse-chat';
- import {
- getHistoryLogs,
- getDialogChatId,
- uploadFileByAgentInfo,
- uploadNewChatInfo,
- getMindMapData,
- getMapById
- } from '../../modules/conversation-dialog/api-dialog';
- import formatDialogSendOptions from '../../modules/conversation-dialog/format-dialog-send-options';
- import formatDialogSendSseOptions from '../../modules/conversation-dialog/format-dialog-send-sse-options';
- import formatDialogHistory from '../../modules/conversation-dialog/format-dialog-history';
- import formatDialogQuestionByClient from '../../modules/conversation-dialog/format-dialog-question-by-client';
- import formatDialogAnswerForLoading from '../../modules/conversation-dialog/format-dialog-answer-for-loading';
- import formatDialogAnswerForException from '../../modules/conversation-dialog/format-dialog-answer-for-exception';
- import formatDialogAnswerFromWebsocketReceiveMessage from '../../modules/conversation-dialog/format-dialog-answer-from-websocket_receive_message';
- import formatDialogAnswerFromSseReceiveMessage from '../../modules/conversation-dialog/format-dialog-answer-from-Sse_receive_message';
- import ConversationChatWordViewer from './ConversationChatWordViewer.vue';
- import useEleSizeV1 from '../../utils/use-ele-size-v1';
- import useInputClear from './use-input-clear';
- import useInputGetOptions from './use-input-get-options';
- import useScroll2Bottom from './use-scroll-bottom';
- import { IconEye } from '@arco-design/web-vue/es/icon';
- import { file, files } from 'jszip';
- import { getFileType } from '../../modules/form-dynamic/file-accept';
- const props = defineProps({
- /**
- * 智能体的ID
- * 此参数新对话中不存在
- */
- agent_id: String,
- /**
- * 智能体的一些关键信息
- */
- CHAT_AGENT_INFOMATION: Object,
- /**
- * 会话ID
- * 如果有此参数,则意味着获取该对话的记录内容
- */
- session_id: String,
- chat_history: String,
- /**
- * 动态表单数据
- * 根据智能体的agent_id 获取到动态表单数据
- * */
- conversation_params: Object
- });
- const emit = defineEmits(['updateSessionId']);
- const i18n = useI18n();
- /**
- * input的一些操作方法
- */
- const inputClearFn1 = useInputClear('dialog_input'); // 主表单清空
- const inputClearFn2 = useInputClear('dialog_input_top'); // 顶部附加表单的数据
- const getInputTopOptions = useInputGetOptions('dialog_input_top'); // 获取附加表单参数的方法
- /**
- * 对话区域滚动到底部
- */
- const scroll2Bottom = useScroll2Bottom('list_scroller');
- const scroll2ListBottom = () => {
- nextTick(() => {
- scroll2Bottom();
- });
- };
- /**
- * 整个对话区域的一些尺寸定义
- */
- const header_height = 30;
- const footer_height = 30;
- const input_height = ref(100);
- /**
- * 获取到对话区域的宽度和高度
- */
- const { width: chat_width, height: chat_height } = useEleSizeV1('chat_scrren_container');
- /**
- * 对话列表区域的高度
- */
- const list_height = computed(() => {
- return chat_height.value - header_height - footer_height - input_height.value - 20;
- });
- const input_style = computed(() => {
- return {
- // height: input_height + 'px'
- };
- });
- const style_header = computed(() => {
- return { height: header_height + 'px' };
- });
- const style_body = computed(() => {
- return { height: chat_height - 30 - 30 + 'px' };
- });
- const style_footer = computed(() => {
- return { height: footer_height + 'px' };
- });
- const style_conversation_chat_content = computed(() => {
- if (is_show_right_page.value || show_word_viewer.value) {
- return {
- width: 55 + '%'
- };
- } else {
- return {
- width: 100 + '%'
- };
- }
- });
- const style_conversation_chat_right = computed(() => {
- if (is_show_right_page.value || show_word_viewer.value) {
- return {
- width: 35 + '%',
- transition: 'width 0.2s ease'
- };
- } else {
- return {
- width: 0,
- transition: 'width 0.2s ease'
- };
- }
- });
- const style_conversation_chat_expand = computed(() => {
- if (loading_mind_map.value) {
- return {
- position: 'relative'
- };
- } else {
- return {
- position: ''
- };
- }
- });
- const style_conversation_chat_main_container = computed(() => {
- if (!show_welcome.value) {
- return {
- height: 80 + '%',
- transition: 'all 0.2s ease'
- };
- } else {
- return {
- height: 20 + '%',
- transition: 'all 0.2s ease'
- };
- }
- });
- const style_conversation_chat_list = computed(() => {
- if (is_show_right_page.value || show_word_viewer.value) {
- return {
- paddingRight: 3 + '%',
- paddingLeft: 3 + '%',
- boxSizing: 'border-box'
- };
- } else {
- return {
- paddingRight: 20 + '%',
- paddingLeft: 20 + '%',
- boxSizing: 'border-box'
- };
- }
- });
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- /**
- * 对话数据列表
- */
- const chat_log_list = ref([]); // 历史对话的数据列表
- const chat_new_list = ref([]); // 新对话的数据列表
- const chat_suggestion = ref([]); // 对话推荐项目
- /**
- * 当前对话使用的ID
- * 当用户有输入后,点击提交,此时创建新对话,新对话的ID为此ID
- * 之后用户可以一直使用此ID进行对话。
- */
- const chat_round_id = ref(null);
- /**
- * 对话发起的次数记录
- * 用户每发起一次会话,此值会加1input_disable
- */
- const chat_round_sent_count = ref(0);
- /**
- * 新对话,客户端的提问数据
- * 用以临时保存客户端的提问数据
- * 每当用户确认进行提问时,将新提问赋给此值
- * 一旦对话消息通过websocket发送到服务器,此值可清空
- */
- const chat_new_question = ref({});
- /**
- * 界面展示的对话列表
- * 当用户从历史会话进入时,历史会话记录有数据,当用户基于历史会话进行对话时,新会话也有数据,
- * 当用户从agent进入时,仅有新会话,没有历史会话
- *
- * 页面渲染的会话列表是 历史会话 + 新会话数据
- */
- const chat_display_list = computed(() => {
- return [].concat(chat_log_list.value, chat_new_list.value);
- });
- /**
- * 是否禁用输入组件
- */
- const input_disabled = ref(false);
- /**
- * 是否显示停止按钮
- * */
- const show_stop_sse = ref(false);
- /**
- * 菜单ID编号
- * 1 报表合并
- * 2 知识问答
- * 3 文档智能
- * 4 智能问答
- * 5 智能数据
- * 6 小数绘图
- * 7 文档出卷
- * 8 出题组卷
- * 9 文档报告
- */
- const current_menu_id = computed(() => {
- const agent = props.CHAT_AGENT_INFOMATION.agent;
- const menu_id = agent.menuId / 1;
- return menu_id;
- });
- const current_agent_name = computed(() => {
- const agent = props.CHAT_AGENT_INFOMATION.agent;
- const name = agent.name || '新会话';
- return name;
- });
- const current_agent_mode = computed(() => {
- const agent = props.CHAT_AGENT_INFOMATION.agent;
- const mode = agent.mode;
- return mode;
- });
- /**
- * 表单区域:是否显示附加参数表单
- *
- * 根据动态表单返回的数据中user_input_form中是否有数据来控制是否显示附加参数表单
- */
- const show_input_others_opts = computed(() => {
- if (
- props.conversation_params &&
- props.conversation_params.user_input_form &&
- props.conversation_params.user_input_form.length
- ) {
- return true;
- }
- return false;
- // const menu_id = current_menu_id.value;
- // /**
- // * 7 文档出卷
- // * 9 文档报告
- // */
- // if (menu_id === 7 || menu_id === 9) {
- // return true;
- // }
- // return false;
- });
- /**
- * 是否支持文本输入
- * 返回 true,输入区域将不存在文本输入框
- * 返回 false,输入区域将可以进行文本输入
- *
- *通过conversation_params.retriever_resource.enabled来控制是否支持文本输入
- */
- const enable_text_input = computed(() => {
- let enabled = false;
- if (props.conversation_params && props.conversation_params.retriever_resource) {
- enabled = props.conversation_params.retriever_resource.enabled;
- }
- return enabled;
- });
- /**
- * 对话文本是否必须
- * 此值如果为 true,则在发起对话之前,会进行 文本的存在性检查
- * 此值如果为 false,则在发起对话之前,不会进行 文件存在性检查
- */
- const is_chat_text_required = computed(() => {
- const is_enable = enable_text_input.value;
- if (!is_enable) {
- return false;
- }
- return true;
- });
- /**
- * 默认的文本值
- */
- const default_text_value = computed(() => {
- const menu_id = current_menu_id.value;
- /**
- * 某些情况下,无需输入文本
- * 但是在对话部分,需要展示用户的提问,此时可以给一个默认的文本值
- * 例如在报表合并情况下,仅需要上传文件,不需要输入文字
- */
- if (menu_id === 1) {
- return '合并Excel';
- }
- return '';
- });
- /**
- * 表单区域:是否允许文件上传
- * 返回 ture,输入区域将会有文件上传按钮
- * 返回 false,输入区域将没有文件上传按钮
- *
- * 根据 conversation_params.file_upload.enabled来控制是否允许文件上传
- */
- const enable_file_upload = computed(() => {
- let enabled = false;
- if (props.conversation_params && props.conversation_params.file_upload) {
- enabled = props.conversation_params.file_upload.enabled;
- }
- return enabled;
- });
- /**
- * 对话文件是否必须上传
- * 此值如果返回 true,则 在对话时,会进行文件检查
- * 此值如果返回 false,则 在对话时,不会检查文件的存在性
- */
- const is_chat_file_required = computed(() => {
- const is_enable = enable_file_upload.value;
- if (!is_enable) {
- return false;
- }
- const menu_id = current_menu_id.value;
- // 报表合并: 文件必须
- if (menu_id === 1) {
- // 当第一次会话时,要求必须上传文件
- // 非第一次,不做要求
- if (chat_round_sent_count.value === 0) {
- return true;
- }
- }
- // 文档出卷:文件必须上传
- if (menu_id === 7) {
- // 当第一次对话时,必须上传文件,
- // 非第一次,不做要求
- if (chat_round_sent_count.value === 0) {
- return true;
- }
- }
- return false;
- });
- /**
- * 此值在 enable_file_upload === true 的前提下有效
- * 表单区域:文件上传允许的文件类型
- * 对应表单参数的 accept
- */
- const file_accept = computed(() => {
- const menu_id = current_menu_id.value;
- /**
- * 1 报表合并:上传几个文档,进行合并 允许 .xlsx
- * 3 文档智能:上传文档,让智能体进行解析 允许: .pdf/.docx
- * 5 智能数据:上传Excel,生成饼状图 允许 .xlsx
- * 6 小数绘图:上传图片,描述图片的内容 允许 .png/jpg/jpeg
- * 9 文档报告: 允许 .docx
- */
- if (menu_id === 1) {
- return '.xlsx';
- }
- if (menu_id === 3) {
- /**
- * 2025-2-8 16:50
- * 王永新和赵源在测试deepseek时发现 文档智能 能上传的文件类型有限
- * 要求将accept调整为和dify的 文档 类型一致
- */
- // return '.pdf,.docx';
- return '.txt,.md,.markdown,.pdf,.html,.xlsx,.xls,.docx,.csv,.eml,.msg,.pptx,.ppt,.xml,.epub';
- }
- // 智能数据
- if (menu_id === 5) {
- return '.xlsx,.xls,.csv';
- }
- if (menu_id === 6) {
- return '.jpg,.jpeg,.png';
- }
- if (menu_id === 9) {
- return '.docx';
- }
- return '*';
- });
- /**
- * 答案可用的操作按钮
- * 可用的值有 [] 或者 ['copy']
- * 后续可能有新值添加
- */
- const answer_action_list = computed(() => {
- const menu_id = current_menu_id.value;
- // 报表合并无操作按钮
- if (menu_id === 1) {
- return [];
- }
- return ['copy', 'retry', 'edit', 'download'];
- });
- /**
- * 控制对话列表滚动条展示
- * 当右侧有页面打开,隐藏滚动条
- *
- */
- const show_right = computed(() => {
- return is_show_right_page.value || show_word_viewer.value;
- });
- /**
- * 内容分享操作
- * @param chat_id
- */
- const handleChatShare = (chat_id) => {};
- const show_word_viewer = ref(false);
- // 要编辑的文本内容
- const edit_txt_value = ref('');
- const closeChatWord = () => {
- show_word_viewer.value = false;
- };
- // 更新输入框中的文本
- const ask_input_text = ref('');
- //
- const updatAskTxt = (txt) => {
- ask_input_text.value = txt;
- };
- /**
- * 编辑文本
- * */
- const handleEditChat = (item) => {
- // edit_txt_value.value = marked(item.answer || '');
- edit_txt_value.value = item.answer;
- is_show_right_page.value = false;
- show_word_viewer.value = true;
- };
- const retry_action_option = ref(null);
- const handleActionConfigChange = (config) => {
- retry_action_option.value = config;
- };
- /**
- * 重新生成
- * */
- const handleRetryChat = async (item) => {
- //根据message_id查找对应的问题
- const question_idx = chat_display_list.value.findIndex(
- (it) => it.client_custom_chat_message_id === item.client_custom_chat_message_id
- );
- if (question_idx != -1) {
- const question_item = chat_display_list.value[question_idx - 1];
- let chatMode = retry_action_option.value?.chatMode || 1;
- let isDeep = retry_action_option.value?.isDeep || 1;
- if (question_item.client_custom_upload_file_list?.length) {
- chatMode = 1;
- }
- if (question_item.client_custom_knowledge_id?.length) {
- chatMode = 3;
- }
- const options = {
- files: question_item.client_custom_upload_file_list || [],
- text: question_item.question,
- config: {
- knowledgeId: question_item.client_custom_knowledge_id || [],
- isDeep,
- chatMode
- }
- };
- toSubmitNewChat(options);
- }
- };
- // 编辑问题重新问答
- const handleSendChat = async (item) => {
- let chatMode = retry_action_option.value?.chatMode || 1;
- let isDeep = retry_action_option.value?.isDeep || 1;
- let parent_id = '';
- const idx = chat_display_list.value.findIndex((it) => it.client_custom_unique_id === item.client_custom_unique_id);
- if (idx !== -1 && idx > 0) {
- parent_id = chat_display_list.value[idx - 1].parent_id || '';
- }
- if (item.client_custom_upload_file_list?.length) {
- chatMode = 1;
- }
- if (item.client_custom_knowledge_id?.length) {
- chatMode = 3;
- }
- if (item.client_custom_upload_file_list?.length) {
- chatMode = 1;
- }
- if (item.client_custom_knowledge_id?.length) {
- chatMode = 3;
- }
- const options = {
- files: item.client_custom_upload_file_list || [],
- text: item.content,
- parent_id,
- config: {
- knowledgeId: item.client_custom_knowledge_id || [],
- isDeep,
- chatMode
- }
- };
- toSubmitNewChat(options);
- };
- /**
- * 在聊天界面点击推荐项
- * 继续对话
- */
- const handleSuggestSubmit = (suggest) => {};
- /**
- * 处理页面中的错误消息
- * @param msg
- */
- const handleErrorMessage = (msg) => {
- Message.error({ content: msg, position: 'top' });
- };
- // ---------------------------------------------
- /**
- * 异常处理
- * 异常处理过程是一个会话模拟的过程
- * 先在界面上显示加载动画,然后紧接着显示错误提示
- * 让用户感知到智能体有处理数据的过程
- * 所以在异常处理阶段,有一些需要处理的关键点,比如欢迎界面的显示(如果在显示,则需要隐藏,否则对话显示不了)
- * @param exceptionInfo
- */
- const handleChatRequestionException = (exceptionInfo) => {
- // 已结束
- const answerData = formatDialogAnswerForException(props.CHAT_AGENT_INFOMATION, exceptionInfo);
- // 原来的最后一项弹出
- chat_new_list.value.pop();
- // 添加新的最后一项
- chat_new_list.value.push(answerData);
- // 对话已结束:文件上传、文本输入区域放开使用
- input_disabled.value = false;
- // 对话区域滚动到底部
- scroll2ListBottom();
- };
- /**
- * 输入区域的尺寸发生了变化
- * 整个对话区域的尺寸也需要依据此变化而变化
- * @param size
- */
- const handleInputSizeChange = (size) => {
- const input_width = size.width;
- // const input_height = size.height;
- setTimeout(() => {
- input_height.value = size.height;
- });
- };
- /**
- * 是否显示欢迎页
- * 当用户进入对话页面,还未正式开始对话时
- * 对话区域会显示欢迎内容
- * 当用户开始对话时,欢迎内容消失,对话列表开始展示
- */
- const show_welcome = ref(false);
- const mindMap_str = ref('');
- /**
- * mindMap组件对象
- *
- * */
- const mind_map = ref();
- /**
- * mindMap 显示的内容
- *
- * */
- const mindMap_content = ref('');
- const mindMap_err = ref('');
- /**
- * 图谱的查询 文本字段
- * */
- const mindMap_txt = ref('');
- const minMap_messageId = ref('');
- const fullScreen_mindMap = ref(null);
- const isFullScreen = ref(false);
- /**
- * mindMap 盒子的尺寸
- * */
- const box_style = computed(() => {
- if (is_show_right_page.value) {
- return {
- width: '100%',
- height: 'calc(100% - 30px)'
- };
- }
- });
- /**
- * mindMap 导图实际尺寸的尺寸
- * */
- const svg_style = computed(() => {
- if (is_show_right_page.value) {
- return {
- width: '100%',
- height: '100%'
- };
- }
- });
- /**
- * mindMap 展开按钮事件
- * node:当前node数据
- * full:全部node数据
- * el:当前点击的元素
- * */
- const extendMindMap = async (item) => {
- const { node, full, el } = item;
- mindMap_txt.value = decodeHtmlCharCodes(node.content);
- getMindMapData({ messageId: minMap_messageId.value, query: mindMap_txt.value }).then((res) => {
- if (res.code / 1 === 200) {
- mindMap_str.value = res.data.mindmap;
- mindMap_content.value = res.data.mindmap;
- } else {
- mindMap_content.value = mindMap_str.value;
- }
- });
- };
- // 转码函数 展开节点用到
- function decodeHtmlCharCodes(str) {
- const textarea = document.createElement('textarea');
- textarea.innerHTML = str;
- return textarea.value;
- }
- const is_show_right_page = ref(false); //控制右侧页面展示显示
- const show_mind_map = ref(false); //控制右侧思维导图是否显示
- const loading_mind_map = ref(false); //初始控制思维导图父盒子显示加载中
- const show_web_page = ref(false); //控制网页搜索展示
- // 关闭网页搜索
- const closeWebPage = () => {
- show_web_page.value = false;
- is_show_right_page.value = false;
- };
- // 展示右侧页面按钮
- const show_right_page_btn = computed(() => {
- return !show_word_viewer.value && !show_welcome.value;
- }); //控制右侧顶部按钮开关
- /**
- * 控制右侧显示/隐藏
- * */
- const toggleRight = () => {
- is_show_right_page.value = !is_show_right_page.value;
- if (is_show_right_page.value) {
- mindMap_content.value = mindMap_str.value;
- setTimeout(() => {
- show_mind_map.value = true;
- }, 200);
- show_web_page.value = true;
- } else {
- show_mind_map.value = false;
- show_web_page.value = false;
- }
- };
- /**
- * 放大
- * */
- const zoomIn = () => {
- mind_map.value.zoomIn();
- };
- /**
- * 缩小
- * */
- const zoomOut = () => {
- mind_map.value.zoomOut();
- };
- /**
- * 自适应
- * */
- const zoomReset = () => {
- mind_map.value.zoomReset();
- };
- const original_obj = ref({
- height: '',
- width: '',
- position: '',
- zIndex: ''
- }); // 用来存储原始高度
- /**
- * 全屏
- * */
- const toFullScreen = () => {
- if (isFullScreen.value) {
- return;
- }
- // 动态设置div高度为屏幕可见高度(排除浏览器头部)
- if (fullScreen_mindMap.value) {
- // 存储原始高度,进入全屏时恢复
- original_obj.value.height = fullScreen_mindMap.value.style.height;
- original_obj.value.width = fullScreen_mindMap.value.style.width;
- original_obj.value.position = fullScreen_mindMap.value.style.position;
- original_obj.value.zIndex = fullScreen_mindMap.value.style.zIndex;
- // 设置div高度为视口高度,避免覆盖浏览器头部
- fullScreen_mindMap.value.style.height = window.innerHeight - 90 + 'px';
- fullScreen_mindMap.value.style.width = window.innerWidth - 10 + 'px';
- fullScreen_mindMap.value.style.position = 'absolute';
- fullScreen_mindMap.value.style.top = '0';
- fullScreen_mindMap.value.style.left = '0';
- fullScreen_mindMap.value.style.zIndex = '9995';
- isFullScreen.value = true;
- zoomReset();
- }
- };
- // 退出全屏模式的函数
- const exitFullScreen = () => {
- // 恢复原始高度
- if (fullScreen_mindMap.value) {
- fullScreen_mindMap.value.style.height = original_obj.value.height;
- fullScreen_mindMap.value.style.width = original_obj.value.width;
- fullScreen_mindMap.value.style.position = original_obj.value.position;
- fullScreen_mindMap.value.style.zIndex = original_obj.value.zIndex;
- isFullScreen.value = false;
- zoomReset();
- }
- };
- /**
- * 下载
- * */
- const downloadMap = () => {
- mind_map.value.downloadPNG();
- };
- /**
- * 打开欢迎页面
- * */
- const toShowWelcome = () => {
- toNewChat();
- show_welcome.value = true;
- chat_display_list.value = [];
- chat_log_list.value = [];
- chat_new_list.value = [];
- is_show_right_page.value = false;
- };
- const toNewChat = () => {
- if (is_init_model.value) {
- pushInitAnswer();
- }
- is_init_model.value = false;
- chat_display_list.value = [];
- if (!show_welcome.value) {
- return;
- }
- show_welcome.value = false;
- pushInitAnswer();
- };
- const pushInitAnswer = () => {
- chat_log_list.value.push({
- answer: 'Hi,我是Smart~ <br> 很高兴遇见你!你可以随时把网址或文件发给我,我来帮你看看',
- client_custom_chat_status: '2',
- client_custom_chat_type: '0',
- client_custom_item_type: 'a',
- client_custom_item_think: false, // 是否有思考
- client_custom_item_think_content: '', //思考内容
- client_custom_item_internet: false, //是否联网
- client_custom_item_internet_list: [], //联网内容
- client_custom_chat_message_id: '' //会话的message_id
- });
- };
- /**
- * 智能体中区分是首次进去展示动态表单,还是点击按钮进去展示动态表单
- * */
- const is_init_model = ref(false);
- const initModel = (val) => {
- is_init_model.value = val;
- };
- const target_action_config = ref({});
- /**
- * 初始化sse相关方法
- * */
- const { startStream, stopStream } = useFetchEventSource();
- /**
- * 输入已经确认要提交了
- *
- * 1. 创建会话 get-chat-id
- * 2. 文件上传 如果有文件,则需要文件上传,没有文件,则不需要文件上传
- * 3. 连接socket,socket 发送文本与文件数据内容
- * 4. 接收 socket 返回的数据项
- */
- const handleInputSubmit = async (options) => {
- show_welcome.value = false;
- if (!chat_display_list.value.length) {
- pushInitAnswer();
- }
- if (!props.agent_id) {
- toSubmitNewChat(options);
- return;
- }
- let ask_text = options.text; // 文本
- const ask_files = options.files; // 文件列表
- const action_config = options.config; //是否深度思考,是否联网,是否选择知识库
- target_action_config.value = {};
- // 用户选定的文件数量
- const file_total = ask_files.length;
- const is_text_required = is_chat_text_required.value;
- const is_file_required = is_chat_file_required.value;
- // 检查对话文字是否必须
- if (is_text_required) {
- if (!ask_text) {
- const msg = i18n.t('conversation.please_input_text');
- handleErrorMessage(msg);
- return;
- }
- } else {
- ask_text = default_text_value.value;
- }
- // 检查对话文件是否必须
- if (is_file_required) {
- if (file_total === 0) {
- const msg = i18n.t('conversation.please_upload_file');
- handleErrorMessage(msg);
- return;
- }
- }
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------消息发送前的准备工作
- // 保存附加参数数据,由于下方有一个 inputClearFn2() 方法的执行
- // 会将所有数据清空,故附件参数需要在清理之前保存
- const other_options = getInputTopOptions();
- /**
- * 当新消息发送时
- * 意味着新一轮对话的开始
- * 此时应该将之前一轮对话的信息进行清空
- *
- * 整理客户端提问的数据
- * 组装Question数据
- */
- const client_question = formatDialogQuestionByClient(ask_text, ask_files);
- // 保存用户的提问信息
- // 当消息正式发出后,将提问数据放入列表中
- chat_new_question.value = client_question;
- // 消息即将发送,记录用户的提问数据
- chat_new_list.value.push(chat_new_question.value);
- // 客户端答案数据(loading状态),客户端模拟的答案数据,依据此数据展示加载中的动画
- const answerLoadingMsg = formatDialogAnswerForLoading(props.CHAT_AGENT_INFOMATION);
- chat_new_list.value.push(answerLoadingMsg);
- /**
- * 会话已确认发送
- * 隐藏欢迎内容,显示对话内容
- */
- show_welcome.value = false;
- // 清空文本数据和文件数据,避免下一次会话冲突
- // 清空表单里的数据
- inputClearFn1();
- inputClearFn2();
- // 清空可能存在的推荐项目
- chat_suggestion.value = [];
- // 清空已保存的提问数据(提问数据已经推入数组,此处无需继续保存)
- chat_new_question.value = null;
- // 文件上传、文本输入区域禁用
- input_disabled.value = true;
- // 对话区域滚动到底部
- scroll2ListBottom();
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------
- // --------------------------------------------
- const agent_id = props.agent_id;
- // 对话分为三个步骤
- // 1. 创建会话,如果已经创建,则不需要再次创建
- // 2. 上传文件,如果不存在文件,则无需文件上传
- // 3. 连接websocket
- /**
- * 创建会话 get chat id
- * 判断对话是否已经创建
- * 如果对话已经创建,则使用已经创建的对话
- * 否则,创建新对话
- */
- if (chat_round_id.value === null) {
- const session_id = props.session_id;
- if (session_id) {
- // 已有会话ID,使用此会话ID
- chat_round_id.value = session_id;
- } else {
- // 无会话ID,则是首页会话
- if (!agent_id) {
- return;
- }
- // 未创建chat,开始创建
- try {
- const chatResult = await getDialogChatId(agent_id);
- if (chatResult.code / 1 === 200) {
- // 成功
- const res_data = chatResult.data;
- chat_round_id.value = res_data.chat_id;
- } else {
- // 失败
- // 处理异常:直接在界面上显示
- handleChatRequestionException({
- message: `code: ${chatResult.code} message: ${chatResult.msg}`
- });
- return;
- }
- } catch (err) {
- console.log('err-nfsdnakiuwirea7', err);
- // 处理错误
- handleChatRequestionException({
- message: err.message
- });
- return;
- }
- }
- } else {
- // 已创建chat,使用已创建的会话ID,进入下一步流程
- }
- /**
- * 查看动态表单中是否有文件需要上传,如果有,则需要先上传文件
- * */
- if (other_options && other_options.files) {
- const files_obj = other_options.files;
- const chat_id = chat_round_id.value;
- const menu_id = current_menu_id.value;
- for (const key in files_obj) {
- const upload_files = files_obj[key].map((item) => item.file);
- const uploadResult = await uploadFileByAgentInfo(agent_id, chat_id, upload_files, menu_id);
- if (uploadResult && uploadResult.length) {
- files_obj[key] = files_obj[key].map((file) => {
- const uploadedFile = uploadResult.find((uploaded) => uploaded.name === file.name);
- // 如果找到了匹配的文件,则回填 id
- if (uploadedFile) {
- file.upload_file_id = uploadedFile.id;
- file.url = '';
- }
- return file;
- });
- // 判断如果对应的文件是单文件上传,则显示为对象
- if (files_obj[key].some((item) => item.limit_1)) {
- files_obj[key] = files_obj[key][0];
- }
- }
- }
- other_options.options = {
- ...other_options.options,
- ...files_obj
- };
- }
- // 文件上传后的信息
- let files_response = null;
- /**
- * 如果存在文件数据,则进行文件上传
- */
- if (file_total !== 0) {
- // 进行文件上传,获取文件信息
- const chat_id = chat_round_id.value;
- if (agent_id) {
- try {
- const menu_id = current_menu_id.value;
- const uploadResult = await uploadFileByAgentInfo(agent_id, chat_id, ask_files, menu_id);
- if (uploadResult.length) {
- files_response = uploadResult.map((item) => {
- return {
- ...item,
- url: '',
- type: getFileType(item),
- transfer_method: 'local_file',
- upload_file_id: item.id
- };
- });
- }
- // if (uploadResult.code / 1 === 200) {
- // // 文件上传成功
- // files_response = uploadResult.data;
- // } else {
- // // 文件上传异常
- // handleChatRequestionException({
- // message: `code: ${uploadResult.code} \n\n message: ${uploadResult.msg}`
- // });
- // return;
- // }
- } catch (err) {
- console.log('err-fhskafhakfjslkfjl', err);
- handleChatRequestionException({
- message: err.message
- });
- return;
- }
- } else {
- }
- }
- // TODO: 重新组装sse参数,调用sse接口问答
- const query_params = {
- agent_id,
- mode: current_agent_mode.value, //智能体类型
- query: ask_text,
- files: files_response || [],
- inputs: other_options ? other_options.options : [],
- session_id: props.session_id || ''
- };
- startStream(query_params, sseOnMessage);
- return;
- };
- // 首页对话
- const toSubmitNewChat = async (options) => {
- let ask_text = options.text; // 文本
- const ask_files = options.files; // 文件列表
- const action_config = options.config; //是否深度思考,是否联网,是否选择知识库
- target_action_config.value = options.config;
- let parent_id = '';
- if (chat_display_list.value.length) {
- const lastItem = chat_display_list.value[chat_display_list.value.length - 1];
- if (lastItem.parent_id) {
- parent_id = lastItem.parent_id;
- }
- }
- if (options.parent_id) {
- parent_id = options.parent_id;
- }
- mindMap_txt.value = options.text;
- // 用户选定的文件数量
- const file_total = ask_files.length;
- if (!ask_text) {
- const msg = i18n.t('conversation.please_input_text');
- handleErrorMessage(msg);
- return;
- }
- const other_options = getInputTopOptions();
- const knowledgeIdList = target_action_config.value?.knowledgeId || [];
- const client_question = formatDialogQuestionByClient(ask_text, ask_files, knowledgeIdList);
- // 保存用户的提问信息
- // 当消息正式发出后,将提问数据放入列表中
- chat_new_question.value = client_question;
- // 消息即将发送,记录用户的提问数据
- chat_new_list.value.push(chat_new_question.value);
- // 客户端答案数据(loading状态),客户端模拟的答案数据,依据此数据展示加载中的动画
- const answerLoadingMsg = formatDialogAnswerForLoading(props.CHAT_AGENT_INFOMATION);
- chat_new_list.value.push(answerLoadingMsg);
- inputClearFn1();
- inputClearFn2();
- // 清空可能存在的推荐项目
- chat_suggestion.value = [];
- // 清空已保存的提问数据(提问数据已经推入数组,此处无需继续保存)
- chat_new_question.value = null;
- // 文件上传、文本输入区域禁用
- input_disabled.value = true;
- // 对话区域滚动到底部
- scroll2ListBottom();
- // 文件上传后的信息
- let files_response = null;
- // 判断是否有要上传的文件,如果有上传文件,否则组合参数进行对话
- if (file_total !== 0) {
- try {
- const uploadResult = await uploadNewChatInfo(1, ask_files);
- files_response = uploadResult.map((item) => {
- return {
- ...item,
- url: '',
- type: getFileType(item),
- transfer_method: 'local_file',
- upload_file_id: item.id
- };
- });
- } catch (e) {
- handleChatRequestionException({
- message: e.message
- });
- }
- }
- // 组合参数
- const query_params = {
- query: ask_text,
- files: files_response,
- session_id: props.session_id || '',
- knowledgeId: action_config.knowledgeId,
- chatMode: action_config.chatMode,
- isDeep: action_config.isDeep,
- parentId: parent_id
- };
- startStream(query_params, sseOnMessage);
- return;
- };
- /**
- * 网页数据
- * */
- const search_list = ref([]);
- const toSearchPage = (item) => {
- search_list.value = [...item.client_custom_item_internet_list];
- minMap_messageId.value = item.client_custom_chat_message_id;
- if (!is_show_right_page.value) {
- is_show_right_page.value = true;
- // if (!mindMap_content.value) {
- // mindMap_err.value = '暂无内容';
- // }
- toShowMindMap(item);
- }
- if (!show_web_page.value) {
- show_web_page.value = true;
- }
- };
- const toShowMindMap = async (item) => {
- const res = await getHistoryMapData(item.client_custom_chat_message_id);
- if (res.code / 1 === 200) {
- if (res.data.mindmap) {
- mindMap_content.value = res.data.mindmap;
- mindMap_err.value = '';
- } else {
- (mindMap_content.value = ''), (mindMap_err.value = '暂无内容');
- }
- } else {
- (mindMap_content.value = ''), (mindMap_err.value = '暂无内容');
- }
- is_show_right_page.value = true;
- minMap_messageId.value = item.client_custom_chat_message_id;
- setTimeout(() => {
- show_mind_map.value = true;
- }, 200);
- };
- /**
- * sseOnMessage处理函数
- * */
- const sseOnMessage = (ev) => {
- // return;
- // sse流返回的数据
- const res_data = JSON.parse(ev.data);
- if (res_data.session_id) {
- emit('updateSessionId', res_data.session_id);
- }
- if (res_data.message_id) {
- minMap_messageId.value = res_data.message_id;
- }
- //sse流式结束
- if (res_data.event === 'message_end') {
- stopStream();
- if (props.agent_id) {
- // return;
- } else {
- is_show_right_page.value = true;
- loading_mind_map.value = true;
- getMindMapData({ messageId: minMap_messageId.value, query: mindMap_txt.value })
- .then((res) => {
- if (res.code / 1 === 200) {
- mindMap_str.value = res.data.mindmap;
- mindMap_content.value = res.data.mindmap;
- mindMap_err.value = '';
- if (!res.data.mindmap) {
- mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
- }
- } else {
- mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
- }
- })
- .catch((e) => {
- mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
- })
- .finally(() => {
- loading_mind_map.value = false;
- setTimeout(() => {
- show_mind_map.value = true;
- }, 200);
- });
- }
- }
- if (res_data.event === 'node_finished' && res_data.data.title && res_data.data.title === 'SearXNG 搜索') {
- if (res_data.data.outputs?.json) {
- search_list.value = res_data.data.outputs.json;
- if (search_list.value.length) {
- show_web_page.value = true;
- }
- }
- }
- if (res_data.event === 'error' || res_data.message === 'error') {
- //sse错误,显示错误信息
- handleChatRequestionException({
- message: res_data.error
- });
- return;
- }
- // TODO: 将返回数据填充到页面
- // 获取当前对话中最后一个对话数据
- // 最后一个对话数据为当前正在进行的对话
- const last_msg = chat_new_list.value[chat_new_list.value.length - 1];
- /**
- * 要混入的回答参数
- * client_custom_item_think: false, // 是否有思考
- * client_custom_item_think_content: '', //思考内容
- * client_custom_item_internet: false, //是否联网
- * client_custom_item_internet_list: [], //联网内容
- * client_custom_chat_message_id: '' //会话的message_id
- *
- */
- if (Object.keys(target_action_config.value)) {
- res_data.isDeep = target_action_config.value.isDeep / 1 === 2 ? true : false;
- res_data.isInternet = target_action_config.value.chatMode / 1 === 2 ? true : false;
- }
- /**
- * 整理返回的数据
- *
- */
- const currentChat = formatDialogAnswerFromSseReceiveMessage(res_data, last_msg, props.CHAT_AGENT_INFOMATION);
- const chat_status = currentChat.status;
- // 处理对话数据
- const handleChatData = () => {
- const chat_data = currentChat.data; // 对话相关的数据项
- // 原来的最后一项弹出
- chat_new_list.value.pop();
- // 添加新的最后一项
- chat_new_list.value.push(chat_data);
- // 滚动到底部
- scroll2ListBottom();
- };
- if (chat_status === 0) {
- // 未开始: 此状态不存在,无需处理
- }
- if (chat_status === 1) {
- // 此轮对话仍然在进行中
- handleChatData();
- show_stop_sse.value = true;
- }
- if (chat_status === 2) {
- // 此轮对话已结束
- handleChatData();
- // 对话已结束:检查是否存在推荐数据
- const chat_suggest = currentChat.suggest; // 对话相关的推荐数据
- if (chat_suggest) {
- chat_suggestion.value = chat_suggest;
- }
- // 对话已结束:文件上传、文本输入区域放开使用
- input_disabled.value = false;
- show_stop_sse.value = false;
- }
- if (chat_status === 3) {
- // 此轮对话出错了
- // TODO: 错误处理
- // 此轮对话已结束
- handleChatData();
- // 对话已结束:文件上传、文本输入区域放开使用
- input_disabled.value = false;
- show_stop_sse.value = false;
- }
- };
- // 停止响应
- const stopResponse = () => {
- stopStream();
- show_stop_sse.value = false;
- input_disabled.value = false;
- // 停止后修改最后一项的状态为已结束
- const lastItem = chat_new_list.value.pop();
- lastItem.client_custom_chat_status = 2;
- chat_new_list.value.push(lastItem);
- scroll2ListBottom();
- };
- watch(
- () => props.agent_id,
- () => {
- if (props.agent_id) {
- show_welcome.value = false;
- }
- }
- );
- watch(
- () => props.session_id,
- () => {
- if (props.session_id) {
- /**
- * 当页面中有记录,则不调用历史记录
- * 防止在新会话中每次问答后更新session_id去调用历史记录,
- * */
- if (chat_display_list.value.length) {
- return;
- }
- // 有历史记录:获取历史记录内容进行展示
- getHistoryLogs(props.session_id)
- .then(async (res) => {
- if (res.code / 1 === 200) {
- const res_data = res.data;
- // 成功
- const session_list = res_data.message;
- // for (let key in session_list) {
- // if (session_list[key].role == 'assistant') {
- // const res = await getHistoryMapData(session_list[key].id);
- // if (res.code / 1 === 200) {
- // session_list[key].mindMap = res.data.mindmap;
- // } else {
- // session_list[key].mindMap = '';
- // }
- // }
- // }
- // 将列表数据进行转化
- const list = formatDialogHistory(session_list, props.CHAT_AGENT_INFOMATION);
- // 如果历史记录不为空
- // 则需要展示对话内容
- // 此时欢迎内容就不需要展示
- if (list.length !== 0) {
- show_welcome.value = false;
- // 滚动到底部
- scroll2ListBottom();
- }
- chat_log_list.value = list;
- } else {
- // 异常
- // TODO:处理异常
- show_welcome.value = false;
- // handleChatRequestionException({
- // message: res.msg
- // });
- // 使用消息提示,而非界面错误提示
- handleErrorMessage('历史会话异常:' + res.msg);
- }
- })
- .catch((err) => {
- console.log('err-mfsjakfjsdkalfjs', err);
- show_welcome.value = false;
- // handleChatRequestionException({
- // message: err.message
- // });
- handleErrorMessage('历史会话错误:' + err.message);
- });
- } else {
- // 无历史记录:等待创建会话内容(用户开始输入、提交完成),列表区域显示欢迎界面
- }
- }
- );
- const getHistoryMapData = async (message_id) => {
- const res = await getMapById(message_id);
- return res;
- };
- onMounted(() => {
- const agent_id = props.agent_id;
- const session_id = props.session_id;
- /**
- * 如果选择智能体,则不显示欢迎页面
- *
- */
- if (props.chat_history) {
- show_welcome.value = false;
- console.log(11111111111111111111);
- } else {
- if (!agent_id && !session_id) {
- show_welcome.value = true;
- } else {
- show_welcome.value = false;
- }
- }
- // 组件挂载
- if (session_id) {
- // 有历史记录:获取历史记录内容进行展示
- getHistoryLogs(session_id)
- .then(async (res) => {
- if (res.code / 1 === 200) {
- const res_data = res.data;
- // 成功
- const session_list = res_data.message;
- // for (let key in session_list) {
- // if (session_list[key].role == 'assistant') {
- // const res = await getHistoryMapData(session_list[key].id);
- // if (res.code / 1 === 200) {
- // session_list[key].mindMap = res.data.mindMap;
- // } else {
- // session_list[key].mindMap = '';
- // }
- // }
- // }
- // 将列表数据进行转化
- const list = formatDialogHistory(session_list, props.CHAT_AGENT_INFOMATION);
- // 如果历史记录不为空
- // 则需要展示对话内容
- // 此时欢迎内容就不需要展示
- if (list.length !== 0) {
- show_welcome.value = false;
- // 滚动到底部
- scroll2ListBottom();
- }
- chat_log_list.value = list;
- } else {
- // 异常
- // TODO:处理异常
- show_welcome.value = false;
- // handleChatRequestionException({
- // message: res.msg
- // });
- // 使用消息提示,而非界面错误提示
- handleErrorMessage('历史会话异常:' + res.msg);
- }
- })
- .catch((err) => {
- console.log('err-mfsjakfjsdkalfjs', err);
- show_welcome.value = false;
- // handleChatRequestionException({
- // message: err.message
- // });
- handleErrorMessage('历史会话错误:' + err.message);
- });
- } else {
- // 无历史记录:等待创建会话内容(用户开始输入、提交完成),列表区域显示欢迎界面
- }
- });
- // ---------------------------------------------------------
- onUnmounted(() => {
- // 组件卸载,关闭组件内的websocket连接
- // closeWSConnect();
- });
- defineExpose({
- toShowWelcome,
- toNewChat
- });
- </script>
- <style lang="css" scoped>
- .conversation-chat-container {
- position: relative;
- display: flex;
- justify-content: center;
- margin-left: auto;
- margin-right: auto;
- height: calc(100% - 52px);
- padding-top: 52px;
- }
- .conversation-chat-left {
- width: 25%;
- flex-shrink: 0;
- }
- .conversation-chat-right {
- width: 25%;
- flex-shrink: 0;
- }
- .conversation-chat-main {
- flex-grow: 1;
- width: 100%;
- height: 100%;
- /* max-width: 960px; */
- margin-left: auto;
- margin-right: auto;
- display: flex;
- /* flex-direction: column; */
- flex-direction: row;
- /* gap: 5%; */
- /* background-color: #aaa; */
- }
- .conversation-chat-main-left {
- /* flex-grow: 1; */
- /* flex-basis: 10%; */
- width: 10%;
- flex-direction: column;
- overflow: hidden;
- height: 100%;
- }
- .conversation-chat-main-content {
- /* flex-grow: 5; */
- /* flex-basis: 50%; */
- flex-direction: column;
- overflow: hidden;
- margin: 0 auto;
- height: 100%;
- }
- .conversation-chat-main-right {
- /* flex-grow: 4; */
- /* flex-basis: 40%; */
- flex-direction: column;
- overflow: hidden;
- height: 100%;
- text-align: right;
- }
- .conversation-chat-expand {
- text-align: right;
- height: 100%;
- width: 100%;
- }
- .conversation-chat-mind-map {
- position: relative;
- /* width: 100%; */
- height: 330px;
- padding: 5px;
- border-radius: 12px;
- background-color: var(--color-bg-1);
- }
- .conversation-chat-mind-map-spin {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 330px;
- padding: 5px;
- border-radius: 12px;
- background-color: var(--color-bg-1);
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .mind_map_error {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 330px;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: var(--color-bg-1);
- }
- .exit-button {
- position: absolute;
- right: 10px;
- top: 10px;
- border: none;
- cursor: pointer;
- z-index: 9999;
- }
- .conversation-chat-mind-map-tools {
- text-align: right;
- }
- .conversation-chat-web-page {
- margin-top: 20px;
- height: calc(100% - 380px);
- padding: 10px;
- border-radius: 12px;
- background-color: var(--color-bg-1);
- }
- .conversation-chat-content {
- flex-grow: 1;
- height: calc(100% - 60px);
- display: flex;
- flex-direction: column;
- overflow: hidden;
- padding-top: 8px;
- }
- .conversation-chat-main-container {
- height: 80%;
- /* flex-grow: 1; */
- }
- .conversation-chat-area {
- flex-grow: 1;
- overflow: auto;
- /* max-width: 960px; */
- }
- .history-list-loading {
- display: flex;
- justify-content: space-between;
- align-items: center;
- min-height: 300px;
- width: 100%;
- }
- .history-list-loading-container {
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .conversation-input-attached {
- flex-shrink: 0;
- width: 100%;
- margin-left: auto;
- margin-right: auto;
- /* margin-top: 5px; */
- margin-bottom: -10px;
- padding: 5px;
- border-radius: 10px;
- display: flex;
- }
- .conversation-chat-input {
- flex-shrink: 0;
- width: 100%;
- margin-left: auto;
- margin-right: auto;
- margin-top: 5px;
- margin-bottom: 5px;
- padding: 5px;
- border-radius: 10px;
- /* display: flex; */
- }
- /* .scroll-left {
- width: 15%;
- flex-shrink: 0;
- }
- .scroll-right {
- width: 15%;
- flex-shrink: 0;
- } */
- </style>
|