From 47be4584f96dff3ed67c580954c6a5d62462ae3c Mon Sep 17 00:00:00 2001 From: zzlgreat Date: Sat, 22 Nov 2025 11:49:20 +0800 Subject: [PATCH] update pay function --- src/views/AgentChat/index.js | 861 ++++++++++++++++------------------- 1 file changed, 401 insertions(+), 460 deletions(-) diff --git a/src/views/AgentChat/index.js b/src/views/AgentChat/index.js index c6f3d81c..fdd8e52b 100644 --- a/src/views/AgentChat/index.js +++ b/src/views/AgentChat/index.js @@ -1,6 +1,6 @@ // src/views/AgentChat/index.js // 超炫酷的 AI 投研助手 - Hero UI 版本 -// 模仿 Google AI Studio 风格 +// 使用 CSS 动画替代 Framer Motion(避免版本冲突) import React, { useState, useEffect, useRef } from 'react'; import { @@ -22,20 +22,15 @@ import { Tab, ScrollShadow, Kbd, - Snippet, Accordion, AccordionItem, } from '@heroui/react'; -import { motion, AnimatePresence } from 'framer-motion'; import { useAuth } from '@contexts/AuthContext'; import { logger } from '@utils/logger'; import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; // 继续使用 Chakra 的 Toast +import { useToast } from '@chakra-ui/react'; -// Framer Motion 包装组件 -const MotionDiv = motion.div; - -// 图标 - 使用 Hero UI 推荐的 Lucide Icons +// 图标 - 使用 Lucide Icons import { Send, Plus, @@ -156,16 +151,13 @@ const AgentChat = () => { // ==================== API 调用函数 ==================== - // 加载会话列表 const loadSessions = async () => { if (!user?.id) return; - setIsLoadingSessions(true); try { const response = await axios.get('/mcp/agent/sessions', { params: { user_id: user.id, limit: 50 }, }); - if (response.data.success) { setSessions(response.data.data); } @@ -176,15 +168,12 @@ const AgentChat = () => { } }; - // 加载会话历史 const loadSessionHistory = async (sessionId) => { if (!sessionId) return; - try { const response = await axios.get(`/mcp/agent/history/${sessionId}`, { params: { limit: 100 }, }); - if (response.data.success) { const history = response.data.data; const formattedMessages = history.map((msg, idx) => ({ @@ -195,7 +184,6 @@ const AgentChat = () => { stepResults: msg.steps ? JSON.parse(msg.steps) : null, timestamp: msg.timestamp, })); - setMessages(formattedMessages); } } catch (error) { @@ -203,7 +191,6 @@ const AgentChat = () => { } }; - // 创建新会话 const createNewSession = () => { setCurrentSessionId(null); setMessages([ @@ -216,13 +203,11 @@ const AgentChat = () => { ]); }; - // 切换会话 const switchSession = (sessionId) => { setCurrentSessionId(sessionId); loadSessionHistory(sessionId); }; - // 发送消息 const handleSendMessage = async () => { if (!inputValue.trim() || isProcessing) return; @@ -238,14 +223,12 @@ const AgentChat = () => { setIsProcessing(true); try { - // 显示思考状态 addMessage({ type: MessageTypes.AGENT_THINKING, content: '正在分析你的问题...', timestamp: new Date().toISOString(), }); - // 调用后端 API const response = await axios.post('/mcp/agent/chat', { message: userInput, conversation_history: messages @@ -262,17 +245,14 @@ const AgentChat = () => { tools: selectedTools, }); - // 移除思考消息 setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING)); if (response.data.success) { const data = response.data; - if (data.session_id && !currentSessionId) { setCurrentSessionId(data.session_id); } - // 显示执行计划 if (data.plan) { addMessage({ type: MessageTypes.AGENT_PLAN, @@ -282,7 +262,6 @@ const AgentChat = () => { }); } - // 显示执行步骤 if (data.steps && data.steps.length > 0) { addMessage({ type: MessageTypes.AGENT_EXECUTING, @@ -293,10 +272,8 @@ const AgentChat = () => { }); } - // 移除执行中消息 setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_EXECUTING)); - // 显示最终结果 addMessage({ type: MessageTypes.AGENT_RESPONSE, content: data.final_answer || data.message || '处理完成', @@ -310,7 +287,6 @@ const AgentChat = () => { } } catch (error) { logger.error('Agent chat error', error); - setMessages((prev) => prev.filter( (m) => m.type !== MessageTypes.AGENT_THINKING && m.type !== MessageTypes.AGENT_EXECUTING @@ -318,7 +294,6 @@ const AgentChat = () => { ); const errorMessage = error.response?.data?.error || error.message || '处理失败'; - addMessage({ type: MessageTypes.ERROR, content: `处理失败:${errorMessage}`, @@ -338,12 +313,10 @@ const AgentChat = () => { } }; - // 添加消息 const addMessage = (message) => { setMessages((prev) => [...prev, { ...message, id: Date.now() + Math.random() }]); }; - // 自动滚动到底部 const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; @@ -352,7 +325,6 @@ const AgentChat = () => { scrollToBottom(); }, [messages]); - // 处理键盘事件 const handleKeyPress = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); @@ -360,7 +332,6 @@ const AgentChat = () => { } }; - // 初始化 useEffect(() => { if (user) { loadSessions(); @@ -368,13 +339,11 @@ const AgentChat = () => { } }, [user]); - // 筛选会话 const filteredSessions = sessions.filter( (session) => !searchQuery || session.last_message?.toLowerCase().includes(searchQuery.toLowerCase()) ); - // 快捷问题 const quickQuestions = [ { text: '全面分析贵州茅台', emoji: '📊' }, { text: '今日涨停股票分析', emoji: '🔥' }, @@ -384,138 +353,116 @@ const AgentChat = () => { return (
- {/* 左侧栏 - 历史记录 */} - - {isLeftSidebarOpen && ( - - {/* 侧边栏头部 */} -
-
-
- -

对话历史

-
- + {/* 左侧栏 */} + {isLeftSidebarOpen && ( +
+
+
+
+ +

对话历史

- - - setSearchQuery(e.target.value)} - startContent={} + isIconOnly size="sm" - variant="bordered" - /> + variant="light" + onPress={() => setIsLeftSidebarOpen(false)} + > + +
- {/* 会话列表 */} - - {isLoadingSessions ? ( -
- -
- ) : filteredSessions.length === 0 ? ( -
- -

{searchQuery ? '没有找到匹配的对话' : '暂无对话记录'}

-
- ) : ( -
- {filteredSessions.map((session, index) => ( - - switchSession(session.session_id)} - className={`${ - currentSessionId === session.session_id - ? 'bg-primary-50 dark:bg-primary-900/20 border-primary-500' - : '' - }`} - > - -
-
-

- {session.last_message || '新对话'} -

-
- - - {new Date(session.last_timestamp).toLocaleDateString('zh-CN', { - month: 'numeric', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - })} - - - {session.message_count} - -
-
- -
-
-
-
- ))} -
- )} -
+ - {/* 用户信息 */} -
-
- -
-

{user?.nickname || '未登录'}

-

{user?.id || 'anonymous'}

-
+ setSearchQuery(e.target.value)} + startContent={} + size="sm" + variant="bordered" + /> +
+ + + {isLoadingSessions ? ( +
+ +
+ ) : filteredSessions.length === 0 ? ( +
+ +

{searchQuery ? '没有找到匹配的对话' : '暂无对话记录'}

+
+ ) : ( +
+ {filteredSessions.map((session) => ( + switchSession(session.session_id)} + className={`transition-all ${ + currentSessionId === session.session_id + ? 'bg-primary-50 dark:bg-primary-900/20 border-primary-500' + : '' + }`} + > + +
+
+

+ {session.last_message || '新对话'} +

+
+ + + {new Date(session.last_timestamp).toLocaleDateString('zh-CN', { + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + })} + + + {session.message_count} + +
+
+ +
+
+
+ ))} +
+ )} +
+ +
+
+ +
+

