mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? feat: add FlowChatBox #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
129 lines
4.3 KiB
TypeScript
129 lines
4.3 KiB
TypeScript
import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
|
|
import { MessageType } from '@/constants/chat';
|
|
import { useTranslate } from '@/hooks/commonHooks';
|
|
import { useGetDocumentUrl } from '@/hooks/documentHooks';
|
|
import { useSelectFileThumbnails } from '@/hooks/knowledgeHook';
|
|
import { useSelectUserInfo } from '@/hooks/userSettingHook';
|
|
import { IReference, Message } from '@/interfaces/database/chat';
|
|
import { IChunk } from '@/interfaces/database/knowledge';
|
|
import classNames from 'classnames';
|
|
import { useMemo } from 'react';
|
|
|
|
import MarkdownContent from '@/pages/chat/markdown-content';
|
|
import { getExtension, isPdf } from '@/utils/documentUtils';
|
|
import { Avatar, Flex, List } from 'antd';
|
|
import NewDocumentLink from '../new-document-link';
|
|
import SvgIcon from '../svg-icon';
|
|
import styles from './index.less';
|
|
|
|
const MessageItem = ({
|
|
item,
|
|
reference,
|
|
loading = false,
|
|
clickDocumentButton,
|
|
}: {
|
|
item: Message;
|
|
reference: IReference;
|
|
loading?: boolean;
|
|
clickDocumentButton: (documentId: string, chunk: IChunk) => void;
|
|
}) => {
|
|
const userInfo = useSelectUserInfo();
|
|
const fileThumbnails = useSelectFileThumbnails();
|
|
const getDocumentUrl = useGetDocumentUrl();
|
|
const { t } = useTranslate('chat');
|
|
|
|
const isAssistant = item.role === MessageType.Assistant;
|
|
|
|
const referenceDocumentList = useMemo(() => {
|
|
return reference?.doc_aggs ?? [];
|
|
}, [reference?.doc_aggs]);
|
|
|
|
const content = useMemo(() => {
|
|
let text = item.content;
|
|
if (text === '') {
|
|
text = t('searching');
|
|
}
|
|
return loading ? text?.concat('~~2$$') : text;
|
|
}, [item.content, loading, t]);
|
|
|
|
return (
|
|
<div
|
|
className={classNames(styles.messageItem, {
|
|
[styles.messageItemLeft]: item.role === MessageType.Assistant,
|
|
[styles.messageItemRight]: item.role === MessageType.User,
|
|
})}
|
|
>
|
|
<section
|
|
className={classNames(styles.messageItemSection, {
|
|
[styles.messageItemSectionLeft]: item.role === MessageType.Assistant,
|
|
[styles.messageItemSectionRight]: item.role === MessageType.User,
|
|
})}
|
|
>
|
|
<div
|
|
className={classNames(styles.messageItemContent, {
|
|
[styles.messageItemContentReverse]: item.role === MessageType.User,
|
|
})}
|
|
>
|
|
{item.role === MessageType.User ? (
|
|
<Avatar
|
|
size={40}
|
|
src={
|
|
userInfo.avatar ??
|
|
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
|
|
}
|
|
/>
|
|
) : (
|
|
<AssistantIcon></AssistantIcon>
|
|
)}
|
|
<Flex vertical gap={8} flex={1}>
|
|
<b>{isAssistant ? '' : userInfo.nickname}</b>
|
|
<div className={styles.messageText}>
|
|
<MarkdownContent
|
|
content={content}
|
|
reference={reference}
|
|
clickDocumentButton={clickDocumentButton}
|
|
></MarkdownContent>
|
|
</div>
|
|
{isAssistant && referenceDocumentList.length > 0 && (
|
|
<List
|
|
bordered
|
|
dataSource={referenceDocumentList}
|
|
renderItem={(item) => {
|
|
const fileThumbnail = fileThumbnails[item.doc_id];
|
|
const fileExtension = getExtension(item.doc_name);
|
|
return (
|
|
<List.Item>
|
|
<Flex gap={'small'} align="center">
|
|
{fileThumbnail ? (
|
|
<img
|
|
src={fileThumbnail}
|
|
className={styles.thumbnailImg}
|
|
></img>
|
|
) : (
|
|
<SvgIcon
|
|
name={`file-icon/${fileExtension}`}
|
|
width={24}
|
|
></SvgIcon>
|
|
)}
|
|
|
|
<NewDocumentLink
|
|
link={getDocumentUrl(item.doc_id)}
|
|
preventDefault={!isPdf(item.doc_name)}
|
|
>
|
|
{item.doc_name}
|
|
</NewDocumentLink>
|
|
</Flex>
|
|
</List.Item>
|
|
);
|
|
}}
|
|
/>
|
|
)}
|
|
</Flex>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default MessageItem;
|