blob: 6cddcbd9254ed1a7152a4c574ed54f0fd8a85b37 [file] [log] [blame]
import React, { useState, useEffect, Profiler } from 'react';
import {
Box,
Grid,
Typography,
Avatar,
Button,
Tabs,
Tab,
Card,
CardMedia,
CardContent,
CardActions,
IconButton,
Divider,
List,
ListItem,
ListItemAvatar,
ListItemText,
TextField,
InputAdornment,
Chip,
Badge,
Fab,
Paper,
MenuItem,
Container,
useMediaQuery,
useTheme,
CircularProgress,
Snackbar,
Alert,
Menu
} from '@mui/material';
import { useParams } from 'react-router-dom';
import {
CameraAlt,
Edit,
Favorite,
Bookmark,
Share,
MoreVert,
LocationOn,
Cake,
Female,
Male,
Public,
Add,
Search,
Notifications,
Person,
Collections,
Group,
ChevronLeft,
ChevronRight,
Close,
People
} from '@mui/icons-material';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { Link, useNavigate } from 'react-router-dom';
// 导入API服务
import {
getCurrentUser,
getUser,
updateUser as updateUserApi,
getFavorites,
followUser as followUserApi,
unfollowUser as unfollowUserApi,
getUserPosts,
getUserFollowing,
getUserInteractions,
getUserFollowers
} from '../api/api_ljc';
// 创建小红书主题
const theme = createTheme({
palette: {
primary: {
main: '#ff4081',
},
secondary: {
main: '#f50057',
},
background: {
default: '#f5f5f5',
},
},
typography: {
fontFamily: '"PingFang SC", "Helvetica Neue", Arial, sans-serif',
h5: {
fontWeight: 600,
},
subtitle1: {
color: 'rgba(0, 0, 0, 0.6)',
},
},
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 20,
textTransform: 'none',
fontWeight: 500,
},
},
},
MuiCard: {
styleOverrides: {
root: {
borderRadius: 16,
},
},
},
},
});
const UserProfile = () => {
const { userId } = useParams();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState(0);
const [isEditing, setIsEditing] = useState(false);
const [followers, setFollowers] = useState([]);
const [snackbar, setSnackbar] = useState({ open: false, message: '', severity: 'success' });
const [anchorEl, setAnchorEl] = useState(null);
// 用户数据状态
const [currentUser, setCurrentUser] = useState(null);
const [profileUser, setProfileUser] = useState(null);
const [favorites, setFavorites] = useState([]);
const [following, setFollowing] = useState([]);
const [posts, setPosts] = useState([]);
const [interactions, setInteractions] = useState({
likes_count: 0,
favorites_count: 0
});
// 加载状态
const [loading, setLoading] = useState(true);
const [updating, setUpdating] = useState(false);
const [tabLoading, setTabLoading] = useState(false);
// 表单状态
const [formData, setFormData] = useState({
avatar: '',
bio: '',
gender: '',
birthday: '',
location: ''
});
const menuOpen = Boolean(anchorEl);
// 显示提示信息
const showSnackbar = (message, severity = 'success') => {
setSnackbar({ open: true, message, severity });
};
// 加载用户数据
useEffect(() => {
const fetchInteractions = async () => {
try {
const response = await getUserInteractions(userId);
if (response.data.success) {
setInteractions(response.data.data);
} else {
console.error(response.data.error);
}
} catch (error) {
console.error('获取互动数据失败:', error);
}
};
fetchInteractions();
const handleFollowUser = async (followeeId) => {
try {
await followUserApi(followeeId);
showSnackbar('关注成功');
// 更新粉丝列表状态(将刚关注的用户标记为已关注)
setFollowers(prev => prev.map(user =>
user.id === followeeId ? { ...user, is_following: true } : user
));
// 更新当前用户关注数
if (currentUser) {
setCurrentUser(prev => ({
...prev,
following_count: prev.following_count + 1
}));
}
} catch (error) {
console.error('关注操作失败:', error);
showSnackbar('关注失败,请重试', 'error');
}
};
const fetchData = async () => {
try {
setLoading(true);
// 获取当前登录用户
const currentUserRes = await getCurrentUser();
setCurrentUser(currentUserRes.data);
// 获取目标用户信息
console.log('userId', userId)
const profileUserRes = await getUser(userId);
setProfileUser(profileUserRes.data);
setFormData({
avatar: profileUserRes.data.avatar || '',
bio: profileUserRes.data.bio || '',
gender: profileUserRes.data.gender || '',
birthday: profileUserRes.data.birthday || '',
location: profileUserRes.data.location || ''
});
// 获取用户帖子
const postsRes = await getUserPosts(userId);
setPosts(postsRes.data);
// 获取用户互动数据(获赞和收藏数量)
const interactionsRes = await getUserInteractions(userId);
setInteractions(interactionsRes.data);
} catch (error) {
console.error('获取用户数据失败:', error);
showSnackbar('获取用户数据失败,请重试', 'error');
} finally {
setLoading(false);
}
};
fetchData();
}, [userId]);
// 根据标签页加载数据
useEffect(() => {
const fetchTabData = async () => {
if (!profileUser) return;
try {
setTabLoading(true);
if (activeTab === 1) {
// 加载收藏数据
const favoritesRes = await getFavorites(userId);
setFavorites(favoritesRes.data);
} else if (activeTab === 2) {
// 加载关注列表
const followingRes = await getUserFollowing(userId);
setFollowing(followingRes.data);
console.log(followingRes.data)
} else if (activeTab === 3) {
// 加载粉丝列表
const followersRes = await getUserFollowers(userId);
//
setFollowers(followersRes.data.data);
console.log(followersRes.data.data)
}
} catch (error) {
console.error('加载数据失败:', error);
showSnackbar('加载数据失败,请重试', 'error');
} finally {
setTabLoading(false);
}
};
fetchTabData();
}, [activeTab, userId, profileUser]);
const handleTabChange = (event, newValue) => {
setActiveTab(newValue);
};
const handleFollowToggle = async () => {
if (!currentUser || !profileUser) return;
try {
if (profileUser.is_following) {
await unfollowUserApi(profileUser.id);
showSnackbar('已取消关注');
} else {
await followUserApi(profileUser.id);
showSnackbar('关注成功');
}
// 更新用户信息
const updatedUser = await getUser(userId);
setProfileUser(updatedUser.data);
// 关注/取关后强制刷新关注和粉丝列表,保证页面和数据库同步
if (activeTab === 2) {
const followingRes = await getUserFollowing(userId);
setFollowing(followingRes.data);
}
if (activeTab === 3) {
const followersRes = await getUserFollowers(userId);
setFollowers(followersRes.data.data);
}
} catch (error) {
console.error('关注操作失败:', error);
showSnackbar('操作失败,请重试', 'error');
}
};
const handleFollowUser = async (followeeId) => {
try {
await followUserApi(followeeId);
showSnackbar('关注成功');
// 更新粉丝列表状态
setFollowers(prev => prev.map(user =>
user.id === followeeId ? {...user, is_following: true} : user
));
// 更新当前用户关注数
if (currentUser) {
setCurrentUser(prev => ({
...prev,
following_count: prev.following_count + 1
}));
}
} catch (error) {
console.error('关注操作失败:', error);
showSnackbar('关注失败,请重试', 'error');
}
};
const handleUnfollow = async (followeeId, e) => {
e.stopPropagation(); // 阻止事件冒泡
try {
await unfollowUserApi(followeeId);
showSnackbar('已取消关注');
// 更新关注列表
setFollowing(prev => prev.filter(user => user.id !== followeeId));
// 更新当前用户关注数
if (currentUser) {
setCurrentUser(prev => ({
...prev,
following_count: prev.following_count - 1
}));
}
// 更新目标用户粉丝数
setProfileUser(prev => ({
...prev,
followers_count: prev.followers_count - 1
}));
} catch (error) {
console.error('取消关注失败:', error);
showSnackbar('操作失败,请重试', 'error');
}
};
const handleFormChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleUpdateProfile = async () => {
if (!profileUser) return;
try {
setUpdating(true);
const data = {
avatar: formData.avatar,
bio: formData.bio,
gender: formData.gender,
birthday: formData.birthday,
location: formData.location
};
// 调用更新API
const updatedUser = await updateUserApi(profileUser.id, data);
// 更新本地状态
setProfileUser({ ...profileUser, ...updatedUser.data });
setFormData({ ...formData, ...data });
showSnackbar('个人资料更新成功');
setIsEditing(false);
} catch (error) {
console.error('更新个人资料失败:', error);
showSnackbar('更新失败,请重试', 'error');
} finally {
setUpdating(false);
}
};
const navigateToUserProfile = (userId) => {
navigate(`/user/${userId}`);
};
const handleMenuOpen = (e) => setAnchorEl(e.currentTarget);
const handleMenuClose = () => setAnchorEl(null);
const handleLogout = () => {
handleMenuClose();
// 清理本地存储
localStorage.clear();
// 在此处添加退出登录逻辑,比如清理本地存储并跳转
navigate('/login');
};
if (loading) {
return (
<Box sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh'
}}>
<CircularProgress size={60} />
</Box>
);
}
if (!profileUser) {
return (
<Box sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
flexDirection: 'column'
}}>
<Typography variant="h6" sx={{ mb: 2 }}>用户不存在</Typography>
<Button variant="outlined" onClick={() => window.location.reload()}>
重新加载
</Button>
</Box>
);
}
const isOwnProfile = currentUser && currentUser.id === parseInt(userId);
return (
<ThemeProvider theme={theme}>
<Box sx={{
bgcolor: 'background.default',
minHeight: '100vh',
pb: isMobile ? 8 : 4
}}>
{/* 顶部横幅 */}
<Box sx={{
height: isMobile ? 200 : 250,
background: 'linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%)',
position: 'relative',
borderBottomLeftRadius: 24,
borderBottomRightRadius: 24,
boxShadow: 1
}}>
<Fab
color="primary"
size="small"
sx={{
position: 'absolute',
bottom: -20,
right: 16
}}
>
<CameraAlt />
</Fab>
</Box>
<Container maxWidth="lg">
{/* 用户信息区域 */}
<Box sx={{ px: isMobile ? 3 : 0, mt: -8, position: 'relative' }}>
<Grid container spacing={3}>
<Grid item xs={12} sm="auto">
<Badge
overlap="circular"
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
badgeContent={
<IconButton
size="small"
sx={{
bgcolor: 'grey.200',
'&:hover': { bgcolor: 'grey.300' }
}}
onClick={() => setIsEditing(true)}
disabled={!isOwnProfile}
>
<Edit fontSize="small" />
</IconButton>
}
>
<Avatar
sx={{
width: 120,
height: 120,
border: '4px solid white',
boxShadow: 3
}}
src={profileUser.avatar || 'https://www.8848seo.cn/zb_users/upload/2023/02/20230210092856_68763.jpeg'}
/>
</Badge>
</Grid>
<Grid item xs={12} sm>
<Box sx={{ display: 'flex', justifyContent: 'space-between', flexDirection: isMobile ? 'column' : 'row' }}>
<Box>
<Typography variant="h5" fontWeight="bold">
{profileUser.username}
</Typography>
<Typography variant="subtitle1" sx={{ mt: 0.5, maxWidth: 600 }}>
{profileUser.bio || '这个人很懒,还没有写简介~'}
</Typography>
<Box sx={{ display: 'flex', mt: 1, gap: 1, flexWrap: 'wrap' }}>
<Chip
icon={<LocationOn fontSize="small" />}
label={formData.location}
size="small"
variant="outlined"
/>
<Chip
icon={<Cake fontSize="small" />}
label={formData.birthday}
size="small"
variant="outlined"
/>
<Chip
icon={<Female fontSize="small" />}
label={formData.gender}
size="small"
variant="outlined"
/>
</Box>
</Box>
<Box sx={{ mt: isMobile ? 2 : 0, alignSelf: 'flex-start' }}>
{!isOwnProfile && currentUser && (
<>
<Button
variant={profileUser.is_following ? "outlined" : "contained"}
color="primary"
onClick={handleFollowToggle}
sx={{
borderRadius: 20,
px: 3,
fontWeight: 'bold'
}}
>
{profileUser.is_following ? '已关注' : '关注'}
</Button>
<IconButton sx={{ ml: 1 }} onClick={handleMenuOpen}>
<MoreVert />
</IconButton>
<Menu
anchorEl={anchorEl}
open={menuOpen}
onClose={handleMenuClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<MenuItem onClick={handleLogout}>退出登录</MenuItem>
</Menu>
</>
)}
</Box>
</Box>
<Grid container spacing={2} sx={{ mt: 2 }}>
<Grid item>
<Box textAlign="center">
<Typography variant="h6">{posts.length}</Typography>
<Typography variant="body2" color="textSecondary">笔记</Typography>
</Box>
</Grid>
<Grid item>
<Box textAlign="center">
<Typography variant="h6">{profileUser.followers_count || 0}</Typography>
<Typography variant="body2" color="textSecondary">粉丝</Typography>
</Box>
</Grid>
<Grid item>
<Box textAlign="center">
<Typography variant="h6">{profileUser.following_count || 0}</Typography>
<Typography variant="body2" color="textSecondary">关注</Typography>
</Box>
</Grid>
<Grid item>
<Box textAlign="center">
{/* 使用真实数据:获赞与收藏总数 */}
<Typography variant="h6">
{(interactions.likes_count + interactions.favorites_count).toLocaleString()}
</Typography>
<Typography variant="body2" color="textSecondary">获赞与收藏</Typography>
</Box>
</Grid>
</Grid>
</Grid>
</Grid>
</Box>
{/* 标签栏 */}
<Box sx={{ mt: 4 }}>
<Tabs
value={activeTab}
onChange={handleTabChange}
variant={isMobile ? "fullWidth" : "standard"}
indicatorColor="primary"
textColor="primary"
sx={{
borderBottom: 1,
borderColor: 'divider'
}}
>
<Tab icon={isMobile ? <Collections /> : null} label="笔记" />
<Tab icon={isMobile ? <Bookmark /> : null} label="收藏" />
<Tab icon={isMobile ? <Group /> : null} label="关注" />
<Tab icon={isMobile ? <People /> : null} label="粉丝" />
</Tabs>
</Box>
{/* 内容区域 */}
<Box sx={{ mt: 3 }}>
{activeTab === 0 && (
<Grid container spacing={3}>
{tabLoading ? (
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Grid>
) : posts.length > 0 ? (
posts.map((post, index) => (
<Grid item xs={12} sm={6} lg={3} key={post.id}>
<Card elevation={0} sx={{
bgcolor: 'white',
borderRadius: 3,
height: '100%',
display: 'flex',
flexDirection: 'column'
}}>
<CardMedia
component="img"
height="180"
image={`https://source.unsplash.com/random/400x300?${index + 1}`}
alt={post.title}
/>
<CardContent sx={{ flexGrow: 1 }}>
<Typography gutterBottom variant="h6" component="div">
{post.title}
</Typography>
<Typography variant="body2" color="text.secondary">
{post.content.substring(0, 60)}...
</Typography>
</CardContent>
<CardActions sx={{ justifyContent: 'space-between', px: 2, pb: 2 }}>
<Box>
<IconButton aria-label="add to favorites">
<Favorite />
<Typography variant="body2" sx={{ ml: 1 }}>
{post.heat || Math.floor(Math.random() * 1000) + 1000}
</Typography>
</IconButton>
<IconButton aria-label="share">
<Share />
</IconButton>
</Box>
<Chip
label={post.type === 'image' ? '图文' : post.type === 'video' ? '视频' : '文档'}
size="small"
color="primary"
variant="outlined"
/>
</CardActions>
</Card>
</Grid>
))
) : (
<Grid item xs={12}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
py: 8,
textAlign: 'center'
}}>
<Collections sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
<Typography variant="h6" sx={{ mb: 1 }}>
还没有发布笔记
</Typography>
<Typography variant="body1" color="textSecondary" sx={{ mb: 3 }}>
{isOwnProfile ? '分享你的生活点滴吧~' : '该用户还没有发布任何笔记'}
</Typography>
{isOwnProfile && (
<Button variant="contained" color="primary">
发布第一篇笔记
</Button>
)}
</Box>
</Grid>
)}
{posts.length > 0 && (
<Grid item xs={12}>
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
<Button
variant="outlined"
sx={{
borderRadius: 20,
px: 4,
display: 'flex',
alignItems: 'center'
}}
>
<ChevronLeft sx={{ mr: 1 }} />
上一页
<ChevronRight sx={{ ml: 2 }} />
</Button>
</Box>
</Grid>
)}
</Grid>
)}
{activeTab === 1 && (
<Grid container spacing={3}>
{tabLoading ? (
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Grid>
) : favorites.length > 0 ? (
favorites.map((favorite) => (
<Grid item xs={12} sm={6} md={4} lg={3} key={favorite.id}>
<Card elevation={0} sx={{
bgcolor: 'white',
borderRadius: 3,
transition: 'transform 0.3s, box-shadow 0.3s',
'&:hover': {
transform: 'translateY(-5px)',
boxShadow: 3
}
}}>
<Box sx={{
height: 160,
position: 'relative',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
overflow: 'hidden'
}}>
<CardMedia
component="img"
height="160"
image={`https://source.unsplash.com/random/400x300?${favorite.id}`}
alt={favorite.title}
/>
<Box sx={{
position: 'absolute',
top: 8,
right: 8,
bgcolor: 'rgba(0,0,0,0.6)',
color: 'white',
px: 1,
py: 0.5,
borderRadius: 4,
fontSize: 12
}}>
{favorite.type === 'image' ? '图文' : favorite.type === 'video' ? '视频' : '文档'}
</Box>
</Box>
<CardContent>
<Typography gutterBottom variant="subtitle1" fontWeight="medium">
{favorite.title}
</Typography>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Favorite fontSize="small" color="error" />
<Typography variant="body2" sx={{ ml: 0.5 }}>
{favorite.heat || Math.floor(Math.random() * 1000) + 1000}
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Bookmark fontSize="small" color="primary" />
<Typography variant="body2" sx={{ ml: 0.5 }}>
{Math.floor(Math.random() * 500) + 100}
</Typography>
</Box>
</Box>
</CardContent>
</Card>
</Grid>
))
) : (
<Grid item xs={12}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
py: 8,
textAlign: 'center'
}}>
<Bookmark sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
<Typography variant="h6" sx={{ mb: 1 }}>
{isOwnProfile ? '你还没有收藏内容' : '该用户没有收藏内容'}
</Typography>
<Typography variant="body1" color="textSecondary">
{isOwnProfile ? '看到喜欢的笔记可以收藏起来哦~' : ''}
</Typography>
</Box>
</Grid>
)}
</Grid>
)}
{activeTab === 2 && (
<Grid container spacing={3}>
{tabLoading ? (
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Grid>
) : following.length > 0 ? (
following.map((follow) => (
<Grid item xs={12} sm={6} md={4} key={follow.id}>
<Paper
elevation={0}
sx={{
bgcolor: 'white',
borderRadius: 3,
p: 2,
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
'&:hover': {
boxShadow: 1
}
}}
onClick={() => navigateToUserProfile(follow.id)}
>
<Avatar
src={follow.avatar || 'https://randomuser.me/api/portraits/men/22.jpg'}
sx={{ width: 60, height: 60 }}
/>
<Box sx={{ ml: 2, flexGrow: 1 }}>
<Typography fontWeight="medium">{follow.username}</Typography>
<Typography variant="body2" color="textSecondary">
{follow.followers_count || Math.floor(Math.random() * 100) + 10} 粉丝
</Typography>
</Box>
{isOwnProfile && (
<Button
variant="outlined"
size="small"
sx={{ borderRadius: 20 }}
onClick={(e) => handleUnfollow(follow.id, e)}
>
已关注
</Button>
)}
</Paper>
</Grid>
))
) : (
<Grid item xs={12}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
py: 8,
textAlign: 'center'
}}>
<Group sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
<Typography variant="h6" sx={{ mb: 1 }}>
{isOwnProfile ? '你还没有关注任何人' : '该用户还没有关注任何人'}
</Typography>
<Typography variant="body1" color="textSecondary">
{isOwnProfile ? '发现有趣的人并关注他们吧~' : ''}
</Typography>
</Box>
</Grid>
)}
</Grid>
)}
{activeTab === 3 && (
<Grid container spacing={3}>
{tabLoading ? (
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Grid>
) : followers.length > 0 ? (
followers.map((follower) => (
<Grid item xs={12} sm={6} md={4} key={follower.id}>
<Paper
elevation={0}
sx={{
bgcolor: 'white',
borderRadius: 3,
p: 2,
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
'&:hover': {
boxShadow: 1
}
}}
onClick={() => navigateToUserProfile(follower.id)}
>
<Avatar
src={follower.avatar || 'https://randomuser.me/api/portraits/men/22.jpg'}
sx={{ width: 60, height: 60 }}
/>
<Box sx={{ ml: 2, flexGrow: 1 }}>
<Typography fontWeight="medium">{follower.username}</Typography>
<Typography variant="body2" color="textSecondary">
{follower.bio || '暂无简介'}
</Typography>
</Box>
{currentUser && currentUser.id !== follower.id && (
<Button
variant={follower.is_following ? "outlined" : "contained"}
color="primary"
size="small"
sx={{ borderRadius: 20 }}
onClick={(e) => {
e.stopPropagation();
if (follower.is_following) {
handleUnfollow(follower.id, e);
} else {
handleFollowUser(follower.id);
}
}}
>
{follower.is_following ? '已关注' : '关注'}
</Button>
)}
</Paper>
</Grid>
))
) : (
<Grid item xs={12}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
py: 8,
textAlign: 'center'
}}>
<People sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
<Typography variant="h6" sx={{ mb: 1 }}>
{isOwnProfile ? '你还没有粉丝' : '该用户还没有粉丝'}
</Typography>
<Typography variant="body1" color="textSecondary">
{isOwnProfile ? '分享更多内容来吸引粉丝吧~' : ''}
</Typography>
</Box>
</Grid>
)}
</Grid>
)}
</Box>
</Container>
{/* 底部导航栏 - 仅移动端显示 */}
{isMobile && (
<Box sx={{
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
bgcolor: 'white',
boxShadow: 3,
py: 1,
display: 'flex',
justifyContent: 'space-around'
}}>
<IconButton color="primary">
<Search fontSize="large" />
</IconButton>
<IconButton>
<Collections fontSize="large" />
</IconButton>
<Fab color="primary" size="medium" sx={{ mt: -2 }}>
<Add />
</Fab>
<IconButton>
<Notifications fontSize="large" />
</IconButton>
<IconButton>
<Person fontSize="large" />
</IconButton>
</Box>
)}
{/* 编辑资料模态框 */}
{isEditing && (
<Box sx={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
bgcolor: 'rgba(0,0,0,0.5)',
zIndex: 1300,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
px: 2
}}>
<Paper sx={{
width: '100%',
maxWidth: 600,
borderRadius: 4,
overflow: 'hidden'
}}>
<Box sx={{
bgcolor: 'primary.main',
color: 'white',
p: 2,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<Typography variant="h6">编辑资料</Typography>
<IconButton color="inherit" onClick={() => setIsEditing(false)}>
<Close />
</IconButton>
</Box>
<Box sx={{ p: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 3 }}>
<Badge
overlap="circular"
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
badgeContent={
<IconButton
size="small"
sx={{
bgcolor: 'grey.200',
'&:hover': { bgcolor: 'grey.300' }
}}
>
<CameraAlt fontSize="small" />
</IconButton>
}
>
<Avatar
sx={{ width: 100, height: 100 }}
src={formData.avatar || 'https://www.8848seo.cn/zb_users/upload/2023/02/20230210092856_68763.jpeg'}
/>
</Badge>
</Box>
<TextField
fullWidth
label="用户名"
value={profileUser.username}
margin="normal"
disabled
/>
<TextField
fullWidth
name="avatar"
label="头像URL"
value={formData.avatar}
onChange={handleFormChange}
margin="normal"
/>
<TextField
fullWidth
name="bio"
label="个人简介"
value={formData.bio}
onChange={handleFormChange}
margin="normal"
multiline
rows={3}
/>
<Grid container spacing={2} sx={{ mt: 1 }}>
<Grid item xs={6}>
<TextField
select
fullWidth
name="gender"
label="性别"
value={formData.gender}
onChange={handleFormChange}
margin="normal"
>
<MenuItem value="female">
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Female sx={{ mr: 1 }} />
</Box>
</MenuItem>
<MenuItem value="male">
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Male sx={{ mr: 1 }} />
</Box>
</MenuItem>
<MenuItem value="other">
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Public sx={{ mr: 1 }} /> 其他
</Box>
</MenuItem>
</TextField>
</Grid>
<Grid item xs={6}>
<TextField
fullWidth
name="birthday"
label="生日"
type="date"
value={formData.birthday}
onChange={handleFormChange}
margin="normal"
InputLabelProps={{ shrink: true }}
/>
</Grid>
</Grid>
<TextField
fullWidth
name="location"
label="地区"
value={formData.location}
onChange={handleFormChange}
margin="normal"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LocationOn />
</InputAdornment>
),
}}
/>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 3 }}>
<Button
variant="outlined"
sx={{ width: '48%' }}
onClick={() => setIsEditing(false)}
disabled={updating}
>
取消
</Button>
<Button
variant="contained"
color="primary"
sx={{ width: '48%' }}
onClick={handleUpdateProfile}
disabled={updating}
>
{updating ? <CircularProgress size={24} /> : '保存'}
</Button>
</Box>
</Box>
</Paper>
</Box>
)}
{/* 提示信息 */}
<Snackbar
open={snackbar.open}
autoHideDuration={3000}
onClose={() => setSnackbar({ ...snackbar, open: false })}
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
>
<Alert
severity={snackbar.severity}
sx={{ width: '100%' }}
onClose={() => setSnackbar({ ...snackbar, open: false })}
>
{snackbar.message}
</Alert>
</Snackbar>
</Box>
</ThemeProvider>
);
};
export default UserProfile;