From a5b19db35501f4d362f66e7105c6105c733d6b8c Mon Sep 17 00:00:00 2001
From: lyf <2514544224@qq.com>
Date: Fri, 10 Jul 2026 11:20:17 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B0=8F=E7=A8=8B=E5=BA=8F?=
=?UTF-8?q?=E5=86=85=E6=9D=A5=E9=A6=86=E5=9C=B0=E5=9B=BE=E5=AF=BC=E8=88=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/navigation/ArrivalPanel.vue | 18 +-
src/pages.json | 7 +
src/pages/open-location/index.vue | 184 +++++++++++++++++++++
src/services/ThirdPartyMapSearchService.ts | 96 +++++++++++
4 files changed, 304 insertions(+), 1 deletion(-)
create mode 100644 src/pages/open-location/index.vue
diff --git a/src/components/navigation/ArrivalPanel.vue b/src/components/navigation/ArrivalPanel.vue
index be9676e..e568109 100644
--- a/src/components/navigation/ArrivalPanel.vue
+++ b/src/components/navigation/ArrivalPanel.vue
@@ -68,7 +68,7 @@
:class="{ disabled: !selectedTarget }"
@tap="handleNavigateTap"
>
- 第三方导航
+ {{ primaryActionText }}
@@ -116,9 +116,11 @@ import {
} from '@/data/arrivalSearchTargets'
import {
openThirdPartyMapSearch,
+ openWechatMiniProgramLocation,
THIRD_PARTY_MAP_PROVIDERS,
type ThirdPartyMapProviderOption
} from '@/services/ThirdPartyMapSearchService'
+import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment'
const props = withDefaults(defineProps<{
visible?: boolean
@@ -142,6 +144,10 @@ const emit = defineEmits<{
const typeOptions = computed(() => ARRIVAL_TARGET_TYPES)
const mapProviders = computed(() => THIRD_PARTY_MAP_PROVIDERS)
+const shouldUseMiniProgramLocation = computed(() => isEmbeddedInWechatMiniProgram())
+const primaryActionText = computed(() => (
+ shouldUseMiniProgramLocation.value ? '打开地图导航' : '第三方导航'
+))
const arrivalPanelRef = ref(null)
const isCollapsed = ref(false)
const providerSheetVisible = ref(false)
@@ -238,6 +244,16 @@ const handleNavigateTap = () => {
return
}
+ if (shouldUseMiniProgramLocation.value) {
+ void openWechatMiniProgramLocation({
+ latitude: props.selectedTarget.latitude,
+ longitude: props.selectedTarget.longitude,
+ name: props.selectedTarget.title,
+ address: props.selectedTarget.subtitle
+ })
+ return
+ }
+
providerSheetVisible.value = true
}
diff --git a/src/pages.json b/src/pages.json
index 884f4df..fd65c81 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -53,6 +53,13 @@
"navigationBarBackgroundColor": "#FFFFFF",
"navigationStyle": "custom"
}
+ },
+ {
+ "path": "pages/open-location/index",
+ "style": {
+ "navigationBarTitleText": "地图导航",
+ "navigationBarBackgroundColor": "#FFFFFF"
+ }
}
],
"globalStyle": {
diff --git a/src/pages/open-location/index.vue b/src/pages/open-location/index.vue
new file mode 100644
index 0000000..3833a29
--- /dev/null
+++ b/src/pages/open-location/index.vue
@@ -0,0 +1,184 @@
+
+
+
+ {{ title }}
+ {{ description }}
+
+
+ 重新打开
+
+
+ 返回导览
+
+
+
+
+
+
+
+
+
diff --git a/src/services/ThirdPartyMapSearchService.ts b/src/services/ThirdPartyMapSearchService.ts
index 8328b19..3e4eaeb 100644
--- a/src/services/ThirdPartyMapSearchService.ts
+++ b/src/services/ThirdPartyMapSearchService.ts
@@ -1,3 +1,5 @@
+import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment'
+
export type ThirdPartyMapProvider = 'amap' | 'baidu' | 'tencent'
export interface ThirdPartyMapSearchTarget {
@@ -5,6 +7,23 @@ export interface ThirdPartyMapSearchTarget {
region: string
}
+export interface WechatMiniProgramLocationTarget {
+ latitude: number
+ longitude: number
+ name: string
+ address?: string
+}
+
+interface WechatMiniProgramBridge {
+ navigateTo?: (options: {
+ url: string
+ success?: () => void
+ fail?: (error: unknown) => void
+ }) => void
+}
+
+let wechatJsSdkLoadPromise: Promise | null = null
+
export interface ThirdPartyMapProviderOption {
provider: ThirdPartyMapProvider
label: string
@@ -55,3 +74,80 @@ export const openThirdPartyMapSearch = (
icon: 'none'
})
}
+
+export const buildWechatMiniProgramOpenLocationUrl = (
+ target: WechatMiniProgramLocationTarget
+) => {
+ const params = new URLSearchParams({
+ latitude: String(target.latitude),
+ longitude: String(target.longitude),
+ name: target.name,
+ address: target.address || ''
+ })
+
+ return `/pages/open-location/index?${params.toString()}`
+}
+
+const getWechatMiniProgramBridge = (): WechatMiniProgramBridge | null => {
+ if (typeof window === 'undefined') return null
+
+ return (window as Window & {
+ wx?: {
+ miniProgram?: WechatMiniProgramBridge
+ }
+ }).wx?.miniProgram || null
+}
+
+const loadWechatJsSdk = () => {
+ if (typeof document === 'undefined') return Promise.resolve(false)
+ if (getWechatMiniProgramBridge()) return Promise.resolve(true)
+ if (wechatJsSdkLoadPromise) return wechatJsSdkLoadPromise
+
+ wechatJsSdkLoadPromise = new Promise((resolve) => {
+ const existingScript = document.querySelector('script[data-wechat-js-sdk="true"]')
+ if (existingScript) {
+ existingScript.addEventListener('load', () => resolve(Boolean(getWechatMiniProgramBridge())), { once: true })
+ existingScript.addEventListener('error', () => resolve(false), { once: true })
+ return
+ }
+
+ const script = document.createElement('script')
+ script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js'
+ script.async = true
+ script.dataset.wechatJsSdk = 'true'
+ script.onload = () => resolve(Boolean(getWechatMiniProgramBridge()))
+ script.onerror = () => resolve(false)
+ document.head.appendChild(script)
+ })
+
+ return wechatJsSdkLoadPromise
+}
+
+export const openWechatMiniProgramLocation = async (
+ target: WechatMiniProgramLocationTarget
+) => {
+ if (!isEmbeddedInWechatMiniProgram()) return false
+
+ await loadWechatJsSdk()
+ const miniProgram = getWechatMiniProgramBridge()
+ if (!miniProgram?.navigateTo) {
+ uni.showToast({
+ title: '请在小程序内打开地图',
+ icon: 'none'
+ })
+ return false
+ }
+
+ miniProgram.navigateTo({
+ url: buildWechatMiniProgramOpenLocationUrl(target),
+ fail: (error) => {
+ console.error('跳转小程序地图页失败:', error)
+ uni.showToast({
+ title: '无法打开地图导航',
+ icon: 'none'
+ })
+ }
+ })
+
+ return true
+}