稳定运行版本v1

Change-Id: Id2cb7e1c6d3fbe156911e42fa342cab74f817193
diff --git a/Merge/front/src/components/UserProfile.jsx b/Merge/front/src/components/UserProfile.jsx
index 6cddcbd..c957473 100644
--- a/Merge/front/src/components/UserProfile.jsx
+++ b/Merge/front/src/components/UserProfile.jsx
@@ -30,14 +30,15 @@
   CircularProgress,
   Snackbar,
   Alert,
-  Menu
+  Menu,
+  Pagination,
+  Stack
 } from '@mui/material';
 import { useParams } from 'react-router-dom';
 import { 
   CameraAlt, 
   Edit, 
   Favorite, 
-  Bookmark, 
   Share, 
   MoreVert, 
   LocationOn, 
@@ -50,11 +51,9 @@
   Notifications,
   Person,
   Collections,
-  Group,
   ChevronLeft,
   ChevronRight,
-  Close,
-  People
+  Close
 } from '@mui/icons-material';
 import { createTheme, ThemeProvider } from '@mui/material/styles';
 import { Link, useNavigate } from 'react-router-dom';
@@ -64,14 +63,12 @@
   getCurrentUser, 
   getUser, 
   updateUser as updateUserApi,
-  getFavorites,
   followUser as followUserApi,
   unfollowUser as unfollowUserApi,
   getUserPosts,
-  getUserFollowing,
-  getUserInteractions,
-  getUserFollowers
+  getUserInteractions
 } from '../api/api_ljc';
