小程序 地理位置授权怎么搞
用uniapp开发小程序,获取位置信息-地理位置授权,怎么做
大概实现样子:
真机
代码如下:
<template><view class="choose-store-wrap"><view class="search-section"><view class="city-selector" @click="selectCity"><text class="city-name">{{ selectedCity }}</text><text class="arrow">▼</text></view><view class="search-box"><text class="search-icon">🔍</text><input class="search-input" type="text" placeholder="搜索你要选择的门店"v-model="searchKeyword"@input="handleSearch"/></view></view><view class="store-list"><view class="store-item" v-for="(store, index) in filteredStores" :key="store.id"@click="selectStore(store)"><view class="store-header"><text class="store-name">{{ store.outShopName }}</text><view class="distance-info"><text class="distance-icon">📍</text><text class="distance">{{ store.lat }}</text></view></view><view class="store-tag" v-if="index === 0">距您最近</view><view class="store-address">{{ store.address }}</view><!-- <view class="store-room">{{ store.termNo }}</view> --></view></view></view>
</template><script>
export default {data() {return {selectedCity: '绿藤市',searchKeyword: '',stores: [// {// id: 1,// outShopName: '绿藤绿地新都汇店',// address: '绿藤市时光里广场时光里广场时光里广场',// lat: '距您304m'// }]}},computed: {filteredStores() {if (!this.searchKeyword) {return this.stores}return this.stores.filter(store => store.outShopName.includes(this.searchKeyword) || store.address.includes(this.searchKeyword))}},onLoad() {this.getNearbyStores()// 页面加载时请求位置权限this.requestLocationPermission()},methods: {goBack() {uni.navigateBack()},selectCity() {// 跳转到城市选择页面uni.navigateTo({url: '/pages/citySelect/citySelect'})},handleSearch() {// 搜索逻辑已在computed中处理},selectStore(store) {// 选择门店后返回上一页const pages = getCurrentPages()const prevPage = pages[pages.length - 2]if (prevPage) {// 将选中的门店信息传递给上一页prevPage.$vm.selectedStore = store}uni.navigateBack()},requestLocationPermission() {// 使用微信原生位置授权APIuni.getSetting({success: (res) => {console.log('获取设置成功:', res)if (res.authSetting['scope.userLocation']) {// 已经授权,直接获取位置this.getUserLocation()} else if (res.authSetting['scope.userLocation'] === false) {// 用户之前拒绝过,引导用户手动开启this.showLocationGuide()} else {// 首次请求位置权限this.requestLocationAuth()}},fail: (err) => {console.error('获取设置失败:', err)// 如果获取设置失败,直接尝试获取位置this.getUserLocation()}})},requestLocationAuth() {// 请求位置权限uni.authorize({scope: 'scope.userLocation',success: () => {console.log('位置权限授权成功')this.getUserLocation()},fail: (err) => {console.log('位置权限授权失败:', err)if (err.errMsg.includes('auth deny')) {// 用户拒绝授权this.showLocationGuide()} else {uni.showToast({title: '位置权限获取失败',icon: 'none'})}}})},getUserLocation() {// 获取用户位置uni.getLocation({type: 'gcj02',success: (res) => {console.log('位置获取成功:', res)// 根据位置获取附近门店this.getNearbyStores(res.latitude, res.longitude)},fail: (err) => {console.error('位置获取失败:', err)if (err.errMsg.includes('auth deny')) {this.showLocationGuide()} else {uni.showToast({title: '位置获取失败,请手动选择城市',icon: 'none'})}}})},showLocationGuide() {// 引导用户手动开启位置权限uni.showModal({title: '位置权限',content: '需要获取您的位置信息来匹配附近门店,请在设置中开启位置权限',confirmText: '去设置',cancelText: '手动选择',success: (res) => {if (res.confirm) {// 跳转到设置页面uni.openSetting({success: (settingRes) => {if (settingRes.authSetting['scope.userLocation']) {// 用户开启了位置权限this.getUserLocation()}}})} else {// 用户选择手动选择城市uni.showToast({title: '请手动选择城市',icon: 'none'})}}})},getNearbyStores(lat, lng) {// 调用API获取附近门店// =============获取门店接口============console.log('获取附近门店', lat, lng)uni.request({url:'https://xxx/app/info/shop/shopList',method:'GET',data:{},success: (res) => {console.log('门店res',res);this.stores = res.data.data},fail: (err) => {console.error('获取门店列表失败:', err)uni.showToast({title: '获取门店列表失败',icon: 'none'})}})}}
}
</script><style>
.choose-store-wrap {min-height: 100vh;background: #f5f5f5;
}.header {background: #fff;/* padding-top: 44px; */
}.nav-bar {display: flex;align-items: center;justify-content: space-between;padding: 12px 16px;height: 44px;
}.back-btn {width: 44px;height: 44px;display: flex;align-items: center;justify-content: center;
}.back-icon {font-size: 24px;color: #333;
}.title {font-size: 18px;font-weight: 600;color: #333;
}.right-icons {display: flex;gap: 12px;width: 44px;justify-content: flex-end;
}.icon {font-size: 16px;color: #666;
}.search-section {display: flex;padding: 12px 16px;background: #fff;gap: 12px;
}.city-selector {display: flex;align-items: center;gap: 4px;padding: 8px 12px;background: #f5f5f5;border-radius: 6px;min-width: 80px;
}.city-name {font-size: 14px;color: #333;
}.arrow {font-size: 12px;color: #666;
}.search-box {flex: 1;display: flex;align-items: center;background: #f5f5f5;border-radius: 6px;padding: 8px 12px;gap: 8px;
}.search-icon {font-size: 16px;color: #999;
}.search-input {flex: 1;font-size: 14px;color: #333;
}.store-list {padding: 12px 16px;
}.store-item {background: #fff;border-radius: 8px;padding: 16px;margin-bottom: 12px;position: relative;
}.store-header {display: flex;justify-content: space-between;align-items: flex-start;margin-bottom: 8px;
}.store-name {font-size: 16px;font-weight: 600;color: #333;flex: 1;
}.distance-info {display: flex;align-items: center;gap: 4px;
}.distance-icon {font-size: 12px;
}.distance {font-size: 12px;color: #666;
}.store-tag {position: absolute;top: 16px;right: 16px;background: #e7f4f2;color: #61aea7;font-size: 12px;padding: 2px 8px;border-radius: 4px;
}.store-address {font-size: 14px;color: #666;line-height: 1.4;margin-bottom: 4px;
}.store-room {font-size: 14px;color: #999;
}
</style>
注意,会报这个:
记得在manifest.json中配置: