590 lines
14 KiB
Vue

<template>
<view class="whole">
<view class="rewardBox" v-if="isReward == 1">
参与晒单最多可得
<view class="icon" :style="{backgroundImage: 'url(' + sp2 + ')'}"></view>
<text :style="{color: priceColor}">{{couponData.amount}}</text> 元优惠券
</view>
<view class="comment">
<view class="list">
<view class="comment-goods" v-for="(item, index) in order.items" :key="index">
<view class="comment-goods-info">
<image :src="item.pic_url"></image>
<view class="right">
<view class="name">
<text class="title">{{item.goods_name}}</text>
<view>
<text class="icon">¥</text>
<text>{{item.price}}</text>
</view>
</view>
<view class="num">
<text class="sku">{{item.sku_name}}</text>
<text class="number">x{{item.number}}</text>
</view>
</view>
</view>
<view class="starBox">
<text style="margin-right: 20rpx;">描述相符</text>
<up-rate v-model="item.score" :active-color="Color" inactive-color="#eee" @change="onScoreChange($event, index)" />
<text style="font-weight: 600;">&nbsp;&nbsp;{{rateText[item.score]}}</text>
</view>
<view class="tagBox" v-if="tagsList.length">
<view class="row"
v-for="it in tagsList"
:key="it.id"
:class="item.comment_tag_ids.indexOf(it.id) != -1 ? 'active' : ''"
@click="selectTag(item, it.id)">{{it.name}}</view>
</view>
<!-- 文字评价 -->
<view class="descBox">
<view class="textarea">
<up-textarea v-model="item.comment" count placeholder="填写评价,可以帮助更多想买的人哦~" style="font-size: 28rpx;" :height="70" :maxlength="500"></up-textarea>
</view>
<view v-if="isReward == 1" class="text">
<text>详细描述</text>
<template v-if="countNum.text_num > 0 && countNum.img_num > 0">
(至少输入{{countNum.text_num}}个字+{{countNum.img_num}}张图片)
</template>
<template v-if="countNum.text_num > 0 && countNum.img_num == 0">
(至少输入{{countNum.text_num}}个字)
</template>
<template v-if="countNum.text_num == 0 && countNum.img_num > 0">
(至少上传{{countNum.img_num}}张图片)
</template>
</view>
</view>
<view style="margin-top: 40rpx;">
<view class="imgBox">
<view class="imgList" v-for="(it, i) in item.imgs" :key="i">
<image v-if="it.type === 1" :src="it.url" mode="aspectFill" class="img" @click="handlePreView(it)"></image>
<image v-if="it.type === 2" :src="it.img_video" mode="aspectFill" class="img"></image>
<view @click="deleteImage(index, i)" class="close"><view class="heng"></view></view>
<view class="play" v-if="it.type === 2" @click="handlePreView(it)">
<up-icon name="play-circle-fill" :size="30" color="#fff" />
</view>
</view>
</view>
<view class="imgBox">
<view @click="uploadImage(index)" class="plus">
<up-icon name="photo-fill" color="#999" :size="22" />
<text>图片上传</text>
</view>
<view @click="uploadVideo(index)" class="plus">
<up-icon name="camera-fill" color="#999" :size="22" />
<text>视频上传</text>
</view>
</view>
</view>
</view>
</view>
<view class="comment-btn" @click="submitBtn">提交评价
<view v-if="score_on && role" class="text1">积分再+{{score_comment}}</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" />
</view>
</view>
</template>
<script>
import api from '/api/index'
import { ref, reactive, toRefs } from 'vue'
import { get, post } from '@/api/request.js'
import { showToast, judgePrivacy } from '@/components/common.js'
import { Style } from '@/utils/list.js'
import { sp2 } from '@/components/img.js'
import privacyPopup from '@/components/privacyPopup/index.vue'
import videoDialog from '@/components/videoDialog/index.vue'
export default {
components: {
privacyPopup, videoDialog
},
setup() {
const data = reactive({
sp2: sp2,
order: {},
show: false,
pic_urls: [],
urls: api.url + '/api/v1/upload',
video: api.url + '/api/v1/upload/video',
isReward: '',
couponData: {},
countNum: {},
rateText: {
'0': '',
'1': '非常差',
'2': '差',
'3': '一般',
'4': '满意',
'5': '超赞'
},
score_on: Number(uni.getStorageSync('score_on')) === 1,
score_comment: Number(uni.getStorageSync('score_comment')),
role: Number(uni.getStorageSync('role')) !== 1,
Color: uni.getStorageSync('theme_color'),
priceColor: Style[uni.getStorageSync('theme_index') * 1].priceColor,
bgColor: Style[uni.getStorageSync('theme_index') * 1].bgColor,
showPrivacy: false,
showVideo: false,
videoUrl: '',
tagsList: []
})
const onScoreChange = (val, index) => {
data.order.items[index].score = val.value
}
const handleBlur = (val, index) => {
console.log(val, index, data.order.items[index].comment)
data.order.items[index].comment = val.detail.value
}
const uploadVideo = async (e) => {
if(await judgePrivacy()) {
data.showPrivacy = true
return false
}
wx.chooseVideo({
sourceType: ['album', 'camera'],
maxDuration: 60,
camera: ['front', 'back'],
compressed: true,
success(res) {
let tempFilePath = res.tempFilePath
let duration = res.duration
let size = parseFloat(res.size / 1024 / 1024)
if (parseFloat(size) > 10) {
wx.showToast({
title: '上传的视频大小超限,请重新上传',
icon: 'none'
})
// uni.compressVideo({
// src: tempFilePath,
// quality: 'medium', //'low':低,'medium':中,'high':高
// success: function(ress) {
// console.log('压缩后', ress)
// uploadFile(ress.tempFilePath, e)
// },
// fail: function(err) {
// console.log(err)
// uni.showToast({
// title: '视频压缩失败',
// icon: 'none'
// }, 2000)
// }
// })
} else {
uploadFile(tempFilePath, e)
}
}
})
}
const uploadFile = (tempFilePath, e) => {
uni.showLoading({
title: '正在上传...',
mask: true
})
wx.uploadFile({
url: data.video,
filePath: tempFilePath,
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || '',
accept: 'application/json',
appid: api.appId
},
success(res) {
var video = JSON.parse(res.data).data
data.order.items[e].imgs.push({
type: 2,
url: video.link,
img_video: video.link + '?x-oss-process=video/snapshot,t_1000,m_fast'
})
uni.hideLoading()
},
fail: function(err) {
console.log(err)
uni.hideLoading()
uni.showToast({
title: '视频上传失败',
icon: 'none'
}, 2000)
}
})
}
const uploadImage = async (e) => {
if(await judgePrivacy()) {
data.showPrivacy = true
return false
}
wx.chooseImage({
success(res) {
const tempFilePaths = res.tempFilePaths
wx.uploadFile({
url: data.urls,
filePath: tempFilePaths[0],
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || '',
accept: 'application/json',
appid: api.appId
},
success(res) {
var img = JSON.parse(res.data).data
data.order.items[e].imgs.push({
type: 1,
url: img.link
})
}
})
}
})
}
const deleteImage = (index, i) => {
data.order.items[index].imgs.splice(i, 1)
}
const handlePreView = (item) => {
if (item.type === 1) {
uni.previewImage({
current: item.url,
urls: [item.url]
})
} else {
data.showVideo = true
data.videoUrl = item.url
}
}
async function getInfo(id) {
let res = await get(`/api/v1/order/${id}`)
data.order = res.data
data.order.items.forEach((element) => {
element.imgs = []
element.score = 0
element.comment = ''
element.comment_tag_ids = []
})
}
// 获取是否设置优惠券
const getShopBaskSetting = () => {
post('/api/v1/Shop/getShopBaskSetting').then((res) => {
data.isReward = res.data.is_reward
data.couponData = res.data.shop_coupon
data.countNum = res.data
})
}
const submitBtn = () => {
let list = data.order.items
let comments = []
for (let i = 0; i < list.length; i++) {
// if (!list[i].comment || list[i].comment.trim() === '') {
// showToast('请填写所有商品评论')
// return
// } else if (!data.score) {
// showToast('请给商品点亮小星星')
// return
// } else {
// }
comments.push({
shop_goods_id: list[i].shop_goods_id,
goods_id: list[i].goods_id,
comment: list[i].comment,
order_item_id: list[i].id,
shop_group_goods_id: list[i].shop_group_goods_id,
material: list[i].imgs,
comment_tag_ids: list[i].comment_tag_ids,
stars: list[i].score
})
}
let ids =
data.order.items[0].shop_group_goods_id != 0 ?
data.order.items[0].shop_group_goods_id :
data.order.items[0].shop_goods_id
post('/api/v1/orderComment', { order_id: data.order.id, comments }).then((res) => {
let url = '/pages/order/comment/success?id=' + data.order.id + '&ids=' + ids
if(data.score_on && data.role) {
url += '&score_comment=' + data.score_comment
}
uni.redirectTo({
url: url
})
})
}
function getTags() {
get(`/api/v1/orderComment/commentTags`, {type: 0}).then((res) => {
data.tagsList = res.data
})
}
function selectTag(row, id) {
if(row.comment_tag_ids.indexOf(id) === -1) {
row.comment_tag_ids.push(id)
} else {
let i = row.comment_tag_ids.indexOf(id)
row.comment_tag_ids.splice(i, 1)
}
}
return {
...toRefs(data),
uploadImage,
uploadVideo,
deleteImage,
getInfo,
submitBtn,
onScoreChange,
handleBlur,
getShopBaskSetting,
handlePreView,
getTags,
selectTag
}
},
async onLoad(options) {
this.getShopBaskSetting()
await this.getInfo(options.id)
this.getTags()
}
}
</script>
<style lang="scss" scoped>
.comment{
position: relative;
padding: 30rpx;
box-sizing: border-box;
&-goods {
padding: 30rpx;
background-color: #fff;
border-radius: 10rpx;
margin-bottom: 30rpx;
&-info {
display: flex;
height: 144rpx;
image {
width: 144rpx;
height: 100%;
background: rgba(203, 202, 203, 0.39);
border-radius: 10rpx;
margin-right: 20rpx;
}
.right {
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1;
.name,
.num {
display: flex;
justify-content: space-between;
}
.name {
font-size: 28rpx;
.title {
font-weight: bold;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.icon {
font-size: 24rpx;
}
}
.num {
font-size: 26rpx;
color: #98989f;
.sku {
flex: 1;
font-size: 24rpx;
}
}
}
}
.descBox{
margin-top: 30rpx;
.textarea{
border: 1rpx solid #E5E5E5;
font-size: 28rpx;
color: #333;
width: 100%;
box-sizing: border-box;
overflow: auto;
}
.text{
font-size: 24rpx;
color: #676767;
text{
font-size: 28rpx;
color: #333;
margin-right: 10rpx;
}
}
}
}
&-btn {
width: calc(100% - 60rpx);
margin: 30rpx auto;
background-color: v-bind('Color');
color: #fff;
height: 80rpx;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 80rpx;
position: relative;
.text1{
border-radius: 20rpx 20rpx 20rpx 0;
border: 1px solid #fff;
background-color: v-bind('Color');
font-size: 22rpx;
color: #fff;
padding: 6rpx 10rpx;
position: absolute;
top: -26rpx;
left: 60%;
}
}
}
.whole{
width: 100%;
}
.rewardBox {
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
background: #fff;
border-top: 1px solid #f7f7f7;
font-size: 28rpx;
font-weight: bold;
position: sticky;
z-index: 10;
top: 0;
.icon{
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-size: 452px 408px;
background-position: -259.67px -136.67px;
}
}
.starBox {
margin-top: 20rpx;
font-size: 28rpx;
display: flex;
align-items: center;
line-height: 50rpx;
}
.imgBox{
display: flex;
align-items: center;
flex-wrap: wrap;
.imgList{
width: 160rpx;
height: 160rpx;
margin: 0 20rpx 20rpx 0;
position: relative;
.img{
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.close{
position: absolute;
right: -17rpx;
top: -17rpx;
color: #fff;
width: 34rpx;
height: 34rpx;
background-color: rgba(0,0,0,0.6);
border-radius: 50%;
z-index: 8;
.heng{
display: block;
width: 20rpx;
height: 4rpx;
background-color: #fff;
margin: 15rpx auto;
}
}
.play{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0,0,0,0.35);
border-radius: 8rpx;
z-index: 1;
}
}
.plus{
border: 1px solid #e1e1e1;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 160rpx;
height: 160rpx;
box-sizing: border-box;
margin: 0 20rpx 20rpx 0;
text{
font-size: 24rpx;
margin-top: 10rpx;
color: #999;
}
}
}
.tagBox{
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 30rpx 0 0;
.row{
font-size: 24rpx;
color: #444;
padding: 8rpx 16rpx;
border-radius: 8rpx;
border: 1px solid #F6F6F6;
background-color: #F6F6F6;
margin: 0 20rpx 20rpx 0;
&.active{
background: v-bind('bgColor');
color: v-bind('Color');
border: 1px solid v-bind('Color');
}
}
}
</style>