This commit is contained in:
donqi 2022-09-26 02:31:29 +08:00
parent 0a2a568a12
commit e0db5cb26d
7 changed files with 442 additions and 28 deletions

35
common/js/dateUtil.js Normal file
View File

@ -0,0 +1,35 @@
export default {
dateCache: null,
countDownDiffCache: null,
countDownDiff(dateStr) {
if (dateStr == this.dateCache) {
return this.countDownDiffCache;
}
let dayTimes = 24*60*60*1000;
let hourTimes = 60*60*1000;
let minTimes = 60*1000;
let secondsTimes = 1000;
let dateTimesDiff = new Date(dateStr).getTime() - new Date().getTime();
let day = Math.floor(dateTimesDiff / dayTimes);
let leftOver = dateTimesDiff % dayTimes;
let hour = Math.floor(leftOver / hourTimes);
leftOver = leftOver % hourTimes;
let min = Math.floor(leftOver / minTimes);
leftOver = leftOver % minTimes;
let seconds = Math.floor(leftOver / secondsTimes);
leftOver = leftOver % secondsTimes;
this.dateCache = dateStr;
this.countDownDiffCache = {
day: day,
hour: hour,
min: min,
seconds: seconds
}
return this.countDownDiffCache;
},
addHours(dateStr, hourAmount) {
let date = new Date(dateStr);
date.setHours(date.getHours() + hourAmount);
return date;
}
}

View File

@ -1,6 +1,7 @@
import globalData from '@/common/js/globalData.js';
export default {
address: 'https://www.opsoul.com',
// 异步接口拦截
addInterceptor() {
uni.addInterceptor('request', {
@ -11,7 +12,7 @@ export default {
})
// request 触发前拼接 url
args.url = 'https://www.opsoul.com' + args.url;
// args.url = 'http://120.79.136.57' + args.url;
// args.url = 'http://192.168.2.20:80' + args.url;
// args.url = 'http://127.0.0.1:80' + args.url;
if (args.data && Object.prototype && Object.prototype.toString.call(args.data) === '[object Object]') {
args.data.deptId = globalData.deptId;
@ -392,11 +393,22 @@ export default {
name: 'uploadFile'
})
let resStr = res[1].data;
let resObj = {};
let resObj = null;
if (resStr != null && resStr.length > 0) {
resObj = JSON.parse(resStr);
try {
resObj = JSON.parse(resStr);
} catch(e) {
console.log(e)
}
}
return resObj;
if (!resObj || resObj.code !== 0) {
uni.showToast({
icon: 'error',
title: '上传失败'
})
return '';
}
return resObj.url;
},
// async qryOrderGoodsPage(params = {}) {
// let res = await uni.request({
@ -562,5 +574,41 @@ export default {
}
})
return res[1].data;
}
},
async getDetailListByMasterId(params = {}) {
let res = await uni.request({
url: '/order/master/app/getDetailListByMasterId',
method: 'POST',
data: params.orderMasterId
})
return res[1].data;
},
async getAfterList() {
let res = await uni.request({
url: '/order/master/after/list',
method: 'POST',
data: {}
})
return res[1].data;
},
async addAfterServiceRecord(params = {}) {
let res = await uni.request({
url: '/worker/record/add',
method: 'POST',
data: params,
header: {
pageNum: params.pageNum,
pageSize: params.pageSize
}
})
return res[1].data;
},
async getOrderAfterServiceRecords(params = {}) {
let res = await uni.request({
url: '/worker/record/app/list',
method: 'POST',
data: params
})
return res[1].data;
},
}

View File

@ -7,6 +7,7 @@ import Data from './common/js/data.js';
import globalFun from './common/js/glogalFun.js';
import validate from './common/js/validate.js';
import request from './common/js/request.js';
import dateUtil from './common/js/dateUtil.js';
import globalData from './common/js/globalData.js';
import vertifyLogin from '@/components/vertify/vertify-login.vue';
import vertifyPhone from '@/components/vertify/vertify-phone.vue';
@ -31,6 +32,7 @@ Vue.prototype.$globalFun = globalFun;
Vue.prototype.$validate = validate;
Vue.prototype.$request = request;
Vue.prototype.$globalData = globalData;
Vue.prototype.$dateUtil = dateUtil;
Vue.config.productionTip = false

View File

