3***@qq.com
3***@qq.com
  • 发布:2026-05-25 22:45
  • 更新:2026-05-25 22:46
  • 阅读:40

想获得定位怎么没有成功呢,权限也有了啊

分类:uni-app
<template>  
  <view class="wrap">  
    <view class="header">私车公用 · 定位轨迹</view>  

    <view class="card">  
      <view class="status">{{ running ? '? 定位中' : '⚪ 已停止' }}</view>  

      <!-- 定位失败状态 在这里显示 -->  
      <view class="gps-status" :class="gpsStatusClass">{{ gpsStatusText }}</view>  

      <view class="distance">{{ (totalDistance / 1000).toFixed(2) }} km</view>  

      <view class="info">  
        <view>用时:{{ formatTime(useTime) }}</view>  
        <view>精度:{{ accuracy }} 米</view>  
        <view>轨迹点:{{ path.length }} 个</view>  
      </view>  
    </view>  

    <view class="btns">  
      <button v-if="!running" type="primary" @click="start">开始行程</button>  
      <button v-else type="warn" @click="stop">结束行程</button>  
    </view>  

    <button v-if="path.length > 0" @click="playback" type="primary" style="margin:20rpx 0;">  
      轨迹回放  
    </button>  

    <canvas v-if="showCanvas" canvas-id="trackCanvas" class="canvas"></canvas>  
  </view>  
</template>  

