shinnosuke
4 天以前 5ce0d76154bf4c1d70543476cdfad9a30195b0f8
rencaika/pages/premium-benefits/premium-benefits.uvue
@@ -1,8 +1,8 @@
<template>
   <view class="page">
      <view class="custom-nav" :class="isSolidNav ? 'is-solid' : ''"><view class="nav-bg"></view><view class="safe-space" :style="'height:' + navTop + 'px'"></view><view class="nav-row" :style="'height:' + navHeight + 'px;padding-right:' + navRight + 'px'"><view class="back-button" @tap="goBack"><image src="/static/food-assets/arrow-left-white.svg" mode="aspectFit"></image></view><text class="nav-title">享—{{topicTitle}}</text><view class="capsule-space" :style="'width:' + navWidth + 'px'"></view></view></view>
      <scroll-view class="page-scroll" scroll-y lower-threshold="80" @scroll="handleScroll" @scrolltolower="loadMore">
         <view class="hero"><image class="hero-image" :src="activeScene.image" mode="aspectFill" @error="replaceImage(activeScene)"></image><view class="hero-top-shade"></view><view class="hero-bottom-shade"></view><text class="scene-name">{{activeScene.name}}</text><scroll-view class="scene-scroll" scroll-x :show-scrollbar="false" scroll-with-animation :scroll-left="sceneScrollLeft" @scroll="handleSceneScroll"><view class="scene-row" :style="'width:' + sceneTrackWidth + 'rpx'"><view class="scene-pad"></view><view v-for="(item, index) in scenes" :key="item.id" class="scene-item" :class="index == activeIndex ? 'active' : ''" @tap="selectScene(index)"><image :src="item.image" mode="aspectFill" @error="replaceImage(item)"></image></view><view class="scene-pad"></view></view></scroll-view></view>
      <scroll-view :show-scrollbar="false" class="page-scroll" scroll-y lower-threshold="80" @scroll="handleScroll" @scrolltolower="loadMore">
         <view class="hero"><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="replaceImage(item)"></image></swiper-item></swiper><image v-else class="hero-image" :src="activeScene.image" mode="aspectFill" @error="replaceImage(activeScene)"></image><view class="hero-top-shade"></view><view class="hero-bottom-shade"></view><text class="scene-name">{{activeScene.name}}</text><scroll-view class="scene-scroll" scroll-x :show-scrollbar="false" scroll-with-animation :scroll-left="sceneScrollLeft" @scroll="handleSceneScroll"><view class="scene-row" :style="'width:' + sceneTrackWidth + 'rpx'"><view class="scene-pad"></view><view v-for="(item, index) in scenes" :key="item.id" class="scene-item" :class="index == activeIndex ? 'active' : ''" @tap="selectScene(index)"><image :src="item.image" mode="aspectFill" @error="replaceImage(item)"></image></view><view class="scene-pad"></view></view></scroll-view></view>
         <view v-if="topicError" class="topic-error"><text>专题配置加载失败</text><text @tap="loadPremiumTopic">重新加载</text></view>
         <view v-if="topicDescription != ''" class="topic-summary"><view class="intro-card"><text>{{topicDescription}}</text></view></view>
         <view class="service-section"><scroll-view class="tab-scroll" scroll-x :show-scrollbar="false"><view class="service-tabs" :style="'width:' + Math.max(750, serviceTabs.length * 234) + 'rpx'"><view v-for="tab in serviceTabs" :key="tab.id" class="service-tab" :class="tab.id == activeTab ? 'active' : ''" @tap="selectTab(tab.id)"><text>{{tab.name}}</text><view class="tab-line"></view></view></view></scroll-view>
@@ -37,6 +37,8 @@
   const sceneIndexFromScroll = (scrollLeft: number): number => { let index = Math.round(scrollLeft * 750 / windowWidth.value / 137); if (index < 0) index = 0; if (index >= scenes.value.length) index = scenes.value.length - 1; return index }
   let sceneSettleTimer = 0
   const handleSceneScroll = (event: any) => { const index = sceneIndexFromScroll(event.detail.scrollLeft as number); if (sceneSettleTimer != 0) clearTimeout(sceneSettleTimer); sceneSettleTimer = setTimeout(() => { sceneSettleTimer = 0; selectScene(index) }, 200) }
   /** 主图左右滑动:滑动落点同步到缩略图、名称与描述。 */
   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 loadPremiumTopic = () => {
      if (!isApiConfigured()) { topicError.value = true; initialLoading.value = false; initialError.value = true; return }
@@ -77,4 +79,6 @@
   /* 标签与折扣并排显示:标签是后台配的文字(如「卓越人才卡」),折扣是另一个字段(如「8折」)。 */
   .service-benefit-row { display:flex; flex-direction:row; align-items:center; }
   .service-benefit-row .service-benefit + .service-benefit { margin-left:10rpx; }
   /* 主图轮播:与下方缩略图带同高同位,盖在原来的静态主图上。 */
   .hero-swiper { position:absolute; left:0; top:0; width:100%; height:730rpx; }
</style>