/** * 轮播图组件 * * 展示首页轮播图,支持自动播放和手动滑动 * 使用真实数据 */ import React, { useState, useEffect, useRef, useCallback } from 'react'; import { View, Image, TouchableOpacity, ScrollView, NativeScrollEvent, NativeSyntheticEvent, ActivityIndicator, Dimensions, Alert, } from 'react-native'; import Colors from '@/constants/Colors'; // import type { Banner } from '@/types/home'; import { styles } from './styles'; import useMsgStore from '@/stores/msgStore'; interface BannerSwiperProps { theme: 'light' | 'dark'; } const { width } = Dimensions.get('window'); /** * 轮播图组件 */ export default function BannerSwiper({ theme }: BannerSwiperProps) { const s = styles[theme]; const [currentIndex, setCurrentIndex] = useState(0); const [loading, setLoading] = useState(true); const scrollViewRef = useRef(null); const autoPlayTimerRef = useRef(null); const { homeBanner } = useMsgStore(); // 加载轮播图数据 useEffect(() => { // 如果有传入的 banners 数据,直接使用 if (homeBanner.length > 0) { setLoading(false); return; } // 如果没有数据,保持 loading 状态显示骨架屏 }, [homeBanner]); // 处理 Banner 点击 const onBannerPress = useCallback((banner: Record) => { Alert.alert('轮播图', `点击了: ${banner.title || banner.id}`); // 这里可以添加导航逻辑 }, []); // 处理滚动事件 const handleScroll = (event: NativeSyntheticEvent) => { const contentOffsetX = event.nativeEvent.contentOffset.x; const index = Math.round(contentOffsetX / (width - 24)); setCurrentIndex(Math.min(index, homeBanner.length - 1)); }; // 启动自动播放 const startAutoPlay = useCallback(() => { if (homeBanner.length <= 1) return; autoPlayTimerRef.current = setInterval(() => { setCurrentIndex((prev) => { const nextIndex = (prev + 1) % homeBanner.length; scrollViewRef.current?.scrollTo({ x: nextIndex * (width - 24), animated: true, }); return nextIndex; }); }, 5000); }, [homeBanner.length]); // 停止自动播放 const stopAutoPlay = useCallback(() => { if (autoPlayTimerRef.current) { clearInterval(autoPlayTimerRef.current); } }, []); // 自动播放 useEffect(() => { if (!loading && homeBanner.length > 0) { startAutoPlay(); } return () => stopAutoPlay(); }, [loading, homeBanner.length, startAutoPlay, stopAutoPlay]); // 骨架屏 - 加载中显示占位符 if (loading || homeBanner.length === 0) { return ( ); } return ( {homeBanner.map((banner) => ( onBannerPress(banner)} activeOpacity={0.9} > ))} {/* 指示器 */} {homeBanner.map((_, index) => ( ))} ); }