+import { fetchPost } from '../api/posts_wzy';
 
 // 创建小红书主题
 const theme = createTheme({
@@ -122,21 +119,24 @@
   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 [allPosts, setAllPosts] = useState([]); // 存储所有帖子数据
   const [interactions, setInteractions] = useState({ 
     likes_count: 0, 
     favorites_count: 0 
   });
   
+  // 分页状态
+  const [currentPage, setCurrentPage] = useState(1);
+  const [postsPerPage] = useState(8); // 每页显示8个帖子
+  const [totalPages, setTotalPages] = useState(0);
+  
   // 加载状态
   const [loading, setLoading] = useState(true);
   const [updating, setUpdating] = useState(false);
@@ -158,6 +158,30 @@
     setSnackbar({ open: true, message, severity });
   };
 
+  // 分页处理函数
+  const updatePaginatedPosts = (page, allPostsData) => {
+    const startIndex = (page - 1) * postsPerPage;
+    const endIndex = startIndex + postsPerPage;
+    const paginatedPosts = allPostsData.slice(startIndex, endIndex);
+    setPosts(paginatedPosts);
+    setTotalPages(Math.ceil(allPostsData.length / postsPerPage));
+  };
+
+  const handlePageChange = (newPage) => {
+    if (newPage >= 1 && newPage <= totalPages) {
+      setCurrentPage(newPage);
+      updatePaginatedPosts(newPage, allPosts);
+    }
+  };
+
+  const handlePrevPage = () => {
+    handlePageChange(currentPage - 1);
+  };
+
+  const handleNextPage = () => {
+    handlePageChange(currentPage + 1);
+  };
+
   // 加载用户数据
   useEffect(() => {
     const fetchInteractions = async () => {
@@ -181,9 +205,9 @@
       showSnackbar('关注成功');
       
       // 更新粉丝列表状态(将刚关注的用户标记为已关注)
-      setFollowers(prev => prev.map(user => 
-        user.id === followeeId ? { ...user, is_following: true } : user
-      ));
+      // setFollowers(prev => prev.map(user => 
+      //   user.id === followeeId ? { ...user, is_following: true } : user
+      // ));
       
       // 更新当前用户关注数
       if (currentUser) {
@@ -220,7 +244,31 @@
         
         // 获取用户帖子
         const postsRes = await getUserPosts(userId);
-        setPosts(postsRes.data);
+        
+        // 为了拿到 media_urls,这里需要拉取每个帖子的详情
+        const postsWithDetails = await Promise.all(
+          postsRes.data.map(async post => {
+            try {
+              const detail = await fetchPost(post.id);
+              return {
+                ...post,
+                media_urls: detail.media_urls || [],
+                user_id: detail.user_id
+              };
+            } catch (error) {
+              console.error(`获取帖子 ${post.id} 详情失败:`, error);
+              return {
+                ...post,
+                media_urls: [],
+                user_id: null
+              };
+            }
+          })
+        );
+        
+        setAllPosts(postsWithDetails); // 存储所有帖子
+        updatePaginatedPosts(1, postsWithDetails); // 初始化第一页数据
+        setCurrentPage(1); // 重置到第一页
         
         // 获取用户互动数据(获赞和收藏数量)
         const interactionsRes = await getUserInteractions(userId);
@@ -239,41 +287,11 @@
 
   // 根据标签页加载数据
   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加载不同数据
   }, [activeTab, userId, profileUser]);
 
   const handleTabChange = (event, newValue) => {
+    // 由于只有一个标签页,不需要切换逻辑
     setActiveTab(newValue);
   };
 
@@ -290,15 +308,6 @@
       // 更新用户信息
       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');
@@ -310,11 +319,6 @@
       await followUserApi(followeeId);
       showSnackbar('关注成功');
       
-      // 更新粉丝列表状态
-      setFollowers(prev => prev.map(user => 
-        user.id === followeeId ? {...user, is_following: true} : user
-      ));
-      
       // 更新当前用户关注数
       if (currentUser) {
         setCurrentUser(prev => ({
@@ -336,9 +340,6 @@
       await unfollowUserApi(followeeId);
       showSnackbar('已取消关注');
       
-      // 更新关注列表
-      setFollowing(prev => prev.filter(user => user.id !== followeeId));
-      
       // 更新当前用户关注数
       if (currentUser) {
         setCurrentUser(prev => ({
@@ -571,7 +572,7 @@
                 <Grid container spacing={2} sx={{ mt: 2 }}>
                   <Grid item>
                     <Box textAlign="center">
-                      <Typography variant="h6">{posts.length}</Typography>
+                      <Typography variant="h6">{allPosts.length}</Typography>
                       <Typography variant="body2" color="textSecondary">笔记</Typography>
                     </Box>
                   </Grid>
@@ -615,346 +616,117 @@
               }}
             >
               <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'
-                      }}>
+            {/* 只保留笔记标签页 */}
+            <Grid container spacing={3}>
+              {tabLoading ? (
+                <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
+                  <CircularProgress />
+                </Grid>
+              ) : allPosts.length === 0 ? (
+                <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.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'
+                    }}>
+                      {/* 只有当帖子有 media_urls 时才显示图片 */}
+                      {post.media_urls && post.media_urls.length > 0 && (
                         <CardMedia
                           component="img"
                           height="180"
-                          image={`https://source.unsplash.com/random/400x300?${index + 1}`}
+                          image={post.media_urls[0]}
                           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>
+                      <CardContent sx={{ flexGrow: 1 }}>
+                        <Typography gutterBottom variant="h6" component="div">
+                          {post.title}
+                        </Typography>
+                        <Typography variant="body2" color="text.secondary">
+                          {post.content ? 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>
-                )}
-                
-                {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
+                ))
+              )}
+              
+              {/* 分页组件 */}
+              {allPosts.length > postsPerPage && (
+                <Grid item xs={12}>
+                  <Stack spacing={2} alignItems="center" sx={{ mt: 4 }}>
+                    <Typography variant="body2" color="textSecondary">
+                      共 {allPosts.length} 篇笔记,第 {currentPage} 页,共 {totalPages} 页
+                    </Typography>
+                    <Pagination 
+                      count={totalPages}
+                      page={currentPage}
+                      onChange={(event, page) => handlePageChange(page)}
+                      color="primary"
+                      size={isMobile ? "small" : "medium"}
+                      showFirstButton 
+                      showLastButton
+                      sx={{
+                        '& .MuiPaginationItem-root': {
+                          borderRadius: 2,
                         }
-                      }}>
-                        <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>
-            )}
+                      }}
+                    />
+                  </Stack>
+                </Grid>
+              )}
+            </Grid>
           </Box>
         </Container>