update ui
This commit is contained in:
@@ -2,10 +2,25 @@
|
||||
// 纵向分栏模式布局组件
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Box, VStack, Flex, Center, Text, useBreakpointValue } from '@chakra-ui/react';
|
||||
import {
|
||||
Box,
|
||||
VStack,
|
||||
Flex,
|
||||
Center,
|
||||
Text,
|
||||
useBreakpointValue,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react';
|
||||
import { InfoIcon } from '@chakra-ui/icons';
|
||||
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
|
||||
import EventDetailScrollPanel from './EventDetailScrollPanel';
|
||||
import DynamicNewsDetailPanel from '../../DynamicNewsDetail/DynamicNewsDetailPanel';
|
||||
|
||||
/**
|
||||
* 纵向分栏模式布局
|
||||
@@ -38,6 +53,20 @@ const VerticalModeLayout = ({
|
||||
const flexDirection = useBreakpointValue({ base: 'column', lg: 'row' });
|
||||
const gap = useBreakpointValue({ base: 3, lg: 6 });
|
||||
|
||||
// 移动端模态框控制
|
||||
const { isOpen: isMobileModalOpen, onOpen: onMobileModalOpen, onClose: onMobileModalClose } = useDisclosure();
|
||||
const [mobileSelectedEvent, setMobileSelectedEvent] = useState(null);
|
||||
|
||||
// 处理移动端事件点击
|
||||
const handleMobileEventClick = (event) => {
|
||||
if (isMobile) {
|
||||
setMobileSelectedEvent(event);
|
||||
onMobileModalOpen();
|
||||
} else {
|
||||
onEventSelect(event);
|
||||
}
|
||||
};
|
||||
|
||||
// 固定布局比例:左侧(4),右侧(6)- 平衡布局,确保左侧有足够空间显示内容
|
||||
const leftFlex = '4';
|
||||
const rightFlex = '6';
|
||||
@@ -89,7 +118,7 @@ const VerticalModeLayout = ({
|
||||
key={event.id}
|
||||
event={event}
|
||||
isSelected={selectedEvent?.id === event.id}
|
||||
onEventClick={() => onEventSelect(event)}
|
||||
onEventClick={() => handleMobileEventClick(event)}
|
||||
isFollowing={eventFollowStatus[event.id]?.isFollowing}
|
||||
followerCount={eventFollowStatus[event.id]?.followerCount}
|
||||
onToggleFollow={onToggleFollow}
|
||||
@@ -133,6 +162,24 @@ const VerticalModeLayout = ({
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* 移动端详情弹窗 */}
|
||||
{isMobile && (
|
||||
<Modal isOpen={isMobileModalOpen} onClose={onMobileModalClose} size="full" scrollBehavior="inside">
|
||||
<ModalOverlay bg="blackAlpha.800" backdropFilter="blur(10px)" />
|
||||
<ModalContent maxW="100vw" m={0} borderRadius={0}>
|
||||
<ModalHeader bg="gray.900" color="white" borderBottom="1px solid" borderColor="gray.700">
|
||||
{mobileSelectedEvent?.title || '事件详情'}
|
||||
</ModalHeader>
|
||||
<ModalCloseButton color="white" />
|
||||
<ModalBody p={0} bg="gray.900">
|
||||
{mobileSelectedEvent && (
|
||||
<DynamicNewsDetailPanel event={mobileSelectedEvent} showHeader={false} />
|
||||
)}
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import React, { useRef, useMemo, useEffect } from 'react';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { Box, Grid, Spinner, Text, VStack, Center, HStack, IconButton } from '@chakra-ui/react';
|
||||
import { Box, Grid, Spinner, Text, VStack, Center, HStack, IconButton, useBreakpointValue } from '@chakra-ui/react';
|
||||
import { RepeatIcon } from '@chakra-ui/icons';
|
||||
import { useColorModeValue } from '@chakra-ui/react';
|
||||
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
@@ -52,14 +52,26 @@ const VirtualizedFourRowGrid = ({
|
||||
const scrollbarThumbBg = useColorModeValue('#888', '#4A5568');
|
||||
const scrollbarThumbHoverBg = useColorModeValue('#555', '#718096');
|
||||
|
||||
// 将事件按 columnsPerRow 个一组分成行
|
||||
// 响应式列数
|
||||
const responsiveColumns = useBreakpointValue({
|
||||
base: 1, // 移动端:单列
|
||||
sm: 2, // 小屏:2列
|
||||
md: 2, // 中屏:2列
|
||||
lg: 3, // 大屏:3列
|
||||
xl: 4, // 超大屏:4列
|
||||
});
|
||||
|
||||
// 使用响应式列数或传入的列数
|
||||
const actualColumnsPerRow = responsiveColumns || columnsPerRow;
|
||||
|
||||
// 将事件按 actualColumnsPerRow 个一组分成行
|
||||
const rows = useMemo(() => {
|
||||
const r = [];
|
||||
for (let i = 0; i < events.length; i += columnsPerRow) {
|
||||
r.push(events.slice(i, i + columnsPerRow));
|
||||
for (let i = 0; i < events.length; i += actualColumnsPerRow) {
|
||||
r.push(events.slice(i, i + actualColumnsPerRow));
|
||||
}
|
||||
return r;
|
||||
}, [events, columnsPerRow]);
|
||||
}, [events, actualColumnsPerRow]);
|
||||
|
||||
// 配置虚拟滚动器(纵向滚动 + 动态高度测量)
|
||||
const rowVirtualizer = useVirtualizer({
|
||||
@@ -301,17 +313,17 @@ const VirtualizedFourRowGrid = ({
|
||||
w="100%"
|
||||
transform={`translateY(${virtualRow.start}px)`}
|
||||
>
|
||||
{/* 使用 Grid 横向排列卡片(列数由 columnsPerRow 决定) */}
|
||||
{/* 使用 Grid 横向排列卡片(列数由 actualColumnsPerRow 决定) */}
|
||||
<Grid
|
||||
templateColumns={`repeat(${columnsPerRow}, 1fr)`}
|
||||
gap={columnsPerRow === 1 ? 3 : 4}
|
||||
templateColumns={`repeat(${actualColumnsPerRow}, 1fr)`}
|
||||
gap={actualColumnsPerRow === 1 ? 3 : 4}
|
||||
w="100%"
|
||||
>
|
||||
{rowEvents.map((event, colIndex) => (
|
||||
<Box key={event.id} w="100%" minW={0}>
|
||||
<CardComponent
|
||||
event={event}
|
||||
index={virtualRow.index * columnsPerRow + colIndex}
|
||||
index={virtualRow.index * actualColumnsPerRow + colIndex}
|
||||
isFollowing={eventFollowStatus[event.id]?.isFollowing || false}
|
||||
followerCount={eventFollowStatus[event.id]?.followerCount || event.follower_count || 0}
|
||||
isSelected={selectedEvent?.id === event.id}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import CollapsibleHeader from './CollapsibleHeader';
|
||||
import { PROFESSIONAL_COLORS } from '../../../../constants/professionalTheme';
|
||||
|
||||
/**
|
||||
* 通用可折叠区块组件
|
||||
@@ -37,7 +38,7 @@ const CollapsibleSection = ({
|
||||
showModeToggle = false,
|
||||
defaultMode = 'detailed'
|
||||
}) => {
|
||||
const sectionBg = useColorModeValue('gray.50', 'gray.750');
|
||||
const sectionBg = PROFESSIONAL_COLORS.background.secondary;
|
||||
|
||||
// 模式状态:'detailed' | 'simple'
|
||||
const [displayMode, setDisplayMode] = useState(defaultMode);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Text,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { PROFESSIONAL_COLORS } from '../../../../constants/professionalTheme';
|
||||
|
||||
/**
|
||||
* 事件描述区组件
|
||||
@@ -15,9 +16,9 @@ import {
|
||||
* @param {string} props.description - 事件描述文本
|
||||
*/
|
||||
const EventDescriptionSection = ({ description }) => {
|
||||
const sectionBg = useColorModeValue('gray.50', 'gray.750');
|
||||
const headingColor = useColorModeValue('gray.700', 'gray.200');
|
||||
const textColor = useColorModeValue('gray.600', 'gray.400');
|
||||
const sectionBg = PROFESSIONAL_COLORS.background.secondary;
|
||||
const headingColor = PROFESSIONAL_COLORS.text.primary;
|
||||
const textColor = PROFESSIONAL_COLORS.text.secondary;
|
||||
|
||||
// 如果没有描述,不渲染
|
||||
if (!description) {
|
||||
|
||||
Reference in New Issue
Block a user