From 12f3dba77915f92a69911d6438a35a65392d3f28 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 11 Sep 2024 15:15:32 +0800 Subject: [PATCH] fix: userselect chatId unrefresh --- .../zh-cn/docs/development/upgrading/4811.md | 1 + .../ChatBox/components/ChatController.tsx | 2 - .../ChatBox/components/ChatItem.tsx | 17 +-- .../core/chat/ChatContainer/ChatBox/index.tsx | 15 +-- .../core/chat/ChatContainer/useChat.ts | 5 +- .../core/chat/components/AIResponseBox.tsx | 115 +++++++----------- projects/app/src/pages/chat/index.tsx | 7 +- 7 files changed, 57 insertions(+), 105 deletions(-) diff --git a/docSite/content/zh-cn/docs/development/upgrading/4811.md b/docSite/content/zh-cn/docs/development/upgrading/4811.md index 5fbcd0d7fd2b..c2aac6ad15ea 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4811.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4811.md @@ -25,3 +25,4 @@ weight: 813 8. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。 9. 优化 - 工作流 handler 性能优化。 10. 修复 - 知识库选择权限问题。 +11. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。 diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatController.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatController.tsx index 368b2c10a0ef..24c43c64bae4 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatController.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatController.tsx @@ -9,13 +9,11 @@ import { formatChatValue2InputType } from '../utils'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { ChatBoxContext } from '../Provider'; import { useContextSelector } from 'use-context-selector'; -import { SendPromptFnType } from '../type'; export type ChatControllerProps = { isLastChild: boolean; chat: ChatSiteItemType; showVoiceIcon?: boolean; - onSendMessage: SendPromptFnType; onRetry?: () => void; onDelete?: () => void; onMark?: () => void; diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx index 3bc11ee14bb5..e245a6eec077 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx @@ -19,7 +19,6 @@ import { useCopyData } from '@/web/common/hooks/useCopyData'; import MyIcon from '@fastgpt/web/components/common/Icon'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useTranslation } from 'next-i18next'; -import { SendPromptFnType } from '../type'; import { AIChatItemValueItemType, ChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { CodeClassNameEnum } from '@/components/Markdown/utils'; import { isEqual } from 'lodash'; @@ -51,7 +50,6 @@ type BasicProps = { type Props = BasicProps & { type: ChatRoleEnum.Human | ChatRoleEnum.AI; - onSendMessage: SendPromptFnType; }; const RenderQuestionGuide = ({ questionGuides }: { questionGuides: string[] }) => { @@ -80,14 +78,12 @@ const AIContentCard = React.memo(function AIContentCard({ dataId, isLastChild, isChatting, - onSendMessage, questionGuides }: { dataId: string; chatValue: ChatItemValueItemType[]; isLastChild: boolean; isChatting: boolean; - onSendMessage: SendPromptFnType; questionGuides: string[]; }) { return ( @@ -101,7 +97,6 @@ const AIContentCard = React.memo(function AIContentCard({ value={value} isLastChild={isLastChild && i === chatValue.length - 1} isChatting={isChatting} - onSendMessage={onSendMessage} /> ); })} @@ -113,16 +108,7 @@ const AIContentCard = React.memo(function AIContentCard({ }); const ChatItem = (props: Props) => { - const { - type, - avatar, - statusBoxData, - children, - isLastChild, - questionGuides = [], - onSendMessage, - chat - } = props; + const { type, avatar, statusBoxData, children, isLastChild, questionGuides = [], chat } = props; const styleMap: BoxProps = type === ChatRoleEnum.Human @@ -270,7 +256,6 @@ const ChatItem = (props: Props) => { dataId={chat.dataId} isLastChild={isLastChild && i === splitAiResponseResults.length - 1} isChatting={isChatting} - onSendMessage={onSendMessage} questionGuides={questionGuides} /> )} diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx index 873c9b5f9528..e71931b90996 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx @@ -60,7 +60,7 @@ import dynamic from 'next/dynamic'; import type { StreamResponseType } from '@/web/common/api/fetch'; import { useContextSelector } from 'use-context-selector'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; -import { useCreation, useMemoizedFn, useThrottleFn, useTrackedEffect } from 'ahooks'; +import { useCreation, useMemoizedFn, useThrottleFn } from 'ahooks'; import MyIcon from '@fastgpt/web/components/common/Icon'; const ResponseTags = dynamic(() => import('./components/ResponseTags')); @@ -832,12 +832,10 @@ const ChatBox = ( }; window.addEventListener('message', windowMessage); - eventBus.on(EventNameEnum.sendQuestion, ({ text }: { text: string }) => { - if (!text) return; - sendPrompt({ - text - }); - }); + const fn: SendPromptFnType = (e) => { + sendPrompt(e); + }; + eventBus.on(EventNameEnum.sendQuestion, fn); eventBus.on(EventNameEnum.editQuestion, ({ text }: { text: string }) => { if (!text) return; resetInputVal({ text }); @@ -881,7 +879,6 @@ const ChatBox = ( onRetry={retryInput(item.dataId)} onDelete={delOneMessage(item.dataId)} isLastChild={index === chatHistories.length - 1} - onSendMessage={sendPrompt} /> )} {item.obj === ChatRoleEnum.AI && ( @@ -891,7 +888,6 @@ const ChatBox = ( avatar={appAvatar} chat={item} isLastChild={index === chatHistories.length - 1} - onSendMessage={sendPrompt} {...{ showVoiceIcon, shareId, @@ -977,7 +973,6 @@ const ChatBox = ( outLinkUid, questionGuides, retryInput, - sendPrompt, shareId, showEmpty, showMarkIcon, diff --git a/projects/app/src/components/core/chat/ChatContainer/useChat.ts b/projects/app/src/components/core/chat/ChatContainer/useChat.ts index 124aebc56153..16f1590938d5 100644 --- a/projects/app/src/components/core/chat/ChatContainer/useChat.ts +++ b/projects/app/src/components/core/chat/ChatContainer/useChat.ts @@ -2,7 +2,8 @@ import { ChatSiteItemType } from '@fastgpt/global/core/chat/type'; import { useCallback, useRef, useState } from 'react'; import { useForm } from 'react-hook-form'; import { PluginRunBoxTabEnum } from './PluginRunBox/constants'; -import { ComponentRef as ChatComponentRef } from './ChatBox/type'; +import { ComponentRef as ChatComponentRef, SendPromptFnType } from './ChatBox/type'; +import { eventBus, EventNameEnum } from '@/web/common/utils/eventbus'; export const useChat = () => { const ChatBoxRef = useRef(null); @@ -61,3 +62,5 @@ export const useChat = () => { resetChatRecords }; }; + +export const onSendPrompt: SendPromptFnType = (e) => eventBus.emit(EventNameEnum.sendQuestion, e); diff --git a/projects/app/src/components/core/chat/components/AIResponseBox.tsx b/projects/app/src/components/core/chat/components/AIResponseBox.tsx index f4a08ea67a6e..c67dd9ab1e1a 100644 --- a/projects/app/src/components/core/chat/components/AIResponseBox.tsx +++ b/projects/app/src/components/core/chat/components/AIResponseBox.tsx @@ -12,24 +12,20 @@ import { import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; import { AIChatItemValueItemType, - ChatSiteItemType, ToolModuleResponseItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import React from 'react'; import MyIcon from '@fastgpt/web/components/common/Icon'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import { SendPromptFnType } from '../ChatContainer/ChatBox/type'; -import { useContextSelector } from 'use-context-selector'; -import { ChatBoxContext } from '../ChatContainer/ChatBox/Provider'; import { InteractiveNodeResponseItemType } from '@fastgpt/global/core/workflow/template/system/userSelect/type'; import { isEqual } from 'lodash'; +import { onSendPrompt } from '../ChatContainer/useChat'; type props = { value: UserChatItemValueItemType | AIChatItemValueItemType; isLastChild: boolean; isChatting: boolean; - onSendMessage?: SendPromptFnType; }; const RenderText = React.memo(function RenderText({ @@ -128,67 +124,51 @@ ${toolResponse}`} }, (prevProps, nextProps) => isEqual(prevProps, nextProps) ); -const RenderInteractive = React.memo( - function RenderInteractive({ - isChatting, - interactive, - onSendMessage, - chatHistories - }: { - isChatting: boolean; - interactive: InteractiveNodeResponseItemType; - onSendMessage?: SendPromptFnType; - chatHistories: ChatSiteItemType[]; - }) { - return ( - <> - {interactive?.params?.description && } - - {interactive.params.userSelectOptions?.map((option) => { - const selected = option.value === interactive?.params?.userSelectedVal; +const RenderInteractive = React.memo(function RenderInteractive({ + interactive +}: { + interactive: InteractiveNodeResponseItemType; +}) { + return ( + <> + {interactive?.params?.description && } + + {interactive.params.userSelectOptions?.map((option) => { + const selected = option.value === interactive?.params?.userSelectedVal; - return ( - - ); - })} - - - ); - }, - ( - prevProps, - nextProps // isChatting 更新时候,onSendMessage 和 chatHistories 肯定都更新了,这里不需要额外的刷新 - ) => - prevProps.isChatting === nextProps.isChatting && - isEqual(prevProps.interactive, nextProps.interactive) -); - -const AIResponseBox = ({ value, isLastChild, isChatting, onSendMessage }: props) => { - const chatHistories = useContextSelector(ChatBoxContext, (v) => v.chatHistories); + } + : {})} + onClick={() => { + onSendPrompt({ + text: option.value, + isInteractivePrompt: true + }); + }} + > + {option.value} + + ); + })} + + + ); +}); +const AIResponseBox = ({ value, isLastChild, isChatting }: props) => { if (value.type === ChatItemValueTypeEnum.text && value.text) return ; if (value.type === ChatItemValueTypeEnum.tool && value.tools) @@ -198,14 +178,7 @@ const AIResponseBox = ({ value, isLastChild, isChatting, onSendMessage }: props) value.interactive && value.interactive.type === 'userSelect' ) - return ( - - ); + return ; }; export default React.memo(AIResponseBox); diff --git a/projects/app/src/pages/chat/index.tsx b/projects/app/src/pages/chat/index.tsx index c43317d1a9be..bf51a6c2d2d6 100644 --- a/projects/app/src/pages/chat/index.tsx +++ b/projects/app/src/pages/chat/index.tsx @@ -130,7 +130,6 @@ const Chat = ({ const completionChatId = chatId || getNanoid(); // Just send a user prompt const histories = messages.slice(-1); - const { responseText, responseData } = await streamFetch({ data: { messages: histories, @@ -146,10 +145,8 @@ const Chat = ({ const newTitle = getChatTitleFromChatMessage(GPTMessages2Chats(histories)[0]); // new chat - if (completionChatId !== chatId) { - if (controller.signal.reason !== 'leave') { - onChangeChatId(completionChatId, true); - } + if (completionChatId !== chatId && controller.signal.reason !== 'leave') { + onChangeChatId(completionChatId, true); } loadHistories();