### What problem does this PR solve? feat: Delete message by id #2088 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.11.0
| @@ -1,5 +1,6 @@ | |||
| import CopyToClipboard from '@/components/copy-to-clipboard'; | |||
| import { useSetModalState } from '@/hooks/common-hooks'; | |||
| import { IRemoveMessageById } from '@/hooks/logic-hooks'; | |||
| import { | |||
| DeleteOutlined, | |||
| DislikeOutlined, | |||
| @@ -11,7 +12,7 @@ import { Radio } from 'antd'; | |||
| import { useCallback } from 'react'; | |||
| import SvgIcon from '../svg-icon'; | |||
| import FeedbackModal from './feedback-modal'; | |||
| import { useSendFeedback } from './hooks'; | |||
| import { useRemoveMessage, useSendFeedback } from './hooks'; | |||
| import PromptModal from './prompt-modal'; | |||
| interface IProps { | |||
| @@ -77,12 +78,20 @@ export const AssistantGroupButton = ({ | |||
| ); | |||
| }; | |||
| interface UserGroupButtonProps { | |||
| interface UserGroupButtonProps extends IRemoveMessageById { | |||
| messageId: string; | |||
| content: string; | |||
| } | |||
| export const UserGroupButton = ({ content }: UserGroupButtonProps) => { | |||
| export const UserGroupButton = ({ | |||
| content, | |||
| messageId, | |||
| removeMessageById, | |||
| }: UserGroupButtonProps) => { | |||
| const { onRemoveMessage, loading } = useRemoveMessage( | |||
| messageId, | |||
| removeMessageById, | |||
| ); | |||
| return ( | |||
| <Radio.Group size="small"> | |||
| <Radio.Button value="a"> | |||
| @@ -91,8 +100,8 @@ export const UserGroupButton = ({ content }: UserGroupButtonProps) => { | |||
| <Radio.Button value="b"> | |||
| <SyncOutlined /> | |||
| </Radio.Button> | |||
| <Radio.Button value="c"> | |||
| <DeleteOutlined /> | |||
| <Radio.Button value="c" onClick={onRemoveMessage} disabled={loading}> | |||
| <DeleteOutlined spin={loading} /> | |||
| </Radio.Button> | |||
| </Radio.Group> | |||
| ); | |||
| @@ -1,5 +1,6 @@ | |||
| import { useFeedback } from '@/hooks/chat-hooks'; | |||
| import { useDeleteMessage, useFeedback } from '@/hooks/chat-hooks'; | |||
| import { useSetModalState } from '@/hooks/common-hooks'; | |||
| import { IRemoveMessageById } from '@/hooks/logic-hooks'; | |||
| import { IFeedbackRequestBody } from '@/interfaces/request/chat'; | |||
| import { getMessagePureId } from '@/utils/chat'; | |||
| import { useCallback } from 'react'; | |||
| @@ -30,3 +31,22 @@ export const useSendFeedback = (messageId: string) => { | |||
| showModal, | |||
| }; | |||
| }; | |||
| export const useRemoveMessage = ( | |||
| messageId: string, | |||
| removeMessageById: IRemoveMessageById['removeMessageById'], | |||
| ) => { | |||
| const { deleteMessage, loading } = useDeleteMessage(); | |||
| const onRemoveMessage = useCallback(async () => { | |||
| const pureId = getMessagePureId(messageId); | |||
| if (pureId) { | |||
| const retcode = await deleteMessage(pureId); | |||
| if (retcode === 0) { | |||
| removeMessageById(messageId); | |||
| } | |||
| } | |||
| }, [deleteMessage, messageId, removeMessageById]); | |||
| return { onRemoveMessage, loading }; | |||
| }; | |||
| @@ -11,6 +11,7 @@ import { | |||
| useFetchDocumentInfosByIds, | |||
| useFetchDocumentThumbnailsByIds, | |||
| } from '@/hooks/document-hooks'; | |||
| import { IRemoveMessageById } from '@/hooks/logic-hooks'; | |||
| import { IMessage } from '@/pages/chat/interface'; | |||
| import MarkdownContent from '@/pages/chat/markdown-content'; | |||
| import { getExtension, isImage } from '@/utils/document-util'; | |||
| @@ -23,7 +24,7 @@ import styles from './index.less'; | |||
| const { Text } = Typography; | |||
| interface IProps { | |||
| interface IProps extends IRemoveMessageById { | |||
| item: IMessage; | |||
| reference: IReference; | |||
| loading?: boolean; | |||
| @@ -40,6 +41,7 @@ const MessageItem = ({ | |||
| avatar = '', | |||
| clickDocumentButton, | |||
| index, | |||
| removeMessageById, | |||
| }: IProps) => { | |||
| const isAssistant = item.role === MessageType.Assistant; | |||
| const isUser = item.role === MessageType.User; | |||
| @@ -125,6 +127,7 @@ const MessageItem = ({ | |||
| <UserGroupButton | |||
| content={item.content} | |||
| messageId={item.id} | |||
| removeMessageById={removeMessageById} | |||
| ></UserGroupButton> | |||
| )} | |||
| @@ -314,6 +314,10 @@ export const useDeleteMessage = () => { | |||
| conversationId, | |||
| }); | |||
| if (data.retcode === 0) { | |||
| message.success(i18n.t(`message.deleted`)); | |||
| } | |||
| return data.retcode; | |||
| }, | |||
| }); | |||
| @@ -5,8 +5,10 @@ import { ResponseType } from '@/interfaces/database/base'; | |||
| import { IAnswer } from '@/interfaces/database/chat'; | |||
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | |||
| import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | |||
| import { IClientConversation } from '@/pages/chat/interface'; | |||
| import api from '@/utils/api'; | |||
| import { getAuthorization } from '@/utils/authorization-util'; | |||
| import { getMessagePureId } from '@/utils/chat'; | |||
| import { PaginationProps } from 'antd'; | |||
| import { FormInstance } from 'antd/lib'; | |||
| import axios from 'axios'; | |||
| @@ -306,6 +308,34 @@ export const useHandleMessageInputChange = () => { | |||
| }; | |||
| }; | |||
| export interface IRemoveMessageById { | |||
| removeMessageById(messageId: string): void; | |||
| } | |||
| export const useRemoveMessageById = ( | |||
| setCurrentConversation: ( | |||
| callback: (state: IClientConversation) => IClientConversation, | |||
| ) => void, | |||
| ) => { | |||
| const removeMessageById = useCallback( | |||
| (messageId: string) => { | |||
| setCurrentConversation((pre) => { | |||
| const nextMessages = | |||
| pre.message?.filter( | |||
| (x) => getMessagePureId(x.id) !== getMessagePureId(messageId), | |||
| ) ?? []; | |||
| return { | |||
| ...pre, | |||
| message: nextMessages, | |||
| }; | |||
| }); | |||
| }, | |||
| [setCurrentConversation], | |||
| ); | |||
| return { removeMessageById }; | |||
| }; | |||
| // #endregion | |||
| /** | |||
| @@ -27,6 +27,7 @@ const ChatContainer = () => { | |||
| addNewestAnswer, | |||
| conversationId, | |||
| loading, | |||
| removeMessageById, | |||
| } = useFetchConversationOnMount(); | |||
| const { | |||
| handleInputChange, | |||
| @@ -69,6 +70,7 @@ const ChatContainer = () => { | |||
| reference={buildMessageItemReference(conversation, message)} | |||
| clickDocumentButton={clickDocumentButton} | |||
| index={i} | |||
| removeMessageById={removeMessageById} | |||
| ></MessageItem> | |||
| ); | |||
| })} | |||
| @@ -17,7 +17,10 @@ import { | |||
| useShowDeleteConfirm, | |||
| useTranslate, | |||
| } from '@/hooks/common-hooks'; | |||
| import { useSendMessageWithSse } from '@/hooks/logic-hooks'; | |||
| import { | |||
| useRemoveMessageById, | |||
| useSendMessageWithSse, | |||
| } from '@/hooks/logic-hooks'; | |||
| import { | |||
| IAnswer, | |||
| IConversation, | |||
| @@ -251,6 +254,7 @@ export const useSelectCurrentConversation = () => { | |||
| const { data: conversation, loading } = useFetchNextConversation(); | |||
| const { data: dialog } = useFetchNextDialog(); | |||
| const { conversationId, dialogId } = useGetChatSearchParams(); | |||
| const { removeMessageById } = useRemoveMessageById(setCurrentConversation); | |||
| // Show the entered message in the conversation immediately after sending the message | |||
| const addNewestConversation = useCallback( | |||
| @@ -348,6 +352,7 @@ export const useSelectCurrentConversation = () => { | |||
| addNewestConversation, | |||
| removeLatestMessage, | |||
| addNewestAnswer, | |||
| removeMessageById, | |||
| loading, | |||
| }; | |||
| }; | |||
| @@ -376,6 +381,7 @@ export const useFetchConversationOnMount = () => { | |||
| removeLatestMessage, | |||
| addNewestAnswer, | |||
| loading, | |||
| removeMessageById, | |||
| } = useSelectCurrentConversation(); | |||
| const ref = useScrollToBottom(currentConversation); | |||
| @@ -387,6 +393,7 @@ export const useFetchConversationOnMount = () => { | |||
| addNewestAnswer, | |||
| conversationId, | |||
| loading, | |||
| removeMessageById, | |||
| }; | |||
| }; | |||
| @@ -408,7 +415,7 @@ export const useHandleMessageInputChange = () => { | |||
| export const useSendMessage = ( | |||
| conversation: IClientConversation, | |||
| addNewestConversation: (message: Partial<Message>, answer?: string) => void, | |||
| addNewestConversation: (message: Message, answer?: string) => void, | |||
| removeLatestMessage: () => void, | |||
| addNewestAnswer: (answer: IAnswer) => void, | |||
| ) => { | |||