community增加事件详情
This commit is contained in:
@@ -1,38 +1,27 @@
|
|||||||
// src/components/EventDetailPanel/CompactMetaBar.js
|
// src/components/EventDetailPanel/CompactMetaBar.js
|
||||||
// 精简信息栏组件(无头部模式下右上角显示)
|
// 精简信息栏组件(无头部模式下右上角显示)- 现代化设计
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
HStack,
|
HStack,
|
||||||
Badge,
|
Box,
|
||||||
Text,
|
Text,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useColorModeValue,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { EventFollowButton } from '@views/Community/components/EventCard/atoms';
|
import { EventFollowButton } from '@views/Community/components/EventCard/atoms';
|
||||||
import { Eye, ExternalLink } from 'lucide-react';
|
import { Eye, Share2, ExternalLink, CheckCircle, AlertTriangle, Flame, Zap } from 'lucide-react';
|
||||||
import ShareButton from '@components/ShareButton';
|
import ShareButton from '@components/ShareButton';
|
||||||
import { getEventDetailUrl } from '@utils/idEncoder';
|
import { getEventDetailUrl, encodeEventId } from '@utils/idEncoder';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 精简信息栏组件
|
* 精简信息栏组件
|
||||||
* 在无头部模式下,显示在 CardBody 右上角
|
* 在无头部模式下,显示在 CardBody 右上角
|
||||||
* 包含:重要性徽章、浏览次数、关注按钮
|
* 现代化毛玻璃设计风格
|
||||||
*
|
|
||||||
* @param {Object} props
|
|
||||||
* @param {Object} props.event - 事件对象
|
|
||||||
* @param {Object} props.importance - 重要性配置对象(包含 level, icon 等)
|
|
||||||
* @param {boolean} props.isFollowing - 是否已关注
|
|
||||||
* @param {number} props.followerCount - 关注数
|
|
||||||
* @param {Function} props.onToggleFollow - 切换关注回调
|
|
||||||
*/
|
*/
|
||||||
const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggleFollow }) => {
|
const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggleFollow }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const viewCountBg = useColorModeValue('white', 'gray.700');
|
|
||||||
const viewCountTextColor = useColorModeValue('gray.600', 'gray.300');
|
|
||||||
|
|
||||||
// 跳转到事件详情页
|
// 跳转到事件详情页
|
||||||
const handleViewDetail = () => {
|
const handleViewDetail = () => {
|
||||||
@@ -41,62 +30,104 @@ const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取重要性文本
|
// 重要性配置
|
||||||
const getImportanceText = () => {
|
const importanceConfig = {
|
||||||
const levelMap = {
|
'S': {
|
||||||
'S': '极高',
|
label: '极高',
|
||||||
'A': '高',
|
icon: Flame,
|
||||||
'B': '中',
|
gradient: 'linear(to-r, #FF416C, #FF4B2B)',
|
||||||
'C': '低'
|
glow: '0 0 20px rgba(255, 65, 108, 0.5)',
|
||||||
};
|
borderColor: 'rgba(255, 65, 108, 0.6)',
|
||||||
return levelMap[importance.level] || '中';
|
},
|
||||||
|
'A': {
|
||||||
|
label: '高',
|
||||||
|
icon: Zap,
|
||||||
|
gradient: 'linear(to-r, #F09819, #FF512F)',
|
||||||
|
glow: '0 0 15px rgba(240, 152, 25, 0.4)',
|
||||||
|
borderColor: 'rgba(240, 152, 25, 0.5)',
|
||||||
|
},
|
||||||
|
'B': {
|
||||||
|
label: '中',
|
||||||
|
icon: AlertTriangle,
|
||||||
|
gradient: 'linear(to-r, #4776E6, #8E54E9)',
|
||||||
|
glow: '0 0 12px rgba(71, 118, 230, 0.3)',
|
||||||
|
borderColor: 'rgba(71, 118, 230, 0.4)',
|
||||||
|
},
|
||||||
|
'C': {
|
||||||
|
label: '低',
|
||||||
|
icon: CheckCircle,
|
||||||
|
gradient: 'linear(to-r, #606c88, #3f4c6b)',
|
||||||
|
glow: 'none',
|
||||||
|
borderColor: 'rgba(96, 108, 136, 0.4)',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const config = importanceConfig[importance.level] || importanceConfig['C'];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack
|
<HStack
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={3}
|
top={3}
|
||||||
right={3}
|
right={3}
|
||||||
spacing={3}
|
spacing={2}
|
||||||
zIndex={1}
|
zIndex={1}
|
||||||
>
|
>
|
||||||
{/* 重要性徽章 - 与 EventHeaderInfo 样式一致,尺寸略小 - H5 隐藏 */}
|
{/* 重要性徽章 - 发光效果 */}
|
||||||
<Badge
|
<Tooltip label={`重要性:${config.label}`} hasArrow placement="bottom">
|
||||||
|
<Box
|
||||||
|
display={{ base: 'none', lg: 'flex' }}
|
||||||
|
alignItems="center"
|
||||||
|
gap={1.5}
|
||||||
px={3}
|
px={3}
|
||||||
py={1.5}
|
py={1.5}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
fontSize="sm"
|
bgGradient={config.gradient}
|
||||||
fontWeight="bold"
|
boxShadow={config.glow}
|
||||||
bgGradient={
|
border="1px solid"
|
||||||
importance.level === 'S' ? 'linear(to-r, red.500, red.700)' :
|
borderColor={config.borderColor}
|
||||||
importance.level === 'A' ? 'linear(to-r, orange.500, orange.700)' :
|
cursor="default"
|
||||||
importance.level === 'B' ? 'linear(to-r, blue.500, blue.700)' :
|
transition="all 0.3s ease"
|
||||||
'linear(to-r, gray.500, gray.700)'
|
_hover={{
|
||||||
}
|
transform: 'scale(1.05)',
|
||||||
color="white"
|
boxShadow: config.glow.replace('0.5', '0.7').replace('0.4', '0.6').replace('0.3', '0.5'),
|
||||||
boxShadow="lg"
|
}}
|
||||||
display={{ base: 'none', lg: 'flex' }}
|
|
||||||
alignItems="center"
|
|
||||||
gap={1}
|
|
||||||
>
|
>
|
||||||
<Icon as={importance.icon} boxSize={4} />
|
<Icon as={config.icon} boxSize={4} color="white" />
|
||||||
<Text>重要性:{getImportanceText()}</Text>
|
<Text fontSize="sm" fontWeight="bold" color="white" letterSpacing="wide">
|
||||||
</Badge>
|
{config.label}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{/* 浏览次数 - 添加容器背景以提高可读性 */}
|
{/* 统计信息容器 - 毛玻璃效果 */}
|
||||||
<HStack
|
<HStack
|
||||||
spacing={1}
|
spacing={0}
|
||||||
bg={viewCountBg}
|
bg="rgba(0, 0, 0, 0.4)"
|
||||||
px={2}
|
backdropFilter="blur(10px)"
|
||||||
py={1}
|
borderRadius="full"
|
||||||
borderRadius="md"
|
border="1px solid rgba(255, 255, 255, 0.1)"
|
||||||
boxShadow="sm"
|
overflow="hidden"
|
||||||
|
boxShadow="0 4px 15px rgba(0, 0, 0, 0.2)"
|
||||||
>
|
>
|
||||||
<Icon as={Eye} boxSize={4} color="gray.400" />
|
{/* 浏览量 */}
|
||||||
<Text fontSize="sm" color={viewCountTextColor} whiteSpace="nowrap">
|
<Tooltip label="浏览量" hasArrow placement="bottom">
|
||||||
|
<HStack
|
||||||
|
spacing={1.5}
|
||||||
|
px={3}
|
||||||
|
py={1.5}
|
||||||
|
cursor="default"
|
||||||
|
_hover={{ bg: 'rgba(255, 255, 255, 0.1)' }}
|
||||||
|
transition="all 0.2s"
|
||||||
|
>
|
||||||
|
<Icon as={Eye} boxSize={4} color="cyan.400" />
|
||||||
|
<Text fontSize="sm" fontWeight="semibold" color="white">
|
||||||
{(event.view_count || 0).toLocaleString()}
|
{(event.view_count || 0).toLocaleString()}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{/* 分隔线 */}
|
||||||
|
<Box h="20px" w="1px" bg="rgba(255, 255, 255, 0.15)" />
|
||||||
|
|
||||||
{/* 关注按钮 */}
|
{/* 关注按钮 */}
|
||||||
<EventFollowButton
|
<EventFollowButton
|
||||||
@@ -105,35 +136,67 @@ const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggl
|
|||||||
onToggle={onToggleFollow}
|
onToggle={onToggleFollow}
|
||||||
size="sm"
|
size="sm"
|
||||||
showCount={true}
|
showCount={true}
|
||||||
|
variant="minimal"
|
||||||
/>
|
/>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
{/* 分享按钮 - 复制链接 */}
|
{/* 操作按钮组 - 毛玻璃效果 */}
|
||||||
|
<HStack
|
||||||
|
spacing={0}
|
||||||
|
bg="rgba(0, 0, 0, 0.4)"
|
||||||
|
backdropFilter="blur(10px)"
|
||||||
|
borderRadius="full"
|
||||||
|
border="1px solid rgba(255, 255, 255, 0.1)"
|
||||||
|
overflow="hidden"
|
||||||
|
boxShadow="0 4px 15px rgba(0, 0, 0, 0.2)"
|
||||||
|
>
|
||||||
|
{/* 分享按钮 */}
|
||||||
<ShareButton
|
<ShareButton
|
||||||
title={event.title}
|
title={event.title}
|
||||||
desc={event.description?.slice(0, 100) || ''}
|
desc={event.description?.slice(0, 100) || ''}
|
||||||
link={`${window.location.origin}/community?event=${event.id}`}
|
link={`${window.location.origin}/event-detail?id=${encodeEventId(event.id)}`}
|
||||||
imgUrl={`${window.location.origin}/logo192.png`}
|
imgUrl={`${window.location.origin}/logo192.png`}
|
||||||
variant="icon"
|
>
|
||||||
size="sm"
|
<Tooltip label="分享事件" hasArrow placement="bottom">
|
||||||
colorScheme="teal"
|
<HStack
|
||||||
/>
|
spacing={1.5}
|
||||||
|
px={3}
|
||||||
|
py={1.5}
|
||||||
|
cursor="pointer"
|
||||||
|
_hover={{ bg: 'rgba(255, 255, 255, 0.1)' }}
|
||||||
|
transition="all 0.2s"
|
||||||
|
>
|
||||||
|
<Icon as={Share2} boxSize={4} color="teal.400" />
|
||||||
|
<Text fontSize="sm" fontWeight="medium" color="gray.300" display={{ base: 'none', md: 'block' }}>
|
||||||
|
分享
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
</Tooltip>
|
||||||
|
</ShareButton>
|
||||||
|
|
||||||
|
{/* 分隔线 */}
|
||||||
|
<Box h="20px" w="1px" bg="rgba(255, 255, 255, 0.15)" />
|
||||||
|
|
||||||
{/* 查看详情按钮 */}
|
{/* 查看详情按钮 */}
|
||||||
<Tooltip label="在新页面查看完整详情" hasArrow>
|
<Tooltip label="在新页面查看完整详情" hasArrow placement="bottom">
|
||||||
<IconButton
|
<HStack
|
||||||
icon={<Icon as={ExternalLink} boxSize={4} />}
|
as="button"
|
||||||
aria-label="查看事件详情"
|
spacing={1.5}
|
||||||
size="sm"
|
px={3}
|
||||||
variant="ghost"
|
py={1.5}
|
||||||
color="blue.300"
|
cursor="pointer"
|
||||||
onClick={handleViewDetail}
|
onClick={handleViewDetail}
|
||||||
_hover={{
|
_hover={{ bg: 'rgba(255, 255, 255, 0.1)' }}
|
||||||
bg: 'blue.500',
|
transition="all 0.2s"
|
||||||
color: 'white',
|
>
|
||||||
}}
|
<Icon as={ExternalLink} boxSize={4} color="blue.400" />
|
||||||
/>
|
<Text fontSize="sm" fontWeight="medium" color="gray.300" display={{ base: 'none', md: 'block' }}>
|
||||||
|
详情
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
</HStack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// src/views/Community/components/EventCard/atoms/EventFollowButton.js
|
// src/views/Community/components/EventCard/atoms/EventFollowButton.js
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IconButton, Box } from '@chakra-ui/react';
|
import { IconButton, Box, HStack, Text, Tooltip } from '@chakra-ui/react';
|
||||||
import { Star } from 'lucide-react';
|
import { Star } from 'lucide-react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,13 +11,15 @@ import { Star } from 'lucide-react';
|
|||||||
* @param {Function} props.onToggle - 切换关注状态的回调函数
|
* @param {Function} props.onToggle - 切换关注状态的回调函数
|
||||||
* @param {string} props.size - 按钮尺寸('xs' | 'sm' | 'md',默认 'sm')
|
* @param {string} props.size - 按钮尺寸('xs' | 'sm' | 'md',默认 'sm')
|
||||||
* @param {boolean} props.showCount - 是否显示关注数(默认 true)
|
* @param {boolean} props.showCount - 是否显示关注数(默认 true)
|
||||||
|
* @param {string} props.variant - 样式变体('default' | 'minimal',默认 'default')
|
||||||
*/
|
*/
|
||||||
const EventFollowButton = ({
|
const EventFollowButton = ({
|
||||||
isFollowing,
|
isFollowing,
|
||||||
followerCount = 0,
|
followerCount = 0,
|
||||||
onToggle,
|
onToggle,
|
||||||
size = 'sm',
|
size = 'sm',
|
||||||
showCount = true
|
showCount = true,
|
||||||
|
variant = 'default'
|
||||||
}) => {
|
}) => {
|
||||||
const iconSize = size === 'xs' ? '16px' : size === 'sm' ? '18px' : '22px';
|
const iconSize = size === 'xs' ? '16px' : size === 'sm' ? '18px' : '22px';
|
||||||
|
|
||||||
@@ -26,6 +28,41 @@ const EventFollowButton = ({
|
|||||||
onToggle?.();
|
onToggle?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 最小样式 - 用于毛玻璃容器内
|
||||||
|
if (variant === 'minimal') {
|
||||||
|
return (
|
||||||
|
<Tooltip label={isFollowing ? '取消关注' : '关注事件'} hasArrow placement="bottom">
|
||||||
|
<HStack
|
||||||
|
as="button"
|
||||||
|
spacing={1.5}
|
||||||
|
px={3}
|
||||||
|
py={1.5}
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={handleClick}
|
||||||
|
_hover={{ bg: 'rgba(255, 255, 255, 0.1)' }}
|
||||||
|
transition="all 0.2s"
|
||||||
|
>
|
||||||
|
<Star
|
||||||
|
size={iconSize}
|
||||||
|
color={isFollowing ? "#FFD700" : "#A0AEC0"}
|
||||||
|
fill={isFollowing ? "#FFD700" : "none"}
|
||||||
|
style={{ transition: 'all 0.2s' }}
|
||||||
|
/>
|
||||||
|
{showCount && (
|
||||||
|
<Text
|
||||||
|
fontSize="sm"
|
||||||
|
fontWeight="semibold"
|
||||||
|
color={isFollowing ? "yellow.400" : "white"}
|
||||||
|
>
|
||||||
|
{followerCount || 0}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认样式
|
||||||
return (
|
return (
|
||||||
<Box display="inline-flex" alignItems="center" gap={1}>
|
<Box display="inline-flex" alignItems="center" gap={1}>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -48,9 +85,6 @@ const EventFollowButton = ({
|
|||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
aria-label={isFollowing ? '取消关注' : '关注'}
|
aria-label={isFollowing ? '取消关注' : '关注'}
|
||||||
/>
|
/>
|
||||||
{/* <Box fontSize="xs" color="gray.500">
|
|
||||||
{followerCount || 0}
|
|
||||||
</Box> */}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user