Browse Source

add order refund logic

tid1731
刘嘉炜 11 months ago
parent
commit
103aecdd72
  1. 38
      src/components/fixed_bar/fixed_bar.vue
  2. 22
      src/components/order_refund/button.vue
  3. 26
      src/components/order_refund/fixed.vue
  4. 215
      src/components/order_refund/modal.vue
  5. 74
      src/components/order_refund_modal/index.vue
  6. 19
      src/subpackage/device/components/order/reservation_site_detail/reservation_site_detail.vue
  7. 50
      src/subpackage/device/pages/order_details/order_details.vue
  8. 2
      src/utils/util.js

38
src/components/fixed_bar/fixed_bar.vue

@ -0,0 +1,38 @@
<template>
<view class="fixed-bar" :style="'padding-top:'+ fbHeight +'px;'">
<view class="fb-fixed" id="fb">
<slot></slot>
</view>
</view>
</template>
<script>
import { getNodeMes } from '@/utils/util'
export default {
data(){
return {
fbHeight: 0,
}
},
mounted() {
getNodeMes('#fb', this).then(res => {
this.fbHeight = res?.height || 0
console.log(res)
})
},
}
</script>
<style lang="scss">
.fixed-bar{
}
.fb-fixed{
padding-top: 20upx;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 10;
}
</style>

22
src/components/order_refund/button.vue

@ -0,0 +1,22 @@
<template>
<view class="order-refund-button" @click="$emit('click')">
<slot>退款</slot>
</view>
</template>
<script>
export default {
}
</script>
<style lang="scss">
.order-refund-button{
width: 192upx;
text-align: center;
border-radius: 10upx;
background-color: #fff;
border: 2upx solid $mColor;
@include flcw(32upx, 84upx, $mColor, 500);
}
</style>

26
src/components/order_refund/fixed.vue

@ -0,0 +1,26 @@
<template>
<fixed-bar>
<view class="order-refund-fixed">
<or-button @click="$emit('click:button')"></or-button>
</view>
</fixed-bar>
</template>
<script>
import fixedBar from "../fixed_bar/fixed_bar.vue";
import orButton from "./button.vue";
export default {
components: {
fixedBar,
orButton
}
}
</script>
<style lang="scss">
.order-refund-fixed{
padding: 10upx 24upx;
background: #F2F2F7;
@include ctf(flex-end);
}
</style>

215
src/components/order_refund/modal.vue

