update pay ui
This commit is contained in:
@@ -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}>
|
||||
暂无相关股票数据
|
||||
|
||||
@@ -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>
|
||||
|
||||
{/* 灵活屏 - 实时行情监控 */}
|
||||
|
||||
Reference in New Issue
Block a user