三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

从外卖到打车:手把手教你为小程序集成‘附近’功能(基于uni-app和wx.getFuzzyLocation)

从外卖到打车:手把手教你为小程序集成‘附近’功能(基于uni-app和wx.getFuzzyLocation)

从外卖到打车:手把手教你为小程序集成‘附近’功能(基于uni-app和wx.getFuzzyLocation)

当用户打开外卖小程序时,最关心的往往是"附近有什么好吃的";使用打车软件时,系统自动定位的准确度直接影响体验。这些场景背后,都依赖LBS(基于位置服务)技术的精准实现。本文将带你用uni-app框架,从商业逻辑出发,完整构建一个"附近商家"功能模块。

1. 商业场景分析与技术选型

在开发"附近"功能前,需要明确业务场景对精度的要求。外卖类应用通常需要50-100米精度即可满足"附近商家"展示需求,而打车软件则需要更高精度的定位来确定上车点。微信小程序提供了两种定位接口:

  • wx.getFuzzyLocation:模糊定位(精度约100-500米)
  • wx.getLocation:精确GPS定位(需单独申请权限)

对于大多数O2O场景,模糊定位完全够用且更容易通过审核。以下是不同业务场景的定位需求对照表:

业务类型推荐接口适用场景审核通过率
外卖/团购getFuzzyLocation商家列表展示85%+
打车/共享单车getLocation精准上车点确认60%左右
社交/活动getFuzzyLocation附近用户/活动推荐90%+

提示:首次申请定位权限时,建议先使用模糊定位接口,待小程序有一定用户基数后再申请精确定位,通过率会显著提高。

2. 权限申请与项目配置实战

2.1 微信后台权限申请技巧

在微信公众平台申请getFuzzyLocation权限时,"申请理由"的撰写直接影响审核结果。避免使用"需要获取用户位置"这类泛泛描述,而应该:

  1. 明确具体使用场景(如"展示用户周边3公里内的餐饮商家")
  2. 说明对用户的价值(如"减少手动输入地址的麻烦")
  3. 承诺数据用途(如"仅用于当前页面展示,不会存储位置数据")

一个通过率较高的申请案例:

用于向用户展示其所在位置周边3公里内的合作商家信息(包括餐饮、超市等),提升本地生活服务匹配效率。位置数据仅用于实时计算距离,不会存储到服务器。

2.2 uni-app项目配置详解

在HBuilderX中创建uni-app项目后,需要配置两个关键文件:

  1. manifest.json的微信小程序专属配置:
"mp-weixin": { "permission": { "scope.userFuzzyLocation": { "desc": "用于展示您附近的优惠活动和商家" } }, "requiredPrivateInfos": ["getFuzzyLocation"] }
  1. 具体页面的page.json配置:
{ "permission": { "scope.userFuzzyLocation": { "desc": "您的位置将用于计算与商家的距离" } } }

注意:desc字段会直接显示在用户授权弹窗上,建议用用户能理解的业务语言,而非技术术语。

3. 核心代码实现与优化

3.1 基础定位功能实现

在页面中调用定位接口时,建议添加完整的错误处理:

async getLocation() { try { const res = await uni.getFuzzyLocation({ type: 'wgs84' // 标准GPS坐标 }); this.longitude = res.longitude; this.latitude = res.latitude; // 触发商家列表更新 this.loadNearbyShops(); } catch (err) { console.error('定位失败:', err); uni.showToast({ title: '无法获取位置,请检查权限设置', icon: 'none' }); // 降级方案:使用默认城市中心坐标 this.useFallbackLocation(); } }

3.2 性能优化实践

频繁调用定位接口会导致用户体验下降,推荐以下优化策略:

  • 缓存机制:将获取的位置信息存储在本地,30分钟内不再重复请求

  • 智能触发:结合页面生命周期和用户操作:

    onShow() { // 每次进入页面检查是否有缓存位置 if (!this.locationCache || this.isCacheExpired()) { this.getLocation(); } } onPullDownRefresh() { // 下拉刷新时强制更新位置 this.getLocation(); }
  • 节流控制:限制定位按钮的点击频率:

    let lastClickTime = 0; handleLocationClick() { const now = Date.now(); if (now - lastClickTime < 3000) { return; } lastClickTime = now; this.getLocation(); }

4. 业务联调与数据展示

4.1 与后端API的交互设计

获取到用户坐标后,通常需要传递给后端获取附近商家。推荐使用以下参数结构:

{ longitude: 116.404, // 经度 latitude: 39.915, // 纬度 range: 3000, // 搜索范围(米) sort: 'distance', // 按距离排序 category: 'food', // 商家分类(可选) limit: 20 // 返回结果数 }

4.2 前端展示最佳实践

商家列表页的UI设计直接影响转化率,关键要素包括:

  1. 距离可视化

    • 1km内显示"约XX米"
    • 1-3km显示"约XX公里"
    • 超过3km建议不展示或标注"距离较远"
  2. 智能排序逻辑

    sortShops(shops, userLoc) { return shops.sort((a, b) => { // 优先展示营业中的店铺 if (a.isOpen !== b.isOpen) { return a.isOpen ? -1 : 1; } // 其次按距离排序 const distA = this.calcDistance(userLoc, a); const distB = this.calcDistance(userLoc, b); return distA - distB; }); }
  3. 地图集成方案

    <map id="nearbyMap" :longitude="longitude" :latitude="latitude" scale="15" :markers="markers" @markertap="handleMarkerTap" style="width: 100%; height: 300rpx;"> </map>

5. 异常处理与用户体验

5.1 定位失败时的降级方案

当无法获取用户位置时,可依次尝试以下策略:

  1. 引导用户手动选择所在区域
  2. 使用IP定位获取城市级位置
  3. 显示平台推荐的热门区域

对应的实现代码:

async useFallbackLocation() { // 方案1:读取用户上次选择的地址 const savedAddress = uni.getStorageSync('lastUsedAddress'); if (savedAddress) { this.location = savedAddress; return; } // 方案2:调用IP定位接口 try { const ipLocation = await this.getIPLocation(); this.location = ipLocation.city; } catch { // 方案3:使用默认城市 this.location = this.defaultCity; } }

5.2 权限引导策略

用户拒绝授权后,应该:

  1. 解释为什么需要位置权限(用业务价值而非技术需求)
  2. 提供图文引导说明如何重新开启权限
  3. 允许用户手动输入地址

示例引导弹窗内容:

【附近优惠】需要您的位置权限 才能为您推荐: ✓ 500米内的限时折扣 ✓ 步行可达的优质商家 ✓ 专属位置优惠券 [去设置] [手动选择地址]

在实际项目中,我们团队发现将定位功能与具体的业务优惠挂钩(如"开启定位获取专属新人红包"),可以将授权率从40%提升到75%以上。

← 返回列表