feat: 虚拟化网格组件通用化 │ │
│ │ │ │ │ │ - 支持多列布局(columnsPerRow 参数,默认4列) │ │ │ │ - 支持自定义卡片组件(CardComponent 参数) │ │ │ │ - 根据列数动态调整间距(单列 gap=3,多列 gap=4) │ │ │ │ - 更新注释和文档
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// src/views/Community/components/DynamicNewsCard/VirtualizedFourRowGrid.js
|
||||
// 四列纵向滚动虚拟化网格组件(每行4列,纵向滚动 + 无限滚动)
|
||||
// 虚拟化网格组件(支持多列布局 + 纵向滚动 + 无限滚动)
|
||||
|
||||
import React, { useRef, useMemo, useEffect } from 'react';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
@@ -8,9 +8,11 @@ import { useColorModeValue } from '@chakra-ui/react';
|
||||
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
|
||||
/**
|
||||
* 四列纵向滚动虚拟化网格组件(支持无限滚动)
|
||||
* 虚拟化网格组件(支持多列布局 + 无限滚动)
|
||||
* @param {Object} props
|
||||
* @param {Array} props.events - 事件列表(累积显示)
|
||||
* @param {number} props.columnsPerRow - 每行列数(默认 4,单列模式传 1)
|
||||
* @param {React.Component} props.CardComponent - 卡片组件(默认 DynamicNewsEventCard)
|
||||
* @param {Object} props.selectedEvent - 当前选中的事件
|
||||
* @param {Function} props.onEventSelect - 事件选择回调
|
||||
* @param {Object} props.eventFollowStatus - 事件关注状态
|
||||
@@ -23,6 +25,8 @@ import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
*/
|
||||
const VirtualizedFourRowGrid = ({
|
||||
events,
|
||||
columnsPerRow = 4,
|
||||
CardComponent = DynamicNewsEventCard,
|
||||
selectedEvent,
|
||||
onEventSelect,
|
||||
eventFollowStatus,
|
||||
@@ -41,14 +45,14 @@ const VirtualizedFourRowGrid = ({
|
||||
const scrollbarThumbBg = useColorModeValue('#888', '#4A5568');
|
||||
const scrollbarThumbHoverBg = useColorModeValue('#555', '#718096');
|
||||
|
||||
// 将事件按4个一组分成行(每行4列)
|
||||
// 将事件按 columnsPerRow 个一组分成行
|
||||
const rows = useMemo(() => {
|
||||
const r = [];
|
||||
for (let i = 0; i < events.length; i += 4) {
|
||||
r.push(events.slice(i, i + 4));
|
||||
for (let i = 0; i < events.length; i += columnsPerRow) {
|
||||
r.push(events.slice(i, i + columnsPerRow));
|
||||
}
|
||||
return r;
|
||||
}, [events]);
|
||||
}, [events, columnsPerRow]);
|
||||
|
||||
// 配置虚拟滚动器(纵向滚动 + 动态高度测量)
|
||||
const rowVirtualizer = useVirtualizer({
|
||||
@@ -159,17 +163,17 @@ const VirtualizedFourRowGrid = ({
|
||||
w="100%"
|
||||
transform={`translateY(${virtualRow.start}px)`}
|
||||
>
|
||||
{/* 每行使用 Grid 横向排列4个卡片 */}
|
||||
{/* 使用 Grid 横向排列卡片(列数由 columnsPerRow 决定) */}
|
||||
<Grid
|
||||
templateColumns="repeat(4, 1fr)"
|
||||
gap={4}
|
||||
templateColumns={`repeat(${columnsPerRow}, 1fr)`}
|
||||
gap={columnsPerRow === 1 ? 3 : 4}
|
||||
w="100%"
|
||||
>
|
||||
{rowEvents.map((event, colIndex) => (
|
||||
<Box key={event.id}>
|
||||
<DynamicNewsEventCard
|
||||
<CardComponent
|
||||
event={event}
|
||||
index={virtualRow.index * 4 + colIndex}
|
||||
index={virtualRow.index * columnsPerRow + colIndex}
|
||||
isFollowing={eventFollowStatus[event.id]?.isFollowing || false}
|
||||
followerCount={eventFollowStatus[event.id]?.followerCount || event.follower_count || 0}
|
||||
isSelected={selectedEvent?.id === event.id}
|
||||
@@ -182,7 +186,7 @@ const VirtualizedFourRowGrid = ({
|
||||
onEventSelect(event);
|
||||
}}
|
||||
onToggleFollow={() => onToggleFollow?.(event.id)}
|
||||
timelineStyle={getTimelineBoxStyle()}
|
||||
timelineStyle={getTimelineBoxStyle?.()}
|
||||
borderColor={borderColor}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user