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

WooCommerce切换商品变体时自定义字段价格更新异常问题

解决WooCommerce变体切换时保修状态价格计算错误的问题

核心问题根源

  1. woocommerce_variation_has_changed事件触发时机过早,此时WooCommerce还未完成变体价格的渲染,导致getOriginalPrice()获取到的是旧价格或无效值。
  2. 重置保修选项后直接调用updatePrice(),但此时没有选中的保修选项,会默认使用1.0的乘数,同时WooCommerce原生的价格更新会覆盖自定义修改的价格HTML。
  3. originalPrice的缓存逻辑没有正确重置,导致切换变体后仍使用旧变体的价格进行计算。

修复方案

1. 监听正确的变体加载事件

使用found_variation事件,该事件在WooCommerce成功加载并渲染完变体数据后触发,确保能获取到最新的变体原始价格。

2. 调整保修选项重置与价格更新逻辑

重置保修选项后,不自动调用updatePrice(),而是引导用户重新选择;同时处理未选中保修选项的情况,避免错误计算。

3. 避免直接修改价格HTML被覆盖

通过在WooCommerce完成价格渲染后,再应用自定义价格计算,或者保存原始价格到变体数据中,确保计算基准正确。

修改后的完整代码

add_action('woocommerce_single_variation', 'add_custom_options', 5);
function add_custom_options() {
    ?>
    <div class="custom-options-wrapper" style="width: 100%;">
        <h4>Great, let's talk about the more details:</h4>
        <div class="custom-warranty-option" style="margin-bottom: 20px;">
            <label>1. Is it still under warranty?</label>
            <label style="display: block;">
                <input type="radio" name="warranty_status" value="no" required> No, the warranty has expired.
            </label>
            <label style="display: block;">
                <input type="radio" name="warranty_status" value="1-6months" required> Yes, 1-6 months warranty
            </label>
            <label style="display: block;">
                <input type="radio" name="warranty_status" value="over6months" required> Yes, over 6 months warranty
            </label>
            <label style="display: block;">
                <input type="radio" name="warranty_status" value="unactivated" required> Yes, 1 year warranty & unactivated
            </label>
        </div>
    </div>
    <!-- 添加隐藏字段存储原始变体价格 -->
    <input type="hidden" id="original_variation_price" value="">

    <script type="text/javascript">
    jQuery(document).ready(function($) {
        var originalPrice;

        // 从变体数据中获取原始价格,避免从DOM读取被修改后的价格
        function setOriginalPriceFromVariation(variation) {
            if (variation && variation.display_price) {
                originalPrice = parseFloat(variation.display_price);
                $('#original_variation_price').val(originalPrice);
            }
        }

        function getOriginalPrice() {
            // 优先从隐藏字段获取,避免DOM读取错误
            var storedPrice = $('#original_variation_price').val();
            if (storedPrice && !isNaN(parseFloat(storedPrice))) {
                return parseFloat(storedPrice);
            }
            //  fallback到DOM读取
            var priceText = $('.woocommerce-variation-price .woocommerce-Price-amount.amount').first().text();
            return parseFloat(priceText.replace(/[^\d.]/g, ''));
        }

        function updatePrice() {
            if (isNaN(originalPrice)) {
                originalPrice = getOriginalPrice();
            }

            // 处理未选中保修选项的情况
            var selectedWarranty = $('input[name="warranty_status"]:checked').val();
            if (!selectedWarranty) {
                // 未选中时恢复原始价格
                $('.woocommerce-variation-price .woocommerce-Price-amount.amount').html('<bdi><span class="woocommerce-Price-currencySymbol">$</span>' + originalPrice + '</bdi>');
                $('#custom_price').val(originalPrice);
                return;
            }

            var warrantyMultiplier = 1.00;

            if (selectedWarranty === 'no') {
                warrantyMultiplier = 0.90; // No warranty, deduct 10%
            } else if (selectedWarranty === '1-6months') {
                warrantyMultiplier = 0.92; // 1-6 months warranty, deduct 8%
            } else if (selectedWarranty === 'over6months') {
                warrantyMultiplier = 0.95; // Over 6 months warranty, deduct 5%
            }

            var newPrice = Math.round(originalPrice * warrantyMultiplier);

            $('.woocommerce-variation-price .woocommerce-Price-amount.amount').html('<bdi><span class="woocommerce-Price-currencySymbol">$</span>' + newPrice + '</bdi>');
            $('#custom_price').val(newPrice);
        }

        // Clear the selected state of all custom options
        function resetCustomOptions() {
            $('input[name="warranty_status"]').prop('checked', false);
        }

        // 监听变体加载完成事件
        $('form.variations_form').on('found_variation', function(event, variation) {
            resetCustomOptions();
            setOriginalPriceFromVariation(variation);
            // 重置后恢复原始价格显示
            $('.woocommerce-variation-price .woocommerce-Price-amount.amount').html('<bdi><span class="woocommerce-Price-currencySymbol">$</span>' + originalPrice + '</bdi>');
            $('#custom_price').val(originalPrice);
        });

        $('input[name="warranty_status"]').change(function() {
            updatePrice();
        });

        // 初始化原始价格
        originalPrice = getOriginalPrice();
        $('#original_variation_price').val(originalPrice);
    });
    </script>
   
    <?php
}

关键修改点说明

  • 使用found_variation事件:该事件会在WooCommerce成功加载变体数据后触发,此时能直接从variation对象中获取原始价格,避免DOM读取的误差。
  • 新增隐藏字段存储原始价格:确保每次计算都基于当前变体的真实原始价格,不会因为之前的修改导致计算基准错误。
  • 处理未选中保修选项的情况:重置选项后恢复显示原始价格,避免无选中状态下的错误计算。
  • 移除过早的updatePrice()调用:重置选项后让用户主动选择,避免自动计算带来的逻辑混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:07:01