修改促销、优化页面布局

Change-Id: Iae813b5b6557efa7059fe6d94bc32e96c984e4ea
diff --git a/src/pages/Forum/promotion-part/PromotionDetailDialog.jsx b/src/pages/Forum/promotion-part/PromotionDetailDialog.jsx
new file mode 100644
index 0000000..5310c79
--- /dev/null
+++ b/src/pages/Forum/promotion-part/PromotionDetailDialog.jsx
@@ -0,0 +1,166 @@
+import { type } from '@testing-library/user-event/dist/type';
+import React from 'react';
+import { useNavigate } from 'react-router-dom';
+
+const PromotionDetailDialog = ({
+  showDetailDialog,
+  promotionDetail,
+  closeDetailDialog,
+  torrents,
+  fetchTorrentDetail
+}) => {
+  const navigate = useNavigate();
+
+  // 处理API返回的日期数组格式
+  const parseApiDate = (dateArray) => {
+    if (!Array.isArray(dateArray) || dateArray.length < 3) return null;
+    
+    // 注意:JavaScript的Date月份是从0开始的,所以需要减1
+    return new Date(
+      dateArray[0],        // 年
+      dateArray[1] - 1,    // 月 (减1)
+      dateArray[2],        // 日
+      dateArray[3] || 0,   // 时 (默认0)
+      dateArray[4] || 0,   // 分 (默认0)
+      dateArray[5] || 0    // 秒 (默认0)
+    );
+  };
+
+  const formatDateTime = (dateArray) => {
+    if (!dateArray) return '未知';
+    
+    try {
+      const date = parseApiDate(dateArray);
+      return date ? date.toLocaleString() : '格式错误';
+    } catch (e) {
+      return '格式错误';
+    }
+  };
+
+  const getUploadBonusDisplay = (promo) => {
+    if (!promo || !promo.discountPercentage) return '无';
+    const bonus = promo.discountPercentage;
+    return bonus > 0 ? `+${bonus}%` : `-${Math.abs(bonus)}%`;
+  };
+
+  const getDownloadDiscountDisplay = (promo) => {
+    if (!promo || !promo.downloadDiscount) return '无';
+    const discount = (1 - promo.downloadDiscount) * 100;
+    return discount > 0 ? `-${discount.toFixed(1)}%` : '无';
+  };
+
+  const redirectToTorrentDetail = (torrentId) => {
+    if (fetchTorrentDetail) {
+      navigate(`/seed/${torrentId}`);
+    }
+  };
+
+  return (
+    showDetailDialog && promotionDetail && (
+      <div className="detail-dialog-overlay">
+        <div className="detail-dialog">
+          <h3 className="detail-dialog-title">{promotionDetail.name}</h3>
+          <button 
+            className="close-btn" 
+            onClick={closeDetailDialog}
+          >
+            &times;
+          </button>
+          
+          <div className="detail-content">
+            {/* <div className="detail-item"> */}
+              {/* <span className="detail-label">促销ID:</span> */}
+              {/* <span className="detail-value">{promotionDetail.id}</span>
+            </div> */}
+            {/* <div className="detail-item">
+              <span className="detail-label">促销名称:</span>
+              <span className="detail-value">{promotionDetail.name}</span>
+            </div> */}
+            <div className="detail-item">
+              <span className="detail-label">开始时间:</span>
+              <span className="detail-value">{formatDateTime(promotionDetail.startTime)}</span>
+            </div>
+            <div className="detail-item">
+              <span className="detail-label">结束时间:</span>
+              <span className="detail-value">{formatDateTime(promotionDetail.endTime)}</span>
+            </div>
+            <div className="detail-item">
+              <span className="detail-label">上传奖励:</span>
+              <span className="detail-value">{getUploadBonusDisplay(promotionDetail)}</span>
+            </div>
+            <div className="detail-item">
+              <span className="detail-label">下载折扣:</span>
+              <span className="detail-value">{getDownloadDiscountDisplay(promotionDetail)}</span>
+            </div>
+            {/* <div className="detail-item">
+              <span className="detail-label">创建时间:</span>
+              <span className="detail-value">{formatDateTime(promotionDetail.createTime)}</span>
+            </div> */}
+            {/* <div className="detail-item">
+              <span className="detail-label">创建者:</span>
+              <span className="detail-value">{promotionDetail.creator || '未知'}</span>
+            </div> */}
+            
+            {promotionDetail.description && (
+              <div className="detail-item">
+                <span className="detail-label">描述:</span>
+                <span className="detail-value">{promotionDetail.description}</span>
+              </div>
+            )}
+            
+            {/* 适用种子列表 */}
+            <div className="detail-item">
+              <span className="detail-label">适用种子:</span>
+              <div className="detail-value">
+                {promotionDetail.applicableTorrentIds ? (
+                  <div className="torrent-list">
+                    {/* 解析字符串形式的数组 */}
+                    {parseTorrentIds(promotionDetail.applicableTorrentIds).map(torrentId => {
+                      const matchedTorrent = torrents.find(t => t.id === torrentId) || {};
+
+                      return (
+                        <button
+                          key={torrentId}
+                          className="torrent-link"
+                          onClick={() => redirectToTorrentDetail(torrentId)}
+                          aria-label={`查看种子${matchedTorrent.name || torrentId}的详情`}
+                        >
+                          {matchedTorrent.name || `种子${torrentId}`}
+                          {/* {matchedTorrent.seeders > 10 && <span className="status-indicator hot">热门</span>}
+                          {matchedTorrent.seeders === 0 && <span className="status-indicator cold">冷门</span>} */}
+                        </button>
+                      );
+                    })}
+                  </div>
+                ) : (
+                  <span className="empty-list">暂无适用种子</span>
+                )}
+              </div>
+            </div>
+          </div>
+          
+          <div className="dialog-buttons">
+            <button onClick={closeDetailDialog}>关闭</button>
+          </div>
+        </div>
+      </div>
+    )
+  );
+};
+
+// 解析种子ID字符串为数组
+const parseTorrentIds = (idString) => {
+  if (typeof idString === 'number') {
+    return [idString];
+  }
+
+  if (Array.isArray(idString)) {
+    return idString;
+  }
+
+  let items = typeof idString === 'string' && !idString.startsWith('[') ? idString.split(',') : JSON.parse(idString || '[]');
+
+  return items;
+};
+
+export default PromotionDetailDialog;
\ No newline at end of file