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

恢复首页来馆快捷入口。
原生微信小程序直接调用地图位置能力,H5 嵌入场景补充宿主环境识别与承接页跳转。
同时修复 H5 与小程序构建中的静态资源平台兼容。
This commit is contained in:
lyf
2026-07-11 01:38:37 +08:00
parent 3f64b3a610
commit 1678f10f27
6 changed files with 120 additions and 36 deletions

View File

@@ -124,7 +124,10 @@ import {
THIRD_PARTY_MAP_PROVIDERS,
type ThirdPartyMapProviderOption
} from '@/services/ThirdPartyMapSearchService'
import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment'
import {
isNativeWechatMiniProgram,
isWechatMiniProgramRuntime
} from '@/utils/hostEnvironment'
const props = withDefaults(defineProps<{
visible?: boolean
@@ -148,7 +151,7 @@ const emit = defineEmits<{
const typeOptions = computed(() => ARRIVAL_TARGET_TYPES)
const mapProviders = computed(() => THIRD_PARTY_MAP_PROVIDERS)
const shouldUseMiniProgramLocation = computed(() => isEmbeddedInWechatMiniProgram())
const shouldUseMiniProgramLocation = computed(() => isWechatMiniProgramRuntime())
const primaryActionText = computed(() => (
shouldUseMiniProgramLocation.value ? '打开地图导航' : '第三方导航'
))
@@ -239,7 +242,7 @@ const startLayoutObserver = () => {
})
}
const handleNavigateTap = () => {
const handleNavigateTap = async () => {
if (!props.selectedTarget) {
uni.showToast({
title: '请先选择点位',
@@ -248,13 +251,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
})
const target = {
latitude: props.selectedTarget.latitude,
longitude: props.selectedTarget.longitude,
name: props.selectedTarget.title,
address: props.selectedTarget.subtitle
}
const isNativeMiniProgram = isNativeWechatMiniProgram()
const openedInMiniProgram = await openWechatMiniProgramLocation(target)
if (openedInMiniProgram || isNativeMiniProgram || isWechatMiniProgramRuntime()) {
return
}

View File

@@ -117,7 +117,6 @@
class="guide-quick-actions"
>
<view
v-if="showArrivalQuickAction"
class="guide-quick-action"
:class="{ active: guideQuickActiveAction === 'arrival' }"
@tap="handleMoreOutdoorNav"
@@ -662,7 +661,6 @@ const showGuideFloatingActions = computed(() => (
&& !isSimulatingRoute.value
&& (!showGuideHomeDock.value || !homeSearchExpanded.value)
))
const showArrivalQuickAction = false
const activeArrivalTargets = computed(() => ARRIVAL_TARGETS_BY_TYPE[activeArrivalType.value])

View File

@@ -105,13 +105,17 @@ onUnmounted(() => {
right: 0;
top: 0;
height: 210px;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0 64px, rgba(0, 0, 0, 0.18) 65px, rgba(0, 0, 0, 0.5) 100%),
url('/static/guide/app-launch-loading.webp') center top / cover no-repeat;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0 64px, rgba(224, 225, 0, 0.2) 65px, rgba(21, 23, 19, 0.36) 100%);
pointer-events: none;
}
/* #ifdef H5 */
.poi-search-page::before {
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0 64px, rgba(0, 0, 0, 0.18) 65px, rgba(0, 0, 0, 0.5) 100%),
url('/static/guide/app-launch-loading.webp') center top / cover no-repeat;
}
.poi-search-page {
height: var(--poi-search-page-height, 100dvh);
min-height: var(--poi-search-page-height, 100dvh);

View File

@@ -1,4 +1,8 @@
import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment'
import { openExternalNavigation } from '@/services/MapNavigationService'
import {
isEmbeddedInWechatMiniProgram,
isNativeWechatMiniProgram
} from '@/utils/hostEnvironment'
export type ThirdPartyMapProvider = 'amap' | 'baidu' | 'tencent'
@@ -15,6 +19,7 @@ export interface WechatMiniProgramLocationTarget {
}
interface WechatMiniProgramBridge {
getEnv?: (callback: (result: { miniprogram?: boolean }) => void) => void
navigateTo?: (options: {
url: string
success?: () => void
@@ -78,14 +83,16 @@ export const openThirdPartyMapSearch = (
export const buildWechatMiniProgramOpenLocationUrl = (
target: WechatMiniProgramLocationTarget
) => {
const params = new URLSearchParams({
latitude: String(target.latitude),
longitude: String(target.longitude),
name: target.name,
address: target.address || ''
})
const params = [
['latitude', String(target.latitude)],
['longitude', String(target.longitude)],
['name', target.name],
['address', target.address || '']
]
.map(([key, value]) => `${key}=${encode(value)}`)
.join('&')
return `/pages/open-location/index?${params.toString()}`
return `/pages/open-location/index?${params}`
}
const getWechatMiniProgramBridge = (): WechatMiniProgramBridge | null => {
@@ -123,31 +130,84 @@ const loadWechatJsSdk = () => {
return wechatJsSdkLoadPromise
}
export const openWechatMiniProgramLocation = async (
target: WechatMiniProgramLocationTarget
) => {
if (!isEmbeddedInWechatMiniProgram()) return false
const isWechatBrowser = () => (
typeof window !== 'undefined'
&& /MicroMessenger/i.test(window.navigator?.userAgent || '')
)
await loadWechatJsSdk()
const miniProgram = getWechatMiniProgramBridge()
if (!miniProgram?.navigateTo) {
uni.showToast({
title: '请在小程序内打开地图',
icon: 'none'
})
return false
const resolveMiniProgramWebViewEnvironment = (
miniProgram: WechatMiniProgramBridge
) => {
if (isEmbeddedInWechatMiniProgram()) return Promise.resolve(true)
const getEnv = miniProgram.getEnv
if (!getEnv) return Promise.resolve(false)
return new Promise<boolean>((resolve) => {
let settled = false
const finish = (isMiniProgram: boolean) => {
if (settled) return
settled = true
clearTimeout(timeout)
resolve(isMiniProgram)
}
const timeout = setTimeout(() => finish(false), 1500)
try {
getEnv((result) => finish(Boolean(result.miniprogram)))
} catch (error) {
console.error('识别小程序 web-view 环境失败:', error)
finish(false)
}
})
}
const navigateToMiniProgramLocationPage = (
miniProgram: WechatMiniProgramBridge,
target: WechatMiniProgramLocationTarget
) => new Promise<boolean>((resolve) => {
if (!miniProgram.navigateTo) {
resolve(false)
return
}
miniProgram.navigateTo({
url: buildWechatMiniProgramOpenLocationUrl(target),
success: () => resolve(true),
fail: (error) => {
console.error('跳转小程序地图页失败:', error)
uni.showToast({
title: '无法打开地图导航',
icon: 'none'
})
resolve(false)
}
})
})
return true
export const openWechatMiniProgramLocation = async (
target: WechatMiniProgramLocationTarget
) => {
if (isNativeWechatMiniProgram()) {
return openExternalNavigation(target)
}
const synchronouslyEmbedded = isEmbeddedInWechatMiniProgram()
if (!synchronouslyEmbedded && !isWechatBrowser()) return false
await loadWechatJsSdk()
const miniProgram = getWechatMiniProgramBridge()
if (!miniProgram?.navigateTo) {
if (synchronouslyEmbedded) {
uni.showToast({
title: '请在小程序内打开地图',
icon: 'none'
})
}
return false
}
const isMiniProgramWebView = await resolveMiniProgramWebViewEnvironment(miniProgram)
if (!isMiniProgramWebView) return false
return navigateToMiniProgramLocationPage(miniProgram, target)
}

View File

@@ -1,3 +1,4 @@
/* #ifdef H5 */
@font-face {
font-family: '鸿蒙黑体';
src: url('/static/Fonts/HarmonyOS_SansSC_Thin.ttf') format('truetype');
@@ -53,6 +54,7 @@
font-style: normal;
font-display: swap;
}
/* #endif */
/* CSS 变量定义 */
:root {

View File

@@ -15,6 +15,16 @@ const getCurrentUrlSearchParams = () => {
return params
}
export const isNativeWechatMiniProgram = () => {
let isNativeRuntime = false
// #ifdef MP-WEIXIN
isNativeRuntime = true
// #endif
return isNativeRuntime
}
export const isEmbeddedInWechatMiniProgram = () => {
if (typeof window === 'undefined') return false
@@ -32,3 +42,7 @@ export const isEmbeddedInWechatMiniProgram = () => {
return /miniProgram/i.test(window.navigator?.userAgent || '')
}
export const isWechatMiniProgramRuntime = () => (
isNativeWechatMiniProgram() || isEmbeddedInWechatMiniProgram()
)