<script>  
export default {  
  data() {  
    return {  
      running: false,  
      lat: 0,  
      lng: 0,  
      accuracy: 999,  
      totalDistance: 0,  
      lastPoint: null,  
      startTime: null,  
      useTime: 0,  
      timer: null,  
      gpsStatusText: '未开始',  
      gpsStatusClass: 'normal',  

      path: [],  
      showCanvas: false,  
      playIndex: 0,  
      playTimer: null  
    }  
  },  

  onUnload() {  
    this.stop()  
  },  

  methods: {  
    start() {  
      this.running = true  
      this.startTime = Date.now()  
      this.lastPoint = null  
      this.totalDistance = 0  
      this.useTime = 0  
      this.path = []  
      this.showCanvas = false  
      this.gpsStatusText = "正在启动GPS定位..."  
      this.gpsStatusClass = "weak"  

      // 计时  
      this.timer = setInterval(() => {  
        this.useTime = Math.floor((Date.now() - this.startTime) / 1000)  
      }, 1000)  

      // ==============================================  
      // 定位启动 + 失败状态 全部写在这里  
      // ==============================================  
      uni.startLocationUpdate({  
        enableHighAccuracy: true,  
        success: () => {  
          let timeout = setTimeout(() => {  
            // 15秒拿不到坐标 → 判定定位失败  
            if (this.accuracy > 500) {  
              this.gpsStatusText = "❌ 定位失败:请检查GPS/高精度/权限"  
              this.gpsStatusClass = "bad"  
            }  
          }, 15000)  

          uni.onLocationChange((res) => {  
            if (!this.running) return  

            // 有坐标 → 清除失败超时  
            clearTimeout(timeout)  

            this.lat = res.latitude  
            this.lng = res.longitude  
            this.accuracy = res.accuracy || 999  

            // GPS状态判断  
            if (this.accuracy > 100) {  
              this.gpsStatusText = "? 室内无卫星 / 信号差"  
              this.gpsStatusClass = "bad"  
            } else if (this.accuracy > 30) {  
              this.gpsStatusText = "? GPS信号弱"  
              this.gpsStatusClass = "weak"  
            } else {  
              this.gpsStatusText = "? GPS正常,记录中"  
              this.gpsStatusClass = "good"  
            }  

            // 记录轨迹  
            if (this.accuracy < 100) {  
              this.path.push({ lat: this.lat, lng: this.lng })  
            }  

            // 计算里程  
            if (this.lastPoint && this.accuracy < 100) {  
              let dis = this.getDistance(  
                this.lastPoint.lat, this.lastPoint.lng,  
                this.lat, this.lng  
              )  
              if (dis > 1.5) this.totalDistance += dis  
            }  

            this.lastPoint = { lat: this.lat, lng: this.lng }  
          })  
        },  
        // ==============================================  
        // 启动失败 → 直接显示失败状态  
        // ==============================================  
        fail: (err) => {  
          this.gpsStatusText = "❌ 定位启动失败:" + err.errMsg  
          this.gpsStatusClass = "bad"  
          console.error("定位失败:", err)  
        }  
      })  
    },  

    stop() {  
      this.running = false  
      clearInterval(this.timer)  
      uni.stopLocationUpdate()  
      this.gpsStatusText = "已停止"  
      this.gpsStatusClass = "normal"  
    },  

    playback() {  
      if (this.path.length < 2) {  
        uni.showToast({ title: '轨迹点不足', icon: 'none' })  
        return  
      }  

      this.showCanvas = true  
      this.playIndex = 0  
      clearInterval(this.playTimer)  
      const ctx = uni.createCanvasContext('trackCanvas')  

      let minLat = Math.min(...this.path.map(p => p.lat))  
      let maxLat = Math.max(...this.path.map(p => p.lat))  
      let minLng = Math.min(...this.path.map(p => p.lng))  
      let maxLng = Math.max(...this.path.map(p => p.lng))  
      let w = 680, h = 400  

      this.playTimer = setInterval(() => {  
        if (this.playIndex >= this.path.length) {  
          clearInterval(this.playTimer)  
          return  
        }  
        let p = this.path[this.playIndex]  
        let x = ((p.lng - minLng) / (maxLng - minLng || 1)) * w  
        let y = h - ((p.lat - minLat) / (maxLat - minLat || 1)) * h  

        ctx.beginPath()  
        ctx.arc(x, y, 6, 0, 2 * Math.PI)  
        ctx.setFillStyle('#007aff')  
        ctx.fill()  
        ctx.draw(true)  
        this.playIndex++  
      }, 80)  
    },  

    getDistance(lat1, lng1, lat2, lng2) {  
      const rad = Math.PI / 180  
      const R = 6371000  
      let dLat = (lat2 - lat1) * rad  
      let dLng = (lng2 - lng1) * rad  
      let a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * rad) * Math.cos(lat2 * rad) * Math.sin(dLng / 2) ** 2  
      return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))  
    },  

    formatTime(s) {  
      const m = Math.floor(s / 60)  
      const sec = s % 60  
      return `${m}分${sec}秒`  
    }  
  }  
}  
</script>  

