diff --git a/src/pages/explain/list.vue b/src/pages/explain/list.vue index 4b27db1..e1d2bdb 100644 --- a/src/pages/explain/list.vue +++ b/src/pages/explain/list.vue @@ -42,6 +42,7 @@ import { import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment' import { explainGuideStopListUrl } from '@/utils/explainNavigation' import { returnToWechatMiniProgram } from '@/services/WechatMiniProgramBridgeService' +import { syncHostNavigationTitle } from '@/utils/hostNavigationTitle' const explainHallItems = ref([]) const explainLoading = ref(false) @@ -236,6 +237,7 @@ const loadExplainHalls = async () => { } onLoad(() => { + if (shouldUseHostNavigation.value) syncHostNavigationTitle('免费讲解') pushExplainListHistory() void loadExplainHalls() }) diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 0240273..6e07a26 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -1032,6 +1032,11 @@ const syncTopTabToUrl = (tabId: GuideTopTab) => { } } +const syncEmbeddedHostNavigationTitle = (tabId: GuideTopTab) => { + if (!isEmbeddedInWechatMiniProgram()) return + syncHostNavigationTitle(tabId === 'explain' ? '免费讲解' : '地图导览') +} + const isPoiSearchOverlayHistoryState = (state: unknown): state is PoiSearchOverlayHistoryState => ( Boolean( state @@ -1133,6 +1138,7 @@ const handleTabChange = (tabId: GuideTopTab) => { } currentTab.value = tabId + syncEmbeddedHostNavigationTitle(tabId) syncTopTabToUrl(tabId) loadTopTabData(tabId) @@ -1160,11 +1166,13 @@ const syncTopTabFromHash = () => { closeArrivalPanel() } syncTopTabToUrl(tab) + syncEmbeddedHostNavigationTitle(tab) return } syncTopTabToUrl(currentTab.value) loadTopTabData(currentTab.value) + syncEmbeddedHostNavigationTitle(currentTab.value) } onMounted(() => { @@ -1173,10 +1181,6 @@ onMounted(() => { if (typeof window === 'undefined') return - if (isEmbeddedInWechatMiniProgram()) { - syncHostNavigationTitle('地图导览') - } - stopOutdoorMapAvailabilitySubscription = subscribeOutdoorMapAvailability(handleOutdoorMapUnavailable) void refreshOutdoorMapAvailability() syncTopTabFromHash() diff --git a/tests/unit/ExplainListNavigation.spec.ts b/tests/unit/ExplainListNavigation.spec.ts index 4eed816..8efdce6 100644 --- a/tests/unit/ExplainListNavigation.spec.ts +++ b/tests/unit/ExplainListNavigation.spec.ts @@ -13,6 +13,10 @@ const miniProgramBridgeMocks = vi.hoisted(() => ({ returnToWechatMiniProgram: vi.fn() })) +const hostNavigationTitleMocks = vi.hoisted(() => ({ + syncHostNavigationTitle: vi.fn() +})) + const testState = vi.hoisted(() => ({ onLoadHandler: null as null | (() => void), onBackPressHandler: null as null | (() => boolean) @@ -35,6 +39,10 @@ vi.mock('@/services/WechatMiniProgramBridgeService', () => ({ returnToWechatMiniProgram: miniProgramBridgeMocks.returnToWechatMiniProgram })) +vi.mock('@/utils/hostNavigationTitle', () => ({ + syncHostNavigationTitle: hostNavigationTitleMocks.syncHostNavigationTitle +})) + vi.mock('@/usecases/explainUseCase', () => ({ explainUseCase: { loadExplainHalls: async () => [], @@ -69,6 +77,7 @@ const mountExplainList = () => mount(ExplainListPage, { beforeEach(() => { hostEnvironmentMocks.embeddedInWechatMiniProgram = false miniProgramBridgeMocks.returnToWechatMiniProgram.mockResolvedValue({ status: 'not-embedded' }) + hostNavigationTitleMocks.syncHostNavigationTitle.mockReset() testState.onLoadHandler = null testState.onBackPressHandler = null window.location.hash = '#/pages/explain/list' @@ -123,7 +132,11 @@ describe('讲解展厅列表返回', () => { window.history.replaceState({}, '', window.location.href) const wrapper = mountExplainList() + testState.onLoadHandler?.() + await flushPromises() + expect(wrapper.getComponent(ExplainHallSelectStub).props('forceInternalHeader')).toBe(false) + expect(hostNavigationTitleMocks.syncHostNavigationTitle).toHaveBeenCalledWith('免费讲解') await wrapper.get('[data-testid="explain-list-back"]').trigger('click') await flushPromises() diff --git a/tests/unit/IndexLaunchOverlay.spec.ts b/tests/unit/IndexLaunchOverlay.spec.ts index dbd7495..e6a4c73 100644 --- a/tests/unit/IndexLaunchOverlay.spec.ts +++ b/tests/unit/IndexLaunchOverlay.spec.ts @@ -11,6 +11,14 @@ const testState = vi.hoisted(() => ({ onShowHandler: null as null | (() => Promise | void) })) +const hostEnvironmentMocks = vi.hoisted(() => ({ + embeddedInWechatMiniProgram: false +})) + +const hostNavigationTitleMocks = vi.hoisted(() => ({ + syncHostNavigationTitle: vi.fn() +})) + vi.mock('@dcloudio/uni-app', () => ({ onLoad: vi.fn(), onShow: (handler: () => Promise | void) => { @@ -19,7 +27,11 @@ vi.mock('@dcloudio/uni-app', () => ({ })) vi.mock('@/utils/hostEnvironment', () => ({ - isEmbeddedInWechatMiniProgram: () => false + isEmbeddedInWechatMiniProgram: () => hostEnvironmentMocks.embeddedInWechatMiniProgram +})) + +vi.mock('@/utils/hostNavigationTitle', () => ({ + syncHostNavigationTitle: hostNavigationTitleMocks.syncHostNavigationTitle })) const modelSource = { @@ -107,7 +119,9 @@ beforeEach(() => { testState.threeMapMountCount = 0 testState.threeMapUnmountCount = 0 testState.onShowHandler = null - window.history.replaceState({}, '', '/#/pages/index/index?tab=guide') + hostEnvironmentMocks.embeddedInWechatMiniProgram = false + hostNavigationTitleMocks.syncHostNavigationTitle.mockReset() + window.location.hash = '#/pages/index/index?tab=guide' vi.stubGlobal('uni', { navigateTo: vi.fn(), navigateBack: vi.fn(), @@ -124,6 +138,16 @@ afterEach(() => { }) describe('首页启动遮罩与馆内模型生命周期', () => { + it('嵌入小程序打开讲解首页时同步免费讲解标题', async () => { + hostEnvironmentMocks.embeddedInWechatMiniProgram = true + window.location.hash = '#/pages/index/index?tab=explain&embedded=wechat-mini-program' + + const wrapper = await mountIndex() + + expect(hostNavigationTitleMocks.syncHostNavigationTitle).toHaveBeenCalledWith('免费讲解') + wrapper.unmount() + }) + it('12 秒超时后仍保持 indoor,且不会挂载 TencentMap', async () => { const wrapper = await mountIndex()