From fb0426419eab110c90c6db08a7326e9fd121941c Mon Sep 17 00:00:00 2001 From: balibabu Date: Wed, 6 Aug 2025 11:42:40 +0800 Subject: [PATCH] Feat: Create a conversation #3221 (#9269) ### What problem does this PR solve? Feat: Create a conversation #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/hooks/use-chat-request.ts | 70 +++++---- web/src/pages/home/chat-list.tsx | 4 +- web/src/pages/next-chats/chat/index.tsx | 4 +- .../pages/next-chats/hooks/use-rename-chat.ts | 45 +++++- web/src/pages/next-chats/index.tsx | 11 +- web/src/services/next-chat-service .ts | 133 ++++++++++++++++++ web/src/utils/api.ts | 3 + 7 files changed, 229 insertions(+), 41 deletions(-) create mode 100644 web/src/services/next-chat-service .ts diff --git a/web/src/hooks/use-chat-request.ts b/web/src/hooks/use-chat-request.ts index 5e7ee80fd..62f05047c 100644 --- a/web/src/hooks/use-chat-request.ts +++ b/web/src/hooks/use-chat-request.ts @@ -1,12 +1,12 @@ import message from '@/components/ui/message'; import { ChatSearchParams } from '@/constants/chat'; import { IDialog } from '@/interfaces/database/chat'; -import chatService from '@/services/chat-service'; +import chatService from '@/services/next-chat-service '; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useDebounce } from 'ahooks'; import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { history, useSearchParams } from 'umi'; +import { useParams, useSearchParams } from 'umi'; import { useGetPaginationWithRouter, useHandleSearchChange, @@ -16,6 +16,7 @@ export const enum ChatApiAction { FetchDialogList = 'fetchDialogList', RemoveDialog = 'removeDialog', SetDialog = 'setDialog', + FetchDialog = 'fetchDialog', } export const useGetChatSearchParams = () => { @@ -52,9 +53,7 @@ export const useClickDialogCard = () => { return { handleClickDialog }; }; -export const useFetchDialogList = (pureFetch = false) => { - const { handleClickDialog } = useClickDialogCard(); - const { dialogId } = useGetChatSearchParams(); +export const useFetchDialogList = () => { const { searchString, handleInputChange } = useHandleSearchChange(); const { pagination, setPagination } = useGetPaginationWithRouter(); const debouncedSearchString = useDebounce(searchString, { wait: 500 }); @@ -63,7 +62,7 @@ export const useFetchDialogList = (pureFetch = false) => { data, isFetching: loading, refetch, - } = useQuery({ + } = useQuery<{ dialogs: IDialog[]; total: number }>({ queryKey: [ ChatApiAction.FetchDialogList, { @@ -71,27 +70,17 @@ export const useFetchDialogList = (pureFetch = false) => { ...pagination, }, ], - initialData: [], + initialData: { dialogs: [], total: 0 }, gcTime: 0, refetchOnWindowFocus: false, - queryFn: async (...params) => { - console.log('🚀 ~ queryFn: ~ params:', params); - const { data } = await chatService.listDialog(); + queryFn: async () => { + const { data } = await chatService.listDialog({ + keywords: debouncedSearchString, + page_size: pagination.pageSize, + page: pagination.current, + }); - if (data.code === 0) { - const list: IDialog[] = data.data; - if (!pureFetch) { - if (list.length > 0) { - if (list.every((x) => x.id !== dialogId)) { - handleClickDialog(data.data[0].id); - } - } else { - history.push('/chat'); - } - } - } - - return data?.data ?? []; + return data?.data ?? { dialogs: [], total: 0 }; }, }); @@ -147,17 +136,14 @@ export const useSetDialog = () => { mutateAsync, } = useMutation({ mutationKey: [ChatApiAction.SetDialog], - mutationFn: async (params: IDialog) => { + mutationFn: async (params: Partial) => { const { data } = await chatService.setDialog(params); if (data.code === 0) { queryClient.invalidateQueries({ exact: false, - queryKey: ['fetchDialogList'], + queryKey: [ChatApiAction.FetchDialogList], }); - queryClient.invalidateQueries({ - queryKey: ['fetchDialog'], - }); message.success( t(`message.${params.dialog_id ? 'modified' : 'created'}`), ); @@ -168,3 +154,29 @@ export const useSetDialog = () => { return { data, loading, setDialog: mutateAsync }; }; + +export const useFetchDialog = () => { + const { id } = useParams(); + + const { + data, + isFetching: loading, + refetch, + } = useQuery({ + queryKey: [ChatApiAction.FetchDialog, id], + gcTime: 0, + initialData: {} as IDialog, + enabled: !!id, + refetchOnWindowFocus: false, + queryFn: async () => { + const { data } = await chatService.getDialog( + { params: { dialogId: id } }, + true, + ); + + return data?.data ?? ({} as IDialog); + }, + }); + + return { data, loading, refetch }; +}; diff --git a/web/src/pages/home/chat-list.tsx b/web/src/pages/home/chat-list.tsx index 2ef8e049e..65d756a85 100644 --- a/web/src/pages/home/chat-list.tsx +++ b/web/src/pages/home/chat-list.tsx @@ -2,9 +2,9 @@ import { useFetchDialogList } from '@/hooks/use-chat-request'; import { ApplicationCard } from './application-card'; export function ChatList() { - const { data } = useFetchDialogList(true); + const { data } = useFetchDialogList(); - return data + return data.dialogs .slice(0, 10) .map((x) => ( - +
@@ -41,7 +45,7 @@ export default function ChatList() {
- {chatList.map((x) => { + {data.dialogs.map((x) => { return ( )} diff --git a/web/src/services/next-chat-service .ts b/web/src/services/next-chat-service .ts new file mode 100644 index 000000000..50a29c974 --- /dev/null +++ b/web/src/services/next-chat-service .ts @@ -0,0 +1,133 @@ +import api from '@/utils/api'; +import { registerNextServer } from '@/utils/register-server'; + +const { + getDialog, + setDialog, + listDialog, + removeDialog, + getConversation, + getConversationSSE, + setConversation, + completeConversation, + listConversation, + removeConversation, + createToken, + listToken, + removeToken, + getStats, + createExternalConversation, + getExternalConversation, + completeExternalConversation, + uploadAndParseExternal, + deleteMessage, + thumbup, + tts, + ask, + mindmap, + getRelatedQuestions, + listNextDialog, +} = api; + +const methods = { + getDialog: { + url: getDialog, + method: 'get', + }, + setDialog: { + url: setDialog, + method: 'post', + }, + removeDialog: { + url: removeDialog, + method: 'post', + }, + listDialog: { + url: listNextDialog, + method: 'post', + }, + listConversation: { + url: listConversation, + method: 'get', + }, + getConversation: { + url: getConversation, + method: 'get', + }, + getConversationSSE: { + url: getConversationSSE, + method: 'get', + }, + setConversation: { + url: setConversation, + method: 'post', + }, + completeConversation: { + url: completeConversation, + method: 'post', + }, + removeConversation: { + url: removeConversation, + method: 'post', + }, + createToken: { + url: createToken, + method: 'post', + }, + listToken: { + url: listToken, + method: 'get', + }, + removeToken: { + url: removeToken, + method: 'post', + }, + getStats: { + url: getStats, + method: 'get', + }, + createExternalConversation: { + url: createExternalConversation, + method: 'get', + }, + getExternalConversation: { + url: getExternalConversation, + method: 'get', + }, + completeExternalConversation: { + url: completeExternalConversation, + method: 'post', + }, + uploadAndParseExternal: { + url: uploadAndParseExternal, + method: 'post', + }, + deleteMessage: { + url: deleteMessage, + method: 'post', + }, + thumbup: { + url: thumbup, + method: 'post', + }, + tts: { + url: tts, + method: 'post', + }, + ask: { + url: ask, + method: 'post', + }, + getMindMap: { + url: mindmap, + method: 'post', + }, + getRelatedQuestions: { + url: getRelatedQuestions, + method: 'post', + }, +} as const; + +const chatService = registerNextServer(methods); + +export default chatService; diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 316820687..98eba37dd 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -108,6 +108,9 @@ export default { completeExternalConversation: `${api_host}/api/completion`, uploadAndParseExternal: `${api_host}/api/document/upload_and_parse`, + // next chat + listNextDialog: `${api_host}/dialog/next`, + // file manager listFile: `${api_host}/file/list`, uploadFile: `${api_host}/file/upload`,