### What problem does this PR solve? fix: remove duplicate MessageItem #1289 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.9.0
| background-color: rgba(249, 250, 251, 1); | background-color: rgba(249, 250, 251, 1); | ||||
| word-break: break-all; | word-break: break-all; | ||||
| } | } | ||||
| .messageTextBase() { | |||||
| padding: 6px 10px; | |||||
| border-radius: 8px; | |||||
| & > p { | |||||
| margin: 0; | |||||
| } | |||||
| } | |||||
| .messageText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: #e6f4ff; | |||||
| word-break: break-all; | |||||
| } | |||||
| .messageUserText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: rgb(248, 247, 247); | |||||
| word-break: break-all; | |||||
| text-align: justify; | |||||
| } | |||||
| .messageEmpty { | .messageEmpty { | ||||
| width: 300px; | width: 300px; | ||||
| } | } |
| import { useTranslate } from '@/hooks/commonHooks'; | import { useTranslate } from '@/hooks/commonHooks'; | ||||
| import { useGetDocumentUrl } from '@/hooks/documentHooks'; | import { useGetDocumentUrl } from '@/hooks/documentHooks'; | ||||
| import { useSelectFileThumbnails } from '@/hooks/knowledgeHook'; | import { useSelectFileThumbnails } from '@/hooks/knowledgeHook'; | ||||
| import { useSelectUserInfo } from '@/hooks/userSettingHook'; | |||||
| import { IReference, Message } from '@/interfaces/database/chat'; | import { IReference, Message } from '@/interfaces/database/chat'; | ||||
| import { IChunk } from '@/interfaces/database/knowledge'; | import { IChunk } from '@/interfaces/database/knowledge'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import SvgIcon from '../svg-icon'; | import SvgIcon from '../svg-icon'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| interface IProps { | |||||
| item: Message; | |||||
| reference: IReference; | |||||
| loading?: boolean; | |||||
| nickname?: string; | |||||
| avatar?: string; | |||||
| clickDocumentButton?: (documentId: string, chunk: IChunk) => void; | |||||
| } | |||||
| const MessageItem = ({ | const MessageItem = ({ | ||||
| item, | item, | ||||
| reference, | reference, | ||||
| loading = false, | loading = false, | ||||
| avatar = '', | |||||
| nickname = '', | |||||
| clickDocumentButton, | clickDocumentButton, | ||||
| }: { | |||||
| item: Message; | |||||
| reference: IReference; | |||||
| loading?: boolean; | |||||
| clickDocumentButton: (documentId: string, chunk: IChunk) => void; | |||||
| }) => { | |||||
| const userInfo = useSelectUserInfo(); | |||||
| }: IProps) => { | |||||
| const isAssistant = item.role === MessageType.Assistant; | |||||
| const { t } = useTranslate('chat'); | |||||
| const fileThumbnails = useSelectFileThumbnails(); | const fileThumbnails = useSelectFileThumbnails(); | ||||
| const getDocumentUrl = useGetDocumentUrl(); | const getDocumentUrl = useGetDocumentUrl(); | ||||
| const { t } = useTranslate('chat'); | |||||
| const isAssistant = item.role === MessageType.Assistant; | |||||
| const referenceDocumentList = useMemo(() => { | const referenceDocumentList = useMemo(() => { | ||||
| return reference?.doc_aggs ?? []; | return reference?.doc_aggs ?? []; | ||||
| <Avatar | <Avatar | ||||
| size={40} | size={40} | ||||
| src={ | src={ | ||||
| userInfo.avatar ?? | |||||
| avatar ?? | |||||
| 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' | 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' | ||||
| } | } | ||||
| /> | /> | ||||
| <AssistantIcon></AssistantIcon> | <AssistantIcon></AssistantIcon> | ||||
| )} | )} | ||||
| <Flex vertical gap={8} flex={1}> | <Flex vertical gap={8} flex={1}> | ||||
| <b>{isAssistant ? '' : userInfo.nickname}</b> | |||||
| <div className={styles.messageText}> | |||||
| <b>{isAssistant ? '' : nickname}</b> | |||||
| <div | |||||
| className={ | |||||
| isAssistant ? styles.messageText : styles.messageUserText | |||||
| } | |||||
| > | |||||
| <MarkdownContent | <MarkdownContent | ||||
| content={content} | content={content} | ||||
| reference={reference} | reference={reference} |
| dsl?: DSL; | dsl?: DSL; | ||||
| avatar?: string; | avatar?: string; | ||||
| }) => { | }) => { | ||||
| const { data } = await flowService.setCanvas(params); | |||||
| const { data = {} } = await flowService.setCanvas(params); | |||||
| if (data.retcode === 0) { | if (data.retcode === 0) { | ||||
| message.success( | message.success( | ||||
| i18n.t(`message.${params?.id ? 'modified' : 'created'}`), | i18n.t(`message.${params?.id ? 'modified' : 'created'}`), |
| const d = val?.data; | const d = val?.data; | ||||
| if (typeof d !== 'boolean') { | if (typeof d !== 'boolean') { | ||||
| console.info('data:', d); | console.info('data:', d); | ||||
| setAnswer(d); | |||||
| setAnswer({ | |||||
| ...d, | |||||
| conversationId: body?.conversation_id, | |||||
| }); | |||||
| } | } | ||||
| } catch (e) { | } catch (e) { | ||||
| console.warn(e); | console.warn(e); |
| export interface IAnswer { | export interface IAnswer { | ||||
| answer: string; | answer: string; | ||||
| reference: IReference; | reference: IReference; | ||||
| conversationId?: string; | |||||
| } | } | ||||
| export interface Docagg { | export interface Docagg { |
| padding-right: 24px; | padding-right: 24px; | ||||
| } | } | ||||
| } | } | ||||
| .messageItem { | |||||
| padding: 24px 0; | |||||
| .messageItemSection { | |||||
| display: inline-block; | |||||
| } | |||||
| .messageItemSectionLeft { | |||||
| width: 70%; | |||||
| } | |||||
| .messageItemSectionRight { | |||||
| width: 40%; | |||||
| } | |||||
| .messageItemContent { | |||||
| display: inline-flex; | |||||
| gap: 20px; | |||||
| } | |||||
| .messageItemContentReverse { | |||||
| flex-direction: row-reverse; | |||||
| } | |||||
| .messageTextBase() { | |||||
| padding: 6px 10px; | |||||
| border-radius: 8px; | |||||
| & > p { | |||||
| margin: 0; | |||||
| } | |||||
| } | |||||
| .messageText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: #e6f4ff; | |||||
| word-break: break-all; | |||||
| } | |||||
| .messageUserText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: rgb(248, 247, 247); | |||||
| word-break: break-all; | |||||
| text-align: justify; | |||||
| } | |||||
| .messageEmpty { | |||||
| width: 300px; | |||||
| } | |||||
| // .referenceIcon { | |||||
| // padding: 0 6px; | |||||
| // } | |||||
| .thumbnailImg { | |||||
| max-width: 20px; | |||||
| } | |||||
| } | |||||
| .messageItemLeft { | |||||
| text-align: left; | |||||
| } | |||||
| .messageItemRight { | |||||
| text-align: right; | |||||
| } | |||||
| // .referencePopoverWrapper { | |||||
| // max-width: 50vw; | |||||
| // } | |||||
| // .referenceChunkImage { | |||||
| // width: 10vw; | |||||
| // object-fit: contain; | |||||
| // } | |||||
| // .referenceImagePreview { | |||||
| // max-width: 45vw; | |||||
| // max-height: 45vh; | |||||
| // } | |||||
| // .chunkContentText { | |||||
| // .chunkText; | |||||
| // max-height: 45vh; | |||||
| // overflow-y: auto; | |||||
| // } | |||||
| // .documentLink { | |||||
| // padding: 0; | |||||
| // } |
| import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; | |||||
| import NewDocumentLink from '@/components/new-document-link'; | |||||
| import MessageItem from '@/components/message-item'; | |||||
| import DocumentPreviewer from '@/components/pdf-previewer'; | import DocumentPreviewer from '@/components/pdf-previewer'; | ||||
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { useSelectFileThumbnails } from '@/hooks/knowledgeHook'; | |||||
| import { useSelectUserInfo } from '@/hooks/userSettingHook'; | |||||
| import { IReference, Message } from '@/interfaces/database/chat'; | |||||
| import { IChunk } from '@/interfaces/database/knowledge'; | |||||
| import { Avatar, Button, Drawer, Flex, Input, List, Spin } from 'antd'; | |||||
| import classNames from 'classnames'; | |||||
| import { useMemo } from 'react'; | |||||
| import { useTranslate } from '@/hooks/commonHooks'; | |||||
| import { Button, Drawer, Flex, Input, Spin } from 'antd'; | |||||
| import { | import { | ||||
| useClickDrawer, | useClickDrawer, | ||||
| useFetchConversationOnMount, | useFetchConversationOnMount, | ||||
| useGetFileIcon, | useGetFileIcon, | ||||
| useGetSendButtonDisabled, | useGetSendButtonDisabled, | ||||
| useSelectConversationLoading, useSendButtonDisabled, | |||||
| useSelectConversationLoading, | |||||
| useSendButtonDisabled, | |||||
| useSendMessage, | useSendMessage, | ||||
| } from '../hooks'; | } from '../hooks'; | ||||
| import MarkdownContent from '../markdown-content'; | |||||
| import SvgIcon from '@/components/svg-icon'; | |||||
| import { useTranslate } from '@/hooks/commonHooks'; | |||||
| import { useGetDocumentUrl } from '@/hooks/documentHooks'; | |||||
| import { getExtension, isPdf } from '@/utils/documentUtils'; | |||||
| import { buildMessageItemReference } from '../utils'; | import { buildMessageItemReference } from '../utils'; | ||||
| 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={isAssistant ? styles.messageText : styles.messageUserText}> | |||||
| <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> | |||||
| ); | |||||
| }; | |||||
| import { useSelectUserInfo } from '@/hooks/userSettingHook'; | |||||
| import styles from './index.less'; | |||||
| const ChatContainer = () => { | const ChatContainer = () => { | ||||
| const { | const { | ||||
| useGetFileIcon(); | useGetFileIcon(); | ||||
| const loading = useSelectConversationLoading(); | const loading = useSelectConversationLoading(); | ||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); | ||||
| const userInfo = useSelectUserInfo(); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| } | } | ||||
| key={message.id} | key={message.id} | ||||
| item={message} | item={message} | ||||
| nickname={userInfo.nickname} | |||||
| avatar={userInfo.avatar} | |||||
| reference={buildMessageItemReference(conversation, message)} | reference={buildMessageItemReference(conversation, message)} | ||||
| clickDocumentButton={clickDocumentButton} | clickDocumentButton={clickDocumentButton} | ||||
| ></MessageItem> | ></MessageItem> |
| return pre; | return pre; | ||||
| }); | }); | ||||
| }, [conversationList, dialogId, prologue]); | |||||
| }, [conversationList, dialogId, prologue, t]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| addTemporaryConversation(); | addTemporaryConversation(); | ||||
| role: MessageType.Assistant, | role: MessageType.Assistant, | ||||
| content: answer, | content: answer, | ||||
| id: uuid(), | id: uuid(), | ||||
| reference: [], | |||||
| reference: {}, | |||||
| } as IMessage, | } as IMessage, | ||||
| ], | ], | ||||
| }; | }; | ||||
| }, []); | }, []); | ||||
| const removeLatestMessage = useCallback(() => { | const removeLatestMessage = useCallback(() => { | ||||
| console.info('removeLatestMessage'); | |||||
| setCurrentConversation((pre) => { | setCurrentConversation((pre) => { | ||||
| const nextMessages = pre.message?.slice(0, -2) ?? []; | const nextMessages = pre.message?.slice(0, -2) ?? []; | ||||
| return { | return { | ||||
| const ref = useRef<HTMLDivElement>(null); | const ref = useRef<HTMLDivElement>(null); | ||||
| const scrollToBottom = useCallback(() => { | const scrollToBottom = useCallback(() => { | ||||
| console.info('useScrollToBottom'); | |||||
| if (currentConversation.id) { | if (currentConversation.id) { | ||||
| ref.current?.scrollIntoView({ behavior: 'instant' }); | ref.current?.scrollIntoView({ behavior: 'instant' }); | ||||
| } | } | ||||
| [ | [ | ||||
| conversation?.message, | conversation?.message, | ||||
| conversationId, | conversationId, | ||||
| // fetchConversation, | |||||
| handleClickConversation, | handleClickConversation, | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| setValue, | setValue, | ||||
| ); | ); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (answer.answer) { | |||||
| if (answer.answer && answer?.conversationId === conversationId) { | |||||
| addNewestAnswer(answer); | addNewestAnswer(answer); | ||||
| console.info('true?'); | |||||
| console.info('send msg:', answer.answer); | |||||
| } | } | ||||
| }, [answer, addNewestAnswer]); | |||||
| }, [answer, addNewestAnswer, conversationId]); | |||||
| const handlePressEnter = useCallback(() => { | const handlePressEnter = useCallback(() => { | ||||
| if (trim(value) === '') return; | if (trim(value) === '') return; | ||||
| }; | }; | ||||
| export const useGetFileIcon = () => { | export const useGetFileIcon = () => { | ||||
| // const req = require.context('@/assets/svg/file-icon'); | |||||
| // const ret = req.keys().map(req); | |||||
| // console.info(ret); | |||||
| // useEffect(() => {}, []); | |||||
| const getFileIcon = (filename: string) => { | const getFileIcon = (filename: string) => { | ||||
| const ext: string = getFileExtension(filename); | const ext: string = getFileExtension(filename); | ||||
| const iconPath = fileIconMap[ext as keyof typeof fileIconMap]; | const iconPath = fileIconMap[ext as keyof typeof fileIconMap]; | ||||
| // const x = require(`@/assets/svg/file-icon/${iconPath}`); | |||||
| return `@/assets/svg/file-icon/${iconPath}`; | return `@/assets/svg/file-icon/${iconPath}`; | ||||
| }; | }; | ||||
| }: { | }: { | ||||
| content: string; | content: string; | ||||
| reference: IReference; | reference: IReference; | ||||
| clickDocumentButton: (documentId: string, chunk: IChunk) => void; | |||||
| clickDocumentButton?: (documentId: string, chunk: IChunk) => void; | |||||
| }) => { | }) => { | ||||
| const fileThumbnails = useSelectFileThumbnails(); | const fileThumbnails = useSelectFileThumbnails(); | ||||
| if (!isPdf) { | if (!isPdf) { | ||||
| return; | return; | ||||
| } | } | ||||
| clickDocumentButton(documentId, chunk); | |||||
| clickDocumentButton?.(documentId, chunk); | |||||
| }, | }, | ||||
| [clickDocumentButton], | [clickDocumentButton], | ||||
| ); | ); |
| padding-right: 6px; | padding-right: 6px; | ||||
| } | } | ||||
| } | } | ||||
| .messageItem { | |||||
| padding: 24px 0; | |||||
| .messageItemSection { | |||||
| display: inline-block; | |||||
| } | |||||
| .messageItemSectionLeft { | |||||
| width: 70%; | |||||
| } | |||||
| .messageItemSectionRight { | |||||
| width: 40%; | |||||
| } | |||||
| .messageItemContent { | |||||
| display: inline-flex; | |||||
| gap: 20px; | |||||
| } | |||||
| .messageItemContentReverse { | |||||
| flex-direction: row-reverse; | |||||
| } | |||||
| .messageTextBase() { | |||||
| padding: 6px 10px; | |||||
| border-radius: 8px; | |||||
| & > p { | |||||
| margin: 0; | |||||
| } | |||||
| } | |||||
| .messageText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: #e6f4ff; | |||||
| word-break: break-all; | |||||
| } | |||||
| .messageUserText { | |||||
| .chunkText(); | |||||
| .messageTextBase(); | |||||
| background-color: rgb(248, 247, 247); | |||||
| word-break: break-all; | |||||
| text-align: justify; | |||||
| } | |||||
| .messageEmpty { | |||||
| width: 300px; | |||||
| } | |||||
| .thumbnailImg { | |||||
| max-width: 20px; | |||||
| } | |||||
| } | |||||
| .messageItemLeft { | |||||
| text-align: left; | |||||
| } | |||||
| .messageItemRight { | |||||
| text-align: right; | |||||
| } |
| import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; | |||||
| import MessageItem from '@/components/message-item'; | |||||
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { useTranslate } from '@/hooks/commonHooks'; | import { useTranslate } from '@/hooks/commonHooks'; | ||||
| import { IReference, Message } from '@/interfaces/database/chat'; | |||||
| import { Avatar, Button, Flex, Input, List, Spin } from 'antd'; | |||||
| import classNames from 'classnames'; | |||||
| import NewDocumentLink from '@/components/new-document-link'; | |||||
| import SvgIcon from '@/components/svg-icon'; | |||||
| import { useGetDocumentUrl } from '@/hooks/documentHooks'; | |||||
| import { useSelectFileThumbnails } from '@/hooks/knowledgeHook'; | |||||
| import { getExtension, isPdf } from '@/utils/documentUtils'; | |||||
| import { forwardRef, useMemo } from 'react'; | |||||
| import MarkdownContent from '../markdown-content'; | |||||
| import { useSendButtonDisabled } from '@/pages/chat/hooks'; | |||||
| import { Button, Flex, Input, Spin } from 'antd'; | |||||
| import { forwardRef } from 'react'; | |||||
| import { | import { | ||||
| useCreateSharedConversationOnMount, | useCreateSharedConversationOnMount, | ||||
| useSelectCurrentSharedConversation, | useSelectCurrentSharedConversation, | ||||
| useSendSharedMessage, | useSendSharedMessage, | ||||
| } from '../shared-hooks'; | } from '../shared-hooks'; | ||||
| import { buildMessageItemReference } from '../utils'; | import { buildMessageItemReference } from '../utils'; | ||||
| import styles from './index.less'; | |||||
| import {useSendButtonDisabled} from "@/pages/chat/hooks"; | |||||
| const MessageItem = ({ | |||||
| item, | |||||
| reference, | |||||
| loading = false, | |||||
| }: { | |||||
| item: Message; | |||||
| reference: IReference; | |||||
| loading?: boolean; | |||||
| }) => { | |||||
| const isAssistant = item.role === MessageType.Assistant; | |||||
| const { t } = useTranslate('chat'); | |||||
| const fileThumbnails = useSelectFileThumbnails(); | |||||
| const getDocumentUrl = useGetDocumentUrl(); | |||||
| 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={ | |||||
| 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' | |||||
| } | |||||
| /> | |||||
| ) : ( | |||||
| <AssistantIcon></AssistantIcon> | |||||
| )} | |||||
| <Flex vertical gap={8} flex={1}> | |||||
| <b>{isAssistant ? '' : 'You'}</b> | |||||
| <div className={isAssistant ? styles.messageText : styles.messageUserText}> | |||||
| <MarkdownContent | |||||
| reference={reference} | |||||
| clickDocumentButton={() => {}} | |||||
| content={content} | |||||
| ></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> | |||||
| ); | |||||
| }; | |||||
| import styles from './index.less'; | |||||
| const ChatContainer = () => { | const ChatContainer = () => { | ||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); | ||||
| <MessageItem | <MessageItem | ||||
| key={message.id} | key={message.id} | ||||
| item={message} | item={message} | ||||
| nickname="You" | |||||
| reference={buildMessageItemReference(conversation, message)} | reference={buildMessageItemReference(conversation, message)} | ||||
| loading={ | loading={ | ||||
| message.role === MessageType.Assistant && | message.role === MessageType.Assistant && |
| import { useSelectCurrentMessages, useSendMessage } from './hooks'; | import { useSelectCurrentMessages, useSendMessage } from './hooks'; | ||||
| import { useSelectUserInfo } from '@/hooks/userSettingHook'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const FlowChatBox = () => { | const FlowChatBox = () => { | ||||
| useClickDrawer(); | useClickDrawer(); | ||||
| useGetFileIcon(); | useGetFileIcon(); | ||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); | ||||
| const userInfo = useSelectUserInfo(); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| currentMessages.length - 1 === i | currentMessages.length - 1 === i | ||||
| } | } | ||||
| key={message.id} | key={message.id} | ||||
| nickname={userInfo.nickname} | |||||
| avatar={userInfo.avatar} | |||||
| item={message} | item={message} | ||||
| reference={buildMessageItemReference( | reference={buildMessageItemReference( | ||||
| { message: currentMessages, reference }, | { message: currentMessages, reference }, |