@ -0,0 +1,215 @@
<template>
<view class="order-refund-modal">
<view class="orm-mask" v-show="isShow">
<view class="om-content">
<image class="oc-close" mode="aspectFit" src="../../static/images/icon/x_close.png" @click="hide"></image>
<view class="oc-title">退款</view>
<view class="oc-section">
<view class="os-info">
<view class="oi-name">{{ refundInfo.stadium_name || '' }}</view>
<view class="oi-line">订单编号{{ refundInfo.order_no || '' }}</view>
<view class="oi-line">手机号码{{ refundInfo.mobile || '' }}</view>
<view class="os-ipts">
<view class="oi-item">
<view class="oi-name">
<text class="on-txt">*</text>
退款金额
</view>
<view class="oi-right">
<input
class="or-ipt"
type="number"
v-model="iptInfo.refund_amount"
:disabled="refundInfo.refund_times > 0"
:class="{ 'or-disabled': refundInfo.refund_times > 0 }"
/>
<view class="or-tip">可退{{ refundInfo.refundable_amount || 0 }}</view>
</view>
</view>
<view class="oi-item">
<view class="oi-name">
<text class="on-txt">*</text>
退款积分
</view>
<view class="oi-right">
<input
class="or-ipt" type="number"
v-model="iptInfo.refund_integral"
:disabled="refundInfo.refund_times > 0"
:class="{ 'or-disabled': refundInfo.refund_times > 0 }"
/>
<view class="or-tip">可退{{ refundInfo.refundable_integral || 0 }}积分</view>
</view>
</view>
</view>
</view>
</view>
<view class="oc-btns">
<view class="ob-item" @click="cancelBtn">取消</view>
<view class="ob-item" @click="confirmBtn">确认</view>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* 全部订单都能退两次, 所有订单最多只能退2次款
* 只要订单金额是未全退的都能退
* 0元订单不能退
*
*/
export default {
data() {
return {
isShow: false,
refundInfo: {
/**
* @param {String} stadium_name 店铺名称
* @param {String} order_no 订单编号
* @param {String} mobile 手机号码
* @param {String} refundable_amount 退款金额
* @param {String} refundable_integral 退款积分
* @param {Number} refund_times 退款次数
* @param {Function} cancel 取消回调
* @param {Function} confirm 确认回调
*/
},
iptInfo: {
refund_amount: '',
refund_integral: ''
}
}
},
methods: {
show(initData){
this.isShow = true;
this.init(initData);
},
init(data){
this.iptInfo.refund_amount = data?.refundable_amount || '0';
this.iptInfo.refund_integral = data?.refundable_integral || '0';
this.refundInfo = data;
},
hide(){
this.isShow = false;
},
cancelBtn() {
this.hide();
this.$emit('click:cancel');
this.refundInfo?.cancel?.(0);
},
confirmBtn() {
let { iptInfo, refundInfo } = this;
this.$emit('click:confirm');
this.refundInfo?.confirm?.(iptInfo);
}
}
}
</script>
<style lang="scss">
.order-refund-modal{}
.orm-mask{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,.5);
z-index: 10;
}
.om-content{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding-bottom: 80upx;
width: 620upx;
border-radius: 10px;
background: #fff;
.oc-close{
position: absolute;
top: 30upx;
right: 30upx;
width: 34upx;
height: 34upx;
}
.oc-title{
padding-top: 78upx;
text-align: center;
@include flcw(32upx, 44upx, #333, 500);
}
.oc-section{
padding: 30upx 30upx 0;
@include ctf(center);
.os-info{
.oi-name{
@include flcw(28upx, 48upx, #333);
}
.oi-line{
@include flcw(28upx, 48upx, #9C9C9F);
}
.os-ipts{
padding-top: 34upx;
.oi-item{
display: flex;
align-items: flex-start;
.oi-name{
@include flcw(28upx, 56upx, #333333);
.on-txt{
color: #EA5061;
}
}
.oi-right{
margin-left: 16upx;
flex-shrink: 0;
width: 312upx;
.or-ipt{
display: block;
box-sizing: border-box;
padding: 0 20upx;
width: 100%;
height: 56upx;
border-radius: 10upx;
border: 2upx solid #D8D8D8;
@include flcw(28upx, 48upx, #9C9C9F);
&.or-disabled{
background: #cecece;
color: #9C9C9F;
}
}
.or-tip{
padding-left: 8upx;
@include flcw(24upx, 48upx, #EA5061);
@include tHide;
}
}
}
}
}
}
.oc-btns{
margin-top: 32upx;
padding: 0 54upx;
@include ctf(space-between);
.ob-item{
width: 240upx;
height: 88upx;
text-align: center;
border: 2upx solid $mColor;
border-radius: 10upx;
@include flcw(32upx, 84upx, $mColor, 500);
&+.ob-item{
background: $mColor;
color: #fff;
}
}
}
}
</style>

74
src/components/order_refund_modal/index.vue

@ -1,14 +1,14 @@
<template>
<view class="order-refund-modal">
<view class="orm-mask">
<view class="orm-mask" v-show="isShow">
<view class="om-content">
<image class="oc-close" mode="aspectFit" src="../../static/images/icon/x_close.png"></image>
<image class="oc-close" mode="aspectFit" src="../../static/images/icon/x_close.png" @click="hide"></image>
<view class="oc-title">退款</view>
<view class="oc-section">
<view class="os-info">
<view class="oi-name">欧轩智能羽毛球馆永泰店</view>
<view class="oi-line">订单编号20195171564566</view>
<view class="oi-line">手机号码218316553478</view>
<view class="oi-name">{{ refundInfo.stadium_name || '' }}</view>
<view class="oi-line">订单编号{{ refundInfo.order_no || '' }}</view>
<view class="oi-line">手机号码{{ refundInfo.mobile || '' }}</view>
<view class="os-ipts">
<view class="oi-item">
@ -17,8 +17,14 @@
退款金额
</view>
<view class="oi-right">
<input class="or-ipt" type="number" />
<view class="or-tip">可退240元</view>
<input
class="or-ipt"
type="number"
v-model="iptInfo.refund_amount"
:disabled="refundInfo.refund_times > 0"
:class="{ 'or-disabled': refundInfo.refund_times > 0 }"
/>
<view class="or-tip">可退{{ refundInfo.refundable_amount || 0 }}</view>
</view>
</view>
<view class="oi-item">
@ -27,8 +33,13 @@
退款积分
</view>
<view class="oi-right">
<input class="or-ipt" type="number" />
<view class="or-tip">可退2积分</view>
<input
class="or-ipt" type="number"
v-model="iptInfo.refund_integral"
:disabled="refundInfo.refund_times > 0"
:class="{ 'or-disabled': refundInfo.refund_times > 0 }"
/>
<view class="or-tip">可退{{ refundInfo.refundable_integral || 0 }}积分</view>
</view>
</view>
</view>
@ -45,18 +56,57 @@
</template>
<script>
/**
* 全部订单都能退两次, 所有订单最多只能退2次款
* 只要订单金额是未全退的都能退
* 0元订单不能退
*
*/
export default {
data() {
return {
isShow: false
isShow: false,
refundInfo: {
/**
* @param {String} stadium_name 店铺名称
* @param {String} order_no 订单编号
* @param {String} mobile 手机号码
* @param {String} refundable_amount 退款金额
* @param {String} refundable_integral 退款积分
* @param {Number} refund_times 退款次数
* @param {Function} cancel 取消回调
* @param {Function} confirm 确认回调
*/
},
iptInfo: {
refund_amount: '',
refund_integral: ''
}
}
},
methods: {
show(initData){
this.isShow = true;
this.init(initData);
},
init(data){
this.iptInfo.refund_amount = data?.refundable_amount || '0';
this.iptInfo.refund_integral = data?.refundable_integral || '0';
this.refundInfo = data;
},
hide(){
this.isShow = false;
},
cancelBtn() {
this.hide();
this.$emit('click:cancel');
this.refundInfo?.cancel?.(0);
},
confirmBtn() {
let { iptInfo, refundInfo } = this;
this.$emit('click:confirm');
this.refundInfo?.confirm?.(iptInfo);
}
}
}
@ -129,6 +179,10 @@ export default {
border-radius: 10upx;
border: 2upx solid #D8D8D8;
@include flcw(28upx, 48upx, #9C9C9F);
&.or-disabled{
background: #cecece;
color: #9C9C9F;
}
}
.or-tip{
padding-left: 8upx;

19
src/subpackage/device/components/order/reservation_site_detail/reservation_site_detail.vue

@ -136,13 +136,16 @@
</view>
<!-- 2022/01/04 PM: 禁用退款功能 -->
<view class="rs-btn" @click="refunndBtn" v-if="orderInfo.pay_status == 1 || orderInfo.pay_status == 2">退款</view>
<order-refund-fixed @click:button="refunndBtn"></order-refund-fixed>
</view>
</template>
<script>
import orderRefundFixed from '@/components/order_refund/fixed.vue'
export default {
components: {
'order-refund-fixed': orderRefundFixed
},
props: {
orderInfo: {
type: Object,
@ -191,7 +194,8 @@ export default {
return _obj[`${_status}`] || '-'
},
refunndBtn(){
this.$emit('refundbtn');
// this.$emit('refundbtn');
this.$emit('click:refund');
}
}
@ -344,15 +348,6 @@ export default {
}
}
.rs-btn{
margin: 24rpx 24rpx 0 auto;
width: 192upx;
line-height: 88upx;
border-radius: 10upx;
background-color: #fff;
text-align: center;
color: $themeColor;
}
}

50
src/subpackage/device/pages/order_details/order_details.vue

@ -2,7 +2,12 @@
<view class="order-details">
<block v-if="optionsQuery.order_type==3">
<!-- pageInfo.order_type 场次(0)/人次(1) -->
<reservation-site-detail :orderInfo="pageInfo" v-if="pageInfo.order_type == 0" @refundbtn='refundBtn' ></reservation-site-detail>
<reservation-site-detail
v-if="pageInfo.order_type == 0"
:orderInfo="pageInfo"
@refundbtn='refundBtn'
@click:refund="siteDetailRefund"
></reservation-site-detail>
<reservation-people-detail
v-if="pageInfo.order_type == 1"
:orderInfo="pageInfo"
@ -38,7 +43,10 @@
ref="ticketCheckModal"
@confirm="verifyConfirm"
></ticket-check>
<order-refund-modal></order-refund-modal>
<order-refund-modal
ref="orderRefundModal"
></order-refund-modal>
</view>
</template>
@ -102,6 +110,44 @@
})
},
methods: {
// -退
siteDetailRefund(){
let { pageInfo } = this;
this.$refs.orderRefundModal.show({
stadium_name: pageInfo?.stadium_name ?? '',
order_no: pageInfo?.order_no ?? '',
mobile: pageInfo?.mobile ?? '',
refundable_amount: pageInfo?.extension?.refundable_amount ?? 0,
refundable_integral: pageInfo?.extension?.refundable_integral ?? 0,
refund_times: pageInfo?.refunds?.length ?? 0,
confirm: e => {
this.siteAndPeopleRefund({
order_no: pageInfo?.order_no ?? '',
amount: e?.refund_amount || 0,
integral: e?.refund_integral || 0,
})
}
});
},
// -退(/)
siteAndPeopleRefund({ order_no = '', amount = 0, integral = 0}){
util.showLoad();
deviceServer.get({
url: deviceApi.orderRefund,
data: { order_no, amount, integral },
isDefaultGet: false
})
.then(res=>{
util.hideLoad();
if(res.data.code == 0){
util.showNone(res.data.message || '操作成功!');
setTimeout(this.refreshPage, 1200);
}else{
util.showNone(res.data.message || '操作失败!');
}
})
.catch(util.hideLoad)
},
verifyConfirm(){
let { optionsQuery } = this;
this.getPageInfo({

2
src/utils/util.js

@ -186,7 +186,7 @@ function previousPageFunction({fnName,query}){
}
// 获取节点信息
function getNodeMes(selector,_this=null){
export function getNodeMes(selector,_this=null){
return new Promise(rs=>{
let query = _this ? uni.createSelectorQuery().in(_this) : uni.createSelectorQuery();
query.select(selector).boundingClientRect(res=>{

Loading…
Cancel
Save