更新代客下单

This commit is contained in:
gyq
2025-11-12 16:03:46 +08:00
parent 0f72c123a0
commit 383ce730a1
6 changed files with 404 additions and 31 deletions

View File

@@ -7,14 +7,14 @@ VITE_APP_BASE_API=/dev-api
# 接口地址 # 接口地址
# VITE_APP_API_URL=https://tapi.cashier.sxczgkj.cn/ # 测试 # VITE_APP_API_URL=https://tapi.cashier.sxczgkj.cn/ # 测试
VITE_APP_API_URL=https://cashier.sxczgkj.com/ # 正式 # VITE_APP_API_URL=https://cashier.sxczgkj.com/ # 正式
# VITE_APP_API_URL=http://192.168.1.42/ # 本地 VITE_APP_API_URL=http://192.168.1.42/ # 本地
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws # WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws
# VITE_APP_WS_ENDPOINT=wss://sockets.sxczgkj.com/wss # VITE_APP_WS_ENDPOINT=wss://sockets.sxczgkj.com/wss
VITE_APP_WS_ENDPOINT=wss://czgeatws.sxczgkj.com/wss # 正式 # VITE_APP_WS_ENDPOINT=wss://czgeatws.sxczgkj.com/wss # 正式
# VITE_APP_WS_ENDPOINT=ws://192.168.1.42:2348 # 本地 VITE_APP_WS_ENDPOINT=ws://192.168.1.42:2348 # 本地
# 启用 Mock 服务 # 启用 Mock 服务

View File

@@ -69,7 +69,7 @@
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-i18n": "^11.1.0", "vue-i18n": "^11.1.0",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
"ysk-utils": "^1.0.50" "ysk-utils": "^1.0.59"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^19.7.1", "@commitlint/cli": "^19.7.1",

View File

