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

WordPress中Google Map Auto-Complete Search API距离计算异常问题

针对你的两个问题,给出具体排查和修复方案

问题1:距离计算不准确

常见原因及修复方法

  1. 使用了错误的距离计算方式
    如果你用的是平面几何公式(比如勾股定理)计算距离,会因为地球是球体产生较大误差,尤其是跨区域的地址。必须用Haversine球面距离公式,这是计算地球上两点距离的行业标准。

    直接替换成下面的PHP实现(适配英里单位):

    function calculate_office_distance($user_lat, $user_lon, $office_lat, $office_lon) {
        // 地球半径(英里)
        $earth_radius = 3956;
        
        // 转弧度计算
        $lat_diff = deg2rad($office_lat - $user_lat);
        $lon_diff = deg2rad($office_lon - $user_lon);
        
        $a = sin($lat_diff / 2) * sin($lat_diff / 2) +
             cos(deg2rad($user_lat)) * cos(deg2rad($office_lat)) *
             sin($lon_diff / 2) * sin($lon_diff / 2);
        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        
        // 返回英里数,保留1位小数
        return round($earth_radius * $c, 1);
    }
    
  2. 坐标或单位转换错误

    • 确保你用的是Google API返回的WGS84标准经纬度(Google Maps默认输出这个,不用额外转换)
    • 检查单位换算:1英里≈1.609公里,不要把公里数直接当英里用

问题2:连续搜索3-4次后显示超范围办公室

常见原因及修复方法

  1. AJAX请求竞态问题
    连续发起无刷新搜索时,旧请求的响应可能晚于新请求,导致旧的超范围结果覆盖新结果。用AbortController取消未完成的旧请求:

    let searchController;
    
    // 绑定搜索表单提交事件
    document.querySelector('#office-search-form').addEventListener('submit', (e) => {
        e.preventDefault();
        
        // 取消之前未完成的请求
        if (searchController) searchController.abort();
        searchController = new AbortController();
        const signal = searchController.signal;
    
        // 这里调用Google AutoComplete获取用户地址经纬度,再发起WordPress AJAX请求
        fetch(ajaxurl, {
            method: 'POST',
            signal: signal,
            body: new FormData(e.target)
        })
        .then(res => res.json())
        .then(data => {
            // 清空并更新结果容器
            document.querySelector('#office-results').innerHTML = data.html;
        })
        .catch(err => {
            // 忽略主动取消的请求错误
            if (err.name !== 'AbortError') console.error(err);
        });
    });
    
  2. 结果缓存/全局变量污染
    如果你在后台用了全局变量存储办公室列表,或者复用了之前的过滤结果,会导致旧数据残留。每次搜索都要重新从数据库拉取所有办公室数据,重新计算距离并过滤:

    add_action('wp_ajax_filter_local_offices', 'filter_local_offices');
    add_action('wp_ajax_nopriv_filter_local_offices', 'filter_local_offices');
    
    function filter_local_offices() {
        // 获取用户提交的经纬度
        $user_lat = sanitize_text_field($_POST['user_lat']);
        $user_lon = sanitize_text_field($_POST['user_lon']);
    
        // 重新从数据库拉取所有办公室(假设自定义post类型为office)
        $offices_query = new WP_Query([
            'post_type' => 'office',
            'posts_per_page' => -1,
            'post_status' => 'publish'
        ]);
    
        $valid_offices = [];
        if ($offices_query->have_posts()) {
            while ($offices_query->have_posts()) {
                $offices_query->the_post();
                $office_lat = get_post_meta(get_the_ID(), 'office_lat', true);
                $office_lon = get_post_meta(get_the_ID(), 'office_lon', true);
                
                // 只保留50英里内的办公室
                if ($office_lat && $office_lon) {
                    $distance = calculate_office_distance($user_lat, $user_lon, $office_lat, $office_lon);
                    if ($distance <= 50) {
                        $valid_offices[] = [
                            'title' => get_the_title(),
                            'distance' => $distance,
                            'address' => get_post_meta(get_the_ID(), 'office_address', true)
                        ];
                    }
                }
            }
            wp_reset_postdata();
        }
    
        // 生成结果HTML
        ob_start();
        if (!empty($valid_offices)) {
            foreach ($valid_offices as $office) {
                echo "<div class='office-item'>
                        <h3>{$office['title']}</h3>
                        <p>{$office['address']}</p>
                        <span>{$office['distance']} 英里</span>
                      </div>";
            }
        } else {
            echo "<p>未找到50英里范围内的办公室,请扩大搜索范围。</p>";
        }
        $html = ob_get_clean();
    
        wp_send_json(['html' => $html]);
        wp_die();
    }
    
  3. 前端结果容器未清空
    每次搜索前手动清空结果容器,避免新旧结果叠加:

    // 在发起AJAX请求前执行
    document.querySelector('#office-results').innerHTML = '<div class="loading">加载中...</div>';
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:37:01