170 lines
6.1 KiB
JavaScript
170 lines
6.1 KiB
JavaScript
// src/views/Community/components/DynamicNews/EventScrollList.js
|
|
// 横向滚动事件列表组件
|
|
|
|
import React, { useRef, useCallback } from "react";
|
|
import { Box, useColorModeValue } from "@chakra-ui/react";
|
|
import VirtualizedFourRowGrid from "./layouts/VirtualizedFourRowGrid";
|
|
import MainlineTimelineView from "./layouts/MainlineTimelineView";
|
|
import VerticalModeLayout from "./layouts/VerticalModeLayout";
|
|
|
|
/**
|
|
* 事件列表组件 - 支持纵向、平铺、主线三种展示模式
|
|
* @param {Array} events - 当前页的事件列表(服务端已分页)
|
|
* @param {Array} displayEvents - 累积显示的事件列表(平铺模式用)
|
|
* @param {Object} filters - 筛选条件(主线模式用)
|
|
* @param {Function} loadNextPage - 加载下一页(无限滚动)
|
|
* @param {Function} loadPrevPage - 加载上一页(双向无限滚动)
|
|
* @param {Function} onFourRowEventClick - 平铺/主线模式事件点击回调(打开弹窗)
|
|
* @param {Object} selectedEvent - 当前选中的事件
|
|
* @param {Function} onEventSelect - 事件选择回调
|
|
* @param {string} borderColor - 边框颜色
|
|
* @param {number} currentPage - 当前页码
|
|
* @param {number} totalPages - 总页数(由服务端返回)
|
|
* @param {Function} onPageChange - 页码改变回调
|
|
* @param {boolean} loading - 全局加载状态
|
|
* @param {Object} error - 错误状态
|
|
* @param {string} mode - 展示模式:'vertical'(纵向分栏)| 'four-row'(平铺网格)| 'mainline'(主线时间轴)
|
|
* @param {boolean} hasMore - 是否还有更多数据
|
|
* @param {Object} eventFollowStatus - 事件关注状态 { [eventId]: { isFollowing, followerCount } }
|
|
* @param {Function} onToggleFollow - 关注按钮回调
|
|
* @param {React.Ref} virtualizedGridRef - VirtualizedFourRowGrid/MainlineTimelineView 的 ref
|
|
*/
|
|
const EventScrollList = React.memo(
|
|
({
|
|
events,
|
|
displayEvents,
|
|
filters = {},
|
|
loadNextPage,
|
|
loadPrevPage,
|
|
onFourRowEventClick,
|
|
selectedEvent,
|
|
onEventSelect,
|
|
borderColor,
|
|
currentPage,
|
|
totalPages,
|
|
onPageChange,
|
|
loading = false,
|
|
error,
|
|
mode = "vertical",
|
|
hasMore = true,
|
|
eventFollowStatus = {},
|
|
onToggleFollow,
|
|
virtualizedGridRef,
|
|
}) => {
|
|
const scrollContainerRef = useRef(null);
|
|
|
|
// 所有 useColorModeValue 必须在组件顶层调用(不能在条件渲染中)
|
|
const timelineBg = useColorModeValue("gray.50", "gray.700");
|
|
const timelineBorderColor = useColorModeValue("gray.400", "gray.500");
|
|
const timelineTextColor = useColorModeValue("blue.600", "blue.400");
|
|
|
|
// 滚动条颜色
|
|
const scrollbarTrackBg = useColorModeValue("#f1f1f1", "#2D3748");
|
|
const scrollbarThumbBg = useColorModeValue("#888", "#4A5568");
|
|
const scrollbarThumbHoverBg = useColorModeValue("#555", "#718096");
|
|
|
|
const getTimelineBoxStyle = () => {
|
|
return {
|
|
bg: timelineBg,
|
|
borderColor: timelineBorderColor,
|
|
borderWidth: "2px",
|
|
textColor: timelineTextColor,
|
|
boxShadow: "sm",
|
|
};
|
|
};
|
|
|
|
// 重试函数
|
|
const handleRetry = useCallback(() => {
|
|
if (onPageChange) {
|
|
onPageChange(currentPage);
|
|
}
|
|
}, [onPageChange, currentPage]);
|
|
|
|
{
|
|
/* 事件卡片容器 */
|
|
}
|
|
return (
|
|
<Box
|
|
ref={scrollContainerRef}
|
|
overflowX="hidden"
|
|
h="100%"
|
|
pt={0}
|
|
pb={4}
|
|
px={mode === "four-row" || mode === "mainline" ? 0 : { base: 0, md: 2 }}
|
|
position="relative"
|
|
data-scroll-container="true"
|
|
css={{
|
|
// 统一滚动条样式(支持横向和纵向)
|
|
"&::-webkit-scrollbar": {
|
|
width: "1px",
|
|
height: "1px",
|
|
},
|
|
"&::-webkit-scrollbar-track": {
|
|
background: scrollbarTrackBg,
|
|
borderRadius: "10px",
|
|
},
|
|
"&::-webkit-scrollbar-thumb": {
|
|
background: scrollbarThumbBg,
|
|
borderRadius: "10px",
|
|
},
|
|
"&::-webkit-scrollbar-thumb:hover": {
|
|
background: scrollbarThumbHoverBg,
|
|
},
|
|
scrollBehavior: "smooth",
|
|
WebkitOverflowScrolling: "touch",
|
|
}}
|
|
>
|
|
{/* 平铺网格模式 - 使用虚拟滚动 + 双向无限滚动 */}
|
|
<VirtualizedFourRowGrid
|
|
ref={mode === "four-row" ? virtualizedGridRef : null}
|
|
display={mode === "four-row" ? "block" : "none"}
|
|
columnsPerRow={4} // 每行显示4列
|
|
events={displayEvents || events} // 使用累积列表(如果有)
|
|
selectedEvent={selectedEvent}
|
|
onEventSelect={onFourRowEventClick} // 四排模式点击打开弹窗
|
|
eventFollowStatus={eventFollowStatus}
|
|
onToggleFollow={onToggleFollow}
|
|
getTimelineBoxStyle={getTimelineBoxStyle}
|
|
borderColor={borderColor}
|
|
loadNextPage={loadNextPage} // 加载下一页
|
|
loadPrevPage={loadPrevPage} // 加载上一页(双向滚动)
|
|
hasMore={hasMore} // 是否还有更多数据
|
|
loading={loading} // 加载状态
|
|
error={error} // 错误状态
|
|
onRetry={handleRetry} // 重试回调
|
|
/>
|
|
|
|
{/* 主线时间轴模式 - 按 lv2 概念分组,调用独立 API */}
|
|
<MainlineTimelineView
|
|
ref={mode === "mainline" ? virtualizedGridRef : null}
|
|
display={mode === "mainline" ? "block" : "none"}
|
|
filters={filters}
|
|
columnsPerRow={3}
|
|
selectedEvent={selectedEvent}
|
|
onEventSelect={onFourRowEventClick}
|
|
eventFollowStatus={eventFollowStatus}
|
|
onToggleFollow={onToggleFollow}
|
|
borderColor={borderColor}
|
|
/>
|
|
|
|
{/* 纵向分栏模式 */}
|
|
<VerticalModeLayout
|
|
display={mode === "vertical" ? "flex" : "none"}
|
|
events={events}
|
|
selectedEvent={selectedEvent}
|
|
onEventSelect={onEventSelect}
|
|
eventFollowStatus={eventFollowStatus}
|
|
onToggleFollow={onToggleFollow}
|
|
getTimelineBoxStyle={getTimelineBoxStyle}
|
|
borderColor={borderColor}
|
|
currentPage={currentPage}
|
|
totalPages={totalPages}
|
|
onPageChange={onPageChange}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|
|
);
|
|
|
|
export default EventScrollList;
|