9544981b868e010ebdac17446f4a8dc4dfc241a7..e04d6a8904fd0c93b931551d8feea0943bae8eac
2025-06-12 cloudroam
add: 评论回复
e04d6a 对比 | 目录
2025-06-12 cloudroam
update: 点赞事件、收藏事件
b0bfc1 对比 | 目录
已修改6个文件
303 ■■■■ 文件已修改
components/card/flow-card.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/comment/comment-item.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/comment/comment-popup.vue 74 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/comment/comment-sub-item.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sub-pages/film-list/film-detail.vue 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/card/flow-card.vue
@@ -17,7 +17,7 @@
            </view>
            <view class="opera-info">
                <up-icon name="heart" size="30rpx" color="#999" />
                <text>{{ item.likeCount }}</text>
                <text>{{ item.voLikeCount }}</text>
            </view>
        </view>
    </view>
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>
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 () => {
  
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>
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>
@@ -72,9 +89,31 @@
                    <view class="comment-input" @click="showCommentLayer">
                        <up-text size="12px" text="说点什么......" margin="0 0 0 20rpx" color="#B9B9B9" />
                    </view>
                    <up-icon name="heart" size="60rpx" color="#B9B9B9" label="11" />
                    <up-icon name="star" size="60rpx" color="#B9B9B9" label="22" />
                    <up-icon name="chat" size="60rpx" color="#B9B9B9" label="33" />
<!--                    <up-icon name="heart" size="60rpx" color="#B9B9B9" label="11" />-->
<!--                    <up-icon name="star" size="60rpx" color="#B9B9B9" label="22" />-->
                        <up-icon
                            name="heart"
                            size="60rpx"
                            :color="liked ? '#FF0000' : '#B9B9B9'"
                            :label="filmInfo?.voLikeCount || 0"
                            @click="toggleLike"
                        />
                        <up-icon
                            name="star"
                            size="60rpx"
                            :color="collected ? '#FFD700' : '#B9B9B9'"
                            :label="filmInfo?.voCollectCount || 0"
                            @click="toggleFavorite"
                        />
                        <up-icon
                            name="chat"
                            size="60rpx"
                            color="#B9B9B9"
                            :label="filmInfo?.voCommentCount || 0"
                            @click="showCommentLayer"
                        />
                    <!-- <up-icon name="chat" size="60rpx" color="#B9B9B9" label="33" /> -->
                </view>
            </view>
        </view>
@@ -109,6 +148,9 @@
    username: '图墙精选',
    avatar: 'https://img.yzcdn.cn/vant/cat.jpeg'
})
const liked = ref(false)      // 是否已点赞
const collected = ref(false)  // 是否已收藏
onLoad((options: any) => {
@@ -164,20 +206,74 @@
    })
}
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>()
@@ -193,6 +289,10 @@
    if (code == 0) {
        filmInfo.value = data
        console.log("详情", filmInfo.value)
      // 设置初始状态
       console.log("filmInfo.value.isLiked",  data.liked)
        liked.value =data.liked || false
        collected.value = data.collected || false
        if (data && data.filmPictures) {
            // 只获取里面的url
            // filmPictureList.value=JSON.parse(data.filmPictures) as Array<FilmPicture>
@@ -214,6 +314,56 @@
        return null;
    }
}
const toggleLike = async () => {
  console.log("toggleLike",filmInfo.value)
  if (!filmInfo.value) return
  const api = liked.value ? '/v2/film-likes/filmLikes/edit' : '/v2/film-likes/filmLikes/edit'
  try {
    const res = await $http.request('post', api, {
      data: { filmId: filmInfo.value.id }
    })
    if (res.code === 0) {
      // 更新本地状态
      liked.value = !liked.value
      filmInfo.value.voLikeCount += liked.value ? 1 : -1
      // 提示信息
      $message.showToast(liked.value ? '点赞成功' : '取消点赞')
    }
  } catch (error) {
    console.error('点赞失败:', error)
    $message.showToast('操作失败')
  }
}
const toggleFavorite = async () => {
  console.log("toggleFavorite",filmInfo.value)
  if (!filmInfo.value) return
  const api = collected.value ? '/v2/film-collects/filmCollects/edit' : '/v2/film-collects/filmCollects/edit'
  try {
    const res = await $http.request('post', api, {
      data: { filmId: filmInfo.value.id }
    })
    if (res.code === 0) {
      // 更新本地状态
      collected.value = !collected.value
      filmInfo.value.voCollectCount += collected.value ? 1 : -1
      // 提示信息
      $message.showToast(collected.value ? '收藏成功' : '取消收藏')
    }
  } catch (error) {
    console.error('收藏失败:', error)
    $message.showToast('操作失败')
  }
}
</script>
types/index.ts
@@ -228,6 +228,11 @@
    createBy: string;
    createTime: string;
    updateBy: string | null;
    liked: boolean;
    collected: boolean;
    voLikeCount: number;
    voCollectCount: number;
    voCommentCount: number;
}