diff --git a/src/components/explain/ExplainHallSelect.vue b/src/components/explain/ExplainHallSelect.vue
index 4344cfd..f25bf24 100644
--- a/src/components/explain/ExplainHallSelect.vue
+++ b/src/components/explain/ExplainHallSelect.vue
@@ -36,11 +36,12 @@
v-for="(hall, index) in filteredHalls"
:key="hall.id"
class="hall-card hall-overview-card"
+ :style="{ '--hall-card-color': hallCardTheme(hall).color }"
@tap="handleHallClick(hall.id)"
>
-
+
{{ hallIconText(hall.name) }}
-
+
{{ hall.name }}
-
-
- {{ hall.floorLabel || '楼层待补充' }}
-
- {{ hallMetaText(hall) }}
-
+ {{ hallCardTheme(hall).englishName }}
+ {{ hallFloorMetaText(hall) }}
+ GO ›
-
- ›
@@ -211,12 +207,24 @@ const hallPreviewMap: Record = {
家园厅: `${HALL_PREVIEW_BASE}/homeland.webp`
}
+const hallCardThemeMap: Record = {
+ 宇宙厅: { color: '#57c7d9', englishName: 'Universe Hall' },
+ 地球厅: { color: '#99de00', englishName: 'Earth Hall' },
+ 演化厅: { color: '#b896f2', englishName: 'Evolution Hall' },
+ 恐龙厅: { color: '#c7a15c', englishName: 'Dinosaur Hall' },
+ 人类厅: { color: '#e8e500', englishName: 'Human Hall' },
+ 动物厅: { color: '#08c4b5', englishName: 'Biology Hall' },
+ 生物厅: { color: '#08c4b5', englishName: 'Biology Hall' },
+ 生态厅: { color: '#8fe5b8', englishName: 'Ecology Hall' },
+ 家园厅: { color: '#ffc2a6', englishName: 'Homeland Hall' }
+}
+
const filteredHalls = computed(() => props.halls)
const shouldUseHostNavigation = computed(() => isEmbeddedInWechatMiniProgram())
const showInternalHeader = computed(() => !shouldUseHostNavigation.value)
const headerTitle = computed(() => {
if (props.stage === 'stop') return props.selectedHallName || '讲解对象'
- return '讲解'
+ return '展厅讲解'
})
const loadingTitle = computed(() => {
if (props.stage === 'stop') return '正在加载讲解对象'
@@ -271,6 +279,12 @@ const hallMetaText = (hall: ExplainHallSelectItem) => (
: hall.explainCount > 0 ? `${hall.explainCount} 个展项` : '展厅'
)
+const hallFloorMetaText = (hall: ExplainHallSelectItem) => `${hall.floorLabel || '楼层待补充'} · ${hallMetaText(hall)}`
+
+const hallCardTheme = (hall: ExplainHallSelectItem) => (
+ hallCardThemeMap[hall.name.trim()] || { color: '#dce5d5', englishName: '' }
+)
+
const handleHallClick = (hallId: string) => {
emit('hallClick', hallId)
}
@@ -318,8 +332,7 @@ const handleBack = () => {
}
.explain-scroll.hall-stage {
- padding: 58px 12px 0;
- overflow: hidden;
+ padding: 76px 16px 16px;
}
.explain-scroll.stop-stage {
@@ -346,34 +359,33 @@ const handleBack = () => {
top: 0;
left: 0;
right: 0;
- height: 56px;
+ height: 64px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 20px;
box-sizing: border-box;
background: #ffffff;
- border-bottom: 1px solid #eceee8;
z-index: 2001;
}
.header-back {
position: absolute;
left: 12px;
- top: 0;
- height: 56px;
- width: 82px;
+ top: 10px;
+ height: 44px;
+ width: 64px;
display: flex;
align-items: center;
justify-content: flex-start;
- gap: 6px;
+ gap: 4px;
z-index: 1;
}
.header-back-icon {
position: relative;
- width: 18px;
- height: 18px;
+ width: 16px;
+ height: 16px;
display: flex;
align-items: center;
justify-content: center;
@@ -384,10 +396,10 @@ const handleBack = () => {
.header-back-icon::before {
content: '';
- width: 9px;
- height: 9px;
- border-left: 2px solid currentColor;
- border-bottom: 2px solid currentColor;
+ width: 8px;
+ height: 8px;
+ border-left: 1.5px solid currentColor;
+ border-bottom: 1.5px solid currentColor;
transform: translateX(2px) rotate(45deg);
}
@@ -395,19 +407,19 @@ const handleBack = () => {
display: flex;
align-items: center;
height: 20px;
- font-size: 15px;
+ font-size: 14px;
line-height: 20px;
- font-weight: 500;
+ font-weight: 400;
color: #151713;
}
.header-title {
- max-width: calc(100% - 188px);
+ max-width: calc(100% - 152px);
padding: 0 8px;
box-sizing: border-box;
font-size: 18px;
line-height: 25px;
- font-weight: 800;
+ font-weight: 700;
color: #151713;
text-align: center;
overflow: hidden;
@@ -422,8 +434,10 @@ const handleBack = () => {
}
.hall-overview-list {
- height: 100%;
- gap: 0;
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ grid-auto-rows: 154px;
+ gap: 12px;
}
.explain-scroll.unit-stage .hall-list,
@@ -445,10 +459,15 @@ const handleBack = () => {
}
.hall-overview-card {
- min-height: 0;
- flex: 1 1 0;
- gap: 7px;
- padding: 4px 10px;
+ position: relative;
+ min-height: 154px;
+ display: block;
+ overflow: hidden;
+ padding: 0;
+ border: 0;
+ border-radius: 8px;
+ box-shadow: none;
+ background: var(--hall-card-color);
}
.hall-card:active {
@@ -470,9 +489,44 @@ const handleBack = () => {
object-fit: contain;
}
-.hall-overview-card .hall-thumb {
- width: 82px;
- height: 56px;
+.hall-overview-card:active {
+ opacity: 0.86;
+ background: var(--hall-card-color);
+}
+
+.hall-overview-card .hall-card-art {
+ position: absolute;
+ top: 46px;
+ right: 14px;
+ width: 62px;
+ height: 62px;
+ overflow: hidden;
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+}
+
+.hall-card-art-image {
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ transition: opacity 0.22s ease;
+}
+
+.hall-overview-card .hall-card-art.is-image-loaded {
+ background: transparent;
+}
+
+.hall-overview-card .hall-card-art.is-image-loaded .hall-card-art-image {
+ opacity: 0.96;
+}
+
+.hall-card-art.placeholder {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(255, 255, 255, 0.24);
+ border-radius: 50%;
}
.hall-thumb-shell.is-image-loaded {
@@ -532,6 +586,14 @@ const handleBack = () => {
flex: 1;
}
+.hall-overview-copy {
+ position: absolute;
+ top: 14px;
+ left: 14px;
+ right: 14px;
+ min-width: 0;
+}
+
.stop-desc {
display: block;
margin-top: 5px;
@@ -555,12 +617,23 @@ const handleBack = () => {
}
.hall-overview-card .hall-name {
- font-size: 15px;
- line-height: 20px;
+ display: block;
+ max-width: 94px;
+ font-size: 19px;
+ line-height: 25px;
+ font-weight: 700;
}
-.hall-overview-card .hall-meta-row {
- margin-top: 3px;
+.hall-overview-english {
+ display: block;
+ max-width: 96px;
+ margin-top: 1px;
+ font-size: 12px;
+ line-height: 17px;
+ color: #444754;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
.stop-title-row {
@@ -645,14 +718,37 @@ const handleBack = () => {
}
.hall-overview-meta {
- min-width: 0;
- font-size: 11px;
- line-height: 15px;
+ display: block;
+ max-width: 92px;
+ margin-top: 5px;
+ font-size: 9px;
+ line-height: 13px;
+ color: #444754;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
+.hall-go-entry {
+ position: absolute;
+ left: 0;
+ top: 98px;
+ width: 50px;
+ height: 25px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ background: #ffffff;
+ border-radius: 13px;
+}
+
+.hall-go-entry-text {
+ font-size: 12px;
+ line-height: 17px;
+ color: #262421;
+}
+
.hall-arrow {
flex-shrink: 0;
font-size: 24px;
diff --git a/static/explain/hall-previews/biology.webp b/static/explain/hall-previews/biology.webp
index 6a35d90..32aaedc 100644
Binary files a/static/explain/hall-previews/biology.webp and b/static/explain/hall-previews/biology.webp differ
diff --git a/static/explain/hall-previews/dinosaur.webp b/static/explain/hall-previews/dinosaur.webp
index 46409fe..2c52384 100644
Binary files a/static/explain/hall-previews/dinosaur.webp and b/static/explain/hall-previews/dinosaur.webp differ
diff --git a/static/explain/hall-previews/earth.webp b/static/explain/hall-previews/earth.webp
index 1dbb11f..3a72823 100644
Binary files a/static/explain/hall-previews/earth.webp and b/static/explain/hall-previews/earth.webp differ
diff --git a/static/explain/hall-previews/ecology.webp b/static/explain/hall-previews/ecology.webp
index 42666bd..a358d67 100644
Binary files a/static/explain/hall-previews/ecology.webp and b/static/explain/hall-previews/ecology.webp differ
diff --git a/static/explain/hall-previews/evolution.webp b/static/explain/hall-previews/evolution.webp
index 8b63603..7c7c1d8 100644
Binary files a/static/explain/hall-previews/evolution.webp and b/static/explain/hall-previews/evolution.webp differ
diff --git a/static/explain/hall-previews/homeland.webp b/static/explain/hall-previews/homeland.webp
index ff95ce5..de3997b 100644
Binary files a/static/explain/hall-previews/homeland.webp and b/static/explain/hall-previews/homeland.webp differ
diff --git a/static/explain/hall-previews/human.webp b/static/explain/hall-previews/human.webp
index 58a0417..1f91314 100644
Binary files a/static/explain/hall-previews/human.webp and b/static/explain/hall-previews/human.webp differ
diff --git a/static/explain/hall-previews/universe.webp b/static/explain/hall-previews/universe.webp
index 4dd571d..0bf2b78 100644
Binary files a/static/explain/hall-previews/universe.webp and b/static/explain/hall-previews/universe.webp differ
diff --git a/tests/unit/ExplainHallSelect.spec.ts b/tests/unit/ExplainHallSelect.spec.ts
index a55b012..c129e6a 100644
--- a/tests/unit/ExplainHallSelect.spec.ts
+++ b/tests/unit/ExplainHallSelect.spec.ts
@@ -35,6 +35,29 @@ describe('讲解展厅选择列表', () => {
expect(wrapper.emitted('hallClick')).toEqual([['hall-evolution']])
})
+ it('展厅阶段按卡片网格展示英文名和进入入口', () => {
+ const wrapper = mount(ExplainHallSelect, {
+ props: {
+ stage: 'hall',
+ halls: [{
+ id: 'hall-dinosaur',
+ name: '恐龙厅',
+ floorLabel: 'L-2',
+ explainCount: 35,
+ guideStopCount: 35,
+ searchText: '恐龙厅'
+ }]
+ }
+ })
+
+ const card = wrapper.get('.hall-overview-card')
+ expect(wrapper.get('.header-title').text()).toBe('展厅讲解')
+ expect(card.attributes('style')).toContain('--hall-card-color: #c7a15c')
+ expect(card.text()).toContain('Dinosaur Hall')
+ expect(card.text()).toContain('L-2 · 35 个讲解对象')
+ expect(card.get('.hall-go-entry').text()).toBe('GO ›')
+ })
+
it('READY 讲解点不显示可讲解标签,非 READY 讲解点保留图文标签和点击事件', async () => {
const readyStop = {
id: 'stop-ready',