feat: 增加代课下单收到商品信息变动时重新获取商品信息初始化购物车数据

This commit is contained in:
YeMingfei666 2025-03-18 14:03:07 +08:00
parent cefabae276
commit 735b325fd3
7 changed files with 274 additions and 73 deletions

View File

@ -3,6 +3,7 @@ import WebSocketManager, { type ApifoxModel, msgType } from "@/utils/websocket";
import orderApi from "@/api/order/order"; import orderApi from "@/api/order/order";
import { useUserStoreHook } from "@/store/modules/user"; import { useUserStoreHook } from "@/store/modules/user";
import { customTruncateToTwoDecimals } from '@/utils/tools' import { customTruncateToTwoDecimals } from '@/utils/tools'
import productApi from "@/api/product/index";
const shopUser = useUserStoreHook(); const shopUser = useUserStoreHook();
export interface CartsState { export interface CartsState {
@ -43,6 +44,24 @@ export const useCartsStore = defineStore("carts", () => {
//代客下单页面商品缓存 //代客下单页面商品缓存
const goods = useStorage<any[]>("Instead_goods", []); const goods = useStorage<any[]>("Instead_goods", []);
async function getGoods(query: any) {
const res = await productApi.getPage({
page: 1,
size: 999,
status: "on_sale",
...query,
});
goods.value = res.records;
setGoodsMap(goods.value)
}
function setGoodsMap(goods: any[]) {
for (let item of goods) {
goodsMap[item.id] = item;
}
}
//赠菜 //赠菜
const giftList = useStorage<any[]>("giftList", []); const giftList = useStorage<any[]>("giftList", []);
let goodsMap: { [key: string]: any } = useStorage('Instead_goods_map', {}); let goodsMap: { [key: string]: any } = useStorage('Instead_goods_map', {});
@ -326,8 +345,10 @@ export const useCartsStore = defineStore("carts", () => {
} }
// 换桌 // 换桌
function changeTable(newVal: string | number) { function changeTable(newVal: string | undefined) {
table_code.value = `${newVal}`; table_code.value = `${newVal}`;
$initParams.table_code = newVal
concocatSocket()
} }
//转桌 //转桌
function rotTable(newVal: string | number, cart_id = []) { function rotTable(newVal: string | number, cart_id = []) {
@ -415,8 +436,10 @@ export const useCartsStore = defineStore("carts", () => {
//获取历史订单 //获取历史订单
async function getOldOrder(table_code: string | number) { async function getOldOrder(table_code: string | number) {
const res = await orderApi.getHistoryList({ tableCode: table_code }) const res = await orderApi.getHistoryList({ tableCode: table_code })
if (res) {
setOldOrder(res) setOldOrder(res)
} }
}
function getProductDetails(v: { product_id: string, sku_id: string }) { function getProductDetails(v: { product_id: string, sku_id: string }) {
const goods = goodsMap[v.product_id] const goods = goodsMap[v.product_id]
@ -497,13 +520,14 @@ export const useCartsStore = defineStore("carts", () => {
function init(initParams: ApifoxModel, $goodsMap: any, $oldOrder: any) { async function init(initParams: ApifoxModel, $oldOrder: any | undefined) {
// 商品id对应的数据map // 商品id对应的数据map
if ($goodsMap) { await getGoods({})
goodsMap = $goodsMap
}
if ($oldOrder) { if ($oldOrder) {
setOldOrder($oldOrder) setOldOrder($oldOrder)
} else {
oldOrder.value = { detailMap: [] }
} }
// console.log('oldOrder.detailMap', oldOrder.value.detailMap) // console.log('oldOrder.detailMap', oldOrder.value.detailMap)
@ -639,6 +663,10 @@ export const useCartsStore = defineStore("carts", () => {
if (msg.operate_type === "batch") { if (msg.operate_type === "batch") {
concocatSocket({ ...$initParams, table_code: table_code.value }) concocatSocket({ ...$initParams, table_code: table_code.value })
} }
if (msg.operate_type === "product_update") {
console.log('商品更新')
init($initParams, oldOrder.value)
}
}); });
} }
@ -687,7 +715,9 @@ export const useCartsStore = defineStore("carts", () => {
changeSelCart, payMoney, changeSelCart, payMoney,
clear, yiyouhui, giftList, clear, yiyouhui, giftList,
changeTable, changeTable,
rotTable rotTable,
getGoods,
setGoodsMap
}; };
}); });

View File

@ -34,6 +34,7 @@ class WebSocketManager {
private maxReconnectAttempts = 10; // 自定义最大重试次数 private maxReconnectAttempts = 10; // 自定义最大重试次数
private reconnectDelay = 5000; // 重试延迟(单位:毫秒) private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
private timer: any | null = null; private timer: any | null = null;
private reconnectTimer: any | null = null
// 初始化 WebSocket 客户端 // 初始化 WebSocket 客户端
setupWebSocket() { setupWebSocket() {
@ -142,7 +143,6 @@ class WebSocketManager {
this.autoConnect = false; this.autoConnect = false;
} }
} }
// 自动重连机制 // 自动重连机制
private reconnect() { private reconnect() {
if (!this.autoConnect) { if (!this.autoConnect) {
@ -151,10 +151,11 @@ class WebSocketManager {
if (this.reconnectAttempts < this.maxReconnectAttempts) { if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++; this.reconnectAttempts++;
console.log(`尝试第 ${this.reconnectAttempts} 次重连...`); console.log(`尝试第 ${this.reconnectAttempts} 次重连...`);
setTimeout(() => { this.reconnectTimer = setTimeout(() => {
this.setupWebSocket(); this.setupWebSocket();
}, this.reconnectDelay); }, this.reconnectDelay);
} else { } else {
clearTimeout(this.reconnectTimer);
console.error("达到最大重连次数,停止重连"); console.error("达到最大重连次数,停止重连");
ElMessageBox.confirm('达到最大重连次数' + this.maxReconnectAttempts + '次,已停止重连,是否立即重连?', '提示', { ElMessageBox.confirm('达到最大重连次数' + this.maxReconnectAttempts + '次,已停止重连,是否立即重连?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
@ -177,6 +178,10 @@ class WebSocketManager {
clearInterval(this.timer); clearInterval(this.timer);
this.timer = null; this.timer = null;
} }
if (this.reconnectTimer) {
clearInterval(this.reconnectTimer);
this.reconnectTimer = null;
}
} }
} }

View File

@ -101,7 +101,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish" :disabled="!carts.isLinkFinshed"
@click="createOrder('wx-aiplay')" @click="createOrder('wx-aiplay')"
> >
微信/支付宝 微信/支付宝
@ -109,7 +109,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish" :disabled="!carts.isLinkFinshed"
@click="createOrder('cash')" @click="createOrder('cash')"
> >
现金 现金
@ -117,7 +117,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish || showOrder" :disabled="!carts.isLinkFinshed || showOrder"
@click="createOrder('more-pay')" @click="createOrder('more-pay')"
> >
更多支付 更多支付
@ -128,7 +128,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish || carts.isEmpty" :disabled="!carts.isLinkFinshed || carts.isEmpty"
@click="createOrder('only-create')" @click="createOrder('only-create')"
> >
仅下单 仅下单
@ -136,7 +136,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish" :disabled="!carts.isLinkFinshed"
@click="createOrder('to-pay')" @click="createOrder('to-pay')"
> >
去结账 去结账
@ -147,7 +147,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!goodsMapisFinish" :disabled="!carts.isLinkFinshed"
@click="createOrder('to-pay')" @click="createOrder('to-pay')"
> >
立即支付 立即支付
@ -201,10 +201,6 @@ const props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
goodsMapisFinish: {
type: Boolean,
default: false,
},
}); });
let isXianFuKuan = computed(() => { let isXianFuKuan = computed(() => {
// if (!props.table.tableCode) { // if (!props.table.tableCode) {
@ -230,31 +226,6 @@ function hideOrder() {
function createOrder(key) { function createOrder(key) {
emits("createOrder", key); emits("createOrder", key);
} }
const selCartId = ref(null);
watch(
() => props.table.tableCode,
(newval) => {
init();
}
);
const goodsMap = {};
watch(
() => props.goodsMapisFinish,
(newval) => {
if (newval) {
init();
}
}
);
function init() {
for (let goods of props.goodsList) {
goodsMap[goods.id] = goods;
}
carts.init({ table_code: props.table.tableCode }, goodsMap, props.oldOrder);
}
function itemClick(item) { function itemClick(item) {
carts.changeSelCart(item); carts.changeSelCart(item);
@ -268,7 +239,6 @@ function changeNumber(step, item) {
// }); // });
defineExpose({ defineExpose({
carts, carts,
init,
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -33,8 +33,8 @@ const controls = ref([
{ label: "打包", key: "is_pack", disabled: false, per: "pack" }, { label: "打包", key: "is_pack", disabled: false, per: "pack" },
{ label: "删除", key: "del", disabled: false, per: "del" }, { label: "删除", key: "del", disabled: false, per: "del" },
{ label: "转桌", key: "rottable", disabled: false, per: "rottable" }, { label: "转桌", key: "rottable", disabled: false, per: "rottable" },
// { label: "", key: "", disabled: false, per: "save" }, { label: "存单", key: "saveCart", disabled: false, per: "saveCart" },
// { label: "", key: "", disabled: false }, { label: "取单", key: "getCart", disabled: false, per: "getCart" },
{ label: "单品备注", key: "one-note", disabled: false, per: "one-note" }, { label: "单品备注", key: "one-note", disabled: false, per: "one-note" },
{ label: "整单备注", key: "all-note", disabled: false, per: "all-note" }, { label: "整单备注", key: "all-note", disabled: false, per: "all-note" },
{ label: "退菜", key: "return", disabled: false, per: "return" }, { label: "退菜", key: "return", disabled: false, per: "return" },
@ -119,6 +119,9 @@ const perList = computed(() => {
if (carts.oldOrder.id) { if (carts.oldOrder.id) {
arr.push("rottable"); arr.push("rottable");
} }
if (!carts.isEmpty) {
arr.push("saveCart");
}
return arr; return arr;
}); });
const canEdit = computed(() => { const canEdit = computed(() => {

View File

@ -0,0 +1,199 @@
<template>
<!-- 取单 -->
<el-dialog width="550px" title="取单" v-model="prveOrder.show">
<div class="take_order_list">
<div class="tol_left_list">
<div
class="tolll_item"
:class="{ active: prveOrder.sel === index }"
@click="changePrveOrder(index)"
v-for="(item, index) in prveOrder.list"
:key="index"
>
<div class="tollli_index">{{ index + 1 }}</div>
<div class="tollli_price">{{ item.totalAmount }}</div>
<div class="tollli_time_and_num">
<div class="tollli_time">{{ item.created_at || "" }}</div>
<div class="tollli_num">({{ item.totalNumber }})</div>
</div>
</div>
</div>
<div class="tol_right_list" v-if="prveOrder.list.length && prveOrder.sel >= 0">
<div class="tolrl_item" v-for="(item, index) in prveOrder.selCart" :key="index">
<div class="tolrli_img">
<img :src="item.coverImg" alt="" />
</div>
<div class="tolrli_right">
<div class="tr_top">
<div class="trt_name">{{ item.name }}</div>
<div class="trt_num">x{{ item.number }}</div>
<div class="trt_price">{{ item.totalAmount || 0 }}</div>
</div>
<div class="tr_bottom">
<span class="trb_item">
{{ item.specSnap }}
</span>
</div>
</div>
</div>
</div>
</div>
<template #footer>
<div class="flex row-center">
<div style="margin-right: 20px">
<el-button type="primary" @click="confirmChoosePrveOrder">确认此单</el-button>
</div>
<el-button @click="delPrveOrder">删除此单</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
const prveOrder = reactive({
list: [],
show: false,
sel: 0,
selCart: [],
});
function show() {
prveOrder.show = true;
}
function close() {
prveOrder.show = false;
}
defineExpose({
show,
close,
});
</script>
<style lang="scss" scoped>
.take_order_list {
padding: 14px 0;
display: flex;
justify-content: space-between;
.tol_left_list {
height: 360px;
margin-right: 24px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
.tolll_item {
border: 1px solid rgb(247, 247, 250);
height: 86px;
width: 130px;
padding: 10px 14px;
margin-bottom: 12px;
border-radius: 4px;
color: #303133;
background-color: #f7f7fa;
&.active {
border: 1px solid rgb(0, 194, 95);
background-color: rgba(0, 194, 95, 0.1);
color: rgb(0, 194, 95) !important;
.tollli_time,
.tollli_num {
color: rgb(0, 194, 95) !important;
}
}
cursor: pointer;
.tollli_index {
font-weight: 600;
font-size: 18px;
}
.tollli_price {
margin-top: 8px;
font-size: 14px;
}
.tollli_time_and_num {
margin-top: 6px;
display: flex;
justify-content: space-between;
.tollli_time,
.tollli_num {
font-size: 12px;
color: #909399;
}
}
}
}
.tol_right_list {
flex: 1;
height: 360px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
.tolrl_item {
display: flex;
padding: 2px 2px 13px 2px;
margin-bottom: 12px;
border-bottom: 1px solid #ebebeb;
.tolrli_img {
img {
width: 40px;
height: 40px;
border-radius: 4px;
}
}
.tolrli_right {
display: flex;
justify-content: space-between;
flex: 1;
flex-direction: column;
padding: 1px 0 1px 8px;
.tr_top {
display: flex;
justify-content: space-between;
.trt_name {
width: 150px;
font-size: 14px;
color: #212121;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.trt_num {
font-size: 14px;
color: #212121;
}
.trt_price {
width: 100px;
text-align: right;
font-size: 14px;
color: #212121;
}
}
.tr_bottom {
font-size: 12px;
color: #999;
}
}
}
}
}
</style>

View File

@ -571,6 +571,7 @@ async function payOrder(payType, isScan, guazhangren) {
if (payType == "arrears") { if (payType == "arrears") {
res = await payApi.creditPay({ ...returnPayParams(), creditBuyerId: guazhangren.id }); res = await payApi.creditPay({ ...returnPayParams(), creditBuyerId: guazhangren.id });
} }
carts.clearCart();
} catch (error) { } catch (error) {
console.log(error); console.log(error);
clearTimeout(payTimer); clearTimeout(payTimer);

View File

@ -1,5 +1,9 @@
<template> <template>
<div class="box" v-loading="cartsLoading" element-loading-text="购物车连接初始化中,请稍等……"> <div
class="box"
v-loading="!carts.isLinkFinshed"
element-loading-text="购物车连接初始化中,请稍等……"
>
<div class="content"> <div class="content">
<div class="top"> <div class="top">
<div class="left u-flex u-col-center"> <div class="left u-flex u-col-center">
@ -107,8 +111,7 @@
@createOrder="createOrder" @createOrder="createOrder"
@hideOrder="hideOrder" @hideOrder="hideOrder"
:showOrder="showOrder" :showOrder="showOrder"
:goodsMapisFinish="goodsMapisFinish" :goodsList="carts.goods"
:goodsList="goods.list"
:oldOrder="oldOrder" :oldOrder="oldOrder"
:perpole="perpole" :perpole="perpole"
:remark="remark" :remark="remark"
@ -158,7 +161,7 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="goods.list.length <= 0" class="no-goods">未找到相关商品</div> <div v-if="carts.goods.length <= 0" class="no-goods">未找到相关商品</div>
<div class="goods-list"> <div class="goods-list">
<div class="lingshicai" @click="showaddLingShiCai"> <div class="lingshicai" @click="showaddLingShiCai">
<el-icon size="26"><Plus /></el-icon> <el-icon size="26"><Plus /></el-icon>
@ -167,7 +170,7 @@
<GoodsItem <GoodsItem
:item="item" :item="item"
@click="goodsClick(item)" @click="goodsClick(item)"
v-for="item in goods.list" v-for="item in carts.goods"
:key="item.id" :key="item.id"
></GoodsItem> ></GoodsItem>
</div> </div>
@ -311,7 +314,9 @@ async function refReturnCartConfirm(e) {
const res1 = await orderApi.getHistoryList({ const res1 = await orderApi.getHistoryList({
orderId: oldOrder.value.id, orderId: oldOrder.value.id,
}); });
if (res1) {
oldOrder.value = res1; oldOrder.value = res1;
}
carts.setOldOrder(res1); carts.setOldOrder(res1);
} }
} }
@ -417,7 +422,9 @@ async function createOrder(key) {
const res1 = await orderApi.getHistoryList({ const res1 = await orderApi.getHistoryList({
orderId: res.id, orderId: res.id,
}); });
if (res1) {
oldOrder.value = res1; oldOrder.value = res1;
}
carts.setOldOrder(res1); carts.setOldOrder(res1);
} }
if (key == "only-create") { if (key == "only-create") {
@ -616,24 +623,12 @@ const goods = reactive({
}, },
}); });
let goodsMapisFinish = ref(false);
async function getGoods() { async function getGoods() {
const res = await productApi.getPage({ carts.getGoods(goods.query);
page: 1,
size: 400,
status: "on_sale",
...goods.query,
});
goods.list = res.records;
carts.goods = goods.list;
goodsMapisFinish.value = true;
} }
const cartsLoading = computed(() => {
return !goodsMapisFinish.value || !carts.isLinkFinshed;
});
function goodsClick(item) { function goodsClick(item) {
if (!goodsMapisFinish.value) { if (!carts.isLinkFinshed) {
return ElMessage.error({ return ElMessage.error({
message: "添加失败socket未连接成功请刷新再试", message: "添加失败socket未连接成功请刷新再试",
type: "error", type: "error",
@ -689,7 +684,6 @@ function skuSelConfirm(item) {
// //
const refCart = ref(null);
function clearCarts() { function clearCarts() {
ElMessageBox.alert("确定要清空点餐列表吗?", "提示", { ElMessageBox.alert("确定要清空点餐列表吗?", "提示", {
confirmButtonText: "确定", confirmButtonText: "确定",
@ -712,7 +706,7 @@ watch(
function init() { function init() {
getTableList(); getTableList();
getCategoryList(); getCategoryList();
getGoods(); carts.init();
} }
onBeforeRouteLeave(() => { onBeforeRouteLeave(() => {
@ -775,13 +769,12 @@ function refresh() {
oldOrder.value = { oldOrder.value = {
detailMap: [], detailMap: [],
}; };
oldOrder.value = {};
showOrder.value = false; showOrder.value = false;
user.value = {}; user.value = {};
table.value = {}; table.value = {};
router.replace(route.path); router.replace(route.path);
carts.dataReset(); carts.dataReset();
refCart.value.carts.init(); carts.init();
// setTimeout(() => { // setTimeout(() => {
// router.go(0); // router.go(0);
// }, 1500); // }, 1500);