feat: 添加教练详情页面及相关数据模型
This commit is contained in:
@@ -1,96 +1,279 @@
|
||||
<template>
|
||||
<view class="about-section">
|
||||
<!-- 老师介绍 -->
|
||||
<view class="about-card">
|
||||
<view class="card-header">
|
||||
<view class="header-dot" />
|
||||
<text class="header-title">老师介绍</text>
|
||||
<view class="section-header">
|
||||
<view>
|
||||
<text class="section-eyebrow">Teacher Spotlight</text>
|
||||
<text class="section-title">老师介绍</text>
|
||||
</view>
|
||||
<image class="teacher-img" :src="teacherImage" mode="widthFix" @tap="previewImages([teacherImage], 0)" />
|
||||
<text class="section-more" @tap="goToDetail">查看详情</text>
|
||||
</view>
|
||||
|
||||
<!-- 场馆介绍 -->
|
||||
<view class="about-card">
|
||||
<view class="card-header">
|
||||
<view class="header-dot" />
|
||||
<text class="header-title">场馆介绍</text>
|
||||
<view class="teacher-card" @tap="goToDetail">
|
||||
<view class="teacher-main">
|
||||
<view class="cover-wrap">
|
||||
<image class="teacher-cover" :src="teacher.avatar" mode="aspectFill" />
|
||||
<view class="cover-badge">
|
||||
<text class="cover-badge-text">{{ teacher.badges[0] }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="teacher-content">
|
||||
<view class="teacher-heading">
|
||||
<view>
|
||||
<view class="name-row">
|
||||
<text class="teacher-name">{{ teacher.name }}</text>
|
||||
<text class="teacher-tag">{{ teacher.badges[1] }}</text>
|
||||
</view>
|
||||
<text class="teacher-title">{{ teacher.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="specialty-row">
|
||||
<text v-for="item in teacher.specialties" :key="item" class="specialty-pill">{{ item }}</text>
|
||||
</view>
|
||||
|
||||
<text class="teacher-intro">{{ teacher.intro }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="studio-gallery">
|
||||
<image v-for="(img, idx) in studioImages" :key="idx" class="gallery-img" :src="img" mode="widthFix"
|
||||
@tap="previewImages(studioImages, idx)" />
|
||||
|
||||
<view class="credential-box">
|
||||
<text class="credential-label">认证背景</text>
|
||||
<text class="credential-text">{{ certificationSummary }}</text>
|
||||
</view>
|
||||
|
||||
<view class="action-row">
|
||||
<view class="secondary-btn" @tap.stop="goToDetail">
|
||||
<text class="secondary-btn-text">查看详情</text>
|
||||
</view>
|
||||
<view class="primary-btn" @tap.stop="goToBooking">
|
||||
<text class="primary-btn-text">立即预约</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const teacherImage = 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/person_desc.jpeg'
|
||||
import { computed } from 'vue'
|
||||
import { irisProfile } from '../utils/teacher'
|
||||
|
||||
const studioImages = [
|
||||
'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/place_1.jpg',
|
||||
'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/place_2.jpg',
|
||||
'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/place_3.jpg',
|
||||
'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/place_4.jpg',
|
||||
]
|
||||
const teacher = irisProfile
|
||||
|
||||
function previewImages(urls: string[], current: number) {
|
||||
uni.previewImage({
|
||||
current,
|
||||
urls,
|
||||
})
|
||||
const certificationSummary = computed(() => teacher.certifications.slice(0, 2).join(' · '))
|
||||
|
||||
function goToDetail() {
|
||||
uni.navigateTo({ url: `/pages/teacher/detail?id=${teacher.id}` })
|
||||
}
|
||||
|
||||
function goToBooking() {
|
||||
uni.switchTab({ url: '/pages/booking/index' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.about-section {
|
||||
padding: 16rpx 24rpx 0;
|
||||
padding: 20rpx 24rpx 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.section-eyebrow {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
letter-spacing: 3rpx;
|
||||
text-transform: uppercase;
|
||||
color: #b99b8c;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #2f2723;
|
||||
}
|
||||
|
||||
.section-more {
|
||||
font-size: 24rpx;
|
||||
color: #c36d52;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.teacher-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
gap: 18rpx;
|
||||
background:
|
||||
radial-gradient(circle at top right, rgba(226, 198, 179, 0.42), transparent 32%),
|
||||
linear-gradient(135deg, #fffdfb 0%, #f8f2ee 46%, #f2e8e2 100%);
|
||||
border-radius: 30rpx;
|
||||
padding: 22rpx;
|
||||
box-shadow: 0 18rpx 38rpx rgba(126, 98, 84, 0.09);
|
||||
}
|
||||
|
||||
.about-card {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
.teacher-main {
|
||||
display: flex;
|
||||
gap: 22rpx;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.cover-wrap {
|
||||
position: relative;
|
||||
width: 188rpx;
|
||||
height: 248rpx;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
padding: 28rpx 24rpx 24rpx;
|
||||
flex-shrink: 0;
|
||||
background: #eadfd7;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.teacher-cover {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cover-badge {
|
||||
position: absolute;
|
||||
left: 14rpx;
|
||||
bottom: 14rpx;
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
background: rgba(41, 34, 30, 0.74);
|
||||
backdrop-filter: blur(12rpx);
|
||||
}
|
||||
|
||||
.cover-badge-text {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
color: #fff7f3;
|
||||
}
|
||||
|
||||
.teacher-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.teacher-heading {
|
||||
margin-bottom: 14rpx;
|
||||
}
|
||||
|
||||
.name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.header-dot {
|
||||
width: 10rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 5rpx;
|
||||
background: linear-gradient(180deg, #D4A59A, #C08B7E);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
.teacher-name {
|
||||
font-size: 38rpx;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
color: #2e2521;
|
||||
}
|
||||
|
||||
.teacher-tag {
|
||||
font-size: 18rpx;
|
||||
line-height: 1;
|
||||
color: #a85d44;
|
||||
background: rgba(221, 150, 118, 0.18);
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 12rpx;
|
||||
}
|
||||
|
||||
.teacher-title {
|
||||
font-size: 24rpx;
|
||||
color: #7f6659;
|
||||
}
|
||||
|
||||
.specialty-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 14rpx;
|
||||
}
|
||||
|
||||
.specialty-pill {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(92, 126, 151, 0.12);
|
||||
color: #5a7a8b;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.teacher-intro {
|
||||
font-size: 22rpx;
|
||||
line-height: 1.7;
|
||||
color: #5e5048;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.credential-box {
|
||||
padding: 16rpx 18rpx;
|
||||
border-radius: 18rpx;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
border: 1rpx solid rgba(190, 161, 145, 0.22);
|
||||
}
|
||||
|
||||
.credential-label {
|
||||
display: block;
|
||||
font-size: 18rpx;
|
||||
letter-spacing: 2rpx;
|
||||
color: #b19486;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.credential-text {
|
||||
font-size: 20rpx;
|
||||
line-height: 1.6;
|
||||
color: #6a5a51;
|
||||
}
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.secondary-btn,
|
||||
.primary-btn {
|
||||
height: 72rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
width: 148rpx;
|
||||
border: 1rpx solid rgba(139, 113, 99, 0.24);
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
flex: 1;
|
||||
background: linear-gradient(135deg, #ff7654 0%, #ff4d38 100%);
|
||||
box-shadow: 0 14rpx 24rpx rgba(255, 92, 69, 0.24);
|
||||
}
|
||||
|
||||
.secondary-btn-text {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #684d40;
|
||||
}
|
||||
|
||||
.primary-btn-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.teacher-img {
|
||||
width: 100%;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.studio-gallery {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.gallery-img {
|
||||
width: 100%;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/teacher/detail",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/admin/index",
|
||||
"style": {
|
||||
|
||||
442
packages/app/src/pages/teacher/detail.vue
Normal file
442
packages/app/src/pages/teacher/detail.vue
Normal file
@@ -0,0 +1,442 @@
|
||||
<template>
|
||||
<view class="teacher-detail-page">
|
||||
<CustomNavBar title="教练详情" show-back />
|
||||
|
||||
<scroll-view class="detail-scroll" scroll-y :style="{ height: scrollHeight }">
|
||||
<view class="nav-spacer" :style="{ height: navBarHeight }" />
|
||||
|
||||
<view class="hero-section">
|
||||
<image class="hero-image" :src="teacher.cover" mode="aspectFill" />
|
||||
<view class="hero-overlay" />
|
||||
|
||||
<view class="hero-content">
|
||||
<view class="hero-badges">
|
||||
<text v-for="item in teacher.badges" :key="item" class="hero-badge">{{ item }}</text>
|
||||
</view>
|
||||
<text class="hero-name">{{ teacher.name }}</text>
|
||||
<text class="hero-title">{{ teacher.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content-wrap">
|
||||
<view class="summary-card">
|
||||
<view class="summary-head">
|
||||
<view>
|
||||
<text class="summary-eyebrow">Private Pilates Coach</text>
|
||||
<text class="summary-title">为你定制更细腻的训练节奏</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="specialty-row">
|
||||
<text v-for="item in teacher.specialties" :key="item" class="specialty-pill">{{ item }}</text>
|
||||
</view>
|
||||
|
||||
<text class="summary-intro">{{ teacher.intro }}</text>
|
||||
|
||||
<view class="stats-grid">
|
||||
<view v-for="item in teacher.stats" :key="item.label" class="stat-item">
|
||||
<text class="stat-value">{{ item.value }}</text>
|
||||
<text class="stat-label">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-card">
|
||||
<text class="card-title">教练介绍</text>
|
||||
<text class="card-text">
|
||||
Iris 注重基础控制与身体感知,课程会围绕呼吸、核心稳定、动作路径和发力节奏展开,帮助学员在安全前提下持续进步。
|
||||
</text>
|
||||
<text class="card-text">
|
||||
无论你希望改善久坐体态、建立训练基础,还是进一步雕塑身体线条,都可以通过私教课程获得更清晰的动作反馈与进阶方案。
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="detail-card">
|
||||
<text class="card-title">认证背景</text>
|
||||
<view v-for="item in teacher.certifications" :key="item" class="list-row">
|
||||
<view class="list-dot" />
|
||||
<text class="list-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-card">
|
||||
<text class="card-title">授课重点</text>
|
||||
<view class="focus-grid">
|
||||
<view v-for="item in teacher.teachingFocus" :key="item.title" class="focus-item">
|
||||
<text class="focus-title">{{ item.title }}</text>
|
||||
<text class="focus-desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-card cta-card">
|
||||
<text class="card-title">适合这样的你</text>
|
||||
<text class="card-text">久坐肩颈紧张、想改善圆肩骨盆前倾、训练没感觉,或想通过更稳定的核心训练提升身体线条与控制力。</text>
|
||||
<view class="cta-inline" @tap="goToBooking">
|
||||
<text class="cta-inline-text">去约 Iris 的课程</text>
|
||||
<text class="cta-inline-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-space" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="bottom-bar">
|
||||
<view class="bottom-note">
|
||||
<text class="bottom-note-title">1 对 1 私教课</text>
|
||||
<text class="bottom-note-sub">60 分钟 · 进入约课页选择时段</text>
|
||||
</view>
|
||||
<view class="booking-btn" @tap="goToBooking">
|
||||
<text class="booking-btn-text">立即预约</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import CustomNavBar from '../../components/CustomNavBar.vue'
|
||||
import { irisProfile } from '../../utils/teacher'
|
||||
import { getSystemLayout } from '../../utils/system'
|
||||
|
||||
const teacher = irisProfile
|
||||
const navBarHeight = ref('64px')
|
||||
const scrollHeight = ref('500px')
|
||||
|
||||
onLoad(() => {
|
||||
updateLayout()
|
||||
})
|
||||
|
||||
function updateLayout() {
|
||||
const { navBarHeight: navBarPx } = getSystemLayout()
|
||||
const { windowHeight } = uni.getWindowInfo()
|
||||
navBarHeight.value = `${navBarPx}px`
|
||||
scrollHeight.value = `${windowHeight}px`
|
||||
}
|
||||
|
||||
function goToBooking() {
|
||||
uni.switchTab({ url: '/pages/booking/index' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.teacher-detail-page {
|
||||
height: 100vh;
|
||||
background: #f7f2ee;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-spacer {
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.hero-section {
|
||||
position: relative;
|
||||
height: 580rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hero-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(33, 24, 22, 0.08) 0%, rgba(33, 24, 22, 0.08) 34%, rgba(33, 24, 22, 0.64) 100%),
|
||||
radial-gradient(circle at top right, rgba(255, 228, 208, 0.26), transparent 28%);
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
right: 32rpx;
|
||||
bottom: 92rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-badges {
|
||||
display: flex;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
height: 42rpx;
|
||||
padding: 0 16rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.24);
|
||||
color: #fff8f3;
|
||||
font-size: 20rpx;
|
||||
backdrop-filter: blur(10rpx);
|
||||
}
|
||||
|
||||
.hero-name {
|
||||
display: block;
|
||||
font-size: 56rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
line-height: 1.05;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 247, 241, 0.88);
|
||||
}
|
||||
|
||||
.detail-scroll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
position: relative;
|
||||
margin-top: -8rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.summary-card,
|
||||
.detail-card {
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border-radius: 28rpx;
|
||||
box-shadow: 0 16rpx 36rpx rgba(120, 91, 79, 0.08);
|
||||
backdrop-filter: blur(12rpx);
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 28rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.summary-head {
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.summary-eyebrow {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #c09a89;
|
||||
letter-spacing: 3rpx;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-size: 34rpx;
|
||||
line-height: 1.35;
|
||||
font-weight: 700;
|
||||
color: #2f2622;
|
||||
}
|
||||
|
||||
.specialty-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.specialty-pill {
|
||||
padding: 10rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(92, 126, 151, 0.12);
|
||||
color: #56778a;
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.summary-intro,
|
||||
.card-text,
|
||||
.list-text {
|
||||
font-size: 25rpx;
|
||||
line-height: 1.78;
|
||||
color: #5f534c;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 14rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
padding: 20rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(180deg, #fff8f4 0%, #f7f1ec 100%);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.45;
|
||||
font-weight: 700;
|
||||
color: #3f3029;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 20rpx;
|
||||
color: #9c8579;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
padding: 28rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
color: #342925;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.card-text + .card-text {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.list-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.list-row + .list-row {
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
|
||||
.list-dot {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
margin-top: 14rpx;
|
||||
flex-shrink: 0;
|
||||
background: linear-gradient(135deg, #ff8b69 0%, #ff593f 100%);
|
||||
}
|
||||
|
||||
.focus-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.focus-item {
|
||||
min-height: 164rpx;
|
||||
border-radius: 22rpx;
|
||||
padding: 22rpx 18rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
background: linear-gradient(135deg, #fff8f5 0%, #f6eee9 100%);
|
||||
}
|
||||
|
||||
.focus-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #5c4a42;
|
||||
}
|
||||
|
||||
.focus-desc {
|
||||
margin-top: 10rpx;
|
||||
font-size: 21rpx;
|
||||
line-height: 1.65;
|
||||
color: #8a7569;
|
||||
}
|
||||
|
||||
.cta-card {
|
||||
background: linear-gradient(135deg, #fff6f1 0%, #fffdfc 100%);
|
||||
}
|
||||
|
||||
.cta-inline {
|
||||
margin-top: 22rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 999rpx;
|
||||
padding: 0 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: linear-gradient(135deg, #ff7f5e 0%, #ff543c 100%);
|
||||
box-shadow: 0 16rpx 28rpx rgba(255, 95, 73, 0.22);
|
||||
}
|
||||
|
||||
.cta-inline-text,
|
||||
.cta-inline-arrow {
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.cta-inline-text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.cta-inline-arrow {
|
||||
font-size: 38rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.bottom-space {
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
left: 24rpx;
|
||||
right: 24rpx;
|
||||
bottom: 24rpx;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
padding: 18rpx;
|
||||
border-radius: 28rpx;
|
||||
background: rgba(35, 29, 27, 0.9);
|
||||
backdrop-filter: blur(18rpx);
|
||||
box-shadow: 0 20rpx 48rpx rgba(36, 28, 26, 0.18);
|
||||
}
|
||||
|
||||
.bottom-note {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bottom-note-title {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #fffaf6;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.bottom-note-sub {
|
||||
font-size: 20rpx;
|
||||
color: rgba(255, 244, 236, 0.72);
|
||||
}
|
||||
|
||||
.booking-btn {
|
||||
width: 224rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #ff815e 0%, #ff5136 100%);
|
||||
}
|
||||
|
||||
.booking-btn-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
</style>
|
||||
60
packages/app/src/utils/teacher.ts
Normal file
60
packages/app/src/utils/teacher.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
export interface TeacherProfile {
|
||||
id: string
|
||||
name: string
|
||||
title: string
|
||||
avatar: string
|
||||
cover: string
|
||||
badges: string[]
|
||||
specialties: string[]
|
||||
intro: string
|
||||
certifications: string[]
|
||||
teachingFocus: Array<{ title: string; desc: string }>
|
||||
stats: Array<{ label: string; value: string }>
|
||||
}
|
||||
|
||||
export const irisProfile: TeacherProfile = {
|
||||
id: 'iris',
|
||||
name: 'Iris',
|
||||
title: '高级普拉提教练',
|
||||
avatar: 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/person_desc.jpeg',
|
||||
cover: 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/mp/images/person_desc.jpeg',
|
||||
badges: ['高级', 'STOTT PILATES'],
|
||||
specialties: ['塑性训练', '体态调整', '产后恢复'],
|
||||
intro: '擅长用循序渐进的核心训练帮助学员改善姿态、建立稳定发力模式,让训练效果更细腻也更可持续。',
|
||||
certifications: [
|
||||
'加拿大 STOTT PILATES 垫上初中级认证',
|
||||
'加拿大 STOTT PILATES 塑身机初中级认证教练',
|
||||
'系统化接受 STOTT PILATES 体系训练',
|
||||
],
|
||||
teachingFocus: [
|
||||
{
|
||||
title: '核心激活',
|
||||
desc: '从骨盆与深层腹部控制入手,建立稳定发力基础。',
|
||||
},
|
||||
{
|
||||
title: '体态调整',
|
||||
desc: '针对圆肩、头前伸、骨盆前倾等常见问题做精细训练。',
|
||||
},
|
||||
{
|
||||
title: '产后恢复',
|
||||
desc: '循序渐进关注核心重建、呼吸配合与身体觉知恢复。',
|
||||
},
|
||||
{
|
||||
title: '塑形训练',
|
||||
desc: '兼顾力量与线条,让臀腿、背部和核心更有支撑感。',
|
||||
},
|
||||
{
|
||||
title: '呼吸控制',
|
||||
desc: '把呼吸节奏融入动作,提高训练效率与身体连接感。',
|
||||
},
|
||||
{
|
||||
title: '一对一进阶',
|
||||
desc: '根据训练基础与目标安排节奏,适合长期稳定提升。',
|
||||
},
|
||||
],
|
||||
stats: [
|
||||
{ label: '擅长方向', value: '塑形 / 体态' },
|
||||
{ label: '授课类型', value: '私教为主' },
|
||||
{ label: '课程时长', value: '60 分钟' },
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user