You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
400 lines
14 KiB
400 lines
14 KiB
<template>
|
|
<view class="verification-record">
|
|
<view class="vr-header">
|
|
<head-bar
|
|
:range="stadiumList" range-key="name" @change="stadiumChange"
|
|
placeholder="请选择场馆" :value="curStadium.name"
|
|
search
|
|
@click:search="toSearch"
|
|
></head-bar>
|
|
<view class="vh-tabs">
|
|
<view v-for="(e,i) in tabs" :key="i" :class="{ 'vt-item': true, active: curTab === i }" @click="curTab = i">{{ e }}</view>
|
|
</view>
|
|
</view>
|
|
<view class="vr-time-board">
|
|
<view class="vtb-time" @click="showPeriodModal">
|
|
<view class="vt-txt">{{ showPeriodStr }}</view>
|
|
<image class="vt-icon" mode="aspectFit" src="/subpackage/verification/static/images/calendar.png"></image>
|
|
</view>
|
|
<view class="vtb-num">核销数量:{{ verificationNum || 0 }}</view>
|
|
</view>
|
|
|
|
<view class="vr-list">
|
|
<block v-for="(e, i) in recordLs" :key="i">
|
|
<site-item
|
|
v-if="curTab === 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="curTab === 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="curTab === 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>
|
|
|
|
<period-select ref="periodSelect" v-model="periodStr" ></period-select>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import headBar from "../components/head_bar.vue";
|
|
import siteItem from "../components/record/site_item.vue";
|
|
import dyItem from "../components/record/dy_item.vue";
|
|
import mallItem from "../components/record/mall_item.vue";
|
|
import periodSelect from "@/components/period_select.vue";
|
|
import { formatDate, showLoad, hideLoad, showModal, showNone, debounce, formatTime, routeTo } from "@/utils/util";
|
|
import API from "../js/api.js";
|
|
import server from "../js/server.js";
|
|
export default {
|
|
components: { headBar, siteItem, dyItem, mallItem, periodSelect },
|
|
computed: {
|
|
// 展示时间段字符串
|
|
showPeriodStr(){
|
|
let { periodStr } = this;
|
|
return periodStr ? periodStr.replace(/\_/, ' 至 ').replace(/\-/g, '.') : ''
|
|
},
|
|
// 时间段对象 用于请求
|
|
periodObj(){
|
|
let { periodStr } = this;
|
|
if(!periodStr)return {};
|
|
let [start, end] = periodStr.split('_');
|
|
if(start)start += ' 00:00:00';
|
|
if(end)end += ' 23:59:59';
|
|
return {
|
|
start: start ?? '',
|
|
end: end ?? '',
|
|
}
|
|
},
|
|
},
|
|
watch: {
|
|
periodStr(nVal, oVal){
|
|
if(oVal&&nVal&&nVal !== oVal)this.refreshRecordLs();
|
|
},
|
|
curTab(nVal, oVal){
|
|
if(nVal !== oVal)this.reloadRecordLs();
|
|
}
|
|
},
|
|
data(){
|
|
return {
|
|
brand_id: '',
|
|
tabs: [ '场地核销记录', '抖音核销记录', '商城核销记录' ],
|
|
curTab: 0,
|
|
periodStr: '',/** ex: 2025-01-01_2025-01-02 */
|
|
stadiumList: [],
|
|
curStadium: {},
|
|
recordLs: [],
|
|
page: 1,
|
|
verificationNum: 0,
|
|
}
|
|
},
|
|
/**
|
|
* @param {Object} options
|
|
* @param {String} options.brand_id // 品牌id
|
|
* @param {String} options.stadium_id // 场馆id
|
|
*/
|
|
async onLoad(options){
|
|
this.brand_id = options?.brand_id ?? '';
|
|
let _stadiumLs = await this.getStadiumLs({ brand_id: options?.brand_id ?? '' });
|
|
if(options?.stadium_id&&_stadiumLs?.length){
|
|
// 设置选中场馆
|
|
let _selected = _stadiumLs.find(ele => +ele.id === +(options?.stadium_id ?? ''));
|
|
if(_selected?.id)this.curStadium = _selected;
|
|
} else if(_stadiumLs?.length){
|
|
// 售后: 只要有门店就随便默认一个是吧
|
|
this.curStadium = _stadiumLs[0];
|
|
}
|
|
this.reloadRecordLs();
|
|
},
|
|
onReachBottom(){
|
|
let { curStadium, periodObj, page, brand_id } = this;
|
|
this.getRecordLs({
|
|
brand_id: brand_id ?? '',
|
|
stadium_id: curStadium?.id ?? '',
|
|
start_time: periodObj?.start ?? '',
|
|
end_time: periodObj?.end ?? '',
|
|
page: page + 1,
|
|
});
|
|
},
|
|
methods: {
|
|
// 搜索
|
|
toSearch(){
|
|
let { brand_id, curTab } = this;
|
|
routeTo(`/subpackage/verification/pages/record_search?brand_id=${brand_id}&type=${curTab}`, 'nT');
|
|
},
|
|
// 手动离场
|
|
siteLeaveBtn: debounce(function(e, idx){
|
|
console.log(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.recordLs[idx].verify_leave_time = formatTime(new Date());
|
|
this.$forceUpdate();
|
|
}
|
|
}
|
|
})
|
|
}, 300, true),
|
|
// 初始化时间段
|
|
initPeriodStr(dayNum = 1){
|
|
let _today = new Date();
|
|
let _todayTimestamp = _today.getTime();
|
|
let _eStr = formatDate({ date: _today });
|
|
let _firstDaysTimestamp = _todayTimestamp - dayNum * 24 * 60 * 60 * 1000;
|
|
let _sStr = formatDate({ date: new Date(_firstDaysTimestamp) });
|
|
return this.periodStr = `${_sStr}_${_eStr}`;
|
|
},
|
|
showPeriodModal(){
|
|
this.$refs?.periodSelect?.show?.();
|
|
},
|
|
// 门店切换
|
|
stadiumChange(e){
|
|
let { stadiumList } = this;
|
|
let _curStadium = stadiumList?.[e?.detail?.value ?? 0] ?? {};
|
|
this.curStadium = _curStadium;
|
|
this.refreshRecordLs();
|
|
},
|
|
// 加载/ 切换订单类型
|
|
reloadRecordLs(){
|
|
let { brand_id } = this;
|
|
this.page = 1;
|
|
this.recordLs = [];
|
|
this.initPeriodStr();
|
|
let { periodObj, curStadium } = this;
|
|
this.getRecordLs({
|
|
brand_id: brand_id ?? '' ,
|
|
stadium_id: curStadium.id ?? '',
|
|
start_time: periodObj.start,
|
|
end_time: periodObj.end,
|
|
});
|
|
},
|
|
// 切换门店/时间
|
|
refreshRecordLs(){
|
|
let { curStadium, periodObj, brand_id } = this;
|
|
this.page = 1;
|
|
this.recordLs = [];
|
|
this.getRecordLs({
|
|
brand_id: brand_id ?? '',
|
|
stadium_id: curStadium?.id ?? '',
|
|
start_time: periodObj?.start ?? '',
|
|
end_time: periodObj?.end ?? '',
|
|
});
|
|
},
|
|
// 获取门店列表
|
|
getStadiumLs({ brand_id }){
|
|
showLoad();
|
|
return server.post({
|
|
url: API.stadiumList,
|
|
data: { page_size: 9999, page: 1, brand_id },
|
|
isDefaultGet: false,
|
|
})
|
|
.then(res => {
|
|
hideLoad();
|
|
let _data = res?.data || {};
|
|
if(_data.code === 0){
|
|
let _ls = _data?.data?.list || [];
|
|
return this.stadiumList = _ls;
|
|
}else{
|
|
return Promise.reject(_data);
|
|
}
|
|
})
|
|
.catch(err => {
|
|
hideLoad();
|
|
showModal({
|
|
title: '提示',
|
|
content: err.message || '加载门店失败!'
|
|
})
|
|
console.warn('verification record getStadiumLs err --->', err);
|
|
// return Promise.reject(err);
|
|
})
|
|
},
|
|
// 商家助手-核销查询列表
|
|
getRecordLs({ brand_id, stadium_id = '', start_time = '', end_time = '', page = 1, page_size = 20 }){
|
|
showLoad();
|
|
return server.post({
|
|
url: this.getRecordLsAPI(),
|
|
data: this.formatQuery({ brand_id, stadium_id, start_time, end_time, page, page_size }),
|
|
isDefaultGet: false,
|
|
})
|
|
.then(res => {
|
|
hideLoad();
|
|
let _data = res?.data || {};
|
|
if(_data.code === 0){
|
|
let _ls = this.formatRecordLs(_data?.data?.list || []);
|
|
let _total = _data?.data?.total ?? 0;
|
|
this.verificationNum = _total;
|
|
if(page === 1)return this.recordLs = _ls;
|
|
if(!_ls.length)return showNone('没有更多!');
|
|
this.page = page;
|
|
this.recordLs = [ ...this.recordLs, ..._ls ];
|
|
return _ls;
|
|
}else{
|
|
return Promise.reject(_data);
|
|
}
|
|
})
|
|
.catch(err => {
|
|
hideLoad();
|
|
showModal({
|
|
title: '提示',
|
|
content: err.message || '加载数据失败!'
|
|
})
|
|
console.warn('verification record getRecordLs err --->', err);
|
|
// return Promise.reject(err);
|
|
})
|
|
},
|
|
// 获取记录列表API
|
|
getRecordLsAPI(){
|
|
let { curTab } = this;
|
|
if(curTab === 0)return API.listVerifyRecord
|
|
if(curTab === 1)return API.dyPoiOrderList
|
|
if(curTab === 2)return API.shop2WriteoffList
|
|
},
|
|
// 格式化查询参数
|
|
formatQuery(query){
|
|
let { curTab } = this;
|
|
if(curTab === 1)query['order_status'] = 'used';
|
|
if(curTab === 2){
|
|
query['stime'] = query?.start_time ?? '';
|
|
query['etime'] = query?.end_time ?? '';
|
|
delete query.start_time
|
|
delete query.end_time
|
|
}
|
|
return query;
|
|
},
|
|
// 格式化数据
|
|
formatRecordLs(ls){
|
|
let { curTab } = this;
|
|
// 抖音
|
|
if(curTab === 1){
|
|
return ls.map(item=>{
|
|
let _code = item?.order_codes?.find(e=>e?.code_status == 'used');
|
|
console.log('_code',item);
|
|
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;
|
|
},
|
|
// 核销记录列表 - 手动离场
|
|
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 leaveVerifyOrder err --->', err);
|
|
// return Promise.reject(err);
|
|
return false;
|
|
})
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.verification-record{
|
|
@include isPd(20upx);
|
|
}
|
|
.vr-header{
|
|
background: #fff;
|
|
.vh-tabs{
|
|
@include ctf(space-around);
|
|
.vt-item{
|
|
position: relative;
|
|
@include flcw(28upx, 88upx, #2D2D2D);
|
|
&.active{
|
|
color: $mColor;
|
|
&::after{
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
height: 4upx;
|
|
background: $mColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.vr-time-board{
|
|
padding: 24upx;
|
|
@include ctf(space-between);
|
|
.vtb-time{
|
|
flex-shrink: 0;
|
|
padding: 0 14upx;
|
|
height: 62upx;
|
|
background: #fff;
|
|
@include ctf;
|
|
.vt-txt{
|
|
max-width: 400upx;
|
|
@include flcw(24upx, 34upx, #1A1A1A, 500);
|
|
@include tHide;
|
|
}
|
|
.vt-icon{
|
|
flex-shrink: 0;
|
|
margin-left: 30upx;
|
|
width: 32upx;
|
|
height: 32upx;
|
|
}
|
|
}
|
|
.vtb-num{
|
|
margin-left: 20upx;
|
|
@include flcw(32upx, 44upx, #1A1A1A, 500);
|
|
@include tHide;
|
|
}
|
|
}
|
|
.vr-list{
|
|
padding: 0 24upx;
|
|
|
|
}
|
|
</style>
|