shop_app/pages/mine/msg/complaint.vue

483 lines
11 KiB
Vue
Raw 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="whole">
<view class="tips" :style="{color: Color}">此投诉为本小程序自有投诉渠道非微信官方投诉渠道</view>
<view class="oneBox">
<view class="row">
<view class="span">补充描述<text>*</text></view>
<view class="pad20">
<up-textarea v-model="desc" count placeholder="补充描述" style="font-size: 28rpx;" :height="70" :maxlength="500"></up-textarea>
</view>
</view>
<view class="row">
<view class="span">联系电话<text>*</text></view>
<view class="pad20">
<input class="input" type="text" v-model="mobile" placeholder="请输入您的联系方式" />
</view>
</view>
<view class="orderBox row" v-if="type == 1">
<view class="span">相关订单</view>
<view class="cont flex" @click="showOrder = true">
<view v-if="order_sn">
<view class="tit">{{order_sn}}</view>
<text>{{goods_name}}</text>
</view>
<view class="tit" v-else>请选择订单</view>
<up-icon name="arrow-right" />
</view>
</view>
<view class="row">
<view class="span">图片凭证(选填)</view>
<view class="upImg">
<view class="hasimg" v-for="(item, index) in imgList" :key="index">
<image :src="item" class="img" mode="aspectFill"></image>
<view class="icon flexc" @click="delUpImg(item, index)"><up-icon name="close" color="#fff" size="12" /></view>
</view>
<view class="plus flexc" @click="uploadImg()">
<up-icon name="camera-fill" color="#9D9D9D" size="24" />
<text>上传凭证</text>
</view>
</view>
</view>
<view class="btmbox flexc" @click="commitSubmit()">提交</view>
</view>
<up-popup :show="showOrder" mode="bottom" :round="10" @close="showOrder = false">
<view class="itemBox">
<view class="title">我的订单</view>
<scroll-view scroll-y="true" class="content" @scrolltolower="scorllBottom">
<view class="item" v-for="item in orderList" :key="item.id" @click="selectOrder(item)">
<view class="one flex">
<view class="no">{{item.order_sn}}</view>
<text>{{statusObj[item.status]}}</text>
</view>
<view class="two" v-for="it in item.items" :key="it.id">
<image :src="it.pic_url + '?x-oss-process=image/format,webp'" :webp="true" mode="aspectFill"></image>
<view class="cont">
<view class="tit">{{it.goods_name}}<view class="sku">{{it.sku_name}}</view></view>
<view class="btm flex">
<view class="price">{{it.price}}</view>
<text>×{{it.number}}</text>
</view>
</view>
</view>
</view>
<view class="noMore" v-if="orderList.length && page >= lastPage && !loading"> 没有更多了 </view>
<view v-if="!orderList.length && !loading">
<up-empty mode="order" icon="https://ct-upimg.yx090.com/g.ii090/images/sprite/empty/order.png" text="暂无订单"></up-empty>
</view>
<view v-if="loading" class="loadbox">
<up-loading-icon text="加载中..." textSize="14"></up-loading-icon>
</view>
</scroll-view>
</view>
</up-popup>
</view>
</template>
<script>
import { reactive, toRefs } from 'vue'
import { get, post } from '@/api/request.js'
import { showToast } from '@/components/common.js'
import { Style } from '@/utils/list.js'
import API from '/api/index'
export default {
setup() {
const data = reactive({
reason: '',
mobile: '',
desc: '',
imgList: [],
Color: uni.getStorageSync('theme_color'),
bgColor: Style[uni.getStorageSync('theme_index') * 1].bgColor,
showPrivacy: false,
order_id: 0,
order_sn: 0,
goods_name: '',
showOrder: false,
page: 1,
lastPage: 0,
orderList: [],
loading: false,
statusObj: {
'0': '待付款',
'1': '待发货',
'2': '处理中',
'3': '待收货',
'7': '已完成',
'6': '退款成功',
'8': '关闭订单',
'9': '取消订单'
},
type: 0
})
function changeDesc(e) {
data.desc = e.detail
}
// 上传图片
async function uploadImg() {
if(data.imgList.length === 5) {
showToast('最多只能添加5张图片喔')
return false
}
data.onDialog = true
uni.chooseImage({
success(res) {
const tempFilePaths = res.tempFilePaths
uni.showLoading({
title: '正在上传...',
mask: true
})
uni.uploadFile({
url: API.url + '/api/v1/upload',
filePath: tempFilePaths[0],
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || '',
accept: 'application/json',
appid: API.appId
},
success(req) {
const imgUrl = JSON.parse(req.data).data.link
data.imgList.push(imgUrl)
uni.hideLoading()
data.onDialog = false
},
fail() {
uni.hideLoading()
data.onDialog = false
}
})
},
fail() {
data.onDialog = false
}
})
}
// 删除图片
function delUpImg(item, index) {
data.imgList.splice(index, 1)
}
// 确认提交
const commitSubmit = async () => {
if(!data.mobile) {
return showToast('请填写联系方式')
}
if(!data.desc) {
return showToast('请输入补充描述')
}
if(data.type == 1 && !data.order_id) {
return showToast('商品问题的投诉需选择相应订单')
}
uni.showLoading({
mask: true,
title: '正在提交'
})
let param = {
complain_type: data.type,
order_id: data.order_id,
complain_reason: data.reason,
contact_phone: data.mobile,
added_desc: data.desc,
images: data.imgList
}
if(data.type != 1) {
param.order_id = ''
}
post('/api/v1/feedback', param).then(res => {
uni.hideLoading()
uni.showToast({
title: '提交成功',
icon: 'success',
duration: 1000,
mask: true,
success() {
setTimeout(() => {
uni.navigateBack({delta: 1})
}, 1000)
}
})
}).catch(() => {
uni.hideLoading()
})
}
function getPhone() {
get('/api/v1/address/default').then(res => {
if(!Array.isArray(res.data)) {
data.mobile = res.data.mobile
}
})
}
function getOrderList() {
data.loading = true
get('/api/v1/order', {page: data.page, pageSize: 20, status: ''}).then(res => {
data.orderList = data.orderList.concat(res.data)
data.lastPage = res.meta.last_page
data.loading = false
}).catch(() => {
data.loading = false
})
}
function getOrderInfo() {
get('/api/v1/order/' + data.order_id).then(res => {
data.order_sn = res.data.order_sn
data.goods_name = res.data.items && res.data.items[0].goods_name
})
}
function scorllBottom() {
if (data.page < data.lastPage) {
data.page++
getOrderList()
}
}
function selectOrder(item) {
data.order_id = item.id
data.order_sn = item.order_sn
data.goods_name = item.items[0].goods_name
data.showOrder = false
}
return {
...toRefs(data),
changeDesc,
commitSubmit,
uploadImg,
delUpImg,
getPhone,
scorllBottom,
getOrderList,
selectOrder,
getOrderInfo
}
},
async onLoad(options) {
this.order_id = (options.order_id || 0) * 1
this.type = (options.type || 0) * 1
// await this.$onLaunched
this.getPhone()
if(this.type == 1) {
this.getOrderList()
if(this.order_id * 1) {
this.getOrderInfo()
}
}
}
}
</script>
<style lang="scss" scoped>
.whole {
background-color: #F5F5F5;
position: relative;
padding-bottom: 140rpx;
.pad20{
padding: 20rpx 0;
box-sizing: border-box;
}
.oneBox{
.row{
padding: 0 24rpx;
font-size: 28rpx;
background-color: #fff;
margin-bottom: 20rpx;
.span{
line-height: 80rpx;
font-weight: 600;
font-size: 30rpx;
position: relative;
&::after{
position: absolute;
border-bottom: 1px solid #f4f4f4;
width: calc(100% + 40rpx);
left: -20rpx;
bottom: 0;
content: '';
}
text{
font-size: 24rpx;
color: #f00;
}
}
.input{
width: 100%;
height: 64rpx;
}
.upImg{
display: flex;
flex-wrap: wrap;
width: 100%;
padding: 24rpx 0;
.hasimg{
width: 130rpx;
height: 130rpx;
margin-right: 30rpx;
margin-bottom: 30rpx;
position: relative;
.img{
width: 100%;
height: 100%;
}
.icon{
position: absolute;
top: -18rpx;
right: -18rpx;
width: 36rpx;
height: 36rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
z-index: 10;
}
}
.plus{
width: 140rpx;
height: 140rpx;
flex-direction: column;
border: 1px dashed #707070;
box-sizing: border-box;
border-radius: 6rpx;
text{
font-size: 24rpx;
color: #9D9D9D;
text-align: center;
}
}
}
}
}
.tips{
position: sticky;
top: 0;
width: 100%;
margin-bottom: 24rpx;
background: v-bind('bgColor');
font-size: 26rpx;
padding: 14rpx 0;
text-align: center;
z-index: 10;
}
.orderBox{
.cont{
padding: 18rpx 0;
.tit{
padding: 8rpx 0;
}
text{
font-size: 26rpx;
color: #9D9D9D;
}
}
}
.btmbox{
width: 94%;
height: 80rpx;
color: #fff;
background: v-bind('Color');
border-radius: 10rpx;
font-size: 30rpx;
position: fixed;
bottom: 30rpx;
left: 3%;
}
.flexc{
display: flex;
align-items: center;
justify-content: center;
}
.flex{
display: flex;
align-items: center;
justify-content: space-between;
}
}
.itemBox{
.title{
font-size: 30rpx;
font-weight: 600;
text-align: center;
line-height: 80rpx;
}
.content{
height: calc(80vh - 80rpx);
overflow: auto;
padding: 1rpx 20rpx 20rpx;
box-sizing: border-box;
background-color: #f2f2f2;
}
.item{
margin-top: 20rpx;
box-sizing: border-box;
font-size: 28rpx;
background: #fff;
padding: 0 20rpx;
border-radius: 10rpx;
.one{
line-height: 70rpx;
border-bottom: 1px solid #e8e8e8;
text{
color: #9D9D9D;
}
}
.two{
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1px solid #f7f7f7;
.cont{
width: calc(100% - 180rpx);
display: flex;
flex-direction: column;
justify-content: space-between;
.tit{
.sku{
font-size: 26rpx;
color: #888;
}
}
.btm{
.price{
font-size: 30rpx;
}
text{
font-size: 24rpx;
color: #9D9D9D;
}
}
}
image{
width: 160rpx;
height: 160rpx;
}
}
}
.noMore{
text-align: center;
font-size: 24rpx;
color: #999;
margin: auto;
padding: 30rpx 0;
width: 100%;
}
.loadbox{
padding: 30rpx 0;
text-align: center;
color: #666;
}
}
</style>