import { defineStore } from "pinia"; // import yskUtils from 'ysk-utils' // const { // OrderPriceCalculator, // BaseCartItem, // BackendCoupon, // ActivityConfig, // OrderExtraConfig, // MerchantReductionConfig, // MerchantReductionType, // GoodsType // } = yskUtils import { OrderPriceCalculator } from "@/utils/goods"; import { ref, computed, reactive, watchEffect, watch } from "vue"; import { productminiApphotsquery, APIgroupquery, } from "@/common/api/product/product.js"; export const useCartsStore = defineStore("cart", () => { // 店铺信息 const shopInfo = ref( uni.cache.get("shopInfo") || { isMemberPrice: 0, isTableFee: 1, } ); //用户信息 const shopUserInfo = ref(uni.cache.get("shopUserInfo") || {}); const consumeDiscount = ref({}); // 适配工具库 BaseCartItem 接口的商品数据转换函数 const convertToBaseCartItem = (item) => { const skuData = item.skuData ? { id: item.skuData.id || item.sku_id, salePrice: item.skuData.salePrice || 0, memberPrice: item.skuData.memberPrice || 0, } : undefined; const goods = getProductDetails({ ...item, product_id: item.product_id || item.productId, sku_id: item.skuId || item.sku_id, }); return { ...item, id: item.id, sku_id: item.skuId || item.sku_id, product_id: item.product_id || item.productId, salePrice: item.salePrice || item.price, number: item.number || item.num || 0, product_type: item.productType, is_temporary: !!(item.is_temporary || item.isTemporary), is_gift: !!(item.is_gift || item.isGift), returnNum: item.returnNum || 0, memberPrice: item.memberPrice || 0, discountSaleAmount: item.discount_sale_amount || item.discountSaleAmount || 0, packFee: item.packFee || (goods ? goods.packFee : 0) || 0, packNumber: item.pack_number || item.packNumber || 0, activityInfo: item.activityInfo ? { type: item.activityInfo.type, discountRate: OrderPriceCalculator.formatDiscountRate( item.activityInfo.discountRate ), vipPriceShare: !!item.activityInfo.vipPriceShare, } : undefined, skuData, }; }; // 合并所有商品列表 const allGoods = ref([]); function getAllGoodsList() { const currentGoods = carts.value.map(convertToBaseCartItem); const giftGoods = [].map(convertToBaseCartItem); // 扁平化历史订单商品 const oldOrderGoods = Object.values(oldOrder.value.detailMap || {}) .flat() .map(convertToBaseCartItem); return [...currentGoods, ...giftGoods, ...oldOrderGoods]; } // 就餐类型 'dine-in' | 'take-out' let dinnerType = ref("dine-in"); function setDinnerType(str) { dinnerType.value = str; } //餐位费配置 const dinersNum = uni.cache.get("dinersNum") || 0; const seatFeeConfig = ref({ pricePerPerson: shopInfo.value.tableFee || 0, personCount: dinersNum || 0, isEnabled: !shopInfo.value.isTableFee, }); watch( () => shopInfo.value.isTableFee, (newval) => { seatFeeConfig.value.isEnabled = !shopInfo.value.isTableFee; seatFeeConfig.value.pricePerPerson = shopInfo.value.tableFee || 0; }, { deep: true, } ); function setSeatFeeConfig(key, val) { seatFeeConfig.value[key] = val; } watch( () => seatFeeConfig.value, (newval) => { console.log("seatFeeConfig", seatFeeConfig.value); }, { deep: true, } ); //积分规则 const pointDeductionRule = ref({ pointsPerYuan: 0, maxDeductionAmount: Infinity, }); function setPointDeductionRule(pointsPerYuan, maxDeductionAmount) { pointDeductionRule.value.pointsPerYuan = pointsPerYuan; pointDeductionRule.value.maxDeductionAmount = maxDeductionAmount; } // 初始配置:默认无减免(固定金额 0 元) const merchantReductionConfig = ref({ type: "fixed_amount", fixedAmount: 0, }); //使用积分数量 const userPoints = ref(0); function setUserPoints(newval) { userPoints.value = newval; } //新客立减 const newUserDiscount = ref(0); //满减活动 const fullReductionActivities = ref([]); //是否使用霸王餐 const isFreeDine = ref(false); // 商家霸王餐配置 const freeDineConfig = ref(null); //限时折扣 const limitTimeDiscount = ref(null); // 订单额外配置 const orderExtraConfig = computed(() => ({ // 引用扩展后的商家减免配置 merchantReduction: merchantReductionConfig.value, additionalFee: 0, pointDeductionRule: pointDeductionRule.value, seatFeeConfig: seatFeeConfig.value, currentStoreId: "", userPoints: userPoints.value, isMember: useVipPrice.value, memberDiscountRate: 1, newUserDiscount: newUserDiscount.value, fullReductionActivities: fullReductionActivities.value, currentDinnerType: dinnerType.value, isFreeDine: isFreeDine.value, freeDineConfig: freeDineConfig.value, limitTimeDiscount: limitTimeDiscount.value, shopUserInfo: shopUserInfo.value, })); // 营销活动列表 const activityList = computed(() => { return []; }); // 优惠券列表 const backendCoupons = ref([]); function setCoupons(cps) { console.log("setCoupons", cps); backendCoupons.value = cps; } // 商品加入购物车顺序 const cartOrder = ref({}); // 订单费用汇总 const orderCostSummary = computed(() => { allGoods.value = getAllGoodsList(); console.log("allGoods.value", allGoods.value); console.log("orderExtraConfig.value", orderExtraConfig.value); const costSummary = OrderPriceCalculator.calculateOrderCostSummary( allGoods.value, dinnerType.value, backendCoupons.value, activityList.value, orderExtraConfig.value, cartOrder.value, new Date() ); console.log(" 订单费用汇总", costSummary); return costSummary; }); const goodsIsloading = ref(true); //商品数据Map const goodsMap = reactive({}); function returnGoods(product_id){ return goodsMap[product_id*1] } //获取商品数据 async function goodsInit() { goodsIsloading.value = true; //获取招牌菜商品 const hotres = await productminiApphotsquery(); for (let product of hotres) { setGoodsMap(product.id, product); } //获取分组商品 const groupres = await APIgroupquery(); for (let group of groupres) { for (let product of group.productList) { setGoodsMap(product.id, product); } } allGoods.value = getAllGoodsList(); goodsIsloading.value = false; } function setGoodsMap(product_id, data) { goodsMap[product_id] = data; } const isLoading = ref(true); function getProductDetails(v) { const goods = goodsMap[v.product_id]; if (!goods) { return undefined; } let skuData = undefined; skuData = goods?.skuList.find((sku) => sku.id == v.sku_id); if (skuData) { return { ...v, productId: v.product_id, salePrice: skuData ? skuData.salePrice : 0, price: skuData ? skuData.salePrice : 0, memberPrice: skuData ? skuData.memberPrice : 0, coverImg: goods.coverImg, productImg: goods.coverImg, name: goods.name, productName: goods.name, specInfo: skuData.specInfo, packFee: goods.packFee || 0, type: goods.type, skuData, skuName: skuData.name, num: v.number * 1, }; } else { return undefined; } } // 用于记录已经处理过的消息的 msg_id const processedMessageIds = new Set(); //购物车商品信息补全初始化 function cartsGoodsInfoInit(arr) { carts.value = arr .map((v) => { return getProductDetails(v); }) .filter((v) => v); } //收到socket消息时对购物车进行处理 async function onMessage(Message) { if (Message) { // 心跳返回 过滤 if ( Message.type == "ping_interval" || Message.msg_id == "ping_interval" ) { isLoading.value = false; return false; } // 检查消息是否已经处理过 if (processedMessageIds.has(Message.msg_id)) { return; } processedMessageIds.add(Message.msg_id); const msgData = Message.data; // 初始化 if (Message.operate_type == "init") { console.log("carts init", msgData); cartsGoodsInfoInit(msgData); uni.hideLoading(); isLoading.value = false; } // 清空购物车 if (Message.operate_type == "cleanup") { carts.value = []; } // 删除除购物车 if (Message.operate_type == "del" && Message.status == 1) { // 优化:使用可选链操作符避免报错 carts.value = carts.value.filter((item) => item.id !== msgData?.id); } // 添加或者减少购物后返回 if (Message.operate_type == "add" || Message.operate_type == "edit") { const index = carts.value.findIndex((v) => v.id == msgData.id); if (index !== -1) { carts.value[index] = getProductDetails(msgData); } else { carts.value.push(getProductDetails(msgData)); } } // 历史订单 if (Message.operate_type == "clearOrder") { } // 购物车数据更新从新请求 if ( Message.type == "product" && Message.data_type == "product_update" && Message.operate_type == "product_update" ) { await goodsInit(); await cartsGoodsInfoInit(); } // 提示 if (Message.status == 0 && Message.type != "no_suit_num") { uni.showToast({ title: Message.msg, icon: "none", }); } //获取限时折扣 // if(Message.operate_type == "time_discount_get"){ // console.log("time_discount_get", Message.data); // limitTimeDiscount.value = Message.data; // } if (Message.type == "no_suit_num") { uni.showModal({ title: "提示", showCancel: false, content: "此商品库存不足起售数量!", success: async (data) => {}, }); } } } //购物车数据 const carts = ref([]); //历史订单数据 const oldOrder = ref({ detailMap: {}, originAmount: 0, }); function setOldOrder(data) { oldOrder.value = data; allGoods.value = getAllGoodsList(); } // 会员信息 const orderVIP = ref( uni.cache.get("orderVIP") || { isVip: false, } ); function updateData(key, newval) { if (key === "orderVIP") { uni.cache.set("orderVIP", newval); return (orderVIP.value = newval); } if (key === "shopInfo") { uni.cache.set("shopInfo", newval); return (shopInfo.value = newval); } } //是否使用会员价 const useVipPrice = computed(() => { if (!orderVIP.value) { return false; } const isUse = orderVIP.value.isVip && shopInfo.value.isMemberPrice ? true : false; return isUse; }); function currentCalcMpneyNumber(item) { const n = item.number - (item.returnNum || 0); return n <= 0 ? 0 : n; } //历史订单商品价格总和 const oldOrderMoney = computed(() => { let total = 0; for (let i in oldOrder.value.detailMap) { total += oldOrder.value.detailMap[i].reduce((prve, cur) => { 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 = currentCalcMpneyNumber(cur); return ( prve + (number <= 0 ? 0 : number) * (discount_sale_amount || (useVipPrice.value ? memberPrice : price)) ); }, 0); } return total; }); //当前购物车总价格 const totalPrice = computed(() => { const money = carts.value.reduce((prve, cur) => { const memberPrice = cur.memberPrice || cur.salePrice; const price = useVipPrice.value ? memberPrice : cur.salePrice; const curMoney = price * currentCalcMpneyNumber(cur); return prve + curMoney; }, 0); return money; }); // 霸王餐购物车原价,不享受任何优惠 const totalOriginPrice = computed(() => { const money = carts.value.reduce((prve, cur) => { const curMoney = cur.salePrice * currentCalcMpneyNumber(cur); return prve + curMoney; }, 0); return money; }); //返回打包数量(称重商品打包数量最大为1) function returnCartPackNumber(cur) { const maxReturnNum = cur.number - (cur.returnNum || 0); let pack_number = cur.number; pack_number = cur.product_type == "weight" && pack_number > 1 ? 1 : pack_number; pack_number = Math.min(maxReturnNum, pack_number); pack_number = pack_number <= 0 ? 0 : pack_number; return pack_number * 1; } //当前购物车打包费 const totalPackFee = computed(() => { const money = carts.value.reduce((prve, cur) => { const curMoney = (cur.packFee || 0) * currentCalcMpneyNumber(cur); return prve + curMoney; }, 0); return money; }); //打包费 const packFee = computed(() => { const nowPackFee = carts.value.reduce((acc, cur) => { return acc + (cur.packFee || 0) * returnCartPackNumber(cur); }, 0); let oldPackfee = 0; for (let i in oldOrder.value.detailMap) { oldPackfee += oldOrder.value.detailMap[i].reduce((prve, cur) => { return prve + (cur.packFee || 0) * returnCartPackNumber(cur); }, 0); } return nowPackFee + oldPackfee; }); //购物车是否为空 const isEmpty = computed(() => { return !carts.value || carts.value.length <= 0; }); // 计算向上取整 const roundUpToTwoDecimals = (num, i) => { // 先将数字乘以 100 并转换为字符串保留足够的小数位 let temp = (num * 100).toFixed(10); // 向上取整 let rounded = null; if (i == "upward") { rounded = Math.ceil(parseFloat(temp)); } else { rounded = Math.floor(parseFloat(temp)); } // 再除以 100 得到保留两位小数的结果 return rounded / 100; }; // 精确计算函数 const preciseCalculation = (num1, num2) => { // 将数字转换为整数,乘以 100 以保留两位小数 const int1 = BigInt(Math.round(num1 * 100)); const int2 = BigInt(Math.round(num2 * 100)); // 执行乘法运算 const result = int1 * int2; // 再除以 10000 以还原为原来的小数 return Number(result) / 10000; }; // 计算购物车商品总价格 const getTotalTotalPrices = (matchedProducts, isBwc = true) => { if (!matchedProducts || !Array.isArray(matchedProducts)) { return 0; } // 购物车总数价格 let cart = matchedProducts.reduce((total, item) => { if (isBwc === true) { return ( total + parseFloat(item.price) * parseFloat(item.num - item.returnNum) ); } // 是否启用会员价 0否1是 if (useVipPrice.value) { // memberPrice会员价 return ( total + parseFloat(item.memberPrice || item.price) * parseFloat(item.num - item.returnNum) ); } else { // salePrice销售价 return ( total + parseFloat(item.price) * parseFloat(item.num - item.returnNum) ); } }, 0); cart = cart.toFixed(2); return parseFloat(cart); }; // 计算商品卷所选择的总价格 const getTotalProductroll = (matchedProducts) => computed(() => { if (!matchedProducts || !Array.isArray(matchedProducts)) { return 0; } // 购物车总数价格 let cart = matchedProducts.reduce((total, item) => { // 是否启用会员价 0否1是 if (useVipPrice.value) { // memberPrice会员价 return total + parseFloat(item.memberPrice || item.price); } else { // salePrice销售价 return total + parseFloat(item.price); } }, 0); // 向上取整并保留两位小数 let result = roundUpToTwoDecimals(cart, "upward"); return result; }); // 桌位置 const getTotalSeatcharge = (seatNum) => computed(() => { // 是否免除桌位费 0 否 1 是 let cart = 0; if (uni.cache.get("ordershopUserInfo").isTableFee == 0 && seatNum) { cart = parseFloat(seatNum) * parseFloat(uni.cache.get("ordershopUserInfo").tableFee); } // 向下取整并保留两位小数 let result = roundUpToTwoDecimals(cart, "downward"); return result; }); // 计算购物车总打包费用(向下取整并保留两位小数) const getTotalPackFee = (cartList) => computed(() => { const total = cartList.reduce((sum, item) => { return ( sum + parseFloat(item.packAmount) * (parseFloat(item.packNumber) || parseFloat(item.num) - parseFloat(item.returnNum)) ); }, 0); // 向下取整并保留两位小数 let result = roundUpToTwoDecimals(total, "downward"); return result; }); function clearOrderConfig() { console.log("clearOrderConfig"); backendCoupons.value = []; allGoods.value = []; carts.value = []; seatFeeConfig.value.personCount = uni.cache.get("dinersNum") || 0; dinnerType.value = "dine-in"; userPoints.value = 0; fullReductionActivities.value = []; isFreeDine.value = false; oldOrder.value = { detailMap: {}, originAmount: 0, }; } return { getTotalPackFee, getTotalSeatcharge, getTotalTotalPrices, getTotalProductroll, carts, isEmpty, setGoodsMap, goodsMap:goodsMap, goodsIsloading, goodsInit, onMessage, totalPrice, totalPackFee, updateData, useVipPrice, totalOriginPrice, orderCostSummary, setCoupons, userPoints, setUserPoints, setPointDeductionRule, setOldOrder, //返回商品信息 returnGoods, //优惠券列表 backendCoupons, allGoods, //就餐类型 dinnerType, setDinnerType, setSeatFeeConfig, seatFeeConfig, shopInfo, //新客立减数据 consumeDiscount, //新客立减金额 newUserDiscount, getAllGoodsList, //清空配置 clearOrderConfig, //满减活动 fullReductionActivities, isFreeDine, //是否使用霸王餐 // 商家霸王餐配置 freeDineConfig, //限时折扣 limitTimeDiscount, }; });