修复地图定位bug

This commit is contained in:
2025-11-28 09:21:37 +08:00
parent 089b8d708e
commit 2a249d04da
11 changed files with 602 additions and 441 deletions
+89 -60
View File
@@ -1,9 +1,9 @@
<template>
<view class="search-page">
<view class="map-wrap">
<MapComponent :userLocation="userLocation" :filteredPositions="filteredPositions"
:enableMarkers="true" :customHeight="'100%'" :hideControls="true" :fullWidth="true"
@mapCenterChange="onMapCenterChange" @relocate="init" @markerTap="goToPositionDetail" />
<MapComponent :userLocation="userLocation" :filteredPositions="filteredPositions" :enableMarkers="true"
:customHeight="'100%'" :hideControls="true" :fullWidth="true" @mapCenterChange="onMapCenterChange"
@relocate="init" @markerTap="goToPositionDetail" />
<!-- 定位按钮 -->
<view class="relocate-btn" @click="init">
<image src="/static/location.png" class="relocate-icon" mode="aspectFit"></image>
@@ -12,15 +12,19 @@
<view class="list-wrap">
<view class="panel">
<view class="filter-tabs">
<view class="tab" :class="{ active: activeTab === 'rent' }" @click="setTab('rent')">{{ $t('location.rent') }}</view>
<view class="tab" :class="{ active: activeTab === 'return' }" @click="setTab('return')">{{ $t('location.return') }}</view>
<view class="tab" :class="{ active: activeTab === 'rent' }" @click="setTab('rent')">
{{ $t('location.rent') }}</view>
<view class="tab" :class="{ active: activeTab === 'return' }" @click="setTab('return')">
{{ $t('location.return') }}</view>
</view>
<scroll-view class="list-scroll" scroll-y="true">
<view class="card" :class="{ available: isRentable(item), invalid: !isValidCoordinate(item.latitude, item.longitude) }"
<view class="card"
:class="{ available: isRentable(item), invalid: !isValidCoordinate(item.latitude, item.longitude) }"
v-for="(item, index) in filteredPositions" :key="item.positionId || index"
@click="goToPositionDetail(item)">
<view class="thumb">
<image v-if="item.deviceImg" :src="item.deviceImg" class="thumb-img" mode="aspectFill"></image>
<image v-if="item.deviceImg" :src="item.deviceImg" class="thumb-img" mode="aspectFill">
</image>
<image v-else src="/static/device-info.png" class="thumb-img" mode="aspectFit"></image>
</view>
<view class="info">
@@ -31,41 +35,44 @@
<view class="row sub" v-if="item.location">
<text class="addr">{{ item.location }}</text>
</view>
<view class="row meta" v-if="item.workTime && item.workTime !== '0'">
<text class="time">{{ $t('location.businessHours') }}{{ item.workTime }}</text>
</view>
<view class="row meta" v-if="!isValidCoordinate(item.latitude, item.longitude)">
<text class="time" style="color: #ff6b6b;">{{ $t('location.coordinateError') }}</text>
</view>
<view class="row meta" v-if="item.availablePowerBankCount !== undefined && item.availablePowerBankCount !== null">
<text class="time">可租借{{ item.availablePowerBankCount }} </text>
</view>
<view class="row meta" v-if="item.availableEmptyGridCount !== undefined && item.availableEmptyGridCount !== null">
<text class="time">可归还{{ item.availableEmptyGridCount }} 个空位</text>
</view>
<view class="row meta remark-info" v-if="item.remark">
<text class="time">💰 {{ item.remark }}</text>
</view>
<view class="tags">
<view class="tag rent" v-if="isRentable(item)">{{ $t('location.rent') }}</view>
<view class="tag return" v-if="isReturnable(item)">{{ $t('location.return') }}</view>
</view>
<view class="row meta" v-if="item.workTime && item.workTime !== '0'">
<text class="time">{{ $t('location.businessHours') }}{{ item.workTime }}</text>
</view>
<view class="row meta" v-if="!isValidCoordinate(item.latitude, item.longitude)">
<text class="time" style="color: #ff6b6b;">{{ $t('location.coordinateError') }}</text>
</view>
<view class="row meta"
v-if="item.availablePowerBankCount !== undefined && item.availablePowerBankCount !== null">
<text class="time">可租借{{ item.availablePowerBankCount }} </text>
</view>
<view class="row meta"
v-if="item.availableEmptyGridCount !== undefined && item.availableEmptyGridCount !== null">
<text class="time">可归还{{ item.availableEmptyGridCount }} 个空位</text>
</view>
<view class="row meta remark-info" v-if="item.remark">
<text class="time">💰 {{ item.remark }}</text>
</view>
<view class="tags">
<view class="tag rent" v-if="isRentable(item)">{{ $t('location.rent') }}</view>
<view class="tag return" v-if="isReturnable(item)">{{ $t('location.return') }}</view>
</view>
</view>
<view class="actions">
<view class="nav"
:class="{ disabled: !isValidCoordinate(item.latitude, item.longitude) }"
<view class="nav" :class="{ disabled: !isValidCoordinate(item.latitude, item.longitude) }"
@click.stop="navigateToPosition(item)">
<image src="/static/luxian.png" class="action-icon" mode="aspectFit"></image>
</view>
<view class="distance" v-if="item.distance && isValidCoordinate(item.latitude, item.longitude)">{{ item.distance }}</view>
<view class="distance"
v-if="item.distance && isValidCoordinate(item.latitude, item.longitude)">
{{ item.distance }}</view>
</view>
</view>
<view class="empty-state" v-if="!isLoading && (!positionList || positionList.length === 0)">
<image class="empty-icon" src="/static/scan-icon.png" mode="aspectFit" />
<text class="empty-text">{{ $t('home.noNearbyDevice') }}</text>
</view>
<view class="empty-state" v-if="!isLoading && (!positionList || positionList.length === 0)">
<image class="empty-icon" src="/static/scan-icon.png" mode="aspectFit" />
<text class="empty-text">{{ $t('home.noNearbyDevice') }}</text>
</view>
</scroll-view>
</view>
</view>
@@ -88,15 +95,25 @@
getRegeo,
calculateDistanceSync
} from '../../utils/mapUtils.js'
import { useI18n } from '@/utils/i18n.js'
import {
useI18n
} from '@/utils/i18n.js'
const { t: $t } = useI18n()
const {
t: $t
} = useI18n()
onMounted(() => {
uni.setNavigationBarTitle({
title: $t('search.title')
})
// uni.showLoading({
// title:'11111',
// mask:true
// })
init()
// uni.hideLoading();
})
const userLocation = ref(null)
@@ -173,7 +190,7 @@
const loadPositions = async (center) => {
try {
isLoading.value = true
if (!center || !center.latitude || !center.longitude) {
console.warn('中心点位置信息不完整,无法查询附近设备')
return
@@ -187,11 +204,11 @@
pageNum: 1,
pageSize: 100
})
if (res.code === 200) {
// 新接口返回的是 data.records
const devices = res.data?.records || []
// 将设备数据转换为统一格式
positionList.value = devices.map(device => {
const transformed = transformDeviceData(device)
@@ -199,10 +216,11 @@
return {
...transformed,
canRent: activeTab.value === 'rent' ? true : (device.availablePowerBankCount > 0),
canReturn: activeTab.value === 'return' ? true : (device.availableEmptyGridCount > 0)
canReturn: activeTab.value === 'return' ? true : (device.availableEmptyGridCount >
0)
}
})
calculateDistances(center)
} else {
positionList.value = []
@@ -217,24 +235,35 @@
}
}
const init = async () => {
isLoading.value = true
try {
const loc = await getUserLocation()
userLocation.value = {
longitude: loc.longitude,
latitude: loc.latitude
}
await loadPositions(userLocation.value)
} catch (e) {
await loadPositions(userLocation.value || {
longitude: 0,
latitude: 0
})
} finally {
isLoading.value = false
const init = async () => {
isLoading.value = true
uni.showLoading({
mask: true
})
try {
const loc = await getUserLocation()
if (!loc?.longitude || !loc?.latitude) {
throw new Error('invalid location result')
}
userLocation.value = {
longitude: loc.longitude,
latitude: loc.latitude
}
await loadPositions(userLocation.value)
} catch (e) {
console.error('初始化定位失败:', e)
userLocation.value = null
positionList.value = []
filteredPositions.value = []
uni.showToast({
title: $t('home.getLocationFailed'),
icon: 'none'
})
} finally {
isLoading.value = false
uni.hideLoading();
}
}
const onMapCenterChange = (center) => {
if (center && typeof center.longitude !== 'undefined' && typeof center.latitude !== 'undefined') {
@@ -276,7 +305,6 @@
url: `/pages/position/detail?positionId=${position.positionId}`
})
}
</script>
<style lang="scss" scoped>
@@ -391,7 +419,7 @@
border-radius: 16rpx;
background: #F0F2F5;
overflow: hidden;
.thumb-img {
width: 100%;
height: 100%;
@@ -427,6 +455,7 @@
.addr {
display: -webkit-box;
line-clamp: 1;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
@@ -435,11 +464,11 @@
.row.meta {
color: #999;
font-size: 22rpx;
&.remark-info {
color: #FF6B35;
font-weight: 500;
.time {
color: #FF6B35;
}