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

如何在WooCommerce账户地址编辑页实现动态联动下拉字段

问题描述

基于Stack Overflow示例代码修改后,我已在WooCommerce结账页成功实现城市与街道的动态联动下拉字段功能。现需将该功能同步至用户账户的地址编辑页面,使其效果与结账页一致。尝试添加woocommerce_default_address_fields等多个钩子后未生效,请问该如何实现?

现有结账页功能实现代码:

function cities_areas_settings() {
    $text_domain = 'woocommerce';
    return array(
        __('', $text_domain) => array( 
        ),
        __('Test', $text_domain) => array( 
            __('Street 2', $text_domain),
            __('Street 3', $text_domain),
            __('Street 4', $text_domain),
        ),
        __('Test1', $text_domain) => array(
            __('Street 5', $text_domain),
            __('Street 6', $text_domain),
        ),
        __('Test2', $text_domain) => array( 
            __('Street 7', $text_domain),
            __('Street 8', $text_domain),
        ),
        __('Test3', $text_domain) => array(
            __('Street 9', $text_domain),
            __('Street 10', $text_domain),
        ),
    );
}

add_filter('woocommerce_checkout_fields', 'custom_checkout_fields');
function custom_checkout_fields($fields) {
    $text_domain = 'woocommerce';
    $option_cities = array();
    $select_areas = array('' => __('Select your street', $text_domain)); 
    $test_areas = array('' => __('Select your street', $text_domain)); 
    $test1_areas = array('' => __('Select your street', $text_domain)); 
    $test2_areas = array('' => __('Select your street', $text_domain)); 

    foreach (cities_areas_settings() as $city => $zone) {
        $option_cities[$city] = $city; 

        if ($city === '') {
            foreach ($zone as $area) { 
                $select_areas[$area] = $area; 
            }
             } elseif ($city === 'Test') {
            foreach ($zone as $area) { 
                $test_areas[$area] = $area; 
            }
        } elseif ($city === 'Test1') { 
            foreach ($zone as $area) { 
                $test1_areas[$area] = $area; 
            }
        } elseif ($city === 'Test2') {
            foreach ($zone as $area) { 
                $test2_areas[$area] = $area; 
            }
        }
    }

    $fields['billing']['billing_city']['type'] = 'select'; 
    $fields['billing']['billing_city']['class'] = array('form-row-first');
    $fields['billing']['billing_city']['input_class'] = array('state_select');
    $fields['billing']['billing_city']['options'] = $option_cities;

    $fields['shipping']['shipping_city']['type'] = 'select'; 
    $fields['shipping']['shipping_city']['class'] = array('form-row-first');
    $fields['shipping']['shipping_city']['input_class'] = array('state_select');
    $fields['shipping']['shipping_city']['options'] = $option_cities;

    $fields['billing']['billing_address_1'] = array(
        'type' => 'select',
        'label' => __('Street', $text_domain),
        'class' => array('form-row-last'),
        'input_class' => array('state_select'),
        'options' => $select_areas,
        'required' => true,
        'default' => '',
        'priority' => 50,
    );

    $fields['shipping']['shipping_address_1'] = array(
        'type' => 'select',
        'label' => __('Street', $text_domain),
        'class' => array('form-row-last'), 
        'input_class' => array('state_select'),
        'options' => $select_areas,
        'required' => true,
        'default' => '',
        'priority' => 50,
    );

    return $fields;
}

