update pay ui

This commit is contained in:
2025-12-10 17:18:58 +08:00
parent beb349ac2f
commit 85c29483dd
25 changed files with 133 additions and 10246 deletions

View File

@@ -23,11 +23,17 @@ import {
Th,
Td,
TableContainer,
Popover,
PopoverTrigger,
PopoverContent,
PopoverBody,
Portal,
} from '@chakra-ui/react';
import { FaArrowUp, FaArrowDown, FaFire, FaChevronDown, FaChevronRight } from 'react-icons/fa';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import { getAlertTypeLabel, formatScore, getScoreColor } from '../utils/chartHelpers';
import MiniTimelineChart from '@components/Charts/Stock/MiniTimelineChart';
/**
* 紧凑型异动卡片
@@ -38,6 +44,8 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
const hoverBg = useColorModeValue('gray.50', '#252525');
const borderColor = useColorModeValue('gray.200', '#333');
const expandedBg = useColorModeValue('purple.50', '#1e1e2e');
const tableBg = useColorModeValue('gray.50', '#151520');
const popoverBg = useColorModeValue('white', '#1a1a1a');
const isUp = alert.alert_type !== 'surge_down';
const typeColor = isUp ? 'red' : 'green';
@@ -175,7 +183,7 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
borderTopWidth="1px"
borderColor={borderColor}
p={3}
bg={useColorModeValue('gray.50', '#151520')}
bg={tableBg}
>
{loadingStocks ? (
<HStack justify="center" py={4}>
@@ -183,62 +191,115 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
<Text fontSize="sm" color="gray.500">加载相关股票...</Text>
</HStack>
) : stocks && stocks.length > 0 ? (
<TableContainer maxH="200px" overflowY="auto">
<Table size="sm" variant="simple">
<Thead position="sticky" top={0} bg={useColorModeValue('gray.50', '#151520')} zIndex={1}>
<Tr>
<Th px={2} py={1} fontSize="xs" color="gray.500">股票</Th>
<Th px={2} py={1} fontSize="xs" color="gray.500" isNumeric>涨跌</Th>
<Th px={2} py={1} fontSize="xs" color="gray.500" maxW="120px">原因</Th>
</Tr>
</Thead>
<Tbody>
{stocks.slice(0, 10).map((stock, idx) => {
const changePct = stock.change_pct;
const hasChange = changePct != null && !isNaN(changePct);
return (
<Tr
key={idx}
cursor="pointer"
_hover={{ bg: hoverBg }}
onClick={(e) => handleStockClick(e, stock.code || stock.stock_code)}
>
<Td px={2} py={1.5}>
<Text fontSize="xs" color="cyan.400" fontWeight="medium">
{stock.name || stock.stock_name || '-'}
</Text>
</Td>
<Td px={2} py={1.5} isNumeric>
<Text
fontSize="xs"
fontWeight="bold"
color={
hasChange && changePct > 0 ? 'red.400' :
hasChange && changePct < 0 ? 'green.400' : 'gray.400'
}
>
{hasChange
? `${changePct > 0 ? '+' : ''}${changePct.toFixed(2)}%`
: '-'
}
</Text>
</Td>
<Td px={2} py={1.5} maxW="120px">
<Text fontSize="xs" color="gray.500" noOfLines={1}>
{stock.reason || '-'}
</Text>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
{stocks.length > 10 && (
<Text fontSize="xs" color="gray.500" textAlign="center" mt={2}>
{stocks.length} 只相关股票显示前 10
</Text>
)}
</TableContainer>
<>
{/* 概念涨跌幅统计 */}
{(() => {
const validStocks = stocks.filter(s => s.change_pct != null && !isNaN(s.change_pct));
if (validStocks.length === 0) return null;
const avgChange = validStocks.reduce((sum, s) => sum + s.change_pct, 0) / validStocks.length;
const upCount = validStocks.filter(s => s.change_pct > 0).length;
const downCount = validStocks.filter(s => s.change_pct < 0).length;
return (
<HStack spacing={4} mb={2} fontSize="xs" color="gray.500">
<HStack>
<Text>概念均涨:</Text>
<Text fontWeight="bold" color={avgChange >= 0 ? 'red.400' : 'green.400'}>
{avgChange >= 0 ? '+' : ''}{avgChange.toFixed(2)}%
</Text>
</HStack>
<HStack spacing={1}>
<Text color="red.400">{upCount}</Text>
<Text>/</Text>
<Text color="green.400">{downCount}</Text>
</HStack>
</HStack>
);
})()}
<TableContainer maxH="200px" overflowY="auto">
<Table size="sm" variant="simple">
<Thead position="sticky" top={0} bg={tableBg} zIndex={1}>
<Tr>
<Th px={2} py={1} fontSize="xs" color="gray.500">股票</Th>
<Th px={2} py={1} fontSize="xs" color="gray.500" isNumeric>涨跌</Th>
<Th px={2} py={1} fontSize="xs" color="gray.500" maxW="120px">原因</Th>
</Tr>
</Thead>
<Tbody>
{stocks.slice(0, 10).map((stock, idx) => {
const changePct = stock.change_pct;
const hasChange = changePct != null && !isNaN(changePct);
const stockCode = stock.code || stock.stock_code;
const stockName = stock.name || stock.stock_name || '-';
return (
<Tr
key={idx}
cursor="pointer"
_hover={{ bg: hoverBg }}
onClick={(e) => handleStockClick(e, stockCode)}
>
<Td px={2} py={1.5}>
<Popover trigger="hover" placement="right" isLazy>
<PopoverTrigger>
<Text
fontSize="xs"
color="cyan.400"
fontWeight="medium"
_hover={{ textDecoration: 'underline' }}
>
{stockName}
</Text>
</PopoverTrigger>
<Portal>
<PopoverContent
w="180px"
h="80px"
bg={popoverBg}
borderColor={borderColor}
boxShadow="lg"
onClick={(e) => e.stopPropagation()}
>
<PopoverBody p={2}>
<Text fontSize="xs" color="gray.500" mb={1}>{stockName} 分时</Text>
<Box h="50px">
<MiniTimelineChart stockCode={stockCode} />
</Box>
</PopoverBody>
</PopoverContent>
</Portal>
</Popover>
</Td>
<Td px={2} py={1.5} isNumeric>
<Text
fontSize="xs"
fontWeight="bold"
color={
hasChange && changePct > 0 ? 'red.400' :
hasChange && changePct < 0 ? 'green.400' : 'gray.400'
}
>
{hasChange
? `${changePct > 0 ? '+' : ''}${changePct.toFixed(2)}%`
: '-'
}
</Text>
</Td>
<Td px={2} py={1.5} maxW="120px">
<Text fontSize="xs" color="gray.500" noOfLines={1}>
{stock.reason || '-'}
</Text>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
{stocks.length > 10 && (
<Text fontSize="xs" color="gray.500" textAlign="center" mt={2}>
{stocks.length} 只相关股票显示前 10
</Text>
)}
</TableContainer>
</>
) : (
<Text fontSize="sm" color="gray.500" textAlign="center" py={2}>
暂无相关股票数据

View File

@@ -843,8 +843,22 @@ const StockOverview = () => {
</Box>
{/* 热点概览 - 大盘走势 + 概念异动 */}
{/* 只在 selectedDate 确定后渲染,避免 null → 日期 的双重请求 */}
<Box mb={10}>
<HotspotOverview selectedDate={selectedDate} />
{selectedDate ? (
<HotspotOverview selectedDate={selectedDate} />
) : (
<Card bg={cardBg} borderWidth="1px" borderColor={borderColor}>
<CardBody>
<Center h="400px">
<VStack spacing={4}>
<Spinner size="xl" color="purple.500" thickness="4px" />
<Text color={subTextColor}>加载热点概览数据...</Text>
</VStack>
</Center>
</CardBody>
</Card>
)}
</Box>
{/* 灵活屏 - 实时行情监控 */}