@ -123,6 +123,14 @@
<text>待确认</text>
</view>
<view class="cu-item" @click="showMyOrders(servOrderTabList, 6, servOrderType)">
<view class="cuIcon-service">
<view class="cu-tag badge" v-if="myInfo.serOrderNum.afterServ > 0">
<block>{{myInfo.serOrderNum.afterServ}}</block>
</view>
</view>
<text>售后中</text>
</view>
<view class="cu-item" @click="showMyOrders(servOrderTabList, 7, servOrderType)">
<view class="cuIcon-forward">
<view class="cu-tag badge" v-if="myInfo.serOrderNum.wait2Forward > 0">
<block>{{myInfo.serOrderNum.wait2Forward}}</block>
@ -307,6 +315,9 @@
}, {
type: 4,
name: '待确认'
}, {
// type: 4,
name: '售后中'
}, {
type: 5,
name: '已完成'

View File

@ -0,0 +1,205 @@
<template>
<view class="cu-modal" :class="show?'show':''">
<view class="cu-dialog bg-white">
<view class="cu-bar">
<view class="content">{{afterServiceType === 1 ? '退单退款' : '发起售后'}}</view>
<view class="action" @click="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding text-left">
<view class="flex justify-start align-center">
<view class="title">选择子单</view>
<my-uni-combox class="form-val-area inline-input" :candidates="detailList" placeholder="请选择" :showField="'remark'"
v-model="detailObj">
</my-uni-combox>
</view>
<view class="flex justify-start align-center margin-top-sm">
<view class="title">申请原因</view>
<my-uni-combox class="form-val-area inline-input" :candidates="customerReasonTypeArr" placeholder="请选择" :showField="'name'"
v-model="customerReasonType">
</my-uni-combox>
</view>
<view class="margin-top-sm flex justify-start align-center margin-top-sm">
<view>退款金额</view>
<input class="radius-input inline-input" v-model="refund" style="flex-basis: 70%;"></input>
</view>
<view class="margin-top-sm flex justify-start margin-top-sm">
<view>具体原因</view>
<textarea style="height: 200rpx;" class="solid radius text-left padding-sm inline-input"
v-model="remark" maxlength="-1"></textarea>
</view>
<!-- 上传图片 -->
<view class="padding-top">
<view class="grid col-3 grid-square flex-sub margin-top-sm">
<view class="bg-img" v-for="(item,index) in imgList" :key="index"
@tap="viewImage($event, imgList)" :data-url="item">
<image :src="item" mode="aspectFill"></image>
<view class="cu-tag bg-red" @tap.stop="delImg($event, imgList)" :data-index="index">
<text class='cuIcon-close'></text>
</view>
</view>
<view class="solids" @tap="chooseImgList(e, imgList)" v-if="imgList.length < 3">
<text class='cuIcon-cameraadd'></text>
</view>
</view>
</view>
</view>
<view class="cu-bar solid-top">
<view class="action margin-0 flex-sub text-black" @click="hideModal">取消</view>
<view class="action margin-0 flex-sub text-main-color solid-left" @click="apply">确认</view>
</view>
</view>
</view>
</template>
<script>
import myUniCombox from '@/components/uni-combox/my-uni-combox.vue';
export default {
name: 'applyAfterSale',
components: {
myUniCombox
},
props: {
show: {
type: Boolean,
default: false
},
data: {
type: Object,
default: {}
}
},
data() {
return {
show: false,
afterServiceType: 2, // 1退2
customerReasonType: null,
refund: null,
remark: null,
imgList: [],
detailList: [],
detailObj: null,
toUpdateStatus: false
}
},
methods: {
async init(curOrder) {
let res = await this.$request.getDetailListByMasterId({
orderMasterId: curOrder.orderMasterId
});
if (res && res.code === 0) {
this.detailList = res.data;
}
},
showModal(curOrder, params) {
this.init(curOrder);
this.afterServiceType = params.afterServiceType;
this.toUpdateStatus = params.toUpdateStatus;
this.show = true;
},
hideModal(e) {
this.resetData();
this.$emit('cancel');
this.show = false;
},
resetData() {
this.afterServiceType = null;
this.customerReasonType = null;
this.data = null;
this.refund = null;
this.imgList = [];
this.remark = null;
},
chooseImgList(e, imgList) {
uni.chooseImage({
count: 3 - imgList.length, //9
sizeType: ['original', 'compressed'], //
sourceType: ['album'], //
success: (res) => {
uni.showLoading({
title: '上传中',
mask: true
});
res.tempFilePaths.forEach((tmpUrl, index) => {
this.$request.uploadFile(tmpUrl).then((url) => {
imgList.push(url);
if (index === res.tempFilePaths.length - 1) {
uni.hideLoading();
}
});
});
}
});
},
viewImage(e, imgList) {
uni.previewImage({
urls: imgList,
current: e.currentTarget.dataset.url
});
},
delImg(e, imgList) {
uni.showModal({
title: '',
content: '确定要删除这张图片吗?',
cancelText: '取消',
confirmText: '确定',
success: res => {
if (res.confirm) {
imgList.splice(e.currentTarget.dataset.index, 1)
}
}
})
},
async apply() {
let imgObjList = [];
this.imgList.forEach(url => {
imgObjList.push({
imgUrl: url,
imgUploadBy: 1
})
})
let res = await this.$request.addAfterServiceRecord({
customerReasonType: this.customerReasonType,
customerReason: this.remark,
orderDetailId: this.detailObj.orderDetailId,
operType: this.afterServiceType,
refund: this.refund,
imgsList: imgObjList,
createBy: 1
});
if (res && res.code === 0) {
let updateStatusRes = {
code: 0
}
if (this.toUpdateStatus) {
updateStatusRes = await this.$request.updateOrder({
id: this.data.orderMasterId,
orderStatus: 3
});
}
if (updateStatusRes && updateStatusRes.code === 0) {
uni.showToast({
icon: 'success',
duration: 1000
})
this.hideModal();
this.$emit('confirmFeedback');
return;
}
}
uni.showToast({
icon: 'error',
duration: 1000
})
}
},
}
</script>
<style scoped>
.inline-input {
flex-basis: 74%;
}
</style>

View File

@ -73,12 +73,7 @@
<view>
<button class="cu-btn sm bg-yellow margin-right-sm"
@click="updateFinisheStatus(shopOrder, 5, false)">确认完单</button>
<!-- <button class="cu-btn sm bg-yellow margin-right-sm"
@click="updateFinisheStatus(shopOrder, 3, true)">拒绝完单</button> -->
<!-- <button v-if="shopOrder.finishOrder.finishStatus === 2"
class="cu-btn sm bg-yellow margin-right-sm" disabled type="">已确认完单</button>
<button v-if="shopOrder.finishOrder.finishStatus === -1"
class="cu-btn sm bg-yellow margin-right-sm" disabled type="">已拒绝完单</button> -->
<button class="cu-btn sm bg-yellow margin-right-sm" @click="showModalByRef('applyAfterService', shopOrder, {afterServiceType: 2, toUpdateStatus: true})">拒绝完单</button>
</view>
</view>
</view>
@ -111,17 +106,20 @@
</view>
<load-status-bar ref="loadStatusBar" @loadMore="loadOrderPage"></load-status-bar>
<confirm-modal ref="confirmModal" :content="'是否确定取消订单?'" @confirm="cancelOrder" @cancel="blurCurOrder"></confirm-modal>
<apply-after-service ref="applyAfterService" :data="curOrder" @confirmFeedback="reloadOrderPage" @cancel="blurCurOrder"></apply-after-service>
</view>
</template>
<script>
import productPicked from '@/pages/my/components/product-picked.vue';
import loadStatusBar from '@/components/custom-bar/load-status-bar.vue';
import applyAfterService from '@/pages/my/components/modal/apply-after-service.vue';
export default {
components: {
productPicked,
loadStatusBar
loadStatusBar,
applyAfterService
},
data() {
return {
@ -187,7 +185,12 @@
params.payStatus = 0;
params.exceptOrderStatus = 6;
}
let res = await this.$request.qryOrderPage(params);
let res = null;
if (this.tabCur === 6) {
res = await this.$request.getAfterList();
} else {
res = await this.$request.qryOrderPage(params);
}
let rowsLength = res.rows.length;
if (rowsLength > 0) {
this.myOrders = this.myOrders.concat(res.rows);
@ -225,14 +228,15 @@
})
}
}
return res;
},
showServDetail(order) {
uni.navigateTo({
url: '/pages/my/serv-detail?order=' + encodeURIComponent(JSON.stringify(order))
})
},
showModalByRef(refName, curOrder) {
this.$refs[refName].showModal();
showModalByRef(refName, curOrder, params) {
this.$refs[refName].showModal(curOrder, params);
this.curOrder = curOrder;
},
blurCurOrder() {

View File

@ -117,6 +117,115 @@
<text>备注{{item.remark}}</text>
</view>
</view>
<view v-if="item.afterServiceRecordList && item.afterServiceRecordList.length" class="bg-white">
<view class="cu-bar">
<view class="action bar-first-action">
<text class="cuIcon-title text-main-color"></text> {{item.afterServiceRecordList[0].operType === 1 ? '退款记录' : '售后记录'}}
</view>
</view>
<view v-for="(afterServiceRecord, afterServiceRecordIndex) in item.afterServiceRecordList" class="solid-top padding-tb">
<view v-if="afterServiceRecord.createBy == 1">
<view class='cu-tag bg-main-color radius light'>客户发起</view>
<view v-if="afterServiceRecord.operType === 1">
<view class="margin-top-sm">
<text>退款申请</text>
<uni-countdown :show-colon="false" :backgroundColor="'#eee'"
:day="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).day"
:hour="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).hour"
:minute="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).min"
:second="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).seconds">
</uni-countdown>
</view>
<view class="margin-top-sm">
<text>退款金额</text>
<text>{{afterServiceRecord.refund}}</text>
</view>
<view class="margin-top-sm">
<text>退款原因</text>
<text>{{afterServiceRecord.customerReason}}</text>
</view>
<view class="grid col-3 grid-square flex-sub margin-top-sm">
<view class="bg-img" v-for="(imgObj, imgIndex) in afterServiceRecord.imgsList" :key="imgIndex">
<image :src="imgObj.imgUrl" @tap="viewImage($event, [imgObj.imgUrl])" :data-url="imgObj.imgUrl" mode="aspectFill"></image>
</view>
</view>
</view>
<view v-else-if="afterServiceRecord.operType === 2">
<view class="flex justify-start align-end">
<text>待处理售后</text>
<uni-countdown :show-colon="false" :backgroundColor="'#eee'"
:day="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).day"
:hour="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).hour"
:minute="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).min"
:second="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).seconds">
</uni-countdown>
</view>
<view>
<text>售后原因</text>
<text>{{afterServiceRecord.customerReason}}</text>
</view>
<view class="margin-top-sm">
<text>完成操作点击处理完成提交由客服回访</text>
</view>
<view class="grid col-3 grid-square flex-sub margin-top-sm">
<view class="bg-img" v-for="(imgObj, imgIndex) in afterServiceRecord.imgsList" :key="imgIndex">
<image :src="imgObj.imgUrl" @tap="viewImage($event, [imgObj.imgUrl])" :data-url="imgObj.imgUrl" mode="aspectFill"></image>
</view>
</view>
</view>
</view>
<view v-if="afterServiceRecord.updateBy == 2">
<view class='cu-tag bg-main-color radius light'>师傅反馈</view>
<view v-if="afterServiceRecord.operType === 1">
<view class="margin-top-sm">
<text>退款申请</text>
<uni-countdown :show-colon="false" :backgroundColor="'#eee'"
:day="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).day"
:hour="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).hour"
:minute="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).min"
:second="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).seconds">
</uni-countdown>
</view>
<view class="margin-top-sm">
<text>退款金额</text>
<text>{{afterServiceRecord.agreedRefund ? afterServiceRecord.agreedRefund : afterServiceRecord.refund}}</text>
</view>
<view class="margin-top-sm">
<text>退款原因</text>
<text>{{afterServiceRecord.workerFeedbackReason}}</text>
</view>
<view class="grid col-3 grid-square flex-sub margin-top-sm">
<view class="bg-img" v-for="(imgObj, imgIndex) in afterServiceRecord.imgsList" :key="imgIndex">
<image :src="imgObj.imgUrl" @tap="viewImage($event, [imgObj.imgUrl])" :data-url="imgObj.imgUrl" mode="aspectFill"></image>
</view>
</view>
</view>
<view v-else-if="afterServiceRecord.operType === 2">
<view class="flex justify-start align-end">
<text>待处理售后</text>
<uni-countdown :show-colon="false" :backgroundColor="'#eee'"
:day="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).day"
:hour="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).hour"
:minute="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).min"
:second="$dateUtil.countDownDiff($dateUtil.addHours(afterServiceRecord.createTime, 24)).seconds">
</uni-countdown>
</view>
<view>
<text>售后原因</text>
<text>{{afterServiceRecord.workerFeedbackReason}}</text>
</view>
<view class="margin-top-sm">
<text>完成操作点击处理完成提交由客服回访</text>
</view>
<view class="grid col-3 grid-square flex-sub margin-top-sm">
<view class="bg-img" v-for="(imgObj, imgIndex) in afterServiceRecord.imgsList" :key="imgIndex">
<image :src="imgObj.imgUrl" @tap="viewImage($event, [imgObj.imgUrl])" :data-url="imgObj.imgUrl" mode="aspectFill"></image>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 订单编码和时间 -->
<view class="bg-white margin-top-sm padding margin-lr-sm margin-bottom-with-bar">