Feat: Create a conversation before uploading files #3221 (#9832)

### What problem does this PR solve?

Feat: Create a conversation before uploading files #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-08-29 18:36:40 +08:00
committed by GitHub
parent 56cd576876
commit bed77ee28f
6 changed files with 118 additions and 82 deletions

View File

@ -398,10 +398,14 @@ export const useDeleteMessage = () => {
type UploadParameters = Parameters<NonNullable<FileUploadProps['onUpload']>>;
type X = { file: UploadParameters[0][0]; options: UploadParameters[1] };
type X = {
file: UploadParameters[0][0];
options: UploadParameters[1];
conversationId?: string;
};
export function useUploadAndParseFile() {
const { conversationId } = useGetChatSearchParams();
const { conversationId: id } = useGetChatSearchParams();
const { t } = useTranslation();
const controller = useRef(new AbortController());
@ -414,11 +418,12 @@ export function useUploadAndParseFile() {
mutationFn: async ({
file,
options: { onProgress, onSuccess, onError },
conversationId,
}: X) => {
try {
const formData = new FormData();
formData.append('file', file);
formData.append('conversation_id', conversationId);
formData.append('conversation_id', conversationId || id);
const { data } = await chatService.uploadAndParse(
{

View File

@ -1,13 +1,11 @@
import { useGetChatSearchParams } from '@/hooks/use-chat-request';
import { useCallback } from 'react';
import {
useSetChatRouteParams,
useSetConversation,
} from './use-send-chat-message';
import { useParams } from 'umi';
import { useSetChatRouteParams } from './use-set-chat-route';
import { useSetConversation } from './use-set-conversation';
export const useCreateConversationBeforeUploadDocument = () => {
const { setConversation } = useSetConversation();
const { dialogId } = useGetChatSearchParams();
const { id: dialogId } = useParams();
const { getConversationIsNew } = useSetChatRouteParams();
const createConversationBeforeUploadDocument = useCallback(

View File

@ -1,4 +1,5 @@
import { ChatSearchParams, MessageType } from '@/constants/chat';
import { FileUploadProps } from '@/components/file-upload';
import { MessageType } from '@/constants/chat';
import {
useHandleMessageInputChange,
useRegenerateMessage,
@ -8,40 +9,19 @@ import {
import {
useFetchConversation,
useGetChatSearchParams,
useUpdateConversation,
} from '@/hooks/use-chat-request';
import { Message } from '@/interfaces/database/chat';
import api from '@/utils/api';
import { trim } from 'lodash';
import { useCallback, useEffect, useMemo } from 'react';
import { useParams, useSearchParams } from 'umi';
import { useCallback, useEffect } from 'react';
import { useParams } from 'umi';
import { v4 as uuid } from 'uuid';
import { IMessage } from '../chat/interface';
import { useFindPrologueFromDialogList } from './use-select-conversation-list';
import { useSetChatRouteParams } from './use-set-chat-route';
import { useSetConversation } from './use-set-conversation';
import { useUploadFile } from './use-upload-file';
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 useSelectNextMessages = () => {
const {
scrollRef,
@ -102,37 +82,6 @@ export const useSelectNextMessages = () => {
};
};
export const useSetConversation = () => {
const { id: dialogId } = useParams();
const { updateConversation } = useUpdateConversation();
const setConversation = useCallback(
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,
content: message,
},
],
});
return data;
},
[updateConversation, dialogId],
);
return { setConversation };
};
export const useSendMessage = (controller: AbortController) => {
const { setConversation } = useSetConversation();
const { conversationId, isNew } = useGetChatSearchParams();
@ -158,6 +107,22 @@ export const useSendMessage = (controller: AbortController) => {
const { setConversationIsNew, getConversationIsNew } =
useSetChatRouteParams();
const onUploadFile: NonNullable<FileUploadProps['onUpload']> = useCallback(
async (files, options) => {
const isNew = getConversationIsNew();
if (isNew === 'true' && Array.isArray(files) && files.length) {
const data = await setConversation(files[0].name, true);
if (data.code === 0) {
handleUploadFile(files, options, data.data?.id);
}
} else {
handleUploadFile(files, options);
}
},
[getConversationIsNew, handleUploadFile, setConversation],
);
const stopOutputMessage = useCallback(() => {
controller.abort();
}, [controller]);
@ -285,7 +250,7 @@ export const useSendMessage = (controller: AbortController) => {
derivedMessages,
removeMessageById,
stopOutputMessage,
handleUploadFile,
handleUploadFile: onUploadFile,
isUploading,
removeFile,
};

View File

@ -0,0 +1,25 @@
import { ChatSearchParams } from '@/constants/chat';
import { useCallback, useMemo } from 'react';
import { useSearchParams } from 'umi';
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 };
};

View File

@ -0,0 +1,35 @@
import { MessageType } from '@/constants/chat';
import { useUpdateConversation } from '@/hooks/use-chat-request';
import { useCallback } from 'react';
import { useParams } from 'umi';
export const useSetConversation = () => {
const { id: dialogId } = useParams();
const { updateConversation } = useUpdateConversation();
const setConversation = useCallback(
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,
content: message,
},
],
});
return data;
},
[updateConversation, dialogId],
);
return { setConversation };
};

View File

@ -7,22 +7,30 @@ export function useUploadFile() {
const [fileIds, setFileIds] = useState<string[]>([]);
const [fileMap, setFileMap] = useState<Map<File, string>>(new Map());
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback(
async (files, options) => {
if (Array.isArray(files) && files.length) {
const ret = await uploadAndParseFile({ file: files[0], options });
if (ret.code === 0 && Array.isArray(ret.data)) {
setFileIds((list) => [...list, ...ret.data]);
setFileMap((map) => {
map.set(files[0], ret.data[0]);
return map;
});
}
type FileUploadParameters = Parameters<
NonNullable<FileUploadProps['onUpload']>
>;
const handleUploadFile = useCallback(
async (
files: FileUploadParameters[0],
options: FileUploadParameters[1],
conversationId?: string,
) => {
if (Array.isArray(files) && files.length) {
const file = files[0];
const ret = await uploadAndParseFile({ file, options, conversationId });
if (ret.code === 0 && Array.isArray(ret.data)) {
setFileIds((list) => [...list, ...ret.data]);
setFileMap((map) => {
map.set(files[0], ret.data[0]);
return map;
});
}
},
[uploadAndParseFile],
);
}
},
[uploadAndParseFile],
);
const clearFileIds = useCallback(() => {
setFileIds([]);