feat本次提交包含的优化
✅ StockChangeIndicators 组件优化 - 调整 padding 使布局更紧凑 - 修复窄卡片中的折行问题 - 自动根据内容调整宽度 ✅ 重要性等级视觉优化 - 统一使用红色系(S→A→B→C:从深红到浅红) - 添加 badgeBg 字段支持新的角标样式 ✅ DynamicNewsEventCard 卡片改版 - 左上角矩形角标显示重要性(镂空边框样式) - 悬浮显示所有等级说明 - 标题限制两行显示 ✅ Mock 数据完整性 - 添加缺失的 related_week_chg 字段 - 确保三个涨跌幅指标数据完整
This commit is contained in:
@@ -127,8 +127,8 @@ const StockChangeIndicators = ({
|
|||||||
borderWidth="2px"
|
borderWidth="2px"
|
||||||
borderColor={borderColor}
|
borderColor={borderColor}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
px={2}
|
px={1.5}
|
||||||
py={1}
|
py={0.5}
|
||||||
display="flex"
|
display="flex"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
|
|||||||
@@ -15,47 +15,55 @@ import {
|
|||||||
export const IMPORTANCE_LEVELS = {
|
export const IMPORTANCE_LEVELS = {
|
||||||
'S': {
|
'S': {
|
||||||
level: 'S',
|
level: 'S',
|
||||||
color: 'purple.600',
|
color: 'red.800',
|
||||||
bgColor: 'purple.50',
|
bgColor: 'red.50',
|
||||||
borderColor: 'purple.200',
|
borderColor: 'red.200',
|
||||||
|
colorScheme: 'red',
|
||||||
|
badgeBg: 'red.800', // 角标边框和文字颜色 - 极深红色
|
||||||
icon: WarningIcon,
|
icon: WarningIcon,
|
||||||
label: '极高',
|
label: '极高',
|
||||||
dotBg: 'purple.500',
|
dotBg: 'red.800',
|
||||||
description: '重大事件,市场影响深远',
|
description: '重大事件,市场影响深远',
|
||||||
antdColor: '#722ed1', // 对应 Ant Design 的紫色
|
antdColor: '#cf1322',
|
||||||
},
|
},
|
||||||
'A': {
|
'A': {
|
||||||
level: 'A',
|
level: 'A',
|
||||||
color: 'red.600',
|
color: 'red.600',
|
||||||
bgColor: 'red.50',
|
bgColor: 'red.50',
|
||||||
borderColor: 'red.200',
|
borderColor: 'red.200',
|
||||||
|
colorScheme: 'red',
|
||||||
|
badgeBg: 'red.600', // 角标边框和文字颜色 - 深红色
|
||||||
icon: WarningTwoIcon,
|
icon: WarningTwoIcon,
|
||||||
label: '高',
|
label: '高',
|
||||||
dotBg: 'red.500',
|
dotBg: 'red.600',
|
||||||
description: '重要事件,影响较大',
|
description: '重要事件,影响较大',
|
||||||
antdColor: '#ff4d4f', // 对应 Ant Design 的红色
|
antdColor: '#ff4d4f',
|
||||||
},
|
},
|
||||||
'B': {
|
'B': {
|
||||||
level: 'B',
|
level: 'B',
|
||||||
color: 'orange.600',
|
color: 'red.500',
|
||||||
bgColor: 'orange.50',
|
bgColor: 'red.50',
|
||||||
borderColor: 'orange.200',
|
borderColor: 'red.100',
|
||||||
|
colorScheme: 'red',
|
||||||
|
badgeBg: 'red.500', // 角标边框和文字颜色 - 中红色
|
||||||
icon: InfoIcon,
|
icon: InfoIcon,
|
||||||
label: '中',
|
label: '中',
|
||||||
dotBg: 'orange.500',
|
dotBg: 'red.500',
|
||||||
description: '普通事件,有一定影响',
|
description: '普通事件,有一定影响',
|
||||||
antdColor: '#faad14', // 对应 Ant Design 的橙色
|
antdColor: '#ff7875',
|
||||||
},
|
},
|
||||||
'C': {
|
'C': {
|
||||||
level: 'C',
|
level: 'C',
|
||||||
color: 'green.600',
|
color: 'red.400',
|
||||||
bgColor: 'green.50',
|
bgColor: 'red.50',
|
||||||
borderColor: 'green.200',
|
borderColor: 'red.100',
|
||||||
|
colorScheme: 'red',
|
||||||
|
badgeBg: 'red.400', // 角标边框和文字颜色 - 浅红色
|
||||||
icon: CheckCircleIcon,
|
icon: CheckCircleIcon,
|
||||||
label: '低',
|
label: '低',
|
||||||
dotBg: 'green.500',
|
dotBg: 'red.400',
|
||||||
description: '参考事件,影响有限',
|
description: '参考事件,影响有限',
|
||||||
antdColor: '#52c41a', // 对应 Ant Design 的绿色
|
antdColor: '#ffa39e',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -753,6 +753,7 @@ export function generateMockEvents(params = {}) {
|
|||||||
const hotScore = Math.max(50, 100 - i);
|
const hotScore = Math.max(50, 100 - i);
|
||||||
const relatedAvgChg = (Math.random() * 20 - 5).toFixed(2); // -5% 到 15%
|
const relatedAvgChg = (Math.random() * 20 - 5).toFixed(2); // -5% 到 15%
|
||||||
const relatedMaxChg = (Math.random() * 30).toFixed(2); // 0% 到 30%
|
const relatedMaxChg = (Math.random() * 30).toFixed(2); // 0% 到 30%
|
||||||
|
const relatedWeekChg = (Math.random() * 30 - 10).toFixed(2); // -10% 到 20%
|
||||||
|
|
||||||
// 生成价格走势数据(前一天、当天、后一天)
|
// 生成价格走势数据(前一天、当天、后一天)
|
||||||
const generatePriceTrend = (seed) => {
|
const generatePriceTrend = (seed) => {
|
||||||
@@ -848,6 +849,7 @@ export function generateMockEvents(params = {}) {
|
|||||||
view_count: Math.floor(Math.random() * 10000),
|
view_count: Math.floor(Math.random() * 10000),
|
||||||
related_avg_chg: parseFloat(relatedAvgChg),
|
related_avg_chg: parseFloat(relatedAvgChg),
|
||||||
related_max_chg: parseFloat(relatedMaxChg),
|
related_max_chg: parseFloat(relatedMaxChg),
|
||||||
|
related_week_chg: parseFloat(relatedWeekChg),
|
||||||
keywords: generateKeywords(industry, i),
|
keywords: generateKeywords(industry, i),
|
||||||
is_ai_generated: i % 4 === 0, // 25% 的事件是AI生成
|
is_ai_generated: i % 4 === 0, // 25% 的事件是AI生成
|
||||||
industry: industry,
|
industry: industry,
|
||||||
|
|||||||
@@ -8,10 +8,17 @@ import {
|
|||||||
CardBody,
|
CardBody,
|
||||||
Box,
|
Box,
|
||||||
Text,
|
Text,
|
||||||
|
HStack,
|
||||||
|
Popover,
|
||||||
|
PopoverTrigger,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverBody,
|
||||||
|
PopoverArrow,
|
||||||
|
Portal,
|
||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
import { getImportanceConfig, getAllImportanceLevels } from '../../../../constants/importanceLevels';
|
||||||
|
|
||||||
// 导入子组件
|
// 导入子组件
|
||||||
import EventFollowButton from './EventFollowButton';
|
import EventFollowButton from './EventFollowButton';
|
||||||
@@ -85,6 +92,7 @@ const DynamicNewsEventCard = ({
|
|||||||
}
|
}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
boxShadow={isSelected ? "lg" : "sm"}
|
boxShadow={isSelected ? "lg" : "sm"}
|
||||||
|
overflow="hidden"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'xl',
|
boxShadow: 'xl',
|
||||||
transform: 'translateY(-2px)',
|
transform: 'translateY(-2px)',
|
||||||
@@ -95,7 +103,74 @@ const DynamicNewsEventCard = ({
|
|||||||
onClick={() => onEventClick?.(event)}
|
onClick={() => onEventClick?.(event)}
|
||||||
>
|
>
|
||||||
<CardBody p={3}>
|
<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}>
|
<Box position="absolute" top={2} right={2} zIndex={1}>
|
||||||
<EventFollowButton
|
<EventFollowButton
|
||||||
isFollowing={isFollowing}
|
isFollowing={isFollowing}
|
||||||
@@ -106,11 +181,12 @@ const DynamicNewsEventCard = ({
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<VStack align="stretch" spacing={2.5}>
|
<VStack align="stretch" spacing={2}>
|
||||||
{/* 第一行:标题 + 重要性(行内文字) */}
|
{/* 标题 - 最多两行,添加上边距避免与角标重叠 */}
|
||||||
<Box
|
<Box
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={(e) => onTitleClick?.(e, event)}
|
onClick={(e) => onTitleClick?.(e, event)}
|
||||||
|
mt={1}
|
||||||
paddingRight="10px"
|
paddingRight="10px"
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
@@ -118,18 +194,10 @@ const DynamicNewsEventCard = ({
|
|||||||
fontWeight="semibold"
|
fontWeight="semibold"
|
||||||
color={linkColor}
|
color={linkColor}
|
||||||
lineHeight="1.4"
|
lineHeight="1.4"
|
||||||
|
noOfLines={2}
|
||||||
_hover={{ textDecoration: 'underline' }}
|
_hover={{ textDecoration: 'underline' }}
|
||||||
>
|
>
|
||||||
{event.title}
|
{event.title}
|
||||||
<Text
|
|
||||||
as="span"
|
|
||||||
fontSize="sm"
|
|
||||||
fontWeight="bold"
|
|
||||||
color={importance.color}
|
|
||||||
ml={2}
|
|
||||||
>
|
|
||||||
[{importance.level}]
|
|
||||||
</Text>
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user