记前端项目定位实现过程

  • 背景:

        一个前端h5项目,需要内嵌到企业微信工作台上使用,项目中有获取定位信息的要求

  • 实现过程:

① 第一次:目标实现方式是调用高德,使用高德地图来获取经纬度,使用获得的经纬度来获取地理位置名称,

具体实现过程如下:

window._AMapSecurityConfig = {
    securityJsCode: "yourSecretKey",
  }; 

const handleGeoLocation = () => {
    AMapLoader.load({
      key: 'yourkey', // 你的高德地图API Key
      version: '2.0', // API 版本
      plugins: ['AMap.Geolocation', 'AMap.Geocoder'], // 加载定位和逆地理编码插件
    }).then((AMap) => {
      // 初始化定位插件
      const geolocation = new AMap.Geolocation({
        enableHighAccuracy: false, // 是否使用高精度定位
        timeout: 20000, // 超时时间
      });

      // 获取当前位置
      geolocation.getCurrentPosition((status, result) => {
        if (status === 'complete') {
          console.log('定位成功:', result);

          // 获取经纬度
          const lng = result.position.lng; // 经度
          const lat = result.position.lat; // 纬度

          // 初始化逆地理编码插件
          const geocoder = new AMap.Geocoder({
            city: '全国', // 城市,默认设置为“全国”
            radius: 1000, // 逆地理编码搜索半径
          });

          // 调用逆地理编码接口
          geocoder.getAddress([lng, lat], (status, result) => {
            if (status === 'complete' && result.info === 'OK') {
              // 逆地理编码成功
              console.log('逆地理编码成功:', result.regeocode.formattedAddress);
            } else {
              // 逆地理编码失败
              console.error('逆地理编码失败:', result);
            }
          });
        } else {
          console.error('定位失败:', result);
        }
      });
    }).catch((error) => {
      console.error('高德地图 API 加载失败:', error);
    });
    return;
}

  问题说明:

        这种情况有一个前提条件是项目的运行浏览器不使用谷歌浏览器,谷歌浏览器是国外的浏览器,由于国内网络保护,导致无法获取当前定位,也就是说,在谷歌浏览器上调用getCurrentPosition方法会报错。具体的原因,帖子上有说把协议改为https就可以调用成功的,本人试了一下,没生效,而且还有一点是,高德地图在localhost也就是本地开发的情况下,是不会做协议限制的,由此也可知,调用不通和协议无关,高德地图官网上也阐述了,谷歌浏览器的定位本身就是一个黑洞,不建议使用。至于具体的原因,目前据我所查没有一个帖子有比较明确的答案(有无大佬评论区解释下,多谢)。这里具体的应该要涉及到各个浏览器定位实现的方式,定位实现的方式各有不同的,具体感兴趣的可以查查。

        ② 第二次:考虑纯后端实现

        获取定位失败的原因未可知,就无法根据问题解决,除了换浏览器,但是企业微信工作台的浏览器是不可能改变的,所以考虑纯后端实现

(说到这里就要进行展开,由于企业微信的内核和谷歌浏览器一样,导致我以为问题出现在企业微信工作台浏览器使用谷歌的缘故,但实质上,企业微信工作台上应用无法调通定位接口的原因是,获得地理位置等信息都属于私人信息,出于安全考虑,内嵌浏览器会禁用所有的敏感信息的获取,所以在没有授权允许的情况下,是无法获得定位的)

纯后端实现是不可能的,后端只能通过解析ip地址来获取的一个大概的信息,地址也就精确到城市,市面上所有的定位都是前端实现的,当然有这种想法也是由于上述的那个说法,都是泪

          ③ 最后一次:一个正确的实现方案

           针对此类型的开发,对于内嵌到企业微信或者钉钉的应用,获取地理信息位置,在对应的开发者工具里面都有具体的实现,这些具体的实现,开发者工具的官网上都有具体的实现,针对企业微信内嵌应用的实现如下:

// 这里的decodeGeocoder使用的是公司封装的解码包,本质上还是用的高德地图的实现
function getDynamicAddress(lng_lat:any = []) {
  const geolocation = new Geolocation();
  try {
    // 初始化
    await geolocation.init();
    await geolocation.initGeolocation();
    // 解析地址
    await geolocation.initGeocoder();
    const addressInfo = await geolocation.decodeGeocoder(lng_lat);
    return {
      lngLat: lng_lat,
      address: addressInfo.address,
      fullInfo: addressInfo.regeocodeInfo,
    };
  } catch (error) {
    console.error("获取地址失败:", error);
    throw error;
  }
}  


async function handleGeolocation() {
    try {
      // 1. 获取当前页面URL(去除hash部分)
      const currentPageUrl = window.location.href.split('#')[0];
      console.log('当前页面URL:', currentPageUrl);

      // 2. 从后端获取配置信息
      const res = await request({
        url: workOrderService.dispatchOrder.queryGeolocation,
        method: 'GET',
        params: { url: currentPageUrl },
      });

      if (!res?.success || !res?.data) {
        console.error('获取配置失败:', res);
        return;
      }

      // 3. 检查wx对象是否存在
      if (typeof wx === 'undefined') {
        console.error('企业微信JS-SDK未加载');
        return;
      }

      // 4. 初始化配置
      wx.config({
        beta: true,
        debug: false, // 生产环境建议关闭
        appId: res.data.appId, // 使用确定存在的值,避免可选链
        timestamp: res.data.timestamp,
        nonceStr: res.data.nonceStr,
        signature: res.data.signature,
        jsApiList: ['getLocation'],
      });

      // 5. 配置错误处理
      wx.error((err) => {
        console.error('JS-SDK配置失败:', err);
        // 可以在这里显示错误提示给用户
      });

      // 6. 配置成功后获取位置
      wx.ready(async () => {
        try {
          wx.getLocation({
            type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
            success: async function (res) {
              let lat = (+res.latitude).toFixed(6);
              let lng = (+res.longitude).toFixed(6);
              console.log('res111', res, lat, lng, res.errMsg == "getLocation:ok");
              if (res.errMsg === "getLocation:ok") {
                console.log('获取位置成功:', lat, lng);
                const  result =await getDynamicAddress([+lng, +lat]);
                return result;
              }
            }
          });
        } catch (error) {
          console.error('获取位置失败:', error);
        }
      });
    } catch (error) {
      console.error('处理地理位置出错:', error);
    }
  }

 

posted on 2025-12-01 14:38  爱敲代码的关耳  阅读(0)  评论(0)    收藏  举报