feat: 集成四排/纵向模式UI和优化交互逻辑
VirtualizedFourRowGrid: - 组件通用化,支持多列布局(通过 columnsPerRow 参数配置) - 支持自定义卡片组件(通过 CardComponent 参数传入) - 根据列数动态调整间距 EventScrollList: - 添加四排和纵向模式切换按钮 - 集成 VirtualizedFourRowGrid 组件(四排模式使用4列,纵向模式使用1列) - 添加纵向分栏布局(1:2 比例,左侧列表+右侧详情) - 启用纵向滚动和统一滚动条样式 - 接收新 props: displayEvents, isAccumulateMode, loadNextPage, onFourRowEventClick DynamicNewsCard: - 添加 Modal 弹窗显示四排模式详情 - 优化自动选中逻辑: · 首次加载时自动选中第一个事件 · 翻页时,单排/双排/纵向模式自动选中当前页第一个事件(保持详情显示) · 翻页时,四排模式清空选中状态(通过弹窗显示详情) - 传递新 props 到 EventScrollList - 添加调试日志
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
Box,
|
||||
Flex,
|
||||
Grid,
|
||||
GridItem,
|
||||
IconButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
@@ -18,7 +19,11 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
||||
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
import CompactEventCard from '../EventCard/CompactEventCard';
|
||||
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
|
||||
import DynamicNewsDetailPanel from '../DynamicNewsDetail';
|
||||
import PaginationControl from './PaginationControl';
|
||||
import VirtualizedFourRowGrid from './VirtualizedFourRowGrid';
|
||||
|
||||
/**
|
||||
* 事件列表组件 - 支持两种展示模式
|
||||
@@ -39,6 +44,10 @@ import PaginationControl from './PaginationControl';
|
||||
*/
|
||||
const EventScrollList = ({
|
||||
events,
|
||||
displayEvents, // 累积显示的事件列表(四排模式用)
|
||||
isAccumulateMode, // 是否累积模式
|
||||
loadNextPage, // 加载下一页(无限滚动)
|
||||
onFourRowEventClick, // 四排模式事件点击回调(打开弹窗)
|
||||
selectedEvent,
|
||||
onEventSelect,
|
||||
borderColor,
|
||||
@@ -88,7 +97,7 @@ const EventScrollList = ({
|
||||
<Flex justify="space-between" align="center" mb={2}>
|
||||
{/* 模式切换按钮 */}
|
||||
<ButtonGroup size="sm" isAttached>
|
||||
<Button
|
||||
{/* <Button
|
||||
onClick={() => onModeChange('carousel')}
|
||||
colorScheme="blue"
|
||||
variant={mode === 'carousel' ? 'solid' : 'outline'}
|
||||
@@ -101,6 +110,20 @@ const EventScrollList = ({
|
||||
variant={mode === 'grid' ? 'solid' : 'outline'}
|
||||
>
|
||||
双排
|
||||
</Button> */}
|
||||
<Button
|
||||
onClick={() => onModeChange('vertical')}
|
||||
colorScheme="blue"
|
||||
variant={mode === 'vertical' ? 'solid' : 'outline'}
|
||||
>
|
||||
纵向
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => onModeChange('four-row')}
|
||||
colorScheme="blue"
|
||||
variant={mode === 'four-row' ? 'solid' : 'outline'}
|
||||
>
|
||||
平铺
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
@@ -126,7 +149,10 @@ const EventScrollList = ({
|
||||
top="50%"
|
||||
transform="translateY(-50%)"
|
||||
zIndex={2}
|
||||
onClick={() => onPageChange(currentPage - 1)}
|
||||
onClick={() => {
|
||||
console.log(`%c🔵 [翻页] 点击上一页: 当前页${currentPage} → 目标页${currentPage - 1} (共${totalPages}页)`, 'color: #3B82F6; font-weight: bold;');
|
||||
onPageChange(currentPage - 1);
|
||||
}}
|
||||
variant="ghost"
|
||||
size="md"
|
||||
w="40px"
|
||||
@@ -146,7 +172,7 @@ const EventScrollList = ({
|
||||
)}
|
||||
|
||||
{/* 右侧翻页按钮 - 下一页 */}
|
||||
{currentPage < totalPages && hasMore && (
|
||||
{currentPage < totalPages && (
|
||||
<IconButton
|
||||
icon={<ChevronRightIcon boxSize={6} color="blue.500" />}
|
||||
position="absolute"
|
||||
@@ -154,7 +180,10 @@ const EventScrollList = ({
|
||||
top="50%"
|
||||
transform="translateY(-50%)"
|
||||
zIndex={2}
|
||||
onClick={() => onPageChange(currentPage + 1)}
|
||||
onClick={() => {
|
||||
console.log(`%c🔵 [翻页] 点击下一页: 当前页${currentPage} → 目标页${currentPage + 1} (共${totalPages}页)`, 'color: #3B82F6; font-weight: bold;');
|
||||
onPageChange(currentPage + 1);
|
||||
}}
|
||||
variant="ghost"
|
||||
size="md"
|
||||
w="40px"
|
||||
@@ -168,7 +197,7 @@ const EventScrollList = ({
|
||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
|
||||
transform: 'translateY(-50%) scale(1.05)'
|
||||
}}
|
||||
isDisabled={currentPage >= totalPages && !hasMore}
|
||||
isDisabled={currentPage >= totalPages}
|
||||
aria-label="下一页"
|
||||
title="下一页"
|
||||
/>
|
||||
@@ -178,13 +207,16 @@ const EventScrollList = ({
|
||||
<Box
|
||||
ref={scrollContainerRef}
|
||||
overflowX={mode === 'carousel' ? 'auto' : 'hidden'}
|
||||
overflowY="hidden"
|
||||
overflowY="auto" // ✅ 启用纵向滚动
|
||||
maxH="600px" // ✅ 添加最大高度限制
|
||||
pt={0}
|
||||
pb={4}
|
||||
px={2}
|
||||
position="relative"
|
||||
css={mode === 'carousel' ? {
|
||||
css={{
|
||||
// 统一滚动条样式(支持横向和纵向)
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '8px',
|
||||
height: '8px',
|
||||
},
|
||||
'&::-webkit-scrollbar-track': {
|
||||
@@ -200,10 +232,10 @@ const EventScrollList = ({
|
||||
},
|
||||
scrollBehavior: 'smooth',
|
||||
WebkitOverflowScrolling: 'touch',
|
||||
} : {}}
|
||||
}}
|
||||
>
|
||||
{/* 加载遮罩 */}
|
||||
{loading && (
|
||||
{/* 加载遮罩 - 四排和纵向模式不显示(使用底部 loading 指示器) */}
|
||||
{loading && mode !== 'four-row' && mode !== 'vertical' && (
|
||||
<Center
|
||||
position="absolute"
|
||||
top={0}
|
||||
@@ -289,6 +321,84 @@ const EventScrollList = ({
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{/* 模式3: 四排网格模式 - 使用虚拟滚动 + 无限滚动 */}
|
||||
{mode === 'four-row' && (
|
||||
<VirtualizedFourRowGrid
|
||||
events={displayEvents || events} // 使用累积列表(如果有)
|
||||
selectedEvent={selectedEvent}
|
||||
onEventSelect={onFourRowEventClick} // 四排模式点击打开弹窗
|
||||
eventFollowStatus={eventFollowStatus}
|
||||
onToggleFollow={onToggleFollow}
|
||||
getTimelineBoxStyle={getTimelineBoxStyle}
|
||||
borderColor={borderColor}
|
||||
loadNextPage={loadNextPage} // 加载下一页
|
||||
hasMore={hasMore} // 是否还有更多数据
|
||||
loading={loading} // 加载状态
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 模式4: 纵向分栏模式 - 横向布局(时间在左,卡片在右) */}
|
||||
{mode === 'vertical' && (
|
||||
<Grid templateColumns="1fr 2fr" gap={6} minH="500px">
|
||||
{/* 左侧:事件列表 (33.3%) - 使用虚拟滚动 + 无限滚动 */}
|
||||
<GridItem>
|
||||
<VirtualizedFourRowGrid
|
||||
events={displayEvents || events} // 使用累积列表
|
||||
columnsPerRow={1} // 单列布局
|
||||
CardComponent={HorizontalDynamicNewsEventCard} // 使用横向卡片
|
||||
selectedEvent={selectedEvent}
|
||||
onEventSelect={onEventSelect}
|
||||
eventFollowStatus={eventFollowStatus}
|
||||
onToggleFollow={onToggleFollow}
|
||||
getTimelineBoxStyle={getTimelineBoxStyle}
|
||||
borderColor={borderColor}
|
||||
loadNextPage={loadNextPage} // 支持无限滚动
|
||||
hasMore={hasMore}
|
||||
loading={loading}
|
||||
/>
|
||||
</GridItem>
|
||||
|
||||
{/* 右侧:事件详情 (66.7%) */}
|
||||
<GridItem>
|
||||
<Box
|
||||
overflowY="auto"
|
||||
maxH="600px"
|
||||
pl={2}
|
||||
css={{
|
||||
overscrollBehavior: 'contain',
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '6px',
|
||||
},
|
||||
'&::-webkit-scrollbar-track': {
|
||||
background: scrollbarTrackBg,
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: scrollbarThumbBg,
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb:hover': {
|
||||
background: scrollbarThumbHoverBg,
|
||||
borderRadius: '10px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{selectedEvent ? (
|
||||
<DynamicNewsDetailPanel event={selectedEvent} />
|
||||
) : (
|
||||
<Center h="100%" minH="400px">
|
||||
<VStack spacing={4}>
|
||||
<Text fontSize="lg" color="gray.500">
|
||||
请选择左侧事件查看详情
|
||||
</Text>
|
||||
</VStack>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const DISPLAY_MODES = {
|
||||
VERTICAL: 'vertical', // 纵向分栏模式
|
||||
};
|
||||
|
||||
export const DEFAULT_MODE = DISPLAY_MODES.CAROUSEL;
|
||||
export const DEFAULT_MODE = DISPLAY_MODES.VERTICAL;
|
||||
|
||||
// ========== Toast 提示配置 ==========
|
||||
export const TOAST_CONFIG = {
|
||||
|
||||
Reference in New Issue
Block a user