feat: 优化事件中心页面 重构后的文件结构

src/views/Community/
     ├── index.js (主组件,150行左右)
     ├── components/
     │   ├── EventTimelineCard.js (新增)
     │   ├── EventTimelineHeader.js (新增)
     │   ├── EventListSection.js (新增)
     │   ├── HotEventsSection.js (新增)
     │   ├── EventModals.js (新增)
     │   ├── UnifiedSearchBox.js (已有)
     │   ├── EventList.js (已有)
     │   └── ...
     └── hooks/
         ├── useEventFilters.js (新增)
         └── useEventData.js (新增)
This commit is contained in:
zdl
2025-10-26 20:31:34 +08:00
parent f1bd9680b6
commit 97c5ce0d4d
8 changed files with 500 additions and 269 deletions

View File

@@ -0,0 +1,91 @@
// src/views/Community/hooks/useEventData.js
// 事件数据加载逻辑 Hook
import { useState, useEffect, useRef, useCallback } from 'react';
import { debounce } from 'lodash';
import { eventService } from '../../../services/eventService';
import { logger } from '../../../utils/logger';
/**
* 事件数据加载 Hook
* @param {Object} filters - 筛选条件
* @param {number} pageSize - 每页数量
* @returns {Object} 事件数据和加载状态
*/
export const useEventData = (filters, pageSize = 10) => {
const [events, setEvents] = useState([]);
const [pagination, setPagination] = useState({
current: 1,
pageSize: pageSize,
total: 0
});
const [loading, setLoading] = useState(false);
const [lastUpdateTime, setLastUpdateTime] = useState(new Date());
// 加载事件列表
const loadEvents = useCallback(async (page = 1) => {
logger.debug('useEventData', 'loadEvents 被调用', { page });
setLoading(true);
try {
const response = await eventService.getEvents({
...filters,
page,
per_page: pagination.pageSize
});
if (response.success) {
setEvents(response.data.events);
setPagination({
current: response.data.pagination.page,
pageSize: response.data.pagination.per_page,
total: response.data.pagination.total
});
setLastUpdateTime(new Date());
logger.debug('useEventData', 'loadEvents 成功', {
count: response.data.events.length,
total: response.data.pagination.total
});
}
} catch (error) {
logger.error('useEventData', 'loadEvents', error, {
page,
filters
});
} finally {
setLoading(false);
}
}, [filters, pagination.pageSize]);
// 创建防抖的 loadEvents 函数500ms 防抖延迟)
const debouncedLoadEvents = useRef(
debounce((page) => {
logger.debug('useEventData', '防抖后执行 loadEvents', { page });
loadEvents(page);
}, 500)
).current;
// 监听 filters 变化,自动加载数据
// 防抖优化:用户快速切换筛选条件时,只执行最后一次请求
useEffect(() => {
logger.debug('useEventData', 'useEffect 触发filters 变化', { filters });
// 使用防抖加载事件
debouncedLoadEvents(filters.page || 1);
// 组件卸载时取消防抖
return () => {
debouncedLoadEvents.cancel();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [filters]); // 监听 filters 状态变化
return {
events,
pagination,
loading,
lastUpdateTime,
loadEvents
};
};

View File

@@ -0,0 +1,76 @@
// src/views/Community/hooks/useEventFilters.js
// 事件筛选逻辑 Hook
import { useState, useCallback } from 'react';
import { useSearchParams } from 'react-router-dom';
import { logger } from '../../../utils/logger';
/**
* 事件筛选逻辑 Hook
* @param {Object} options - 配置选项
* @param {Function} options.navigate - 路由导航函数
* @param {Function} options.onEventClick - 事件点击回调
* @param {Object} options.eventTimelineRef - 时间轴ref用于滚动
* @returns {Object} 筛选状态和处理函数
*/
export const useEventFilters = ({ navigate, onEventClick, eventTimelineRef } = {}) => {
const [searchParams] = useSearchParams();
// 筛选参数状态 - 初始化时从URL读取之后只用本地状态
const [filters, setFilters] = useState(() => {
return {
sort: searchParams.get('sort') || 'new',
importance: searchParams.get('importance') || 'all',
date_range: searchParams.get('date_range') || '',
q: searchParams.get('q') || '',
industry_classification: searchParams.get('industry_classification') || '',
industry_code: searchParams.get('industry_code') || '',
stock_code: searchParams.get('stock_code') || '',
page: parseInt(searchParams.get('page') || '1', 10)
};
});
// 更新筛选参数 - 直接替换(由 UnifiedSearchBox 输出完整参数)
const updateFilters = useCallback((newFilters) => {
logger.debug('useEventFilters', 'updateFilters 接收到完整参数', newFilters);
setFilters(newFilters);
}, []);
// 处理分页变化
const handlePageChange = useCallback((page) => {
// 保持现有筛选条件,只更新页码
updateFilters({ ...filters, page });
// 滚动到实时事件时间轴(平滑滚动)
if (eventTimelineRef && eventTimelineRef.current) {
setTimeout(() => {
eventTimelineRef.current.scrollIntoView({
behavior: 'smooth', // 平滑滚动
block: 'start' // 滚动到元素顶部
});
}, 100); // 延迟100ms确保DOM更新
}
}, [filters, updateFilters, eventTimelineRef]);
// 处理事件点击
const handleEventClick = useCallback((event) => {
if (onEventClick) {
onEventClick(event);
}
}, [onEventClick]);
// 处理查看详情
const handleViewDetail = useCallback((eventId) => {
if (navigate) {
navigate(`/event-detail/${eventId}`);
}
}, [navigate]);
return {
filters,
updateFilters,
handlePageChange,
handleEventClick,
handleViewDetail
};
};