diff --git a/src/views/Community/components/EventCard/EventDescription.js b/src/views/Community/components/EventCard/EventDescription.js new file mode 100644 index 00000000..0554bfe0 --- /dev/null +++ b/src/views/Community/components/EventCard/EventDescription.js @@ -0,0 +1,56 @@ +// src/views/Community/components/EventCard/EventDescription.js +import React, { useState } from 'react'; +import { Box, Text, Button } from '@chakra-ui/react'; + +/** + * 事件描述组件(支持展开/收起) + * @param {Object} props + * @param {string} props.description - 描述文本 + * @param {string} props.textColor - 文字颜色 + * @param {number} props.minLength - 触发展开/收起的最小长度(默认 120) + * @param {number} props.noOfLines - 未展开时显示的行数(默认 3) + */ +const EventDescription = ({ + description, + textColor, + minLength = 120, + noOfLines = 3 +}) => { + const [isExpanded, setIsExpanded] = useState(false); + + // 如果没有描述,不渲染 + if (!description) { + return null; + } + + const handleToggle = (e) => { + e.stopPropagation(); + setIsExpanded(!isExpanded); + }; + + return ( + + + {description} + + {description.length > minLength && ( + + )} + + ); +}; + +export default EventDescription; diff --git a/src/views/Community/components/EventCard/EventFollowButton.js b/src/views/Community/components/EventCard/EventFollowButton.js new file mode 100644 index 00000000..9b7a3e3c --- /dev/null +++ b/src/views/Community/components/EventCard/EventFollowButton.js @@ -0,0 +1,43 @@ +// src/views/Community/components/EventCard/EventFollowButton.js +import React from 'react'; +import { Button } from '@chakra-ui/react'; +import { StarIcon } from '@chakra-ui/icons'; + +/** + * 事件关注按钮组件 + * @param {Object} props + * @param {boolean} props.isFollowing - 是否已关注 + * @param {number} props.followerCount - 关注数 + * @param {Function} props.onToggle - 切换关注状态的回调函数 + * @param {string} props.size - 按钮尺寸('xs' | 'sm' | 'md',默认 'sm') + * @param {boolean} props.showCount - 是否显示关注数(默认 true) + */ +const EventFollowButton = ({ + isFollowing, + followerCount = 0, + onToggle, + size = 'sm', + showCount = true +}) => { + const iconSize = size === 'xs' ? '10px' : '12px'; + + const handleClick = (e) => { + e.stopPropagation(); + onToggle?.(); + }; + + return ( + + ); +}; + +export default EventFollowButton; diff --git a/src/views/Community/components/EventCard/EventImportanceBadge.js b/src/views/Community/components/EventCard/EventImportanceBadge.js new file mode 100644 index 00000000..7470f795 --- /dev/null +++ b/src/views/Community/components/EventCard/EventImportanceBadge.js @@ -0,0 +1,96 @@ +// src/views/Community/components/EventCard/EventImportanceBadge.js +import React from 'react'; +import { Badge, Tooltip, VStack, HStack, Text, Divider, Circle } from '@chakra-ui/react'; +import { InfoIcon } from '@chakra-ui/icons'; +import { getImportanceConfig, getAllImportanceLevels } from '../../../../constants/importanceLevels'; + +/** + * 事件重要性等级标签组件 + * @param {Object} props + * @param {string} props.importance - 重要性等级(S/A/B/C/D) + * @param {boolean} props.showTooltip - 是否显示详细提示框(默认 false) + * @param {boolean} props.showIcon - 是否显示信息图标(默认 false) + * @param {string} props.size - 标签大小(xs/sm/md/lg,默认 xs) + */ +const EventImportanceBadge = ({ + importance, + showTooltip = false, + showIcon = false, + size = 'xs' +}) => { + const importanceConfig = getImportanceConfig(importance); + + // 简单模式:只显示标签 + if (!showTooltip) { + return ( + + {importance || 'C'}级 + + ); + } + + // 详细模式:带提示框的标签 + return ( + + + 重要性等级说明 + + + {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" + > + + {showIcon && } + {importance || 'C'}级 + + + ); +}; + +export default EventImportanceBadge; diff --git a/src/views/Community/components/EventCard/EventPriceDisplay.js b/src/views/Community/components/EventCard/EventPriceDisplay.js new file mode 100644 index 00000000..54371cec --- /dev/null +++ b/src/views/Community/components/EventCard/EventPriceDisplay.js @@ -0,0 +1,121 @@ +// src/views/Community/components/EventCard/EventPriceDisplay.js +import React from 'react'; +import { HStack, Badge, Text, Tooltip } from '@chakra-ui/react'; +import { PriceArrow } from '../../../../utils/priceFormatters'; + +/** + * 事件价格变动显示组件 + * @param {Object} props + * @param {number|null} props.avgChange - 平均涨跌幅 + * @param {number|null} props.maxChange - 最大涨跌幅 + * @param {number|null} props.weekChange - 周涨跌幅 + * @param {boolean} props.compact - 是否为紧凑模式(只显示平均值,默认 false) + * @param {boolean} props.inline - 是否内联显示(默认 false) + */ +const EventPriceDisplay = ({ + avgChange, + maxChange, + weekChange, + compact = false, + inline = false +}) => { + // 获取颜色方案 + const getColorScheme = (value) => { + if (value == null) return 'gray'; + return value > 0 ? 'red' : value < 0 ? 'green' : 'gray'; + }; + + // 格式化百分比 + const formatPercent = (value) => { + if (value == null) return '--'; + return `${value > 0 ? '+' : ''}${value.toFixed(2)}%`; + }; + + // 紧凑模式:只显示平均值,内联在标题后 + if (compact && avgChange != null) { + return ( + + + + {formatPercent(avgChange)} + + + ); + } + + // 详细模式:显示所有价格变动 + return ( + + {/* 平均涨幅 - 始终显示,无数据时显示 -- */} + + + 平均 + + {formatPercent(avgChange)} + + + + + {/* 最大涨幅 - 始终显示,无数据时显示 -- */} + + + 最大 + + {formatPercent(maxChange)} + + + + + {/* 周涨幅 - 始终显示,无数据时显示 -- */} + + + + {weekChange != null && } + + {formatPercent(weekChange)} + + + + + ); +}; + +export default EventPriceDisplay; diff --git a/src/views/Community/components/EventCard/EventStats.js b/src/views/Community/components/EventCard/EventStats.js new file mode 100644 index 00000000..f97cdce4 --- /dev/null +++ b/src/views/Community/components/EventCard/EventStats.js @@ -0,0 +1,58 @@ +// src/views/Community/components/EventCard/EventStats.js +import React from 'react'; +import { HStack, Text, Tooltip } from '@chakra-ui/react'; +import { ViewIcon, ChatIcon, StarIcon } from '@chakra-ui/icons'; + +/** + * 事件统计信息组件(浏览量、帖子数、关注数) + * @param {Object} props + * @param {number} props.viewCount - 浏览量 + * @param {number} props.postCount - 帖子数 + * @param {number} props.followerCount - 关注数 + * @param {string} props.size - 尺寸('sm' | 'md',默认 'sm') + * @param {number} props.spacing - 间距(默认 3) + * @param {Object} props.display - 响应式显示控制(默认 { base: 'none', md: 'flex' }) + * @param {string} props.mutedColor - 文字颜色(可选) + */ +const EventStats = ({ + viewCount = 0, + postCount = 0, + followerCount = 0, + size = 'sm', + spacing = 3, + display = { base: 'none', md: 'flex' }, + mutedColor +}) => { + const fontSize = size === 'sm' ? 'xs' : 'sm'; + const iconSize = size === 'sm' ? '12px' : '16px'; + + return ( + + {/* 浏览量 */} + + + + {viewCount} + + + + {/* 帖子数 */} + + + + {postCount} + + + + {/* 关注数 */} + + + + {followerCount} + + + + ); +}; + +export default EventStats; diff --git a/src/views/Community/components/EventCard/EventTimeline.js b/src/views/Community/components/EventCard/EventTimeline.js new file mode 100644 index 00000000..d2bfdce0 --- /dev/null +++ b/src/views/Community/components/EventCard/EventTimeline.js @@ -0,0 +1,62 @@ +// src/views/Community/components/EventCard/EventTimeline.js +import React from 'react'; +import { Box, VStack, Text, useColorModeValue } from '@chakra-ui/react'; +import moment from 'moment'; + +/** + * 事件时间轴组件 + * @param {Object} props + * @param {string} props.createdAt - 事件创建时间 + * @param {Object} props.timelineStyle - 时间轴样式配置 + * @param {string} props.borderColor - 竖线边框颜色 + * @param {string} props.minHeight - 竖线最小高度(例如:'40px' 或 '80px') + */ +const EventTimeline = ({ createdAt, timelineStyle, borderColor, minHeight = '40px' }) => { + return ( + + {/* 时间长方形卡片 */} + + {/* 日期 YYYY-MM-DD */} + + {moment(createdAt).format('YYYY-MM-DD')} + + {/* 时间 HH:mm */} + + {moment(createdAt).format('HH:mm')} + + + {/* 时间轴竖线 */} + + + ); +}; + +export default EventTimeline;