This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<view class="guide-stop-catalog" :class="{ 'host-navigation': shouldUseHostNavigation, 'has-embedded-back': showEmbeddedBack }">
|
||||
<view v-if="showInternalHeader || showEmbeddedBack" class="catalog-header">
|
||||
<view v-if="showInternalBack" class="header-back" @tap="emit('back')">
|
||||
<view class="guide-stop-catalog" :class="{ 'host-navigation': shouldUseHostNavigation }">
|
||||
<view v-if="showInternalHeader" class="catalog-header">
|
||||
<view class="header-back" @tap="emit('back')">
|
||||
<text class="header-back-icon" />
|
||||
<text class="header-back-text">返回</text>
|
||||
</view>
|
||||
<text v-if="showInternalHeader" class="header-title">{{ selectedHallName || '讲解对象' }}</text>
|
||||
<text class="header-title">{{ selectedHallName || '讲解对象' }}</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="explain-scroll" scroll-y :show-scrollbar="false" @scroll="handleScroll" @scrolltolower="requestMore">
|
||||
@@ -71,18 +71,16 @@ export interface ExplainGuideStopCatalogItem {
|
||||
const props = withDefaults(defineProps<{
|
||||
guideStops?: ExplainGuideStopCatalogItem[]
|
||||
selectedHallName?: string
|
||||
showEmbeddedBack?: boolean
|
||||
loading?: boolean
|
||||
loadingMore?: boolean
|
||||
hasMore?: boolean
|
||||
error?: string
|
||||
loadMoreError?: string
|
||||
}>(), { guideStops: () => [], selectedHallName: '', showEmbeddedBack: false, loading: false, loadingMore: false, hasMore: false, error: '', loadMoreError: '' })
|
||||
}>(), { guideStops: () => [], selectedHallName: '', loading: false, loadingMore: false, hasMore: false, error: '', loadMoreError: '' })
|
||||
|
||||
const emit = defineEmits<{ guideStopClick: [stop: ExplainGuideStopCatalogItem], back: [], retry: [], retryMore: [] }>()
|
||||
const shouldUseHostNavigation = computed(() => isEmbeddedInWechatMiniProgram())
|
||||
const showInternalHeader = computed(() => !shouldUseHostNavigation.value)
|
||||
const showInternalBack = computed(() => !shouldUseHostNavigation.value || props.showEmbeddedBack)
|
||||
const failedImageIds = ref(new Set<string>())
|
||||
const visibleCoverIds = ref(new Set<string>())
|
||||
const coverSlots = new Map<string, Element>()
|
||||
@@ -157,7 +155,7 @@ const handleScroll = (event: Event) => { const target = event.target as HTMLElem
|
||||
.catalog-header { position: absolute; z-index: 2; top: 0; left: 0; right: 0; height: 64px; display: flex; align-items: center; justify-content: center; background: #f7f9f2; }
|
||||
.header-back { position: absolute; left: 12px; top: 10px; width: 44px; height: 44px; display: flex; align-items: center; }.header-back-icon { width: 20px; height: 20px; position: relative; } .header-back-icon::before { content: ''; position: absolute; left: 3px; top: 4px; width: 10px; height: 10px; border-left: 1.5px solid #262421; border-bottom: 1.5px solid #262421; transform: rotate(45deg); }
|
||||
.header-back-text { display: none; }.header-title { max-width: calc(100% - 152px); padding: 0 8px; font-size: 18px; line-height: 26px; font-weight: 700; color: #262421; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.explain-scroll { height: 100%; padding: 80px 16px calc(16px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f7f9f2; }.host-navigation .explain-scroll { padding-top: 16px; }.host-navigation.has-embedded-back .explain-scroll { padding-top: 80px; }
|
||||
.explain-scroll { height: 100%; padding: 80px 16px calc(16px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f7f9f2; }.host-navigation .explain-scroll { padding-top: 16px; }
|
||||
.stop-list { display: flex; width: 100%; min-width: 0; flex-direction: column; gap: 4px; }.stop-card { width: 100%; min-width: 0; height: 80px; padding: 8px 0; display: flex; align-items: center; gap: 12px; box-sizing: border-box; overflow: hidden; border: 0; border-bottom: 1px solid #dbded4; border-radius: 0; background: transparent; }.stop-card:active { background: rgba(227, 235, 201, 0.4); }.stop-cover { flex: 0 0 64px; width: 64px; height: 64px; overflow: hidden; border-radius: 6px; background: #f5f5ed; }.stop-cover-fallback { font-size: 22px; line-height: 28px; color: #a9b29b; }.stop-copy { min-width: 0; display: flex; flex: 1; overflow: hidden; }.stop-name { display: -webkit-box; max-height: 40px; font-size: 14px; line-height: 20px; font-weight: 700; color: #262421; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }.stop-status { flex: 0 0 44px; width: 44px; height: 24px; display: flex; align-items: center; justify-content: center; border-radius: 12px; background: #e3ebc9; }.stop-status-text { font-size: 11px; line-height: 16px; color: #262421; white-space: nowrap; }
|
||||
.state-block { margin: 34px 0; padding: 22px 16px; box-sizing: border-box; text-align: center; border: 1px solid #e4e6df; border-radius: 8px; background: #fff; }.state-block.error { border-color: #e5c2c2; background: #fff7f7; }.state-title,.state-desc { display: block; }.state-title { font-size: 15px; line-height: 21px; font-weight: 700; color: #141412; }.state-desc { margin-top: 6px; font-size: 12px; line-height: 18px; color: #68725d; }.state-retry { margin-top: 12px; padding: 0 14px; font-size: 13px; line-height: 32px; color: #141412; background: #e0df00; border: 0; border-radius: 6px; }.load-more-state { min-height: 52px; padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); text-align: center; }
|
||||
</style>
|
||||
|
||||
@@ -53,13 +53,19 @@
|
||||
v-if="!isHallPreviewError(hall.id)"
|
||||
class="hall-full-card-image"
|
||||
:src="hallPreviewUrl(hall)"
|
||||
mode="aspectFill"
|
||||
mode="aspectFit"
|
||||
:lazy-load="isHallPreviewLazy(index)"
|
||||
@load="handleHallPreviewLoad(hall.id)"
|
||||
@error="handleHallPreviewError(hall.id)"
|
||||
/>
|
||||
<view v-else class="hall-full-card-fallback">
|
||||
<text class="hall-name">{{ hall.name }}</text>
|
||||
<view v-if="isHallPreviewError(hall.id)" class="hall-full-card-fallback">
|
||||
<text class="hall-thumb-text">{{ hallIconText(hall.name) }}</text>
|
||||
</view>
|
||||
<view class="hall-full-card-copy">
|
||||
<text class="hall-full-card-name">{{ hall.name }}</text>
|
||||
<text v-if="hallCardTheme(hall).englishName" class="hall-full-card-english">
|
||||
{{ hallCardTheme(hall).englishName }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<template v-else>
|
||||
@@ -253,7 +259,7 @@ const emit = defineEmits<{
|
||||
retryMore: []
|
||||
}>()
|
||||
|
||||
const HALL_PREVIEW_BASE = '/static/icons/halls/custom-cards'
|
||||
const HALL_PREVIEW_BASE = '/static/icons/halls/portal-icons'
|
||||
const HALL_PREVIEW_EAGER_COUNT = 4
|
||||
const loadedHallPreviewIds = ref(new Set<string>())
|
||||
const failedHallPreviewIds = ref(new Set<string>())
|
||||
@@ -271,15 +277,15 @@ const hallPreviewMap: Record<string, string> = {
|
||||
}
|
||||
|
||||
const hallCardThemeMap: Record<string, { color: string; englishName: string }> = {
|
||||
宇宙厅: { color: '#65d2e4', englishName: '' },
|
||||
地球厅: { color: '#b8e51b', englishName: '' },
|
||||
演化厅: { color: '#cba7ff', englishName: '' },
|
||||
恐龙厅: { color: '#d9b06c', englishName: '' },
|
||||
人类厅: { color: '#e9ea16', englishName: '' },
|
||||
动物厅: { color: '#20c9c0', englishName: '' },
|
||||
生物厅: { color: '#20c9c0', englishName: '' },
|
||||
生态厅: { color: '#94e7be', englishName: '' },
|
||||
家园厅: { color: '#ffc6a5', englishName: '' }
|
||||
宇宙厅: { color: '#5ed0e4', englishName: 'Cosmos Hall' },
|
||||
地球厅: { color: '#94d40b', englishName: 'Earth Hall' },
|
||||
演化厅: { color: '#bc9afb', englishName: 'Evolution Hall' },
|
||||
恐龙厅: { color: '#bb965a', englishName: 'Dinosaur Hall' },
|
||||
人类厅: { color: '#e0e100', englishName: 'Human Hall' },
|
||||
动物厅: { color: '#00c3b3', englishName: 'Biology Hall' },
|
||||
生物厅: { color: '#00c3b3', englishName: 'Biology Hall' },
|
||||
生态厅: { color: '#87e0b0', englishName: 'Ecology Hall' },
|
||||
家园厅: { color: '#ffbe9e', englishName: 'Homeland Hall' }
|
||||
}
|
||||
|
||||
const filteredHalls = computed(() => props.halls)
|
||||
@@ -935,9 +941,13 @@ const handleBack = () => {
|
||||
}
|
||||
|
||||
.hall-full-card-image {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 12px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 78%;
|
||||
height: calc(100% - 66px);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.hall-full-card-fallback {
|
||||
@@ -945,10 +955,47 @@ const handleBack = () => {
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24px;
|
||||
justify-content: center;
|
||||
padding-bottom: 46px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hall-full-card-copy {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
bottom: 9px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hall-full-card-name,
|
||||
.hall-full-card-english {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hall-full-card-name {
|
||||
font-size: 19px;
|
||||
line-height: 25px;
|
||||
font-weight: 500;
|
||||
color: #151713;
|
||||
}
|
||||
|
||||
.hall-full-card-english {
|
||||
margin-top: 0;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-weight: 300;
|
||||
color: rgba(21, 23, 19, 0.72);
|
||||
}
|
||||
|
||||
.hall-overview-copy {
|
||||
top: 24px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user