// src/components/ChatBot/MessageBubble.js // 聊天消息气泡组件 import React from 'react'; import { Box, Flex, Text, Avatar, useColorModeValue, IconButton, HStack, Code, Badge, VStack, } from '@chakra-ui/react'; import { FiCopy, FiThumbsUp, FiThumbsDown } from 'react-icons/fi'; import ReactMarkdown from 'react-markdown'; /** * 消息气泡组件 * @param {Object} props * @param {Object} props.message - 消息对象 * @param {boolean} props.isUser - 是否是用户消息 * @param {Function} props.onCopy - 复制消息回调 * @param {Function} props.onFeedback - 反馈回调 */ export const MessageBubble = ({ message, isUser, onCopy, onFeedback }) => { const userBg = useColorModeValue('blue.500', 'blue.600'); const botBg = useColorModeValue('gray.100', 'gray.700'); const userColor = 'white'; const botColor = useColorModeValue('gray.800', 'white'); const handleCopy = () => { navigator.clipboard.writeText(message.content); onCopy?.(); }; return ( {/* 头像 */} {/* 消息内容 */} {message.type === 'text' ? ( {message.content} ) : message.type === 'markdown' ? ( {message.content} ) : message.type === 'data' ? ( {message.data && Array.isArray(message.data) && message.data.slice(0, 5).map((item, idx) => ( {Object.entries(item).map(([key, value]) => ( {key}: {String(value)} ))} ))} {message.data && message.data.length > 5 && ( +{message.data.length - 5} 更多结果 )} ) : null} {/* 消息操作按钮(仅AI消息) */} {!isUser && ( } size="xs" variant="ghost" aria-label="复制" onClick={handleCopy} /> } size="xs" variant="ghost" aria-label="赞" onClick={() => onFeedback?.('positive')} /> } size="xs" variant="ghost" aria-label="踩" onClick={() => onFeedback?.('negative')} /> )} {/* 时间戳 */} {message.timestamp ? new Date(message.timestamp).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', }) : ''} ); }; export default MessageBubble;