feat: 优化首页、个人中心页面 UI
This commit is contained in:
@@ -1,52 +1,22 @@
|
||||
<template>
|
||||
<view class="home-page">
|
||||
<!-- ① Brand Banner — fixed background layer -->
|
||||
<view class="home-page" :style="{ height: pageHeight }">
|
||||
<view class="banner-fixed">
|
||||
<BrandBanner :studio-info="studioStore.studioInfo" />
|
||||
</view>
|
||||
|
||||
<!-- Pull-to-refresh wrapper — scrollable foreground -->
|
||||
<scroll-view
|
||||
class="page-scroll"
|
||||
scroll-y
|
||||
:scroll-top="scrollTop"
|
||||
:scroll-with-animation="true"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="handleRefresh"
|
||||
@refresherrestore="refreshing = false"
|
||||
>
|
||||
<!-- Transparent spacer to reveal Banner behind -->
|
||||
<scroll-view class="page-scroll" scroll-y :scroll-into-view="scrollTarget"
|
||||
scroll-with-animation refresher-enabled :refresher-triggered="refreshing"
|
||||
@refresherrefresh="handleRefresh" @refresherrestore="refreshing = false">
|
||||
<view class="banner-spacer" />
|
||||
|
||||
<!-- Floating card with rounded top corners -->
|
||||
<view class="floating-card">
|
||||
<!-- Drag indicator -->
|
||||
<view class="card-handle">
|
||||
<view class="card-handle-bar" />
|
||||
</view>
|
||||
|
||||
<!-- ② Studio Info (photo strip + address/phone) -->
|
||||
<StudioInfo :studio-info="studioStore.studioInfo" />
|
||||
|
||||
<!-- ③ Quick Entry (login / trial / book / renew) -->
|
||||
<view class="card-handle"><view class="card-handle-bar" /></view>
|
||||
<QuickEntry @scroll-to-card-shop="scrollToCardShop" />
|
||||
|
||||
<!-- ④ Upcoming Bookings -->
|
||||
<UpcomingBooking />
|
||||
|
||||
<!-- ④.5 Flash Sale Section -->
|
||||
<StudioInfo :studio-info="studioStore.studioInfo" />
|
||||
<FlashSaleSection ref="flashSaleRef" />
|
||||
|
||||
<!-- ⑤ Card Shop (vertical list) -->
|
||||
<view :id="cardShopAnchorId">
|
||||
<CardShop ref="cardShopRef" />
|
||||
</view>
|
||||
|
||||
<!-- ⑥ About (teacher + studio gallery) -->
|
||||
<AboutSection />
|
||||
|
||||
<!-- Bottom padding for tab bar -->
|
||||
<view class="bottom-padding" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -55,7 +25,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onUnmounted } from 'vue'
|
||||
import { onShow, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
||||
import { onShow, onResize, onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
|
||||
|
||||
import BrandBanner from '../../components/BrandBanner.vue'
|
||||
import StudioInfo from '../../components/StudioInfo.vue'
|
||||
@@ -94,7 +64,9 @@ const refreshing = ref(false)
|
||||
const cardShopRef = ref<InstanceType<typeof CardShop> | null>(null)
|
||||
const flashSaleRef = ref<InstanceType<typeof FlashSaleSection> | null>(null)
|
||||
const cardShopAnchorId = 'card-shop-anchor'
|
||||
const scrollTop = ref(0)
|
||||
const scrollTarget = ref('')
|
||||
const pageHeight = ref(`${uni.getWindowInfo().windowHeight}px`)
|
||||
onResize(() => { pageHeight.value = `${uni.getWindowInfo().windowHeight}px` })
|
||||
const pendingScrollToCardShop = ref(false)
|
||||
|
||||
// Listen for cross-page scroll request (e.g. from booking page "去购买")
|
||||
@@ -132,8 +104,10 @@ async function refreshData() {
|
||||
await Promise.allSettled(tasks)
|
||||
|
||||
// Also refresh card shop and flash sales
|
||||
cardShopRef.value?.fetchCardTypes()
|
||||
flashSaleRef.value?.fetchFlashSales()
|
||||
await Promise.allSettled([
|
||||
cardShopRef.value?.fetchCardTypes(),
|
||||
flashSaleRef.value?.fetchFlashSales(),
|
||||
])
|
||||
}
|
||||
|
||||
async function handleRefresh() {
|
||||
@@ -145,78 +119,30 @@ async function handleRefresh() {
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToCardShop() {
|
||||
// Reset first so setting the same value still triggers scroll
|
||||
scrollTop.value = 0
|
||||
nextTick(() => {
|
||||
uni.createSelectorQuery()
|
||||
.select(`#${cardShopAnchorId}`)
|
||||
.boundingClientRect()
|
||||
.selectViewport()
|
||||
.scrollOffset((res) => {
|
||||
if (res) {
|
||||
scrollTop.value = (res as UniApp.NodeInfo).scrollTop ?? 0
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
async function scrollToCardShop() {
|
||||
scrollTarget.value = ''
|
||||
await nextTick()
|
||||
scrollTarget.value = cardShopAnchorId
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home-page {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
background: #FAF8F5;
|
||||
}
|
||||
|
||||
/* Banner fixed behind everything */
|
||||
.banner-fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Scroll layer sits above banner */
|
||||
.page-scroll {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex: 1;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Transparent spacer lets banner peek through */
|
||||
.banner-spacer {
|
||||
height: 420rpx;
|
||||
}
|
||||
|
||||
/* Floating card that overlaps the banner */
|
||||
.home-page { position: relative; height: 100vh; background: #fbf9f6; }
|
||||
.banner-fixed { position: fixed; top: 0; left: 0; width: 100%; z-index: 0; }
|
||||
.page-scroll { position: relative; z-index: 1; height: 100%; }
|
||||
.banner-spacer { height: 420rpx; }
|
||||
.floating-card {
|
||||
position: relative;
|
||||
background: #FAF8F5;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
min-height: 100vh;
|
||||
padding-top: 12rpx;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
/* Small drag indicator at top of card */
|
||||
.card-handle {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 16rpx 0 8rpx;
|
||||
}
|
||||
|
||||
.card-handle-bar {
|
||||
width: 64rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 4rpx;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.bottom-padding {
|
||||
height: 120rpx;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
border-top: 1rpx solid rgba(255, 255, 255, 0.7);
|
||||
background: linear-gradient(180deg, rgba(251, 249, 246, 0.86), #fbf9f6 260rpx);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
backdrop-filter: blur(16px);
|
||||
box-shadow: 0 -4rpx 20rpx rgba(66, 54, 45, 0.06);
|
||||
}
|
||||
.card-handle { display: flex; justify-content: center; padding: 16rpx 0 8rpx; }
|
||||
.card-handle-bar { width: 64rpx; height: 8rpx; border-radius: 4rpx; background: rgba(112, 94, 79, 0.18); }
|
||||
.bottom-padding { height: 48rpx; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user