blob: 16fdcd267b466dbb2d1e5b1bc3b257aba9b22735 [file] [log] [blame]
import React, { useState, useEffect } from "react";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
import "./App.css";
export default function UserProfile() {
const navigate = useNavigate();
const [userInfo, setUserInfo] = useState({
avatar_url: "",
username: "示例用户",
email: "user@example.com",
invite_left: "",
school: "",
account_status: "",
gender: "",
});
const [tempUserInfo, setTempUserInfo] = useState({ ...userInfo });
const [userSeeds, setUserSeeds] = useState([]);
const [userStats, setUserStats] = useState({
magic: 0,
upload: 0,
download: 0,
ratio: 0,
});
// 新增:根据userid从后端获取用户信息
useEffect(() => {
const fetchUserInfo = async () => {
// 假设userid存储在localStorage或其他地方
// const userid = localStorage.getItem("userid");
const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid
if (!userid) return;
try {
const res = await fetch(`${API_BASE_URL}/api/user-profile?userid=${userid}`);
if (res.ok) {
const data = await res.json();
setUserInfo(data);
setTempUserInfo(data);
// console.log(data);
}
} catch (err) {
// 可以根据需要处理错误
console.error("获取用户信息失败", err);
}
};
fetchUserInfo();
}, []);
// 动态加载用户上传种子列表
useEffect(() => {
const fetchUserSeeds = async () => {
// const userid = localStorage.getItem("userid");
const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid
if (!userid) return;
try {
const res = await fetch(`${API_BASE_URL}/api/user-seeds?userid=${userid}`);
if (res.ok) {
const data = await res.json();
setUserSeeds(data);
}
} catch (err) {
console.error("获取种子列表失败", err);
}
};
fetchUserSeeds();
}, []);
// 动态加载用户活跃度信息
useEffect(() => {
const fetchUserStats = async () => {
// const userid = localStorage.getItem("userid");
const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid
if (!userid) return;
try {
const res = await fetch(`${API_BASE_URL}/api/user-stats?userid=${userid}`);
if (res.ok) {
const data = await res.json();
setUserStats(data);
}
} catch (err) {
console.error("获取活跃度信息失败", err);
}
};
fetchUserStats();
}, []);
const handleInputChange = (field, value) => {
setTempUserInfo({ ...tempUserInfo, [field]: value });
};
const handleSave = async () => {
if (tempUserInfo.gender === "男性") {
tempUserInfo.gender = "m";
} else if (tempUserInfo.gender === "女性") {
tempUserInfo.gender = "f";
}
setUserInfo({ ...tempUserInfo });
console.log("保存的用户信息:", tempUserInfo);
// 获取userid
// const userid = localStorage.getItem("userid");
const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid
try {
const res = await fetch(`${API_BASE_URL}/api/change-profile`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userid, ...tempUserInfo }),
});
if (res.ok) {
alert("信息已保存!");
} else {
alert("保存失败,请重试。");
}
} catch (err) {
alert("保存失败,请检查网络连接。");
console.error("保存用户信息失败", err);
}
};
const handleAvatarClick = () => {
const pictureUrl = prompt("请输入头像的URL:");
if (pictureUrl) {
setTempUserInfo({ ...tempUserInfo, avatar_url: pictureUrl });
}
};
return (
<div className="container" style={{ minHeight: '100vh', background: 'linear-gradient(135deg, #f0f4ff 0%, #e0e7ff 100%)', display: 'grid', gridTemplateColumns: '1fr 2fr', gridTemplateRows: 'auto 1fr', gap: '20px', padding: '40px' }}>
{/* 左侧:用户资料 */}
<div style={{ gridColumn: '1 / 2', gridRow: '1 / 3', display: 'flex', flexDirection: 'column', alignItems: 'center', background: '#fff', borderRadius: 18, boxShadow: '0 4px 24px #e0e7ff', padding: '20px' }}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 16 }}>
<div onClick={handleAvatarClick} style={{ cursor: 'pointer', position: 'relative' }}>
<AccountCircleIcon style={{ fontSize: 90, color: '#1a237e', marginBottom: 12 }} />
{tempUserInfo.avatar_url && (
<img
src={tempUserInfo.avatar_url}
alt="用户头像"
style={{
position: 'absolute',
top: 0,
left: 0,
width: 90,
height: 90,
borderRadius: '50%',
objectFit: 'cover',
}}
/>
)}
</div>
<h2 style={{ color: '#1a237e', marginBottom: 0, fontSize: 24 }}>用户个人资料</h2>
</div>
<div className="card" style={{ padding: 28, width: '100%', background: '#fff', borderRadius: 18, boxShadow: '0 4px 24px #e0e7ff', flex: 1 }}>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>用户名:</b>
<input
type="text"
value={tempUserInfo.username}
onChange={(e) => handleInputChange("username", e.target.value)}
style={{ flex: 1, padding: '6px 10px', borderRadius: 7, border: '1px solid #b2b2b2', minWidth: 0, fontSize: 15 }}
/>
</div>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>邮箱:</b>
<span
style={{ flex: 1, padding: '6px 10px', borderRadius: 7, border: '1px solid #b2b2b2', minWidth: 0, fontSize: 15, backgroundColor: '#f5f5f5', color: '#888' }}
>
{tempUserInfo.email}
</span>
</div>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>邀请剩余:</b>
<span
style={{ flex: 1, padding: '6px 10px', borderRadius: 7, border: '1px solid #b2b2b2', minWidth: 0, fontSize: 15, backgroundColor: '#f5f5f5', color: '#888' }}
>
{tempUserInfo.invite_left || "0"}
</span>
</div>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>学校:</b>
<input
type="text"
value={tempUserInfo.school}
onChange={(e) => handleInputChange("school", e.target.value)}
style={{ flex: 1, padding: '6px 10px', borderRadius: 7, border: '1px solid #b2b2b2', minWidth: 0, fontSize: 15 }}
/>
</div>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>账号状态:</b>
<span
style={{ flex: 1, display: 'flex', alignItems: 'center', padding: '6px 10px', borderRadius: 7, border: '1px solid #b2b2b2', minWidth: 0, fontSize: 15, backgroundColor: '#f5f5f5', color: '#888' }}
>
{tempUserInfo.account_status === 1 || tempUserInfo.account_status === "1" ? "封禁" : "正常"}
<span style={{
display: 'inline-block',
width: 12,
height: 12,
borderRadius: '50%',
backgroundColor: tempUserInfo.account_status === 1 || tempUserInfo.account_status === "1" ? '#e53935' : '#43a047',
marginLeft: 10,
border: '1px solid #b2b2b2',
}} />
</span>
</div>
<div style={{ marginBottom: 18, display: 'flex', alignItems: 'center' }}>
<b style={{ width: 72, textAlign: 'left', marginRight: 0, fontSize: 16 }}>性别:</b>
<div style={{ position: 'relative', flex: 1 }}>
<button
onClick={() => setTempUserInfo({ ...tempUserInfo, showGenderOptions: !tempUserInfo.showGenderOptions })}
style={{
width: '100%',
padding: '6px 10px',
borderRadius: 7,
border: '1px solid #b2b2b2',
textAlign: 'left',
backgroundColor: '#fff',
fontSize: 15,
cursor: 'pointer',
}}
>
{tempUserInfo.gender === 'm' ? '男性'
: tempUserInfo.gender === 'f' ? '女性'
: '性别'}
</button>
{tempUserInfo.showGenderOptions && (
<ul
style={{
position: 'absolute',
top: '100%',
left: 0,
right: 0,
backgroundColor: '#fff',
border: '1px solid #b2b2b2',
borderRadius: 7,
listStyle: 'none',
margin: 0,
padding: 0,
zIndex: 10,
}}
>
{[{ value: 'm', label: '男性' }, { value: 'f', label: '女性' }].map(opt => (
<li
key={opt.value}
onClick={() => setTempUserInfo({ ...tempUserInfo, gender: opt.value, showGenderOptions: false })}
style={{
padding: '6px 10px',
cursor: 'pointer',
borderBottom: '1px solid #e0e0e0',
backgroundColor: tempUserInfo.gender === opt.value ? '#f0f0f0' : '#fff',
}}
>
{opt.label}
</li>
))}
</ul>
)}
</div>
</div>
<button
onClick={handleSave}
style={{
marginTop: 20,
padding: '10px 20px',
backgroundColor: '#1a237e',
color: '#fff',
border: 'none',
borderRadius: 7,
cursor: 'pointer',
fontSize: 16,
alignSelf: 'center', // Center the button horizontally
}}
onMouseOver={(e) => (e.target.style.backgroundColor = '#0d1b5e')}
onMouseOut={(e) => (e.target.style.backgroundColor = '#1a237e')}
>
保存
</button>
</div>
</div>
{/* 上传种子列表 */}
<div style={{ gridColumn: '2 / 3', gridRow: '1 / 2', background: '#fff', borderRadius: 18, boxShadow: '0 4px 24px #e0e7ff', padding: '20px' }}>
<h3 style={{ color: '#1a237e', fontSize: 22, marginBottom: 18 }}>个人上传种子列表</h3>
<div style={{ border: '1px dashed #b2b2b2', borderRadius: 12, minHeight: 60, padding: 12 }}>
{userSeeds.length === 0 ? (
<div style={{ color: '#b2b2b2', fontSize: 18, textAlign: 'center' }}>(暂无上传种子)</div>
) : (
<ul style={{ listStyle: 'none', margin: 0, padding: 0 }}>
{userSeeds.map((seed, idx) => (
<li
key={seed.seed_id || idx}
style={{ display: 'flex', alignItems: 'center', padding: '10px 0', borderBottom: '1px solid #e0e7ff', cursor: 'pointer' }}
onClick={e => {
// 阻止点击删除按钮时跳转
if (e.target.classList.contains('delete-btn')) return;
navigate(`/torrent/${seed.seedid}`);
}}
>
<span style={{ flex: 2, fontWeight: 500, color: '#1a237e', textDecoration: 'underline' }}>{seed.title}</span>
<span style={{ flex: 1, color: '#5c6bc0' }}>{seed.tags}</span>
<span style={{ flex: 1, color: '#ff9800', textAlign: 'right' }}>人气: {seed.downloadtimes}</span>
<button
className="delete-btn"
style={{ marginLeft: 18, background: '#e53935', color: '#fff', border: 'none', borderRadius: 6, padding: '4px 14px', cursor: 'pointer', fontSize: 14 }}
onClick={async (e) => {
e.stopPropagation();
// const userid = localStorage.getItem("userid");
// const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid
try {
const res = await fetch(`${API_BASE_URL}/api/delete-seed`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ seedid: seed.seedid }),
});
// console.log(seed.seedid);
if (res.ok) {
setUserSeeds(userSeeds.filter((s, i) => (s.seedid || i) !== (seed.seedid || idx)));
} else {
alert('删除失败,请重试');
}
} catch (err) {
alert('删除失败,请检查网络');
}
}}
>删除</button>
</li>
))}
</ul>
)}
</div>
</div>
{/* 活跃度模块 */}
<div style={{ gridColumn: '2 / 3', gridRow: '2 / 3', background: '#fff', borderRadius: 18, boxShadow: '0 4px 24px #e0e7ff', padding: '20px' }}>
<h3 style={{ color: '#1a237e', fontSize: 22, marginBottom: 18 }}>活跃度</h3>
<div style={{ border: '1px dashed #b2b2b2', borderRadius: 12, minHeight: 60, padding: 18, display: 'flex', flexDirection: 'column', gap: 12, fontSize: 18 }}>
<div>魔力值:<b style={{ color: '#1976d2' }}>{userStats.magic}</b></div>
<div>上传量:<b style={{ color: '#43a047' }}>{userStats.upload} GB</b></div>
<div>下载量:<b style={{ color: '#e53935' }}>{userStats.download} GB</b></div>
<div>上传/下载值:<b style={{ color: '#ff9800' }}>{userStats.ratio}</b></div>
</div>
</div>
</div>
);
}