fix-send-message

Change-Id: I43a2f333a56eea499c960b057cd796b1621c771b
diff --git a/src/pages/UserCenter/UserCollect.css b/src/pages/UserCenter/UserCollect.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/pages/UserCenter/UserCollect.css
diff --git a/src/pages/UserCenter/UserCollect.jsx b/src/pages/UserCenter/UserCollect.jsx
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/pages/UserCenter/UserCollect.jsx
diff --git a/src/pages/UserCenter/UserFriends.css b/src/pages/UserCenter/UserFriends.css
index e69de29..2533959 100644
--- a/src/pages/UserCenter/UserFriends.css
+++ b/src/pages/UserCenter/UserFriends.css
@@ -0,0 +1,83 @@
+.friend-card {
+  background-color: #fff5e1;
+  border-radius: 16px;
+  padding: 20px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+  display: flex;
+  align-items: center;
+  gap: 20px;
+}
+
+.friend-avatar {
+  width: 60px;
+  height: 60px;
+  border-radius: 50%;
+  object-fit: cover;
+  border: 2px solid #ddd;
+}
+
+.friend-info {
+  flex: 1;
+}
+
+.friend-info h4 {
+  margin: 0;
+  font-size: 1.2em;
+  color: #333;
+}
+
+.friend-info p {
+  margin: 5px 0 0;
+  color: #666;
+  font-size: 0.9em;
+}
+.chat-modal-content {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  width: 420px;
+  max-width: 90%;
+  background: #fffefc;
+  border-radius: 12px;
+  padding: 24px;
+  transform: translate(-50%, -50%);
+  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
+  z-index: 1010;
+  font-family: 'Arial', sans-serif;
+}
+
+.chat-modal-content textarea {
+  border: 1px solid #ccc;
+  border-radius: 8px;
+  font-size: 14px;
+  padding: 10px;
+  font-family: inherit;
+  transition: border-color 0.2s;
+}
+
+.chat-modal-content textarea:focus {
+  border-color: #409eff;
+  outline: none;
+  box-shadow: 0 0 5px rgba(64, 158, 255, 0.5);
+}
+.chat-actions button {
+  padding: 8px 20px;
+  border-radius: 6px;
+  font-weight: bold;
+  transition: background-color 0.2s;
+}
+
+.chat-actions button:hover {
+  filter: brightness(1.1);
+}
+
+.chat-actions button:last-child:hover {
+  background-color: #ff4d4f;
+}
+.status-msg {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #666;
+  font-style: italic;
+}
diff --git a/src/pages/UserCenter/UserFriends.jsx b/src/pages/UserCenter/UserFriends.jsx
index e69de29..3aaec44 100644
--- a/src/pages/UserCenter/UserFriends.jsx
+++ b/src/pages/UserCenter/UserFriends.jsx
@@ -0,0 +1,209 @@
+import React, { useEffect, useState } from 'react';
+import axios from 'axios';
+import UserNav from './UserNav';
+import Header from '../../components/Header';
+import './UserFriends.css';
+import { useUser } from '../../context/UserContext';
+
+const UserFriends = () => {
+  const { user, loading } = useUser();
+  const [friends, setFriends] = useState([]);
+  const [error, setError] = useState(null);
+
+  // 私信相关状态
+  const [chatOpen, setChatOpen] = useState(false);
+  const [chatFriend, setChatFriend] = useState(null);
+  const [messageContent, setMessageContent] = useState('');
+  const [sendingStatus, setSendingStatus] = useState(null);
+
+  // 新增:聊天记录
+  const [chatMessages, setChatMessages] = useState([]);
+  const [loadingMessages, setLoadingMessages] = useState(false);
+  const [messagesError, setMessagesError] = useState(null);
+
+  useEffect(() => {
+    if (loading) return;
+
+    const fetchFriends = async () => {
+      if (!user || !user.userId) {
+        setError('未登录或用户信息缺失');
+        return;
+      }
+
+      try {
+        const res = await axios.get(`/echo/user/${user.userId}/friends`);
+        setFriends(res.data || []);
+        setError(null);
+      } catch (err) {
+        setError('加载好友失败,请稍后再试');
+      }
+    };
+
+    fetchFriends();
+  }, [user, loading]);
+
+  // 打开聊天框时加载聊天记录
+  const openChat = async (friend) => {
+    setChatFriend(friend);
+    setMessageContent('');
+    setSendingStatus(null);
+    setChatMessages([]);
+    setMessagesError(null);
+    setChatOpen(true);
+
+    if (!user || !user.userId) return;
+
+    setLoadingMessages(true);
+    try {
+      const res = await axios.get(`/echo/message/${user.userId}/getUserMessages`);
+      if (res.data.status === 'success') {
+        // 过滤出和这个好友的聊天消息(发或收都算)
+        const allMessages = res.data.messages || [];
+        const related = allMessages.filter(m =>
+          (m.sender_id === user.userId && m.receiver_id === friend.id) ||
+          (m.sender_id === friend.id && m.receiver_id === user.userId)
+        );
+        // 按时间排序(升序)
+        related.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
+        setChatMessages(related);
+      } else {
+        setMessagesError('无法加载聊天记录');
+      }
+    } catch (err) {
+      setMessagesError('加载聊天记录失败,请稍后再试');
+    } finally {
+      setLoadingMessages(false);
+    }
+  };
+
+  const closeChat = () => {
+    setChatOpen(false);
+    setChatFriend(null);
+    setMessageContent('');
+    setSendingStatus(null);
+    setChatMessages([]);
+    setMessagesError(null);
+  };
+
+  const sendMessage = async () => {
+    if (!messageContent.trim()) {
+      setSendingStatus('消息不能为空');
+      return;
+    }
+    setSendingStatus('发送中...');
+    try {
+      const res = await axios.post('/echo/message/sendMessages', {
+        sender_id: user.userId,
+        receiver_id: chatFriend.id,
+        content: messageContent.trim(),
+      });
+      if (res.data.status === 'success') {
+        setSendingStatus('发送成功');
+        setMessageContent('');
+        // 发送成功后,将这条消息追加到聊天记录
+        const newMsg = {
+          message_id: res.data.message_id,
+          sender_id: user.userId,
+          sender_username: user.username || '我',
+          receiver_id: chatFriend.id,
+          receiver_username: chatFriend.nickname,
+          content: messageContent.trim(),
+          timestamp: new Date().toISOString(),
+        };
+        setChatMessages(prev => [...prev, newMsg]);
+      } else {
+        setSendingStatus(res.data.message || '发送失败');
+      }
+    } catch (err) {
+      setSendingStatus('发送失败,请稍后再试');
+    }
+  };
+
+  if (loading) return <p>正在加载...</p>;
+  if (error) return <p className="error">{error}</p>;
+
+  return (
+    <div className="user-friends-container">
+      <Header />
+      <div className="user-center">
+        <div className="user-nav-container">
+          <UserNav />
+        </div>
+        <div className="common-card">
+          <h2>我的好友</h2>
+          <div className="friends-list">
+            {friends.length === 0 && <p>暂无好友</p>}
+            {friends.map((friend) => (
+              <div key={friend.id} className="friend-card">
+                <img src={friend.avatar} alt={friend.nickname} className="friend-avatar" />
+                <div className="friend-info">
+                  <p><strong>{friend.nickname}</strong></p>
+                  <p>{friend.email}</p>
+                  <button
+                    className="send-message-btn"
+                    onClick={() => openChat(friend)}
+                  >
+                    发送私信
+                  </button>
+                </div>
+              </div>
+            ))}
+          </div>
+        </div>
+      </div>
+
+      {/* 私信弹窗 */}
+      {chatOpen && (
+        <div className="chat-modal">
+          <div className="chat-modal-content">
+            <h3>给 {chatFriend.nickname} 发送私信</h3>
+            <div className="chat-messages" style={{height: '250px', overflowY: 'auto', border: '1px solid #ccc', padding: '8px', marginBottom: '8px'}}>
+              {loadingMessages && <p>加载聊天记录中...</p>}
+              {messagesError && <p className="error">{messagesError}</p>}
+              {!loadingMessages && chatMessages.length === 0 && <p>暂无聊天记录</p>}
+              {chatMessages.map(msg => (
+                <div
+                  key={msg.message_id}
+                  style={{
+                    textAlign: msg.sender_id === user.userId ? 'right' : 'left',
+                    marginBottom: '8px'
+                  }}
+                >
+                  <div style={{
+                    display: 'inline-block',
+                    backgroundColor: msg.sender_id === user.userId ? '#409eff' : '#f0f0f0',
+                    color: msg.sender_id === user.userId ? 'white' : 'black',
+                    borderRadius: '10px',
+                    padding: '6px 12px',
+                    maxWidth: '70%',
+                    wordBreak: 'break-word'
+                  }}>
+                    <p style={{margin: 0}}>{msg.content}</p>
+                    <small style={{fontSize: '10px', opacity: 0.7}}>
+                      {new Date(msg.timestamp).toLocaleString()}
+                    </small>
+                  </div>
+                </div>
+              ))}
+            </div>
+            <textarea
+              rows="3"
+              value={messageContent}
+              onChange={(e) => setMessageContent(e.target.value)}
+              placeholder="输入消息内容"
+              style={{width: '100%', marginBottom: '8px'}}
+            />
+            <div className="chat-actions">
+              <button onClick={sendMessage}>发送</button>
+              <button onClick={closeChat}>关闭</button>
+            </div>
+            {sendingStatus && <p className="status-msg">{sendingStatus}</p>}
+          </div>
+          <div className="chat-modal-backdrop" onClick={closeChat}></div>
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default UserFriends;