优化会员信息模块及首页组件,清理冗余图片资源

This commit is contained in:
future
2026-06-07 22:41:55 +08:00
parent be7eabdbb1
commit 51bdf15613
111 changed files with 667 additions and 523 deletions
+44 -44
View File
@@ -5,7 +5,7 @@ export const memberCenterMock = {
name: '张小芳', name: '张小芳',
phone: '13812345678 已绑定微信', phone: '13812345678 已绑定微信',
memberLevel: '黄金会员', memberLevel: '黄金会员',
avatar: '/static/images/AvatarEditWrap.png' avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AvatarEditWrap.png'
}, },
stats: { stats: {
checkInCount: 128, checkInCount: 128,
@@ -75,7 +75,7 @@ export const userInfoMock = {
height: '165', height: '165',
weight: '63.5', weight: '63.5',
fitnessGoals: ['减脂', '塑形'], fitnessGoals: ['减脂', '塑形'],
avatar: '/static/images/AvatarEditWrap.png' avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AvatarEditWrap.png'
} }
export const fitnessGoalOptions = ['减脂', '塑形', '增肌', '提升耐力', '改善体态'] export const fitnessGoalOptions = ['减脂', '塑形', '增肌', '提升耐力', '改善体态']
@@ -102,7 +102,7 @@ export const memberCardMock = {
time: '2024-07-12 09:05', time: '2024-07-12 09:05',
value: '-1次', value: '-1次',
valueType: 'negative', valueType: 'negative',
icon: '/static/images/dumbbell.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/dumbbell.png',
iconTheme: 'orange' iconTheme: 'orange'
}, },
{ {
@@ -112,7 +112,7 @@ export const memberCardMock = {
time: '2024-07-11 18:30', time: '2024-07-11 18:30',
value: '-1天', value: '-1天',
valueType: 'negative', valueType: 'negative',
icon: '/static/images/mappin.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin.png',
iconTheme: 'green' iconTheme: 'green'
}, },
{ {
@@ -122,7 +122,7 @@ export const memberCardMock = {
time: '2024-07-01 10:00', time: '2024-07-01 10:00',
value: '+90天', value: '+90天',
valueType: 'positive', valueType: 'positive',
icon: '/static/images/pluscircle.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/pluscircle.png',
iconTheme: 'orange' iconTheme: 'orange'
} }
], ],
@@ -156,14 +156,14 @@ export const bodyTestMock = {
{ step: 3, title: '确认连接', desc: '点击下方按钮搜索并配对设备' } { step: 3, title: '确认连接', desc: '点击下方按钮搜索并配对设备' }
], ],
metricDefs: [ metricDefs: [
{ key: 'weight', label: '体重', unit: 'kg', icon: '/static/images/target.png' }, { key: 'weight', label: '体重', unit: 'kg', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/target.png' },
{ key: 'bmi', label: 'BMI', unit: '', icon: '/static/images/activity.png' }, { key: 'bmi', label: 'BMI', unit: '', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png' },
{ key: 'bodyFat', label: '体脂率', unit: '%', icon: '/static/images/trendingdown.png' }, { key: 'bodyFat', label: '体脂率', unit: '%', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/trendingdown.png' },
{ key: 'muscleMass', label: '肌肉量', unit: 'kg', icon: '/static/images/dumbbell.png' }, { key: 'muscleMass', label: '肌肉量', unit: 'kg', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/dumbbell.png' },
{ key: 'visceralFat', label: '内脏脂肪', unit: '级', icon: '/static/images/alertcircle.png' }, { key: 'visceralFat', label: '内脏脂肪', unit: '级', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/alertcircle.png' },
{ key: 'bmr', label: '基础代谢', unit: 'kcal', icon: '/static/images/clock.png' }, { key: 'bmr', label: '基础代谢', unit: 'kcal', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png' },
{ key: 'bodyWater', label: '体水分', unit: '%', icon: '/static/images/shield.png' }, { key: 'bodyWater', label: '体水分', unit: '%', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/shield.png' },
{ key: 'boneMass', label: '骨量', unit: 'kg', icon: '/static/images/user.png' } { key: 'boneMass', label: '骨量', unit: 'kg', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user.png' }
], ],
radarLabels: [ radarLabels: [
{ key: 'weight', label: '体重控制' }, { key: 'weight', label: '体重控制' },
@@ -185,7 +185,7 @@ export const bodyTestMock = {
title: '燃脂 HIIT 团课', title: '燃脂 HIIT 团课',
coach: '李明教练', coach: '李明教练',
schedule: '每周二、四 19:00', schedule: '每周二、四 19:00',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
tag: '减脂推荐' tag: '减脂推荐'
}, },
{ {
@@ -193,7 +193,7 @@ export const bodyTestMock = {
title: '核心力量塑形', title: '核心力量塑形',
coach: '王强教练', coach: '王强教练',
schedule: '每周一、三 18:30', schedule: '每周一、三 18:30',
banner: '/static/images/AC2Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
tag: '塑形推荐' tag: '塑形推荐'
} }
], ],
@@ -352,7 +352,7 @@ export const bookingMock = {
{ {
id: 1, id: 1,
title: '瑜伽基础班', title: '瑜伽基础班',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
status: 'booked', status: 'booked',
statusLabel: '已预约', statusLabel: '已预约',
schedule: '07月15日 09:00-10:00', schedule: '07月15日 09:00-10:00',
@@ -368,7 +368,7 @@ export const bookingMock = {
{ {
id: 2, id: 2,
title: '私教健身课', title: '私教健身课',
banner: '/static/images/AC2Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
status: 'pending', status: 'pending',
statusLabel: '待上课', statusLabel: '待上课',
schedule: '07月18日 14:00-15:00', schedule: '07月18日 14:00-15:00',
@@ -386,7 +386,7 @@ export const bookingMock = {
{ {
id: 3, id: 3,
title: '动感单车', title: '动感单车',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
status: 'completed', status: 'completed',
statusLabel: '已完成', statusLabel: '已完成',
schedule: '07月10日 19:00-20:00', schedule: '07月10日 19:00-20:00',
@@ -397,7 +397,7 @@ export const bookingMock = {
{ {
id: 4, id: 4,
title: '普拉提进阶', title: '普拉提进阶',
banner: '/static/images/AC2Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
status: 'cancelled', status: 'cancelled',
statusLabel: '已取消', statusLabel: '已取消',
schedule: '07月05日 10:00-11:00', schedule: '07月05日 10:00-11:00',
@@ -428,7 +428,7 @@ export const courseCatalogMock = {
title: '瑜伽基础班', title: '瑜伽基础班',
type: 'group', type: 'group',
coach: '李明教练', coach: '李明教练',
coachAvatar: '/static/images/user0.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user0.png',
date: '2024-07-15', date: '2024-07-15',
startTime: '09:00', startTime: '09:00',
endTime: '10:00', endTime: '10:00',
@@ -438,7 +438,7 @@ export const courseCatalogMock = {
price: '次卡扣 1 次', price: '次卡扣 1 次',
payType: 'session', payType: 'session',
period: 'morning', period: 'morning',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
intro: '适合零基础学员,重点提升柔韧性与呼吸控制。', intro: '适合零基础学员,重点提升柔韧性与呼吸控制。',
suitable: '久坐办公族、初学者、想改善体态者', suitable: '久坐办公族、初学者、想改善体态者',
coachBio: '国家一级瑜伽指导员,5年教学经验', coachBio: '国家一级瑜伽指导员,5年教学经验',
@@ -454,7 +454,7 @@ export const courseCatalogMock = {
title: 'HIIT 燃脂团课', title: 'HIIT 燃脂团课',
type: 'group', type: 'group',
coach: '赵敏教练', coach: '赵敏教练',
coachAvatar: '/static/images/user1.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user1.png',
date: '2024-07-15', date: '2024-07-15',
startTime: '19:00', startTime: '19:00',
endTime: '20:00', endTime: '20:00',
@@ -464,7 +464,7 @@ export const courseCatalogMock = {
price: '时长卡', price: '时长卡',
payType: 'duration', payType: 'duration',
period: 'evening', period: 'evening',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
intro: '高强度间歇训练,快速燃脂提升心肺。', intro: '高强度间歇训练,快速燃脂提升心肺。',
suitable: '有一定运动基础、目标减脂者', suitable: '有一定运动基础、目标减脂者',
coachBio: 'ACE 认证教练,擅长 HIIT 与动感单车', coachBio: 'ACE 认证教练,擅长 HIIT 与动感单车',
@@ -477,7 +477,7 @@ export const courseCatalogMock = {
title: '私教 · 力量训练', title: '私教 · 力量训练',
type: 'private', type: 'private',
coach: '王强教练', coach: '王强教练',
coachAvatar: '/static/images/user2.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user2.png',
date: '2024-07-16', date: '2024-07-16',
startTime: '14:00', startTime: '14:00',
endTime: '15:00', endTime: '15:00',
@@ -487,7 +487,7 @@ export const courseCatalogMock = {
price: '私教课时卡', price: '私教课时卡',
payType: 'private', payType: 'private',
period: 'afternoon', period: 'afternoon',
banner: '/static/images/AC2Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
intro: '一对一力量训练,定制训练计划。', intro: '一对一力量训练,定制训练计划。',
suitable: '增肌塑形、康复训练', suitable: '增肌塑形、康复训练',
coachBio: 'NSCA 认证私教,8年从业经验', coachBio: 'NSCA 认证私教,8年从业经验',
@@ -500,7 +500,7 @@ export const courseCatalogMock = {
title: '普拉提进阶', title: '普拉提进阶',
type: 'group', type: 'group',
coach: '李明教练', coach: '李明教练',
coachAvatar: '/static/images/user0.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user0.png',
date: '2024-07-17', date: '2024-07-17',
startTime: '10:30', startTime: '10:30',
endTime: '11:30', endTime: '11:30',
@@ -510,7 +510,7 @@ export const courseCatalogMock = {
price: '次卡扣 1 次', price: '次卡扣 1 次',
payType: 'session', payType: 'session',
period: 'morning', period: 'morning',
banner: '/static/images/AC2Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
intro: '核心稳定与体态矫正进阶课程。', intro: '核心稳定与体态矫正进阶课程。',
suitable: '有普拉提基础者', suitable: '有普拉提基础者',
coachBio: '国家一级瑜伽指导员', coachBio: '国家一级瑜伽指导员',
@@ -523,7 +523,7 @@ export const courseCatalogMock = {
title: '动感单车', title: '动感单车',
type: 'group', type: 'group',
coach: '赵敏教练', coach: '赵敏教练',
coachAvatar: '/static/images/user1.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user1.png',
date: '2024-07-18', date: '2024-07-18',
startTime: '18:30', startTime: '18:30',
endTime: '19:30', endTime: '19:30',
@@ -533,7 +533,7 @@ export const courseCatalogMock = {
price: '储值卡 ¥39', price: '储值卡 ¥39',
payType: 'stored', payType: 'stored',
period: 'evening', period: 'evening',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
intro: '音乐骑行,团队氛围燃脂。', intro: '音乐骑行,团队氛围燃脂。',
suitable: '所有级别,可调节阻力', suitable: '所有级别,可调节阻力',
coachBio: 'ACE 认证教练', coachBio: 'ACE 认证教练',
@@ -720,10 +720,10 @@ export const moduleMock = {
rule: '签到、训练、邀请好友、购课均可获得积分;积分可用于商城兑换。' rule: '签到、训练、邀请好友、购课均可获得积分;积分可用于商城兑换。'
}, },
pointsRewards: [ pointsRewards: [
{ id: 1, name: '团课体验券', cost: 500, stock: 12, icon: '/static/images/ticket.png' }, { id: 1, name: '团课体验券', cost: 500, stock: 12, icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/ticket.png' },
{ id: 2, name: '运动毛巾', cost: 800, stock: 5, icon: '/static/images/dumbbell.png' }, { id: 2, name: '运动毛巾', cost: 800, stock: 5, icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/dumbbell.png' },
{ id: 3, name: '私教体验30分钟', cost: 2000, stock: 3, icon: '/static/images/usercheck.png' }, { id: 3, name: '私教体验30分钟', cost: 2000, stock: 3, icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/usercheck.png' },
{ id: 4, name: '蛋白粉小样', cost: 350, stock: 20, icon: '/static/images/star.png' } { id: 4, name: '蛋白粉小样', cost: 350, stock: 20, icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/star.png' }
], ],
pointsHistory: [ pointsHistory: [
{ id: 1, type: 'earn', title: '团课签到', amount: 50, time: '2024-07-12 09:10', balance: 1250 }, { id: 1, type: 'earn', title: '团课签到', amount: 50, time: '2024-07-12 09:10', balance: 1250 },
@@ -739,11 +739,11 @@ export const moduleMock = {
'积分可用于兑换课程体验券及周边礼品' '积分可用于兑换课程体验券及周边礼品'
], ],
referralRecords: [ referralRecords: [
{ id: 1, name: '李**', avatar: '/static/images/user0.png', status: 'purchased', statusLabel: '已购课', time: '2024-07-05', reward: '+300积分', rewardStatus: '已发放' }, { id: 1, name: '李**', avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user0.png', status: 'purchased', statusLabel: '已购课', time: '2024-07-05', reward: '+300积分', rewardStatus: '已发放' },
{ id: 2, name: '王**', avatar: '/static/images/user1.png', status: 'registered', statusLabel: '已注册', time: '2024-06-20', reward: '+100积分', rewardStatus: '已发放' }, { id: 2, name: '王**', avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user1.png', status: 'registered', statusLabel: '已注册', time: '2024-06-20', reward: '+100积分', rewardStatus: '已发放' },
{ id: 3, name: '陈**', avatar: '/static/images/user2.png', status: 'invited', statusLabel: '已邀请', time: '2024-06-15', reward: '待注册', rewardStatus: '待发放' }, { id: 3, name: '陈**', avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user2.png', status: 'invited', statusLabel: '已邀请', time: '2024-06-15', reward: '待注册', rewardStatus: '待发放' },
{ id: 4, name: '赵**', avatar: '/static/images/user3.png', status: 'purchased', statusLabel: '已购课', time: '2024-06-01', reward: '+300积分', rewardStatus: '已发放' }, { id: 4, name: '赵**', avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user3.png', status: 'purchased', statusLabel: '已购课', time: '2024-06-01', reward: '+300积分', rewardStatus: '已发放' },
{ id: 5, name: '刘**', avatar: '/static/images/user0.png', status: 'registered', statusLabel: '已注册', time: '2024-05-28', reward: '+100积分', rewardStatus: '已发放' } { id: 5, name: '刘**', avatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user0.png', status: 'registered', statusLabel: '已注册', time: '2024-05-28', reward: '+100积分', rewardStatus: '已发放' }
], ],
referralRewardSummary: { referralRewardSummary: {
totalPoints: 800, totalPoints: 800,
@@ -763,7 +763,7 @@ export const moduleMock = {
id: 1, id: 1,
title: '瑜伽基础班', title: '瑜伽基础班',
coach: '李明教练', coach: '李明教练',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
progress: 6, progress: 6,
total: 12, total: 12,
schedule: '每周二、四 09:00', schedule: '每周二、四 09:00',
@@ -778,7 +778,7 @@ export const moduleMock = {
id: 3, id: 3,
title: '动感单车入门', title: '动感单车入门',
coach: '赵敏教练', coach: '赵敏教练',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
progress: 8, progress: 8,
total: 8, total: 8,
schedule: '已结课', schedule: '已结课',
@@ -791,7 +791,7 @@ export const moduleMock = {
private: { private: {
remaining: 7, remaining: 7,
coach: '王强教练', coach: '王强教练',
coachAvatar: '/static/images/user2.png', coachAvatar: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user2.png',
nextClass: '07月15日 14:00', nextClass: '07月15日 14:00',
bookings: [ bookings: [
{ id: 2, title: '私教 · 力量训练', time: '07月18日 14:00', status: '已预约', location: 'B区私教室' } { id: 2, title: '私教 · 力量训练', time: '07月18日 14:00', status: '已预约', location: 'B区私教室' }
@@ -804,7 +804,7 @@ export const moduleMock = {
{ {
id: 201, id: 201,
title: '居家核心训练', title: '居家核心训练',
cover: '/static/images/AC2Banner.png', cover: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC2Banner.png',
duration: '45分钟', duration: '45分钟',
progress: 60, progress: 60,
chapters: 6, chapters: 6,
@@ -814,7 +814,7 @@ export const moduleMock = {
{ {
id: 202, id: 202,
title: '直播 · 晨间拉伸', title: '直播 · 晨间拉伸',
cover: '/static/images/AC1Banner.png', cover: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
duration: '30分钟', duration: '30分钟',
progress: 0, progress: 0,
liveTime: '07月20日 07:00', liveTime: '07月20日 07:00',
@@ -825,7 +825,7 @@ export const moduleMock = {
{ {
id: 301, id: 301,
title: '28天减脂训练营', title: '28天减脂训练营',
banner: '/static/images/AC1Banner.png', banner: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AC1Banner.png',
progress: 3, progress: 3,
total: 10, total: 10,
coach: '李明教练', coach: '李明教练',
+1 -1
View File
@@ -275,7 +275,7 @@ export function renewMemberCard(store, addDays = 90) {
time: formatRecordTime(new Date()), time: formatRecordTime(new Date()),
value: `+${addDays}`, value: `+${addDays}`,
valueType: 'positive', valueType: 'positive',
icon: '/static/images/pluscircle.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/pluscircle.png',
iconTheme: 'orange' iconTheme: 'orange'
}) })
@@ -0,0 +1,33 @@
@font-face {
font-family: "iconfont"; /* Project id */
src: url('tabbar.ttf?t=1780818759010') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-home:before {
content: "\e666";
}
.icon-course:before {
content: "\e692";
}
.icon-train:before {
content: "\e8be";
}
.icon-discover:before {
content: "\e726";
}
.icon-profile:before {
content: "\e501";
}
@@ -0,0 +1,45 @@
<template>
<view class="skeleton" :style="{ padding: padding }">
<slot />
</view>
</template>
<script setup>
defineProps({
padding: {
type: String,
default: '20rpx'
}
})
</script>
<style lang="scss" scoped>
.skeleton {
background-color: #f5f5f5;
min-height: 100vh;
}
:deep(.skeleton-shimmer) {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
:deep(.skeleton-line) {
height: 32rpx;
border-radius: 16rpx;
}
:deep(.skeleton-block) {
border-radius: 16rpx;
}
:deep(.skeleton-circle) {
border-radius: 50%;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
</style>
+72 -86
View File
@@ -8,11 +8,13 @@
hover-class="tab-item--hover" hover-class="tab-item--hover"
@tap.stop="onTabTap(index)" @tap.stop="onTabTap(index)"
> >
<image <!-- 判断是否使用字体图标我的页面用字体其他用图片 -->
:src="currentActiveIndex === index ? tab.iconActive : tab.icon" <text
mode="aspectFit" v-if="tab.useFontIcon"
class="tab-icon" :class="['iconfont', tab.icon]"
/> class="tab-icon-font"
:style="{ fontSize: tab.fontSize}"
></text>
<text class="tab-label">{{ tab.label }}</text> <text class="tab-label">{{ tab.label }}</text>
</view> </view>
</view> </view>
@@ -34,32 +36,27 @@ const props = defineProps({
const emit = defineEmits(['update:active', 'tab-change']) const emit = defineEmits(['update:active', 'tab-change'])
// 当前激活的索引 - 默认从路由获取
const currentActiveIndex = ref(-1) const currentActiveIndex = ref(-1)
// 是否需要显示 TabBar
const shouldShowTabBar = ref(true) const shouldShowTabBar = ref(true)
// 不需要显示 TabBar 的页面路径列表(注意:不要带开头的 /)
const HIDE_TABBAR_PAGES = [ const HIDE_TABBAR_PAGES = [
'pages/memberInfo/courseList', // 预约课程 'pages/memberInfo/courseList',
'pages/memberInfo/courseDetail', // 课程详情 'pages/memberInfo/courseDetail',
'pages/memberInfo/booking', // 我的预约 'pages/memberInfo/booking',
'pages/memberInfo/bodyTestReport', // 体测报告 'pages/memberInfo/bodyTestReport',
'pages/groupCourse/list', // 团课列表 'pages/groupCourse/list',
'pages/groupCourse/detail', // 团课详情 'pages/groupCourse/detail',
'pages/searchCourse/searchCourse', // 搜索课程 'pages/searchCourse/searchCourse',
'pages/checkIn/checkIn', // 会员签到 'pages/checkIn/checkIn',
'pages/memberInfo/myCourses', // 我的课程 'pages/memberInfo/myCourses',
'pages/memberInfo/coupons', // 我的优惠券 'pages/memberInfo/coupons',
'pages/memberInfo/points', // 我的积分 'pages/memberInfo/points',
'pages/memberInfo/pointsMall', // 积分商城 'pages/memberInfo/pointsMall',
'pages/memberInfo/referral', // 邀请好友 'pages/memberInfo/referral',
'pages/memberInfo/userInfo', // 个人信息 'pages/memberInfo/userInfo',
'pages/memberInfo/memberCard', // 我的会员卡 'pages/memberInfo/memberCard',
] ]
// 从路由获取当前激活的 tab
function getActiveIndexFromRoute() { function getActiveIndexFromRoute() {
const routePath = getCurrentRoutePath() const routePath = getCurrentRoutePath()
const index = getTabIndexByRoute(routePath) const index = getTabIndexByRoute(routePath)
@@ -67,16 +64,12 @@ function getActiveIndexFromRoute() {
return index >= 0 ? index : 0 return index >= 0 ? index : 0
} }
// 同步激活状态(高优先级:路由 > props)
function syncActiveState() { function syncActiveState() {
// 优先从路由获取(最准确)
const routeIndex = getActiveIndexFromRoute() const routeIndex = getActiveIndexFromRoute()
if (routeIndex >= 0) { if (routeIndex >= 0) {
currentActiveIndex.value = routeIndex currentActiveIndex.value = routeIndex
return return
} }
// 其次使用 props
if (props.active >= 0) { if (props.active >= 0) {
currentActiveIndex.value = props.active currentActiveIndex.value = props.active
} else if (props.activeTab >= 0) { } else if (props.activeTab >= 0) {
@@ -86,23 +79,16 @@ function syncActiveState() {
} }
} }
// 检查当前页面是否需要隐藏 TabBar
function checkShouldShow() { function checkShouldShow() {
let routePath = getCurrentRoutePath() let routePath = getCurrentRoutePath()
// 标准化路径:去掉开头的 /
if (routePath.startsWith('/')) { if (routePath.startsWith('/')) {
routePath = routePath.slice(1) routePath = routePath.slice(1)
} }
// 去掉查询参数(?后面的内容)
if (routePath.includes('?')) { if (routePath.includes('?')) {
routePath = routePath.split('?')[0] routePath = routePath.split('?')[0]
} }
// 检查是否在隐藏列表中
const shouldHide = HIDE_TABBAR_PAGES.includes(routePath) const shouldHide = HIDE_TABBAR_PAGES.includes(routePath)
shouldShowTabBar.value = !shouldHide shouldShowTabBar.value = !shouldHide
console.log('=== TabBar 显示控制 ===') console.log('=== TabBar 显示控制 ===')
console.log('原始路径:', getCurrentRoutePath()) console.log('原始路径:', getCurrentRoutePath())
console.log('标准化路径:', routePath) console.log('标准化路径:', routePath)
@@ -110,25 +96,19 @@ function checkShouldShow() {
console.log('是否显示 TabBar:', shouldShowTabBar.value) console.log('是否显示 TabBar:', shouldShowTabBar.value)
} }
// 监听路由变化(页面切换时自动同步)
let routeWatcher = null let routeWatcher = null
let appRouteCallback = null let appRouteCallback = null
onMounted(() => { onMounted(() => {
// 初始同步
syncActiveState() syncActiveState()
checkShouldShow() checkShouldShow()
// #ifdef APP-PLUS // #ifdef APP-PLUS
// App 端:监听页面显示
routeWatcher = setInterval(() => { routeWatcher = setInterval(() => {
syncActiveState() syncActiveState()
checkShouldShow() checkShouldShow()
}, 300) }, 300)
// #endif // #endif
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
// 小程序端:监听路由变化
if (typeof uni.onAppRoute === 'function') { if (typeof uni.onAppRoute === 'function') {
appRouteCallback = () => { appRouteCallback = () => {
setTimeout(() => { setTimeout(() => {
@@ -143,11 +123,8 @@ onMounted(() => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
// #ifdef APP-PLUS // #ifdef APP-PLUS
if (routeWatcher) { if (routeWatcher) { clearInterval(routeWatcher) }
clearInterval(routeWatcher)
}
// #endif // #endif
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
if (appRouteCallback && typeof uni.offAppRoute === 'function') { if (appRouteCallback && typeof uni.offAppRoute === 'function') {
uni.offAppRoute(appRouteCallback) uni.offAppRoute(appRouteCallback)
@@ -155,44 +132,48 @@ onBeforeUnmount(() => {
// #endif // #endif
}) })
// 监听 props 变化
watch(() => props.active, () => { watch(() => props.active, () => {
const routeIndex = getActiveIndexFromRoute() const routeIndex = getActiveIndexFromRoute()
if (routeIndex !== currentActiveIndex.value) { if (routeIndex !== currentActiveIndex.value) { syncActiveState() }
syncActiveState()
}
}) })
// tabs 配置:只有"我的"用字体图标
const tabs = [ const tabs = [
{ {
path: PAGE.INDEX, path: PAGE.INDEX,
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/home.png', icon: 'icon-home',
iconActive: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/active/home.png', label: '首页',
label: '首页' useFontIcon: true,
fontSize:"36rpx"
}, },
{ {
path: PAGE.COURSE, path: PAGE.COURSE,
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/course.png', icon: 'icon-course',
iconActive: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/active/course.png', iconActive: '/static/tabBar/active/course.png',
label: '课程' label: '课程',
useFontIcon: true,
fontSize:"36rpx"
}, },
{ {
path: PAGE.TRAIN, path: PAGE.TRAIN,
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/train.png', icon: 'icon-train',
iconActive: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/active/train.png', label: '训练',
label: '训练' useFontIcon: true,
fontSize:"48rpx"
}, },
{ {
path: PAGE.DISCOVER, path: PAGE.DISCOVER,
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/discover.png', icon: 'icon-discover',
iconActive: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/active/discover.png', label: '发现',
label: '发现' useFontIcon: true,
fontSize:"48rpx"
}, },
{ {
path: PAGE.MEMBER, path: PAGE.MEMBER,
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/profile.png', icon: 'icon-profile',
iconActive: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/tabBar/active/profile.png', label: '我的',
label: '我的' useFontIcon: true,
fontSize:"36rpx"
} }
] ]
@@ -200,37 +181,22 @@ let isSwitching = false
function onTabTap(index) { function onTabTap(index) {
if (isSwitching) return if (isSwitching) return
const targetPath = TAB_ROUTES[index] const targetPath = TAB_ROUTES[index]
const currentPath = TAB_ROUTES[currentActiveIndex.value] const currentPath = TAB_ROUTES[currentActiveIndex.value]
if (targetPath === currentPath) return if (targetPath === currentPath) return
console.log('Tab 点击:', index, targetPath) console.log('Tab 点击:', index, targetPath)
// 1. 立即更新 UI 高亮
currentActiveIndex.value = index currentActiveIndex.value = index
// 2. 通知父组件
emit('update:active', index) emit('update:active', index)
emit('tab-change', index) emit('tab-change', index)
// 3. 显示 loading(可选)
let timer = setTimeout(() => { let timer = setTimeout(() => {
uni.showLoading({ title: '加载中...', mask: true }) uni.showLoading({ title: '加载中...', mask: true })
}, 50) }, 50)
isSwitching = true isSwitching = true
// 4. 执行跳转
uni.switchTab({ uni.switchTab({
url: targetPath, url: targetPath,
success: () => { success: () => { console.log('switchTab 成功:', targetPath) },
console.log('switchTab 成功:', targetPath)
},
fail: (err) => { fail: (err) => {
console.error('switchTab 失败:', err) console.error('switchTab 失败:', err)
// 降级
uni.reLaunch({ url: targetPath }) uni.reLaunch({ url: targetPath })
}, },
complete: () => { complete: () => {
@@ -238,7 +204,6 @@ function onTabTap(index) {
uni.hideLoading() uni.hideLoading()
setTimeout(() => { setTimeout(() => {
isSwitching = false isSwitching = false
// 跳转完成后,再次同步确保高亮正确
syncActiveState() syncActiveState()
checkShouldShow() checkShouldShow()
}, 100) }, 100)
@@ -248,19 +213,24 @@ function onTabTap(index) {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 引入字体图标 CSS(定义 @font-face
@import '/common/style/tabbar_icon/tabbar.css';
.tab-bar { .tab-bar {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
height: 120rpx; height: 120rpx;
background: #1A4A6F; background: rgba(200, 225, 238, 0.8);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
padding-bottom: constant(safe-area-inset-bottom); padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06); box-shadow: 0 -4rpx 24rpx rgba(120, 185, 215, 0.2);
border-radius: 32rpx 32rpx 0 0; border-radius: 32rpx 32rpx 0 0;
z-index: 999; z-index: 999;
} }
@@ -278,18 +248,34 @@ function onTabTap(index) {
transform: scale(0.95); transform: scale(0.95);
} }
// 图片图标样式
.tab-icon { .tab-icon {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
} }
// 字体图标样式
.tab-icon-font {
font-size: 44rpx;
line-height: 1;
}
// 字体图标颜色控制(根据选中状态)
.tab-item .iconfont {
color: gray; // 未选中颜色
}
.tab-item.active .iconfont {
color: #5A98B0; // 选中颜色
}
.tab-label { .tab-label {
font-size: 22rpx; font-size: 22rpx;
color: #94a3b8; color: #8AABBB;
} }
.tab-item.active .tab-label { .tab-item.active .tab-label {
color: #f97316; color: #5A98B0;
font-weight: 600; font-weight: 600;
} }
</style> </style>
@@ -0,0 +1,85 @@
<!-- components/GlobalLoading.vue -->
<template>
<view v-if="visible" class="global-loading">
<view class="loading-mask"></view>
<view class="loading-content">
<view class="loading-spinner"></view>
<text class="loading-text">{{ text }}</text>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const visible = ref(false)
const text = ref('加载中...')
// 显示
function show(loadingText = '加载中...') {
visible.value = true
text.value = loadingText
}
// 隐藏
function hide() {
visible.value = false
}
// 挂载到全局
if (typeof uni !== 'undefined') {
uni.$globalLoading = { show, hide }
}
</script>
<style lang="scss" scoped>
.global-loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.loading-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
}
.loading-content {
position: relative;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 16rpx;
padding: 32rpx 48rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
}
.loading-spinner {
width: 48rpx;
height: 48rpx;
border: 4rpx solid rgba(255, 255, 255, 0.3);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading-text {
color: #fff;
font-size: 24rpx;
}
</style>
@@ -1,7 +1,5 @@
<template> <template>
<!-- 轮播图容器 -->
<view class="banner-container"> <view class="banner-container">
<!-- 轮播图组件 -->
<swiper <swiper
class="banner-swiper" class="banner-swiper"
:circular="true" :circular="true"
@@ -11,15 +9,10 @@
:indicator-dots="false" :indicator-dots="false"
@change="onSwiperChange" @change="onSwiperChange"
> >
<!-- 轮播项 -->
<swiper-item v-for="(banner, index) in banners" :key="index"> <swiper-item v-for="(banner, index) in banners" :key="index">
<!-- 轮播内容 -->
<view class="banner-content"> <view class="banner-content">
<!-- 轮播图片 -->
<image :src="banner.image" mode="aspectFill" class="banner-image" /> <image :src="banner.image" mode="aspectFill" class="banner-image" />
<!-- 图片遮罩层 -->
<view class="banner-overlay"></view> <view class="banner-overlay"></view>
<!-- 轮播文字信息 -->
<view class="banner-text"> <view class="banner-text">
<text class="banner-title">{{ banner.title }}</text> <text class="banner-title">{{ banner.title }}</text>
<text class="banner-subtitle">{{ banner.subtitle }}</text> <text class="banner-subtitle">{{ banner.subtitle }}</text>
@@ -28,7 +21,6 @@
</view> </view>
</swiper-item> </swiper-item>
</swiper> </swiper>
<!-- 轮播指示器点 -->
<view class="banner-dots"> <view class="banner-dots">
<view <view
v-for="(_, index) in banners" v-for="(_, index) in banners"
@@ -42,7 +34,6 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
// 轮播图数据列表
const banners = [ const banners = [
{ {
image: 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=800&q=80', image: 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=800&q=80',
@@ -64,29 +55,25 @@ const banners = [
} }
] ]
// 当前轮播索引,用于控制指示器激活状态
const currentIndex = ref(0) const currentIndex = ref(0)
// 轮播图切换时的回调函数,更新当前索引
const onSwiperChange = (e) => { const onSwiperChange = (e) => {
currentIndex.value = e.detail.current currentIndex.value = e.detail.current
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 轮播图容器样式 */
.banner-container { .banner-container {
position: relative; position: relative;
z-index: 2;
width: 100%; width: 100%;
} }
/* 轮播图组件样式 */
.banner-swiper { .banner-swiper {
width: 100%; width: 100%;
height: 360rpx; height: 480rpx;
} }
/* 轮播内容容器样式 */
.banner-content { .banner-content {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -94,78 +81,108 @@ const onSwiperChange = (e) => {
overflow: hidden; overflow: hidden;
} }
/* 轮播图片样式 */
.banner-image { .banner-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
/* 图片遮罩层样式,添加渐变效果 */
.banner-overlay { .banner-overlay {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
background: linear-gradient(135deg, rgba(11, 43, 75, 0.85) 0%, rgba(26, 74, 111, 0.6) 100%);
} }
/* 轮播文字信息容器样式 */ .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 { .banner-text {
position: absolute; position: absolute;
left: 32rpx; left: 36rpx;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
z-index: 2; z-index: 2;
} }
/* 轮播标题样式 */
.banner-title { .banner-title {
display: block; display: block;
font-size: 48rpx; font-size: 48rpx;
font-weight: 800; font-weight: 800;
color: #ffffff; color: #ffffff;
margin-bottom: 8rpx; margin-bottom: 8rpx;
text-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.3); text-shadow: 0 4rpx 16rpx rgba(80, 150, 190, 0.4);
} }
/* 轮播副标题样式 */
.banner-subtitle { .banner-subtitle {
display: block; display: block;
font-size: 56rpx; font-size: 56rpx;
font-weight: 800; font-weight: 800;
color: #f97316; color: #E0F0FA;
margin-bottom: 16rpx; margin-bottom: 16rpx;
text-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.3); text-shadow: 0 4rpx 16rpx rgba(80, 150, 190, 0.4);
} }
/* 轮播描述文字样式 */
.banner-desc { .banner-desc {
display: block; display: block;
font-size: 26rpx; font-size: 26rpx;
color: rgba(255, 255, 255, 0.8); color: rgba(255, 255, 255, 0.85);
} }
/* 轮播指示器容器样式 */
.banner-dots { .banner-dots {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 16rpx; gap: 16rpx;
margin-top: 24rpx; margin-top: -100rpx;
position: relative;
z-index: 3;
} }
/* 轮播指示器点样式 */
.dot { .dot {
width: 48rpx; width: 48rpx;
height: 8rpx; height: 8rpx;
border-radius: 9999rpx; border-radius: 9999rpx;
background: #d1d5db; background: #D0E4EE;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
/* 轮播指示器激活状态样式 */
.dot.active { .dot.active {
width: 64rpx; width: 64rpx;
background: #f97316; background: linear-gradient(90deg, #7AB5CC, #9CCFDF);
} }
</style> </style>
@@ -1,21 +1,15 @@
<template> <template>
<!-- 快捷入口容器 -->
<view class="quick-entry"> <view class="quick-entry">
<!-- 快捷入口项 -->
<view <view
v-for="(item, index) in entries" v-for="(item, index) in entries"
:key="index" :key="index"
class="entry-item" class="entry-item"
@tap="QEClick(item.path)" @tap="QEClick(item.path)"
> >
<!-- 入口图标容器 -->
<view :class="['entry-icon', { accent: item.accent }]"> <view :class="['entry-icon', { accent: item.accent }]">
<!-- 入口图标图片 -->
<image :src="item.icon" mode="aspectFit" class="icon-img" /> <image :src="item.icon" mode="aspectFit" class="icon-img" />
</view> </view>
<!-- 入口标题 -->
<text class="entry-title">{{ item.title }}</text> <text class="entry-title">{{ item.title }}</text>
<!-- 入口描述 -->
<text class="entry-desc">{{ item.desc }}</text> <text class="entry-desc">{{ item.desc }}</text>
</view> </view>
</view> </view>
@@ -28,7 +22,6 @@ const QEClick = path => {
url:path url:path
}) })
} }
// 快捷入口数据列表
const entries = [ const entries = [
{ {
icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/course.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/icons/course.png',
@@ -66,18 +59,21 @@ const entries = [
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 快捷入口容器样式 */
.quick-entry { .quick-entry {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 32rpx 24rpx; padding: 32rpx 24rpx;
background: #ffffff; background: rgba(255, 255, 255, 0.55);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
margin: 24rpx; margin: 24rpx;
border-radius: 24rpx; border-radius: 28rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); box-shadow: 0 8rpx 32rpx rgba(120, 185, 215, 0.18);
border: 1rpx solid rgba(255, 255, 255, 0.7);
position: relative;
z-index: 3;
} }
/* 快捷入口项样式 */
.entry-item { .entry-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -85,40 +81,36 @@ const entries = [
flex: 1; flex: 1;
} }
/* 入口图标容器样式 */
.entry-icon { .entry-icon {
width: 104rpx; width: 104rpx;
height: 104rpx; height: 104rpx;
border-radius: 20rpx; border-radius: 24rpx;
background: #072A4E; background: linear-gradient(135deg, #7AB5CC 0%, #9CCFDF 100%);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-bottom: 16rpx; margin-bottom: 16rpx;
box-shadow: 0 6rpx 20rpx rgba(122, 181, 204, 0.35);
} }
/* 入口图标图片样式 */
.icon-img { .icon-img {
width: 52rpx; width: 52rpx;
height: 52rpx; height: 52rpx;
} }
/* 入口图标强调色样式(橙色背景) */
.entry-icon.accent { .entry-icon.accent {
background: #FC5A15; background: linear-gradient(135deg, #6BA8C0 0%, #8CC5D5 100%);
} }
/* 入口标题样式 */
.entry-title { .entry-title {
font-size: 26rpx; font-size: 26rpx;
font-weight: 600; font-weight: 600;
color: #1a202c; color: #2D4A5A;
margin-bottom: 4rpx; margin-bottom: 4rpx;
} }
/* 入口描述文字样式 */
.entry-desc { .entry-desc {
font-size: 22rpx; font-size: 22rpx;
color: #94a3b8; color: #8AABBB;
} }
</style> </style>
@@ -9,7 +9,7 @@
<view class="view-more"> <view class="view-more">
<text>查看更多</text> <text>查看更多</text>
<text class="arrow"> <text class="arrow">
<uni-icons type="right" size="20" color="#94a3b8"/> <uni-icons type="right" size="20" color="#8CA0B0"/>
</text> </text>
</view> </view>
</view> </view>
@@ -94,41 +94,21 @@ const getCourseTypeName = (type) => {
// 根据课程信息获取标签文本 // 根据课程信息获取标签文本
const getTag = (course) => { const getTag = (course) => {
// 满员标签 if (course.currentMembers >= course.maxMembers) return '已满员'
if (course.currentMembers >= course.maxMembers) { if (course.status === '2') return '已结束'
return '已满员' if (course.currentMembers / course.maxMembers >= 0.8) return '热门'
}
// 已结束的课程
if (course.status === '2') {
return '已结束'
}
// 高人气标签(参与人数超过最大人数的80%)
if (course.currentMembers / course.maxMembers >= 0.8) {
return '热门'
}
// 课程类型标签
return getCourseTypeName(course.courseType) return getCourseTypeName(course.courseType)
} }
// 根据课程信息获取标签样式类型 // 根据课程信息获取标签样式类型
const getTagType = (course) => { const getTagType = (course) => {
// 满员标签样式 if (course.currentMembers >= course.maxMembers) return 'full'
if (course.currentMembers >= course.maxMembers) { if (course.status === '2') return 'ended'
return 'full' if (course.currentMembers / course.maxMembers >= 0.8) return 'hot'
}
// 已结束标签样式
if (course.status === '2') {
return 'ended'
}
// 热门标签样式
if (course.currentMembers / course.maxMembers >= 0.8) {
return 'hot'
}
// 默认样式
return 'default' return 'default'
} }
// 计算课程时长(从startTime和endTime计算) // 计算课程时长
const calculateDuration = (startTime, endTime) => { const calculateDuration = (startTime, endTime) => {
if (!startTime || !endTime) return '60分钟' if (!startTime || !endTime) return '60分钟'
const start = new Date(startTime) const start = new Date(startTime)
@@ -137,9 +117,8 @@ const calculateDuration = (startTime, endTime) => {
return `${durationMinutes}分钟` return `${durationMinutes}分钟`
} }
// 获取课程难度(基于课程类型和描述简单判断) // 获取课程难度
const getCourseLevel = (course) => { const getCourseLevel = (course) => {
// 可以根据实际需求调整逻辑
if (course.courseType === '2') return '中级' if (course.courseType === '2') return '中级'
if (course.courseType === '3') return '高级' if (course.courseType === '3') return '高级'
if (course.courseType === '1') return '初级' if (course.courseType === '1') return '初级'
@@ -148,169 +127,61 @@ const getCourseLevel = (course) => {
// 处理图片URL // 处理图片URL
const getImageUrl = (coverImage) => { const getImageUrl = (coverImage) => {
if (!coverImage) { if (!coverImage) return 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=400&q=80'
return 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=400&q=80' if (coverImage.startsWith('http')) return coverImage
}
// 如果已经是完整URL直接返回,否则拼接基础路径
if (coverImage.startsWith('http')) {
return coverImage
}
// 这里需要根据您的实际图片基础路径配置
return `https://your-domain.com${coverImage}` return `https://your-domain.com${coverImage}`
} }
// 获取推荐课程(按最火排序,返回5条) // 获取推荐课程
const fetchRecommendCourses = async () => { const fetchRecommendCourses = async () => {
try { try {
const res = await getGroupCoursePage({ const res = await getGroupCoursePage({
page: 0, page: 0, size: 5, sort: 'current_members', order: 'desc'
size: 5,
sort: 'current_members', // 按参与人数排序
order: 'desc' // 降序,即最火的在前
}, { cache: true, cacheTime: 5 * 60 * 1000 }) }, { cache: true, cacheTime: 5 * 60 * 1000 })
if (res && res.content && Array.isArray(res.content)) { if (res && res.content && Array.isArray(res.content)) {
// 将后端数据转换为组件所需格式
courses.value = res.content.map(course => ({ courses.value = res.content.map(course => ({
id: course.id, id: course.id, image: getImageUrl(course.coverImage), tag: getTag(course),
image: getImageUrl(course.coverImage), tagType: getTagType(course), name: course.courseName || '未知课程',
tag: getTag(course),
tagType: getTagType(course),
name: course.courseName || '未知课程',
duration: calculateDuration(course.startTime, course.endTime), duration: calculateDuration(course.startTime, course.endTime),
level: getCourseLevel(course), level: getCourseLevel(course), participants: course.currentMembers || 0, rawData: course
participants: course.currentMembers || 0,
// 保存原始数据供点击事件使用
rawData: course
})) }))
} else { } else { useFallbackData() }
// 如果没有数据,使用提供的示例数据作为fallback } catch (err) { useFallbackData() }
useFallbackData()
}
} catch (err) {
// console.error('获取推荐课程失败:', err)
// 使用提供的示例数据作为fallback
useFallbackData()
}
} }
// 使用提供的响应数据作为默认数据
const useFallbackData = () => { const useFallbackData = () => {
const fallbackContent = [ const fallbackContent = [
{ { id: "3", courseName: "燃脂搏击", courseType: "2", startTime: "2026-06-10T18:30:00", endTime: "2026-06-10T19:30:00", maxMembers: 20, currentMembers: 20, status: "0", coverImage: "/images/kickboxing.jpg", description: "高强度间歇训练" },
id: "3", { id: "2", courseName: "清晨流瑜伽", courseType: "1", startTime: "2026-06-12T09:00:00", endTime: "2026-06-12T10:30:00", maxMembers: 15, currentMembers: 5, status: "0", coverImage: "/images/yoga_flow.jpg", description: "流畅体式" },
courseName: "燃脂搏击", { id: "4", courseName: "哈他瑜伽", courseType: "1", startTime: "2026-06-01T15:20:00", endTime: "2026-06-01T16:50:00", maxMembers: 12, currentMembers: 3, status: "0", coverImage: "/images/hatha_yoga.jpg", description: "基础瑜伽" },
courseType: "2", { id: "6", courseName: "蜜桃臀塑造", courseType: "3", startTime: "2026-05-30T19:00:00", endTime: "2026-05-30T20:00:00", maxMembers: 10, currentMembers: 8, status: "2", coverImage: "/images/glute.jpg", description: "臀部训练" },
startTime: "2026-06-10T18:30:00", { id: "7", courseName: "午间冥想放松", courseType: "1", startTime: "2026-05-31T12:00:00", endTime: "2026-05-31T13:00:00", maxMembers: 15, currentMembers: 6, status: "2", coverImage: "/images/meditation_noon.jpg", description: "冥想" }
endTime: "2026-06-10T19:30:00",
maxMembers: 20,
currentMembers: 20,
status: "0",
coverImage: "/images/kickboxing.jpg",
description: "高强度间歇训练,配合音乐快速燃脂,释放压力。名额已满,无法预约。"
},
{
id: "2",
courseName: "清晨流瑜伽",
courseType: "1",
startTime: "2026-06-12T09:00:00",
endTime: "2026-06-12T10:30:00",
maxMembers: 15,
currentMembers: 5,
status: "0",
coverImage: "/images/yoga_flow.jpg",
description: "适合有一定基础的学员,通过流畅的体式连接呼吸,唤醒身体能量。"
},
{
id: "4",
courseName: "哈他瑜伽",
courseType: "1",
startTime: "2026-06-01T15:20:00",
endTime: "2026-06-01T16:50:00",
maxMembers: 12,
currentMembers: 3,
status: "0",
coverImage: "/images/hatha_yoga.jpg",
description: "基础哈他瑜伽,适合所有级别。距开始不足30分钟,已停止预约。"
},
{
id: "6",
courseName: "蜜桃臀塑造",
courseType: "3",
startTime: "2026-05-30T19:00:00",
endTime: "2026-05-30T20:00:00",
maxMembers: 10,
currentMembers: 8,
status: "2",
coverImage: "/images/glute.jpg",
description: "针对性训练臀部肌肉群,课程已于5月30日结束,无法预约。"
},
{
id: "7",
courseName: "午间冥想放松",
courseType: "1",
startTime: "2026-05-31T12:00:00",
endTime: "2026-05-31T13:00:00",
maxMembers: 15,
currentMembers: 6,
status: "2",
coverImage: "/images/meditation_noon.jpg",
description: "午间冥想课程,已于5月31日结束。"
}
] ]
courses.value = fallbackContent.map(course => ({ courses.value = fallbackContent.map(course => ({
id: course.id, id: course.id, image: getImageUrl(course.coverImage), tag: getTag(course),
image: getImageUrl(course.coverImage), tagType: getTagType(course), name: course.courseName || '未知课程',
tag: getTag(course),
tagType: getTagType(course),
name: course.courseName || '未知课程',
duration: calculateDuration(course.startTime, course.endTime), duration: calculateDuration(course.startTime, course.endTime),
level: getCourseLevel(course), level: getCourseLevel(course), participants: course.currentMembers || 0, rawData: course
participants: course.currentMembers || 0,
rawData: course
})) }))
} }
// 处理参与课程点击
const handleJoinCourse = (course) => { const handleJoinCourse = (course) => {
// 根据课程状态判断是否可以参与 if (course.rawData.status === '2') { uni.showToast({ title: '课程已结束', icon: 'none' }); return }
if (course.rawData.status === '2') { if (course.rawData.currentMembers >= course.rawData.maxMembers) { uni.showToast({ title: '课程已满员', icon: 'none' }); return }
uni.showToast({ uni.navigateTo({ url: `/pages/course/detail?id=${course.id}` })
title: '课程已结束',
icon: 'none'
})
return
}
if (course.rawData.currentMembers >= course.rawData.maxMembers) {
uni.showToast({
title: '课程已满员',
icon: 'none'
})
return
}
// 跳转到课程详情页
uni.navigateTo({
url: `/pages/course/detail?id=${course.id}`
})
} }
// 组件挂载时获取数据 onMounted(() => { fetchRecommendCourses() })
onMounted(() => {
fetchRecommendCourses()
})
</script> </script>
<style lang="scss"> <style lang="scss">
/* 推荐课程容器样式 */
.recommend-courses { .recommend-courses {
padding: 0 24rpx; padding: 0 24rpx;
margin-bottom: 32rpx; margin-bottom: 32rpx;
position: relative;
z-index: 1;
} }
/* 区域标题栏样式 */
.section-header { .section-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -318,50 +189,46 @@ onMounted(() => {
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
/* 区域标题样式 */
.section-title { .section-title {
font-size: 34rpx; font-size: 34rpx;
font-weight: 700; font-weight: 700;
color: #1a202c; color: #2D4A5A;
} }
/* 查看更多按钮样式 */
.view-more { .view-more {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4rpx; gap: 4rpx;
font-size: 26rpx; font-size: 26rpx;
color: #94a3b8; color: #8AABBB;
} }
/* 箭头图标样式 */
.arrow { .arrow {
font-size: 32rpx; font-size: 32rpx;
} }
/* 课程横向滚动容器样式 */
.courses-scroll { .courses-scroll {
white-space: nowrap; white-space: nowrap;
} }
/* 课程列表样式 */
.courses-list { .courses-list {
display: inline-flex; display: inline-flex;
gap: 48rpx; gap: 48rpx;
} }
/* 课程卡片样式 */
.course-card { .course-card {
width: 320rpx; width: 320rpx;
background: #ffffff; background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-radius: 24rpx; border-radius: 24rpx;
overflow: hidden; overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); box-shadow: 0 8rpx 28rpx rgba(120, 185, 215, 0.18);
border: 1rpx solid rgba(255, 255, 255, 0.6);
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
} }
/* 课程图片区域样式 */
.course-image { .course-image {
height: 280rpx; height: 280rpx;
position: relative; position: relative;
@@ -371,7 +238,6 @@ onMounted(() => {
padding: 20rpx; padding: 20rpx;
} }
/* 课程封面图片样式 */
.img { .img {
position: absolute; position: absolute;
left: 0; left: 0;
@@ -380,17 +246,15 @@ onMounted(() => {
height: 100%; height: 100%;
} }
/* 图片渐变遮罩样式 */
.course-overlay { .course-overlay {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%); background: linear-gradient(to top, rgba(45, 74, 90, 0.7) 0%, transparent 60%);
} }
/* 课程标签样式 */
.course-tag { .course-tag {
position: absolute; position: absolute;
top: 16rpx; top: 16rpx;
@@ -400,47 +264,33 @@ onMounted(() => {
font-size: 20rpx; font-size: 20rpx;
font-weight: 600; font-weight: 600;
color: #ffffff; color: #ffffff;
background: #f97316; background: linear-gradient(135deg, #7AB5CC, #9CCFDF);
z-index: 2; z-index: 2;
/* 热门标签 */
&.hot { &.hot {
background: #ef4444; background: linear-gradient(135deg, #6BA8C0, #8CC5D5);
} }
/* 新课标签 */
&.new { &.new {
background: #10b981; background: linear-gradient(135deg, #6DB5C8, #90CEDD);
} }
/* 免费标签 */
&.free { &.free {
background: #3b82f6; background: linear-gradient(135deg, #7AB5CC, #9CCFDF);
} }
/* 满员标签 */
&.full { &.full {
background: #64748b; background: linear-gradient(135deg, #A0B8C8, #B8CCD8);
} }
/* 已结束标签 */
&.ended { &.ended {
background: #94a3b8; background: linear-gradient(135deg, #B0C0CC, #C4D2DC);
} }
/* 默认标签 */
&.default { &.default {
background: #f97316; background: linear-gradient(135deg, #7AB5CC, #9CCFDF);
} }
} }
/* 课程信息区域样式 */
.course-info { .course-info {
position: relative; position: relative;
z-index: 2; z-index: 2;
} }
/* 课程名称样式 */
.course-name { .course-name {
display: block; display: block;
font-size: 28rpx; font-size: 28rpx;
@@ -449,14 +299,12 @@ onMounted(() => {
margin-bottom: 8rpx; margin-bottom: 8rpx;
} }
/* 课程元信息容器样式 */
.course-meta { .course-meta {
display: flex; display: flex;
gap: 16rpx; gap: 16rpx;
align-items: center; align-items: center;
} }
/* 课程元信息项样式 */
.meta-item { .meta-item {
display: flex; display: flex;
align-items: end; align-items: end;
@@ -465,7 +313,6 @@ onMounted(() => {
color: rgba(255, 255, 255, 0.8); color: rgba(255, 255, 255, 0.8);
} }
/* 元信息图标样式 */
.meta-icon { .meta-icon {
font-size: 20rpx; font-size: 20rpx;
image{ image{
@@ -476,7 +323,6 @@ onMounted(() => {
} }
} }
/* 课程底部区域样式 */
.course-footer { .course-footer {
padding: 16rpx 10rpx; padding: 16rpx 10rpx;
display: flex; display: flex;
@@ -484,16 +330,14 @@ onMounted(() => {
align-items: center; align-items: center;
} }
/* 参与人数信息样式 */
.participants { .participants {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 6rpx; gap: 6rpx;
font-size: 22rpx; font-size: 22rpx;
color: #94a3b8; color: #8AABBB;
} }
/* 火热图标样式 */
.fire-icon { .fire-icon {
font-size: 24rpx; font-size: 24rpx;
image{ image{
@@ -504,14 +348,14 @@ onMounted(() => {
} }
} }
/* 去参与按钮样式 */
.join-btn { .join-btn {
padding: 12rpx 28rpx; padding: 12rpx 28rpx;
background: transparent; background: linear-gradient(135deg, #7AB5CC 0%, #9CCFDF 100%);
border: 2rpx solid #f97316; border: none;
border-radius: 9999rpx; border-radius: 9999rpx;
font-size: 22rpx; font-size: 22rpx;
font-weight: 600; font-weight: 600;
color: #f97316; color: #ffffff;
box-shadow: 0 6rpx 16rpx rgba(122, 181, 204, 0.35);
} }
</style> </style>
@@ -9,7 +9,7 @@
<view class="view-more"> <view class="view-more">
<text>查看更多</text> <text>查看更多</text>
<text class="arrow"> <text class="arrow">
<uni-icons type="right" size="20" color="#94a3b8"></uni-icons> <uni-icons type="right" size="20" color="#8CA0B0"></uni-icons>
</text> </text>
</view> </view>
</view> </view>
@@ -77,12 +77,12 @@ const recommends = [
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 今日推荐容器样式 */
.today-recommend { .today-recommend {
padding: 0 24rpx; padding: 0 24rpx;
position: relative;
z-index: 1;
} }
/* 区域标题栏样式 */
.section-header { .section-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -90,45 +90,42 @@ const recommends = [
margin-bottom: 24rpx; margin-bottom: 24rpx;
} }
/* 区域标题样式 */
.section-title { .section-title {
font-size: 34rpx; font-size: 34rpx;
font-weight: 700; font-weight: 700;
color: #1a202c; color: #2D4A5A;
} }
/* 查看更多按钮样式 */
.view-more { .view-more {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4rpx; gap: 4rpx;
font-size: 26rpx; font-size: 26rpx;
color: #94a3b8; color: #8AABBB;
} }
/* 箭头图标样式 */
.arrow { .arrow {
font-size: 32rpx; font-size: 32rpx;
} }
/* 推荐列表样式 */
.recommend-list { .recommend-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 24rpx; gap: 24rpx;
} }
/* 推荐项卡片样式 */
.recommend-item { .recommend-item {
display: flex; display: flex;
gap: 24rpx; gap: 24rpx;
background: #ffffff; background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-radius: 24rpx; border-radius: 24rpx;
padding: 20rpx; padding: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); box-shadow: 0 8rpx 28rpx rgba(120, 185, 215, 0.18);
border: 1rpx solid rgba(255, 255, 255, 0.6);
} }
/* 推荐项图片样式 */
.item-image { .item-image {
width: 200rpx; width: 200rpx;
height: 160rpx; height: 160rpx;
@@ -136,7 +133,6 @@ const recommends = [
flex-shrink: 0; flex-shrink: 0;
} }
/* 推荐项内容区域样式 */
.item-content { .item-content {
flex: 1; flex: 1;
display: flex; display: flex;
@@ -145,40 +141,35 @@ const recommends = [
min-width: 0; min-width: 0;
} }
/* 推荐项标题样式 */
.item-title { .item-title {
font-size: 30rpx; font-size: 30rpx;
font-weight: 600; font-weight: 600;
color: #1a202c; color: #2D4A5A;
margin-bottom: 12rpx; margin-bottom: 12rpx;
} }
/* 推荐项标签列表样式 */
.item-tags { .item-tags {
display: flex; display: flex;
gap: 12rpx; gap: 12rpx;
margin-bottom: 12rpx; margin-bottom: 12rpx;
} }
/* 推荐项标签样式 */
.tag { .tag {
padding: 6rpx 16rpx; padding: 6rpx 16rpx;
background: #f1f5f9; background: rgba(122, 181, 204, 0.12);
border-radius: 8rpx; border-radius: 8rpx;
font-size: 22rpx; font-size: 22rpx;
color: #64748b; color: #6BA8C0;
} }
/* 推荐项描述文字样式 */
.item-desc { .item-desc {
font-size: 24rpx; font-size: 24rpx;
color: #94a3b8; color: #8AABBB;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
/* 推荐项操作区域样式 */
.item-action { .item-action {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -188,15 +179,13 @@ const recommends = [
flex-shrink: 0; flex-shrink: 0;
} }
/* 开始训练按钮样式 */
.start-btn { .start-btn {
padding: 16rpx 28rpx; padding: 16rpx 28rpx;
background: linear-gradient(135deg, #f97316 0%, #fb923c 100%); background: linear-gradient(135deg, #7AB5CC 0%, #9CCFDF 100%);
border-radius: 9999rpx; border-radius: 9999rpx;
box-shadow: 0 4rpx 16rpx rgba(249, 115, 22, 0.4); box-shadow: 0 6rpx 20rpx rgba(122, 181, 204, 0.4);
} }
/* 开始训练按钮文字样式 */
.start-btn-text { .start-btn-text {
font-size: 24rpx; font-size: 24rpx;
font-weight: 600; font-weight: 600;
@@ -204,10 +193,9 @@ const recommends = [
white-space: nowrap; white-space: nowrap;
} }
/* 参与人数文字样式 */
.participants { .participants {
font-size: 22rpx; font-size: 22rpx;
color: #94a3b8; color: #8AABBB;
white-space: nowrap; white-space: nowrap;
} }
</style> </style>
@@ -13,7 +13,7 @@
<text class="body-report-section__history-link">历史记录</text> <text class="body-report-section__history-link">历史记录</text>
<image <image
class="body-report-section__link-arrow" class="body-report-section__link-arrow"
src="/static/images/chevronright3.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright3.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -34,7 +34,7 @@
> >
<image <image
class="body-report-section__view-icon" class="body-report-section__view-icon"
src="/static/images/filetext.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/filetext.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="body-report-section__view-report">查看报告</text> <text class="body-report-section__view-report">查看报告</text>
@@ -77,7 +77,7 @@
<view class="body-report-section__goal"> <view class="body-report-section__goal">
<image <image
class="body-report-section__goal-icon" class="body-report-section__goal-icon"
src="/static/images/target.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/target.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="body-report-section__goal-text"> <text class="body-report-section__goal-text">
@@ -87,7 +87,7 @@
<view class="body-report-section__change"> <view class="body-report-section__change">
<image <image
class="body-report-section__change-icon" class="body-report-section__change-icon"
src="/static/images/trendingdown.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/trendingdown.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="body-report-section__metric-value-2"> <text class="body-report-section__metric-value-2">
@@ -13,7 +13,7 @@
<text class="booking-section__view-all">预约记录</text> <text class="booking-section__view-all">预约记录</text>
<image <image
class="booking-section__link-arrow" class="booking-section__link-arrow"
src="/static/images/chevronright4.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright4.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -41,13 +41,13 @@
<view class="booking-section__meta-inner"> <view class="booking-section__meta-inner">
<image <image
class="booking-section__icon-coach" class="booking-section__icon-coach"
src="/static/images/user2.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user2.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="booking-section__coach">教练{{ item.coach }}</text> <text class="booking-section__coach">教练{{ item.coach }}</text>
<image <image
class="booking-section__icon-location" class="booking-section__icon-location"
src="/static/images/mappin1.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin1.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="booking-section__text">{{ item.location }}</text> <text class="booking-section__text">{{ item.location }}</text>
@@ -13,7 +13,7 @@
<text class="checkin-section__view-all">查看全部</text> <text class="checkin-section__view-all">查看全部</text>
<image <image
class="checkin-section__link-arrow" class="checkin-section__link-arrow"
src="/static/images/chevronright2.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright2.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -13,7 +13,7 @@
<text class="coupon-section__view-all">更多详情</text> <text class="coupon-section__view-all">更多详情</text>
<image <image
class="coupon-section__link-arrow" class="coupon-section__link-arrow"
src="/static/images/chevronright5.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright5.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -6,12 +6,12 @@
<view class="profile-header__nav-left"> <view class="profile-header__nav-left">
<image <image
class="profile-header__icon-bell" class="profile-header__icon-bell"
src="/static/images/bell.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/bell.png"
mode="aspectFit" mode="aspectFit"
/> />
<image <image
class="profile-header__icon-settings" class="profile-header__icon-settings"
src="/static/images/settings.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/settings.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -37,7 +37,7 @@
<view class="profile-header__avatar-badge"> <view class="profile-header__avatar-badge">
<image <image
class="profile-header__avatar-badge-icon" class="profile-header__avatar-badge-icon"
src="/static/images/camera.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/camera.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -49,7 +49,7 @@
<view class="profile-header__badge"> <view class="profile-header__badge">
<image <image
class="profile-header__badge-icon" class="profile-header__badge-icon"
src="/static/images/crown0.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/crown0.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="profile-header__level">{{ userInfo.memberLevel }}</text> <text class="profile-header__level">{{ userInfo.memberLevel }}</text>
@@ -100,7 +100,7 @@ export default {
emits: ['user-info'], emits: ['user-info'],
computed: { computed: {
displayAvatar() { displayAvatar() {
return this.userInfo.avatar || '/static/images/AvatarEditWrap.png' return this.userInfo.avatar || 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AvatarEditWrap.png'
} }
}, },
data() { data() {
@@ -8,7 +8,7 @@
> >
<image <image
class="logout-section__icon" class="logout-section__icon"
src="/static/images/logout.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/logout.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="logout-section__text">退出登录</text> <text class="logout-section__text">退出登录</text>
@@ -17,7 +17,7 @@
> >
查看全部 查看全部
</text> </text>
<image class="member-card-section__link-arrow" src="/static/images/chevronright12.png" mode="aspectFit" /> <image class="member-card-section__link-arrow" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright12.png" mode="aspectFit" />
</view> </view>
</view> </view>
</view> </view>
@@ -46,7 +46,7 @@
class="member-card-preview__icon-stroke" class="member-card-preview__icon-stroke"
></view> ></view>
</view> </view>
<image class="member-card-preview__icon-line" src="/static/images/Line_2_468.png" mode="aspectFill" /> <image class="member-card-preview__icon-line" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Line_2_468.png" mode="aspectFill" />
</view> </view>
<text <text
class="member-card-preview__name" class="member-card-preview__name"
@@ -101,7 +101,7 @@
<view class="member-card-tip"> <view class="member-card-tip">
<view class="member-card-tip__inner"> <view class="member-card-tip__inner">
<view class="member-card-tip__content"> <view class="member-card-tip__content">
<image class="member-card-tip__icon" src="/static/images/clock1.png" mode="aspectFit" /> <image class="member-card-tip__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock1.png" mode="aspectFit" />
<text <text
class="member-card-tip__text" class="member-card-tip__text"
> >
@@ -17,12 +17,12 @@
<view v-if="item.key === 'booking'" class="quick-actions__icon"> <view v-if="item.key === 'booking'" class="quick-actions__icon">
<image <image
class="quick-actions__icon-part" class="quick-actions__icon-part"
src="/static/images/Vector_2_490.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Vector_2_490.png"
mode="aspectFit" mode="aspectFit"
/> />
<image <image
class="quick-actions__icon-part" class="quick-actions__icon-part"
src="/static/images/Vector_2_491.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Vector_2_491.png"
mode="aspectFit" mode="aspectFit"
/> />
<view class="quick-actions__border-wrap"> <view class="quick-actions__border-wrap">
@@ -31,12 +31,12 @@
</view> </view>
<image <image
class="quick-actions__icon-part" class="quick-actions__icon-part"
src="/static/images/Vector_2_493.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Vector_2_493.png"
mode="aspectFit" mode="aspectFit"
/> />
<image <image
class="quick-actions__icon-part" class="quick-actions__icon-part"
src="/static/images/Vector_2_494.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Vector_2_494.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -94,15 +94,15 @@ export default {
return { return {
row1: [ row1: [
{ key: 'booking', label: '预约课程', textClass: 'quick-actions__title', icon: '' }, { key: 'booking', label: '预约课程', textClass: 'quick-actions__title', icon: '' },
{ key: 'bodyTest', label: '智能体测', textClass: 'quick-actions__title-2', icon: '/static/images/mappin2.png' }, { key: 'bodyTest', label: '智能体测', textClass: 'quick-actions__title-2', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin2.png' },
{ key: 'bodyReport', label: '体测报告', textClass: 'quick-actions__title-3', icon: '/static/images/activity.png' }, { key: 'bodyReport', label: '体测报告', textClass: 'quick-actions__title-3', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png' },
{ key: 'trainReport', label: '训练报告', textClass: 'quick-actions__coach', icon: '/static/images/usercheck.png' } { key: 'trainReport', label: '训练报告', textClass: 'quick-actions__coach', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/usercheck.png' }
], ],
row2: [ row2: [
{ key: 'coupon', label: '我的优惠券', textClass: 'quick-actions__text', icon: '/static/images/ticket.png' }, { key: 'coupon', label: '我的优惠券', textClass: 'quick-actions__text', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/ticket.png' },
{ key: 'points', label: '我的积分', textClass: 'quick-actions__points-desc', icon: '/static/images/star.png' }, { key: 'points', label: '我的积分', textClass: 'quick-actions__points-desc', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/star.png' },
{ key: 'referral', label: '邀请好友', textClass: 'quick-actions__title-4', icon: '/static/images/share2.png' }, { key: 'referral', label: '邀请好友', textClass: 'quick-actions__title-4', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/share2.png' },
{ key: 'course', label: '我的课程', textClass: 'quick-actions__text-2', icon: '/static/images/play.png' } { key: 'course', label: '我的课程', textClass: 'quick-actions__text-2', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/play.png' }
] ]
} }
} }
@@ -12,7 +12,7 @@
<text class="referral-section__records-link">规则说明</text> <text class="referral-section__records-link">规则说明</text>
<image <image
class="referral-section__link-arrow" class="referral-section__link-arrow"
src="/static/images/chevronright11.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright11.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -43,7 +43,7 @@
</text> </text>
<image <image
class="settings-section__item-arrow" class="settings-section__item-arrow"
src="/static/images/chevronright10.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright10.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -68,32 +68,32 @@ export default {
{ {
key: 'notify', key: 'notify',
label: '通知设置', label: '通知设置',
icon: '/static/images/bell.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/bell.png',
iconWrapClass: '' iconWrapClass: ''
}, },
{ {
key: 'password', key: 'password',
label: '修改密码', label: '修改密码',
icon: '/static/images/Vector_2_727.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/Vector_2_727.png',
iconWrapClass: 'settings-section__item-icon-wrap--blue' iconWrapClass: 'settings-section__item-icon-wrap--blue'
}, },
{ {
key: 'privacy', key: 'privacy',
label: '隐私政策', label: '隐私政策',
icon: '/static/images/shield.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/shield.png',
iconWrapClass: 'settings-section__item-icon-wrap--green' iconWrapClass: 'settings-section__item-icon-wrap--green'
}, },
{ {
key: 'nfc', key: 'nfc',
label: 'NFC 门禁卡', label: 'NFC 门禁卡',
subtitle: '已绑定', subtitle: '已绑定',
icon: '/static/images/ticket.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/ticket.png',
iconWrapClass: '' iconWrapClass: ''
}, },
{ {
key: 'delete', key: 'delete',
label: '注销账户', label: '注销账户',
icon: '/static/images/userx.png', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/userx.png',
iconWrapClass: 'settings-section__item-icon-wrap--red', iconWrapClass: 'settings-section__item-icon-wrap--red',
labelClass: 'settings-section__item-label--danger' labelClass: 'settings-section__item-label--danger'
} }
@@ -5,7 +5,7 @@
<view class="sub-nav__back" @tap.stop="$emit('back')"> <view class="sub-nav__back" @tap.stop="$emit('back')">
<image <image
class="sub-nav__back-icon" class="sub-nav__back-icon"
src="/static/images/chevronleft.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronleft.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
+1
View File
@@ -3,6 +3,7 @@
{ {
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"navigationStyle":"custom",
"navigationBarTitleText": "健身房", "navigationBarTitleText": "健身房",
"app-plus": { "app-plus": {
"animationType": "fade-in", "animationType": "fade-in",
+168 -15
View File
@@ -1,29 +1,44 @@
<template> <template>
<!-- 水波纹背景 - 顶层显示 -->
<view class="bg-wrapper">
<image src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/wave_top.png" mode="widthFix" class="wave-bg wave-top" />
<image src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/wave_bottom.png" mode="widthFix" class="wave-bg wave-bottom" />
</view>
<!-- 固定白色块滚动时显示 -->
<view class="hand" :style="{height : handHeight + 'rpx'}" v-show="isShow"></view>
<!-- 滚动内容区域 -->
<scroll-view
scroll-y
refresher-enabled
:refresher-triggered="isRefreshing"
refresher-default-style="none"
@refresherrefresh="onRefresh"
@scroll="handleScroll"
class="scroll-container"
>
<!-- 主内容 -->
<view class="home-page"> <view class="home-page">
<!-- 骨架屏 --> <!-- 骨架屏 -->
<HomeSkeleton v-if="loading" /> <HomeSkeleton v-if="loading" />
<!-- 实际内容 --> <!-- 实际内容 -->
<template v-else> <template v-else>
<!-- Banner轮播 -->
<BannerSwiper /> <BannerSwiper />
<!-- 功能入口 -->
<QuickEntry /> <QuickEntry />
<!-- 推荐课程 -->
<RecommendCourses /> <RecommendCourses />
<!-- 今日推荐 -->
<TodayRecommend /> <TodayRecommend />
<!-- 底部占位 TabBar 留出空间 -->
<!-- 底部占位 -->
<view class="bottom-placeholder"></view> <view class="bottom-placeholder"></view>
<!-- TabBar -->
<TabBar />
</template> </template>
</view> </view>
</scroll-view>
<!-- TabBar 固定在底部不参与滚动 -->
<view class="tabbar-fixed">
<TabBar />
</view>
</template> </template>
<script setup> <script setup>
@@ -36,23 +51,161 @@ import TabBar from '@/components/TabBar.vue'
import HomeSkeleton from '@/components/Skeleton/HomeSkeleton.vue' import HomeSkeleton from '@/components/Skeleton/HomeSkeleton.vue'
const loading = ref(true) const loading = ref(true)
const isShow = ref(false)
const handHeight = ref(0)
const scrollDistance = ref(0)
const isRefreshing = ref(false)
// 滚动监听
const handleScroll = (e) => {
const distance = e.detail.scrollTop
scrollDistance.value = distance
// 控制白色块显示/隐藏
isShow.value = distance > 238
}
// 下拉刷新处理
const onRefresh = async () => {
console.log('开始下拉刷新')
isRefreshing.value = true
try {
await refreshData()
isRefreshing.value = false
uni.showToast({
title: '刷新成功',
icon: 'success'
})
} catch (error) {
console.error('刷新失败', error)
isRefreshing.value = false
uni.showToast({
title: '刷新失败',
icon: 'error'
})
}
}
// 刷新数据
const refreshData = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('数据已刷新')
resolve()
}, 1500)
})
}
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
loading.value = false loading.value = false
}, 1500) }, 1500)
// 获取胶囊按钮高度
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
const navTotalHeight = menuButtonInfo.top + menuButtonInfo.height
handHeight.value = navTotalHeight * 2
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 背景包装器 - 固定在最底层 */
.bg-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
.wave-bg {
position: fixed;
left: 0;
width: 100%;
pointer-events: none;
opacity: 0.6;
}
.wave-top {
top: 0;
opacity: 0.5;
}
.wave-bottom {
bottom: 100rpx;
opacity: 0.35;
}
/* 滚动容器 */
.scroll-container {
position: relative;
z-index: 1;
height: 100vh;
width: 100%;
background: linear-gradient(180deg, #D6EEF8 0%, #E4F2FA 15%, #EEF6FB 30%, #F5FAFD 50%, #FAFCFE 70%, #FFFFFF 100%);
}
/* 主内容区域 */
.home-page { .home-page {
min-height: 100vh; min-height: 100vh;
background-color: #f0f4f8; padding-bottom: 160rpx; /* 为 TabBar 留出空间 */
padding-bottom: 160rpx; }
/* 固定白色块 */
.hand {
position: fixed;
top: 0;
left: 0;
z-index: 100;
background-color: white;
width: 100%;
}
/* 固定 TabBar */
.tabbar-fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 20;
background-color: transparent;
} }
.bottom-placeholder { .bottom-placeholder {
height: 40rpx; height: 120rpx; /* 调整高度,避免内容被 TabBar 遮挡 */
} }
/* 其他样式保持不变 */
.glow {
position: absolute;
border-radius: 50%;
pointer-events: none;
z-index: 0;
}
.glow-1 {
width: 400rpx;
height: 400rpx;
top: 60rpx;
right: -100rpx;
background: radial-gradient(circle, rgba(160, 210, 235, 0.35) 0%, transparent 70%);
}
.glow-2 {
width: 300rpx;
height: 300rpx;
top: 500rpx;
left: -80rpx;
background: radial-gradient(circle, rgba(180, 220, 240, 0.3) 0%, transparent 70%);
}
.glow-3 {
width: 250rpx;
height: 250rpx;
top: 900rpx;
right: -60rpx;
background: radial-gradient(circle, rgba(170, 215, 238, 0.25) 0%, transparent 70%);
}
</style> </style>
@@ -35,7 +35,7 @@
<view v-if="connected" class="bt-card"> <view v-if="connected" class="bt-card">
<view class="bt-device"> <view class="bt-device">
<view class="bt-device__icon-wrap"> <view class="bt-device__icon-wrap">
<image class="bt-device__icon" src="/static/images/shield.png" mode="aspectFit" /> <image class="bt-device__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/shield.png" mode="aspectFit" />
</view> </view>
<view class="bt-device__info"> <view class="bt-device__info">
<text class="bt-device__name">连接成功</text> <text class="bt-device__name">连接成功</text>
@@ -34,7 +34,7 @@
:hover-stay-time="150" :hover-stay-time="150"
@tap="startMeasure" @tap="startMeasure"
> >
<image class="bt-btn__icon" src="/static/images/activity.png" mode="aspectFit" /> <image class="bt-btn__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png" mode="aspectFit" />
<text class="bt-btn__text">开始体测</text> <text class="bt-btn__text">开始体测</text>
</view> </view>
<view <view
@@ -53,7 +53,7 @@
<text class="bt-card__title">设备状态</text> <text class="bt-card__title">设备状态</text>
<view class="bt-device"> <view class="bt-device">
<view class="bt-device__icon-wrap"> <view class="bt-device__icon-wrap">
<image class="bt-device__icon" src="/static/images/mappin2.png" mode="aspectFit" /> <image class="bt-device__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin2.png" mode="aspectFit" />
</view> </view>
<view class="bt-device__info"> <view class="bt-device__info">
<text class="bt-device__name">{{ device.name }}</text> <text class="bt-device__name">{{ device.name }}</text>
@@ -121,10 +121,10 @@ export default {
latest: null, latest: null,
device: {}, device: {},
quickLinks: [ quickLinks: [
{ key: 'history', label: '历史记录', icon: '/static/images/clock.png' }, { key: 'history', label: '历史记录', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png' },
{ key: 'compare', label: '历史对比', icon: '/static/images/trendingdown.png' }, { key: 'compare', label: '历史对比', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/trendingdown.png' },
{ key: 'trend', label: '趋势分析', icon: '/static/images/activity.png' }, { key: 'trend', label: '趋势分析', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png' },
{ key: 'report', label: '体测报告', icon: '/static/images/filetext.png' } { key: 'report', label: '体测报告', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/filetext.png' }
] ]
} }
}, },
@@ -94,7 +94,7 @@
<text class="bt-trend-link__text">查看完整趋势分析</text> <text class="bt-trend-link__text">查看完整趋势分析</text>
<image <image
class="bt-trend-link__arrow" class="bt-trend-link__arrow"
src="/static/images/chevronright3.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright3.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -140,7 +140,7 @@
:hover-stay-time="150" :hover-stay-time="150"
@tap="exportReport" @tap="exportReport"
> >
<image class="bt-btn__icon" src="/static/images/filetext.png" mode="aspectFit" /> <image class="bt-btn__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/filetext.png" mode="aspectFit" />
<text class="bt-btn__text">导出 PDF</text> <text class="bt-btn__text">导出 PDF</text>
</view> </view>
<view <view
@@ -149,7 +149,7 @@
:hover-stay-time="150" :hover-stay-time="150"
@tap="shareReport" @tap="shareReport"
> >
<image class="bt-btn__icon" src="/static/images/share2.png" mode="aspectFit" /> <image class="bt-btn__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/share2.png" mode="aspectFit" />
<text class="bt-btn__text">分享</text> <text class="bt-btn__text">分享</text>
</view> </view>
<view <view
@@ -76,7 +76,7 @@
<text class="bt-card__title">设备管理</text> <text class="bt-card__title">设备管理</text>
<view class="bt-device"> <view class="bt-device">
<view class="bt-device__icon-wrap"> <view class="bt-device__icon-wrap">
<image class="bt-device__icon" src="/static/images/mappin2.png" mode="aspectFit" /> <image class="bt-device__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin2.png" mode="aspectFit" />
</view> </view>
<view class="bt-device__info"> <view class="bt-device__info">
<text class="bt-device__name">{{ device.name }}</text> <text class="bt-device__name">{{ device.name }}</text>
@@ -44,7 +44,7 @@
> >
<image <image
class="booking-page__alert-icon" class="booking-page__alert-icon"
src="/static/images/clock1.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock1.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="booking-page__alert-text">{{ upcomingAlert }}</text> <text class="booking-page__alert-text">{{ upcomingAlert }}</text>
@@ -82,7 +82,7 @@
<view class="bk-card__meta-row"> <view class="bk-card__meta-row">
<image <image
class="bk-card__meta-icon" class="bk-card__meta-icon"
src="/static/images/clock0.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock0.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="bk-card__meta-text">{{ item.schedule }}</text> <text class="bk-card__meta-text">{{ item.schedule }}</text>
@@ -90,7 +90,7 @@
<view class="bk-card__meta-row"> <view class="bk-card__meta-row">
<image <image
class="bk-card__meta-icon" class="bk-card__meta-icon"
src="/static/images/user0.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/user0.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="bk-card__meta-text">{{ item.coach }}</text> <text class="bk-card__meta-text">{{ item.coach }}</text>
@@ -27,7 +27,7 @@
@tap="showDetail(item)" @tap="showDetail(item)"
> >
<view class="mi-mod-checkin-row__icon" :class="'mi-mod-checkin-row__icon--' + item.tagTheme"> <view class="mi-mod-checkin-row__icon" :class="'mi-mod-checkin-row__icon--' + item.tagTheme">
<image class="mi-mod-checkin-row__icon-img" src="/static/images/usercheck.png" mode="aspectFit" /> <image class="mi-mod-checkin-row__icon-img" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/usercheck.png" mode="aspectFit" />
</view> </view>
<view class="mi-mod-checkin-row__info"> <view class="mi-mod-checkin-row__info">
<text class="mi-mod-checkin-row__title">{{ item.title }}</text> <text class="mi-mod-checkin-row__title">{{ item.title }}</text>
@@ -39,13 +39,13 @@
<picker :range="coaches" @change="onCoachChange"> <picker :range="coaches" @change="onCoachChange">
<view class="mi-course-list__picker"> <view class="mi-course-list__picker">
<text>{{ coach }}</text> <text>{{ coach }}</text>
<image class="mi-course-list__arrow" src="/static/images/chevronright3.png" mode="aspectFit" /> <image class="mi-course-list__arrow" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright3.png" mode="aspectFit" />
</view> </view>
</picker> </picker>
<picker :range="periodLabels" @change="onPeriodChange"> <picker :range="periodLabels" @change="onPeriodChange">
<view class="mi-course-list__picker"> <view class="mi-course-list__picker">
<text>{{ periodLabel }}</text> <text>{{ periodLabel }}</text>
<image class="mi-course-list__arrow" src="/static/images/chevronright3.png" mode="aspectFit" /> <image class="mi-course-list__arrow" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright3.png" mode="aspectFit" />
</view> </view>
</picker> </picker>
</view> </view>
@@ -103,7 +103,7 @@
hover-class="mi-tap-btn--hover" hover-class="mi-tap-btn--hover"
@tap="goMyBooking" @tap="goMyBooking"
> >
<image class="mi-course-list__fab-icon" src="/static/images/clock.png" mode="aspectFit" /> <image class="mi-course-list__fab-icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png" mode="aspectFit" />
<text class="mi-course-list__fab-text">我的预约</text> <text class="mi-course-list__fab-text">我的预约</text>
</view> </view>
</view> </view>
@@ -8,7 +8,7 @@
<view class="mc-hero__title-row"> <view class="mc-hero__title-row">
<image <image
class="mc-hero__crown" class="mc-hero__crown"
src="/static/images/crown.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/crown.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="mc-hero__name">{{ card.name }}</text> <text class="mc-hero__name">{{ card.name }}</text>
@@ -31,7 +31,7 @@
> >
<image <image
class="mc-hero__renew-icon" class="mc-hero__renew-icon"
src="/static/images/refreshcw.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/refreshcw.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="mc-hero__renew-text">立即续费</text> <text class="mc-hero__renew-text">立即续费</text>
@@ -16,7 +16,7 @@
<view class="bt-card"> <view class="bt-card">
<text class="bt-card__title">视频播放</text> <text class="bt-card__title">视频播放</text>
<view class="mi-online-player"> <view class="mi-online-player">
<image class="mi-online-player__play" src="/static/images/play.png" mode="aspectFit" /> <image class="mi-online-player__play" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/play.png" mode="aspectFit" />
<text class="mi-online-player__hint">点击播放支持倍速与拖拽</text> <text class="mi-online-player__hint">点击播放支持倍速与拖拽</text>
</view> </view>
<view class="mi-online-controls"> <view class="mi-online-controls">
@@ -13,19 +13,19 @@
<text class="bt-card__title">快捷入口</text> <text class="bt-card__title">快捷入口</text>
<view class="bt-grid"> <view class="bt-grid">
<view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goMall"> <view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goMall">
<image class="bt-grid__icon" src="/static/images/star.png" mode="aspectFit" /> <image class="bt-grid__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/star.png" mode="aspectFit" />
<text class="bt-grid__label">积分商城</text> <text class="bt-grid__label">积分商城</text>
</view> </view>
<view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goHistory"> <view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goHistory">
<image class="bt-grid__icon" src="/static/images/clock.png" mode="aspectFit" /> <image class="bt-grid__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png" mode="aspectFit" />
<text class="bt-grid__label">积分明细</text> <text class="bt-grid__label">积分明细</text>
</view> </view>
<view class="bt-grid__item" hover-class="mi-tap--hover" @tap="checkIn"> <view class="bt-grid__item" hover-class="mi-tap--hover" @tap="checkIn">
<image class="bt-grid__icon" src="/static/images/usercheck.png" mode="aspectFit" /> <image class="bt-grid__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/usercheck.png" mode="aspectFit" />
<text class="bt-grid__label">签到赚积分</text> <text class="bt-grid__label">签到赚积分</text>
</view> </view>
<view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goReferral"> <view class="bt-grid__item" hover-class="mi-tap--hover" @tap="goReferral">
<image class="bt-grid__icon" src="/static/images/share2.png" mode="aspectFit" /> <image class="bt-grid__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/share2.png" mode="aspectFit" />
<text class="bt-grid__label">邀请赚积分</text> <text class="bt-grid__label">邀请赚积分</text>
</view> </view>
</view> </view>
@@ -25,7 +25,7 @@
:hover-stay-time="150" :hover-stay-time="150"
@tap="shareInvite" @tap="shareInvite"
> >
<image class="bt-btn__icon" src="/static/images/share2.png" mode="aspectFit" /> <image class="bt-btn__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/share2.png" mode="aspectFit" />
<text class="bt-btn__text">分享给好友</text> <text class="bt-btn__text">分享给好友</text>
</view> </view>
</view> </view>
@@ -21,7 +21,7 @@
> >
<image <image
class="avatar-block__icon" class="avatar-block__icon"
src="/static/images/camera.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/camera.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="avatar-block__text">更换</text> <text class="avatar-block__text">更换</text>
@@ -41,7 +41,7 @@
<text class="Pixso-paragraph-2_813">{{ name }}</text> <text class="Pixso-paragraph-2_813">{{ name }}</text>
<image <image
class="Pixso-vector-2_814" class="Pixso-vector-2_814"
src="/static/images/chevronright1.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright1.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -70,7 +70,7 @@
</view> </view>
<image <image
class="Pixso-vector-2_823" class="Pixso-vector-2_823"
src="/static/images/chevronright.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -90,7 +90,7 @@
> >
<image <image
class="gender-btn__icon" class="gender-btn__icon"
src="/static/images/venus.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/venus.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="gender-btn__text"></text> <text class="gender-btn__text"></text>
@@ -104,7 +104,7 @@
> >
<image <image
class="gender-btn__icon" class="gender-btn__icon"
src="/static/images/mars.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mars.png"
mode="aspectFit" mode="aspectFit"
/> />
<text class="gender-btn__text"></text> <text class="gender-btn__text"></text>
@@ -125,7 +125,7 @@
<text class="Pixso-paragraph-2_844">{{ birthday }}</text> <text class="Pixso-paragraph-2_844">{{ birthday }}</text>
<image <image
class="Pixso-vector-2_845" class="Pixso-vector-2_845"
src="/static/images/chevronright0.png" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/chevronright0.png"
mode="aspectFit" mode="aspectFit"
/> />
</view> </view>
@@ -228,7 +228,7 @@ import {
showValidationError showValidationError
} from '@/common/memberInfo/validate.js' } from '@/common/memberInfo/validate.js'
const DEFAULT_AVATAR = '/static/images/AvatarEditWrap.png' const DEFAULT_AVATAR = 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AvatarEditWrap.png'
export default { export default {
components: { MemberInfoSubNav }, components: { MemberInfoSubNav },
Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 773 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Some files were not shown because too many files have changed in this diff Show More