事件中心UI优化

This commit is contained in:
2025-11-07 10:56:08 +08:00
parent 2a122b0013
commit 3eff0554f9
7 changed files with 219 additions and 77 deletions

View File

@@ -8,6 +8,7 @@ import {
Tooltip,
useColorModeValue,
} from '@chakra-ui/react';
import { getChangeColor, getChangeBackgroundGradient, getChangeBorderColor } from '../../../../utils/colorUtils';
/**
* 精简模式股票卡片组件
@@ -30,31 +31,6 @@ const CompactStockItem = ({ stock, quote = null }) => {
return `${prefix}${parseFloat(value).toFixed(2)}%`;
};
// 获取涨跌幅颜色(涨红跌绿)
const getChangeColor = (value) => {
const num = parseFloat(value);
if (isNaN(num) || num === 0) return 'gray.500';
return num > 0 ? 'red.500' : 'green.500';
};
// 获取背景渐变色(涨红跌绿)
const getBackgroundGradient = (value) => {
const num = parseFloat(value);
if (isNaN(num) || num === 0) {
return 'linear(to-br, gray.50, gray.100)';
}
return num > 0
? 'linear(to-br, red.50, red.100)'
: 'linear(to-br, green.50, green.100)';
};
// 获取边框颜色
const getBorderColor = (value) => {
const num = parseFloat(value);
if (isNaN(num) || num === 0) return 'gray.300';
return num > 0 ? 'red.300' : 'green.300';
};
// 获取涨跌幅数据(优先使用 quotefallback 到 stock
const change = quote?.change ?? stock.daily_change ?? null;
@@ -68,9 +44,9 @@ const CompactStockItem = ({ stock, quote = null }) => {
fontSize="xs"
>
<Box
bgGradient={getBackgroundGradient(change)}
bgGradient={getChangeBackgroundGradient(change)}
borderWidth="3px"
borderColor={getBorderColor(change)}
borderColor={getChangeBorderColor(change)}
borderRadius="2xl"
p={4}
onClick={handleViewDetail}
@@ -85,7 +61,7 @@ const CompactStockItem = ({ stock, quote = null }) => {
left: 0,
right: 0,
height: '4px',
bg: getBorderColor(change),
bg: getChangeBorderColor(change),
}}
_hover={{
boxShadow: '2xl',

View File

@@ -18,6 +18,7 @@ import { StarIcon } from '@chakra-ui/icons';
import MiniTimelineChart from '../StockDetailPanel/components/MiniTimelineChart';
import MiniKLineChart from './MiniKLineChart';
import StockChartModal from '../../../../components/StockChart/StockChartModal';
import { getChangeColor } from '../../../../utils/colorUtils';
/**
* 股票卡片组件
@@ -66,12 +67,7 @@ const StockListItem = ({
return `${prefix}${parseFloat(value).toFixed(2)}%`;
};
// 获取涨跌幅颜色
const getChangeColor = (value) => {
const num = parseFloat(value);
if (isNaN(num) || num === 0) return 'gray.500';
return num > 0 ? 'red.500' : 'green.500';
};
// 使用工具函数获取涨跌幅颜色(已从 colorUtils 导入)
// 获取涨跌幅数据(优先使用 quotefallback 到 stock
const change = quote?.change ?? stock.daily_change ?? null;

View File

@@ -13,9 +13,10 @@ import {
} from '@chakra-ui/react';
import moment from 'moment';
import { getImportanceConfig } from '../../../../constants/importanceLevels';
import { getChangeColor } from '../../../../utils/colorUtils';
// 导入子组件
import ImportanceBadge from './ImportanceBadge';
import ImportanceStamp from './ImportanceStamp';
import EventFollowButton from './EventFollowButton';
import StockChangeIndicators from '../../../../components/StockChangeIndicators';
@@ -153,43 +154,37 @@ const DynamicNewsEventCard = ({
};
/**
* 根据平均涨幅计算背景色(分级策略)
* 根据平均涨幅计算背景色(分级策略)- 使用毛玻璃效果
* @param {number} avgChange - 平均涨跌幅
* @returns {string} Chakra UI 颜色值
*/
const getChangeBasedBgColor = (avgChange) => {
// 转换为数字类型(处理可能的字符串类型数据)
const numChange = Number(avgChange);
// 🔍 调试日志:排查背景色计算问题
console.log('📊 [背景色计算]', {
rawValue: avgChange,
numValue: numChange,
type: typeof avgChange,
isNull: avgChange == null,
isNaN: isNaN(numChange),
title: event.title.substring(0, 30) + '...'
});
// 如果没有涨跌幅数据或转换失败,使用默认的奇偶行背景
// 如果没有涨跌幅数据,使用半透明背景
if (avgChange == null || isNaN(numChange)) {
return index % 2 === 0 ? cardBg : useColorModeValue('gray.50', 'gray.750');
return useColorModeValue('rgba(255, 255, 255, 0.8)', 'rgba(26, 32, 44, 0.8)');
}
// 根据涨跌幅分级返回背景色
if (numChange >= 5) {
return useColorModeValue('red.100', 'red.900');
} else if (numChange >= 3) {
return useColorModeValue('red.100', 'red.800');
} else if (numChange > 0) {
return useColorModeValue('red.50', 'red.700');
} else if (numChange > -3) {
return useColorModeValue('green.50', 'green.700');
} else if (numChange > -5) {
return useColorModeValue('green.100', 'green.800');
} else {
return useColorModeValue('green.100', 'green.900');
// 根据涨跌幅分级返回半透明背景色(毛玻璃效果)
const absChange = Math.abs(numChange);
if (numChange > 0) {
// 涨:红色系半透明
if (absChange >= 9) return useColorModeValue('rgba(254, 202, 202, 0.9)', 'rgba(127, 29, 29, 0.9)');
if (absChange >= 7) return useColorModeValue('rgba(254, 202, 202, 0.8)', 'rgba(153, 27, 27, 0.8)');
if (absChange >= 5) return useColorModeValue('rgba(254, 226, 226, 0.8)', 'rgba(185, 28, 28, 0.8)');
if (absChange >= 3) return useColorModeValue('rgba(254, 226, 226, 0.7)', 'rgba(220, 38, 38, 0.7)');
return useColorModeValue('rgba(254, 242, 242, 0.7)', 'rgba(239, 68, 68, 0.7)');
} else if (numChange < 0) {
// 跌:绿色系半透明
if (absChange >= 9) return useColorModeValue('rgba(187, 247, 208, 0.9)', 'rgba(20, 83, 45, 0.9)');
if (absChange >= 7) return useColorModeValue('rgba(187, 247, 208, 0.8)', 'rgba(22, 101, 52, 0.8)');
if (absChange >= 5) return useColorModeValue('rgba(209, 250, 229, 0.8)', 'rgba(21, 128, 61, 0.8)');
if (absChange >= 3) return useColorModeValue('rgba(209, 250, 229, 0.7)', 'rgba(22, 163, 74, 0.7)');
return useColorModeValue('rgba(240, 253, 244, 0.7)', 'rgba(34, 197, 94, 0.7)');
}
return useColorModeValue('rgba(255, 255, 255, 0.8)', 'rgba(26, 32, 44, 0.8)');
};
// 获取当前事件的交易时段、样式和文字标签
@@ -208,17 +203,18 @@ const DynamicNewsEventCard = ({
? useColorModeValue('blue.50', 'blue.900')
: getChangeBasedBgColor(event.related_avg_chg)
}
backdropFilter="blur(10px)" // 毛玻璃效果
borderWidth={isSelected ? "2px" : "1px"}
borderColor={isSelected
? useColorModeValue('blue.500', 'blue.400')
: borderColor
}
borderRadius="md"
boxShadow={isSelected ? "lg" : "sm"}
// overflow="hidden"
borderRadius="lg"
boxShadow={isSelected ? "xl" : "md"}
overflow="visible"
_hover={{
boxShadow: 'xl',
transform: 'translateY(-2px)',
boxShadow: '2xl',
transform: 'translateY(-4px)',
borderColor: isSelected ? 'blue.600' : importance.color,
}}
transition="all 0.3s ease"
@@ -226,8 +222,10 @@ const DynamicNewsEventCard = ({
onClick={() => onEventClick?.(event)}
>
<CardBody p={3}>
{/* 上角:重要性标签 */}
<ImportanceBadge importance={event.importance} position={{ top:-1, left: 0}} />
{/* 上角:重要性印章 */}
<Box position="absolute" top={-8} right={8} zIndex={2}>
<ImportanceStamp importance={event.importance} />
</Box>
{/* 时间标签 - 在卡片上方,宽度自适应,左对齐 */}
<Box

View File

@@ -0,0 +1,74 @@
// src/views/Community/components/EventCard/ImportanceStamp.js
// 重要性印章组件
import React from 'react';
import {
Box,
Text,
useColorModeValue,
} from '@chakra-ui/react';
import { getImportanceConfig } from '../../../../constants/importanceLevels';
/**
* 重要性印章组件(模拟盖章效果)
* @param {Object} props
* @param {string} props.importance - 重要性等级 (S/A/B/C)
*/
const ImportanceStamp = ({ importance }) => {
const config = getImportanceConfig(importance);
// 印章颜色
const stampColor = useColorModeValue(config.badgeBg, config.badgeBg);
return (
<Box
position="relative"
display="inline-block"
>
{/* 外层圆形边框(双圈) */}
<Box
position="relative"
w="50px"
h="50px"
borderRadius="50%"
borderWidth="3px"
borderColor={stampColor}
display="flex"
alignItems="center"
justifyContent="center"
transform="rotate(-15deg)"
opacity={0.85}
boxShadow="0 2px 8px rgba(0,0,0,0.15)"
_hover={{
opacity: 1,
transform: "rotate(-15deg) scale(1.1)",
}}
transition="all 0.3s ease"
>
{/* 内层圆形边框 */}
<Box
position="absolute"
w="42px"
h="42px"
borderRadius="50%"
borderWidth="2px"
borderColor={stampColor}
/>
{/* 印章文字 */}
<Text
fontSize="xl"
fontWeight="black"
color={stampColor}
fontFamily="'STKaiti', 'KaiTi', 'SimKai', serif"
letterSpacing="2px"
textShadow="0 0 1px currentColor"
>
{config.stampText}
</Text>
</Box>
</Box>
);
};
export default ImportanceStamp;