// src/views/Community/components/DynamicNewsDetail/DynamicNewsDetailPanel.js // 动态新闻详情面板主组件(组装所有子组件) import React, { useState, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Card, CardBody, VStack, Text, Spinner, Center, useColorModeValue, useToast, } from '@chakra-ui/react'; import { getImportanceConfig } from '../../../../constants/importanceLevels'; import { eventService } from '../../../../services/eventService'; import { useEventStocks } from '../StockDetailPanel/hooks/useEventStocks'; import { toggleEventFollow, selectEventFollowStatus } from '../../../../store/slices/communityDataSlice'; import EventHeaderInfo from './EventHeaderInfo'; import EventDescriptionSection from './EventDescriptionSection'; import RelatedConceptsSection from './RelatedConceptsSection'; import RelatedStocksSection from './RelatedStocksSection'; import CollapsibleSection from './CollapsibleSection'; import HistoricalEvents from '../../../EventDetail/components/HistoricalEvents'; import TransmissionChainAnalysis from '../../../EventDetail/components/TransmissionChainAnalysis'; /** * 动态新闻详情面板主组件 * @param {Object} props * @param {Object} props.event - 事件对象(包含详情数据) */ const DynamicNewsDetailPanel = ({ event }) => { const dispatch = useDispatch(); const cardBg = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.700'); const textColor = useColorModeValue('gray.600', 'gray.400'); const toast = useToast(); // 从 Redux 读取关注状态 const eventFollowStatus = useSelector(selectEventFollowStatus); const isFollowing = event?.id ? (eventFollowStatus[event.id]?.isFollowing || false) : false; const followerCount = event?.id ? (eventFollowStatus[event.id]?.followerCount || event.follower_count || 0) : 0; // 使用 Hook 获取实时数据 const { stocks, quotes, eventDetail, historicalEvents, expectationScore, loading } = useEventStocks(event?.id, event?.created_at); // 折叠状态管理 const [isStocksOpen, setIsStocksOpen] = useState(true); const [isHistoricalOpen, setIsHistoricalOpen] = useState(true); const [isTransmissionOpen, setIsTransmissionOpen] = useState(false); // 自选股管理(使用 localStorage) const [watchlistSet, setWatchlistSet] = useState(() => { try { const saved = localStorage.getItem('stock_watchlist'); return saved ? new Set(JSON.parse(saved)) : new Set(); } catch { return new Set(); } }); // 切换关注状态 const handleToggleFollow = useCallback(async () => { if (!event?.id) return; dispatch(toggleEventFollow(event.id)); }, [dispatch, event?.id]); // 切换自选股 const handleWatchlistToggle = useCallback(async (stockCode, isInWatchlist) => { try { const newWatchlist = new Set(watchlistSet); if (isInWatchlist) { newWatchlist.delete(stockCode); toast({ title: '已移除自选股', status: 'info', duration: 2000, isClosable: true, }); } else { newWatchlist.add(stockCode); toast({ title: '已添加至自选股', status: 'success', duration: 2000, isClosable: true, }); } setWatchlistSet(newWatchlist); localStorage.setItem('stock_watchlist', JSON.stringify(Array.from(newWatchlist))); } catch (error) { console.error('切换自选股失败:', error); toast({ title: '操作失败', description: error.message, status: 'error', duration: 3000, isClosable: true, }); } }, [watchlistSet, toast]); // 空状态 if (!event) { return ( 请选择一个事件查看详情 ); } const importance = getImportanceConfig(event.importance); return ( {/* 头部信息区 */} {/* 事件描述 */} {/* 相关概念 */} {/* 相关股票(可折叠) */} {loading.stocks || loading.quotes ? (
加载股票数据中...
) : ( setIsStocksOpen(!isStocksOpen)} onWatchlistToggle={handleWatchlistToggle} /> )} {/* 历史事件对比(可折叠) */} setIsHistoricalOpen(!isHistoricalOpen)} count={historicalEvents?.length || 0} > {loading.historicalEvents ? (
加载历史事件...
) : ( )}
{/* 传导链分析(可折叠) */} setIsTransmissionOpen(!isTransmissionOpen)} >
); }; export default DynamicNewsDetailPanel;