Files
management/src/views/table/table_list.vue
2024-10-21 11:05:46 +08:00

639 lines
17 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>
<div class="app-container">
<el-tabs v-model="tabVlaue" type="card" @tab-click="tabClick">
<el-tab-pane label="全部" name=""></el-tab-pane>
<el-tab-pane
v-for="item in tabs"
:key="item.id"
:label="item.name"
:name="`${item.id}`"
>
<div slot="label">
{{ item.name }}
<i
class="icon el-icon-edit"
@click.stop="$refs.addEara.show(item)"
></i>
<el-popconfirm title="确定删除吗?" @confirm="delHandle([item.id])">
<i class="icon el-icon-delete" slot="reference" @click.stop=""></i>
</el-popconfirm>
</div>
</el-tab-pane>
</el-tabs>
<div class="head-container">
<div class="filter_wrap">
<el-button icon="el-icon-plus" @click="$refs.addEara.show()"
>添加区域</el-button
>
<el-button
type="primary"
icon="el-icon-plus"
@click="$refs.addTable.show()"
>添加台桌</el-button
>
<el-button
type="primary"
icon="el-icon-download"
@click="$refs.downloadTableCode.show()"
>
下载台桌码
</el-button>
<el-button
type="primary"
icon="el-icon-download"
@click="downloadShopCode"
>下载店铺码</el-button
>
</div>
</div>
<div class="u-flex u-p-b-15 u-font-14">
<div class="state u-m-r-24" v-for="(item, key) in status" :key="key">
<span
class="dot"
:style="{
backgroundColor: status[key] ? status[key].type : '',
}"
></span>
{{ item.label }}
</div>
</div>
<div class="head-container">
<div class="table_list" v-loading="loading">
<div
class="item"
v-for="item in tableList"
:key="item.id"
:style="{ 'background-color': status[item.status].type }"
>
<div class="new-top flex u-row-between">
<div class="u-flex u-flex-1 u-p-r-10">
<span class="name u-line-1" style="max-width: 50px">
{{ item.name }}</span
>
<span class="u-font-14 u-line-1"
>{{ areaMap[item.areaId] || "" }}</span
>
</div>
<el-dropdown trigger="click" @command="tableComman($event, item)">
<i class="el-icon-more cur-pointer color-fff"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="edit">
<i class="i el-icon-edit"></i>
<span>编辑</span>
</el-dropdown-item>
<el-dropdown-item command="del">
<i class="i el-icon-delete"></i>
<span>删除</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="box">
<div class="top">
<!-- <div class="row row1">
<span>{{ item.name }}</span>
<div class="state">
<span
class="dot"
:style="{
backgroundColor: status[item.status]
? status[item.status].type
: '',
}"
></span>
{{ status[item.status] ? status[item.status].label : "" }}
</div>
</div> -->
<!-- <div class="row">
<el-tag type="warning" size="mini">{{
item.type == 0 ? "低消" : "计时"
}}</el-tag>
<el-tag :type="item.isPredate == 1 ? '' : 'info'" size="mini">{{
item.isPredate == 1 ? "可预约" : "不可预约"
}}</el-tag>
</div> -->
<!-- <div class="row">
<span class="tips">客座次数{{ item.maxCapacity }}</span>
</div> -->
<div class="u-font-18 font-600 total-price">
<span
class="cur-pointer"
v-if="item.status == 'using'"
@click="diancanShow(item, 'isAddGoods')"
>
¥{{ item.totalAmount || 0 }}{{ item.productNum }}
</span>
<span class="color-fff" v-else>|</span>
</div>
<div class="row btn-group">
<template v-if="item.status == 'idle'">
<el-button
type="primary"
:disabled="!item.tableId || item.status === 'closed'"
@click="diancanShow(item)"
>点餐</el-button
>
</template>
<template v-else>
<template v-if="item.status == 'using'">
<el-button
:disabled="!item.tableId || item.status === 'closed'"
@click="diancanShow(item, 'isAddGoods')"
>加菜</el-button
>
<el-button
type="danger"
:disabled="!item.tableId || item.status === 'closed'"
@click="diancanShow(item, 'isPayOrder')"
>结账</el-button
>
</template>
<template v-else-if="item.status == 'closed'">
<el-button type="info" disabled>已关台</el-button>
</template>
<template v-else-if="item.status == 'cleaning'">
<el-button
type="info"
@click="cleanTableHandle(item)"
:style="{
backgroundColor: status[item.status].type,
borderColor: status[item.status].type,
}"
>清台</el-button
>
</template>
<template v-else>
<el-button type="info" disabled>点餐</el-button>
</template>
</template>
</div>
</div>
<div
class="u-flex u-col-bottom bottom u-row-between color-666"
:class="{ 'opacity-0': item.status == 'closed' }"
>
<div class="u-flex u-col-center">
<img
style="width: 16px; height: 16px; filter: contrast(0.5)"
src="@/assets/images/perpole.png"
alt=""
/>
<span class="u-m-t-4 u-font-12 u-m-l-2"
>{{ item.useNum || 0 }}/{{ item.maxCapacity }}</span
>
</div>
<div class="u-flex" v-if="item.status == 'using'">
<img
style="width: 16px; height: 16px; filter: contrast(0.5)"
src="@/assets/images/shalou.png"
alt=""
/>
<span class="u-m-t-4 u-font-12">{{
item.durationTime | formatTime
}}</span>
</div>
</div>
</div>
</div>
<div class="empty_wrap">
<el-empty description="空空如也~" v-if="!tableList.length"></el-empty>
</div>
</div>
</div>
<addEara ref="addEara" @success="tbShopAreaGet" />
<!-- 批量添加台桌 -->
<addTable ref="addTable" @success="tbShopTableGet" />
<!-- 编辑台桌 -->
<table-edit ref="editTable" @success="tbShopTableGet"></table-edit>
<downloadTableCode :total="total" ref="downloadTableCode" />
<!-- 点餐 -->
<!-- <table-diancan ref="diancan" @close="onDiancanClose"></table-diancan> -->
<!-- 选择人数 -->
<choose-diners-number
ref="refChooseDinersNumber"
:max="selTable.maxCapacity"
@confirm="chooseDinersNumberConfirm"
></choose-diners-number>
</div>
</template>
<script>
import addEara from "./components/addEara";
import addTable from "./components/addTable";
import tableEdit from "./components/table-edit";
import downloadTableCode from "./components/downloadTableCode";
import tableDiancan from "./components/table-diancan.vue";
import $status from "./status.js";
import chooseDinersNumber from "./components/table-diancan-components/choose-diners-number.vue";
import { tbShopInfo } from "@/api/user";
import { hasPermission } from "@/utils/limits.js";
import {
tbShopTableGet,
tbShopAreaGet,
tbShopAreaDelete,
tbShopTableDelete,
tbShopTable,
} from "@/api/table";
import dayjs from "dayjs";
import { downloadFile } from "@/utils/index";
export default {
components: {
addEara,
addTable,
downloadTableCode,
tableDiancan,
chooseDinersNumber,
tableEdit,
},
data() {
return {
tabVlaue: "",
tabs: [],
loading: false,
total: 0,
tableList: [],
status: $status,
selTable: "", //当前选中的桌台
areaMap: {},
shopInfo: {},
timer: null,
};
},
beforeDestroy() {
this.clearTimer();
console.log("beforeDestroy");
},
mounted() {
this.clearTimer();
this.setTimter(60);
this.tbShopAreaGet();
this.getShopInfo();
},
filters: {
formatTime(milliseconds) {
console.log(milliseconds);
if (!milliseconds) {
return "";
}
const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor(
(milliseconds % (1000 * 60 * 60)) / (1000 * 60)
);
return `${days ? days + "天" : ""} ${hours ? hours + "时" : ""} ${
minutes + "分"
}`;
},
},
methods: {
async downloadShopCode() {
try {
const link = document.createElement("a");
link.href = this.shopInfo.smallQrcode;
const fileName = this.shopInfo.shopName +"店铺码"+ ".png";
console.log(fileName)
link.setAttribute("download", fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success("下载成功");
} catch (error) {
console.log(error);
}
},
clearTimer() {
console.log("clearTimer");
clearInterval(this.timer);
this.timer = null;
},
setTimter(time = 60) {
this.timer = setInterval(() => {
const showloading = false;
this.tbShopTableGet(showloading);
}, time * 1000);
},
//获取店铺信息
async getShopInfo() {
try {
const shopId = localStorage.getItem("shopId");
const res = await tbShopInfo(shopId);
this.shopInfo = res;
console.log(res);
} catch (error) {}
},
// 清台
cleanTableHandle(item) {
this.$confirm("确定要清台:" + item.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
tbShopTable(
{
...item,
status: "idle",
qrcode: item.tableId,
shopId: localStorage.getItem("shopId"),
},
"put"
).then((res) => {
this.tbShopTableGet();
});
});
},
tableComman(command, item) {
if (command == "edit") {
return this.$refs.editTable.show(item);
}
if (command == "del") {
return this.delPop(item);
}
},
delPop(item) {
this.$confirm("是否删除" + item.name + "台桌", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.delTableHandle([item.id]);
})
.catch(() => {});
},
onDiancanClose() {
this.tbShopTableGet();
},
async diancanShow(item, key) {
if(key=='isPayOrder'){
const canShoukuan=await hasPermission('允许收款')
if(!canShoukuan){
return
}
}
const canXiadan=await hasPermission('允许下单')
if(!canXiadan){
return
}
//key isAddGoods 加菜
//key isPayOrder 结账
this.selTable = item;
if (this.shopInfo.isTableFee) {
//免餐位费
this.toInstead({ num: 0, key });
// this.$refs.diancan.open(item, key, '');
return;
}
const num = item.useNum || 0;
if (item.useNum <= 0) {
return this.$refs.refChooseDinersNumber.open();
}
this.toInstead({ num: num, key });
// this.$refs.diancan.open(item, key, num);
},
toInstead(query) {
this.$router.push({
path: "/tool/Instead/index",
query: {
table_name: this.selTable.name,
tableId: this.selTable.tableId,
useType: this.selTable.useType,
maxCapacity: this.selTable.maxCapacity,
masterId: this.selTable.masterId,
orderId: this.selTable.orderId,
...query,
},
});
},
chooseDinersNumberConfirm(num) {
this.toInstead({ num: num });
// this.$refs.diancan.open(this.selTable, undefined, num);
},
tabClick() {
this.tbShopTableGet();
},
// 删除桌台
async delTableHandle(ids) {
try {
await tbShopTableDelete(ids);
this.tbShopTableGet();
} catch (error) {
console.log(error);
}
},
// 删除区域
async delHandle(ids) {
try {
await tbShopAreaDelete(ids);
this.tabVlaue = "";
this.tbShopAreaGet();
} catch (error) {
console.log(error);
}
},
// 台桌列表
async tbShopTableGet(showloading = true) {
this.loading = showloading;
try {
const { content, total } = await tbShopTableGet({
shopId: localStorage.getItem("shopId"),
areaId: this.tabVlaue,
});
this.tableList = content;
// this.tableList = content.sort((a,b)=>{
// if(a.status=='idle'&&b.status!='idle'){
// return 1
// }else if(a.status!='idle'&&b.status=='idle'){
// return -1
// }
// });
this.total = total;
setTimeout(() => {
this.loading = false;
}, 300);
} catch (error) {
this.loading = false;
console.log(error);
}
},
// 获取区域
async tbShopAreaGet() {
try {
const { content } = await tbShopAreaGet({
shopId: localStorage.getItem("shopId"),
});
this.tabs = content;
this.areaMap = content.reduce((prve, cur) => {
prve[cur.id] = cur.name;
return prve;
}, {});
this.tbShopTableGet();
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style>
.el-tabs {
margin-bottom: 0;
}
</style>
<style scoped lang="scss">
.cur-pointer {
cursor: pointer;
}
.opacity-0 {
opacity: 0;
}
.icon {
margin-left: 10px;
}
::v-deep .btn-group .el-button {
width: 100%;
}
::v-deep .el-dropdown-menu__item {
line-height: 36px;
padding: 0 20px;
min-width: 60px;
text-align: center;
}
.state {
display: flex;
align-items: center;
.dot {
$size: 8px;
width: $size;
height: $size;
border-radius: 50%;
margin-right: $size;
}
}
.table_list {
display: flex;
flex-wrap: wrap;
gap: 20px;
min-height: 150px;
.empty_wrap {
flex: 1;
display: flex;
justify-content: center;
}
.btn-group {
display: flex;
gap: 10px;
}
.item {
padding: 1px;
overflow: hidden;
border: 1px solid #ddd;
display: flex;
flex-direction: column;
justify-content: space-between;
border-radius: 6px;
background-color: #1890ff;
max-width: 172px;
min-width: 160px;
&.using {
background-color: rgb(250, 85, 85);
}
&.closed {
background-color: rgb(221, 221, 221);
filter: grayscale(1);
}
.total-price {
line-height: 35px;
height: 35px;
&:hover {
text-decoration: underline;
}
}
.new-top {
height: 30px;
color: #fff;
padding: 0 12px;
}
.name {
font-size: 16px;
line-height: 30px;
margin-right: 10px;
overflow: hidden;
text-overflow: ellipsis;
}
.box {
background-color: #fff;
border-radius: 3px 3px 6px 6px;
}
.bottom {
border-top: 1px solid #f7f7fa;
padding: 6px 15px;
}
.top {
padding: 10px;
background-color: #fff;
flex: 1;
border-radius: 3px 3px 0 0;
.row {
display: flex;
gap: 10px;
.tips {
font-size: 12px;
}
&.row1 {
justify-content: space-between;
font-size: 14px;
}
}
}
.btm {
border-top: 1px solid #ddd;
background-color: #efefef;
display: flex;
border-radius: 0 0 6px 6px;
.btm_item {
flex: 1;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&:hover {
cursor: pointer;
}
&:nth-child(1) {
&::before {
content: "";
height: 50%;
border-right: 1px solid #ddd;
position: absolute;
top: 25%;
right: 0;
}
}
.i {
color: #666;
}
}
}
}
}
</style>