{user?.nickname || '未登录'}

+

{user?.id || 'anonymous'}

- - )} - +
+
+ )} {/* 中间主聊天区域 */}
- {/* 聊天头部 */} - +
{!isLeftSidebarOpen && ( @@ -529,17 +476,12 @@ const AgentChat = () => { )} - - } - classNames={{ - base: 'bg-gradient-to-br from-purple-500 to-pink-500', - }} - /> - + } + classNames={{ + base: 'bg-gradient-to-br from-purple-500 to-pink-500 animate-spin-slow', + }} + />

@@ -579,35 +521,21 @@ const AgentChat = () => { )}

- +
- {/* 消息列表 */}
- - {messages.map((message, index) => ( - - - - ))} - + {messages.map((message) => ( +
+ +
+ ))}
- {/* 快捷问题 */} {messages.length <= 2 && !isProcessing && ( - +

@@ -615,32 +543,26 @@ const AgentChat = () => {

{quickQuestions.map((question, idx) => ( - - - + ))}
- +
)} - {/* 输入框 */} - +
{ variant="bordered" classNames={{ input: 'text-base', - inputWrapper: 'border-2 hover:border-primary-500', + inputWrapper: 'border-2 hover:border-primary-500 transition-colors', }} /> - - - +
- {/* 键盘提示 */}
Enter @@ -687,134 +606,185 @@ const AgentChat = () => {
- +
- {/* 右侧栏 - 模型和工具配置 */} - - {isRightSidebarOpen && ( - - {/* 侧边栏头部 */} -
-
-
- -

配置中心

-
- + {/* 右侧栏 */} + {isRightSidebarOpen && ( +
+
+
+
+ +

配置中心

+
+
- {/* 配置面板 */} - - - -
- {AVAILABLE_MODELS.map((model) => ( - - setSelectedModel(model.id)} - className={`${ - selectedModel === model.id - ? 'border-2 border-' + model.color + '-500 bg-' + model.color + '-50' - : 'border-2 border-transparent' - }`} - > - -
-
-
{model.icon}
-
-

{model.name}

-

{model.description}

-
-
- {selectedModel === model.id && ( - - )} + + + +
+ {AVAILABLE_MODELS.map((model) => ( + setSelectedModel(model.id)} + className={`hover:scale-102 transition-transform ${ + selectedModel === model.id + ? 'border-2 border-' + model.color + '-500 bg-' + model.color + '-50' + : 'border-2 border-transparent' + }`} + > + +
+
+
{model.icon}
+
+

{model.name}

+

{model.description}

- - - - ))} -
- +
+ {selectedModel === model.id && ( + + )} +
+ + + ))} +
+ - -
-

选择 AI 可以使用的工具

- -
- {AVAILABLE_TOOLS.map((tool) => ( - - -
- {tool.icon} - {tool.name} -
-
-
- ))} -
-
-
-
+ +
+

选择 AI 可以使用的工具

+ +
+ {AVAILABLE_TOOLS.map((tool) => ( + +
+ {tool.icon} + {tool.name} +
+
+ ))} +
+
+
+
- - - -
- 历史会话 - - {sessions.length} - -
- -
- 当前消息 - - {messages.length} - -
- -
- 启用工具 - - {selectedTools.length} - -
-
-
-
- - -
- )} - + + + +
+ 历史会话 + + {sessions.length} + +
+ +
+ 当前消息 + + {messages.length} + +
+ +
+ 启用工具 + + {selectedTools.length} + +
+
+
+
+ + +
+ )} + +
); }; /** - * 消息渲染器组件 + * 消息渲染器 */ const MessageRenderer = ({ message, userAvatar }) => { switch (message.type) { @@ -822,13 +792,11 @@ const MessageRenderer = ({ message, userAvatar }) => { return (
- - - -

{message.content}

-
-
-
+ + +

{message.content}

+
+
} size="sm" />
@@ -840,26 +808,19 @@ const MessageRenderer = ({ message, userAvatar }) => {
} - classNames={{ - base: 'bg-gradient-to-br from-purple-500 to-pink-500', - }} + classNames={{ base: 'bg-gradient-to-br from-purple-500 to-pink-500' }} size="sm" /> - - - -
- -

- {message.content} -

-
-
-
-
+ + +
+ +

+ {message.content} +

+
+
+
); @@ -870,57 +831,50 @@ const MessageRenderer = ({ message, userAvatar }) => {
} - classNames={{ - base: 'bg-gradient-to-br from-blue-500 to-purple-500', - }} + classNames={{ base: 'bg-gradient-to-br from-blue-500 to-purple-500' }} size="sm" />
- - - -

{message.content}

+ + +

{message.content}

- {/* 操作按钮 */} -
- - - - - - - - - +
+ + + + + + + + + - {/* 元数据 */} - {message.metadata && ( -
- 步骤: {message.metadata.total_steps} - ✓ {message.metadata.successful_steps} - {message.metadata.failed_steps > 0 && ( - ✗ {message.metadata.failed_steps} - )} - ⏱ {message.metadata.total_execution_time?.toFixed(1)}s -
- )} -
- - - + {message.metadata && ( +
+ 步骤: {message.metadata.total_steps} + ✓ {message.metadata.successful_steps} + {message.metadata.failed_steps > 0 && ( + ✗ {message.metadata.failed_steps} + )} + ⏱ {message.metadata.total_execution_time?.toFixed(1)}s +
+ )} +
+
+
- {/* 执行步骤(可展开) */} {message.stepResults && message.stepResults.length > 0 && ( )} @@ -938,16 +892,11 @@ const MessageRenderer = ({ message, userAvatar }) => { classNames={{ base: 'bg-danger-500' }} size="sm" /> - - - -

{message.content}

-
-
-
+ + +

{message.content}

+
+
); @@ -958,7 +907,7 @@ const MessageRenderer = ({ message, userAvatar }) => { }; /** - * 步骤结果面板组件 + * 步骤结果面板 */ const StepResultsPanel = ({ stepResults }) => { return ( @@ -975,49 +924,41 @@ const StepResultsPanel = ({ stepResults }) => { >
{stepResults.map((result, idx) => ( - - - -
-
-

- 步骤 {idx + 1}: {result.tool} -

- - {result.status} - -
-

{result.execution_time?.toFixed(2)}s

+ +
+
+

+ 步骤 {idx + 1}: {result.tool} +

+ + {result.status} +
- {result.error && ( -

⚠️ {result.error}

- )} - - - +

{result.execution_time?.toFixed(2)}s

+
+ {result.error &&

⚠️ {result.error}

} +
+ ))}