恢复首页来馆快捷入口。 原生微信小程序直接调用地图位置能力,H5 嵌入场景补充宿主环境识别与承接页跳转。 同时修复 H5 与小程序构建中的静态资源平台兼容。
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user