update ui
This commit is contained in:
@@ -2,6 +2,28 @@
|
||||
// 顶部说明面板组件:产品功能介绍 + 沪深指数折线图 + 热门概念词云图
|
||||
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
|
||||
// 定义 pulse 动画
|
||||
const pulseAnimation = `
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.6;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// 注入样式到页面
|
||||
if (typeof document !== 'undefined') {
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.type = 'text/css';
|
||||
styleSheet.innerText = pulseAnimation;
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
@@ -103,8 +125,9 @@ const MiniIndexChart = ({ indexCode, indexName }) => {
|
||||
const [currentDate, setCurrentDate] = useState('');
|
||||
|
||||
const chartBg = useColorModeValue('transparent', 'transparent');
|
||||
const upColor = '#00da3c';
|
||||
const downColor = '#ec0000';
|
||||
// 中国市场惯例:涨红跌绿
|
||||
const upColor = '#ec0000'; // 上涨:红色
|
||||
const downColor = '#00da3c'; // 下跌:绿色
|
||||
|
||||
// 加载日线数据
|
||||
const loadDailyData = useCallback(async () => {
|
||||
@@ -260,21 +283,21 @@ const MiniIndexChart = ({ indexCode, indexName }) => {
|
||||
const changePct = prevClose ? ((change / prevClose) * 100).toFixed(2) : '0.00';
|
||||
const isUp = close >= prevClose;
|
||||
|
||||
// Bloomberg 风格格式化
|
||||
const changeColor = isUp ? '#00da3c' : '#ec0000';
|
||||
// Bloomberg 风格格式化(涨红跌绿)
|
||||
const changeColor = isUp ? '#ec0000' : '#00da3c';
|
||||
const changeSign = isUp ? '+' : '';
|
||||
|
||||
return `
|
||||
<div style="font-weight: bold; border-bottom: 1px solid #FFD700; padding-bottom: 4px; margin-bottom: 6px;">
|
||||
${rawDataItem.time}
|
||||
<div style="font-weight: bold; border-bottom: 1px solid #FFD700; padding-bottom: 6px; margin-bottom: 8px; font-size: 12px;">
|
||||
📅 ${rawDataItem.time}
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; line-height: 1.6;">
|
||||
<span style="color: #aaa;">开盘</span><span style="font-weight: bold;">${open.toFixed(2)}</span>
|
||||
<span style="color: #aaa;">最高</span><span style="font-weight: bold; color: #00da3c;">${high.toFixed(2)}</span>
|
||||
<span style="color: #aaa;">最低</span><span style="font-weight: bold; color: #ec0000;">${low.toFixed(2)}</span>
|
||||
<span style="color: #aaa;">收盘</span><span style="font-weight: bold;">${close.toFixed(2)}</span>
|
||||
<span style="color: #aaa;">涨跌</span><span style="font-weight: bold; color: ${changeColor};">${changeSign}${change.toFixed(2)}</span>
|
||||
<span style="color: #aaa;">涨跌幅</span><span style="font-weight: bold; color: ${changeColor};">${changeSign}${changePct}%</span>
|
||||
<div style="display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; line-height: 1.8;">
|
||||
<span style="color: #999;">开盘</span><span style="font-weight: bold; font-size: 13px;">${open.toFixed(2)}</span>
|
||||
<span style="color: #999;">最高</span><span style="font-weight: bold; font-size: 13px; color: #ec0000;">${high.toFixed(2)}</span>
|
||||
<span style="color: #999;">最低</span><span style="font-weight: bold; font-size: 13px; color: #00da3c;">${low.toFixed(2)}</span>
|
||||
<span style="color: #999;">收盘</span><span style="font-weight: bold; font-size: 13px;">${close.toFixed(2)}</span>
|
||||
<span style="color: #999;">涨跌</span><span style="font-weight: bold; font-size: 13px; color: ${changeColor};">${changeSign}${change.toFixed(2)}</span>
|
||||
<span style="color: #999;">涨跌幅</span><span style="font-weight: bold; font-size: 14px; color: ${changeColor};">${changeSign}${changePct}%</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -315,30 +338,46 @@ const MiniIndexChart = ({ indexCode, indexName }) => {
|
||||
<VStack spacing={2} align="stretch" h="140px">
|
||||
<HStack justify="space-between">
|
||||
<VStack align="start" spacing={0}>
|
||||
<Text fontSize="xs" color="whiteAlpha.700">{indexName}</Text>
|
||||
<Text fontSize="lg" fontWeight="bold" color="white">
|
||||
<Text fontSize="xs" color="whiteAlpha.700" fontWeight="medium">{indexName}</Text>
|
||||
<Text
|
||||
fontSize="2xl"
|
||||
fontWeight="extrabold"
|
||||
color="white"
|
||||
textShadow="0 2px 4px rgba(0,0,0,0.3)"
|
||||
>
|
||||
{latestData?.close.toFixed(2)}
|
||||
</Text>
|
||||
<Text fontSize="xs" color="whiteAlpha.500">
|
||||
{currentDate}
|
||||
📅 {currentDate}
|
||||
</Text>
|
||||
</VStack>
|
||||
<VStack align="end" spacing={0}>
|
||||
<VStack align="end" spacing={1}>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
fontWeight="bold"
|
||||
color={latestData?.isPositive ? 'green.300' : 'red.300'}
|
||||
fontSize="lg"
|
||||
fontWeight="extrabold"
|
||||
color={latestData?.isPositive ? '#ec0000' : '#00da3c'}
|
||||
textShadow={latestData?.isPositive ? '0 2px 8px rgba(236, 0, 0, 0.4)' : '0 2px 8px rgba(0, 218, 60, 0.4)'}
|
||||
>
|
||||
{latestData?.isPositive ? '↑' : '↓'} {latestData?.isPositive ? '+' : ''}{latestData?.change}%
|
||||
{latestData?.isPositive ? '↗' : '↘'} {latestData?.isPositive ? '+' : ''}{latestData?.change}%
|
||||
</Text>
|
||||
{isInTradingTime() && (
|
||||
<Text fontSize="xs" color="green.400">
|
||||
● 实时更新
|
||||
</Text>
|
||||
<HStack spacing={1}>
|
||||
<Box
|
||||
w="6px"
|
||||
h="6px"
|
||||
borderRadius="full"
|
||||
bg="green.400"
|
||||
animation="pulse 2s infinite"
|
||||
boxShadow="0 0 6px rgba(72, 187, 120, 0.8)"
|
||||
/>
|
||||
<Text fontSize="xs" color="green.400" fontWeight="medium">
|
||||
实时更新
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</VStack>
|
||||
</HStack>
|
||||
<Box flex="1">
|
||||
<Box flex="1" position="relative">
|
||||
<ReactECharts
|
||||
option={chartOption}
|
||||
style={{ height: '90px', width: '100%' }}
|
||||
@@ -405,9 +444,14 @@ const ConceptWordCloud = () => {
|
||||
const changePct = params.data.change_pct;
|
||||
const sign = changePct > 0 ? '+' : '';
|
||||
const color = changePct > 0 ? '#ec0000' : '#00da3c';
|
||||
const icon = changePct > 0 ? '📈' : '📉';
|
||||
return `
|
||||
<div style="font-weight: bold; margin-bottom: 4px;">${params.name}</div>
|
||||
<div style="color: ${color}; font-weight: bold;">涨跌幅: ${sign}${changePct.toFixed(2)}%</div>
|
||||
<div style="font-weight: bold; font-size: 14px; margin-bottom: 6px; border-bottom: 1px solid #FFD700; padding-bottom: 4px;">
|
||||
${icon} ${params.name}
|
||||
</div>
|
||||
<div style="color: ${color}; font-weight: bold; font-size: 16px;">
|
||||
涨跌幅: ${sign}${changePct.toFixed(2)}%
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
},
|
||||
@@ -432,23 +476,30 @@ const ConceptWordCloud = () => {
|
||||
color: function (params) {
|
||||
// 根据涨跌幅设置颜色(中国市场惯例:涨红跌绿)
|
||||
const changePct = params.data.change_pct;
|
||||
if (changePct > 7) return '#ff0000'; // 超大涨:纯红
|
||||
if (changePct > 5) return '#ff1744'; // 大涨:亮红色
|
||||
if (changePct > 3) return '#ff4d4f'; // 中涨:红色
|
||||
if (changePct > 1) return '#ff7875'; // 小涨:浅红
|
||||
if (changePct > 0) return '#ffa940'; // 微涨:橙色
|
||||
if (changePct === 0) return '#FFD700'; // 平盘:金色
|
||||
if (changePct > -1) return '#95de64'; // 微跌:浅绿
|
||||
if (changePct > -1) return '#73d13d'; // 微跌:浅绿
|
||||
if (changePct > -3) return '#52c41a'; // 小跌:绿色
|
||||
if (changePct > -5) return '#00c853'; // 中跌:深绿
|
||||
return '#00796b'; // 大跌:墨绿
|
||||
}
|
||||
if (changePct > -7) return '#00a152'; // 大跌:更深绿
|
||||
return '#00796b'; // 超大跌:墨绿
|
||||
},
|
||||
shadowBlur: 3,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
shadowOffsetX: 1,
|
||||
shadowOffsetY: 1
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'self',
|
||||
textStyle: {
|
||||
shadowBlur: 12,
|
||||
shadowBlur: 20,
|
||||
shadowColor: '#FFD700',
|
||||
fontSize: 24
|
||||
fontSize: 28,
|
||||
fontWeight: 'bolder'
|
||||
}
|
||||
},
|
||||
data: concepts
|
||||
@@ -525,21 +576,49 @@ const HeroPanel = () => {
|
||||
bg={gradientBg}
|
||||
borderColor={borderColor}
|
||||
borderWidth={cardBorder}
|
||||
boxShadow="0 8px 32px rgba(0, 0, 0, 0.4)"
|
||||
boxShadow="0 12px 48px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 215, 0, 0.1) inset"
|
||||
mb={6}
|
||||
overflow="hidden"
|
||||
position="relative"
|
||||
transition="all 0.3s ease"
|
||||
_hover={{
|
||||
boxShadow: "0 16px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 215, 0, 0.2) inset",
|
||||
transform: "translateY(-2px)"
|
||||
}}
|
||||
>
|
||||
{/* 装饰性背景图案 */}
|
||||
{/* 装饰性背景图案 - 多层叠加 */}
|
||||
<Box
|
||||
position="absolute"
|
||||
top="-20%"
|
||||
right="-10%"
|
||||
width="500px"
|
||||
height="500px"
|
||||
top="-30%"
|
||||
right="-15%"
|
||||
width="600px"
|
||||
height="600px"
|
||||
borderRadius="full"
|
||||
bg="radial-gradient(circle, rgba(255, 215, 0, 0.1) 0%, transparent 70%)"
|
||||
bg="radial-gradient(circle, rgba(255, 215, 0, 0.15) 0%, rgba(255, 165, 0, 0.08) 40%, transparent 70%)"
|
||||
pointerEvents="none"
|
||||
filter="blur(40px)"
|
||||
/>
|
||||
<Box
|
||||
position="absolute"
|
||||
bottom="-20%"
|
||||
left="-10%"
|
||||
width="400px"
|
||||
height="400px"
|
||||
borderRadius="full"
|
||||
bg="radial-gradient(circle, rgba(236, 0, 0, 0.08) 0%, transparent 60%)"
|
||||
pointerEvents="none"
|
||||
filter="blur(50px)"
|
||||
/>
|
||||
<Box
|
||||
position="absolute"
|
||||
top="50%"
|
||||
left="50%"
|
||||
transform="translate(-50%, -50%)"
|
||||
width="80%"
|
||||
height="80%"
|
||||
bg="radial-gradient(circle, rgba(255, 215, 0, 0.02) 0%, transparent 60%)"
|
||||
pointerEvents="none"
|
||||
filter="blur(60px)"
|
||||
/>
|
||||
|
||||
<CardBody p={6}>
|
||||
@@ -586,7 +665,7 @@ const HeroPanel = () => {
|
||||
</VStack>
|
||||
</Box>
|
||||
|
||||
{/* 中间:沪深指数折线图 */}
|
||||
{/* 中间:沪深指数K线图 */}
|
||||
<Box>
|
||||
<VStack spacing={4} h="100%">
|
||||
<Box
|
||||
@@ -597,6 +676,14 @@ const HeroPanel = () => {
|
||||
borderWidth="1px"
|
||||
borderColor="whiteAlpha.200"
|
||||
backdropFilter="blur(10px)"
|
||||
boxShadow="0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05)"
|
||||
transition="all 0.3s ease"
|
||||
_hover={{
|
||||
bg: "whiteAlpha.150",
|
||||
borderColor: "whiteAlpha.300",
|
||||
boxShadow: "0 6px 24px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
||||
transform: "translateY(-1px)"
|
||||
}}
|
||||
>
|
||||
<MiniIndexChart indexCode="000001" indexName="上证指数" />
|
||||
</Box>
|
||||
@@ -608,6 +695,14 @@ const HeroPanel = () => {
|
||||
borderWidth="1px"
|
||||
borderColor="whiteAlpha.200"
|
||||
backdropFilter="blur(10px)"
|
||||
boxShadow="0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05)"
|
||||
transition="all 0.3s ease"
|
||||
_hover={{
|
||||
bg: "whiteAlpha.150",
|
||||
borderColor: "whiteAlpha.300",
|
||||
boxShadow: "0 6px 24px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
||||
transform: "translateY(-1px)"
|
||||
}}
|
||||
>
|
||||
<MiniIndexChart indexCode="399001" indexName="深证成指" />
|
||||
</Box>
|
||||
@@ -617,13 +712,37 @@ const HeroPanel = () => {
|
||||
{/* 右侧:热门概念词云图 */}
|
||||
<Box>
|
||||
<VStack align="start" spacing={3} h="100%">
|
||||
<HStack>
|
||||
<Text fontSize="md" fontWeight="bold" color="white">
|
||||
🔥 热门概念
|
||||
</Text>
|
||||
<Text fontSize="xs" color="whiteAlpha.600">
|
||||
实时更新
|
||||
</Text>
|
||||
<HStack
|
||||
spacing={2}
|
||||
p={2}
|
||||
borderRadius="md"
|
||||
bg="whiteAlpha.50"
|
||||
w="full"
|
||||
justify="space-between"
|
||||
>
|
||||
<HStack spacing={2}>
|
||||
<Text
|
||||
fontSize="lg"
|
||||
fontWeight="extrabold"
|
||||
bgGradient="linear(to-r, #FFD700, #FFA500, #FF4500)"
|
||||
bgClip="text"
|
||||
>
|
||||
🔥 热门概念
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack spacing={1}>
|
||||
<Box
|
||||
w="6px"
|
||||
h="6px"
|
||||
borderRadius="full"
|
||||
bg="orange.400"
|
||||
animation="pulse 2s infinite"
|
||||
boxShadow="0 0 6px rgba(251, 146, 60, 0.8)"
|
||||
/>
|
||||
<Text fontSize="xs" color="orange.400" fontWeight="medium">
|
||||
实时更新
|
||||
</Text>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<Box
|
||||
w="100%"
|
||||
@@ -633,13 +752,24 @@ const HeroPanel = () => {
|
||||
borderWidth="1px"
|
||||
borderColor="whiteAlpha.200"
|
||||
backdropFilter="blur(10px)"
|
||||
boxShadow="0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05)"
|
||||
p={3}
|
||||
position="relative"
|
||||
overflow="hidden"
|
||||
transition="all 0.3s ease"
|
||||
_hover={{
|
||||
bg: "whiteAlpha.150",
|
||||
borderColor: "whiteAlpha.300",
|
||||
boxShadow: "0 6px 24px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
|
||||
}}
|
||||
>
|
||||
<ConceptWordCloud />
|
||||
</Box>
|
||||
<Text fontSize="xs" color="whiteAlpha.600" textAlign="center" w="100%">
|
||||
字体大小表示热度 · 颜色表示涨跌幅
|
||||
</Text>
|
||||
<HStack spacing={2} fontSize="xs" color="whiteAlpha.600" w="100%" justify="center">
|
||||
<Text>💡 字体大小表示热度</Text>
|
||||
<Text>•</Text>
|
||||
<Text>🎨 颜色表示涨跌幅</Text>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
|
||||
@@ -35,16 +35,34 @@ const HotEventsSection = ({ events, onEventClick }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card mt={0} bg={cardBg}>
|
||||
<CardHeader pb={0} display="flex" justifyContent="space-between" alignItems="flex-start">
|
||||
<Card
|
||||
mt={6}
|
||||
mb={8}
|
||||
bg={cardBg}
|
||||
boxShadow="lg"
|
||||
borderWidth="1px"
|
||||
borderColor={useColorModeValue('gray.200', 'gray.700')}
|
||||
position="relative"
|
||||
zIndex={1}
|
||||
>
|
||||
<CardHeader pb={3} display="flex" justifyContent="space-between" alignItems="flex-start">
|
||||
<Box>
|
||||
<Heading size="md">🔥 热点事件</Heading>
|
||||
<p className="section-subtitle" style={{paddingTop: '8px'}}>展示最近5天内涨幅最高的事件,助您把握市场热点</p>
|
||||
<Heading
|
||||
size="lg"
|
||||
bgGradient="linear(to-r, #FF4500, #FFD700)"
|
||||
bgClip="text"
|
||||
fontWeight="extrabold"
|
||||
>
|
||||
🔥 热点事件
|
||||
</Heading>
|
||||
<p className="section-subtitle" style={{paddingTop: '8px', color: useColorModeValue('#666', '#aaa')}}>
|
||||
展示最近5天内涨幅最高的事件,助您把握市场热点
|
||||
</p>
|
||||
</Box>
|
||||
{/* 页码指示器 */}
|
||||
{totalPages > 1 && (
|
||||
<Badge
|
||||
colorScheme="blue"
|
||||
colorScheme="orange"
|
||||
fontSize="sm"
|
||||
px={3}
|
||||
py={1}
|
||||
@@ -55,7 +73,7 @@ const HotEventsSection = ({ events, onEventClick }) => {
|
||||
</Badge>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardBody py={0} px={4}>
|
||||
<CardBody py={4} px={4}>
|
||||
<HotEvents
|
||||
events={events}
|
||||
onPageChange={handlePageChange}
|
||||
|
||||
Reference in New Issue
Block a user