【退款】

1、退款详情
2、退货界面
pull/1/MERGE
YunaiV 2023-08-18 19:14:39 +08:00
parent 40883fda3b
commit a4846939dd
8 changed files with 288 additions and 138 deletions

View File

@ -1,5 +1,11 @@
import request from "@/utils/request.js";
export function getAfterSale(id) {
return request.get("app-api/trade/after-sale/get", {
id
});
}
export function getAfterSalePage(data) {
return request.get("app-api/trade/after-sale/page", data);
}
@ -13,3 +19,11 @@ export function getAfterSaleReasonList(way) {
export function createAfterSale(data) {
return request.post("app-api/trade/after-sale/create", data);
}
export function cancelAfterSale(id) {
return request.delete("app-api/trade/after-sale/cancel?id=" + id);
}
export function deliveryAfterSale(data) {
return request.put("app-api/trade/after-sale/delivery", data);
}

View File

@ -16,3 +16,8 @@ export function getDeliveryPickUpStore(id) {
id
});
}
// 获得快递公司列表
export function getDeliveryExpressList() {
return request.get("app-api/trade/delivery/express/list");
}

View File

@ -361,6 +361,12 @@
"navigationBarTitleText": "申请退货"
}
},
{
"path": "goods_return_delivery/index",
"style": {
"navigationBarTitleText": "填写退货物流"
}
},
{
"path": "login/index",
"style": {

View File

@ -1,6 +1,7 @@
<template>
<view>
<view class='order-details'>
<!-- 当前状态 -->
<view class='header bg-color'>
<view class='picTxt acea-row row-middle'>
<!-- 状态图 -->

View File

@ -18,7 +18,7 @@
<view class='item acea-row row-between-wrapper'>
<view>售后方式</view>
<!-- 如果未发货则只能退款 -->
<view class="" v-if="order.status === 20">退</view>
<view class="" v-if="order.status === 10">退</view>
<picker v-else class='num' @change="wayChange"
:value="wayIndex" :range="ways">
<view class="picker acea-row row-between-wrapper">
@ -205,13 +205,12 @@
applyDescription: formData.applyDescription,
applyPicUrls: this.applyPicUrls,
}).then(res => {
// TODO
this.$util.Tips({
title: '申请成功',
icon: 'success'
}, {
tab: 5,
url: '/pages/users/user_return_list/index?isT=1'
url: '/pages/users/user_return_detail/index?id=' + res.data
});
}).catch(err=>{
return this.$util.Tips({

View File

@ -0,0 +1,135 @@
<template>
<view>
<!-- TODO 芋艿退货地址后续写在这里还是写在退款详情界面 -->
<form @submit="subRefund" report-submit='true'>
<view class='apply-return'>
<view class='list borRadius14'>
<view class='item acea-row row-between-wrapper'>
<view>物流公司</view>
<picker class='num' @change="bindPickerChange" :value="expressIndex"
:range="expresses" range-key="name">
<view class="picker acea-row row-between-wrapper">
<view class='reason'>{{ expresses[expressIndex].name }}</view>
<text class='iconfont icon-jiantou'></text>
</view>
</picker>
</view>
<view class='item textarea acea-row row-between'>
<view>物流单号</view>
<input placeholder='请填写物流单号' class='num' name="logisticsNo" placeholder-class='placeholder' />
</view>
<button class='returnBnt bg-color' form-type="submit">提交</button>
</view>
</view>
</form>
</view>
</template>
<script>
import { toLogin } from '@/libs/login.js';
import { mapGetters } from "vuex";
import * as AfterSaleApi from '@/api/trade/afterSale.js';
import * as DeliveryApi from '@/api/trade/delivery.js';
export default {
data() {
return {
id: 0, //
expresses: [], //
expressIndex: 0, // expresses
};
},
computed: mapGetters(['isLogin']),
watch:{
isLogin:{
handler: function(newV, oldV) {
if (newV) {
this.getExpressList();
}
},
deep:true
}
},
onLoad: function (options) {
if (!this.isLogin) {
toLogin();
return;
}
if (!options.id) {
return this.$util.Tips({
title: '缺少退款编号,无法查看'
},{
tab: 3,
url:1
});
}
this.id = parseInt(options.id);
this.getExpressList();
},
methods: {
onLoadFun:function() {
this.getExpressList();
},
/**
* 获得快递公司
*/
getExpressList: function() {
DeliveryApi.getDeliveryExpressList().then(res => {
this.expresses = res.data;
})
},
/**
* 选择快递公司
*/
bindPickerChange: function(e) {
this.$set(this, 'expressIndex', e.detail.value);
},
/**
* 申请退货
*/
subRefund:function(e) {
const formData = e.detail.value;
AfterSaleApi.deliveryAfterSale({
id: this.id,
logisticsId: this.expresses[this.expressIndex].id,
logisticsNo: formData.logisticsNo,
}).then(res => {
this.$util.Tips({
title: '填写退货成功',
icon: 'success'
}, {
tab: 5,
url: '/pages/users/user_return_detail/index?id=' + this.id
});
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
}
}
}
</script>
<style scoped lang="scss">
.apply-return{
padding: 20rpx 30rpx 70rpx 30rpx;
}
.apply-return .list{background-color:#fff;margin-top:18rpx;padding:0 24rpx 70rpx 24rpx;}
.apply-return .list .item{min-height:90rpx;border-bottom:1rpx solid #eee;font-size:30rpx;color:#333;}
.apply-return .list .item .num{color:#282828;width:427rpx;text-align:right;}
.apply-return .list .item .num .picker .reason{width:385rpx;}
.apply-return .list .item .num .picker .iconfont{color:#666;font-size:30rpx;margin-top:2rpx;}
.apply-return .list .item.textarea{padding:24rpx 0;}
.apply-return .list .item textarea{height:100rpx;font-size:30rpx;}
.apply-return .list .item .placeholder{color:#bbb;}
.apply-return .list .item .title{height:95rpx;width:100%;}
.apply-return .list .item .title .tip{font-size:30rpx;color:#bbb;}
.apply-return .list .item .upload{padding-bottom:36rpx;}
.apply-return .list .item .upload .pictrue{border-radius: 14rpx; margin:22rpx 23rpx 0 0;width:156rpx;height:156rpx;position:relative;font-size:24rpx;color:#bbb;}
.apply-return .list .item .upload .pictrue:nth-of-type(4n){margin-right:0;}
.apply-return .list .item .upload .pictrue image{width:100%;height:100%;border-radius:14rpx;}
.apply-return .list .item .upload .pictrue .icon-guanbi1{position:absolute;font-size:45rpx;top:-10rpx;right:-10rpx;}
.apply-return .list .item .upload .pictrue .icon-icon25201{color:#bfbfbf;font-size:50rpx;}
.apply-return .list .item .upload .pictrue:nth-last-child(1){border:1rpx solid #ddd;box-sizing:border-box;}
.apply-return .returnBnt{font-size:32rpx;color:#fff;width:100%;height:86rpx;border-radius:50rpx;text-align:center;line-height:86rpx;margin:43rpx auto;}
</style>

View File

@ -1,34 +1,86 @@
<template>
<view>
<view class='order-details'>
<view class="pad30">
<!-- TODO 芋艿退款各种 -->
<view class='nav refund'>
<view class="title">
<image src="/static/images/shuoming.png" mode="" />
{{order.refundStatus==1?'商家审核中':order.refundStatus==2?'商家已退款':'商家拒绝退款'}}
<!-- 当前状态 -->
<view class='header bg-color'>
<view class='picTxt acea-row row-middle'>
<!-- 状态图 -->
<view class='pictrue'>
<image v-if="afterSale.status === 10" src="@/static/images/order/status_0.gif" />
<image v-if="afterSale.status === 20" src="@/static/images/order/status_10.gif" />
<image v-if="afterSale.status === 30" src="@/static/images/order/status_20.gif" />
<image v-if="afterSale.status === 40" src="@/static/images/order/status_30a.gif" />
<image v-if="afterSale.status === 50" src="@/static/images/order/status_30b.gif" />
<image v-if="afterSale.status === 61" src="@/static/images/order/status_40.gif" />
<image v-if="afterSale.status === 62" src="@/static/images/order/status_40.gif" />
<image v-if="afterSale.status === 63" src="@/static/images/order/status_40.gif" />
</view>
<view class='data'>
<!-- 状态提示 -->
<view class='state' v-if="afterSale.status === 10">退</view>
<view class='state' v-if="afterSale.status === 20">退</view>
<view class='state' v-if="afterSale.status === 30">退退</view>
<view class='state' v-if="afterSale.status === 40">退</view>
<view class='state' v-if="afterSale.status === 50">退</view>
<view class='state' v-if="afterSale.status === 61">退</view>
<view class='state' v-if="afterSale.status === 62">退{{ afterSale.auditReason }}</view>
<view class='state' v-if="afterSale.status === 63">退{{ afterSale.auditReason }}</view> <!-- TODO -->
</view>
</view>
</view>
<view>
<view class='goodsStyle acea-row row-between borRadius14'>
<view class='pictrue'>
<image :src='afterSale.picUrl' />
</view>
<view class='text acea-row row-between'>
<view class='line2'>{{ afterSale.spuName }}</view>
<view class='attr line1' v-if="afterSale.properties">
<text v-for="property in afterSale.properties" style="padding-right: 2px">{{property.valueName}}</text>
</view>
<view class="con pad30">
{{
order.refundStatus==1 ? "您已成功发起退款申请,请耐心等待商家处理;退款前请与商家协商一致,有助于更好的处理售后问题":
order.refundStatus==2 ? "退款已成功受理,如商家已寄出商品请尽快退回;感谢您的支持" : "拒绝原因:" + order.refundReason
}}
</view>
</view>
<!-- TODO 芋艿退款订单详情 -->
<view class='wrapper borRadius14' >
<view class='item acea-row row-between'>
<view>收货人</view>
<view class='conter'>{{order.realName}}</view>
<view>退款金额</view>
<view class='conter'> {{ fen2yuan(afterSale.refundPrice) }}</view>
</view>
<view class='item acea-row row-between'>
<view>联系电话</view>
<view class='conter'>{{order.userPhone}}</view>
<view>售后方式</view>
<view class='conter'>{{ afterSale.way === 10 ? '仅退款' : '退款退货' }}</view>
</view>
<view class='item acea-row row-between'>
<view>收货地址</view>
<view class='conter'>{{order.userAddress}}</view>
<view>退款原因</view>
<view class='conter'>{{ afterSale.applyReason }}</view>
</view>
</view>
<view class='wrapper borRadius14' >
<view class='item acea-row row-between'>
<view>售后单号</view>
<view class='conter'>{{ afterSale.no }}</view>
</view>
<view class='item acea-row row-between'>
<view>申请时间</view>
<view class='conter'>{{ formatDate(afterSale.createTime) }}</view>
</view>
<view class='item acea-row row-between'>
<view>数量</view>
<view class='conter'>{{ afterSale.count }}</view>
</view>
</view>
</view>
<view>
<!-- 操作区域 -->
<view class='footer acea-row row-right row-middle'>
<view class="qs-btn" v-if="[20].includes(afterSale.status)" @click.stop="cancelAfterSale">
填写退货信息
</view>
<view class="qs-btn" v-if="[10, 20, 30].includes(afterSale.status)" @click.stop="cancelAfterSale">
撤销申请
</view>
</view>
</view>
@ -38,23 +90,14 @@
<script>
import { toLogin } from '@/libs/login.js';
import { mapGetters } from "vuex";
import * as TradeOrderApi from '@/api/trade/order.js';
import * as AfterSaleApi from '@/api/trade/afterSale.js';
import dayjs from '@/plugin/dayjs/dayjs.min.js';
import * as Util from '@/utils/util.js';
export default {
data() {
return {
orderId: 0,
orderItemId: 0,
order: {}, //
orderItem: {}, //
wayIndex: 0, // ways
ways: ['仅退款', '退款退货'], //
reasons: [], //
reasonIndex: 0, // reasons
applyPicUrls: [], //
id: 0, //
afterSale: {}, //
};
},
computed: mapGetters(['isLogin']),
@ -62,8 +105,7 @@
isLogin:{
handler: function(newV, oldV) {
if (newV) {
this.getOrderInfo();
this.getRefundReason();
this.getAfterSale();
}
},
deep:true
@ -74,110 +116,62 @@
toLogin();
return;
}
// if (!options.orderId || !options.orderItemId) {
// return this.$util.Tips({
// title:'id,退'
// },{
// tab: 3,
// url:1
// });
// }
// this.orderId = parseInt(options.orderId);
// this.orderItemId = parseInt(options.orderItemId);
// this.getOrderInfo();
// this.getRefundReason();
if (!options.id) {
return this.$util.Tips({
title: '缺少退款编号,无法查看'
},{
tab: 3,
url:1
});
}
this.id = parseInt(options.id);
this.getAfterSale();
},
methods: {
onLoadFun:function() {
this.getOrderInfo();
this.getRefundReason();
},
/**
* 获取订单详情
* 获取售后订单
*/
getOrderInfo:function(){
TradeOrderApi.getOrderDetail(this.orderId).then(res => {
//
const order = res.data;
this.order = order;
//
this.orderItem = order.items.find(item => item.id === this.orderItemId) || {};
getAfterSale: function() {
AfterSaleApi.getAfterSale(this.id).then(res => {
this.afterSale = res.data || {}
}).catch(err => {
return this.$util.Tips({
title: err
});
})
},
/**
* 更改售后方式
* 取消售后
*/
wayChange: function(e) {
this.$set(this, 'wayIndex', e.detail.value);
this.getRefundReason();
},
/**
* 获得售后方式
*/
getWay: function () {
return this.wayIndex === 0 ? 10 : 20
},
/**
* 获取退款理由
*/
getRefundReason: function() {
const way = this.getWay();
AfterSaleApi.getAfterSaleReasonList(way).then(res => {
this.reasons = res.data;
cancelAfterSale: function() {
uni.showModal({
title: '提示',
content: '确认取消该售后?',
success: res => {
if (!res.confirm) {
return;
}
AfterSaleApi.cancelAfterSale(this.id).then(() => {
this.$util.Tips({
title: '取消成功'
})
},
/**
* 选择售后原因
*/
bindPickerChange: function(e) {
this.$set(this, 'reasonIndex', e.detail.value);
},
/**
* 删除图片
*/
DelPic:function(index) {
this.applyPicUrls.splice(index, 1);
},
/**
* 上传文件
*/
uploadpic:function(){
this.$util.uploadImageOne({}, res => {
this.applyPicUrls.push(res.data);
this.$set(this, 'applyPicUrls', this.applyPicUrls);
this.getAfterSale();
}).catch((err) => {
this.$util.Tips({
title: err
})
this.getAfterSale();
});
}
});
},
/**
* 申请退货
*/
subRefund:function(e) {
const formData = e.detail.value;
AfterSaleApi.createAfterSale({
orderItemId: this.orderItemId,
way: this.getWay(),
refundPrice: this.orderItem.payPrice,
applyReason: this.reasons[this.reasonIndex],
applyDescription: formData.applyDescription,
applyPicUrls: this.applyPicUrls,
}).then(res => {
// TODO
this.$util.Tips({
title: '申请成功',
icon: 'success'
}, {
tab: 5,
url: '/pages/users/user_return_list/index?isT=1'
});
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
fen2yuan(price) {
return Util.fen2yuan(price)
},
formatDate: function(date) {
return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
}
}
}
@ -218,7 +212,7 @@
}
.order-details .header {
height: 250rpx;
height: 150rpx;
padding: 0 30rpx;
}

View File

@ -1,7 +1,7 @@
<template>
<view>
<view class='return-list pad30' v-if="orderList.length">
<view class='goodWrapper borRadius14' v-for="(item,index) in orderList" :key="index" @click='goOrderDetails(item.orderId)'>
<view class='goodWrapper borRadius14' v-for="(item,index) in orderList" :key="index" @click='goOrderDetails(item.id)'>
<!-- 根据状态展示 icon -->
<!-- TODO 芋艿需要优化下 icon目前没展示出来 -->
<view class='iconfont icon-shenqingzhong powder' v-if="[10].includes(item.status)" />
@ -89,21 +89,17 @@
this.getOrderList();
},
methods: {
onLoadFun() {
this.getOrderList();
},
/**
* 去订单详情
*/
goOrderDetails: function(order_id) {
if (!order_id) {
return that.$util.Tips({
goOrderDetails: function(id) {
if (!id) {
return this.$util.Tips({
title: '缺少订单号无法查看订单详情'
});
}
// TODO
uni.navigateTo({
url: '/pages/order_details/index?order_id=' + order_id + '&isReturen=1'
url: '/pages/users/user_return_detail/index?id=' + id
})
},