feat: 10.10线上最新代码提交

This commit is contained in:
zdl
2025-10-11 16:16:02 +08:00
parent 4d0dc109bc
commit 495ad758ea
3338 changed files with 460147 additions and 152745 deletions

View File

@@ -33,7 +33,8 @@ import {
Tr,
Th,
Td,
TableContainer
TableContainer,
Link
} from '@chakra-ui/react';
import {
FaExclamationTriangle,
@@ -144,6 +145,47 @@ 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 (
@@ -206,7 +248,7 @@ const HistoricalEvents = ({
超预期得分: {expectationScore}
</Text>
<Text fontSize="xs" color="yellow.700">
基于历史事件判断当前事件的超预期情况满分100分
基于历史事件判断当前事件的超预期情况满分100分AI合成
</Text>
</VStack>
</HStack>
@@ -317,10 +359,10 @@ const HistoricalEvents = ({
</HStack>
</HStack>
{/* 事件简介 */}
<Text fontSize="sm" color={textSecondary} lineHeight="1.5">
{event.content || '暂无内容'}
</Text>
{/* 事件简介 */}
<Text fontSize="sm" color={textSecondary} lineHeight="1.5">
{event.content ? `${event.content}AI合成` : '暂无内容'}
</Text>
{/* 展开的详细信息 */}
<Collapse in={isExpanded} animateOpacity>
@@ -359,9 +401,9 @@ const HistoricalEvents = ({
</VStack>
{/* 事件相关股票模态框 */}
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<Modal isOpen={isOpen} onClose={onClose} size="4xl">
<ModalOverlay />
<ModalContent>
<ModalContent maxW="80vw" maxH="85vh">
<ModalHeader>
<VStack align="flex-start" spacing={1}>
<Text>{selectedEvent?.title || '历史事件'}</Text>
@@ -372,7 +414,7 @@ const HistoricalEvents = ({
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<ModalBody overflowY="auto" maxH="calc(85vh - 180px)">
{loadingStocks ? (
<VStack spacing={4} py={8}>
<Spinner size="lg" color="blue.500" />
@@ -381,6 +423,7 @@ const HistoricalEvents = ({
) : (
<StocksList
stocks={selectedEvent ? eventStocks[selectedEvent.id] || [] : []}
eventTradingDate={selectedEvent ? selectedEvent.event_date : null}
/>
)}
</ModalBody>
@@ -395,8 +438,14 @@ const HistoricalEvents = ({
};
// 股票列表子组件
const StocksList = ({ stocks }) => {
const StocksList = ({ stocks, eventTradingDate }) => {
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 (
@@ -409,50 +458,81 @@ const StocksList = ({ stocks }) => {
}
return (
<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>
<>
{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>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</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>
</>
);
};