zdtap-uniapp-main/pagesMy/myWineReview.vue

473 lines
9.6 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- 排序选项 -->
<view class="sort-options">
<view
class="sort-item"
:class="{ active: sortType === 'time' }"
@tap="changeSortType('time')"
>
<text class="cuIcon-time"></text>
<text>最新酒评</text>
</view>
<view
class="sort-item"
:class="{ active: sortType === 'score' }"
@tap="changeSortType('score')"
>
<text class="cuIcon-favorfill"></text>
<text>评分排序</text>
</view>
</view>
<!-- 评价列表 -->
<scroll-view
v-if="myReviewList.length > 0"
class="review-list"
scroll-y="true"
@scrolltolower="changePage"
>
<view class="review-item" v-for="(item, index) in myReviewList" :key="index">
<!-- 酒款信息头部 -->
<view class="review-header">
<view class="beer-info">
<view class="beer-meta">
<text class="beer-name">{{item.beerName || '未知酒款'}}</text>
<view class="rating-row">
<uni-rate
:value="item.overallRating"
:readonly="true"
:size="16"
:touchable="false"
color="#ECECEC"
active-color="#FEE034"
/>
<text class="score-text">{{item.overallRating.toFixed(1)}}</text>
<view class="like-count">
<image src="/static/like.png" class="like-icon"></image>
<text class="count-text">{{item.reviewLike || 0}}</text>
</view>
</view>
</view>
</view>
<view class="review-meta">
<text class="review-time">{{item.createTime.slice(0,10)}}</text>
<view class="review-tag">我的评价</view>
</view>
</view>
<!-- 评论内容区域 -->
<view class="review-content">
<!-- 评论文本 -->
<view class="review-text">{{item.reviewContent}}</view>
<!-- 底部区域图片和删除按钮 -->
<view class="bottom-section">
<!-- 评论图片区域 -->
<scroll-view v-if="item.reviewImg" class="image-scroll" scroll-x="true">
<view class="image-container">
<image
v-for="(img, imgIndex) in item.reviewImg.split(',')"
:key="imgIndex"
:src="img"
class="review-image"
mode="aspectFill"
@tap="previewImage(item.reviewImg.split(','), imgIndex)"
></image>
</view>
</scroll-view>
<!-- 操作区域 -->
<view class="action-section">
<!-- 删除按钮 -->
<view class="action-btn delete-btn" @click="delReview(item)">
<text class="cuIcon-delete"></text>
<text>删除</text>
</view>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" v-if="myReviewList.length < total">
<text class="load-text">加载更多...</text>
</view>
</scroll-view>
<!-- 空状态 -->
<view v-else class="empty-state">
<text class="cuIcon-info"></text>
<text class="empty-text">暂无评价</text>
</view>
</view>
</template>
<script>
import {
listMyReview,
delReview
} from '@/api/user.js'
export default {
data() {
return {
myReviewList: [],
total: 0,
queryForm: {
pageNum: 1,
pageSize: 10,
sortType: 'time' // 添加排序类型参数
},
sortType: 'time'
}
},
onLoad() {
this.getMyReviewList()
},
methods: {
// 获取酒评列表
getMyReviewList() {
listMyReview(this.queryForm).then(res => {
this.total = res.total
if(res.rows && res.rows.length > 0) {
res.rows.forEach(item => {
this.myReviewList.push(item)
})
}
})
},
// 删除酒评
delReview(item) {
uni.showModal({
title: '提示',
content: '确定删除该评论吗?',
success: (res) => {
if (res.confirm) {
delReview(item.id).then(res => {
this.queryForm.pageNum = 1
this.myReviewList = []
this.getMyReviewList()
uni.showToast({
title: '删除成功',
icon: 'success'
})
})
}
}
})
},
// 加载更多
changePage() {
if(this.myReviewList.length < this.total) {
this.queryForm.pageNum++
this.getMyReviewList()
}
},
// 预览图片
previewImage(urls, current) {
uni.previewImage({
urls: urls,
current: urls[current]
})
},
// 切换排序方式
changeSortType(type) {
if (this.sortType === type) return
this.sortType = type
this.queryForm.sortType = type
this.queryForm.pageNum = 1
this.myReviewList = []
this.getMyReviewList()
}
}
}
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #F7F7F7;
padding-bottom: 32rpx;
.sort-options {
display: flex;
background: #FFFFFF;
padding: 24rpx 32rpx;
margin: 24rpx 32rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
border-radius: 16rpx;
position: sticky;
top: 0;
z-index: 10;
.sort-item {
margin-right: 48rpx;
padding: 12rpx 24rpx;
border-radius: 8rpx;
transition: all 0.3s ease;
display: flex;
align-items: center;
.cuIcon-time, .cuIcon-favorfill {
font-size: 28rpx;
margin-right: 8rpx;
}
text {
font-size: 28rpx;
color: #666666;
}
&.active {
background: rgba(25, 54, 122, 0.1);
text {
color: #19367A;
font-weight: 600;
}
.cuIcon-time, .cuIcon-favorfill {
color: #19367A;
}
}
&:active {
transform: scale(0.95);
}
}
}
.review-list {
height: calc(100vh - 180rpx);
padding: 0 32rpx;
}
.review-item {
background: #FFFFFF;
border-radius: 16rpx;
margin-bottom: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
position: relative;
overflow: hidden;
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.review-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding-bottom: 24rpx;
.beer-info {
flex: 1;
.beer-meta {
.beer-name {
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 12rpx;
display: block;
}
.rating-row {
display: flex;
align-items: center;
.score-text {
font-size: 24rpx;
color: #FFB800;
margin-left: 8rpx;
font-weight: 600;
}
.like-count {
display: flex;
align-items: center;
margin-left: 16rpx;
padding: 4rpx 12rpx;
background: rgba(25, 54, 122, 0.05);
border-radius: 20rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
background: rgba(25, 54, 122, 0.1);
}
.like-icon {
width: 24rpx;
height: 24rpx;
margin-right: 4rpx;
}
.count-text {
font-size: 22rpx;
color: #666666;
font-weight: 500;
}
}
}
}
}
.review-meta {
display: flex;
flex-direction: column;
align-items: flex-end;
.review-time {
font-size: 24rpx;
color: #999999;
margin-bottom: 8rpx;
}
.review-tag {
font-size: 20rpx;
color: #FFFFFF;
background: linear-gradient(to right, #19367A, #4A6FCC);
padding: 4rpx 12rpx;
border-radius: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(25, 54, 122, 0.2);
}
}
}
.review-content {
margin-bottom: 24rpx;
.review-text {
font-size: 28rpx;
color: #666666;
line-height: 1.6;
margin-bottom: 24rpx;
position: relative;
padding: 16rpx 24rpx;
word-break: break-all;
white-space: pre-wrap;
overflow-wrap: break-word;
background: rgba(25, 54, 122, 0.02);
border-radius: 12rpx;
box-shadow: inset 0 2rpx 8rpx rgba(0, 0, 0, 0.02);
&::before {
content: '"';
position: absolute;
left: 16rpx;
top: -8rpx;
font-size: 40rpx;
color: rgba(25, 54, 122, 0.2);
font-family: serif;
}
}
.bottom-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
padding-top: 16rpx;
.image-scroll {
flex: 1;
width: 70%;
white-space: nowrap;
.image-container {
display: inline-flex;
.review-image {
width: 160rpx;
height: 160rpx;
border-radius: 12rpx;
margin-right: 16rpx;
object-fit: cover;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
}
&:last-child {
margin-right: 0;
}
}
}
}
.action-section {
display: flex;
align-items: center;
justify-content: flex-end;
width: 30%;
.action-btn {
display: flex;
align-items: center;
padding: 8rpx 16rpx;
border-radius: 8rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
text {
font-size: 24rpx;
}
&.delete-btn {
background: rgba(255, 77, 79, 0.1);
color: #FF4D4F;
box-shadow: 0 2rpx 8rpx rgba(255, 77, 79, 0.1);
.cuIcon-delete {
margin-right: 8rpx;
}
}
}
}
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.cuIcon-info {
font-size: 64rpx;
color: #CCCCCC;
margin-bottom: 24rpx;
}
.empty-text {
font-size: 28rpx;
color: #999999;
}
}
.load-more {
text-align: center;
padding: 24rpx 0;
.load-text {
font-size: 24rpx;
color: #999999;
}
}
}
</style>