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
-
307src/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