@@ -21,6 +21,9 @@ import {
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
import { canUseLimitTimeDiscount, returnPrice } from '@/utils/order-utils' import { canUseLimitTimeDiscount, returnPrice } from '@/utils/order-utils'
import yskUtils from 'ysk-utils'
// const limitUtils = yskUtils.limitUtils
import limitUtils from './limit'
const shopUser = useUserStoreHook(); const shopUser = useUserStoreHook();
export interface CartsState { export interface CartsState {
@@ -37,7 +40,6 @@ interface PointDeductionRule {
maxDeductionAmount: number; maxDeductionAmount: number;
} }
export const useCartsStore = defineStore("carts", () => { export const useCartsStore = defineStore("carts", () => {
// ------------------------------ 1. 移到内部的工具函数(核心修复) ------------------------------ // ------------------------------ 1. 移到内部的工具函数(核心修复) ------------------------------
// 适配工具库 BaseCartItem 接口的商品数据转换函数(原外部函数,现在内部) // 适配工具库 BaseCartItem 接口的商品数据转换函数(原外部函数,现在内部)
@@ -61,13 +63,12 @@ export const useCartsStore = defineStore("carts", () => {
return { return {
id: item.id, id: item.id,
product_id: item.product_id, product_id: item.product_id,
salePrice: item.salePrice || 0,
number: item.number || 0, number: item.number || 0,
product_type: productType, product_type: productType,
is_temporary: !!item.is_temporary, is_temporary: !!item.is_temporary,
is_gift: !!item.is_gift, is_gift: !!item.is_gift,
returnNum: item.returnNum || 0, returnNum: item.returnNum || 0,
memberPrice: item.memberPrice || 0, memberPrice: item.is_time_discount == 1 ? item.limitDiscountPrice : (item.memberPrice || 0),
discountSaleAmount: item.discount_sale_amount || 0, discountSaleAmount: item.discount_sale_amount || 0,
packFee: item.packFee || 0, packFee: item.packFee || 0,
packNumber: item.pack_number || 0, packNumber: item.pack_number || 0,
@@ -79,9 +80,9 @@ export const useCartsStore = defineStore("carts", () => {
} }
: undefined, : undefined,
skuData, skuData,
is_time_discount: item.isTimeDiscount, is_time_discount: item.is_time_discount,
isTimeDiscount: item.isTimeDiscount, isTimeDiscount: item.is_time_discount,
salePrice: item.limitDiscountPrice salePrice: item.limitDiscountPrice || 0
}; };
}; };
@@ -97,18 +98,21 @@ export const useCartsStore = defineStore("carts", () => {
// console.log('list=====================================', list.value); // console.log('list=====================================', list.value);
// console.log('giftList=====================================', giftList.value); // console.log('giftList=====================================', giftList.value);
// console.log('oldOrder.value.detailMap=====================================', oldOrder.value.detailMap); // console.log('oldOrder.value.detailMap=====================================', oldOrder.value.detailMap);
// console.log('getAllGoodsList.[]===================', [...currentGoods, ...giftGoods, ...oldOrderGoods])
console.log('getAllGoodsList.[]===================', [...currentGoods, ...giftGoods, ...oldOrderGoods])
return [...currentGoods, ...giftGoods, ...oldOrderGoods]; return [...currentGoods, ...giftGoods, ...oldOrderGoods];
}; };
const limitDiscountRes = ref(null) const limitDiscountRes = ref<Record<string, any> | null>(null);
// ------------------------------ 2. Store 内部原有响应式变量 ------------------------------ // ------------------------------ 2. Store 内部原有响应式变量 ------------------------------
// 选择用户 // 选择用户
const vipUser = ref<{ id?: string | number, isVip?: boolean }>({}); const vipUser = ref<{ id?: string | number, isVip?: boolean }>({});
function changeUser(user: any) { function changeUser(user: any) {
vipUser.value = user; vipUser.value = {
...user,
isMemberPrice: shopUser.userInfo.isMemberPrice
};
getGoods({})
payParamsInit() payParamsInit()
} }
@@ -169,9 +173,10 @@ export const useCartsStore = defineStore("carts", () => {
}) })
// 获取满减活动 // 获取满减活动
fullReductionActivities.value = await limitTimeDiscountApi.getDiscountActivity({ const fullReductionRes = await limitTimeDiscountApi.getDiscountActivity({
shopId: localStorage.getItem("shopId") shopId: localStorage.getItem("shopId")
}) });
fullReductionActivities.value = fullReductionRes?.data || [];
if (limitDiscountRes.value !== null) { if (limitDiscountRes.value !== null) {
checkLinkFinished().then(() => { checkLinkFinished().then(() => {
@@ -195,13 +200,41 @@ export const useCartsStore = defineStore("carts", () => {
...query, ...query,
}); });
const shopInfo = JSON.parse(localStorage.getItem('userInfo')) const shopInfoStr = localStorage.getItem('userInfo') || '{}';
goods.value = res.records.map(item => { const shopInfo = JSON.parse(shopInfoStr);
interface ProductItem {
id: string | number;
lowMemberPrice?: number;
lowPrice?: number;
[key: string]: any;
}
interface LimitDiscountResult {
discountPriority?: 'limit-time' | 'vip-price' | string;
[key: string]: any;
}
interface GoodsWithDiscount extends ProductItem {
isLimitDiscount: boolean;
limitDiscountPrice: number;
}
const shopInfoTyped = shopInfo as Record<string, any>;
const ldRes = limitDiscountRes.value as LimitDiscountResult | null;
goods.value = (res.records as ProductItem[]).map((item: ProductItem): GoodsWithDiscount => {
return { return {
...item, ...item,
isLimitDiscount: limitDiscountRes.value !== null && canUseLimitTimeDiscount(item, limitDiscountRes.value, shopInfo, vipUser.value), isLimitDiscount: ldRes !== null && limitUtils.canUseLimitTimeDiscount(item, ldRes, shopInfoTyped, vipUser.value, 'id'),
limitDiscountPrice: limitDiscountRes.value !== null && returnPrice({ goods: { ...item, memberPrice: item.lowMemberPrice, salePrice: item.lowPrice }, shopInfo: shopInfo, limitTimeDiscountRes: limitDiscountRes.value, shopUserInfo: vipUser.value, idKey: 'id' }) limitDiscountPrice: limitUtils.returnPrice({
} goods: { ...item, memberPrice: item.lowMemberPrice, salePrice: item.lowPrice },
shopInfo: shopInfoTyped,
limitTimeDiscountRes: ldRes,
shopUserInfo: vipUser.value,
idKey: 'id'
})
} as GoodsWithDiscount;
}); });
console.log('代客下单页面商品缓存.goods.value', goods.value); console.log('代客下单页面商品缓存.goods.value', goods.value);
@@ -292,8 +325,7 @@ export const useCartsStore = defineStore("carts", () => {
pointsPerYuan: 100, pointsPerYuan: 100,
maxDeductionAmount: Infinity maxDeductionAmount: Infinity
}) })
const fullReductionActivities = ref<any[]>([])
const fullReductionActivities = ref([])
//使用积分数量 //使用积分数量
const userPoints = ref(0); const userPoints = ref(0);
@@ -364,8 +396,8 @@ export const useCartsStore = defineStore("carts", () => {
// 订单费用汇总(调用内部的 getAllGoodsList // 订单费用汇总(调用内部的 getAllGoodsList
const orderCostSummary = computed(() => { const orderCostSummary = computed(() => {
allGoods.value = getAllGoodsList(); allGoods.value = getAllGoodsList();
console.log(' allGoods.value+++++++++++++++++++++++++', allGoods.value); console.log('allGoods.value+++++++++++++++++++++++++', allGoods.value);
console.log(' orderExtraConfig.value', orderExtraConfig.value); console.log('orderExtraConfig.value', orderExtraConfig.value);
const costSummary = OrderPriceCalculator.calculateOrderCostSummary( const costSummary = OrderPriceCalculator.calculateOrderCostSummary(
allGoods.value, allGoods.value,
dinnerType.value, dinnerType.value,
@@ -614,8 +646,6 @@ export const useCartsStore = defineStore("carts", () => {
giftList.value = []; giftList.value = [];
cartOrder.value = {}; cartOrder.value = {};
userPoints.value = 0; userPoints.value = 0;
} }
interface GroupSnap { interface GroupSnap {

345
src/store/modules/limit.ts Normal file
View File

@@ -0,0 +1,345 @@
import BigNumber from "bignumber.js";
import _ from "lodash";
export interface Goods {
productId: string | number; // 商品ID唯一标识商品用于优惠券/活动匹配,必选)
skuId: string | number; // 商品规格ID唯一标识商品规格如颜色/尺寸)
id: string | number; // 购物车ID唯一标识购物车中的条目如购物车项主键
product_id: string | number; // 商品ID唯一标识商品用于优惠券/活动匹配,必选)
salePrice: number; // 商品原价(元)
number: number; // 商品数量
product_type: string; // 商品类型
is_temporary?: number; // 是否临时菜默认false
is_gift?: number; // 是否赠菜默认false
returnNum?: number; // 退货数量历史订单用默认0
memberPrice: number; // 商品会员价(元,优先级:商品会员价 > 会员折扣)
discountSaleAmount?: number; // 商家改价后单价(元,优先级最高)
packFee?: number; // 单份打包费默认0
packNumber?: number; // 堂食打包数量默认0
skuData?: {
// SKU扩展数据可选
id: string | number; // SKU ID唯一标识商品规格如颜色/尺寸)
memberPrice?: number; // SKU会员价
salePrice?: number; // SKU原价
};
discount_sale_amount: number; // 商家改价后单价(元,优先级最高)
[property: string]: any;
}
export interface User {
isVip: number; // 是否会员 1是会员
[property: string]: any;
}
export interface ShopInfo {
isMemberPrice: number; // 是否开启会员价 1是开启
[property: string]: any;
}
export interface ThresholdFood {
id: string | number; // 商品ID
[property: string]: any;
}
export interface UseFood {
id: string | number;
[property: string]: any;
}
export interface Coupon {
id: string | number;
use: boolean;
type: number;
thresholdFoods: ThresholdFood[];
useFoods: UseFood[];
noUseRestrictions?: string;
discountShare: number; // 是否与折扣优惠同享 1是同享
vipPriceShare: number; // 是否与会员优惠同享 1是同享
otherCouponShare: number; // 是否与其他优惠券同享 1是同享
fullAmount: number; // 使用门槛金额
discountRate: number; // 折扣率(满减券:折扣金额/门槛金额,折扣券:折扣率)
maxDiscountAmount: number; // 最大折扣金额(满减券:折扣金额,折扣券:折扣金额)
discountNum: number; // 抵扣商品数量商品券抵扣商品数量折扣券0
useRule: string; // 使用规则price_asc按商品单价升序price_desc按商品单价降序
}
export interface couponDiscount {
discountPrice: number;
hasDiscountGoodsArr: Goods[];
}
export interface selCoupon extends Coupon {
discount?: couponDiscount;
}
export interface couponCalcParams {
canDikouGoodsArr: Goods[];
coupon: Coupon;
user: User;
shopInfo: ShopInfo;
selCoupon: selCoupon[];
goodsOrderPrice: number; //商品订单总价
isMemberPrice: number; // 是否开启会员价 1是开启
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
}
//限时折扣配置
export interface TimeLimitDiscountConfig {
/**
* 折扣优先级 limit-time/vip-price
*/
discountPriority: string;
/**
* 折扣% 范围1-99
*/
discountRate: number;
/**
* 参与商品
*/
foods: string;
/**
* 参与商品 1全部 2部分
*/
foodType: number;
/**
* 自增主键
*/
id: number;
/**
* 店铺ID
*/
shopId: number;
/**
* 可使用类型:堂食 dine-in 外带 take-out 外卖 take-away 配送 post
*/
useType: string;
[property: string]: any;
}
export interface CanDikouGoodsArrArgs {
canDikouGoodsArr: Goods[];
selCoupon: selCoupon[];
user: User;
shopInfo: ShopInfo;
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
}
/**
* 判断商品是否可以使用限时折扣
* @param goods 商品对象
* @param limitTimeDiscountRes 限时折扣配置
* @param shopInfo 店铺信息
* @param shopUserInfo 店铺用户信息
* @param idKey 商品ID键名默认"id"
* @returns
*/
export function canUseLimitTimeDiscount(
goods: Goods,
limitTimeDiscountRes: TimeLimitDiscountConfig | null | undefined,
shopInfo: ShopInfo,
shopUserInfo: User,
idKey = "id"
) {
shopInfo = shopInfo || {};
shopUserInfo = shopUserInfo || {};
if (!limitTimeDiscountRes || !limitTimeDiscountRes.id) {
return false;
}
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
const goodsCanUse =
limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes(`${goods[idKey]}`);
if (!goodsCanUse) {
return false;
}
if (limitTimeDiscountRes.discountPriority == "limit-time") {
return true;
}
if (limitTimeDiscountRes.discountPriority == "vip-price") {
if (goods.id == 727) {
console.log('goods', goods);
console.log('shopUserInfo', shopUserInfo);
}
if (shopUserInfo.isVip != 1 || shopUserInfo.isMemberPrice != 1) {
return true;
}
if (
shopUserInfo.isVip == 1 &&
shopUserInfo.isMemberPrice == 1 &&
goods.memberPrice * 1 <= 0
) {
return true;
}
}
return false;
}
export interface CanDikouGoodsArrArgs {
goods: Goods;
shopInfo: ShopInfo;
limitTimeDiscountRes: TimeLimitDiscountConfig | null | undefined;
shopUserInfo: User;
idKey?: string;
}
/**
* 返回商品显示价格
* @params {*} args 参数对象
* @params {*} args.goods 商品对象
* @params {*} args.shopInfo 店铺信息
* @params {*} args.limitTimeDiscountRes 限时折扣信息
* @params {*} args.shopUserInfo 店铺用户信息
* @returns
*/
export function returnPrice(args: CanDikouGoodsArrArgs) {
let {
goods,
shopInfo,
limitTimeDiscountRes,
shopUserInfo,
idKey = "product_id",
} = args;
limitTimeDiscountRes = limitTimeDiscountRes || {
foods: "",
foodType: 2,
discountPriority: "",
discountRate: 0,
id: 0,
shopId: 0,
useType: "",
};
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
const includesGoods =
limitTimeDiscountRes.foodType == 1 ||
canUseFoods.includes("" + goods[idKey]);
shopInfo = shopInfo || {};
shopUserInfo = shopUserInfo || {};
if (
shopUserInfo.isMemberPrice == 1 &&
shopUserInfo.isVip == 1 &&
shopInfo.isMemberPrice == 1
) {
const memberPrice = goods.memberPrice || goods.salePrice;
//是会员而且启用会员价
if (limitTimeDiscountRes) {
//使用限时折扣
//限时折扣优先
if (limitTimeDiscountRes.discountPriority == "limit-time") {
if (includesGoods) {
return returnLimitPrice({
price: goods.salePrice,
limitTimeDiscountRes,
});
} else {
return memberPrice;
}
}
if (
limitTimeDiscountRes.discountPriority == "vip-price" &&
includesGoods
) {
if (goods.memberPrice * 1 > 0) {
//会员优先
return memberPrice;
} else {
const price = returnLimitPrice({
price: goods.salePrice,
limitTimeDiscountRes,
goods: goods,
});
return price;
}
} else {
return memberPrice;
}
} else {
//是会员没有限时折扣
return memberPrice;
}
} else {
// console.log('不是会员或者没有启用会员价',goods,limitTimeDiscountRes);
//不是会员或者没有启用会员价
if (limitTimeDiscountRes && limitTimeDiscountRes.id && includesGoods) {
const price = returnLimitPrice({
price: goods.salePrice,
limitTimeDiscountRes,
goods: goods,
});
return price;
} else {
return goods.salePrice;
}
}
}
interface returnLimitPriceArgs {
limitTimeDiscountRes: TimeLimitDiscountConfig | null | undefined;
price: number;
goods?: Goods;
}
/**
* 返回限时折扣价格
* @params {*} args 参数对象
* @params {*} args.limitTimeDiscountRes 限时折扣信息
* @params {*} args.price 商品价格
* @param {*} args.goods 商品对象
* @returns
*/
export function returnLimitPrice(args: returnLimitPriceArgs) {
const { limitTimeDiscountRes, price, goods } = args;
const discountRate = new BigNumber(
limitTimeDiscountRes ? limitTimeDiscountRes.discountRate : 100
).dividedBy(100);
const result = BigNumber(price)
.times(discountRate)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber();
return result;
}
/**
* 判断是否返回会员价
* @param {*} args 参数对象
* @param {*} args.shopInfo 店铺信息
* @param {*} args.shopUserInfo 店铺用户信息
* @returns
*/
interface CanReturnMemberPriceArgs {
shopInfo?: ShopInfo;
shopUserInfo: User;
}
export function canReturnMemberPrice(args: CanReturnMemberPriceArgs) {
const { shopInfo, shopUserInfo } = args;
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
return true;
} else {
return false;
}
}
/**
* 返回会员价格
* @param {*} goods
* @returns
*/
export function returnMemberPrice(goods: Goods) {
return goods.memberPrice || goods.salePrice;
}
export const utils = {
returnPrice,
canUseLimitTimeDiscount,
returnLimitPrice,
canReturnMemberPrice,
returnMemberPrice,
};
export default utils;

View File

@@ -130,7 +130,7 @@ function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
position: absolute; position: absolute;
box-sizing: border-box; box-sizing: border-box;
padding: 8px; padding: 8px;
z-index: 99; z-index: 2;
inset: 0; inset: 0;
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@@ -123,7 +123,6 @@
</GoodsItem> </GoodsItem>
</div> </div>
</template> </template>
<!-- 订单信息展示 --> <!-- 订单信息展示 -->
<Order ref="refOrder" :orderInfo="carts.oldOrder" @chooseUser="showChooseUser" @paysuccess="refresh" <Order ref="refOrder" :orderInfo="carts.oldOrder" @chooseUser="showChooseUser" @paysuccess="refresh"
:table="table" :perpole="perpole" v-else :user="user"></Order> :table="table" :perpole="perpole" v-else :user="user"></Order>
@@ -148,7 +147,6 @@
<change-taocan ref="refAddTaocan" @confirm="taocanConfirm"></change-taocan> <change-taocan ref="refAddTaocan" @confirm="taocanConfirm"></change-taocan>
<!-- 选择用户 --> <!-- 选择用户 -->
<choose-user ref="refChooseUser" @chooseUser="chooseUserConfirm"></choose-user> <choose-user ref="refChooseUser" @chooseUser="chooseUserConfirm"></choose-user>
<!-- 就餐人数 --> <!-- 就餐人数 -->
<diner-number ref="refDinerNumber" @confirm="dinerNumberConfirm"></diner-number> <diner-number ref="refDinerNumber" @confirm="dinerNumberConfirm"></diner-number>
<!-- 退菜 --> <!-- 退菜 -->