优化点位搜索快捷入口
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-13 23:12:37 +08:00
parent 93645a2640
commit 350491157a
4 changed files with 239 additions and 245 deletions

View File

@@ -47,16 +47,17 @@
<view v-if="variant === 'home' && !showSearchContent && !isHomeCategoryMode" class="home-category-strip">
<view
v-for="item in homeCategories"
v-for="item in collapsedHomeCategories"
:key="item.id"
class="home-category-chip"
:class="{ active: activeCategoryId === item.id }"
:data-testid="`poi-category-${item.id}`"
@tap="handleFacilityShortcut(item)"
>
<view class="home-category-icon line-icon" :class="`icon-${item.icon}`">
<view class="icon-part a"></view>
<view class="icon-part b"></view>
<view class="icon-part c"></view>
<view class="home-category-icon">
<svg class="poi-category-icon" viewBox="0 0 32 32" aria-hidden="true">
<use :href="getPoiCategoryIconHref(item.id)" />
</svg>
</view>
<text class="home-category-label">{{ item.label }}</text>
</view>
@@ -130,7 +131,7 @@
</view>
<view class="category-scroll">
<view class="category-grid">
<view class="category-grid" :class="{ 'home-shortcut-grid': variant === 'home' }">
<view
v-for="item in searchCategoryColumns"
:key="item.id"
@@ -139,10 +140,10 @@
:data-testid="`poi-category-${item.id}`"
@tap="handleFacilityShortcut(item)"
>
<view class="line-icon" :class="`icon-${item.icon}`">
<view class="icon-part a"></view>
<view class="icon-part b"></view>
<view class="icon-part c"></view>
<view class="category-icon-shell">
<svg class="poi-category-icon" viewBox="0 0 32 32" aria-hidden="true">
<use :href="getPoiCategoryIconHref(item.id)" />
</svg>
</view>
<text class="category-label">{{ item.label }}</text>
</view>
@@ -230,6 +231,7 @@ import {
HOME_POI_CATEGORIES,
POI_CATEGORIES,
findPoiCategoryByKeyword,
getPoiCategoryIconHref,
getPoiCategoryById,
getPoiDataIssues,
inspectPoiCollection,
@@ -273,8 +275,11 @@ type PreparedPoiResults = {
}
const homeCategories = HOME_POI_CATEGORIES
const collapsedHomeCategories = computed(() => homeCategories.slice(0, 5))
const searchCategories = POI_CATEGORIES
const searchCategoryColumns = searchCategories
const searchCategoryColumns = computed(() => (
props.variant === 'home' ? homeCategories : searchCategories
))
const searchKeyword = ref('')
const searchDraftKeyword = ref('')
@@ -1083,89 +1088,76 @@ defineExpose({
.home-category-strip {
margin-top: 10px;
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 6px;
}
.variant-home.is-collapsed .home-category-strip {
margin-top: 7px;
gap: 5px;
gap: 6px;
}
.home-category-chip {
min-width: 0;
height: 60px;
min-height: 68px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 5px;
padding: 6px 2px;
gap: 4px;
padding: 6px 2px 5px;
box-sizing: border-box;
background: #fffef2;
border: 1px solid #ecebd2;
background: #f5f5ed;
border: 1px solid #dfe2d7;
border-radius: 8px;
box-shadow: none;
box-shadow: 0 2px 5px rgba(21, 23, 19, 0.1);
transition: background-color 0.18s ease, border-color 0.18s ease, transform 0.14s ease;
}
.variant-home.is-collapsed .home-category-chip {
min-width: 0;
height: 56px;
gap: 4px;
padding: 5px 1px;
border-radius: 7px;
min-height: 68px;
}
.home-category-chip:active {
transform: translateY(1px);
border-color: #d8d900;
background: #eef06d;
border-color: #c8ca00;
}
.home-category-chip.active {
background: #f2f48d;
border-color: #bfc100;
}
.home-category-icon {
width: 24px;
height: 23px;
flex: 0 0 24px;
width: 28px;
height: 28px;
flex: 0 0 28px;
}
.poi-category-icon {
display: block;
width: 100%;
height: 100%;
color: #151713;
pointer-events: none;
}
.home-category-icon.line-icon {
width: 24px;
height: 23px;
}
.home-category-icon .icon-part {
transform: scale(0.8);
transform-origin: center;
}
.variant-home.is-collapsed .home-category-icon,
.variant-home.is-collapsed .home-category-icon.line-icon {
width: 22px;
height: 21px;
flex-basis: 22px;
}
.variant-home.is-collapsed .home-category-icon .icon-part {
transform: scale(0.74);
.home-category-chip.active .poi-category-icon,
.category-item.active .poi-category-icon {
color: #151713;
}
.home-category-label {
min-width: 0;
max-width: 100%;
font-size: 12px;
line-height: 16px;
font-size: 11px;
line-height: 15px;
font-weight: 700;
color: #151713;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.variant-home.is-collapsed .home-category-label {
max-width: 100%;
font-size: 11px;
line-height: 14px;
}
.home-category-results {
@@ -1436,6 +1428,14 @@ defineExpose({
touch-action: pan-x;
}
.variant-home .category-scroll {
width: calc(100% - 8px);
margin: 0 4px;
overflow: visible;
padding-bottom: 0;
touch-action: pan-y;
}
.category-scroll::-webkit-scrollbar {
display: none;
}
@@ -1455,22 +1455,24 @@ defineExpose({
min-width: 0;
min-height: 70px;
position: relative;
padding: 9px 6px 10px;
padding: 9px 4px 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 7px;
box-sizing: border-box;
overflow: hidden;
background: #fffef2;
border: 1px solid #ecebd2;
overflow: visible;
background: #f5f5ed;
border: 1px solid #dfe2d7;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(21, 23, 19, 0.08);
transition: background-color 0.18s ease, border-color 0.18s ease, transform 0.14s ease;
}
.category-item.active {
background: #fffddc;
border-color: #d8d900;
background: #f2f48d;
border-color: #bfc100;
}
.home-category-chip.disabled,
@@ -1482,170 +1484,52 @@ defineExpose({
.category-item.active::after {
content: '';
position: absolute;
left: 14px;
right: 14px;
bottom: 0;
height: 4px;
background: var(--museum-accent);
}
.line-icon {
width: 26px;
height: 24px;
position: relative;
color: #151713;
}
.category-item.active .line-icon {
color: #151713;
}
.icon-part {
position: absolute;
box-sizing: border-box;
}
.icon-service .icon-part.a,
.icon-exhibition .icon-part.a,
.icon-cinema .icon-part.a,
.icon-ticket .icon-part.a,
.icon-drink .icon-part.a,
.icon-bag .icon-part.a {
left: 4px;
right: 4px;
top: 5px;
bottom: 5px;
border: 2px solid currentColor;
border-radius: 3px;
}
.icon-service .icon-part.b,
.icon-exhibition .icon-part.b,
.icon-cinema .icon-part.b,
.icon-ticket .icon-part.b,
.icon-drink .icon-part.b,
.icon-bag .icon-part.b {
left: 9px;
right: 9px;
top: 1px;
height: 5px;
border: 2px solid currentColor;
border-bottom: 0;
border-radius: 6px 6px 0 0;
}
.icon-elevator .icon-part.a,
.icon-escalator .icon-part.a,
.icon-restroom .icon-part.a,
.icon-nursing .icon-part.a,
.icon-restaurant .icon-part.a,
.icon-stairs .icon-part.a,
.icon-entrance .icon-part.a {
left: 4px;
right: 4px;
top: 3px;
bottom: 3px;
border: 2px solid currentColor;
border-radius: 4px;
}
.icon-elevator .icon-part.b {
left: 9px;
top: 7px;
width: 8px;
height: 10px;
border-left: 2px solid currentColor;
border-right: 2px solid currentColor;
}
.icon-escalator .icon-part.b,
.icon-entrance .icon-part.b {
left: 7px;
top: 12px;
width: 13px;
height: 2px;
background: currentColor;
transform: rotate(-22deg);
}
.icon-restroom .icon-part.b,
.icon-nursing .icon-part.b {
left: 8px;
top: 8px;
width: 4px;
height: 4px;
background: currentColor;
border-radius: 50%;
box-shadow: 8px 0 0 currentColor;
}
.icon-exhibition .icon-part.c {
left: 6px;
right: 6px;
bottom: 2px;
height: 2px;
background: currentColor;
border-radius: 2px;
}
.icon-cinema .icon-part.b {
left: 2px;
right: 2px;
top: 4px;
height: 4px;
border: 0;
border-top: 2px solid currentColor;
border-bottom: 2px solid currentColor;
border-radius: 0;
}
.icon-restaurant .icon-part.b {
left: 7px;
top: 6px;
width: 2px;
height: 12px;
background: currentColor;
box-shadow: 5px 0 0 currentColor, 10px 0 0 currentColor;
}
.icon-restaurant .icon-part.c {
right: 3px;
top: 5px;
width: 7px;
height: 15px;
border-left: 2px solid currentColor;
border-bottom: 2px solid currentColor;
border-radius: 0 0 0 5px;
}
.icon-stairs .icon-part.b {
left: 6px;
top: 7px;
width: 14px;
height: 12px;
border-left: 2px solid currentColor;
border-bottom: 2px solid currentColor;
}
.icon-stairs .icon-part.c {
left: 10px;
top: 11px;
width: 10px;
height: 8px;
border-left: 2px solid currentColor;
border-bottom: 2px solid currentColor;
right: 10px;
bottom: -1px;
height: 3px;
background: var(--museum-accent);
border-radius: 3px 3px 0 0;
}
.category-icon-shell {
width: 28px;
height: 28px;
flex: 0 0 28px;
}
.category-item:active {
transform: translateY(1px);
background: #eef06d;
border-color: #c8ca00;
}
.variant-home .home-shortcut-grid {
display: grid;
grid-auto-flow: row;
grid-template-columns: repeat(5, minmax(0, 1fr));
grid-template-rows: repeat(2, 72px);
grid-auto-columns: auto;
width: 100%;
min-width: 0;
gap: 6px;
}
.variant-home .category-item {
min-height: 72px;
height: 72px;
padding: 6px 2px 5px;
gap: 4px;
}
.category-label {
max-width: 100%;
font-size: 12px;
line-height: 16px;
font-size: 11px;
line-height: 15px;
font-weight: 700;
color: #151713;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.category-item.active .category-label {

View File

@@ -4,6 +4,7 @@ import type {
} from '@/domain/museum'
export type PoiCategoryId =
| 'itinerary'
| 'exhibition-hall'
| 'cinema'
| 'ticket-office'
@@ -25,25 +26,37 @@ export interface PoiCategoryDefinition {
keywords: readonly string[]
categoryIds: readonly string[]
iconTypes: readonly string[]
excludedCategoryIds?: readonly string[]
}
const definitions: PoiCategoryDefinition[] = [
{
id: 'exhibition-hall',
label: '展厅',
icon: 'exhibition',
id: 'itinerary',
label: '行程',
icon: 'itinerary',
order: 1,
homeVisible: true,
keywords: ['展厅', '览', '展馆', 'exhibition_hall', 'touring_poi', 'hall'],
categoryIds: ['exhibition_hall', 'exhibition_hall_entrance', 'touring_poi'],
iconTypes: ['exhibition_hall', 'hall_entrance', 'exhibition']
keywords: ['行程', '览', '参观', 'touring_poi'],
categoryIds: ['touring_poi'],
iconTypes: ['touring', 'guide']
},
{
id: 'exhibition-hall',
label: '展览',
icon: 'exhibition',
order: 2,
homeVisible: true,
keywords: ['展厅', '展览', '展馆', 'exhibition_hall', 'hall'],
categoryIds: ['exhibition_hall', 'exhibition_hall_entrance'],
iconTypes: ['exhibition_hall', 'hall_entrance', 'exhibition'],
excludedCategoryIds: ['touring_poi']
},
{
id: 'cinema',
label: '影院',
icon: 'cinema',
order: 2,
homeVisible: false,
order: 3,
homeVisible: true,
keywords: ['影院', '影厅', '剧场', '报告厅', 'cinema', 'theater'],
categoryIds: ['space_theater'],
iconTypes: ['cinema', 'theater']
@@ -52,8 +65,8 @@ const definitions: PoiCategoryDefinition[] = [
id: 'ticket-office',
label: '售票处',
icon: 'ticket',
order: 3,
homeVisible: false,
order: 6,
homeVisible: true,
keywords: ['售票处', '售票', '票务', 'ticket_office'],
categoryIds: [],
iconTypes: ['ticket_office']
@@ -62,18 +75,18 @@ const definitions: PoiCategoryDefinition[] = [
id: 'service-center',
label: '服务中心',
icon: 'service',
order: 4,
homeVisible: false,
order: 8,
homeVisible: true,
keywords: ['服务中心', '服务台', '咨询台', 'service_desk'],
categoryIds: [],
iconTypes: ['service_desk']
},
{
id: 'dining',
label: '餐',
label: '餐',
icon: 'restaurant',
order: 5,
homeVisible: false,
homeVisible: true,
keywords: ['餐饮', '餐厅', '快餐', '咖啡', 'restaurant', 'dining', 'food', 'cafe'],
categoryIds: [],
iconTypes: ['restaurant', 'dining', 'food', 'cafe']
@@ -82,7 +95,7 @@ const definitions: PoiCategoryDefinition[] = [
id: 'souvenir',
label: '文创',
icon: 'bag',
order: 6,
order: 11,
homeVisible: false,
keywords: ['文创', '纪念品', '商店', 'souvenir', 'gift', 'shop'],
categoryIds: [],
@@ -100,9 +113,9 @@ const definitions: PoiCategoryDefinition[] = [
},
{
id: 'restroom',
label: '卫生间',
label: '洗手间',
icon: 'restroom',
order: 8,
order: 4,
homeVisible: true,
keywords: ['卫生间', '洗手间', '厕所', 'toilet', 'accessible_toilet', 'restroom'],
categoryIds: [],
@@ -122,8 +135,8 @@ const definitions: PoiCategoryDefinition[] = [
id: 'stairs',
label: '楼梯',
icon: 'stairs',
order: 10,
homeVisible: true,
order: 12,
homeVisible: false,
keywords: ['楼梯', 'stairs', 'stair'],
categoryIds: [],
iconTypes: ['stairs', 'stair']
@@ -132,7 +145,7 @@ const definitions: PoiCategoryDefinition[] = [
id: 'escalator',
label: '扶梯',
icon: 'escalator',
order: 11,
order: 10,
homeVisible: true,
keywords: ['扶梯', 'escalator'],
categoryIds: [],
@@ -145,11 +158,15 @@ export const POI_CATEGORIES = Object.freeze(
)
const homeCategoryOrder: readonly PoiCategoryId[] = [
'itinerary',
'exhibition-hall',
'cinema',
'restroom',
'dining',
'ticket-office',
'nursing-room',
'service-center',
'elevator',
'stairs',
'escalator'
]
@@ -159,6 +176,25 @@ export const HOME_POI_CATEGORIES = Object.freeze(
))
)
const POI_CATEGORY_ICON_SYMBOLS: Readonly<Record<PoiCategoryId, string>> = {
itinerary: 'poi-itinerary',
'exhibition-hall': 'poi-exhibition-hall',
cinema: 'poi-cinema',
'ticket-office': 'poi-ticket-office',
'service-center': 'poi-service-center',
dining: 'poi-dining',
souvenir: 'poi-souvenir',
'nursing-room': 'poi-nursing-room',
restroom: 'poi-restroom',
elevator: 'poi-elevator',
stairs: 'poi-stairs',
escalator: 'poi-escalator'
}
export const getPoiCategoryIconHref = (categoryId: PoiCategoryId) => (
`/static/icons/poi/shortcut-icons.svg#${POI_CATEGORY_ICON_SYMBOLS[categoryId]}`
)
type PoiCategorySource = Pick<MuseumPoi, 'name' | 'primaryCategory' | 'categories'>
const normalizeValue = (value?: string | null) => (value || '').trim().toLowerCase()
@@ -177,6 +213,12 @@ export const matchesPoiCategory = (
const normalizedCategoryIds = new Set(categories.map((category) => normalizeValue(category.id)))
const normalizedIconTypes = new Set(categories.map((category) => normalizeValue(category.iconType)))
if (definition.excludedCategoryIds?.some((categoryId) => (
normalizedCategoryIds.has(normalizeValue(categoryId))
))) {
return false
}
if (definition.categoryIds.some((categoryId) => normalizedCategoryIds.has(normalizeValue(categoryId)))) {
return true
}

View File

@@ -0,0 +1,55 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs>
<symbol id="poi-itinerary" viewBox="0 0 32 32" fill="none">
<path d="M5 7.5 12 5l8 2.5L27 5v19.5L20 27l-8-2.5-7 2.5V7.5Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
<path d="M12 5v19.5M20 7.5V27M8.5 11.5c3.5-3 7.5 3 11-1.5 1.8-1.8 3.2-1.4 4.5-.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="8.5" cy="11.5" r="1.2" fill="currentColor" stroke="none"/>
</symbol>
<symbol id="poi-exhibition-hall" viewBox="0 0 32 32" fill="none">
<path d="M6 25.5h20M8 23V7.5h16V23M12 11.5h8v7h-8z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 12.5c-1.8 1.1-2.7 2.8-2.6 5 2.3-.1 4-1.2 5-3.1.5-1 .6-2 .4-3.2-1.2-.1-2.1.2-2.8 1.3Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-cinema" viewBox="0 0 32 32" fill="none">
<rect x="5" y="8" width="22" height="16" rx="3" stroke="currentColor" stroke-width="1.8"/>
<path d="m14 12 6 4-6 4v-8ZM5.5 12h21M9 8l3 4M15 8l3 4M21 8l3 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-restroom" viewBox="0 0 32 32" fill="none">
<circle cx="11" cy="7.5" r="2.5" stroke="currentColor" stroke-width="1.8"/>
<circle cx="21" cy="7.5" r="2.5" stroke="currentColor" stroke-width="1.8"/>
<path d="M11 11v6.5m-3-4 3 4 3-4M9 26l2-8.5 2 8.5M21 11v5.5m-3.5-2 3.5 2 3.5-2M17.5 26l3.5-9.5 3.5 9.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-dining" viewBox="0 0 32 32" fill="none">
<path d="M9 5v8m-3-8v8m6-8v8M6 13h6m-3 0v14M20 5v22M20 5c4.5 2.6 5.5 7 0 10" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M23.5 23.5c1-2.7 2-5.5 2-8.3-2.8 1.1-4.8 3.1-5.5 5.7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-ticket-office" viewBox="0 0 32 32" fill="none">
<path d="M7 8h18v5c-2.7 0-2.7 6 0 6v5H7v-5c2.7 0 2.7-6 0-6V8Z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 10.5v2m0 3v2m0 3v2M10.5 12h2.5M19 20h2.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</symbol>
<symbol id="poi-nursing-room" viewBox="0 0 32 32" fill="none">
<path d="M5.5 23.5h21M8 21V14c0-2.2 1.8-4 4-4h8c2.2 0 4 1.8 4 4v7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 19.5c1.4-2.7 3.1-4 5-4s3.6 1.3 5 4M16 13.5a2.2 2.2 0 1 0 0-4.4 2.2 2.2 0 0 0 0 4.4Z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24.5 8.5c1.4 1.1 2.1 2.5 2.1 4.2M7.5 8.5C6.1 9.6 5.4 11 5.4 12.7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</symbol>
<symbol id="poi-service-center" viewBox="0 0 32 32" fill="none">
<circle cx="16" cy="8" r="3" stroke="currentColor" stroke-width="1.8"/>
<path d="M10 23v-3c0-3.3 2.7-6 6-6s6 2.7 6 6v3M6 27h20M8 23h16v4H8zM16 17.5v3.2M16 15.5v.1" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-elevator" viewBox="0 0 32 32" fill="none">
<rect x="6" y="4.5" width="20" height="23" rx="3" stroke="currentColor" stroke-width="1.8"/>
<path d="M11 25V11h10v14M16 11v14M11 8.5l2-2 2 2M21 8.5l-2-2-2 2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-escalator" viewBox="0 0 32 32" fill="none">
<path d="M6 25h20M7 22.5l12-12h5.5L27 13M9.5 22.5l10-10M14 22.5h7M17 19.5h7M20 16.5h7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="10" cy="9" r="2.2" stroke="currentColor" stroke-width="1.8"/>
<path d="m11.5 11 3 4.2 2.8 1.6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="poi-souvenir" viewBox="0 0 32 32" fill="none">
<path d="M7 11.5h18l-1.2 14H8.2L7 11.5ZM12 11.5V9a4 4 0 0 1 8 0v2.5M13 17.5c1.8 1.4 4.2 1.4 6 0" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 15v6M13 18h6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</symbol>
<symbol id="poi-stairs" viewBox="0 0 32 32" fill="none">
<path d="M6 25h20M8 23h5v-4h5v-4h5v-4h3M9 8.5h9M18 5.5l3 3-3 3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -88,7 +88,7 @@ afterEach(() => {
})
describe('POI 搜索面板实际渲染与状态闭环', () => {
it('首页显示六类统一入口,搜索页显示完整十一类入口', async () => {
it('首页收缩和展开复用同一份十项快捷入口,搜索页保留完整分类', async () => {
const homeWrapper = mount(PoiSearchPanel, {
props: {
variant: 'home',
@@ -99,19 +99,30 @@ describe('POI 搜索面板实际渲染与状态闭环', () => {
await flushMountedSearch()
const homeCategories = homeWrapper.findAll('.home-category-chip')
expect(homeCategories).toHaveLength(6)
expect(homeCategories).toHaveLength(5)
expect(homeCategories.map((item) => item.text())).toEqual([
'展厅', '卫生间', '母婴室', '电梯', '楼梯', '扶梯'
'行程', '展览', '影院', '洗手间', '餐厅'
])
homeCategories.forEach((item) => {
expect(item.find('.line-icon').exists()).toBe(true)
expect(item.find('.poi-category-icon').exists()).toBe(true)
expect(item.find('.home-category-label').exists()).toBe(true)
})
await homeWrapper.get('.search-box').trigger('tap')
await flushMountedSearch()
const expandedCategories = homeWrapper.findAll('.home-shortcut-grid .category-item')
expect(expandedCategories).toHaveLength(10)
expect(expandedCategories.map((item) => item.text())).toEqual([
'行程', '展览', '影院', '洗手间', '餐厅',
'售票处', '母婴室', '服务中心', '电梯', '扶梯'
])
expect(expandedCategories.slice(0, 5).map((item) => item.text()))
.toEqual(homeCategories.map((item) => item.text()))
homeWrapper.unmount()
const pageWrapper = mount(PoiSearchPanel, { props: { variant: 'page' } })
await flushMountedSearch()
expect(pageWrapper.findAll('.category-item')).toHaveLength(11)
expect(pageWrapper.findAll('.category-item')).toHaveLength(12)
expect(pageWrapper.text()).toContain('影院')
expect(pageWrapper.text()).toContain('服务中心')
expect(pageWrapper.text()).toContain('文创')
@@ -189,6 +200,8 @@ describe('POI 搜索面板实际渲染与状态闭环', () => {
await wrapper.get('[data-testid="poi-category-cancel"]').trigger('tap')
await flushMountedSearch()
await wrapper.get('.search-box').trigger('tap')
await flushMountedSearch()
await wrapper.get('[data-testid="poi-category-nursing-room"]').trigger('tap')
await flushMountedSearch()
expect(wrapper.find('[data-testid="poi-result-nursing-2"]').exists()).toBe(true)
@@ -197,7 +210,7 @@ describe('POI 搜索面板实际渲染与状态闭环', () => {
await flushMountedSearch()
expect(wrapper.get('[data-testid="poi-empty"]').text()).toContain('当前楼层暂无匹配点位')
expect((wrapper.emitted('results-change') || []).at(-1)?.[0]).toMatchObject({
active: true,
active: false,
visiblePoiIds: []
})
wrapper.unmount()
@@ -221,7 +234,7 @@ describe('POI 搜索面板实际渲染与状态闭环', () => {
const query = new URLSearchParams(url.split('?')[1])
expect(query.get('source')).toBe('search')
expect(query.get('searchOrigin')).toBe('page')
expect(query.get('searchKeyword')).toBe('卫生间')
expect(query.get('searchKeyword')).toBe('洗手间')
expect(query.get('searchCategoryId')).toBe('restroom')
expect(query.get('searchFloorId')).toBe('floor-2')
expect(query.get('resultCount')).toBe('3')