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

View File

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

View File

@@ -105,13 +105,17 @@ onUnmounted(() => {
right: 0; right: 0;
top: 0; top: 0;
height: 210px; height: 210px;
background: 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%);
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;
pointer-events: none; pointer-events: none;
} }
/* #ifdef H5 */ /* #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 { .poi-search-page {
height: var(--poi-search-page-height, 100dvh); height: var(--poi-search-page-height, 100dvh);
min-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' export type ThirdPartyMapProvider = 'amap' | 'baidu' | 'tencent'
@@ -15,6 +19,7 @@ export interface WechatMiniProgramLocationTarget {
} }
interface WechatMiniProgramBridge { interface WechatMiniProgramBridge {
getEnv?: (callback: (result: { miniprogram?: boolean }) => void) => void
navigateTo?: (options: { navigateTo?: (options: {
url: string url: string
success?: () => void success?: () => void
@@ -78,14 +83,16 @@ export const openThirdPartyMapSearch = (
export const buildWechatMiniProgramOpenLocationUrl = ( export const buildWechatMiniProgramOpenLocationUrl = (
target: WechatMiniProgramLocationTarget target: WechatMiniProgramLocationTarget
) => { ) => {
const params = new URLSearchParams({ const params = [
latitude: String(target.latitude), ['latitude', String(target.latitude)],
longitude: String(target.longitude), ['longitude', String(target.longitude)],
name: target.name, ['name', target.name],
address: target.address || '' ['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 => { const getWechatMiniProgramBridge = (): WechatMiniProgramBridge | null => {
@@ -123,31 +130,84 @@ const loadWechatJsSdk = () => {
return wechatJsSdkLoadPromise return wechatJsSdkLoadPromise
} }
export const openWechatMiniProgramLocation = async ( const isWechatBrowser = () => (
target: WechatMiniProgramLocationTarget typeof window !== 'undefined'
) => { && /MicroMessenger/i.test(window.navigator?.userAgent || '')
if (!isEmbeddedInWechatMiniProgram()) return false )
await loadWechatJsSdk() const resolveMiniProgramWebViewEnvironment = (
const miniProgram = getWechatMiniProgramBridge() miniProgram: WechatMiniProgramBridge
if (!miniProgram?.navigateTo) { ) => {
uni.showToast({ if (isEmbeddedInWechatMiniProgram()) return Promise.resolve(true)
title: '请在小程序内打开地图', const getEnv = miniProgram.getEnv
icon: 'none' if (!getEnv) return Promise.resolve(false)
})
return 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({ miniProgram.navigateTo({
url: buildWechatMiniProgramOpenLocationUrl(target), url: buildWechatMiniProgramOpenLocationUrl(target),
success: () => resolve(true),
fail: (error) => { fail: (error) => {
console.error('跳转小程序地图页失败:', error) console.error('跳转小程序地图页失败:', error)
uni.showToast({ uni.showToast({
title: '无法打开地图导航', title: '无法打开地图导航',
icon: 'none' 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-face {
font-family: '鸿蒙黑体'; font-family: '鸿蒙黑体';
src: url('/static/Fonts/HarmonyOS_SansSC_Thin.ttf') format('truetype'); src: url('/static/Fonts/HarmonyOS_SansSC_Thin.ttf') format('truetype');
@@ -53,6 +54,7 @@
font-style: normal; font-style: normal;
font-display: swap; font-display: swap;
} }
/* #endif */
/* CSS 变量定义 */ /* CSS 变量定义 */
:root { :root {

View File

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