<style scoped>  
.wrap { padding: 30rpx; background: #f5f7fa; min-height: 100vh; }  
.header { font-size: 36rpx; font-weight: bold; text-align: center; margin: 20rpx 0; }  
.card { background: #fff; border-radius: 20rpx; padding: 30rpx; margin-bottom: 20rpx; }  
.status { font-size: 28rpx; color: #007aff; text-align: center; margin-bottom: 10rpx; }  

.gps-status {  
  text-align: center;  
  padding: 12rpx;  
  border-radius: 10rpx;  
  font-size: 26rpx;  
  margin-bottom: 20rpx;  
}  
.gps-status.normal { background: #f5f7fa; color: #333; }  
.gps-status.weak { background: #fff4e4; color: #f57c00; }  
.gps-status.bad { background: #ffeaea; color: #d32f2f; }  
.gps-status.good { background: #e6f7e6; color: #2e7d32; }  

.distance { font-size: 54rpx; font-weight: bold; color: #02c266; text-align: center; margin: 20rpx 0; }  
.info { font-size: 24rpx; color: #666; line-height: 40rpx; }  
.btns { display: flex; justify-content: center; gap: 30rpx; }  
.canvas { width: 680rpx; height: 400rpx; background: #fff; border: 1rpx solid #eee; margin: 20rpx auto; }  
</style>
2026-05-25 22:45 负责人:无 分享
已邀请:
Ask小助手

Ask小助手 - Ask社区AI助手

欢迎到专业群( uni-app 官方技术交流群 1 ) 咨询,群中有相关专业的管理员和群友。

根据你提供的代码和问题描述,定位获取不成功但权限已经配置了,可能有以下几个原因:

1. 权限申请时机问题
虽然你在 manifest.json 中配置了权限,但在部分平台上(特别是微信小程序和鸿蒙),还需要在代码中主动调用授权。建议在 start 方法中,先调用 uni.authorize 确保权限已授权:

start() {  
  // 先检查并请求定位权限  
  uni.authorize({  
    scope: 'scope.userLocation',  
    success: () => {  
      // 权限已授权,继续启动定位  
      this.startLocationUpdate()  
    },  
    fail: () => {  
      this.gpsStatusText = "❌ 定位权限未授权,请前往设置开启"  
      this.gpsStatusClass = "bad"  
      // 引导用户去设置页面  
      uni.showModal({  
        title: '权限提示',  
        content: '需要定位权限才能记录轨迹,请开启定位权限',  
        success: (res) => {  
          if (res.confirm) {  
            uni.openSetting()  
          }  
        }  
      })  
    }  
  })  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

2. 微信小程序特殊处理
如果是微信小程序,需要注意:

  • manifest.json 中配置微信小程序的定位权限描述
  • 小程序需要用户主动触发才能调用定位相关 API
  • 建议在微信开发者工具中检查是否有权限相关的报错

3. 不同平台的定位 API 差异
根据知识库中的信息,不同平台可能需要不同的处理方式:

鸿蒙平台

  • 需要在 harmony-mp-configs/entry/src/main/module.json5 中添加权限配置:
    "ohos.permission.LOCATION",  
    "ohos.permission.APPROXIMATELY_LOCATION"

    本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

  • 必须先调用 uni.authorize 请求用户授权
  • 需要在华为 AppGallery Connect 后台开通地图服务
  • 详细配置参考:鸿蒙位置设置指南

4. 定位启动延迟问题
你在代码中使用了 15 秒超时判断,但实际环境中 GPS 冷启动可能需要更长时间。建议:

  • 增加超时时间到 30 秒
  • 在室内或信号差的环境下,提示用户到开阔地带

5. 真机调试建议

  • 确保使用真机调试,模拟器通常不支持 GPS 定位
  • 检查手机的系统定位服务是否开启
  • 检查应用的具体定位权限设置(精确位置 vs 大致位置)

6. 优化后的代码示例

start() {  
  this.running = true  
  this.startTime = Date.now()  
  // ... 其他初始化代码  

  // 先检查权限  
  uni.getSetting({  
    success: (res) => {  
      if (!res.authSetting['scope.userLocation']) {  
        // 未授权,请求授权  
        uni.authorize({  
          scope: 'scope.userLocation',  
          success: () => {  
            this.startLocationUpdate()  
          },  
          fail: () => {  
            this.gpsStatusText = "❌ 定位权限被拒绝"  
            this.gpsStatusClass = "bad"  
            this.running = false  
          }  
        })  
      } else {  
        // 已授权,直接启动定位  
        this.startLocationUpdate()  
      }  
    }  
  })  
},  

startLocationUpdate() {  
  uni.startLocationUpdate({  
    enableHighAccuracy: true,  
    success: () => {  
      // ... 定位启动成功后的逻辑  
    },  
    fail: (err) => {  
      this.gpsStatusText = "❌ 定位启动失败:" + err.errMsg  
      this.gpsStatusClass = "bad"  
      console.error("定位失败:", err)  
    }  
  })  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

如果以上方法都不能解决问题,建议提供具体的运行平台(iOS/Android/微信小程序/鸿蒙等)和环境信息,以便进一步排查。

内容为 AI 生成,仅供参考

要回复问题请先登录注册