Merge branch 'ymf' of https://newgitea.sxczgkj.cn/czg_team/cashier-web into gyq
This commit is contained in:
commit
0405a0fb99
|
|
@ -1,5 +1,5 @@
|
||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
const baseURL = "account/admin/";
|
const baseURL = "/account/admin/";
|
||||||
|
|
||||||
const AuthAPI = {
|
const AuthAPI = {
|
||||||
/** 登录接口*/
|
/** 登录接口*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
const baseURL = "account/admin/";
|
const baseURL = "/account/admin/";
|
||||||
|
|
||||||
const RegisterApi = {
|
const RegisterApi = {
|
||||||
/** 获取当前用户菜单列表*/
|
/** 获取当前用户菜单列表*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
const baseURL = "account/admin/role";
|
const baseURL = "/account/admin/role";
|
||||||
|
|
||||||
const RoleApi = {
|
const RoleApi = {
|
||||||
/** 获取当前用户菜单列表*/
|
/** 获取当前用户菜单列表*/
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,13 @@ export function returnCouponCanUse(args) {
|
||||||
}
|
}
|
||||||
// 商品兑换券,第二件半价和买一送一判断是否有可用商品
|
// 商品兑换券,第二件半价和买一送一判断是否有可用商品
|
||||||
if ([2, 4, 5].includes(coupon.type)) {
|
if ([2, 4, 5].includes(coupon.type)) {
|
||||||
|
if (coupon.type == 2 && fullAmount < coupon.fullAmount) {
|
||||||
|
return {
|
||||||
|
canUse: false,
|
||||||
|
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 没有符合条件的商品
|
// 没有符合条件的商品
|
||||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -210,8 +217,8 @@ export function returnCouponCanUse(args) {
|
||||||
let canUse = false;
|
let canUse = false;
|
||||||
if (isDikouAll) {
|
if (isDikouAll) {
|
||||||
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
||||||
} else if (canCalcGoodsArr.length > 0) {
|
} else if (canUseGoodsArr.length > 0) {
|
||||||
canUse = canCalcGoodsArr.some((v) => v.num >= 2);
|
canUse = canUseGoodsArr.some((v) => v.num >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canUse) {
|
if (!canUse) {
|
||||||
|
|
@ -227,10 +234,9 @@ export function returnCouponCanUse(args) {
|
||||||
let canUse = false;
|
let canUse = false;
|
||||||
if (isDikouAll) {
|
if (isDikouAll) {
|
||||||
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
||||||
} else if (canCalcGoodsArr.length > 0) {
|
} else if (canUseGoodsArr.length > 0) {
|
||||||
canUse = canCalcGoodsArr.some((v) => v.num >= 2);
|
canUse = canUseGoodsArr.some((v) => v.num >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canUse) {
|
if (!canUse) {
|
||||||
return {
|
return {
|
||||||
canUse: false,
|
canUse: false,
|
||||||
|
|
@ -265,12 +271,14 @@ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, s
|
||||||
const shengyuNum = discountNum - hasCountNum;
|
const shengyuNum = discountNum - hasCountNum;
|
||||||
const num = Math.min(goods.num, shengyuNum);
|
const num = Math.min(goods.num, shengyuNum);
|
||||||
discountPrice += returnGoodsPrice(goods, user, shopInfo) * num;
|
discountPrice += returnGoodsPrice(goods, user, shopInfo) * num;
|
||||||
|
|
||||||
hasCountNum += num;
|
hasCountNum += num;
|
||||||
hasDiscountGoodsArr.push({
|
hasDiscountGoodsArr.push({
|
||||||
...goods,
|
...goods,
|
||||||
num,
|
num,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
discountPrice,
|
discountPrice,
|
||||||
hasDiscountGoodsArr,
|
hasDiscountGoodsArr,
|
||||||
|
|
@ -287,6 +295,7 @@ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, s
|
||||||
* @param shopInfo 店铺信息
|
* @param shopInfo 店铺信息
|
||||||
*/
|
*/
|
||||||
export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoupon, shopInfo) {
|
export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoupon, shopInfo) {
|
||||||
|
arr = returnCanDikouGoods(arr, user, shopInfo);
|
||||||
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
||||||
if (coupon.type == 2) {
|
if (coupon.type == 2) {
|
||||||
return returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shopInfo);
|
return returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shopInfo);
|
||||||
|
|
@ -330,7 +339,6 @@ export function returnCouponZhekouDiscount(
|
||||||
|
|
||||||
// 将商品订单价格转换为BigNumber并减去优惠券折扣
|
// 将商品订单价格转换为BigNumber并减去优惠券折扣
|
||||||
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(goodsCouponDiscount);
|
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(goodsCouponDiscount);
|
||||||
console.log("adjustedGoodsOrderPrice", adjustedGoodsOrderPrice.toNumber());
|
|
||||||
|
|
||||||
// 计算优惠比例:(100 - 折扣率) / 100
|
// 计算优惠比例:(100 - 折扣率) / 100
|
||||||
const discountAmountRatio = new BigNumber(100).minus(discountRate).dividedBy(100);
|
const discountAmountRatio = new BigNumber(100).minus(discountRate).dividedBy(100);
|
||||||
|
|
@ -366,9 +374,7 @@ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shop
|
||||||
//抵扣全部商品
|
//抵扣全部商品
|
||||||
if (useFoods.length === 0) {
|
if (useFoods.length === 0) {
|
||||||
if (useRule == "price_asc") {
|
if (useRule == "price_asc") {
|
||||||
discountGoodsArr = canDikouGoodsArr
|
discountGoodsArr = canDikouGoodsArr.slice(discountNum * -1).reverse();
|
||||||
.slice(canDikouGoodsArr.length - discountNum, canDikouGoodsArr.length)
|
|
||||||
.reverse();
|
|
||||||
} else {
|
} else {
|
||||||
discountGoodsArr = canDikouGoodsArr.slice(0, discountNum);
|
discountGoodsArr = canDikouGoodsArr.slice(0, discountNum);
|
||||||
}
|
}
|
||||||
|
|
@ -378,9 +384,7 @@ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shop
|
||||||
useFoods.find((food) => food.id == v.productId)
|
useFoods.find((food) => food.id == v.productId)
|
||||||
);
|
);
|
||||||
if (useRule == "price_asc") {
|
if (useRule == "price_asc") {
|
||||||
discountGoodsArr = discountSelGoodsArr
|
discountGoodsArr = discountSelGoodsArr.slice(discountNum * -1).reverse();
|
||||||
.slice(discountSelGoodsArr.length - discountNum, discountSelGoodsArr.length)
|
|
||||||
.reverse();
|
|
||||||
} else {
|
} else {
|
||||||
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,7 @@ export interface OrderExtraConfig {
|
||||||
export interface OrderCostSummary {
|
export interface OrderCostSummary {
|
||||||
// 商品总件数
|
// 商品总件数
|
||||||
goodsTotal: number;
|
goodsTotal: number;
|
||||||
|
totalDiscountAmount: number,
|
||||||
goodsRealAmount: number; // 商品真实原价总和
|
goodsRealAmount: number; // 商品真实原价总和
|
||||||
goodsOriginalAmount: number; // 商品原价总和
|
goodsOriginalAmount: number; // 商品原价总和
|
||||||
goodsDiscountAmount: number; // 商品折扣金额
|
goodsDiscountAmount: number; // 商品折扣金额
|
||||||
|
|
@ -263,333 +264,10 @@ export interface OrderCostSummary {
|
||||||
pointUsed: number; // 实际使用的积分
|
pointUsed: number; // 实际使用的积分
|
||||||
newUserDiscount: number; // 新用户减免金额(元,默认0)
|
newUserDiscount: number; // 新用户减免金额(元,默认0)
|
||||||
dinnerType?: "dine-in" | "take-out"; // 就餐类型(堂食/自取/配送/快递)
|
dinnerType?: "dine-in" | "take-out"; // 就餐类型(堂食/自取/配送/快递)
|
||||||
|
config: OrderExtraConfig; // 订单额外费用配置
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================ 2. 基础工具函数(核心修正:所有商品ID匹配用product_id) ============================
|
|
||||||
/**
|
|
||||||
* 后端优惠券转工具库Coupon的转换函数
|
|
||||||
* @param backendCoupon 后端返回的优惠券
|
|
||||||
* @param currentStoreId 当前门店ID(用于验证门店适用性)
|
|
||||||
* @param dinnerType 就餐类型(用于验证使用场景)
|
|
||||||
* @param currentTime 当前时间(默认取当前时间,用于有效期判断)
|
|
||||||
* @returns 工具库 Coupon | null(不支持的券类型/无效券返回null)
|
|
||||||
*/
|
|
||||||
export function convertBackendCouponToToolCoupon(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentStoreId: string,
|
|
||||||
dinnerType: "dine-in" | "take-out",
|
|
||||||
currentTime: Date = new Date()
|
|
||||||
): Coupon | null {
|
|
||||||
// 1. 基础校验:必选字段缺失直接返回null
|
|
||||||
if (!backendCoupon.id || backendCoupon.type === undefined) {
|
|
||||||
console.warn("优惠券必选字段缺失", backendCoupon);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 转换券类型:后端数字枚举 → 工具库字符串枚举
|
|
||||||
const couponType = mapBackendCouponTypeToTool(backendCoupon.type);
|
|
||||||
if (!couponType) {
|
|
||||||
console.warn(
|
|
||||||
`不支持的优惠券类型:${backendCoupon.type}(券ID:${backendCoupon.id})`
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 统一处理所有券类型的applicableProductIds(映射后端foods,此处为商品ID列表)
|
|
||||||
const applicableProductIds =
|
|
||||||
backendCoupon.foods === "" || !backendCoupon.foods
|
|
||||||
? [] // 空字符串/undefined → 全部商品(按商品ID匹配)
|
|
||||||
: backendCoupon.foods.split(",").map((id) => id.trim()); // 逗号分隔 → 指定商品ID数组
|
|
||||||
|
|
||||||
const useType =
|
|
||||||
backendCoupon?.useType?.split(",")?.map((v) =>
|
|
||||||
v
|
|
||||||
.replace(/[\[\]]/g, "")
|
|
||||||
.replace(/""/g, '"')
|
|
||||||
.replace(/["']/g, "")
|
|
||||||
) || [];
|
|
||||||
// 4. 计算基础公共字段(含多维度可用性校验)
|
|
||||||
const baseCoupon: BaseCoupon = {
|
|
||||||
id: backendCoupon.id,
|
|
||||||
type: couponType,
|
|
||||||
name: backendCoupon.name || "",
|
|
||||||
available: isCouponAvailable(
|
|
||||||
backendCoupon,
|
|
||||||
currentStoreId,
|
|
||||||
dinnerType,
|
|
||||||
currentTime
|
|
||||||
),
|
|
||||||
useShops: getApplicableStoreIds(backendCoupon, currentStoreId),
|
|
||||||
discountShare: backendCoupon.discountShare === 1,
|
|
||||||
vipPriceShare: backendCoupon.vipPriceShare === 1,
|
|
||||||
useType: useType,
|
|
||||||
isValid: isCouponInValidPeriod(backendCoupon, currentTime),
|
|
||||||
applicableProductIds: applicableProductIds,
|
|
||||||
};
|
|
||||||
// 5. 按券类型补充专属字段
|
|
||||||
switch (couponType) {
|
|
||||||
case CouponType.FULL_REDUCTION:
|
|
||||||
return {
|
|
||||||
...baseCoupon,
|
|
||||||
fullAmount: backendCoupon.fullAmount || 0,
|
|
||||||
discountAmount: backendCoupon.discountAmount || 0,
|
|
||||||
maxDiscountAmount: backendCoupon.maxDiscountAmount ?? Infinity,
|
|
||||||
} as FullReductionCoupon;
|
|
||||||
|
|
||||||
case CouponType.DISCOUNT:
|
|
||||||
return {
|
|
||||||
...baseCoupon,
|
|
||||||
discountRate: formatDiscountRate(backendCoupon.discountRate),
|
|
||||||
maxDiscountAmount: backendCoupon.maxDiscountAmount ?? Infinity,
|
|
||||||
} as DiscountCoupon;
|
|
||||||
|
|
||||||
case CouponType.SECOND_HALF:
|
|
||||||
return {
|
|
||||||
...baseCoupon,
|
|
||||||
maxUseCountPerOrder:
|
|
||||||
backendCoupon.useLimit === -10086
|
|
||||||
? Infinity
|
|
||||||
: backendCoupon.useLimit || 1,
|
|
||||||
} as SecondHalfPriceCoupon;
|
|
||||||
|
|
||||||
case CouponType.BUY_ONE_GET_ONE:
|
|
||||||
return {
|
|
||||||
...baseCoupon,
|
|
||||||
maxUseCountPerOrder:
|
|
||||||
backendCoupon.useLimit === -10086
|
|
||||||
? Infinity
|
|
||||||
: backendCoupon.useLimit || 1,
|
|
||||||
} as BuyOneGetOneCoupon;
|
|
||||||
|
|
||||||
case CouponType.EXCHANGE:
|
|
||||||
return {
|
|
||||||
...baseCoupon,
|
|
||||||
deductCount: backendCoupon.discountNum || 1,
|
|
||||||
sortRule:
|
|
||||||
backendCoupon.useRule === "price_asc"
|
|
||||||
? "low_price_first"
|
|
||||||
: "high_price_first",
|
|
||||||
} as ExchangeCoupon;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------ 转换辅助函数 ------------------------------
|
|
||||||
/**
|
|
||||||
* 后端优惠券类型(数字)→ 工具库优惠券类型(字符串枚举)
|
|
||||||
*/
|
|
||||||
function mapBackendCouponTypeToTool(
|
|
||||||
backendType: number
|
|
||||||
): CouponType | undefined {
|
|
||||||
const typeMap: Record<number, CouponType> = {
|
|
||||||
1: CouponType.FULL_REDUCTION, // 1-满减券
|
|
||||||
2: CouponType.EXCHANGE, // 2-商品兑换券
|
|
||||||
3: CouponType.DISCOUNT, // 3-折扣券
|
|
||||||
4: CouponType.SECOND_HALF, // 4-第二件半价券
|
|
||||||
6: CouponType.BUY_ONE_GET_ONE, // 6-买一送一券
|
|
||||||
};
|
|
||||||
return typeMap[backendType];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多维度判断优惠券是否可用:状态+库存+有效期+隔天生效+每日时段+每周周期+门店+就餐类型
|
|
||||||
*/
|
|
||||||
function isCouponAvailable(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentStoreId: string,
|
|
||||||
dinnerType: "dine-in" | "take-out",
|
|
||||||
currentTime: Date = new Date()
|
|
||||||
): boolean {
|
|
||||||
// 1. 状态校验:必须启用(status=1)
|
|
||||||
if (backendCoupon.status === 0) return false;
|
|
||||||
|
|
||||||
// 3. 有效期校验:必须在有效期内
|
|
||||||
if (!isCouponInValidPeriod(backendCoupon, currentTime)) return false;
|
|
||||||
|
|
||||||
// 4. 隔天生效校验:若设置了隔天生效,需超过生效时间
|
|
||||||
if (!isCouponEffectiveAfterDays(backendCoupon, currentTime)) return false;
|
|
||||||
|
|
||||||
// 5. 每日时段校验:当前时间需在每日可用时段内(useTimeType=custom时生效)
|
|
||||||
if (!isCouponInDailyTimeRange(backendCoupon, currentTime)) return false;
|
|
||||||
|
|
||||||
// 6. 每周周期校验:当前星期几需在可用周期内(useDays非空时生效)
|
|
||||||
// if (!isCouponInWeekDays(backendCoupon, currentTime)) return false;
|
|
||||||
|
|
||||||
// 7. 门店匹配校验:当前门店需在适用门店范围内
|
|
||||||
// if (!isStoreMatch(backendCoupon, currentStoreId)) return false;
|
|
||||||
|
|
||||||
// 8. 就餐类型校验:当前就餐类型需在可用类型范围内
|
|
||||||
// if (!isDinnerTypeMatch(backendCoupon, dinnerType)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断优惠券是否在有效期内(处理后端validType逻辑)
|
|
||||||
*/
|
|
||||||
function isCouponInValidPeriod(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentTime: Date
|
|
||||||
): boolean {
|
|
||||||
const { validType, validStartTime, validEndTime, validDays, createTime } =
|
|
||||||
backendCoupon;
|
|
||||||
|
|
||||||
// 固定时间有效期(validType=fixed):直接对比validStartTime和validEndTime
|
|
||||||
if (validType === "fixed" && validStartTime && validEndTime) {
|
|
||||||
const start = new Date(validStartTime);
|
|
||||||
const end = new Date(validEndTime);
|
|
||||||
return currentTime >= start && currentTime <= end;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自定义天数有效期(validType=custom):创建时间+validDays天
|
|
||||||
if (validType === "custom" && createTime && validDays) {
|
|
||||||
const create = new Date(createTime);
|
|
||||||
const end = new Date(create.getTime() + validDays * 24 * 60 * 60 * 1000); // 加N天
|
|
||||||
|
|
||||||
return currentTime <= end;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 无有效期配置:默认视为无效
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 隔天生效校验:若设置了daysToTakeEffect,需超过生效时间(创建时间+N天的0点)
|
|
||||||
*/
|
|
||||||
function isCouponEffectiveAfterDays(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentTime: Date
|
|
||||||
): boolean {
|
|
||||||
if (!backendCoupon.daysToTakeEffect || backendCoupon.daysToTakeEffect <= 0)
|
|
||||||
return true;
|
|
||||||
if (!backendCoupon.createTime) return false;
|
|
||||||
|
|
||||||
const create = new Date(backendCoupon.createTime);
|
|
||||||
const effectiveTime = new Date(create);
|
|
||||||
effectiveTime.setDate(create.getDate() + backendCoupon.daysToTakeEffect);
|
|
||||||
effectiveTime.setHours(0, 0, 0, 0); // 隔天0点生效
|
|
||||||
|
|
||||||
return currentTime >= effectiveTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每日时段校验:当前时间需在useStartTime和useEndTime之间(仅比较时分秒,支持跨天)
|
|
||||||
*/
|
|
||||||
function isCouponInDailyTimeRange(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentTime: Date
|
|
||||||
): boolean {
|
|
||||||
// 全时段可用或未配置时段类型 → 直接通过
|
|
||||||
if (backendCoupon.useTimeType === "all" || !backendCoupon.useTimeType)
|
|
||||||
return true;
|
|
||||||
// 非自定义时段 → 默认可用(兼容未配置场景)
|
|
||||||
if (backendCoupon.useTimeType !== "custom") return true;
|
|
||||||
// 缺少时段配置 → 无效
|
|
||||||
if (!backendCoupon.useStartTime || !backendCoupon.useEndTime) return false;
|
|
||||||
|
|
||||||
// 解析时分(如"10:30" → [10, 30])
|
|
||||||
const [startHours, startMinutes] = backendCoupon.useStartTime
|
|
||||||
.split(":")
|
|
||||||
.map(Number);
|
|
||||||
const [endHours, endMinutes] = backendCoupon.useEndTime
|
|
||||||
.split(":")
|
|
||||||
.map(Number);
|
|
||||||
|
|
||||||
// 转换为当天分钟数(便于比较)
|
|
||||||
const currentMinutes = currentTime.getHours() * 60 + currentTime.getMinutes();
|
|
||||||
const startTotalMinutes = startHours * 60 + startMinutes;
|
|
||||||
const endTotalMinutes = endHours * 60 + endMinutes;
|
|
||||||
|
|
||||||
// 处理跨天场景(如22:00-02:00)
|
|
||||||
if (startTotalMinutes <= endTotalMinutes) {
|
|
||||||
return (
|
|
||||||
currentMinutes >= startTotalMinutes && currentMinutes <= endTotalMinutes
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
currentMinutes >= startTotalMinutes || currentMinutes <= endTotalMinutes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每周周期校验:当前星期几需在useDays范围内(如"周一,周二")
|
|
||||||
*/
|
|
||||||
function isCouponInWeekDays(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentTime: Date
|
|
||||||
): boolean {
|
|
||||||
if (!backendCoupon.useDays) return true; // 未配置周期 → 默认可用
|
|
||||||
|
|
||||||
// 星期映射:getDay()返回0=周日,1=周一...6=周六
|
|
||||||
const weekDayMap = {
|
|
||||||
0: "周七",
|
|
||||||
1: "周一",
|
|
||||||
2: "周二",
|
|
||||||
3: "周三",
|
|
||||||
4: "周四",
|
|
||||||
5: "周五",
|
|
||||||
6: "周六",
|
|
||||||
};
|
|
||||||
const currentWeekDay =
|
|
||||||
weekDayMap[currentTime.getDay() as keyof typeof weekDayMap];
|
|
||||||
return backendCoupon.useDays.split(",").includes(currentWeekDay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 门店匹配校验:根据useShopType判断当前门店是否适用
|
|
||||||
*/
|
|
||||||
function isStoreMatch(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentStoreId: string
|
|
||||||
): boolean {
|
|
||||||
const { useShopType, useShops, shopId } = backendCoupon;
|
|
||||||
|
|
||||||
switch (useShopType) {
|
|
||||||
case "all": // 所有门店适用
|
|
||||||
return true;
|
|
||||||
case "custom": // 指定门店适用(useShops逗号分割,门店ID)
|
|
||||||
return useShops ? useShops.split(",").includes(currentStoreId) : false;
|
|
||||||
case "only": // 仅本店适用(shopId为门店ID)
|
|
||||||
return shopId ? String(shopId) === currentStoreId : false;
|
|
||||||
default: // 未配置 → 默认为仅本店
|
|
||||||
return shopId ? String(shopId) === currentStoreId : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 就餐类型匹配校验:当前就餐类型需在useType范围内(如"dine,pickup")
|
|
||||||
*/
|
|
||||||
function isDinnerTypeMatch(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
dinnerType: string
|
|
||||||
): boolean {
|
|
||||||
if (!backendCoupon.useType) return true; // 未配置 → 默认可用
|
|
||||||
return backendCoupon.useType.split(",").includes(dinnerType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理适用门店ID:根据useShopType返回对应数组(供BaseCoupon使用)
|
|
||||||
*/
|
|
||||||
function getApplicableStoreIds(
|
|
||||||
backendCoupon: BackendCoupon,
|
|
||||||
currentStoreId: string
|
|
||||||
): string[] {
|
|
||||||
const { useShopType, useShops, shopId } = backendCoupon;
|
|
||||||
|
|
||||||
switch (useShopType) {
|
|
||||||
case "all": // 所有门店适用:返回空数组(工具库空数组表示无限制)
|
|
||||||
return [];
|
|
||||||
case "custom": // 指定门店适用:useShops逗号分割转数组(门店ID)
|
|
||||||
return useShops ? useShops.split(",").map((id) => id.trim()) : [];
|
|
||||||
case "only": // 仅当前店铺适用:返回shopId(转字符串,门店ID)
|
|
||||||
return shopId ? [shopId.toString()] : [];
|
|
||||||
default: // 未配置:默认仅当前门店适用
|
|
||||||
return [currentStoreId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 折扣率格式化:后端discountRate(%)→ 工具库小数(如90→0.9)
|
* 折扣率格式化:后端discountRate(%)→ 工具库小数(如90→0.9)
|
||||||
|
|
@ -1406,25 +1084,7 @@ function isStoreMatchByList(
|
||||||
return useShops.includes(currentStoreId);
|
return useShops.includes(currentStoreId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 优惠券计算策略工厂(根据优惠券类型获取对应策略,易扩展)
|
|
||||||
*/
|
|
||||||
function getCouponStrategy(couponType: CouponType): CouponCalculationStrategy {
|
|
||||||
switch (couponType) {
|
|
||||||
case CouponType.FULL_REDUCTION:
|
|
||||||
return new FullReductionStrategy();
|
|
||||||
case CouponType.DISCOUNT:
|
|
||||||
return new DiscountStrategy();
|
|
||||||
case CouponType.SECOND_HALF:
|
|
||||||
return new SecondHalfPriceStrategy();
|
|
||||||
case CouponType.BUY_ONE_GET_ONE:
|
|
||||||
return new BuyOneGetOneStrategy();
|
|
||||||
case CouponType.EXCHANGE:
|
|
||||||
return new ExchangeCouponStrategy();
|
|
||||||
default:
|
|
||||||
throw new Error(`不支持的优惠券类型:${couponType}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算优惠券抵扣金额(处理互斥逻辑,选择最优优惠券,按商品ID排除,新增细分统计)
|
* 计算优惠券抵扣金额(处理互斥逻辑,选择最优优惠券,按商品ID排除,新增细分统计)
|
||||||
|
|
@ -1502,15 +1162,18 @@ export function calcTotalPackFee(
|
||||||
goodsList: BaseCartItem[],
|
goodsList: BaseCartItem[],
|
||||||
dinnerType: "dine-in" | "take-out"
|
dinnerType: "dine-in" | "take-out"
|
||||||
): number {
|
): number {
|
||||||
if (dinnerType !== "take-out") return 0;
|
// if (dinnerType !== "take-out") return 0;
|
||||||
let total = new BigNumber(0);
|
let total = new BigNumber(0);
|
||||||
|
|
||||||
for (const goods of goodsList) {
|
for (const goods of goodsList) {
|
||||||
const availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
|
const packNumber = goods.packNumber ? goods.packNumber * 1 : 0;
|
||||||
|
let availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
|
||||||
|
availableNum = Math.min(availableNum, packNumber);
|
||||||
|
|
||||||
if (availableNum === 0) continue;
|
if (availableNum === 0) continue;
|
||||||
|
|
||||||
// 计算单个商品打包数量(外卖全打包,堂食按配置,称重商品≤1)
|
// 计算单个商品打包数量(外卖全打包,堂食按配置,称重商品≤1)
|
||||||
let packNum = dinnerType === "take-out" ? availableNum : 0;
|
let packNum = availableNum;
|
||||||
if (goods.product_type === GoodsType.WEIGHT) {
|
if (goods.product_type === GoodsType.WEIGHT) {
|
||||||
packNum = Math.min(packNum, 1);
|
packNum = Math.min(packNum, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -1661,8 +1324,8 @@ export function calculateOrderCostSummary(
|
||||||
const merchantReductionConfig = config.merchantReduction;
|
const merchantReductionConfig = config.merchantReduction;
|
||||||
let merchantReductionActualAmount = 0;
|
let merchantReductionActualAmount = 0;
|
||||||
|
|
||||||
// 计算商家减免的可抵扣上限:商品实际金额 - 优惠券 - 积分(避免减免后为负)
|
// 计算商家减免的可抵扣上限:商品实际金额 - 优惠券 - 积分(避免减免后为负) 再加上餐位费和打包费
|
||||||
const maxMerchantReductionLimit = new BigNumber(goodsRealAmount)
|
let maxMerchantReductionLimit = new BigNumber(goodsRealAmount)
|
||||||
.minus(couponDeductionAmount)
|
.minus(couponDeductionAmount)
|
||||||
.minus(pointDeductionAmount)
|
.minus(pointDeductionAmount)
|
||||||
.isGreaterThan(0)
|
.isGreaterThan(0)
|
||||||
|
|
@ -1671,6 +1334,9 @@ export function calculateOrderCostSummary(
|
||||||
.minus(pointDeductionAmount)
|
.minus(pointDeductionAmount)
|
||||||
: new BigNumber(0);
|
: new BigNumber(0);
|
||||||
|
|
||||||
|
maxMerchantReductionLimit = maxMerchantReductionLimit.plus(seatFee).plus(packFee)
|
||||||
|
|
||||||
|
|
||||||
switch (merchantReductionConfig.type) {
|
switch (merchantReductionConfig.type) {
|
||||||
case MerchantReductionType.FIXED_AMOUNT:
|
case MerchantReductionType.FIXED_AMOUNT:
|
||||||
// 固定金额减免:取配置金额与上限的最小值,且不小于0
|
// 固定金额减免:取配置金额与上限的最小值,且不小于0
|
||||||
|
|
@ -1707,18 +1373,42 @@ export function calculateOrderCostSummary(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 最终实付金额计算(整合所有费用)
|
// 5. 最终实付金额计算(整合所有费用)
|
||||||
const finalPayAmount = new BigNumber(goodsOriginalAmount) // 商品原价总和
|
// 先计算减去所有折扣后的金额,并确保最小值为0
|
||||||
|
const discountedAmount = new BigNumber(goodsOriginalAmount) // 商品原价总和
|
||||||
.minus(goodsDiscountAmount) // 减去商品折扣
|
.minus(goodsDiscountAmount) // 减去商品折扣
|
||||||
.minus(couponDeductionAmount) // 减去优惠券抵扣
|
.minus(couponDeductionAmount) // 减去优惠券抵扣
|
||||||
.minus(newUserDiscount) // 新客立减
|
.minus(newUserDiscount) // 新客立减
|
||||||
.minus(pointDeductionAmount) // 减去积分抵扣
|
.minus(pointDeductionAmount) // 减去积分抵扣
|
||||||
.minus(merchantReductionActualAmount) // 减去商家实际减免金额
|
// .minus(merchantReductionActualAmount); // 减去商家实际减免金额
|
||||||
|
|
||||||
|
// 确保折扣后金额不小于0,再加上后续费用
|
||||||
|
const nonNegativeAmount = discountedAmount.gt(0) ? discountedAmount : new BigNumber(0);
|
||||||
|
const finalPayAmount = nonNegativeAmount
|
||||||
.plus(seatFee) // 加上餐位费(不参与减免)
|
.plus(seatFee) // 加上餐位费(不参与减免)
|
||||||
.plus(packFee) // 加上打包费(不参与减免)
|
.plus(packFee) // 加上打包费(不参与减免)
|
||||||
.plus(additionalFee); // 加上附加费
|
.plus(additionalFee) // 加上附加费
|
||||||
|
.minus(merchantReductionActualAmount); // 减去商家实际减免金额
|
||||||
|
|
||||||
|
|
||||||
const finalPayAmountNonNegative = Math.max(0, finalPayAmount.toNumber());
|
const finalPayAmountNonNegative = Math.max(0, finalPayAmount.toNumber());
|
||||||
|
|
||||||
|
//计算全部的优惠金额
|
||||||
|
const totalDiscountAmount = new BigNumber(goodsDiscountAmount) // 商品折扣
|
||||||
|
.plus(couponDeductionAmount) // 减去优惠券抵扣
|
||||||
|
.plus(newUserDiscount) // 新客立减
|
||||||
|
.plus(pointDeductionAmount) // 减去积分抵扣
|
||||||
|
.plus(merchantReductionActualAmount).toNumber(); // 减去商家实际减免金额
|
||||||
|
|
||||||
|
//最原始价格
|
||||||
|
const originalAmount = new BigNumber(goodsRealAmount) // 商品真实原价总和
|
||||||
|
.minus(goodsDiscountAmount) // 减去商品折扣
|
||||||
|
.minus(couponDeductionAmount) // 减去优惠券抵扣
|
||||||
|
.minus(newUserDiscount) // 新客立减
|
||||||
|
.minus(pointDeductionAmount) // 减去积分抵扣
|
||||||
|
.minus(merchantReductionActualAmount).toNumber(); // 减去商家实际减免金额
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 6. 返回完整费用汇总(包含商家减免明细)
|
// 6. 返回完整费用汇总(包含商家减免明细)
|
||||||
return {
|
return {
|
||||||
// 商品总件数
|
// 商品总件数
|
||||||
|
|
@ -1732,7 +1422,8 @@ export function calculateOrderCostSummary(
|
||||||
pointDeductionAmount,
|
pointDeductionAmount,
|
||||||
seatFee,
|
seatFee,
|
||||||
packFee,
|
packFee,
|
||||||
|
// 全部优惠金额
|
||||||
|
totalDiscountAmount,
|
||||||
// 商家减免明细(含类型、原始配置、实际金额)
|
// 商家减免明细(含类型、原始配置、实际金额)
|
||||||
merchantReduction: {
|
merchantReduction: {
|
||||||
type: merchantReductionConfig.type,
|
type: merchantReductionConfig.type,
|
||||||
|
|
@ -1745,6 +1436,7 @@ export function calculateOrderCostSummary(
|
||||||
pointUsed: usedPoints,
|
pointUsed: usedPoints,
|
||||||
newUserDiscount,
|
newUserDiscount,
|
||||||
dinnerType,
|
dinnerType,
|
||||||
|
config
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1761,9 +1453,6 @@ export const OrderPriceCalculator = {
|
||||||
formatDiscountRate,
|
formatDiscountRate,
|
||||||
filterThresholdGoods,
|
filterThresholdGoods,
|
||||||
isWeightGoods,
|
isWeightGoods,
|
||||||
// 优惠券转换
|
|
||||||
convertBackendCouponToToolCoupon,
|
|
||||||
mapBackendCouponTypeToTool,
|
|
||||||
// 商品价格计算
|
// 商品价格计算
|
||||||
calcSingleGoodsRealPrice,
|
calcSingleGoodsRealPrice,
|
||||||
calcGoodsOriginalAmount,
|
calcGoodsOriginalAmount,
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,14 @@
|
||||||
<!-- 打包费 -->
|
<!-- 打包费 -->
|
||||||
<template v-if="carts.packNum > 0">
|
<template v-if="carts.packNum > 0">
|
||||||
<div class="cart-title"><span>打包费</span></div>
|
<div class="cart-title"><span>打包费</span></div>
|
||||||
<extra-fee name="打包费" :number="carts.packNum" :price="carts.packFee"></extra-fee>
|
<extra-fee
|
||||||
|
name="打包费"
|
||||||
|
:number="carts.packNum"
|
||||||
|
:price="carts.orderCostSummary.packFee"
|
||||||
|
></extra-fee>
|
||||||
</template>
|
</template>
|
||||||
<!-- 餐位费 -->
|
<!-- 餐位费 -->
|
||||||
<template v-if="perpole >= 1">
|
<template v-if="perpole >= 1 && carts.dinnerType == 'dine-in'">
|
||||||
<div class="cart-title"><span>餐位费</span></div>
|
<div class="cart-title"><span>餐位费</span></div>
|
||||||
<extra-fee name="餐位费" :number="perpole" :price="canWeiFee"></extra-fee>
|
<extra-fee name="餐位费" :number="perpole" :price="canWeiFee"></extra-fee>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,15 @@
|
||||||
<span class="u-font-14">不使用</span>
|
<span class="u-font-14">不使用</span>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
<el-radio :value="0" :disabled="!pointsRes.usable">
|
<el-radio :value="0" :disabled="!pointsRes.usable">
|
||||||
<span class="u-font-14">全部抵扣</span>
|
<span class="u-font-14">使用</span>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
<el-radio :value="1" :disabled="!pointsRes.usable">
|
<!-- <el-radio :value="1" :disabled="!pointsRes.usable">
|
||||||
<span class="u-font-14">部分抵扣</span>
|
<span class="u-font-14">部分抵扣</span>
|
||||||
</el-radio>
|
</el-radio> -->
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
class="u-m-l-10"
|
class="u-m-l-10"
|
||||||
v-if="score.sel == 1"
|
v-if="score.sel != -1"
|
||||||
v-model="usePointsNumber"
|
v-model="usePointsNumber"
|
||||||
step-strictly
|
step-strictly
|
||||||
:step="pointsRes.equivalentPoints"
|
:step="pointsRes.equivalentPoints"
|
||||||
|
|
@ -168,11 +168,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="u-flex u-m-b-10 u-row-between">
|
<div class="u-flex u-m-b-10 u-row-between">
|
||||||
<span class="title">商品优惠券</span>
|
<span class="title">商品优惠券</span>
|
||||||
<span class="u-m-l-10 value">¥{{ productCouponDiscountAmount }}</span>
|
<span class="u-m-l-10 value">-¥{{ productCouponDiscountAmount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="u-flex u-m-b-10 u-row-between">
|
<div class="u-flex u-m-b-10 u-row-between">
|
||||||
<span class="title">满减优惠券</span>
|
<span class="title">其他优惠券</span>
|
||||||
<span class="u-m-l-10 value">¥{{ fullCouponDiscountAmount }}</span>
|
<span class="u-m-l-10 value">-¥{{ fullCouponDiscountAmount }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="u-flex u-m-b-10 u-row-between">
|
<div class="u-flex u-m-b-10 u-row-between">
|
||||||
|
|
@ -253,11 +253,7 @@ function refGuaZhangConfirm(guazhangRen) {
|
||||||
function refGuaZhangShow() {
|
function refGuaZhangShow() {
|
||||||
refGuaZhang.value.open();
|
refGuaZhang.value.open();
|
||||||
}
|
}
|
||||||
//商品列表
|
|
||||||
let goodsArr = [];
|
|
||||||
|
|
||||||
//优惠券
|
|
||||||
let $goodsPayPriceMap = {};
|
|
||||||
const refCoupon = ref();
|
const refCoupon = ref();
|
||||||
let quansSelArr = ref([]);
|
let quansSelArr = ref([]);
|
||||||
function openCoupon() {
|
function openCoupon() {
|
||||||
|
|
@ -276,10 +272,6 @@ function refCouponConfirm(e, goodsList) {
|
||||||
title: v.name,
|
title: v.name,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
goodsArr = goodsList;
|
|
||||||
usePointsNumber.value = 0;
|
|
||||||
pointsDiscountAmount.value = 0;
|
|
||||||
score.sel = -1;
|
|
||||||
console.log("refCouponConfirm", e);
|
console.log("refCouponConfirm", e);
|
||||||
carts.setCoupons(e);
|
carts.setCoupons(e);
|
||||||
|
|
||||||
|
|
@ -294,7 +286,6 @@ function delQuan(row) {
|
||||||
}
|
}
|
||||||
carts.setCoupons(quansSelArr.value);
|
carts.setCoupons(quansSelArr.value);
|
||||||
}
|
}
|
||||||
function couponChange(data) {}
|
|
||||||
|
|
||||||
//打折
|
//打折
|
||||||
const refDiscount = ref();
|
const refDiscount = ref();
|
||||||
|
|
@ -316,25 +307,40 @@ function discountConfirm(e) {
|
||||||
usePointsNumber.value = 0;
|
usePointsNumber.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//计算商家减免前金额
|
// 计算商家减免前金额(使用bignumber.js确保精度)
|
||||||
function returnMerchantReductionDiscount() {
|
function returnMerchantReductionDiscount() {
|
||||||
const {
|
const {
|
||||||
goodsOriginalAmount, // 商品原价总和
|
goodsOriginalAmount, // 商品原价总和
|
||||||
goodsDiscountAmount, // 减去商品折扣
|
goodsDiscountAmount, // 商品折扣
|
||||||
couponDeductionAmount, // 减去优惠券抵扣
|
couponDeductionAmount, // 优惠券抵扣
|
||||||
pointDeductionAmount, // 减去积分抵扣
|
pointDeductionAmount, // 积分抵扣
|
||||||
merchantReductionActualAmount, // 减去商家实际减免金额
|
seatFee, // 餐位费(不参与减免)
|
||||||
seatFee, // 加上餐位费(不参与减免)
|
packFee, // 打包费(不参与减免)
|
||||||
packFee, // 加上打包费(不参与减免)
|
|
||||||
additionalFee,
|
additionalFee,
|
||||||
} = carts.orderCostSummary;
|
} = carts.orderCostSummary;
|
||||||
const total =
|
|
||||||
goodsOriginalAmount - // 商品原价总和
|
|
||||||
goodsDiscountAmount - // 减去商品折扣
|
|
||||||
couponDeductionAmount; // 减去优惠券抵扣
|
|
||||||
|
|
||||||
return total <= 0 ? 0 : total;
|
// 将所有金额转换为BigNumber实例
|
||||||
|
const originalAmount = new BigNumber(goodsOriginalAmount);
|
||||||
|
const discountAmount = new BigNumber(goodsDiscountAmount);
|
||||||
|
const couponAmount = new BigNumber(couponDeductionAmount);
|
||||||
|
const pointAmount = new BigNumber(pointDeductionAmount);
|
||||||
|
const seat = new BigNumber(seatFee);
|
||||||
|
const pack = new BigNumber(packFee);
|
||||||
|
const additional = new BigNumber(additionalFee);
|
||||||
|
|
||||||
|
// 按照原逻辑进行精确计算
|
||||||
|
const total = originalAmount
|
||||||
|
.minus(discountAmount) // 减去商品折扣
|
||||||
|
.minus(couponAmount) // 减去优惠券抵扣
|
||||||
|
.minus(pointAmount) // 减去积分抵扣
|
||||||
|
.plus(seat) // 加上餐位费
|
||||||
|
.plus(pack) // 加上打包费
|
||||||
|
.plus(additional); // 加上附加费
|
||||||
|
|
||||||
|
// 确保结果不小于0,返回数字类型
|
||||||
|
return total.lte(0) ? 0 : total.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
function discountShow(e) {
|
function discountShow(e) {
|
||||||
refDiscount.value.open({
|
refDiscount.value.open({
|
||||||
// amount: carts.goodsTotal - productCouponDiscountAmount.value,
|
// amount: carts.goodsTotal - productCouponDiscountAmount.value,
|
||||||
|
|
@ -399,29 +405,28 @@ const pointsRes = ref({ usable: true, maxUsablePoints: 0, minDeductionPoints: 0
|
||||||
const usePointsNumber = ref(0);
|
const usePointsNumber = ref(0);
|
||||||
//积分可抵扣最大金额
|
//积分可抵扣最大金额
|
||||||
const scoreMaxMoney = computed(() => {
|
const scoreMaxMoney = computed(() => {
|
||||||
return carts.orderCostSummary.finalPayAmount - carts.orderCostSummary.pointDeductionAmount;
|
return (
|
||||||
|
carts.orderCostSummary.finalPayAmount +
|
||||||
|
carts.orderCostSummary.pointDeductionAmount -
|
||||||
|
carts.orderCostSummary.merchantReduction.actualAmount
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const pointsDiscountAmount = ref(0);
|
|
||||||
watch(
|
watch(
|
||||||
() => scoreMaxMoney.value,
|
() => scoreMaxMoney.value,
|
||||||
(newval) => {
|
(newval, oldval) => {
|
||||||
pointsInit();
|
if (newval != oldval) {
|
||||||
|
pointsInit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 返回积分抵扣前金额
|
|
||||||
function returnPointsDiscountAmount() {
|
|
||||||
const total = currentpayMoney.value * 1 + carts.orderCostSummary.pointDeductionAmount * 1;
|
|
||||||
return total <= 0 ? 0 : total;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function pointsInit() {
|
async function pointsInit() {
|
||||||
if (!props.user.id) {
|
if (!props.user.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const res = await PointsApi.calcOrderUsablePoints({
|
const res = await PointsApi.calcOrderUsablePoints({
|
||||||
shopUserId: props.user.id,
|
shopUserId: props.user.id,
|
||||||
orderAmount: returnPointsDiscountAmount(),
|
orderAmount: scoreMaxMoney.value,
|
||||||
});
|
});
|
||||||
pointsRes.value = res;
|
pointsRes.value = res;
|
||||||
carts.pointDeductionRule.pointsPerYuan = res.equivalentPoints;
|
carts.pointDeductionRule.pointsPerYuan = res.equivalentPoints;
|
||||||
|
|
@ -431,41 +436,17 @@ async function pointsInit() {
|
||||||
|
|
||||||
usePointsNumber.value = res.usable ? res.maxUsablePoints : 0;
|
usePointsNumber.value = res.usable ? res.maxUsablePoints : 0;
|
||||||
if (res.usable) {
|
if (res.usable) {
|
||||||
pointsToMoney();
|
|
||||||
} else {
|
} else {
|
||||||
score.sel = -1;
|
score.sel = -1;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
// 根据积分计算可抵扣金额
|
|
||||||
async function pointsToMoney() {
|
|
||||||
try {
|
|
||||||
const res = await PointsApi.calcPointsToMoney({
|
|
||||||
shopUserId: props.user.id,
|
|
||||||
orderAmount: returnPointsDiscountAmount(),
|
|
||||||
points: usePointsNumber.value,
|
|
||||||
});
|
|
||||||
if (!res) {
|
|
||||||
score.sel = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pointsDiscountAmount.value = res;
|
|
||||||
} catch (e) {
|
|
||||||
score.sel = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const emits = defineEmits(["chooseUser", "paysuccess"]);
|
const emits = defineEmits(["chooseUser", "paysuccess"]);
|
||||||
function chooseUser() {
|
function chooseUser() {
|
||||||
emits("chooseUser");
|
emits("chooseUser");
|
||||||
}
|
}
|
||||||
const coupDiscount = computed(() => {
|
|
||||||
const total =
|
|
||||||
props.orderInfo.fullCouponDiscountAmount * 1 + props.orderInfo.productCouponDiscountAmount * 1;
|
|
||||||
if (total <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return total.toFixed(2);
|
|
||||||
});
|
|
||||||
const score = reactive({
|
const score = reactive({
|
||||||
list: [],
|
list: [],
|
||||||
sel: -1,
|
sel: -1,
|
||||||
|
|
@ -480,7 +461,6 @@ watch(
|
||||||
(newval) => {
|
(newval) => {
|
||||||
console.log(newval);
|
console.log(newval);
|
||||||
usePointsNumber.value = 0;
|
usePointsNumber.value = 0;
|
||||||
pointsDiscountAmount.value = 0;
|
|
||||||
pointsInit();
|
pointsInit();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -521,7 +501,7 @@ function returnPayParams() {
|
||||||
orderId: props.orderInfo.id,
|
orderId: props.orderInfo.id,
|
||||||
// discountRatio: (checkOrderPay.discount / 100).toFixed(2),
|
// discountRatio: (checkOrderPay.discount / 100).toFixed(2),
|
||||||
discountRatio: 0,
|
discountRatio: 0,
|
||||||
seatNum: props.perpole * 1,
|
seatNum: carts.dinnerType == "dine-in" ? props.perpole * 1 : 0,
|
||||||
originAmount: carts.orderCostSummary.goodsRealAmount,
|
originAmount: carts.orderCostSummary.goodsRealAmount,
|
||||||
discountAmount: discountAmount.value,
|
discountAmount: discountAmount.value,
|
||||||
productCouponDiscountAmount: carts.orderCostSummary.productCouponDeduction,
|
productCouponDiscountAmount: carts.orderCostSummary.productCouponDeduction,
|
||||||
|
|
@ -667,16 +647,6 @@ const productCouponDiscountAmount = computed(() => {
|
||||||
// 优先从 Store 扩展字段取,若无则用 props 数据(过渡方案)
|
// 优先从 Store 扩展字段取,若无则用 props 数据(过渡方案)
|
||||||
return carts.orderCostSummary.productCouponDeduction;
|
return carts.orderCostSummary.productCouponDeduction;
|
||||||
});
|
});
|
||||||
//除开客座费,打包费总金额
|
|
||||||
const totalMoney = computed(() => {
|
|
||||||
return (
|
|
||||||
carts.goodsTotal -
|
|
||||||
productCouponDiscountAmount.value -
|
|
||||||
discountAmount.value -
|
|
||||||
fullCouponDiscountAmount.value -
|
|
||||||
pointsDiscountAmount.value
|
|
||||||
).toFixed(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
const totalPrice = computed(() => {
|
const totalPrice = computed(() => {
|
||||||
// 使用bignumber.js处理高精度计算
|
// 使用bignumber.js处理高精度计算
|
||||||
|
|
@ -693,7 +663,10 @@ const totalPrice = computed(() => {
|
||||||
.minus(merchantReduction)
|
.minus(merchantReduction)
|
||||||
.minus(pointDeduction)
|
.minus(pointDeduction)
|
||||||
.decimalPlaces(2, BigNumber.ROUND_DOWN); // 保持与工具库一致的舍入策略
|
.decimalPlaces(2, BigNumber.ROUND_DOWN); // 保持与工具库一致的舍入策略
|
||||||
|
const n = total.toNumber();
|
||||||
|
if (n <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return total.toNumber();
|
return total.toNumber();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog width="900px" :title="title" v-model="show" top="20px" @close="reset">
|
<el-dialog width="1000px" :title="title" v-model="show" top="20px" @close="reset">
|
||||||
<div class="u-p-15">
|
<div class="u-p-15">
|
||||||
<div class="">
|
<div class="">
|
||||||
<el-tabs v-model="activeName" @tab-click="tabClick">
|
<el-tabs v-model="activeName" @tab-click="tabClick">
|
||||||
|
|
@ -69,6 +69,12 @@
|
||||||
></el-checkbox>
|
></el-checkbox>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="id" width="100" label="ID">
|
||||||
|
<template v-slot="scope">
|
||||||
|
{{ scope.row.id }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column type="index" width="50" label="#"></el-table-column>
|
<el-table-column type="index" width="50" label="#"></el-table-column>
|
||||||
<el-table-column prop="name" label="券名称"></el-table-column>
|
<el-table-column prop="name" label="券名称"></el-table-column>
|
||||||
|
|
||||||
|
|
@ -280,6 +286,7 @@ async function getcoup() {
|
||||||
|
|
||||||
let noUseGoodsCoupon = [];
|
let noUseGoodsCoupon = [];
|
||||||
let noUseDiscountCoupon = [];
|
let noUseDiscountCoupon = [];
|
||||||
|
console.log("orderPrice", orderPrice.value);
|
||||||
for (let i = 0; i < couponList.length; i++) {
|
for (let i = 0; i < couponList.length; i++) {
|
||||||
const coupon = couponList[i];
|
const coupon = couponList[i];
|
||||||
const selCoupon =
|
const selCoupon =
|
||||||
|
|
@ -289,7 +296,7 @@ async function getcoup() {
|
||||||
const canuseResult = UTILS.returnCouponCanUse({
|
const canuseResult = UTILS.returnCouponCanUse({
|
||||||
canDikouGoodsArr,
|
canDikouGoodsArr,
|
||||||
coupon,
|
coupon,
|
||||||
orderPrice: orderPrice.value,
|
goodsOrderPrice: orderPrice.value,
|
||||||
user: props.user,
|
user: props.user,
|
||||||
selCoupon,
|
selCoupon,
|
||||||
shopInfo: shopUser.userInfo,
|
shopInfo: shopUser.userInfo,
|
||||||
|
|
@ -323,7 +330,7 @@ async function getcoup() {
|
||||||
v,
|
v,
|
||||||
props.user,
|
props.user,
|
||||||
orderPrice.value,
|
orderPrice.value,
|
||||||
quansSelArr.value,
|
quansSelArr.value.filter((v) => v.type != 2),
|
||||||
shopUser.userInfo
|
shopUser.userInfo
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
|
@ -339,7 +346,7 @@ async function getcoup() {
|
||||||
v,
|
v,
|
||||||
props.user,
|
props.user,
|
||||||
orderPrice.value,
|
orderPrice.value,
|
||||||
quansSelArr.value,
|
quansSelArr.value.filter((v) => v.type == 2),
|
||||||
shopUser.userInfo
|
shopUser.userInfo
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
|
@ -426,6 +433,15 @@ function updateSelCoupon() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
otherCoupon = otherCoupon.map((v) => {
|
otherCoupon = otherCoupon.map((v) => {
|
||||||
|
const canuseResult = UTILS.returnCouponCanUse({
|
||||||
|
canDikouGoodsArr,
|
||||||
|
coupon: v,
|
||||||
|
orderPrice: orderPrice.value,
|
||||||
|
user: props.user,
|
||||||
|
selCoupon: goodsCoupon,
|
||||||
|
shopInfo: shopUser.userInfo,
|
||||||
|
});
|
||||||
|
|
||||||
const discount = UTILS.returnCouponDiscount(
|
const discount = UTILS.returnCouponDiscount(
|
||||||
canDikouGoodsArr,
|
canDikouGoodsArr,
|
||||||
v,
|
v,
|
||||||
|
|
@ -436,12 +452,35 @@ function updateSelCoupon() {
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
...v,
|
...v,
|
||||||
|
canuseResult,
|
||||||
discount,
|
discount,
|
||||||
discountAmount: discount ? discount.discountPrice : v.discountAmount,
|
discountAmount: discount ? discount.discountPrice : v.discountAmount,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
couponSel.value = otherCoupon[0];
|
if (!otherCoupon[0].canuseResult.canUse) {
|
||||||
|
couponSel.value = { id: "" };
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
`选择该券后优惠券${otherCoupon[0].name}不可用,不可用原因:${otherCoupon[0].canuseResult.reason}`,
|
||||||
|
"提示",
|
||||||
|
{
|
||||||
|
type: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonText: "取消当前券的选择",
|
||||||
|
confirmButtonText: "剔除不可用的优惠券",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
couponSel.value = { id: "" };
|
||||||
|
goodsCouponSel.value = goodsCoupon[0];
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
goodsCouponSel.value = { id: "" };
|
||||||
|
couponSel.value = otherCoupon[0];
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
goodsCouponSel.value = goodsCoupon[0];
|
goodsCouponSel.value = goodsCoupon[0];
|
||||||
|
couponSel.value = otherCoupon[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue