cloudroam
2025-06-12 b0bfc153bf3c9aa430ee6a86588648cdd1c27132
components/comment/comment-item.vue
@@ -1,161 +1,174 @@
<template>
    <view class="comment-item">
      <view class="comment-item-header">
        <view class="comment-item-header-left">
          <view class="avatar">
            <up-avatar :src="avatar" size="50rpx" shape="circle" />
  <view class="comment-item">
    <view class="comment-item-header">
      <view class="comment-item-header-left">
        <view class="avatar">
          <up-avatar :src="avatar" size="50rpx" shape="circle" />
        </view>
        <view class="comment-content">
          <view class="author">
            <text class="nickname">{{ nickname }}</text>
            <view v-if="isAuthor" class="author-flag">作者</view>
          </view>
          <view class="comment-content">
            <view class="author">
              <text class="nickname">{{ nickname }}</text>
              <view v-if="isAuthor" class="author-flag">作者</view>
            </view>
            <view class="comment-content-text">
              <text>{{ content }}</text>
              <up-album :urls="images" multipleSize="180rpx" singleSize="500rpx" />
              <text class="date">{{ date }}</text>
              <text class="address">{{ address }}</text>
              <text class="reply" @click="onReply">回复</text>
            </view>
          </view>
          <view class="comment-opeartor">
            <up-icon name="heart" size="30rpx" />
            <view class="comment-opeartor-heart-number">{{ likes }}</view>
          <view class="comment-content-text">
            <text>{{ content }}</text>
            <up-album :urls="images" multipleSize="180rpx" singleSize="500rpx" />
            <text class="date">{{ date }}</text>
            <text class="address">{{ address }}</text>
            <text class="reply" @click="onReply">回复</text>
          </view>
        </view>
      </view>
      <!-- 子评论区域 -->
      <view class="sub-comment">
        <comment-sub-item
          avatar="https://img.yzcdn.cn/vant/cat.jpeg"
          nickname="图墙精选"
          :isAuthor="true"
          content="如果路线里全是常规景区,没一个特殊的点位..."
          :images="urls2"
          date="2天前"
          address="湖北"
          :likes="30"
          @reply="emitReply"
        />
        <view class="comment-opeartor">
          <up-icon name="heart" size="30rpx" />
          <view class="comment-opeartor-heart-number">{{ likes }}</view>
        </view>
      </view>
    </view>
  </template>
  <script setup lang="ts">
    import { ref, onMounted } from 'vue'
  interface Props {
    avatar: string
    nickname: string
    isAuthor: boolean
    content: string
    images: string[]
    date: string
    address: string
    likes: number
    <!-- 子评论区域 -->
    <view class="sub-comment">
      <comment-sub-item
        v-for="(item, index) in child"
        :avatar="item.picture"
        :nickname="item.commentUserName"
        :isAuthor="item.createBy === filmInfo.createBy"
        :content="item.content"
        :images="getImageList(item)"
        :date="item.createTime"
        address="湖北"
         :likes="item.likeCount"
        @reply="emitReply"
        :filmInfo="filmInfo"
        />
    </view>
  </view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { CommentDTO } from '@/types/index'
interface Props {
  avatar: string
  nickname: string
  isAuthor: boolean
  content: string
  images: string[]
  date: string
  address: string
  likes: number
  child: CommentDTO[]
  filmInfo: CommentDTO
}
const props = defineProps<Props>()
const emit = defineEmits<{
  (e: 'reply'): void
}>()
const getImageList = (item: any): string[] => {
  if (!item || !item.filmPictures || typeof item.filmPictures !== 'string') {
    return [];
  }
  const props = defineProps<Props>()
  const emit = defineEmits<{
    (e: 'reply'): void
  }>()
  const urls2 = ref<string[]>([
    'https://img.yzcdn.cn/vant/cat.jpeg',
    'https://img.yzcdn.cn/vant/cat.jpeg',
    'https://img.yzcdn.cn/vant/cat.jpeg',
    'https://img.yzcdn.cn/vant/cat.jpeg',
    'https://img.yzcdn.cn/vant/cat.jpeg'
  ])
  const onReply = () => {
    emit('reply')
  try {
    const pictures = JSON.parse(item.filmPictures);
    return Array.isArray(pictures) ? pictures.map((p: any) => p.url) : [];
  } catch (e) {
    console.error('filmPictures JSON parse error:', e, item.filmPictures);
    return [];
  }
  const emitReply = () => {
    emit('reply')
  }
  </script>
  <style lang="scss" scoped>
  .comment-item {
    .comment-item-header {
};
const onReply = () => {
  emit('reply')
}
const emitReply = () => {
  emit('reply')
}
</script>
<style lang="scss" scoped>
.comment-item {
  .comment-item-header {
    display: flex;
    align-items: center;
    .comment-item-header-left {
      display: flex;
      align-items: center;
      .comment-item-header-left {
      width: 100%;
      .avatar {
        margin-right: 10rpx;
      }
      .comment-content {
        width: 92%;
        display: flex;
        width: 100%;
        .avatar {
          margin-right: 10rpx;
        }
        .comment-content {
          width: 92%;
        flex-direction: column;
        .author {
          display: flex;
          flex-direction: column;
          .author {
            display: flex;
            align-items: center;
            .nickname {
              font-size: 30rpx;
              color: #858585;
            }
            .author-flag {
              font-size: 18rpx;
              color: #ff4d4f;
              font-weight: bold;
              border-radius: 50rpx;
              padding: 5rpx 10rpx;
              background-color: rgba(219, 19, 22, 0.219);
              margin-left: 10rpx;
              height: 25rpx;
            }
          align-items: center;
          .nickname {
            font-size: 30rpx;
            color: #858585;
          }
          .comment-content-text {
            margin-top: 10rpx;
            font-size: 26rpx;
            letter-spacing: 1rpx;
            line-height: 1.5;
            .date,
            .address {
              font-size: 20rpx;
              padding: 10rpx;
              color: #858585;
            }
            .reply {
              font-size: 24rpx;
              padding: 10rpx;
              color: #2979ff;
            }
          .author-flag {
            font-size: 18rpx;
            color: #ff4d4f;
            font-weight: bold;
            border-radius: 50rpx;
            padding: 5rpx 10rpx;
            background-color: rgba(219, 19, 22, 0.219);
            margin-left: 10rpx;
            height: 25rpx;
          }
        }
        .comment-opeartor {
          display: flex;
          flex-direction: column;
          align-items: flex-start;
          .comment-opeartor-heart-number {
            text-align: center;
        .comment-content-text {
          margin-top: 10rpx;
          font-size: 26rpx;
          letter-spacing: 1rpx;
          line-height: 1.5;
          .date,
          .address {
            font-size: 20rpx;
            padding: 10rpx;
            color: #858585;
          }
          .reply {
            font-size: 24rpx;
            padding: 10rpx;
            color: #2979ff;
          }
        }
      }
    }
    .sub-comment {
      margin-left: 60rpx;
      margin-top: 10rpx;
      .comment-opeartor {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        .comment-opeartor-heart-number {
          width: 100%;
          text-align: center;
          font-size: 20rpx;
        }
      }
    }
  }
  </style>
  .sub-comment {
    margin-left: 60rpx;
    margin-top: 10rpx;
  }
}
</style>