From ad933e9fb25a1be411b868561493a5cdc1fc6464 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Wed, 5 Nov 2025 23:54:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20UI=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/StockChangeIndicators.js | 21 +- .../EventCard/DynamicNewsEventCard.js | 206 ++++++++++++------ 2 files changed, 152 insertions(+), 75 deletions(-) diff --git a/src/components/StockChangeIndicators.js b/src/components/StockChangeIndicators.js index 0d0ecbc4..b9cc3039 100644 --- a/src/components/StockChangeIndicators.js +++ b/src/components/StockChangeIndicators.js @@ -90,13 +90,15 @@ const StockChangeIndicators = ({ borderWidth={isLarge ? "2px" : "1px"} borderColor={borderColor} borderRadius="md" - px={isLarge ? 4 : (isDefault ? 2 : (isComfortable ? 3 : 2))} + 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" : (isDefault ? "120px" : "none")} + maxW={isLarge ? "200px" : "none"} + flex="0 1 auto" + minW="0" > {/* Large 和 Default 模式:标签单独一行 */} {(isLarge || isDefault) && ( @@ -111,14 +113,14 @@ const StockChangeIndicators = ({ {value !== 0 && ( value > 0 ? ( ) : ( ) @@ -131,6 +133,8 @@ const StockChangeIndicators = ({ color={numberColor} lineHeight="1.2" whiteSpace="nowrap" + overflow="hidden" + textOverflow="ellipsis" > {/* Comfortable 模式:标签和数字在同一行 */} {!isLarge && !isDefault && ( @@ -138,7 +142,8 @@ const StockChangeIndicators = ({ {label} )} - {sign}{numStr}% + {sign}{numStr} + % @@ -151,7 +156,7 @@ const StockChangeIndicators = ({ } return ( - + {renderIndicator('平均涨幅', avgChange)} {renderIndicator('最大涨幅', maxChange)} {renderIndicator('周涨幅', weekChange)} diff --git a/src/views/Community/components/EventCard/DynamicNewsEventCard.js b/src/views/Community/components/EventCard/DynamicNewsEventCard.js index 32e360c5..3153bdcc 100644 --- a/src/views/Community/components/EventCard/DynamicNewsEventCard.js +++ b/src/views/Community/components/EventCard/DynamicNewsEventCard.js @@ -48,9 +48,9 @@ const DynamicNewsEventCard = ({ const importance = getImportanceConfig(event.importance); /** - * 判断交易时段(盘前、盘中、盘后) + * 判断交易时段(盘前、盘中上午、午休、盘中下午、盘后) * @param {string} timestamp - 事件时间戳 - * @returns {'pre-market' | 'trading' | 'after-market'} + * @returns {'pre-market' | 'morning-trading' | 'lunch-break' | 'afternoon-trading' | 'after-market'} */ const getTradingPeriod = (timestamp) => { const eventTime = moment(timestamp); @@ -58,18 +58,30 @@ const DynamicNewsEventCard = ({ const minute = eventTime.minute(); const timeInMinutes = hour * 60 + minute; - // 盘中时间:09:30-11:30, 13:00-15:00 - const morningStart = 9 * 60 + 30; // 09:30 = 570分钟 - const morningEnd = 11 * 60 + 30; // 11:30 = 690分钟 - const afternoonStart = 13 * 60; // 13:00 = 780分钟 - const afternoonEnd = 15 * 60; // 15:00 = 900分钟 + // 时间常量 + const morningStart = 9 * 60 + 30; // 09:30 = 570分钟 + const morningEnd = 11 * 60 + 30; // 11:30 = 690分钟 + const lunchEnd = 13 * 60; // 13:00 = 780分钟 + const afternoonEnd = 15 * 60; // 15:00 = 900分钟 - if ((timeInMinutes >= morningStart && timeInMinutes < morningEnd) || - (timeInMinutes >= afternoonStart && timeInMinutes < afternoonEnd)) { - return 'trading'; - } else if (timeInMinutes < morningStart) { + // 盘中上午:09:30-11:30 + if (timeInMinutes >= morningStart && timeInMinutes < morningEnd) { + return 'morning-trading'; + } + // 午休:11:30-13:00 + else if (timeInMinutes >= morningEnd && timeInMinutes < lunchEnd) { + return 'lunch-break'; + } + // 盘中下午:13:00-15:00 + else if (timeInMinutes >= lunchEnd && timeInMinutes < afternoonEnd) { + return 'afternoon-trading'; + } + // 盘前:00:00-09:30 + else if (timeInMinutes < morningStart) { return 'pre-market'; - } else { + } + // 盘后:15:00-23:59 + else { return 'after-market'; } }; @@ -82,26 +94,34 @@ const DynamicNewsEventCard = ({ const getTimeLabelStyle = (period) => { switch (period) { case 'pre-market': - // 盘前:蓝色系 + // 盘前:粉红色系(浅红) return { - bg: useColorModeValue('blue.50', 'blue.900'), - borderColor: useColorModeValue('blue.400', 'blue.500'), - textColor: useColorModeValue('blue.600', 'blue.300'), + bg: useColorModeValue('pink.50', 'pink.900'), + borderColor: useColorModeValue('pink.300', 'pink.500'), + textColor: useColorModeValue('pink.600', 'pink.300'), }; - case 'trading': - // 盘中:绿色系(表示交易中) + case 'morning-trading': + case 'afternoon-trading': + // 盘中:红色系(强烈,表示交易活跃) return { - bg: useColorModeValue('green.50', 'green.900'), - borderColor: useColorModeValue('green.400', 'green.500'), - textColor: useColorModeValue('green.600', 'green.300'), + bg: useColorModeValue('red.50', 'red.900'), + borderColor: useColorModeValue('red.400', 'red.500'), + textColor: useColorModeValue('red.700', 'red.300'), }; - case 'after-market': - // 盘后:灰色系(市场关闭) + case 'lunch-break': + // 午休:灰色系(中性) return { bg: useColorModeValue('gray.100', 'gray.800'), borderColor: useColorModeValue('gray.400', 'gray.500'), textColor: useColorModeValue('gray.600', 'gray.400'), }; + case 'after-market': + // 盘后:橙色系(暖色但区别于盘中红色) + return { + bg: useColorModeValue('orange.50', 'orange.900'), + borderColor: useColorModeValue('orange.400', 'orange.500'), + textColor: useColorModeValue('orange.600', 'orange.300'), + }; default: return { bg: useColorModeValue('gray.100', 'gray.800'), @@ -111,61 +131,75 @@ const DynamicNewsEventCard = ({ } }; + /** + * 获取交易时段文字标签 + * @param {string} period - 交易时段 + * @returns {string} 时段文字标签 + */ + const getPeriodLabel = (period) => { + switch (period) { + case 'pre-market': + return '盘前'; + case 'morning-trading': + case 'afternoon-trading': + return '盘中'; + case 'lunch-break': + return '午休'; + case 'after-market': + return '盘后'; + default: + return ''; + } + }; + /** * 根据平均涨幅计算背景色(分级策略) * @param {number} avgChange - 平均涨跌幅 * @returns {string} Chakra UI 颜色值 */ const getChangeBasedBgColor = (avgChange) => { - // 如果没有涨跌幅数据,使用默认的奇偶行背景 - if (avgChange == null) { + // 转换为数字类型(处理可能的字符串类型数据) + 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'); } // 根据涨跌幅分级返回背景色 - if (avgChange >= 5) { + if (numChange >= 5) { return useColorModeValue('red.100', 'red.900'); - } else if (avgChange >= 3) { - return useColorModeValue('red.75', 'red.800'); - } else if (avgChange > 0) { + } else if (numChange >= 3) { + return useColorModeValue('red.100', 'red.800'); + } else if (numChange > 0) { return useColorModeValue('red.50', 'red.700'); - } else if (avgChange > -3) { + } else if (numChange > -3) { return useColorModeValue('green.50', 'green.700'); - } else if (avgChange > -5) { - return useColorModeValue('green.75', 'green.800'); + } else if (numChange > -5) { + return useColorModeValue('green.100', 'green.800'); } else { return useColorModeValue('green.100', 'green.900'); } }; - // 获取当前事件的交易时段和样式 + // 获取当前事件的交易时段、样式和文字标签 const tradingPeriod = getTradingPeriod(event.created_at); const timeLabelStyle = getTimeLabelStyle(tradingPeriod); + const periodLabel = getPeriodLabel(tradingPeriod); return ( - - {/* 时间标签 - 在卡片上方,宽度自适应,左对齐 */} - - - {moment(event.created_at).format('YYYY-MM-DD HH:mm')} - - + + {/* 事件卡片 */} {/* 左上角:重要性标签 */} - + + + {/* 时间标签 - 在卡片上方,宽度自适应,左对齐 */} + + + {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + {periodLabel && ( + <> + {' • '} + + {periodLabel} + + + )} + + {/* 右上角:关注按钮 */} @@ -207,7 +275,7 @@ const DynamicNewsEventCard = ({ - {/* 标题 - 最多两行,hover 显示完整内容 */} + {/* 标题 - 固定两行高度,保持卡片高度一致 */} onTitleClick?.(e, event)} mt={1} paddingRight="10px" + minHeight="2.8em" + display="flex" + alignItems="center" > {event.title} - - {/* 第二行:涨跌幅数据 */} - + + {/* 第二行:涨跌幅数据 */} + +