blob: 9af56bc8f92b46fc6d85ffa6ee98b906283da749 [file] [log] [blame]
Krishyaf1d0ea82025-05-03 17:01:58 +08001import React, { useEffect, useState, useRef } from 'react';
2import './Promotion.css';
3
4const API_BASE = process.env.REACT_APP_API_BASE;
5
6const Promotion = () => {
7 const [promotions, setPromotions] = useState([]);
8 const [coldResources, setColdResources] = useState([]);
9 const [loading, setLoading] = useState(true);
10
11 // 轮播索引
12 const [promoIndex, setPromoIndex] = useState(0);
13 const [coldIndex, setColdIndex] = useState(0);
14
15 // 计时器引用,用于清理
16 const promoTimerRef = useRef(null);
17 const coldTimerRef = useRef(null);
18
19 useEffect(() => {
20 fetchData();
21 }, []);
22
23 // 自动轮播:促销活动
24 useEffect(() => {
25 if (promotions.length === 0) return;
26 // 清理旧的计时器
27 clearInterval(promoTimerRef.current);
28 promoTimerRef.current = setInterval(() => {
29 setPromoIndex(prev => (prev + 1) % promotions.length);
30 }, 5000);
31 return () => clearInterval(promoTimerRef.current);
32 }, [promotions]);
33
34 // 自动轮播:冷门资源
35 useEffect(() => {
36 if (coldResources.length === 0) return;
37 clearInterval(coldTimerRef.current);
38 coldTimerRef.current = setInterval(() => {
39 setColdIndex(prev => (prev + 1) % coldResources.length);
40 }, 5000);
41 return () => clearInterval(coldTimerRef.current);
42 }, [coldResources]);
43
44 const fetchData = async () => {
45 try {
46 const promoResponse = await fetch(`${API_BASE}/echo/promotions/active`);
47 const promoData = await promoResponse.json();
48 setPromotions(promoData);
49
50 const coldResponse = await fetch(`${API_BASE}/echo/resources/cold`);
51 const coldData = await coldResponse.json();
52 setColdResources(coldData);
53 } catch (error) {
54 console.error('获取数据失败:', error);
55 } finally {
56 setLoading(false);
57 }
58 };
59
60 if (loading) {
61 return <div className="promotion-container">加载中...</div>;
62 }
63
64 // 手动切换
65 const prevPromo = () => setPromoIndex((promoIndex - 1 + promotions.length) % promotions.length);
66 const nextPromo = () => setPromoIndex((promoIndex + 1) % promotions.length);
67 const prevCold = () => setColdIndex((coldIndex - 1 + coldResources.length) % coldResources.length);
68 const nextCold = () => setColdIndex((coldIndex + 1) % coldResources.length);
69
70 const currentPromo = promotions[promoIndex];
71 const currentCold = coldResources[coldIndex];
72
73 return (
74 <div className="promotion-container carousel-container">
75 {/* 促销活动轮播 */}
76 <section className="carousel-section">
77 <h2>当前促销活动</h2>
78 {promotions.length === 0 ? (
79 <div className="empty-state">暂无促销活动</div>
80 ) : (
81 <div
82 className="carousel"
83 onMouseEnter={() => clearInterval(promoTimerRef.current)}
84 onMouseLeave={() => {
85 promoTimerRef.current = setInterval(() => {
86 setPromoIndex(prev => (prev + 1) % promotions.length);
87 }, 3000);
88 }}
89 >
90 <button className="arrow left" onClick={prevPromo}>&lt;</button>
91 <div className="slide">
92 <div><strong>种子类型:</strong>{currentPromo.category}</div>
93 <div><strong>促销时间:</strong>
94 {new Date(currentPromo.promotion_start_time).toLocaleString()} ~{' '}
95 {new Date(currentPromo.promotion_end_time).toLocaleString()}
96 </div>
97 <div><strong>下载折扣:</strong>{currentPromo.download_discount ?? '无'}</div>
98 <div><strong>上传奖励:</strong>{currentPromo.upload_reward ?? '无'}</div>
99 {currentPromo.description && (
100 <div><strong>详细描述:</strong>{currentPromo.description}</div>
101 )}
102 </div>
103 <button className="arrow right" onClick={nextPromo}>&gt;</button>
104 </div>
105 )}
106 </section>
107
108 {/* 冷门资源轮播 */}
109 <section className="carousel-section">
110 <h2>冷门资源推荐</h2>
111 {coldResources.length === 0 ? (
112 <div className="empty-state">暂无冷门资源推荐</div>
113 ) : (
114 <div
115 className="carousel"
116 onMouseEnter={() => clearInterval(coldTimerRef.current)}
117 onMouseLeave={() => {
118 coldTimerRef.current = setInterval(() => {
119 setColdIndex(prev => (prev + 1) % coldResources.length);
120 }, 3000);
121 }}
122 >
123 <button className="arrow left" onClick={prevCold}>&lt;</button>
124 <div className="slide cold-slide">
125 <img src={currentCold.poster} alt={currentCold.title} className="resource-poster" />
126 <div className="resource-info">
127 <div><strong>标题:</strong>{currentCold.title}</div>
128 <div><strong>下载量:</strong>{currentCold.download_count} | <strong>种子数:</strong>{currentCold.seed_count}</div>
129 <div><strong>激励:</strong>
130 {currentCold.incentives?.download_exempt && <span className="incentive-badge">免下载量</span>}
131 {currentCold.incentives?.extra_seed_bonus && <span className="incentive-badge">做种加成</span>}
132 {!(currentCold.incentives?.download_exempt || currentCold.incentives?.extra_seed_bonus) && '无'}
133 </div>
134 </div>
135 </div>
136 <button className="arrow right" onClick={nextCold}>&gt;</button>
137 </div>
138 )}
139 </section>
140 </div>
141 );
142};
143
144export default Promotion;