刘嘉炜 5 months ago
parent
commit
361b20e9a4
  1. 2
      package.json
  2. 12121
      pnpm-lock.yaml
  3. 194
      src/components/end_billing_modal/end_billing_modal.vue
  4. 2
      src/components/fixed_bar/fixed_bar.vue
  5. 5
      src/components/order_refund/modal.vue
  6. 49
      src/components/order_refund/permission_btn.vue
  7. 185
      src/components/timing_order/timing_order.vue
  8. 1
      src/js/api.js
  9. 36
      src/pages.json
  10. 12
      src/pages/order_list/order_list.vue
  11. 4
      src/pages/order_search/order_search.vue
  12. 3
      src/store/actions.js
  13. 1
      src/subpackage/device/js/device_api.js
  14. 32
      src/subpackage/order/components/kv_line.vue
  15. 36
      src/subpackage/order/components/kvs_line.vue
  16. 92
      src/subpackage/order/components/order_list/filter_modal.vue
  17. 112
      src/subpackage/order/components/order_list/header.vue
  18. 140
      src/subpackage/order/components/order_list/period_modal.vue
  19. 100
      src/subpackage/order/components/order_list/stadium_select.vue
  20. 11
      src/subpackage/order/js/api.js
  21. 18
      src/subpackage/order/pages/order_manage/order_manage.vue
  22. 24
      src/subpackage/order/pages/timekeeping/modules/order_detail/bottom_fixed.vue
  23. 261
      src/subpackage/order/pages/timekeeping/modules/order_detail/end_billing_modal.vue
  24. 43
      src/subpackage/order/pages/timekeeping/modules/order_detail/header_temp.vue
  25. 34
      src/subpackage/order/pages/timekeeping/modules/order_detail/info_temp.vue
  26. 58
      src/subpackage/order/pages/timekeeping/modules/order_list/deposit.vue
  27. 68
      src/subpackage/order/pages/timekeeping/modules/order_list/item_temp.vue
  28. 84
      src/subpackage/order/pages/timekeeping/modules/order_list/person.vue
  29. 94
      src/subpackage/order/pages/timekeeping/modules/order_list/site.vue
  30. 62
      src/subpackage/order/pages/timekeeping/modules/order_search/search_bar.vue
  31. 126
      src/subpackage/order/pages/timekeeping/order_detail/common.js
  32. 211
      src/subpackage/order/pages/timekeeping/order_detail/deposit.vue
  33. 268
      src/subpackage/order/pages/timekeeping/order_detail/person.vue
  34. 382
      src/subpackage/order/pages/timekeeping/order_detail/site.vue
  35. 281
      src/subpackage/order/pages/timekeeping/order_list.vue
  36. 132
      src/subpackage/order/pages/timekeeping/order_search.vue
  37. 379
      src/subpackage/order/pages/timing/detail.vue
  38. BIN
      src/subpackage/order/static/images/filter.png
  39. BIN
      src/subpackage/order/static/images/order_manage/order_22.png
  40. 0
      src/subpackage/order/static/images/order_manage/order_23.png
  41. BIN
      src/subpackage/order/static/images/round_close.png
  42. BIN
      src/subpackage/order/static/images/search.png
  43. 20197
      yarn.lock

2
package.json

