feat: HistoricalEvents UI 布局优化
- 从网格布局(SimpleGrid 3列)改为单列纵向布局(VStack) - 卡片样式优化:添加顶部渐变条装饰(蓝-紫-粉渐变) - 卡片内部从垂直布局改为横向布局(HStack) - 优化间距和边距,提升视觉层次感 - 调整卡片padding和borderRadius 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa';
|
||||||
import { stockService } from '../../../services/eventService';
|
import { stockService } from '../../../services/eventService';
|
||||||
import { logger } from '../../../utils/logger';
|
import { logger } from '../../../utils/logger';
|
||||||
|
import CitedContent from '../../../components/Citation/CitedContent';
|
||||||
|
|
||||||
const HistoricalEvents = ({
|
const HistoricalEvents = ({
|
||||||
events = [],
|
events = [],
|
||||||
@@ -224,8 +225,8 @@ const HistoricalEvents = ({
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 历史事件卡片网格 */}
|
{/* 历史事件卡片列表 - 混合布局 */}
|
||||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={4}>
|
<VStack spacing={3} align="stretch">
|
||||||
{events.map((event) => {
|
{events.map((event) => {
|
||||||
const importanceColor = getImportanceColor(event.importance);
|
const importanceColor = getImportanceColor(event.importance);
|
||||||
|
|
||||||
@@ -235,92 +236,126 @@ const HistoricalEvents = ({
|
|||||||
bg={cardBg}
|
bg={cardBg}
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor={borderColor}
|
borderColor={borderColor}
|
||||||
borderRadius="md"
|
borderRadius="lg"
|
||||||
p={4}
|
position="relative"
|
||||||
|
overflow="visible"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={() => handleCardClick(event)}
|
onClick={() => handleCardClick(event)}
|
||||||
|
_before={{
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
height: '3px',
|
||||||
|
bgGradient: 'linear(to-r, blue.400, purple.500, pink.500)',
|
||||||
|
borderTopLeftRadius: 'lg',
|
||||||
|
borderTopRightRadius: 'lg',
|
||||||
|
}}
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'lg',
|
boxShadow: 'lg',
|
||||||
borderColor: 'blue.400',
|
borderColor: 'blue.400',
|
||||||
transform: 'translateY(-2px)',
|
|
||||||
}}
|
}}
|
||||||
transition="all 0.2s"
|
transition="all 0.2s"
|
||||||
>
|
>
|
||||||
<VStack align="stretch" spacing={3}>
|
<VStack align="stretch" spacing={2} p={3}>
|
||||||
{/* 事件名称 */}
|
{/* 顶部区域:左侧(标题+时间) + 右侧(按钮) */}
|
||||||
<Text
|
<HStack align="flex-start" spacing={3}>
|
||||||
fontSize="md"
|
{/* 左侧:标题 + 时间信息(允许折行) */}
|
||||||
fontWeight="bold"
|
<VStack flex="1" align="flex-start" spacing={1}>
|
||||||
color={useColorModeValue('blue.600', 'blue.400')}
|
{/* 标题 */}
|
||||||
noOfLines={2}
|
<Text
|
||||||
lineHeight="1.4"
|
fontSize="md"
|
||||||
cursor="pointer"
|
fontWeight="bold"
|
||||||
onClick={(e) => {
|
color={useColorModeValue('blue.600', 'blue.400')}
|
||||||
e.stopPropagation();
|
lineHeight="1.4"
|
||||||
handleCardClick(event);
|
cursor="pointer"
|
||||||
}}
|
onClick={(e) => {
|
||||||
_hover={{ textDecoration: 'underline' }}
|
e.stopPropagation();
|
||||||
>
|
handleCardClick(event);
|
||||||
{event.title || '未命名事件'}
|
}}
|
||||||
</Text>
|
_hover={{ textDecoration: 'underline' }}
|
||||||
|
|
||||||
{/* 日期 + Badges */}
|
|
||||||
<HStack spacing={2} flexWrap="wrap">
|
|
||||||
<Text fontSize="sm" color={textSecondary}>
|
|
||||||
{formatDate(getEventDate(event))}
|
|
||||||
</Text>
|
|
||||||
<Text fontSize="sm" color={textSecondary}>
|
|
||||||
({getRelativeTime(getEventDate(event))})
|
|
||||||
</Text>
|
|
||||||
{event.relevance && (
|
|
||||||
<Badge colorScheme="blue" size="sm">
|
|
||||||
相关度: {event.relevance}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
{event.importance && (
|
|
||||||
<Badge colorScheme={importanceColor} size="sm">
|
|
||||||
重要性: {event.importance}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
{event.avg_change_pct !== undefined && event.avg_change_pct !== null && (
|
|
||||||
<Badge
|
|
||||||
colorScheme={event.avg_change_pct > 0 ? 'red' : event.avg_change_pct < 0 ? 'green' : 'gray'}
|
|
||||||
size="sm"
|
|
||||||
>
|
>
|
||||||
涨幅: {event.avg_change_pct > 0 ? '+' : ''}{event.avg_change_pct.toFixed(2)}%
|
{event.title || '未命名事件'}
|
||||||
</Badge>
|
</Text>
|
||||||
)}
|
|
||||||
|
{/* 时间 + Badges(允许折行) */}
|
||||||
|
<HStack spacing={2} flexWrap="wrap">
|
||||||
|
<Text fontSize="sm" color={textSecondary}>
|
||||||
|
{formatDate(getEventDate(event))}
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="sm" color={textSecondary}>
|
||||||
|
({getRelativeTime(getEventDate(event))})
|
||||||
|
</Text>
|
||||||
|
{event.importance && (
|
||||||
|
<Badge colorScheme={importanceColor} size="sm">
|
||||||
|
重要性: {event.importance}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{event.avg_change_pct !== undefined && event.avg_change_pct !== null && (
|
||||||
|
<Badge
|
||||||
|
colorScheme={event.avg_change_pct > 0 ? 'red' : event.avg_change_pct < 0 ? 'green' : 'gray'}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
涨幅: {event.avg_change_pct > 0 ? '+' : ''}{event.avg_change_pct.toFixed(2)}%
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
{/* 右侧:相关股票按钮 */}
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
leftIcon={<Icon as={FaChartLine} />}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleViewStocks(event);
|
||||||
|
}}
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="outline"
|
||||||
|
flexShrink={0}
|
||||||
|
>
|
||||||
|
相关股票
|
||||||
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{/* 事件描述 */}
|
{/* 底部:描述(独占整行)- 升级和降级处理 */}
|
||||||
<Text
|
<Box>
|
||||||
fontSize="sm"
|
{(() => {
|
||||||
color={nameColor}
|
const content = getEventContent(event);
|
||||||
lineHeight="1.6"
|
// 检查是否有 data 结构(升级版本)
|
||||||
noOfLines={4}
|
if (content && typeof content === 'object' && content.data) {
|
||||||
>
|
return (
|
||||||
{getEventContent(event) ? `${getEventContent(event)}(AI合成)` : '暂无内容'}
|
<CitedContent
|
||||||
</Text>
|
data={content}
|
||||||
|
title=""
|
||||||
{/* 相关股票按钮 */}
|
showAIBadge={true}
|
||||||
<Button
|
containerStyle={{
|
||||||
size="sm"
|
backgroundColor: useColorModeValue('#f7fafc', 'rgba(45, 55, 72, 0.6)'),
|
||||||
leftIcon={<Icon as={FaChartLine} />}
|
borderRadius: '8px',
|
||||||
onClick={(e) => {
|
padding: '0',
|
||||||
e.stopPropagation();
|
}}
|
||||||
handleViewStocks(event);
|
/>
|
||||||
}}
|
);
|
||||||
colorScheme="blue"
|
}
|
||||||
variant="outline"
|
// 降级版本:纯文本
|
||||||
width="full"
|
return (
|
||||||
>
|
<Text
|
||||||
相关股票
|
fontSize="sm"
|
||||||
</Button>
|
color={nameColor}
|
||||||
|
lineHeight="1.6"
|
||||||
|
noOfLines={2}
|
||||||
|
>
|
||||||
|
{content ? `${content}(AI合成)` : '暂无内容'}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</Box>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</SimpleGrid>
|
</VStack>
|
||||||
|
|
||||||
{/* 相关股票 Modal - 条件渲染 */}
|
{/* 相关股票 Modal - 条件渲染 */}
|
||||||
{stocksModalOpen && (
|
{stocksModalOpen && (
|
||||||
|
|||||||
Reference in New Issue
Block a user