cashier_app/pageTable/index/index.vue

666 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="color-333 u-font-28 min-page bg-gray ">
<!-- <view class="fixed-top bg-fff u-flex u-p-l-30 u-row-between">
<view class="u-flex u-flex-1 u-row-between">
<view class="u-flex u-p-t-30 u-p-b-30 u-flex-1 u-row-center" @tap="showsTimesToggle">
<text class="u-m-r-12">{{times.list[times.active]}}</text>
<image src="/pageTable/static/images/icon-arrow-down-fill.svg" class="icon-arrow-down-fill" mode="">
</image>
</view>
<view class="u-flex u-p-t-30 u-p-b-30 u-flex-1 u-row-center" @tap="showstatusToggle">
<text class="u-m-r-12"
:class="{'color-main':status.active!=0}">{{status.list[status.active].label }}</text>
<image src="/pageTable/static/images/icon-arrow-down-fill.svg" class="icon-arrow-down-fill" mode="">
</image>
</view>
</view>
<view style="width: 164rpx;"></view>
<view class="search-box">
<view class="search-btn u-flex" @tap="showSearch" :style="{width:search.show?'694rpx':'164rpx'}">
<image src="@/static/iconImg/icon-search.svg" class="input-icon" />
<view class="u-flex-1 u-p-l-10">
<input v-model="search.keyword" @confirm="searchConfirm" type="text"
placeholder-style="font-size:28rpx;" placeholder="搜索" />
</view>
<view @tap.stop="clearSearch" v-if="search.show">取消</view>
</view>
</view>
<view :style="{height:times.show?timesHeight:0}" class="tranistion status overflow-hide">
<view @tap="changeTimesActive(index)" class="u-flex u-p-l-30 lh30 u-p-r-30 u-row-between"
v-for="(item,index) in times.list" :key="index">
<view>{{item}}</view>
<uni-icons v-if="times.active===index" type="checkmarkempty" :color="color.ColorMain"></uni-icons>
</view>
<view :style="{height: status.bottomHeight+'px'}"></view>
</view>
<view :style="{height:status.show?statusHeight:0}" class="tranistion status overflow-hide">
<view @tap="changestatusActive(index,item)" class="u-flex u-p-l-30 lh30 u-p-r-30 u-row-between"
v-for="(item,index) in status.list" :key="index">
<view>{{item.label}}</view>
<uni-icons v-if="status.active===index" type="checkmarkempty" :color="color.ColorMain"></uni-icons>
</view>
<view :style="{height: status.bottomHeight+'px'}"></view>
</view>
</view> -->
<up-sticky>
<view class="bg-fff u-p-l-30 u-p-b-30 u-relative">
<!-- <view class="myTabs ">
<myTabs :list="tabsList" @change="tabsChange"></myTabs>
</view> -->
<view class="input-wrapper">
<view class="input-main">
<view class="u-flex u-p-r-30 u-font-28" @click="showstatusToggle">
<text class="u-m-r-10 u-line-1" :class="{'color-main':status.active!=0}"
style="max-width: 100rpx;">{{status.list[status.active].label }}</text>
<up-icon name="arrow-down" size="16"></up-icon>
</view>
<uni-easyinput clearable class='jeepay-search' :inputBorder="false"
trim="all"
placeholder="搜索" v-model="search.keyword"
@clear="searchConfirm"
@confirm="searchConfirm">
<template #prefixIcon>
<image src="@/static/iconImg/icon-search.svg" class="input-icon" />
</template>
</uni-easyinput>
<view class="u-m-l-4">
<button class="" type="text" @click="searchConfirm"> <text class="color-333">搜索</text></button>
</view>
</view>
</view>
<view :style="{height:status.show?statusHeight:0}" class="tranistion status overflow-hide">
<view @tap="changestatusActive(index,item)" class="u-flex u-p-l-30 lh30 u-p-r-30 u-row-between"
v-for="(item,index) in status.list" :key="index">
<view>{{item.label}}</view>
<uni-icons v-if="status.active===index" type="checkmarkempty" :color="color.ColorMain"></uni-icons>
</view>
<view :style="{height: status.bottomHeight+'px'}"></view>
</view>
</view>
</up-sticky>
<view class="list u-p-30">
<view class="my-bg-main table-type u-flex border-r-12 color-fff ">
<view class="item u-p-20" :class="{sel:tables.area.sel===item.id}" @tap="changeAreaSel(item)"
v-for="(item,index) in tables.area.list" :key="index">
<view class="box">
<view>{{item.name}}</view>
<view class="u-m-t-10">0/12</view>
</view>
</view>
</view>
<view class="u-m-t-30 ">
<template v-if="tables.list.length">
<view class="u-flex u-flex-wrap u-row-between">
<view class="u-m-b-30" v-for="(item,index) in tables.list" :key="index">
<table-item @bind="unBind" @update="getTable" :areaMap="areaMap" @more="moreShow(item)" :data="item"></table-item>
</view>
</view>
<my-pagination :page="query.page" :totalElements="query.totalElements" :size="query.size"
@change="pageChange"></my-pagination>
</template>
<my-img-empty v-if="tables.hasAjax&&!tables.list.length" tips="未找到相关桌台"></my-img-empty>
</view>
</view>
</view>
<my-action-sheet :active="4" @itemClick="actionSheetClick" ref="refMoreSheet" :list="actionSheet.list"
:title="actionSheet.title">
<template #title>
<view class="color-999 u-p-30 u-text-center border-bottom">桌号:{{actionSheet.title}}</view>
</template>
</my-action-sheet>
<my-mask ref="mask" @close="hideType"></my-mask>
<add-table ref="refTable" @update="tableUpdate"></add-table>
</template>
<script setup>
import {
$status
} from '@/commons/table-status.js'
import {
$table,
$tableArea,
$bind
} from '@/http/yskApi/table.js'
import {
objToArrary
} from '@/commons/utils/returrn-data.js'
import {
onLoad,
onReady,
onHide,
onShow,
onPageScroll,
onPullDownRefresh
} from '@dcloudio/uni-app';
import color from '@/commons/color';
import go from '@/commons/utils/go.js';
import myMask from '@/components/my-components/my-mask'
import addTable from './components/add-table'
import myActionSheet from '@/components/my-components/my-action-sheet';
import tableItem from './components/table-item'
import * as $fun from './util.js'
import {
ref,
reactive,
computed,
onBeforeUnmount,
watch
} from 'vue';
import infoBox from '@/commons/utils/infoBox.js'
import {hasPermission} from '@/commons/utils/hasPermission.js'
const refMoreSheet = ref(null)
const actionSheet = reactive({
list: ['结账', '清台', '增减菜', '换台', '打印订单', '历史订单','绑定码牌'],
title: '',
selTable: ''
})
function moreShow(table) {
actionSheet.title = table.name
actionSheet.selTable = table
refMoreSheet.value.open()
}
function toPay(item) {
go.to('PAGES_ORDER_PAY', {
tableId: item.tableId,
tableName: item.name,
masterId: item.masterId,
orderId: item.orderId,
discount: 1,
userId:item.userId
})
}
async function actionSheetClick(index) {
console.log(index);
const item = actionSheet.selTable
//编辑
// refTableShow()
if (index == 0) {
if (!item.orderId) {
return infoBox.showToast('该桌台暂无要结账的订单!')
}
const canJieZhang=await hasPermission('允许收款')
if(!canJieZhang){
return
}
return toPay(item)
}
if (index == 1) {
//清台
return uni.showModal({
title: '提示',
content: '确定要清台:' + item.name + '',
success(res) {
if (res.confirm) {
$table.update({
...item,
status: "idle",
qrcode: item.tableId,
}).then(res => {
infoBox.showToast('清台成功')
tableUpdate()
})
}
}
})
}
if (index == 2) {
return infoBox.showToast('待开放,请敬请期待!')
}
if (index == 3) {
return infoBox.showToast('待开放,请敬请期待!')
}
if (index == 4) {
//打印订单
const res = await $fun.printOrder(actionSheet.selTable.tableId)
return
}
if (index == 6) {
//打印订单
scanCode(item)
// const res = await $fun.printOrder(actionSheet.selTable.tableId)
return
}
infoBox.showToast('待开放,请敬请期待!')
}
function unBind (item) {
scanCode(item)
}
function scanCode(item) {
if ( item.status != 'unbind') {
infoBox.showToast('当前桌台已绑定')
return;
}
uni.scanCode({
onlyFromCamera: true,
success: function(res) {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
let params = getQueryString(res.result);
$bind({
"code": params.code,
"id": item.id,
}).then(res => {
getTable()
})
}
});
}
function getQueryString(url) { //解码
let params = {};
// 正则表达式来匹配URL中的查询字符串
let reg = /(?:\?|#|&){1}([^=]*)=([^&]*)/g;
url.replace(reg, (match, key, value) => {
params[key] = value;
});
return params;
}
const refTable = ref(null)
function refTableShow() {
refTable.value.open(actionSheet.selTable)
}
function refTableClose() {
refTable.value.close()
}
const search = reactive({
keyword: '',
show: false
})
function searchConfirm() {
hideSearch()
query.page=1;
getTable()
// tables.list = tables.originList.filter((v) =>
// v.name.includes(search.keyword.trim())
// );
}
function clearSearch(){
search.keyword=''
hideSearch()
}
function hideSearch() {
search.show = false
maskHide()
}
function showSearch() {
search.show = true
status.show = false
times.show = false
maskShow()
}
const page = reactive({
list: [1, 2],
status: 'noMore'
})
function showsTimesToggle() {
times.show = !times.show
search.show = false
status.show = false
if (times.show) {
maskShow()
} else {
maskHide()
}
}
const times = reactive({
list: [10, 15, 20, 30],
active: 0,
show: false,
bottomHeight: 14
})
const timesHeight = computed(() => {
return 30 * times.list.length + times.bottomHeight + 'px'
})
function changeTimesActive(i) {
times.active = i
search.show = false
times.show = false
status.show = false
maskHide()
}
const statusList = objToArrary($status)
statusList.unshift({
key: 'all',
label: '全部'
})
const status = reactive({
list: statusList,
active: 0,
show: false,
bottomHeight: 14
})
function hideType() {
status.show = false
search.show = false
times.show = false
}
const statusHeight = computed(() => {
return 30 * status.list.length + status.bottomHeight + 'px'
})
function changestatusActive(i) {
status.active = i
status.show = false
toggleMask()
}
function showstatusToggle() {
status.show = !status.show
search.show = false
times.show = false
if (status.show) {
maskShow()
} else {
maskHide()
}
}
const filters = reactive({
time: {
start: '',
end: ''
}
})
function clearTime() {
filters.time.start = ''
filters.time.end = ''
}
const datePicker = ref(null)
function datePickerConfirm(e) {
console.log(e);
filters.time.start = e.start
filters.time.end = e.end
}
function timeToggle() {
datePicker.value.toggle()
}
const mask = ref(null)
function toggleMask(show) {
mask.value.toggle()
}
function maskShow() {
mask.value.open()
}
function maskHide() {
mask.value.close()
}
const query = reactive({
page: 1,
size: 10,
areaId: 0,
totalElements:0
})
// 页数改变事件
function pageChange(page) {
console.log(page);
query.page = page
getTable()
}
const tables = reactive({
hasAjax: false,
originList: [],
list: [],
area: {
list: [],
sel: ''
}
})
function changeAreaSel(item) {
tables.area.sel = item.id
query.areaId = item.id
}
async function getTable() {
let state=status.list[status.active].key
state=state?(state=='all'?'':state):''
const {
content,total
} = await $table.get({...query,name:search.keyword,state})
tables.hasAjax = true
query.totalElements=total||0
tables.list = content
}
const areaMap = ref({})
async function getArea() {
const {
content
} = await $tableArea.get({
page: 0,
size: 300
})
tables.area.list = content
areaMap.value = content.reduce((prve, cur) => {
prve[cur.id] = cur.name
return prve
}, {})
}
watch(() => tables.area.sel, (newval) => {
console.log(newval);
query.page = 1
getTable()
})
watch(() => status.active, (newval) => {
query.page = 1
// if (newval === 0) {
// return tables.list = tables.originList
// }
// tables.list = tables.originList.filter((v) => {
// return v.status == status.list[status.active].key
// });
getTable()
})
watch(() => times.active, (newval) => {
setTimer()
})
function tableUpdate() {
query.page = 0
getTable()
}
let timer = null
function getData() {
getTable()
getArea()
}
function setTimer() {
clearInterval(timer)
getData()
// timer = setInterval(() => {
// getData()
// }, times.list[times.active] * 1000)
}
watch(() => times.active, (newval) => {
setTimer()
})
onBeforeUnmount(() => {
console.log('table page onBeforeUnmount');
clearInterval(timer)
})
onHide(() => {
console.log('table page hide');
clearInterval(timer)
})
onShow(opt => {
setTimer()
})
</script>
<style lang="scss" scoped>
.fixed-top {
z-index: 10;
}
.input-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 26rpx;
background-color: $J-bg-ff;
.input-main {
flex: 1;
display: flex;
align-items: center;
height: 64rpx;
image {
padding: 22rpx;
width: 26rpx;
height: 26rpx;
}
input {
flex: 1;
font-size: 27rpx;
}
::v-deep uni-button {
font-size: 28rpx;
color: $my-main-color;
background: rgba(255, 255, 255, 1);
}
::v-deep.uni-easyinput {
.uni-easyinput__content {
background-color: $J-bg-f5 !important;
border-radius: $J-b-r12;
.uni-easyinput__content-input {
padding-left: 0 !important;
.uni-input-input {
border-radius: $J-b-r12 !important;
overflow: hidden !important;
}
}
.uni-input-placeholder {
font-size: 27rpx;
}
.uni-icons {
color: rgba(230, 230, 230, 1) !important;
}
}
}
}
}
.table-type {
flex-wrap: wrap;
padding: 0 10rpx 0 10rpx;
.item {
width: 25%;
margin-bottom: 10rpx;
.box {
position: relative;
padding: 10rpx;
border-radius: 10rpx;
&::after {
position: absolute;
display: block;
content: '';
top: 0;
bottom: 0;
width: 2px;
border-radius: 2px;
right: -20rpx;
background-color: rgba(255, 255, 255, .5);
}
}
&:nth-of-type(4n) {
.box::after {
background-color: transparent;
}
}
&.sel {
.box {
background-color: rgba(255, 255, 255, .6);
}
}
}
}
.search-box {
background-color: #fff;
padding: 16rpx 0;
display: flex;
.search-btn {
padding: 0 30rpx;
box-sizing: border-box;
display: flex;
align-items: center;
// width: 164rpx;
transition: all .3s ease-in-out;
background-color: rgb(247, 247, 247);
border-radius: 100px;
}
}
.status {
position: absolute;
top: 100%;
left: 0;
right: 0;
z-index: 10;
background-color: #fff;
}
.icon-arrow-down-fill {
width: 16rpx;
height: 10rpx;
}
.list {
// margin-top: 52px;
}
</style>