update pay ui
This commit is contained in:
@@ -112,29 +112,29 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
|
||||
{getAlertTypeLabel(alert.alert_type)}
|
||||
</Badge>
|
||||
{/* 确认率 */}
|
||||
{isV2 && alert.confirm_ratio !== undefined && (
|
||||
{isV2 && alert.confirm_ratio != null && (
|
||||
<HStack spacing={1}>
|
||||
<Box w="30px" h="4px" bg="gray.200" borderRadius="full" overflow="hidden">
|
||||
<Box
|
||||
w={`${alert.confirm_ratio * 100}%`}
|
||||
w={`${(alert.confirm_ratio || 0) * 100}%`}
|
||||
h="100%"
|
||||
bg={alert.confirm_ratio >= 0.8 ? 'green.500' : 'orange.500'}
|
||||
bg={(alert.confirm_ratio || 0) >= 0.8 ? 'green.500' : 'orange.500'}
|
||||
/>
|
||||
</Box>
|
||||
<Text>{Math.round(alert.confirm_ratio * 100)}%</Text>
|
||||
<Text>{Math.round((alert.confirm_ratio || 0) * 100)}%</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
{/* Alpha + Z-Score 简化显示 */}
|
||||
<HStack spacing={3}>
|
||||
{alert.alpha !== undefined && (
|
||||
<Text color={alert.alpha >= 0 ? 'red.500' : 'green.500'} fontWeight="medium">
|
||||
α {alert.alpha >= 0 ? '+' : ''}{alert.alpha.toFixed(2)}%
|
||||
{alert.alpha != null && (
|
||||
<Text color={(alert.alpha || 0) >= 0 ? 'red.500' : 'green.500'} fontWeight="medium">
|
||||
α {(alert.alpha || 0) >= 0 ? '+' : ''}{(alert.alpha || 0).toFixed(2)}%
|
||||
</Text>
|
||||
)}
|
||||
{isV2 && alert.alpha_zscore !== undefined && (
|
||||
<Tooltip label={`Alpha Z-Score: ${alert.alpha_zscore.toFixed(2)}σ`}>
|
||||
{isV2 && alert.alpha_zscore != null && (
|
||||
<Tooltip label={`Alpha Z-Score: ${(alert.alpha_zscore || 0).toFixed(2)}σ`}>
|
||||
<HStack spacing={0.5}>
|
||||
<Box
|
||||
w="24px"
|
||||
@@ -146,23 +146,23 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
|
||||
>
|
||||
<Box
|
||||
position="absolute"
|
||||
left={alert.alpha_zscore >= 0 ? '50%' : undefined}
|
||||
right={alert.alpha_zscore < 0 ? '50%' : undefined}
|
||||
w={`${Math.min(Math.abs(alert.alpha_zscore) / 5 * 50, 50)}%`}
|
||||
left={(alert.alpha_zscore || 0) >= 0 ? '50%' : undefined}
|
||||
right={(alert.alpha_zscore || 0) < 0 ? '50%' : undefined}
|
||||
w={`${Math.min(Math.abs(alert.alpha_zscore || 0) / 5 * 50, 50)}%`}
|
||||
h="100%"
|
||||
bg={alert.alpha_zscore >= 0 ? 'red.500' : 'green.500'}
|
||||
bg={(alert.alpha_zscore || 0) >= 0 ? 'red.500' : 'green.500'}
|
||||
/>
|
||||
</Box>
|
||||
<Text color={alert.alpha_zscore >= 0 ? 'red.400' : 'green.400'}>
|
||||
{alert.alpha_zscore >= 0 ? '+' : ''}{alert.alpha_zscore.toFixed(1)}σ
|
||||
<Text color={(alert.alpha_zscore || 0) >= 0 ? 'red.400' : 'green.400'}>
|
||||
{(alert.alpha_zscore || 0) >= 0 ? '+' : ''}{(alert.alpha_zscore || 0).toFixed(1)}σ
|
||||
</Text>
|
||||
</HStack>
|
||||
</Tooltip>
|
||||
)}
|
||||
{alert.limit_up_ratio > 0.05 && (
|
||||
{(alert.limit_up_ratio || 0) > 0.05 && (
|
||||
<HStack spacing={0.5} color="orange.500">
|
||||
<Icon as={FaFire} boxSize={3} />
|
||||
<Text>{Math.round(alert.limit_up_ratio * 100)}%</Text>
|
||||
<Text>{Math.round((alert.limit_up_ratio || 0) * 100)}%</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
@@ -193,40 +193,44 @@ const AlertCard = ({ alert, isExpanded, onToggle, stocks, loadingStocks }) => {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{stocks.slice(0, 10).map((stock, idx) => (
|
||||
<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={
|
||||
stock.change_pct > 0 ? 'red.400' :
|
||||
stock.change_pct < 0 ? 'green.400' : 'gray.400'
|
||||
}
|
||||
>
|
||||
{stock.change_pct !== undefined
|
||||
? `${stock.change_pct > 0 ? '+' : ''}${stock.change_pct.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>
|
||||
))}
|
||||
{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 && (
|
||||
|
||||
@@ -152,8 +152,9 @@ export const formatScore = (score) => {
|
||||
* @returns {string} 颜色代码
|
||||
*/
|
||||
export const getScoreColor = (score) => {
|
||||
if (score >= 80) return '#ff4757';
|
||||
if (score >= 60) return '#ff6348';
|
||||
if (score >= 40) return '#ffa502';
|
||||
const s = score || 0;
|
||||
if (s >= 80) return '#ff4757';
|
||||
if (s >= 60) return '#ff6348';
|
||||
if (s >= 40) return '#ffa502';
|
||||
return '#747d8c';
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user