合并

Change-Id: I19ca58c58a513cba20c162c9ed7cbab90e060bf6
diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx
index 97a01cc..836daa7 100644
--- a/src/components/Dashboard.jsx
+++ b/src/components/Dashboard.jsx
@@ -3,7 +3,7 @@
 // import { getUserInfo } from '../api/auth';  

 import {createTorrent, getTorrents} from '../api/torrent';

 import './Dashboard.css';

-import {createPost, getPosts} from '../api/helpPost';

+import {createPost, getPosts, getPostDetail} from '../api/helpPost';

 

 

 const Dashboard = ({onLogout}) => {

@@ -34,6 +34,8 @@
     const [helpError, setHelpError] = useState(null);

     const [currentPage, setCurrentPage] = useState(1);

     const [totalPages, setTotalPages] = useState(1);

+    const [likedPosts,setLikedPosts] = useState({});

+

 

     // 添加状态

     const [torrentPosts, setTorrentPosts] = useState([]);

@@ -179,28 +181,29 @@
     const handlePostSubmit = async (e) => {

         e.preventDefault();

         try {

-            const username = localStorage.getItem('username');

-            const response = await createPost(

-                postTitle,

-                postContent,

-                username

-            );

-

-            if (response.data.code === 200) {

-                // 刷新帖子列表

-                await fetchHelpPosts();

-                // 重置表单

-                setShowPostModal(false);

-                setPostTitle('');

-                setPostContent('');

-                setSelectedImage(null);

-            } else {

-                setHelpError(response.data.message || '发帖失败');

-            }

+          const username = localStorage.getItem('username');

+          const response = await createPost(

+            postTitle,

+            postContent,

+            username,

+            selectedImage

+          );

+          

+          if (response.data.code === 200) {

+            // 刷新帖子列表

+            await fetchHelpPosts(currentPage);

+            // 重置表单

+            setShowPostModal(false);

+            setPostTitle('');

+            setPostContent('');

+            setSelectedImage(null);

+          } else {

+            setHelpError(response.data.message || '发帖失败');

+          }

         } catch (err) {

-            setHelpError(err.message || '发帖失败');

+          setHelpError(err.message || '发帖失败');

         }

-    };

+      };

 

     // 获取Torrent帖子列表

     const fetchTorrentPosts = async (page = 1) => {

@@ -232,20 +235,40 @@
     const fetchHelpPosts = async (page = 1) => {

         setHelpLoading(true);

         try {

-            const response = await getPosts(page);

-            if (response.data.code === 200) {

-                setHelpPosts(response.data.data.records);

-                setTotalPages(Math.ceil(response.data.data.total / 5)); // 假设每页5条

-                setCurrentPage(page);

-            } else {

-                setHelpError(response.data.message || '获取求助帖失败');

-            }

+          const response = await getPosts(page);

+          if (response.data.code === 200) {

+            const postsWithCounts = await Promise.all(

+              response.data.data.records.map(async (post) => {

+                try {

+                  const detailResponse = await getPostDetail(post.id);

+                  if (detailResponse.data.code === 200) {

+                    return {

+                      ...post,

+                      replyCount: detailResponse.data.data.post.replyCount || 0,

+                      isLiked: false // 根据需要添加其他字段

+                    };

+                  }

+                  return post; // 如果获取详情失败,返回原始帖子数据

+                } catch (err) {

+                  console.error(`获取帖子${post.id}详情失败:`, err);

+                  return post;

+                }

+              })

+            );

+            setHelpPosts(postsWithCounts);

+            setTotalPages(Math.ceil(response.data.data.total / 5)); // 假设每页5条

+            setCurrentPage(page);

+          } else {

+            setHelpError(response.data.message || '获取求助帖失败');

+          }

         } catch (err) {

-            setHelpError(err.message || '获取求助帖失败');

+          setHelpError(err.message || '获取求助帖失败');

         } finally {

-            setHelpLoading(false);

+          setHelpLoading(false);

         }

-    };

+      };

+

