@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user