From 6074f716efd6c32ac00242bf8df2890b59f8eadd Mon Sep 17 00:00:00 2001 From: rd <1344903914@qq.com> Date: Thu, 28 Aug 2025 14:13:59 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=B8=AD=E6=96=ADSSE=E3=80=81=E6=9B=B4?= =?UTF-8?q?=E6=8D=A2=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/all/chat.ts | 6 +-- src/components/xt-chat/chat-view/constants.ts | 2 +- src/components/xt-chat/chat-view/index.vue | 38 ++++++++++--------- .../xt-chat/chat-view/useChatHandler.tsx | 32 +++++++--------- .../xt-chat/xt-bubble/hooks/useTypedEffect.ts | 4 +- src/components/xt-chat/xt-bubble/style.scss | 2 +- src/utils/querySSE.ts | 20 +++++----- 7 files changed, 51 insertions(+), 53 deletions(-) diff --git a/src/api/all/chat.ts b/src/api/all/chat.ts index 8e3efa3..ebd37d6 100644 --- a/src/api/all/chat.ts +++ b/src/api/all/chat.ts @@ -2,6 +2,7 @@ import Http from '@/api'; import axios from 'axios'; import { glsWithCatch } from '@/utils/stroage'; import { useEnterpriseStore } from '@/stores/modules/enterprise'; +export const BASE_PYTHON_URL = 'https://agent.lvfunai.com'; // 历史记录-列表 export const getAgentHistory = (id: string) => { @@ -28,7 +29,6 @@ export const getConversationList = (params: {}) => { return Http.get(`/v1/conversation/message/list`, params); }; -export const baseUrl = 'https://agent.lvfunai.com'; export const getHeaders = () => { const store = useEnterpriseStore(); return { @@ -43,7 +43,7 @@ export const getHeaders = () => { * 获取智能体信息 */ export const getAgentData = async () => { - const { data } = await axios.get(`${baseUrl}/api/agent/info`, { + const { data } = await axios.get(`${BASE_PYTHON_URL}/api/agent/info`, { headers: getHeaders(), }); return data; @@ -53,7 +53,7 @@ export const getAgentData = async () => { * 生成会话id */ export const createSession = async () => { - const { data } = await axios.get(`${baseUrl}/api/agent/create_session`, { + const { data } = await axios.get(`${BASE_PYTHON_URL}/api/agent/create_session`, { headers: getHeaders(), }); return data; diff --git a/src/components/xt-chat/chat-view/constants.ts b/src/components/xt-chat/chat-view/constants.ts index 6bfbafa..f223056 100644 --- a/src/components/xt-chat/chat-view/constants.ts +++ b/src/components/xt-chat/chat-view/constants.ts @@ -24,7 +24,7 @@ export const ANSWER_STYLE = { export interface UseChatHandlerReturn { roles?: BubbleListProps['roles']; - currentTaskId?: Ref; + generateTeamRunTaskId?: Ref; handleMessage?: (parsedData: { event: string; data: MESSAGE.Answer }) => void; handleOpen?: (data: Response) => void; generateLoading?: Ref; diff --git a/src/components/xt-chat/chat-view/index.vue b/src/components/xt-chat/chat-view/index.vue index 18b4f6b..d012c4c 100644 --- a/src/components/xt-chat/chat-view/index.vue +++ b/src/components/xt-chat/chat-view/index.vue @@ -45,11 +45,16 @@ export default { initSse({ message }); }; + const clearSseController = () => { + if (sseController.value) { + sseController.value.abort?.(); + sseController.value = null; + } + } + const handleCancel = () => { - // 中止当前正在输出的回答 - console.log('handleCancel', currentTaskId.value); if (generateLoading.value) { - bubbleListRef.value?.abortTypingByKey(currentTaskId.value); + bubbleListRef.value?.abortTypingByKey(generateTeamRunTaskId.value); sseController.value?.abort?.(); } if (showRightView.value) { @@ -60,18 +65,15 @@ export default { antdMessage.info('取消生成'); }; - const initSse = (inputInfo: CHAT.TInputInfo): void => { - if (sseController.value) { - sseController.value.abort?.(); - sseController.value = null; - } + const initSse = async (inputInfo: CHAT.TInputInfo): Promise => { + clearSseController(); try { const { message } = inputInfo; generateLoading.value = true; - sseController.value = querySSE({ + sseController.value = await querySSE({ method: 'POST', handleMessage, body: JSON.stringify({ @@ -93,13 +95,11 @@ export default { agent_id: chatStore.agentInfo.agent_id, }); if (code === 200) { - conversationList.value = [ - ...conversationList.value, - ...(data.list?.flat(1) ?? []).map((v) => ({ - ...v, - teamRunTaskId: v.step_run_id, - })), - ]; + const remoteData = (data.list?.flat(1) ?? []).map((v: any) => ({ + ...v, + teamRunTaskId: v.step_run_id, + })); + conversationList.value = [...conversationList.value, ...remoteData]; } }; @@ -107,7 +107,7 @@ export default { roles, showRightView, rightViewData, - currentTaskId, + generateTeamRunTaskId, handleMessage, conversationList, generateLoading, @@ -140,6 +140,10 @@ export default { { immediate: true }, ); + onUnmounted(() => { + clearSseController(); + }) + return () => (
diff --git a/src/components/xt-chat/chat-view/useChatHandler.tsx b/src/components/xt-chat/chat-view/useChatHandler.tsx index 2bc5200..ebb9d22 100644 --- a/src/components/xt-chat/chat-view/useChatHandler.tsx +++ b/src/components/xt-chat/chat-view/useChatHandler.tsx @@ -44,7 +44,7 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { const senderRef = ref(null); const conversationList = ref([]); const generateLoading = ref(false); - const currentTaskId = ref(null); + const generateTeamRunTaskId = ref(null); const showRightView = ref(false); const rightViewData = ref({}); const lastTeamRunTaskId = ref(null); // 最近一个对话的id @@ -74,9 +74,9 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { placement: 'start', variant: 'borderless', typing: { step: 2, interval: 100 }, - onTypingComplete: () => { - currentTaskId.value = null; - }, + // onTypingComplete: () => { + // generateTeamRunTaskId.value = null; + // }, style: ROLE_STYLE, }, [QUESTION_ROLE]: { @@ -128,6 +128,7 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { // 重置生成状态 const resetGenerateStatus = () => { generateLoading.value = false; + generateTeamRunTaskId.value = null; }; const handleRemoteRefresh = (item: MESSAGE.Answer) => { @@ -192,7 +193,7 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { // 过程节点开始 const handleRunTaskStart = (data: MESSAGE.Answer) => { const { run_id } = data; - currentTaskId.value = run_id; + // generateTeamRunTaskId.value = run_id; conversationList.value.push({ run_id, key: run_id, @@ -210,20 +211,15 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { return ( <> {isFirstRunTask(run_id) && ( -
+
setRunTaskCollapse(lastTeamRunTaskId.value, !isCollapse)} + > 智能思考 {isCollapse ? ( - setRunTaskCollapse(lastTeamRunTaskId.value, false)} - /> + ) : ( - setRunTaskCollapse(lastTeamRunTaskId.value, true)} - /> + )}
)} @@ -269,7 +265,7 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { const handleTeamRunTaskStart = (data: MESSAGE.Answer) => { const { run_id } = data; lastTeamRunTaskId.value = run_id; - currentTaskId.value = run_id; + generateTeamRunTaskId.value = run_id; conversationList.value.push({ run_id, isTeamRunTask: true, @@ -390,7 +386,7 @@ export default function useChatHandler({ initSse }): UseChatHandlerReturn { return { roles, senderRef, - currentTaskId, + generateTeamRunTaskId, handleMessage, generateLoading, conversationList, diff --git a/src/components/xt-chat/xt-bubble/hooks/useTypedEffect.ts b/src/components/xt-chat/xt-bubble/hooks/useTypedEffect.ts index eaffc0a..deb13a4 100644 --- a/src/components/xt-chat/xt-bubble/hooks/useTypedEffect.ts +++ b/src/components/xt-chat/xt-bubble/hooks/useTypedEffect.ts @@ -22,7 +22,7 @@ function isString(str: any): str is string { * 打字效果Hook * 当启用打字效果时,返回渐进式显示的内容和打字状态 * 否则直接返回原始内容 - * + * * @param content - 原始内容 * @param typingEnabled - 是否启用打字效果 * @param typingStep - 每次显示的字符数 @@ -51,7 +51,7 @@ const useTypedEffect = ( const prevContentValue = unref(prevContent); // 更新上一次的内容记录 setPrevContent(content.value); - + // 如果未启用打字效果且内容为字符串 if (!mergedTypingEnabled.value && isString(content.value)) { // 若外部触发中止,则保持当前索引,不再自动跳到全文 diff --git a/src/components/xt-chat/xt-bubble/style.scss b/src/components/xt-chat/xt-bubble/style.scss index 918139e..6d2f469 100644 --- a/src/components/xt-chat/xt-bubble/style.scss +++ b/src/components/xt-chat/xt-bubble/style.scss @@ -94,7 +94,7 @@ display: flex; justify-content: center; align-items: center; - border-radius: 50px; + border-radius: 16px; background-color: var(--BG-200, #f2f3f5); } diff --git a/src/utils/querySSE.ts b/src/utils/querySSE.ts index 54a03a4..b0f4960 100644 --- a/src/utils/querySSE.ts +++ b/src/utils/querySSE.ts @@ -2,11 +2,9 @@ import { fetchEventSource } from '@microsoft/fetch-event-source'; import type { EventSourceMessage } from '@microsoft/fetch-event-source'; import { useEnterpriseStore } from '@/stores/modules/enterprise'; import { glsWithCatch } from '@/utils/stroage'; +import { BASE_PYTHON_URL } from '@/api/all/chat'; -const customHost = 'https://agent.lvfunai.com'; -// -// const customHost = 'http://localhost:3000'; -const DEFAULT_SSE_URL = `${customHost}/api/agent/runs`; +const DEFAULT_SSE_URL = `${BASE_PYTHON_URL}/api/agent/runs`; const SSE_HEADERS = { 'Content-Type': 'application/json', @@ -42,10 +40,10 @@ export default async (config: SSEConfig, url: string = DEFAULT_SSE_URL): Promise handleClose, } = config; const store = useEnterpriseStore(); - + // 创建AbortController实例用于中断请求 const abortController = new AbortController(); - + fetchEventSource(url, { method, // credentials: 'include', @@ -70,21 +68,21 @@ export default async (config: SSEConfig, url: string = DEFAULT_SSE_URL): Promise } }, onerror(error: Error) { - // console.error('SSE error:', error); + // console.error('SSE error:', error); handleError?.(error); }, onclose() { - // console.log('SSE connection closed'); + // console.log('SSE connection closed'); handleClose?.(); }, async onopen(response: Response) { - // console.log('onopen', response); + // console.log('onopen', response); handleOpen?.(response); }, }); - + // 返回abort方法供外部调用 return { - abort: () => abortController.abort() + abort: () => abortController.abort(), }; };