add_action('wp_footer', 'custom_checkout_js_script');
function custom_checkout_js_script() {
    if (is_checkout() && !is_wc_endpoint_url()) :
        $text_domain = 'woocommerce';
        $test_areas = array('' => __('Select your street', $text_domain)); 
        $test1_areas = array('' => __('Select your street', $text_domain));
        $test2_areas = array('' => __('Select your street', $text_domain)); 
        $test3_areas = array('' => __('Select your street', $text_domain)); 
        $settings = cities_areas_settings(); 
        
        foreach ($settings['Test'] as $area) { 
            $test_areas[$area] = $area; 
        }
        foreach ($settings['Test1'] as $area) { 
            $test1_areas[$area] = $area; 
        }

        foreach ($settings['Test2'] as $area) { 
            $test2_areas[$area] = $area; 
        }

        foreach ($settings['Test3'] as $area) {
            $test3_areas[$area] = $area; 
        }
        ?>
        <script language="javascript">
            jQuery(function($) {
                var a = 'select[name="billing_city"]',
                    b = 'select[name="billing_address_1"]',
                    l = <?php echo json_encode($test_areas); ?>,
                    o = <?php echo json_encode($test1_areas); ?>,
                    r = <?php echo json_encode($test2_areas); ?>,
                    i = <?php echo json_encode($test3_areas); ?>,
                    s = $(b).html();

                function dynamicSelectOptions(opt) {
                    var options = '';
                    $.each(opt, function(key, value) {
                        options += '<option value="' + key + '">' + value + '</option>';
                    });
                    $(b).html(options);
                }
                
                if ($(a).val() === 'Test') {
                    dynamicSelectOptions(l);
                } else  if ($(a).val() === 'Test1') {
                    dynamicSelectOptions(o);
                } else if ($(a).val() === 'Test2') { 
                    dynamicSelectOptions(r);
                } else if ($(a).val() === 'Test3') {
                    dynamicSelectOptions(i);
                }

                console.log($(a).val());

                $('form.woocommerce-checkout').on('change', a, function() { 
                    console.log($(this).val());
                    if ($(this).val() === 'Test') {
                        dynamicSelectOptions(l);
                    } else if ($(this).val() === 'Test1') {
                        dynamicSelectOptions(o);
                    } else if ($(this).val() === 'Test2') { 
                        dynamicSelectOptions(r);
                    } else if ($(this).val() === 'Test3') {
                        dynamicSelectOptions(i);
                    } else {
                        $(b).html(s);
                    }
                });
            });
        </script>

        <script language="javascript">
            jQuery(function($) {
                var a = 'select[name="shipping_city"]',
                    b = 'select[name="shipping_address_1"]',
                    l = <?php echo json_encode($test_areas); ?>,
                    o = <?php echo json_encode($test1_areas); ?>,
                    r = <?php echo json_encode($test2_areas); ?>,
                    i = <?php echo json_encode($test3_areas); ?>,
                    s = $(b).html();

                function dynamicSelectOptions(opt) {
                    var options = '';
                    $.each(opt, function(key, value) {
                        options += '<option value="' + key + '">' + value + '</option>';
                    });
                    $(b).html(options);
                }
                
                if ($(a).val() === 'Test') {
                    dynamicSelectOptions(l);
                } else if ($(a).val() === 'Test1') {
                    dynamicSelectOptions(o);
                } else if ($(a).val() === 'Test2') { 
                    dynamicSelectOptions(r);
                } else if ($(a).val() === 'Test3') {
                    dynamicSelectOptions(i);
                }

                console.log($(a).val());

                $('form.woocommerce-checkout').on('change', a, function() { 
                    console.log($(this).val());
                    if ($(this).val() === 'Test') {
                        dynamicSelectOptions(l);
                    } else if ($(this).val() === 'Test1') {
                        dynamicSelectOptions(o);
                    } else if ($(this).val() === 'Test2') { 
                        dynamicSelectOptions(r);
                    } else if ($(this).val() === 'Test3') {
                        dynamicSelectOptions(i);
                    } else {
                        $(b).html(s);
                    }
                });
            });
        </script>
    <?php
    endif;
}
解决方案

要在账户地址编辑页实现相同联动效果,需针对账户页的字段钩子和页面判断做调整,完整修改后的代码如下:

function cities_areas_settings() {
    $text_domain = 'woocommerce';
    return array(
        __('', $text_domain) => array( 
        ),
        __('Test', $text_domain) => array( 
            __('Street 2', $text_domain),
            __('Street 3', $text_domain),
            __('Street 4', $text_domain),
        ),
        __('Test1', $text_domain) => array(
            __('Street 5', $text_domain),
            __('Street 6', $text_domain),
        ),
        __('Test2', $text_domain) => array( 
            __('Street 7', $text_domain),
            __('Street 8', $text_domain),
        ),
        __('Test3', $text_domain) => array(
            __('Street 9', $text_domain),
            __('Street 10', $text_domain),
        ),
    );
}

// 处理结账页字段
add_filter('woocommerce_checkout_fields', 'custom_checkout_fields');
// 处理账户地址页的账单字段
add_filter('woocommerce_billing_fields', 'custom_address_fields');
// 处理账户地址页的配送字段
add_filter('woocommerce_shipping_fields', 'custom_address_fields');

function custom_checkout_fields($fields) {
    return custom_address_fields($fields);
}

