feat: switch explain flow to API data
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-06 23:18:51 +08:00
parent e2b6a331ba
commit 50902eca82
21 changed files with 1417 additions and 632 deletions

View File

@@ -62,20 +62,22 @@
<view class="home-collapse-bar"></view>
</view>
<view class="category-grid">
<view
v-for="item in primaryFacilities"
:key="item.id"
class="category-item"
:class="{ active: searchKeyword === item.label }"
@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-scroll">
<view class="category-grid">
<view
v-for="item in primaryFacilityColumns"
:key="item.id"
class="category-item"
:class="{ active: searchKeyword === item.label }"
@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>
<text class="category-label">{{ item.label }}</text>
</view>
<text class="category-label">{{ item.label }}</text>
</view>
</view>
@@ -182,14 +184,36 @@ const emit = defineEmits<{
}>()
const primaryFacilities: ShortcutItem[] = [
{ id: 'service', label: '服务台', icon: 'service', keywords: ['服务台', 'service_desk'] },
{ id: 'exhibition', label: '展览', icon: 'exhibition', keywords: ['展览', '展厅', '展馆', 'exhibition_hall', 'temp_exhibition'] },
{ id: 'cinema', label: '影院', icon: 'cinema', keywords: ['影院', '剧场', '影厅', 'cinema', 'theater'] },
{ id: 'restroom', label: '洗手间', icon: 'restroom', keywords: ['洗手间', '卫生间', 'toilet', 'accessible_toilet'] },
{ id: 'restaurant', label: '餐厅', icon: 'restaurant', keywords: ['餐厅', '餐饮', '咖啡', 'restaurant', 'commercial'] },
{ id: 'ticket-office', label: '售票处', icon: 'ticket', keywords: ['售票处', '售票', '票务', 'ticket_office'] },
{ id: 'nursing', label: '母婴室', icon: 'nursing', keywords: ['母婴室', 'mother_baby_room'] },
{ id: 'service-center', label: '服务中心', icon: 'service', keywords: ['服务中心', '服务台', '咨询台', 'service_desk', 'service_space'] },
{ id: 'elevator', label: '电梯', icon: 'elevator', keywords: ['电梯', 'elevator'] },
{ id: 'escalator', label: '扶梯', icon: 'escalator', keywords: ['扶梯', 'escalator'] },
{ id: 'restroom', label: '洗手间', icon: 'restroom', keywords: ['洗手间', '卫生间', 'toilet', 'accessible_toilet'] },
{ id: 'nursing', label: '母婴室', icon: 'nursing', keywords: ['母婴室', 'mother_baby_room'] },
{ id: 'entrance', label: '出入口', icon: 'entrance', keywords: ['出入口', '入口', '出口', 'entrance_exit'] }
{ id: 'stairs', label: '楼梯', icon: 'stairs', keywords: ['楼梯', 'stairs', 'stair'] }
]
const primaryFacilityVisibleColumnCount = 4
const primaryFacilityRowCount = 2
const primaryFacilityColumns = computed(() => {
const firstScreenItems = primaryFacilities.slice(0, primaryFacilityVisibleColumnCount * primaryFacilityRowCount)
const overflowItems = primaryFacilities.slice(primaryFacilityVisibleColumnCount * primaryFacilityRowCount)
const orderedItems: ShortcutItem[] = []
for (let columnIndex = 0; columnIndex < primaryFacilityVisibleColumnCount; columnIndex += 1) {
const topItem = firstScreenItems[columnIndex]
const bottomItem = firstScreenItems[columnIndex + primaryFacilityVisibleColumnCount]
if (topItem) orderedItems.push(topItem)
if (bottomItem) orderedItems.push(bottomItem)
}
return orderedItems.concat(overflowItems)
})
const serviceFacilities: ShortcutItem[] = [
{ id: 'drink', label: '饮料售卖机', icon: 'drink', keywords: ['饮料售卖机', '饮料', '售卖机', 'vending'] },
{ id: 'ticket', label: '票务售卖机', icon: 'ticket', keywords: ['票务售卖机', '票务', '售票', 'ticket_office'] },
@@ -678,9 +702,11 @@ defineExpose({
.poi-search-panel {
width: 100%;
max-width: 100%;
box-sizing: border-box;
color: #262421;
font-family: '鸿蒙黑体', 'HarmonyOS Sans SC', 'HarmonyOS Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
overflow-x: hidden;
}
.variant-home.expanded {
@@ -758,6 +784,8 @@ defineExpose({
}
.variant-home .search-box {
background: #f5f5ed;
border-color: rgba(224, 225, 0, 0.72);
box-shadow: none;
}
@@ -768,6 +796,8 @@ defineExpose({
overflow-x: auto;
padding-bottom: 2px;
scrollbar-width: none;
overscroll-behavior-x: contain;
-webkit-overflow-scrolling: touch;
}
.home-category-strip::-webkit-scrollbar {
@@ -775,18 +805,50 @@ defineExpose({
}
.home-category-chip {
min-width: 70px;
height: 42px;
flex: 0 0 auto;
min-width: 112px;
height: 58px;
flex: 0 0 112px;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 0 10px;
justify-content: space-between;
gap: 8px;
padding: 0 11px;
box-sizing: border-box;
background: #f4f5ef;
border: 1px solid #dde5df;
background: #e0df00;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 8px;
background-image:
linear-gradient(116deg, rgba(255, 255, 255, 0.22) 0 32%, rgba(255, 255, 255, 0) 33%),
linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(0, 0, 0, 0.02));
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.16);
}
.home-category-chip:nth-child(2) {
background-color: #18c2b6;
}
.home-category-chip:nth-child(3) {
background-color: #b99cf0;
}
.home-category-chip:nth-child(4) {
background-color: #8ad9ae;
}
.home-category-chip:nth-child(5) {
background-color: #ffc0a1;
}
.home-category-chip:nth-child(6) {
background-color: #5ed0e4;
}
.home-category-chip:nth-child(7) {
background-color: #c9a463;
}
.home-category-chip:nth-child(8) {
background-color: #f4f5ef;
}
.home-category-chip:active {
@@ -794,14 +856,16 @@ defineExpose({
}
.home-category-icon {
width: 20px;
height: 19px;
flex: 0 0 20px;
width: 24px;
height: 23px;
flex: 0 0 24px;
order: 2;
color: #050704;
}
.home-category-icon.line-icon {
width: 20px;
height: 19px;
width: 24px;
height: 23px;
}
.home-category-icon .icon-part {
@@ -810,11 +874,12 @@ defineExpose({
}
.home-category-label {
max-width: 58px;
font-size: 12px;
line-height: 16px;
font-weight: 700;
color: #151713;
min-width: 0;
max-width: 70px;
font-size: 14px;
line-height: 18px;
font-weight: 800;
color: #050704;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -919,6 +984,7 @@ defineExpose({
}
.variant-page .poi-search-content {
margin-top: 14px;
flex: 1;
min-height: 0;
display: flex;
@@ -959,30 +1025,63 @@ defineExpose({
padding-right: 0;
}
.category-scroll {
width: 100%;
max-width: 100%;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 4px;
scrollbar-width: none;
overscroll-behavior-x: contain;
-webkit-overflow-scrolling: touch;
touch-action: pan-x;
}
.category-scroll::-webkit-scrollbar {
display: none;
}
.category-grid {
--category-gap: 8px;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
grid-auto-flow: column;
grid-template-rows: repeat(2, minmax(70px, auto));
grid-auto-columns: calc((100% - 32px) / 5);
gap: var(--category-gap);
width: calc(125% + 2px);
min-width: calc(125% + 2px);
}
.category-item {
min-width: 0;
min-height: 70px;
padding: 9px 6px;
position: relative;
padding: 9px 6px 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 7px;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.92);
border: 1px solid #e2e4da;
overflow: hidden;
background: #fffef2;
border: 1px solid #ecebd2;
border-radius: 8px;
}
.category-item.active {
background: #151713;
border-color: #151713;
background: #fffddc;
border-color: #d8d900;
}
.category-item.active::after {
content: '';
position: absolute;
left: 14px;
right: 14px;
bottom: 0;
height: 4px;
background: var(--museum-accent);
}
.line-icon {
@@ -993,7 +1092,7 @@ defineExpose({
}
.category-item.active .line-icon {
color: var(--museum-accent);
color: #151713;
}
.icon-part {
@@ -1002,6 +1101,8 @@ defineExpose({
}
.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 {
@@ -1014,6 +1115,8 @@ defineExpose({
}
.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 {
@@ -1030,6 +1133,8 @@ defineExpose({
.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;
@@ -1069,6 +1174,63 @@ defineExpose({
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;
}
.category-label {
max-width: 100%;
font-size: 12px;
@@ -1082,12 +1244,24 @@ defineExpose({
}
.category-item.active .category-label {
color: var(--museum-accent);
color: #151713;
}
.section-title-row {
margin-top: 14px;
margin-bottom: 8px;
position: relative;
margin-top: 16px;
margin-bottom: 10px;
padding-left: 12px;
}
.section-title-row::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 4px;
height: 16px;
background: var(--museum-accent);
}
.section-title {
@@ -1113,19 +1287,30 @@ defineExpose({
.facility-chip {
height: 34px;
flex: 0 0 auto;
position: relative;
display: flex;
align-items: center;
gap: 7px;
padding: 0 12px;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.94);
border: 1px solid #e2e4da;
background: #fffef6;
border: 1px solid #e8e7d2;
border-radius: 8px;
}
.facility-chip.active {
background: #151713;
border-color: #151713;
background: #fffddc;
border-color: #d6d700;
}
.facility-chip.active::after {
content: '';
position: absolute;
left: 12px;
right: 12px;
bottom: -1px;
height: 3px;
background: var(--museum-accent);
}
.chip-icon {
@@ -1140,7 +1325,7 @@ defineExpose({
}
.facility-chip.active .chip-icon {
color: var(--museum-accent);
color: #151713;
}
.facility-chip-text {
@@ -1152,26 +1337,27 @@ defineExpose({
}
.facility-chip.active .facility-chip-text {
color: var(--museum-accent);
color: #151713;
}
.result-card {
margin-top: 12px;
margin-top: 14px;
overflow: hidden;
background: rgba(255, 255, 255, 0.96);
border: 1px solid #e2e4da;
background: #fffef7;
border: 1px solid #ecebd8;
border-radius: 8px;
box-shadow: 0 10px 24px rgba(75, 78, 60, 0.08);
}
.result-card-header {
height: 42px;
padding: 0 12px;
height: 46px;
padding: 0 14px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
box-sizing: border-box;
border-bottom: 1px solid #eceee6;
border-bottom: 1px solid #efeedf;
}
.museum-title,
@@ -1196,14 +1382,15 @@ defineExpose({
}
.floor-tabs {
width: 58px;
flex: 0 0 58px;
padding: 8px 0;
width: 62px;
flex: 0 0 62px;
padding: 9px 0;
box-sizing: border-box;
background: #f3f4ee;
background: #f6f5e8;
}
.floor-tab {
position: relative;
height: 31px;
display: flex;
align-items: center;
@@ -1216,6 +1403,16 @@ defineExpose({
font-weight: 800;
}
.floor-tab.active::after {
content: '';
position: absolute;
left: 8px;
right: 8px;
bottom: 2px;
height: 3px;
background: var(--museum-accent);
}
.floor-tab-text {
font-size: 12px;
line-height: 16px;
@@ -1227,6 +1424,7 @@ defineExpose({
}
.variant-page .category-grid,
.variant-page .category-scroll,
.variant-page .section-title-row,
.variant-page .facility-chip-row {
flex: 0 0 auto;
@@ -1257,6 +1455,7 @@ defineExpose({
}
.variant-home.expanded .category-grid,
.variant-home.expanded .category-scroll,
.variant-home.expanded .section-title-row,
.variant-home.expanded .facility-chip-row {
flex: 0 0 auto;
@@ -1282,13 +1481,13 @@ defineExpose({
}
.result-row {
min-height: 54px;
min-height: 58px;
display: flex;
align-items: center;
gap: 9px;
padding: 9px 10px;
padding: 10px 12px;
box-sizing: border-box;
border-bottom: 1px solid #edf0e8;
border-bottom: 1px solid #efefe1;
}
.result-row:last-child {
@@ -1377,12 +1576,7 @@ defineExpose({
@media (max-width: 360px) {
.category-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.variant-page .category-grid,
.variant-home.expanded .category-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(62px, auto));
}
.variant-page .category-item,