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