blob: 491c19c7afa20bbbf8a0623799f431c079c90e81 [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">
Krishya73cd8822025-06-07 15:48:41 +0800338
339 <div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginLeft: '-12%' }}>
340 <div className="search">
341 <input
342 type="text"
343 value={email}
344 onChange={(e) => setEmail(e.target.value)}
345 placeholder="搜索邮箱添加好友"
346 />
347 </div>
348
Krishya767f9b92025-06-05 23:59:37 +0800349 <button className="btn submit" onClick={handleSubmit}>
350 添加
351 </button>
352 </div>
Krishya73cd8822025-06-07 15:48:41 +0800353
354 {/* 增加间距 */}
355 <div style={{ marginBottom: '30px' }}></div>
356
Krishyac6b24832025-06-05 20:13:20 +0800357 <div className="friends-list">
358 {friends.length === 0 && <p>暂无好友</p>}
359 {friends.map((friend) => (
360 <div key={friend.id} className="friend-card">
361 <img src={friend.avatar} alt={friend.nickname} className="friend-avatar" />
362 <div className="friend-info">
363 <p><strong>{friend.nickname}</strong></p>
364 <p>{friend.email}</p>
Krishya73cd8822025-06-07 15:48:41 +0800365 <button style={{ padding: '6px 12px', fontSize: '15px', float: 'right' }} onClick={() => openChat(friend)}>
Krishyac6b24832025-06-05 20:13:20 +0800366 发送私信
367 </button>
368 </div>
22301009648cb7e2025-06-04 08:54:23 +0800369 </div>
Krishyac6b24832025-06-05 20:13:20 +0800370 ))}
22301009648cb7e2025-06-04 08:54:23 +0800371 </div>
372
373 {/* 私信弹窗 */}
374 {chatOpen && (
375 <div className="chat-modal">
376 <div className="chat-modal-content">
377 <h3> {chatFriend.nickname} 发送私信</h3>
Krishyac6b24832025-06-05 20:13:20 +0800378 <div className="chat-messages">
22301009648cb7e2025-06-04 08:54:23 +0800379 {loadingMessages && <p>加载聊天记录中...</p>}
380 {messagesError && <p className="error">{messagesError}</p>}
381 {!loadingMessages && chatMessages.length === 0 && <p>暂无聊天记录</p>}
382 {chatMessages.map(msg => (
383 <div
384 key={msg.message_id}
385 style={{
386 textAlign: msg.sender_id === user.userId ? 'right' : 'left',
387 marginBottom: '8px'
388 }}
389 >
Krishyac6b24832025-06-05 20:13:20 +0800390 <div className={`chat-bubble ${msg.sender_id === user.userId ? 'self' : 'other'}`}>
391 <p>{msg.content}</p>
392 <small>{new Date(msg.timestamp).toLocaleString()}</small>
22301009648cb7e2025-06-04 08:54:23 +0800393 </div>
394 </div>
395 ))}
396 </div>
397 <textarea
398 rows="3"
399 value={messageContent}
400 onChange={(e) => setMessageContent(e.target.value)}
401 placeholder="输入消息内容"
22301009648cb7e2025-06-04 08:54:23 +0800402 />
403 <div className="chat-actions">
404 <button onClick={sendMessage}>发送</button>
405 <button onClick={closeChat}>关闭</button>
406 </div>
407 {sendingStatus && <p className="status-msg">{sendingStatus}</p>}
408 </div>
409 <div className="chat-modal-backdrop" onClick={closeChat}></div>
410 </div>
411 )}
412 </div>
413 );
414};
415
416export default UserFriends;
Krishyac6b24832025-06-05 20:13:20 +0800417