import { store } from "@/store"; import WebSocketManager, { type ApifoxModel, msgType } from "@/utils/websocket"; import orderApi from "@/api/order/order"; import { useUserStoreHook } from "@/store/modules/user"; const shopUser = useUserStoreHook(); export interface CartsState { id: string | number; [property: string]: any; } export const useCartsStore = defineStore("carts", () => { //选择用户 const vipUser = ref<{ id?: string | number, isVip?: boolean }>({}); function changeUser(user: any) { vipUser.value = user; } //就餐类型 dine-in take-out let dinnerType = ref('dine-in'); //是否启用会员价 const useVipPrice = computed(() => { return (shopUser.userInfo.isMemberPrice && vipUser.value.id && vipUser.value.isVip) ? true : false }) //台桌id // const table_code = useStorage('Instead_table_code', ''); const table_code = ref('') //购物车是否初始化连接加载完成 const isLinkFinshed = ref(false) //当前购物车数据 const list = useStorage("carts", []); //历史订单数据 const oldOrder = useStorage("Instead_olold_order", { detailMap: [], originAmount: 0 }); //代客下单页面商品缓存 const goods = useStorage("Instead_goods", []); //赠菜 const giftList = useStorage("giftList", []); let goodsMap: { [key: string]: any } = useStorage('Instead_goods_map', {}); //当前选中cart let selListIndex = ref(-1); //当前选中商品是否是赠菜 const isSelGift = ref(false); //当前选中是否是历史订单 const isOldOrder = ref(false); //选中历史订单中的第几次下单 const selPlaceNum = ref(-1); const defaultCart = { id: '', number: 0, } //购物车是否为空 const isEmpty = computed(() => { return list.value.length === 0 && giftList.value.length === 0 }) //当前购物车选中数据 const selCart = computed(() => { if (isOldOrder.value && selPlaceNum.value >= 0) { return oldOrder.value.detailMap[selPlaceNum.value][selListIndex.value] } if (isSelGift.value) { return giftList.value[selListIndex.value] || defaultCart } return list.value[selListIndex.value] || defaultCart }) //当前购物车选中对应商品数据 const selGoods = computed(() => { return goodsMap[selCart.value.product_id] }) //当前选中购物车数据是否是可选套餐商品 const isCanSelectGroup = computed(() => { if (!selGoods.value) { return false } return selGoods.value.type == 'package' && selGoods.value.groupType == 1 }) //赠菜总价 const giftMoney = computed(() => { let oldGiftMoney = 0 for (let i in oldOrder.value.detailMap) { oldGiftMoney += oldOrder.value.detailMap[i].filter((v: any) => v.isGift).reduce((prve: number, cur: any) => { const memberPrice = cur.memberPrice || cur.salePrice return prve + cur.number * (useVipPrice.value ? memberPrice : cur.salePrice) }, 0) } const nowTotal = giftList.value.reduce((acc: number, cur: any) => { const memberPrice = cur.memberPrice || cur.salePrice return acc + cur.number * (useVipPrice.value ? memberPrice : cur.salePrice) }, 0) return (nowTotal + oldGiftMoney) }) //打包数量 const packNum = computed(() => { const nowCartNumber = list.value.reduce((acc: number, cur: any) => { return acc + cur.pack_number * 1 }, 0) const giftNumber = giftList.value.reduce((acc: number, cur: any) => { return acc + cur.pack_number * 1 }, 0) let oldNumber = 0 for (let i in oldOrder.value.detailMap) { oldNumber += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => { return prve + cur.pack_number }, 0) } return nowCartNumber + giftNumber + oldNumber }) //打包费 const packFee = computed(() => { const nowPackFee = list.value.reduce((acc: number, cur: any) => { return acc + (cur.packFee || 0) * cur.pack_number }, 0) const giftPackFee = giftList.value.reduce((acc: number, cur: any) => { return acc + (cur.packFee || 0) * cur.pack_number }, 0) let oldPackfee = 0; for (let i in oldOrder.value.detailMap) { oldPackfee += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => { return prve + (cur.packFee || 0) * cur.pack_number }, 0) } return nowPackFee + giftPackFee + oldPackfee }) //会员优惠 const vipDiscount = computed(() => { if (!useVipPrice.value) { return 0 } const listTotal = list.value.reduce((acc: number, cur: any) => { const n = (cur.salePrice * 1 - cur.memberPrice * 1) * cur.number return acc + (n <= 0 ? 0 : n) }, 0) const giftTotal = giftList.value.reduce((acc: number, cur: any) => { const n = (cur.salePrice * 1 - cur.memberPrice * 1) * cur.number return acc + (n <= 0 ? 0 : n) }, 0) let oldTotal = 0; for (let i in oldOrder.value.detailMap) { oldTotal += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => { const n = (cur.salePrice * 1 - cur.memberPrice * 1) * cur.number return prve + (n <= 0 ? 0 : n) }, 0) } return listTotal + giftTotal + oldTotal }) //单品改价优惠 const singleDiscount = computed(() => { const listTotal = list.value.reduce((acc: number, cur: any) => { if (cur.discount_sale_amount * 1 <= 0) { return acc + 0 } const originPrice = useVipPrice.value ? (cur.memberPrice || cur.salePrice) : cur.salePrice const n = (originPrice * 1 - cur.discount_sale_amount * 1) * cur.number return acc + (n <= 0 ? 0 : n) }, 0) return listTotal }) // 优惠 const yiyouhui = computed(() => { const youhui = giftMoney.value * 1 + vipDiscount.value * 1 + singleDiscount.value * 1 if (youhui > 0) { return '已优惠¥' + youhui.toFixed(2) } return '' }) //历史订单价格 const oldOrderMoney = computed(() => { let total = 0 for (let i in oldOrder.value.detailMap) { total += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => { if (cur.isGift) { return prve + 0 } const discount_sale_amount = cur.discount_sale_amount * 1 || 0 const memberPrice = cur.skuData ? (cur.skuData.memberPrice || cur.skuData.salePrice) : 0 const price = (discount_sale_amount || cur.salePrice || 0) const number = (cur.number - cur.returnNum) return prve + (number <= 0 ? 0 : number) * (discount_sale_amount || (useVipPrice.value ? memberPrice : price)) }, 0) } return total }) //支付总价 const payMoney = computed(() => { const money = list.value.reduce((acc: number, cur: any) => { const discount_sale_amount = cur.discount_sale_amount * 1 || 0 const memberPrice = cur.skuData ? (cur.skuData.memberPrice || cur.skuData.salePrice) : 0 const price = (cur.discount_sale_amount * 1 || cur.salePrice || 0) return acc + cur.number * (discount_sale_amount || (useVipPrice.value ? memberPrice : price)) }, 0) return (money + packFee.value + oldOrderMoney.value * 1).toFixed(2) }) //只算商品的总价 const goodsTotal = computed(() => { const money = list.value.reduce((acc: number, cur: any) => { const discount_sale_amount = cur.discount_sale_amount * 1 || 0 const memberPrice = cur.skuData ? (cur.skuData.memberPrice || cur.skuData.salePrice) : 0 const price = (cur.discount_sale_amount * 1 || cur.salePrice || 0) return acc + cur.number * (discount_sale_amount || (useVipPrice.value ? memberPrice : price)) }, 0) return (money + oldOrderMoney.value * 1).toFixed(2) }) //总计数量 const totalNumber = computed(() => { const cartNumber = list.value.reduce((acc: number, cur: any) => { return acc + cur.number * 1 }, 0) const giftNumber = list.value.reduce((acc: number, cur: any) => { return acc + cur.number * 1 }, 0) let oldNumber = 0 for (let i in oldOrder.value.detailMap) { oldNumber += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => { return prve + cur.number * 1 }, 0) } return cartNumber + giftNumber + oldNumber }) function changeNumber(step: number, item: CartsState) { if (item.number * 1 + step <= 0) { del(item); return; } const newNumber = item.number * 1 + step * 1; let pack_number = newNumber < item.pack_number ? (item.pack_number * 1 + step * 1) : item.pack_number; if (dinnerType.value == 'take-out') { pack_number = newNumber } update({ ...item, number: newNumber, pack_number }); } function changeSelCart(cart: CartsState) { console.log(cart) if (!cart.id) { return } if (cart.placeNum) { selPlaceNum.value = cart.placeNum isOldOrder.value = true console.log(oldOrder.value.detailMap[cart.placeNum]) selListIndex.value = oldOrder.value.detailMap[cart.placeNum].findIndex((item: CartsState) => { return item.id == cart.id }) return } if (cart.is_gift) { isSelGift.value = true } else { isSelGift.value = false } if (cart.is_gift) { isSelGift.value = true selListIndex.value = giftList.value.findIndex((item: CartsState) => item.id === cart.id); console.log(selListIndex.value) } else { isSelGift.value = false selListIndex.value = list.value.findIndex((item: CartsState) => item.id === cart.id); } } const basic_msg = { number: 1, is_gift: 0, is_temporary: 0, discount_sale_amount: 0, discount_sale_note: "", is_print: 1, pro_group_info: '', is_wait_call: 0, product_name: "", remark: "", sku_id: '', } //当前购物车直接添加 function cartsPush(data: any) { sendMessage('add', { ...basic_msg, ...data }); } function add(data: any) { const msg = { ...basic_msg, ...data } const hasCart = list.value.find((cartItem) => { return cartItem.product_id == msg.product_id && cartItem.sku_id == msg.sku_id; }); if (hasCart) { update({ ...hasCart, ...msg, number: hasCart.number * 1 + msg.number * 1 }) } else { console.log(msg); sendMessage('add', msg); } } // 换桌 function changeTable(newVal: string | number) { if (table_code.value) { sendMessage('rottable', { new_table_code: newVal, table_code: table_code.value }); } else { table_code.value = `${newVal}`; } } function del(data: any) { sendMessage('del', { id: data.id }); } function update(data: any) { console.log(data); const suitNum = data.skuData ? (data.skuData.suitNum || 1) : 1; if (data.number * 1 < suitNum * 1) { return sendMessage('del', data); } const pack_number = dinnerType.value == 'take-out' ? data.number : data.pack_number sendMessage('edit', { ...data, pack_number }); } function updateTag(key: string, val: any, cart: CartsState = selCart.value) { const skuData = cart.skuData || { suitNum: 1 } if (cart.number * 1 < skuData.suitNum * 1) { return sendMessage('del', cart); } console.log(key, val) if (key == 'discount_sale_amount' && val * 1 <= 0) { return ElMessage.error('价格不能为0!') } const msg = { ...cart, [key]: val } if (key == 'number' && dinnerType.value == 'take-out') { msg.pack_number == val } sendMessage('edit', msg); } // 更改全部商品打包状态 function changePack(is_pack: number | string) { sendMessage('batch', { is_pack }); } function clear() { sendMessage('cleanup', {}); } function dataReset() { selListIndex.value = -1; selPlaceNum.value = 1 isOldOrder.value = false isSelGift.value = false list.value = []; giftList.value = []; oldOrder.value = { detailMap: [], originAmount: 0 } vipUser.value = {} } function nowCartsClear() { if (selPlaceNum.value == 1) { selListIndex.value = -1; } list.value = []; giftList.value = []; } // 寻找套餐商品sku interface GroupSnap { goods: { [key: string]: any }[]; } function findInGroupSnapSku(groupSnap: GroupSnap[], sku_id: string | number) { for (let i in groupSnap) { const sku = groupSnap[i].goods.find(v => v.sku_id == sku_id) if (sku) { return sku } } } function getProductDetails(v: { product_id: string, sku_id: string }) { const goods = goodsMap[v.product_id] if (!goods) { return undefined } let skuData = undefined; skuData = goods?.skuList.find((sku: { id: string, salePrice: number }) => sku.id == v.sku_id); // if (goods.type == 'package') { // //套餐商品 // const SnapSku = findInGroupSnapSku(goods.groupSnap, v.sku_id) // skuData = { ...SnapSku, salePrice: SnapSku ? SnapSku.price : 0 } // } else { // skuData = goods?.skuList.find((sku: { id: string, salePrice: number }) => sku.id == v.sku_id); // } skuData = goods?.skuList.find((sku: { id: string, salePrice: number }) => sku.id == v.sku_id); if (skuData) { return { salePrice: skuData ? skuData.salePrice : 0, memberPrice: skuData ? skuData.memberPrice : 0, coverImg: goods.coverImg, name: goods.name, specInfo: skuData.specInfo, packFee: goods.packFee || 0, type: goods.type, skuData } } else { return undefined } } function returnDetailMap(data: any) { const newData: { [key: string]: any } = {} for (let i in data) { newData[i] = data[i].map((v: any) => { const skuData = getProductDetails({ product_id: v.productId, sku_id: v.skuId }) return { ...v, ...skuData, placeNum: v.placeNum, number: v.num, id: v.id, pack_number: v.packNumber, discount_sale_amount: v.discountSaleAmount * 1 || 0, is_print: v.isPrint, is_wait_call: v.isWaitCall, is_gift: v.isGift, is_temporary: v.isTemporary, discount_sale_note: v.discountSaleNote, product_name: v.productName, sku_name: v.skuName, sku_id: v.skuId } }) } return newData } function setOldOrder(data: any) { oldOrder.value = { ...data, detailMap: returnDetailMap(data.detailMap) } } let $initParams = {} as ApifoxModel /** * * @param initParams 购物车初始化参数 * @param $goodsMap 商品id对应的map * @param oldOrder 历史订单数据 */ function init(initParams: ApifoxModel, $goodsMap: any, $oldOrder: any) { // 商品id对应的数据map if ($goodsMap) { goodsMap = $goodsMap } if ($oldOrder) { setOldOrder($oldOrder) } // console.log('oldOrder.detailMap', oldOrder.value.detailMap) // const cache_table_code = localStorage.getItem('cache_table_code'); // const randomTableCode = cache_table_code ? cache_table_code : ('APC' + (1000 + Math.floor(Math.random() * 9000))) if (initParams) { initParams.table_code = initParams.table_code ? initParams.table_code : '' table_code.value = initParams.table_code $initParams = initParams; } console.log($initParams) // localStorage.setItem('cache_table_code', table_code.value); concocatSocket($initParams) } function concocatSocket(initParams = $initParams) { console.log("初始化参数", initParams); WebSocketManager.subscribeToTopic(initParams, (msg) => { console.log("收到消息:", msg); if (msg.hasOwnProperty('status') && msg.status != 1) { return ElMessage.error(msg.message || '操作失败') } if (msg && msg.data) { if (Array.isArray(msg.data) && msg.data.length && msg.data[0].table_code) { table_code.value = msg.data[0].table_code } if (msg.data.table_code) { table_code.value = table_code.value ? table_code.value : msg.data.table_code } if (msg.table_code) { table_code.value = table_code.value ? table_code.value : msg.table_code } } // 初始化 if (msg.operate_type === "manage_init") { isLinkFinshed.value = true // 设置单价 list.value = msg.data.filter((v: Record) => { if (v.is_temporary) { return v } const skuData = getProductDetails({ product_id: v.product_id, sku_id: v.sku_id }) if (skuData) { (Object.keys(skuData) as (keyof typeof skuData)[]).forEach((key) => { v[key] = skuData[key]; }); } else { del({ id: v.id }) return false } return !v.is_gift }) giftList.value = msg.data.filter((v: Record) => { if (v.is_temporary) { return v && v.is_gift } const skuData = getProductDetails({ product_id: v.product_id, sku_id: v.sku_id }) if (skuData) { (Object.keys(skuData) as (keyof typeof skuData)[]).forEach((key) => { v[key] = skuData[key]; }); } else { del({ id: v.id }) return false } return v.is_gift }) } //广播 if (msg.type === "bc") { msg.operate_type = 'manage_' + msg.operate_type } if (msg.operate_type === "manage_add") { if (list.value.find(v => v.id == msg.data.id)) { return ElMessage.warning(msg.message || '该商品已存在') } const skuData = getProductDetails({ product_id: msg.data.product_id, sku_id: msg.data.sku_id }) const newGoods = { ...skuData, ...msg.data } console.log('newGoods', newGoods) list.value.push(newGoods) return ElMessage.success(msg.message || '添加成功') } if (msg.operate_type === "manage_edit") { const newCart = msg.data const index = list.value.findIndex((item) => item.id === newCart.id) const giftIndex = giftList.value.findIndex((item) => item.id === newCart.id) const cartItem = list.value[index] || { is_gift: false }; const giftItem = giftList.value[giftIndex]; if (giftItem) { //操作赠菜 if (!newCart.is_gift) { giftList.value.splice(giftIndex, 1) list.value.push({ ...giftItem, ...newCart }) selListIndex.value = -1 } else { giftList.value[giftIndex] = { ...giftItem, ...newCart } } } if (cartItem) { //操作非赠菜 if (newCart.is_gift) { list.value.splice(index, 1) giftList.value.push({ ...cartItem, ...newCart }) selListIndex.value = -1 } else { list.value[index] = { ...cartItem, ...newCart } } } ElMessage.success(msg.message || '修改成功') } if (msg.operate_type === "manage_del") { const cartId = Array.isArray(msg.data) ? msg.data[0].id : msg.data.id const listIndex = list.value.findIndex((item) => item.id == cartId) if (listIndex > -1) { list.value.splice(listIndex, 1) } const giftIndex = giftList.value.findIndex((item) => item.id == cartId) if (giftIndex > -1) { giftList.value.splice(giftIndex, 1) } return ElMessage.success(msg.message || '删除成功') } if (msg.operate_type === "manage_cleanup") { nowCartsClear() } if (msg.operate_type === "batch") { concocatSocket({ ...$initParams, table_code: table_code.value }) } }); } function disconnect() { sendMessage('disconnect', undefined) } const delArr = ['skuData', 'coverImg', 'specInfo', 'placeNum', 'update_time', 'create_time', 'packFee', 'memberPrice', 'type'] function sendMessage(operate_type: msgType, message: any) { const msg = { ...message, operate_type: operate_type, table_code: table_code.value } for (let i in delArr) { delete msg[delArr[i]] } console.log('send msg', msg) WebSocketManager.sendMessage(msg); } return { disconnect, dinnerType, changePack, giftMoney, goodsTotal, isLinkFinshed, setOldOrder, singleDiscount, vipDiscount, dataReset, useVipPrice, changeUser, packNum, packFee, isOldOrder, oldOrder, isCanSelectGroup, goods, selGoods, cartsPush, table_code, updateTag, list, add, del, update, init, changeNumber, isEmpty, selCart, totalNumber, changeSelCart, payMoney, clear, yiyouhui, giftList, changeTable }; }); export function useCartsStoreHook() { return useCartsStore(store); }