修改好友动态、发布动态、促销模块、创建帖子,Resolve review.

Change-Id: I84a2460dd1208bc703b0527d98225204d03e5efc
diff --git a/src/pages/FriendMoments/FriendMoments.jsx b/src/pages/FriendMoments/FriendMoments.jsx
index 4e1a704..fdf101c 100644
--- a/src/pages/FriendMoments/FriendMoments.jsx
+++ b/src/pages/FriendMoments/FriendMoments.jsx
@@ -1,55 +1,210 @@
-// import React from 'react';
-// import './FriendMoments.css'; 
-// import { Link } from 'wouter'; 
-// import logo from '../../assets/logo.png'; 
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+import './FriendMoments.css';
+import Header from '../../components/Header';
+import { Edit } from '@icon-park/react';
 
-// const FriendMoments = () => {
-//   return (
-//     <div className="friend-moments">
-//       {/* 顶部栏 */}
-//       <header className="header">
-//         {/* 左侧 logo 和网站名称 */}
-//         <div className="logo-and-name">
-//           {/* 确保此处没有语法错误 */}
-//           <img src={logo} alt="网站 logo" className="logo" />
-//           <span className="site-name">Echo</span>
-//         </div>
-//         {/* 右侧用户头像和消息中心 */}
-//         <div className="user-and-message">
-//           <img src="user-avatar.png" alt="用户头像" className="user-avatar" />
-//           <span className="message-center">消息</span>
-//         </div>
-//       </header>
-//       {/* 导航栏 */}
-//       <nav className="nav">
-//         <Link to="/friend-moments" className="nav-item active">好友动态</Link>
-//         <Link to="/forum" className="nav-item">论坛</Link>
-//         <Link to="/interest-groups" className="nav-item">兴趣小组</Link>
-//         <Link to="/seed-list" className="nav-item">种子列表</Link>
-//         <Link to="/publish-seed" className="nav-item">发布种子</Link>
-//       </nav>
-//       {/* 好友动态内容区域 */}
-//       <div className="content">
-//         {/* 用户动态示例,可从后端获取数据循环展示 */}
-//         <div className="user-post">
-//           <div className="user-info">
-//             <img src="user1-avatar.png" alt="用户头像" className="user-avatar-small" />
-//             <span className="username">user1</span>
-//           </div>
-//           <div className="post-content">
-//             <p>动态内容...</p>
-//           </div>
-//           <div className="post-actions">
-//             {/* <GoodTwo theme="outline" size="24" fill="#fff" /> */}
-//             <span className="like-count">21</span>
-//             {/* <Comment theme="outline" size="24" fill="#fff"/> */}
-//             <span className="comment-count">2</span>
-//           </div>
-//           <img src="image1.png" alt="动态图片" className="post-image" />
-//         </div>
-//       </div>
-//     </div>
-//   );
-// };
+const API_BASE = process.env.REACT_APP_API_BASE;
+const USER_ID = 456;
 
