refactor: 提取翻页按钮为可复用组件

- 创建 PageNavigationButton 组件
  · 通过 direction 参数区分上一页/下一页
  · 内置主题适配和模式判断逻辑
  · 自动处理显示条件(只在单排/双排模式显示)

- 重构 EventScrollList
  · 删除重复的翻页按钮代码(减少 66 行)
  · 使用 PageNavigationButton 组件替换原有按钮
  · 移除未使用的导入(IconButton, ChevronLeftIcon, ChevronRightIcon)
  · 移除翻页按钮主题色定义(已移至子组件)

优点:
- 消除重复代码,提升可维护性
- 职责分离,逻辑更清晰
- 易于扩展(可添加首页/末页按钮)
This commit is contained in:
zdl
2025-11-05 09:15:33 +08:00
parent 188783a8d2
commit b223be2f01
2 changed files with 97 additions and 66 deletions

View File

@@ -7,7 +7,6 @@ import {
Flex,
Grid,
GridItem,
IconButton,
Button,
ButtonGroup,
Center,
@@ -17,13 +16,13 @@ import {
Text,
useColorModeValue
} from '@chakra-ui/react';
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
import CompactEventCard from '../EventCard/CompactEventCard';
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
import DynamicNewsDetailPanel from '../DynamicNewsDetail';
import PaginationControl from './PaginationControl';
import VirtualizedFourRowGrid from './VirtualizedFourRowGrid';
import PageNavigationButton from './PageNavigationButton';
/**
* 事件列表组件 - 支持两种展示模式
@@ -68,10 +67,6 @@ const EventScrollList = ({
const timelineBorderColor = useColorModeValue('gray.400', 'gray.500');
const timelineTextColor = useColorModeValue('blue.600', 'blue.400');
// 翻页按钮颜色
const arrowBtnBg = useColorModeValue('rgba(255, 255, 255, 0.9)', 'rgba(0, 0, 0, 0.6)');
const arrowBtnHoverBg = useColorModeValue('rgba(255, 255, 255, 1)', 'rgba(0, 0, 0, 0.8)');
// 滚动条颜色
const scrollbarTrackBg = useColorModeValue('#f1f1f1', '#2D3748');
const scrollbarThumbBg = useColorModeValue('#888', '#4A5568');
@@ -140,68 +135,21 @@ const EventScrollList = ({
{/* 横向滚动区域 */}
<Box position="relative">
{/* 左侧翻页按钮 - 上一页 */}
{currentPage > 1 && (
<IconButton
icon={<ChevronLeftIcon boxSize={6} color="blue.500" />}
position="absolute"
left="0"
top="50%"
transform="translateY(-50%)"
zIndex={2}
onClick={() => {
console.log(`%c🔵 [翻页] 点击上一页: 当前页${currentPage} → 目标页${currentPage - 1} (共${totalPages}页)`, 'color: #3B82F6; font-weight: bold;');
onPageChange(currentPage - 1);
}}
variant="ghost"
size="md"
w="40px"
h="40px"
minW="40px"
borderRadius="full"
bg={arrowBtnBg}
boxShadow="0 2px 8px rgba(0, 0, 0, 0.15)"
_hover={{
bg: arrowBtnHoverBg,
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
transform: 'translateY(-50%) scale(1.05)'
}}
aria-label="上一页"
title="上一页"
{/* 翻页导航按钮 */}
<PageNavigationButton
direction="prev"
currentPage={currentPage}
totalPages={totalPages}
onPageChange={onPageChange}
mode={mode}
/>
)}
{/* 右侧翻页按钮 - 下一页 */}
{currentPage < totalPages && (
<IconButton
icon={<ChevronRightIcon boxSize={6} color="blue.500" />}
position="absolute"
right="0"
top="50%"
transform="translateY(-50%)"
zIndex={2}
onClick={() => {
console.log(`%c🔵 [翻页] 点击下一页: 当前页${currentPage} → 目标页${currentPage + 1} (共${totalPages}页)`, 'color: #3B82F6; font-weight: bold;');
onPageChange(currentPage + 1);
}}
variant="ghost"
size="md"
w="40px"
h="40px"
minW="40px"
borderRadius="full"
bg={arrowBtnBg}
boxShadow="0 2px 8px rgba(0, 0, 0, 0.15)"
_hover={{
bg: arrowBtnHoverBg,
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
transform: 'translateY(-50%) scale(1.05)'
}}
isDisabled={currentPage >= totalPages}
aria-label="下一页"
title="下一页"
<PageNavigationButton
direction="next"
currentPage={currentPage}
totalPages={totalPages}
onPageChange={onPageChange}
mode={mode}
/>
)}
{/* 事件卡片容器 */}
<Box

View File

@@ -0,0 +1,83 @@
// src/views/Community/components/DynamicNewsCard/PageNavigationButton.js
// 翻页导航按钮组件
import React from 'react';
import { IconButton, useColorModeValue } from '@chakra-ui/react';
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
/**
* 翻页导航按钮组件
* @param {Object} props
* @param {'prev'|'next'} props.direction - 按钮方向prev=上一页next=下一页)
* @param {number} props.currentPage - 当前页码
* @param {number} props.totalPages - 总页数
* @param {Function} props.onPageChange - 翻页回调
* @param {string} props.mode - 显示模式只在carousel/grid模式下显示
*/
const PageNavigationButton = ({
direction,
currentPage,
totalPages,
onPageChange,
mode
}) => {
// 主题适配
const arrowBtnBg = useColorModeValue('rgba(255, 255, 255, 0.9)', 'rgba(0, 0, 0, 0.6)');
const arrowBtnHoverBg = useColorModeValue('rgba(255, 255, 255, 1)', 'rgba(0, 0, 0, 0.8)');
// 根据方向计算配置
const isPrev = direction === 'prev';
const isNext = direction === 'next';
const Icon = isPrev ? ChevronLeftIcon : ChevronRightIcon;
const position = isPrev ? 'left' : 'right';
const label = isPrev ? '上一页' : '下一页';
const targetPage = isPrev ? currentPage - 1 : currentPage + 1;
const shouldShow = isPrev
? currentPage > 1
: currentPage < totalPages;
const isDisabled = isNext ? currentPage >= totalPages : false;
// 判断是否显示(只在单排/双排模式显示)
const shouldRender = shouldShow && (mode === 'carousel' || mode === 'grid');
if (!shouldRender) return null;
const handleClick = () => {
console.log(
`%c🔵 [翻页] 点击${label}: 当前页${currentPage} → 目标页${targetPage} (共${totalPages}页)`,
'color: #3B82F6; font-weight: bold;'
);
onPageChange(targetPage);
};
return (
<IconButton
icon={<Icon boxSize={6} color="blue.500" />}
position="absolute"
{...{ [position]: 0 }}
top="50%"
transform="translateY(-50%)"
zIndex={2}
onClick={handleClick}
variant="ghost"
size="md"
w="40px"
h="40px"
minW="40px"
borderRadius="full"
bg={arrowBtnBg}
boxShadow="0 2px 8px rgba(0, 0, 0, 0.15)"
_hover={{
bg: arrowBtnHoverBg,
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.2)',
transform: 'translateY(-50%) scale(1.05)'
}}
isDisabled={isDisabled}
aria-label={label}
title={label}
/>
);
};
export default PageNavigationButton;