优化多个页面样式及组件功能,优化课程、发现、训练、首页等核心页面样式

This commit is contained in:
future
2026-06-08 14:54:36 +08:00
parent 51bdf15613
commit 33d1140fbf
7 changed files with 222 additions and 87 deletions
+92 -9
View File
@@ -1,25 +1,37 @@
/**
* ============================================
* 健身房管理系统小程序 - 全局配色变量
* 主题:活力运动风格
* 主色调:深蓝专业 + 活力橙热情
* 主题:清新健康运动风格
* 主色调:浅蓝渐变 + 活力橙点缀
* 兼容暗色/浅色模式基础,保证可访问性
* ============================================
*/
:root {
/* ========== 主品牌色 ========== */
--primary-dark: #0B2B4B; /* 深蓝主色 - 用于头部导航栏、重要按钮、品牌标识,体现专业信赖感 */
--primary-deep: #1A4A6F; /* 中深蓝色 - 用于hover状态、次级按钮、图标点缀,增加层次感 */
--primary-light: #2C6288; /* 浅蓝色(预留)- 用于选中态或辅助背景,保持和谐渐变 */
/* ========== 主品牌色(清新浅蓝色系)========== */
--primary-dark: #0B2B4B; /* 深蓝主色 - 用于重要文字、品牌标识,体现专业信赖感 */
--primary-deep: #1A4A6F; /* 中深蓝色 - 用于hover状态、次级按钮、图标点缀,增加层次感 */
/* ========== 强调/行动色 ========== */
/* 主页主题浅蓝渐变色系 */
--primary-sky-100: #D6EEF8; /* 最浅蓝 - 渐变起始色,清新自然 */
--primary-sky-200: #E4F2FA; /* 浅蓝 - 渐变第二层 */
--primary-sky-300: #EEF6FB; /* 淡蓝 - 渐变第三层 */
--primary-sky-400: #F5FAFD; /* 微蓝 - 渐变第四层 */
--primary-sky-500: #FAFCFE; /* 极浅蓝 - 渐变第五层,接近白色 */
/* 光晕效果色 */
--glow-blue-1: rgba(160, 210, 235, 0.35); /* 蓝绿色光晕 */
--glow-blue-2: rgba(180, 220, 240, 0.3); /* 浅蓝色光晕 */
--glow-blue-3: rgba(170, 215, 238, 0.25); /* 浅蓝绿色光晕 */
/* ========== 强调/行动色(活力橙)========== */
--accent-orange: #FF6B35; /* 活力橙 - 主要CTA按钮、会员标识、高亮徽章、关键数据,刺激行动力 */
--accent-orange-light: #FF8C5A; /* 浅橙色 - hover轻量背景、渐变辅助,带来温暖运动感 */
--accent-orange-dark: #E55A2B; /* 深橙色 - 按压状态或重要警告,保持色彩体系完整 */
/* ========== 背景色系 ========== */
--bg-light: #F9FAFE; /* 全局浅灰蓝背景 - 柔和且提升深蓝/橙色的视觉舒适度 */
/* ========== 背景色系(主页主题)========== */
--bg-gradient-primary: linear-gradient(180deg, #D6EEF8 0%, #E4F2FA 15%, #EEF6FB 30%, #F5FAFD 50%, #FAFCFE 70%, #FFFFFF 100%); /* 主页主渐变背景 */
--bg-light: #F5FAFD; /* 全局浅蓝背景 - 柔和且提升蓝色/橙色的视觉舒适度 */
--bg-white: #FFFFFF; /* 纯白卡片背景 - 用于内容卡片、表单区域,提高可读性与层次感 */
--bg-gray: #F2F5F9; /* 浅灰辅助背景 - 分割区域或禁用态背景 */
@@ -42,6 +54,7 @@
/* ========== 渐变色 (提升活力感) ========== */
--gradient-orange: linear-gradient(135deg, #FF6B35 0%, #FF8C5A 100%); /* 橙色渐变 - 会员按钮、重要徽章 */
--gradient-blue: linear-gradient(135deg, #0B2B4B 0%, #1A4A6F 100%); /* 深蓝渐变 - 头部banner或特别卡片 */
--gradient-sky: linear-gradient(180deg, #D6EEF8 0%, #E4F2FA 15%, #EEF6FB 30%, #F5FAFD 50%, #FAFCFE 70%, #FFFFFF 100%); /* 主页天空渐变 - 全局背景 */
--gradient-subtle: linear-gradient(120deg, #F9FAFE 0%, #FFFFFF 100%); /* 微弱渐变 - 增加细节精致度 */
/* ========== 阴影层级 ========== */
@@ -49,6 +62,7 @@
--shadow-md: 0 12px 28px rgba(0, 0, 0, 0.08); /* 中等阴影 - 弹窗或下拉菜单 */
--shadow-lg: 0 20px 35px rgba(0, 0, 0, 0.12); /* 大阴影 - 模态框、悬浮元素 */
--shadow-orange-glow: 0 4px 12px rgba(255, 107, 53, 0.25); /* 橙色光晕 - 增强CTA吸引力 */
--shadow-sky-glow: 0 4px 12px rgba(160, 210, 235, 0.2); /* 蓝色光晕 - 主页效果增强 */
/* ========== 圆角规范 (柔和运动风) ========== */
--radius-sm: 12px; /* 小组件、标签圆角 */
@@ -95,18 +109,62 @@
}
/* ========== 辅助类 (方便开发直接复用) ========== */
/* 背景色类 */
.bg-primary {
background-color: var(--primary-dark);
}
.bg-accent {
background-color: var(--accent-orange);
}
.bg-gradient-sky {
background: var(--gradient-sky);
}
.bg-gradient-primary {
background: var(--bg-gradient-primary);
}
.bg-sky-100 {
background-color: var(--primary-sky-100);
}
.bg-sky-200 {
background-color: var(--primary-sky-200);
}
.bg-sky-300 {
background-color: var(--primary-sky-300);
}
.bg-sky-400 {
background-color: var(--primary-sky-400);
}
.bg-sky-500 {
background-color: var(--primary-sky-500);
}
/* 文字色类 */
.text-primary {
color: var(--primary-dark);
}
.text-accent {
color: var(--accent-orange);
}
.text-sky-100 {
color: var(--primary-sky-100);
}
.text-sky-200 {
color: var(--primary-sky-200);
}
/* 光晕效果类 */
.glow-blue-1 {
background: radial-gradient(circle, var(--glow-blue-1) 0%, transparent 70%);
}
.glow-blue-2 {
background: radial-gradient(circle, var(--glow-blue-2) 0%, transparent 70%);
}
.glow-blue-3 {
background: radial-gradient(circle, var(--glow-blue-3) 0%, transparent 70%);
}
/* 按钮类 */
.btn-orange {
background: var(--gradient-orange);
color: white;
@@ -121,10 +179,35 @@
transform: scale(0.97);
background: var(--accent-orange-dark);
}
/* 卡片类 */
.card-default {
background: var(--bg-white);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
border: 1px solid var(--border-light);
padding: var(--spacing-md);
}
.card-sky {
background: var(--gradient-sky);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
}
/* 阴影类 */
.shadow-sky {
box-shadow: var(--shadow-sky-glow);
}
/* 通用页面容器 */
.page-container-sky {
min-height: 100vh;
background: var(--gradient-sky);
}
/* 滚动容器 */
.scroll-container-sky {
height: 100vh;
width: 100%;
background: var(--gradient-sky);
}
@@ -4,6 +4,7 @@
overflow-x: hidden;
overflow-y: auto;
box-sizing: border-box;
background: var(--gradient-sky);
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
@@ -36,7 +37,7 @@
display: flex;
flex-direction: column;
align-items: stretch;
background-color: var(--bg-light);
background: var(--gradient-sky);
box-sizing: border-box;
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}
@@ -10,14 +10,27 @@
@change="onSwiperChange"
>
<swiper-item v-for="(banner, index) in banners" :key="index">
<view class="banner-content">
<image :src="banner.image" mode="aspectFill" class="banner-image" />
<view class="banner-content" @click="previewImage(index)">
<!-- 添加 lazy-load 属性实现懒加载 -->
<image
:src="banner.image"
mode="aspectFill"
class="banner-image"
lazy-load
:show-menu-by-longpress="false"
@load="onImageLoad(index)"
@error="onImageError(index)"
/>
<view class="banner-overlay"></view>
<view class="banner-text">
<text class="banner-title">{{ banner.title }}</text>
<text class="banner-subtitle">{{ banner.subtitle }}</text>
<text class="banner-desc">{{ banner.desc }}</text>
</view>
<!-- 可选添加加载占位符 -->
<view v-if="!imageLoaded[index]" class="image-placeholder">
<view class="loading-spinner"></view>
</view>
</view>
</swiper-item>
</swiper>
@@ -56,10 +69,35 @@ const banners = [
]
const currentIndex = ref(0)
// 记录每张图片的加载状态
const imageLoaded = ref(banners.map(() => false))
const onSwiperChange = (e) => {
currentIndex.value = e.detail.current
}
const previewImage = (index) => {
const urls = banners.map(banner => banner.image)
uni.previewImage({
urls: urls,
current: urls[index],
indicator: 'default',
loop: true
})
}
// 图片加载成功回调
const onImageLoad = (index) => {
imageLoaded.value[index] = true
console.log(`图片 ${index} 加载完成`)
}
// 图片加载失败回调
const onImageError = (index) => {
console.error(`图片 ${index} 加载失败`)
// 可选:设置默认占位图
// banners[index].image = '默认图片URL'
}
</script>
<style lang="scss" scoped>
@@ -86,58 +124,50 @@ const onSwiperChange = (e) => {
height: 100%;
}
/* 添加图片占位符样式 */
.image-placeholder {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid rgba(255, 255, 255, 0.3);
border-top: 4rpx solid #7AB5CC;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.banner-overlay {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 2; /* 确保遮罩层在占位符上面 */
}
.wave-transition {
position: absolute;
left: 0;
right: 0;
bottom: -2rpx;
height: 100rpx;
z-index: 3;
overflow: hidden;
}
.wt-layer {
position: absolute;
left: -10%;
width: 120%;
height: 100%;
}
.wt-layer-1 {
bottom: 0;
background: #C0DDE9;
border-radius: 45% 55% 0 0;
opacity: 0.9;
}
.wt-layer-2 {
bottom: -10rpx;
background: #D4EAF2;
border-radius: 55% 45% 0 0;
opacity: 0.85;
}
.wt-layer-3 {
bottom: -20rpx;
background: #E8F4F9;
border-radius: 40% 60% 0 0;
opacity: 0.9;
}
/* 其余样式保持不变 */
.banner-text {
position: absolute;
left: 36rpx;
top: 50%;
transform: translateY(-50%);
z-index: 2;
z-index: 3;
}
.banner-title {
+23 -14
View File
@@ -126,7 +126,7 @@ function goMyCourses() {
<style lang="scss" scoped>
.tab-page {
min-height: 100vh;
background-color: #f0f4f8;
background: $gradient-sky;
padding-bottom: 160rpx;
}
@@ -137,15 +137,15 @@ function goMyCourses() {
.tab-page__title {
display: block;
font-size: 40rpx;
font-weight: 700;
color: #1a202c;
font-weight: $font-weight-bold;
color: $text-dark;
}
.tab-page__subtitle {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #64748b;
color: $text-muted;
}
.tab-page__actions {
@@ -157,26 +157,34 @@ function goMyCourses() {
.tab-page__btn {
flex: 1;
height: 80rpx;
border-radius: 999rpx;
background: linear-gradient(135deg, #ff6b35 0%, #ff8c5a 100%);
border-radius: $radius-full;
background: $gradient-orange;
display: flex;
align-items: center;
justify-content: center;
box-shadow: $shadow-orange-glow;
transition: all 0.2s ease;
}
.tab-page__btn:active {
transform: scale(0.97);
background: $accent-orange-dark;
}
.tab-page__btn--ghost {
background: #fff;
border: 1px solid #e2e8f0;
background: $bg-white;
border: 1px solid $border-light;
box-shadow: $shadow-sm;
}
.tab-page__btn-text {
font-size: 28rpx;
font-weight: 600;
color: #fff;
font-weight: $font-weight-bold;
color: $text-inverse;
}
.tab-page__btn-text--ghost {
color: #1a4a6f;
color: $primary-deep;
}
.bottom-placeholder {
@@ -191,8 +199,9 @@ function goMyCourses() {
.skeleton-item {
margin-bottom: 24rpx;
padding: 20rpx;
background: #fff;
border-radius: 20rpx;
background: $bg-white;
border-radius: $radius-md;
box-shadow: $shadow-sm;
}
.skeleton-img {
@@ -201,7 +210,7 @@ function goMyCourses() {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
border-radius: 16rpx;
border-radius: $radius-sm;
}
.skeleton-text {
+16 -10
View File
@@ -48,7 +48,7 @@ function goPointsMall() {
<style lang="scss" scoped>
.tab-page {
min-height: 100vh;
background-color: #f0f4f8;
background: $gradient-sky;
padding-bottom: 160rpx;
}
@@ -59,15 +59,15 @@ function goPointsMall() {
.tab-page__title {
display: block;
font-size: 40rpx;
font-weight: 700;
color: #1a202c;
font-weight: $font-weight-bold;
color: $text-dark;
}
.tab-page__subtitle {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #64748b;
color: $text-muted;
}
.discover-links {
@@ -79,23 +79,29 @@ function goPointsMall() {
.discover-link {
padding: 24rpx 28rpx;
border-radius: 20rpx;
background: #fff;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
border-radius: $radius-md;
background: $bg-white;
box-shadow: $shadow-sm;
border: 1px solid $border-light;
transition: all 0.2s ease;
}
.discover-link:active {
transform: scale(0.98);
}
.discover-link__title {
display: block;
font-size: 28rpx;
font-weight: 600;
color: #1e2a3a;
font-weight: $font-weight-bold;
color: $text-dark;
}
.discover-link__desc {
display: block;
margin-top: 6rpx;
font-size: 22rpx;
color: #64748b;
color: $text-muted;
}
.bottom-placeholder {
+2 -2
View File
@@ -116,7 +116,7 @@ onMounted(() => {
left: 0;
width: 100%;
height: 100%;
z-index: 0;
z-index: 1;
pointer-events: none;
}
@@ -144,7 +144,7 @@ onMounted(() => {
z-index: 1;
height: 100vh;
width: 100%;
background: linear-gradient(180deg, #D6EEF8 0%, #E4F2FA 15%, #EEF6FB 30%, #F5FAFD 50%, #FAFCFE 70%, #FFFFFF 100%);
// background: linear-gradient(180deg, #D6EEF8 0%, #E4F2FA 15%, #EEF6FB 30%, #F5FAFD 50%, #FAFCFE 70%, #FFFFFF 100%);
}
/* 主内容区域 */
+16 -10
View File
@@ -53,7 +53,7 @@ function goCheckIn() {
<style lang="scss" scoped>
.tab-page {
min-height: 100vh;
background-color: #f0f4f8;
background: $gradient-sky;
padding-bottom: 160rpx;
}
@@ -64,15 +64,15 @@ function goCheckIn() {
.tab-page__title {
display: block;
font-size: 40rpx;
font-weight: 700;
color: #1a202c;
font-weight: $font-weight-bold;
color: $text-dark;
}
.tab-page__subtitle {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #64748b;
color: $text-muted;
}
.train-cards {
@@ -84,23 +84,29 @@ function goCheckIn() {
.train-card {
padding: 28rpx 32rpx;
border-radius: 24rpx;
background: #fff;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
border-radius: $radius-md;
background: $bg-white;
box-shadow: $shadow-sm;
border: 1px solid $border-light;
transition: all 0.2s ease;
}
.train-card:active {
transform: scale(0.98);
}
.train-card__title {
display: block;
font-size: 30rpx;
font-weight: 700;
color: #1e2a3a;
font-weight: $font-weight-bold;
color: $text-dark;
}
.train-card__desc {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #64748b;
color: $text-muted;
}
.bottom-placeholder {