fix: 恢复原有涨跌幅样式,将周涨幅改为超预期得分
- 恢复HorizontalDynamicNewsEventCard使用StockChangeIndicators组件 - 修改StockChangeIndicators:周涨幅→超预期得分,平均涨幅→平均超额,最大涨幅→最大超额 - 超预期得分显示为分数形式(如60分),根据分数显示不同颜色
This commit is contained in:
@@ -9,15 +9,15 @@ import { getChangeColor } from '../utils/colorUtils';
|
|||||||
/**
|
/**
|
||||||
* 股票涨跌幅指标组件(3分天下布局)
|
* 股票涨跌幅指标组件(3分天下布局)
|
||||||
* @param {Object} props
|
* @param {Object} props
|
||||||
* @param {number} props.avgChange - 平均涨跌幅
|
* @param {number} props.avgChange - 平均超额涨幅
|
||||||
* @param {number} props.maxChange - 最大涨跌幅
|
* @param {number} props.maxChange - 最大超额涨幅
|
||||||
* @param {number} props.weekChange - 周涨跌幅
|
* @param {number} props.expectationScore - 超预期得分(0-100)
|
||||||
* @param {'default'|'comfortable'|'large'} props.size - 尺寸模式:default=紧凑,comfortable=舒适(事件列表),large=大卡片(详情面板)
|
* @param {'default'|'comfortable'|'large'} props.size - 尺寸模式:default=紧凑,comfortable=舒适(事件列表),large=大卡片(详情面板)
|
||||||
*/
|
*/
|
||||||
const StockChangeIndicators = ({
|
const StockChangeIndicators = ({
|
||||||
avgChange,
|
avgChange,
|
||||||
maxChange,
|
maxChange,
|
||||||
weekChange,
|
expectationScore,
|
||||||
size = 'default',
|
size = 'default',
|
||||||
}) => {
|
}) => {
|
||||||
const isLarge = size === 'large';
|
const isLarge = size === 'large';
|
||||||
@@ -146,16 +146,92 @@ const StockChangeIndicators = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 渲染超预期得分指标(特殊样式,分数而非百分比)
|
||||||
|
const renderScoreIndicator = (label, score) => {
|
||||||
|
if (score == null) return null;
|
||||||
|
|
||||||
|
const labelColor = useColorModeValue('gray.600', 'gray.400');
|
||||||
|
|
||||||
|
// 根据分数确定颜色:>=60红色,>=40橙色,>=20蓝色,其他灰色
|
||||||
|
const getScoreColor = (s) => {
|
||||||
|
if (s >= 60) return useColorModeValue('red.600', 'red.400');
|
||||||
|
if (s >= 40) return useColorModeValue('orange.600', 'orange.400');
|
||||||
|
if (s >= 20) return useColorModeValue('blue.600', 'blue.400');
|
||||||
|
return useColorModeValue('gray.600', 'gray.400');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScoreBgColor = (s) => {
|
||||||
|
if (s >= 60) return useColorModeValue('red.50', 'red.900');
|
||||||
|
if (s >= 40) return useColorModeValue('orange.50', 'orange.900');
|
||||||
|
if (s >= 20) return useColorModeValue('blue.50', 'blue.900');
|
||||||
|
return useColorModeValue('gray.50', 'gray.800');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScoreBorderColor = (s) => {
|
||||||
|
if (s >= 60) return useColorModeValue('red.200', 'red.700');
|
||||||
|
if (s >= 40) return useColorModeValue('orange.200', 'orange.700');
|
||||||
|
if (s >= 20) return useColorModeValue('blue.200', 'blue.700');
|
||||||
|
return useColorModeValue('gray.200', 'gray.700');
|
||||||
|
};
|
||||||
|
|
||||||
|
const scoreColor = getScoreColor(score);
|
||||||
|
const bgColor = getScoreBgColor(score);
|
||||||
|
const borderColor = getScoreBorderColor(score);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
bg={bgColor}
|
||||||
|
borderWidth={isLarge ? "2px" : "1px"}
|
||||||
|
borderColor={borderColor}
|
||||||
|
borderRadius="md"
|
||||||
|
px={isLarge ? 4 : (isDefault ? 1.5 : (isComfortable ? 3 : 2))}
|
||||||
|
py={isLarge ? 3 : (isDefault ? 1.5 : (isComfortable ? 2 : 1))}
|
||||||
|
display="flex"
|
||||||
|
flexDirection={(isLarge || isDefault) ? "column" : "row"}
|
||||||
|
alignItems={(isLarge || isDefault) ? "flex-start" : "center"}
|
||||||
|
gap={(isLarge || isDefault) ? (isLarge ? 2 : 1) : 1}
|
||||||
|
maxW={isLarge ? "200px" : "none"}
|
||||||
|
flex="0 1 auto"
|
||||||
|
minW="0"
|
||||||
|
>
|
||||||
|
{/* Large 和 Default 模式:标签单独一行 */}
|
||||||
|
{(isLarge || isDefault) && (
|
||||||
|
<Text fontSize={isLarge ? "sm" : "xs"} color={labelColor} fontWeight="medium">
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 数值 */}
|
||||||
|
<Text
|
||||||
|
fontSize={isLarge ? "2xl" : (isDefault ? "md" : "lg")}
|
||||||
|
fontWeight="bold"
|
||||||
|
color={scoreColor}
|
||||||
|
lineHeight="1.2"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
>
|
||||||
|
{/* Comfortable 模式:标签和数字在同一行 */}
|
||||||
|
{!isLarge && !isDefault && (
|
||||||
|
<Text as="span" color={labelColor} fontWeight="medium" fontSize="sm">
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{Math.round(score)}
|
||||||
|
<Text as="span" fontWeight="medium" fontSize="sm">分</Text>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// 如果没有任何数据,不渲染
|
// 如果没有任何数据,不渲染
|
||||||
if (avgChange == null && maxChange == null && weekChange == null) {
|
if (avgChange == null && maxChange == null && expectationScore == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex width="100%" justify="flex-start" align="center" gap={isLarge ? 4 : (isDefault ? 2 : 1)}>
|
<Flex width="100%" justify="flex-start" align="center" gap={isLarge ? 4 : (isDefault ? 2 : 1)}>
|
||||||
{renderIndicator('平均涨幅', avgChange)}
|
{renderIndicator('最大超额', maxChange)}
|
||||||
{renderIndicator('最大涨幅', maxChange)}
|
{renderIndicator('平均超额', avgChange)}
|
||||||
{renderIndicator('周涨幅', weekChange)}
|
{renderScoreIndicator('超预期', expectationScore)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import dayjs from 'dayjs';
|
|||||||
import ImportanceStamp from './ImportanceStamp';
|
import ImportanceStamp from './ImportanceStamp';
|
||||||
import EventTimeline from './EventTimeline';
|
import EventTimeline from './EventTimeline';
|
||||||
import EventFollowButton from './EventFollowButton';
|
import EventFollowButton from './EventFollowButton';
|
||||||
import EventPriceDisplay from './EventPriceDisplay';
|
import StockChangeIndicators from '../../../../components/StockChangeIndicators';
|
||||||
import KeywordsCarousel from './KeywordsCarousel';
|
import KeywordsCarousel from './KeywordsCarousel';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +38,7 @@ import KeywordsCarousel from './KeywordsCarousel';
|
|||||||
* @param {Function} props.onToggleFollow - 切换关注事件
|
* @param {Function} props.onToggleFollow - 切换关注事件
|
||||||
* @param {Object} props.timelineStyle - 时间轴样式配置
|
* @param {Object} props.timelineStyle - 时间轴样式配置
|
||||||
* @param {string} props.borderColor - 边框颜色
|
* @param {string} props.borderColor - 边框颜色
|
||||||
|
* @param {string} props.indicatorSize - 涨幅指标尺寸 ('default' | 'comfortable' | 'large')
|
||||||
* @param {string} props.layout - 布局模式 ('vertical' | 'four-row'),影响时间轴竖线高度
|
* @param {string} props.layout - 布局模式 ('vertical' | 'four-row'),影响时间轴竖线高度
|
||||||
*/
|
*/
|
||||||
const HorizontalDynamicNewsEventCard = React.memo(({
|
const HorizontalDynamicNewsEventCard = React.memo(({
|
||||||
@@ -51,6 +52,7 @@ const HorizontalDynamicNewsEventCard = React.memo(({
|
|||||||
onToggleFollow,
|
onToggleFollow,
|
||||||
timelineStyle,
|
timelineStyle,
|
||||||
borderColor: timelineBorderColor,
|
borderColor: timelineBorderColor,
|
||||||
|
indicatorSize = 'comfortable',
|
||||||
layout = 'vertical',
|
layout = 'vertical',
|
||||||
}) => {
|
}) => {
|
||||||
const importance = getImportanceConfig(event.importance);
|
const importance = getImportanceConfig(event.importance);
|
||||||
@@ -243,12 +245,12 @@ const HorizontalDynamicNewsEventCard = React.memo(({
|
|||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{/* 第二行:最大超额 + 超预期得分 */}
|
{/* 第二行:涨跌幅数据 */}
|
||||||
<EventPriceDisplay
|
<StockChangeIndicators
|
||||||
avgChange={event.related_avg_chg}
|
|
||||||
maxChange={event.related_max_chg}
|
maxChange={event.related_max_chg}
|
||||||
|
avgChange={event.related_avg_chg}
|
||||||
expectationScore={event.expectation_surprise_score}
|
expectationScore={event.expectation_surprise_score}
|
||||||
compact={false}
|
size={indicatorSize}
|
||||||
/>
|
/>
|
||||||
</VStack>
|
</VStack>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user