You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

价格计算交互问题求助:折扣输入累加异常与NaN问题

价格计算与显示问题修复

问题描述

  • 页面重载后可正常显示选中treatment的总价,但在相对折扣输入框输入数值时,每次按键都会基于当前显示总价累加输入值(如初始总价为7,输入11时会先计算7+1=8,再计算8+11=19,而非预期的折扣后价格),导致计算结果错误。
  • 当使用绝对折扣输入框且相对折扣输入框为空时,计算结果出现NaN值。

相关代码

HTML

<div class="mb-3">
    <div for="treatment" class="form-label">List treatments</div>
    @foreach ($treatments as $treatment)
        <input class="checkp" type="checkbox" id="{{$treatment->title}}" data-price="{{$treatment->price}}" name="treatments[]" value="{{$treatment->id}}" @if (count($quote->treatments->where('id', $treatment->id))) checked @endif>
        <label for="{{$treatment->title}}"> {{$treatment->title}} - </label><span class="price"> {{$treatment->price}}</span><br>
    @endforeach
<p class="mt-5">Total price: <span id="total-price"></span></p>
</div>

<div class="mb-3">
<label for="discount" class="form-label">Discount</label>
<div class="form-check my-2 mb-3">
    <input class="form-check-input" type="radio" name="discount" id="flexRadioNoDisconunt" value="nodiscount" checked>
    <label class="form-check-label" for="flexRadioNoDisconunt"> No discount </label>
</div>
<div class="form-check my-2 mb-3">
    <input class="form-check-input" type="radio" name="discount" id="flexRadioRelativeDisconunt" value="relativediscount">
    <label class="form-check-label" for="flexRadioRelativeDisconunt"> Relative discount (in %)</label>
    <input type="number" id="inputrelativediscount" class="form-control p-3 inputs selectorelative" min="0" max="100" name="relativediscount" value="{{$quote->relativediscount }}">                    
</div>
<div class="form-check my-2 mb-3">
    <input class="form-check-input" type="radio" name="discount" id="flexRadioAbsoluteDisconunt" value="absolutediscount">
    <label class="form-check-label" for="flexRadioAbsoluteDisconunt"> Absolute discount (in €)</label>
    <input type="number" id="inputabsolutediscount" class="form-control p-3 inputs selectorabsolute" min="0" name="absolutediscount" value="{{ $quote->absolutediscount }}">
</div> 

JavaScript(原始代码)

document.querySelectorAll('input[type=checkbox]').forEach((elem) => elem.addEventListener("click", function (event) {
        if (event.target.checked) {
            sum = sum + parseInt(elem.getAttribute('data-price'))
        } else {
            let el = parseInt(elem.getAttribute('data-price'))
            sum = sum - el
        }
        //console.log(sum); 
        document.getElementById("total-price").innerHTML = sum;
    }));

    document.querySelectorAll('.inputs').forEach((elem) => elem.addEventListener("keyup", function () {
        if (document.querySelector('.selectorelative')) {
            document.getElementById("total-price").innerHTML = parseInt(document.getElementById("total-price").innerHTML) + parseInt(document.querySelector('.selectorelative').value);            
        } else {
            document.getElementById("total-price").innerHTML = parseInt(document.getElementById("total-price").innerHTML) + parseInt(document.querySelector('.selectorabsolute').value); 
        }

    }
    ))

修复方案

核心问题分析

  1. 折扣计算没有基于原始总价,而是直接修改显示的总价,导致每次按键都叠加计算,结果错误。
  2. 输入框为空时parseInt()返回NaN,与数值运算后导致最终结果为NaN。
  3. 没有区分当前选中的折扣类型,错误地同时处理两种折扣输入框。

修改后的JavaScript代码

// 初始化原始总价和当前总价
let originalTotal = 0;
let currentTotal = 0;

// 页面加载时先计算初始选中的treatment总价
document.querySelectorAll('input[type=checkbox]:checked').forEach(elem => {
    originalTotal += parseInt(elem.getAttribute('data-price'));
});
currentTotal = originalTotal;
document.getElementById("total-price").innerHTML = currentTotal;

// 复选框点击事件:更新原始总价和当前总价
document.querySelectorAll('input[type=checkbox]').forEach((elem) => elem.addEventListener("click", function (event) {
    const price = parseInt(elem.getAttribute('data-price'));
    if (event.target.checked) {
        originalTotal += price;
    } else {
        originalTotal -= price;
    }
    // 重新计算折扣后的总价
    calculateDiscount();
}));

// 折扣输入框和单选按钮的事件监听
document.querySelectorAll('.inputs, input[name="discount"]').forEach(elem => {
    elem.addEventListener("input", calculateDiscount);
});

// 统一计算折扣的函数
function calculateDiscount() {
    const selectedDiscount = document.querySelector('input[name="discount"]:checked').value;
    let discountValue = 0;

    switch(selectedDiscount) {
        case "relativediscount":
            // 处理相对折扣,为空时默认0,避免NaN
            discountValue = parseInt(document.getElementById("inputrelativediscount").value) || 0;
            currentTotal = originalTotal - (originalTotal * discountValue / 100);
            break;
        case "absolutediscount":
            // 处理绝对折扣,为空时默认0
            discountValue = parseInt(document.getElementById("inputabsolutediscount").value) || 0;
            currentTotal = originalTotal - discountValue;
            // 确保总价不低于0
            currentTotal = Math.max(currentTotal, 0);
            break;
        default:
            // 无折扣时直接显示原始总价
            currentTotal = originalTotal;
            break;
    }

    // 更新显示的总价,保留两位小数(可选,根据需求调整)
    document.getElementById("total-price").innerHTML = currentTotal.toFixed(2);
}

修复说明

  1. 保留原始总价:新增originalTotal变量存储未应用折扣的总价,所有折扣计算都基于这个值,避免叠加错误。
  2. 统一计算逻辑:封装calculateDiscount()函数,根据选中的折扣类型重新计算总价,每次输入或单选按钮变化时触发。
  3. 处理空输入:使用|| 0确保输入框为空时取0,避免NaN问题。
  4. 优化事件监听:同时监听折扣输入框和单选按钮的变化,确保切换折扣类型时立即更新总价。
  5. 边界处理:绝对折扣时确保总价不低于0,避免出现负数。

内容的提问来源于stack exchange,提问作者Sarah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 20:01:02