heropanel修改
This commit is contained in:
6
app.py
6
app.py
@@ -11418,10 +11418,10 @@ def get_events_effectiveness_stats():
|
||||
'topEvents': top_events
|
||||
})
|
||||
|
||||
# 找出表现最好的事件(全局)
|
||||
# 找出表现最好的事件(全局,按平均超额排序)
|
||||
top_performers = sorted(
|
||||
[e for e in events_query if e.related_max_chg is not None],
|
||||
key=lambda x: x.related_max_chg,
|
||||
[e for e in events_query if e.related_avg_chg is not None],
|
||||
key=lambda x: x.related_avg_chg,
|
||||
reverse=True
|
||||
)[:10]
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
TrophyOutlined,
|
||||
StockOutlined,
|
||||
CalendarOutlined,
|
||||
ReloadOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { getApiBase } from '@utils/apiConfig';
|
||||
|
||||
@@ -346,8 +347,8 @@ const TopEventItem = ({ event, rank }) => {
|
||||
{event.title}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
<Text fontSize="xs" fontWeight="bold" color={getChgColor(event.maxChg)}>
|
||||
{formatChg(event.maxChg)}
|
||||
<Text fontSize="xs" fontWeight="bold" color={getChgColor(event.avgChg)}>
|
||||
{formatChg(event.avgChg)}
|
||||
</Text>
|
||||
</HStack>
|
||||
);
|
||||
@@ -392,13 +393,18 @@ const TopStockItem = ({ stock, rank }) => {
|
||||
|
||||
const EventDailyStats = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [stats, setStats] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
const [selectedDate, setSelectedDate] = useState('');
|
||||
|
||||
const fetchStats = useCallback(async (dateStr = '') => {
|
||||
setLoading(true);
|
||||
const fetchStats = useCallback(async (dateStr = '', isRefresh = false) => {
|
||||
if (isRefresh) {
|
||||
setRefreshing(true);
|
||||
} else {
|
||||
setLoading(true);
|
||||
}
|
||||
setError(null);
|
||||
try {
|
||||
const apiBase = getApiBase();
|
||||
@@ -416,6 +422,7 @@ const EventDailyStats = () => {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setRefreshing(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -423,10 +430,10 @@ const EventDailyStats = () => {
|
||||
fetchStats(selectedDate);
|
||||
}, [fetchStats, selectedDate]);
|
||||
|
||||
// 自动刷新(仅当选择今天时)
|
||||
// 自动刷新(仅当选择今天时,每60秒刷新一次)
|
||||
useEffect(() => {
|
||||
if (!selectedDate) {
|
||||
const interval = setInterval(() => fetchStats(''), 5 * 60 * 1000);
|
||||
const interval = setInterval(() => fetchStats('', true), 60 * 1000);
|
||||
return () => clearInterval(interval);
|
||||
}
|
||||
}, [selectedDate, fetchStats]);
|
||||
@@ -435,6 +442,13 @@ const EventDailyStats = () => {
|
||||
setSelectedDate(e.target.value);
|
||||
};
|
||||
|
||||
// 手动刷新
|
||||
const handleRefresh = () => {
|
||||
if (!refreshing) {
|
||||
fetchStats(selectedDate, true);
|
||||
}
|
||||
};
|
||||
|
||||
const isToday = !selectedDate;
|
||||
|
||||
if (loading) {
|
||||
@@ -549,6 +563,27 @@ const EventDailyStats = () => {
|
||||
)}
|
||||
</HStack>
|
||||
<HStack spacing={2}>
|
||||
{/* 刷新按钮 */}
|
||||
<Tooltip label="刷新数据" placement="bottom" hasArrow>
|
||||
<Box
|
||||
p={1.5}
|
||||
bg="rgba(255,255,255,0.03)"
|
||||
border="1px solid rgba(255,255,255,0.08)"
|
||||
borderRadius="lg"
|
||||
cursor="pointer"
|
||||
_hover={{ bg: 'rgba(6, 182, 212, 0.15)', borderColor: 'rgba(6, 182, 212, 0.3)', transform: 'scale(1.05)' }}
|
||||
transition="all 0.2s"
|
||||
onClick={handleRefresh}
|
||||
>
|
||||
<ReloadOutlined
|
||||
style={{
|
||||
color: 'rgba(6, 182, 212, 0.8)',
|
||||
fontSize: '14px',
|
||||
}}
|
||||
spin={refreshing}
|
||||
/>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
{/* 今天按钮 - 仅在查看历史时显示 */}
|
||||
{!isToday && (
|
||||
<Box
|
||||
@@ -607,50 +642,59 @@ const EventDailyStats = () => {
|
||||
</HStack>
|
||||
</Flex>
|
||||
|
||||
{/* 内容区域 - 使用 flex: 1 填充剩余空间 */}
|
||||
<VStack spacing={4} align="stretch" flex="1">
|
||||
{/* 胜率对比仪表盘 */}
|
||||
<WinRateGauge
|
||||
eventRate={summary?.positiveRate || 0}
|
||||
marketRate={marketStats?.risingRate || 0}
|
||||
marketStats={marketStats}
|
||||
/>
|
||||
{/* 内容区域 - 固定高度滚动 */}
|
||||
<Box
|
||||
flex="1"
|
||||
overflowY="auto"
|
||||
pr={1}
|
||||
css={{
|
||||
'&::-webkit-scrollbar': { width: '4px' },
|
||||
'&::-webkit-scrollbar-track': { background: 'rgba(255,255,255,0.02)', borderRadius: '2px' },
|
||||
'&::-webkit-scrollbar-thumb': { background: 'rgba(124, 58, 237, 0.3)', borderRadius: '2px' },
|
||||
'&::-webkit-scrollbar-thumb:hover': { background: 'rgba(124, 58, 237, 0.5)' },
|
||||
}}
|
||||
>
|
||||
<VStack spacing={4} align="stretch">
|
||||
{/* 胜率对比仪表盘 */}
|
||||
<WinRateGauge
|
||||
eventRate={summary?.positiveRate || 0}
|
||||
marketRate={marketStats?.risingRate || 0}
|
||||
marketStats={marketStats}
|
||||
/>
|
||||
|
||||
{/* 核心指标 - 2x2 网格 */}
|
||||
<Box display="grid" gridTemplateColumns="repeat(2, 1fr)" gap={2}>
|
||||
<CompactStatCard
|
||||
label="事件数"
|
||||
value={summary?.totalEvents || 0}
|
||||
icon={<FireOutlined />}
|
||||
color="#FFD700"
|
||||
subText="追踪中"
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="关联股票"
|
||||
value={summary?.totalStocks || 0}
|
||||
icon={<StockOutlined />}
|
||||
color="#1890FF"
|
||||
subText="去重"
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="平均超额"
|
||||
value={formatChg(summary?.avgChg)}
|
||||
icon={<RiseOutlined />}
|
||||
color={getChgColor(summary?.avgChg)}
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="最大超额"
|
||||
value={formatChg(summary?.maxChg)}
|
||||
icon={<ThunderboltOutlined />}
|
||||
color="#FF4D4F"
|
||||
/>
|
||||
</Box>
|
||||
{/* 核心指标 - 2x2 网格 */}
|
||||
<Box display="grid" gridTemplateColumns="repeat(2, 1fr)" gap={3}>
|
||||
<CompactStatCard
|
||||
label="事件数"
|
||||
value={summary?.totalEvents || 0}
|
||||
icon={<FireOutlined />}
|
||||
color="#F59E0B"
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="关联股票"
|
||||
value={summary?.totalStocks || 0}
|
||||
icon={<StockOutlined />}
|
||||
color="#06B6D4"
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="平均超额"
|
||||
value={formatChg(summary?.avgChg)}
|
||||
icon={<RiseOutlined />}
|
||||
color={summary?.avgChg >= 0 ? '#F31260' : '#17C964'}
|
||||
/>
|
||||
<CompactStatCard
|
||||
label="最大超额"
|
||||
value={formatChg(summary?.maxChg)}
|
||||
icon={<ThunderboltOutlined />}
|
||||
color="#F31260"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* 分割线 */}
|
||||
<Box h="1px" bg="rgba(255,215,0,0.1)" flexShrink={0} />
|
||||
{/* 分割线 */}
|
||||
<Box h="1px" bg="rgba(255,255,255,0.06)" />
|
||||
|
||||
{/* TOP 表现 - Tab 切换,flex: 1 填充剩余空间 */}
|
||||
<Box flex="1" display="flex" flexDirection="column" minH={0}>
|
||||
{/* TOP 表现 - Tab 切换 */}
|
||||
<Box>
|
||||
<Tabs
|
||||
variant="soft-rounded"
|
||||
colorScheme="yellow"
|
||||
@@ -742,8 +786,9 @@ const EventDailyStats = () => {
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
</VStack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2617,8 +2617,8 @@ const RightPanelTabs = () => {
|
||||
</Box>
|
||||
</HStack>
|
||||
|
||||
{/* Tab 内容区域 - 固定高度确保一致 */}
|
||||
<Box flex="1" minH="650px" p={3} overflow="hidden">
|
||||
{/* Tab 内容区域 */}
|
||||
<Box flex="1" p={3} overflow="hidden">
|
||||
{activeTab === 'comet' ? (
|
||||
<Box h="100%">
|
||||
<ThemeCometChart />
|
||||
@@ -2808,14 +2808,14 @@ const HeroPanel = () => {
|
||||
</Flex>
|
||||
|
||||
{/* AI舆情时空决策驾驶舱 - 左侧今日统计(2/5),右侧Tab切换(3/5) */}
|
||||
<Flex gap={5}>
|
||||
<Flex gap={5} align="stretch" h="720px">
|
||||
{/* 左侧:今日事件统计 */}
|
||||
<Box flex="2" minW="0">
|
||||
<Box flex="2" minW="0" h="100%">
|
||||
<EventDailyStats />
|
||||
</Box>
|
||||
|
||||
{/* 右侧:连板情绪 / 日历 Tab 切换 */}
|
||||
<Box flex="3" minW="0">
|
||||
<Box flex="3" minW="0" h="100%">
|
||||
<RightPanelTabs />
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
Reference in New Issue
Block a user