agent功能开发增加MCP后端

This commit is contained in:
2025-11-07 18:11:29 +08:00
parent a1c76a257c
commit e7ba8c4c2d
11 changed files with 936 additions and 1 deletions

View File

@@ -0,0 +1,149 @@
// 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 (
<Flex
w="100%"
justify={isUser ? 'flex-end' : 'flex-start'}
mb={4}
>
<Flex
maxW="75%"
flexDirection={isUser ? 'row-reverse' : 'row'}
align="flex-start"
>
{/* 头像 */}
<Avatar
size="sm"
name={isUser ? '用户' : 'AI助手'}
bg={isUser ? 'blue.500' : 'green.500'}
color="white"
mx={3}
/>
{/* 消息内容 */}
<Box>
<Box
bg={isUser ? userBg : botBg}
color={isUser ? userColor : botColor}
px={4}
py={3}
borderRadius="lg"
boxShadow="sm"
>
{message.type === 'text' ? (
<Text fontSize="sm" whiteSpace="pre-wrap">
{message.content}
</Text>
) : message.type === 'markdown' ? (
<Box fontSize="sm" className="markdown-content">
<ReactMarkdown>{message.content}</ReactMarkdown>
</Box>
) : message.type === 'data' ? (
<VStack align="stretch" spacing={2}>
{message.data && Array.isArray(message.data) && message.data.slice(0, 5).map((item, idx) => (
<Box
key={idx}
p={3}
bg={useColorModeValue('white', 'gray.600')}
borderRadius="md"
fontSize="xs"
>
{Object.entries(item).map(([key, value]) => (
<Flex key={key} justify="space-between" mb={1}>
<Text fontWeight="bold" mr={2}>{key}:</Text>
<Text>{String(value)}</Text>
</Flex>
))}
</Box>
))}
{message.data && message.data.length > 5 && (
<Badge colorScheme="blue" alignSelf="center">
+{message.data.length - 5} 更多结果
</Badge>
)}
</VStack>
) : null}
</Box>
{/* 消息操作按钮仅AI消息 */}
{!isUser && (
<HStack mt={2} spacing={2}>
<IconButton
icon={<FiCopy />}
size="xs"
variant="ghost"
aria-label="复制"
onClick={handleCopy}
/>
<IconButton
icon={<FiThumbsUp />}
size="xs"
variant="ghost"
aria-label="赞"
onClick={() => onFeedback?.('positive')}
/>
<IconButton
icon={<FiThumbsDown />}
size="xs"
variant="ghost"
aria-label="踩"
onClick={() => onFeedback?.('negative')}
/>
</HStack>
)}
{/* 时间戳 */}
<Text
fontSize="xs"
color="gray.500"
mt={1}
textAlign={isUser ? 'right' : 'left'}
>
{message.timestamp ? new Date(message.timestamp).toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit',
}) : ''}
</Text>
</Box>
</Flex>
</Flex>
);
};
export default MessageBubble;