diff --git a/src/views/AgentChat/index.js.heroui-backup b/src/views/AgentChat/index.js.heroui-backup
deleted file mode 100644
index 468c504c..00000000
--- a/src/views/AgentChat/index.js.heroui-backup
+++ /dev/null
@@ -1,1565 +0,0 @@
-// src/views/AgentChat/index.js
-// 超炫酷的 AI 投研助手 - Hero UI 深色模式版本
-// 使用 Framer Motion 物理动画引擎
-
-import React, { useState, useEffect, useRef } from 'react';
-import { motion, AnimatePresence } from 'framer-motion';
-import {
- Button,
- Card,
- Input,
- Avatar,
- Chip,
- Separator,
- Spinner,
- Tooltip,
- Checkbox,
- CheckboxGroup,
- Kbd,
- Accordion,
-} from '@heroui/react';
-import {
- Tabs,
- TabList,
- TabPanels,
- Tab,
- TabPanel,
- useToast
-} from '@chakra-ui/react';
-import { useAuth } from '@contexts/AuthContext';
-import { logger } from '@utils/logger';
-import axios from 'axios';
-
-// 图标 - 使用 Lucide Icons
-import {
- Send,
- Plus,
- Search,
- MessageSquare,
- Trash2,
- MoreVertical,
- RefreshCw,
- Download,
- Cpu,
- User,
- Zap,
- Clock,
- Settings,
- ChevronLeft,
- ChevronRight,
- Activity,
- Code,
- Database,
- TrendingUp,
- FileText,
- BookOpen,
- Menu,
- X,
- Check,
- Circle,
- Maximize2,
- Minimize2,
- Copy,
- ThumbsUp,
- ThumbsDown,
- Sparkles,
- Brain,
- Rocket,
- Paperclip,
- Image as ImageIcon,
- File,
- Calendar,
- Globe,
- DollarSign,
- Newspaper,
- BarChart3,
- PieChart,
- LineChart,
- Briefcase,
- Users,
-} from 'lucide-react';
-
-/**
- * Framer Motion 动画变体配置
- */
-const animations = {
- slideInLeft: {
- initial: { x: -320, opacity: 0 },
- animate: {
- x: 0,
- opacity: 1,
- transition: {
- type: 'spring',
- stiffness: 300,
- damping: 30,
- },
- },
- exit: {
- x: -320,
- opacity: 0,
- transition: { duration: 0.2 },
- },
- },
- slideInRight: {
- initial: { x: 320, opacity: 0 },
- animate: {
- x: 0,
- opacity: 1,
- transition: {
- type: 'spring',
- stiffness: 300,
- damping: 30,
- },
- },
- exit: {
- x: 320,
- opacity: 0,
- transition: { duration: 0.2 },
- },
- },
- fadeInUp: {
- initial: { opacity: 0, y: 20 },
- animate: {
- opacity: 1,
- y: 0,
- transition: {
- type: 'spring',
- stiffness: 400,
- damping: 25,
- },
- },
- },
- staggerItem: {
- initial: { opacity: 0, y: 10 },
- animate: { opacity: 1, y: 0 },
- },
- staggerContainer: {
- animate: {
- transition: {
- staggerChildren: 0.05,
- },
- },
- },
- pressScale: {
- whileTap: { scale: 0.95 },
- whileHover: { scale: 1.05 },
- },
-};
-
-/**
- * 消息类型
- */
-const MessageTypes = {
- USER: 'user',
- AGENT_THINKING: 'agent_thinking',
- AGENT_PLAN: 'agent_plan',
- AGENT_EXECUTING: 'agent_executing',
- AGENT_RESPONSE: 'agent_response',
- ERROR: 'error',
-};
-
-/**
- * 可用模型配置
- */
-const AVAILABLE_MODELS = [
- {
- id: 'kimi-k2-thinking',
- name: 'Kimi K2 Thinking',
- description: '深度思考模型,适合复杂分析',
- icon: ,
- color: 'secondary',
- },
- {
- id: 'kimi-k2',
- name: 'Kimi K2',
- description: '快速响应模型,适合简单查询',
- icon: ,
- color: 'primary',
- },
- {
- id: 'deepmoney',
- name: 'DeepMoney',
- description: '金融专业模型',
- icon: ,
- color: 'success',
- },
-];
-
-/**
- * MCP 工具配置(完整列表)
- */
-const MCP_TOOLS = [
- // 新闻搜索类
- {
- id: 'search_news',
- name: '全球新闻搜索',
- icon: ,
- category: '新闻资讯',
- description: '搜索全球新闻,支持关键词和日期过滤'
- },
- {
- id: 'search_china_news',
- name: '中国新闻搜索',
- icon: ,
- category: '新闻资讯',
- description: 'KNN语义搜索中国新闻'
- },
- {
- id: 'search_medical_news',
- name: '医疗健康新闻',
- icon: ,
- category: '新闻资讯',
- description: '医药、医疗设备、生物技术新闻'
- },
-
- // 概念板块类
- {
- id: 'search_concepts',
- name: '概念板块搜索',
- icon: ,
- category: '概念板块',
- description: '搜索股票概念板块及相关股票'
- },
- {
- id: 'get_concept_details',
- name: '概念详情',
- icon: ,
- category: '概念板块',
- description: '获取概念板块详细信息'
- },
- {
- id: 'get_stock_concepts',
- name: '股票概念',
- icon: ,
- category: '概念板块',
- description: '查询股票相关概念板块'
- },
- {
- id: 'get_concept_statistics',
- name: '概念统计',
- icon: ,
- category: '概念板块',
- description: '涨幅榜、跌幅榜、活跃榜等'
- },
-
- // 涨停分析类
- {
- id: 'search_limit_up_stocks',
- name: '涨停股票搜索',
- icon: ,
- category: '涨停分析',
- description: '搜索涨停股票,支持多条件筛选'
- },
- {
- id: 'get_daily_stock_analysis',
- name: '涨停日报',
- icon: ,
- category: '涨停分析',
- description: '每日涨停股票分析报告'
- },
-
- // 研报路演类
- {
- id: 'search_research_reports',
- name: '研报搜索',
- icon: ,
- category: '研报路演',
- description: '搜索研究报告,支持语义搜索'
- },
- {
- id: 'search_roadshows',
- name: '路演活动',
- icon: ,
- category: '研报路演',
- description: '上市公司路演、投资者交流活动'
- },
-
- // 股票数据类
- {
- id: 'get_stock_basic_info',
- name: '股票基本信息',
- icon: ,
- category: '股票数据',
- description: '公司名称、行业、主营业务等'
- },
- {
- id: 'get_stock_financial_index',
- name: '财务指标',
- icon: ,
- category: '股票数据',
- description: 'EPS、ROE、营收增长率等'
- },
- {
- id: 'get_stock_trade_data',
- name: '交易数据',
- icon: ,
- category: '股票数据',
- description: '价格、成交量、涨跌幅等'
- },
- {
- id: 'get_stock_balance_sheet',
- name: '资产负债表',
- icon: ,
- category: '股票数据',
- description: '资产、负债、所有者权益'
- },
- {
- id: 'get_stock_cashflow',
- name: '现金流量表',
- icon: ,
- category: '股票数据',
- description: '经营、投资、筹资现金流'
- },
- {
- id: 'search_stocks_by_criteria',
- name: '条件选股',
- icon: ,
- category: '股票数据',
- description: '按行业、地区、市值筛选'
- },
- {
- id: 'get_stock_comparison',
- name: '股票对比',
- icon: ,
- category: '股票数据',
- description: '多只股票财务指标对比'
- },
-
- // 用户数据类
- {
- id: 'get_user_watchlist',
- name: '自选股列表',
- icon: ,
- category: '用户数据',
- description: '用户关注的股票及行情'
- },
- {
- id: 'get_user_following_events',
- name: '关注事件',
- icon: ,
- category: '用户数据',
- description: '用户关注的重大事件'
- },
-];
-
-// 按类别分组工具
-const TOOL_CATEGORIES = {
- '新闻资讯': MCP_TOOLS.filter(t => t.category === '新闻资讯'),
- '概念板块': MCP_TOOLS.filter(t => t.category === '概念板块'),
- '涨停分析': MCP_TOOLS.filter(t => t.category === '涨停分析'),
- '研报路演': MCP_TOOLS.filter(t => t.category === '研报路演'),
- '股票数据': MCP_TOOLS.filter(t => t.category === '股票数据'),
- '用户数据': MCP_TOOLS.filter(t => t.category === '用户数据'),
-};
-
-/**
- * Hero Agent Chat - 主组件(深色模式)
- */
-const AgentChat = () => {
- const { user } = useAuth();
- const toast = useToast();
-
- // 会话管理
- const [sessions, setSessions] = useState([]);
- const [currentSessionId, setCurrentSessionId] = useState(null);
- const [isLoadingSessions, setIsLoadingSessions] = useState(false);
-
- // 消息管理
- const [messages, setMessages] = useState([]);
- const [inputValue, setInputValue] = useState('');
- const [isProcessing, setIsProcessing] = useState(false);
-
- // UI 状态
- const [searchQuery, setSearchQuery] = useState('');
- const [selectedModel, setSelectedModel] = useState('kimi-k2-thinking');
- const [selectedTools, setSelectedTools] = useState([
- 'search_news',
- 'search_china_news',
- 'search_concepts',
- 'search_limit_up_stocks',
- 'search_research_reports',
- ]);
- const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(true);
- const [isRightSidebarOpen, setIsRightSidebarOpen] = useState(true);
-
- // 文件上传
- const [uploadedFiles, setUploadedFiles] = useState([]);
- const fileInputRef = useRef(null);
-
- // Refs
- const messagesEndRef = useRef(null);
- const inputRef = useRef(null);
-
- // ==================== 启用深色模式 ====================
- useEffect(() => {
- // 为 AgentChat 页面强制启用深色模式
- document.documentElement.classList.add('dark');
-
- return () => {
- // 组件卸载时不移除,让其他页面自己控制
- // document.documentElement.classList.remove('dark');
- };
- }, []);
-
- // ==================== 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);
- }
- } catch (error) {
- logger.error('加载会话列表失败', error);
- } finally {
- setIsLoadingSessions(false);
- }
- };
-
- 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) => ({
- id: `${sessionId}-${idx}`,
- type: msg.message_type === 'user' ? MessageTypes.USER : MessageTypes.AGENT_RESPONSE,
- content: msg.message,
- plan: msg.plan ? JSON.parse(msg.plan) : null,
- stepResults: msg.steps ? JSON.parse(msg.steps) : null,
- timestamp: msg.timestamp,
- }));
- setMessages(formattedMessages);
- }
- } catch (error) {
- logger.error('加载会话历史失败', error);
- }
- };
-
- const createNewSession = () => {
- setCurrentSessionId(null);
- setMessages([
- {
- id: Date.now(),
- type: MessageTypes.AGENT_RESPONSE,
- content: `你好${user?.nickname || ''}!👋\n\n我是**价小前**,你的 AI 投研助手。\n\n**我能做什么?**\n• 📊 全面分析股票基本面和技术面\n• 🔥 追踪市场热点和涨停板块\n• 📈 研究行业趋势和投资机会\n• 📰 汇总最新财经新闻和研报\n\n直接输入你的问题开始探索!`,
- timestamp: new Date().toISOString(),
- },
- ]);
- };
-
- const switchSession = (sessionId) => {
- setCurrentSessionId(sessionId);
- loadSessionHistory(sessionId);
- };
-
- const handleSendMessage = async () => {
- if (!inputValue.trim() || isProcessing) return;
-
- const userMessage = {
- type: MessageTypes.USER,
- content: inputValue,
- timestamp: new Date().toISOString(),
- files: uploadedFiles.length > 0 ? uploadedFiles : undefined,
- };
-
- addMessage(userMessage);
- const userInput = inputValue;
- setInputValue('');
- setUploadedFiles([]);
- setIsProcessing(true);
-
- try {
- addMessage({
- type: MessageTypes.AGENT_THINKING,
- content: '正在分析你的问题...',
- timestamp: new Date().toISOString(),
- });
-
- const response = await axios.post('/mcp/agent/chat', {
- message: userInput,
- conversation_history: messages
- .filter((m) => m.type === MessageTypes.USER || m.type === MessageTypes.AGENT_RESPONSE)
- .map((m) => ({
- isUser: m.type === MessageTypes.USER,
- content: m.content,
- })),
- user_id: user?.id || 'anonymous',
- user_nickname: user?.nickname || '匿名用户',
- user_avatar: user?.avatar || '',
- subscription_type: user?.subscription_type || 'free',
- session_id: currentSessionId,
- model: selectedModel,
- tools: selectedTools,
- files: uploadedFiles.length > 0 ? uploadedFiles : undefined,
- });
-
- 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,
- content: '已制定执行计划',
- plan: data.plan,
- timestamp: new Date().toISOString(),
- });
- }
-
- if (data.steps && data.steps.length > 0) {
- addMessage({
- type: MessageTypes.AGENT_EXECUTING,
- content: '正在执行步骤...',
- plan: data.plan,
- stepResults: data.steps,
- timestamp: new Date().toISOString(),
- });
- }
-
- setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_EXECUTING));
-
- addMessage({
- type: MessageTypes.AGENT_RESPONSE,
- content: data.final_answer || data.message || '处理完成',
- plan: data.plan,
- stepResults: data.steps,
- metadata: data.metadata,
- timestamp: new Date().toISOString(),
- });
-
- loadSessions();
- }
- } catch (error) {
- logger.error('Agent chat error', error);
- setMessages((prev) =>
- prev.filter(
- (m) => m.type !== MessageTypes.AGENT_THINKING && m.type !== MessageTypes.AGENT_EXECUTING
- )
- );
-
- const errorMessage = error.response?.data?.error || error.message || '处理失败';
- addMessage({
- type: MessageTypes.ERROR,
- content: `处理失败:${errorMessage}`,
- timestamp: new Date().toISOString(),
- });
-
- toast({
- title: '处理失败',
- description: errorMessage,
- status: 'error',
- duration: 5000,
- });
- } finally {
- setIsProcessing(false);
- }
- };
-
- // 文件上传处理
- const handleFileSelect = (event) => {
- const files = Array.from(event.target.files || []);
- const fileData = files.map(file => ({
- name: file.name,
- size: file.size,
- type: file.type,
- // 实际上传时需要转换为 base64 或上传到服务器
- url: URL.createObjectURL(file),
- }));
- setUploadedFiles(prev => [...prev, ...fileData]);
- };
-
- const removeFile = (index) => {
- setUploadedFiles(prev => prev.filter((_, i) => i !== index));
- };
-
- const addMessage = (message) => {
- setMessages((prev) => [
- ...prev,
- {
- id: Date.now() + Math.random(),
- ...message,
- },
- ]);
- };
-
- const handleKeyPress = (e) => {
- if (e.key === 'Enter' && !e.shiftKey) {
- e.preventDefault();
- handleSendMessage();
- }
- };
-
- useEffect(() => {
- loadSessions();
- createNewSession();
- }, [user]);
-
- useEffect(() => {
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
- }, [messages]);
-
- // ==================== 按日期分组会话 ====================
- const groupSessionsByDate = (sessions) => {
- const today = new Date();
- const yesterday = new Date(today);
- yesterday.setDate(yesterday.getDate() - 1);
- const weekAgo = new Date(today);
- weekAgo.setDate(weekAgo.getDate() - 7);
-
- const groups = {
- today: [],
- yesterday: [],
- thisWeek: [],
- older: [],
- };
-
- sessions.forEach(session => {
- const sessionDate = new Date(session.created_at || session.timestamp);
- const daysDiff = Math.floor((today - sessionDate) / (1000 * 60 * 60 * 24));
-
- if (daysDiff === 0) {
- groups.today.push(session);
- } else if (daysDiff === 1) {
- groups.yesterday.push(session);
- } else if (daysDiff <= 7) {
- groups.thisWeek.push(session);
- } else {
- groups.older.push(session);
- }
- });
-
- return groups;
- };
-
- const sessionGroups = groupSessionsByDate(sessions);
- const filteredSessions = searchQuery
- ? sessions.filter((s) =>
- s.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||
- s.session_id?.toLowerCase().includes(searchQuery.toLowerCase())
- )
- : sessions;
-
- const quickQuestions = [
- { text: '今日涨停板块分析', emoji: '🔥' },
- { text: '新能源概念机会', emoji: '⚡' },
- { text: '半导体行业动态', emoji: '💾' },
- { text: '本周热门研报', emoji: '📊' },
- ];
-
- return (
-
- {/* 左侧栏 - 深色毛玻璃 */}
- {isLeftSidebarOpen && (
-
-
-
-
-
- 对话历史
-
-
-
-
-
-
-
-
-
-
-
-
}
- size="sm"
- variant="bordered"
- classNames={{
- input: 'text-sm text-gray-100',
- inputWrapper: 'border-gray-700 bg-gray-800/50 hover:border-gray-600',
- }}
- />
-
-
-
- {/* 按日期分组显示会话 */}
- {sessionGroups.today.length > 0 && (
-
-
今天
-
- {sessionGroups.today.map((session) => (
- switchSession(session.session_id)}
- />
- ))}
-
-
- )}
-
- {sessionGroups.yesterday.length > 0 && (
-
-
昨天
-
- {sessionGroups.yesterday.map((session) => (
- switchSession(session.session_id)}
- />
- ))}
-
-
- )}
-
- {sessionGroups.thisWeek.length > 0 && (
-
-
本周
-
- {sessionGroups.thisWeek.map((session) => (
- switchSession(session.session_id)}
- />
- ))}
-
-
- )}
-
- {sessionGroups.older.length > 0 && (
-
-
更早
-
- {sessionGroups.older.map((session) => (
- switchSession(session.session_id)}
- />
- ))}
-
-
- )}
-
- {isLoadingSessions && (
-
-
-
- )}
-
- {sessions.length === 0 && !isLoadingSessions && (
-
-
-
还没有对话历史
-
开始一个新对话吧!
-
- )}
-
-
-
-
-
-
-
{user?.nickname || '未登录'}
-
{user?.subscription_type || 'free'} 用户
-
-
-
-
- )}
-
- {/* 中间主聊天区域 */}
-
- {/* 顶部标题栏 - 深色 */}
-
-
-
- {!isLeftSidebarOpen && (
-
- )}
-
-
- }
- classNames={{
- base: 'bg-gradient-to-br from-purple-500 to-pink-500',
- }}
- />
-
-
-
-
- 价小前投研 AI
-
-
- }
- classNames={{
- base: 'bg-green-500/20',
- content: 'text-green-400',
- }}
- >
- 智能分析
-
-
- {AVAILABLE_MODELS.find((m) => m.id === selectedModel)?.name}
-
-
-
-
-
-
-
-
-
- {!isRightSidebarOpen && (
-
- )}
-
-
-
-
- {/* 消息列表 */}
-
-
-
- {messages.map((message, index) => (
-
-
-
- ))}
-
-
-
-
-
- {/* 快捷问题 */}
-
- {messages.length <= 2 && !isProcessing && (
-
-
-
-
- 快速开始
-
-
- {quickQuestions.map((question, idx) => (
-
-
-
- ))}
-
-
-
- )}
-
-
- {/* 输入栏 - 深色 */}
-
-
- {/* 已上传文件预览 */}
- {uploadedFiles.length > 0 && (
-
- {uploadedFiles.map((file, idx) => (
- removeFile(idx)}
- variant="flat"
- classNames={{
- base: 'bg-gray-800 border border-gray-700',
- content: 'text-gray-300',
- }}
- >
- {file.name}
-
- ))}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enter
- 发送
-
-
- Shift
- +
- Enter
- 换行
-
-
-
-
-
-
- {/* 右侧栏 - 深色配置中心 */}
- {isRightSidebarOpen && (
-
-
-
-
-
- 配置中心
-
-
-
-
-
-
-
-
-
- {/* 模型选择 */}
-
-
- 模型
-
- }
- >
-
- {AVAILABLE_MODELS.map((model) => (
-
setSelectedModel(model.id)}
- className={`transition-all ${
- selectedModel === model.id
- ? 'bg-blue-500/20 border-2 border-blue-500'
- : 'bg-gray-800/50 border-2 border-gray-700 hover:border-gray-600'
- }`}
- >
-
-
-
- {model.icon}
-
-
-
{model.name}
-
{model.description}
-
- {selectedModel === model.id && (
-
- )}
-
-
-
- ))}
-
-
-
- {/* 工具选择 - 按分类显示 */}
-
-
- 工具
- {selectedTools.length > 0 && (
-
- {selectedTools.length}
-
- )}
-
- }
- >
-
-
- {Object.entries(TOOL_CATEGORIES).map(([category, tools]) => (
-
- {category}
-
- {tools.filter(t => selectedTools.includes(t.id)).length}/{tools.length}
-
-
- }
- >
-
- {tools.map((tool) => (
-
-
-
{tool.icon}
-
-
{tool.name}
-
{tool.description}
-
-
-
- ))}
-
-
- ))}
-
-
-
-
-
-
-
-
-
- {/* 统计信息 */}
-
-
- 统计
-
- }
- >
-
-
-
-
-
-
对话数
-
{sessions.length}
-
-
-
-
-
-
-
-
-
-
-
消息数
-
{messages.length}
-
-
-
-
-
-
-
-
-
-
-
已选工具
-
{selectedTools.length}
-
-
-
-
-
-
-
-
-
-
- )}
-
- );
-};
-
-export default AgentChat;
-
-/**
- * 会话卡片组件
- */
-const SessionCard = ({ session, isActive, onPress }) => {
- return (
-
-
-
-
-
- {session.title || '新对话'}
-
-
- {new Date(session.created_at || session.timestamp).toLocaleString('zh-CN', {
- month: 'numeric',
- day: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- })}
-
-
- {session.message_count && (
-
- {session.message_count}
-
- )}
-
-
-
- );
-};
-
-/**
- * 消息渲染器
- */
-const MessageRenderer = ({ message, userAvatar }) => {
- switch (message.type) {
- case MessageTypes.USER:
- return (
-
-
-
-
- {message.content}
- {message.files && message.files.length > 0 && (
-
- {message.files.map((file, idx) => (
-
-
- {file.name}
-
- ))}
-
- )}
-
-
-
}
- size="sm"
- classNames={{
- base: 'bg-gradient-to-br from-blue-500 to-purple-600',
- }}
- />
-
-
- );
-
- case MessageTypes.AGENT_THINKING:
- return (
-
-
-
}
- size="sm"
- classNames={{
- base: 'bg-gradient-to-br from-purple-500 to-pink-500',
- }}
- />
-
-
-
- {message.content}
-
-
-
-
- );
-
- case MessageTypes.AGENT_RESPONSE:
- return (
-
-
-
}
- size="sm"
- classNames={{
- base: 'bg-gradient-to-br from-purple-500 to-pink-500',
- }}
- />
-
-
-
- {message.content}
-
-
- {message.stepResults && message.stepResults.length > 0 && (
-
-
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
- {new Date(message.timestamp).toLocaleTimeString('zh-CN', {
- hour: '2-digit',
- minute: '2-digit',
- })}
-
-
-
-
-
-
- );
-
- case MessageTypes.ERROR:
- return (
-
-
-
- {message.content}
-
-
-
- );
-
- default:
- return null;
- }
-};
-
-/**
- * 执行步骤显示组件
- */
-const ExecutionStepsDisplay = ({ steps, plan }) => {
- return (
-
-
-
- 执行详情
-
- {steps.length} 步骤
-
-
- }
- >
-
- {steps.map((result, idx) => (
-
-
-
-
- 步骤 {idx + 1}: {result.tool_name}
-
-
- {result.status}
-
-
- {result.execution_time?.toFixed(2)}s
- {result.error && ⚠️ {result.error}
}
-
-
- ))}
-
-
-
- );
-};
diff --git a/src/views/Concept/index.js b/src/views/Concept/index.js
index 0bd97fe6..4d912700 100644
--- a/src/views/Concept/index.js
+++ b/src/views/Concept/index.js
@@ -693,139 +693,235 @@ const ConceptCenter = () => {
init();
}, []);
- // 概念卡片组件 - 优化版
+ // 概念卡片组件 - 科幻毛玻璃版
const ConceptCard = ({ concept, position = 0 }) => {
const changePercent = concept.price_info?.avg_change_pct;
const changeColor = getChangeColor(changePercent);
const hasChange = changePercent !== null && changePercent !== undefined;
+ // 生成随机涨幅数字背景
+ const generateNumbersBackground = () => {
+ const numbers = [];
+ for (let i = 0; i < 30; i++) {
+ const isPositive = Math.random() > 0.5;
+ const value = (Math.random() * 15).toFixed(2);
+ const sign = isPositive ? '+' : '-';
+ numbers.push(`${sign}${value}%`);
+ }
+ return numbers;
+ };
+
+ const backgroundNumbers = generateNumbersBackground();
+
return (
handleConceptClick(concept.concept_id, concept.concept, concept, position)}
bg="white"
borderWidth="1px"
- borderColor="gray.200"
+ borderColor="transparent"
overflow="hidden"
_hover={{
transform: 'translateY(-8px)',
- boxShadow: 'xl',
- borderColor: 'purple.300',
+ boxShadow: '0 20px 40px rgba(139, 92, 246, 0.3)',
+ borderColor: 'purple.400',
}}
transition="all 0.3s"
position="relative"
+ boxShadow="0 4px 12px rgba(0, 0, 0, 0.1)"
>
+ {/* 毛玻璃涨幅数字背景 */}
-
-
-
- }
- />
+ {/* 渐变背景层 */}
0
+ ? "linear(135deg, #667eea 0%, #764ba2 100%)"
+ : hasChange && changePercent < 0
+ ? "linear(135deg, #f093fb 0%, #f5576c 100%)"
+ : "linear(135deg, #4facfe 0%, #00f2fe 100%)"
+ }
/>
- {hasChange && (
- 5 ? `${pulseAnimation} 2s infinite` : 'none'}
- >
- 0 ? FaArrowUp : changePercent < 0 ? FaArrowDown : null}
- boxSize={3}
- />
- {formatChangePercent(changePercent)}
-
- )}
+ {/* 数字矩阵层 */}
+
+ {backgroundNumbers.map((num, idx) => (
+
+ {num}
+
+ ))}
+
+ {/* 毛玻璃层 */}
+
+
+ {/* 渐变遮罩 */}
+
+
+ {/* 发光边框效果 */}
+
+
+ {/* 右上角股票数量徽章 */}
{concept.stock_count || 0} 只股票
-
-
+
+ {/* 概念名称 */}
+
{concept.concept}
+ {/* 描述信息 */}
{concept.description || '暂无描述信息'}
+ {/* 涨跌幅信息卡片 */}
{hasChange && concept.price_info?.trade_date && (
-
- 交易日期: {new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}
-
-
- {formatChangePercent(changePercent)}
-
-
+ 0
+ ? "linear(to-r, rgba(139, 92, 246, 0.1), rgba(168, 85, 247, 0.05))"
+ : "linear(to-r, rgba(236, 72, 153, 0.1), rgba(251, 113, 133, 0.05))"
+ }
+ border="1px solid"
+ borderColor={changePercent > 0 ? "purple.200" : "pink.200"}
+ >
+
+
+ 0 ? "purple.500" : "pink.500"}
+ />
+
+ {new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}
+
+
+
+ 0 ? FaArrowUp : FaArrowDown}
+ boxSize={3}
+ color={changePercent > 0 ? "red.500" : "green.500"}
+ />
+ 0 ? "red.500" : "green.500"}
+ >
+ {formatChangePercent(changePercent)}
+
+
+
+
)}
{concept.stocks && concept.stocks.length > 0 && (
handleViewStocks(e, concept)}
- _hover={{ bg: 'gray.100' }}
- transition="background 0.2s"
+ _hover={{
+ bg: 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%)',
+ transform: 'translateX(2px)',
+ }}
+ transition="all 0.2s"
+ border="1px solid"
+ borderColor="purple.100"
>
-
-
+
+
+
热门个股
{!hasFeatureAccess('hot_stocks') && (
-
- 🔒需Pro
+
+ 🔒Pro
)}
@@ -833,13 +929,20 @@ const ConceptCenter = () => {
{hasFeatureAccess('hot_stocks') ? (
<>
{concept.stocks.slice(0, 2).map((stock, idx) => (
-
+
{stock.stock_name}
))}
{concept.stocks.length > 2 && (
-
- +{concept.stocks.length - 2}更多
+
+ +{concept.stocks.length - 2}
)}
>
@@ -862,36 +965,41 @@ const ConceptCenter = () => {
)}
-
+
{formatHappenedTimes(concept.happened_times)}
} // 改成时间轴图标
- colorScheme="purple" // 改成紫色主题
+ leftIcon={}
+ bgGradient="linear(to-r, purple.500, pink.500)"
+ color="white"
variant="solid"
- onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)} // 传入concept_id
+ onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
borderRadius="full"
px={4}
fontWeight="medium"
- boxShadow="sm"
- _hover={{ transform: 'scale(1.05)', boxShadow: 'md' }}
+ boxShadow="0 4px 12px rgba(139, 92, 246, 0.3)"
+ _hover={{
+ transform: 'scale(1.05)',
+ boxShadow: '0 6px 16px rgba(139, 92, 246, 0.4)',
+ }}
transition="all 0.2s"
>
- 历史时间轴 {/* 改按钮文字 */}
+ 时间轴
+ {/* 顶部发光条 */}
{
);
- // 日期选择组件
+ // 日期选择组件 - 科幻风格
const DateSelector = () => (
-
-
- 交易日期:
+
+
+
+
+ 交易日期:
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
- {latestTradeDate && (
-
-
-
-
- 最新数据: {latestTradeDate.toLocaleDateString('zh-CN')}
-
-
-
- )}
-
+ {latestTradeDate && (
+
+
+
+
+ 最新: {latestTradeDate.toLocaleDateString('zh-CN')}
+
+
+
+ )}
+
+
);
return (
-
+
{/* 导航栏已由 MainLayout 提供 */}
- {/* Hero Section */}
+ {/* Hero Section - 精简版 */}
+ {/* 科幻网格背景 */}
+ {/* 发光球体 */}
-
-
-
-
-
+
+
+ {/* 标题区域 */}
+
+
+
-
+
概念中心
-
-
- 约下午4点更新
+
+
+ 数据约下午4点更新
-
- 大模型辅助的信息整理与呈现平台
-
-
- 以大模型协助汇聚与清洗多源信息,结合自主训练的领域知识图谱,
-
- 并由资深分析师进行人工整合与校准,提供结构化参考信息
-
+
+
+ AI驱动的概念板块分析平台 · 实时追踪市场热点 · 智能挖掘投资机会
+
-
-
-
- 实时更新
-
- 毫秒级数据同步
-
-
-
-
-
- 智能追踪
-
- 算法智能追踪
-
-
-
-
-
- 深度分析
-
- 多维度数据挖掘
-
-
-
-
-
- 专业可靠
-
- 权威数据源保障
-
-
-
-
- }>
-
- 500+
- 概念板块
-
-
- 5000+
- 相关个股
-
-
- 24/7
- 全天候监控
-
+ {/* 核心数据展示 */}
+ }
+ bg="whiteAlpha.100"
+ backdropFilter="blur(10px)"
+ px={8}
+ py={3}
+ borderRadius="full"
+ border="1px solid"
+ borderColor="whiteAlpha.300"
+ boxShadow="0 8px 32px rgba(0, 0, 0, 0.3)"
+ >
+
+
+
+ 500+
+ 概念板块
+
+
+
+
+
+ 5000+
+ 相关个股
+
+
+
+
+
+ 24/7
+ 实时监控
+
+
+ {/* 搜索框 */}
-
+
@@ -1330,7 +1463,8 @@ const ConceptCenter = () => {
bgGradient="linear(to-r, purple.500, pink.500)"
color="white"
_hover={{
- bgGradient: 'linear(to-r, purple.600, pink.600)'
+ bgGradient: 'linear(to-r, purple.600, pink.600)',
+ boxShadow: '0 0 20px rgba(168, 85, 247, 0.4)'
}}
_active={{
bgGradient: 'linear(to-r, purple.700, pink.700)',
@@ -1349,7 +1483,7 @@ const ConceptCenter = () => {
{searchQuery && sortBy === '_score' && (
-
+
正在搜索 "{searchQuery}",已自动切换到相关度排序
)}
@@ -1370,7 +1504,14 @@ const ConceptCenter = () => {
{/* 左侧概念卡片区域 */}
-
+
{
gap={4}
>
- 排序方式:
+
+ 排序方式:
{searchQuery && sortBy === '_score' && (
-
-
-
+
+
+
智能排序
@@ -1412,10 +1565,13 @@ const ConceptCenter = () => {
setViewMode('grid');
}
}}
- bg={viewMode === 'grid' ? 'purple.500' : 'transparent'}
+ bg={viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
color={viewMode === 'grid' ? 'white' : 'purple.500'}
borderColor="purple.500"
- _hover={{ bg: viewMode === 'grid' ? 'purple.600' : 'purple.50' }}
+ _hover={{
+ bg: viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
+ boxShadow: viewMode === 'grid' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
+ }}
aria-label="网格视图"
/>
{
setViewMode('list');
}
}}
- bg={viewMode === 'list' ? 'purple.500' : 'transparent'}
+ bg={viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
color={viewMode === 'list' ? 'white' : 'purple.500'}
borderColor="purple.500"
- _hover={{ bg: viewMode === 'list' ? 'purple.600' : 'purple.50' }}
+ _hover={{
+ bg: viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
+ boxShadow: viewMode === 'list' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
+ }}
aria-label="列表视图"
/>
@@ -1474,18 +1633,39 @@ const ConceptCenter = () => {
)}
-
+
-
+
{[...Array(Math.min(5, totalPages))].map((_, i) => {
const pageNum = currentPage <= 3 ? i + 1 :
currentPage >= totalPages - 2 ? totalPages - 4 + i :
@@ -1496,8 +1676,16 @@ const ConceptCenter = () => {
key={pageNum}
size="sm"
onClick={() => handlePageChange(pageNum)}
- colorScheme="purple"
- variant={pageNum === currentPage ? 'solid' : 'outline'}
+ bg={pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
+ color={pageNum === currentPage ? 'white' : 'purple.600'}
+ variant={pageNum === currentPage ? 'solid' : 'ghost'}
+ borderRadius="full"
+ minW="40px"
+ fontWeight="bold"
+ _hover={{
+ bg: pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
+ boxShadow: pageNum === currentPage ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
+ }}
>
{pageNum}
@@ -1509,8 +1697,19 @@ const ConceptCenter = () => {
size="sm"
onClick={() => handlePageChange(Math.min(totalPages, currentPage + 1))}
isDisabled={currentPage === totalPages}
- colorScheme="purple"
- variant="outline"
+ bgGradient="linear(to-r, purple.500, pink.500)"
+ color="white"
+ variant="solid"
+ borderRadius="full"
+ _hover={{
+ bgGradient: 'linear(to-r, purple.600, pink.600)',
+ boxShadow: '0 0 15px rgba(139, 92, 246, 0.4)',
+ }}
+ _disabled={{
+ bg: 'gray.200',
+ color: 'gray.400',
+ cursor: 'not-allowed',
+ }}
>
下一页