修正帖子列表、帖子详情的头像与名字显示问题
Change-Id: Ibcb01510f9474ea43c8739f3013c3aaa32e32640
diff --git a/Merge/back_rhj/app/user_post_graph.txt b/Merge/back_rhj/app/user_post_graph.txt
index f8ef7df..f2f2e58 100644
--- a/Merge/back_rhj/app/user_post_graph.txt
+++ b/Merge/back_rhj/app/user_post_graph.txt
@@ -1,12 +1,7 @@
-0 0 0 1 1 0 1 0 11 1749827292 1749953091 1749953091 1749953480 1749953480 1749954059 1749954059 1749955282 1 1 2 2 1 2 1 5
-1 1 4 0 12 1749827292 1749955282 1749955282 1749955282 5 5 2 1
-2 6 5 6 5 13 1 0 0 1 1 2 1749953091 1749953091 1749953480 1749953480 1749955282 1749955282 1750372189 1750372215 1750372231 1750372241 1750372258 2 1 2 1 2 5 3 2 3 2 2
-3 2 2 0 1749953091 1749953480 1749954059 2 2 2
-4 1 5 1749954059 1749955282 5 5
-5 2 6 1749955282 1749955282 5 1
-6 7 1749955282 2
-7 3 8 1749955282 1749955282 2 5
-8 9 1749955282 1
-9 10 1749955282 2
-10 12 1749894174 5
-11 1 4 7 0 2 13 4 11 1750372862 1750372873 1750373008 1750373592 1750373596 1750374164 1750374867 1750374871 3 3 3 2 2 2 2 2
+0 0 0 1 0 1 0 1 1749827292 1749953091 1749953091 1749953480 1749953480 1749954059 1749954059 1 1 2 1 2 1 2
+1 1 0 3 1749827292 1749955282 1749955282 5 2 5
+2 1 0 0 1 1 1749955282 1750372189 1750372215 1750372231 1750372241 5 3 2 3 2
+3 0 1749954059 2
+4 1 1749954059 5
+5 2 1749955282 2
+6 1 3 0 3 0 1750372862 1750372873 1750373592 1750374867 1750392753 3 3 2 2 3
diff --git a/Merge/front/src/api/api_ljc.js b/Merge/front/src/api/api_ljc.js
index b8130ca..1adea99 100644
--- a/Merge/front/src/api/api_ljc.js
+++ b/Merge/front/src/api/api_ljc.js
@@ -1,4 +1,5 @@
import axios from 'axios';
+import { getUserInfo } from '../utils/auth';
const api = axios.create({
baseURL: 'http://10.126.59.25:5715/api/',
@@ -14,8 +15,12 @@
export const getFavorites = (userId) => api.get(`/user/${userId}/favorites`);
// 关注相关API
-export const followUser = (followeeId) => api.post(`/follow/${followeeId}`);
-export const unfollowUser = (followeeId) => api.delete(`/follow/${followeeId}`);
+export const followUser = (followeeId) => {
+ return api.post(`/follow/${followeeId}`);
+};
+export const unfollowUser = (followeeId) => {
+ return api.delete(`/follow/${followeeId}`);
+};
// 帖子相关API
export const getUserPosts = (userId) => api.get(`/user/${userId}/posts`);
diff --git a/Merge/front/src/api/posts_api.js b/Merge/front/src/api/posts_api.js
index a336da0..06cf2c7 100644
--- a/Merge/front/src/api/posts_api.js
+++ b/Merge/front/src/api/posts_api.js
@@ -2,7 +2,7 @@
// 整合不同后端服务的帖子功能
// WZY 后端服务 - 帖子CRUD、点赞、评论
-const WZY_BASE_URL = 'http://10.126.59.25:5714'
+const WZY_BASE_URL = 'http://192.168.5.235:5714'
// LJC 后端服务 - 用户相关功能
const LJC_BASE_URL = 'http://10.126.59.25:5715'
diff --git a/Merge/front/src/api/search_jwlll.js b/Merge/front/src/api/search_jwlll.js
index 085507b..01b743f 100644
--- a/Merge/front/src/api/search_jwlll.js
+++ b/Merge/front/src/api/search_jwlll.js
@@ -5,7 +5,7 @@
// JWLLL 后端服务 - 仅用于推荐和搜索
const JWLLL_BASE_URL = 'http://10.126.59.25:5717'
// WZY 后端服务 - 用于帖子详情、点赞、评论等
-const WZY_BASE_URL = 'http://10.126.59.25:5714'
+const WZY_BASE_URL = 'http://192.168.5.235:5714'
// 通用请求函数
const request = async (url, options = {}) => {
diff --git a/Merge/front/src/components/FollowButton.jsx b/Merge/front/src/components/FollowButton.jsx
index 0776191..3e94161 100644
--- a/Merge/front/src/components/FollowButton.jsx
+++ b/Merge/front/src/components/FollowButton.jsx
@@ -1,31 +1,50 @@
-import React from 'react';
+import React, { useState } from 'react';
import { followUser, unfollowUser } from '../api/api_ljc';
-const FollowButton = ({ userId, isFollowing, onFollowChange }) => {
+const FollowButton = ({ userId, isFollowing, onFollowChange, style }) => {
+ const [loading, setLoading] = useState(false);
const handleFollow = async () => {
+ if (loading) return;
+ setLoading(true);
try {
+ console.log('FollowButton clicked, isFollowing:', isFollowing, 'userId:', userId);
if (isFollowing) {
- await unfollowUser(userId);
+ const res = await unfollowUser(userId);
+ console.log('unfollowUser response:', res);
onFollowChange(false);
} else {
- await followUser(userId);
+ const res = await followUser(userId);
+ console.log('followUser response:', res);
onFollowChange(true);
}
} catch (error) {
+ alert('关注操作失败,请重试!');
console.error('关注操作失败:', error);
+ } finally {
+ setLoading(false);
}
};
return (
- <button
+ <button
onClick={handleFollow}
- className={`px-6 py-2 rounded-full text-sm font-medium transition-all ${
- isFollowing
- ? 'bg-gray-100 text-gray-800 hover:bg-gray-200'
- : 'bg-red-500 text-white hover:bg-red-600'
- }`}
+ disabled={loading}
+ style={{
+ border: 'none',
+ outline: 'none',
+ borderRadius: 20,
+ padding: '6px 22px',
+ fontSize: 15,
+ fontWeight: 600,
+ cursor: loading ? 'not-allowed' : 'pointer',
+ background: isFollowing ? '#f5f5f5' : 'linear-gradient(90deg,#ff4b2b,#ff416c)',
+ color: isFollowing ? '#888' : '#fff',
+ boxShadow: isFollowing ? 'none' : '0 2px 8px #ff416c22',
+ transition: 'all 0.2s',
+ ...style
+ }}
>
- {isFollowing ? '已关注' : '关注'}
+ {loading ? '处理中...' : isFollowing ? '已关注' : '+ 关注'}
</button>
);
};
diff --git a/Merge/front/src/components/HomeFeed.jsx b/Merge/front/src/components/HomeFeed.jsx
index 1fb12a5..2e42621 100644
--- a/Merge/front/src/components/HomeFeed.jsx
+++ b/Merge/front/src/components/HomeFeed.jsx
@@ -7,6 +7,7 @@
import { searchAPI } from '../api/search_jwlll'
import { getUserInfo } from '../utils/auth'
import { deepRecommend } from '../api/recommend_rhj'
+import postsAPI from '../api/posts_api'
import '../style/HomeFeed.css'
const categories = [
@@ -40,6 +41,7 @@
const [recMode, setRecMode] = useState('tag')
const [recCFNum, setRecCFNum] = useState(20)
const [useSearchRecommend, setUseSearchRecommend] = useState(false) // 是否使用搜索推荐模式 // JWLLL 搜索推荐功能函数
+ const [userMap, setUserMap] = useState({}) // user_id: {username, nickname}
// JWLLL搜索推荐内容
const fetchSearchContent = useCallback(async (keyword = '') => {
@@ -47,16 +49,34 @@
setError(null)
try {
const data = await searchAPI.search(keyword || activeCat, activeCat === '推荐' ? undefined : activeCat)
- const formattedItems = (data.results || []).map(item => ({
- id: item.id,
- title: item.title,
- author: item.author || '佚名',
- avatar: `https://i.pravatar.cc/40?img=${item.id}`,
- img: item.img || '',
- likes: item.heat || 0,
- content: item.content
- }))
- setItems(formattedItems)
+ // 新增:拉取详情,保证和推荐一致
+ const detailed = await Promise.all(
+ (data.results || []).map(async item => {
+ try {
+ const d = await fetchPost(item.id)
+ return {
+ id: d.id,
+ title: d.title,
+ author: `作者 ${d.user_id}`,
+ avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
+ img: d.media_urls?.[0] || '',
+ likes: d.heat,
+ content: d.content || ''
+ }
+ } catch {
+ return {
+ id: item.id,
+ title: item.title,
+ author: item.author || '佚名',
+ avatar: `https://i.pravatar.cc/40?img=${item.id}`,
+ img: item.img || '',
+ likes: item.heat || 0,
+ content: item.content || ''
+ }
+ }
+ })
+ )
+ setItems(detailed)
} catch (e) {
console.error('搜索失败:', e)
setError('搜索失败')
@@ -213,6 +233,20 @@
setLoading(false)
}, [recMode, fetchTagRecommend, fetchCFRecommend, fetchDeepRecommend])
+ // 拉取所有涉及用户的昵称
+ const fetchUserNames = async (userIds) => {
+ const map = {}
+ await Promise.all(userIds.map(async uid => {
+ try {
+ const user = await postsAPI.getUser(uid)
+ map[uid] = user.username || user.nickname || `用户${uid}`
+ } catch {
+ map[uid] = `用户${uid}`
+ }
+ }))
+ setUserMap(map)
+ }
+
useEffect(() => {
// 原始数据加载函数
const loadPosts = async () => {
@@ -225,7 +259,7 @@
return {
id: d.id,
title: d.title,
- author: `作者 ${d.user_id}`,
+ authorId: d.user_id,
avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
img: d.media_urls?.[0] || '', // 用第一张媒体作为封面
likes: d.heat
@@ -233,6 +267,9 @@
})
)
setItems(detailed)
+ // 拉取所有涉及用户的昵称
+ const userIds = [...new Set(detailed.map(i => i.authorId))]
+ fetchUserNames(userIds)
} catch (e) {
setError(e.message)
} finally {
@@ -399,8 +436,8 @@
{item.content && <div className="card-content">{item.content.slice(0, 60) || ''}</div>}
<div className="card-footer">
<div className="card-author">
- <img className="avatar" src={item.avatar} alt={item.author} />
- <span className="username">{item.author}</span>
+ <img className="avatar" src={item.avatar} alt={userMap[item.authorId] || item.authorId} />
+ <span className="username">{userMap[item.authorId] || item.authorId}</span>
</div>
<div className="card-likes">
<ThumbsUp size={16} />
diff --git a/Merge/front/src/components/PostDetailJWLLL.jsx b/Merge/front/src/components/PostDetailJWLLL.jsx
index 009ba6c..cc5eb96 100644
--- a/Merge/front/src/components/PostDetailJWLLL.jsx
+++ b/Merge/front/src/components/PostDetailJWLLL.jsx
@@ -3,6 +3,8 @@
import { ArrowLeft, ThumbsUp, MessageCircle, Share2, BookmarkPlus, Heart, Eye } from 'lucide-react'
import { searchAPI } from '../api/search_jwlll'
import { getUserInfo } from '../utils/auth'
+import FollowButton from './FollowButton'
+import postsAPI from '../api/posts_api'
import '../style/PostDetail.css'
export default function PostDetail() {
@@ -17,6 +19,8 @@
const [comments, setComments] = useState([])
const [newComment, setNewComment] = useState('')
const [showComments, setShowComments] = useState(false)
+ const [isFollowing, setIsFollowing] = useState(false)
+ const [authorInfo, setAuthorInfo] = useState(null)
// 获取当前用户ID
const getCurrentUserId = () => {
const userInfo = getUserInfo()
@@ -47,6 +51,33 @@
}
}, [id])
+ // 检查当前用户是否已关注发帖人
+ useEffect(() => {
+ if (post && post.user_id) {
+ // 这里假设有API postsAPI.getUserFollowing
+ const checkFollow = async () => {
+ 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 {}
+ }
+ checkFollow()
+ }
+ }, [post])
+
+ // 拉取发帖人信息
+ useEffect(() => {
+ if (post && post.user_id) {
+ postsAPI.getUser(post.user_id).then(res => setAuthorInfo(res || {})).catch(() => setAuthorInfo({}))
+ }
+ }, [post])
+
useEffect(() => {
fetchPostDetail()
fetchComments()
@@ -108,6 +139,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 {}
+ }
+ }
+
if (loading) {
return (
<div className="post-detail">
@@ -119,6 +168,7 @@
)
}
+ // 优化错误和不存在的判断逻辑
if (error) {
return (
<div className="post-detail">
@@ -134,11 +184,12 @@
)
}
- if (!post) {
+ // 只有明确为 null 或 undefined 时才显示不存在
+ if (post === null || post === undefined) {
return (
<div className="post-detail">
<div className="error-container">
- <h2>😔 帖子不存在</h2>
+ <h2>😔 帖子不存在或已被删除</h2>
<p>该帖子可能已被删除或不存在</p>
<button onClick={handleBack} className="back-btn">
<ArrowLeft size={20} />
@@ -179,13 +230,26 @@
<div className="post-meta">
<div className="author-info">
<div className="avatar">
- {post.author ? post.author.charAt(0).toUpperCase() : 'U'}
+ {authorInfo && authorInfo.avatar && authorInfo.avatar.startsWith('http') ? (
+ <img className="avatar" src={authorInfo.avatar} alt={authorInfo.username || authorInfo.nickname || post.author || '用户'} />
+ ) : (
+ <img className="avatar" src={`https://i.pravatar.cc/40?img=${post.user_id}`} alt={authorInfo?.username || authorInfo?.nickname || post.author || '用户'} />
+ )}
</div>
<div className="author-details">
- <span className="author-name">{post.author || '匿名用户'}</span>
+ <span className="author-name">{authorInfo?.username || authorInfo?.nickname || post.author || '匿名用户'}</span>
<span className="post-date">
{post.create_time ? new Date(post.create_time).toLocaleDateString('zh-CN') : '未知时间'}
</span>
+ {/* 关注按钮 */}
+ {post.user_id && (
+ <FollowButton
+ userId={post.user_id}
+ isFollowing={isFollowing}
+ onFollowChange={handleFollowChange}
+ style={{marginLeft: 12}}
+ />
+ )}
</div>
</div>
<div className="post-stats">
diff --git a/Merge/front/src/components/UserProfile.jsx b/Merge/front/src/components/UserProfile.jsx
index 53618db..6cddcbd 100644
--- a/Merge/front/src/components/UserProfile.jsx
+++ b/Merge/front/src/components/UserProfile.jsx
@@ -279,7 +279,6 @@
const handleFollowToggle = async () => {
if (!currentUser || !profileUser) return;
-
try {
if (profileUser.is_following) {
await unfollowUserApi(profileUser.id);
@@ -288,11 +287,18 @@
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');