1.修复购物车清空已下单商品的问题

2.转桌/并桌只显示已下单商品
This commit is contained in:
gyq 2024-12-17 09:59:41 +08:00
parent 4b54fdaff1
commit 8dfa5b7aac
8 changed files with 304 additions and 15871 deletions

File diff suppressed because one or more lines are too long

View File

@ -246,3 +246,16 @@ export function orderPrint(data) {
data,
});
}
/**
* 转台/并台
* @param {*} data
* @returns
*/
export function orderSwitcht(data) {
return request({
method: "PUT",
url: "/order/switch",
data,
});
}

View File

@ -3,10 +3,12 @@
<el-drawer size="60%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0">
<div class="drawerbox_box">
<div class="drawerbox_bo_top">
<div class="drawerbox_bo_top_left">
<div class="drawerbox_bo_top_left" @click="computeExpired">
<div class="drawerbox_bo_top_left_one" style="font-size: 24px;">
{{ store.userInfo.shopName }}
</div>
<div class="tips" style="margin-top: 4px; color: var(--el-color-warning);" v-if="!showTips">注意您的账号将于{{
store.userInfo.expireDate }}后过期请尽快续期</div>
<div class="drawerbox_bo_top_left_tow" style="margin-top: 10px">
收银员{{ store.userInfo.loginAccount }}
</div>
@ -109,8 +111,21 @@ const screenref = ref(null);
const dialogVisible = ref(false);
const showTips = ref(false)
function show() {
dialogVisible.value = true;
computeExpired()
}
// 30
function computeExpired() {
//
let now = dayjs()
//
let expired = dayjs(store.userInfo.expireDate).subtract(30, 'day')
// 30
showTips.value = now.isBefore(expired)
}
//

View File

