修改信息

Change-Id: Ic5613c897dc716af06503b865fd9895a0614d6bc
diff --git a/Merge/front/src/api/posts_api.js b/Merge/front/src/api/posts_api.js
index 06cf2c7..d42ede2 100644
--- a/Merge/front/src/api/posts_api.js
+++ b/Merge/front/src/api/posts_api.js
@@ -130,7 +130,14 @@
   // 获取收藏列表
   getFavorites: async (userId) => {
     return await request(`${LJC_BASE_URL}/api/user/${userId}/favorites`)
-  }
+  },
+
+  // 获取点赞状态
+  // GET /posts/:postId/like/status?user_id=123
+  hasLikedPost: async (postId, userId) => {
+    const url = `${WZY_BASE_URL}/posts/${postId}/like/status?user_id=${userId}`
+    return await request(url)
+  },
 }
 
 export default postsAPI
diff --git a/Merge/front/src/api/search_jwlll.js b/Merge/front/src/api/search_jwlll.js
index e18efa3..e75abb0 100644
--- a/Merge/front/src/api/search_jwlll.js
+++ b/Merge/front/src/api/search_jwlll.js
@@ -17,7 +17,25 @@
       },
       ...options
     })
-    return await response.json()
+    
+    // 检查响应状态码
+    if (!response.ok) {
+      let errorData
+      try {
+        errorData = await response.json()
+      } catch {
+        errorData = { error: `HTTP ${response.status}` }
+      }
+      throw new Error(errorData.error || `HTTP ${response.status}`)
+    }
+    
+    // 处理空响应(如204 No Content)
+    const contentType = response.headers.get('content-type')
+    if (contentType && contentType.includes('application/json')) {
+      return await response.json()
+    } else {
+      return {} // 返回空对象而不是尝试解析JSON
+    }
   } catch (error) {
     console.error('API请求错误:', error)
     throw error
@@ -62,8 +80,7 @@
   // 获取帖子详情
   getPostDetail: async (postId) => {
     return await request(`${WZY_BASE_URL}/posts/${postId}`)
-  },
-  // 点赞帖子
+  },  // 点赞帖子
   likePost: async (postId, userId) => {
     return await request(`${WZY_BASE_URL}/posts/${postId}/like`, {
       method: 'POST',
@@ -78,11 +95,10 @@
       body: JSON.stringify({ user_id: userId })
     })
   },
