### What problem does this PR solve? feat: Fetch conversation list by @tanstack/react-query feat: Displays error message that task_executor does not exist ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.11.0
| .thumbnailImg { | .thumbnailImg { | ||||
| display: inline-block; | |||||
| max-width: 20px; | max-width: 20px; | ||||
| } | } |
| Agent = 'agent', | Agent = 'agent', | ||||
| Chat = 'chat', | Chat = 'chat', | ||||
| } | } | ||||
| export enum ChatSearchParams { | |||||
| DialogId = 'dialogId', | |||||
| ConversationId = 'conversationId', | |||||
| } | |||||
| export const EmptyConversationId = 'empty'; |
| import { ChatSearchParams } from '@/constants/chat'; | |||||
| import { | import { | ||||
| IConversation, | IConversation, | ||||
| IDialog, | IDialog, | ||||
| IStats, | IStats, | ||||
| IToken, | IToken, | ||||
| Message, | |||||
| } from '@/interfaces/database/chat'; | } from '@/interfaces/database/chat'; | ||||
| import i18n from '@/locales/config'; | |||||
| import { IClientConversation, IMessage } from '@/pages/chat/interface'; | |||||
| import chatService from '@/services/chat-service'; | import chatService from '@/services/chat-service'; | ||||
| import { isConversationIdExist } from '@/utils/chat'; | |||||
| import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | ||||
| import { message } from 'antd'; | |||||
| import dayjs, { Dayjs } from 'dayjs'; | import dayjs, { Dayjs } from 'dayjs'; | ||||
| import { useCallback, useState } from 'react'; | |||||
| import { useDispatch, useSelector } from 'umi'; | |||||
| import { useCallback, useMemo, useState } from 'react'; | |||||
| import { useSearchParams } from 'umi'; | |||||
| import { v4 as uuid } from 'uuid'; | |||||
| //#region logic | |||||
| export const useClickDialogCard = () => { | |||||
| const [, setSearchParams] = useSearchParams(); | |||||
| const newQueryParameters: URLSearchParams = useMemo(() => { | |||||
| return new URLSearchParams(); | |||||
| }, []); | |||||
| const handleClickDialog = useCallback( | |||||
| (dialogId: string) => { | |||||
| newQueryParameters.set(ChatSearchParams.DialogId, dialogId); | |||||
| // newQueryParameters.set( | |||||
| // ChatSearchParams.ConversationId, | |||||
| // EmptyConversationId, | |||||
| // ); | |||||
| setSearchParams(newQueryParameters); | |||||
| }, | |||||
| [newQueryParameters, setSearchParams], | |||||
| ); | |||||
| export const useFetchDialogList = () => { | |||||
| const dispatch = useDispatch(); | |||||
| return { handleClickDialog }; | |||||
| }; | |||||
| const fetchDialogList = useCallback(() => { | |||||
| return dispatch<any>({ type: 'chatModel/listDialog' }); | |||||
| }, [dispatch]); | |||||
| export const useGetChatSearchParams = () => { | |||||
| const [currentQueryParameters] = useSearchParams(); | |||||
| return fetchDialogList; | |||||
| return { | |||||
| dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', | |||||
| conversationId: | |||||
| currentQueryParameters.get(ChatSearchParams.ConversationId) || '', | |||||
| }; | |||||
| }; | }; | ||||
| export const useSelectDialogList = () => { | |||||
| const dialogList: IDialog[] = useSelector( | |||||
| (state: any) => state.chatModel.dialogList, | |||||
| ); | |||||
| //#endregion | |||||
| return dialogList; | |||||
| }; | |||||
| //#region dialog | |||||
| export const useFetchConversationList = () => { | |||||
| const dispatch = useDispatch(); | |||||
| export const useFetchNextDialogList = () => { | |||||
| const { handleClickDialog } = useClickDialogCard(); | |||||
| const fetchConversationList = useCallback( | |||||
| async (dialogId: string) => { | |||||
| if (dialogId) { | |||||
| dispatch({ | |||||
| type: 'chatModel/listConversation', | |||||
| payload: { dialog_id: dialogId }, | |||||
| }); | |||||
| const { | |||||
| data, | |||||
| isFetching: loading, | |||||
| refetch, | |||||
| } = useQuery<IDialog[]>({ | |||||
| queryKey: ['fetchDialogList'], | |||||
| initialData: [], | |||||
| gcTime: 0, | |||||
| refetchOnWindowFocus: false, | |||||
| queryFn: async () => { | |||||
| const { data } = await chatService.listDialog(); | |||||
| if (data.retcode === 0 && data.data.length > 0) { | |||||
| handleClickDialog(data.data[0].id); | |||||
| } | } | ||||
| return data?.data ?? []; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return fetchConversationList; | |||||
| return { data, loading, refetch }; | |||||
| }; | }; | ||||
| export const useSelectConversationList = () => { | |||||
| const conversationList: IConversation[] = useSelector( | |||||
| (state: any) => state.chatModel.conversationList, | |||||
| ); | |||||
| export const useSetNextDialog = () => { | |||||
| const queryClient = useQueryClient(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['setDialog'], | |||||
| mutationFn: async (params: IDialog) => { | |||||
| const { data } = await chatService.setDialog(params); | |||||
| if (data.retcode === 0) { | |||||
| queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] }); | |||||
| message.success( | |||||
| i18n.t(`message.${params.id ? 'modified' : 'created'}`), | |||||
| ); | |||||
| } | |||||
| return data?.retcode; | |||||
| }, | |||||
| }); | |||||
| return conversationList; | |||||
| return { data, loading, setDialog: mutateAsync }; | |||||
| }; | }; | ||||
| export const useFetchConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const fetchConversation = useCallback( | |||||
| (conversationId: string, needToBeSaved = true) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/getConversation', | |||||
| payload: { | |||||
| needToBeSaved, | |||||
| conversation_id: conversationId, | |||||
| }, | |||||
| }); | |||||
| export const useFetchNextDialog = () => { | |||||
| const { dialogId } = useGetChatSearchParams(); | |||||
| const { data, isFetching: loading } = useQuery<IDialog>({ | |||||
| queryKey: ['fetchDialog', dialogId], | |||||
| gcTime: 0, | |||||
| initialData: {} as IDialog, | |||||
| enabled: !!dialogId, | |||||
| refetchOnWindowFocus: false, | |||||
| queryFn: async () => { | |||||
| const { data } = await chatService.getDialog({ dialogId }); | |||||
| return data?.data ?? ({} as IDialog); | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return fetchConversation; | |||||
| return { data, loading }; | |||||
| }; | }; | ||||
| export const useFetchDialog = () => { | |||||
| const dispatch = useDispatch(); | |||||
| export const useFetchManualDialog = () => { | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['fetchManualDialog'], | |||||
| gcTime: 0, | |||||
| mutationFn: async (dialogId: string) => { | |||||
| const { data } = await chatService.getDialog({ dialogId }); | |||||
| const fetchDialog = useCallback( | |||||
| (dialogId: string, needToBeSaved = true) => { | |||||
| if (dialogId) { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/getDialog', | |||||
| payload: { dialog_id: dialogId, needToBeSaved }, | |||||
| }); | |||||
| return data; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, fetchDialog: mutateAsync }; | |||||
| }; | |||||
| export const useRemoveNextDialog = () => { | |||||
| const queryClient = useQueryClient(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['removeDialog'], | |||||
| mutationFn: async (dialogIds: string[]) => { | |||||
| const { data } = await chatService.removeDialog({ dialogIds }); | |||||
| if (data.retcode === 0) { | |||||
| queryClient.invalidateQueries({ queryKey: ['fetchDialogList'] }); | |||||
| message.success(i18n.t('message.deleted')); | |||||
| } | } | ||||
| return data.retcode; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return fetchDialog; | |||||
| return { data, loading, removeDialog: mutateAsync }; | |||||
| }; | }; | ||||
| export const useRemoveDialog = () => { | |||||
| const dispatch = useDispatch(); | |||||
| //#endregion | |||||
| //#region conversation | |||||
| const removeDocument = useCallback( | |||||
| (dialogIds: Array<string>) => { | |||||
| return dispatch({ | |||||
| type: 'chatModel/removeDialog', | |||||
| payload: { | |||||
| dialog_ids: dialogIds, | |||||
| }, | |||||
| }); | |||||
| export const useFetchNextConversationList = () => { | |||||
| const { dialogId } = useGetChatSearchParams(); | |||||
| const { | |||||
| data, | |||||
| isFetching: loading, | |||||
| refetch, | |||||
| } = useQuery<IConversation[]>({ | |||||
| queryKey: ['fetchConversationList', dialogId], | |||||
| initialData: [], | |||||
| gcTime: 0, | |||||
| refetchOnWindowFocus: false, | |||||
| enabled: !!dialogId, | |||||
| queryFn: async () => { | |||||
| const { data } = await chatService.listConversation({ dialogId }); | |||||
| return data?.data; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return removeDocument; | |||||
| return { data, loading, refetch }; | |||||
| }; | }; | ||||
| export const useUpdateConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| export const useFetchNextConversation = () => { | |||||
| const { conversationId } = useGetChatSearchParams(); | |||||
| const { | |||||
| data, | |||||
| isFetching: loading, | |||||
| refetch, | |||||
| } = useQuery<IClientConversation>({ | |||||
| queryKey: ['fetchConversation', conversationId], | |||||
| initialData: {} as IClientConversation, | |||||
| // enabled: isConversationIdExist(conversationId), | |||||
| gcTime: 0, | |||||
| refetchOnWindowFocus: false, | |||||
| queryFn: async () => { | |||||
| if (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 = | |||||
| conversation?.message?.map((x: Message | IMessage) => ({ | |||||
| ...x, | |||||
| id: 'id' in x && x.id ? x.id : uuid(), | |||||
| })) ?? []; | |||||
| return { ...conversation, message: messageList }; | |||||
| } | |||||
| return { message: [] }; | |||||
| }, | |||||
| }); | |||||
| const updateConversation = useCallback( | |||||
| (payload: any) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/setConversation', | |||||
| payload, | |||||
| }); | |||||
| return { data, loading, refetch }; | |||||
| }; | |||||
| export const useFetchManualConversation = () => { | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['fetchManualConversation'], | |||||
| gcTime: 0, | |||||
| mutationFn: async (conversationId: string) => { | |||||
| const { data } = await chatService.getConversation({ conversationId }); | |||||
| return data; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return updateConversation; | |||||
| return { data, loading, fetchConversation: mutateAsync }; | |||||
| }; | }; | ||||
| export const useUpdateNextConversation = () => { | export const useUpdateNextConversation = () => { | ||||
| const queryClient = useQueryClient(); | |||||
| const { | const { | ||||
| data, | data, | ||||
| isPending: loading, | isPending: loading, | ||||
| mutationKey: ['updateConversation'], | mutationKey: ['updateConversation'], | ||||
| mutationFn: async (params: Record<string, any>) => { | mutationFn: async (params: Record<string, any>) => { | ||||
| const { data } = await chatService.setConversation(params); | const { data } = await chatService.setConversation(params); | ||||
| if (data.retcode === 0) { | |||||
| queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] }); | |||||
| } | |||||
| return data; | return data; | ||||
| }, | }, | ||||
| }); | }); | ||||
| return { data, loading, updateConversation: mutateAsync }; | return { data, loading, updateConversation: mutateAsync }; | ||||
| }; | }; | ||||
| export const useSetDialog = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const setDialog = useCallback( | |||||
| (payload: IDialog) => { | |||||
| return dispatch<any>({ type: 'chatModel/setDialog', payload }); | |||||
| }, | |||||
| [dispatch], | |||||
| ); | |||||
| return setDialog; | |||||
| }; | |||||
| export const useRemoveConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const removeConversation = useCallback( | |||||
| (conversationIds: Array<string>, dialogId: string) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/removeConversation', | |||||
| payload: { | |||||
| dialog_id: dialogId, | |||||
| conversation_ids: conversationIds, | |||||
| }, | |||||
| }); | |||||
| }, | |||||
| [dispatch], | |||||
| ); | |||||
| return removeConversation; | |||||
| }; | |||||
| export const useRemoveNextConversation = () => { | |||||
| const queryClient = useQueryClient(); | |||||
| const { dialogId } = useGetChatSearchParams(); | |||||
| /* | |||||
| @deprecated | |||||
| */ | |||||
| export const useCompleteConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const completeConversation = useCallback( | |||||
| (payload: any) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/completeConversation', | |||||
| payload, | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['removeConversation'], | |||||
| mutationFn: async (conversationIds: string[]) => { | |||||
| const { data } = await chatService.removeConversation({ | |||||
| conversationIds, | |||||
| dialogId, | |||||
| }); | }); | ||||
| if (data.retcode === 0) { | |||||
| queryClient.invalidateQueries({ queryKey: ['fetchConversationList'] }); | |||||
| } | |||||
| return data.retcode; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return completeConversation; | |||||
| return { data, loading, removeConversation: mutateAsync }; | |||||
| }; | }; | ||||
| //#endregion | |||||
| // #region API provided for external calls | // #region API provided for external calls | ||||
| export const useCreateToken = (params: Record<string, any>) => { | |||||
| const dispatch = useDispatch(); | |||||
| const createToken = useCallback(() => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/createToken', | |||||
| payload: params, | |||||
| }); | |||||
| }, [dispatch, params]); | |||||
| return createToken; | |||||
| }; | |||||
| export const useCreateNextToken = () => { | export const useCreateNextToken = () => { | ||||
| const queryClient = useQueryClient(); | const queryClient = useQueryClient(); | ||||
| const { | const { | ||||
| //#region shared chat | //#region shared chat | ||||
| export const useCreateSharedConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| export const useCreateNextSharedConversation = () => { | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['createSharedConversation'], | |||||
| mutationFn: async (userId?: string) => { | |||||
| const { data } = await chatService.createExternalConversation({ userId }); | |||||
| const createSharedConversation = useCallback( | |||||
| (userId?: string) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/createExternalConversation', | |||||
| payload: { userId }, | |||||
| }); | |||||
| return data; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return createSharedConversation; | |||||
| return { data, loading, createSharedConversation: mutateAsync }; | |||||
| }; | }; | ||||
| export const useFetchSharedConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| export const useFetchNextSharedConversation = () => { | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['fetchSharedConversation'], | |||||
| mutationFn: async (conversationId: string) => { | |||||
| const { data } = await chatService.getExternalConversation( | |||||
| null, | |||||
| conversationId, | |||||
| ); | |||||
| const fetchSharedConversation = useCallback( | |||||
| (conversationId: string) => { | |||||
| return dispatch<any>({ | |||||
| type: 'chatModel/getExternalConversation', | |||||
| payload: conversationId, | |||||
| }); | |||||
| return data; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return fetchSharedConversation; | |||||
| return { data, loading, fetchConversation: mutateAsync }; | |||||
| }; | }; | ||||
| //#endregion | //#endregion |
| mysql: Minio; | mysql: Minio; | ||||
| redis: Redis; | redis: Redis; | ||||
| task_executor: { | task_executor: { | ||||
| error?: string; | |||||
| status: string; | status: string; | ||||
| elapsed: TaskExecutorElapsed; | |||||
| elapsed?: TaskExecutorElapsed; | |||||
| }; | }; | ||||
| } | } | ||||
| useFetchConversationOnMount, | useFetchConversationOnMount, | ||||
| useGetFileIcon, | useGetFileIcon, | ||||
| useGetSendButtonDisabled, | useGetSendButtonDisabled, | ||||
| useSelectConversationLoading, | |||||
| useSendButtonDisabled, | useSendButtonDisabled, | ||||
| useSendMessage, | useSendMessage, | ||||
| } from '../hooks'; | } from '../hooks'; | ||||
| import MessageInput from '@/components/message-input'; | import MessageInput from '@/components/message-input'; | ||||
| import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | ||||
| import { memo } from 'react'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const ChatContainer = () => { | const ChatContainer = () => { | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| addNewestAnswer, | addNewestAnswer, | ||||
| conversationId, | conversationId, | ||||
| loading, | |||||
| } = useFetchConversationOnMount(); | } = useFetchConversationOnMount(); | ||||
| const { | const { | ||||
| handleInputChange, | handleInputChange, | ||||
| const disabled = useGetSendButtonDisabled(); | const disabled = useGetSendButtonDisabled(); | ||||
| const sendDisabled = useSendButtonDisabled(value); | const sendDisabled = useSendButtonDisabled(value); | ||||
| useGetFileIcon(); | useGetFileIcon(); | ||||
| const loading = useSelectConversationLoading(); | |||||
| const { data: userInfo } = useFetchUserInfo(); | const { data: userInfo } = useFetchUserInfo(); | ||||
| const { createConversationBeforeUploadDocument } = | const { createConversationBeforeUploadDocument } = | ||||
| useCreateConversationBeforeUploadDocument(); | useCreateConversationBeforeUploadDocument(); | ||||
| ); | ); | ||||
| }; | }; | ||||
| export default ChatContainer; | |||||
| export default memo(ChatContainer); |
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { fileIconMap } from '@/constants/common'; | import { fileIconMap } from '@/constants/common'; | ||||
| import { | import { | ||||
| useFetchConversation, | |||||
| useFetchConversationList, | |||||
| useFetchDialog, | |||||
| useFetchDialogList, | |||||
| useRemoveConversation, | |||||
| useRemoveDialog, | |||||
| useSelectConversationList, | |||||
| useSelectDialogList, | |||||
| useSetDialog, | |||||
| useUpdateConversation, | |||||
| useFetchManualConversation, | |||||
| useFetchManualDialog, | |||||
| useFetchNextConversation, | |||||
| useFetchNextConversationList, | |||||
| useFetchNextDialog, | |||||
| useGetChatSearchParams, | |||||
| useRemoveNextConversation, | |||||
| useRemoveNextDialog, | |||||
| useSetNextDialog, | |||||
| useUpdateNextConversation, | |||||
| } from '@/hooks/chat-hooks'; | } from '@/hooks/chat-hooks'; | ||||
| import { | import { | ||||
| useSetModalState, | useSetModalState, | ||||
| useTranslate, | useTranslate, | ||||
| } from '@/hooks/common-hooks'; | } from '@/hooks/common-hooks'; | ||||
| import { useSendMessageWithSse } from '@/hooks/logic-hooks'; | import { useSendMessageWithSse } from '@/hooks/logic-hooks'; | ||||
| import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; | |||||
| import { | import { | ||||
| IAnswer, | IAnswer, | ||||
| IConversation, | IConversation, | ||||
| } from '@/interfaces/database/chat'; | } from '@/interfaces/database/chat'; | ||||
| import { IChunk } from '@/interfaces/database/knowledge'; | import { IChunk } from '@/interfaces/database/knowledge'; | ||||
| import { getFileExtension } from '@/utils'; | import { getFileExtension } from '@/utils'; | ||||
| import { useMutationState } from '@tanstack/react-query'; | |||||
| import { get } from 'lodash'; | |||||
| import omit from 'lodash/omit'; | import omit from 'lodash/omit'; | ||||
| import trim from 'lodash/trim'; | import trim from 'lodash/trim'; | ||||
| import { | import { | ||||
| useRef, | useRef, | ||||
| useState, | useState, | ||||
| } from 'react'; | } from 'react'; | ||||
| import { useDispatch, useSearchParams, useSelector } from 'umi'; | |||||
| import { useSearchParams } from 'umi'; | |||||
| import { v4 as uuid } from 'uuid'; | import { v4 as uuid } from 'uuid'; | ||||
| import { ChatSearchParams } from './constants'; | import { ChatSearchParams } from './constants'; | ||||
| import { | import { | ||||
| IMessage, | IMessage, | ||||
| VariableTableDataType, | VariableTableDataType, | ||||
| } from './interface'; | } from './interface'; | ||||
| import { ChatModelState } from './model'; | |||||
| import { isConversationIdExist } from './utils'; | |||||
| export const useSelectCurrentDialog = () => { | export const useSelectCurrentDialog = () => { | ||||
| const currentDialog: IDialog = useSelector( | |||||
| (state: any) => state.chatModel.currentDialog, | |||||
| ); | |||||
| return currentDialog; | |||||
| }; | |||||
| export const useFetchDialogOnMount = ( | |||||
| dialogId: string, | |||||
| visible: boolean, | |||||
| ): IDialog => { | |||||
| const currentDialog: IDialog = useSelectCurrentDialog(); | |||||
| const fetchDialog = useFetchDialog(); | |||||
| useEffect(() => { | |||||
| if (dialogId && visible) { | |||||
| fetchDialog(dialogId); | |||||
| } | |||||
| }, [dialogId, fetchDialog, visible]); | |||||
| return currentDialog; | |||||
| }; | |||||
| export const useSetCurrentDialog = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const currentDialog: IDialog = useSelector( | |||||
| (state: any) => state.chatModel.currentDialog, | |||||
| ); | |||||
| const setCurrentDialog = useCallback( | |||||
| (dialogId: string) => { | |||||
| dispatch({ | |||||
| type: 'chatModel/setCurrentDialog', | |||||
| payload: { id: dialogId }, | |||||
| }); | |||||
| const data = useMutationState({ | |||||
| filters: { mutationKey: ['fetchDialog'] }, | |||||
| select: (mutation) => { | |||||
| return get(mutation, 'state.data.data', {}); | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return { currentDialog, setCurrentDialog }; | |||||
| }; | |||||
| export const useResetCurrentDialog = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const resetCurrentDialog = useCallback(() => { | |||||
| dispatch({ | |||||
| type: 'chatModel/setCurrentDialog', | |||||
| payload: {}, | |||||
| }); | |||||
| }, [dispatch]); | |||||
| return { resetCurrentDialog }; | |||||
| return (data.at(-1) ?? {}) as IDialog; | |||||
| }; | }; | ||||
| export const useSelectPromptConfigParameters = (): VariableTableDataType[] => { | export const useSelectPromptConfigParameters = (): VariableTableDataType[] => { | ||||
| const currentDialog: IDialog = useSelector( | |||||
| (state: any) => state.chatModel.currentDialog, | |||||
| ); | |||||
| const { data: currentDialog } = useFetchNextDialog(); | |||||
| const finalParameters: VariableTableDataType[] = useMemo(() => { | const finalParameters: VariableTableDataType[] = useMemo(() => { | ||||
| const parameters = currentDialog?.prompt_config?.parameters ?? []; | const parameters = currentDialog?.prompt_config?.parameters ?? []; | ||||
| export const useDeleteDialog = () => { | export const useDeleteDialog = () => { | ||||
| const showDeleteConfirm = useShowDeleteConfirm(); | const showDeleteConfirm = useShowDeleteConfirm(); | ||||
| const removeDocument = useRemoveDialog(); | |||||
| const { removeDialog } = useRemoveNextDialog(); | |||||
| const onRemoveDialog = (dialogIds: Array<string>) => { | const onRemoveDialog = (dialogIds: Array<string>) => { | ||||
| showDeleteConfirm({ onOk: () => removeDocument(dialogIds) }); | |||||
| showDeleteConfirm({ onOk: () => removeDialog(dialogIds) }); | |||||
| }; | }; | ||||
| return { onRemoveDialog }; | return { onRemoveDialog }; | ||||
| }; | }; | ||||
| export const useGetChatSearchParams = () => { | |||||
| const [currentQueryParameters] = useSearchParams(); | |||||
| return { | |||||
| dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', | |||||
| conversationId: | |||||
| currentQueryParameters.get(ChatSearchParams.ConversationId) || '', | |||||
| }; | |||||
| }; | |||||
| export const useSetCurrentConversation = () => { | |||||
| const dispatch = useDispatch(); | |||||
| const setCurrentConversation = useCallback( | |||||
| (currentConversation: IClientConversation) => { | |||||
| dispatch({ | |||||
| type: 'chatModel/setCurrentConversation', | |||||
| payload: currentConversation, | |||||
| }); | |||||
| }, | |||||
| [dispatch], | |||||
| ); | |||||
| return setCurrentConversation; | |||||
| }; | |||||
| export const useClickDialogCard = () => { | |||||
| const [currentQueryParameters, setSearchParams] = useSearchParams(); | |||||
| const newQueryParameters: URLSearchParams = useMemo(() => { | |||||
| return new URLSearchParams(); | |||||
| }, []); | |||||
| const handleClickDialog = useCallback( | |||||
| (dialogId: string) => { | |||||
| newQueryParameters.set(ChatSearchParams.DialogId, dialogId); | |||||
| // newQueryParameters.set( | |||||
| // ChatSearchParams.ConversationId, | |||||
| // EmptyConversationId, | |||||
| // ); | |||||
| setSearchParams(newQueryParameters); | |||||
| }, | |||||
| [newQueryParameters, setSearchParams], | |||||
| ); | |||||
| return { handleClickDialog }; | |||||
| }; | |||||
| export const useSelectFirstDialogOnMount = () => { | |||||
| const fetchDialogList = useFetchDialogList(); | |||||
| const dialogList = useSelectDialogList(); | |||||
| const { handleClickDialog } = useClickDialogCard(); | |||||
| const fetchList = useCallback(async () => { | |||||
| const data = await fetchDialogList(); | |||||
| if (data.retcode === 0 && data.data.length > 0) { | |||||
| handleClickDialog(data.data[0].id); | |||||
| } | |||||
| }, [fetchDialogList, handleClickDialog]); | |||||
| useEffect(() => { | |||||
| fetchList(); | |||||
| }, [fetchList]); | |||||
| return dialogList; | |||||
| }; | |||||
| export const useHandleItemHover = () => { | export const useHandleItemHover = () => { | ||||
| const [activated, setActivated] = useState<string>(''); | const [activated, setActivated] = useState<string>(''); | ||||
| export const useEditDialog = () => { | export const useEditDialog = () => { | ||||
| const [dialog, setDialog] = useState<IDialog>({} as IDialog); | const [dialog, setDialog] = useState<IDialog>({} as IDialog); | ||||
| const fetchDialog = useFetchDialog(); | |||||
| const submitDialog = useSetDialog(); | |||||
| const loading = useOneNamespaceEffectsLoading('chatModel', ['setDialog']); | |||||
| const { fetchDialog } = useFetchManualDialog(); | |||||
| const { setDialog: submitDialog, loading } = useSetNextDialog(); | |||||
| const { | const { | ||||
| visible: dialogEditVisible, | visible: dialogEditVisible, | ||||
| const handleShowDialogEditModal = useCallback( | const handleShowDialogEditModal = useCallback( | ||||
| async (dialogId?: string) => { | async (dialogId?: string) => { | ||||
| if (dialogId) { | if (dialogId) { | ||||
| const ret = await fetchDialog(dialogId, false); | |||||
| const ret = await fetchDialog(dialogId); | |||||
| if (ret.retcode === 0) { | if (ret.retcode === 0) { | ||||
| setDialog(ret.data); | setDialog(ret.data); | ||||
| } | } | ||||
| //#region conversation | //#region conversation | ||||
| export const useFetchConversationListOnMount = () => { | |||||
| const conversationList = useSelectConversationList(); | |||||
| const { dialogId } = useGetChatSearchParams(); | |||||
| const fetchConversationList = useFetchConversationList(); | |||||
| useEffect(() => { | |||||
| fetchConversationList(dialogId); | |||||
| }, [fetchConversationList, dialogId]); | |||||
| return conversationList; | |||||
| }; | |||||
| export const useSelectDerivedConversationList = () => { | export const useSelectDerivedConversationList = () => { | ||||
| const { t } = useTranslate('chat'); | |||||
| const [list, setList] = useState<Array<IConversation>>([]); | const [list, setList] = useState<Array<IConversation>>([]); | ||||
| let chatModel: ChatModelState = useSelector((state: any) => state.chatModel); | |||||
| const { conversationList, currentDialog } = chatModel; | |||||
| const { data: currentDialog } = useFetchNextDialog(); | |||||
| const { data: conversationList, loading } = useFetchNextConversationList(); | |||||
| const { dialogId } = useGetChatSearchParams(); | const { dialogId } = useGetChatSearchParams(); | ||||
| const prologue = currentDialog?.prompt_config?.prologue ?? ''; | const prologue = currentDialog?.prompt_config?.prologue ?? ''; | ||||
| const { t } = useTranslate('chat'); | |||||
| const addTemporaryConversation = useCallback(() => { | const addTemporaryConversation = useCallback(() => { | ||||
| setList((pre) => { | setList((pre) => { | ||||
| if (dialogId) { | if (dialogId) { | ||||
| addTemporaryConversation(); | addTemporaryConversation(); | ||||
| }, [addTemporaryConversation]); | }, [addTemporaryConversation]); | ||||
| return { list, addTemporaryConversation }; | |||||
| return { list, addTemporaryConversation, loading }; | |||||
| }; | }; | ||||
| export const useClickConversationCard = () => { | export const useClickConversationCard = () => { | ||||
| export const useSetConversation = () => { | export const useSetConversation = () => { | ||||
| const { dialogId } = useGetChatSearchParams(); | const { dialogId } = useGetChatSearchParams(); | ||||
| const updateConversation = useUpdateConversation(); | |||||
| const { updateConversation } = useUpdateNextConversation(); | |||||
| const setConversation = useCallback( | const setConversation = useCallback( | ||||
| (message: string) => { | (message: string) => { | ||||
| export const useSelectCurrentConversation = () => { | export const useSelectCurrentConversation = () => { | ||||
| const [currentConversation, setCurrentConversation] = | const [currentConversation, setCurrentConversation] = | ||||
| useState<IClientConversation>({} as IClientConversation); | useState<IClientConversation>({} as IClientConversation); | ||||
| const conversation: IClientConversation = useSelector( | |||||
| (state: any) => state.chatModel.currentConversation, | |||||
| ); | |||||
| const dialog = useSelectCurrentDialog(); | |||||
| const { data: conversation, loading } = useFetchNextConversation(); | |||||
| const { data: dialog } = useFetchNextDialog(); | |||||
| const { conversationId, dialogId } = useGetChatSearchParams(); | const { conversationId, dialogId } = useGetChatSearchParams(); | ||||
| const addNewestConversation = useCallback( | const addNewestConversation = useCallback( | ||||
| addNewestConversation, | addNewestConversation, | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| addNewestAnswer, | addNewestAnswer, | ||||
| loading, | |||||
| }; | }; | ||||
| }; | }; | ||||
| export const useFetchConversationOnMount = () => { | export const useFetchConversationOnMount = () => { | ||||
| const { conversationId } = useGetChatSearchParams(); | const { conversationId } = useGetChatSearchParams(); | ||||
| const fetchConversation = useFetchConversation(); | |||||
| const { | const { | ||||
| currentConversation, | currentConversation, | ||||
| addNewestConversation, | addNewestConversation, | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| addNewestAnswer, | addNewestAnswer, | ||||
| loading, | |||||
| } = useSelectCurrentConversation(); | } = useSelectCurrentConversation(); | ||||
| const ref = useScrollToBottom(currentConversation); | const ref = useScrollToBottom(currentConversation); | ||||
| const fetchConversationOnMount = useCallback(() => { | |||||
| if (isConversationIdExist(conversationId)) { | |||||
| fetchConversation(conversationId); | |||||
| } | |||||
| }, [fetchConversation, conversationId]); | |||||
| useEffect(() => { | |||||
| fetchConversationOnMount(); | |||||
| }, [fetchConversationOnMount]); | |||||
| return { | return { | ||||
| currentConversation, | currentConversation, | ||||
| addNewestConversation, | addNewestConversation, | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| addNewestAnswer, | addNewestAnswer, | ||||
| conversationId, | conversationId, | ||||
| loading, | |||||
| }; | }; | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useDeleteConversation = () => { | export const useDeleteConversation = () => { | ||||
| const { dialogId } = useGetChatSearchParams(); | |||||
| const { handleClickConversation } = useClickConversationCard(); | const { handleClickConversation } = useClickConversationCard(); | ||||
| const showDeleteConfirm = useShowDeleteConfirm(); | const showDeleteConfirm = useShowDeleteConfirm(); | ||||
| const removeConversation = useRemoveConversation(); | |||||
| const { removeConversation } = useRemoveNextConversation(); | |||||
| const deleteConversation = (conversationIds: Array<string>) => async () => { | const deleteConversation = (conversationIds: Array<string>) => async () => { | ||||
| const ret = await removeConversation(conversationIds, dialogId); | |||||
| const ret = await removeConversation(conversationIds); | |||||
| if (ret === 0) { | if (ret === 0) { | ||||
| handleClickConversation(''); | handleClickConversation(''); | ||||
| } | } | ||||
| const [conversation, setConversation] = useState<IClientConversation>( | const [conversation, setConversation] = useState<IClientConversation>( | ||||
| {} as IClientConversation, | {} as IClientConversation, | ||||
| ); | ); | ||||
| const fetchConversation = useFetchConversation(); | |||||
| const { fetchConversation } = useFetchManualConversation(); | |||||
| const { | const { | ||||
| visible: conversationRenameVisible, | visible: conversationRenameVisible, | ||||
| hideModal: hideConversationRenameModal, | hideModal: hideConversationRenameModal, | ||||
| showModal: showConversationRenameModal, | showModal: showConversationRenameModal, | ||||
| } = useSetModalState(); | } = useSetModalState(); | ||||
| const updateConversation = useUpdateConversation(); | |||||
| const { updateConversation, loading } = useUpdateNextConversation(); | |||||
| const onConversationRenameOk = useCallback( | const onConversationRenameOk = useCallback( | ||||
| async (name: string) => { | async (name: string) => { | ||||
| [updateConversation, conversation, hideConversationRenameModal], | [updateConversation, conversation, hideConversationRenameModal], | ||||
| ); | ); | ||||
| const loading = useOneNamespaceEffectsLoading('chatModel', [ | |||||
| 'setConversation', | |||||
| ]); | |||||
| const handleShowConversationRenameModal = useCallback( | const handleShowConversationRenameModal = useCallback( | ||||
| async (conversationId: string) => { | async (conversationId: string) => { | ||||
| const ret = await fetchConversation(conversationId, false); | |||||
| const ret = await fetchConversation(conversationId); | |||||
| if (ret.retcode === 0) { | if (ret.retcode === 0) { | ||||
| setConversation(ret.data); | setConversation(ret.data); | ||||
| } | } | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useSelectDialogListLoading = () => { | |||||
| return useOneNamespaceEffectsLoading('chatModel', ['listDialog']); | |||||
| }; | |||||
| export const useSelectConversationListLoading = () => { | |||||
| return useOneNamespaceEffectsLoading('chatModel', ['listConversation']); | |||||
| }; | |||||
| export const useSelectConversationLoading = () => { | |||||
| return useOneNamespaceEffectsLoading('chatModel', ['getConversation']); | |||||
| }; | |||||
| export const useGetSendButtonDisabled = () => { | export const useGetSendButtonDisabled = () => { | ||||
| const { dialogId, conversationId } = useGetChatSearchParams(); | const { dialogId, conversationId } = useGetChatSearchParams(); | ||||
| import ChatContainer from './chat-container'; | import ChatContainer from './chat-container'; | ||||
| import { | import { | ||||
| useClickConversationCard, | useClickConversationCard, | ||||
| useClickDialogCard, | |||||
| useDeleteConversation, | useDeleteConversation, | ||||
| useDeleteDialog, | useDeleteDialog, | ||||
| useEditDialog, | useEditDialog, | ||||
| useFetchConversationListOnMount, | |||||
| useFetchDialogOnMount, | |||||
| useGetChatSearchParams, | |||||
| useHandleItemHover, | useHandleItemHover, | ||||
| useRenameConversation, | useRenameConversation, | ||||
| useSelectConversationListLoading, | |||||
| useSelectDerivedConversationList, | useSelectDerivedConversationList, | ||||
| useSelectDialogListLoading, | |||||
| useSelectFirstDialogOnMount, | |||||
| } from './hooks'; | } from './hooks'; | ||||
| import ChatOverviewModal from '@/components/api-service/chat-overview-modal'; | import ChatOverviewModal from '@/components/api-service/chat-overview-modal'; | ||||
| import { | |||||
| useClickDialogCard, | |||||
| useFetchNextDialogList, | |||||
| useGetChatSearchParams, | |||||
| } from '@/hooks/chat-hooks'; | |||||
| import { useSetModalState, useTranslate } from '@/hooks/common-hooks'; | import { useSetModalState, useTranslate } from '@/hooks/common-hooks'; | ||||
| import { useSetSelectedRecord } from '@/hooks/logic-hooks'; | import { useSetSelectedRecord } from '@/hooks/logic-hooks'; | ||||
| import { IDialog } from '@/interfaces/database/chat'; | import { IDialog } from '@/interfaces/database/chat'; | ||||
| const { Text } = Typography; | const { Text } = Typography; | ||||
| const Chat = () => { | const Chat = () => { | ||||
| const dialogList = useSelectFirstDialogOnMount(); | |||||
| const { data: dialogList, loading: dialogLoading } = useFetchNextDialogList(); | |||||
| const { onRemoveDialog } = useDeleteDialog(); | const { onRemoveDialog } = useDeleteDialog(); | ||||
| const { onRemoveConversation } = useDeleteConversation(); | const { onRemoveConversation } = useDeleteConversation(); | ||||
| const { handleClickDialog } = useClickDialogCard(); | const { handleClickDialog } = useClickDialogCard(); | ||||
| const { handleClickConversation } = useClickConversationCard(); | const { handleClickConversation } = useClickConversationCard(); | ||||
| const { dialogId, conversationId } = useGetChatSearchParams(); | const { dialogId, conversationId } = useGetChatSearchParams(); | ||||
| const { list: conversationList, addTemporaryConversation } = | |||||
| useSelectDerivedConversationList(); | |||||
| const { | |||||
| list: conversationList, | |||||
| addTemporaryConversation, | |||||
| loading: conversationLoading, | |||||
| } = useSelectDerivedConversationList(); | |||||
| const { activated, handleItemEnter, handleItemLeave } = useHandleItemHover(); | const { activated, handleItemEnter, handleItemLeave } = useHandleItemHover(); | ||||
| const { | const { | ||||
| activated: conversationActivated, | activated: conversationActivated, | ||||
| hideDialogEditModal, | hideDialogEditModal, | ||||
| showDialogEditModal, | showDialogEditModal, | ||||
| } = useEditDialog(); | } = useEditDialog(); | ||||
| const dialogLoading = useSelectDialogListLoading(); | |||||
| const conversationLoading = useSelectConversationListLoading(); | |||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); | ||||
| const { | const { | ||||
| visible: overviewVisible, | visible: overviewVisible, | ||||
| } = useSetModalState(); | } = useSetModalState(); | ||||
| const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>(); | const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>(); | ||||
| useFetchDialogOnMount(dialogId, true); | |||||
| const handleAppCardEnter = (id: string) => () => { | const handleAppCardEnter = (id: string) => () => { | ||||
| handleItemEnter(id); | handleItemEnter(id); | ||||
| }; | }; | ||||
| return appItems; | return appItems; | ||||
| }; | }; | ||||
| useFetchConversationListOnMount(); | |||||
| return ( | return ( | ||||
| <Flex className={styles.chatWrapper}> | <Flex className={styles.chatWrapper}> | ||||
| <Flex className={styles.chatAppWrapper}> | <Flex className={styles.chatAppWrapper}> |
| import { MessageType, SharedFrom } from '@/constants/chat'; | import { MessageType, SharedFrom } from '@/constants/chat'; | ||||
| import { | import { | ||||
| useCreateSharedConversation, | |||||
| useFetchSharedConversation, | |||||
| useCreateNextSharedConversation, | |||||
| useFetchNextSharedConversation, | |||||
| } from '@/hooks/chat-hooks'; | } from '@/hooks/chat-hooks'; | ||||
| import { useSendMessageWithSse } from '@/hooks/logic-hooks'; | import { useSendMessageWithSse } from '@/hooks/logic-hooks'; | ||||
| import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; | |||||
| import { IAnswer, Message } from '@/interfaces/database/chat'; | import { IAnswer, Message } from '@/interfaces/database/chat'; | ||||
| import api from '@/utils/api'; | import api from '@/utils/api'; | ||||
| import omit from 'lodash/omit'; | import omit from 'lodash/omit'; | ||||
| const [currentQueryParameters] = useSearchParams(); | const [currentQueryParameters] = useSearchParams(); | ||||
| const [conversationId, setConversationId] = useState(''); | const [conversationId, setConversationId] = useState(''); | ||||
| const createConversation = useCreateSharedConversation(); | |||||
| const { createSharedConversation: createConversation } = | |||||
| useCreateNextSharedConversation(); | |||||
| const sharedId = currentQueryParameters.get('shared_id'); | const sharedId = currentQueryParameters.get('shared_id'); | ||||
| const userId = currentQueryParameters.get('user_id'); | const userId = currentQueryParameters.get('user_id'); | ||||
| const setConversation = useCallback(async () => { | const setConversation = useCallback(async () => { | ||||
| console.info(sharedId); | |||||
| if (sharedId) { | if (sharedId) { | ||||
| const data = await createConversation(userId ?? undefined); | const data = await createConversation(userId ?? undefined); | ||||
| const id = data.data?.id; | const id = data.data?.id; | ||||
| export const useSelectCurrentSharedConversation = (conversationId: string) => { | export const useSelectCurrentSharedConversation = (conversationId: string) => { | ||||
| const [currentConversation, setCurrentConversation] = | const [currentConversation, setCurrentConversation] = | ||||
| useState<IClientConversation>({} as IClientConversation); | useState<IClientConversation>({} as IClientConversation); | ||||
| const fetchConversation = useFetchSharedConversation(); | |||||
| const loading = useOneNamespaceEffectsLoading('chatModel', [ | |||||
| 'getExternalConversation', | |||||
| ]); | |||||
| const { fetchConversation, loading } = useFetchNextSharedConversation(); | |||||
| const ref = useScrollToBottom(currentConversation); | const ref = useScrollToBottom(currentConversation); | ||||
| addNewestAnswer: (answer: IAnswer) => void, | addNewestAnswer: (answer: IAnswer) => void, | ||||
| ) => { | ) => { | ||||
| const conversationId = conversation.id; | const conversationId = conversation.id; | ||||
| const setConversation = useCreateSharedConversation(); | |||||
| const { createSharedConversation: setConversation } = | |||||
| useCreateNextSharedConversation(); | |||||
| const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | ||||
| const { send, answer, done } = useSendMessageWithSse( | const { send, answer, done } = useSendMessageWithSse( |
| import { Authorization } from '@/constants/authorization'; | import { Authorization } from '@/constants/authorization'; | ||||
| import { getAuthorization } from '@/utils/authorization-util'; | import { getAuthorization } from '@/utils/authorization-util'; | ||||
| import { PlusOutlined } from '@ant-design/icons'; | import { PlusOutlined } from '@ant-design/icons'; | ||||
| import type { GetProp, UploadFile, UploadProps } from 'antd'; | |||||
| import type { UploadFile, UploadProps } from 'antd'; | |||||
| import { Image, Input, Upload } from 'antd'; | import { Image, Input, Upload } from 'antd'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import { useGetChatSearchParams } from '../chat/hooks'; | |||||
| type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0]; | |||||
| const getBase64 = (file: FileType): Promise<string> => | |||||
| new Promise((resolve, reject) => { | |||||
| const reader = new FileReader(); | |||||
| reader.readAsDataURL(file); | |||||
| reader.onload = () => resolve(reader.result as string); | |||||
| reader.onerror = (error) => reject(error); | |||||
| }); | |||||
| const InputWithUpload = () => { | const InputWithUpload = () => { | ||||
| const [previewOpen, setPreviewOpen] = useState(false); | const [previewOpen, setPreviewOpen] = useState(false); | ||||
| const [previewImage, setPreviewImage] = useState(''); | const [previewImage, setPreviewImage] = useState(''); | ||||
| const { conversationId } = useGetChatSearchParams(); | |||||
| const [fileList, setFileList] = useState<UploadFile[]>([ | |||||
| { | |||||
| uid: '-1', | |||||
| name: 'image.png', | |||||
| status: 'done', | |||||
| url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', | |||||
| }, | |||||
| { | |||||
| uid: '-2', | |||||
| name: 'image.png', | |||||
| status: 'done', | |||||
| url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', | |||||
| }, | |||||
| { | |||||
| uid: '-3', | |||||
| name: 'image.png', | |||||
| status: 'done', | |||||
| url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', | |||||
| }, | |||||
| { | |||||
| uid: '-4', | |||||
| name: 'image.png', | |||||
| status: 'done', | |||||
| url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', | |||||
| }, | |||||
| { | |||||
| uid: '-xxx', | |||||
| percent: 50, | |||||
| name: 'image.png', | |||||
| status: 'uploading', | |||||
| url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', | |||||
| }, | |||||
| { | |||||
| uid: '-5', | |||||
| name: 'image.png', | |||||
| status: 'error', | |||||
| }, | |||||
| ]); | |||||
| const handlePreview = async (file: UploadFile) => { | |||||
| if (!file.url && !file.preview) { | |||||
| file.preview = await getBase64(file.originFileObj as FileType); | |||||
| } | |||||
| setPreviewImage(file.url || (file.preview as string)); | |||||
| setPreviewOpen(true); | |||||
| }; | |||||
| const [fileList, setFileList] = useState<UploadFile[]>([]); | |||||
| const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => | const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => | ||||
| setFileList(newFileList); | setFileList(newFileList); | ||||
| action="/v1/document/upload_and_parse" | action="/v1/document/upload_and_parse" | ||||
| listType="picture-card" | listType="picture-card" | ||||
| fileList={fileList} | fileList={fileList} | ||||
| onPreview={handlePreview} | |||||
| onChange={handleChange} | onChange={handleChange} | ||||
| multiple | multiple | ||||
| headers={{ [Authorization]: getAuthorization() }} | headers={{ [Authorization]: getAuthorization() }} |
| key={key} | key={key} | ||||
| > | > | ||||
| {key === 'task_executor' ? ( | {key === 'task_executor' ? ( | ||||
| <TaskBarChat | |||||
| data={info.elapsed as TaskExecutorElapsed} | |||||
| ></TaskBarChat> | |||||
| info?.elapsed ? ( | |||||
| <TaskBarChat | |||||
| data={info.elapsed as TaskExecutorElapsed} | |||||
| ></TaskBarChat> | |||||
| ) : ( | |||||
| <Text className={styles.error}>{info.error}</Text> | |||||
| ) | |||||
| ) : ( | ) : ( | ||||
| Object.keys(info) | Object.keys(info) | ||||
| .filter((x) => x !== 'status') | .filter((x) => x !== 'status') |
| import { EmptyConversationId } from '@/constants/chat'; | |||||
| export const isConversationIdExist = (conversationId: string) => { | |||||
| return conversationId !== EmptyConversationId && conversationId !== ''; | |||||
| }; |