18 changed files with 927 additions and 50 deletions
-
138src/components/period_select.vue
-
12src/pages.json
-
2src/pages/index/index.vue
-
2src/pages/order_search/order_search.vue
-
2src/subpackage/verification/components/head_bar.vue
-
21src/subpackage/verification/components/record/dy_item.vue
-
95src/subpackage/verification/components/record/mall_item.vue
-
37src/subpackage/verification/components/record/site_item.vue
-
15src/subpackage/verification/components/stadium_picker.vue
-
5src/subpackage/verification/js/api.js
-
35src/subpackage/verification/pages/index.vue
-
62src/subpackage/verification/pages/null.vue
-
305src/subpackage/verification/pages/record.vue
-
244src/subpackage/verification/pages/record_search.vue
-
BINsrc/subpackage/verification/static/images/order/null_code.png
-
BINsrc/subpackage/verification/static/images/order/null_range.png
-
BINsrc/subpackage/verification/static/images/order/null_search.png
-
BINsrc/subpackage/verification/static/images/round_close.png
@ -0,0 +1,138 @@ |
|||||
|
<template> |
||||
|
<!-- 时间段选择 --> |
||||
|
<view class="period-select-mask" v-if="isShow" @click="isShow = false"> |
||||
|
<view class="ol-period" @click.stop="()=>false"> |
||||
|
<view class="op-tit">日期范围</view> |
||||
|
<picker mode="date" class="op-picker" @change="startTimeChange" :value="startTime"> |
||||
|
<view class="op-time"> |
||||
|
<text class="ot-tit">开始时间</text> |
||||
|
<view class="ot-right"> |
||||
|
<input class="or-ipt" placeholder="选择时间" disabled :value="startTime"/> |
||||
|
<image class="or-icon" mode="aspectFit" src="/static/images/icon/arrow_b2.png"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</picker> |
||||
|
<picker mode="date" class="op-picker" @change="endTimeChange" :value="endTime"> |
||||
|
<view class="op-time"> |
||||
|
<text class="ot-tit">截止时间</text> |
||||
|
<view class="ot-right"> |
||||
|
<input class="or-ipt" placeholder="选择时间" disabled :value="endTime"/> |
||||
|
<image class="or-icon" mode="aspectFit" src="/static/images/icon/arrow_b2.png"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</picker> |
||||
|
<view class="pl-btn active" @click="confirmBtn">确定</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { showNone, showModal } from '@/utils/util'; |
||||
|
export default { |
||||
|
props: { |
||||
|
value: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value: { |
||||
|
handler(val) { |
||||
|
let [start, end] = val.split('_'); |
||||
|
this.startTime = start; |
||||
|
this.endTime = end; |
||||
|
}, |
||||
|
immediate: true |
||||
|
} |
||||
|
}, |
||||
|
data(){ |
||||
|
return { |
||||
|
isShow: false, |
||||
|
startTime: '', |
||||
|
endTime: '', |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
show(){ |
||||
|
this.isShow = true |
||||
|
}, |
||||
|
hide(){ |
||||
|
this.isShow = false |
||||
|
}, |
||||
|
startTimeChange(e){ |
||||
|
this.startTime = e.detail.value; |
||||
|
}, |
||||
|
endTimeChange(e){ |
||||
|
this.endTime = e.detail.value; |
||||
|
}, |
||||
|
confirmBtn(){ |
||||
|
let { startTime, endTime } = this; |
||||
|
let _sTimestemp = new Date(startTime.replace(/\-/g,'/')).getTime(); |
||||
|
let _eTimestemp = new Date(endTime.replace(/\-/g,'/')).getTime(); |
||||
|
if(_sTimestemp > _eTimestemp)return showModal({ content: '开始时间不能大于结束时间' }); |
||||
|
this.$emit('input', `${startTime}_${endTime}`); |
||||
|
this.hide(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.period-select-mask{ |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background: rgba(0,0,0,0.4); |
||||
|
z-index: 9999; |
||||
|
} |
||||
|
.ol-period{ |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
padding-left: 38upx; |
||||
|
padding-top: 66upx; |
||||
|
height: 472upx; |
||||
|
width: 100%; |
||||
|
background-color: #fff; |
||||
|
.op-tit{ |
||||
|
@include flcw(24upx, 34upx, #9c9c9f); |
||||
|
} |
||||
|
.op-picker{ |
||||
|
width: 100%; |
||||
|
|
||||
|
} |
||||
|
.op-time{ |
||||
|
padding-right: 40upx; |
||||
|
height: 124upx; |
||||
|
border-bottom: 2upx solid #D8D8D8; |
||||
|
@include ctf(space-between); |
||||
|
.ot-tit{ |
||||
|
flex-shrink: 0; |
||||
|
@include flcw(32upx, 44upx, #1a1a1a); |
||||
|
} |
||||
|
.ot-right{ |
||||
|
flex-grow: 1; |
||||
|
@include ctf(flex-end); |
||||
|
.or-ipt{ |
||||
|
flex-grow: 1; |
||||
|
height: 100%; |
||||
|
text-align: right; |
||||
|
@include flcw(32upx, 44upx, #1a1a1a); |
||||
|
} |
||||
|
.or-icon{ |
||||
|
flex-shrink: 0; |
||||
|
margin-left: 36upx; |
||||
|
width: 28upx; |
||||
|
height: 28upx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.pl-btn{ |
||||
|
min-height: 124upx; |
||||
|
text-align: center; |
||||
|
@include flcw(32upx, 124upx, $mColor, 500); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,95 @@ |
|||||
|
<template> |
||||
|
<view class="site-item"> |
||||
|
<view class="si-order-num"> |
||||
|
<view class="son-txt">订单编号:{{ orderNum || '-' }}</view> |
||||
|
<view class="son-copy" @click="copyBtn">复制</view> |
||||
|
</view> |
||||
|
<view class="si-lines"> |
||||
|
<view class="sl-item"> |
||||
|
<view class="sl-left">取货码:{{ orderCode || '-' }}</view> |
||||
|
</view> |
||||
|
<view class="sl-item"> |
||||
|
<view class="sl-left">取货人:{{ userName || '-' }} {{ userPhone || '-' }}</view> |
||||
|
</view> |
||||
|
<view class="sl-item"> |
||||
|
<view class="sl-left">商品:{{ goodsStr || '-' }}</view> |
||||
|
</view> |
||||
|
<view class="sl-item"> |
||||
|
<view class="sl-left">核验人:{{ optUser || '-' }}</view> |
||||
|
</view> |
||||
|
<view class="sl-item"> |
||||
|
<view class="sl-left">取货时间:{{ createdAt || '-' }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
<script> |
||||
|
export default { |
||||
|
props: [ |
||||
|
'orderNum', |
||||
|
'orderCode', |
||||
|
'userPhone', |
||||
|
'userName', |
||||
|
'goodsStr', |
||||
|
'optUser', |
||||
|
'createdAt', |
||||
|
], |
||||
|
methods: { |
||||
|
copyBtn(){ |
||||
|
uni.setClipboardData({ data: this.orderNum }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
<style lang="scss"> |
||||
|
.site-item{ |
||||
|
position: relative; |
||||
|
padding: 0 20upx; |
||||
|
border-radius: 10upx; |
||||
|
background: #fff; |
||||
|
.si-order-num{ |
||||
|
min-height: 100upx; |
||||
|
border-bottom: 2upx solid #D8D8D8; |
||||
|
@include ctf; |
||||
|
.son-txt{ |
||||
|
flex-grow: 1; |
||||
|
@include flcw(28upx, 98upx, #1A1A1A, 500); |
||||
|
@include tHide; |
||||
|
} |
||||
|
.son-copy{ |
||||
|
padding-right: 20upx; |
||||
|
margin-left: 20upx; |
||||
|
flex-shrink: 0; |
||||
|
@include flcw(28upx, 98upx, $mColor, 500); |
||||
|
} |
||||
|
} |
||||
|
.si-lines{ |
||||
|
padding-top: 8upx; |
||||
|
padding-bottom: 32upx; |
||||
|
.sl-item{ |
||||
|
display: flex; |
||||
|
.sl-left{ |
||||
|
@include flcw(28upx, 52upx, #9c9c9f); |
||||
|
@include tHide; |
||||
|
} |
||||
|
.sl-right{ |
||||
|
max-width: 200upx; |
||||
|
flex-shrink: 0; |
||||
|
margin-left: 10upx; |
||||
|
@include flcw(28upx, 52upx, $mColor); |
||||
|
@include tHide; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.si-btn{ |
||||
|
position: absolute; |
||||
|
right: 20upx; |
||||
|
bottom: 32upx; |
||||
|
width: 192upx; |
||||
|
text-align: center; |
||||
|
background-color: $mColor; |
||||
|
border-radius: 10upx; |
||||
|
@include flcw(32upx, 80upx, #fff, 500); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,15 @@ |
|||||
|
<template> |
||||
|
<view class="stadium-picker"> |
||||
|
|
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
|
||||
|
</style> |
@ -0,0 +1,62 @@ |
|||||
|
<template> |
||||
|
<view class="null-container"> |
||||
|
<image v-if="tipHas('二维码')" class="nc-pic" mode="aspectFit" src="/subpackage/verification/static/images/order/null_code.png"></image> |
||||
|
<image v-else-if="tipHas('范围')" class="nc-pic" mode="aspectFit" src="/subpackage/verification/static/images/order/null_range.png"></image> |
||||
|
<image v-else class="nc-pic" mode="aspectFit" src="/subpackage/verification/static/images/order/null_search.png"></image> |
||||
|
<view class="nc-txt">{{ tip || '很抱歉!获取找不到订单信息' }}</view> |
||||
|
<view class="nc-btn" @click="routeTo">返回</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { jsonPar, routeTo } from '@/utils/util'; |
||||
|
export default { |
||||
|
data(){ |
||||
|
return { |
||||
|
tip: '', |
||||
|
} |
||||
|
}, |
||||
|
onLoad(options){ |
||||
|
let _tip = options?.tip ?? ''; |
||||
|
this.tip = jsonPar(_tip); |
||||
|
}, |
||||
|
methods: { |
||||
|
tipHas(txt){ |
||||
|
let { tip } = this; |
||||
|
return tip.indexOf(txt) > -1; |
||||
|
}, |
||||
|
routeTo, |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
page{ |
||||
|
background: #fff; |
||||
|
} |
||||
|
.null-container{ |
||||
|
padding-top: 220upx; |
||||
|
.nc-pic{ |
||||
|
display: block; |
||||
|
width: 400upx; |
||||
|
height: 400upx; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
.nc-txt{ |
||||
|
padding: 0 30upx; |
||||
|
margin-top: 80upx; |
||||
|
text-align: center; |
||||
|
@include flcw(28upx, 40upx, #9C9C9F); |
||||
|
} |
||||
|
.nc-btn{ |
||||
|
margin: 260upx auto 0; |
||||
|
width: 280upx; |
||||
|
text-align: center; |
||||
|
height: 92upx; |
||||
|
border-radius: 10upx; |
||||
|
border: 2upx solid $mColor; |
||||
|
@include flcw(32upx, 88upx, $mColor); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,244 @@ |
|||||
|
<template> |
||||
|
<view class="record-search"> |
||||
|
<view class="os-bar"> |
||||
|
<view> |
||||
|
<image mode="aspectFit" src="/subpackage/verification/static/images/search.png"></image> |
||||
|
<input placeholder="请输入手机号/核销码" v-model="searchTxt" confirm-type="search" @confirm="iptConfirm" /> |
||||
|
<image v-if="searchTxt!==''" mode="aspectFit" src="/subpackage/verification/static/images/round_close.png" @click="clearSearch"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="rs-ls"> |
||||
|
<block v-for="(e, i) in searchLs" :key="i"> |
||||
|
<site-item |
||||
|
v-if="orderType === 0" |
||||
|
:stadium-name="e.extension&&e.extension.stadium_name" |
||||
|
:order-num="e.order_no" |
||||
|
:order-type="e.type" |
||||
|
:user-phone="e.extension&&e.extension.user_phone" |
||||
|
:user-nickname="e.extension&&e.extension.nickname" |
||||
|
:verify-code="e.verify_code" |
||||
|
:verify-method="e.desc" |
||||
|
:verify-time="e.verify_time" |
||||
|
:verify-leave-time="e.verify_leave_time" |
||||
|
@click:leave="siteLeaveBtn(e, i)" |
||||
|
></site-item> |
||||
|
<dy-item |
||||
|
v-if="orderType === 1" |
||||
|
:order-num="e.order_no" |
||||
|
:user-phone="e.user_phone" |
||||
|
:verify-code="e.verify_code" |
||||
|
:verify-method="e.verify_method" |
||||
|
:verify-time="e.verify_time" |
||||
|
></dy-item> |
||||
|
<mall-item |
||||
|
v-if="orderType === 2" |
||||
|
:order-num="e.product_order_no" |
||||
|
:order-code="e.product_order_self_pickup_info.gcode" |
||||
|
:user-phone="e.product_order_self_pickup_info.phone" |
||||
|
:user-name="e.product_order_self_pickup_info.name" |
||||
|
:goods-str="e.product_order_goods.join(';')" |
||||
|
:opt-user="e.optuname" |
||||
|
:created-at="e.created_at" |
||||
|
></mall-item> |
||||
|
<view class="vl-space" style="height: 24rpx;"></view> |
||||
|
</block> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { formatDate, showLoad, hideLoad, showModal, showNone, debounce, formatTime, routeTo } from "@/utils/util"; |
||||
|
import API from "../js/api.js"; |
||||
|
import server from "../js/server.js"; |
||||
|
import siteItem from "../components/record/site_item.vue"; |
||||
|
import dyItem from "../components/record/dy_item.vue"; |
||||
|
import mallItem from "../components/record/mall_item.vue"; |
||||
|
export default { |
||||
|
components: { siteItem, dyItem, mallItem }, |
||||
|
data(){ |
||||
|
return { |
||||
|
brand_id: '', |
||||
|
orderType: '', |
||||
|
searchTxt: '', |
||||
|
page: 1, |
||||
|
searchLs: [], |
||||
|
} |
||||
|
}, |
||||
|
onLoad(options){ |
||||
|
this.brand_id = options?.brand_id ?? ''; |
||||
|
this.orderType = +(options?.type ?? ''); |
||||
|
}, |
||||
|
onReachBottom(){ |
||||
|
let { searchTxt, page } = this; |
||||
|
this.getRecordLs({ |
||||
|
keyword: searchTxt, |
||||
|
page: ++page |
||||
|
}) |
||||
|
}, |
||||
|
methods: { |
||||
|
clearSearch(){ |
||||
|
this.searchTxt = ''; |
||||
|
}, |
||||
|
iptConfirm(e){ |
||||
|
let { brand_id } = this; |
||||
|
console.log(e); |
||||
|
this.page = 1; |
||||
|
this.searchLs = []; |
||||
|
this.getRecordLs({ |
||||
|
brand_id, |
||||
|
keyword: e?.detail?.value || '' |
||||
|
}) |
||||
|
}, |
||||
|
// 手动离场 |
||||
|
siteLeaveBtn: debounce(function(e, idx){ |
||||
|
showModal({ |
||||
|
content: '是否确认手动离场?', |
||||
|
showCancel: true, |
||||
|
success: async mRes=>{ |
||||
|
if(mRes.confirm){ |
||||
|
let _status = await this.leaveVerifyOrder({ brand_id: e?.brand_id ?? '', id: e?.id ?? '' }); |
||||
|
if(_status)this.searchLs[idx].verify_leave_time = formatTime(new Date()); |
||||
|
this.$forceUpdate(); |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}, 300, true), |
||||
|
// 核销记录列表 - 手动离场 |
||||
|
leaveVerifyOrder({ brand_id, id }){ |
||||
|
showLoad(); |
||||
|
return server.post({ |
||||
|
url: API.leaveVerifyOrder, |
||||
|
data: { brand_id, id }, |
||||
|
isDefaultGet: false, |
||||
|
}) |
||||
|
.then(res => { |
||||
|
hideLoad(); |
||||
|
let _data = res?.data || {}; |
||||
|
if(_data.code === 0){ |
||||
|
showNone(_data?.message || '操作成功!') |
||||
|
return true; |
||||
|
}else{ |
||||
|
return Promise.reject(_data); |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
hideLoad(); |
||||
|
showModal({ |
||||
|
title: '提示', |
||||
|
content: err.message || '操作失败!' |
||||
|
}) |
||||
|
console.warn('verification record_search leaveVerifyOrder err --->', err); |
||||
|
// return Promise.reject(err); |
||||
|
return false; |
||||
|
}) |
||||
|
}, |
||||
|
// 商家助手-核销查询列表 |
||||
|
getRecordLs({ brand_id, stadium_id = '', start_time = '', end_time = '', page = 1, page_size = 20, keyword = '' }){ |
||||
|
showLoad(); |
||||
|
return server.post({ |
||||
|
url: this.getRecordLsAPI(), |
||||
|
data: this.formatQuery({ brand_id, stadium_id, start_time, end_time, page, page_size, keyword }), |
||||
|
isDefaultGet: false, |
||||
|
}) |
||||
|
.then(res => { |
||||
|
hideLoad(); |
||||
|
let _data = res?.data || {}; |
||||
|
if(_data.code === 0){ |
||||
|
let _ls = this.formatRecordLs(_data?.data?.list || []); |
||||
|
if(page === 1)return this.searchLs = _ls; |
||||
|
if(!_ls.length)return showNone('没有更多!'); |
||||
|
this.page = page; |
||||
|
this.searchLs = [ ...this.searchLs, ..._ls ]; |
||||
|
return _ls; |
||||
|
}else{ |
||||
|
return Promise.reject(_data); |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
hideLoad(); |
||||
|
showModal({ |
||||
|
title: '提示', |
||||
|
content: err.message || '加载数据失败!' |
||||
|
}) |
||||
|
console.warn('verification record_search getRecordLs err --->', err); |
||||
|
// return Promise.reject(err); |
||||
|
}) |
||||
|
}, |
||||
|
getRecordLsAPI(){ |
||||
|
let { orderType } = this; |
||||
|
if(orderType === 0)return API.listVerifyRecord |
||||
|
if(orderType === 1)return API.dyPoiOrderList |
||||
|
if(orderType === 2)return API.shop2WriteoffList |
||||
|
}, |
||||
|
formatQuery(query){ |
||||
|
let { orderType } = this; |
||||
|
if(orderType === 1)query['order_status'] = 'used'; |
||||
|
if(orderType === 2){ |
||||
|
query['stime'] = query?.start_time ?? ''; |
||||
|
query['etime'] = query?.end_time ?? ''; |
||||
|
delete query.start_time |
||||
|
delete query.end_time |
||||
|
} |
||||
|
return query; |
||||
|
}, |
||||
|
formatRecordLs(ls){ |
||||
|
let { orderType } = this; |
||||
|
// 抖音 |
||||
|
if(orderType === 1){ |
||||
|
return ls.map(item=>{ |
||||
|
let _code = item?.order_codes?.find(e=>e?.code_status == 'used'); |
||||
|
return { |
||||
|
order_no: item?.order_no ?? '', |
||||
|
user_phone: item?.mobile ?? '', |
||||
|
verify_code: _code?.code ?? '', |
||||
|
verify_method: _code?.verification_method ?? '', |
||||
|
verify_time: _code?.verification_time ?? '', |
||||
|
}; |
||||
|
}) |
||||
|
} |
||||
|
return ls; |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.record-search{ |
||||
|
@include isPd(20upx); |
||||
|
} |
||||
|
.os-bar{ |
||||
|
margin-bottom: 24upx; |
||||
|
height: 144upx; |
||||
|
background-color: #fff; |
||||
|
@include ctf(center); |
||||
|
>view{ |
||||
|
padding: 0 20upx; |
||||
|
height: 92upx; |
||||
|
width: 702upx; |
||||
|
border-radius: 10upx; |
||||
|
background-color: #f2f2f7; |
||||
|
@include ctf(center); |
||||
|
>image{ |
||||
|
margin-right: 20upx; |
||||
|
flex-shrink: 0; |
||||
|
width: 40upx; |
||||
|
height: 40upx; |
||||
|
} |
||||
|
>input{ |
||||
|
height: 100%; |
||||
|
flex-grow: 1; |
||||
|
@include flcw(32upx, 44upx, #1a1a1a); |
||||
|
&+image{ |
||||
|
flex-shrink: 0; |
||||
|
margin-right: 0; |
||||
|
margin-left: 20upx; |
||||
|
width: 32upx; |
||||
|
height: 32upx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.rs-ls{ |
||||
|
padding: 0 24upx; |
||||
|
} |
||||
|
</style> |
After Width: 200 | Height: 148 | Size: 7.6 KiB |
After Width: 185 | Height: 185 | Size: 3.6 KiB |
After Width: 185 | Height: 185 | Size: 4.4 KiB |
After Width: 32 | Height: 32 | Size: 369 B |
Write
Preview
Loading…
Cancel
Save
Reference in new issue