'use client'; import { useState, useEffect, useRef, useCallback, useMemo } from 'react'; import { Swiper, SwiperSlide } from "swiper/react"; import { Navigation, Pagination, Thumbs, FreeMode } from "swiper/modules"; // 导入Swiper样式 import "swiper/css"; import "swiper/css/navigation"; import "swiper/css/pagination"; import "swiper/css/thumbs"; import "swiper/css/free-mode"; const ProductImageGallery = ({ data }) => { const [currentImageIndex, setCurrentImageIndex] = useState(0); const [thumbsSwiper, setThumbsSwiper] = useState(null); const thumbsSwiperRef = useRef(null); // 如果没有attachments,不显示组件 if (!data?.attachments || data.attachments.length === 0) { return null; } // 使用useMemo优化主图索引计算 const mainImageIndex = useMemo(() => { if (!data.image) return 0; const mainImageIndex = data.attachments.findIndex( attachment => attachment.file_url === data.image ); return mainImageIndex >= 0 ? mainImageIndex : 0; }, [data.image, data.attachments]); // 使用useMemo优化当前图片URL const currentImage = useMemo(() => { return data.attachments[currentImageIndex]?.file_url || data.attachments[0]?.file_url; }, [data.attachments, currentImageIndex]); // 使用useCallback优化缩略图滚动函数 const scrollThumbnailToIndex = useCallback((index) => { if (thumbsSwiperRef.current?.swiper) { try { const swiper = thumbsSwiperRef.current.swiper; if (index === 0) { // 第一张图片,滚动到最左侧 swiper.scrollTo(0, 300); } else { // 其他图片使用原有的slideTo方法,保持正常滚动 swiper.slideTo(index, 300); } } catch (error) { // 静默处理错误 } } }, []); // 使用useCallback优化主图切换函数 const changeMainImage = useCallback((direction) => { if (data.attachments.length <= 1) return; let newIndex; if (direction === 'next') { newIndex = (currentImageIndex + 1) % data.attachments.length; } else { newIndex = (currentImageIndex - 1 + data.attachments.length) % data.attachments.length; } setCurrentImageIndex(newIndex); // 自动滚动缩略图到对应位置 setTimeout(() => { scrollThumbnailToIndex(newIndex); }, 100); }, [currentImageIndex, data.attachments.length, scrollThumbnailToIndex]); // 使用useCallback优化按索引切换主图函数 const changeMainImageByIndex = useCallback((index) => { setCurrentImageIndex(index); // 智能滚动缩略图到可见区域 setTimeout(() => { scrollThumbnailToIndex(index); }, 100); }, [scrollThumbnailToIndex]); // 初始化当前索引为主图索引 useEffect(() => { setCurrentImageIndex(mainImageIndex); }, [mainImageIndex]); // 键盘导航支持 - 使用useCallback优化 const handleKeyDown = useCallback((event) => { if (data.attachments.length <= 1) return; switch (event.key) { case 'ArrowLeft': event.preventDefault(); changeMainImage('prev'); break; case 'ArrowRight': event.preventDefault(); changeMainImage('next'); break; case 'Home': event.preventDefault(); setCurrentImageIndex(0); setTimeout(() => scrollThumbnailToIndex(0), 100); break; case 'End': event.preventDefault(); setCurrentImageIndex(data.attachments.length - 1); setTimeout(() => scrollThumbnailToIndex(data.attachments.length - 1), 100); break; default: break; } }, [data.attachments.length, changeMainImage, scrollThumbnailToIndex]); useEffect(() => { document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [handleKeyDown]); // 使用useMemo优化缩略图渲染 const thumbnailSlides = useMemo(() => { return data.attachments.map((attachment, index) => ( changeMainImageByIndex(index)} >
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); changeMainImageByIndex(index); } }} > {`${data?.title { e.target.style.display = 'none'; }} /> {/* 缩略图加载状态指示 */}
)); }, [data.attachments, currentImageIndex, data?.title, changeMainImageByIndex]); return (
{/* 主图显示区域 */}
{data?.title {/* 图片计数器 */} {data.attachments.length > 1 && (
{currentImageIndex + 1} / {data.attachments.length}
)} {/* 导航箭头 - 悬浮时显示 */} {data.attachments.length > 1 && ( <> )}
{/* 缩略图列表 - 使用Swiper实现最佳滚动效果 */} {data.attachments.length > 1 && (
{thumbnailSlides}
)}
{/* 内联样式 */}
); }; export default ProductImageGallery;