| | |
| | | <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> |