精简首页加载页并补充品牌标识
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-13 17:37:41 +08:00
parent 140f13633e
commit d265089875
4 changed files with 132 additions and 234 deletions

View File

@@ -263,38 +263,24 @@
:class="{ leaving: launchOverlayLeaving }"
>
<view class="app-launch-stage">
<image
class="app-launch-image app-launch-image-lqip"
src="/static/guide/app-launch-loading-lqip.webp"
mode="aspectFill"
/>
<image
class="app-launch-image app-launch-image-full"
:class="{ loaded: launchImageLoaded && !launchImageFailed }"
src="/static/guide/app-launch-loading.webp"
mode="aspectFill"
@load="handleLaunchImageLoad"
@error="handleLaunchImageError"
/>
<view class="app-launch-shade"></view>
<view class="app-launch-brand">
<text class="app-launch-kicker">探索万物生息</text>
<text class="app-launch-title">深圳自然博物馆</text>
<text class="app-launch-subtitle">Shenzhen Natural History Museum</text>
</view>
<view class="app-launch-status">
<text class="app-launch-loading-text">{{ launchLoadingText }}</text>
<view class="app-launch-progress">
<view class="app-launch-progress-bar" :style="launchProgressStyle"></view>
</view>
<view v-if="launchOverlayRecoverable" class="app-launch-actions">
<view class="app-launch-action secondary" @tap="handleLaunchRetry">
<text class="app-launch-action-text">重新加载</text>
</view>
<view class="app-launch-action primary" @tap="handleLaunchContinue">
<text class="app-launch-action-text">继续进入</text>
</view>
</view>
<view class="app-launch-content">
<image
class="app-launch-logo"
src="/static/guide/museum-brand-icons.webp"
mode="widthFix"
/>
<text class="app-launch-name-en">SHENZHEN NATURAL HISTORY MUSEUM</text>
<text class="app-launch-name-cn">深圳自然博物馆</text>
<progress
class="app-launch-progress"
:percent="launchProgress"
active
active-mode="forwards"
:stroke-width="3"
active-color="#e0e100"
background-color="#eceee7"
:show-info="false"
/>
</view>
</view>
</view>
@@ -381,7 +367,6 @@ const topTabFromHash = () => {
const launchOverlayMinDisplayMs = 700
const launchOverlayGuideTimeoutMs = 12000
const launchOverlayNonGuideTimeoutMs = 900
const launchOverlayDefaultText = '正在进入智能导览'
const shouldShowLaunchOverlay = () => {
if (typeof window === 'undefined') return false
@@ -407,11 +392,7 @@ const currentTab = ref<GuideTopTab>(initialTopTab())
const launchOverlayVisible = ref(shouldShowLaunchOverlay())
const launchOverlayLeaving = ref(false)
const launchProgress = ref(8)
const launchLoadingText = ref(launchOverlayDefaultText)
const launchInitialModelSettled = ref(false)
const launchOverlayRecoverable = ref(false)
const launchImageLoaded = ref(false)
const launchImageFailed = ref(false)
const showRoutePlanner = ref(false)
const routeStartPoint = ref<RoutePointOption | null>(null)
const routeEndPoint = ref<RoutePointOption | null>(null)
@@ -448,10 +429,6 @@ let launchOverlayFadeTimer: ReturnType<typeof setTimeout> | null = null
let launchOverlayHideDelayTimer: ReturnType<typeof setTimeout> | null = null
let launchOverlayStartedAt = 0
const launchProgressStyle = computed(() => ({
width: `${launchProgress.value}%`
}))
const clearLaunchTimers = () => {
if (launchOverlayFallbackTimer) {
clearTimeout(launchOverlayFallbackTimer)
@@ -515,8 +492,6 @@ const continueLaunchWithoutInitialModel = (reason: string, event?: { view: Guide
})
launchInitialModelSettled.value = true
launchOverlayRecoverable.value = false
launchLoadingText.value = launchOverlayDefaultText
launchProgress.value = Math.max(launchProgress.value, 96)
is3DMode.value = false
guideOutdoorState.value = 'home'
@@ -531,10 +506,8 @@ const startLaunchOverlay = () => {
clearLaunchTimers()
launchInitialModelSettled.value = false
launchOverlayRecoverable.value = false
launchOverlayStartedAt = Date.now()
launchProgress.value = shouldWaitForLaunchModel() ? 8 : 68
launchLoadingText.value = launchOverlayDefaultText
const timeoutMs = shouldWaitForLaunchModel()
? launchOverlayGuideTimeoutMs
@@ -552,52 +525,23 @@ const startLaunchOverlay = () => {
const handleInitialModelProgress = (event: { progress: number; message: string; view: GuideIndoorView; floorId?: string; elapsedMs?: number }) => {
if (!launchOverlayVisible.value || launchInitialModelSettled.value || !shouldWaitForLaunchModel()) return
launchOverlayRecoverable.value = false
launchProgress.value = Math.min(99, Math.max(8, event.progress))
launchLoadingText.value = launchOverlayDefaultText
}
const settleLaunchOverlayByModel = (status: 'ready' | 'failed', event?: { view: GuideIndoorView; floorId?: string; message?: string; elapsedMs?: number }) => {
launchInitialModelSettled.value = true
launchOverlayRecoverable.value = status === 'failed'
if (status === 'failed') {
continueLaunchWithoutInitialModel('failed', event)
return
} else {
launchProgress.value = 100
launchLoadingText.value = launchOverlayDefaultText
console.log('首页前置加载页收到初始模型加载完成:', event)
}
hideLaunchOverlay()
}
const handleLaunchRetry = () => {
if (typeof window !== 'undefined') {
window.location.reload()
}
}
const handleLaunchImageLoad = () => {
launchImageLoaded.value = true
launchImageFailed.value = false
}
const handleLaunchImageError = () => {
launchImageLoaded.value = false
launchImageFailed.value = true
}
const handleLaunchContinue = () => {
launchOverlayRecoverable.value = false
if (shouldWaitForLaunchModel() && !launchInitialModelSettled.value) {
continueLaunchWithoutInitialModel('manual')
return
}
hideLaunchOverlay()
}
const showArrivalPanel = ref(false)
const showArrivalPanelCollapsed = ref(false)
const arrivalPanelRef = ref<InstanceType<typeof ArrivalPanel> | null>(null)
@@ -1582,7 +1526,7 @@ const handleExplainBack = () => {
display: flex;
justify-content: center;
overflow: hidden;
background: #e9e8dc;
background: #ffffff;
opacity: 1;
transition: opacity 0.36s ease, transform 0.36s ease;
}
@@ -1594,194 +1538,82 @@ const handleExplainBack = () => {
}
.app-launch-stage {
position: relative;
width: 100%;
max-width: 430px;
height: 100vh;
height: 100dvh;
min-height: 560px;
overflow: hidden;
background:
radial-gradient(circle at 50% 20%, rgba(224, 225, 0, 0.24), rgba(224, 225, 0, 0) 34%),
linear-gradient(180deg, #f5f5ed 0%, #e1e5d9 42%, #151713 100%);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
}
.app-launch-image {
position: absolute;
inset: 0;
z-index: 0;
width: 100%;
height: 100%;
transform-origin: center;
}
.app-launch-image-lqip {
filter: blur(10px);
transform: scale(1.08);
}
.app-launch-image-full {
opacity: 0;
transform: scale(1.01);
transition: opacity 0.24s ease;
}
.app-launch-image-full.loaded {
opacity: 1;
}
.app-launch-shade {
position: absolute;
inset: 0;
z-index: 1;
background:
linear-gradient(180deg, rgba(245, 245, 237, 0.92) 0%, rgba(245, 245, 237, 0.62) 24%, rgba(10, 12, 9, 0.08) 52%, rgba(0, 0, 0, 0.56) 100%),
linear-gradient(180deg, rgba(224, 225, 0, 0.28) 0, rgba(224, 225, 0, 0) 138px);
}
.app-launch-brand {
position: absolute;
z-index: 2;
top: calc(env(safe-area-inset-top) + 58px);
left: 24px;
right: 24px;
display: flex;
flex-direction: column;
gap: 6px;
}
.app-launch-kicker {
width: fit-content;
padding: 4px 8px;
box-sizing: border-box;
background: #000000;
font-size: 12px;
line-height: 17px;
font-weight: 700;
color: var(--museum-accent);
}
.app-launch-title {
font-size: 31px;
line-height: 39px;
font-weight: 800;
letter-spacing: 0;
color: #000000;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.46);
}
.app-launch-subtitle {
max-width: 300px;
font-size: 14px;
line-height: 19px;
font-weight: 500;
color: #424754;
}
.app-launch-status {
position: absolute;
z-index: 2;
left: 24px;
right: 24px;
bottom: calc(env(safe-area-inset-bottom) + 56px);
padding: 16px;
box-sizing: border-box;
background: rgba(0, 0, 0, 0.88);
border: 1px solid rgba(224, 225, 0, 0.34);
}
.app-launch-loading-text {
display: block;
font-size: 15px;
line-height: 21px;
font-weight: 700;
color: #ffffff;
}
.app-launch-progress {
height: 4px;
margin-top: 12px;
overflow: hidden;
background: rgba(255, 255, 255, 0.18);
}
.app-launch-progress-bar {
height: 100%;
width: 18%;
background: var(--museum-accent);
transition: width 0.22s ease;
}
.app-launch-actions {
margin-top: 14px;
display: flex;
gap: 10px;
}
.app-launch-action {
height: 36px;
flex: 1;
min-height: 480px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: #ffffff;
}
.app-launch-content {
width: 100%;
padding: 0 28px;
display: flex;
align-items: center;
flex-direction: column;
box-sizing: border-box;
border-radius: 8px;
transform: translateY(-3vh);
}
.app-launch-action.secondary {
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.38);
.app-launch-logo {
width: min(84vw, 350px);
height: auto;
}
.app-launch-action.primary {
background: var(--museum-accent);
border: 1px solid var(--museum-accent);
}
.app-launch-action-text {
.app-launch-name-en {
margin-top: 20px;
white-space: nowrap;
font-family: 'HarmonyOS Sans SC', 'HarmonyOS Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
font-size: 13px;
line-height: 18px;
font-weight: 700;
color: #ffffff;
font-weight: 500;
letter-spacing: 0;
color: #262421;
}
.app-launch-action.primary .app-launch-action-text {
color: #151713;
.app-launch-name-cn {
margin-top: 8px;
white-space: nowrap;
font-family: 'Songti SC', STSong, SimSun, serif;
font-size: 36px;
line-height: 48px;
font-weight: 500;
letter-spacing: 0;
color: #000000;
}
.app-launch-progress {
width: 112px;
margin-top: 32px;
}
@media (max-width: 360px) {
.app-launch-brand {
top: calc(env(safe-area-inset-top) + 48px);
left: 20px;
right: 20px;
.app-launch-content {
padding: 0 24px;
}
.app-launch-title {
font-size: 28px;
line-height: 36px;
.app-launch-logo {
width: calc(100vw - 52px);
}
.app-launch-subtitle {
font-size: 13px;
line-height: 18px;
}
.app-launch-status {
left: 20px;
right: 20px;
bottom: calc(env(safe-area-inset-bottom) + 42px);
padding: 14px;
.app-launch-name-cn {
font-size: 32px;
line-height: 43px;
}
}
@media (max-height: 680px) {
.app-launch-brand {
top: calc(env(safe-area-inset-top) + 38px);
.app-launch-content {
transform: translateY(-1vh);
}
.app-launch-status {
bottom: calc(env(safe-area-inset-bottom) + 32px);
.app-launch-progress {
margin-top: 26px;
}
}