Compare commits
16 Commits
Author | SHA1 | Message | Date |
---|---|---|---|
|
494c2689e3 |
fix for md0726
|
3 months ago |
|
6a2118234e |
fix for md0726
|
3 months ago |
|
a06dced7ef |
clash for marge dev
|
3 months ago |
|
a15b3aeba7 |
change regist text
|
7 months ago |
|
f70a1f03de |
add shower order
|
9 months ago |
|
949e09327c |
add shower order style
|
9 months ago |
|
25271dc0ce |
Merge branch 'dev' of https://git.ouxuan.net/liujw/ox_zhiNengZhuShou into md0726
|
9 months ago |
|
cfea3f2f39 |
fix md0726
|
9 months ago |
|
d74b71ca86 |
fix md0726
|
9 months ago |
|
62155a8916 |
fix permissionObj serve key
|
9 months ago |
|
59a7a87534 |
fix md0726
|
9 months ago |
|
0b8ef0eaeb |
add api logic
|
9 months ago |
|
3bcf19c67d |
add md0726 logic
|
9 months ago |
|
451fb7c386 |
add md0726 api logic
|
9 months ago |
|
a63897e66e |
add md0726 shower style
|
10 months ago |
|
b236b4c45e |
add md0726 style
|
10 months ago |
-
92src/components/filter/filter_modal.vue
-
109src/components/filter/header.vue
-
139src/components/filter/period_modal.vue
-
107src/components/filter/stadium_select.vue
-
16src/components/kv_line.vue
-
0src/components/kvs_line.vue
-
4src/components/order_refund/fixed.vue
-
47src/pages.json
-
7src/pages/index/index.vue
-
BINsrc/static/images/icon/index/tab_13.png
-
3src/store/index.js
-
23src/subpackage/common/pages/pay_type_select.vue
-
39src/subpackage/device/pages/switch_manage/switch_manage.vue
-
5src/subpackage/order/pages/order_manage/order_manage.vue
-
5src/subpackage/order/pages/timekeeping/modules/order_list/deposit.vue
-
5src/subpackage/order/pages/timekeeping/modules/order_list/person.vue
-
5src/subpackage/order/pages/timekeeping/modules/order_list/site.vue
-
16src/subpackage/order/pages/timekeeping/order_detail/deposit.vue
-
12src/subpackage/order/pages/timekeeping/order_detail/person.vue
-
12src/subpackage/order/pages/timekeeping/order_detail/site.vue
-
8src/subpackage/order/pages/ym_card/detail/detail.vue
-
6src/subpackage/party/pages/login/regist.vue
-
103src/subpackage/shower/components/number_edit.vue
-
276src/subpackage/shower/components/popup/deduction.vue
-
146src/subpackage/shower/components/popup/device_deduction.vue
-
111src/subpackage/shower/components/popup/recharge.vue
-
72src/subpackage/shower/components/popup/template.vue
-
100src/subpackage/shower/components/time_range.vue
-
17src/subpackage/shower/js/api.js
-
10src/subpackage/shower/js/server.js
-
274src/subpackage/shower/pages/card/detail.vue
-
192src/subpackage/shower/pages/card/manage.vue
-
172src/subpackage/shower/pages/card/use_record.vue
-
203src/subpackage/shower/pages/device/use_detail.vue
-
263src/subpackage/shower/pages/device/use_record.vue
-
289src/subpackage/shower/pages/order/detail.vue
-
252src/subpackage/shower/pages/order/list.vue
-
BINsrc/subpackage/shower/static/images/arrow.png
-
BINsrc/subpackage/shower/static/images/calendar.png
-
BINsrc/subpackage/shower/static/images/close.png
-
BINsrc/subpackage/shower/static/images/locate.png
@ -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> |
@ -0,0 +1,109 @@ |
|||
<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 v-if="isCount">成功交易{{ successCount || 0 }}笔,退款{{ refundCount || 0 }}笔</text> |
|||
</view> |
|||
<view class="ob-btns"> |
|||
<image v-if="isSearch" @click="$emit('click:search')" class="ob-icon" src="/static/images/icon/search.png"></image> |
|||
<image @click="$emit('click:filter')" class="ob-icon" src="/static/images/icon/filter.png"></image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import stadiumSelect from './stadium_select.vue'; |
|||
export default { |
|||
components: { |
|||
'stadium-select': stadiumSelect, |
|||
}, |
|||
props: { |
|||
startTime: { |
|||
default: '' |
|||
}, |
|||
endTime: { |
|||
default: '' |
|||
}, |
|||
successCount: { |
|||
default: 0 |
|||
}, |
|||
refundCount: { |
|||
default: 0 |
|||
}, |
|||
isCount: Boolean, |
|||
isSearch: Boolean |
|||
}, |
|||
data(){ |
|||
return { |
|||
isStadium: false |
|||
} |
|||
}, |
|||
methods: { |
|||
initStadiumSelect({ brand_id, stadium_id }){ |
|||
this.isStadium = !!brand_id; |
|||
if(!brand_id) return; |
|||
return this.$refs.stadiumSelect.initStadiums({ brand_id, stadium_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> |
@ -0,0 +1,139 @@ |
|||
<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> |
@ -0,0 +1,107 @@ |
|||
<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/icon/arrow_b2.png"></image> |
|||
</view> |
|||
</picker> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { API } from '../../js/api'; |
|||
import { servers } 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); |
|||
}, |
|||
async initStadiums({ brand_id, stadium_id }){ |
|||
if(!brand_id) return; |
|||
let _ls = await this.getStadiumList(brand_id); |
|||
let _curStadium = _ls.find(e=>+e.id === +stadium_id); |
|||
if(_curStadium)this.curStadium = _curStadium; |
|||
}, |
|||
// 获取品牌店铺列表 |
|||
getStadiumList(brand_id){ |
|||
return servers.get({ |
|||
url: 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; |
|||
transform: rotateZ(90deg); |
|||
} |
|||
} |
|||
} |
|||
.ocs-store{ |
|||
|
|||
} |
|||
} |
|||
</style> |
Before Width: 52 | Height: 52 | Size: 1.2 KiB After Width: 138 | Height: 100 | Size: 573 B |
@ -0,0 +1,103 @@ |
|||
<template> |
|||
<view class="number-edit"> |
|||
<view class="rpu-number"> |
|||
<view class="rn-name"><text class="red">*</text>{{ label || '' }}</view> |
|||
<view class="rn-operate"> |
|||
<view class="rn-btn" @click="number--"></view> |
|||
<input type="number" class="rn-num" v-model="number"> |
|||
<view class="rn-btn" @click="number++"></view> |
|||
</view> |
|||
<view class="ne-unit">{{ unit || '' }}</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
label: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
unit: { |
|||
type: String, |
|||
default: '分钟' |
|||
}, |
|||
value: { |
|||
default: 0 |
|||
}, |
|||
}, |
|||
computed: { |
|||
number: { |
|||
get(){ |
|||
return this.$props.value; |
|||
}, |
|||
set(val){ |
|||
this.$emit('input', val); |
|||
} |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
|
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.number-edit{ |
|||
.rpu-number{ |
|||
@include ctf(space-between); |
|||
.rn-name{ |
|||
@include flcw(28upx, 40upx, #333333); |
|||
.red{ |
|||
color: #EA5061; |
|||
} |
|||
} |
|||
.rn-operate{ |
|||
margin-left: auto; |
|||
margin-right: 0; |
|||
padding: 2upx; |
|||
border-radius: 10upx; |
|||
background: #E8ECEF; |
|||
@include ctf; |
|||
.rn-btn{ |
|||
position: relative; |
|||
width: 56upx; |
|||
height: 54upx; |
|||
&::before, &::after{ |
|||
content: ''; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
display: block; |
|||
width: 30upx; |
|||
height: 4upx; |
|||
background: #9A9A9D; |
|||
border-radius: 2upx; |
|||
} |
|||
} |
|||
.rn-num{ |
|||
margin: 0 2upx; |
|||
text-align: center; |
|||
height: 54upx; |
|||
width: 104upx; |
|||
background: #fff; |
|||
@include flcw(28upx, 40upx, #333); |
|||
&+.rn-btn{ |
|||
&::after{ |
|||
transform: translate(-50%, -50%) rotate(90deg); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.ne-unit{ |
|||
min-width: 60upx; |
|||
margin-left: 28upx; |
|||
@include flcw(28upx, 40upx, #333333); |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,276 @@ |
|||
<template> |
|||
<view class="deduction-popup"> |
|||
<popup-template |
|||
title="扣减时长" |
|||
:show="isShow" |
|||
@click:close="hide" |
|||
> |
|||
<view class="rp-container"> |
|||
<kv-line label="水阀卡卡号:">{{ initData.water_card_no || '-' }}</kv-line> |
|||
<kv-line label="手机号码:">{{ initData.mobile || '-' }}</kv-line> |
|||
<kv-line label="可用时长:"><text class="rc-orange">{{ initData.valid_duration_text || '-' }}</text></kv-line> |
|||
<view class="rc-space"></view> |
|||
<number-edit label="扣减时长" v-model="editData.deductDuration"></number-edit> |
|||
<view class="rc-time-select"> |
|||
<view class="rts-name">开始日期</view> |
|||
<picker mode="date" :value="editData.sDate" @change="sDateChange"> |
|||
<input disabled type="text" v-model="editData.sDate" class="rts-ipt" placeholder="开始日期"> |
|||
</picker> |
|||
</view> |
|||
<view class="rc-time-select"> |
|||
<view class="rts-name">开始时间</view> |
|||
<picker mode="multiSelector" :range="timePickerList" :value="editData.sTime" @change="sTimeChange"> |
|||
<input disabled type="text" v-model="editData.sTime" class="rts-ipt" placeholder="开始时间"> |
|||
</picker> |
|||
</view> |
|||
<view class="rc-time-select"> |
|||
<view class="rts-name">结束日期</view> |
|||
<picker mode="date" :value="editData.eDate" @change="eDateChange"> |
|||
<input disabled type="text" v-model="editData.eDate" class="rts-ipt" placeholder="结束日期"> |
|||
</picker> |
|||
</view> |
|||
<view class="rc-time-select"> |
|||
<view class="rts-name">结束时间</view> |
|||
<picker mode="multiSelector" :range="timePickerList" :value="editData.eTime" @change="eTimeChange"> |
|||
<input disabled type="text" v-model="editData.eTime" class="rts-ipt" placeholder="结束时间"> |
|||
</picker> |
|||
</view> |
|||
<textarea class="rc-remark" placeholder="备注(选填)" v-model="editData.remark"></textarea> |
|||
<view class="rc-btn" @click="confirmBtn">确认</view> |
|||
</view> |
|||
</popup-template> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import popup_template from "./template.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import number_edit from "../number_edit.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { formatDate, formatNumber, formatTime, showNone, debounce, showLoad, hideLoad, showModal } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'popup-template': popup_template, |
|||
'kv-line': kv_line, |
|||
'number-edit': number_edit |
|||
}, |
|||
watch: { |
|||
'editData.deductDuration': { |
|||
handler(nVal, oVal){ |
|||
this.initDeductTime(); |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
isShow: false, |
|||
timePickerList: this.getTimePickerList(), |
|||
initData: { |
|||
/** |
|||
* @param {String} water_card_no |
|||
* @param {String} mobile |
|||
* @param {String} valid_duration_text |
|||
* @param {Number} valid_duration |
|||
* @param {Function} success |
|||
* */ |
|||
}, |
|||
editData: { |
|||
deductDuration: 10, |
|||
sDate: '', |
|||
eDate: '', |
|||
sTime: '', |
|||
eTime: '', |
|||
remark: '' |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
confirmBtn: debounce(function(){ |
|||
let { deductDuration, sDate, sTime, eDate, eTime, remark } = this.editData; |
|||
let { initData } = this; |
|||
let _queryObj = { |
|||
duration: deductDuration, |
|||
start_time: `${sDate} ${sTime}`, |
|||
end_time: `${eDate} ${eTime}`, |
|||
remark, |
|||
water_card_no: initData?.water_card_no || '', |
|||
brand_id: initData?.brand_id || '', |
|||
stadium_id: initData?.stadium_id || '', |
|||
resource_type: 2 // 0:后台,2:商家助手 |
|||
} |
|||
// console.log('扣减时长提交参数:', _queryObj); |
|||
// initData?.success?.(); |
|||
this.deductionReq(_queryObj); |
|||
this.hide(); |
|||
}, 300, true), |
|||
deductionReq(data){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: SHOWER_API.CardFeeDeduction, |
|||
data, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showModal({ |
|||
title: '提示', |
|||
content: _data.message || '操作成功!' |
|||
}) |
|||
this.initData?.success?.('SUCCESS'); |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '操作失败!' |
|||
}) |
|||
console.warn('deduction deductionReq err --->', err); |
|||
}) |
|||
}, |
|||
sDateChange(e){ |
|||
if(!this.isCorrectTimeScope({ sDate: e.detail.value }))return; |
|||
this.editData.sDate = e.detail.value; |
|||
this.getDeductDurationForTimeChange(); |
|||
}, |
|||
sTimeChange(e){ |
|||
let { timePickerList, editData } = this; |
|||
let _timeStr = this.getPickerTimeStr(e.detail.value, timePickerList); |
|||
if(!this.isCorrectTimeScope({ sTime: _timeStr }))return; |
|||
this.editData.sTime = _timeStr; |
|||
this.getDeductDurationForTimeChange(); |
|||
}, |
|||
eDateChange(e){ |
|||
if(!this.isCorrectTimeScope({ eDate: e.detail.value }))return; |
|||
this.editData.eDate = e.detail.value; |
|||
this.getDeductDurationForTimeChange(); |
|||
}, |
|||
eTimeChange(e){ |
|||
let { timePickerList } = this; |
|||
let _timeStr = this.getPickerTimeStr(e.detail.value, timePickerList); |
|||
if(!this.isCorrectTimeScope({ eTime: _timeStr }))return; |
|||
this.editData.eTime = _timeStr; |
|||
this.getDeductDurationForTimeChange(); |
|||
}, |
|||
getDeductDurationForTimeChange(){ |
|||
let { sDate, sTime, eDate, eTime } = this.editData; |
|||
let _startStr = `${sDate} ${sTime}`; |
|||
let _endStr = `${eDate} ${eTime}`; |
|||
let _startStamp = new Date(this.getCalDate(_startStr)).getTime(); |
|||
let _endStamp = new Date(this.getCalDate(_endStr)).getTime(); |
|||
this.editData.deductDuration = (_endStamp - _startStamp) / 1000 / 60; |
|||
}, |
|||
isCorrectTimeScope({ |
|||
sDate = '', sTime = '', eDate = '', eTime = '' |
|||
}){ |
|||
let _sDate = sDate || this.editData.sDate; |
|||
let _sTime = sTime || this.editData.sTime; |
|||
let _eDate = eDate || this.editData.eDate; |
|||
let _eTime = eTime || this.editData.eTime; |
|||
let _startStr = `${_sDate} ${_sTime}`; |
|||
let _endStr = `${_eDate} ${_eTime}`; |
|||
let _startStamp = new Date(this.getCalDate(_startStr)).getTime(); |
|||
let _endStamp = new Date(this.getCalDate(_endStr)).getTime(); |
|||
if(_startStamp >= _endStamp){ |
|||
showNone('开始时间不能大于结束时间!'); |
|||
return false; |
|||
}else{ |
|||
return true; |
|||
} |
|||
}, |
|||
getPickerTimeStr(value = [], pickList = []){ |
|||
let [ _hourList, _minuteList, _secondList ] = pickList; |
|||
let [ _hour, _minute, _second ] = value; |
|||
return `${_hourList[_hour]}:${_minuteList[_minute]}:${_secondList[_second]}`; |
|||
}, |
|||
getCalDate(dateStr){ |
|||
return dateStr.replace(/\-/g, '/') || ''; |
|||
}, |
|||
initDeductTime(){ |
|||
let { deductDuration, sDate, sTime } = this.editData; |
|||
let _startStr = `${this.getCalDate(sDate)} ${sTime}`; |
|||
let _curDate = _startStr === ' ' ? new Date() : new Date(_startStr); |
|||
let _curTimeStamp = _curDate.getTime(); |
|||
let _deductLaterTimeStamp = _curTimeStamp + deductDuration * 60 * 1000; |
|||
let _startArr = formatTime(new Date(_curTimeStamp)).split(' '); |
|||
let _endStr = formatTime(new Date(_deductLaterTimeStamp)).split(' '); |
|||
this.editData.sDate = _startArr[0]; |
|||
this.editData.sTime = _startArr[1]; |
|||
this.editData.eDate = _endStr[0]; |
|||
this.editData.eTime = _endStr[1]; |
|||
}, |
|||
getTimePickerList(){ |
|||
let _hourList = new Array(24).fill(0).map((e, i) => formatNumber(i)); |
|||
let _minuteList = new Array(60).fill(0).map((e, i) => formatNumber(i)); |
|||
let _secondList = new Array(60).fill(0).map((e, i) => formatNumber(i)); |
|||
return [_hourList, _minuteList, _secondList]; |
|||
}, |
|||
init(data){ |
|||
this.initData = data || {}; |
|||
this.show(); |
|||
this.initDeductTime(); |
|||
}, |
|||
show(){ |
|||
this.isShow = true; |
|||
}, |
|||
hide(){ |
|||
this.isShow = false; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.rp-container{ |
|||
padding: 0 60upx; |
|||
.rc-space{ |
|||
padding-top: 40upx; |
|||
} |
|||
.rc-orange{ |
|||
color: #FF873D; |
|||
} |
|||
.rc-time-select{ |
|||
margin-top: 40upx; |
|||
@include ctf(space-between); |
|||
.rts-name{ |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
} |
|||
.rts-ipt{ |
|||
display: block; |
|||
box-sizing: border-box; |
|||
padding: 0upx 30upx; |
|||
width: 358upx; |
|||
height: 56upx; |
|||
border-radius: 10upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
} |
|||
.rc-remark{ |
|||
width: auto; |
|||
margin-top: 40upx; |
|||
padding: 20upx 24upx; |
|||
height: 144upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
.rc-btn{ |
|||
margin: 64upx auto 0upx; |
|||
width: 240upx; |
|||
height: 88upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(28upx, 88upx, #fff); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,146 @@ |
|||
<template> |
|||
<view class="recharge-popup"> |
|||
<popup-template |
|||
title="结束计时" |
|||
:show="isShow" |
|||
@click:close="hide" |
|||
> |
|||
<view class="rp-container"> |
|||
<kv-line label="时长合计:">{{ initData.settle_duration || '-' }}</kv-line> |
|||
<view class="rc-space"></view> |
|||
<number-edit label="扣减时长" unit="分钟" v-model="editData.minute"></number-edit> |
|||
<view class="rc-btn" @click="confirm">确认</view> |
|||
</view> |
|||
</popup-template> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import popup_template from "./template.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import number_edit from "../number_edit.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { formatDate, formatNumber, formatTime, showNone, debounce, showLoad, hideLoad, showModal } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'popup-template': popup_template, |
|||
'kv-line': kv_line, |
|||
'number-edit': number_edit |
|||
}, |
|||
data(){ |
|||
return { |
|||
isShow: false, |
|||
initData: {}, |
|||
editData: { |
|||
minute: 10 |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
confirm: debounce(function(){ |
|||
let { initData, editData } = this; |
|||
// initData?.success?.({ |
|||
// deductionMinute: +editData?.minute |
|||
// }); |
|||
let _query = { |
|||
duration: +editData?.minute, |
|||
id: initData?.id, |
|||
stadium_id: initData?.stadium_id, |
|||
brand_id: initData?.brand_id, |
|||
} |
|||
this.deductionReq(_query); |
|||
this.hide(); |
|||
}, 300, true), |
|||
init(data){ |
|||
this.initData = data; |
|||
this.editData.minute = data?.settle_duration || 10; |
|||
this.show(); |
|||
}, |
|||
show(){ |
|||
this.isShow = true; |
|||
}, |
|||
hide(){ |
|||
this.isShow = false; |
|||
}, |
|||
deductionReq(data){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: SHOWER_API.endOfUseWaterWave, |
|||
data, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showModal({ |
|||
title: '提示', |
|||
content: _data.message || '操作成功!' |
|||
}) |
|||
this.initData?.success?.('SUCCESS'); |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '操作失败!' |
|||
}) |
|||
console.warn('deduction deductionReq err --->', err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.rp-container{ |
|||
padding: 0 60upx; |
|||
.rc-space{ |
|||
padding-top: 40upx; |
|||
} |
|||
.rc-orange{ |
|||
color: #FF873D; |
|||
} |
|||
.rc-time-select{ |
|||
margin-top: 40upx; |
|||
@include ctf(space-between); |
|||
.rts-name{ |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
} |
|||
.rts-ipt{ |
|||
display: block; |
|||
box-sizing: border-box; |
|||
padding: 10upx 30upx; |
|||
width: 358upx; |
|||
height: 56upx; |
|||
border-radius: 10upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
} |
|||
.rc-remark{ |
|||
width: auto; |
|||
margin-top: 40upx; |
|||
padding: 20upx 24upx; |
|||
height: 144upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
.rc-btn{ |
|||
margin: 64upx auto 0upx; |
|||
width: 240upx; |
|||
height: 88upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(28upx, 88upx, #fff); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,111 @@ |
|||
<template> |
|||
<view class="recharge-popup"> |
|||
<popup-template |
|||
title="充值时长" |
|||
:show="isShow" |
|||
@click:close="hide" |
|||
> |
|||
<view class="rp-container"> |
|||
<kv-line label="水阀卡卡号:">{{ initData.water_card_no || '-' }}</kv-line> |
|||
<kv-line label="手机号码:">{{ initData.mobile || '-' }}</kv-line> |
|||
<kv-line label="可用时长:"><text class="rc-orange">{{ initData.valid_duration_text || '-' }}</text></kv-line> |
|||
<view class="rc-space"></view> |
|||
<number-edit label="充值时长" v-model="editData.duration"></number-edit> |
|||
<view class="rc-space"></view> |
|||
<number-edit label="支付金额" unit="元" v-model="editData.amount"></number-edit> |
|||
<view class="rc-btn" @click="confirm">确认</view> |
|||
</view> |
|||
</popup-template> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import popup_template from "./template.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import number_edit from "../number_edit.vue"; |
|||
import { debounce } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'popup-template': popup_template, |
|||
'kv-line': kv_line, |
|||
'number-edit': number_edit |
|||
}, |
|||
data(){ |
|||
return { |
|||
isShow: false, |
|||
initData: {}, |
|||
editData: { |
|||
duration: 10, |
|||
amount: 1 |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
confirm: debounce(function(){ |
|||
let { initData, editData } = this; |
|||
initData?.success?.({ |
|||
pay_amount: +editData?.amount, |
|||
duration: +editData?.duration |
|||
}); |
|||
this.hide(); |
|||
}, 300, true), |
|||
init(data){ |
|||
this.initData = data; |
|||
this.show(); |
|||
}, |
|||
show(){ |
|||
this.isShow = true; |
|||
}, |
|||
hide(){ |
|||
this.isShow = false; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.rp-container{ |
|||
padding: 0 60upx; |
|||
.rc-space{ |
|||
padding-top: 40upx; |
|||
} |
|||
.rc-orange{ |
|||
color: #FF873D; |
|||
} |
|||
.rc-time-select{ |
|||
margin-top: 40upx; |
|||
@include ctf(space-between); |
|||
.rts-name{ |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
} |
|||
.rts-ipt{ |
|||
display: block; |
|||
box-sizing: border-box; |
|||
padding: 10upx 30upx; |
|||
width: 358upx; |
|||
height: 56upx; |
|||
border-radius: 10upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
} |
|||
.rc-remark{ |
|||
width: auto; |
|||
margin-top: 40upx; |
|||
padding: 20upx 24upx; |
|||
height: 144upx; |
|||
background: #F2F2F7; |
|||
@include flcw(24upx, 34upx, #333333); |
|||
} |
|||
.rc-btn{ |
|||
margin: 64upx auto 0upx; |
|||
width: 240upx; |
|||
height: 88upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(28upx, 88upx, #fff); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,72 @@ |
|||
<template> |
|||
<view class="popup-template" v-show="show"> |
|||
<view class="pt-mask"> |
|||
<view class="pm-container"> |
|||
<image |
|||
class="pc-close" |
|||
mode="aspectFit" |
|||
src="/subpackage/shower/static/images/close.png" |
|||
@click="$emit('click:close')" |
|||
></image> |
|||
<view class="pc-title">{{ title }}</view> |
|||
<view class="pc-content"> |
|||
<slot></slot> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
show: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.pt-mask{ |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
background: rgba(0, 0, 0, 0.5); |
|||
z-index: 99; |
|||
.pm-container{ |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%, -50%); |
|||
padding-top: 44upx; |
|||
padding-bottom: 48upx; |
|||
width: 640upx; |
|||
background: #fff; |
|||
border-radius: 10upx; |
|||
.pc-close{ |
|||
position: absolute; |
|||
top: 24upx; |
|||
right: 24upx; |
|||
width: 34upx; |
|||
height: 34upx; |
|||
} |
|||
.pc-title{ |
|||
padding: 0 30upx; |
|||
text-align: center; |
|||
@include flcw(32upx, 44upx, #333, 500); |
|||
@include tHide; |
|||
} |
|||
.pc-content{ |
|||
padding-top: 24upx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<view class="time-range"> |
|||
<view class="tr-name">日期</view> |
|||
<view class="tr-right"> |
|||
<picker mode="date" @change="startDateChange"> |
|||
<view class="tr-frame"> |
|||
<input type="text" disabled class="tf-ipt" :value="sDate" placeholder="请选择时间"> |
|||
<image class="tf-icon" mode="aspectFit" src="/subpackage/shower/static/images/calendar.png"></image> |
|||
</view> |
|||
</picker> |
|||
<view class="tr-txt">至</view> |
|||
<picker mode="date" @change="endDateChange"> |
|||
<view class="tr-frame"> |
|||
<input type="text" disabled class="tf-ipt" :value="eDate" placeholder="请选择时间"> |
|||
<image class="tf-icon" mode="aspectFit" src="/subpackage/shower/static/images/calendar.png"></image> |
|||
</view> |
|||
</picker> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { showNone } from "@/utils/util"; |
|||
export default { |
|||
data(){ |
|||
return { |
|||
sDate: '', |
|||
eDate: '' |
|||
} |
|||
}, |
|||
methods: { |
|||
init(data){ |
|||
this.sDate = data?.start_time || ''; |
|||
this.eDate = data?.end_time || ''; |
|||
}, |
|||
endDateChange(e){ |
|||
let { sDate, getDateStrTimeStamp } = this; |
|||
let _val = e.detail.value || ''; |
|||
if(getDateStrTimeStamp(_val) < getDateStrTimeStamp(sDate)){ |
|||
return showNone('结束时间不能小于开始时间'); |
|||
} |
|||
this.eDate = e.detail.value; |
|||
this.$emit('change:date', { start_time: this.sDate, end_time: this.eDate }); |
|||
}, |
|||
startDateChange(e){ |
|||
let { eDate, getDateStrTimeStamp } = this; |
|||
let _val = e.detail.value || ''; |
|||
if(getDateStrTimeStamp(_val) > getDateStrTimeStamp(eDate)){ |
|||
return showNone('开始时间不能大于结束时间'); |
|||
} |
|||
this.sDate = e.detail.value; |
|||
this.$emit('change:date', { start_time: this.sDate, end_time: this.eDate }); |
|||
}, |
|||
getDateStrTimeStamp(dateStr){ |
|||
let _str = dateStr.replace(/-/g, '/'); |
|||
return new Date(`${_str} 00:00:00`).getTime(); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.time-range{ |
|||
padding: 20upx 24upx; |
|||
background: #fff; |
|||
@include ctf(space-between); |
|||
.tr-name{ |
|||
flex-shrink: 0; |
|||
@include flcw(32upx, 44upx, #1A1A1A, 500); |
|||
} |
|||
.tr-right{ |
|||
@include ctf(flex-end); |
|||
.tr-frame{ |
|||
flex-shrink: 0; |
|||
padding: 0 18upx; |
|||
width: 230upx; |
|||
height: 62upx; |
|||
border: 2upx solid #979797; |
|||
border-radius: 4upx; |
|||
@include ctf(space-between); |
|||
.tf-ipt{ |
|||
flex-grow: 1; |
|||
@include flcw(24upx, 34upx, #1A1A1A, 500); |
|||
} |
|||
.tf-icon{ |
|||
margin-left: 10upx; |
|||
flex-shrink: 0; |
|||
display: block; |
|||
width: 32upx; |
|||
height: 32upx; |
|||
} |
|||
} |
|||
.tr-txt{ |
|||
margin: 0 28upx; |
|||
flex-shrink: 0; |
|||
@include flcw(32upx, 44upx, #1A1A1A, 500); |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,17 @@ |
|||
import { ORIGIN } from '../../../js/api'; |
|||
|
|||
export const SHOWER_API = { |
|||
CardList:`${ORIGIN}/admin/stadiumWaterCard/list`, // 后台-水卡-列表
|
|||
CardDetails:`${ORIGIN}/admin/stadiumWaterCard/details`, // 后台-水卡-详情
|
|||
CardUseRecord:`${ORIGIN}/admin/stadiumWaterCardUseRecord/listOfCardByAssistant`, // 后台-水卡使用记录-(某张水卡的)列表
|
|||
CardRecharge:`${ORIGIN}/admin/stadiumWaterCard/recharge`, // 后台-水卡-充值
|
|||
CardFeeDeduction:`${ORIGIN}/admin/stadiumWaterCard/feeDeduction`, // 后台-水卡-扣费
|
|||
waterOrderList:`${ORIGIN}/admin/stadiumWaterCardUseRecord/list`, // 后台-水阀订单-列表
|
|||
waterOrderDetails:`${ORIGIN}/admin/stadiumWaterCardUseRecord/details`, // 后台-水阀订单-详情
|
|||
endOfUseWaterWave:`${ORIGIN}/admin/stadiumWaterCardUseRecord/endOfUseWaterWave`, // 后台-水卡使用记录-详情
|
|||
cardOrderList:`${ORIGIN}/admin/stadiumWaterCardOrder/list`, // 后台-水阀订单-列表
|
|||
cardOrderDetails:`${ORIGIN}/admin/stadiumWaterCardOrder/details`, // 后台-水阀订单-详情
|
|||
orderRefund:`${ORIGIN}/admin/stadium/order/refund`, // A订单管理-场馆预订订单-订单退款
|
|||
} |
|||
|
|||
export default SHOWER_API; |
@ -0,0 +1,10 @@ |
|||
import { Server } from '../../../js/server'; |
|||
|
|||
class DeviceServer extends Server { |
|||
constructor(props){ |
|||
super(props) |
|||
} |
|||
} |
|||
|
|||
|
|||
export default new DeviceServer(); |
@ -0,0 +1,274 @@ |
|||
<template> |
|||
<view class="card-detail"> |
|||
<view class="cd-box cb-card"> |
|||
<view class="cc-stadium"> |
|||
<view class="cs-txt">{{ water_card.stadium_name || '' }}</view> |
|||
</view> |
|||
<view class="cc-lines"> |
|||
<kv-line label-style="color: #1A1A1A;" label="水阀卡卡号:">{{ water_card.water_card_no || '' }}</kv-line> |
|||
<kv-line label-style="color: #1A1A1A;" label="手机号码:">{{ water_card.mobile || '' }}</kv-line> |
|||
<kv-line label-style="color: #1A1A1A;" label="微信昵称:">{{ water_card.nick_name || '' }}</kv-line> |
|||
<kv-line label-style="color: #1A1A1A;font-weitht: 500;" label="可用时长:"><text class="cl-orange">{{ water_card.valid_duration_text || '' }}</text></kv-line> |
|||
</view> |
|||
<view class="cc-btns"> |
|||
<view class="cb-item" @click="toRecords">消费记录</view> |
|||
<view class="cb-item red" @click="deductionBtn">扣费</view> |
|||
<view class="cb-item orange" @click="rechargeBtn">充值</view> |
|||
</view> |
|||
</view> |
|||
<view class="cd-box cd-record"> |
|||
<view class="cr-tit">购卡记录</view> |
|||
<view class="cr-time">购卡 {{ water_card_order.pay_time || '-' }}</view> |
|||
<view class="cr-lines"> |
|||
<kv-line label="名称:">{{ water_card.water_card_name || '-' }}</kv-line> |
|||
<kv-line label="时长:">{{ water_card_order.duration_text || '-' }}</kv-line> |
|||
<kv-line label="售价:">¥{{ water_card_order.amount || '0' }}</kv-line> |
|||
<kv-line label="支付金额:">¥{{ water_card_order.pay_amount || '0' }}</kv-line> |
|||
<kv-line label="途径:">{{ water_card.resource_text || '-' }}</kv-line> |
|||
</view> |
|||
</view> |
|||
|
|||
<recharge-popup ref="rechangePopup"></recharge-popup> |
|||
<deduction-popup ref="deductionPopup"></deduction-popup> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import rechargePopup from "../../components/popup/recharge.vue"; |
|||
import deductionPopup from "../../components/popup/deduction.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate, jsonStr, showModal } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'kv-line': kv_line, |
|||
'recharge-popup': rechargePopup, |
|||
'deduction-popup': deductionPopup |
|||
}, |
|||
computed: { |
|||
water_card(){ |
|||
let { cardInfo } = this; |
|||
return cardInfo?.water_card || {}; |
|||
}, |
|||
water_card_order(){ |
|||
let { cardInfo } = this; |
|||
return cardInfo?.water_card_order || {}; |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
cardInfo: {} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
let { id, brand_id } = options; |
|||
this.getCardInfo({ id, brand_id }); |
|||
}, |
|||
methods: { |
|||
rechargeBtn(){ |
|||
let { water_card } = this; |
|||
this.$refs.rechangePopup.init({ |
|||
water_card_no: water_card?.water_card_no || '', |
|||
mobile: water_card?.mobile || '', |
|||
valid_duration_text: water_card?.valid_duration_text || '', |
|||
success: rData => { |
|||
let _query = { |
|||
type: 5, |
|||
brand_id: water_card?.brand_id || '', |
|||
amount: rData?.pay_amount || 0, |
|||
stadiumInfo: { |
|||
id: water_card?.stadium_id || '', |
|||
name: water_card?.stadium_name || '', |
|||
logo: water_card?.stadium_logo || '', |
|||
}, |
|||
}; |
|||
uni.navigateTo({ |
|||
url: `/subpackage/common/pages/pay_type_select?query=${jsonStr(_query)}`, |
|||
events: { payConfirm: pData => this.rechargePayConfirm({ rData, pData }) }, |
|||
}) |
|||
} |
|||
}); |
|||
}, |
|||
async rechargePayConfirm({ rData, pData }){ |
|||
let { water_card } = this; |
|||
let _reqData = { |
|||
brand_id: water_card?.brand_id || '', |
|||
stadium_id: water_card?.stadium_id || '', |
|||
water_card_no: water_card?.water_card_no || '', |
|||
duration: rData?.duration || 0, |
|||
mobile: water_card?.mobile || '', |
|||
pay_type: this.getTextForType(pData?.payTypeName || ''), |
|||
pay_amount: pData?.amount || 0, |
|||
// 后端:都要传,,,(我也不知道什么原因 |
|||
card_no: pData?.selectedCardNo || '', |
|||
order_no: pData?.selectedCardNo || '' |
|||
} |
|||
let _rechargeRes = await this.rechargePayReq(_reqData); |
|||
if(_rechargeRes === 'SUCCESS'){ |
|||
setTimeout(_=>{ |
|||
this.getCardInfo({ id: water_card?.id, brand_id: water_card?.brand_id }); |
|||
}, 1200) |
|||
} |
|||
}, |
|||
rechargePayReq(data){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: SHOWER_API.CardRecharge, |
|||
data, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showModal({ |
|||
title: '提示', |
|||
content: _data.message || '操作成功!' |
|||
}) |
|||
return "SUCCESS"; |
|||
// this.initData?.success?.('SUCCESS'); |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '操作失败!' |
|||
}) |
|||
console.warn('deduction deductionReq err --->', err); |
|||
}) |
|||
}, |
|||
|
|||
// // 0: 微信支付 1: 支付宝支付 2: 储值卡支付 3:商家主动 4:押金抵扣 5:任务奖品 6:抖音团购兑换 7:付款码支付 |
|||
getTextForType(payTxt){ |
|||
switch(payTxt){ |
|||
case '微信支付': return 0; |
|||
case '支付宝支付': return 1; |
|||
case '储值卡支付': return 2; |
|||
case '商家主动': return 3; |
|||
case '押金抵扣': return 4; |
|||
case '任务奖品': return 5; |
|||
case '抖音团购兑换': return 6; |
|||
case '付款码支付': return 7; |
|||
default: return 8; |
|||
} |
|||
}, |
|||
deductionBtn(){ |
|||
let { water_card } = this; |
|||
this.$refs.deductionPopup.init({ |
|||
water_card_no: water_card?.water_card_no || '', |
|||
mobile: water_card?.mobile || '', |
|||
valid_duration_text: water_card?.valid_duration_text || '', |
|||
valid_duration: water_card?.valid_duration || '', |
|||
// 扣减提交参数 |
|||
brand_id: water_card?.brand_id || '', |
|||
stadium_id: water_card?.stadium_id || '', |
|||
|
|||
success: () => { |
|||
this.getCardInfo({ id: water_card?.id, brand_id: water_card?.brand_id }); |
|||
} |
|||
}); |
|||
}, |
|||
toRecords(){ |
|||
let { water_card } = this; |
|||
let _qryStr = `brand_id=${water_card?.brand_id || ''}&water_card_no=${water_card?.water_card_no || ''}`; |
|||
routeTo(`/subpackage/shower/pages/card/use_record?${_qryStr}`, 'nT'); |
|||
}, |
|||
getCardInfo({ |
|||
id = '', brand_id = '' |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.CardDetails, |
|||
data: { brand_id, id }, |
|||
failMsg: '获取用水卡信息失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
this.cardInfo = res || {}; |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('card detail getCardInfo err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.card-detail{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
.cd-box{ |
|||
position: relative; |
|||
padding: 30upx; |
|||
background: #fff; |
|||
border-radius: 10upx; |
|||
&+.cd-box{ |
|||
margin-top: 24upx; |
|||
} |
|||
} |
|||
.cb-card{ |
|||
.cc-stadium{ |
|||
.cs-txt{ |
|||
@include flcw(28upx, 40upx, #333333, 500); |
|||
@include tHide; |
|||
} |
|||
&::after{ |
|||
content: ''; |
|||
display: block; |
|||
margin-top: 26upx; |
|||
height: 1px; |
|||
background: #D8D8D8; |
|||
} |
|||
} |
|||
.cc-lines{ |
|||
padding-top: 20upx; |
|||
.cl-orange{ |
|||
color: #FF873D; |
|||
font-weight: 500; |
|||
} |
|||
} |
|||
.cc-btns{ |
|||
margin-top: 30upx; |
|||
@include ctf; |
|||
.cb-item{ |
|||
width: 176upx; |
|||
text-align: center; |
|||
border: 2upx solid #9A9A9D; |
|||
border-radius: 10upx; |
|||
@include flcw(32upx, 76upx, #9a9a9d, 500); |
|||
&.red{ |
|||
color: #EA5061; |
|||
border-color: #EA5061; |
|||
} |
|||
&.orange{ |
|||
color: #FF873D; |
|||
border-color: #FF873D; |
|||
} |
|||
&+.cb-item{ |
|||
margin-left: 58upx; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.cd-record{ |
|||
.cr-tit{ |
|||
@include flcw(28upx, 40upx, #9C9C9F); |
|||
} |
|||
.cr-time{ |
|||
margin-top: 20upx; |
|||
@include flcw(28upx, 52upx, #1A1A1A, 500); |
|||
} |
|||
} |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,192 @@ |
|||
<template> |
|||
<view class="card-manage"> |
|||
<order-filter |
|||
ref="orderFilter" |
|||
@change:stadium="condition.stadium_id = $event.id" |
|||
@click:time="showPeriodModal" |
|||
@click:filter="showFilterModal" |
|||
:start-time="condition.start_time" |
|||
:end-time="condition.end_time" |
|||
></order-filter> |
|||
<view class="cm-list"> |
|||
<view class="cl-item" v-for="(e, i) in cardOrderList" :key="i" @click="toDetail(e)"> |
|||
<view class="ci-bar"> |
|||
<view class="cb-name">{{ e.stadium_name || '-' }}</view> |
|||
<view class="cb-status">{{ e.status_text || '' }}</view> |
|||
</view> |
|||
<view class="ci-lines"> |
|||
<kv-line label="卡名称:">{{ e.water_card_no || '-' }}</kv-line> |
|||
<kv-line label="水阀卡号:">{{ e.water_card_name || '-' }}</kv-line> |
|||
<kv-line label="手机号码:">{{ e.mobile || '-' }}</kv-line> |
|||
<kv-line label="微信昵称:">{{ e.nick_name || '-' }}</kv-line> |
|||
<kv-line label="可用时长:"><text class="cl-txt">{{ e.valid_duration_text || '-' }}</text></kv-line> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 时间段选择 --> |
|||
<period-modal ref="periodModal"></period-modal> |
|||
<!-- status窗口 --> |
|||
<filter-modal ref="filterModal"></filter-modal> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import orderFilter from "@/components/filter/header.vue"; |
|||
import periodModal from "@/components/filter/period_modal.vue"; |
|||
import filterModal from "@/components/filter/filter_modal.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'order-filter': orderFilter, |
|||
'period-modal': periodModal, |
|||
'filter-modal': filterModal, |
|||
'kv-line': kv_line |
|||
}, |
|||
watch: { |
|||
condition: { |
|||
handler(nVal, oVal){ |
|||
this.cardOrderList = []; |
|||
this.page = 1; |
|||
let { brand_id } = this; |
|||
this.getCardList({ |
|||
brand_id: brand_id || '', |
|||
...nVal, |
|||
}) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
brand_id: '', |
|||
condition: { |
|||
stadium_id: '', // 场馆id |
|||
start_time: '', |
|||
end_time: '', |
|||
status: '', // 0: 未激活 1: 已激活 |
|||
}, |
|||
cardOrderList: [], |
|||
page: 1 |
|||
} |
|||
}, |
|||
onReachBottom(){ |
|||
let { brand_id, condition, page } = this; |
|||
this.getCardList({ brand_id, page: ++page, ...condition }); |
|||
}, |
|||
onLoad(options){ |
|||
let _bid = options?.brand_id || ''; |
|||
this.brand_id = _bid; |
|||
this.$refs.orderFilter.initStadiumSelect({ brand_id: _bid }); |
|||
// this.getCardList({ brand_id: _bid }); |
|||
this.initDate(); // watch 监听触发 |
|||
}, |
|||
methods: { |
|||
toDetail(e){ |
|||
routeTo(`/subpackage/shower/pages/card/detail?id=${e?.id || ''}&brand_id=${e?.brand_id || ''}`, 'nT') |
|||
}, |
|||
// 默认显示三个月内的水阀卡数据 |
|||
initDate(){ |
|||
let _Date = new Date(); |
|||
let _timeStamp = _Date.getTime(); |
|||
let _start = _timeStamp - 90 * 24 * 60 * 60 * 1000; |
|||
this.condition.start_time = formatDate({ date: _start }); |
|||
this.condition.end_time = formatDate({ date: _timeStamp }); |
|||
}, |
|||
showPeriodModal(){ |
|||
let { start_time, end_time } = this.condition; |
|||
this.$refs.periodModal.init({ |
|||
start: start_time, |
|||
end: end_time, |
|||
success: res=>{ |
|||
this.condition.start_time = res.start; |
|||
this.condition.end_time = res.end; |
|||
} |
|||
}); |
|||
}, |
|||
showFilterModal(){ |
|||
this.$refs.filterModal.init({ |
|||
title: '订单状态', |
|||
list: [ |
|||
{ label: '全部', value: '' }, |
|||
{ label: '使用中', value: '1' }, |
|||
{ label: '待激活', value: '0' }, |
|||
], |
|||
curValue: this.condition.status, |
|||
success: res=>{ |
|||
this.condition.status = res.value; |
|||
} |
|||
}); |
|||
}, |
|||
/** |
|||
* @param {String} number 卡号或者手机号 |
|||
* */ |
|||
getCardList({ |
|||
brand_id = '', stadium_id = '', |
|||
start_time = '', end_time = '', number = '', status = '', |
|||
page = 1, page_size = 10 |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.CardList, |
|||
data: { brand_id, stadium_id, start_time, end_time, number, status, page, page_size }, |
|||
failMsg: '获取用水卡列表失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _ls = res?.list || []; |
|||
if(page === 1)return this.cardOrderList = _ls; |
|||
if(!_ls.length)return showNone('没有更多!'); |
|||
this.page = page; |
|||
return this.cardOrderList = [...this.cardOrderList, ..._ls]; |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('manage getCardList err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.cm-list{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
.cl-item{ |
|||
padding: 0upx 20upx 30upx; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
.ci-bar{ |
|||
padding: 30upx 0upx; |
|||
border-bottom: 1upx solid #D8D8D8; |
|||
@include ctf(space-between); |
|||
.cb-name{ |
|||
@include flcw(28upx, 40upx, #1A1A1A, 500); |
|||
@include tHide; |
|||
} |
|||
.cb-status{ |
|||
flex-shrink: 0; |
|||
max-width: 30%; |
|||
@include tHide; |
|||
@include flcw(28upx, 40upx, $mColor); |
|||
} |
|||
} |
|||
.ci-lines{ |
|||
padding-top: 20upx; |
|||
.cl-txt{ |
|||
color: #FF873D; |
|||
} |
|||
} |
|||
&+.cl-item{ |
|||
margin-top: 24upx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,172 @@ |
|||
<template> |
|||
<view class="use-record"> |
|||
<time-range ref="timeRange" @change:date="condition = $event"></time-range> |
|||
<view class="ur-list"> |
|||
<view class="ul-item" v-for="(e, i) in recordList" :key="i"> |
|||
<view class="ui-tit-bar"> |
|||
<view class="utb-tit" v-if="e.type === 0">消费时长</view> |
|||
<view class="utb-tit" v-if="e.type === 1">充值时长</view> |
|||
<view class="utb-right"> |
|||
<view class="ur-time" v-if="e.status === 0">正在计时</view> |
|||
<block v-if="(e.type === 0&&e.status === 1) || e.type === 1"> |
|||
<view class="ur-time" v-if="e.type === 0">-{{ e.deduction_duration || '-' }}</view> |
|||
<view class="ur-time orange" v-if="e.type === 1">+{{ e.recharge_duration || '-' }}分钟</view> |
|||
<view class="ur-surplus">剩余:{{ e.total_duration_text || '-' }}</view> |
|||
</block> |
|||
</view> |
|||
</view> |
|||
<view class="ui-lines"> |
|||
<kv-line label="门店名称:">{{ e.stadium_name || '-' }}</kv-line> |
|||
<kv-line label="开始时间:">{{ e.start_time || e.created_at || '-' }}</kv-line> |
|||
<block v-if="e.type === 0"> |
|||
<kv-line label="设备名称:">{{ e.hardware_name || '-' }}</kv-line> |
|||
<kv-line label="结束时间:">{{ e.end_time || '-' }}</kv-line> |
|||
<kv-line label="时长合计:">{{ e.settle_duration || '-' }}</kv-line> |
|||
</block> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import time_range from "../../components/time_range.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'time-range': time_range, |
|||
'kv-line': kv_line |
|||
}, |
|||
watch: { |
|||
condition: { |
|||
handler(val){ |
|||
let { start_time, end_time } = val; |
|||
let { optionsQuery } = this; |
|||
this.recordList = []; |
|||
this.page = 1; |
|||
this.getCardUseRecord({ |
|||
brand_id: optionsQuery?.brand_id || '', |
|||
water_card_no: optionsQuery?.water_card_no || '', |
|||
start_time, end_time |
|||
}) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
condition: { |
|||
start_time: '', |
|||
end_time: '' |
|||
}, |
|||
optionsQuery: {}, |
|||
recordList: [], |
|||
page: 1 |
|||
} |
|||
}, |
|||
onReachBottom(){ |
|||
let { optionsQuery, page, condition } = this; |
|||
this.getCardUseRecord({ |
|||
brand_id: optionsQuery?.brand_id || '', |
|||
water_card_no: optionsQuery?.water_card_no || '', |
|||
page: ++page, |
|||
...condition |
|||
}); |
|||
}, |
|||
onLoad(options){ |
|||
this.optionsQuery = options; |
|||
this.initDate(); |
|||
// this.getCardUseRecord({ brand_id, water_card_no }); |
|||
}, |
|||
methods: { |
|||
initDate(){ |
|||
let _Date = new Date(); |
|||
let _timeStamp = _Date.getTime(); |
|||
let _start = _timeStamp - 90 * 24 * 60 * 60 * 1000; |
|||
this.condition.start_time = formatDate({ date: _start }); |
|||
this.condition.end_time = formatDate({ date: _timeStamp }); |
|||
this.$refs.timeRange.init(this.condition); |
|||
return this.condition |
|||
}, |
|||
getCardUseRecord({ |
|||
brand_id = '', water_card_no = '', page = 1, page_size = 10, |
|||
start_time, end_time |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.CardUseRecord, |
|||
data: { |
|||
brand_id, water_card_no, page, page_size, |
|||
start_time: `${start_time} 00:00:00`, |
|||
end_time: `${end_time} 23:59:59` |
|||
}, |
|||
failMsg: '获取用水卡使用记录失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _ls = res?.list || []; |
|||
if(page === 1)return this.recordList = _ls; |
|||
if(!_ls.length)return showNone('没有更多!'); |
|||
this.page = page; |
|||
return this.recordList = [...this.recordList, ..._ls]; |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('card use_record getCardUseRecord err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.use-record{ |
|||
.ur-list{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
.ul-item{ |
|||
padding: 0 20upx; |
|||
background: #fff; |
|||
border-radius: 10upx; |
|||
&+.ul-item{ |
|||
margin-top: 24upx; |
|||
} |
|||
} |
|||
.ui-tit-bar{ |
|||
padding: 16upx 0upx; |
|||
@include ctf(space-between); |
|||
.utb-tit{ |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #1A1A1A, 500); |
|||
} |
|||
.utb-right{ |
|||
.ur-time{ |
|||
text-align: right; |
|||
@include flcw(28upx, 40upx, $mColor); |
|||
@include tHide; |
|||
&.orange{ |
|||
color: #FF873D; |
|||
} |
|||
} |
|||
.ur-surplus{ |
|||
text-align: right; |
|||
@include tHide; |
|||
@include flcw(20upx, 28upx, #9C9C9F); |
|||
} |
|||
} |
|||
} |
|||
.ui-lines{ |
|||
padding-top: 10upx; |
|||
padding-bottom: 30upx; |
|||
border-top: 1px solid #D8D8D8; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,203 @@ |
|||
<template> |
|||
<view class="use-detail"> |
|||
<view class="ud-box"> |
|||
<view class="ub-stadium"> |
|||
<image class="us-logo" mode="aspectFit" :src="orderInfo.logo"></image> |
|||
<view class="us-name">{{ orderInfo.stadium_name || '-' }}</view> |
|||
</view> |
|||
<view class="ub-lines"> |
|||
<kv-line label="创建时间:"> |
|||
<template slot="default">{{ orderInfo.created_at || '-' }}</template> |
|||
<template slot="right"> |
|||
<view class="ul-status">{{ statusTxt || '' }}</view> |
|||
</template> |
|||
</kv-line> |
|||
<kv-line label="手机号码:">{{ orderInfo.mobile || '-' }}</kv-line> |
|||
<kv-line label="用户昵称:">{{ orderInfo.nick_name || '-' }}</kv-line> |
|||
<kv-line label="结束计时方式:">小程序(欧轩智能场馆)</kv-line> |
|||
</view> |
|||
</view> |
|||
<view class="ud-box"> |
|||
<kv-line label="计时信息"></kv-line> |
|||
<view class="ub-lines"> |
|||
<kv-line label="设备名称:">{{ orderInfo.hardware_name || '-' }}</kv-line> |
|||
<kv-line label="开始时间:">{{ orderInfo.start_time || '-' }}</kv-line> |
|||
|
|||
<kv-line label="结束时间:" v-if="orderInfo.status === 1">{{ orderInfo.end_time || '-' }}</kv-line> |
|||
|
|||
<kv-line label="时长合计:">{{ orderInfo.settle_duration || '-' }}</kv-line> |
|||
|
|||
<kv-line label="免费时长:" v-if="orderInfo.status === 1">{{ orderInfo.free_duration || '-' }}</kv-line> |
|||
</view> |
|||
<view class="ui-deduction" v-if="orderInfo.status === 1"> |
|||
<text class="ud-txt">扣减时长:</text>{{ orderInfo.deduction_duration || '-' }} |
|||
</view> |
|||
<view class="ui-btn" v-if="orderInfo.status === 0" @click="endTimekeeping">结束计时</view> |
|||
</view> |
|||
|
|||
<!-- 结束计时弹窗 --> |
|||
<device-deduction ref="deviceDeduction"></device-deduction> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import deviceDeduction from "../../components/popup/device_deduction.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'kv-line': kv_line, |
|||
'device-deduction': deviceDeduction |
|||
}, |
|||
|
|||
computed: { |
|||
statusTxt(){ |
|||
let { orderInfo } = this; |
|||
switch(+orderInfo.status){ |
|||
case 0: |
|||
return '正在计时'; |
|||
case 1: |
|||
return '已完成'; |
|||
default: |
|||
return '-'; |
|||
} |
|||
}, |
|||
/** |
|||
* SettleType = 0 //小程序结束3个用法 |
|||
SettleType = 1 // 后台结束 2个用法 |
|||
SettleType = 2 // 硬件结束 2个用法 |
|||
SettleType = 3 // 商家助手结束 |
|||
* */ |
|||
settleTypeTxt(){ |
|||
let { orderInfo } = this; |
|||
switch(+orderInfo.settle_type){ |
|||
case 0: |
|||
return '小程序结束'; |
|||
case 1: |
|||
return '后台结束'; |
|||
case 2: |
|||
return '硬件结束'; |
|||
case 3: |
|||
return '商家助手结束'; |
|||
default: |
|||
return '-'; |
|||
} |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
orderInfo: {}, |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.getUseDetail({ |
|||
id: options?.id || '', |
|||
brand_id: options?.brand_id || '' |
|||
}) |
|||
.then(res=>{ |
|||
if(res?.status === 0&&options?.isRefund === '1')this.endTimekeeping(); |
|||
}) |
|||
}, |
|||
methods: { |
|||
endTimekeeping(){ |
|||
let { orderInfo } = this; |
|||
this.$refs.deviceDeduction.init({ |
|||
settle_duration: orderInfo?.settle_duration || 0, |
|||
id: orderInfo?.id || '', |
|||
stadium_id: orderInfo?.stadium_id || '', |
|||
brand_id: orderInfo?.brand_id || '', |
|||
success: res=>{ |
|||
this.getUseDetail({ |
|||
id: orderInfo?.id || '', |
|||
brand_id: orderInfo?.brand_id || '' |
|||
}); |
|||
} |
|||
}); |
|||
}, |
|||
getUseDetail({ |
|||
id = '', brand_id = '' |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.waterOrderDetails, |
|||
data: { brand_id, id }, |
|||
failMsg: '获取信息失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
return this.orderInfo = res || {}; |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('use_detail getUseDetail err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.use-detail{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
.ud-box{ |
|||
padding: 30upx; |
|||
background: #fff; |
|||
border-radius: 10upx; |
|||
&+.ud-box{ |
|||
margin-top: 24upx; |
|||
} |
|||
} |
|||
.ub-stadium{ |
|||
@include ctf; |
|||
padding-bottom: 26upx; |
|||
border-bottom: 1px solid #D8D8D8; |
|||
.us-logo{ |
|||
margin-right: 14upx; |
|||
flex-shrink: 0; |
|||
width: 40upx; |
|||
height: 40upx; |
|||
} |
|||
.us-name{ |
|||
margin-left: 20upx; |
|||
font-size: 28upx; |
|||
color: #333333; |
|||
@include tHide; |
|||
@include flcw(28upx, 40upx, #333333, 500); |
|||
} |
|||
} |
|||
.ub-lines{ |
|||
padding-top: 24upx; |
|||
.ul-status{ |
|||
text-align: right; |
|||
@include flcw(28upx, 40upx, #9C9C9F); |
|||
} |
|||
} |
|||
|
|||
.ui-deduction{ |
|||
margin-top: 30upx; |
|||
padding-top: 24upx; |
|||
text-align: right; |
|||
border-top: 1upx solid #D8D8D8; |
|||
@include flcw(28upx, 40upx, $mColor); |
|||
@include tHide; |
|||
.ud-txt{ |
|||
color: #9C9C9F; |
|||
} |
|||
} |
|||
|
|||
.ui-btn{ |
|||
margin: 10upx 0upx 0upx auto; |
|||
width: 192upx; |
|||
height: 80upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(32upx, 80upx, #fff); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,263 @@ |
|||
<template> |
|||
<view class="use-record"> |
|||
<order-filter |
|||
ref="orderFilter" |
|||
@change:stadium="condition.stadium_id = $event.id" |
|||
@click:time="showPeriodModal" |
|||
@click:filter="showFilterModal" |
|||
:start-time="condition.start_time" |
|||
:end-time="condition.end_time" |
|||
></order-filter> |
|||
<view class="ur-list"> |
|||
<!-- status 0进行中;1已完成 --> |
|||
<view class="ul-item" v-for="(e, i) in orderList" :key="i" @click="toDetail(e)"> |
|||
<view class="ui-bar"> |
|||
<view class="ub-name">{{ e.stadium_name || '-' }}</view> |
|||
<image class="ub-icon" mode="aspectFit" src="/subpackage/shower/static/images/arrow.png"></image> |
|||
</view> |
|||
<view class="ui-lines"> |
|||
<kv-line label="设备名称:">{{ e.hardware_name || '-' }}</kv-line> |
|||
<kv-line label="时长合计:"> |
|||
{{ e.settle_duration || '-' }} |
|||
<block v-if="e.free_duration"> |
|||
(免费时长{{ e.free_duration || 0 }}) |
|||
</block> |
|||
</kv-line> |
|||
<kv-line label="手机号码:">{{ e.mobile || '-' }}</kv-line> |
|||
<kv-line label="创建时间:">{{ e.created_at || '-' }}</kv-line> |
|||
</view> |
|||
<view class="ui-deduction" v-if="e.status === 1"> |
|||
<text class="ud-txt">扣减时长:</text>{{ e.deduction_duration || '0' }} |
|||
</view> |
|||
<view class="ui-btn" v-if="e.status === 0" @click.stop="endTimekeeping(e)">结束计时</view> |
|||
</view> |
|||
</view> |
|||
<!-- 时间段选择 --> |
|||
<period-modal ref="periodModal"></period-modal> |
|||
<!-- status窗口 --> |
|||
<filter-modal ref="filterModal"></filter-modal> |
|||
<!-- 结束计时弹窗 --> |
|||
<device-deduction ref="deviceDeduction"></device-deduction> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import orderFilter from "@/components/filter/header.vue"; |
|||
import periodModal from "@/components/filter/period_modal.vue"; |
|||
import filterModal from "@/components/filter/filter_modal.vue"; |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import deviceDeduction from "../../components/popup/device_deduction.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'order-filter': orderFilter, |
|||
'period-modal': periodModal, |
|||
'filter-modal': filterModal, |
|||
'kv-line': kv_line, |
|||
'device-deduction': deviceDeduction |
|||
}, |
|||
watch: { |
|||
condition: { |
|||
handler(nVal, oVal){ |
|||
this.orderList = []; |
|||
this.page = 1; |
|||
let { brand_id } = this; |
|||
this.getOrderList({ |
|||
brand_id: brand_id || '', |
|||
...nVal, |
|||
}) |
|||
}, |
|||
deep: true |
|||
}, |
|||
}, |
|||
data(){ |
|||
return { |
|||
condition: { |
|||
stadium_id: '', |
|||
start_time: '', |
|||
end_time: '', |
|||
status: '' // 状态:0进行中;1已完成 |
|||
}, |
|||
orderList: [], |
|||
page: 1, |
|||
brand_id: '' |
|||
} |
|||
}, |
|||
onReachBottom(){ |
|||
let { condition, page, brand_id } = this; |
|||
this.getOrderList({ |
|||
...condition, |
|||
page: ++page, |
|||
brand_id |
|||
}) |
|||
}, |
|||
async onLoad(options){ |
|||
this.$refs.orderFilter.initStadiumSelect({ |
|||
brand_id: options?.brand_id || '', |
|||
stadium_id: options?.stadium_id || '' |
|||
}); |
|||
this.brand_id = options?.brand_id || ''; |
|||
this.condition.stadium_id = options?.stadium_id || ''; |
|||
// this.getOrderList({ brand_id: options?.brand_id }); |
|||
this.initDate(); |
|||
}, |
|||
methods: { |
|||
endTimekeeping(e){ |
|||
let _qryStr = `id=${e?.id || ''}&brand_id=${e?.brand_id || ''}&isRefund=1`; |
|||
routeTo(`/subpackage/shower/pages/device/use_detail?${_qryStr}`, 'nT'); |
|||
return |
|||
this.$refs.deviceDeduction.init({ |
|||
settle_duration: e?.settle_duration || 0, |
|||
id: e?.id || '', |
|||
stadium_id: e?.stadium_id || '', |
|||
brand_id: e?.brand_id || '', |
|||
success: res=>{ |
|||
let { condition, brand_id } = this; |
|||
this.orderList = []; |
|||
this.page = 1; |
|||
this.getOrderList({ |
|||
brand_id: brand_id || '', |
|||
...condition |
|||
}) |
|||
} |
|||
}); |
|||
}, |
|||
toDetail(e){ |
|||
let _qryStr = `id=${e?.id || ''}&brand_id=${e?.brand_id || ''}`; |
|||
routeTo(`/subpackage/shower/pages/device/use_detail?${_qryStr}`, 'nT'); |
|||
}, |
|||
// 默认显示三个月内的水阀卡数据 |
|||
initDate(){ |
|||
let _Date = new Date(); |
|||
let _timeStamp = _Date.getTime(); |
|||
let _start = _timeStamp - 90 * 24 * 60 * 60 * 1000; |
|||
Object.assign(this.condition, { |
|||
start_time: formatDate({ date: _start }), |
|||
end_time: formatDate({ date: _timeStamp }) |
|||
}) |
|||
}, |
|||
showPeriodModal(){ |
|||
let { start_time, end_time } = this.condition; |
|||
this.$refs.periodModal.init({ |
|||
start: start_time, |
|||
end: end_time, |
|||
success: res=>{ |
|||
this.condition.start_time = res.start; |
|||
this.condition.end_time = res.end; |
|||
} |
|||
}); |
|||
}, |
|||
// 0:未支付;1:已支付;2:已使用;4:已退款; |
|||
// 5:退款中;6:拒绝退款;7:关闭支付;8:使用中 |
|||
showFilterModal(){ |
|||
this.$refs.filterModal.init({ |
|||
title: '订单状态', |
|||
list: [ |
|||
{ label: '全部', value: '' }, |
|||
{ label: '进行中', value: '0' }, |
|||
{ label: '已完成', value: '1' }, |
|||
], |
|||
curValue: this.condition.status, |
|||
success: res=>{ |
|||
this.condition.status = res.value; |
|||
} |
|||
}); |
|||
}, |
|||
/** |
|||
* @param { status } 状态:0进行中;1已完成 |
|||
* */ |
|||
getOrderList({ |
|||
brand_id = '', stadium_id = '', |
|||
start_time = '', end_time = '', status = '', |
|||
page = 1, page_size = 10 |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.waterOrderList, |
|||
data: { |
|||
brand_id, |
|||
stadium_id, |
|||
start_time: `${start_time} 00:00:00`, |
|||
end_time: `${end_time} 23:59:59`, |
|||
status, |
|||
page, |
|||
page_size |
|||
}, |
|||
failMsg: '获取水阀订单失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _ls = res?.list || []; |
|||
if(page === 1)return this.orderList = _ls; |
|||
if(!_ls.length)return showNone('没有更多!'); |
|||
this.page = page; |
|||
return this.orderList = [...this.orderList, ..._ls]; |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('device user_record getOrderList err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.use-record{ |
|||
.ur-list{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
.ul-item{ |
|||
padding: 0upx 20upx 30upx; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
&+.ul-item{ |
|||
margin-top: 24upx; |
|||
} |
|||
.ui-bar{ |
|||
padding: 30upx 0upx; |
|||
border-bottom: 1upx solid #D8D8D8; |
|||
@include ctf(space-between); |
|||
.ub-name{ |
|||
@include flcw(28upx, 40upx, #1A1A1A, 500); |
|||
@include tHide; |
|||
} |
|||
.ub-icon{ |
|||
margin-left: 12upx; |
|||
flex-shrink: 0; |
|||
width: 28upx; |
|||
height: 28upx; |
|||
} |
|||
} |
|||
.ui-lines{ |
|||
padding-top: 14upx; |
|||
} |
|||
.ui-deduction{ |
|||
margin-top: 30upx; |
|||
padding-top: 24upx; |
|||
text-align: right; |
|||
border-top: 1upx solid #D8D8D8; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
@include tHide; |
|||
.ud-txt{ |
|||
color: #9C9C9F; |
|||
} |
|||
} |
|||
.ui-btn{ |
|||
margin: 10upx 0upx 0upx auto; |
|||
width: 192upx; |
|||
height: 80upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(32upx, 80upx, #fff); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,289 @@ |
|||
<template> |
|||
<view class="order-detail"> |
|||
<view class="od-header"> |
|||
<view class="oh-stadium"> |
|||
<image class="os-img" mode="aspectFit" :src="orderInfo.logo || ''"></image> |
|||
<view class="os-name">{{ orderInfo.stadium_name || '-' }}</view> |
|||
</view> |
|||
<view class="oh-bot"> |
|||
<kv-line label="订单编号:"> |
|||
<template slot="default">{{ orderInfo.order_no || '-' }}</template> |
|||
<template slot="right"> |
|||
<view class="ob-status">{{ getPayStatusTxt(orderInfo.pay_status || -1) }}</view> |
|||
</template> |
|||
</kv-line> |
|||
<kv-line label="创建时间:">{{ orderInfo.created_at || '-' }}</kv-line> |
|||
<kv-line label="手机号码:">{{ orderInfo.mobile || '-' }}</kv-line> |
|||
<kv-line label="用户昵称:">{{ orderInfo.nick_name || '-' }}</kv-line> |
|||
<kv-line label="来源:">{{ orderInfo.source || '-' }}</kv-line> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="od-goods"> |
|||
<view class="og-tit">订单信息</view> |
|||
<view class="og-lines"> |
|||
<kv-line label="名称:">{{ orderInfo.water_card_name || '-' }}</kv-line> |
|||
<kv-line label="水阀卡号:">{{ orderInfo.water_card_no || '-' }}</kv-line> |
|||
<kv-line label="时长:">{{ orderInfo.duration_text || '-' }}</kv-line> |
|||
<kv-line label="途径:">{{ orderInfo.desc || '-' }}</kv-line> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="od-price-info"> |
|||
<kvs-line label="金额小计">¥{{ orderInfo.amount || 0 }}</kvs-line> |
|||
<kvs-line label="积分抵扣">-¥{{ orderInfo.deduction_amount || 0 }}</kvs-line> |
|||
<kvs-line label="折扣金额">-¥{{ orderInfo.discount_amount || 0 }}</kvs-line> |
|||
<kvs-line label="优惠券优惠">-¥{{ orderInfo.coupons_amount || 0 }}</kvs-line> |
|||
<view class="opi-total"> |
|||
合计支付:<text class="ot-num">¥{{ orderInfo.pay_amount || 0 }}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="od-pay-info"> |
|||
<view class="opi-tit">支付信息</view> |
|||
<view class="opi-lines"> |
|||
<kv-line label="支付方式:">{{ _extension.pay_type_text || '-' }}</kv-line> |
|||
<kv-line label="支付时间:">{{ orderInfo.pay_time || '-' }}</kv-line> |
|||
<kv-line label="微信交易号:">{{ orderInfo.trade_no || '-' }}</kv-line> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 退款列表 --> |
|||
<block v-for="(e, i) in refundList" :key="i"> |
|||
<view class="od-space"></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> |
|||
</block> |
|||
|
|||
<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> |
|||
|
|||
<order-refund-modal |
|||
ref="orderRefundModal" |
|||
></order-refund-modal> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import kv_line from "@/components/kv_line.vue"; |
|||
import kvs_line from "@/components/kvs_line.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'; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'kv-line': kv_line, |
|||
'kvs-line': kvs_line, |
|||
'order-refund-fixed': orderRefundFixed, |
|||
'order-refund-modal': orderRefundModal, |
|||
'order-refund-info': orderRefundInfo |
|||
}, |
|||
computed: { |
|||
_extension(){ |
|||
return this.orderInfo?.extension || {}; |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
orderInfo: {}, |
|||
refundList: [], |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.getCardOrderDetails({ |
|||
id: options?.id, |
|||
brand_id: options?.brand_id, |
|||
order_no: options?.order_no |
|||
}) |
|||
.then(res=>{ |
|||
if(res.order_no)this.getRefundInfo(res.order_no || ''); |
|||
}) |
|||
}, |
|||
methods: { |
|||
refunndBtn(){ |
|||
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 || 0, |
|||
confirm: e => { |
|||
console.log('confirm --->', e); |
|||
this.orderRefund({ |
|||
order_no: orderInfo?.order_no || '', |
|||
amount: e.refund_amount || 0, |
|||
integral: e.refund_integral || 0, |
|||
brand_id: orderInfo?.brand_id || '' |
|||
}) |
|||
} |
|||
}); |
|||
}, |
|||
orderRefund({ order_no = '', amount = 0, integral = 0, brand_id }){ |
|||
showLoad(); |
|||
server.post({ |
|||
url: SHOWER_API.orderRefund, |
|||
data: { order_no, amount, integral, brand_id }, |
|||
isDefaultGet: false |
|||
}) |
|||
.then(res=>{ |
|||
hideLoad(); |
|||
if(res.data.code == 0){ |
|||
showNone(res.data.message || '操作成功!'); |
|||
}else{ |
|||
showNone(res.data.message || '操作失败!'); |
|||
} |
|||
}) |
|||
.catch(hideLoad) |
|||
.finally(_=> |
|||
setTimeout(_=>{ |
|||
let { orderInfo } = this; |
|||
this.getCardOrderDetails({ |
|||
id: orderInfo?.id, |
|||
order_no: orderInfo?.order_no, |
|||
brand_id: orderInfo?.brand_id, |
|||
}) |
|||
.then(res=>{ |
|||
if(res.order_no)this.getRefundInfo(res.order_no || ''); |
|||
}) |
|||
}, 1200) |
|||
); |
|||
}, |
|||
async getRefundInfo(order_no){ |
|||
try{ |
|||
let _refundRes = await this.$store.dispatch('getOrderRefundList', order_no); |
|||
let _ls = _refundRes?.data?.data?.list || []; |
|||
this.refundList = _ls; |
|||
}catch(err){ |
|||
console.warn('shower order detail getRefundInfo err', err); |
|||
} |
|||
}, |
|||
getPayStatusTxt(payStatus){ |
|||
let _txt = ''; |
|||
switch(payStatus){ |
|||
case 0: _txt = '未支付'; break; |
|||
case 1: _txt = '已支付'; break; |
|||
case 2: _txt = '已使用'; break; |
|||
case 4: _txt = '已退款'; break; |
|||
case 5: _txt = '退款中'; break; |
|||
case 6: _txt = '拒绝退款'; break; |
|||
case 7: _txt = '关闭支付'; break; |
|||
case 8: _txt = '使用中'; break; |
|||
default: _txt = '-'; |
|||
} |
|||
return _txt; |
|||
}, |
|||
getCardOrderDetails({ |
|||
id = '', brand_id = '', order_no = '' |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.cardOrderDetails, |
|||
data: { brand_id, id, order_no }, |
|||
failMsg: '获取信息失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
return this.orderInfo = res || {}; |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('shower order details err --->', err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.order-detail{ |
|||
@include isPd(24upx); |
|||
.od-space{ |
|||
padding-top: 24upx; |
|||
} |
|||
.od-header{ |
|||
padding: 0 24upx; |
|||
background: #fff; |
|||
.oh-stadium{ |
|||
padding: 24upx 0; |
|||
border-bottom: 1px solid #D8D8D8; |
|||
@include ctf; |
|||
.os-img{ |
|||
flex-shrink: 0; |
|||
margin-right: 14upx; |
|||
width: 40upx; |
|||
height: 40upx; |
|||
} |
|||
.os-name{ |
|||
@include flcw(28upx, 40upx, #1A1A1A, 500); |
|||
@include tHide; |
|||
} |
|||
} |
|||
.oh-bot{ |
|||
padding-top: 24upx; |
|||
padding-bottom: 30upx; |
|||
.ob-status{ |
|||
text-align: right; |
|||
@include flcw(28upx, 40upx, #9A9A9D); |
|||
} |
|||
} |
|||
} |
|||
.od-goods{ |
|||
margin-top: 24upx; |
|||
padding: 20upx 24upx 0; |
|||
background: #fff; |
|||
|
|||
.opi-tit{ |
|||
@include flcw(32upx, 44upx, #1A1A1A); |
|||
} |
|||
.og-lines{ |
|||
margin-top: 28upx; |
|||
padding-bottom: 30upx; |
|||
border-bottom: 1px solid #D8D8D8; |
|||
} |
|||
|
|||
} |
|||
.od-price-info{ |
|||
padding: 30upx; |
|||
background: #fff; |
|||
.opi-total{ |
|||
text-align: right; |
|||
@include flcw(28upx, 50upx, #9A9A9D); |
|||
.ot-num{ |
|||
color: #1A1A1A; |
|||
font-weight: 500; |
|||
} |
|||
} |
|||
} |
|||
.od-pay-info{ |
|||
margin-top: 24upx; |
|||
padding: 30upx 24upx; |
|||
background: #fff; |
|||
.opi-tit{ |
|||
@include flcw(32upx, 44upx, #1A1A1A); |
|||
} |
|||
.opi-lines{ |
|||
margin-top: 16upx; |
|||
.ob-copy{ |
|||
margin-left: 20upx; |
|||
@include flcw(28upx, 40upx, $mColor); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,252 @@ |
|||
<template> |
|||
<view class="order-list"> |
|||
|
|||
<order-filter |
|||
ref="orderFilter" |
|||
@change:stadium="condition.stadium_id = $event.id" |
|||
@click:time="showPeriodModal" |
|||
@click:filter="showFilterModal" |
|||
:start-time="condition.start_time" |
|||
:end-time="condition.end_time" |
|||
></order-filter> |
|||
|
|||
<view class="ol-ls"> |
|||
<view class="ol-item" v-for="(e, i) in cardOrderList" :key="i" @click="itemClick(e)"> |
|||
<view class="oi-header"> |
|||
<view class="oh-top"> |
|||
<view class="ot-name">{{ e.stadium_name || '-' }}</view> |
|||
<view class="ot-status">{{ getPayStatusTxt(e.pay_status || -1) }}</view> |
|||
</view> |
|||
<!-- <view class="oh-device-name"> |
|||
<image class="odn-img" mode="aspectFit" src="/subpackage/shower/static/images/locate.png"></image> |
|||
<view class="odn-txt">1号女沐浴间</view> |
|||
</view> --> |
|||
</view> |
|||
<view class="oi-lines"> |
|||
<kv-line label="订单编号:">{{ e.order_no || '-' }}</kv-line> |
|||
<kv-line label="名称:">{{ e.water_card_name || '-' }}</kv-line> |
|||
<kv-line label="手机号码:">{{ e.mobile || '-' }}</kv-line> |
|||
<kv-line label="支付时间:">{{ e.pay_time || '-' }}</kv-line> |
|||
<kv-line label="途径:">{{ e.source || '-' }}</kv-line> |
|||
</view> |
|||
<view class="oi-total"> |
|||
合计支付:<text class="ot-price">¥{{ e.pay_amount || 0 }}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 时间段选择 --> |
|||
<period-modal ref="periodModal"></period-modal> |
|||
<!-- status窗口 --> |
|||
<filter-modal ref="filterModal"></filter-modal> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import orderFilter from "@/components/filter/header.vue"; |
|||
import periodModal from "@/components/filter/period_modal.vue"; |
|||
import filterModal from "@/components/filter/filter_modal.vue"; |
|||
|
|||
import kv_line from "@/components/kv_line.vue"; |
|||
|
|||
import { SHOWER_API } from "../../js/api"; |
|||
import server from "../../js/server"; |
|||
import { routeTo, showLoad, hideLoad, showNone, formatDate } from "@/utils/util"; |
|||
export default { |
|||
components: { |
|||
'order-filter': orderFilter, |
|||
'period-modal': periodModal, |
|||
'filter-modal': filterModal, |
|||
'kv-line': kv_line |
|||
}, |
|||
watch: { |
|||
condition: { |
|||
handler(nVal, oVal){ |
|||
console.log('nVal --->', nVal); |
|||
this.cardOrderList = []; |
|||
this.page = 1; |
|||
let { brand_id } = this; |
|||
this.getCardOrderList({ |
|||
brand_id: brand_id || '', |
|||
...nVal, |
|||
}) |
|||
}, |
|||
deep: true |
|||
}, |
|||
}, |
|||
data(){ |
|||
return { |
|||
condition: { |
|||
stadium_id: '', |
|||
start_time: '', |
|||
end_time: '', |
|||
pay_status: '' |
|||
}, |
|||
brand_id: '', |
|||
cardOrderList: [], |
|||
page: 1 |
|||
} |
|||
}, |
|||
onReachBottom(){ |
|||
let { brand_id, condition, page } = this; |
|||
this.getCardOrderList({ brand_id, page: ++page, ...condition }); |
|||
}, |
|||
onLoad(options){ |
|||
let _bid = options?.brand_id || ''; |
|||
this.brand_id = _bid; |
|||
this.$refs.orderFilter.initStadiumSelect({ brand_id: _bid }); |
|||
this.initDate(); // watch 监听触发 |
|||
}, |
|||
methods: { |
|||
getPayStatusTxt(payStatus){ |
|||
let _txt = ''; |
|||
switch(payStatus){ |
|||
case 0: _txt = '未支付'; break; |
|||
case 1: _txt = '已支付'; break; |
|||
case 2: _txt = '已使用'; break; |
|||
case 4: _txt = '已退款'; break; |
|||
case 5: _txt = '退款中'; break; |
|||
case 6: _txt = '拒绝退款'; break; |
|||
case 7: _txt = '关闭支付'; break; |
|||
case 8: _txt = '使用中'; break; |
|||
default: _txt = '-'; |
|||
} |
|||
return _txt; |
|||
}, |
|||
itemClick(e){ |
|||
let _qryStr = `id=${e.id || ''}&brand_id=${e.brand_id || ''}&order_no=${e.order_no || ''}`; |
|||
routeTo(`/subpackage/shower/pages/order/detail?${_qryStr}`, 'nT'); |
|||
}, |
|||
// 默认显示三个月内的水阀卡数据 |
|||
initDate(){ |
|||
let _Date = new Date(); |
|||
let _timeStamp = _Date.getTime(); |
|||
let _start = _timeStamp - 90 * 24 * 60 * 60 * 1000; |
|||
this.condition.start_time = formatDate({ date: _start }); |
|||
this.condition.end_time = formatDate({ date: _timeStamp }); |
|||
}, |
|||
// 时间段选择 |
|||
showPeriodModal(){ |
|||
let { start_time, end_time } = this.condition; |
|||
this.$refs.periodModal.init({ |
|||
start: start_time, |
|||
end: end_time, |
|||
success: res=>{ |
|||
this.condition.start_time = res.start; |
|||
this.condition.end_time = res.end; |
|||
} |
|||
}); |
|||
}, |
|||
// 订单状态筛选 |
|||
showFilterModal(){ |
|||
this.$refs.filterModal.init({ |
|||
title: '订单状态', |
|||
list: [ |
|||
{ label: '全部', value: '' }, |
|||
{ label: '已支付', value: '1' }, |
|||
{ label: '已使用', value: '2' }, |
|||
{ label: '已退款', value: '4' }, |
|||
], |
|||
curValue: this.condition.pay_status, |
|||
success: res=>{ |
|||
this.condition.pay_status = res.value; |
|||
} |
|||
}); |
|||
}, |
|||
/** |
|||
* @param {String} number 卡号或者手机号 |
|||
* @param {String} pay_status |
|||
* 0:未支付;1:已支付;2:已使用;4:已退款;5:退款中;6:拒绝退款;7:关闭支付;8:使用中 |
|||
* |
|||
* */ |
|||
getCardOrderList({ |
|||
brand_id = '', stadium_id = '', |
|||
start_time = '', end_time = '', number = '', pay_status = '', |
|||
page = 1, page_size = 10, order_no = '' |
|||
}){ |
|||
showLoad(); |
|||
return server.get({ |
|||
url: SHOWER_API.cardOrderList, |
|||
data: { |
|||
brand_id, stadium_id, start_time, end_time, |
|||
number, pay_status, page, page_size, |
|||
order_no |
|||
}, |
|||
failMsg: '获取用水卡列表失败' |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _ls = res?.list || []; |
|||
if(page === 1)return this.cardOrderList = _ls; |
|||
if(!_ls.length)return showNone('没有更多!'); |
|||
this.page = page; |
|||
return this.cardOrderList = [...this.cardOrderList, ..._ls]; |
|||
|
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
console.warn('shower order list getCardOrderList err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.order-list{ |
|||
|
|||
} |
|||
.ol-ls{ |
|||
padding: 24upx; |
|||
.ol-item{ |
|||
padding: 30upx 20upx; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
&+.ol-item{ |
|||
margin-top: 24upx; |
|||
} |
|||
.oi-header{ |
|||
padding-bottom: 20upx; |
|||
border-bottom: 1px solid #D8D8D8; |
|||
.oh-top{ |
|||
@include ctf(space-between); |
|||
.ot-name{ |
|||
@include flcw(28upx, 40upx, #1A1A1A, 500); |
|||
@include tHide; |
|||
} |
|||
.ot-status{ |
|||
margin-left: 10upx; |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #9A9A9D); |
|||
} |
|||
} |
|||
.oh-device-name{ |
|||
margin-top: 10upx; |
|||
@include ctf; |
|||
.odn-img{ |
|||
margin-right: 12upx; |
|||
flex-shrink: 0; |
|||
width: 28upx; |
|||
height: 28upx; |
|||
} |
|||
.odn-txt{ |
|||
@include flcw(28upx, 40upx, #9A9A9D); |
|||
@include tHide; |
|||
} |
|||
} |
|||
} |
|||
.oi-lines{ |
|||
padding-top: 20upx; |
|||
} |
|||
.oi-total{ |
|||
text-align: right; |
|||
@include flcw(28upx, 40upx, #9A9A9D); |
|||
.ot-price{ |
|||
font-weight: 500; |
|||
color: #333333; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
After Width: 28 | Height: 28 | Size: 258 B |
After Width: 32 | Height: 32 | Size: 323 B |
After Width: 34 | Height: 34 | Size: 256 B |
After Width: 28 | Height: 28 | Size: 714 B |