JavaScript 促销多折扣算法实现:键盘阶梯优惠金额计算方案
代码问题分析
- 折扣规则不符合业务要求:原代码硬编码4~6台的折扣为60%/70%/80%,和给定的「3台及以上最高享40%折扣」规则冲突
- 优惠额计算逻辑错误:原代码仅扣除单台键盘的优惠额,未按实际参与优惠的商品总金额计算折扣
- 未满足动态匹配折扣的要求:全量硬编码每个购买数量对应的if判断,可维护性极差
- 超量规则未实现:购买超过6台时,超出部分不享受折扣的逻辑完全缺失
修正后实现方案
我们将折扣阶梯做成可配置数组,自动匹配最优折扣,不需要硬编码每个数量的判断逻辑:
// 可配置的折扣阶梯,后续调整规则只需改这个数组即可 const discountTiers = [ { minQty: 1, discount: 0.2 }, // 1台享20%折扣 { minQty: 2, discount: 0.3 }, // 2台享30%折扣 { minQty: 3, discount: 0.4 }, // 3台及以上最高享40%折扣 ] const MAX_DISCOUNT_QTY = 6 // 最多6台可参与折扣 const KEYBOARD_PRICE = 199.99 // 单台Yamaha PSR-E273 Keyboard常规售价 let cart = [] // 添加商品到购物车 const addKeyboardToCart = () => { cart.push({ id: "1001", name: "Yamaha PSR-E273 Keyboard", reg_price: KEYBOARD_PRICE }) } // 动态匹配当前购买数量对应的最优折扣 const getApplicableDiscount = (qty) => { // 倒序遍历阶梯,找到第一个满足购买数量要求的最高折扣 for (let i = discountTiers.length - 1; i >= 0; i--) { if (qty >= discountTiers[i].minQty) { return discountTiers[i].discount } } return 0 // 不足1台无折扣 } // 计算订单总应付金额 const calculateTotal = () => { const totalQty = cart.length if (totalQty < 1) { console.log("Please add an item") return 0 } // 参与折扣的数量最多为6台 const discountableQty = Math.min(totalQty, MAX_DISCOUNT_QTY) // 超出6台的部分按原价计算 const fullPriceQty = Math.max(totalQty - MAX_DISCOUNT_QTY, 0) // 获取对应数量的最优折扣 const discount = getApplicableDiscount(discountableQty) // 总金额 = 折扣部分金额 + 原价部分金额 const discountableAmount = discountableQty * KEYBOARD_PRICE * (1 - discount) const fullPriceAmount = fullPriceQty * KEYBOARD_PRICE return Number((discountableAmount + fullPriceAmount).toFixed(2)) } // 测试用例 // 测试1:购买6台 for(let i=0; i<6; i++) addKeyboardToCart() console.log(calculateTotal()) // 输出719.96,即6*199.99*0.6 // 测试2:再添加2台,共8台,超出的2台按原价计算 addKeyboardToCart() addKeyboardToCart() console.log(calculateTotal()) // 输出1119.94,即6*199.99*0.6 + 2*199.99
实现说明
- 折扣规则全部配置在
discountTiers数组中,后续调整折扣阶梯无需修改计算逻辑,符合「不硬编码每个数量对应折扣」的要求 - 自动适配1~6台的最优折扣,超过6台的部分自动按原价计算,完全符合给定的活动规则
- 金额计算后保留2位小数,符合货币计算规范
内容的提问来源于stack exchange,提问作者SpringBlanket
相关产品推荐
相关产品推荐