-
   // 查看是否点赞
   hasLiked: async (postId, userId) => {
     const res = await request(
-      `${WZY_BASE_URL}/posts/${postId}/like?user_id=${userId}`,
+      `${WZY_BASE_URL}/posts/${postId}/like/status?user_id=${userId}`,
       {
         method: 'GET'
       }
diff --git a/Merge/front/src/components/PostDetailJWLLL.jsx b/Merge/front/src/components/PostDetailJWLLL.jsx
index 01f64b5..417105a 100644
--- a/Merge/front/src/components/PostDetailJWLLL.jsx
+++ b/Merge/front/src/components/PostDetailJWLLL.jsx
@@ -8,6 +8,7 @@
 import MediaPreview from './MediaPreview'
 import '../style/PostDetail.css'
 import dayjs from 'dayjs'
+import { followUser, unfollowUser } from '../api/api_ljc'
 
 export default function PostDetail() {
   const { id } = useParams()
@@ -22,16 +23,15 @@
   const [newComment, setNewComment] = useState('')
   const [showComments, setShowComments] = useState(false)
   const [isFollowing, setIsFollowing] = useState(false)
+  const [followLoading, setFollowLoading] = useState(false)
   const [authorInfo, setAuthorInfo] = useState(null)
   const [previewImg, setPreviewImg] = useState(null)
   const [commentUserMap, setCommentUserMap] = useState({}) // user_id: username
-  const [commentUserAvatarMap, setCommentUserAvatarMap] = useState({}) // user_id: avatar
-  // 获取当前用户ID
+  const [commentUserAvatarMap, setCommentUserAvatarMap] = useState({}) // user_id: avatar  // 获取当前用户ID
   const getCurrentUserId = () => {
     const userInfo = getUserInfo()
     return userInfo?.id || '3' // 如果未登录或无用户信息,使用默认值3
   }
-
   const fetchPostDetail = useCallback(async () => {
     setLoading(true)
     setError(null)
@@ -39,6 +39,16 @@
       const data = await searchAPI.getPostDetail(id)
       setPost(data)
       setLikeCount(data.heat || 0)
+      
+      // 检查当前用户是否已点赞
+      const currentUserId = getCurrentUserId()
+      try {
+        const hasLiked = await searchAPI.hasLiked(id, currentUserId)
+        setLiked(hasLiked)
+      } catch (error) {
+        console.error('检查点赞状态失败:', error)
+        setLiked(false) // 如果检查失败,默认为未点赞
+      }
     } catch (error) {
       console.error('获取帖子详情失败:', error)
       setError('帖子不存在或已被删除')
@@ -124,26 +134,48 @@
       fetchCommentUserAvatars(userIds)
     }
   }, [comments])
-
   const handleBack = () => {
     navigate(-1)
   }
   const handleLike = async () => {
+    const currentUserId = getCurrentUserId()
+    const originalLiked = liked
+    const originalLikeCount = likeCount
+    
     try {
-      const currentUserId = getCurrentUserId()
+      // 先乐观更新UI,提供即时反馈
       const newLiked = !liked
+      setLiked(newLiked)
+      setLikeCount(prev => newLiked ? prev + 1 : prev - 1)
+      
+      // 调用后端API
       if (newLiked) {
         await searchAPI.likePost(id, currentUserId)
       } else {
         await searchAPI.unlikePost(id, currentUserId)
       }
-      setLiked(newLiked)
-      setLikeCount(prev => newLiked ? prev + 1 : prev - 1)
+      
+      // API调用成功,状态已经更新,无需再次设置
     } catch (error) {
-      console.error('点赞失败:', error)
-      // 回滚状态
-      setLiked(!liked)
-      setLikeCount(prev => liked ? prev + 1 : prev - 1)
+      console.error('点赞操作失败:', error)
+      
+      // 检查是否是可以忽略的错误
+      const errorMessage = error.message || error.toString()
+      const isIgnorableError = errorMessage.includes('already liked') || 
+                              errorMessage.includes('not liked yet') ||
+                              errorMessage.includes('already favorited') ||
+                              errorMessage.includes('not favorited yet')
+      
+      if (isIgnorableError) {
+        // 这些错误可以忽略,因为最终状态是正确的
+        console.log('忽略重复操作错误:', errorMessage)
+        return
+      }
+      
+      // 发生真正的错误时回滚到原始状态
+      setLiked(originalLiked)
+      setLikeCount(originalLikeCount)
+      alert('操作失败,请重试')
     }
   }
 
@@ -182,22 +214,24 @@
   }
 
   // 关注后刷新关注状态
-  const handleFollowChange = async (followed) => {
-    setIsFollowing(followed)
-    // 关注/取关后重新拉取一次关注状态,保证和数据库同步
-    if (post && post.user_id) {
-      try {
-        const userInfo = getUserInfo()
-        if (!userInfo?.id) return
-        const res = await postsAPI.getUserFollowing(userInfo.id)
-        if (Array.isArray(res)) {
-          setIsFollowing(res.some(u => u.id === post.user_id))
-        } else if (Array.isArray(res.following)) {
-          setIsFollowing(res.following.some(u => u.id === post.user_id))
-        }
-      } catch {}
+  const handleFollowAction = async () => {
+  // 添加了加载状态和错误处理
+  setFollowLoading(true);
+  const currentUserId = getCurrentUserId()
+  try {
+    if (isFollowing) {
+      await unfollowUser(currentUserId, post.user_id);
+    } else {
+      await followUser(currentUserId, post.user_id);
     }
+    setIsFollowing(!isFollowing);
+  } catch (error) {
+    console.error(isFollowing ? '取消关注失败' : '关注失败', error);
+    alert(`操作失败: ${error.message || '请重试'}`);
+  } finally {
+    setFollowLoading(false);
   }
+};
 
   if (loading) {
     return (
@@ -285,12 +319,23 @@
               </span>
               {/* 关注按钮 */}
               {post.user_id && (
-                <FollowButton
-                  userId={post.user_id}
-                  isFollowing={isFollowing}
-                  onFollowChange={handleFollowChange}
-                  style={{marginLeft: 12}}
-                />
+                <button 
+                  className={`follow-btn ${isFollowing ? 'following' : ''}`}
+                  onClick={handleFollowAction}
+                  disabled={followLoading}
+                  style={{ 
+                    marginLeft: '12px', 
+                    padding: '4px 12px', 
+                    borderRadius: '20px', 
+                    border: '1px solid #ccc', 
+                    background: isFollowing ? '#f0f0f0' : '#007bff', 
+                    color: isFollowing ? '#333' : 'white', 
+                    cursor: 'pointer',
+                    fontSize: '14px'
+                  }}
+                >
+                  {followLoading ? '处理中...' : (isFollowing ? '已关注' : '关注')}
+                </button>
               )}
             </div>
           </div>