function custom_address_fields($fields) {
    $text_domain = 'woocommerce';
    $option_cities = array();
    $select_areas = array('' => __('Select your street', $text_domain)); 
    $test_areas = array('' => __('Select your street', $text_domain)); 
    $test1_areas = array('' => __('Select your street', $text_domain)); 
    $test2_areas = array('' => __('Select your street', $text_domain)); 

    foreach (cities_areas_settings() as $city => $zone) {
        $option_cities[$city] = $city; 

        if ($city === '') {
            foreach ($zone as $area) { 
                $select_areas[$area] = $area; 
            }
        } elseif ($city === 'Test') {
            foreach ($zone as $area) { 
                $test_areas[$area] = $area; 
            }
        } elseif ($city === 'Test1') { 
            foreach ($zone as $area) { 
                $test1_areas[$area] = $area; 
            }
        } elseif ($city === 'Test2') {
            foreach ($zone as $area) { 
                $test2_areas[$area] = $area; 
            }
        }
    }

    // 修改城市字段为下拉选择
    if (isset($fields['billing_city'])) {
        $fields['billing_city']['type'] = 'select'; 
        $fields['billing_city']['class'] = array('form-row-first');
        $fields['billing_city']['input_class'] = array('state_select');
        $fields['billing_city']['options'] = $option_cities;
    }

    if (isset($fields['shipping_city'])) {
        $fields['shipping_city']['type'] = 'select'; 
        $fields['shipping_city']['class'] = array('form-row-first');
        $fields['shipping_city']['input_class'] = array('state_select');
        $fields['shipping_city']['options'] = $option_cities;
    }

    // 修改街道字段为下拉选择
    if (isset($fields['billing_address_1'])) {
        $fields['billing_address_1'] = array(
            'type' => 'select',
            'label' => __('Street', $text_domain),
            'class' => array('form-row-last'),
            'input_class' => array('state_select'),
            'options' => $select_areas,
            'required' => true,
            'default' => '',
            'priority' => 50,
        );
    }

    if (isset($fields['shipping_address_1'])) {
        $fields['shipping_address_1'] = array(
            'type' => 'select',
            'label' => __('Street', $text_domain),
            'class' => array('form-row-last'), 
            'input_class' => array('state_select'),
            'options' => $select_areas,
            'required' => true,
            'default' => '',
            'priority' => 50,
        );
    }

    return $fields;
}

add_action('wp_footer', 'custom_address_js_script');
function custom_address_js_script() {
    // 同时匹配结账页和账户地址编辑页
    if (is_checkout() && !is_wc_endpoint_url() || is_account_page() && isset($_GET['edit-address'])) :
        $text_domain = 'woocommerce';
        $test_areas = array('' => __('Select your street', $text_domain)); 
        $test1_areas = array('' => __('Select your street', $text_domain));
        $test2_areas = array('' => __('Select your street', $text_domain)); 
        $test3_areas = array('' => __('Select your street', $text_domain)); 
        $settings = cities_areas_settings(); 
        
        foreach ($settings['Test'] as $area) { 
            $test_areas[$area] = $area; 
        }
        foreach ($settings['Test1'] as $area) { 
            $test1_areas[$area] = $area; 
        }

        foreach ($settings['Test2'] as $area) { 
            $test2_areas[$area] = $area; 
        }

        foreach ($settings['Test3'] as $area) {
            $test3_areas[$area] = $area; 
        }
        ?>
        <script language="javascript">
            jQuery(function($) {
                // 处理账单地址联动
                var billingCity = 'select[name="billing_city"]',
                    billingStreet = 'select[name="billing_address_1"]',
                    testAreas = <?php echo json_encode($test_areas); ?>,
                    test1Areas = <?php echo json_encode($test1_areas); ?>,
                    test2Areas = <?php echo json_encode($test2_areas); ?>,
                    test3Areas = <?php echo json_encode($test3_areas); ?>,
                    defaultStreetHtml = $(billingStreet).html();

                function dynamicSelectOptions(selectEl, options) {
                    var optionsHtml = '';
                    $.each(options, function(key, value) {
                        optionsHtml += '<option value="' + key + '">' + value + '</option>';
                    });
                    $(selectEl).html(optionsHtml);
                }
                
                // 页面加载时初始化街道选项
                if ($(billingCity).val() === 'Test') {
                    dynamicSelectOptions(billingStreet, testAreas);
                } else if ($(billingCity).val() === 'Test1') {
                    dynamicSelectOptions(billingStreet, test1Areas);
                } else if ($(billingCity).val() === 'Test2') { 
                    dynamicSelectOptions(billingStreet, test2Areas);
                } else if ($(billingCity).val() === 'Test3') {
                    dynamicSelectOptions(billingStreet, test3Areas);
                }

                // 城市选择变化时更新街道
                $('form').on('change', billingCity, function() { 
                    if ($(this).val() === 'Test') {
                        dynamicSelectOptions(billingStreet, testAreas);
                    } else if ($(this).val() === 'Test1') {
                        dynamicSelectOptions(billingStreet, test1Areas);
                    } else if ($(this).val() === 'Test2') { 
                        dynamicSelectOptions(billingStreet, test2Areas);
                    } else if ($(this).val() === 'Test3') {
                        dynamicSelectOptions(billingStreet, test3Areas);
                    } else {
                        $(billingStreet).html(defaultStreetHtml);
                    }
                });

                // 处理配送地址联动
                var shippingCity = 'select[name="shipping_city"]',
                    shippingStreet = 'select[name="shipping_address_1"]';

                // 页面加载时初始化街道选项
                if ($(shippingCity).val() === 'Test') {
                    dynamicSelectOptions(shippingStreet, testAreas);
                } else if ($(shippingCity).val()
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:48:25