refactor: Community 目录结构重组 + 修复导入路径 + 添加 Mock 数据

## 目录重构
- DynamicNewsCard/ → DynamicNews/(含 layouts/, hooks/ 子目录)
- EventCard 原子组件 → EventCard/atoms/
- EventDetailModal 独立目录化
- HotEvents 独立目录化(含 CSS)
- SearchFilters 独立目录化(CompactSearchBox, TradingTimeFilter)

## 导入路径修复
- EventCard/*.js: 统一使用 @constants/, @utils/, @components/ 别名
- atoms/*.js: 修复移动后的相对路径问题
- DynamicNewsCard.js: 更新 contexts, store, constants 导入
- EventHeaderInfo.js, CompactMetaBar.js: 修复 EventFollowButton 导入

## Mock Handler 添加
- /api/events/:eventId/expectation-score - 事件超预期得分
- /api/index/:indexCode/realtime - 指数实时行情

## 警告修复
- CitationMark.js: overlayInnerStyle → styles (Antd 5.x)
- CitedContent.js: 移除不支持的 jsx 属性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-09 13:16:43 +08:00
parent c704b12bce
commit 15f5c445c5
47 changed files with 409 additions and 76 deletions

View File

@@ -0,0 +1,152 @@
// 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 VerticalModeLayout from './layouts/VerticalModeLayout';
/**
* 事件列表组件 - 支持纵向和平铺两种展示模式
* @param {Array} events - 当前页的事件列表(服务端已分页)
* @param {Array} displayEvents - 累积显示的事件列表(平铺模式用)
* @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'(平铺网格)
* @param {boolean} hasMore - 是否还有更多数据
* @param {Object} eventFollowStatus - 事件关注状态 { [eventId]: { isFollowing, followerCount } }
* @param {Function} onToggleFollow - 关注按钮回调
* @param {React.Ref} virtualizedGridRef - VirtualizedFourRowGrid 的 ref用于获取滚动位置
*/
const EventScrollList = React.memo(({
events,
displayEvents,
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' ? 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={virtualizedGridRef} // ⚡ 传递 ref用于获取滚动位置
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} // 重试回调
/>
{/* 纵向分栏模式 */}
<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;