| | |
| | | |
| | | <scroll-view class="page-scroll" scroll-y lower-threshold="80" @scroll="handleScroll" @scrolltolower="loadMore"> |
| | | <view class="hero"> |
| | | <image class="hero-image" :src="currentScene.image" mode="aspectFill" @error="replaceHeroImage"></image> |
| | | <swiper v-if="scenes.length > 0" class="hero-swiper" :current="activeIndex < 0 ? 0 : activeIndex" :circular="scenes.length > 1" :duration="240" @change="handleHeroChange"> |
| | | <swiper-item v-for="(item, index) in scenes" :key="item.id"> |
| | | <image class="hero-image" :src="item.image" mode="aspectFill" @error="replaceSceneImage(index)"></image> |
| | | </swiper-item> |
| | | </swiper> |
| | | <image v-else class="hero-image" :src="currentScene.image" mode="aspectFill" @error="replaceHeroImage"></image> |
| | | <view class="hero-shade"></view> |
| | | <text v-if="currentScene.name != ''" class="scene-name">{{currentScene.name}}</text> |
| | | <text v-if="scenes.length == 0" class="no-gallery">暂无图册内容</text> |
| | |
| | | if (index >= scenes.value.length) index = scenes.value.length - 1 |
| | | selectScene(index) |
| | | } |
| | | /** 主图左右滑动:滑动落点同步到缩略图、名称与描述。 */ |
| | | const handleHeroChange = (event: any) => { |
| | | const current = event != null && event.detail != null && event.detail.current != null ? Number(event.detail.current) : -1 |
| | | if (current < 0) return |
| | | selectScene(current) |
| | | } |
| | | const handleScroll = (event: any) => { isSolidNav.value = event.detail.scrollTop > 64 } |
| | | const loadServices = (append: boolean) => { |
| | | if (!isApiConfigured()) { initialLoading.value = false; loadingMore.value = false; initialError.value = true; return } |
| | |
| | | </script> |
| | | |
| | | <style> |
| | | /* 顶部大图标题用行楷:优先 App.uvue 动态加载的服务器完整字体,回退包内子集与系统字体。 */ |
| | | .scene-name { font-family: 'FoodCalligraphyFull', 'FoodCalligraphy'; } |
| | | .page, .page-scroll { width: 100%; height: 100vh; background-color: #FFFFFF; } |
| | | .custom-nav { position: fixed; z-index: 20; left: 0; right: 0; top: 0; padding-bottom: 20rpx; } |
| | | .nav-bg { position: absolute; left: 0; right: 0; top: 0; bottom: 0; opacity: 0; background-image: linear-gradient(180deg, #F26A38 0%, #EE542B 100%); transition: opacity 280ms ease-out; } |
| | |
| | | .topic-summary { position: relative; z-index: 4; margin-top: -66rpx; }.intro-card { margin: 0 31rpx; box-sizing: border-box; padding: 25rpx 31rpx; border-radius: 26rpx; background-image: linear-gradient(90deg, #FF5320 0%, #FF8A22 100%); box-shadow: 0 10rpx 22rpx rgba(255,104,28,.24); }.intro-card text { color: #FFFFFF; font-size: 23rpx; line-height: 34rpx; } |
| | | .service-section { padding: 32rpx 31rpx 0; }.section-heading { display: flex; width: 132rpx; height: 72rpx; flex-direction: column; align-items: center; }.section-heading text { display: block; color: #363636; font-size: 32rpx; font-weight: 700; }.section-heading view { width: 61rpx; height: 7rpx; margin: 12rpx 0 18rpx; border-radius: 4rpx; background-image: linear-gradient(90deg, #FF4D36 0%, #FFBF3A 100%); }.service-item { display: flex; min-height: 205rpx; margin-bottom: 20rpx; flex-direction: row; }.service-item.is-unavailable { opacity: .56; }.service-image { width: 184rpx; height: 184rpx; border-radius: 17rpx; flex-shrink: 0; background-color: #EEE; }.service-info { display: flex; min-width: 0; min-height: 184rpx; flex: 1; padding: 4rpx 0 4rpx 24rpx; flex-direction: column; justify-content: space-between; }.service-name { color: #292929; font-size: 29rpx; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }.discount-tag { display: block; width: fit-content; padding: 6rpx 9rpx; border-radius: 6rpx; background-color: #FFF0EC; color: #FF5D37; font-size: 21rpx; }.address { display: flex; min-width: 0; box-sizing: border-box; padding: 7rpx 10rpx; border-radius: 7rpx; background-image: linear-gradient(90deg, rgba(239,240,242,.98) 0%, rgba(242,243,245,.76) 58%, rgba(255,255,255,0) 100%); flex-direction: row; align-items: flex-start; }.address image { width: 27rpx; height: 27rpx; margin-right: 8rpx; flex-shrink: 0; }.address text { min-width: 0; flex: 1; color: #7E8490; font-size: 21rpx; line-height: 31rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| | | .list-state, .no-more { display: flex; height: 150rpx; color: #989DA5; font-size: 23rpx; justify-content: center; align-items: center; }.list-state.compact { height: 90rpx; }.error-state { flex-direction: column; }.retry-text, .load-error text { margin-top: 18rpx; color: #F26A38; }.loading-spinner { width: 26rpx; height: 26rpx; margin-right: 12rpx; box-sizing: border-box; border: 3rpx solid #FFD6C4; border-top-color: #FF6C2B; border-radius: 50%; animation: entertainment-loading 720ms linear infinite; }@keyframes entertainment-loading { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }.bottom-space { height: calc(30rpx + env(safe-area-inset-bottom)); } |
| | | /* 主图轮播:与下方缩略图带同高同位,盖在原来的静态主图上。 */ |
| | | .hero-swiper { position: absolute; left: 0; top: 0; width: 100%; height: 730rpx; } |
| | | </style> |