updated
This commit is contained in:
@@ -33,8 +33,7 @@ import {
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableContainer,
|
||||
Link
|
||||
TableContainer
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
FaExclamationTriangle,
|
||||
@@ -145,47 +144,6 @@ const HistoricalEvents = ({
|
||||
return `${Math.floor(diffDays / 365)}年前`;
|
||||
};
|
||||
|
||||
// 可展开的文本组件
|
||||
const ExpandableText = ({ text, maxLength = 20 }) => {
|
||||
const { isOpen, onToggle } = useDisclosure();
|
||||
const [shouldTruncate, setShouldTruncate] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (text && text.length > maxLength) {
|
||||
setShouldTruncate(true);
|
||||
} else {
|
||||
setShouldTruncate(false);
|
||||
}
|
||||
}, [text, maxLength]);
|
||||
|
||||
if (!text) return <Text fontSize="xs">--</Text>;
|
||||
|
||||
const displayText = shouldTruncate && !isOpen
|
||||
? text.substring(0, maxLength) + '...'
|
||||
: text;
|
||||
|
||||
return (
|
||||
<VStack align="flex-start" spacing={1}>
|
||||
<Text fontSize="xs" noOfLines={isOpen ? undefined : 2} maxW="300px">
|
||||
{displayText}{text.includes('AI合成') ? '' : '(AI合成)'}
|
||||
</Text>
|
||||
{shouldTruncate && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="link"
|
||||
color="blue.500"
|
||||
onClick={onToggle}
|
||||
height="auto"
|
||||
py={0}
|
||||
minH={0}
|
||||
>
|
||||
{isOpen ? '收起' : '展开'}
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
// 加载状态
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -248,7 +206,7 @@ const HistoricalEvents = ({
|
||||
超预期得分: {expectationScore}
|
||||
</Text>
|
||||
<Text fontSize="xs" color="yellow.700">
|
||||
基于历史事件判断当前事件的超预期情况,满分100分(AI合成)
|
||||
基于历史事件判断当前事件的超预期情况,满分100分
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
@@ -359,10 +317,10 @@ const HistoricalEvents = ({
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
{/* 事件简介 */}
|
||||
<Text fontSize="sm" color={textSecondary} lineHeight="1.5">
|
||||
{event.content ? `${event.content}(AI合成)` : '暂无内容'}
|
||||
</Text>
|
||||
{/* 事件简介 */}
|
||||
<Text fontSize="sm" color={textSecondary} lineHeight="1.5">
|
||||
{event.content || '暂无内容'}
|
||||
</Text>
|
||||
|
||||
{/* 展开的详细信息 */}
|
||||
<Collapse in={isExpanded} animateOpacity>
|
||||
@@ -401,9 +359,9 @@ const HistoricalEvents = ({
|
||||
</VStack>
|
||||
|
||||
{/* 事件相关股票模态框 */}
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="4xl">
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW="80vw" maxH="85vh">
|
||||
<ModalContent>
|
||||
<ModalHeader>
|
||||
<VStack align="flex-start" spacing={1}>
|
||||
<Text>{selectedEvent?.title || '历史事件'}</Text>
|
||||
@@ -414,7 +372,7 @@ const HistoricalEvents = ({
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
|
||||
<ModalBody overflowY="auto" maxH="calc(85vh - 180px)">
|
||||
<ModalBody>
|
||||
{loadingStocks ? (
|
||||
<VStack spacing={4} py={8}>
|
||||
<Spinner size="lg" color="blue.500" />
|
||||
@@ -423,7 +381,6 @@ const HistoricalEvents = ({
|
||||
) : (
|
||||
<StocksList
|
||||
stocks={selectedEvent ? eventStocks[selectedEvent.id] || [] : []}
|
||||
eventTradingDate={selectedEvent ? selectedEvent.event_date : null}
|
||||
/>
|
||||
)}
|
||||
</ModalBody>
|
||||
@@ -438,14 +395,8 @@ const HistoricalEvents = ({
|
||||
};
|
||||
|
||||
// 股票列表子组件
|
||||
const StocksList = ({ stocks, eventTradingDate }) => {
|
||||
const StocksList = ({ stocks }) => {
|
||||
const textSecondary = useColorModeValue('gray.600', 'gray.400');
|
||||
|
||||
// 处理股票代码,移除.SZ/.SH后缀
|
||||
const formatStockCode = (stockCode) => {
|
||||
if (!stockCode) return '';
|
||||
return stockCode.replace(/\.(SZ|SH)$/i, '');
|
||||
};
|
||||
|
||||
if (!stocks || stocks.length === 0) {
|
||||
return (
|
||||
@@ -458,81 +409,50 @@ const StocksList = ({ stocks, eventTradingDate }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{eventTradingDate && (
|
||||
<Box mb={4} p={3} bg={useColorModeValue('blue.50', 'blue.900')} borderRadius="md">
|
||||
<Text fontSize="sm" color={useColorModeValue('blue.700', 'blue.300')}>
|
||||
📅 事件对应交易日:{new Date(eventTradingDate).toLocaleDateString('zh-CN')}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
<TableContainer>
|
||||
<Table size="md">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>股票代码</Th>
|
||||
<Th>股票名称</Th>
|
||||
<Th>板块</Th>
|
||||
<Th isNumeric>相关度</Th>
|
||||
<Th isNumeric>事件日涨幅</Th>
|
||||
<Th>关联原因</Th>
|
||||
<TableContainer>
|
||||
<Table size="sm">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>股票代码</Th>
|
||||
<Th>股票名称</Th>
|
||||
<Th>板块</Th>
|
||||
<Th isNumeric>相关度</Th>
|
||||
<Th>关联原因</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{stocks.map((stock, index) => (
|
||||
<Tr key={stock.id || index}>
|
||||
<Td fontFamily="mono" fontWeight="medium">
|
||||
{stock.stock_code}
|
||||
</Td>
|
||||
<Td>{stock.stock_name || '--'}</Td>
|
||||
<Td>
|
||||
<Badge size="sm" variant="outline">
|
||||
{stock.sector || '未知'}
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td isNumeric>
|
||||
<Badge
|
||||
colorScheme={
|
||||
stock.correlation >= 0.8 ? 'red' :
|
||||
stock.correlation >= 0.6 ? 'orange' : 'green'
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{Math.round((stock.correlation || 0) * 100)}%
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td>
|
||||
<Text fontSize="xs" noOfLines={2} maxW="200px">
|
||||
{stock.relation_desc || '--'}
|
||||
</Text>
|
||||
</Td>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{stocks.map((stock, index) => (
|
||||
<Tr key={stock.id || index}>
|
||||
<Td fontFamily="mono" fontWeight="medium">
|
||||
<Link
|
||||
href={`https://valuefrontier.cn/company?scode=${stock.stock_code ? stock.stock_code.replace(/\.(SZ|SH)$/i, '') : ''}`}
|
||||
isExternal
|
||||
color="blue.500"
|
||||
_hover={{ textDecoration: 'underline' }}
|
||||
>
|
||||
{stock.stock_code ? stock.stock_code.replace(/\.(SZ|SH)$/i, '') : ''}
|
||||
</Link>
|
||||
</Td>
|
||||
<Td>{stock.stock_name || '--'}</Td>
|
||||
<Td>
|
||||
<Badge size="sm" variant="outline">
|
||||
{stock.sector || '未知'}
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td isNumeric>
|
||||
<Badge
|
||||
colorScheme={
|
||||
stock.correlation >= 0.8 ? 'red' :
|
||||
stock.correlation >= 0.6 ? 'orange' : 'green'
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{Math.round((stock.correlation || 0) * 100)}%
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td isNumeric>
|
||||
{stock.event_day_change_pct !== null && stock.event_day_change_pct !== undefined ? (
|
||||
<Text
|
||||
fontWeight="medium"
|
||||
color={stock.event_day_change_pct >= 0 ? 'red.500' : 'green.500'}
|
||||
>
|
||||
{stock.event_day_change_pct >= 0 ? '+' : ''}{stock.event_day_change_pct.toFixed(2)}%
|
||||
</Text>
|
||||
) : (
|
||||
<Text color={textSecondary} fontSize="sm">--</Text>
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
<VStack align="flex-start" spacing={1}>
|
||||
<Text fontSize="xs" noOfLines={2} maxW="300px">
|
||||
{stock.relation_desc ? `${stock.relation_desc}(AI合成)` : '--'}
|
||||
</Text>
|
||||
</VStack>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user