feat: 添加 EventScrollList.js 组件

This commit is contained in:
zdl
2025-11-03 11:42:04 +08:00
parent 6cde2175db
commit bdea4209b2
2 changed files with 184 additions and 149 deletions

View File

@@ -0,0 +1,175 @@
// src/views/Community/components/DynamicNewsCard/EventScrollList.js
// 横向滚动事件列表组件
import React, { useRef, useState } from 'react';
import {
Box,
Flex,
IconButton,
useColorModeValue
} from '@chakra-ui/react';
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
/**
* 横向滚动事件列表组件
* @param {Array} events - 事件列表
* @param {Object} selectedEvent - 当前选中的事件
* @param {Function} onEventSelect - 事件选择回调
* @param {string} borderColor - 边框颜色
*/
const EventScrollList = ({
events,
selectedEvent,
onEventSelect,
borderColor
}) => {
const scrollContainerRef = useRef(null);
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(true);
// 滚动到左侧
const scrollLeft = () => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollBy({
left: -400,
behavior: 'smooth'
});
}
};
// 滚动到右侧
const scrollRight = () => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollBy({
left: 400,
behavior: 'smooth'
});
}
};
// 监听滚动位置,更新箭头显示状态
const handleScroll = (e) => {
const container = e.target;
const scrollLeft = container.scrollLeft;
const scrollWidth = container.scrollWidth;
const clientWidth = container.clientWidth;
setShowLeftArrow(scrollLeft > 0);
setShowRightArrow(scrollLeft < scrollWidth - clientWidth - 10);
};
// 时间轴样式配置
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',
};
};
return (
<Box position="relative">
{/* 左侧滚动按钮 */}
{showLeftArrow && (
<IconButton
icon={<ChevronLeftIcon boxSize={6} />}
position="absolute"
left="-4"
top="50%"
transform="translateY(-50%)"
zIndex={2}
onClick={scrollLeft}
colorScheme="blue"
variant="solid"
size="md"
borderRadius="full"
shadow="md"
aria-label="向左滚动"
/>
)}
{/* 右侧滚动按钮 */}
{showRightArrow && (
<IconButton
icon={<ChevronRightIcon boxSize={6} />}
position="absolute"
right="-4"
top="50%"
transform="translateY(-50%)"
zIndex={2}
onClick={scrollRight}
colorScheme="blue"
variant="solid"
size="md"
borderRadius="full"
shadow="md"
aria-label="向右滚动"
/>
)}
{/* 横向滚动容器 */}
<Flex
ref={scrollContainerRef}
overflowX="auto"
overflowY="hidden"
gap={4}
py={4}
px={2}
onScroll={handleScroll}
css={{
'&::-webkit-scrollbar': {
height: '8px',
},
'&::-webkit-scrollbar-track': {
background: useColorModeValue('#f1f1f1', '#2D3748'),
borderRadius: '10px',
},
'&::-webkit-scrollbar-thumb': {
background: useColorModeValue('#888', '#4A5568'),
borderRadius: '10px',
},
'&::-webkit-scrollbar-thumb:hover': {
background: useColorModeValue('#555', '#718096'),
},
// 平滑滚动
scrollBehavior: 'smooth',
// 触摸设备优化
WebkitOverflowScrolling: 'touch',
}}
>
{events.map((event, index) => (
<Box
key={event.id}
minW="calc((100% - 64px) / 5)"
maxW="calc((100% - 64px) / 5)"
flexShrink={0}
>
<DynamicNewsEventCard
event={event}
index={index}
isFollowing={false}
followerCount={event.follower_count || 0}
isSelected={selectedEvent?.id === event.id}
onEventClick={(clickedEvent) => {
onEventSelect(clickedEvent);
}}
onTitleClick={(e) => {
e.preventDefault();
e.stopPropagation();
onEventSelect(event);
}}
onToggleFollow={() => {}}
timelineStyle={getTimelineBoxStyle()}
borderColor={borderColor}
/>
</Box>
))}
</Flex>
</Box>
);
};
export default EventScrollList;