import React, { useState, useEffect } from 'react'; import { Layout, List, Input, Button, Avatar, Typography, Space, Modal, Form, Select, Tag, message, Dropdown, Popconfirm, Alert } from 'antd'; import { SendOutlined, PlusOutlined, RobotOutlined, UserOutlined, SettingOutlined, MessageOutlined, DeleteOutlined, EditOutlined, PlusSquareOutlined } from '@ant-design/icons'; const { Sider, Content } = Layout; const { Title, Text } = Typography; const { TextArea } = Input; interface Message { id: string; content: string; role: 'user' | 'assistant'; timestamp: string; } interface Conversation { id: string; title: string; botName: string; botType: 'feishu' | 'other'; lastMessage: string; timestamp: string; messages: Message[]; } interface BotConfig { id: string; name: string; type: 'feishu' | 'other'; appId: string; appSecret: string; description: string; } const ConversationsPage: React.FC = () => { const [conversations, setConversations] = useState([]); const [selectedConversation, setSelectedConversation] = useState(null); const [messageInput, setMessageInput] = useState(''); const [botConfigs, setBotConfigs] = useState([]); const [showBotModal, setShowBotModal] = useState(false); const [showConversationModal, setShowConversationModal] = useState(false); const [editingBot, setEditingBot] = useState(null); const [form] = Form.useForm(); const [conversationForm] = Form.useForm(); useEffect(() => { loadData(); }, []); const loadData = () => { // 加载飞书机器人配置 const savedBots = localStorage.getItem('botConfigs'); if (savedBots) { setBotConfigs(JSON.parse(savedBots)); } else { // 默认配置示例 const defaultBots: BotConfig[] = [ { id: '1', name: '助手机器人', type: 'feishu', appId: 'cli_xxxxxxxxxxxxx', appSecret: 'xxxxxxxxxxxxx', description: '用于日常事务处理和提醒' } ]; setBotConfigs(defaultBots); localStorage.setItem('botConfigs', JSON.stringify(defaultBots)); } // 加载会话列表 const savedConversations = localStorage.getItem('conversations'); if (savedConversations) { setConversations(JSON.parse(savedConversations)); } else { // 默认会话示例 const defaultConversations: Conversation[] = [ { id: '1', title: '欢迎使用飞书机器人', botName: '助手机器人', botType: 'feishu', lastMessage: '你好!我是飞书助手机器人,有什么可以帮助您的吗?', timestamp: new Date().toISOString(), messages: [ { id: '1', content: '你好!我是飞书助手机器人,有什么可以帮助您的吗?', role: 'assistant', timestamp: new Date().toISOString() } ] } ]; setConversations(defaultConversations); localStorage.setItem('conversations', JSON.stringify(defaultConversations)); } }; const handleSendMessage = async () => { if (!messageInput.trim() || !selectedConversation) return; const newMessage: Message = { id: Date.now().toString(), content: messageInput, role: 'user', timestamp: new Date().toISOString() }; const updatedConversation = { ...selectedConversation, messages: [...selectedConversation.messages, newMessage], lastMessage: messageInput, timestamp: new Date().toISOString() }; setSelectedConversation(updatedConversation); setConversations(conversations.map(conv => conv.id === selectedConversation.id ? updatedConversation : conv )); // 保存到本地存储 localStorage.setItem('conversations', JSON.stringify( conversations.map(conv => conv.id === selectedConversation.id ? updatedConversation : conv) )); setMessageInput(''); // 模拟飞书应用回复 setTimeout(() => { const botReply: Message = { id: (Date.now() + 1).toString(), content: `收到您的消息:"${messageInput}"。这是一个模拟的飞书应用回复。在实际使用中,这里会调用飞书自建应用API来发送消息。`, role: 'assistant', timestamp: new Date().toISOString() }; const updatedWithReply = { ...updatedConversation, messages: [...updatedConversation.messages, botReply], lastMessage: botReply.content, timestamp: new Date().toISOString() }; setSelectedConversation(updatedWithReply); setConversations(conversations.map(conv => conv.id === selectedConversation.id ? updatedWithReply : conv )); localStorage.setItem('conversations', JSON.stringify( conversations.map(conv => conv.id === selectedConversation.id ? updatedWithReply : conv) )); }, 1000); }; const handleSubmitConversation = () => { conversationForm.validateFields().then(values => { const selectedBot = botConfigs.find(bot => bot.id === values.botId); if (!selectedBot) return; const newConversation: Conversation = { id: Date.now().toString(), title: values.title, botName: selectedBot.name, botType: selectedBot.type, lastMessage: '新会话已创建', timestamp: new Date().toISOString(), messages: [] }; setConversations([newConversation, ...conversations]); localStorage.setItem('conversations', JSON.stringify([newConversation, ...conversations])); setShowConversationModal(false); conversationForm.resetFields(); setSelectedConversation(newConversation); message.success('会话创建成功'); }); }; const handleAddBot = () => { setEditingBot(null); form.resetFields(); setShowBotModal(true); }; const handleEditBot = (bot: BotConfig) => { setEditingBot(bot); form.setFieldsValue(bot); setShowBotModal(true); }; const handleDeleteBot = (botId: string) => { const updatedBots = botConfigs.filter(bot => bot.id !== botId); setBotConfigs(updatedBots); localStorage.setItem('botConfigs', JSON.stringify(updatedBots)); message.success('机器人配置已删除'); }; const handleSubmitBot = () => { form.validateFields().then(values => { if (editingBot) { // 编辑模式 const updatedBot: BotConfig = { ...editingBot, name: values.name, type: values.type, appId: values.appId, appSecret: values.appSecret, description: values.description }; const updatedBots = botConfigs.map(bot => bot.id === editingBot.id ? updatedBot : bot ); setBotConfigs(updatedBots); localStorage.setItem('botConfigs', JSON.stringify(updatedBots)); message.success('飞书应用配置已更新'); } else { // 新增模式 const newBot: BotConfig = { id: Date.now().toString(), name: values.name, type: values.type, appId: values.appId, appSecret: values.appSecret, description: values.description }; setBotConfigs([...botConfigs, newBot]); localStorage.setItem('botConfigs', JSON.stringify([...botConfigs, newBot])); message.success('飞书应用配置已添加'); } setShowBotModal(false); form.resetFields(); setEditingBot(null); }); }; const handleDeleteConversation = (conversationId: string) => { const updatedConversations = conversations.filter(conv => conv.id !== conversationId); setConversations(updatedConversations); localStorage.setItem('conversations', JSON.stringify(updatedConversations)); if (selectedConversation?.id === conversationId) { setSelectedConversation(null); } message.success('会话已删除'); }; const getBotItems = () => { return [ { key: 'add', label: (
handleAddBot()}> 添加飞书应用
) }, { type: 'divider' as const, }, ...botConfigs.map(bot => ({ key: bot.id, label: (
{bot.name} {bot.type === 'feishu' ? '飞书' : '其他'} { e.stopPropagation(); handleEditBot(bot); }} /> { e?.stopPropagation(); handleDeleteBot(bot.id); }} okText="确定" cancelText="取消" > e.stopPropagation()} />
) })) ]; }; return (
<MessageOutlined style={{ color: '#1890ff' }} /> 飞书机器人会话 与飞书自建应用进行对话,指挥AI助手完成各种任务
{/* 左侧会话列表 */}
{/* 飞书应用列表 */}
飞书应用
{botConfigs.length > 0 ? ( {botConfigs.map(bot => { const hasConversation = conversations.some(conv => conv.botName === bot.name); return (
{ if (hasConversation) { const existingConv = conversations.find(conv => conv.botName === bot.name); if (existingConv) { setSelectedConversation(existingConv); } } else { // 创建新会话 const newConversation: Conversation = { id: Date.now().toString(), title: bot.name, botName: bot.name, botType: bot.type, lastMessage: '新会话已创建', timestamp: new Date().toISOString(), messages: [] }; setConversations([newConversation, ...conversations]); localStorage.setItem('conversations', JSON.stringify([newConversation, ...conversations])); setSelectedConversation(newConversation); } }} style={{ display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', background: selectedConversation?.botName === bot.name ? '#e6f7ff' : 'white', borderRadius: '8px', cursor: 'pointer', border: '1px solid #f0f0f0', transition: 'all 0.3s' }} onMouseEnter={(e) => { if (selectedConversation?.botName !== bot.name) { e.currentTarget.style.background = '#f5f5f5'; e.currentTarget.style.borderColor = '#d9d9d9'; } }} onMouseLeave={(e) => { if (selectedConversation?.botName !== bot.name) { e.currentTarget.style.background = 'white'; e.currentTarget.style.borderColor = '#f0f0f0'; } }} > } style={{ backgroundColor: '#1890ff' }} />
{bot.name} {bot.type === 'feishu' ? '飞书' : '其他'}
{hasConversation ? '点击继续对话' : '点击开始对话'}
); })}
) : (
暂无飞书应用
)}
{/* 会话列表 */}
会话列表
( setSelectedConversation(conversation)} style={{ padding: '12px', cursor: 'pointer', background: selectedConversation?.id === conversation.id ? '#e6f7ff' : 'transparent', borderRadius: '8px', marginBottom: '8px', border: '1px solid #f0f0f0', transition: 'all 0.3s' }} onMouseEnter={(e) => { if (selectedConversation?.id !== conversation.id) { e.currentTarget.style.background = '#f5f5f5'; e.currentTarget.style.borderColor = '#d9d9d9'; } }} onMouseLeave={(e) => { if (selectedConversation?.id !== conversation.id) { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.borderColor = '#f0f0f0'; } }} > } style={{ backgroundColor: '#1890ff' }} /> } title={
{conversation.title} {conversation.botType === 'feishu' ? '飞书' : '其他'}
} description={
{conversation.lastMessage} {new Date(conversation.timestamp).toLocaleString()}
} />
)} />
{/* 右侧会话内容 */} {selectedConversation ? ( <> {/* 会话头部 */}
} style={{ backgroundColor: '#1890ff' }} />
{selectedConversation.title} 飞书机器人:{selectedConversation.botName}
handleDeleteConversation(selectedConversation.id)} okText="确定" cancelText="取消" >
{/* 消息列表 */}
{selectedConversation.messages.length === 0 ? (
暂无消息,开始与机器人对话吧!
) : ( {selectedConversation.messages.map((message) => (
{message.role === 'assistant' && ( } style={{ backgroundColor: '#1890ff' }} /> )}
{message.role === 'assistant' && ( {selectedConversation.botName} )}
{message.content}
{new Date(message.timestamp).toLocaleString()}
{message.role === 'user' && ( } style={{ backgroundColor: '#52c41a' }} /> )}
))}
)}
{/* 消息输入区 */}