From f1047414bbf00a254e1c0cf99755556e45a18e6f Mon Sep 17 00:00:00 2001 From: lyf <2514544224@qq.com> Date: Mon, 27 Jul 2026 19:56:53 +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=E5=B5=8C=E9=A1=B5=E9=9D=A2=E6=A0=87=E9=A2=98=E5=90=8C?= =?UTF-8?q?=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages.json | 2 +- src/pages/explain/list.vue | 3 +- src/pages/index/index.vue | 9 ++++ src/utils/hostNavigationTitle.ts | 39 +++++++++++++++ tests/unit/ExplainListNavigation.spec.ts | 2 +- tests/unit/hostNavigationTitle.spec.ts | 61 ++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 src/utils/hostNavigationTitle.ts create mode 100644 tests/unit/hostNavigationTitle.spec.ts diff --git a/src/pages.json b/src/pages.json index b0ad303..b6a2272 100644 --- a/src/pages.json +++ b/src/pages.json @@ -25,7 +25,7 @@ { "path": "pages/explain/list", "style": { - "navigationBarTitleText": "全部讲解", + "navigationBarTitleText": "免费讲解", "navigationBarBackgroundColor": "#FFFFFF", "navigationStyle": "custom" } diff --git a/src/pages/explain/list.vue b/src/pages/explain/list.vue index 6adead1..e220cab 100644 --- a/src/pages/explain/list.vue +++ b/src/pages/explain/list.vue @@ -10,7 +10,6 @@ ([]) @@ -218,6 +218,7 @@ const loadExplainHalls = async () => { } onLoad(() => { + syncHostNavigationTitle('免费讲解') pushExplainListHistory() void loadExplainHalls() }) diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 056aa7e..a8449bf 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -276,6 +276,7 @@ import { type GuideTopTab } from '@/utils/guideTopTabs' import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment' +import { syncHostNavigationTitle } from '@/utils/hostNavigationTitle' import { guideUseCase } from '@/usecases/guideUseCase' @@ -419,6 +420,14 @@ let pendingPoiDetailUiContext: Readonly<{ // 状态 const currentTab = ref(initialTopTab()) +const topTabNavigationTitle = (tab: GuideTopTab) => ( + tab === 'explain' ? '免费讲解' : '地图导览' +) + +watch(currentTab, (tab) => { + syncHostNavigationTitle(topTabNavigationTitle(tab)) +}, { immediate: true }) + const launchOverlayVisible = ref(shouldShowLaunchOverlay()) const launchOverlayLeaving = ref(false) const launchProgress = ref(8) diff --git a/src/utils/hostNavigationTitle.ts b/src/utils/hostNavigationTitle.ts new file mode 100644 index 0000000..3fab94d --- /dev/null +++ b/src/utils/hostNavigationTitle.ts @@ -0,0 +1,39 @@ +import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment' + +export const MINI_PROGRAM_NAVIGATION_TITLE_MESSAGE = 'museum-guide:navigation-title' + +type MiniProgramBridge = { + postMessage?: (options: { + data: { + type: typeof MINI_PROGRAM_NAVIGATION_TITLE_MESSAGE + title: string + } + }) => void +} + +const getMiniProgramBridge = () => { + if (typeof window === 'undefined') return undefined + + return (window as Window & { + wx?: { + miniProgram?: MiniProgramBridge + } + }).wx?.miniProgram +} + +export const syncHostNavigationTitle = (title: string) => { + if (typeof document !== 'undefined') document.title = title + + if (typeof uni !== 'undefined' && typeof uni.setNavigationBarTitle === 'function') { + uni.setNavigationBarTitle({ title }) + } + + if (!isEmbeddedInWechatMiniProgram()) return + + getMiniProgramBridge()?.postMessage?.({ + data: { + type: MINI_PROGRAM_NAVIGATION_TITLE_MESSAGE, + title + } + }) +} diff --git a/tests/unit/ExplainListNavigation.spec.ts b/tests/unit/ExplainListNavigation.spec.ts index 1836a95..440972c 100644 --- a/tests/unit/ExplainListNavigation.spec.ts +++ b/tests/unit/ExplainListNavigation.spec.ts @@ -112,7 +112,7 @@ describe('讲解展厅列表返回', () => { window.history.replaceState({}, '', window.location.href) const wrapper = mountExplainList() - expect(wrapper.getComponent(ExplainHallSelectStub).props('forceInternalHeader')).toBe(true) + expect(wrapper.getComponent(ExplainHallSelectStub).props('forceInternalHeader')).toBe(false) await wrapper.get('[data-testid="explain-list-back"]').trigger('click') expect(uni.navigateBack).not.toHaveBeenCalled() diff --git a/tests/unit/hostNavigationTitle.spec.ts b/tests/unit/hostNavigationTitle.spec.ts new file mode 100644 index 0000000..97a6f25 --- /dev/null +++ b/tests/unit/hostNavigationTitle.spec.ts @@ -0,0 +1,61 @@ +// @vitest-environment happy-dom + +import { afterEach, describe, expect, it, vi } from 'vitest' +import { + MINI_PROGRAM_NAVIGATION_TITLE_MESSAGE, + syncHostNavigationTitle +} from '@/utils/hostNavigationTitle' + +const hostEnvironmentMocks = vi.hoisted(() => ({ + embeddedInWechatMiniProgram: false +})) + +vi.mock('@/utils/hostEnvironment', () => ({ + isEmbeddedInWechatMiniProgram: () => hostEnvironmentMocks.embeddedInWechatMiniProgram +})) + +afterEach(() => { + hostEnvironmentMocks.embeddedInWechatMiniProgram = false + vi.unstubAllGlobals() +}) + +describe('小程序宿主标题同步', () => { + it('嵌入态同步免费讲解标题并通知小程序宿主', () => { + const postMessage = vi.fn() + const setNavigationBarTitle = vi.fn() + hostEnvironmentMocks.embeddedInWechatMiniProgram = true + vi.stubGlobal('uni', { setNavigationBarTitle }) + vi.stubGlobal('window', { + ...window, + wx: { + miniProgram: { postMessage } + } + }) + + syncHostNavigationTitle('免费讲解') + + expect(document.title).toBe('免费讲解') + expect(setNavigationBarTitle).toHaveBeenCalledWith({ title: '免费讲解' }) + expect(postMessage).toHaveBeenCalledWith({ + data: { + type: MINI_PROGRAM_NAVIGATION_TITLE_MESSAGE, + title: '免费讲解' + } + }) + }) + + it('非嵌入态不向小程序桥接发送标题', () => { + const postMessage = vi.fn() + vi.stubGlobal('window', { + ...window, + wx: { + miniProgram: { postMessage } + } + }) + + syncHostNavigationTitle('免费讲解') + + expect(document.title).toBe('免费讲解') + expect(postMessage).not.toHaveBeenCalled() + }) +})