import React, { useState, useEffect } from 'react'; import { useParams, useLocation } from 'react-router-dom'; import { Box, Container, VStack, HStack, Spinner, Alert, AlertIcon, AlertTitle, AlertDescription, Flex, useColorModeValue, Grid, GridItem, Icon, Text, Badge, Divider, useDisclosure, Button, Heading, Stat, StatLabel, StatNumber, StatHelpText, SimpleGrid, Tabs, TabList, TabPanels, Tab, TabPanel, Textarea, Avatar, IconButton, Input, Collapse, Center, useToast, Skeleton, Link, } from '@chakra-ui/react'; import { FiLock } from 'react-icons/fi'; import { FiTrendingUp, FiActivity, FiMessageSquare, FiClock, FiBarChart2, FiLink, FiZap, FiGlobe, FiHeart, FiTrash2, FiChevronDown, FiChevronUp, } from 'react-icons/fi'; import { FaHeart, FaRegHeart, FaComment } from 'react-icons/fa'; import { format } from 'date-fns'; import { zhCN } from 'date-fns/locale'; // 导入新建的业务组件 import EventHeader from './components/EventHeader'; import RelatedConcepts from './components/RelatedConcepts'; import HistoricalEvents from './components/HistoricalEvents'; import RelatedStocks from './components/RelatedStocks'; import HomeNavbar from '../../components/Navbars/HomeNavbar'; import SubscriptionUpgradeModal from '../../components/SubscriptionUpgradeModal'; import { useAuth } from '../../contexts/AuthContext'; import { useSubscription } from '../../hooks/useSubscription'; import TransmissionChainAnalysis from './components/TransmissionChainAnalysis'; // 导入你的 Flask API 服务 import { eventService } from '../../services/eventService'; import { debugEventService } from '../../utils/debugEventService'; // 临时调试代码 - 生产环境测试后请删除 if (typeof window !== 'undefined') { console.log('EventDetail - 调试 eventService'); debugEventService(); } // 统计卡片组件 - 更简洁的设计 const StatCard = ({ icon, label, value, color }) => { const bg = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.700'); const iconColor = useColorModeValue(`${color}.500`, `${color}.300`); return ( {label} {value} ); }; // 帖子组件 const PostItem = ({ post, onRefresh }) => { const [showComments, setShowComments] = useState(false); const [comments, setComments] = useState([]); const [newComment, setNewComment] = useState(''); const [isLoading, setIsLoading] = useState(false); const [liked, setLiked] = useState(post.liked || false); const [likesCount, setLikesCount] = useState(post.likes_count || 0); const toast = useToast(); const { user } = useAuth(); const bg = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.700'); const loadComments = async () => { if (!showComments) { setShowComments(true); setIsLoading(true); try { const result = await eventService.getPostComments(post.id); if (result.success) { setComments(result.data); } } catch (error) { console.error('Failed to load comments:', error); } finally { setIsLoading(false); } } else { setShowComments(false); } }; const handleLike = async () => { try { const result = await eventService.likePost(post.id); if (result.success) { setLiked(result.liked); setLikesCount(result.likes_count); } } catch (error) { toast({ title: '操作失败', status: 'error', duration: 2000, }); } }; const handleAddComment = async () => { if (!newComment.trim()) return; try { const result = await eventService.addPostComment(post.id, { content: newComment, }); if (result.success) { toast({ title: '评论发表成功', status: 'success', duration: 2000, }); setNewComment(''); // 重新加载评论 const commentsResult = await eventService.getPostComments(post.id); if (commentsResult.success) { setComments(commentsResult.data); } } } catch (error) { toast({ title: '评论失败', status: 'error', duration: 2000, }); } }; const handleDelete = async () => { if (window.confirm('确定要删除这个帖子吗?')) { try { const result = await eventService.deletePost(post.id); if (result.success) { toast({ title: '删除成功', status: 'success', duration: 2000, }); onRefresh(); } } catch (error) { toast({ title: '删除失败', status: 'error', duration: 2000, }); } } }; return ( {/* 帖子头部 */} {post.user?.username || '匿名用户'} {format(new Date(post.created_at), 'yyyy-MM-dd HH:mm', { locale: zhCN })} } variant="ghost" size="sm" onClick={handleDelete} /> {/* 帖子内容 */} {post.title && ( {post.title} )} {post.content} {/* 操作栏 */} {/* 评论区 */} {/* 评论输入 */}