feat: 创建纵向模式的横向卡片组件
This commit is contained in:
@@ -0,0 +1,204 @@
|
|||||||
|
// src/views/Community/components/EventCard/HorizontalDynamicNewsEventCard.js
|
||||||
|
// 横向布局的动态新闻事件卡片组件(时间在左,卡片在右)
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
HStack,
|
||||||
|
Card,
|
||||||
|
CardBody,
|
||||||
|
VStack,
|
||||||
|
Box,
|
||||||
|
Text,
|
||||||
|
Popover,
|
||||||
|
PopoverTrigger,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverBody,
|
||||||
|
PopoverArrow,
|
||||||
|
Portal,
|
||||||
|
useColorModeValue,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { getImportanceConfig, getAllImportanceLevels } from '../../../../constants/importanceLevels';
|
||||||
|
|
||||||
|
// 导入子组件
|
||||||
|
import EventTimeline from './EventTimeline';
|
||||||
|
import EventFollowButton from './EventFollowButton';
|
||||||
|
import StockChangeIndicators from '../../../../components/StockChangeIndicators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 横向布局的动态新闻事件卡片组件
|
||||||
|
* @param {Object} props
|
||||||
|
* @param {Object} props.event - 事件对象
|
||||||
|
* @param {number} props.index - 事件索引
|
||||||
|
* @param {boolean} props.isFollowing - 是否已关注
|
||||||
|
* @param {number} props.followerCount - 关注数
|
||||||
|
* @param {boolean} props.isSelected - 是否被选中
|
||||||
|
* @param {Function} props.onEventClick - 卡片点击事件
|
||||||
|
* @param {Function} props.onTitleClick - 标题点击事件
|
||||||
|
* @param {Function} props.onToggleFollow - 切换关注事件
|
||||||
|
* @param {Object} props.timelineStyle - 时间轴样式配置
|
||||||
|
* @param {string} props.borderColor - 边框颜色
|
||||||
|
*/
|
||||||
|
const HorizontalDynamicNewsEventCard = ({
|
||||||
|
event,
|
||||||
|
index,
|
||||||
|
isFollowing,
|
||||||
|
followerCount,
|
||||||
|
isSelected = false,
|
||||||
|
onEventClick,
|
||||||
|
onTitleClick,
|
||||||
|
onToggleFollow,
|
||||||
|
timelineStyle,
|
||||||
|
borderColor,
|
||||||
|
}) => {
|
||||||
|
const importance = getImportanceConfig(event.importance);
|
||||||
|
const cardBg = useColorModeValue('white', 'gray.800');
|
||||||
|
const linkColor = useColorModeValue('blue.600', 'blue.400');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HStack align="stretch" spacing={3} w="full">
|
||||||
|
{/* 左侧时间轴 */}
|
||||||
|
<EventTimeline
|
||||||
|
createdAt={event.created_at}
|
||||||
|
timelineStyle={timelineStyle}
|
||||||
|
borderColor={borderColor}
|
||||||
|
minHeight="60px"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 右侧事件卡片 */}
|
||||||
|
<Card
|
||||||
|
flex="1"
|
||||||
|
position="relative"
|
||||||
|
bg={isSelected
|
||||||
|
? useColorModeValue('blue.50', 'blue.900')
|
||||||
|
: (index % 2 === 0 ? cardBg : useColorModeValue('gray.50', 'gray.750'))
|
||||||
|
}
|
||||||
|
borderWidth={isSelected ? "2px" : "1px"}
|
||||||
|
borderColor={isSelected
|
||||||
|
? useColorModeValue('blue.500', 'blue.400')
|
||||||
|
: borderColor
|
||||||
|
}
|
||||||
|
borderRadius="md"
|
||||||
|
boxShadow={isSelected ? "lg" : "sm"}
|
||||||
|
overflow="hidden"
|
||||||
|
_hover={{
|
||||||
|
boxShadow: 'xl',
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
borderColor: isSelected ? 'blue.600' : importance.color,
|
||||||
|
}}
|
||||||
|
transition="all 0.3s ease"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() => onEventClick?.(event)}
|
||||||
|
>
|
||||||
|
<CardBody p={3}>
|
||||||
|
{/* 左上角:重要性矩形角标(镂空边框样式) */}
|
||||||
|
<Popover trigger="hover" placement="right" isLazy>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
zIndex={1}
|
||||||
|
bg="transparent"
|
||||||
|
color={importance.badgeBg}
|
||||||
|
borderWidth="2px"
|
||||||
|
borderColor={importance.badgeBg}
|
||||||
|
fontSize="11px"
|
||||||
|
fontWeight="bold"
|
||||||
|
px={1.5}
|
||||||
|
py={0.5}
|
||||||
|
minW="auto"
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
lineHeight="1"
|
||||||
|
borderBottomRightRadius="md"
|
||||||
|
cursor="help"
|
||||||
|
>
|
||||||
|
{importance.label}
|
||||||
|
</Box>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<Portal>
|
||||||
|
<PopoverContent width="auto" maxW="350px">
|
||||||
|
<PopoverArrow />
|
||||||
|
<PopoverBody p={3}>
|
||||||
|
<VStack align="stretch" spacing={2}>
|
||||||
|
<Text fontSize="sm" fontWeight="bold" mb={1}>
|
||||||
|
重要性等级说明
|
||||||
|
</Text>
|
||||||
|
{getAllImportanceLevels().map(item => (
|
||||||
|
<HStack key={item.level} spacing={2} align="flex-start">
|
||||||
|
<Box
|
||||||
|
w="20px"
|
||||||
|
h="20px"
|
||||||
|
borderWidth="2px"
|
||||||
|
borderColor={item.badgeBg}
|
||||||
|
color={item.badgeBg}
|
||||||
|
fontSize="9px"
|
||||||
|
fontWeight="bold"
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
borderRadius="sm"
|
||||||
|
flexShrink={0}
|
||||||
|
>
|
||||||
|
{item.level}
|
||||||
|
</Box>
|
||||||
|
<Text fontSize="xs" flex={1}>
|
||||||
|
<Text as="span" fontWeight="bold">
|
||||||
|
{item.label}:
|
||||||
|
</Text>
|
||||||
|
{item.description}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
))}
|
||||||
|
</VStack>
|
||||||
|
</PopoverBody>
|
||||||
|
</PopoverContent>
|
||||||
|
</Portal>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
{/* 右上角:关注按钮 */}
|
||||||
|
<Box position="absolute" top={2} right={2} zIndex={1}>
|
||||||
|
<EventFollowButton
|
||||||
|
isFollowing={isFollowing}
|
||||||
|
followerCount={followerCount}
|
||||||
|
onToggle={() => onToggleFollow?.(event.id)}
|
||||||
|
size="xs"
|
||||||
|
showCount={false}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<VStack align="stretch" spacing={2}>
|
||||||
|
{/* 标题 - 最多两行,添加上边距避免与角标重叠 */}
|
||||||
|
<Box
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={(e) => onTitleClick?.(e, event)}
|
||||||
|
mt={1}
|
||||||
|
paddingRight="10px"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontSize="md"
|
||||||
|
fontWeight="semibold"
|
||||||
|
color={linkColor}
|
||||||
|
lineHeight="1.4"
|
||||||
|
noOfLines={2}
|
||||||
|
_hover={{ textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
{event.title}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* 第二行:涨跌幅数据 */}
|
||||||
|
<StockChangeIndicators
|
||||||
|
avgChange={event.related_avg_chg}
|
||||||
|
maxChange={event.related_max_chg}
|
||||||
|
weekChange={event.related_week_chg}
|
||||||
|
/>
|
||||||
|
</VStack>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
</HStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HorizontalDynamicNewsEventCard;
|
||||||
Reference in New Issue
Block a user