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

<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>