2025-05-08 09:16:37 +08:00
|
|
|
|
<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
|
2025-06-14 10:01:48 +08:00
|
|
|
|
this.desc = options.desc || ''
|
2025-05-08 09:16:37 +08:00
|
|
|
|
// 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>
|