- 添加日夜主题CSS变量定义,支持琥珀夜光和暖白琥珀两种风格 - 实现主题切换逻辑,根据时间自动切换白天(light)和夜间(dark)主题 - 在App.vue中集成主题初始化和token恢复功能 - 更新全局样式类应用主题颜色变量,包括卡片、文本、边框等 - 创建主题混入(mixin)供各页面使用,确保主题同步更新 - 实现导航栏和TabBar主题动态切换,提升用户体验 - 添加API服务层封装HaveADrink SDK,统一处理认证和请求 - 优化DrinkCard组件显示饮酒感受信息,丰富打卡记录展示 - 更新项目依赖配置,集成新的API客户端库
239 lines
5.1 KiB
Vue
239 lines
5.1 KiB
Vue
<template>
|
|
<view :class="themeClass" class="page-container onboarding">
|
|
<!-- 跳过按钮 -->
|
|
<view class="skip-bar">
|
|
<text class="btn-text" @click="goLogin">跳过</text>
|
|
</view>
|
|
|
|
<!-- 滑动引导 -->
|
|
<swiper
|
|
class="swiper"
|
|
:style="{ height: swiperHeight + 'px' }"
|
|
:current="currentSlide"
|
|
@change="onSlideChange"
|
|
circular
|
|
>
|
|
<swiper-item v-for="(slide, index) in slides" :key="index">
|
|
<view class="slide">
|
|
<!-- 图标区域 -->
|
|
<view class="slide-icon-area">
|
|
<view class="slide-icon">
|
|
<text class="slide-emoji">{{ slide.emoji }}</text>
|
|
</view>
|
|
<!-- 装饰光环 -->
|
|
<view class="slide-glow" :style="{ background: slide.glowColor }"></view>
|
|
</view>
|
|
|
|
<!-- 文案区域 -->
|
|
<view class="slide-text">
|
|
<text class="slide-title">{{ slide.title }}</text>
|
|
<text class="slide-desc">{{ slide.desc }}</text>
|
|
</view>
|
|
</view>
|
|
</swiper-item>
|
|
</swiper>
|
|
|
|
<!-- 底部控制区 -->
|
|
<view class="bottom-controls">
|
|
<!-- 指示器 -->
|
|
<view class="dots">
|
|
<view
|
|
v-for="(slide, index) in slides"
|
|
:key="index"
|
|
class="dot"
|
|
:class="{ 'dot-active': currentSlide === index }"
|
|
></view>
|
|
</view>
|
|
|
|
<!-- 按钮 -->
|
|
<view class="action-area">
|
|
<button
|
|
v-if="currentSlide < slides.length - 1"
|
|
class="btn-secondary"
|
|
@click="nextSlide"
|
|
>下一步</button>
|
|
<button
|
|
v-else
|
|
class="btn-cta"
|
|
@click="goLogin"
|
|
>开始体验</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import themeMixin from '../../common/theme-mixin'
|
|
|
|
export default {
|
|
mixins: [themeMixin],
|
|
data() {
|
|
return {
|
|
currentSlide: 0,
|
|
swiperHeight: 600,
|
|
slides: [
|
|
{
|
|
emoji: '🍻',
|
|
title: '记录每一杯',
|
|
desc: '轻松打卡,让每一杯酒都有迹可循。白酒、啤酒、红酒…你的饮酒档案从这里开始',
|
|
glowColor: 'radial-gradient(circle, rgba(232,168,56,0.2) 0%, transparent 70%)'
|
|
},
|
|
{
|
|
emoji: '📸',
|
|
title: '分享你的酒局',
|
|
desc: '自动生成精美卡片,配上酒言酒语,一键分享到微信群和朋友圈',
|
|
glowColor: 'radial-gradient(circle, rgba(139,133,184,0.2) 0%, transparent 70%)'
|
|
},
|
|
{
|
|
emoji: '🏆',
|
|
title: '解锁成就徽章',
|
|
desc: '从"初来乍到"到"年度酒神",每一个成就都记录着你的饮酒故事',
|
|
glowColor: 'radial-gradient(circle, rgba(94,198,160,0.2) 0%, transparent 70%)'
|
|
}
|
|
]
|
|
}
|
|
},
|
|
onLoad() {
|
|
// 计算swiper高度: 屏幕高度 - 顶部跳过按钮 - 底部控制区
|
|
const sys = uni.getSystemInfoSync()
|
|
this.swiperHeight = sys.windowHeight - 60 - 200
|
|
},
|
|
methods: {
|
|
onSlideChange(e) {
|
|
this.currentSlide = e.detail.current
|
|
},
|
|
nextSlide() {
|
|
if (this.currentSlide < this.slides.length - 1) {
|
|
this.currentSlide++
|
|
}
|
|
},
|
|
goLogin() {
|
|
uni.reLaunch({ url: '/pages/login/login' })
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.onboarding {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.skip-bar {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
padding: $sp-xl $sp-lg $sp-sm;
|
|
z-index: 10;
|
|
}
|
|
|
|
.swiper {
|
|
width: 100%;
|
|
}
|
|
|
|
.slide {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0 $sp-xl;
|
|
padding-bottom: 200rpx;
|
|
}
|
|
|
|
.slide-icon-area {
|
|
position: relative;
|
|
width: 360rpx;
|
|
height: 360rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: $sp-2xl;
|
|
}
|
|
|
|
.slide-icon {
|
|
width: 240rpx;
|
|
height: 240rpx;
|
|
background: $bg-card;
|
|
border-radius: $radius-xl;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: $shadow-md;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.slide-emoji {
|
|
font-size: 120rpx;
|
|
}
|
|
|
|
.slide-glow {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
z-index: 1;
|
|
filter: blur(40rpx);
|
|
}
|
|
|
|
.slide-text {
|
|
text-align: center;
|
|
max-width: 560rpx;
|
|
}
|
|
|
|
.slide-title {
|
|
display: block;
|
|
font-size: $fs-2xl;
|
|
font-weight: $fw-black;
|
|
color: $text-primary;
|
|
margin-bottom: $sp-lg;
|
|
letter-spacing: -1rpx;
|
|
}
|
|
|
|
.slide-desc {
|
|
display: block;
|
|
font-size: $fs-md;
|
|
color: $text-secondary;
|
|
line-height: $lh-loose;
|
|
}
|
|
|
|
.bottom-controls {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
padding: $sp-xl $sp-xl;
|
|
padding-bottom: calc(env(safe-area-inset-bottom) + $sp-xl);
|
|
background: linear-gradient(to top, $bg-base 60%, transparent);
|
|
}
|
|
|
|
.dots {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: $sp-sm;
|
|
margin-bottom: $sp-xl;
|
|
}
|
|
|
|
.dot {
|
|
width: 12rpx;
|
|
height: 12rpx;
|
|
border-radius: $radius-full;
|
|
background-color: $text-tertiary;
|
|
transition: all $duration-base $ease-out;
|
|
|
|
&.dot-active {
|
|
width: 40rpx;
|
|
background-color: $amber;
|
|
}
|
|
}
|
|
|
|
.action-area {
|
|
.btn-secondary, .btn-cta {
|
|
width: 100%;
|
|
}
|
|
}
|
|
</style>
|