修改好友动态、发布动态、促销模块、创建帖子,Resolve review.

Change-Id: I84a2460dd1208bc703b0527d98225204d03e5efc
diff --git a/src/pages/Forum/promotion-part/Promotion.jsx b/src/pages/Forum/promotion-part/Promotion.jsx
new file mode 100644
index 0000000..9af56bc
--- /dev/null
+++ b/src/pages/Forum/promotion-part/Promotion.jsx
@@ -0,0 +1,144 @@
+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}>&lt;</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}>&gt;</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}>&lt;</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}>&gt;</button>
+          </div>
+        )}
+      </section>
+    </div>
+  );
+};
+
+export default Promotion;