blob: 8c60baff5bf456f4c6e3065c839bd13fd5dccc38 [file] [log] [blame]
// Personal.jsx
import React, { useState, useEffect } from 'react';
import { useNavigate, useLocation, Outlet } from 'react-router-dom';
import { getUserInfo, getDownloadQuota, getDownloadProgress } from '../../api/personal';
import './Personal.css';
import ActionCard from './ActionCard';
const Personal = () => {
const navigate = useNavigate();
const location = useLocation();
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [downloadProgress, setDownloadProgress] = useState({});
useEffect(() => {
const fetchData = async () => {
try {
// 并行获取用户信息和下载额度
const [userInfo, downloadQuota] = await Promise.all([
getUserInfo(),
getDownloadQuota()
]);
setUserData({
username: userInfo.username,
avatar: 'https://via.placeholder.com/150',
joinDate: userInfo.registTime,
level: userInfo.level, // 可以根据userInfo.level设置不同等级
points: userInfo.magicPoints,
upload: userInfo.upload,
download: userInfo.download,
ratio: userInfo.shareRate,
downloadQuota: {
total: downloadQuota.total,
used: downloadQuota.used,
remaining: downloadQuota.remaining
}
});
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// 获取下载进度数据
const fetchDownloadProgress = async () => {
try {
const progressData = await getDownloadProgress();
setDownloadProgress(progressData);
} catch (err) {
console.error('获取下载进度失败:', err);
}
};
useEffect(() => {
// 初始获取下载进度
fetchDownloadProgress();
// 设置定时器,每10秒获取一次下载进度
const intervalId = setInterval(fetchDownloadProgress, 10000);
// 组件卸载时清除定时器
return () => clearInterval(intervalId);
}, []);
if (loading) {
return <div className="loading">加载中...</div>;
}
if (error) {
return <div className="error">错误: {error}</div>;
}
if (!userData) {
return <div className="error">未获取到用户数据</div>;
}
const features = [
{
title: '兑换区',
description: '下载量/邀请码',
path: '/personal/Exchange' // 相对路径
},
{
title: '上传记录',
description: '管理上传的资源',
path: '/personal/Upload'
},
{
title: '消息通知',
description: '查看系统消息',
path: '/personal/Notice'
},
{
title: '设置',
description: '修改个人资料',
path: '/personal/Setting'
}
];
const handleCardClick = (path) => {
navigate(path); // 相对导航
};
const handleBack = () => {
if (location.state?.fromSubpage) {
// 如果是从子页面返回,则继续返回到Dashboard
navigate(`/dashboard/${location.state.dashboardTab || ''}`, {
replace: true
});
} else {
// 普通返回逻辑
navigate(-1);
}
};
const formatSize = (bytes) => {
if (bytes < 1024) return `${bytes} B`;
const kb = bytes / 1024;
if (kb < 1024) return `${kb.toFixed(2)} KB`;
const mb = kb / 1024;
if (mb < 1024) return `${mb.toFixed(2)} MB`;
const gb = mb / 1024;
return `${gb.toFixed(2)} GB`;
};
// 添加进度条颜色函数
const getProgressColor = (percentage) => {
if (percentage < 0.3) return '#4CAF50'; // 绿色
if (percentage < 0.7) return '#FFC107'; // 黄色
return '#F44336'; // 红色
};
return (
<div className="personal-container">
{/* 返回按钮 */}
<button className="back-button" onClick={handleBack}>
&larr; 返回
</button>
{/* 用户基本信息卡片 */}
<div className="profile-card">
<div className="profile-header">
<img
src={userData.avatar}
alt={userData.username}
className="profile-avatar"
/>
<div className="profile-info">
<h2 className="username">{userData.username}</h2>
<div className="user-meta">
<span>加入时间: {userData.joinDate}</span>
<span>会员等级: Lv.{userData.level}</span>
</div>
</div>
</div>
{/* 用户数据统计 */}
<div className="stats-grid">
<div className="stat-item">
<div className="stat-label">保种积分</div>
<div className="stat-value">{userData.points}</div>
</div>
<div className="stat-item">
<div className="stat-label">上传量</div>
<div className="stat-value">{formatSize(userData.upload)}</div>
</div>
<div className="stat-item">
<div className="stat-label">下载量</div>
<div className="stat-value">{formatSize(userData.download)}</div>
</div>
<div className="stat-item">
<div className="stat-label">分享率</div>
<div className="stat-value">{userData.ratio}</div>
</div>
</div>
</div>
{/* 下载额度卡片 */}
<div className="quota-card">
<h3>下载额度</h3>
<div className="quota-info">
<span className="quota-used">
{formatSize(userData.downloadQuota.used)} 已使用
</span>
<span className="quota-remaining">
{formatSize(userData.downloadQuota.remaining)} 剩余
</span>
</div>
<div className="progress-bar">
<div
className="progress-fill"
style={{
width: `${(userData.downloadQuota.used / userData.downloadQuota.total) * 100}%`,
backgroundColor: getProgressColor(userData.downloadQuota.used / userData.downloadQuota.total)
}}
></div>
</div>
<div className="quota-total">
总额度: {formatSize(userData.downloadQuota.total)}
</div>
</div>
{Object.keys(downloadProgress).length > 0 && (
<div className="progress-card">
<h3>当前下载进度</h3>
{Object.entries(downloadProgress).map(([taskId, progress]) => (
<div key={taskId} className="download-task">
<div className="task-info">
<span className="task-id">任务: {taskId.substring(0, 8)}...</span>
<span className="task-progress">{Math.round(progress * 100)}%</span>
</div>
<div className="progress-bar">
<div
className="progress-fill"
style={{ width: `${progress * 100}%` }}
></div>
</div>
</div>
))}
</div>
)}
{/* 功能卡片区 */}
<div className="action-cards">
{features.map((feature) => (
<div
key={feature.path}
className="action-card"
onClick={() => handleCardClick(feature.path)}
>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</div>
))}
</div>
{/* 子路由出口 */}
<div className="subpage-container">
<Outlet />
</div>
</div>
);
};
export default Personal;