From e04d6a8904fd0c93b931551d8feea0943bae8eac Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期四, 12 六月 2025 18:11:06 +0800
Subject: [PATCH] add: 评论回复

---
 components/comment/comment-item.vue     |   34 ++++++--
 components/comment/comment-popup.vue    |   74 +++++++++++++----
 sub-pages/film-list/film-detail.vue     |   83 +++++++++++++++++++-
 components/comment/comment-sub-item.vue |   20 ++++
 4 files changed, 175 insertions(+), 36 deletions(-)

diff --git a/components/comment/comment-item.vue b/components/comment/comment-item.vue
index 5278054..5d18656 100644
--- a/components/comment/comment-item.vue
+++ b/components/comment/comment-item.vue
@@ -19,7 +19,12 @@
           </view>
         </view>
         <view class="comment-opeartor">
-          <up-icon name="heart" size="30rpx" />
+          <up-icon 
+            name="heart" 
+            size="30rpx" 
+            :color="isLiked ? '#FF0000' : '#B9B9B9'"
+             @click="handleLike(props.id)"
+          />
           <view class="comment-opeartor-heart-number">{{ likes }}</view>
         </view>
       </view>
@@ -29,6 +34,7 @@
     <view class="sub-comment">
       <comment-sub-item 
         v-for="(item, index) in child"
+        :key="index"
         :avatar="item.picture" 
         :nickname="item.commentUserName" 
         :isAuthor="item.createBy === filmInfo.createBy"
@@ -36,10 +42,13 @@
         :images="getImageList(item)" 
         :date="item.createTime" 
         address="湖北" 
-         :likes="item.likeCount"
-        @reply="emitReply" 
+        :likes="item.likeCount"
+        :isLiked="item.isLike"
+        :id="item.id"
+        @reply="handleSubReply" 
+        @like="handleLike"
         :filmInfo="filmInfo"
-        />
+      />
     </view>
   </view>
 </template>
@@ -58,12 +67,15 @@
   likes: number
   child: CommentDTO[]
   filmInfo: CommentDTO
+  isLiked: boolean
+  id: number
 }
 
 const props = defineProps<Props>()
 
 const emit = defineEmits<{
-  (e: 'reply'): void
+  (e: 'reply', id?: number): void
+  (e: 'like', id: number): void
 }>()
 
 
@@ -83,11 +95,17 @@
 
 
 const onReply = () => {
-  emit('reply')
+  emit('reply', props.id) // ✅ 传递父评论ID
 }
 
-const emitReply = () => {
-  emit('reply')
+const handleSubReply = (commentId: number) => {
+	console.log("commentId",commentId)
+  emit('reply', commentId)
+}
+
+const handleLike = (commentId: number) => {
+  console.log('handleLike', commentId)
+  emit('like', commentId)
 }
 </script>
 
diff --git a/components/comment/comment-popup.vue b/components/comment/comment-popup.vue
index 48fbdc3..a7eac02 100644
--- a/components/comment/comment-popup.vue
+++ b/components/comment/comment-popup.vue
@@ -169,29 +169,65 @@
   fileList.value.splice(index, 1);
 };
 
+// const sendComment = async () => {
+//   if (!canSend.value) return;
+
+//   try {
+//     const res = await $http.request('post', '/api/comment/create', {
+//       data: comment.value
+//     })
+    
+//     if (res.code == 0) {
+//       emit('success')
+//       emit('update:modelValue', false)
+      
+//       // 清除评论内容
+//       comment.value.content = ''
+//       fileList.value = []
+//       pictureList.value = []
+//     } else {
+//       $message.showToast('评论失败')
+//     }
+//   } catch (error) {
+//     console.error('评论失败:', error)
+//     $message.showToast('评论失败')
+//   }
+// }
 const sendComment = async () => {
   if (!canSend.value) return;
 
-  console.log("评论添加:", comment.value)
-  const {
-    code, data
-  } = await $http.request('post', '/api/comment/create', {
-    data: comment.value
-  })
-  if (code == 0) {
-    // 保存成功,返回评论?
-    console.log("评论新增成功")
-    emit('success'); // 告诉父组件刷新列表
-    emit('update:modelValue', false); // 关闭弹窗
-
-  } else {
-    $message.showToast('系统异常,无法获取当前微信是否已经绑定过账号')
+  try {
+    // 构建评论数据
+    const commentData = {
+      ...comment.value,
+      parentId: props.parentId || undefined, // 如果有parentId则使用,没有则为undefined
+      filmId: props.filmId,
+      content: comment.value.content,
+      fileList: comment.value.fileList,
+      filmPictures: comment.value.filmPictures
+    }
+	  console.log("commentData",commentData);
+    console.log("当前 parentId:", props.parentId); // 检查是否收到值
+    const res = await $http.request('post', '/api/comment/create', {
+      data: commentData
+    })
+    
+    if (res.code == 0) {
+      emit('success')
+      emit('update:modelValue', false)
+      
+      // 清除评论内容
+      comment.value.content = ''
+      fileList.value = []
+      pictureList.value = []
+    } else {
+      $message.showToast('评论失败')
+    }
+  } catch (error) {
+    console.error('评论失败:', error)
+    $message.showToast('评论失败')
   }
-
-  fileList.value = [];
-  // handleClose();
-};
-
+}
 
 const submitComment = async () => {
   
diff --git a/components/comment/comment-sub-item.vue b/components/comment/comment-sub-item.vue
index ded7a6b..e36c47d 100644
--- a/components/comment/comment-sub-item.vue
+++ b/components/comment/comment-sub-item.vue
@@ -19,7 +19,12 @@
           </view>
         </view>
         <view class="comment-opeartor">
-          <up-icon name="heart" size="30rpx" />
+          <up-icon
+              name="heart"
+              size="30rpx"
+              :color="isLiked ? '#FF0000' : '#B9B9B9'"
+              @click="() => handleLike(props.id)"
+          />
           <view class="comment-opeartor-heart-number">{{ likes }}</view>
         </view>
       </view>
@@ -39,14 +44,23 @@
   address: string
   likes: number
   filmInfo: CommentDTO
+  isLiked: boolean
+  id: number
 }>()
 
 const emit = defineEmits<{
-  (e: 'reply'): void
+  (e: 'reply', id: number): void
+  (e: 'like', id: number): void
 }>()
 
 const onReply = () => {
-  emit('reply')
+  console.log("onReply",props)
+  emit('reply', props.id)
+}
+
+const handleLike = (id: number) => {  // 添加参数
+  console.log("handleLike", id)
+  emit('like', id)
 }
 </script>
 