-// export default FriendMoments;
\ No newline at end of file
+const FriendMoments = () => {
+  const [feeds, setFeeds] = useState([]);
+  const [filteredFeeds, setFilteredFeeds] = useState([]);
+  const [query, setQuery] = useState('');
+
+  // Modal state & form fields
+  const [showModal, setShowModal] = useState(false);
+  const [title, setTitle] = useState('');
+  const [content, setContent] = useState('');
+  const [previewUrls, setPreviewUrls] = useState([]);
+  const [images, setImages] = useState([]);
+
+  // 拉取好友动态列表
+  const fetchFeeds = async () => {
+    try {
+      const res = await axios.get(`${API_BASE}/echo/users/${USER_ID}/feeds`);
+      setFeeds(res.data.feeds);
+      setFilteredFeeds(res.data.feeds);
+    } catch (err) {
+      console.error('获取动态列表失败:', err);
+    }
+  };
+
+  useEffect(() => {
+    fetchFeeds();
+  }, []);
+
+  // 搜索处理
+  const handleSearch = () => {
+    const q = query.trim().toLowerCase();
+    if (!q) return;
+    setFilteredFeeds(
+      feeds.filter(f => (f.title || '').toLowerCase().includes(q))
+    );
+  };
+  const handleReset = () => {
+    setQuery('');
+    setFilteredFeeds(feeds);
+  };
+
+  // 对话框内:本地预览 & 上传
+  const handleImageChange = async (e) => {
+    const files = Array.from(e.target.files);
+    if (!files.length) return;
+    setPreviewUrls(files.map(f => URL.createObjectURL(f)));
+    try {
+      const uploaded = await Promise.all(files.map(f => uploadImageToServer(f)));
+      setImages(uploaded);
+    } catch (err) {
+      console.error('图片上传失败', err);
+      alert('图片上传失败,请重试');
+    }
+  };
+  const uploadImageToServer = async (file) => {
+    const fd = new FormData();
+    fd.append('file', file);
+    const res = await axios.post(`${API_BASE}/upload`, fd, {
+      headers: {'Content-Type':'multipart/form-data'}
+    });
+    return res.data.url;
+  };
+
+  // 对话框内:提交新动态
+  const handleSubmit = async () => {
+    if (!content.trim()) {
+      alert('内容不能为空');
+      return;
+    }
+    try {
+      await axios.post(
+        `${API_BASE}/echo/users/${USER_ID}/createFeed`,
+        { title: title.trim() || undefined, friend_content: content.trim(), images }
+      );
+      // 重置表单
+      setTitle('');
+      setContent('');
+      setImages([]);
+      setPreviewUrls([]);
+      setShowModal(false);
+      fetchFeeds();
+    } catch (err) {
+      console.error('发布失败', err);
+      alert('发布失败,请稍后重试');
+    }
+  };
+
+  // 删除动态
+  const handleDelete = async (feedId) => {
+    if (!window.confirm('确定要删除这条动态吗?')) return;
+    try {
+      await axios.delete(`${API_BASE}/echo/users/me/feed/${feedId}`);
+      fetchFeeds();
+    } catch (err) {
+      console.error('删除失败', err);
+      alert('删除失败');
+    }
+  };
+
+  return (
+    <div className="friend-moments-container">
+      <Header />
+      <div className="fm-header">
+        <button className="create-btn" onClick={() => setShowModal(true)}>
+          <Edit theme="outline" size="18" style={{ marginRight: '6px' }} />
+          创建动态
+        </button>
+        <div className="f-search-bar">
+          <input
+            className="search-input"
+            type="text"
+            value={query}
+            onChange={e => setQuery(e.target.value)}
+            placeholder="输入要搜索的动态"
+          />
+          <button className="search-btn" onClick={handleSearch}>搜索</button>
+          <button className="search-btn" onClick={handleReset}>重置</button>
+        </div>
+      </div>
+
+      <div className="feed-list">
+        {filteredFeeds.map(feed => (
+          <div className="feed-item" key={feed.feed_id}>
+            {feed.title && <h4>{feed.title}</h4>}
+            <p>{feed.friend_content}</p>
+
+            {feed.images?.length > 0 && (
+              <div className="feed-images">
+                {feed.images.map((url, i) => (
+                  <img key={i} src={url} alt={`动态图${i}`} />
+                ))}
+              </div>
+            )}
+
+            <div className="feed-footer">
+              <span className="feed-date">
+                {new Date(feed.created_at).toLocaleString()}
+              </span>
+              {feed.is_mine && (
+                <button className="delete-btn" onClick={() => handleDelete(feed.feed_id)}>
+                  删除
+                </button>
+              )}
+            </div>
+          </div>
+        ))}
+      </div>
+
+      {/* Modal 对话框 */}
+      {showModal && (
+        <div className="modal-overlay" onClick={() => setShowModal(false)}>
+          <div className="modal-dialog" onClick={e => e.stopPropagation()}>
+            <h3>发布新动态</h3>
+            <input
+              type="text"
+              placeholder="标题"
+              value={title}
+              onChange={e => setTitle(e.target.value)}
+            />
+            <textarea
+              placeholder="写下你的内容..."
+              value={content}
+              onChange={e => setContent(e.target.value)}
+            />
+            {/* <input
+              type="file"
+              accept="image/*"
+              multiple
+              onChange={handleImageChange}
+            /> */}
+            <label className="file-label">
+              选择图片
+              <input
+                type="file"
+                accept="image/*"
+                multiple
+                onChange={handleImageChange}
+                style={{ display: 'none' }}
+              />
+            </label>
+            <div className="cf-preview">
+              {previewUrls.map((url, i) => (
+                <img key={i} src={url} alt={`预览${i}`} />
+              ))}
+            </div>
+            <div className="modal-actions">
+              <button className="btn cancel" onClick={() => setShowModal(false)}>
+                取消
+              </button>
+              <button className="btn submit" onClick={handleSubmit}>
+                发布
+              </button>
+            </div>
+          </div>
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default FriendMoments;
+