<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>
|
<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>
|
</view>
|
</view>
|
|
<!-- 子评论区域 -->
|
<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 [];
|
}
|
|
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 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;
|
width: 100%;
|
|
.avatar {
|
margin-right: 10rpx;
|
}
|
|
.comment-content {
|
width: 92%;
|
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;
|
}
|
}
|
|
.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;
|
}
|
}
|
}
|
|
.comment-opeartor {
|
display: flex;
|
flex-direction: column;
|
align-items: flex-start;
|
|
.comment-opeartor-heart-number {
|
width: 100%;
|
text-align: center;
|
font-size: 20rpx;
|
}
|
}
|
}
|
}
|
|
.sub-comment {
|
margin-left: 60rpx;
|
margin-top: 10rpx;
|
}
|
}
|
</style>
|