// src/components/StockChangeIndicators.js // 股票涨跌幅指标组件(通用) import React from 'react'; import { Flex, Box, Text, useColorModeValue } from '@chakra-ui/react'; import { TriangleUpIcon, TriangleDownIcon } from '@chakra-ui/icons'; import { getChangeColor } from '../utils/colorUtils'; /** * 股票涨跌幅指标组件(3分天下布局) * @param {Object} props * @param {number} props.avgChange - 平均涨跌幅 * @param {number} props.maxChange - 最大涨跌幅 * @param {number} props.weekChange - 周涨跌幅 * @param {'default'|'comfortable'|'large'} props.size - 尺寸模式:default=紧凑,comfortable=舒适(事件列表),large=大卡片(详情面板) */ const StockChangeIndicators = ({ avgChange, maxChange, weekChange, size = 'default', }) => { const isLarge = size === 'large'; const isComfortable = size === 'comfortable'; const isDefault = size === 'default'; // 根据涨跌幅获取数字颜色(动态深浅) const getNumberColor = (value) => { if (value == null) { return useColorModeValue('gray.700', 'gray.400'); } // 使用动态颜色函数 return getChangeColor(value); }; // 根据涨跌幅获取背景色(永远比文字色浅) const getBgColor = (value) => { if (value == null) { return useColorModeValue('gray.50', 'gray.800'); } // 0值使用中性灰色背景 if (value === 0) { return useColorModeValue('gray.50', 'gray.800'); } // 统一背景色:上涨红色系,下跌绿色系 return value > 0 ? useColorModeValue('red.50', 'red.900') : useColorModeValue('green.50', 'green.900'); }; // 根据涨跌幅获取边框色(比背景深,比文字浅) const getBorderColor = (value) => { if (value == null) { return useColorModeValue('gray.200', 'gray.700'); } // 0值使用中性灰色边框 if (value === 0) { return useColorModeValue('gray.200', 'gray.700'); } // 统一边框色:上涨红色系,下跌绿色系 return value > 0 ? useColorModeValue('red.200', 'red.700') : useColorModeValue('green.200', 'green.700'); }; // 渲染单个指标 const renderIndicator = (label, value) => { if (value == null) return null; const sign = value > 0 ? '+' : '-'; // 0值显示为 "0",其他值显示两位小数 const numStr = value === 0 ? '0' : Math.abs(value).toFixed(2); const numberColor = getNumberColor(value); const bgColor = getBgColor(value); const borderColor = getBorderColor(value); const labelColor = useColorModeValue('gray.600', 'gray.400'); return ( {/* Large 和 Default 模式:标签单独一行 */} {(isLarge || isDefault) && ( {label.trim()} )} {/* 数值 + 图标 */} {/* 三角形图标 */} {value !== 0 && ( value > 0 ? ( ) : ( ) )} {/* 数字 */} {/* Comfortable 模式:标签和数字在同一行 */} {!isLarge && !isDefault && ( {label} )} {sign}{numStr} % ); }; // 如果没有任何数据,不渲染 if (avgChange == null && maxChange == null && weekChange == null) { return null; } return ( {renderIndicator('平均涨幅', avgChange)} {renderIndicator('最大涨幅', maxChange)} {renderIndicator('周涨幅', weekChange)} ); }; export default StockChangeIndicators;