670 lines
17 KiB
Vue
670 lines
17 KiB
Vue
<template>
|
|
<!-- 团购评论 -->
|
|
<view class="whole">
|
|
<view class="tabBox">
|
|
<view class="Tit">
|
|
<view class="row" @click="changeTab(0)"><view class="tit" :class="tabIndex == 0 ? 'on' : ''">全部</view><text>({{total}})</text></view>
|
|
<view class="row" v-for="it in tabList" :key="it.id" @click="changeTab(it.id)">
|
|
<view class="tit" :class="tabIndex == it.id ? 'on' : ''">{{it.name}}</view><text>({{it.count}})</text>
|
|
</view>
|
|
</view>
|
|
<view class="filter">
|
|
<view class="icon" @click="showFilter = !showFilter">
|
|
<text class="iconfont icon-paixu"></text>
|
|
</view>
|
|
<view class="box" v-if="showFilter">
|
|
<view class="row" v-for="it in sortList" :key="it.id" @click="toFilter(it.id)" :class="sort == it.id ? 'on' : ''">{{it.name}}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<scroll-view scroll-y="true" @scrolltolower="scorllBottom" style="height: calc(100vh - 90rpx);" lower-threshold="200">
|
|
|
|
<view class="contBox">
|
|
<view class="oneBox">
|
|
<view class="cont">
|
|
<view class="top">
|
|
<view class="rateBox">
|
|
<view class="rate">{{goodCommentRate}}</view>
|
|
<text>好评率</text>
|
|
</view>
|
|
<view class="star">
|
|
<up-rate v-model="rateValue" :count="5" allowHalf readonly :size="25" activeColor="#ffd21e" inactiveColor="#eee" />
|
|
</view>
|
|
</view>
|
|
<view class="topBox">
|
|
<view class="row" v-for="item in tagsList" :key="item.id" :class="tagIndex === item.id ? 'active' : ''" @click="changeTag(item.id)">{{item.name}} <text>{{item.count}}</text></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="listBox">
|
|
<view class="item" v-for="(item, index) in infoList" :key="item.id">
|
|
<view class="cont">
|
|
<view class="userInfo">
|
|
<image :src="item.user.avatar"></image>
|
|
<view class="box">
|
|
<view class="user">
|
|
<view class="right">
|
|
<view class="name">{{parseName(item.user.nickname)}}</view>
|
|
<span class="border" v-if="!from">已购{{item.report && item.report.total_trade_count}}次</span>
|
|
</view>
|
|
<view class="time" v-if="!from">{{item.date.replace(/-/g, '/')}}发布于{{provTxt[item.order.province_id]}}</view>
|
|
</view>
|
|
<view class="starBox">
|
|
<view class="rate">
|
|
<view class="star" v-for="i in 5" :key="i">
|
|
<up-icon v-if="i <= Math.ceil(item.stars)" name="star-fill" color="#FFD81E" size="18" />
|
|
<up-icon v-else name="star-fill" color="#ccc" :size="18" />
|
|
</view>
|
|
</view>
|
|
<view class="tags" v-if="item.tags.length">
|
|
<text v-for="(it, i) in item.tags" :key="it.id"><template v-if="i != 0"> | </template>{{it.name}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="item.item" class="sku_name">{{item.item.goods_name}}
|
|
<template v-if="item.item.sku_name">【{{item.item.sku_name}}】</template>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="comment"><text @longpress="copyComment(item.comment)">{{item.comment}}</text></view>
|
|
<view class="box_zong" v-if="item.material.length">
|
|
<view class="box_imgs" v-for="(it, index) in item.material" :key="index">
|
|
<image :src="it.url" v-if="it.type === 1" @click="hanleImgs(it, item.material)" mode="aspectFill"></image>
|
|
<template v-else>
|
|
<image :src="it.img_video" mode="aspectFill"></image>
|
|
<view class="play" @click="hanleImgs(it)"><up-icon name="play-right-fill" color="#fff" size="40" /></view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<view class="replyBox" v-if="item.reply">
|
|
<view>店家回复</view>
|
|
<view class="text">{{item.reply}}</view>
|
|
</view>
|
|
<template v-if="item.add_comments && item.add_comments.length">
|
|
<view class="addBox" v-for="itm in item.add_comments" :key="itm.id">
|
|
<view class="tit">
|
|
<text>{{getDayDiff(itm.created_at.substr(0, 10), item.created_at.substr(0, 10))}}追评</text>
|
|
<text class="time">{{itm.created_at.substr(0, 16)}}</text>
|
|
</view>
|
|
<text class="comment" style="display: inline-block;margin-top: 10rpx;" @longpress="copyComment(itm.comment)">
|
|
{{itm.comment}}
|
|
</text>
|
|
<view class="box_zong" v-if="itm.material.length">
|
|
<view class="box_imgs" v-for="(it, index) in itm.material" :key="index">
|
|
<image :src="it.url" v-if="it.type === 1" @click="hanleImgs(it, itm.material)" mode="aspectFill"></image>
|
|
<template v-else>
|
|
<image :src="it.img_video" mode="aspectFill"></image>
|
|
<view class="play" @click="hanleImgs(it)"><up-icon name="play-right-fill" color="#fff" size="40" /></view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<view class="replyBox itm" v-if="itm.reply">
|
|
<view>店家回复</view>
|
|
<view class="text">{{itm.reply}}</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<view class="btm">
|
|
<view style="display: flex;margin-right: 10px;" @click="toPingbi(index)"><up-icon name="eye-off" color="#666" />屏蔽</view>
|
|
<view style="display: flex;" @click="toTousu(item)"><up-icon name="warning-fill" color="#666" />举报</view>
|
|
</view>
|
|
</view>
|
|
<view class="bottom" v-if="page >= lastPage && infoList.length && !loading">- 到底啦 -</view>
|
|
<view class="bottom" v-if="loading"><van-loading type="spinner" size="24px" vertical color="#999">加载中...</van-loading></view>
|
|
|
|
<view v-if="!infoList.length && !loading">
|
|
<up-empty icon="https://ct-upimg.yx090.com/g.ii090/images/sprite/empty/comment.png" mode="comment" text="暂无评价喔" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<video-dialog :url="videoUrl" :show="showVideo" @close="showVideo = false"></video-dialog>
|
|
|
|
<!-- 隐私协议弹窗 -->
|
|
<privacy-popup :show-dialog="showPrivacy" @close="showPrivacy = false" @agree="showPrivacy = false" @refuse="showPrivacy = false" />
|
|
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, reactive, toRefs } from 'vue'
|
|
import { get } from '@/api/request.js'
|
|
import { Style } from '@/utils/list.js'
|
|
import privacyPopup from '@/components/privacyPopup/index.vue'
|
|
import { judgePrivacy, getDayDiff } from '@/components/common.js'
|
|
import videoDialog from '@/components/videoDialog/index.vue'
|
|
import { provTxt } from '@/components/img.js'
|
|
|
|
export default {
|
|
components: {
|
|
privacyPopup, videoDialog
|
|
},
|
|
setup() {
|
|
const data = reactive({
|
|
tabIndex: 0,
|
|
id: '',
|
|
from: '',
|
|
infoList: [],
|
|
loading: false,
|
|
lastPage: 0,
|
|
page: 1,
|
|
showVideo: false,
|
|
videoUrl: '',
|
|
total: 0,
|
|
tagsList: [],
|
|
tagIndex: 0,
|
|
Color: uni.getStorageSync('theme_color'),
|
|
bgColor: Style[uni.getStorageSync('theme_index') * 1].bgColor,
|
|
showPrivacy: false,
|
|
is_show_sales: 'true',
|
|
goodCommentRate: '',
|
|
rateValue: 0,
|
|
showFilter: false,
|
|
sort: 0,
|
|
tabList: [
|
|
{id: 1, name: '图片/视频', count: 0},
|
|
{id: 2, name: '追评', count: 0},
|
|
{id: 3, name: '回头客', count: 0}
|
|
],
|
|
sortList: [
|
|
{id: 0, name: '默认排序'},
|
|
{id: 1, name: '最新评价'}
|
|
]
|
|
})
|
|
|
|
const hanleImgs = (it, imgs) => {
|
|
var img = []
|
|
imgs && imgs.forEach((res) => {
|
|
if (res.type == 1) {
|
|
img.push(res.url)
|
|
}
|
|
})
|
|
if (it.type === 1) {
|
|
uni.previewImage({
|
|
current: it.url,
|
|
urls: img
|
|
})
|
|
} else {
|
|
data.showVideo = true
|
|
data.videoUrl = it.url
|
|
}
|
|
}
|
|
|
|
// 触底加载下一页
|
|
function scorllBottom() {
|
|
if (data.page < data.lastPage) {
|
|
data.page++
|
|
getList()
|
|
}
|
|
}
|
|
|
|
const getList = (val = 0) => {
|
|
data.loading = true
|
|
get(`/api/v1/goods/comment/${data.id}`, {
|
|
page: data.page,
|
|
pageSize: 20,
|
|
type: 1,
|
|
stars_level: '',
|
|
has_material: '',
|
|
comment_tag_type: data.tabIndex || 0,
|
|
comment_tag_id: data.tagIndex || 0,
|
|
sortType: data.sort + 1
|
|
}).then((res) => {
|
|
data.infoList = data.infoList.concat(res.data)
|
|
data.goodCommentRate = res.goodCommentRate
|
|
data.rateValue = (res.goodCommentRate.split('%')[0] * 0.05).toFixed(2)
|
|
console.log(data.rateValue)
|
|
if(val == 1) {
|
|
data.total = res.meta.total
|
|
}
|
|
data.lastPage = data.is_show_sales == 'true' ? res.meta.last_page : 1
|
|
data.loading = false
|
|
}).catch(() => {
|
|
data.loading = false
|
|
})
|
|
}
|
|
|
|
// 复制评论
|
|
const copyComment = async (text) => {
|
|
if(await judgePrivacy()) {
|
|
data.showPrivacy = true
|
|
return false
|
|
}
|
|
uni.setClipboardData({
|
|
data: String(text),
|
|
success: function () {
|
|
uni.showToast({
|
|
icon: 'none',
|
|
title: '评论已复制'
|
|
})
|
|
},
|
|
fail: function () {
|
|
uni.showToast({
|
|
icon: 'none',
|
|
title: '复制失败'
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
function changeTab(id) {
|
|
if(id == data.tabIndex) {
|
|
return
|
|
}
|
|
data.tagIndex = 0
|
|
|
|
data.tabIndex = id
|
|
|
|
data.page = 1
|
|
data.infoList = []
|
|
getList()
|
|
}
|
|
|
|
function changeTag(id) {
|
|
if(id == data.tagIndex) {
|
|
data.tagIndex = 0
|
|
} else {
|
|
data.tagIndex = id
|
|
}
|
|
|
|
data.tabIndex = 0
|
|
|
|
data.page = 1
|
|
data.infoList = []
|
|
getList()
|
|
}
|
|
|
|
function getTags() {
|
|
get(`/api/v1/orderComment/commentTags`, {type: 1, shop_group_goods_id: data.id}).then((res) => {
|
|
data.tabList[0].count = res.data[0].count
|
|
data.tabList[1].count = res.data[1].count
|
|
data.tabList[2].count = res.data[2].count
|
|
data.tagsList = res.data.slice(3)
|
|
})
|
|
}
|
|
|
|
function toFilter(id) {
|
|
data.sort = id
|
|
data.showFilter = false
|
|
data.page = 1
|
|
data.infoList = []
|
|
getList()
|
|
}
|
|
|
|
function parseName(name) {
|
|
const regex = /^(.{2}).+(.{2})$/
|
|
return name.replace(regex, '$1**$2')
|
|
}
|
|
|
|
function toTousu(item) {
|
|
let text = '举报用户“' + item.user.nickname + '”' + '在团购ID“' + data.id + '”的评论'
|
|
uni.navigateTo({
|
|
url: '/pages/mine/msg/complaint?type=2&desc=' + text
|
|
})
|
|
}
|
|
|
|
function toPingbi(i) {
|
|
data.infoList.splice(i, 1)
|
|
}
|
|
|
|
return {
|
|
getDayDiff,
|
|
provTxt,
|
|
...toRefs(data),
|
|
scorllBottom,
|
|
getList,
|
|
hanleImgs,
|
|
copyComment,
|
|
changeTab,
|
|
changeTag,
|
|
getTags,
|
|
toFilter,
|
|
parseName,
|
|
toTousu,
|
|
toPingbi
|
|
}
|
|
},
|
|
async onLoad(options) {
|
|
this.id = options.id
|
|
this.from = options.from || ''
|
|
this.is_show_sales = options.is_show_sales ? options.is_show_sales : 'true'
|
|
await this.getList(1)
|
|
this.getTags()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.whole{
|
|
height: 100%;
|
|
box-sizing: border-box;
|
|
overflow: auto;
|
|
.tabBox{
|
|
background-color: #fff;
|
|
z-index: 2;
|
|
position: sticky;
|
|
top: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 24rpx 0;
|
|
box-sizing: border-box;
|
|
height: 90rpx;
|
|
.Tit{
|
|
display: flex;
|
|
align-items: center;
|
|
.row{
|
|
margin-right: 16rpx;
|
|
display: flex;
|
|
align-items: baseline;
|
|
&:last-child{
|
|
margin-right: 0;
|
|
}
|
|
.tit{
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
font-weight: 600;
|
|
line-height: 1;
|
|
position: relative;
|
|
&.on::after{
|
|
position: absolute;
|
|
left: 0;
|
|
width: 56rpx;
|
|
height: 4px;
|
|
bottom: -5px;
|
|
content: '';
|
|
background: linear-gradient(to right, #fff -10%, v-bind('Color'));
|
|
}
|
|
}
|
|
text{
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
.filter{
|
|
position: relative;
|
|
.icon{
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
height: 30px;
|
|
padding-top: 3px;
|
|
.heng{
|
|
width: 28rpx;
|
|
height: 2px;
|
|
background-color: #444;
|
|
margin-bottom: 3px;
|
|
&.er{
|
|
width: 24rpx;
|
|
margin-right: 4rpx;
|
|
}
|
|
&.san{
|
|
width: 20rpx;
|
|
margin-right: 10rpx;
|
|
}
|
|
}
|
|
}
|
|
.box{
|
|
position: absolute;
|
|
top: 60rpx;
|
|
right: -10rpx;
|
|
width: 200rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
padding: 14rpx 0;
|
|
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.2);
|
|
z-index: 2;
|
|
background-color: #fff;
|
|
border-radius: 8rpx;
|
|
&:before{
|
|
position: absolute;
|
|
width: 0;
|
|
height: 0;
|
|
border-color: transparent;
|
|
border-style: solid;
|
|
border-width: 6px;
|
|
content: '';
|
|
border-top-width: 0;
|
|
border-bottom-color: #fff;
|
|
top: -6px;
|
|
right: 14rpx;
|
|
}
|
|
.row{
|
|
padding: 14rpx 0;
|
|
&.on{
|
|
color: v-bind('Color');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.contBox{
|
|
padding: 24rpx;
|
|
}
|
|
.oneBox{
|
|
border-bottom: 1rpx solid #e8e8e8;
|
|
.cont{
|
|
background-color: #fff;
|
|
padding: 24rpx 24rpx 8rpx;
|
|
border-radius: 10rpx 10rpx 0 0;
|
|
}
|
|
.top{
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 24rpx;
|
|
.rateBox{
|
|
font-size: 24rpx;
|
|
color: v-bind('Color');
|
|
.rate{
|
|
font-size: 42rpx;
|
|
font-weight: 600;
|
|
margin-bottom: 4px;
|
|
font-family: cursive;
|
|
}
|
|
}
|
|
.star{
|
|
border-left: 1px solid #f1f1f1;
|
|
padding-left: 24rpx;
|
|
margin-left: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
.topBox{
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
.row{
|
|
font-size: 24rpx;
|
|
color: #444;
|
|
padding: 6rpx 16rpx;
|
|
border-radius: 8rpx;
|
|
background-color: #F6F6F6;
|
|
margin: 0 16rpx 16rpx 0;
|
|
&.active{
|
|
background: v-bind('bgColor');
|
|
}
|
|
text{
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
.listBox{
|
|
// padding: 0 24rpx 24rpx;
|
|
.item{
|
|
padding: 20rpx;
|
|
border-bottom: 1rpx solid #F5F5F5;
|
|
background-color: #fff;
|
|
.cont{
|
|
padding: 0 0 20rpx;
|
|
border-bottom: 1rpx solid #f7f2f2;
|
|
}
|
|
.userInfo{
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
image{
|
|
width: 70rpx;
|
|
height: 70rpx;
|
|
border-radius: 50%;
|
|
margin-right: 15rpx;
|
|
}
|
|
.box{
|
|
width: 100%;
|
|
.user{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.right{
|
|
font-size: 22rpx;
|
|
color: #98989f;
|
|
width: calc(100% - 150rpx);
|
|
display: flex;
|
|
align-items: center;
|
|
.name{
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: bold;
|
|
margin-right: 10rpx;
|
|
display: inline-block;
|
|
}
|
|
.border{
|
|
background: rgba(255, 255, 255, 0.39);
|
|
border: 1px solid v-bind('Color');
|
|
color: v-bind('Color');
|
|
padding: 1px 10rpx;
|
|
border-radius: 5rpx;
|
|
font-size: 20rpx;
|
|
font-weight: normal;
|
|
}
|
|
}
|
|
.time{
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
}
|
|
.sku_name{
|
|
color: #999;
|
|
margin-top: 10rpx;
|
|
font-size: 24rpx;
|
|
}
|
|
.starBox{
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 6rpx;
|
|
.rate{
|
|
display: flex;
|
|
align-items: center;
|
|
.star{
|
|
margin-right: 3px;
|
|
}
|
|
}
|
|
.tags{
|
|
margin-left: 10rpx;
|
|
color: #666;
|
|
font-size: 20rpx;
|
|
}
|
|
}
|
|
|
|
.comment{
|
|
display: inline-block;
|
|
font-size: 28rpx;
|
|
line-height: 48rpx;
|
|
margin-top: 20rpx;
|
|
}
|
|
.box_zong{
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
.box_imgs{
|
|
margin: 20rpx 20rpx 0 0;
|
|
position: relative;
|
|
width: 180rpx;
|
|
height: 180rpx;
|
|
&:nth-child(3n+3) {
|
|
margin-right: 0;
|
|
}
|
|
image{
|
|
width: 100%;
|
|
height: 100%;
|
|
vertical-align: bottom;
|
|
border-radius: 8rpx;
|
|
}
|
|
.play{
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
background-color: rgba(0, 0, 0, 0.4);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 8rpx;
|
|
z-index: 1;
|
|
}
|
|
}
|
|
}
|
|
.replyBox{
|
|
padding: 25rpx;
|
|
background: rgba(246, 246, 246, 0.6);
|
|
border-radius: 10rpx;
|
|
font-size: 28rpx;
|
|
margin-top: 24rpx;
|
|
&.itm{
|
|
border-radius: 0;
|
|
border-left: 3px solid #ddd;
|
|
}
|
|
.text{
|
|
margin-top: 20rpx;
|
|
color: #98989f;
|
|
}
|
|
}
|
|
.addBox{
|
|
background-color: #F7F7F7;
|
|
border-radius: 10rpx;
|
|
padding: 16rpx;
|
|
font-size: 28rpx;
|
|
margin-top: 24rpx;
|
|
.tit{
|
|
color: #f00;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
.time{
|
|
color: #98989f;
|
|
font-size: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
.btm{
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
padding: 16rpx 24rpx;
|
|
background: #f6f6f6;
|
|
border-radius: 4px;
|
|
margin-top: 20rpx;
|
|
}
|
|
}
|
|
.bottom {
|
|
text-align: center;
|
|
font-size: 24rpx;
|
|
color: #999999;
|
|
margin: auto;
|
|
line-height: 80rpx;
|
|
}
|
|
}
|
|
}
|
|
</style>
|