+

     useEffect(() => {

         if (activeTab === 'help') {

             fetchHelpPosts(currentPage);

diff --git a/src/components/HelpDetail.jsx b/src/components/HelpDetail.jsx
index da50850..7e7b7c8 100644
--- a/src/components/HelpDetail.jsx
+++ b/src/components/HelpDetail.jsx
@@ -3,12 +3,14 @@
 import { 

   getPostDetail,

   addPostComment,

-  likePost

+  likePost,

+  deletePost

 } from '../api/helpPost';

 import {

   likePostComment,

   getCommentReplies,

-  addCommentReply

+  addCommentReply,

+  deleteComment

 } from '../api/helpComment';

 import './HelpDetail.css';

 

@@ -22,12 +24,13 @@
   const [loading, setLoading] = useState(true);

   const [error, setError] = useState(null);

   const [newComment, setNewComment] = useState('');

-  const [newReply, setNewReply] = useState({});

-  const [images, setImages] = useState([]);

+  const [replyContent, setReplyContent] = useState('');

+  const [replyImage, setReplyImage] = useState([]);

+  const [commentImage, setCommentImage] = useState([]);

   const [expandedReplies, setExpandedReplies] = useState({}); // 记录哪些评论的回复是展开的

   const [loadingReplies, setLoadingReplies] = useState({});

   const [setReplyingTo] = useState(null);

-  const [replyContent, setReplyContent] = useState('');

+  

 

   const [activeReplyId, setActiveReplyId] = useState(null);

     const [replyModal, setReplyModal] = useState({

@@ -58,7 +61,7 @@
       setReplyContent('');

     };

 

-    const Comment = ({ comment, onLike, onReply, isReply = false }) => {

+    const Comment = ({ comment, onLike, onReply, onDelete, isReply = false }) => {

       return (

         <div className={`comment-container ${isReply ? "is-reply" : ""}`}>

           <div className="comment-item">

@@ -76,6 +79,17 @@
                 </span>

               </div>

               <p className="comment-text">{comment.content}</p>

+              {/* 添加评论图片展示 */}

+              {comment.imageUrl && (

+                <div className="comment-image-container">

+                  <img 

+                    src={`http://localhost:8088${comment.imageUrl}`} 

+                    alt="评论图片" 

+                    className="comment-image"

+                    onClick={() => window.open(comment.imageUrl, '_blank')}

+                  />

+                </div>

+              )}

               <div className="comment-actions">

                 <button onClick={() => onLike(comment.id)}>

                   👍 ({comment.likeCount || 0})

@@ -83,6 +97,14 @@
                 <button onClick={() => onReply(comment.id, comment.authorId)}>

                   回复

                 </button>

+                {comment.authorId === localStorage.getItem('username') && (

+                  <button 

+                    className="delete-comment-btn"

+                    onClick={() => onDelete(comment.id)}

+                  >

+                    删除

+                  </button>

+                )}

               </div>

             </div>

           </div>

@@ -99,6 +121,7 @@
           onLike={handleLikeComment}

           onReply={openReplyModal}

           isReply={depth > 0}

+          onDelete={handleDeleteComment}

         />

         

         {/* 递归渲染所有回复 */}

@@ -140,6 +163,19 @@
         setError('点赞失败: ' + (err.response?.data?.message || err.message));

       }

     };

+

+     // 添加删除处理函数

+     const handleDeletePost = async (postId) => {

+      if (window.confirm('确定要删除这个帖子吗?所有评论也将被删除!')) {

+        try {

+          const username = localStorage.getItem('username');

+          await deletePost(postId, username);

+          navigate('/dashboard/help'); // 删除成功后返回求助区

+        } catch (err) {

+          setError('删除失败: ' + (err.response?.data?.message || err.message));

+        }

+      }

+    };

   

     const handleCommentSubmit = async (e) => {

       e.preventDefault();

@@ -196,6 +232,18 @@
       }

     };

 

+    const handleDeleteComment = async (commentId) => {

+      if (window.confirm('确定要删除这条评论吗?')) {

+        try {

+          const username = localStorage.getItem('username');

+          await deleteComment(commentId, username);

+          await fetchPostDetail(); // 刷新评论列表

+        } catch (err) {

+          setError('删除失败: ' + (err.response?.data?.message || err.message));

+        }

+      }

+    };

+

 

     // 修改startReply函数

     const startReply = (commentId) => {

@@ -217,15 +265,16 @@
       try {

         const username = localStorage.getItem('username');

         const response = await addCommentReply(replyModal.replyingTo, {

+          authorId: username,

           content: replyContent,

-          authorId: username

+          image: replyImage

         });

     

         console.log('回复响应:', response.data); // 调试

         

         if (response.data && response.data.code === 200) {

           await fetchPostDetail();

-    

+          setReplyContent('');

           closeReplyModal();

         }

       } catch (err) {

@@ -251,15 +300,15 @@
     }));

   };

 

-  const handleImageUpload = (e) => {

-    const files = Array.from(e.target.files);

-    const newImages = files.map(file => URL.createObjectURL(file));

-    setImages(prev => [...prev, ...newImages]);

-  };

+  // const handleImageUpload = (e) => {

+  //   const files = Array.from(e.target.files);

+  //   const newImages = files.map(file => URL.createObjectURL(file));

+  //   setImages(prev => [...prev, ...newImages]);

+  // };

 

-  const handleRemoveImage = (index) => {

-    setImages(prev => prev.filter((_, i) => i !== index));

-  };

+  // const handleRemoveImage = (index) => {

+  //   setImages(prev => prev.filter((_, i) => i !== index));

+  // };

 

   

 

@@ -284,9 +333,19 @@
             <div className="post-author">{post.authorId}</div>

             <div className="post-date">

               {new Date(post.createTime).toLocaleString()}

-            </div>

+              </div>

           </div>

-          {post.isSolved && <span className="solved-badge">已解决</span>}

+          {post.isSolved && <span ClassName="solved-badge">已解决</span>}

+          <div classname="delete-post">

+            {post.authorId === localStorage.getItem('username') && (

+              <button 

+                className="delete-button"

+                onClick={() => handleDeletePost(post.id)}

+              >

+                删除帖子

+              </button>

+            )}

+          </div>

         </div>

         

         <h1 className="post-title">{post.title}</h1>

@@ -295,6 +354,21 @@
           {post.content.split('\n').map((para, i) => (

             <p key={i}>{para}</p>

           ))}

+          {/* 添加帖子图片展示 */}

+          {post.imageUrl && (

+            <div className="post-image-container">

+              <img 

+                src={`http://localhost:8088${post.imageUrl}`} 

+                alt="帖子图片" 

+                className="post-image"

+                // onError={(e) => {

+                //   e.target.onerror = null; 

+                //   e.target.src = 'https://via.placeholder.com/400x300?text=图片加载失败';

+                //   console.error('图片加载失败:', post.imageUrl);

+                // }}

+              />

+            </div>

+          )}

         </div>

         

         <div className="post-actions">

@@ -325,8 +399,21 @@
             required

           />

           <button type="submit">发表评论</button>

+

+          {/* 图片上传部分 */}

+          <div className="form-group">

+            <div className="upload-image-btn">

+              <input 

+                type="file" 

+                accept="image/*" 

+                onChange={(e) => setCommentImage(e.target.files[0])} 

+                data-testid="comment-image-input"  

+              />

+            </div>

+          </div>

         </form>

         

+        

         <div className="comment-list">

           {comments.map(comment => renderComment(comment))}

         </div>

@@ -347,6 +434,18 @@
                   autoFocus

                   required

                 />

+

+                {/* 图片上传部分 */}

+                <div className="form-group">

+                  <div className="upload-image-btn">

+                    <input 

+                      type="file" 

+                      accept="image/*" 

+                      onChange={(e) => setReplyImage(e.target.files[0])} 

+                    />

+                  </div>

+                </div>

+

                 <div className="modal-actions">

                   <button type="button" onClick={closeReplyModal} className="cancel-btn">

                     取消