@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
55
static/icons/poi/shortcut-icons.svg
Normal file
55
static/icons/poi/shortcut-icons.svg
Normal 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 |
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user