2团
Published on 2026-06-08 / 0 Visits
0
0

心情日历小程序:模糊定位、逆地理编码与手动选点的独立开发实录

背景

心情手账日历是一款记录每日心情的微信小程序,最近想加入地理打卡功能,顺便把实现过程中踩的坑记下来。这个项目是我独立开发的,所有决策和实现都是一个人摸索完成。

阶段一:模糊定位

起初没有配置隐私声明,只能申请wx.getFuzzyLocation模糊定位。我用uni-app开发,因此通过uni.getFuzzyLocation获取终端的粗略位置。该接口只返回经纬度,不包含地址描述,需要后端调用地图服务做逆地理编码。

uni.getFuzzyLocation({
  type: 'gcj02',
  success: (pos) => {
    // pos = { latitude: 39.90, longitude: 116.40 }
    // 只有经纬度,没有城市/区县等文字
    // 需要后端 geocode API → "北京市朝阳区望京街道"
  }
})

局限:虽然能拿到坐标,但精度较低、偏差明显,难以在地图上精确标记。

阶段二:前端直调地图SDK

拿到经纬度后,需要将其转换为人类可读的地址描述,总不能直接展示火星坐标系下的经纬度给用户。

一开始我直接在前端接入腾讯地图JS SDK(qqmap-wx-jssdk)做逆地理编码:

import QQMapWX from 'qqmap-wx-jssdk'

const qqmap = new QQMapWX({
  key: import.meta.env.VITE_TENCENT_MAP_KEY as string,
})

uni.getLocation({
  type: 'gcj02',
  success: (pos) => {
    qqmap.reverseGeocoder({
      location: { latitude: pos.latitude, longitude: pos.longitude },
      success: (res) => {
        const addr = res.result.address
        const city = res.result.address_component.city
      }
    })
  }
})

问题:地图Key会直接暴露在前端代码中,安全风险很大。

阶段三:逆地理编码迁移到后端

为了把地图服务商的Key藏起来,我把逆地理编码挪到了后端:

async fn geocode(query, config) -> Result<HttpResponse> {
    // 调用腾讯地图 WebService API,Key 放在后端环境变量
    let resp = client.get("https://apis.map.qq.com/ws/geocoder/v1/")
        .query(&[("location", format!("{},{}", lat, lng)), ("key", config.tencent_map_key)])
        .send().await?;
    // ...
}

收益:地图服务商的Key只保留在后端,前端无法获取;代价是多了一次网络请求。

阶段四:尝试精确定位

为了进一步提升打卡位置的精度和体验,我尝试申请wx.getLocation精确定位权限:

uni.getLocation({
  type: 'gcj02',
  isHighAccuracy: true,  // GPS 级精度
  success: (pos) => {
    // 后端逆地理编码 → "北京市朝阳区建国路 93 号"
  }
})

审核结果:被拒

反复申请均被驳回。查阅社区资料后发现,微信对个人开发者审核较严,心情记录这类应用不属于“强位置依赖”场景,getLocation权限基本无望,于是我放弃了这个方案。

阶段五(当前):模糊定位 + 手动选点

精确定位这条路走不通,我便采用了折中方案:若自动定位不准确,允许用户自行手动调整位置。于是转而申请了wx.chooseLocation,该权限相对容易通过审核。

现在的流程如下:

用户点击“添加位置”
    ├── 自动定位 → getFuzzyLocation(返回经纬度)→ 后端 geocode API 逆地理编码 → 地址文本
    └── 手动选择 → chooseLocation → 地图选点,直接返回坐标 + 地址
  • 自动定位:通过getFuzzyLocation获取坐标,后端逆地理编码返回“南京市夫子庙大门口”级别的地址;

  • 手动选点:用户在地图上自行点选精确位置,chooseLocation属于用户主动行为,审核宽松不少。

数据模型中的经纬度字段设计为可空。无论是自动定位还是手动选点,只要成功获取了位置,都会写入坐标;当用户定位失败或取消选点操作时,字段保持为 null。

interface MoodRecord {
  location: string        // 地址文本(自动定位:后端逆地理编码返回;手动选择:chooseLocation 直接提供)
  locationCity: string    // 城市名
  latitude: number | null // 可为空;自动或手动定位成功时写入,定位失败/取消选点时为 null
  longitude: number | null
}


Comment