查看种子详细信息用户端和管理员端界面

Change-Id: I29e761d67a1eab741a91feb3f4c686055bb1b382
diff --git a/src/pages/managetorrentdetail.jsx b/src/pages/managetorrentdetail.jsx
new file mode 100644
index 0000000..029d06d
--- /dev/null
+++ b/src/pages/managetorrentdetail.jsx
@@ -0,0 +1,287 @@
+import React, { useState, useEffect } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { 
+   Descriptions,
+  Table, 
+  Button, 
+  Modal, 
+  Image, 
+  message, 
+  Spin, 
+  Input, 
+  Select,
+  Pagination,
+  Space,
+  Card
+} from 'antd';
+import { ExclamationCircleOutlined } from '@ant-design/icons';
+import axios from 'axios';
+import '../torrentdetailmanage.css'; // 引入样式
+
+const { confirm } = Modal;
+const { Option } = Select;
+
+//const { confirm } = Modal;
+
+const TorrentDetailmanage = () => {
+  const { id } = useParams(); // 从URL获取种子ID
+  const navigate = useNavigate(); // 用于返回上一页
+  const [torrent, setTorrent] = useState(null);
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState(null);
+  const [isLoading, setIsLoading] = useState(false);
+
+  console.log('Torrent ID:', id);
+
+  const currentUserId = 1; // 示例,实际应从认证系统获取
+  
+
+  // 格式化日期
+  const formatDate = (dateString) => {
+    if (!dateString) return '未知';
+    const date = new Date(dateString);
+    return date.toLocaleString('zh-CN', {
+      year: 'numeric',
+      month: '2-digit',
+      day: '2-digit',
+      hour: '2-digit',
+      minute: '2-digit'
+    });
+  };
+
+  // 处理删除种子
+  const handleDeleteTorrent = async (torrentId) => {
+    if (!currentUserId) {
+      message.warning('请先登录');
+      return;
+    }
+
+    confirm({
+      title: '确认删除',
+      icon: <ExclamationCircleOutlined />,
+      content: '确定要删除这个种子吗?此操作不可恢复!',
+      onOk: async () => {
+        try {
+          await axios.delete(`http://localhost:8080/torrent/delete/${torrentId}`, {
+            params: { userid: currentUserId }
+          });
+          // 成功删除后,更新状态或返回上一页
+          setTorrent(null); // 清空当前种子详情
+          navigate(-1); // 返回上一页
+          message.success('种子删除成功');
+        } catch (err) {
+          console.error('删除种子失败', err);
+          if (err.response && err.response.status === 403) {
+            message.error('无权删除此种子');
+          } else {
+            message.error('删除种子失败');
+          }
+        }
+      }
+    });
+  };
+
+
+const handleDownloadTorrent = async (torrentId) => {
+  if (!currentUserId) {
+    message.warning('请先登录');
+    return;
+  }
+
+  setIsLoading(true); // 开始加载
+  try {
+    // 使用axios发送带有参数的GET请求
+    // const response = await axios.get(`http://localhost:8080/torrent/download/${torrentId}`, {
+    //   params: { userId: currentUserId },  // 正确添加请求参数
+    //   responseType: 'blob'  // 重要:指定响应类型为blob以处理文件下载
+    // });
+
+    // // 创建下载链接
+    // const url = window.URL.createObjectURL(new Blob([response.data]));
+    // const link = document.createElement('a');
+    // link.href = url;
+    // //link.setAttribute('download', 'torrent_file.torrent');  // 可以设置为动态文件名
+    // document.body.appendChild(link);
+    // link.click();
+    // document.body.removeChild(link);
+    // window.URL.revokeObjectURL(url);
+    open(`http://localhost:8080/torrent/download/${torrentId}?userId=${currentUserId}`, '_blank');
+
+    message.success('种子下载开始');
+  } catch (err) {
+    console.error('下载种子失败', err);
+    if (err.response?.status === 404) {
+      message.error('种子不存在');
+    } else {
+      message.error('下载失败: ' + (err.response?.data?.message || err.message));
+    }
+  } finally {
+    setIsLoading(false); // 结束加载
+  }
+};
+
+
+  // 格式化文件大小
+  const formatFileSize = (bytes) => {
+    if (bytes === 0) return '0 Bytes';
+    const k = 1024;
+    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    const i = Math.floor(Math.log(bytes) / Math.log(k));
+    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+  };
+
+  // 在组件函数内部添加这个函数
+const getPromotionName = (promotionId) => {
+  const promotionMap = {
+    1: '上传加倍',
+    2: '下载减半',
+    3: '免费下载',
+    0: '无促销'
+  };
+  
+  return promotionMap[promotionId] || '未知促销';
+};
+
+  // 获取种子详情
+  useEffect(() => {
+    const fetchTorrentDetail = async () => {
+      try {
+        const response = await axios.get(`http://localhost:8080/torrent/${id}`);
+        if (response.status === 200) {
+          setTorrent(response.data);
+        } else {
+          setError('获取种子详情失败');
+        }
+      } catch (err) {
+        console.error('获取种子详情失败:', err);
+        if (err.response) {
+          if (err.response.status === 404) {
+            setError('种子不存在');
+          } else {
+            setError('获取种子详情失败: ' + err.response.data);
+          }
+        } else {
+          setError('网络错误,请稍后重试');
+        }
+      } finally {
+        setLoading(false);
+      }
+    };
+
+    fetchTorrentDetail();
+  }, [id]);
+
+  console.log('Torrent Detail:', torrent);
+
+  // 返回上一页
+  const handleBack = () => {
+    navigate(-1); // 返回上一页
+  };
+
+  // 如果正在加载
+  if (loading) {
+    return (
+      <div className="flex justify-center items-center h-96">
+        <Spin size="large" tip="加载中..." />
+      </div>
+    );
+  }
+
+  // 如果有错误
+  if (error) {
+    return (
+      <div className="p-6">
+        <Card>
+          <div className="text-center p-6">
+            <ExclamationCircleOutlined className="text-2xl text-red-500 mb-4" />
+            <h3 className="text-lg font-medium text-red-600 mb-2">错误</h3>
+            <p className="text-gray-600">{error}</p>
+            <Button type="primary" onClick={handleBack} className="mt-4">
+              返回
+            </Button>
+          </div>
+        </Card>
+      </div>
+    );
+  }
+
+  // 如果种子不存在
+  if (!torrent) {
+    return (
+      <div className="p-6">
+        <Card>
+          <div className="text-center p-6">
+            <ExclamationCircleOutlined className="text-2xl text-yellow-500 mb-4" />
+            <h3 className="text-lg font-medium text-yellow-600 mb-2">种子不存在</h3>
+            <p className="text-gray-600">抱歉,您查找的种子不存在或已被删除。</p>
+            <Button type="primary" onClick={handleBack} className="mt-4">
+              返回
+            </Button>
+          </div>
+        </Card>
+      </div>
+    );
+  }
+
+return (
+  <div className="torrent-detail-page">
+    <Card
+      className="torrent1-card"
+      title={<div className="torrent-title">种子详情</div>}
+      extra={
+        <Button type="primary" onClick={handleBack}>
+          返回列表
+        </Button>
+      }
+    >
+      <Descriptions bordered column={1} size="middle">
+        <Descriptions.Item label="ID">{torrent.torrentid}</Descriptions.Item>
+
+        {torrent.coverImagePath && (
+          <Descriptions.Item label="封面图片">
+            <Image
+              className="torrent-cover-image"
+              src={torrent.coverImagePath}
+              alt="种子封面"
+              width={260}
+              height={160}
+              placeholder={
+                <div className="w-60 h-40 bg-gray-200 flex items-center justify-center">
+                  加载中...
+                </div>
+              }
+            />
+          </Descriptions.Item>
+        )}
+
+        <Descriptions.Item label="文件名">{torrent.filename}</Descriptions.Item>
+        <Descriptions.Item label="大小">{formatFileSize(torrent.torrentSize)}</Descriptions.Item>
+        <Descriptions.Item label="上传者ID">{torrent.uploader_id}</Descriptions.Item>
+        <Descriptions.Item label="上传时间">{formatDate(torrent.uploadTime)}</Descriptions.Item>
+        <Descriptions.Item label="下载次数">{torrent.downloadCount}</Descriptions.Item>
+        <Descriptions.Item label="促销">{getPromotionName(torrent.promotionid)}</Descriptions.Item>
+        <Descriptions.Item label="描述">{torrent.description || '无描述'}</Descriptions.Item>
+      </Descriptions>
+
+      <div className="torrent-buttons">
+        <Button 
+          danger 
+          onClick={() => handleDeleteTorrent(torrent.torrentid)}
+          loading={isLoading}
+        >
+          删除
+        </Button>
+        <Button 
+          type="primary" 
+          onClick={() => handleDownloadTorrent(torrent.torrentid)}
+          loading={isLoading}
+        >
+          下载
+        </Button>
+      </div>
+    </Card>
+  </div>
+);
+};
+
+export default TorrentDetailmanage;
\ No newline at end of file