@ -66,7 +66,7 @@
"flyio": "^0.6.2",
"pinyin-engine": "^1.2.2",
"regenerator-runtime": "^0.12.1",
"sass": "^1.63.3",
"sass": "1.63.3",
"vue": "^2.6.11"
},
"devDependencies": {

12121
pnpm-lock.yaml
File diff suppressed because it is too large
View File

194
src/components/end_billing_modal/end_billing_modal.vue

@ -1,194 +0,0 @@
<template>
<!-- 弹框 结束计费 -->
<view class="ox-dark-mask" @touchmove.stop.prevent="moveHandle" @click.stop="">
<view class="odm-end-modal" >
<view class="oem-close">
<image src="/static/images/icon/x_close.png" @click="closeChange"></image>
</view>
<view class="oem-tit">结束计费</view>
<view class="oem-line">操作人{{orderInfo.end_bill_operator_name || '-'}}</view>
<view class="oem-line">时长合计<text class="ol-txt1">{{orderInfo.extension.duration || '-'}}</text></view>
<view class="oem-line">金额合计<text class="ol-txt2">¥{{orderInfo.amount || 0}}</text></view>
<view class="oem-box">
<view @click="selectBtn(1)">
<image :class="[selectType==1?'ob-img':'']" :src="selectType==1?'/static/images/icon/selected_ring.png':''"></image>
<view :class="[selectType==1?'ov-active':'']">停止计时</view>
</view>
<view @click="selectBtn(2)">
<image :class="[selectType==2?'ob-img':'']" :src="selectType==2?'/static/images/icon/selected_ring.png':''"></image>
<view :class="[selectType==2?'ov-active':'']">完结订单</view>
</view>
</view>
<view class="oem-tips">*<text>请输入金额</text></view>
<view class="oem-ipt"><input type="digit" v-model="input_amount"/></view>
<view class="oem-btn" hover-class="hover-active" @click="confirmChange" >确认</view>
</view>
</view>
</template>
<script>
import util from '@/utils/util';
import deviceApi from '../../subpackage/device/js/device_api.js';
import deviceServer from '../../subpackage/device/js/device_server.js';
import { mapState } from 'vuex';
export default {
props: {
orderInfo: {
type: Object,
default: ()=>({})
}
},
computed: {
...mapState(['brandInfo']),
},
data() {
return {
input_amount: "",
selectType: 1, //1() 2()
}
},
methods: {
moveHandle(){},
closeChange(){
this.$emit('close');
},
confirmChange(){
let { brandInfo, orderInfo, input_amount, selectType } = this
if(input_amount == '')return util.showNone('请输入金额!');
util.showLoad();
deviceServer.get({
url: deviceApi.timeOrderEnd,
data: {
brand_id: brandInfo.brand.id,
order_no: orderInfo.order_no,
pay_amount: parseFloat(input_amount),
end_type: selectType==1?'end_timing':selectType==2?'end_order':'',
},
failMsg: '加载失败!'
})
.then(res=>{
util.hideLoad()
util.showNone('操作成功!');
this.$emit('close');
// setTimeout(()=>uni.navigateBack(),1200);
this.$emit('timeEndBtn');
})
.catch(util.hideLoad)
},
selectBtn(type){
this.selectType = type
},
},
}
</script>
<style lang="scss" >
@import '~style/public.scss';
.odm-end-modal{
position: absolute;
left: 65rpx;
top: 12%;
background-color: #fff;
width: 620rpx;
padding: 30rpx 0rpx 60rpx;
border-radius: 10rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.oem-close{
width: 100%;
@include centerFlex(flex-end);
>image{
width: 32rpx;
height: 32rpx;
margin-right: 30rpx;
}
}
.oem-tit {
color: #1A1A1A;
font-size: 32rpx;
font-weight: 700;
margin: 16rpx 0rpx 34rpx;
}
.oem-line{
width: 456rpx;
color: #1A1A1A;
font-size: 28rpx;
line-height: 48rpx;
.ol-txt1{
color: #009874;
}
.ol-txt2{
color: #FF873D;
}
}
.oem-box{
margin: 58rpx 0 48rpx;
width: 456rpx;
@include centerFlex(space-between);
>view{
@include centerFlex(flex-start);
>image{
flex-shrink: 0;
width: 28rpx;
height: 28rpx;
border-radius: 50%;
border: 2rpx solid #D8D8D8;
&.ob-img{
width: 32rpx;
height: 32rpx;
border: 0rpx solid #D8D8D8;
}
}
>view{
margin-left: 12rpx;
font-size: 28rpx;
line-height: 48rpx;
color: #9C9C9F;
&.ov-active{
color: #1A1A1A;
}
}
}
}
.oem-tips{
width: 456rpx;
margin: 0rpx 0rpx 8rpx;
color: #EA5061;
font-size: 28rpx;
>text{
color: #333333;
}
}
.oem-ipt{
width: 456rpx;
border: 2rpx solid #D8D8D8;
border-radius: 10rpx;
& input {
flex-grow: 1;
height: 88rpx;
color: #1A1A1A;
font-size: 28rpx;
padding: 0rpx 20rpx;
}
}
.oem-btn{
width: 240rpx;
height: 88rpx;
margin-top: 60rpx;
border-radius: 10rpx;
background-color: #009874;
color: #FFF;
font-size: 32rpx;
line-height: 88rpx;
text-align: center;
}
}
</style>

2
src/components/fixed_bar/fixed_bar.vue

@ -28,8 +28,8 @@ export default {
}
.fb-fixed{
padding-top: 20upx;
position: fixed;
padding-top: 20upx;
bottom: 0;
left: 0;
width: 100%;

5
src/components/order_refund/modal.vue

@ -121,7 +121,10 @@ export default {
let { iptInfo, refundInfo } = this;
this.$emit('click:confirm');
this.refundInfo?.confirm?.(iptInfo);
this.refundInfo?.confirm?.({
refund_amount: +iptInfo?.refund_amount || 0,
refund_integral: +iptInfo?.refund_integral || 0
});
this.hide();
}
}

49
src/components/order_refund/permission_btn.vue

@ -0,0 +1,49 @@
<template>
<view class="permissinon-btn">
<or-button v-if="isShow" @click="$emit('click:button')"><slot>退款</slot></or-button>
</view>
</template>
<script>
import orButton from "./button.vue";
import { mapState } from 'vuex';
/**
* 全部订单都能退两次, 所有订单最多只能退2次款
* 只要订单金额是未全退的都能退
* 0元订单不能退
*
*/
export default {
components: {
orButton
},
props: [ 'pay_amount', 'refund_amount', 'refund_times' ],
computed: {
...mapState([ 'brandInfo' ]),
payAmount(){
let { pay_amount } = this;
return +pay_amount || 0
},
refundAmount(){
let { refund_amount } = this;
return +refund_amount || 0
},
isShow(){
let { payAmount, refundAmount, refund_times, brandInfo } = this;
console.log('brandInfo', payAmount, refundAmount, refund_times, brandInfo)
if(
payAmount - refundAmount > 0
&&[0, 1].includes(refund_times)
&&brandInfo?.permission?.['1018'] // 退
){
return true
}
return false
}
},
}
</script>
<style>
</style>

185
src/components/timing_order/timing_order.vue

@ -1,185 +0,0 @@
<template>
<view class="timing-order" @click="toOrderDetails">
<view class="ro-header">
<view class="rh-view">{{orderInfo.stadium_name || '-'}}</view>
<text :class="[ 'rh-text', orderInfo.pay_status == 0?'rh-active':'' ]">{{zh_order_status(orderInfo.pay_status)}}</text>
</view>
<view class="ro-section">
<view class="rs-line">
<view class="rl-view">订单编号</view>
<view class="rl-view">
<view class="rv-view">{{orderInfo.order_no || '-'}}</view>
</view>
<image class="rl-image" src="/static/images/icon/arrow_b2.png"></image>
</view>
<!-- 场时有 人时没有 order_type: 1场时 2人时 -->
<view class="rs-line" v-if="orderInfo.order_type == 1">
<view class="rl-view">项目</view>
<view class="rl-view">
<view class="rv-view">{{orderInfo.project_name || '-'}}</view>
</view>
</view>
<view class="rs-line">
<view class="rl-view">时长</view>
<view class="rl-view">
<view :class="[ 'rv-view', orderInfo.pay_status == 0?'rv-active':'' ]">{{ orderInfo.extension.duration || '-'}}</view>
</view>
</view>
<view class="rs-btn" v-if="orderInfo.pay_status == 0&&orderInfo.early_end_timing==false"><view @click.stop="isEndBill=true">结束计费</view></view>
</view>
<view class="ro-bot" v-if="orderInfo.pay_status != 0">
<view class="rb-total">实付款 <text class="rt-txt"> ¥{{orderInfo.pay_amount || 0}}</text></view>
</view>
<!-- 结束计费弹框 -->
<end-billing-modal
v-if="isEndBill==true"
@close="isEndBill=false"
@timeEndBtn="timeEndBtn"
:orderInfo="orderInfo"
></end-billing-modal>
</view>
</template>
<script>
import util from '@/utils/util';
import end_billing_modal from '../end_billing_modal/end_billing_modal.vue';
export default {
components: {
'end-billing-modal': end_billing_modal,
},
props: {
orderInfo: {
type: Object,
default: ()=>({})
}
},
computed: {
zh_order_status(){
// 01
let { orderInfo } = this
return status =>{
const _obj = {
'0': orderInfo.early_end_timing==true?'待支付':'计费中',
'1': '已完成',
'4': '已退款',
}
return _obj[`${status}`] || '-'
}
},
},
data() {
return {
isEndBill: false,
}
},
methods:{
toOrderDetails(){
let { orderInfo } = this
// let _query = {}
// _query["stadium_id"] = orderInfo.stadium_id
// _query["order_no"] = orderInfo.order_no
// _query["order_type"] = 1
let _str = `stadium_id=${orderInfo.stadium_id || ''}&order_no=${orderInfo.order_no || ''}`
util.routeTo(`/subpackage/order/pages/timing/detail?${_str}`,'nT');
// this.$emit('orderDetailChange');
},
timeEndBtn(){
this.$emit('refreshList');
},
}
}
</script>
<style lang="scss" >
@import '~style/public.scss';
.timing-order{
padding: 0 24upx;
border-radius: 10upx;
background-color: #fff;
.ro-header{
margin-bottom: 18upx;
height: 98upx;
line-height: 96upx;
border-bottom: 2upx solid #D8D8D8;
@include centerFlex(space-between);
.rh-view{
flex-grow: 1;
font-size: 28upx;
color: #1a1a1a;
@include textHide(1);
}
.rh-text{
margin-left: 20upx;
flex-shrink: 0;
font-size: 28upx;
color: #9C9C9F;
}
.rh-active{
color: $themeColor;
}
}
.ro-section{
padding-bottom: 30upx;
.rs-line{
display: flex;
.rl-view,.rv-view{
line-height: 40upx;
font-size: 24upx;
color: #9c9c9f;
}
.rl-view{
&:first-child{
flex-shrink: 0;
}
&+.rl-view{
flex-grow: 1;
.rv-view{
@include textHide(1);
}
}
}
.rv-active{
color: $themeColor;
}
>.rl-image{
width: 32rpx;
height: 32rpx;
}
}
.rs-btn{
margin-top: 8rpx;
@include centerFlex(flex-end);
>view{
width: 192rpx;
height: 80rpx;
border: 2rpx solid #009874;
border-radius: 10rpx;
color: #009874;
font-size: 32rpx;
font-weight: 500;
text-align: center;
line-height: 80rpx;
}
}
}
.ro-bot{
padding-top: 20upx;
padding-bottom: 30upx;
border-top: 2upx solid #D8D8D8;
.rb-total{
line-height: 40upx;
text-align: right;
font-size: 24upx;
color: #9c9c9f;
.rt-txt{
color: #1A1A1A;
margin-left: 10rpx;
}
}
}
}
</style>

1
src/js/api.js

@ -30,7 +30,6 @@ export const API = {
// reservationOrder: `${ORIGIN}/admin/stadium/order/list`, // 预约订单
reservationOrder:`${ORIGIN}/admin/assistant/stadiumOrder/list`, //k-订单管理-预约订单列表 PM:2021/4/19
timeOrder:`${ORIGIN}/admin/assistant/timeOrder/list`, //k-订单管理-计时订单列表 PM:2021/4/19
membershipOrder: `${ORIGIN}/admin/member_card/order/list`, // 会员卡订单

36
src/pages.json

@ -480,6 +480,36 @@
"root": "subpackage/order",
"pages": [
{
"path": "pages/timekeeping/order_search",
"style" : {
"navigationBarTitleText": "订单搜索"
}
},
{
"path": "pages/timekeeping/order_list",
"style" : {
"navigationBarTitleText": "计时订单"
}
},
{
"path": "pages/timekeeping/order_detail/person",
"style" : {
"navigationBarTitleText": "散客计时订单详情"
}
},
{
"path": "pages/timekeeping/order_detail/site",
"style" : {
"navigationBarTitleText": "场地计时订单详情"
}
},
{
"path": "pages/timekeeping/order_detail/deposit",
"style" : {
"navigationBarTitleText": "场地计时订单详情"
}
},
{
"path": "pages/stored_value_card/detail/detail",
"style" : {
"navigationBarTitleText": "储值卡订单详情"
@ -604,12 +634,6 @@
"style" : {
"navigationBarTitleText": "租球机订单详情"
}
},
{
"path": "pages/timing/detail",
"style" : {
"navigationBarTitleText": "计时订单详情"
}
}
]
},

12
src/pages/order_list/order_list.vue

@ -50,7 +50,6 @@
<reservation-order :order-info="e" v-if="orderType == 3" @verify="reservationVerify(i)"></reservation-order>
<membership-order :order-info="e" v-if="orderType == 4"></membership-order>
<integral-order :order-info="e" v-if="orderType == 5"></integral-order>
<timing-order :order-info="e" @refreshList="refreshList" v-if="orderType == 1"></timing-order>
<organize-order :order-info="e" v-if="orderType == 10" @refreshList="refreshList"></organize-order>
<curriculum :order-info="e" v-if="orderType == 12"></curriculum>
@ -127,7 +126,6 @@
import reservation_order from '../../components/reservation_order/reservation_order';
import integral_order from '../../components/integral_order/integral_order';
import membership_order from '../../components/membership_order/membership_order';
import timing_order from '../../components/timing_order/timing_order.vue';
import organize_order from '../../components/organize_order/organize_order.vue';
// 20210910
import value_card from '../../components/order_list/value_card/value_card.vue'; // 20220725
@ -157,7 +155,6 @@
'reservation-order': reservation_order,
'membership-order': membership_order,
'integral-order': integral_order,
'timing-order': timing_order,
'organize-order': organize_order,
'spectacular-monent': spectacular_monent,
'value-card': value_card,
@ -180,7 +177,7 @@
let { orderType } = this;
return (
orderType == 3 || orderType == 4 ||
orderType == 1 || orderType == 10 ||
orderType == 10 ||
orderType == 18 || orderType == 12 ||
orderType == 18 || orderType == 12 ||
orderType == 15 || orderType == 16 ||
@ -444,7 +441,6 @@
if(type == 3)return API.reservationOrder;
if(type == 4)return API.membershipOrder;
if(type == 5)return API.integralOrder;
if(type == 1)return API.timeOrder;
if(type == 10)return API.organizeOrderList; //
if(type == 12)return API.venueCourseOrderList; //
if(type == 18)return API.userValueCardList; //
@ -488,7 +484,7 @@
delete _obj['status'];
_obj['order_status_in'] = +curTabID === -1 ? '0,1,2,3' : curTabID + ''
}
// :0,1; :/[1/2]
// :0,1;
if(orderType == 3)_obj['order_type'] = appointOrderType;
// , 0430.0507()
@ -549,8 +545,6 @@
return '会员卡订单';
case 5:
return '积分商城订单';
case 1:
return '计时订单';
case 10:
return '约玩订单';
case 12:
@ -596,8 +590,6 @@
return [ {id: '', name: '全部'}, {id: 1, name: '使用中'}, {id: 0, name: '已失效'},];
case 5: // tab
return [ {id: '', name: '全部'}, {id: 1, name: '待发货'}, {id: 2, name: '已发货'}, {id: 3, name: '已完成'}, ];
case 1: // tab ///退 [/0/1/4]
return [ {id: '', name: '全部'}, {id: 0, name: '计费中'}, {id: 1, name: '已完成'}, {id: 4, name: '已退款'}, ];
case 10: // tab ///退 [/0/1/4]
return [ {id: '', name: '全部'}, {id: 1, name: '已付款'}, {id: 2, name: '已完成'}, {id: 4, name: '已退款'}, ];
case 12: // tab ///退 [/0/1/4]

4
src/pages/order_search/order_search.vue

@ -17,7 +17,6 @@
<reservation-order :order-info="e" v-if="orderType == 3"></reservation-order>
<membership-order :order-info="e" v-if="orderType == 4"></membership-order>
<integral-order :order-info="e" v-if="orderType == 5"></integral-order>
<timing-order :order-info="e" v-if="orderType == 1"></timing-order>
<organize-order :order-info="e" v-if="orderType == 10"></organize-order>
<!-- 20210910 -->
@ -44,7 +43,6 @@
import reservation_order from '../../components/reservation_order/reservation_order';
import integral_order from '../../components/integral_order/integral_order';
import membership_order from '../../components/membership_order/membership_order';
import timing_order from '../../components/timing_order/timing_order.vue'
import organize_order from '../../components/organize_order/organize_order.vue'
// 20210910
import value_card from '../../components/order_list/value_card/value_card.vue';
@ -71,7 +69,6 @@ export default {
'reservation-order': reservation_order,
'membership-order': membership_order,
'integral-order': integral_order,
'timing-order': timing_order,
'organize-order': organize_order,
// <!-- 20210910 -->
'spectacular-monent': spectacular_monent,
@ -137,7 +134,6 @@ export default {
if(type == 3)return API.reservationOrder;
if(type == 4)return API.membershipOrder;
if(type == 5)return API.integralOrder;
if(type == 1)return API.timeOrder;
if(type == 10)return API.organizeOrderList;
// <!-- 20210910 -->
if(type == 12)return API.venueCourseOrderList; //

3
src/store/actions.js

@ -21,5 +21,8 @@ export default {
data: { order_no },
isDefaultGet: false
})
.catch(err=>{
console.warn('actions getOrderRefundList err -->', err);
})
}
}

1
src/subpackage/device/js/device_api.js

@ -35,7 +35,6 @@ export const DEVICE_API = {
checkIccard:`${ORIGIN}/admin/assistant/checkIccard`, //k-订单管理-校验ic卡
storeHouseList:`${ORIGIN}/admin/assistant/storeHouse/list`, //k-仓库列表
iccardList:`${ORIGIN}/admin/assistant/iccard/list`, //k-ic卡列表
timeOrderDetail:`${ORIGIN}/admin/assistant/timeOrder/detail`, //k-订单管理-计时订单详情
timeOrderEnd:`${ORIGIN}/admin/assistant/timeOrder/end`, //k-订单管理-订单计时结束
timeOrderComplete:`${ORIGIN}/admin/assistant/timeOrder/complete`, //【20220208】k-订单管理-计时订单完结

32
src/subpackage/order/components/kv_line.vue

@ -0,0 +1,32 @@
<template>
<view class="kv-line">
<view class="kl-name">{{ label || '' }}</view>
<view class="kl-val"><slot name="default">value</slot></view>
<slot name="right"></slot>
</view>
</template>
<script>
export default {
props: {
label: {
type: String,
default: ''
},
}
}
</script>
<style lang="scss">
.kv-line{
@include ctf;
.kl-name{
flex-shrink: 0;
@include flcw(28upx, 48upx, #9C9C9F);
}
.kl-val{
@include flcw(28upx, 48upx, #1A1A1A);
@include tHide;
}
}
</style>

36
src/subpackage/order/components/kvs_line.vue

@ -0,0 +1,36 @@
<template>
<view class="s-line">
<view class="sl-view">{{ label }}</view>
<view class="sl-view">
<slot></slot>
</view>
</view>
</template>
<script>
export default {
props: {
label: {
default: ''
}
}
}
</script>
<style lang="scss">
.s-line{
@include ctf(space-between);
.sl-view{
&:first-child{
flex-shrink: 0;
@include flcw(28upx, 60upx, #1A1A1A);
}
&+.sl-view{
margin-left: 20upx;
@include flcw(24upx, 60upx, #1A1A1A);
@include tHide;
}
}
}
</style>

92
src/subpackage/order/components/order_list/filter_modal.vue

@ -0,0 +1,92 @@
<template>
<view class="filter-modal" v-show="visibled" @click="hide">
<scroll-view class="fm-container" scroll-y @click.stop="_=>false">
<view class="fc-title">{{ title }}</view>
<view class="fc-list">
<view
class="fl-item"
:class="{ active: curValue === e.value }"
v-for="(e, i) in list"
:key="i"
@click="itemClick(e)"
>{{ e.label }}</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data(){
return {
visibled: false,
title: '',
list: [],
curValue: '',
initOption: {
// success,
}
}
},
methods: {
show(){
this.visibled = true;
},
hide(){
this.visibled = false;
},
init(e){
this.title = e.title;
this.list = e.list;
this.curValue = e.curValue;
this.initOption = e;
this.show();
},
itemClick(e){
this.initOption?.success?.(e);
this.hide();
}
}
}
</script>
<style lang="scss">
.filter-modal{
position: fixed;
left: 0;
top: var(--window-top);
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
z-index: 10;
.fm-container{
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 500upx;
height: 100%;
padding-left: 42upx;
background-color: #fff;
padding-top: 26upx;
padding-left: 42upx;
padding-bottom: 40upx;
.fc-title{
margin-bottom: 58upx;
padding: 50upx 0;
border-bottom: 2upx solid #D8D8D8;
@include flcw(24upx, 34upx, #9c9c9f);
}
.fc-list{
.fl-item{
margin-bottom: 50upx;
@include tHide;
@include flcw(32upx, 44upx, #1a1a1a);
&.active{
color: $mColor;
}
}
}
}
}
</style>

112
src/subpackage/order/components/order_list/header.vue

@ -0,0 +1,112 @@
<template>
<view class="order-list-header">
<!-- 门店选择 -->
<stadium-select
ref="stadiumSelect"
:visibled="isStadium"
@change:stadium="$emit('change:stadium', $event)"
></stadium-select>
<!-- 时间段 -->
<view class="olh-period">
<view class="op-txt" @click="$emit('click:time')">{{ startTime || '' }} ~ {{ endTime || '' }}</view>
<view class="op-icon" @click="$emit('click:time')"></view>
</view>
<!-- 交易明细&按钮 -->
<view class="olh-bot">
<view class="ob-desc">
<text>成功交易{{ successCount || 0 }}退款{{ refundCount || 0 }}</text>
</view>
<view class="ob-btns">
<image @click="$emit('click:search')" class="ob-icon" src="../../static/images/search.png"></image>
<image @click="$emit('click:filter')" class="ob-icon" src="../../static/images/filter.png"></image>
</view>
</view>
<!-- 时间段选择弹窗 -->
<period-modal
ref="periodModal"
></period-modal>
</view>
</template>
<script>
import stadiumSelect from './stadium_select.vue';
import periodModal from "./period_modal.vue";
export default {
components: {
'stadium-select': stadiumSelect,
'period-modal': periodModal
},
props: {
startTime: {
default: ''
},
endTime: {
default: ''
},
successCount: {
default: 0
},
refundCount: {
default: 0
},
},
data(){
return {
isStadium: false
}
},
methods: {
initStadiumSelect(brand_id){
this.isStadium = !!brand_id;
return this.$refs.stadiumSelect.getStadiumList(brand_id);
},
showPeriodModal(e){
this.$refs.periodModal.show(e);
},
periodConfirm(e){
console.log('periodConfirm:', e)
}
}
}
</script>
<style lang="scss">
.order-list-header{
.olh-period{
padding: 24upx 24upx 0upx;
@include ctf(flex-start);
.op-txt{
@include flcw(32upx, 44upx, #1a1a1a, 500);
@include tHide(1);
}
.op-icon{
flex-shrink: 0;
margin-left: 14upx;
width: 0;
height: 0;
border-left: 10upx solid transparent;
border-right: 10upx solid transparent;
border-top: 10upx solid #1a1a1a;
}
}
.olh-bot{
padding: 16upx 24upx;
@include ctf(space-between);
.ob-desc{
flex-grow: 1;
@include flcw(24upx, 34upx, #9c9c9f);
@include tHide(1);
}
.ob-btns{
flex-shrink: 0;
@include ctf(flex-end);
.ob-icon{
flex-shrink: 0;
margin-left: 40upx;
width: 40upx;
height: 40upx;
}
}
}
}
</style>

140
src/subpackage/order/components/order_list/period_modal.vue

@ -0,0 +1,140 @@
<template>
<view class="period-modal" v-show="visibled" @click="hide">
<view class="pm-period" @click.stop="()=>false">
<view class="pp-tit">日期范围</view>
<picker class="pp-picker" mode="date" @change="startTimeChange" :value="start">
<view class="pp-time">
<text class="pt-txt">开始时间</text>
<view class="pt-right">
<input class="pr-ipt" placeholder="选择时间" disabled :value="start" />
<image class="pr-img" mode="aspectFit" src="/static/images/icon/arrow_b2.png"></image>
</view>
</view>
</picker>
<picker class="pp-picker" mode="date" @change="endTimeChange" :value="end">
<view class="pp-time">
<text class="pt-txt">截止时间</text>
<view class="pt-right">
<input class="pr-ipt" placeholder="选择时间" disabled :value="end" />
<image class="pr-img" mode="aspectFit" src="/static/images/icon/arrow_b2.png"></image>
</view>
</view>
</picker>
<view class="pl-btn active" @click="confirmPeriod">确定</view>
</view>
</view>
</template>
<script>
import { showNone } from '@/utils/util';
export default {
data(){
return {
start: '',
end: '',
visibled: false,
initOption: {
// success,
}
}
},
methods: {
init(e){
this.start = e.start;
this.end = e.end;
this.initOption = e;
this.show();
},
show(){
this.visibled = true;
},
hide(){
this.visibled = false;
},
startTimeChange(e){
this.start = e.detail.value;
},
endTimeChange(e){
this.end = e.detail.value;
},
confirmPeriod(){
let { start, end, initOption } = this;
if(!start || !end)return showNone('请选择日期范围!');
if(
new Date(start.replace(/\-/g,'/')).getTime()
> new Date(end.replace(/\-/g,'/')).getTime()
)return showNone('请选择合理时间!');
this.hide();
initOption?.success?.({ start, end });
this.$emit('click:cofirm', { start, end });
}
}
}
</script>
<style lang="scss">
.period-modal{
position: fixed;
left: 0;
top: var(--window-top);
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
z-index: 10;
.pm-period{
position: absolute;
left: 0;
top: 0;
padding-left: 38upx;
padding-top: 66upx;
height: 472upx;
width: 100%;
background-color: #fff;
.pp-tit{
@include flcw(24upx, 34upx, #9c9c9f);
}
.pp-picker{
width: 100%;
}
.pp-time{
padding-right: 40upx;
height: 124upx;
border-bottom: 2upx solid #D8D8D8;
@include ctf(space-between);
.pt-txt{
flex-shrink: 0;
@include flcw(32upx, 44upx, #1a1a1a);
}
.pt-right{
flex-grow: 1;
@include ctf(flex-end);
.pr-ipt{
flex-grow: 1;
height: 100%;
text-align: right;
@include flcw(32upx, 44upx, #1a1a1a);
}
.pr-img{
flex-shrink: 0;
margin-left: 36upx;
width: 28upx;
height: 28upx;
}
}
}
.pl-btn{
text-align: center;
@include flcw(32upx, 124upx, rgba(0, 152, 116, .2), 500);
color: rgba(0, 152, 116, .2);
&.active{
color: $mColor;
}
}
}
}
</style>

100
src/subpackage/order/components/order_list/stadium_select.vue

@ -0,0 +1,100 @@
<template>
<view class="stadium-select" v-show="visibled">
<text class="ss-txt">当前门店</text>
<picker mode="selector" class="ss-picker" :range="stadiumList" range-key="name" @change="pickerChange">
<view class="ss-frame">
<input type="text" disabled class="sf-ipt" :value="curStadium.name || ''" placeholder="全部"/>
<image class="sf-img" mode="aspectFit" src="../../static/images/arrow.png"></image>
</view>
</picker>
</view>
</template>
<script>
import { ORDER_API } from '../../js/api';
import server from '../../js/server';
export default {
props: {
visibled: {
type: Boolean,
default: false
}
},
data(){
return {
stadiumList: [
{ id: '', name: '全部' }
],
curStadium: {}
}
},
methods: {
pickerChange(e){
let { value } = e.detail;
let { stadiumList } = this;
this.curStadium = stadiumList[value];
this.$emit('change:stadium', this.curStadium);
},
//
getStadiumList(brand_id){
return server.get({
url: ORDER_API.stadiumList,
data: { brand_id },
isDefaultGet: false
})
.then(res=>{
let _data = res?.data || {};
if(_data.code === 0){
let _list = _data?.data?.list || [];
return this.stadiumList = [ ...this.stadiumList, ..._list ];
}else{
console.warn('getStoreList err:', err);
return this.stadiumList;
}
})
.catch(err=>{
console.warn('getStoreList err:', err);
return this.stadiumList;
})
},
}
}
</script>
<style lang="scss">
.stadium-select{
padding: 0 24upx;
height: 144upx;
background-color: #fff;
@include ctf(space-between);
.ss-txt{
margin-right: 20upx;
flex-shrink: 0;
@include flcw(28upx, 40upx, #9c9c9f);
}
.ss-picker{
flex-grow: 1;
.ss-frame{
padding: 0 20upx;
height: 92upx;
border-radius: 10upx;
background-color: #F2F2F7;
@include ctf(space-between);
.sf-ipt{
flex-grow: 1;
@include flcw(28upx, 40upx, #1a1a1a);
@include tHide(1);
}
.sf-img{
margin-left: 10upx;
flex-shrink: 0;
width: 28upx;
height: 28upx;
}
}
}
.ocs-store{
}
}
</style>

11
src/subpackage/order/js/api.js

@ -35,11 +35,18 @@ export const ORDER_API = {
rentballEndBilling:`${ORIGIN}/admin/stadium/rentball/order/end`, // 结束订单-后台
// 20220727
rentBallOrderDetails:`${ORIGIN}/admin/stadium/hardware/order/rentBallOrderDetails`, // 硬件管理-订单详情_copy
// 20240624 tid1553 计时订单拆分
stadiumList: `${ORIGIN}/admin/stadium/list`, // 店铺列表
billingOrderList: `${ORIGIN}/admin/stadium/billing/order/list`, // 计时订单列表
billingOrderDetail: `${ORIGIN}/admin/stadium/billing/order/detail`, // 散客计时订单详情
timeOrderEnd: `${ORIGIN}/admin/assistant/timeOrder/end`, //k-订单管理-订单计时结束
timeOrderComplete:`${ORIGIN}/admin/assistant/timeOrder/complete`, //【20220208】k-订单管理-计时订单完结
subscribeCancel:`${ORIGIN}/admin/stadium/billing/order/subscribeCancel`, //【1000969】取消场时预约订单
// 20240614 tid1523 统一退款
venueCourseOrderRefund:`${ORIGIN}/admin/venueCourse/orderRefund`, // 课程订单-退款
userValueCardRefundFixed:`${ORIGIN}/admin/userValueCard/refundFixed`, // 储值卡订单-退款
timeOrderDetail:`${ORIGIN}/admin/assistant/timeOrder/detail`, //k-订单管理-计时订单详情
timeOrderComplete:`${ORIGIN}/admin/assistant/timeOrder/complete`, //【20220208】k-订单管理-计时订单完结
orderRefund:`${ORIGIN}/admin/stadium/order/refund`, // A订单管理-场馆预订订单-订单退款 (零售订单、场地、次卡)
userMonthlyCardRefundFixed:`${ORIGIN}/admin/userMonthlyCard/refundFixed`, // 年月卡订单-订单退款
}

18
src/subpackage/order/pages/order_manage/order_manage.vue

@ -15,19 +15,29 @@
</template>
<script>
import util from '../../../../utils/util'
import util from '../../../../utils/util';
import { mapState } from 'vuex';
export default {
data(){
return {
tabList: getTabList()
}
},
computed: {
...mapState([ 'brandInfo' ])
},
methods: {
getIconPath(iconName){
return `../../static/images/order_manage/${iconName}.png`
},
tabClick(ele){
let { brandInfo } = this;
if(!this.isFinish(ele.key))return util.showNone('待开放中!');
// 20240813 tid1553
if([22, 23].includes(ele.key)){
let _qryStr = `order_type=${ele.orderType}&brand_id=${brandInfo?.brand?.id || ''}`;
return util.routeTo(`/subpackage/order/pages/timekeeping/order_list?${_qryStr}`, 'nT');
}
if(ele.orderType === 3){ // &
let _type = ele.key - 1; // 0 -> / 1 ->
@ -38,7 +48,7 @@ export default {
util.routeTo(getTabRoutePath() + `?order_type=${ele.orderType}`,'nT');
},
isFinish(key){
let _endKeyArr = [ 1, 2, 3, 4, 5, 7, 9, 10, 14, 16, 15, 13, 6, 8, 11, 12, 18, 19];
let _endKeyArr = [ 1, 2, 4, 5, 7, 9, 10, 14, 16, 15, 13, 6, 8, 11, 12, 18, 19, 22, 23];
return _endKeyArr.includes(key);
}
}
@ -57,7 +67,8 @@ function getTabList(){
tabArr: [
{ id: 1, name: '订场订单', key: 1, iconName: 'order_14', orderType: 3 },
{ id: 2, name: '次卡订单', key: 2, iconName: 'order_2', orderType: 3 },
{ id: 3, name: '计时订单', key: 3, iconName: 'order_6', orderType: 1 },
{ id: 11, name: '散客计时订单', key: 22, iconName: 'order_22', orderType: 2 },
{ id: 12, name: '场地计时订单', key: 23, iconName: 'order_23', orderType: 1 },
{ id: 4, name: '储值卡订单', key: 4, iconName: 'order_1', orderType: 21 },
{ id: 10, name: '年月卡订单', key: 19, iconName: 'order_19', orderType: 20 },
{ id: 5, name: '课程订单', key: 5, iconName: 'order_8', orderType: 12 },
@ -66,6 +77,7 @@ function getTabList(){
{ id: 8, name: '商城订单', key: 8, iconName: 'order_4', orderType: 2 },
{ id: 9, name: '积分兑换订单', key: 9, iconName: 'order_5', orderType: 5 },
{ id: 9, name: '零售订单', key: 18, iconName: 'order_18', orderType: 19 },
]
}

24
src/subpackage/order/pages/timekeeping/modules/order_detail/bottom_fixed.vue

@ -0,0 +1,24 @@
<template>
<fixed-bar>
<view class="bottom-fixed">
<slot></slot>
</view>
</fixed-bar>
</template>
<script>
import fixed_bar from "@/components/fixed_bar/fixed_bar.vue";
export default {
components: {
'fixed-bar': fixed_bar
}
}
</script>
<style lang="scss">
.bottom-fixed{
padding: 10upx 24upx;
background: #F2F2F7;
@include ctf(flex-end);
}
</style>

261
src/subpackage/order/pages/timekeeping/modules/order_detail/end_billing_modal.vue

@ -0,0 +1,261 @@
<template>
<view class="end-billing-modal">
<view class="ebm-mask" v-show="isShow">
<view class="em-container">
<view class="ec-close" @click="isShow = false"></view>
<view class="ec-title">结束计费</view>
<view class="ec-info">
<view class="ei-line"><text class="el-txt">操作人</text>{{ info.operator || '-' }}</view>
<view class="ei-line"><text class="el-txt">时长合计</text>{{ info.duration || '-' }}</view>
<view class="ei-line"><text class="el-txt">金额合计</text>{{ info.amount || '-' }}</view>
</view>
<view class="ec-opts">
<view
class="eo-item"
:class="{ active: end_type === 'end_timing' }"
@click="end_type = 'end_timing'"
>
<view class="ei-icon"></view>
<view class="ei-txt">停止计时</view>
</view>
<view
class="eo-item"
:class="{ active: end_type === 'end_order' }"
@click="end_type = 'end_order'"
>
<view class="ei-icon"></view>
<view class="ei-txt">完结订单</view>
</view>
</view>
<view class="ec-amount">
<view class="et-name"><text class="en-txt">*</text>请输入金额</view>
<input type="digit" class="ea-ipt" v-model="amount">
</view>
<view class="ec-btn" @click="confirmBtn">确认</view>
</view>
</view>
</view>
</template>
<script>
import { ORDER_API } from '../../../../js/api';
import server from '../../../../js/server';
import { showLoad, hideLoad, formatDate, showNone } from '@/utils/util';
export default {
data(){
return {
isShow: false,
info: {
// operator: '',
// duration: '1259',
// amount: '¥100.2'
},
end_type: 'end_timing', // end_timing/ end_order
amount: '',
initOptions: {}
}
},
methods: {
show(){
this.isShow = true;
},
hide(){
this.isShow = false;
},
initModal(data){
let { operator, duration, amount, ...opts } = data;
this.info.operator = operator || '';
this.info.duration = duration || '';
this.info.amount = amount || '';
this.initOptions = opts;
this.show();
},
async confirmBtn(){
let { end_type, amount, initOptions } = this;
// initOptions?.success?.({ type: end_type, amount: +amount || 0 });
// this.hide();
try{
let { end_type, amount, initOptions } = this;
showLoad();
let _query = {
brand_id: initOptions?.brand_id || '',
order_no: initOptions?.order_no || '',
end_type,
pay_amount: +amount || 0
};
let _rRes = await this.cancelReq(_query);
hideLoad();
if(_rRes === 'end_success'){
showNone('操作成功!');
initOptions?.success?.(_query);
this.hide();
}else{
throw new Error(_rRes);
}
}catch(err){
hideLoad();
showNone('操作失败!');
console.warn('end billing modal confirmBtn err -->', err);
initOptions?.fail?.(err);
}
},
cancelReq({
brand_id, order_no, pay_amount, end_type
}){
return server.get({
url: ORDER_API.timeOrderEnd,
data: {
brand_id, order_no, pay_amount, end_type
},
failMsg: '加载失败!'
})
.then(res=>{
return 'end_success';
})
},
}
}
</script>
<style lang="scss">
.ebm-mask{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.em-container{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0upx 80upx;
width: 620upx;
height: 806upx;
border-radius: 10upx;
background: #fff;
.ec-close{
position: absolute;
right: 30upx;
top: 30upx;
width: 48upx;
height: 48upx;
transform: rotate(45deg);
&::before, &::after{
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 4upx;
background: #9a9a9d;
border-radius: 4upx;
}
&::after{
transform: translate(-50%, -50%) rotate(90deg);
}
}
.ec-title{
padding-top: 78upx;
text-align: center;
@include flcw(32upx, 44upx, #1A1A1A, 500);
}
.ec-btn{
margin: 60upx auto 0upx;
width: 240upx;
text-align: center;
border-radius: 10upx;
background: $mColor;
@include flcw(32upx, 88upx, #fff, 500);
}
}
.ec-info{
padding-top: 34upx;
.ei-line{
@include flcw(28upx, 48upx, #1A1A1A);
@include tHide;
.el-txt{
color: #1A1A1A;
}
&:nth-child(2){
color: $mColor;
}
&:nth-child(3){
color: #FF873D;
}
}
}
.ec-opts{
padding-top: 58upx;
@include ctf(space-between);
.eo-item{
flex-shrink: 0;
width: 50%;
@include ctf;
.ei-icon{
flex-shrink: 0;
margin-right: 12upx;
padding: 4upx;
width: 32upx;
height: 32upx;
border: 4upx solid #d8d8d8;
border-radius: 50%;
@include ctf(center);
}
.ei-txt{
@include flcw(28upx, 48upx, #d8d8d8);
}
&.active{
.ei-icon{
border-color: $mColor;
&::after{
content: '';
display: block;
width: 100%;
height: 100%;
background: $mColor;
border-radius: 50%;
}
}
.ei-txt{
color: #1A1A1A;
}
}
}
}
.ec-amount{
padding-top: 48upx;
.et-name{
@include flcw(28upx, 48upx, #1A1A1A);
.en-txt{
color: #EA5061;
}
}
.ea-ipt{
margin-top: 8upx;
padding: 0 12upx;
height: 88upx;
border-radius: 10upx;
border: 2upx solid #D8D8D8;
@include flcw(28upx, 48upx, #1A1A1A);
}
}
</style>

43
src/subpackage/order/pages/timekeeping/modules/order_detail/header_temp.vue

@ -0,0 +1,43 @@
<template>
<view class="order-detail-header">
<view class="odh-stadium">
<image class="os-img" mode="aspectFit" :src="stadiumLogo"></image>
<view class="os-name">{{ stadiumName || '-' }}</view>
</view>
<view class="odh-content">
<slot>content</slot>
</view>
</view>
</template>
<script>
export default {
props: [ 'stadiumName', 'stadiumLogo' ]
}
</script>
<style lang="scss">
.order-detail-header{
padding: 0 30upx 40upx;
border-radius: 10upx;
background: #fff;
.odh-stadium{
padding: 26upx 0;
border-bottom: 1px solid #D8D8D8;
@include ctf(flex-start);
.os-img{
flex-shrink: 0;
margin-right: 14upx;
width: 40upx;
height: 40upx;
}
.os-name{
@include flcw(28upx, 40upx, #333333, 500);
@include tHide;
}
}
.odh-content{
padding-top: 26upx;
}
}
</style>

34
src/subpackage/order/pages/timekeeping/modules/order_detail/info_temp.vue

@ -0,0 +1,34 @@
<template>
<view class="order-detail-info">
<view class="odi-title">{{ title }}</view>
<view class="odi-content">
<slot name="default">content</slot>
</view>
</view>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
},
}
}
</script>
<style lang="scss">
.order-detail-info{
padding: 30upx;
border-radius: 10upx;
background: #fff;
.odi-title{
@include flcw(28upx, 40upx, #9C9C9F);
@include tHide;
}
.odi-content{
padding-top: 20upx;
}
}
</style>

58
src/subpackage/order/pages/timekeeping/modules/order_list/deposit.vue

@ -0,0 +1,58 @@
<template>
<list-item-temp
:stadium="order.stadium_name || ''"
:status="order.status_text || ''"
:price="order.pay_amount || ''"
:price-show="true"
@click:item="toDetail"
>
<template v-slot:default>
<view class="lc-info">
<kv-line label="订单编号:">
<template v-slot:default>{{ order.order_no || '-' }}</template>
<template v-slot:right>
<image class="li-icon" src="../../../../static/images/arrow.png"></image>
</template>
</kv-line>
<kv-line label="项目类型:">{{ order.project_type_name || '-' }}</kv-line>
<kv-line label="创建时间:">{{ order.created_at || '-' }}</kv-line>
</view>
</template>
</list-item-temp>
</template>
<script>
import kvLine from "../../../../components/kv_line.vue";
import listItemTemp from "./item_temp.vue";
import { routeTo } from '@/utils/util';
export default {
props: {
order: {
type: Object,
default: () => ({})
}
},
components: {
'kv-line': kvLine,
'list-item-temp': listItemTemp
},
methods: {
toDetail(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/deposit?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}`, 'nT');
}
}
}
</script>
<style lang="scss">
.lc-info{
padding-top: 12upx;
.li-icon{
margin-left: auto;
flex-shrink: 0;
width: 32upx;
height: 32upx;
}
}
</style>

68
src/subpackage/order/pages/timekeeping/modules/order_list/item_temp.vue

@ -0,0 +1,68 @@
<template>
<view class="list-item-temp" @click="$emit('click:item')">
<view class="lit-stadium-status">
<view class="lss-stadium">{{ stadium || '' }}</view>
<view
class="lss-status"
:class="{ active: statusActive }"
>{{ status }}</view>
</view>
<slot name="default">content</slot>
<view class="lit-price" v-if="priceShow">
<text class="lp-txt">支付金额</text>¥{{ price || 0 }}
</view>
<slot name="bottom"></slot>
</view>
</template>
<script>
export default {
props: {
stadium: String,
status: String,
price: String,
statusActive: Boolean,
priceShow: Boolean
},
data(){
return{ }
}
}
</script>
<style lang="scss">
.list-item-temp{
padding: 0 20upx 30upx;
border-radius: 10upx;
background: #fff;
.lit-stadium-status{
padding: 30upx 0 26upx;
border-bottom: 1px solid #D8D8D8;
@include ctf(space-between);
.lss-stadium{
@include flcw(28upx, 40upx, #1A1A1A, 500);
@include tHide;
}
.lss-status{
flex-shrink: 0;
margin-left: 12upx;
@include flcw(28upx, 40upx, #9A9A9D);
&.active{
color: $mColor;
}
}
}
.lit-price{
margin-top: 30upx;
padding-top: 20upx;
text-align: right;
border-top: 1px solid #D8D8D8;
@include flcw(28upx, 40upx, #1A1A1A);
@include tHide;
.lp-txt{
margin-right: 6upx;
color: #9C9C9F;
}
}
}
</style>

84
src/subpackage/order/pages/timekeeping/modules/order_list/person.vue

@ -0,0 +1,84 @@
<template>
<list-item-temp
:stadium="order.stadium_name || ''"
:status="order.status_text || ''"
:price="order.pay_amount || ''"
:status-active="['待支付', '计费中'].includes(order.status_text)"
:price-show="['待支付', '已完成', '已退款'].includes(order.status_text)"
@click:item="toDetail"
>
<template v-slot:default>
<view class="lc-info">
<kv-line label="订单编号:">
<template v-slot:default>{{ order.order_no || '' }}</template>
<template v-slot:right>
<image class="li-icon" src="../../../../static/images/arrow.png"></image>
</template>
</kv-line>
<kv-line label="项目类型:">人时{{ order.project_type_name || '-' }}</kv-line>
<kv-line label="计费时长:">
<text :style="order.status_text === '计费中' ? 'color: #009874;' : ''">{{ (order.extension&&order.extension.duration) || '' }}</text>
</kv-line>
<kv-line label="创建时间:">{{ order.created_at || '' }}</kv-line>
</view>
</template>
<template v-slot:bottom v-if="order.status_text === '计费中'">
<view class="lc-btns">
<view class="lb-item" @click.stop="endBilling">结束计费</view>
</view>
</template>
</list-item-temp>
</template>
<script>
import kvLine from "../../../../components/kv_line.vue";
import listItemTemp from "./item_temp.vue";
import { routeTo } from '@/utils/util';
export default {
props: {
order: {
type: Object,
default: () => ({})
}
},
components: {
'kv-line': kvLine,
'list-item-temp': listItemTemp
},
methods: {
toDetail(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/person?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}`, 'nT');
},
endBilling(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/person?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}&is_end=1`, 'nT');
}
}
}
</script>
<style lang="scss">
.lc-info{
padding-top: 12upx;
.li-icon{
margin-left: auto;
flex-shrink: 0;
width: 32upx;
height: 32upx;
}
}
.lc-btns{
margin-top: 24upx;
@include ctf(flex-end);
.lb-item{
width: 192upx;
height: 80upx;
text-align: center;
border-radius: 10upx;
border: 2upx solid $mColor;
@include flcw(32upx, 76upx, $mColor, 500);
}
}
</style>

94
src/subpackage/order/pages/timekeeping/modules/order_list/site.vue

@ -0,0 +1,94 @@
<template>
<list-item-temp
:stadium="order.stadium_name || ''"
:status="order.status_text || ''"
:price="order.pay_amount || ''"
:status-active="['待支付', '计费中','待使用', '使用中'].includes(order.status_text)"
:price-show="['待支付', '待使用', '使用中', '已完成', '已失效', '已退款'].includes(order.status_text)"
@click:item="toDetail"
>
<template v-slot:default>
<view class="lc-info">
<kv-line label="项目类型:">
<template v-slot:default>{{ order.project_type_name || '-' }}</template>
<template v-slot:right>
<image class="li-icon" src="../../../../static/images/arrow.png"></image>
</template>
</kv-line>
<kv-line label="开始时间:">{{ order.start_time || '-' }}</kv-line>
<kv-line label="结束时间:">{{ order.end_time || '-' }}</kv-line>
<kv-line label="时长合计:">
<text :style="order.status_text === '计费中' ? 'color: #009874;' : ''">{{ (order.extension&&order.extension.duration) || '' }}</text>
</kv-line>
<kv-line label="创建时间:">{{ order.created_at || '-' }}</kv-line>
</view>
</template>
<template v-slot:bottom>
<view class="lc-btns">
<view class="lb-item" v-if="order.status_text === '待使用'" @click.stop="cancelBtn">取消预约</view>
<view class="lb-item" v-if="order.status_text === '计费中'" @click.stop="endBilling">结束计费</view>
</view>
</template>
</list-item-temp>
</template>
<script>
import kvLine from "../../../../components/kv_line.vue";
import listItemTemp from "./item_temp.vue";
import { routeTo } from '@/utils/util';
export default {
props: {
order: {
type: Object,
default: () => ({})
}
},
components: {
'kv-line': kvLine,
'list-item-temp': listItemTemp
},
methods: {
toDetail(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/site?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}`, 'nT');
},
endBilling(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/site?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}&is_end=1`, 'nT');
},
cancelBtn(){
let { order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/site?order_no=${order?.order_no || ''}&brand_id=${order?.brand_id || ''}&is_end=2`, 'nT');
}
}
}
</script>
<style lang="scss">
.lc-info{
padding-top: 12upx;
.li-icon{
margin-left: auto;
flex-shrink: 0;
width: 32upx;
height: 32upx;
}
}
.lc-btns{
margin-top: 24upx;
@include ctf(flex-end);
.lb-item{
width: 192upx;
height: 80upx;
text-align: center;
border-radius: 10upx;
border: 2upx solid $mColor;
@include flcw(32upx, 76upx, $mColor, 500);
&+.lb-item{
margin-left: 24upx;
}
}
}
</style>

62
src/subpackage/order/pages/timekeeping/modules/order_search/search_bar.vue

@ -0,0 +1,62 @@
<template>
<view class="search-bar">
<view class="sb-box">
<image class="sb-search-icon" mode="aspectFit" src="/subpackage/order/static/images/search.png"></image>
<input class="sb-ipt" placeholder="你输入订单号" v-model="searchTxt" confirm-type="search" @confirm="iptConfirm" />
<image class="sb-clear-icon" v-if="searchTxt!=''" mode="aspectFit" src="/subpackage/order/static/images/round_close.png" @click="clearSearch"></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
searchTxt: ''
}
},
methods: {
iptConfirm(){
this.$emit('confirm:search', this.searchTxt);
},
clearSearch(){
this.searchTxt = '';
this.$emit('click:clear', '');
}
}
}
</script>
<style lang="scss">
.search-bar{
margin-bottom: 24upx;
height: 144upx;
background-color: #fff;
@include ctf(center);
.sb-box{
padding: 0 20upx;
height: 92upx;
width: 702upx;
border-radius: 10upx;
background-color: #f2f2f7;
@include ctf(center);
.sb-search-icon{
margin-right: 20upx;
flex-shrink: 0;
width: 40upx;
height: 40upx;
}
.sb-clear-icon{
flex-shrink: 0;
margin-right: 0;
margin-left: 20upx;
width: 32upx;
height: 32upx;
}
.sb-ipt{
flex-grow: 1;
@include flcw(32upx, 44upx, #1A1A1A);
}
}
}
</style>

126
src/subpackage/order/pages/timekeeping/order_detail/common.js

@ -0,0 +1,126 @@
import { ORDER_API } from '../../../js/api';
import server from '../../../js/server';
import { showLoad, hideLoad, showNone, showModal } from '@/utils/util';
// 获取订单详情
export function getOrderDetail({
brand_id = '', order_no = ''
}){
showLoad();
return server.get({
url: ORDER_API.billingOrderDetail,
data: {
brand_id, order_no
},
failMsg: '加载失败!'
})
.then(res=>{
hideLoad();
// this.orderInfo = res || {};
return res;
})
.catch(err=>{
hideLoad();
showNone('加载失败!');
console.warn('getOrderDetail err -->', err);
})
}
// 完结订单
export function endOrderServer({
brand_id, order_no, stadium_id
}){
showLoad();
return server.get({
url: ORDER_API.timeOrderComplete,
data: {
brand_id, order_no, stadium_id
},
failMsg: '操作失败!'
})
.then(res=>{
hideLoad();
showNone('操作成功!');
return res;
})
.catch(err=>{
hideLoad();
showNone('操作失败!');
console.warn('endOrderServer err -->', err);
})
}
// 取消订单
export function cancelOrderServer({
brand_id, order_no, reason = ''
}){
showLoad();
return server.get({
url: ORDER_API.subscribeCancel,
data: {
brand_id, order_no, reason
},
failMsg: '操作失败!'
})
.then(res=>{
hideLoad();
showNone('操作成功!');
return res;
})
.catch(err=>{
hideLoad();
showNone('操作失败!');
console.warn('cancelOrderServer err -->', err);
})
}
// 完结订单弹窗
export function finishOrder({
brand_id, order_no, stadium_id, opts = {}
}){
showModal({
title: '提示',
content: '是否确认完结订单?',
showCancel: true,
success: modalRes=>{
if(modalRes.confirm)endOrderServer({
brand_id: brand_id || '',
order_no: order_no || '',
stadium_id: stadium_id || ''
})
.finally(res=>{
// setTimeout(()=>{
// this.getOrderDetail({
// brand_id: brand_id || '',
// order_no: order_no || ''
// });
// }, 1000);
opts?.finally?.(res);
});
}
})
}
export function siteAndPeopleRefundServer({ order_no = '', amount = 0, integral = 0 }){
showLoad();
return server.post({
url: ORDER_API.orderRefund,
data: {
order_no, amount, integral
},
failMsg: '操作失败!'
})
.then(res=>{
hideLoad();
showNone('操作成功!');
// this.orderInfo = res || {};
return 'success';
})
.catch(err=>{
hideLoad();
showNone('操作失败!');
console.warn('getOrderDetail err -->', err);
})
}

211
src/subpackage/order/pages/timekeeping/order_detail/deposit.vue

@ -0,0 +1,211 @@
<template>
<view class="deposit-order-detail">
<header-temp
:stadium-name="orderInfo.stadium_name"
:stadium-logo="orderInfo.stadium_logo"
>
<kv-line label="订单编号:">
<template v-slot:default>{{ orderInfo.order_no || '-' }}</template>
<template v-slot:right>
<text class="dod-status">{{ orderInfo.status_text || '-' }}</text>
</template>
</kv-line>
<kv-line label="创建时间:">{{ orderInfo.created_at || '-' }}</kv-line>
<kv-line label="手机号码:">{{ orderInfo.mobile || '-' }}</kv-line>
<kv-line label="用户昵称:">{{ orderInfo.nickname || '-' }}</kv-line>
<kv-line label="订单来源:">{{ orderInfo.source || '-' }}</kv-line>
<kv-line label="订单备注:">{{ orderInfo.desc || '-' }}</kv-line>
</header-temp>
<view class="od-margin"></view>
<info-temp title="订单信息">
<kv-line label="项目类型:">{{ orderInfo.project_type_name || '-' }}</kv-line>
<kv-line label="押金金额:">{{ orderInfo.amount || '0' }}</kv-line>
<view class="od-pay-info">
<kvs-line label="金额小计">¥{{ orderInfo.amount || '0' }}</kvs-line>
<kvs-line label="折扣金额">-¥{{ orderInfo.discount_amount || '0' }}</kvs-line>
<kvs-line label="积分抵扣">-¥{{ orderInfo.deduction_amount || '0' }}</kvs-line>
<kvs-line label="优惠券优惠">-¥{{ orderInfo.coupons_amount || '0' }}</kvs-line>
</view>
<view class="od-total">
<text class="ot-name">合计支付</text>{{ orderInfo.pay_amount || '0' }}
</view>
</info-temp>
<view class="od-margin"></view>
<info-temp title="关联押金订单">
<kv-line label="押金订单号:">
<template v-slot:default>{{ link_order.order_no || '-' }}</template>
<template v-slot:right>
<text class="od-check" @click="toTimingOrder">查看计时订单</text>
</template>
</kv-line>
<kv-line label="押金金额:">{{ orderInfo.amount || '-' }}</kv-line>
<kv-line label="订单状态:">{{ orderInfo.status_text || '-' }}</kv-line>
</info-temp>
<view class="od-margin"></view>
<info-temp title="支付信息">
<kv-line label="支付方式:">{{ orderInfo.pay_type_text || '-' }}</kv-line>
<kv-line label="支付时间:">{{ orderInfo.pay_time || '-' }}</kv-line>
<kv-line label="交易流水:">{{ orderInfo.trade_no || '-' }}</kv-line>
</info-temp>
<!-- 退款列表 -->
<view v-for="(e, i) in refundList" :key="i">
<view class="od-margin"></view>
<order-refund-info
:refund_price="e.amount || 0"
:refund_no="e.refund_no || '-'"
:refund_time="e.refund_time || '-'"
:refund_reason="e.reason || '-'"
:nameKey="i + 1"
></order-refund-info>
</view>
<bottom-fixed v-if="[ '已完成', '已退款', '已抵扣' ].includes(orderInfo.status_text)">
<refund-button
:pay_amount="orderInfo.pay_amount"
:refund_amount="orderInfo.refund_amount"
:refund_times="refundList.length || 0"
@click:button="refundOrder"
>退款</refund-button>
</bottom-fixed>
<!-- 退款弹窗 -->
<order-refund-modal
ref="orderRefundModal"
></order-refund-modal>
</view>
</template>
<script>
import headerTemp from "../modules/order_detail/header_temp.vue";
import infoTemp from "../modules/order_detail/info_temp.vue";
import kvLine from "../../../components/kv_line.vue";
import kvsLine from "../../../components/kvs_line.vue";
import bottomFixed from "../modules/order_detail/bottom_fixed.vue";
import refundButton from "@/components/order_refund/permission_btn.vue";
import orderRefundModal from '@/components/order_refund/modal.vue';
import orderRefundInfo from '@/components/order_refund/info.vue';
import { getOrderDetail, siteAndPeopleRefundServer } from "./common";
export default {
components: {
'header-temp': headerTemp,
'info-temp': infoTemp,
'kv-line': kvLine,
'kvs-line': kvsLine,
'bottom-fixed': bottomFixed,
'refund-button': refundButton,
'order-refund-modal': orderRefundModal,
'order-refund-info': orderRefundInfo
},
computed: {
link_order(){
let { orderInfo } = this;
return orderInfo?.extension?.link_order || {};
},
extension(){
return this.orderInfo?.extension || {};
}
},
data(){
return {
orderInfo: {},
refundList: []
}
},
async onLoad(options){
this.getOrderDetail({
brand_id: options?.brand_id || '',
order_no: options?.order_no || ''
})
},
methods: {
refundOrder(){
let { orderInfo, extension, refundList } = this;
this.$refs.orderRefundModal.show({
stadium_name: orderInfo?.stadium_name ?? '',
order_no: orderInfo?.order_no ?? '',
mobile: orderInfo?.mobile ?? '',
refundable_amount: extension?.refundable_amount ?? 0,
refundable_integral: extension?.refundable_integral ?? 0,
refund_times: refundList?.length || -1,
confirm: e => {
console.log('e', e)
siteAndPeopleRefundServer({
order_no: orderInfo?.order_no || '',
amount: e?.refund_amount || 0,
integral: e?.refund_integral || 0,
})
.finally(()=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id || '',
order_no: orderInfo?.order_no || ''
});
}, 1000);
})
}
});
},
toTimingOrder(){
let { order, link_order } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/site?order_no=${link_order?.order_no || ''}&brand_id=${order?.brand_id || ''}`, 'rT');
},
//
async getOrderDetail({ brand_id = '', order_no = '' }){
let _detail = await getOrderDetail({ brand_id, order_no });
this.orderInfo = _detail || {};
this.getRefundData({ order_no });
return _detail;
},
// 退
async getRefundData({ order_no }){
let _refundRes = await this.$store.dispatch('getOrderRefundList', order_no);
let _refundLs = _refundRes?.data?.data?.list || [];
this.refundList = _refundLs;
},
}
}
</script>
<style lang="scss">
.deposit-order-detail{
padding: 24upx;
.dod-status{
margin-left: auto;
flex-shrink: 0;
@include flcw(28upx, 40upx, #9C9C9F);
}
.od-margin{
height: 24upx;
background: transparent;
}
.od-pay-info{
margin-top: 20upx;
border-top: 1px solid #D8D8D8;
}
.od-total{
padding-top: 10upx;
text-align: right;
@include flcw(28upx, 50upx, #1A1A1A, 500);
@include tHide;
.ot-name{
color: #9A9A9D;
font-weight: 400;
}
}
.od-check{
margin-left: auto;
flex-shrink: 0;
@include flcw(24upx, 40upx, $mColor);
}
}
</style>

268
src/subpackage/order/pages/timekeeping/order_detail/person.vue

@ -0,0 +1,268 @@
<template>
<view class="person-order-detail">
<header-temp
:stadium-name="orderInfo.stadium_name"
:stadium-logo="orderInfo.stadium_logo"
>
<kv-line label="订单编号:">
<template v-slot:default>{{ orderInfo.order_no || '-' }}</template>
<template v-slot:right>
<text
class="pod-status"
:class="{ active: [ '计费中', '待支付' ].includes(orderInfo.status_text) }"
>{{ orderInfo.status_text || '-' }}</text>
</template>
</kv-line>
<kv-line label="创建时间:">{{ orderInfo.created_at || '-' }}</kv-line>
<kv-line label="手机号码:">{{ orderInfo.mobile || '-' }}</kv-line>
<kv-line label="用户昵称:">{{ orderInfo.nickname || '-' }}</kv-line>
</header-temp>
<view class="pod-margin"></view>
<info-temp title="计时信息">
<kv-line label="项目类型:">人时({{ orderInfo.project_type_name || '-' }})</kv-line>
<kv-line label="进场时间:">{{ orderInfo.start_time || '-' }}</kv-line>
<kv-line label="离场时间:">{{ orderInfo.end_time || '-' }}</kv-line>
<kv-line label="时长合计:">{{ extension.duration || '-' }}</kv-line>
<block v-if="[ '已完成', '已退款', '待支付' ].includes(orderInfo.status_text)">
<view class="pod-pay-info">
<kvs-line label="金额小计">¥{{ orderInfo.amount || '0' }}</kvs-line>
<kvs-line label="折扣金额">-¥{{ orderInfo.discount_amount || '0' }}</kvs-line>
<kvs-line label="积分抵扣">-¥{{ orderInfo.deduction_amount || '0' }}</kvs-line>
<kvs-line label="优惠券优惠">-¥{{ orderInfo.coupons_amount || '0' }}</kvs-line>
</view>
<view class="pod-total">
<text class="pt-name">合计支付</text>{{ orderInfo.pay_amount || '0' }}
</view>
</block>
</info-temp>
<blcok v-if="[ '已完成', '已退款' ].includes(orderInfo.status_text)">
<view class="pod-margin"></view>
<info-temp title="支付信息">
<kv-line label="支付方式:">{{ orderInfo.pay_type_text || '-' }}</kv-line>
<kv-line label="支付时间:">{{ orderInfo.pay_time || '-' }}</kv-line>
<kv-line label="微信交易号:">{{ orderInfo.trade_no || '-' }}</kv-line>
</info-temp>
</blcok>
<!-- 退款列表 -->
<view v-for="(e, i) in refundList" :key="i">
<view class="pod-margin"></view>
<order-refund-info
:refund_price="e.amount || 0"
:refund_no="e.refund_no || '-'"
:refund_time="e.refund_time || '-'"
:refund_reason="e.reason || '-'"
:nameKey="i + 1"
></order-refund-info>
</view>
<block v-if="[ '待支付', '计费中' ].includes(orderInfo.status_text)">
<view class="pod-margin"></view>
<view class="pod-margin"></view>
<view
class="pod-btn"
v-if="orderInfo.status_text === '待支付'"
@click="finishOrder"
>完结订单</view>
<view
class="pod-btn"
v-if="orderInfo.status_text === '计费中'"
@click="endOrder"
>结束计费</view>
</block>
<!-- <view class="pod-fixed">
<view class="pf-btn">取消预约</view>
</view> -->
<bottom-fixed v-if="[ '已完成', '已退款' ].includes(orderInfo.status_text)">
<refund-button
:pay_amount="orderInfo.pay_amount"
:refund_amount="orderInfo.refund_amount"
:refund_times="refundList.length || 0"
@click:button="refundOrder"
>退款</refund-button>
</bottom-fixed>
<!-- 结束计费弹窗 -->
<end-billing-modal ref="endBillingModal"></end-billing-modal>
<!-- 退款弹窗 -->
<order-refund-modal
ref="orderRefundModal"
></order-refund-modal>
</view>
</template>
<script>
import headerTemp from "../modules/order_detail/header_temp.vue";
import infoTemp from "../modules/order_detail/info_temp.vue";
import kvLine from "../../../components/kv_line.vue";
import kvsLine from "../../../components/kvs_line.vue";
import endBillingModal from "../modules/order_detail/end_billing_modal.vue";
import bottomFixed from "../modules/order_detail/bottom_fixed.vue";
import refundButton from "@/components/order_refund/permission_btn.vue";
import orderRefundModal from '@/components/order_refund/modal.vue';
import orderRefundInfo from '@/components/order_refund/info.vue';
// import bottomFixed from "../modules/order_detail/bf_button.vue";
import { getOrderDetail, finishOrder, siteAndPeopleRefundServer } from "./common";
export default {
components: {
'header-temp': headerTemp,
'info-temp': infoTemp,
'kv-line': kvLine,
'kvs-line': kvsLine,
'bottom-fixed': bottomFixed,
'end-billing-modal': endBillingModal,
'refund-button': refundButton,
'order-refund-modal': orderRefundModal,
'order-refund-info': orderRefundInfo
},
computed: {
extension(){
return this.orderInfo?.extension || {};
}
},
data(){
return {
orderInfo: {},
refundList: []
}
},
async onLoad(options){
this.getOrderDetail({
brand_id: options?.brand_id || '',
order_no: options?.order_no || ''
})
.then(res=>{
if(res?.status_text === '计费中'&&options?.is_end === '1'){
this.endOrder();
}
});
},
methods: {
refundOrder(){
let { orderInfo, extension, refundList } = this;
this.$refs.orderRefundModal.show({
stadium_name: orderInfo?.stadium_name ?? '',
order_no: orderInfo?.order_no ?? '',
mobile: orderInfo?.mobile ?? '',
refundable_amount: extension?.refundable_amount ?? 0,
refundable_integral: extension?.refundable_integral ?? 0,
refund_times: refundList?.length || -1,
confirm: e => {
console.log('e', e)
siteAndPeopleRefundServer({
order_no: orderInfo?.order_no || '',
amount: e?.refund_amount || 0,
integral: e?.refund_integral || 0,
})
.finally(()=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id || '',
order_no: orderInfo?.order_no || ''
});
}, 1000);
})
}
});
},
//
endOrder(){
let { orderInfo } = this;
this.$refs.endBillingModal.initModal({
operator: orderInfo?.end_bill_operator_name,
duration: orderInfo?.extension?.duration,
amount: orderInfo?.amount,
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no,
success: res=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no
});
}, 1000);
}
});
},
// //
finishOrder(){
let { orderInfo } = this;
finishOrder({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no,
stadium_id: orderInfo?.stadium_id,
opts: {
finally: ()=> {
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no
});
}, 1000);
}
}
})
},
//
async getOrderDetail({ brand_id = '', order_no = '' }){
let _detail = await getOrderDetail({ brand_id, order_no });
this.orderInfo = _detail || {};
this.getRefundData({ order_no });
return _detail;
},
// 退
async getRefundData({ order_no }){
let _refundRes = await this.$store.dispatch('getOrderRefundList', order_no);
let _refundLs = _refundRes?.data?.data?.list || [];
this.refundList = _refundLs;
}
}
}
</script>
<style lang="scss">
.person-order-detail{
padding: 24upx;
.pod-status{
margin-left: auto;
flex-shrink: 0;
@include flcw(28upx, 40upx, #9C9C9F);
&.active{
color: $mColor;
}
}
}
.pod-margin{
height: 24upx;
background: transparent;
}
.pod-pay-info{
margin-top: 20upx;
border-top: 1px solid #D8D8D8;
}
.pod-total{
padding-top: 10upx;
text-align: right;
@include flcw(28upx, 50upx, #1A1A1A, 500);
@include tHide;
.pt-name{
color: #9A9A9D;
font-weight: 400;
}
}
.pod-btn{
text-align: center;
border-radius: 10upx;
background: $mColor;
@include flcw(32upx, 112upx, #fff, 500);
}
</style>

382
src/subpackage/order/pages/timekeeping/order_detail/site.vue

@ -0,0 +1,382 @@
<template>
<view class="site-order-detail">
<header-temp
:stadium-name="orderInfo.stadium_name"
:stadium-logo="orderInfo.stadium_logo"
>
<kv-line label="订单编号:">
<template v-slot:default>{{ orderInfo.order_no || '-' }}</template>
<template v-slot:right>
<text
class="od-status"
:class="[ '待使用', '使用中', '待支付', '计费中' ].includes(orderInfo.status_text) ? 'active' : ''"
>{{ orderInfo.status_text || '-' }}</text>
</template>
</kv-line>
<kv-line label="创建时间:">{{ orderInfo.created_at || '-' }}</kv-line>
<kv-line label="手机号码:">{{ orderInfo.mobile || '-' }}</kv-line>
<kv-line label="用户昵称:">{{ orderInfo.nickname || '-' }}</kv-line>
</header-temp>
<view class="od-margin"></view>
<info-temp title="场地计时信息">
<kv-line label="项目类型:">({{ orderInfo.project_type_name || '-' }})</kv-line>
<kv-line label="进场时间:">{{ orderInfo.start_time || '-' }}</kv-line>
<kv-line
label="离场时间:"
v-if="[ '待使用', '已取消预约', '计费中', '使用中' ].includes(orderInfo.status_text)&&orderInfo.settlement_type === 1"
>现场扫码结算</kv-line>
<kv-line label="离场时间:" v-else>{{ orderInfo.end_time || '-' }}</kv-line>
<kv-line label="时长合计:">{{ orderInfo.extension&&orderInfo.extension.duration || '-' }}</kv-line>
<block
v-if="orderInfo.settlement_type === 1 || [ '已完成', '已退款', '待支付', '已失效' ].includes(orderInfo.status_text)"
>
<view class="od-pay-info">
<kvs-line label="金额小计">¥{{ orderInfo.amount || '0' }}</kvs-line>
<kvs-line label="折扣金额">-¥{{ orderInfo.discount_amount || '0' }}</kvs-line>
<kvs-line label="积分抵扣">-¥{{ orderInfo.deduction_amount || '0' }}</kvs-line>
<kvs-line label="优惠券优惠">-¥{{ orderInfo.coupons_amount || '0' }}</kvs-line>
</view>
<view class="od-total">
<text class="pt-name">合计支付</text>{{ orderInfo.pay_amount || '0' }}
</view>
</block>
</info-temp>
<block v-if="extension.show_deposit">
<view class="od-margin"></view>
<info-temp title="关联押金订单">
<kv-line label="押金订单号:">
<template v-slot:default>{{ orderInfo.deposit_order_no || '-' }}</template>
<template v-slot:right>
<text class="od-check" @click="toDepoistDetail">查看押金订单</text>
</template>
</kv-line>
<kv-line label="押金金额:">{{ extension.deposit_amount || '0' }}</kv-line>
<kv-line label="订单状态:">
<template v-slot:default>{{ extension.deposit_status_text || '-' }}</template>
<!-- <template v-slot:right>
<text class="od-deposit-explain">(押金已原路退返账户请留意查收!)</text>
</template> -->
</kv-line>
</info-temp>
</block>
<block v-if="orderInfo.status_text === '已取消预约'">
<view class="od-margin"></view>
<info-temp>
<kv-line label="取消时间:">{{ orderInfo.cancel_time || '-' }}</kv-line>
<kv-line label="取消原因:">{{ orderInfo.cancel_reason || '-' }}</kv-line>
</info-temp>
</block>
<block v-if="orderInfo.settlement_type === 1 || [ '已完成', '已退款', '已失效' ].includes(orderInfo.status_text)">
<view class="od-margin"></view>
<info-temp title="支付信息">
<kv-line label="支付方式:">{{ orderInfo.pay_type_text || '-' }}</kv-line>
<kv-line label="支付时间:">{{ orderInfo.pay_time || '-' }}</kv-line>
<kv-line label="交易流水:">{{ orderInfo.trade_no || '-' }}</kv-line>
</info-temp>
</block>
<block v-if="orderInfo.status_text === '计费中'">
<view class="od-margin"></view>
<info-temp title="费用详情">
<kv-line label="产生费用:"><text class="od-check">{{ orderInfo.amount || '0' }}</text></kv-line>
</info-temp>
</block>
<!-- <view class="od-margin"></view>
<info-temp title="退款信息1">
<kv-line label="退款金额:">998</kv-line>
<kv-line label="退款单号:">TF-20195171564566</kv-line>
<kv-line label="退款时间:">2019-05-17 11:12:58</kv-line>
<kv-line label="退款原因:">商家主动退款</kv-line>
</info-temp>
<view class="od-margin"></view>
<info-temp title="退款信息2">
<kv-line label="退款金额:">998</kv-line>
<kv-line label="退款单号:">TF-20195171564566</kv-line>
<kv-line label="退款时间:">2019-05-17 11:12:58</kv-line>
<kv-line label="退款原因:">商家主动退款</kv-line>
</info-temp> -->
<!-- 退款列表 -->
<view v-for="(e, i) in refundList" :key="i">
<view class="od-margin"></view>
<order-refund-info
:refund_price="e.amount || 0"
:refund_no="e.refund_no || '-'"
:refund_time="e.refund_time || '-'"
:refund_reason="e.reason || '-'"
:nameKey="i + 1"
></order-refund-info>
</view>
<block v-if="[ '待支付', '计费中', '待使用' ].includes(orderInfo.status_text)">
<view class="od-margin"></view>
<view class="od-margin"></view>
<view
class="pod-btn"
v-if="orderInfo.status_text === '待支付'"
@click="finishOrder"
>完结订单</view>
<view
class="pod-btn"
v-if="orderInfo.status_text === '计费中'"
@click="endOrder"
>结束计费</view>
<view
class="pod-btn"
v-if="orderInfo.status_text === '待使用'"
@click="cancelOrder"
>取消预约</view>
</block>
<bottom-fixed v-if="[ '使用中', '已失效', '已完成', '已退款' ].includes(orderInfo.status_text)">
<refund-button
:pay_amount="orderInfo.pay_amount"
:refund_amount="orderInfo.refund_amount"
:refund_times="refundList.length || 0"
@click:button="refundOrder"
>退款</refund-button>
</bottom-fixed>
<!-- 结束计费弹窗 -->
<end-billing-modal ref="endBillingModal"></end-billing-modal>
<!-- 退款弹窗 -->
<order-refund-modal ref="orderRefundModal" ></order-refund-modal>
</view>
</template>
<script>
/*
这页面只是场时订单
type:
2是人时 1 3是场时
1是场时 3是场时的押金
预约订单是另外一个字段判断 -> enable_subscribe
------------------
enable_subscribe= true&&type= 1 --> 预约订单
enable_subscribe= true&&type= 3 --> 预约的押金订单
settlement_type --> 结算方式[0离场结算1用前结算]
人时和场时分开不考虑人时订单
*/
import headerTemp from "../modules/order_detail/header_temp.vue";
import infoTemp from "../modules/order_detail/info_temp.vue";
import kvLine from "../../../components/kv_line.vue";
import kvsLine from "../../../components/kvs_line.vue";
import endBillingModal from "../modules/order_detail/end_billing_modal.vue";
import bottomFixed from "../modules/order_detail/bottom_fixed.vue";
import refundButton from "@/components/order_refund/permission_btn.vue";
import orderRefundModal from '@/components/order_refund/modal.vue';
import orderRefundInfo from '@/components/order_refund/info.vue';
import { showModal, routeTo } from '@/utils/util';
import { getOrderDetail, cancelOrderServer, finishOrder, siteAndPeopleRefundServer } from "./common";
export default {
components: {
'header-temp': headerTemp,
'info-temp': infoTemp,
'kv-line': kvLine,
'kvs-line': kvsLine,
'bottom-fixed': bottomFixed,
'end-billing-modal': endBillingModal,
'refund-button': refundButton,
'order-refund-modal': orderRefundModal,
'order-refund-info': orderRefundInfo
},
computed: {
extension(){
let { orderInfo } = this;
return orderInfo?.extension || {};
}
},
data(){
return {
orderInfo: {},
refundList: []
}
},
onLoad(options){
this.getOrderDetail({
brand_id: options?.brand_id || '',
order_no: options?.order_no || ''
})
.then(res=>{
if(res?.status_text === '计费中'&&options?.is_end === '1'){
this.endOrder();
}
if(res?.status_text === '待使用'&&options?.is_end === '2'){
this.cancelOrder();
}
});
},
methods: {
refundOrder(){
let { orderInfo, extension, refundList } = this;
this.$refs.orderRefundModal.show({
stadium_name: orderInfo?.stadium_name ?? '',
order_no: orderInfo?.order_no ?? '',
mobile: orderInfo?.mobile ?? '',
refundable_amount: extension?.refundable_amount ?? 0,
refundable_integral: extension?.refundable_integral ?? 0,
refund_times: refundList?.length || -1,
confirm: e => {
console.log('e', e)
siteAndPeopleRefundServer({
order_no: orderInfo?.order_no || '',
amount: e?.refund_amount || 0,
integral: e?.refund_integral || 0,
})
.finally(()=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id || '',
order_no: orderInfo?.order_no || ''
});
}, 1000);
})
}
});
},
//
cancelOrder(){
let { orderInfo } = this;
showModal({
title: '提示',
content: '是否确认取消订单?',
showCancel: true,
success: modalRes=>{
if(modalRes.confirm)cancelOrderServer({
brand_id: orderInfo?.brand_id || '',
order_no: orderInfo?.order_no || ''
})
.finally(res=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no
});
}, 1000);
});
}
})
},
//
endOrder(){
let { orderInfo } = this;
this.$refs.endBillingModal.initModal({
operator: orderInfo?.end_bill_operator_name,
duration: orderInfo?.extension?.duration,
amount: orderInfo?.amount,
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no,
success: res=>{
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no
});
}, 1000);
}
});
},
// //
finishOrder(){
let { orderInfo } = this;
finishOrder({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no,
stadium_id: orderInfo?.stadium_id,
opts: {
finally: ()=> {
setTimeout(()=>{
this.getOrderDetail({
brand_id: orderInfo?.brand_id,
order_no: orderInfo?.order_no
});
}, 1000);
}
}
})
},
toDepoistDetail(){
let { orderInfo } = this;
routeTo(`/subpackage/order/pages/timekeeping/order_detail/deposit?order_no=${orderInfo.deposit_order_no || ''}&brand_id=${orderInfo.brand_id || ''}`, 'rT');
},
//
async getOrderDetail({ brand_id = '', order_no = '' }){
let _detail = await getOrderDetail({ brand_id, order_no });
this.orderInfo = _detail || {};
this.getRefundData({ order_no });
return _detail;
},
// 退
async getRefundData({ order_no }){
let _refundRes = await this.$store.dispatch('getOrderRefundList', order_no);
let _refundLs = _refundRes?.data?.data?.list || [];
this.refundList = _refundLs;
}
}
}
</script>
<style lang="scss">
.site-order-detail{
padding: 24upx;
.od-status{
margin-left: auto;
flex-shrink: 0;
@include flcw(28upx, 40upx, #9C9C9F);
&.active{
color: $mColor;
}
}
.od-check{
margin-left: auto;
flex-shrink: 0;
@include flcw(24upx, 40upx, $mColor);
}
.od-pay-info{
margin-top: 20upx;
border-top: 1px solid #D8D8D8;
}
.od-total{
padding-top: 10upx;
text-align: right;
@include flcw(28upx, 50upx, #1A1A1A, 500);
@include tHide;
.pt-name{
color: #9A9A9D;
font-weight: 400;
}
}
.od-deposit-explain{
margin-left: 12upx;
@include flcw(24upx, 40upx, #9C9C9F);
@include tHide;
}
}
.od-margin{
height: 24upx;
background: transparent;
}
.pod-btn{
text-align: center;
border-radius: 10upx;
background: $mColor;
@include flcw(32upx, 112upx, #fff, 500);
}
</style>

281
src/subpackage/order/pages/timekeeping/order_list.vue

@ -0,0 +1,281 @@
<template>
<view class="timekeeping-order-list">
<order-list-header
ref="orderListHeader"
@change:stadium="changeStadium"
@click:time="showPeriodModal"
@click:filter="showFilterModal"
@click:search="searchOrder"
:start-time="condition.start"
:end-time="condition.end"
:success-count="countInfo.success_count"
:refund-count="countInfo.refund_count"
></order-list-header>
<view class="tol-list">
<block v-for="(e, i) in orderList" :key="i">
<view class="tl-item" v-if="e.order_type === 1">
<site-list-item :order="e"></site-list-item>
</view>
<view class="tl-item" v-if="e.order_type === 2">
<person-list-item :order="e"></person-list-item>
</view>
<view class="tl-item" v-if="e.order_type === 3">
<deposit-list-item :order="e"></deposit-list-item>
</view>
</block>
</view>
<!-- 时间段选择 -->
<period-modal ref="periodModal" ></period-modal>
<!-- status窗口 -->
<filter-modal ref="filterModal"></filter-modal>
</view>
</template>
<script>
import orderListHeader from "../../components/order_list/header.vue";
import periodModal from "../../components/order_list/period_modal.vue";
import filterModal from "../../components/order_list/filter_modal.vue";
import personListItem from "./modules/order_list/person.vue";
import siteListItem from "./modules/order_list/site.vue";
import depositListItem from "./modules/order_list/deposit.vue";
import { ORDER_API } from '../../js/api';
import server from '../../js/server';
import { showLoad, hideLoad, formatDate, showNone, routeTo } from '@/utils/util';
const enumOrderType = {
site: '1', //
person: '2' //
}
export default {
components: {
'order-list-header': orderListHeader,
'period-modal': periodModal,
'filter-modal': filterModal,
'person-list-item': personListItem,
'site-list-item': siteListItem,
'deposit-list-item': depositListItem,
},
watch: {
condition: {
handler(nVal, oVal){
this.orderList = [];
this.countInfo.refund_count = 0;
this.countInfo.success_count = 0;
let { brand_id, order_type } = this;
this.getOrderList({
brand_id: brand_id || '',
order_type: order_type || '',
...nVal,
})
},
deep: true
}
},
data(){
return {
brand_id: '',
order_type: '', // 2: 1:
condition: { //
stadium_id: '', // id
start: '', //
end: '', //
status: '', //
status_text: '', //
},
page: 1,
orderList: [],
countInfo: {
// refund_count: 0, // 退
// success_count: 0, //
// total: 0, //
},
}
},
async onLoad(options){
let _bID = options?.brand_id || '';
let _order_type = options?.order_type || '';
this.setTitle(_order_type);
let { start, end } = this.initDefaultDate();
let { value } = this.initDefaultStatus(_order_type);
this.getOrderList({
brand_id: _bID,
start: start,
end: end,
status_text: value,
order_type: _order_type
})
this.brand_id = _bID;
this.order_type = _order_type;
let _list = await this.$refs.orderListHeader.initStadiumSelect(_bID);
},
onReachBottom(){
let { brand_id, order_type, condition, page } = this;
this.getOrderList({
brand_id: brand_id || '',
order_type: order_type || '',
page: page + 1,
...condition,
})
},
methods: {
//
searchOrder(){
let { brand_id, order_type } = this;
let _qryStr = `brand_id=${brand_id || ''}&order_type=${order_type || ''}`;
routeTo(`/subpackage/order/pages/timekeeping/order_search?${_qryStr}`, 'nT');
},
setTitle(type){
let _title = '';
switch(type){
case enumOrderType.site:
_title = '场地计时订单';
break;
case enumOrderType.person:
_title = '散客计时订单';
break;
}
uni.setNavigationBarTitle({
title: _title
})
},
//
showFilterModal(){
this.$refs.filterModal.init({
title: '订单状态',
list: this.getFilterList(this.order_type),
curValue: this.condition.status_text,
success: item =>{
console.log(item);
this.condition.status_text = item.value;
}
});
},
//
initDefaultStatus(order_type){
let _ls = this.getFilterList(order_type);
let _defaultItem = _ls?.[0] || {}
this.condition.status_text = _defaultItem?.value;
return _defaultItem;
},
//
getFilterList(order_type){
let _obj = {
[enumOrderType.site]: [
{ label: '全部', value: '' },
{ label: '待使用', value: '待使用' },
{ label: '计费中', value: '计费中' },
{ label: '待支付', value: '待支付' },
{ label: '已完成', value: '已完成' },
{ label: '已退款', value: '已退款' },
{ label: '押金', value: '押金' },
],
[enumOrderType.person]: [
{ label: '全部', value: '' },
{ label: '计费中', value: '计费中' },
{ label: '待支付', value: '待支付' },
{ label: '已完成', value: '已完成' },
{ label: '已退款', value: '已退款' },
]
}
return _obj?.[order_type] ?? {};
},
//
changeStadium(e){
this.condition.stadium_id = e.id;
},
//
showPeriodModal(){
let { start, end } = this.condition;
this.$refs.periodModal.init({
start: start,
end: end,
success: res=>{
this.condition.start = res.start;
this.condition.end = res.end;
}
});
},
//
initDefaultDate(){
let _date = new Date();
let _sevenTimeStemp = 7*24*60*60*1000;
let _beforeSeven = _date.getTime() - _sevenTimeStemp;
let _obj = {
start: formatDate({ date: _beforeSeven }),
end: formatDate({})
}
this.condition.start = _obj.start;
this.condition.end = _obj.end;
return _obj;
},
/**
* @param {String} brand_id 品牌id
* @param {String} stadium_id 场馆id
* @param {String} status 支付状态:未支付/已支付/已退款/反馈[0/1/2/3]
* @param {String} start 开始时间
* @param {String} end 结束时间
* @param {String} order_type 订单类型:场时/人时[1/2]
* @param {String} status_text 已关闭/计费中/待支付/待使用/使用中/已失效/已完成/已抵扣/已退款/已取消预约
*
* */
getOrderList({
brand_id = '', stadium_id = '',
status = '', start = '', end = '',
order_type = '', page = 1, page_size = 20,
status_text = ''
}){
showLoad();
server.get({
url: ORDER_API.billingOrderList,
data: {
brand_id, stadium_id, status,
start: start + ' 00:00:00', end: end + ' 23:59:59',
order_type: this.getReqOrderType(order_type), page, page_size,
status_text: status_text === '押金' ? '' : status_text
},
failMsg: '加载失败!'
})
.then(res=>{
hideLoad();
let { list, ...info } = res;
let _list = list || [];
if(page == 1){
this.countInfo = info;
this.orderList = _list;
return
}
if(_list?.length <= 0)return showNone('没有更多数据了!');
this.orderList = [...this.orderList, ..._list];
this.page = page;
})
},
//
getReqOrderType(type){
let { condition } = this;
if(type === enumOrderType.site&&condition.status_text === '押金')return '3'; //
if(type === enumOrderType.site)return '1,3'; //
return type;
}
}
}
</script>
<style lang="scss">
.timekeeping-order-list{
@include isPd(20upx);
}
.tol-list{
padding: 0 24upx;
.tl-item + .tl-item{
margin-top: 24upx;
}
}
</style>

132
src/subpackage/order/pages/timekeeping/order_search.vue

@ -0,0 +1,132 @@
<template>
<view class="order-search">
<search-bar
@confirm:search="searchOrder"
></search-bar>
<view class="os-list">
<block v-for="(e, i) in orderList" :key="i">
<view class="tl-item" v-if="e.order_type === 1">
<site-list-item :order="e"></site-list-item>
</view>
<view class="tl-item" v-if="e.order_type === 2">
<person-list-item :order="e"></person-list-item>
</view>
<view class="tl-item" v-if="e.order_type === 3">
<deposit-list-item :order="e"></deposit-list-item>
</view>
</block>
</view>
</view>
</template>
<script>
import search_bar from './modules/order_search/search_bar.vue';
import personListItem from "./modules/order_list/person.vue";
import siteListItem from "./modules/order_list/site.vue";
import depositListItem from "./modules/order_list/deposit.vue";
import { ORDER_API } from '../../js/api';
import server from '../../js/server';
import { showLoad, hideLoad, showNone } from '@/utils/util';
const enumOrderType = {
site: '1', //
person: '2' //
}
export default {
components: {
'search-bar': search_bar,
'person-list-item': personListItem,
'site-list-item': siteListItem,
'deposit-list-item': depositListItem,
},
data() {
return {
orderList: [],
page: 1,
optionsQuery: {
brand_id: '',
order_type: '',
},
searchTxt: ''
}
},
onLoad(options) {
this.optionsQuery = options;
},
onReachBottom(){
let { page, optionsQuery, searchTxt } = this;
this.getOrderList({
brand_id: optionsQuery?.brand_id || '',
order_type: optionsQuery?.order_type || '',
key: searchTxt || '',
page: ++page
})
},
methods: {
searchOrder(value){
let { optionsQuery } = this;
this.searchTxt = value;
this.getOrderList({
brand_id: optionsQuery.brand_id,
order_type: optionsQuery.order_type,
key: value
})
},
/**
* @param {String} brand_id 品牌id
* @param {String} stadium_id 场馆id
* @param {String} status 支付状态:未支付/已支付/已退款/反馈[0/1/2/3]
* @param {String} start 开始时间
* @param {String} end 结束时间
* @param {String} order_type 订单类型:场时/人时[1/2]
* @param {String} status_text 已关闭/计费中/待支付/待使用/使用中/已失效/已完成/已抵扣/已退款/已取消预约
* @param {String} key 搜索关键字
*
* */
getOrderList({
brand_id = '', stadium_id = '',
status = '', start = '', end = '',
order_type = '', page = 1, page_size = 20,
status_text = '', key = ''
}){
showLoad();
server.get({
url: ORDER_API.billingOrderList,
data: {
brand_id, stadium_id, status,
start, end, order_type: this.getReqOrderType(order_type), page, page_size,
status_text, key
},
failMsg: '加载失败!'
})
.then(res=>{
hideLoad();
let { list, ...info } = res;
let _list = list || [];
if(page == 1)return this.orderList = _list;
if(_list?.length <= 0)return showNone('没有更多数据了!');
this.page = page;
this.orderList = [...this.orderList, ..._list];
})
},
//
getReqOrderType(type){
if(type === enumOrderType.site)return '1,3'; //
return type;
}
}
}
</script>
<style lang="scss">
.os-list{
padding: 24upx;
@include isPd(24upx);
.tl-item + .tl-item{
margin-top: 24upx;
}
}
</style>

379
src/subpackage/order/pages/timing/detail.vue

@ -1,379 +0,0 @@
<template>
<view class="timing-details">
<view class="td-head">
<view class="th-store">
<image :src="orderInfo.stadium_logo || ''"></image>
<view>{{orderInfo.stadium_name || '-'}}</view>
</view>
<view class="th-line">
<view>订单编号<text>{{orderInfo.order_no || '-'}}</text></view>
<view><text :class="[orderInfo.pay_status == 0?'tl-active':'']">{{zh_order_status(orderInfo.pay_status)}}</text></view>
</view>
<view class="th-line">
<view>创建时间<text>{{orderInfo.model.created_at || '-'}}</text></view>
</view>
<view class="th-line">
<view>用户昵称<text>{{orderInfo.nickname || '-'}}</text></view>
</view>
</view>
<view class="td-box">
<view class="tb-title">计时信息</view>
<view class="tb-line">
<!-- 项目 场时有 人时没有 order_type: 1场时 2人时 -->
<view v-if="orderInfo.order_type==1">项目<text>{{orderInfo.project_name || '-'}}({{orderInfo.venue_name || '-'}})</text></view>
<view>进场时间<text>{{orderInfo.start_time || '-'}}</text></view>
<!-- 离场时间 已完成显示 -->
<view v-if="orderInfo.pay_status != 0">离场时间<text>{{orderInfo.end_time || '-'}}</text></view>
<view>时长合计<text>{{orderInfo.extension.duration || '-'}}</text></view>
</view>
<view class="tb-section" v-if="!(orderInfo.pay_status== 0&&orderInfo.early_end_timing==false)">
<view class="ts-line">
<view>金额小计</view>
<view>¥{{orderInfo.amount || 0}}</view>
</view>
<view class="ts-line">
<view>积分抵扣</view>
<view>-¥{{orderInfo.deduction_amount ||0}}</view>
</view>
<view class="ts-line">
<view>折扣金额</view>
<view>-¥{{orderInfo.discount_amount||0}}</view>
</view>
<view class="ts-line">
<view>优惠券优惠</view>
<view>-¥{{orderInfo.coupons_amount || 0}}</view>
</view>
<view class="ts-total">
<view>合计支付<text></text><text>{{orderInfo.pay_amount ||0}}</text></view>
</view>
</view>
</view>
<view class="td-box" v-if="orderInfo.pay_status != 0">
<view class="tb-title">支付信息</view>
<view class="tb-line">
<view>支付方式<text>{{zh_pay_type(orderInfo.pay_type)}}</text></view>
<view>支付时间<text>{{orderInfo.pay_time || '-'}}</text></view>
<view v-if="orderInfo.pay_type==0">微信交易号<text>{{orderInfo.trade_no || ''}}</text></view>
<view v-if="orderInfo.pay_type==3">操作人<text>{{orderInfo.end_bill_operator_name || ''}}</text></view>
</view>
</view>
<!-- 退款列表 -->
<view v-for="(e, i) in refundList" :key="i" style="padding: 24rpx 24rpx 0;">
<order-refund-info
:refund_price="e.amount || 0"
:refund_no="e.refund_no || '-'"
:refund_time="e.refund_time || '-'"
:refund_reason="e.reason || '-'"
:nameKey="i + 1"
></order-refund-info>
</view>
<view class="td-btn" @click="isEndBill = true" v-if="orderInfo.pay_status == 0&&orderInfo.early_end_timing==false">结束计费</view>
<view class="td-btn" @click="completeBtn" v-if="orderInfo.pay_status == 0&&orderInfo.early_end_timing==true">完结订单</view>
<!-- 退款按钮拦 -->
<order-refund-fixed
:pay_amount="orderInfo.pay_amount || 0"
:refund_amount="orderInfo.refund_amount || 0"
:refund_times="(refundList&&refundList.length) || 0"
@click:button="refunndBtn"
></order-refund-fixed>
<!-- 结束计费弹框 -->
<end-billing-modal
v-if="isEndBill==true"
@close="isEndBill=false"
@timeEndBtn="timeEndBtn"
:orderInfo="orderInfo"
></end-billing-modal>
<!-- 退款弹窗 -->
<order-refund-modal
ref="orderRefundModal"
></order-refund-modal>
</view>
</template>
<script>
import util from '@/utils/util';
import { ORDER_API } from '../../js/api';
import server from '../../js/server';
import { mapState } from 'vuex';
import end_billing_modal from '@/components/end_billing_modal/end_billing_modal.vue';
import orderRefundFixed from '@/components/order_refund/fixed.vue'
import orderRefundModal from '@/components/order_refund/modal.vue';
import orderRefundInfo from '@/components/order_refund/info.vue';
export default {
components: {
'end-billing-modal': end_billing_modal,
'order-refund-fixed': orderRefundFixed,
'order-refund-modal': orderRefundModal,
'order-refund-info': orderRefundInfo
},
computed: {
...mapState(['brandInfo']),
zh_order_status(){
// 01
let { orderInfo } = this
return status =>{
const _obj = {
'0': orderInfo.early_end_timing==true?'待支付':'计费中',
'1': '已完成',
'4': '已退款',
}
return _obj[`${status}`] || '-'
}
},
},
data() {
return {
isEndBill: false,
orderInfo: {},
refundList: [], // 退
}
},
onLoad(options){
this.getOrderInfo({
order_no: options?.order_no || '',
stadium_id: options?.stadium_id || ''
})
this.getRefundTimes(options?.order_no || '');
},
methods: {
refunndBtn(){
let { orderInfo, refundList } = this;
this.$refs.orderRefundModal.show({
stadium_name: orderInfo?.stadium_name ?? '',
order_no: orderInfo?.order_no ?? '',
mobile: orderInfo?.mobile ?? '',
refundable_amount: orderInfo?.extension?.refundable_amount ?? 0,
refundable_integral: orderInfo?.extension?.refundable_integral ?? 0,
refund_times: refundList?.length || -1,
confirm: e => {
this.orderRefund({
order_no: orderInfo?.order_no || '',
amount: e.refund_amount || 0,
integral: e.refund_integral || 0,
stadium_id: orderInfo?.stadium_id || ''
})
}
});
},
orderRefund({ order_no = '', amount = 0, integral = 0, stadium_id = ''}){
util.showLoad();
server.get({
url: ORDER_API.orderRefund,
data: { order_no, amount, integral },
isDefaultGet: false
})
.then(res=>{
util.hideLoad();
if(res.data.code == 0){
util.showNone(res.data.message || '操作成功!');
}else{
util.showNone(res.data.message || '操作失败!');
}
})
.catch(util.hideLoad)
.finally(_=>setTimeout(_=>{
this.getOrderInfo({ order_no, stadium_id });
this.getRefundTimes(order_no);
}, 1200));
},
async getRefundTimes(order_no){
try{
let _refundRes = await this.$store.dispatch('getOrderRefundList', order_no);
let _refundLs = _refundRes?.data?.data?.list || [];
this.refundList = _refundLs;
}catch(err){
console.warn('getRefundTimes err', err);
}
},
getOrderInfo({ order_no, stadium_id }){
util.showLoad();
server.get({
url: ORDER_API.timeOrderDetail,
data: { order_no, stadium_id },
failMsg: '加载失败!'
})
.then(res=>{
util.hideLoad()
this.orderInfo = res || {}
})
.catch(util.hideLoad)
},
zh_pay_type: util.order_pay_type_txt,
completeBtn(){
this.$emit('completeBtn');
},
timeEndBtn(){
let { orderInfo } = this;
this.getOrderInfo({
order_no: orderInfo?.order_no || '',
stadium_id: orderInfo?.stadium_id || ''
})
},
// -
completeBtn(){
let { orderInfo } = this
util.showModal({
title: '提示',
content: '是否确认完结订单?',
showCancel: true,
success: modalRes=>{
if(modalRes.confirm)this.timeOrderComplete({
brand_id: orderInfo?.brand_id || '',
order_no: orderInfo?.order_no || '',
stadium_id: orderInfo?.stadium_id || ''
})
}
})
},
//
timeOrderComplete({ brand_id, order_no, stadium_id }){
util.showLoad();
server.get({
url: ORDER_API.timeOrderComplete, //
data: { brand_id, order_no },
failMsg: '请求失败!'
})
.then(res=>{
util.hideLoad();
util.showNone('操作成功!');
setTimeout(_=>{
this.getOrderInfo({ order_no, stadium_id });
util.previousPageFunction({
fnName: 'refreshList',
query: { isLoad: false},
});
}, 1200)
})
.catch(util.hideLoad)
}
}
}
</script>
<style lang="scss" >
.timing-details{
margin-bottom: 24rpx;
.td-head{
margin: 24rpx 24rpx 0rpx;
padding: 30rpx;
background-color: #FFF;
border-radius: 10rpx 10rpx 0px 0px;
.th-store{
padding-bottom: 26rpx;
margin-bottom: 18rpx;
border-bottom: 2rpx solid #D8D8D8;
display: flex;
justify-content: flex-start;
>image{
flex-shrink: 0;
width: 40rpx;
height: 40rpx;
}
>view{
flex-grow: 1;
margin-left: 14rpx;
color: #333333;
font-size: 28rpx;
}
}
.th-line{
margin-top: 8rpx;
@include ctf(space-between);
>view{
line-height: 40rpx;
font-size: 28rpx;
&:first-child{
color: #9A9A9D;
>text{
color: #333333;
}
}
&:nth-child(2){
>text{
color: #9A9A9D;
}
.tl-active{
color: $mColor;
}
}
}
}
}
.td-box{
margin: 24rpx 24rpx 0rpx;
padding: 30rpx;
background-color: #FFF;
border-radius: 10rpx;
.tb-title{
color: #9A9A9D;
font-size: 28rpx;
margin-bottom: 20rpx;
}
.tb-line{
>view{
line-height: 52rpx;
font-size: 28rpx;
color: #9A9A9D;
>text{
color: #333333;
}
}
}
.tb-section{
margin-top: 30rpx;
border-top: 2rpx solid #D8D8D8;
.ts-line{
margin-top: 26rpx;
@include ctf(space-between);
>view{
color: #333333;
&:first-child{
font-size: 28rpx;
}
&:nth-child(2){
font-size: 24rpx;
margin-right: 8rpx;
}
}
}
.ts-total{
margin-top: 22rpx;
@include ctf(flex-end);
>view{
color: #333333;
font-size: 28rpx;
>text{
color: #FF873D;
&:first-child{
font-size: 28rpx;
}
&:nth-child(2){
font-size: 36rpx;
margin-right: 8rpx;
}
}
}
}
}
}
.td-btn{
height: 112rpx;
margin: 80rpx 24rpx 10upx;
border-radius: 10rpx;
background-color: $mColor;
color: #FFF;
font-size: 32rpx;
line-height: 112rpx;
text-align: center;
}
}
</style>

BIN
src/subpackage/order/static/images/filter.png

After

Width: 40  |  Height: 40  |  Size: 127 B

BIN
src/subpackage/order/static/images/order_manage/order_22.png

After

Width: 60  |  Height: 60  |  Size: 920 B

0
src/subpackage/order/static/images/order_manage/order_6.png → src/subpackage/order/static/images/order_manage/order_23.png

Before

Width: 120  |  Height: 120  |  Size: 1.2 KiB

After

Width: 120  |  Height: 120  |  Size: 1.2 KiB

BIN
src/subpackage/order/static/images/round_close.png

After

Width: 32  |  Height: 32  |  Size: 369 B

BIN
src/subpackage/order/static/images/search.png

After

Width: 40  |  Height: 40  |  Size: 386 B

20197
yarn.lock
File diff suppressed because it is too large
View File

Loading…
Cancel
Save