diff --git a/src/views/Community/components/HeroPanel.js b/src/views/Community/components/HeroPanel.js index 7fd0625a..d3340dae 100644 --- a/src/views/Community/components/HeroPanel.js +++ b/src/views/Community/components/HeroPanel.js @@ -14,11 +14,6 @@ import { useColorModeValue, SimpleGrid, Icon, - Stat, - StatLabel, - StatNumber, - StatHelpText, - StatArrow, Spinner, Center, } from '@chakra-ui/react'; @@ -27,15 +22,20 @@ import ReactECharts from 'echarts-for-react'; import { logger } from '../../../utils/logger'; /** - * 获取指数行情数据 + * 获取指数行情数据(日线数据) */ const fetchIndexKline = async (indexCode) => { try { - const response = await fetch(`/api/index/${indexCode}/kline`); + // 使用日线数据,获取最近60个交易日 + const response = await fetch(`/api/index/${indexCode}/kline?type=daily`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } const data = await response.json(); + logger.debug('HeroPanel', 'fetchIndexKline success', { indexCode, dataLength: data?.data?.length }); return data; } catch (error) { - logger.error('HeroPanel', 'fetchIndexKline', error); + logger.error('HeroPanel', 'fetchIndexKline error', { indexCode, error: error.message }); return null; } }; @@ -86,30 +86,41 @@ const MiniIndexChart = ({ indexCode, indexName }) => { const areaColor = useColorModeValue('rgba(255, 215, 0, 0.15)', 'rgba(255, 215, 0, 0.1)'); useEffect(() => { + let isMounted = true; + const loadData = async () => { setLoading(true); const data = await fetchIndexKline(indexCode); - if (data && data.data && data.data.length > 0) { + if (isMounted && data && data.data && data.data.length > 0) { // 取最近一个交易日的数据 const latest = data.data[data.data.length - 1]; + const prevClose = latest.prev_close || latest.close; + setLatestData({ - close: latest[2], - change: ((latest[2] - latest[1]) / latest[1] * 100).toFixed(2), - isPositive: latest[2] >= latest[1] + close: latest.close, + change: prevClose ? (((latest.close - prevClose) / prevClose) * 100).toFixed(2) : '0.00', + isPositive: latest.close >= prevClose }); // 准备图表数据(最近60个交易日) const recentData = data.data.slice(-60); setChartData({ - dates: recentData.map(item => item[0]), - values: recentData.map(item => item[2]) + dates: recentData.map(item => item.time), + values: recentData.map(item => item.close) }); } - setLoading(false); + + if (isMounted) { + setLoading(false); + } }; loadData(); + + return () => { + isMounted = false; + }; }, [indexCode]); const chartOption = useMemo(() => { @@ -184,13 +195,12 @@ const MiniIndexChart = ({ indexCode, indexName }) => { - - {latestData?.isPositive ? '+' : ''}{latestData?.change}% + {latestData?.isPositive ? '↑' : '↓'} {latestData?.isPositive ? '+' : ''}{latestData?.change}% @@ -215,14 +225,24 @@ const ConceptWordCloud = () => { const chartBg = useColorModeValue('transparent', 'transparent'); useEffect(() => { + let isMounted = true; + const loadConcepts = async () => { setLoading(true); const data = await fetchPopularConcepts(); - setConcepts(data); - setLoading(false); + if (isMounted && data && data.length > 0) { + setConcepts(data); + } + if (isMounted) { + setLoading(false); + } }; loadConcepts(); + + return () => { + isMounted = false; + }; }, []); const chartOption = useMemo(() => { diff --git a/src/views/Community/index.js b/src/views/Community/index.js index 88ad6a92..9ed3d275 100644 --- a/src/views/Community/index.js +++ b/src/views/Community/index.js @@ -120,10 +120,15 @@ const Community = () => { }; // ⚡ 首次进入页面时滚动到内容区域(考虑导航栏高度) + const hasScrolled = useRef(false); useEffect(() => { + // 只在第一次挂载时执行滚动 + if (hasScrolled.current) return; + // 延迟执行,确保DOM已完全渲染 const timer = setTimeout(() => { if (containerRef.current) { + hasScrolled.current = true; // 滚动到容器顶部,自动考虑导航栏的高度 containerRef.current.scrollIntoView({ behavior: 'auto', @@ -131,7 +136,7 @@ const Community = () => { inline: 'nearest' }); } - }, 0); + }, 100); return () => clearTimeout(timer); }, []); // 空依赖数组,只在组件挂载时执行一次