事件中心的涨停原因里面和事件相关
This commit is contained in:
@@ -500,6 +500,9 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
||||
const [expandedReasons, setExpandedReasons] = useState({});
|
||||
const [klineModalVisible, setKlineModalVisible] = useState(false);
|
||||
const [selectedKlineStock, setSelectedKlineStock] = useState(null);
|
||||
// 关联事件弹窗状态
|
||||
const [relatedEventsModalVisible, setRelatedEventsModalVisible] = useState(false);
|
||||
const [selectedRelatedEvents, setSelectedRelatedEvents] = useState({ sectorName: '', events: [] });
|
||||
|
||||
// 板块数据处理 - 必须在条件返回之前调用所有hooks
|
||||
const sectorList = useMemo(() => {
|
||||
@@ -1157,80 +1160,67 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
||||
return '#6B7280';
|
||||
};
|
||||
|
||||
// 点击打开事件详情弹窗
|
||||
const handleClick = (e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedRelatedEvents({
|
||||
sectorName: record.name,
|
||||
events: sortedEvents,
|
||||
count: record.count,
|
||||
});
|
||||
setRelatedEventsModalVisible(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<VStack align="start" spacing={1}>
|
||||
<Tooltip
|
||||
title={
|
||||
<Box maxW="300px">
|
||||
<Text fontWeight="bold" mb={1}>{topEvent.title}</Text>
|
||||
{topEvent.relevance_reason && (
|
||||
<Text fontSize="12px" color="#ccc">{topEvent.relevance_reason}</Text>
|
||||
)}
|
||||
{topEvent.matched_concepts?.length > 0 && (
|
||||
<Box mt={2}>
|
||||
<Text fontSize="11px" color="#888" mb={1}>匹配概念:</Text>
|
||||
<HStack flexWrap="wrap" spacing={1}>
|
||||
{topEvent.matched_concepts.slice(0, 5).map((c, i) => (
|
||||
<Tag key={i} style={{ fontSize: '10px', margin: '1px', background: 'rgba(139, 92, 246, 0.2)', border: 'none', color: '#A78BFA' }}>
|
||||
{c}
|
||||
</Tag>
|
||||
))}
|
||||
</HStack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
}
|
||||
placement="left"
|
||||
overlayStyle={{ maxWidth: 350 }}
|
||||
<Box
|
||||
cursor="pointer"
|
||||
p={1.5}
|
||||
borderRadius="md"
|
||||
bg="rgba(96, 165, 250, 0.1)"
|
||||
_hover={{ bg: 'rgba(96, 165, 250, 0.2)', transform: 'translateY(-1px)' }}
|
||||
transition="all 0.2s"
|
||||
maxW="260px"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Box
|
||||
cursor="pointer"
|
||||
p={1.5}
|
||||
borderRadius="md"
|
||||
bg="rgba(96, 165, 250, 0.1)"
|
||||
_hover={{ bg: 'rgba(96, 165, 250, 0.2)' }}
|
||||
transition="background 0.2s"
|
||||
maxW="260px"
|
||||
>
|
||||
<HStack spacing={1.5} align="start">
|
||||
<FileText size={14} color="#60A5FA" style={{ flexShrink: 0, marginTop: 2 }} />
|
||||
<VStack align="start" spacing={0.5} flex={1}>
|
||||
<AntText
|
||||
<HStack spacing={1.5} align="start">
|
||||
<FileText size={14} color="#60A5FA" style={{ flexShrink: 0, marginTop: 2 }} />
|
||||
<VStack align="start" spacing={0.5} flex={1}>
|
||||
<AntText
|
||||
style={{
|
||||
color: '#E0E0E0',
|
||||
fontSize: '12px',
|
||||
lineHeight: '1.3',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 2,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
{topEvent.title}
|
||||
</AntText>
|
||||
<HStack spacing={2}>
|
||||
<Tag
|
||||
style={{
|
||||
color: '#E0E0E0',
|
||||
fontSize: '12px',
|
||||
lineHeight: '1.3',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 2,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
overflow: 'hidden',
|
||||
fontSize: '10px',
|
||||
padding: '0 6px',
|
||||
background: `${getRelevanceColor(topEvent.relevance_score || 0)}20`,
|
||||
border: 'none',
|
||||
color: getRelevanceColor(topEvent.relevance_score || 0),
|
||||
borderRadius: '4px',
|
||||
}}
|
||||
>
|
||||
{topEvent.title}
|
||||
</AntText>
|
||||
<HStack spacing={2}>
|
||||
<Tag
|
||||
style={{
|
||||
fontSize: '10px',
|
||||
padding: '0 6px',
|
||||
background: `${getRelevanceColor(topEvent.relevance_score || 0)}20`,
|
||||
border: 'none',
|
||||
color: getRelevanceColor(topEvent.relevance_score || 0),
|
||||
borderRadius: '4px',
|
||||
}}
|
||||
>
|
||||
相关度 {topEvent.relevance_score || 0}
|
||||
</Tag>
|
||||
{events.length > 1 && (
|
||||
<AntText style={{ fontSize: '10px', color: '#888' }}>
|
||||
+{events.length - 1}条
|
||||
</AntText>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
相关度 {topEvent.relevance_score || 0}
|
||||
</Tag>
|
||||
{events.length > 1 && (
|
||||
<AntText style={{ fontSize: '10px', color: '#888' }}>
|
||||
+{events.length - 1}条
|
||||
</AntText>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
</VStack>
|
||||
);
|
||||
},
|
||||
@@ -2457,6 +2447,165 @@ const DetailModal = ({ isOpen, onClose, selectedDate, ztDetail, events, loading
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
{/* 关联事件弹窗 - 涨停归因详情 */}
|
||||
<Modal
|
||||
isOpen={relatedEventsModalVisible}
|
||||
onClose={() => {
|
||||
setRelatedEventsModalVisible(false);
|
||||
setSelectedRelatedEvents({ sectorName: '', events: [] });
|
||||
}}
|
||||
size="xl"
|
||||
scrollBehavior="inside"
|
||||
>
|
||||
<ModalOverlay bg="blackAlpha.700" backdropFilter={GLASS_BLUR.sm} />
|
||||
<ModalContent
|
||||
maxW="700px"
|
||||
maxH="80vh"
|
||||
bg="linear-gradient(135deg, rgba(15,15,30,0.98) 0%, rgba(25,25,50,0.98) 100%)"
|
||||
border="1px solid rgba(96,165,250,0.3)"
|
||||
borderRadius="2xl"
|
||||
>
|
||||
<ModalHeader borderBottom="1px solid rgba(96,165,250,0.2)" py={4}>
|
||||
<HStack spacing={3}>
|
||||
<Box
|
||||
p={2}
|
||||
bg="rgba(96,165,250,0.15)"
|
||||
borderRadius="lg"
|
||||
border="1px solid rgba(96,165,250,0.3)"
|
||||
>
|
||||
<FileText size={18} color="#60A5FA" />
|
||||
</Box>
|
||||
<VStack align="start" spacing={0}>
|
||||
<HStack spacing={2}>
|
||||
<Text fontSize="lg" fontWeight="bold" color="#60A5FA">
|
||||
{selectedRelatedEvents.sectorName} - 涨停归因
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack spacing={3}>
|
||||
<Text fontSize="xs" color="whiteAlpha.500">
|
||||
涨停 <Text as="span" color="#EF4444" fontWeight="bold">{selectedRelatedEvents.count || 0}</Text> 只
|
||||
</Text>
|
||||
<Text fontSize="xs" color="whiteAlpha.500">
|
||||
关联事件 <Text as="span" color="#60A5FA" fontWeight="bold">{selectedRelatedEvents.events?.length || 0}</Text> 条
|
||||
</Text>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</ModalHeader>
|
||||
<ModalCloseButton color="whiteAlpha.600" _hover={{ color: 'white' }} />
|
||||
<ModalBody py={4} overflowY="auto">
|
||||
{selectedRelatedEvents.events?.length > 0 ? (
|
||||
<VStack spacing={3} align="stretch">
|
||||
{selectedRelatedEvents.events.map((event, idx) => {
|
||||
const getRelevanceColor = (score) => {
|
||||
if (score >= 80) return '#10B981';
|
||||
if (score >= 60) return '#F59E0B';
|
||||
return '#6B7280';
|
||||
};
|
||||
const relevanceColor = getRelevanceColor(event.relevance_score || 0);
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={event.event_id || idx}
|
||||
p={4}
|
||||
bg="rgba(30,30,50,0.8)"
|
||||
borderRadius="xl"
|
||||
border="1px solid rgba(255,255,255,0.06)"
|
||||
cursor="pointer"
|
||||
onClick={() => {
|
||||
// 跳转到事件详情页
|
||||
window.open(`/community?event_id=${event.event_id}`, '_blank');
|
||||
}}
|
||||
_hover={{
|
||||
bg: 'rgba(40,40,70,0.9)',
|
||||
borderColor: 'rgba(96,165,250,0.3)',
|
||||
transform: 'translateY(-2px)',
|
||||
}}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<VStack align="stretch" spacing={3}>
|
||||
{/* 标题 */}
|
||||
<HStack justify="space-between" align="start">
|
||||
<HStack spacing={2} flex={1}>
|
||||
<FileText size={16} color="#60A5FA" style={{ flexShrink: 0 }} />
|
||||
<Text fontSize="sm" fontWeight="600" color="#E0E0E0" noOfLines={2}>
|
||||
{event.title}
|
||||
</Text>
|
||||
</HStack>
|
||||
<Badge
|
||||
bg={`${relevanceColor}20`}
|
||||
color={relevanceColor}
|
||||
fontSize="xs"
|
||||
px={2}
|
||||
py={0.5}
|
||||
borderRadius="md"
|
||||
>
|
||||
相关度 {event.relevance_score || 0}
|
||||
</Badge>
|
||||
</HStack>
|
||||
|
||||
{/* 相关原因 */}
|
||||
{event.relevance_reason && (
|
||||
<Text fontSize="xs" color="whiteAlpha.600" lineHeight="1.6">
|
||||
{event.relevance_reason}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* 匹配概念 */}
|
||||
{event.matched_concepts?.length > 0 && (
|
||||
<Box>
|
||||
<Text fontSize="xs" color="whiteAlpha.400" mb={1.5}>
|
||||
匹配概念:
|
||||
</Text>
|
||||
<HStack spacing={1.5} flexWrap="wrap">
|
||||
{event.matched_concepts.slice(0, 6).map((concept, i) => (
|
||||
<Tag
|
||||
key={i}
|
||||
style={{
|
||||
fontSize: '10px',
|
||||
margin: '2px',
|
||||
background: 'rgba(139, 92, 246, 0.15)',
|
||||
border: 'none',
|
||||
color: '#A78BFA',
|
||||
borderRadius: '4px',
|
||||
padding: '2px 8px',
|
||||
}}
|
||||
>
|
||||
{concept}
|
||||
</Tag>
|
||||
))}
|
||||
{event.matched_concepts.length > 6 && (
|
||||
<Tag
|
||||
style={{
|
||||
fontSize: '10px',
|
||||
margin: '2px',
|
||||
background: 'rgba(255,255,255,0.1)',
|
||||
border: 'none',
|
||||
color: '#888',
|
||||
borderRadius: '4px',
|
||||
padding: '2px 8px',
|
||||
}}
|
||||
>
|
||||
+{event.matched_concepts.length - 6}
|
||||
</Tag>
|
||||
)}
|
||||
</HStack>
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</VStack>
|
||||
) : (
|
||||
<Center h="200px">
|
||||
<Text color="whiteAlpha.500">暂无关联事件</Text>
|
||||
</Center>
|
||||
)}
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user