From 70dbf3b4923a40f62b57af5c9d02078c409783b8 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Wed, 5 Nov 2025 15:19:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20StockChangeIndicators=20=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/StockChangeIndicators.js | 146 +++++++++++------------- 1 file changed, 66 insertions(+), 80 deletions(-) diff --git a/src/components/StockChangeIndicators.js b/src/components/StockChangeIndicators.js index 58220228..922a4fc7 100644 --- a/src/components/StockChangeIndicators.js +++ b/src/components/StockChangeIndicators.js @@ -3,6 +3,7 @@ import React from 'react'; import { Flex, Box, Text, useColorModeValue } from '@chakra-ui/react'; +import { TriangleUpIcon, TriangleDownIcon } from '@chakra-ui/icons'; /** * 股票涨跌幅指标组件(3分天下布局) @@ -10,13 +11,18 @@ import { Flex, Box, Text, useColorModeValue } from '@chakra-ui/react'; * @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', }) => { - // 根据涨跌幅获取数字颜色(多颜色梯度:5级分级) + const isLarge = size === 'large'; + const isComfortable = size === 'comfortable'; + + // 根据涨跌幅获取数字颜色(统一颜色,不分级) const getNumberColor = (value) => { if (value == null) { return useColorModeValue('gray.700', 'gray.400'); @@ -27,24 +33,8 @@ const StockChangeIndicators = ({ return 'gray.700'; } - const absValue = Math.abs(value); - const isPositive = value > 0; - - if (isPositive) { - // 上涨:红色系 → 橙色系 - if (absValue >= 10) return 'red.900'; // 10%以上:最深红 - if (absValue >= 5) return 'red.700'; // 5-10%:深红 - if (absValue >= 3) return 'red.500'; // 3-5%:中红 - if (absValue >= 1) return 'orange.600'; // 1-3%:橙色 - return 'orange.400'; // 0-1%:浅橙 - } else { - // 下跌:绿色系 → 青色系 - if (absValue >= 10) return 'green.900'; // -10%以下:最深绿 - if (absValue >= 5) return 'green.700'; // -10% ~ -5%:深绿 - if (absValue >= 3) return 'green.500'; // -5% ~ -3%:中绿 - if (absValue >= 1) return 'teal.600'; // -3% ~ -1%:青色 - return 'teal.400'; // -1% ~ 0%:浅青 - } + // 统一颜色:上涨红色,下跌绿色 + return value > 0 ? 'red.500' : 'green.500'; }; // 根据涨跌幅获取背景色(永远比文字色浅) @@ -58,24 +48,10 @@ const StockChangeIndicators = ({ return useColorModeValue('gray.50', 'gray.800'); } - const absValue = Math.abs(value); - const isPositive = value > 0; - - if (isPositive) { - // 上涨背景:红色系 → 橙色系(统一使用 50 最浅色) - if (absValue >= 10) return useColorModeValue('red.50', 'red.900'); - if (absValue >= 5) return useColorModeValue('red.50', 'red.900'); - if (absValue >= 3) return useColorModeValue('red.50', 'red.900'); - if (absValue >= 1) return useColorModeValue('orange.50', 'orange.900'); - return useColorModeValue('orange.50', 'orange.900'); - } else { - // 下跌背景:绿色系 → 青色系(统一使用 50 最浅色) - if (absValue >= 10) return useColorModeValue('green.50', 'green.900'); - if (absValue >= 5) return useColorModeValue('green.50', 'green.900'); - if (absValue >= 3) return useColorModeValue('green.50', 'green.900'); - if (absValue >= 1) return useColorModeValue('teal.50', 'teal.900'); - return useColorModeValue('teal.50', 'teal.900'); - } + // 统一背景色:上涨红色系,下跌绿色系 + return value > 0 + ? useColorModeValue('red.50', 'red.900') + : useColorModeValue('green.50', 'green.900'); }; // 根据涨跌幅获取边框色(比背景深,比文字浅) @@ -89,64 +65,74 @@ const StockChangeIndicators = ({ return useColorModeValue('gray.200', 'gray.700'); } - const absValue = Math.abs(value); - const isPositive = value > 0; - - if (isPositive) { - // 上涨边框:红色系 → 橙色系(跟随文字深浅) - if (absValue >= 10) return useColorModeValue('red.200', 'red.800'); // 文字 red.900 - if (absValue >= 5) return useColorModeValue('red.200', 'red.700'); // 文字 red.700 - if (absValue >= 3) return useColorModeValue('red.100', 'red.600'); // 文字 red.500 - if (absValue >= 1) return useColorModeValue('orange.200', 'orange.700'); // 文字 orange.600 - return useColorModeValue('orange.100', 'orange.600'); // 文字 orange.400 - } else { - // 下跌边框:绿色系 → 青色系(跟随文字深浅) - if (absValue >= 10) return useColorModeValue('green.200', 'green.800'); // 文字 green.900 - if (absValue >= 5) return useColorModeValue('green.200', 'green.700'); // 文字 green.700 - if (absValue >= 3) return useColorModeValue('green.100', 'green.600'); // 文字 green.500 - if (absValue >= 1) return useColorModeValue('teal.200', 'teal.700'); // 文字 teal.600 - return useColorModeValue('teal.100', 'teal.600'); // 文字 teal.400 - } + // 统一边框色:上涨红色系,下跌绿色系 + 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(1); + 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.700', 'gray.400'); + const labelColor = useColorModeValue('gray.600', 'gray.400'); return ( - - - {label} + {/* Large 模式:标签单独一行 */} + {isLarge && ( + + {label.trim()} - - {sign} + )} + + {/* 数值 + 图标 */} + + {/* 三角形图标 */} + {value !== 0 && ( + value > 0 ? ( + + ) : ( + + ) + )} + + {/* 数字 */} + + {/* Default 模式:标签和数字在同一行 */} + {!isLarge && ( + + {label} + + )} + {sign}{numStr}% - - {value < 0 ? '-' : ''}{numStr} - - - % - - + ); }; @@ -157,10 +143,10 @@ const StockChangeIndicators = ({ } return ( - - {renderIndicator('平均 ', avgChange)} - {renderIndicator('最大 ', maxChange)} - {renderIndicator('周涨 ', weekChange)} + + {renderIndicator('平均涨幅', avgChange)} + {renderIndicator('最大涨幅', maxChange)} + {renderIndicator('周涨幅', weekChange)} ); };