174 lines
5.4 KiB
JavaScript
174 lines
5.4 KiB
JavaScript
// src/views/Community/components/DynamicNewsCard/VerticalModeLayout.js
|
||
// 纵向分栏模式布局组件
|
||
|
||
import React, { useState, useEffect } from 'react';
|
||
import { Box, IconButton, Tooltip, VStack, Flex, Center, Text } from '@chakra-ui/react';
|
||
import { ViewIcon, ViewOffIcon, InfoIcon } from '@chakra-ui/icons';
|
||
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
|
||
import EventDetailScrollPanel from './EventDetailScrollPanel';
|
||
|
||
/**
|
||
* 纵向分栏模式布局
|
||
* 支持两种展示模式:
|
||
* - detail(默认):左侧事件列表 1fr | 右侧详情 2fr
|
||
* - list:左侧事件列表 7fr | 右侧详情 300px
|
||
*
|
||
* @param {string} display - CSS display 属性(用于显示/隐藏组件)
|
||
* @param {Array} events - 当前页的事件列表(分页数据)
|
||
* @param {Object} selectedEvent - 当前选中的事件
|
||
* @param {Function} onEventSelect - 事件选择回调
|
||
* @param {Object} eventFollowStatus - 事件关注状态
|
||
* @param {Function} onToggleFollow - 关注按钮回调
|
||
* @param {Function} getTimelineBoxStyle - 时间线样式获取函数
|
||
* @param {string} borderColor - 边框颜色
|
||
*/
|
||
const VerticalModeLayout = ({
|
||
display = 'flex',
|
||
events,
|
||
selectedEvent,
|
||
onEventSelect,
|
||
eventFollowStatus,
|
||
onToggleFollow,
|
||
getTimelineBoxStyle,
|
||
borderColor,
|
||
}) => {
|
||
// 布局模式状态:'detail' = 聚焦详情(默认),'list' = 聚焦列表
|
||
const [layoutMode, setLayoutMode] = useState('list');
|
||
|
||
// 详情面板重置 key(切换到 list 模式时改变,强制重新渲染)
|
||
const [detailPanelKey, setDetailPanelKey] = useState(0);
|
||
|
||
// 监听事件选择 - 自动切换到详情模式
|
||
useEffect(() => {
|
||
if (selectedEvent) {
|
||
setLayoutMode('detail');
|
||
}
|
||
}, [selectedEvent]);
|
||
|
||
// 切换布局模式
|
||
const toggleLayoutMode = () => {
|
||
const newMode = layoutMode === 'detail' ? 'list' : 'detail';
|
||
setLayoutMode(newMode);
|
||
|
||
// 如果切换到 list 模式,重置详情面板(收起所有 CollapsibleSection)
|
||
if (newMode === 'list') {
|
||
setDetailPanelKey(prev => prev + 1); // 改变 key,强制重新渲染
|
||
}
|
||
};
|
||
|
||
// 根据模式计算 flex 比例
|
||
const leftFlex = layoutMode === 'detail' ? '4' : '6';
|
||
const rightFlex = layoutMode === 'detail' ? '6' : '4';
|
||
|
||
return (
|
||
<Flex
|
||
display={display}
|
||
gap={6}
|
||
position="relative"
|
||
transition="all 0.3s ease-in-out"
|
||
h="100%"
|
||
overflow="hidden"
|
||
>
|
||
{/* 左侧:事件列表 - 独立滚动 */}
|
||
<Box
|
||
flex={leftFlex}
|
||
minWidth={0}
|
||
overflowY="auto"
|
||
h="100%"
|
||
data-event-list-container="true"
|
||
css={{
|
||
overscrollBehavior: 'contain',
|
||
'&::-webkit-scrollbar': {
|
||
width: '6px',
|
||
},
|
||
'&::-webkit-scrollbar-track': {
|
||
background: '#f1f1f1',
|
||
},
|
||
'&::-webkit-scrollbar-thumb': {
|
||
background: '#888',
|
||
borderRadius: '3px',
|
||
},
|
||
'&::-webkit-scrollbar-thumb:hover': {
|
||
background: '#555',
|
||
},
|
||
}}
|
||
>
|
||
{/* 事件列表 */}
|
||
{events && events.length > 0 ? (
|
||
<VStack
|
||
spacing={2}
|
||
align="stretch"
|
||
p={2}
|
||
>
|
||
{events.map((event) => (
|
||
<HorizontalDynamicNewsEventCard
|
||
key={event.id}
|
||
event={event}
|
||
isSelected={selectedEvent?.id === event.id}
|
||
onEventClick={() => onEventSelect(event)}
|
||
isFollowing={eventFollowStatus[event.id]?.isFollowing}
|
||
followerCount={eventFollowStatus[event.id]?.followerCount}
|
||
onToggleFollow={onToggleFollow}
|
||
timelineStyle={getTimelineBoxStyle()}
|
||
borderColor={borderColor}
|
||
indicatorSize={layoutMode === 'detail' ? 'default' : 'comfortable'}
|
||
layout="vertical"
|
||
/>
|
||
))}
|
||
</VStack>
|
||
) : (
|
||
/* 空状态 */
|
||
<Center h="100%" minH="400px">
|
||
<VStack spacing={4}>
|
||
<InfoIcon w={12} h={12} color="gray.400" />
|
||
<Text fontSize="lg" color="gray.500" textAlign="center">
|
||
当前筛选条件下暂无数据
|
||
</Text>
|
||
<Text fontSize="sm" color="gray.400" textAlign="center">
|
||
请尝试调整筛选条件
|
||
</Text>
|
||
</VStack>
|
||
</Center>
|
||
)}
|
||
</Box>
|
||
|
||
{/* 右侧:事件详情 - 独立滚动 */}
|
||
<Box
|
||
flex={rightFlex}
|
||
minHeight={0}
|
||
position="relative"
|
||
overflow="hidden"
|
||
h="100%"
|
||
>
|
||
{/* 布局切换按钮 */}
|
||
<Tooltip
|
||
label={layoutMode === 'detail' ? '展开事件列表' : '展开详情面板'}
|
||
placement="left"
|
||
>
|
||
<IconButton
|
||
position="absolute"
|
||
top={2}
|
||
right={2}
|
||
zIndex={9999}
|
||
size="md"
|
||
icon={layoutMode === 'detail' ? <ViewOffIcon /> : <ViewIcon />}
|
||
onClick={toggleLayoutMode}
|
||
aria-label="切换布局模式"
|
||
colorScheme="blue"
|
||
variant="solid"
|
||
/>
|
||
</Tooltip>
|
||
|
||
{/* 详情面板 */}
|
||
<EventDetailScrollPanel
|
||
key={detailPanelKey}
|
||
detailMode="no-header"
|
||
selectedEvent={selectedEvent}
|
||
/>
|
||
</Box>
|
||
</Flex>
|
||
);
|
||
};
|
||
|
||
export default VerticalModeLayout;
|