blob: 55409111e37f99219dcbbe2b1ef1ab79950c9ca6 [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
Krishya767f9b92025-06-05 23:59:37 +0800229 const [email, setEmail] = useState('');
230
22301009648cb7e2025-06-04 08:54:23 +0800231 useEffect(() => {
232 if (loading) return;
233
234 const fetchFriends = async () => {
235 if (!user || !user.userId) {
236 setError('未登录或用户信息缺失');
237 return;
238 }
239
240 try {
241 const res = await axios.get(`/echo/user/${user.userId}/friends`);
242 setFriends(res.data || []);
243 setError(null);
244 } catch (err) {
245 setError('加载好友失败,请稍后再试');
246 }
247 };
248
249 fetchFriends();
250 }, [user, loading]);
251
22301009648cb7e2025-06-04 08:54:23 +0800252 const openChat = async (friend) => {
253 setChatFriend(friend);
254 setMessageContent('');
255 setSendingStatus(null);
256 setChatMessages([]);
257 setMessagesError(null);
258 setChatOpen(true);
259
260 if (!user || !user.userId) return;
261
262 setLoadingMessages(true);
263 try {
264 const res = await axios.get(`/echo/message/${user.userId}/getUserMessages`);
265 if (res.data.status === 'success') {
22301009648cb7e2025-06-04 08:54:23 +0800266 const allMessages = res.data.messages || [];
267 const related = allMessages.filter(m =>
268 (m.sender_id === user.userId && m.receiver_id === friend.id) ||
269 (m.sender_id === friend.id && m.receiver_id === user.userId)
270 );
22301009648cb7e2025-06-04 08:54:23 +0800271 related.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
272 setChatMessages(related);
273 } else {
274 setMessagesError('无法加载聊天记录');
275 }
276 } catch (err) {
277 setMessagesError('加载聊天记录失败,请稍后再试');
278 } finally {
279 setLoadingMessages(false);
280 }
281 };
282
283 const closeChat = () => {
284 setChatOpen(false);
285 setChatFriend(null);
286 setMessageContent('');
287 setSendingStatus(null);
288 setChatMessages([]);
289 setMessagesError(null);
290 };
291
292 const sendMessage = async () => {
293 if (!messageContent.trim()) {
294 setSendingStatus('消息不能为空');
295 return;
296 }
297 setSendingStatus('发送中...');
298 try {
299 const res = await axios.post('/echo/message/sendMessages', {
300 sender_id: user.userId,
301 receiver_id: chatFriend.id,
302 content: messageContent.trim(),
303 });
304 if (res.data.status === 'success') {
305 setSendingStatus('发送成功');
306 setMessageContent('');
22301009648cb7e2025-06-04 08:54:23 +0800307 const newMsg = {
308 message_id: res.data.message_id,
309 sender_id: user.userId,
310 sender_username: user.username || '我',
311 receiver_id: chatFriend.id,
312 receiver_username: chatFriend.nickname,
313 content: messageContent.trim(),
314 timestamp: new Date().toISOString(),
315 };
316 setChatMessages(prev => [...prev, newMsg]);
317 } else {
318 setSendingStatus(res.data.message || '发送失败');
319 }
320 } catch (err) {
321 setSendingStatus('发送失败,请稍后再试');
322 }
323 };
324
Krishya767f9b92025-06-05 23:59:37 +0800325 const handleSubmit = async () => {
326 const res = await axios.post(`/echo/user/addFriend`, { email: email, userid: user.userId });
327 console.log(res);
328 const response = await axios.get(`/echo/user/${user.userId}/friends`);
329 setFriends(response.data || []);
330 alert(res.data.msg);
331 }
332
22301009648cb7e2025-06-04 08:54:23 +0800333 if (loading) return <p>正在加载...</p>;
334 if (error) return <p className="error">{error}</p>;
335
336 return (
Krishyac6b24832025-06-05 20:13:20 +0800337 <div className="user-subpage-card">
338 <h2>我的好友</h2>
Krishya767f9b92025-06-05 23:59:37 +0800339 <div>
340 <input type="text" value={email} placeholder="请输入好友邮箱" onChange={e => setEmail(e.target.value)} />
341 <button className="btn submit" onClick={handleSubmit}>
342 添加
343 </button>
344 </div>
Krishyac6b24832025-06-05 20:13:20 +0800345 <div className="friends-list">
346 {friends.length === 0 && <p>暂无好友</p>}
347 {friends.map((friend) => (
348 <div key={friend.id} className="friend-card">
349 <img src={friend.avatar} alt={friend.nickname} className="friend-avatar" />
350 <div className="friend-info">
351 <p><strong>{friend.nickname}</strong></p>
352 <p>{friend.email}</p>
353 <button className="send-message-btn" onClick={() => openChat(friend)}>
354 发送私信
355 </button>
356 </div>
22301009648cb7e2025-06-04 08:54:23 +0800357 </div>
Krishyac6b24832025-06-05 20:13:20 +0800358 ))}
22301009648cb7e2025-06-04 08:54:23 +0800359 </div>
360
361 {/* 私信弹窗 */}
362 {chatOpen && (
363 <div className="chat-modal">
364 <div className="chat-modal-content">
365 <h3> {chatFriend.nickname} 发送私信</h3>
Krishyac6b24832025-06-05 20:13:20 +0800366 <div className="chat-messages">
22301009648cb7e2025-06-04 08:54:23 +0800367 {loadingMessages && <p>加载聊天记录中...</p>}
368 {messagesError && <p className="error">{messagesError}</p>}
369 {!loadingMessages && chatMessages.length === 0 && <p>暂无聊天记录</p>}
370 {chatMessages.map(msg => (
371 <div
372 key={msg.message_id}
373 style={{
374 textAlign: msg.sender_id === user.userId ? 'right' : 'left',
375 marginBottom: '8px'
376 }}
377 >
Krishyac6b24832025-06-05 20:13:20 +0800378 <div className={`chat-bubble ${msg.sender_id === user.userId ? 'self' : 'other'}`}>
379 <p>{msg.content}</p>
380 <small>{new Date(msg.timestamp).toLocaleString()}</small>
22301009648cb7e2025-06-04 08:54:23 +0800381 </div>
382 </div>
383 ))}
384 </div>
385 <textarea
386 rows="3"
387 value={messageContent}
388 onChange={(e) => setMessageContent(e.target.value)}
389 placeholder="输入消息内容"
22301009648cb7e2025-06-04 08:54:23 +0800390 />
391 <div className="chat-actions">
392 <button onClick={sendMessage}>发送</button>
393 <button onClick={closeChat}>关闭</button>
394 </div>
395 {sendingStatus && <p className="status-msg">{sendingStatus}</p>}
396 </div>
397 <div className="chat-modal-backdrop" onClick={closeChat}></div>
398 </div>
399 )}
400 </div>
401 );
402};
403
404export default UserFriends;
Krishyac6b24832025-06-05 20:13:20 +0800405