blob: e1c978904611234cce467c7fa1bc41aa8f54b9ba [file] [log] [blame]
Krishyac6b24832025-06-05 20:13:20 +08001// import React, { useEffect, useState } from 'react';
2// import axios from 'axios';
3// import UserNav from './UserNav';
4// import Header from '../../components/Header';
5// import './UserFriends.css';
6// import { useUser } from '../../context/UserContext';
7
8// const UserFriends = () => {
9// const { user, loading } = useUser();
10// const [friends, setFriends] = useState([]);
11// const [error, setError] = useState(null);
12
13// // 私信相关状态
14// const [chatOpen, setChatOpen] = useState(false);
15// const [chatFriend, setChatFriend] = useState(null);
16// const [messageContent, setMessageContent] = useState('');
17// const [sendingStatus, setSendingStatus] = useState(null);
18
19// // 新增:聊天记录
20// const [chatMessages, setChatMessages] = useState([]);
21// const [loadingMessages, setLoadingMessages] = useState(false);
22// const [messagesError, setMessagesError] = useState(null);
23
24// useEffect(() => {
25// if (loading) return;
26
27// const fetchFriends = async () => {
28// if (!user || !user.userId) {
29// setError('未登录或用户信息缺失');
30// return;
31// }
32
33// try {
34// const res = await axios.get(`/echo/user/${user.userId}/friends`);
35// setFriends(res.data || []);
36// setError(null);
37// } catch (err) {
38// setError('加载好友失败,请稍后再试');
39// }
40// };
41
42// fetchFriends();
43// }, [user, loading]);
44
45// // 打开聊天框时加载聊天记录
46// const openChat = async (friend) => {
47// setChatFriend(friend);
48// setMessageContent('');
49// setSendingStatus(null);
50// setChatMessages([]);
51// setMessagesError(null);
52// setChatOpen(true);
53
54// if (!user || !user.userId) return;
55
56// setLoadingMessages(true);
57// try {
58// const res = await axios.get(`/echo/message/${user.userId}/getUserMessages`);
59// if (res.data.status === 'success') {
60// // 过滤出和这个好友的聊天消息(发或收都算)
61// const allMessages = res.data.messages || [];
62// const related = allMessages.filter(m =>
63// (m.sender_id === user.userId && m.receiver_id === friend.id) ||
64// (m.sender_id === friend.id && m.receiver_id === user.userId)
65// );
66// // 按时间排序(升序)
67// related.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
68// setChatMessages(related);
69// } else {
70// setMessagesError('无法加载聊天记录');
71// }
72// } catch (err) {
73// setMessagesError('加载聊天记录失败,请稍后再试');
74// } finally {
75// setLoadingMessages(false);
76// }
77// };
78
79// const closeChat = () => {
80// setChatOpen(false);
81// setChatFriend(null);
82// setMessageContent('');
83// setSendingStatus(null);
84// setChatMessages([]);
85// setMessagesError(null);
86// };
87
88// const sendMessage = async () => {
89// if (!messageContent.trim()) {
90// setSendingStatus('消息不能为空');
91// return;
92// }
93// setSendingStatus('发送中...');
94// try {
95// const res = await axios.post('/echo/message/sendMessages', {
96// sender_id: user.userId,
97// receiver_id: chatFriend.id,
98// content: messageContent.trim(),
99// });
100// if (res.data.status === 'success') {
101// setSendingStatus('发送成功');
102// setMessageContent('');
103// // 发送成功后,将这条消息追加到聊天记录
104// const newMsg = {
105// message_id: res.data.message_id,
106// sender_id: user.userId,
107// sender_username: user.username || '我',
108// receiver_id: chatFriend.id,
109// receiver_username: chatFriend.nickname,
110// content: messageContent.trim(),
111// timestamp: new Date().toISOString(),
112// };
113// setChatMessages(prev => [...prev, newMsg]);
114// } else {
115// setSendingStatus(res.data.message || '发送失败');
116// }
117// } catch (err) {
118// setSendingStatus('发送失败,请稍后再试');
119// }
120// };
121
122// if (loading) return <p>正在加载...</p>;
123// if (error) return <p className="error">{error}</p>;
124
125// return (
126// <div className="user-friends-container">
127// <Header />
128// <div className="user-center">
129// <div className="user-nav-container">
130// <UserNav />
131// </div>
132// <div className="common-card">
133// <h2>我的好友</h2>
134// <div className="friends-list">
135// {friends.length === 0 && <p>暂无好友</p>}
136// {friends.map((friend) => (
137// <div key={friend.id} className="friend-card">
138// <img src={friend.avatar} alt={friend.nickname} className="friend-avatar" />
139// <div className="friend-info">
140// <p><strong>{friend.nickname}</strong></p>
141// <p>{friend.email}</p>
142// <button
143// className="send-message-btn"
144// onClick={() => openChat(friend)}
145// >
146// 发送私信
147// </button>
148// </div>
149// </div>
150// ))}
151// </div>
152// </div>
153// </div>
154
155// {/* 私信弹窗 */}
156// {chatOpen && (
157// <div className="chat-modal">
158// <div className="chat-modal-content">
159// <h3>给 {chatFriend.nickname} 发送私信</h3>
160// <div className="chat-messages" style={{height: '250px', overflowY: 'auto', border: '1px solid #ccc', padding: '8px', marginBottom: '8px'}}>
161// {loadingMessages && <p>加载聊天记录中...</p>}
162// {messagesError && <p className="error">{messagesError}</p>}
163// {!loadingMessages && chatMessages.length === 0 && <p>暂无聊天记录</p>}
164// {chatMessages.map(msg => (
165// <div
166// key={msg.message_id}
167// style={{
168// textAlign: msg.sender_id === user.userId ? 'right' : 'left',
169// marginBottom: '8px'
170// }}
171// >
172// <div style={{
173// display: 'inline-block',
174// backgroundColor: msg.sender_id === user.userId ? '#409eff' : '#f0f0f0',
175// color: msg.sender_id === user.userId ? 'white' : 'black',
176// borderRadius: '10px',
177// padding: '6px 12px',
178// maxWidth: '70%',
179// wordBreak: 'break-word'
180// }}>
181// <p style={{margin: 0}}>{msg.content}</p>
182// <small style={{fontSize: '10px', opacity: 0.7}}>
183// {new Date(msg.timestamp).toLocaleString()}
184// </small>
185// </div>
186// </div>
187// ))}
188// </div>
189// <textarea
190// rows="3"
191// value={messageContent}
192// onChange={(e) => setMessageContent(e.target.value)}
193// placeholder="输入消息内容"
194// style={{width: '100%', marginBottom: '8px'}}
195// />
196// <div className="chat-actions">
197// <button onClick={sendMessage}>发送</button>
198// <button onClick={closeChat}>关闭</button>
199// </div>
200// {sendingStatus && <p className="status-msg">{sendingStatus}</p>}
201// </div>
202// <div className="chat-modal-backdrop" onClick={closeChat}></div>
203// </div>
204// )}
205// </div>
206// );
207// };
208
209// export default UserFriends;
210
22301009648cb7e2025-06-04 08:54:23 +0800211import React, { useEffect, useState } from 'react';
212import axios from 'axios';
22301009648cb7e2025-06-04 08:54:23 +0800213import { useUser } from '../../context/UserContext';
Krishyac6b24832025-06-05 20:13:20 +0800214import './UserFriends.css';
22301009648cb7e2025-06-04 08:54:23 +0800215
216const UserFriends = () => {
217 const { user, loading } = useUser();
218 const [friends, setFriends] = useState([]);
219 const [error, setError] = useState(null);
220
22301009648cb7e2025-06-04 08:54:23 +0800221 const [chatOpen, setChatOpen] = useState(false);
222 const [chatFriend, setChatFriend] = useState(null);
223 const [messageContent, setMessageContent] = useState('');
224 const [sendingStatus, setSendingStatus] = useState(null);
22301009648cb7e2025-06-04 08:54:23 +0800225 const [chatMessages, setChatMessages] = useState([]);
226 const [loadingMessages, setLoadingMessages] = useState(false);
227 const [messagesError, setMessagesError] = useState(null);
228
229 useEffect(() => {
230 if (loading) return;
231
232 const fetchFriends = async () => {
233 if (!user || !user.userId) {
234 setError('未登录或用户信息缺失');
235 return;
236 }
237
238 try {
239 const res = await axios.get(`/echo/user/${user.userId}/friends`);
240 setFriends(res.data || []);
241 setError(null);
242 } catch (err) {
243 setError('加载好友失败,请稍后再试');
244 }
245 };
246
247 fetchFriends();
248 }, [user, loading]);
249
22301009648cb7e2025-06-04 08:54:23 +0800250 const openChat = async (friend) => {
251 setChatFriend(friend);
252 setMessageContent('');
253 setSendingStatus(null);
254 setChatMessages([]);
255 setMessagesError(null);
256 setChatOpen(true);
257
258 if (!user || !user.userId) return;
259
260 setLoadingMessages(true);
261 try {
262 const res = await axios.get(`/echo/message/${user.userId}/getUserMessages`);
263 if (res.data.status === 'success') {
22301009648cb7e2025-06-04 08:54:23 +0800264 const allMessages = res.data.messages || [];
265 const related = allMessages.filter(m =>
266 (m.sender_id === user.userId && m.receiver_id === friend.id) ||
267 (m.sender_id === friend.id && m.receiver_id === user.userId)
268 );
22301009648cb7e2025-06-04 08:54:23 +0800269 related.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
270 setChatMessages(related);
271 } else {
272 setMessagesError('无法加载聊天记录');
273 }
274 } catch (err) {
275 setMessagesError('加载聊天记录失败,请稍后再试');
276 } finally {
277 setLoadingMessages(false);
278 }
279 };
280
281 const closeChat = () => {
282 setChatOpen(false);
283 setChatFriend(null);
284 setMessageContent('');
285 setSendingStatus(null);
286 setChatMessages([]);
287 setMessagesError(null);
288 };
289
290 const sendMessage = async () => {
291 if (!messageContent.trim()) {
292 setSendingStatus('消息不能为空');
293 return;
294 }
295 setSendingStatus('发送中...');
296 try {
297 const res = await axios.post('/echo/message/sendMessages', {
298 sender_id: user.userId,
299 receiver_id: chatFriend.id,
300 content: messageContent.trim(),
301 });
302 if (res.data.status === 'success') {
303 setSendingStatus('发送成功');
304 setMessageContent('');
22301009648cb7e2025-06-04 08:54:23 +0800305 const newMsg = {
306 message_id: res.data.message_id,
307 sender_id: user.userId,
308 sender_username: user.username || '我',
309 receiver_id: chatFriend.id,
310 receiver_username: chatFriend.nickname,
311 content: messageContent.trim(),
312 timestamp: new Date().toISOString(),
313 };
314 setChatMessages(prev => [...prev, newMsg]);
315 } else {
316 setSendingStatus(res.data.message || '发送失败');
317 }
318 } catch (err) {
319 setSendingStatus('发送失败,请稍后再试');
320 }
321 };
322
323 if (loading) return <p>正在加载...</p>;
324 if (error) return <p className="error">{error}</p>;
325
326 return (
Krishyac6b24832025-06-05 20:13:20 +0800327 <div className="user-subpage-card">
328 <h2>我的好友</h2>
329 <div className="friends-list">
330 {friends.length === 0 && <p>暂无好友</p>}
331 {friends.map((friend) => (
332 <div key={friend.id} className="friend-card">
333 <img src={friend.avatar} alt={friend.nickname} className="friend-avatar" />
334 <div className="friend-info">
335 <p><strong>{friend.nickname}</strong></p>
336 <p>{friend.email}</p>
337 <button className="send-message-btn" onClick={() => openChat(friend)}>
338 发送私信
339 </button>
340 </div>
22301009648cb7e2025-06-04 08:54:23 +0800341 </div>
Krishyac6b24832025-06-05 20:13:20 +0800342 ))}
22301009648cb7e2025-06-04 08:54:23 +0800343 </div>
344
345 {/* 私信弹窗 */}
346 {chatOpen && (
347 <div className="chat-modal">
348 <div className="chat-modal-content">
349 <h3> {chatFriend.nickname} 发送私信</h3>
Krishyac6b24832025-06-05 20:13:20 +0800350 <div className="chat-messages">
22301009648cb7e2025-06-04 08:54:23 +0800351 {loadingMessages && <p>加载聊天记录中...</p>}
352 {messagesError && <p className="error">{messagesError}</p>}
353 {!loadingMessages && chatMessages.length === 0 && <p>暂无聊天记录</p>}
354 {chatMessages.map(msg => (
355 <div
356 key={msg.message_id}
357 style={{
358 textAlign: msg.sender_id === user.userId ? 'right' : 'left',
359 marginBottom: '8px'
360 }}
361 >
Krishyac6b24832025-06-05 20:13:20 +0800362 <div className={`chat-bubble ${msg.sender_id === user.userId ? 'self' : 'other'}`}>
363 <p>{msg.content}</p>
364 <small>{new Date(msg.timestamp).toLocaleString()}</small>
22301009648cb7e2025-06-04 08:54:23 +0800365 </div>
366 </div>
367 ))}
368 </div>
369 <textarea
370 rows="3"
371 value={messageContent}
372 onChange={(e) => setMessageContent(e.target.value)}
373 placeholder="输入消息内容"
22301009648cb7e2025-06-04 08:54:23 +0800374 />
375 <div className="chat-actions">
376 <button onClick={sendMessage}>发送</button>
377 <button onClick={closeChat}>关闭</button>
378 </div>
379 {sendingStatus && <p className="status-msg">{sendingStatus}</p>}
380 </div>
381 <div className="chat-modal-backdrop" onClick={closeChat}></div>
382 </div>
383 )}
384 </div>
385 );
386};
387
388export default UserFriends;
Krishyac6b24832025-06-05 20:13:20 +0800389