From 267b415673cae00fffc959b121b6e29d6c5cda9d Mon Sep 17 00:00:00 2001 From: lyf <2514544224@qq.com> Date: Tue, 14 Jul 2026 10:19:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BE=AE=E4=BF=A1=E5=86=85?= =?UTF-8?q?=E5=B5=8C=E7=82=B9=E4=BD=8D=E6=90=9C=E7=B4=A2=E5=AF=BC=E8=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/search/PoiSearchPanel.vue | 9 ++- src/pages/index/index.vue | 6 +- tests/unit/IndexPoiSearchFlow.spec.ts | 8 +++ tests/unit/PoiSearchPanel.spec.ts | 74 ++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/components/search/PoiSearchPanel.vue b/src/components/search/PoiSearchPanel.vue index 09a3eb5..f1381ab 100644 --- a/src/components/search/PoiSearchPanel.vue +++ b/src/components/search/PoiSearchPanel.vue @@ -14,7 +14,7 @@ @mouseup="handlePanelMouseEnd" @mouseleave="resetPanelMouse" > - + @@ -245,6 +245,7 @@ import type { PoiCategoryResultState, PoiSearchContext } from '@/domain/poiSearch' +import { isEmbeddedInWechatMiniProgram } from '@/utils/hostEnvironment' const props = withDefaults(defineProps<{ initialKeyword?: string @@ -308,6 +309,12 @@ let searchRequestSeq = 0 const collapseDragThreshold = 48 const homeExpandTapGuardMs = 360 const showSearchContent = computed(() => props.variant === 'page' || homeExpanded.value) +const shouldUseHostNavigation = computed(() => isEmbeddedInWechatMiniProgram()) +const showHomeFullscreenNav = computed(() => ( + props.variant === 'home' + && showSearchContent.value + && !shouldUseHostNavigation.value +)) const isHomeCategoryMode = computed(() => ( props.variant === 'home' && homeCategoryMode.value && !homeExpanded.value )) diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 0933b1d..fc6b4d9 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -715,7 +715,11 @@ const syncTopTabToUrl = (tabId: GuideTopTab) => { if (typeof window === 'undefined') return if (!isIndexHashRoute()) return - const url = `#/pages/index/index?tab=${tabId}` + const currentHash = window.location.hash || '' + const queryStart = currentHash.indexOf('?') + const params = new URLSearchParams(queryStart >= 0 ? currentHash.slice(queryStart + 1) : '') + params.set('tab', tabId) + const url = `#/pages/index/index?${params.toString()}` if (window.location.hash !== url) { window.history.replaceState(window.history.state, '', url) } diff --git a/tests/unit/IndexPoiSearchFlow.spec.ts b/tests/unit/IndexPoiSearchFlow.spec.ts index b3c11c7..c96e0e4 100644 --- a/tests/unit/IndexPoiSearchFlow.spec.ts +++ b/tests/unit/IndexPoiSearchFlow.spec.ts @@ -172,6 +172,14 @@ afterEach(() => { }) describe('首页搜索与地图闭环', () => { + it('同步首页标签时保留内嵌宿主参数', async () => { + window.location.hash = '#/pages/index/index?tab=guide&embedded=wechat-mini-program' + + await mountIndex() + + expect(window.location.hash).toBe('#/pages/index/index?tab=guide&embedded=wechat-mini-program') + }) + it('首页暂不展示来馆入口及其到馆面板', async () => { const wrapper = await mountIndex() diff --git a/tests/unit/PoiSearchPanel.spec.ts b/tests/unit/PoiSearchPanel.spec.ts index 747d83a..9717d36 100644 --- a/tests/unit/PoiSearchPanel.spec.ts +++ b/tests/unit/PoiSearchPanel.spec.ts @@ -11,10 +11,18 @@ const guideMocks = vi.hoisted(() => ({ searchPois: vi.fn() })) +const hostEnvironmentMocks = vi.hoisted(() => ({ + embeddedInWechatMiniProgram: false +})) + vi.mock('@/usecases/guideUseCase', () => ({ guideUseCase: guideMocks })) +vi.mock('@/utils/hostEnvironment', () => ({ + isEmbeddedInWechatMiniProgram: () => hostEnvironmentMocks.embeddedInWechatMiniProgram +})) + const floors: MuseumFloor[] = [ { id: 'floor-1', label: '1F', order: 1 }, { id: 'floor-2', label: '2F', order: 2 } @@ -67,6 +75,7 @@ const createDeferred = () => { } beforeEach(() => { + hostEnvironmentMocks.embeddedInWechatMiniProgram = false guideMocks.getFloors.mockResolvedValue(floors) guideMocks.getInitialSearchSpacePoints.mockResolvedValue(poiPool) guideMocks.searchPois.mockImplementation(async (keyword = '') => ( @@ -130,6 +139,71 @@ describe('POI 搜索面板实际渲染与状态闭环', () => { pageWrapper.unmount() }) + it('普通 H5 展开时保留内部标题与返回,并可分类和收起', async () => { + const wrapper = mount(PoiSearchPanel, { + props: { + variant: 'home', + currentFloorId: 'floor-1', + currentFloorLabel: '1F' + } + }) + await flushMountedSearch() + + await wrapper.get('.search-box').trigger('tap') + await flushMountedSearch() + expect(wrapper.get('.home-fullscreen-nav').text()).toContain('点位搜索') + expect(wrapper.find('[data-testid="poi-search-cancel"]').exists()).toBe(true) + + await wrapper.get('[data-testid="poi-category-restroom"]').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('[data-testid="poi-home-category-results"]').exists()).toBe(true) + + await wrapper.get('[data-testid="poi-category-cancel"]').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('.home-category-strip').exists()).toBe(true) + + await wrapper.get('.search-box').trigger('tap') + await flushMountedSearch() + await wrapper.get('[data-testid="poi-search-cancel"]').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('.home-category-strip').exists()).toBe(true) + wrapper.unmount() + }) + + it('内嵌微信小程序展开时不渲染内部标题与返回,并可分类和收起', async () => { + hostEnvironmentMocks.embeddedInWechatMiniProgram = true + const wrapper = mount(PoiSearchPanel, { + props: { + variant: 'home', + currentFloorId: 'floor-1', + currentFloorLabel: '1F' + } + }) + await flushMountedSearch() + + await wrapper.get('.search-box').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('.home-fullscreen-nav').exists()).toBe(false) + expect(wrapper.find('[data-testid="poi-search-cancel"]').exists()).toBe(false) + expect(wrapper.get('.poi-search-panel').element.firstElementChild?.classList.contains('search-box')) + .toBe(true) + + await wrapper.get('[data-testid="poi-category-restroom"]').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('[data-testid="poi-home-category-results"]').exists()).toBe(true) + + await wrapper.get('[data-testid="poi-category-cancel"]').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('.home-category-strip').exists()).toBe(true) + + await wrapper.get('.search-box').trigger('tap') + await flushMountedSearch() + await wrapper.get('.home-collapse-handle').trigger('tap') + await flushMountedSearch() + expect(wrapper.find('.home-category-strip').exists()).toBe(true) + wrapper.unmount() + }) + it('展开态快捷入口退出全屏并进入当前楼层的分类结果', async () => { const wrapper = mount(PoiSearchPanel, { props: {