mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-05-31 18:45:54 +08:00
### What problem does this PR solve? feat: Delete the file from the upload control of the message input box #1880 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
6b3a40be5c
commit
c6c3961250
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 8.3 KiB |
@ -15,7 +15,7 @@ const IndentedTreeModal = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={t('chunk.graph')}
|
title={t('chunk.mind')}
|
||||||
open={visible}
|
open={visible}
|
||||||
onCancel={hideModal}
|
onCancel={hideModal}
|
||||||
width={'90vw'}
|
width={'90vw'}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Authorization } from '@/constants/authorization';
|
import { Authorization } from '@/constants/authorization';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
|
import { useRemoveNextDocument } from '@/hooks/document-hooks';
|
||||||
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 } from 'antd';
|
import type { GetProp, UploadFile } from 'antd';
|
||||||
@ -14,7 +15,7 @@ interface IProps {
|
|||||||
value: string;
|
value: string;
|
||||||
sendDisabled: boolean;
|
sendDisabled: boolean;
|
||||||
sendLoading: boolean;
|
sendLoading: boolean;
|
||||||
onPressEnter(documentIds: string[]): Promise<any>;
|
onPressEnter(documentIds: string[]): void;
|
||||||
onInputChange: ChangeEventHandler<HTMLInputElement>;
|
onInputChange: ChangeEventHandler<HTMLInputElement>;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
}
|
}
|
||||||
@ -37,50 +38,41 @@ const MessageInput = ({
|
|||||||
conversationId,
|
conversationId,
|
||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
const { t } = useTranslate('chat');
|
const { t } = useTranslate('chat');
|
||||||
|
const { removeDocument } = useRemoveNextDocument();
|
||||||
|
|
||||||
const [fileList, setFileList] = useState<UploadFile[]>([
|
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
||||||
// {
|
|
||||||
// uid: '-1',
|
|
||||||
// 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) => {
|
const handlePreview = async (file: UploadFile) => {
|
||||||
if (!file.url && !file.preview) {
|
if (!file.url && !file.preview) {
|
||||||
file.preview = await getBase64(file.originFileObj as FileType);
|
file.preview = await getBase64(file.originFileObj as FileType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setPreviewImage(file.url || (file.preview as string));
|
|
||||||
// setPreviewOpen(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
||||||
console.log('🚀 ~ newFileList:', newFileList);
|
console.log('🚀 ~ newFileList:', newFileList);
|
||||||
setFileList(newFileList);
|
setFileList(newFileList);
|
||||||
};
|
};
|
||||||
|
const isUploadingFile = fileList.some((x) => x.status === 'uploading');
|
||||||
|
|
||||||
const handlePressEnter = useCallback(async () => {
|
const handlePressEnter = useCallback(async () => {
|
||||||
|
if (isUploadingFile) return;
|
||||||
const ids = fileList.reduce((pre, cur) => {
|
const ids = fileList.reduce((pre, cur) => {
|
||||||
return pre.concat(get(cur, 'response.data', []));
|
return pre.concat(get(cur, 'response.data', []));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
await onPressEnter(ids);
|
onPressEnter(ids);
|
||||||
setFileList([]);
|
setFileList([]);
|
||||||
}, [fileList, onPressEnter]);
|
}, [fileList, onPressEnter, isUploadingFile]);
|
||||||
|
|
||||||
|
const handleRemove = useCallback(
|
||||||
|
(file: UploadFile) => {
|
||||||
|
const ids = get(file, 'response.data', []);
|
||||||
|
if (ids.length) {
|
||||||
|
removeDocument(ids[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[removeDocument],
|
||||||
|
);
|
||||||
|
|
||||||
const uploadButton = (
|
const uploadButton = (
|
||||||
<button style={{ border: 0, background: 'none' }} type="button">
|
<button style={{ border: 0, background: 'none' }} type="button">
|
||||||
@ -101,7 +93,7 @@ const MessageInput = ({
|
|||||||
type="primary"
|
type="primary"
|
||||||
onClick={handlePressEnter}
|
onClick={handlePressEnter}
|
||||||
loading={sendLoading}
|
loading={sendLoading}
|
||||||
disabled={sendDisabled}
|
disabled={sendDisabled || isUploadingFile}
|
||||||
>
|
>
|
||||||
{t('send')}
|
{t('send')}
|
||||||
</Button>
|
</Button>
|
||||||
@ -119,6 +111,7 @@ const MessageInput = ({
|
|||||||
headers={{ [Authorization]: getAuthorization() }}
|
headers={{ [Authorization]: getAuthorization() }}
|
||||||
data={{ conversation_id: conversationId }}
|
data={{ conversation_id: conversationId }}
|
||||||
method="post"
|
method="post"
|
||||||
|
onRemove={handleRemove}
|
||||||
>
|
>
|
||||||
{fileList.length >= 8 ? null : uploadButton}
|
{fileList.length >= 8 ? null : uploadButton}
|
||||||
</Upload>
|
</Upload>
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
.messageItemSectionRight {
|
.messageItemSectionRight {
|
||||||
width: 80%;
|
// width: 80%;
|
||||||
|
// max-width: 50vw;
|
||||||
}
|
}
|
||||||
.messageItemContent {
|
.messageItemContent {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -7,15 +7,20 @@ import { IChunk } from '@/interfaces/database/knowledge';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { useFetchDocumentInfosByIds } from '@/hooks/document-hooks';
|
import {
|
||||||
|
useFetchDocumentInfosByIds,
|
||||||
|
useFetchDocumentThumbnailsByIds,
|
||||||
|
} from '@/hooks/document-hooks';
|
||||||
import MarkdownContent from '@/pages/chat/markdown-content';
|
import MarkdownContent from '@/pages/chat/markdown-content';
|
||||||
import { getExtension, isImage } from '@/utils/document-util';
|
import { getExtension, isImage } from '@/utils/document-util';
|
||||||
import { Avatar, Button, Flex, List } from 'antd';
|
import { Avatar, Button, Flex, List, Typography } from 'antd';
|
||||||
import IndentedTreeModal from '../indented-tree/modal';
|
import IndentedTreeModal from '../indented-tree/modal';
|
||||||
import NewDocumentLink from '../new-document-link';
|
import NewDocumentLink from '../new-document-link';
|
||||||
import SvgIcon from '../svg-icon';
|
import SvgIcon from '../svg-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
item: Message;
|
item: Message;
|
||||||
reference: IReference;
|
reference: IReference;
|
||||||
@ -38,7 +43,8 @@ const MessageItem = ({
|
|||||||
const { t } = useTranslate('chat');
|
const { t } = useTranslate('chat');
|
||||||
const fileThumbnails = useSelectFileThumbnails();
|
const fileThumbnails = useSelectFileThumbnails();
|
||||||
const { data: documentList, setDocumentIds } = useFetchDocumentInfosByIds();
|
const { data: documentList, setDocumentIds } = useFetchDocumentInfosByIds();
|
||||||
console.log('🚀 ~ documentList:', documentList);
|
const { data: documentThumbnails, setDocumentIds: setIds } =
|
||||||
|
useFetchDocumentThumbnailsByIds();
|
||||||
const { visible, hideModal, showModal } = useSetModalState();
|
const { visible, hideModal, showModal } = useSetModalState();
|
||||||
const [clickedDocumentId, setClickedDocumentId] = useState('');
|
const [clickedDocumentId, setClickedDocumentId] = useState('');
|
||||||
|
|
||||||
@ -66,8 +72,12 @@ const MessageItem = ({
|
|||||||
const ids = item?.doc_ids ?? [];
|
const ids = item?.doc_ids ?? [];
|
||||||
if (ids.length) {
|
if (ids.length) {
|
||||||
setDocumentIds(ids);
|
setDocumentIds(ids);
|
||||||
|
const documentIds = ids.filter((x) => !(x in fileThumbnails));
|
||||||
|
if (documentIds.length) {
|
||||||
|
setIds(documentIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [item.doc_ids, setDocumentIds]);
|
}, [item.doc_ids, setDocumentIds, setIds, fileThumbnails]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -117,6 +127,7 @@ const MessageItem = ({
|
|||||||
dataSource={referenceDocumentList}
|
dataSource={referenceDocumentList}
|
||||||
renderItem={(item) => {
|
renderItem={(item) => {
|
||||||
const fileThumbnail = fileThumbnails[item.doc_id];
|
const fileThumbnail = fileThumbnails[item.doc_id];
|
||||||
|
|
||||||
const fileExtension = getExtension(item.doc_name);
|
const fileExtension = getExtension(item.doc_name);
|
||||||
return (
|
return (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
@ -151,7 +162,8 @@ const MessageItem = ({
|
|||||||
bordered
|
bordered
|
||||||
dataSource={documentList}
|
dataSource={documentList}
|
||||||
renderItem={(item) => {
|
renderItem={(item) => {
|
||||||
const fileThumbnail = fileThumbnails[item.id];
|
const fileThumbnail =
|
||||||
|
documentThumbnails[item.id] || fileThumbnails[item.id];
|
||||||
const fileExtension = getExtension(item.name);
|
const fileExtension = getExtension(item.name);
|
||||||
return (
|
return (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
@ -181,7 +193,12 @@ const MessageItem = ({
|
|||||||
type={'text'}
|
type={'text'}
|
||||||
onClick={handleUserDocumentClick(item.id)}
|
onClick={handleUserDocumentClick(item.id)}
|
||||||
>
|
>
|
||||||
{item.name}
|
<Text
|
||||||
|
style={{ maxWidth: '40vw' }}
|
||||||
|
ellipsis={{ tooltip: item.name }}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@ -4,7 +4,7 @@ import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
|
|||||||
import kbService from '@/services/knowledge-service';
|
import kbService from '@/services/knowledge-service';
|
||||||
import { api_host } from '@/utils/api';
|
import { api_host } from '@/utils/api';
|
||||||
import { buildChunkHighlights } from '@/utils/document-util';
|
import { buildChunkHighlights } from '@/utils/document-util';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { UploadFile } from 'antd';
|
import { UploadFile } from 'antd';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { IHighlight } from 'react-pdf-highlighter';
|
import { IHighlight } from 'react-pdf-highlighter';
|
||||||
@ -278,15 +278,38 @@ export const useFetchDocumentInfosByIds = () => {
|
|||||||
|
|
||||||
export const useFetchDocumentThumbnailsByIds = () => {
|
export const useFetchDocumentThumbnailsByIds = () => {
|
||||||
const [ids, setDocumentIds] = useState<string[]>([]);
|
const [ids, setDocumentIds] = useState<string[]>([]);
|
||||||
const { data } = useQuery({
|
const { data } = useQuery<Record<string, string>>({
|
||||||
queryKey: ['fetchDocumentThumbnails', ids],
|
queryKey: ['fetchDocumentThumbnails', ids],
|
||||||
initialData: [],
|
enabled: ids.length > 0,
|
||||||
|
initialData: {},
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await kbService.document_thumbnails({ doc_ids: ids });
|
const { data } = await kbService.document_thumbnails({ doc_ids: ids });
|
||||||
|
if (data.retcode === 0) {
|
||||||
return data;
|
return data.data;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return { data, setDocumentIds };
|
return { data, setDocumentIds };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useRemoveNextDocument = () => {
|
||||||
|
// const queryClient = useQueryClient();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: ['removeDocument'],
|
||||||
|
mutationFn: async (documentId: string) => {
|
||||||
|
const data = await kbService.document_rm({ doc_id: documentId });
|
||||||
|
// if (data.retcode === 0) {
|
||||||
|
// queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
|
||||||
|
// }
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, removeDocument: mutateAsync };
|
||||||
|
};
|
||||||
|
@ -80,24 +80,6 @@ const ChatContainer = () => {
|
|||||||
onPressEnter={handlePressEnter}
|
onPressEnter={handlePressEnter}
|
||||||
conversationId={conversation.id}
|
conversationId={conversation.id}
|
||||||
></MessageInput>
|
></MessageInput>
|
||||||
{/* <Input
|
|
||||||
size="large"
|
|
||||||
placeholder={t('sendPlaceholder')}
|
|
||||||
value={value}
|
|
||||||
disabled={disabled}
|
|
||||||
suffix={
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={handlePressEnter}
|
|
||||||
loading={sendLoading}
|
|
||||||
disabled={sendDisabled}
|
|
||||||
>
|
|
||||||
{t('send')}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
onPressEnter={handlePressEnter}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
/> */}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="Document Previewer"
|
title="Document Previewer"
|
||||||
|
@ -19,7 +19,12 @@ import {
|
|||||||
} 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 { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks';
|
||||||
import { IAnswer, IConversation, IDialog } from '@/interfaces/database/chat';
|
import {
|
||||||
|
IAnswer,
|
||||||
|
IConversation,
|
||||||
|
IDialog,
|
||||||
|
Message,
|
||||||
|
} 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 omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
@ -379,7 +384,7 @@ export const useSelectCurrentConversation = () => {
|
|||||||
const { conversationId, dialogId } = useGetChatSearchParams();
|
const { conversationId, dialogId } = useGetChatSearchParams();
|
||||||
|
|
||||||
const addNewestConversation = useCallback(
|
const addNewestConversation = useCallback(
|
||||||
(message: string, answer: string = '') => {
|
(message: Partial<Message>, answer: string = '') => {
|
||||||
setCurrentConversation((pre) => {
|
setCurrentConversation((pre) => {
|
||||||
return {
|
return {
|
||||||
...pre,
|
...pre,
|
||||||
@ -387,7 +392,8 @@ export const useSelectCurrentConversation = () => {
|
|||||||
...pre.message,
|
...pre.message,
|
||||||
{
|
{
|
||||||
role: MessageType.User,
|
role: MessageType.User,
|
||||||
content: message,
|
content: message.content,
|
||||||
|
doc_ids: message.doc_ids,
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
} as IMessage,
|
} as IMessage,
|
||||||
{
|
{
|
||||||
@ -535,7 +541,7 @@ export const useHandleMessageInputChange = () => {
|
|||||||
|
|
||||||
export const useSendMessage = (
|
export const useSendMessage = (
|
||||||
conversation: IClientConversation,
|
conversation: IClientConversation,
|
||||||
addNewestConversation: (message: string, answer?: string) => void,
|
addNewestConversation: (message: Partial<Message>, answer?: string) => void,
|
||||||
removeLatestMessage: () => void,
|
removeLatestMessage: () => void,
|
||||||
addNewestAnswer: (answer: IAnswer) => void,
|
addNewestAnswer: (answer: IAnswer) => void,
|
||||||
) => {
|
) => {
|
||||||
@ -589,12 +595,12 @@ export const useSendMessage = (
|
|||||||
const handleSendMessage = useCallback(
|
const handleSendMessage = useCallback(
|
||||||
async (message: string, documentIds: string[]) => {
|
async (message: string, documentIds: string[]) => {
|
||||||
if (conversationId !== '') {
|
if (conversationId !== '') {
|
||||||
return sendMessage(message, documentIds);
|
sendMessage(message, documentIds);
|
||||||
} else {
|
} else {
|
||||||
const data = await setConversation(message);
|
const data = await setConversation(message);
|
||||||
if (data.retcode === 0) {
|
if (data.retcode === 0) {
|
||||||
const id = data.data.id;
|
const id = data.data.id;
|
||||||
return sendMessage(message, documentIds, id);
|
sendMessage(message, documentIds, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -616,15 +622,14 @@ export const useSendMessage = (
|
|||||||
}, [setDone, conversationId]);
|
}, [setDone, conversationId]);
|
||||||
|
|
||||||
const handlePressEnter = useCallback(
|
const handlePressEnter = useCallback(
|
||||||
async (documentIds: string[]) => {
|
(documentIds: string[]) => {
|
||||||
if (trim(value) === '') return;
|
if (trim(value) === '') return;
|
||||||
let ret;
|
|
||||||
|
addNewestConversation({ content: value, doc_ids: documentIds });
|
||||||
if (done) {
|
if (done) {
|
||||||
setValue('');
|
setValue('');
|
||||||
ret = await handleSendMessage(value.trim(), documentIds);
|
handleSendMessage(value.trim(), documentIds);
|
||||||
}
|
}
|
||||||
addNewestConversation(value);
|
|
||||||
return ret;
|
|
||||||
},
|
},
|
||||||
[addNewestConversation, handleSendMessage, done, setValue, value],
|
[addNewestConversation, handleSendMessage, done, setValue, value],
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user