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