修复小程序内来馆地图导航
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-11 17:24:45 +08:00
parent 12c0b5ede2
commit f9fefa11ef
12 changed files with 1161 additions and 146 deletions

View File

@@ -16,15 +16,13 @@
</template>
<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import { computed, ref } from 'vue'
interface OpenLocationOptions {
latitude?: string
longitude?: string
name?: string
address?: string
}
import { openWechatHostLocation } from '@/services/WechatOpenLocationService'
import {
parseWechatOpenLocationPageOptions,
type WechatOpenLocationPageOptions
} from '@/utils/wechatOpenLocationProtocol'
const latitude = ref<number | null>(null)
const longitude = ref<number | null>(null)
@@ -32,6 +30,10 @@ const locationName = ref('')
const locationAddress = ref('')
const hasOpened = ref(false)
const hasError = ref(false)
const isOpening = ref(false)
const errorMessage = ref('')
let isPageActive = true
let autoBackTimer: ReturnType<typeof setTimeout> | null = null
const title = computed(() => {
if (hasError.value) return '地图打开失败'
@@ -40,22 +42,18 @@ const title = computed(() => {
})
const description = computed(() => {
if (hasError.value) return '请返回导览后重试,或检查小程序位置权限。'
if (hasError.value) return errorMessage.value || '请返回导览后重试,或检查小程序位置权限。'
if (locationName.value) return locationName.value
return '正在为你唤起地图位置页。'
})
const safeDecode = (value?: string) => {
if (!value) return ''
try {
return decodeURIComponent(value)
} catch {
return value
}
}
const goBack = () => {
if (!isPageActive) return
isPageActive = false
if (autoBackTimer) {
clearTimeout(autoBackTimer)
autoBackTimer = null
}
uni.navigateBack({
delta: 1,
fail: () => {
@@ -66,9 +64,11 @@ const goBack = () => {
})
}
const openLocation = () => {
const openLocation = async () => {
if (isOpening.value) return
if (latitude.value === null || longitude.value === null) {
hasError.value = true
errorMessage.value = '地图参数无效,请返回导览后重试。'
uni.showToast({
title: '缺少地图坐标',
icon: 'none'
@@ -76,42 +76,57 @@ const openLocation = () => {
return
}
uni.openLocation({
isOpening.value = true
const result = await openWechatHostLocation({
latitude: latitude.value,
longitude: longitude.value,
name: locationName.value,
address: locationAddress.value,
scale: 18,
success: () => {
hasOpened.value = true
hasError.value = false
setTimeout(goBack, 300)
},
fail: (error) => {
console.error('打开地图位置失败:', error)
hasError.value = true
uni.showToast({
title: '无法打开地图',
icon: 'none'
})
}
address: locationAddress.value
})
}
if (!isPageActive) return
isOpening.value = false
onLoad((options?: OpenLocationOptions) => {
latitude.value = Number(options?.latitude)
longitude.value = Number(options?.longitude)
locationName.value = safeDecode(options?.name) || '深圳自然博物馆'
locationAddress.value = safeDecode(options?.address)
if (!Number.isFinite(latitude.value) || !Number.isFinite(longitude.value)) {
latitude.value = null
longitude.value = null
hasError.value = true
if (result.status === 'opened') {
hasOpened.value = true
hasError.value = false
autoBackTimer = setTimeout(goBack, 300)
return
}
openLocation()
hasError.value = true
errorMessage.value = result.reason === 'timeout'
? '微信地图响应超时,请重试或返回导览。'
: '微信地图能力调用失败,请检查权限后重试。'
uni.showToast({
title: result.reason === 'timeout' ? '微信地图响应超时' : '无法打开地图',
icon: 'none'
})
}
onLoad((options?: WechatOpenLocationPageOptions) => {
isPageActive = true
const result = parseWechatOpenLocationPageOptions(options)
if (!result.ok) {
hasError.value = true
errorMessage.value = result.message
uni.showToast({
title: result.message,
icon: 'none'
})
return
}
latitude.value = result.value.latitude
longitude.value = result.value.longitude
locationName.value = result.value.name
locationAddress.value = result.value.address || ''
void openLocation()
})
onUnload(() => {
isPageActive = false
if (autoBackTimer) clearTimeout(autoBackTimer)
autoBackTimer = null
})
</script>