| import React, { useEffect, useState, useRef } from 'react'; |
| import './Promotion.css'; |
| |
| const API_BASE = process.env.REACT_APP_API_BASE; |
| |
| const Promotion = () => { |
| const [promotions, setPromotions] = useState([]); |
| const [coldResources, setColdResources] = useState([]); |
| const [loading, setLoading] = useState(true); |
| |
| // 轮播索引 |
| const [promoIndex, setPromoIndex] = useState(0); |
| const [coldIndex, setColdIndex] = useState(0); |
| |
| // 计时器引用,用于清理 |
| const promoTimerRef = useRef(null); |
| const coldTimerRef = useRef(null); |
| |
| useEffect(() => { |
| fetchData(); |
| }, []); |
| |
| // 自动轮播:促销活动 |
| useEffect(() => { |
| if (promotions.length === 0) return; |
| // 清理旧的计时器 |
| clearInterval(promoTimerRef.current); |
| promoTimerRef.current = setInterval(() => { |
| setPromoIndex(prev => (prev + 1) % promotions.length); |
| }, 5000); |
| return () => clearInterval(promoTimerRef.current); |
| }, [promotions]); |
| |
| // 自动轮播:冷门资源 |
| useEffect(() => { |
| if (coldResources.length === 0) return; |
| clearInterval(coldTimerRef.current); |
| coldTimerRef.current = setInterval(() => { |
| setColdIndex(prev => (prev + 1) % coldResources.length); |
| }, 5000); |
| return () => clearInterval(coldTimerRef.current); |
| }, [coldResources]); |
| |
| const fetchData = async () => { |
| try { |
| const promoResponse = await fetch(`${API_BASE}/echo/promotions/active`); |
| const promoData = await promoResponse.json(); |
| setPromotions(promoData); |
| |
| const coldResponse = await fetch(`${API_BASE}/echo/resources/cold`); |
| const coldData = await coldResponse.json(); |
| setColdResources(coldData); |
| } catch (error) { |
| console.error('获取数据失败:', error); |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| if (loading) { |
| return <div className="promotion-container">加载中...</div>; |
| } |
| |
| // 手动切换 |
| const prevPromo = () => setPromoIndex((promoIndex - 1 + promotions.length) % promotions.length); |
| const nextPromo = () => setPromoIndex((promoIndex + 1) % promotions.length); |
| const prevCold = () => setColdIndex((coldIndex - 1 + coldResources.length) % coldResources.length); |
| const nextCold = () => setColdIndex((coldIndex + 1) % coldResources.length); |
| |
| const currentPromo = promotions[promoIndex]; |
| const currentCold = coldResources[coldIndex]; |
| |
| return ( |
| <div className="promotion-container carousel-container"> |
| {/* 促销活动轮播 */} |
| <section className="carousel-section"> |
| <h2>当前促销活动</h2> |
| {promotions.length === 0 ? ( |
| <div className="empty-state">暂无促销活动</div> |
| ) : ( |
| <div |
| className="carousel" |
| onMouseEnter={() => clearInterval(promoTimerRef.current)} |
| onMouseLeave={() => { |
| promoTimerRef.current = setInterval(() => { |
| setPromoIndex(prev => (prev + 1) % promotions.length); |
| }, 3000); |
| }} |
| > |
| <button className="arrow left" onClick={prevPromo}><</button> |
| <div className="slide"> |
| <div><strong>种子类型:</strong>{currentPromo.category}</div> |
| <div><strong>促销时间:</strong> |
| {new Date(currentPromo.promotion_start_time).toLocaleString()} ~{' '} |
| {new Date(currentPromo.promotion_end_time).toLocaleString()} |
| </div> |
| <div><strong>下载折扣:</strong>{currentPromo.download_discount ?? '无'}</div> |
| <div><strong>上传奖励:</strong>{currentPromo.upload_reward ?? '无'}</div> |
| {currentPromo.description && ( |
| <div><strong>详细描述:</strong>{currentPromo.description}</div> |
| )} |
| </div> |
| <button className="arrow right" onClick={nextPromo}>></button> |
| </div> |
| )} |
| </section> |
| |
| {/* 冷门资源轮播 */} |
| <section className="carousel-section"> |
| <h2>冷门资源推荐</h2> |
| {coldResources.length === 0 ? ( |
| <div className="empty-state">暂无冷门资源推荐</div> |
| ) : ( |
| <div |
| className="carousel" |
| onMouseEnter={() => clearInterval(coldTimerRef.current)} |
| onMouseLeave={() => { |
| coldTimerRef.current = setInterval(() => { |
| setColdIndex(prev => (prev + 1) % coldResources.length); |
| }, 3000); |
| }} |
| > |
| <button className="arrow left" onClick={prevCold}><</button> |
| <div className="slide cold-slide"> |
| <img src={currentCold.poster} alt={currentCold.title} className="resource-poster" /> |
| <div className="resource-info"> |
| <div><strong>标题:</strong>{currentCold.title}</div> |
| <div><strong>下载量:</strong>{currentCold.download_count} | <strong>种子数:</strong>{currentCold.seed_count}</div> |
| <div><strong>激励:</strong> |
| {currentCold.incentives?.download_exempt && <span className="incentive-badge">免下载量</span>} |
| {currentCold.incentives?.extra_seed_bonus && <span className="incentive-badge">做种加成</span>} |
| {!(currentCold.incentives?.download_exempt || currentCold.incentives?.extra_seed_bonus) && '无'} |
| </div> |
| </div> |
| </div> |
| <button className="arrow right" onClick={nextCold}>></button> |
| </div> |
| )} |
| </section> |
| </div> |
| ); |
| }; |
| |
| export default Promotion; |