blob: 36d6319f868b62e710d334648fd6b790e9c503c2 [file] [log] [blame]
Krishyaf1d0ea82025-05-03 17:01:58 +08001import React, { useEffect, useState, useRef } from 'react';
2import './Promotion.css';
3
Krishyaf1d0ea82025-05-03 17:01:58 +08004const Promotion = () => {
5 const [promotions, setPromotions] = useState([]);
6 const [coldResources, setColdResources] = useState([]);
7 const [loading, setLoading] = useState(true);
8
Krishyaf1d0ea82025-05-03 17:01:58 +08009 const [promoIndex, setPromoIndex] = useState(0);
10 const [coldIndex, setColdIndex] = useState(0);
11
Krishyaf1d0ea82025-05-03 17:01:58 +080012 const promoTimerRef = useRef(null);
13 const coldTimerRef = useRef(null);
14
15 useEffect(() => {
16 fetchData();
17 }, []);
18
Krishyaf1d0ea82025-05-03 17:01:58 +080019 useEffect(() => {
20 if (promotions.length === 0) return;
Krishyaf1d0ea82025-05-03 17:01:58 +080021 clearInterval(promoTimerRef.current);
22 promoTimerRef.current = setInterval(() => {
23 setPromoIndex(prev => (prev + 1) % promotions.length);
24 }, 5000);
25 return () => clearInterval(promoTimerRef.current);
26 }, [promotions]);
27
Krishyaf1d0ea82025-05-03 17:01:58 +080028 useEffect(() => {
29 if (coldResources.length === 0) return;
30 clearInterval(coldTimerRef.current);
31 coldTimerRef.current = setInterval(() => {
32 setColdIndex(prev => (prev + 1) % coldResources.length);
33 }, 5000);
34 return () => clearInterval(coldTimerRef.current);
35 }, [coldResources]);
36
37 const fetchData = async () => {
38 try {
Krishya2e0f49a2025-05-29 10:59:01 +080039 // ✅ 获取促销活动列表(新接口)
40 const promoResponse = await fetch(`seeds/promotions`);
41 const promoJson = await promoResponse.json();
42 const promoData = Array.isArray(promoJson?.result) ? promoJson.result : [];
Krishyaf1d0ea82025-05-03 17:01:58 +080043 setPromotions(promoData);
44
Krishya2e0f49a2025-05-29 10:59:01 +080045 // 冷门资源(接口保持不变,若已更换请提供文档)
Krishya2283d882025-05-27 22:25:19 +080046 const coldResponse = await fetch(`/echo/resources/cold`);
Krishyaf1d0ea82025-05-03 17:01:58 +080047 const coldData = await coldResponse.json();
48 setColdResources(coldData);
49 } catch (error) {
50 console.error('获取数据失败:', error);
51 } finally {
52 setLoading(false);
53 }
54 };
55
56 if (loading) {
57 return <div className="promotion-container">加载中...</div>;
58 }
59
Krishyaf1d0ea82025-05-03 17:01:58 +080060 const prevPromo = () => setPromoIndex((promoIndex - 1 + promotions.length) % promotions.length);
61 const nextPromo = () => setPromoIndex((promoIndex + 1) % promotions.length);
62 const prevCold = () => setColdIndex((coldIndex - 1 + coldResources.length) % coldResources.length);
63 const nextCold = () => setColdIndex((coldIndex + 1) % coldResources.length);
64
65 const currentPromo = promotions[promoIndex];
66 const currentCold = coldResources[coldIndex];
67
68 return (
69 <div className="promotion-container carousel-container">
70 {/* 促销活动轮播 */}
71 <section className="carousel-section">
72 <h2>当前促销活动</h2>
Krishya2283d882025-05-27 22:25:19 +080073 {promotions.length === 0 || !currentPromo ? (
Krishyaf1d0ea82025-05-03 17:01:58 +080074 <div className="empty-state">暂无促销活动</div>
75 ) : (
76 <div
77 className="carousel"
78 onMouseEnter={() => clearInterval(promoTimerRef.current)}
79 onMouseLeave={() => {
80 promoTimerRef.current = setInterval(() => {
81 setPromoIndex(prev => (prev + 1) % promotions.length);
82 }, 3000);
83 }}
84 >
85 <button className="arrow left" onClick={prevPromo}>&lt;</button>
86 <div className="slide">
Krishya2e0f49a2025-05-29 10:59:01 +080087 <div><strong>促销名称:</strong>{currentPromo?.name ?? '未知'}</div>
Krishyaf1d0ea82025-05-03 17:01:58 +080088 <div><strong>促销时间:</strong>
Krishya2e0f49a2025-05-29 10:59:01 +080089 {currentPromo?.pStartTime && currentPromo?.pEndTime
90 ? `${new Date(currentPromo.pStartTime).toLocaleString()} ~ ${new Date(currentPromo.pEndTime).toLocaleString()}`
Krishya2283d882025-05-27 22:25:19 +080091 : '未知'}
Krishyaf1d0ea82025-05-03 17:01:58 +080092 </div>
Krishya2e0f49a2025-05-29 10:59:01 +080093 <div><strong>上传奖励系数:</strong>{currentPromo?.uploadCoeff ?? '无'}</div>
94 <div><strong>下载折扣系数:</strong>{currentPromo?.downloadCoeff ?? '无'}</div>
Krishya2283d882025-05-27 22:25:19 +080095 {currentPromo?.description && (
Krishya2e0f49a2025-05-29 10:59:01 +080096 <div><strong>描述:</strong>{currentPromo.description}</div>
Krishyaf1d0ea82025-05-03 17:01:58 +080097 )}
98 </div>
99 <button className="arrow right" onClick={nextPromo}>&gt;</button>
100 </div>
101 )}
102 </section>
103
104 {/* 冷门资源轮播 */}
105 <section className="carousel-section">
106 <h2>冷门资源推荐</h2>
Krishya2283d882025-05-27 22:25:19 +0800107 {coldResources.length === 0 || !currentCold ? (
Krishyaf1d0ea82025-05-03 17:01:58 +0800108 <div className="empty-state">暂无冷门资源推荐</div>
109 ) : (
110 <div
111 className="carousel"
112 onMouseEnter={() => clearInterval(coldTimerRef.current)}
113 onMouseLeave={() => {
114 coldTimerRef.current = setInterval(() => {
115 setColdIndex(prev => (prev + 1) % coldResources.length);
116 }, 3000);
117 }}
118 >
119 <button className="arrow left" onClick={prevCold}>&lt;</button>
120 <div className="slide cold-slide">
121 <img src={currentCold.poster} alt={currentCold.title} className="resource-poster" />
122 <div className="resource-info">
123 <div><strong>标题:</strong>{currentCold.title}</div>
Krishya2e0f49a2025-05-29 10:59:01 +0800124 <div><strong>下载量:</strong>{currentCold.download_count ?? 0} | <strong>种子数:</strong>{currentCold.seed_count ?? 0}</div>
Krishyaf1d0ea82025-05-03 17:01:58 +0800125 <div><strong>激励:</strong>
126 {currentCold.incentives?.download_exempt && <span className="incentive-badge">免下载量</span>}
127 {currentCold.incentives?.extra_seed_bonus && <span className="incentive-badge">做种加成</span>}
Krishya2283d882025-05-27 22:25:19 +0800128 {!currentCold.incentives?.download_exempt && !currentCold.incentives?.extra_seed_bonus && '无'}
Krishyaf1d0ea82025-05-03 17:01:58 +0800129 </div>
130 </div>
131 </div>
132 <button className="arrow right" onClick={nextCold}>&gt;</button>
133 </div>
134 )}
135 </section>
136 </div>
137 );
138};
139
140export default Promotion;
Krishya2283d882025-05-27 22:25:19 +0800141