perf: 完善新用户引导

This commit is contained in:
richarjiang
2026-04-06 15:50:22 +08:00
parent 66d47ec162
commit f8268cb6f6
15 changed files with 483 additions and 119 deletions

View File

@@ -37,8 +37,10 @@
<!-- Empty state -->
<view v-else-if="filteredSlots.length === 0" class="empty-wrap">
<view class="empty-icon-circle">
<text class="empty-icon-text">📅</text>
<view class="empty-illustration">
<view class="empty-circle outer" />
<view class="empty-circle inner" />
<view class="empty-dot" />
</view>
<text class="empty-text">当日暂无可约时段</text>
<text class="empty-sub">请选择其他日期或时段查看</text>
@@ -189,10 +191,10 @@ async function onBookTap(slot: TimeSlotWithBookingStatus) {
success: async (res) => {
if (res.confirm) {
try {
await userStore.login()
await userStore.fetchMemberships()
// Retry booking flow after login
onBookTap(slot)
const { isNewUser } = await userStore.loginWithSetup()
if (!isNewUser) {
onBookTap(slot)
}
} catch {
uni.showToast({ title: '登录失败', icon: 'none' })
}
@@ -413,34 +415,75 @@ onMounted(async () => {
flex-direction: column;
align-items: center;
justify-content: center;
padding: 140rpx 40rpx;
gap: 16rpx;
padding: 120rpx 40rpx 80rpx;
gap: 0;
}
.empty-icon-circle {
width: 140rpx;
height: 140rpx;
/* Zen-inspired geometric illustration */
.empty-illustration {
position: relative;
width: 200rpx;
height: 200rpx;
margin-bottom: 56rpx;
}
.empty-circle {
position: absolute;
border-radius: 50%;
background: $primary-border;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
&.outer {
width: 180rpx;
height: 180rpx;
border: 2rpx solid $primary-border;
animation: breathe 3s ease-in-out infinite;
}
&.inner {
width: 120rpx;
height: 120rpx;
background: linear-gradient(135deg, $primary-light 0%, $primary-color 50%, $primary-dark 100%);
opacity: 0.6;
animation: breathe 3s ease-in-out infinite 0.5s;
}
}
.empty-icon-text {
font-size: 56rpx;
.empty-dot {
position: absolute;
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: $primary-dark;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation: pulse 2s ease-in-out infinite;
}
.empty-text {
font-size: 30rpx;
color: #666;
font-size: 32rpx;
color: $primary-dark;
font-weight: 600;
letter-spacing: 2rpx;
margin-bottom: 16rpx;
}
.empty-sub {
font-size: 26rpx;
color: #bbb;
color: $primary-color;
letter-spacing: 1rpx;
}
@keyframes breathe {
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.6; }
50% { transform: translate(-50%, -50%) scale(1.05); opacity: 0.4; }
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
50% { opacity: 0.5; transform: translate(-50%, -50%) scale(0.8); }
}
/* ── Bottom spacer ─────────────────────────────────── */