diff --git a/sub-pages/film-list/film-detail.vue b/sub-pages/film-list/film-detail.vue
index 441b44a..afeab9e 100644
--- a/sub-pages/film-list/film-detail.vue
+++ b/sub-pages/film-list/film-detail.vue
@@ -59,10 +59,27 @@
                     </view>
 
                     <!-- 示例评论项,comment-item 可替换为实际组件 -->
-                    <comment-item v-for="(item, index) in commentList" :avatar="item.picture"
-                        :nickname="item.commentUserName" :isAuthor="item.createBy === filmInfo.createBy"
-                        :content="item.content" :images="getImageList(item)" :date="item.createTime" address="湖北"
-                        :likes="item.likeCount" :child="item.child" :filmInfo="filmInfo" @reply="showCommentLayer" />
+<!--                    <comment-item v-for="(item, index) in commentList" :avatar="item.picture"-->
+<!--                        :nickname="item.commentUserName" :isAuthor="item.createBy === filmInfo.createBy"-->
+<!--                        :content="item.content" :images="getImageList(item)" :date="item.createTime" address="湖北"-->
+<!--                        :likes="item.likeCount" :child="item.child" :filmInfo="filmInfo" @reply="showCommentLayer" />-->
+                  <comment-item
+                      v-for="(item, index) in commentList"
+                      :avatar="item.picture"
+                      :nickname="item.commentUserName"
+                      :isAuthor="item.createBy === filmInfo.createBy"
+                      :content="item.content"
+                      :images="getImageList(item)"
+                      :date="item.createTime"
+                      address="湖北"
+                      :likes="item.likeCount"
+                      :isLiked="item.isLike"
+                      :id="item.id"
+                      :child="item.child"
+                      :filmInfo="filmInfo"
+                      @reply="(id) => showCommentLayer(id)"
+                      @like="handleCommentLike"
+                  />
                 </view>
             </scroll-view>
 
@@ -189,21 +206,75 @@
     })
 }
 
-const showCommentLayer = () => {
-    commentShow.value = true
+// film-detail.vue
+const showCommentLayer = (parentId?: number) => {
+  console.log('点击了评论按钮',parentId)
+  commentShow.value = true
+  // 如果有parentId,说明是回复评论,需要设置parentId
+  // 如果没有parentId,说明是直接评论,不需要设置parentId
+  commentParendId.value = parentId ? String(parentId) : ''
 }
 
 const handleCommentSuccess = (data) => {
     // 例如重新请求评论列表
     //   fetchCommentList();
+    // 重新获取评论列表
     getCommentList(filmId.value)
     commentShow.value = false
+    commentParendId.value = '' // 清除父评论ID
 };
 
 onShow(() => {
 
 });
 
+// 处理评论点赞
+const handleCommentLike = async (commentId: number) => {
+  console.log('点击了评论点赞', commentId)
+  try {
+    const res = await $http.request('post', '/v2/comment-likes/commentLikes/edit', {
+      data: { commentId }
+    })
+
+    if (res.code === 0) {
+      // 更新评论列表中的点赞状态和数量
+      const updateCommentLike = (comments: CommentDTO[]) => {
+        comments.forEach(comment => {
+          if (comment.id === commentId) {
+            comment.isLike = !comment.isLike
+            comment.likeCount += comment.isLike ? 1 : -1
+          }
+          if (comment.child && comment.child.length > 0) {
+            updateCommentLike(comment.child)
+          }
+        })
+      }
+
+      updateCommentLike(commentList.value)
+      // 根据当前点赞状态显示对应提示
+      const comment = findCommentById(commentList.value, commentId)
+      $message.showToast(comment?.isLike ? '点赞成功' : '取消点赞')
+    }
+  } catch (error) {
+    console.error('评论点赞失败:', error)
+    $message.showToast('操作失败')
+  }
+}
+
+// 添加一个辅助函数来查找评论
+const findCommentById = (comments: CommentDTO[], id: number): CommentDTO | undefined => {
+  for (const comment of comments) {
+    if (comment.id === id) {
+      return comment
+    }
+    if (comment.child && comment.child.length > 0) {
+      const found = findCommentById(comment.child, id)
+      if (found) return found
+    }
+  }
+  return undefined
+}
+
 const filmInfo = ref<FilmInfo>()
 
 const filmPictureList = ref<string[]>([])

--
Gitblit v1.9.3