diff --git a/api/apps/conversation_app.py b/api/apps/conversation_app.py index 401afd9eb7..7329e0569f 100644 --- a/api/apps/conversation_app.py +++ b/api/apps/conversation_app.py @@ -37,7 +37,9 @@ def set_conversation(): req = request.json conv_id = req.get("conversation_id") - if conv_id: + is_new = req.get("is_new") + del req["is_new"] + if not is_new: del req["conversation_id"] try: if not ConversationService.update_by_id(conv_id, req): @@ -56,7 +58,7 @@ def set_conversation(): if not e: return get_data_error_result(retmsg="Dialog not found") conv = { - "id": get_uuid(), + "id": conv_id, "dialog_id": req["dialog_id"], "name": req.get("name", "New conversation"), "message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}] diff --git a/web/.umirc.ts b/web/.umirc.ts index bcdae7c74e..bd25fb577c 100644 --- a/web/.umirc.ts +++ b/web/.umirc.ts @@ -30,7 +30,7 @@ export default defineConfig({ copy: ['src/conf.json'], proxy: { '/v1': { - target: 'http://127.0.0.1:9456/', + target: 'http://127.0.0.1:9380/', changeOrigin: true, ws: true, logger: console, diff --git a/web/src/components/message-input/index.tsx b/web/src/components/message-input/index.tsx index 56e8d6afdc..fb9ea4c9df 100644 --- a/web/src/components/message-input/index.tsx +++ b/web/src/components/message-input/index.tsx @@ -117,7 +117,7 @@ const MessageInput = ({ file, }) => { let nextConversationId: string = conversationId; - if (createConversationBeforeUploadDocument && !conversationId) { + if (createConversationBeforeUploadDocument) { const creatingRet = await createConversationBeforeUploadDocument( file.name, ); @@ -234,8 +234,14 @@ const MessageInput = ({ > diff --git a/web/src/components/message-item/hooks.ts b/web/src/components/message-item/hooks.ts index b228b7c1d0..a411c570cc 100644 --- a/web/src/components/message-item/hooks.ts +++ b/web/src/components/message-item/hooks.ts @@ -2,11 +2,10 @@ import { useDeleteMessage, useFeedback } from '@/hooks/chat-hooks'; import { useSetModalState } from '@/hooks/common-hooks'; import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks'; import { IFeedbackRequestBody } from '@/interfaces/request/chat'; -import { ConversationContext } from '@/pages/chat/context'; import { getMessagePureId } from '@/utils/chat'; import { hexStringToUint8Array } from '@/utils/common-util'; import { SpeechPlayer } from 'openai-speech-stream-player'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; export const useSendFeedback = (messageId: string) => { const { visible, hideModal, showModal } = useSetModalState(); @@ -59,24 +58,21 @@ export const useSpeech = (content: string, audioBinary?: string) => { const { read } = useSpeechWithSse(); const player = useRef(); const [isPlaying, setIsPlaying] = useState(false); - const callback = useContext(ConversationContext); const initialize = useCallback(async () => { player.current = new SpeechPlayer({ audio: ref.current!, onPlaying: () => { setIsPlaying(true); - callback?.(true); }, onPause: () => { setIsPlaying(false); - callback?.(false); }, onChunkEnd: () => {}, mimeType: 'audio/mpeg', }); await player.current.init(); - }, [callback]); + }, []); const pause = useCallback(() => { player.current?.pause(); @@ -103,7 +99,11 @@ export const useSpeech = (content: string, audioBinary?: string) => { if (audioBinary) { const units = hexStringToUint8Array(audioBinary); if (units) { - player.current?.feed(units); + try { + player.current?.feed(units); + } catch (error) { + console.warn(error); + } } } }, [audioBinary]); diff --git a/web/src/constants/chat.ts b/web/src/constants/chat.ts index 882c8e9158..977c727c4e 100644 --- a/web/src/constants/chat.ts +++ b/web/src/constants/chat.ts @@ -19,6 +19,7 @@ export enum SharedFrom { export enum ChatSearchParams { DialogId = 'dialogId', ConversationId = 'conversationId', + isNew = 'isNew', } export const EmptyConversationId = 'empty'; diff --git a/web/src/hooks/chat-hooks.ts b/web/src/hooks/chat-hooks.ts index 91054c75b5..49b1e2166e 100644 --- a/web/src/hooks/chat-hooks.ts +++ b/web/src/hooks/chat-hooks.ts @@ -12,18 +12,22 @@ import { import i18n from '@/locales/config'; import { IClientConversation } from '@/pages/chat/interface'; import chatService from '@/services/chat-service'; -import { buildMessageListWithUuid, isConversationIdExist } from '@/utils/chat'; +import { + buildMessageListWithUuid, + getConversationId, + isConversationIdExist, +} from '@/utils/chat'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { message } from 'antd'; import dayjs, { Dayjs } from 'dayjs'; import { has, set } from 'lodash'; import { useCallback, useMemo, useState } from 'react'; -import { useSearchParams } from 'umi'; +import { history, useSearchParams } from 'umi'; //#region logic export const useClickDialogCard = () => { - const [, setSearchParams] = useSearchParams(); + const [_, setSearchParams] = useSearchParams(); const newQueryParameters: URLSearchParams = useMemo(() => { return new URLSearchParams(); @@ -44,6 +48,25 @@ export const useClickDialogCard = () => { return { handleClickDialog }; }; +export const useClickConversationCard = () => { + const [currentQueryParameters, setSearchParams] = useSearchParams(); + const newQueryParameters: URLSearchParams = useMemo( + () => new URLSearchParams(currentQueryParameters.toString()), + [currentQueryParameters], + ); + + const handleClickConversation = useCallback( + (conversationId: string, isNew: string) => { + newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); + newQueryParameters.set(ChatSearchParams.isNew, isNew); + setSearchParams(newQueryParameters); + }, + [setSearchParams, newQueryParameters], + ); + + return { handleClickConversation }; +}; + export const useGetChatSearchParams = () => { const [currentQueryParameters] = useSearchParams(); @@ -51,6 +74,7 @@ export const useGetChatSearchParams = () => { dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', conversationId: currentQueryParameters.get(ChatSearchParams.ConversationId) || '', + isNew: currentQueryParameters.get(ChatSearchParams.isNew) || '', }; }; @@ -60,6 +84,7 @@ export const useGetChatSearchParams = () => { export const useFetchNextDialogList = () => { const { handleClickDialog } = useClickDialogCard(); + const { dialogId } = useGetChatSearchParams(); const { data, @@ -70,11 +95,20 @@ export const useFetchNextDialogList = () => { initialData: [], gcTime: 0, refetchOnWindowFocus: false, - queryFn: async () => { + refetchOnMount: false, + queryFn: async (...params) => { + console.log('🚀 ~ queryFn: ~ params:', params); const { data } = await chatService.listDialog(); - if (data.retcode === 0 && data.data.length > 0) { - handleClickDialog(data.data[0].id); + if (data.retcode === 0) { + const list: IDialog[] = data.data; + if (list.length > 0) { + if (list.every((x) => x.id !== dialogId)) { + handleClickDialog(data.data[0].id); + } + } else { + history.push('/chat'); + } } return data?.data ?? []; @@ -86,6 +120,7 @@ export const useFetchNextDialogList = () => { export const useSetNextDialog = () => { const queryClient = useQueryClient(); + const { data, isPending: loading, @@ -96,8 +131,10 @@ export const useSetNextDialog = () => { const { data } = await chatService.setDialog(params); if (data.retcode === 0) { queryClient.invalidateQueries({ + exact: false, queryKey: ['fetchDialogList'], }); + queryClient.invalidateQueries({ queryKey: ['fetchDialog'], }); @@ -166,6 +203,7 @@ export const useRemoveNextDialog = () => { const { data } = await chatService.removeDialog({ dialogIds }); if (data.retcode === 0) { queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] }); + message.success(i18n.t('message.deleted')); } return data.retcode; @@ -181,6 +219,7 @@ export const useRemoveNextDialog = () => { export const useFetchNextConversationList = () => { const { dialogId } = useGetChatSearchParams(); + const { handleClickConversation } = useClickConversationCard(); const { data, isFetching: loading, @@ -193,7 +232,9 @@ export const useFetchNextConversationList = () => { enabled: !!dialogId, queryFn: async () => { const { data } = await chatService.listConversation({ dialogId }); - + if (data.retcode === 0 && data.data.length > 0) { + handleClickConversation(data.data[0].id, ''); + } return data?.data; }, }); @@ -202,7 +243,7 @@ export const useFetchNextConversationList = () => { }; export const useFetchNextConversation = () => { - const { conversationId } = useGetChatSearchParams(); + const { isNew, conversationId } = useGetChatSearchParams(); const { data, isFetching: loading, @@ -214,17 +255,9 @@ export const useFetchNextConversation = () => { gcTime: 0, refetchOnWindowFocus: false, queryFn: async () => { - if (isConversationIdExist(conversationId)) { + if (isNew !== 'true' && isConversationIdExist(conversationId)) { const { data } = await chatService.getConversation({ conversationId }); - // if (data.retcode === 0 && needToBeSaved) { - // yield put({ - // type: 'kFModel/fetch_document_thumbnails', - // payload: { - // doc_ids: getDocumentIdsFromConversionReference(data.data), - // }, - // }); - // yield put({ type: 'setCurrentConversation', payload: data.data }); - // } + const conversation = data?.data ?? {}; const messageList = buildMessageListWithUuid(conversation?.message); @@ -265,7 +298,12 @@ export const useUpdateNextConversation = () => { } = useMutation({ mutationKey: ['updateConversation'], mutationFn: async (params: Record) => { - const { data } = await chatService.setConversation(params); + const { data } = await chatService.setConversation({ + ...params, + conversation_id: params.conversation_id + ? params.conversation_id + : getConversationId(), + }); if (data.retcode === 0) { queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] }); } diff --git a/web/src/hooks/logic-hooks.ts b/web/src/hooks/logic-hooks.ts index e51cb9ad40..c1a7e92e8e 100644 --- a/web/src/hooks/logic-hooks.ts +++ b/web/src/hooks/logic-hooks.ts @@ -224,6 +224,7 @@ export const useSendMessageWithSse = ( const send = useCallback( async ( body: any, + controller?: AbortController, ): Promise<{ response: Response; data: ResponseType } | undefined> => { try { setDone(false); @@ -234,6 +235,7 @@ export const useSendMessageWithSse = ( 'Content-Type': 'application/json', }, body: JSON.stringify(body), + signal: controller?.signal, }); const res = response.clone().json(); @@ -249,6 +251,7 @@ export const useSendMessageWithSse = ( const { done, value } = x; if (done) { console.info('done'); + setAnswer({} as IAnswer); break; } try { @@ -268,9 +271,12 @@ export const useSendMessageWithSse = ( } console.info('done?'); setDone(true); + setAnswer({} as IAnswer); return { data: await res, response }; } catch (e) { setDone(true); + setAnswer({} as IAnswer); + console.warn(e); } }, diff --git a/web/src/interfaces/database/chat.ts b/web/src/interfaces/database/chat.ts index 271634037a..e00d4ed7ed 100644 --- a/web/src/interfaces/database/chat.ts +++ b/web/src/interfaces/database/chat.ts @@ -63,6 +63,7 @@ export interface IConversation { name: string; update_date: string; update_time: number; + is_new: true; } export interface Message { diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 20c78f0b27..c20a79acca 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -580,7 +580,7 @@ The above is the content you need to summarize.`, addGoogleRegion: 'Google Cloud Region', GoogleRegionMessage: 'Please input Google Cloud Region', modelProvidersWarn: - 'Please add both embedding model and LLM in Settings > Model providers firstly.', + 'Please add both embedding model and LLM in Settings > Model providers firstly.', }, message: { registered: 'Registered!', diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index 398aece57a..a6ebf55db2 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -19,10 +19,13 @@ import { } from '@/hooks/chat-hooks'; import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; import { memo } from 'react'; -import { ConversationContext } from '../context'; import styles from './index.less'; -const ChatContainer = () => { +interface IProps { + controller: AbortController; +} + +const ChatContainer = ({ controller }: IProps) => { const { conversationId } = useGetChatSearchParams(); const { data: conversation } = useFetchNextConversation(); @@ -36,8 +39,7 @@ const ChatContainer = () => { handlePressEnter, regenerateMessage, removeMessageById, - redirectToNewConversation, - } = useSendNextMessage(); + } = useSendNextMessage(controller); const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = useClickDrawer(); @@ -54,35 +56,33 @@ const ChatContainer = () => {
- - {derivedMessages?.map((message, i) => { - return ( - - ); - })} - + {derivedMessages?.map((message, i) => { + return ( + + ); + })}
diff --git a/web/src/pages/chat/constants.ts b/web/src/pages/chat/constants.ts index 0c93f8ddff..8c9a965f46 100644 --- a/web/src/pages/chat/constants.ts +++ b/web/src/pages/chat/constants.ts @@ -1,6 +1 @@ -export enum ChatSearchParams { - DialogId = 'dialogId', - ConversationId = 'conversationId', -} - export const EmptyConversationId = 'empty'; diff --git a/web/src/pages/chat/hooks.ts b/web/src/pages/chat/hooks.ts index b11b9e0980..7444990dcc 100644 --- a/web/src/pages/chat/hooks.ts +++ b/web/src/pages/chat/hooks.ts @@ -1,4 +1,4 @@ -import { MessageType } from '@/constants/chat'; +import { ChatSearchParams, MessageType } from '@/constants/chat'; import { fileIconMap } from '@/constants/common'; import { useFetchManualConversation, @@ -24,6 +24,8 @@ import { } from '@/hooks/logic-hooks'; import { IConversation, IDialog, Message } from '@/interfaces/database/chat'; import { getFileExtension } from '@/utils'; +import api from '@/utils/api'; +import { getConversationId } from '@/utils/chat'; import { useMutationState } from '@tanstack/react-query'; import { get } from 'lodash'; import trim from 'lodash/trim'; @@ -32,18 +34,57 @@ import { useCallback, useEffect, useMemo, - useRef, useState, } from 'react'; import { useSearchParams } from 'umi'; import { v4 as uuid } from 'uuid'; -import { ChatSearchParams } from './constants'; import { IClientConversation, IMessage, VariableTableDataType, } from './interface'; +export const useSetChatRouteParams = () => { + const [currentQueryParameters, setSearchParams] = useSearchParams(); + const newQueryParameters: URLSearchParams = useMemo( + () => new URLSearchParams(currentQueryParameters.toString()), + [currentQueryParameters], + ); + + const setConversationIsNew = useCallback( + (value: string) => { + newQueryParameters.set(ChatSearchParams.isNew, value); + setSearchParams(newQueryParameters); + }, + [newQueryParameters, setSearchParams], + ); + + const getConversationIsNew = useCallback(() => { + return newQueryParameters.get(ChatSearchParams.isNew); + }, [newQueryParameters]); + + return { setConversationIsNew, getConversationIsNew }; +}; + +export const useSetNewConversationRouteParams = () => { + const [currentQueryParameters, setSearchParams] = useSearchParams(); + const newQueryParameters: URLSearchParams = useMemo( + () => new URLSearchParams(currentQueryParameters.toString()), + [currentQueryParameters], + ); + + const setNewConversationRouteParams = useCallback( + (conversationId: string, isNew: string) => { + newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); + newQueryParameters.set(ChatSearchParams.isNew, isNew); + setSearchParams(newQueryParameters); + }, + [newQueryParameters, setSearchParams], + ); + + return { setNewConversationRouteParams }; +}; + export const useSelectCurrentDialog = () => { const data = useMutationState({ filters: { mutationKey: ['fetchDialog'] }, @@ -169,22 +210,26 @@ export const useSelectDerivedConversationList = () => { const { data: conversationList, loading } = useFetchNextConversationList(); const { dialogId } = useGetChatSearchParams(); const prologue = currentDialog?.prompt_config?.prologue ?? ''; + const { setNewConversationRouteParams } = useSetNewConversationRouteParams(); const addTemporaryConversation = useCallback(() => { + const conversationId = getConversationId(); setList((pre) => { if (dialogId) { + setNewConversationRouteParams(conversationId, 'true'); const nextList = [ { - id: '', + id: conversationId, name: t('newConversation'), dialog_id: dialogId, + is_new: true, message: [ { content: prologue, role: MessageType.Assistant, }, ], - } as IConversation, + } as any, ...conversationList, ]; return nextList; @@ -192,42 +237,32 @@ export const useSelectDerivedConversationList = () => { return pre; }); - }, [conversationList, dialogId, prologue, t]); + }, [conversationList, dialogId, prologue, t, setNewConversationRouteParams]); + + // When you first enter the page, select the top conversation card useEffect(() => { - addTemporaryConversation(); - }, [addTemporaryConversation]); + setList([...conversationList]); + }, [conversationList]); return { list, addTemporaryConversation, loading }; }; -export const useClickConversationCard = () => { - const [currentQueryParameters, setSearchParams] = useSearchParams(); - const newQueryParameters: URLSearchParams = useMemo( - () => new URLSearchParams(currentQueryParameters.toString()), - [currentQueryParameters], - ); - - const handleClickConversation = useCallback( - (conversationId: string) => { - newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); - setSearchParams(newQueryParameters); - }, - [newQueryParameters, setSearchParams], - ); - - return { handleClickConversation }; -}; - export const useSetConversation = () => { const { dialogId } = useGetChatSearchParams(); const { updateConversation } = useUpdateNextConversation(); const setConversation = useCallback( - (message: string) => { - return updateConversation({ + async ( + message: string, + isNew: boolean = false, + conversationId?: string, + ) => { + const data = await updateConversation({ dialog_id: dialogId, name: message, + is_new: isNew, + conversation_id: conversationId, message: [ { role: MessageType.Assistant, @@ -235,6 +270,8 @@ export const useSetConversation = () => { }, ], }); + + return data; }, [updateConversation, dialogId], ); @@ -242,22 +279,6 @@ export const useSetConversation = () => { return { setConversation }; }; -// export const useScrollToBottom = (currentConversation: IClientConversation) => { -// const ref = useRef(null); - -// const scrollToBottom = useCallback(() => { -// if (currentConversation.id) { -// ref.current?.scrollIntoView({ behavior: 'instant' }); -// } -// }, [currentConversation]); - -// useEffect(() => { -// scrollToBottom(); -// }, [scrollToBottom]); - -// return ref; -// }; - export const useSelectNextMessages = () => { const { ref, @@ -271,10 +292,10 @@ export const useSelectNextMessages = () => { } = useSelectDerivedMessages(); const { data: conversation, loading } = useFetchNextConversation(); const { data: dialog } = useFetchNextDialog(); - const { conversationId, dialogId } = useGetChatSearchParams(); + const { conversationId, dialogId, isNew } = useGetChatSearchParams(); const addPrologue = useCallback(() => { - if (dialogId !== '' && conversationId === '') { + if (dialogId !== '' && isNew === 'true') { const prologue = dialog.prompt_config?.prologue; const nextMessage = { @@ -285,17 +306,25 @@ export const useSelectNextMessages = () => { setDerivedMessages([nextMessage]); } - }, [conversationId, dialog, dialogId, setDerivedMessages]); + }, [isNew, dialog, dialogId, setDerivedMessages]); useEffect(() => { addPrologue(); }, [addPrologue]); useEffect(() => { - if (conversationId) { + if ( + conversationId && + isNew !== 'true' && + conversation.message?.length > 0 + ) { setDerivedMessages(conversation.message); } - }, [conversation.message, conversationId, setDerivedMessages]); + + if (!conversationId) { + setDerivedMessages([]); + } + }, [conversation.message, conversationId, setDerivedMessages, isNew]); return { ref, @@ -325,12 +354,14 @@ export const useHandleMessageInputChange = () => { }; }; -export const useSendNextMessage = () => { +export const useSendNextMessage = (controller: AbortController) => { const { setConversation } = useSetConversation(); - const { conversationId } = useGetChatSearchParams(); + const { conversationId, isNew } = useGetChatSearchParams(); const { handleInputChange, value, setValue } = useHandleMessageInputChange(); - const { handleClickConversation } = useClickConversationCard(); - const { send, answer, done, setDone, resetAnswer } = useSendMessageWithSse(); + + const { send, answer, done } = useSendMessageWithSse( + api.completeConversation, + ); const { ref, derivedMessages, @@ -341,17 +372,8 @@ export const useSendNextMessage = () => { removeMessageById, removeMessagesAfterCurrentMessage, } = useSelectNextMessages(); - const { data: dialog } = useFetchNextDialog(); - const currentConversationIdRef = useRef(''); - - const redirectToNewConversation = useCallback( - (isPlaying: boolean) => { - if (!conversationId && dialog?.prompt_config?.tts && !isPlaying) { - handleClickConversation(currentConversationIdRef.current); - } - }, - [dialog, handleClickConversation, conversationId], - ); + const { setConversationIsNew, getConversationIsNew } = + useSetChatRouteParams(); const sendMessage = useCallback( async ({ @@ -363,49 +385,46 @@ export const useSendNextMessage = () => { currentConversationId?: string; messages?: Message[]; }) => { - const res = await send({ - conversation_id: currentConversationId ?? conversationId, - messages: [...(messages ?? derivedMessages ?? []), message], - }); + const res = await send( + { + conversation_id: currentConversationId ?? conversationId, + messages: [...(messages ?? derivedMessages ?? []), message], + }, + controller, + ); if (res && (res?.response.status !== 200 || res?.data?.retcode !== 0)) { // cancel loading setValue(message.content); console.info('removeLatestMessage111'); removeLatestMessage(); - } else { - if (currentConversationId) { - console.info('111'); - // new conversation - if (!dialog?.prompt_config?.tts) { - handleClickConversation(currentConversationId); - } - } else { - console.info('222'); - // fetchConversation(conversationId); - } } }, [ - dialog, derivedMessages, conversationId, - handleClickConversation, removeLatestMessage, setValue, send, + controller, ], ); const handleSendMessage = useCallback( async (message: Message) => { - if (conversationId !== '') { + const isNew = getConversationIsNew(); + if (isNew !== 'true') { sendMessage({ message }); } else { - const data = await setConversation(message.content); + const data = await setConversation( + message.content, + true, + conversationId, + ); if (data.retcode === 0) { + setConversationIsNew(''); const id = data.data.id; - currentConversationIdRef.current = id; + // currentConversationIdRef.current = id; sendMessage({ message, currentConversationId: id, @@ -414,7 +433,13 @@ export const useSendNextMessage = () => { } } }, - [conversationId, setConversation, sendMessage], + [ + setConversation, + sendMessage, + setConversationIsNew, + getConversationIsNew, + conversationId, + ], ); const { regenerateMessage } = useRegenerateMessage({ @@ -425,24 +450,10 @@ export const useSendNextMessage = () => { useEffect(() => { // #1289 - console.log('🚀 ~ useEffect ~ answer:', answer, done); - if ( - answer.answer && - (answer?.conversationId === conversationId || - ((!done || (done && answer.audio_binary)) && conversationId === '')) - ) { + if (answer.answer && conversationId && isNew !== 'true') { addNewestAnswer(answer); } - }, [answer, addNewestAnswer, conversationId, done]); - - useEffect(() => { - // #1289 switch to another conversion window when the last conversion answer doesn't finish. - if (conversationId) { - setDone(true); - } else { - resetAnswer(); - } - }, [setDone, conversationId, resetAnswer]); + }, [answer, addNewestAnswer, conversationId, isNew]); const handlePressEnter = useCallback( (documentIds: string[]) => { @@ -479,7 +490,6 @@ export const useSendNextMessage = () => { ref, derivedMessages, removeMessageById, - redirectToNewConversation, }; }; @@ -494,15 +504,12 @@ export const useGetFileIcon = () => { }; export const useDeleteConversation = () => { - const { handleClickConversation } = useClickConversationCard(); const showDeleteConfirm = useShowDeleteConfirm(); const { removeConversation } = useRemoveNextConversation(); const deleteConversation = (conversationIds: Array) => async () => { const ret = await removeConversation(conversationIds); - if (ret === 0) { - handleClickConversation(''); - } + return ret; }; @@ -531,6 +538,7 @@ export const useRenameConversation = () => { ...conversation, conversation_id: conversation.id, name, + is_new: false, }); if (ret.retcode === 0) { @@ -564,7 +572,7 @@ export const useRenameConversation = () => { export const useGetSendButtonDisabled = () => { const { dialogId, conversationId } = useGetChatSearchParams(); - return dialogId === '' && conversationId === ''; + return dialogId === '' || conversationId === ''; }; export const useSendButtonDisabled = (value: string) => { @@ -575,18 +583,13 @@ export const useCreateConversationBeforeUploadDocument = () => { const { setConversation } = useSetConversation(); const { dialogId } = useGetChatSearchParams(); - const { handleClickConversation } = useClickConversationCard(); - const createConversationBeforeUploadDocument = useCallback( async (message: string) => { - const data = await setConversation(message); - if (data.retcode === 0) { - const id = data.data.id; - handleClickConversation(id); - } + const data = await setConversation(message, true); + return data; }, - [setConversation, handleClickConversation], + [setConversation], ); return { diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 3201b82fe3..5bd5d973ad 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -17,15 +17,15 @@ import { Space, Spin, Tag, + Tooltip, Typography, } from 'antd'; import { MenuItemProps } from 'antd/lib/menu/MenuItem'; import classNames from 'classnames'; -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import ChatConfigurationModal from './chat-configuration-modal'; import ChatContainer from './chat-container'; import { - useClickConversationCard, useDeleteConversation, useDeleteDialog, useEditDialog, @@ -36,6 +36,7 @@ import { import ChatOverviewModal from '@/components/api-service/chat-overview-modal'; import { + useClickConversationCard, useClickDialogCard, useFetchNextDialogList, useGetChatSearchParams, @@ -89,6 +90,7 @@ const Chat = () => { showModal: showOverviewModal, } = useSetModalState(); const { currentRecord, setRecord } = useSetSelectedRecord(); + const [controller, setController] = useState(new AbortController()); const handleAppCardEnter = (id: string) => () => { handleItemEnter(id); @@ -139,31 +141,28 @@ const Chat = () => { showConversationRenameModal(conversationId); }; - const handleDialogCardClick = (dialogId: string) => () => { - handleClickDialog(dialogId); - }; + const handleDialogCardClick = useCallback( + (dialogId: string) => () => { + handleClickDialog(dialogId); + }, + [handleClickDialog], + ); - const handleConversationCardClick = (dialogId: string) => () => { - handleClickConversation(dialogId); - }; + const handleConversationCardClick = useCallback( + (conversationId: string, isNew: boolean) => () => { + handleClickConversation(conversationId, isNew ? 'true' : ''); + setController((pre) => { + pre.abort(); + return new AbortController(); + }); + }, + [handleClickConversation], + ); const handleCreateTemporaryConversation = useCallback(() => { addTemporaryConversation(); }, [addTemporaryConversation]); - const items: MenuProps['items'] = [ - { - key: '1', - onClick: handleCreateTemporaryConversation, - label: ( - - - {t('newChat')} - - ), - }, - ]; - const buildAppItems = (dialog: IDialog) => { const dialogId = dialog.id; @@ -297,10 +296,9 @@ const Chat = () => { {t('chat')} {conversationList.length} - - {/* */} - - + + + @@ -312,7 +310,7 @@ const Chat = () => { { - + {dialogEditVisible && ( label={t('addFishAudioRefID')} name="fish_audio_refid" - rules={[{ required: false, message: t('FishAudioRefIDMessage') }]} + rules={[{ required: true, message: t('FishAudioRefIDMessage') }]} > diff --git a/web/src/utils/chat.ts b/web/src/utils/chat.ts index 984f9bc9d7..1caf001790 100644 --- a/web/src/utils/chat.ts +++ b/web/src/utils/chat.ts @@ -32,3 +32,7 @@ export const buildMessageListWithUuid = (messages?: Message[]) => { })) ?? [] ); }; + +export const getConversationId = () => { + return uuid().replace(/-/g, ''); +};