602 lines
15 KiB
Vue
602 lines
15 KiB
Vue
<template>
|
||
<view v-if="!isLoading" class="container" :style="appThemeStyle">
|
||
<view class="goods-list">
|
||
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
||
<!-- 商品详情 -->
|
||
<!-- <view class="goods-main">
|
||
<view class="goods-image">
|
||
<image class="image" :src="item.goods_image" mode="scaleToFill"></image>
|
||
</view>
|
||
<view class="goods-content">
|
||
<view class="goods-title"><text class="twoline-hide">{{ item.goods_name }}</text></view>
|
||
<view class="goods-props clearfix">
|
||
<view class="goods-props-item" v-for="(props, idx) in item.goods_props" :key="idx">
|
||
<text>{{ props.value.name }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="goods-trade">
|
||
<view class="goods-price">
|
||
<text class="unit">¥</text>
|
||
<text class="value">{{ item.goods_price }}</text>
|
||
</view>
|
||
<view class="goods-num">
|
||
<text>×{{ item.total_num }}</text>
|
||
</view>
|
||
</view>
|
||
</view> -->
|
||
<!-- 选择评价 -->
|
||
<view class="score-row">
|
||
<view class="score-item score-praise" :class="{ active: formData[index].level == 'good' }" @click="setScore(index, 'good')">
|
||
<view class="score">
|
||
<text class="score-icon iconfont icon-haoping"></text>
|
||
<text class="score-text">好评</text>
|
||
</view>
|
||
</view>
|
||
<view class="score-item score-review" :class="{ active: formData[index].level == 'common' }" @click="setScore(index, 'common')">
|
||
<view class="score">
|
||
<text class="score-icon iconfont icon-zhongping"></text>
|
||
<text class="score-text">中评</text>
|
||
</view>
|
||
</view>
|
||
<view class="score-item score-negative" :class="{ active: formData[index].level == 'notgood' }" @click="setScore(index, 'notgood')">
|
||
<view class="score">
|
||
<text class="score-icon iconfont icon-chaping"></text>
|
||
<text class="score-text">差评</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 评分详情 -->
|
||
<view class="rating-detail">
|
||
<view class="rating-item">
|
||
<text class="rating-label">商品分:</text>
|
||
<view class="rating-stars">
|
||
<u-rate
|
||
:current="formData[index].descMatch || 5"
|
||
:count="5"
|
||
:size="28"
|
||
active-color="#FFD700"
|
||
inactive-color="#E0E0E0"
|
||
@change="(val) => setGoodsScore(index, val)"
|
||
></u-rate>
|
||
</view>
|
||
</view>
|
||
<view class="rating-item">
|
||
<text class="rating-label">卖家服务评分:</text>
|
||
<view class="rating-stars">
|
||
<u-rate
|
||
:current="formData[index].sellerService || 5"
|
||
:count="5"
|
||
:size="28"
|
||
active-color="#FFD700"
|
||
inactive-color="#E0E0E0"
|
||
@change="(val) => setServiceScore(index, val)"
|
||
></u-rate>
|
||
</view>
|
||
</view>
|
||
<view class="rating-item">
|
||
<text class="rating-label">物流评分:</text>
|
||
<view class="rating-stars">
|
||
<u-rate
|
||
:current="formData[index].logisticsService || 5"
|
||
:count="5"
|
||
:size="28"
|
||
active-color="#FFD700"
|
||
inactive-color="#E0E0E0"
|
||
@change="(val) => setLogisticsScore(index, val)"
|
||
></u-rate>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 评价内容 -->
|
||
<view class="form-content">
|
||
<textarea class="textarea" v-model="formData[index].serviceComment" maxlength="500" placeholder="请输入评价内容 (留空则不评价)"></textarea>
|
||
</view>
|
||
|
||
<!-- 图片列表 -->
|
||
<view class="image-list">
|
||
<view class="image-preview" v-for="(image, imageIndex) in formData[index].imageList" :key="imageIndex">
|
||
<text class="image-delete iconfont icon-shanchu" @click="deleteImage(index, imageIndex)"></text>
|
||
<image class="image" mode="aspectFill" :src="image.path"></image>
|
||
</view>
|
||
<view v-if="!formData[index].imageList || formData[index].imageList.length < maxImageLength" class="image-picker"
|
||
@click="chooseImage(index)">
|
||
<text class="choose-icon iconfont icon-camera"></text>
|
||
<text class="choose-text">上传图片</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部操作按钮 -->
|
||
<view class="footer-fixed">
|
||
<view class="btn-wrapper">
|
||
<view class="btn-item btn-item-main" :class="{ disabled }" @click="handleSubmit()">确认提交</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import * as OrderCommentApi from '@/api/order/comment'
|
||
import * as OrderApi from '@/api/order'
|
||
|
||
const maxImageLength = 6
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
isLoading: true,
|
||
orderId: null,
|
||
goodsList: [{}],
|
||
formData: [],
|
||
maxImageLength,
|
||
disabled: false,
|
||
trackNumber: null
|
||
}
|
||
},
|
||
onLoad({ tradeOrderId, trackNumber }) {
|
||
this.orderId = tradeOrderId
|
||
this.trackNumber = trackNumber
|
||
this.initFormData()
|
||
this.isLoading = false
|
||
// this.getGoodsList()
|
||
},
|
||
|
||
methods: {
|
||
/* // 获取待评价商品列表
|
||
getGoodsList() {
|
||
const app = this
|
||
app.isLoading = true
|
||
OrderCommentApi.list(app.orderId)
|
||
.then(result => {
|
||
app.goodsList = result.data.goodsList
|
||
app.initFormData()
|
||
app.isLoading = false
|
||
})
|
||
}, */
|
||
// 初始化form数据
|
||
initFormData() {
|
||
const { goodsList } = this
|
||
const formData = goodsList.map(item => {
|
||
return {
|
||
trackNumber: this.trackNumber,
|
||
level: 'good',
|
||
descMatch: 0, // 商品分,默认5
|
||
sellerService: 0, // 卖家服务评分,默认2
|
||
logisticsService: 0, // 物流评分,默认3
|
||
serviceComment: '',
|
||
commentDetailList: '',
|
||
imageList: [],
|
||
uploaded: []
|
||
}
|
||
})
|
||
this.formData = formData
|
||
},
|
||
// 设置评分
|
||
setScore(index, level) {
|
||
this.formData[index].level = level
|
||
},
|
||
// 设置商品分
|
||
setGoodsScore(index, score) {
|
||
this.formData[index].descMatch = score
|
||
},
|
||
// 设置卖家服务评分
|
||
setServiceScore(index, score) {
|
||
this.formData[index].sellerService = score
|
||
},
|
||
// 设置物流评分
|
||
setLogisticsScore(index, score) {
|
||
this.formData[index].logisticsService = score
|
||
},
|
||
// 选择图片
|
||
chooseImage(index) {
|
||
const app = this
|
||
const oldImageList = app.formData[index].imageList
|
||
// 选择图片
|
||
uni.chooseImage({
|
||
count: maxImageLength - oldImageList.length,
|
||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
|
||
success({ tempFiles }) {
|
||
// tempFiles = [{path:'xxx', size:100}]
|
||
app.formData[index].imageList = oldImageList.concat(tempFiles)
|
||
}
|
||
});
|
||
},
|
||
// 删除图片
|
||
deleteImage(index, imageIndex) {
|
||
this.formData[index].imageList.splice(imageIndex, 1)
|
||
},
|
||
// 表单提交
|
||
handleSubmit() {
|
||
const app = this
|
||
if (app.disabled === true) return false
|
||
app.disabled = true
|
||
const imagesLength = app.getImagesLength()
|
||
if (imagesLength > 0) {
|
||
const imageList = app.formData.map(item => item.imageList)
|
||
OrderApi.apiUploadFile(imageList.flat())
|
||
.then(results => {
|
||
app.formData[0].commentDetailList = results.map(result => {
|
||
return {"commentUrl":result.data[0].url,"type":"image"}
|
||
});
|
||
app.onSubmit();
|
||
})
|
||
.catch(err => {
|
||
app.disabled = false
|
||
if (err.statusCode !== 0) {
|
||
app.$toast(err.errMsg)
|
||
}
|
||
console.log('err', err)
|
||
})
|
||
} else {
|
||
app.onSubmit()
|
||
}
|
||
},
|
||
// 统计图片数量
|
||
getImagesLength() {
|
||
const { formData } = this
|
||
let imagesLength = 0
|
||
formData.forEach(item => {
|
||
if (item.serviceComment.trim()) {
|
||
imagesLength += item.imageList.length
|
||
}
|
||
})
|
||
return imagesLength
|
||
},
|
||
// 提交到后端
|
||
onSubmit() {
|
||
const app = this
|
||
const params = { ...app.formData[0], imageList: undefined }
|
||
OrderApi.apiApplyComment(params)
|
||
.then(result => {
|
||
app.$toast(result.msg)
|
||
setTimeout(() => {
|
||
app.disabled = false
|
||
uni.navigateBack()
|
||
}, 1500)
|
||
})
|
||
.catch(err => app.disabled = false)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.container {
|
||
// 设置ios刘海屏底部横线安全区域
|
||
padding-bottom: calc(constant(safe-area-inset-bottom) + 140rpx);
|
||
padding-bottom: calc(env(safe-area-inset-bottom) + 140rpx);
|
||
}
|
||
|
||
.goods-list {
|
||
font-size: 28rpx;
|
||
padding-top: 30rpx;
|
||
}
|
||
|
||
.goods-item {
|
||
width: 94%;
|
||
background: #fff;
|
||
padding: 24rpx 24rpx;
|
||
box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05);
|
||
margin: 0 auto 30rpx auto;
|
||
border-radius: 20rpx;
|
||
|
||
.goods-detail {
|
||
padding: 24rpx 20rpx;
|
||
|
||
.left {
|
||
.goods-image {
|
||
display: block;
|
||
width: 150rpx;
|
||
height: 150rpx;
|
||
}
|
||
}
|
||
|
||
.right {
|
||
padding-left: 20rpx;
|
||
}
|
||
}
|
||
|
||
.score-row {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding: 24rpx 20rpx;
|
||
|
||
.score-item {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
|
||
&.score-praise {
|
||
color: $main-bg;
|
||
|
||
.score-icon {
|
||
background: $main-bg;
|
||
}
|
||
}
|
||
|
||
&.score-review {
|
||
color: $vice-bg;
|
||
|
||
.score-icon {
|
||
background: $vice-bg;
|
||
}
|
||
}
|
||
|
||
&.score-negative {
|
||
color: #9b9b9b;
|
||
|
||
.score-icon {
|
||
background: #9b9b9b;
|
||
}
|
||
}
|
||
|
||
.score {
|
||
padding: 10rpx 20rpx 10rpx 10rpx;
|
||
border-radius: 30rpx;
|
||
|
||
.score-icon {
|
||
margin-right: 10rpx;
|
||
padding: 10rpx;
|
||
border-radius: 50%;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
.score {
|
||
color: #fff;
|
||
}
|
||
|
||
&.score-praise {
|
||
.score {
|
||
background: $main-bg;
|
||
}
|
||
}
|
||
|
||
&.score-review {
|
||
.score {
|
||
background: $vice-bg;
|
||
}
|
||
}
|
||
|
||
&.score-negative {
|
||
.score {
|
||
background: #9b9b9b;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 评分详情
|
||
.rating-detail {
|
||
padding: 20rpx 20rpx;
|
||
margin-top: 10rpx;
|
||
|
||
.rating-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.rating-label {
|
||
width: 200rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.rating-stars {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 评价内容
|
||
.form-content {
|
||
padding: 14rpx 10rpx;
|
||
|
||
.textarea {
|
||
width: 100%;
|
||
height: 220rpx;
|
||
padding: 12rpx;
|
||
border: 1rpx solid #e8e8e8;
|
||
border-radius: 5rpx;
|
||
box-sizing: border-box;
|
||
font-size: 26rpx;
|
||
}
|
||
}
|
||
|
||
.image-list {
|
||
padding: 0 20rpx;
|
||
margin-top: 20rpx;
|
||
margin-bottom: -20rpx;
|
||
|
||
&:after {
|
||
clear: both;
|
||
content: " ";
|
||
display: table;
|
||
}
|
||
|
||
.image {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.image-picker,
|
||
.image-preview {
|
||
width: 184rpx;
|
||
height: 184rpx;
|
||
margin-right: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
float: left;
|
||
|
||
&:nth-child(3n+0) {
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
|
||
.image-picker {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border: 1rpx dashed #ccc;
|
||
color: #ccc;
|
||
|
||
.choose-icon {
|
||
font-size: 48rpx;
|
||
margin-bottom: 6rpx;
|
||
}
|
||
|
||
.choose-text {
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
|
||
.image-preview {
|
||
position: relative;
|
||
|
||
.image-delete {
|
||
position: absolute;
|
||
top: -15rpx;
|
||
right: -15rpx;
|
||
height: 42rpx;
|
||
width: 42rpx;
|
||
background: rgba(0, 0, 0, 0.64);
|
||
border-radius: 50%;
|
||
color: #fff;
|
||
font-weight: bolder;
|
||
font-size: 22rpx;
|
||
z-index: 10;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// 商品项
|
||
.goods-main {
|
||
display: flex;
|
||
margin-bottom: 20rpx;
|
||
|
||
// 商品图片
|
||
.goods-image {
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
|
||
.image {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
|
||
// 商品内容
|
||
.goods-content {
|
||
flex: 1;
|
||
padding-left: 16rpx;
|
||
// padding-top: 16rpx;
|
||
|
||
.goods-title {
|
||
font-size: 26rpx;
|
||
max-height: 76rpx;
|
||
}
|
||
|
||
.goods-props {
|
||
margin-top: 14rpx;
|
||
color: #ababab;
|
||
font-size: 24rpx;
|
||
overflow: hidden;
|
||
|
||
.goods-props-item {
|
||
padding: 4rpx 16rpx;
|
||
border-radius: 12rpx;
|
||
background-color: #fcfcfc;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
// 交易信息
|
||
.goods-trade {
|
||
padding-top: 16rpx;
|
||
width: 150rpx;
|
||
text-align: right;
|
||
color: $uni-text-color-grey;
|
||
font-size: 26rpx;
|
||
|
||
.goods-price {
|
||
vertical-align: bottom;
|
||
margin-bottom: 16rpx;
|
||
|
||
.unit {
|
||
margin-right: -2rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// 底部操作栏
|
||
.footer-fixed {
|
||
position: fixed;
|
||
bottom: var(--window-bottom);
|
||
left: var(--window-left);
|
||
right: var(--window-right);
|
||
z-index: 11;
|
||
|
||
// 设置ios刘海屏底部横线安全区域
|
||
padding-bottom: constant(safe-area-inset-bottom);
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
|
||
.btn-wrapper {
|
||
height: 140rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
.btn-item {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
height: 80rpx;
|
||
color: #fff;
|
||
border-radius: 50rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.btn-item-main {
|
||
background: linear-gradient(to right, $main-bg, $main-bg2);
|
||
color: $main-text;
|
||
|
||
// 禁用按钮
|
||
&.disabled {
|
||
opacity: 0.6;
|
||
}
|
||
}
|
||
|
||
}
|
||
</style> |