feat: 提取 usePagination Hook

This commit is contained in:
zdl
2025-11-04 14:58:02 +08:00
parent ce46820105
commit 0a10270ab0

View File

@@ -26,52 +26,20 @@ import UnifiedSearchBox from './UnifiedSearchBox';
import { fetchDynamicNews, toggleEventFollow, selectEventFollowStatus } from '../../../store/slices/communityDataSlice'; import { fetchDynamicNews, toggleEventFollow, selectEventFollowStatus } from '../../../store/slices/communityDataSlice';
/** /**
* 实时要闻·动态追踪 - 事件展示卡片组件 * 分页逻辑自定义 Hook
* @param {Array} allCachedEvents - 完整缓存事件列表(从 Redux 传入) * @param {Object} options - Hook 配置选项
* @param {boolean} loading - 加载状态 * @param {Array} options.allCachedEvents - 完整缓存事件列表
* @param {number} total - 服务端总数量 * @param {number} options.total - 服务端总数量
* @param {number} cachedCount - 已缓存数量 * @param {number} options.cachedCount - 已缓存数量
* @param {Object} filters - 筛选条件 * @param {Function} options.dispatch - Redux dispatch 函数
* @param {Array} popularKeywords - 热门关键词 * @param {Function} options.toast - Toast 通知函数
* @param {Date} lastUpdateTime - 最后更新时间 * @returns {Object} 分页状态和方法
* @param {Function} onSearch - 搜索回调
* @param {Function} onSearchFocus - 搜索框获得焦点回调
* @param {Function} onEventClick - 事件点击回调
* @param {Function} onViewDetail - 查看详情回调
* @param {Object} ref - 用于滚动的ref
*/ */
const DynamicNewsCard = forwardRef(({ const usePagination = ({ allCachedEvents, total, cachedCount, dispatch, toast }) => {
allCachedEvents = [],
loading,
total = 0,
cachedCount = 0,
filters = {},
popularKeywords = [],
lastUpdateTime,
onSearch,
onSearchFocus,
onEventClick,
onViewDetail,
...rest
}, ref) => {
const dispatch = useDispatch();
const toast = useToast();
const cardBg = useColorModeValue('white', 'gray.800');
const borderColor = useColorModeValue('gray.200', 'gray.700');
// 从 Redux 读取关注状态
const eventFollowStatus = useSelector(selectEventFollowStatus);
// 关注按钮点击处理
const handleToggleFollow = useCallback((eventId) => {
dispatch(toggleEventFollow(eventId));
}, [dispatch]);
// 本地状态 // 本地状态
const [selectedEvent, setSelectedEvent] = useState(null); const [currentPage, setCurrentPage] = useState(1);
const [mode, setMode] = useState('carousel'); // 'carousel' 或 'grid',默认单排 const [loadingPage, setLoadingPage] = useState(null);
const [currentPage, setCurrentPage] = useState(1); // 当前页码 const [mode, setMode] = useState('carousel'); // 'carousel' 或 'grid'
const [loadingPage, setLoadingPage] = useState(null); // 正在加载的目标页码(用于 UX 提示)
// 根据模式决定每页显示数量 // 根据模式决定每页显示数量
const pageSize = mode === 'carousel' ? 5 : 10; const pageSize = mode === 'carousel' ? 5 : 10;
@@ -335,6 +303,86 @@ const DynamicNewsCard = forwardRef(({
// 如果第1页数据完整不发起请求直接切换 // 如果第1页数据完整不发起请求直接切换
}, [mode, allCachedEvents, total, dispatch]); }, [mode, allCachedEvents, total, dispatch]);
return {
// 状态
currentPage,
mode,
loadingPage,
pageSize,
totalPages,
hasMore,
currentPageEvents,
// 方法
handlePageChange,
handleModeToggle
};
};
/**
* 实时要闻·动态追踪 - 事件展示卡片组件
* @param {Array} allCachedEvents - 完整缓存事件列表(从 Redux 传入)
* @param {boolean} loading - 加载状态
* @param {number} total - 服务端总数量
* @param {number} cachedCount - 已缓存数量
* @param {Object} filters - 筛选条件
* @param {Array} popularKeywords - 热门关键词
* @param {Date} lastUpdateTime - 最后更新时间
* @param {Function} onSearch - 搜索回调
* @param {Function} onSearchFocus - 搜索框获得焦点回调
* @param {Function} onEventClick - 事件点击回调
* @param {Function} onViewDetail - 查看详情回调
* @param {Object} ref - 用于滚动的ref
*/
const DynamicNewsCard = forwardRef(({
allCachedEvents = [],
loading,
total = 0,
cachedCount = 0,
filters = {},
popularKeywords = [],
lastUpdateTime,
onSearch,
onSearchFocus,
onEventClick,
onViewDetail,
...rest
}, ref) => {
const dispatch = useDispatch();
const toast = useToast();
const cardBg = useColorModeValue('white', 'gray.800');
const borderColor = useColorModeValue('gray.200', 'gray.700');
// 从 Redux 读取关注状态
const eventFollowStatus = useSelector(selectEventFollowStatus);
// 关注按钮点击处理
const handleToggleFollow = useCallback((eventId) => {
dispatch(toggleEventFollow(eventId));
}, [dispatch]);
// 本地状态
const [selectedEvent, setSelectedEvent] = useState(null);
// 使用分页 Hook
const {
currentPage,
mode,
loadingPage,
pageSize,
totalPages,
hasMore,
currentPageEvents,
handlePageChange,
handleModeToggle
} = usePagination({
allCachedEvents,
total,
cachedCount,
dispatch,
toast
});
// 初始加载 // 初始加载
useEffect(() => { useEffect(() => {
if (allCachedEvents.length === 0) { if (allCachedEvents.length === 0) {