@ -16,6 +16,7 @@ export const useSocket = defineStore({
uuid: "", // 长连接唯一id
heartbeatTimer: null, // 心跳计时器
orderList: [],
log: true,
}),
actions: {
// 创建uuid
@ -33,7 +34,7 @@ export const useSocket = defineStore({
},
// 关闭ws
close() {
console.log("关闭ws");
if (this.log) console.log("关闭ws");
this.online = false;
this.ws.close(1000);
this.ws = null;
@ -57,7 +58,7 @@ export const useSocket = defineStore({
printStore.init();
if (this.ws == null) {
console.log("创建新的ws连接");
if (this.log) console.log("创建新的ws连接");
const protocols = []; // 可选的子协议数组
const options = {
@ -67,17 +68,17 @@ export const useSocket = defineStore({
};
this.ws = new ReconnectingWebSocket(wsUrl, protocols, options);
} else {
console.log("重新连接ws");
if (this.log) console.log("重新连接ws");
this.wsReconnect();
}
this.ws.addEventListener("open", (event) => {
console.log("wss连接成功");
if (this.log) console.log("wss连接成功");
this.online = true;
// 清除心跳
this.clearHeartBeat();
console.log(this);
if (this.log) console.log(this);
this.ws.send(
JSON.stringify({
@ -92,7 +93,7 @@ export const useSocket = defineStore({
this.ws.addEventListener("message", (e) => {
let data = JSON.parse(e.data);
if (data.type == "order") {
console.log("接收消息", data);
if (this.log) console.log("接收消息", data);
this.ws.send(
JSON.stringify({
type: "send",
@ -112,18 +113,18 @@ export const useSocket = defineStore({
}
}
} else if (data.type == "heartbeat") {
console.log("接收心跳");
if (this.log) console.log("接收心跳");
}
});
this.ws.addEventListener("error", () => {
console.log("WebSocket连接发生错误");
if (this.log) console.log("WebSocket连接发生错误");
this.online = false;
this.clearHeartBeat();
});
this.ws.addEventListener("error", (e) => {
console.log("ws关闭了", e);
if (this.log) console.log("ws关闭了", e);
this.online = false;
this.clearHeartBeat();
});
@ -131,7 +132,7 @@ export const useSocket = defineStore({
// 启动心跳连接
startheartbeat() {
this.heartbeatTimer = setInterval(() => {
console.log("发送心跳");
if (this.log) console.log("发送心跳");
this.ws.send(JSON.stringify({ type: "heartbeat" }));
}, 10000);
},

View File

@ -56,6 +56,13 @@
</el-icon>
<el-text class="t">挂单</el-text>
</div>
<div class="item" @click="tableMergingHandle" :class="{ disabled: !props.item.id }"
v-if="shopStore.info.registerType == 'restaurant' && props.item.tableId">
<el-icon class="icon">
<EditPen />
</el-icon>
<el-text class="t">转桌</el-text>
</div>
<div class="item" @click="props.item.id && emit('clearCart')">
<el-icon class="icon">
<RefreshRight />
@ -117,7 +124,7 @@ const props = defineProps({
default: {}
}
})
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart'])
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging'])
const takeFoodCodeRef = ref(null)
const skuModalRef = ref([])
@ -280,6 +287,14 @@ async function kitchenPrint() {
}
}
/**免厨打印 end */
//
function tableMergingHandle() {
if (props.item.id) {
emit('merging')
}
}
</script>
<style scoped lang="scss">
@ -287,7 +302,7 @@ async function kitchenPrint() {
padding: 10px;
display: flex;
flex-direction: column;
gap: 15px;
gap: 10px;
.item {
width: 70px;

View File

@ -44,7 +44,7 @@
</div>
<div class="shop_list" :class="{ img: shopListType == 'img' }" v-loading="loading">
<!-- <swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> -->
<swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange">
<swiper ref="swiperRef" :loop="false" class="swiper_box" direction="vertical" @slideChange="onSlideChange">
<swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index">
<div class="item_wrap" v-for="item in goods" :key="item.id" @click="showSkuHandle(item)">
<div class="item">
@ -225,7 +225,7 @@
<script setup>
import { ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import { onMounted, ref } from 'vue'
import { nextTick, onMounted, ref } from 'vue'
import _ from 'lodash'
import useStorage from "@/utils/useStorage";
import skuModal from '@/components/skuModal.vue'
@ -239,6 +239,8 @@ import { staffPermission } from '@/api/user.js'
import { useGlobal } from '@/store/global.js'
import { inputFilterFloat } from '@/utils/index.js'
const swiperRef = ref(null)
const global = useGlobal()
const store = useUser()
@ -594,14 +596,14 @@ async function queryCategoryAjax() {
}
//
async function productqueryCommodityInfoAjax() {
async function productqueryCommodityInfoAjax(page = goodsPage.value) {
try {
// loading.value = true
const res = await queryNewCommodityInfo({
shopId: store.userInfo.shopId,
categoryId: categorys.value[categorysActive.value].id,
commdityName: commdityName.value,
page: goodsPage.value,
page: page,
pageSize: goodsPageSize.value,
masterId: props.masterId,
tableId: global.tableInfo.qrcode || '',
@ -657,9 +659,7 @@ async function updataGoods() {
}
searchLoading.value = false
} else {
goodsPage.value = currentGoodsIndex.value + 1
// console.log('', goodsPage.value);
const res = await productqueryCommodityInfoAjax()
const res = await productqueryCommodityInfoAjax(currentGoodsIndex.value + 1)
goodsList.value[currentGoodsIndex.value] = res.list
searchLoading.value = false
}
@ -669,7 +669,6 @@ async function updataGoods() {
const onSlideChange = _.debounce(async function (e) {
if (e.activeIndex == e.previousIndex) return
if (e.activeIndex > e.previousIndex) {
// console.log('');
{
goodsPage.value++
const res = await productqueryCommodityInfoAjax()
@ -681,24 +680,19 @@ const onSlideChange = _.debounce(async function (e) {
const res = await productqueryCommodityInfoAjax()
res.list.length && goodsList.value.push(res.list)
}
// goodsList.value.shift()
} else {
// console.log('');
// goodsPage.value--
// const res = await productqueryCommodityInfoAjax()
// goodsList.value.unshift(res)
// goodsList.value.pop()
}
currentGoodsIndex.value = e.activeIndex
}, 500)
//
//
function clearDot() {
goodsList.value.map(item => {
item.map(val => {
val.orderCount = 0
})
})
// goodsList.value.map(item => {
// item.map(val => {
// val.orderCount = 0
// })
// })
updateData()
}
const showEditor = ref(false)
@ -770,6 +764,7 @@ async function showPutawayHandle(item) {
}
}
//
async function putawayHandle(item) {
try {
showPutawayLoading.value = true
@ -875,6 +870,7 @@ onMounted(async () => {
getUnitListAjax()
await updateCategoryActive()
await queryCategoryAjax()
updataGoods()
})
</script>

View File

@ -0,0 +1,203 @@
<!-- 合并/转桌 -->
<template>
<el-dialog title="转桌/并桌" width="700px" v-model="visible" @closed="onClose" top="10vh">
<div class="scroll_y">
<el-form :model="form" ref="formRef" :rules="rules" label-position="top">
<el-form-item label="转入台桌" prop="targetTableId">
<el-select v-model="form.targetTableId" style="width: 200px;" placeholder="请选择目标台桌">
<el-option :label="item.name" :value="item.qrcode" v-for="item in tableList"
:key="item.qrcode"></el-option>
</el-select>
</el-form-item>
<el-form-item label="转入类型">
<el-radio-group v-model="form.isFull">
<el-radio :value="false" border>转桌可将部分商品转入</el-radio>
<el-radio :value="true" border>并桌并台会将全部购物车商品转入</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="转入商品" prop="cartIds" v-if="!form.isFull">
<div v-for="item in props.data" style="width: 100%;">
<div>{{ `${item.placeNum}次下单` }}</div>
<el-table ref="tableRefs" :data="item.info" border>
<el-table-column type="selection" align="center" width="50px"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="数量" prop="number"></el-table-column>
<el-table-column label="规格" prop="skuName"></el-table-column>
<el-table-column label="价格" prop="salePrice"></el-table-column>
</el-table>
</div>
</el-form-item>
</el-form>
</div>
<div class="footer" style="display: flex;">
<el-button style="width: 100%" @click="visible = false">
取消
</el-button>
<el-button type="primary" style="width: 100%" :loading="loading" @click="confirmHandle">
确认
</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { queryShopTable } from '@/api/table.js'
import { orderSwitcht } from '@/api/product.js'
import { useUser } from "@/store/user.js"
import { useGlobal } from '@/store/global.js'
import { ElMessage } from 'element-plus'
const store = useUser()
const global = useGlobal()
const visible = ref(false)
const props = reactive({
data: []
})
const emits = defineEmits(['success'])
const tableRefs = ref([])
const list = ref([])
const loading = ref(false)
const formRef = ref(null)
const resetForm = ref({})
const form = ref({
shopId: store.userInfo.shopId,
masterId: '',
orderId: '',
cartIds: [],
isFull: false,
currentTableId: '',
targetTableId: '',
})
const rules = ref({
targetTableId: [
{
required: true,
message: ' ',
trigger: 'change',
}
],
cartIds: [
{
required: true,
validator: (rule, value, callback) => {
let arr = []
props.data.map((item, index) => {
arr.push(...tableRefs.value[index].getSelectionRows())
})
if (!arr.length) {
ElMessage.error('至少选择一个商品')
callback(new Error('至少选择一个商品'))
} else {
callback()
}
},
trigger: 'blur',
}
]
})
const tableList = ref([])
//
async function queryShopTableAjax() {
try {
const res = await queryShopTable({
shopId: store.userInfo.shopId,
areaId: '',
status: '',
page: 1,
pageSize: 100
})
tableList.value = res.list.filter(item => item.qrcode != props.data[0].info[0].tableId && item.status == 'using')
} catch (error) {
console.log(error)
}
}
//
function confirmHandle() {
formRef.value.validate(async valid => {
try {
if (valid) {
loading.value = true
form.value.masterId = props.data[0].info[0].masterId
form.value.orderId = props.data[0].info[0].orderId
form.value.currentTableId = props.data[0].info[0].tableId
if (!form.value.isFull) {
let arr = []
props.data.map((item, index) => {
arr.push(...tableRefs.value[index].getSelectionRows())
})
form.value.cartIds = arr.map(item => item.id)
}
await orderSwitcht(form.value)
loading.value = false
//
global.setOrderTable(tableList.value.find(item => item.qrcode == form.value.targetTableId))
visible.value = false
emits('success', { isTemporary: true })
}
} catch (error) {
loading.value = false
console.log(error);
}
})
}
function onClose() {
form.value = { ...resetForm.value }
formRef.value.resetFields()
}
function show(data) {
props.data = data
visible.value = true
queryShopTableAjax()
}
defineExpose({
show
})
onMounted(() => {
resetForm.value = { ...form.value }
})
</script>
<style scoped lang="scss">
$btmH: 50px;
.scroll_y {
height: 50vh;
overflow-y: auto;
padding-bottom: $btmH;
}
.footer {
position: relative;
&::before {
content: "";
height: $btmH;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
width: 100%;
position: absolute;
top: $btmH*-1;
left: 0;
z-index: 10;
}
}
</style>

View File

@ -97,7 +97,7 @@
</div>
<!-- 购物车操作栏 -->
<cartOperation :item="cartListActiveItem" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle"
@pending="pendingCart" @clearCart="clearCartHandle" />
@pending="pendingCart" @clearCart="clearCartHandle" @merging="showTableMerging" />
</div>
<div class="footer">
<div class="top">
@ -165,6 +165,8 @@
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
<!-- 检查版本升级 -->
<updateDialog />
<!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="addCart" />
</template>
<script>
@ -185,6 +187,7 @@ import cartOperation from "@/views/home/components/cartOperation.vue";
import settleAccount from "@/views/home/components/settleAccount.vue";
import fastCashier from "@/views/home/components/fastCashier.vue";
import pendingCartModal from "@/views/home/components/pendingCartModal.vue";
import tableMerging from '@/views/home/components/tableMerging.vue'
import useStorage from '@/utils/useStorage'
import { formatDecimal } from '@/utils/index.js'
@ -209,6 +212,7 @@ import member from "@/views/member/index.vue";
import { ElMessage } from "element-plus";
import { useShop } from '@/store/shop.js'
import TableMerging from "./components/tableMerging.vue";
const shopStore = useShop()
@ -224,6 +228,7 @@ const goodsRef = ref(null);
const pendingCartModalRef = ref(null);
const settleAccountRef = ref(null);
const fastCashierRef = ref(null);
const tableMergingRef = ref(null)
const allSelected = ref(false);
@ -493,7 +498,7 @@ async function queryCartAjax() {
cartInfo.value = res.amount;
pendingCartNum.value = res.num;
goodsRef.value.updateData();
// goodsRef.value.updateData();
let i = 0;
res.list.map((item) => {
@ -568,6 +573,12 @@ function clearMember() {
createCodeAjax()
}
// /
function showTableMerging() {
let data = cartList.value.filter(item => item.placeNum)
tableMergingRef.value.show(data)
}
onMounted(() => {
createCodeAjax()
shopStore.queryShopInfo()