diff --git a/src/views/Community/components/EventList.js b/src/views/Community/components/EventList.js index 9a2a4943..71a31750 100644 --- a/src/views/Community/components/EventList.js +++ b/src/views/Community/components/EventList.js @@ -413,124 +413,208 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai navigate(`/event-detail/${eventId}`); }; - // 精简模式的事件渲染 - const renderCompactEvent = (event) => { + // 时间轴样式配置(固定使用轻量卡片样式) + const getTimelineBoxStyle = () => { + return { + bg: useColorModeValue('gray.50', 'gray.700'), + borderColor: useColorModeValue('gray.400', 'gray.500'), + borderWidth: '2px', + textColor: useColorModeValue('blue.600', 'blue.400'), + boxShadow: 'sm', + }; + }; + + // 精简模式的事件渲染(优化版:标题2行+标签内联+按钮右侧) + const renderCompactEvent = (event, index) => { const importance = getImportanceConfig(event.importance); const isFollowing = !!followingMap[event.id]; const followerCount = followCountMap[event.id] ?? (event.follower_count || 0); + const timelineStyle = getTimelineBoxStyle(); return ( - - {/* 时间线和重要性标记 */} - - + {/* 左侧时间轴 - 动态样式 */} + + {/* 时间长方形卡片 */} + - {event.importance || 'C'} - + {/* 日期 YYYY-MM-DD */} + + {moment(event.created_at).format('YYYY-MM-DD')} + + {/* 时间 HH:mm */} + + {moment(event.created_at).format('HH:mm')} + + + {/* 时间轴竖线 */} - {/* 精简事件卡片 */} + {/* 右侧内容卡片 */} onEventClick(event)} - mb={3} + mb={2} > - - - {/* 左侧:标题和时间 */} - - handleTitleClick(e, event)} - cursor="pointer" - noOfLines={1} - > - {event.title} - - - - {moment(event.created_at).format('MM-DD HH:mm')} - - {event.creator?.username || 'Anonymous'} - - - - {/* 右侧:涨跌幅指标 */} - - - + + {/* 第一行:标题(2行)+ 标签(内联)+ 按钮(右侧) */} + + {/* 标题区域:标题+标签(内联) */} + + handleTitleClick(e, event)} + cursor="pointer" + > + {event.title} + + {' '} + {/* 重要性标签 - 内联 */} + - - - + {' '} + {/* 涨跌幅标签 - 内联 */} + {event.related_avg_chg != null && ( + + 0 ? 'red' : 'green'} + fontSize="xs" + px={2} + py={1} + borderRadius="md" fontWeight="bold" - color={getPriceChangeColor(event.related_avg_chg)} + display="inline-flex" + alignItems="center" + gap={1} + verticalAlign="middle" > - {event.related_avg_chg != null - ? `${event.related_avg_chg > 0 ? '+' : ''}${event.related_avg_chg.toFixed(2)}%` - : '--'} - - - - + + {event.related_avg_chg > 0 ? '+' : ''}{event.related_avg_chg.toFixed(2)}% + + + )} + - - - - + {/* 操作按钮 - 固定右侧 */} + + + + + + + {/* 第二行:统计数据(左) + 作者时间(右) */} + + {/* 左侧:统计数据 */} + + + + + {event.view_count || 0} + + + + + + + {event.post_count || 0} + + + + + + + {followerCount} + + + + + {/* 右侧:作者 + 时间(统一格式 YYYY-MM-DD HH:mm) */} + + @{event.creator?.username || 'Anonymous'} + + + {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + + + + @@ -542,28 +626,52 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai const importance = getImportanceConfig(event.importance); const isFollowing = !!followingMap[event.id]; const followerCount = followCountMap[event.id] ?? (event.follower_count || 0); + const timelineStyle = getTimelineBoxStyle(); return ( - - {/* 时间线和重要性标记 */} - - + {/* 左侧时间轴 - 动态样式 */} + + {/* 时间长方形卡片 */} + - {event.importance || 'C'} - + {/* 日期 YYYY-MM-DD */} + + {moment(event.created_at).format('YYYY-MM-DD')} + + {/* 时间 HH:mm */} + + {moment(event.created_at).format('HH:mm')} + + + {/* 时间轴竖线 */} @@ -573,264 +681,122 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai bg={cardBg} borderWidth="1px" borderColor={borderColor} - borderRadius="lg" + borderRadius="md" boxShadow="sm" _hover={{ - boxShadow: 'md', - transform: 'translateY(-2px)', + boxShadow: 'xl', + transform: 'translateY(-3px)', borderColor: importance.color, }} - transition="all 0.2s" + transition="all 0.3s ease" cursor="pointer" onClick={() => onEventClick(event)} - mb={4} + mb={3} > - - - {/* 标题和重要性标签 */} - - - handleTitleClick(e, event)} - cursor="pointer" + + + {/* 第一行:标题+优先级 | 统计+关注 */} + + {/* 左侧:标题 + 优先级标签 */} + + - {event.title} - - - - - 重要性等级说明 - - - {getAllImportanceLevels().map((level) => ( - - - - {level.level}级 - {level.description} - - - ))} - - } - placement="left" - hasArrow - bg="white" - color="gray.800" - fontSize="md" - p={3} - borderRadius="lg" - borderWidth="1px" - borderColor="gray.200" - boxShadow="lg" - > - handleTitleClick(e, event)} + cursor="pointer" + > + {event.title} + + + + + + 重要性等级说明 + + + {getAllImportanceLevels().map((level) => ( + + + + {level.level}级 + {level.description} + + + ))} + + } + placement="top" + hasArrow + bg="white" + color="gray.800" + fontSize="md" + p={3} + borderRadius="lg" + borderWidth="1px" + borderColor="gray.200" + boxShadow="lg" > - - {importance.label}优先级 - - - - - {/* 元信息 */} - - - - {moment(event.created_at).format('YYYY-MM-DD HH:mm')} - - - {event.creator?.username || 'Anonymous'} - - - {/* 描述 */} - - {event.description} - - - {/* 价格变化指标 */} - - - - - - - 平均 - - - {event.related_avg_chg != null ? ( - - - - {event.related_avg_chg > 0 ? '+' : ''}{event.related_avg_chg.toFixed(2)}% - - - ) : ( - -- - )} - - - - - - - - - - 最大 - - - {event.related_max_chg != null ? ( - - - - {event.related_max_chg > 0 ? '+' : ''}{event.related_max_chg.toFixed(2)}% - - - ) : ( - -- - )} - - - - - - - - - - 周 - - - {event.related_week_chg != null ? ( - - - - {event.related_week_chg > 0 ? '+' : ''}{event.related_week_chg.toFixed(2)}% - - - ) : ( - -- - )} - - - - - - - - - - {/* 统计信息和操作按钮 */} - - - - - - {event.view_count || 0} - - - - - - {event.post_count || 0} - - - - - - {followerCount} - + + {event.importance || 'C'}级 + - - - + {/* 右侧:统计数据 + 关注按钮 */} + + {/* 统计数据 */} + + + + + {event.view_count || 0} + + + + + + {event.post_count || 0} + + + + + + {followerCount} + + + + + {/* 关注按钮 */} - + + + {/* 第二行:价格标签 | 时间+作者 */} + + {/* 左侧:价格标签 */} + + {/* 平均涨幅 - 始终显示,无数据时显示 -- */} + 0 ? 'red' : event.related_avg_chg < 0 ? 'green' : 'gray') + : 'gray'} + fontSize="xs" + px={2} + py={0.5} + borderRadius="md" + cursor="pointer" + _hover={{ transform: 'scale(1.05)', boxShadow: 'md' }} + transition="all 0.2s" + > + + 平均 + + {event.related_avg_chg != null + ? `${event.related_avg_chg > 0 ? '+' : ''}${event.related_avg_chg.toFixed(2)}%` + : '--'} + + + + + {/* 最大涨幅 - 始终显示,无数据时显示 -- */} + 0 ? 'red' : event.related_max_chg < 0 ? 'green' : 'gray') + : 'gray'} + fontSize="xs" + px={2} + py={0.5} + borderRadius="md" + cursor="pointer" + _hover={{ transform: 'scale(1.05)', boxShadow: 'md' }} + transition="all 0.2s" + > + + 最大 + + {event.related_max_chg != null + ? `${event.related_max_chg > 0 ? '+' : ''}${event.related_max_chg.toFixed(2)}%` + : '--'} + + + + + {/* 周涨幅 - 始终显示,无数据时显示 -- */} + 0 ? 'red' : event.related_week_chg < 0 ? 'green' : 'gray') + : 'gray'} + fontSize="xs" + px={2} + py={0.5} + borderRadius="md" + cursor="pointer" + _hover={{ transform: 'scale(1.05)', boxShadow: 'md' }} + transition="all 0.2s" + > + + + {event.related_week_chg != null && } + + {event.related_week_chg != null + ? `${event.related_week_chg > 0 ? '+' : ''}${event.related_week_chg.toFixed(2)}%` + : '--'} + + + + + + {/* 右侧:时间 + 作者 */} + + + {moment(event.created_at).format('YYYY-MM-DD HH:mm')} + + + @{event.creator?.username || 'Anonymous'} + + + + {/* 第三行:描述文字 + 展开/收起 */} + {event.description && ( + + + {event.description} + + {event.description.length > 120 && ( + + )} + + )} @@ -946,47 +1028,117 @@ const EventList = ({ events, pagination, onPageChange, onEventClick, onViewDetai return ( - - {/* 顶部控制栏:连接状态 + 视图切换 */} - - {/* WebSocket 连接状态指示器 */} - - - {isConnected ? '🟢 实时推送已开启' : '🔴 实时推送未连接'} - - {isConnected && ( - - 新事件将自动推送 - + {/* 顶部控制栏:左空白 + 中间分页器 + 右侧控制(固定sticky) - 铺满全宽 */} + + + + {/* 左侧占位 */} + + + {/* 中间:分页器 */} + {pagination.total > 0 && localEvents.length > 0 ? ( + + + + 第 {pagination.current} / {Math.ceil(pagination.total / pagination.pageSize)} 页 + + + + 共 {pagination.total} 条 + + + ) : ( + )} - - {/* 视图切换控制 */} - - - 精简模式 - - setIsCompactMode(e.target.checked)} - colorScheme="blue" - /> - - + {/* 右侧:控制按钮 */} + + {/* WebSocket 连接状态 */} + + {isConnected ? '🟢 实时' : '🔴 离线'} + + {/* 桌面推送开关 */} + + + 推送 + + + + + + + {/* 视图切换控制 */} + + + 精简 + + setIsCompactMode(e.target.checked)} + colorScheme="blue" + /> + + + + + + + {/* 事件列表内容 */} + {localEvents.length > 0 ? ( {localEvents.map((event, index) => ( {isCompactMode - ? renderCompactEvent(event) + ? renderCompactEvent(event, index) : renderDetailedEvent(event) }