You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
933 lines
21 KiB
933 lines
21 KiB
<!--学员课程安排页面-->
|
|
<template>
|
|
<view class="main_box">
|
|
<!-- 自定义导航栏 -->
|
|
<view class="navbar_section">
|
|
<view class="navbar_back" @click="goBack">
|
|
<text class="back_icon">‹</text>
|
|
</view>
|
|
<view class="navbar_title">课程安排</view>
|
|
<view class="navbar_action">
|
|
<view class="today_button" @click="goToToday">
|
|
<text class="today_text">今天</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 学员信息 -->
|
|
<view class="student_info_section" v-if="studentInfo">
|
|
<view class="student_name">{{ studentInfo.name }}</view>
|
|
<view class="schedule_stats">
|
|
<text class="stat_item">本周课程:{{ weeklyStats.total_courses }}节</text>
|
|
<text class="stat_item">已完成:{{ weeklyStats.completed_courses }}节</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 日历切换 -->
|
|
<view class="calendar_section">
|
|
<view class="calendar_header">
|
|
<view class="month_controls">
|
|
<view class="control_button" @click="prevWeek">‹</view>
|
|
<view class="current_period">{{ currentWeekText }}</view>
|
|
<view class="control_button" @click="nextWeek">›</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="week_tabs">
|
|
<view
|
|
v-for="day in weekDays"
|
|
:key="day.date"
|
|
:class="['week_tab', selectedDate === day.date ? 'active' : '', day.isToday ? 'today' : '']"
|
|
@click="selectDate(day.date)"
|
|
>
|
|
<view class="tab_weekday">{{ day.weekday }}</view>
|
|
<view class="tab_date">{{ day.day }}</view>
|
|
<view class="tab_indicator" v-if="day.hasCourse"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课程列表 -->
|
|
<view class="courses_section">
|
|
<view v-if="loading" class="loading_section">
|
|
<view class="loading_text">加载中...</view>
|
|
</view>
|
|
|
|
<view v-else-if="dailyCourses.length === 0" class="empty_section">
|
|
<view class="empty_icon">📅</view>
|
|
<view class="empty_text">当日暂无课程安排</view>
|
|
<view class="empty_hint">选择其他日期查看课程</view>
|
|
</view>
|
|
|
|
<view v-else class="courses_list">
|
|
<view
|
|
v-for="course in dailyCourses"
|
|
:key="course.id"
|
|
:class="['course_item', course.status]"
|
|
@click="viewCourseDetail(course)"
|
|
>
|
|
<view class="course_time">
|
|
<view class="time_range">{{ course.start_time }}</view>
|
|
<view class="time_duration">{{ course.duration }}分钟</view>
|
|
</view>
|
|
|
|
<view class="course_info">
|
|
<view class="course_name">{{ course.course_name }}</view>
|
|
<view class="course_details">
|
|
<view class="detail_row">
|
|
<text class="detail_label">教练:</text>
|
|
<text class="detail_value">{{ course.coach_name }}</text>
|
|
</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">场地:</text>
|
|
<text class="detail_value">{{ course.venue_name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="course_status">
|
|
<view :class="['status_badge', course.status]">
|
|
{{ getStatusText(course.status) }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 课程详情弹窗 -->
|
|
<view class="course_popup" v-if="showCoursePopup" @click="closeCoursePopup">
|
|
<view class="popup_content" @click.stop>
|
|
<view class="popup_header">
|
|
<view class="popup_title">课程详情</view>
|
|
<view class="popup_close" @click="closeCoursePopup">×</view>
|
|
</view>
|
|
|
|
<view class="popup_course_detail" v-if="selectedCourse">
|
|
<view class="detail_section">
|
|
<view class="section_title">基本信息</view>
|
|
<view class="info_grid">
|
|
<view class="info_row">
|
|
<text class="info_label">课程名称:</text>
|
|
<text class="info_value">{{ selectedCourse.course_name }}</text>
|
|
</view>
|
|
<view class="info_row">
|
|
<text class="info_label">上课时间:</text>
|
|
<text class="info_value">{{ formatDateTime(selectedCourse.course_date, selectedCourse.start_time) }}</text>
|
|
</view>
|
|
<view class="info_row">
|
|
<text class="info_label">课程时长:</text>
|
|
<text class="info_value">{{ selectedCourse.duration }}分钟</text>
|
|
</view>
|
|
<view class="info_row">
|
|
<text class="info_label">授课教练:</text>
|
|
<text class="info_value">{{ selectedCourse.coach_name }}</text>
|
|
</view>
|
|
<view class="info_row">
|
|
<text class="info_label">上课地点:</text>
|
|
<text class="info_value">{{ selectedCourse.venue_name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail_section" v-if="selectedCourse.course_description">
|
|
<view class="section_title">课程介绍</view>
|
|
<view class="course_description">{{ selectedCourse.course_description }}</view>
|
|
</view>
|
|
|
|
<view class="detail_section" v-if="selectedCourse.preparation_items">
|
|
<view class="section_title">课前准备</view>
|
|
<view class="preparation_list">
|
|
<view
|
|
v-for="item in selectedCourse.preparation_items"
|
|
:key="item"
|
|
class="preparation_item"
|
|
>
|
|
• {{ item }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="popup_actions">
|
|
<fui-button
|
|
v-if="selectedCourse && selectedCourse.status === 'scheduled'"
|
|
background="#f39c12"
|
|
@click="requestLeave"
|
|
>
|
|
请假
|
|
</fui-button>
|
|
|
|
<fui-button
|
|
background="#f8f9fa"
|
|
color="#666"
|
|
@click="closeCoursePopup"
|
|
>
|
|
关闭
|
|
</fui-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import apiRoute from '@/api/apiRoute.js'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
studentId: 0,
|
|
studentInfo: {},
|
|
selectedDate: '',
|
|
currentWeekStart: new Date(),
|
|
weekDays: [],
|
|
dailyCourses: [],
|
|
weeklyStats: {},
|
|
loading: false,
|
|
showCoursePopup: false,
|
|
selectedCourse: null
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
currentWeekText() {
|
|
const start = new Date(this.currentWeekStart)
|
|
const end = new Date(start)
|
|
end.setDate(start.getDate() + 6)
|
|
|
|
const startMonth = start.getMonth() + 1
|
|
const startDay = start.getDate()
|
|
const endMonth = end.getMonth() + 1
|
|
const endDay = end.getDate()
|
|
|
|
if (startMonth === endMonth) {
|
|
return `${startMonth}月${startDay}日-${endDay}日`
|
|
} else {
|
|
return `${startMonth}月${startDay}日-${endMonth}月${endDay}日`
|
|
}
|
|
}
|
|
},
|
|
|
|
onLoad(options) {
|
|
this.studentId = parseInt(options.student_id) || 0
|
|
if (this.studentId) {
|
|
this.initPage()
|
|
} else {
|
|
uni.showToast({
|
|
title: '参数错误',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
goBack() {
|
|
uni.navigateBack()
|
|
},
|
|
|
|
async initPage() {
|
|
await this.loadStudentInfo()
|
|
this.generateWeekDays()
|
|
|
|
// 默认选择今天
|
|
const today = this.formatDateString(new Date())
|
|
this.selectedDate = today
|
|
await this.loadDailyCourses()
|
|
await this.loadWeeklyStats()
|
|
},
|
|
|
|
async loadStudentInfo() {
|
|
try {
|
|
// 模拟获取学员信息
|
|
const mockStudentInfo = {
|
|
id: this.studentId,
|
|
name: '小明'
|
|
}
|
|
this.studentInfo = mockStudentInfo
|
|
} catch (error) {
|
|
console.error('获取学员信息失败:', error)
|
|
}
|
|
},
|
|
|
|
generateWeekDays() {
|
|
const days = []
|
|
const startDate = new Date(this.currentWeekStart)
|
|
const today = new Date()
|
|
const todayStr = this.formatDateString(today)
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
const date = new Date(startDate)
|
|
date.setDate(startDate.getDate() + i)
|
|
|
|
const dateStr = this.formatDateString(date)
|
|
days.push({
|
|
date: dateStr,
|
|
day: date.getDate(),
|
|
weekday: this.getWeekday(date.getDay()),
|
|
isToday: dateStr === todayStr,
|
|
hasCourse: false // 待后续加载课程数据后更新
|
|
})
|
|
}
|
|
|
|
this.weekDays = days
|
|
},
|
|
|
|
prevWeek() {
|
|
this.currentWeekStart.setDate(this.currentWeekStart.getDate() - 7)
|
|
this.generateWeekDays()
|
|
this.loadDailyCourses()
|
|
this.loadWeeklyStats()
|
|
},
|
|
|
|
nextWeek() {
|
|
this.currentWeekStart.setDate(this.currentWeekStart.getDate() + 7)
|
|
this.generateWeekDays()
|
|
this.loadDailyCourses()
|
|
this.loadWeeklyStats()
|
|
},
|
|
|
|
goToToday() {
|
|
const today = new Date()
|
|
this.currentWeekStart = this.getWeekStartDate(today)
|
|
this.generateWeekDays()
|
|
this.selectedDate = this.formatDateString(today)
|
|
this.loadDailyCourses()
|
|
this.loadWeeklyStats()
|
|
},
|
|
|
|
selectDate(date) {
|
|
this.selectedDate = date
|
|
this.loadDailyCourses()
|
|
},
|
|
|
|
async loadDailyCourses() {
|
|
if (!this.selectedDate) return
|
|
|
|
this.loading = true
|
|
try {
|
|
console.log('加载课程安排:', this.selectedDate, '学员ID:', this.studentId)
|
|
|
|
// 调用真实API
|
|
const response = await apiRoute.getCourseScheduleList({
|
|
student_id: this.studentId,
|
|
date: this.selectedDate
|
|
})
|
|
|
|
console.log('课程安排API响应:', response)
|
|
|
|
if (response.code === 1) {
|
|
// 处理API返回的数据格式
|
|
const courses = response.data.list || []
|
|
this.dailyCourses = courses.map(course => ({
|
|
id: course.id,
|
|
course_date: course.course_date,
|
|
start_time: course.start_time,
|
|
end_time: course.end_time,
|
|
duration: course.duration,
|
|
course_name: course.course_name,
|
|
course_description: course.course_description,
|
|
coach_name: course.coach_name,
|
|
venue_name: course.venue_name,
|
|
status: this.mapApiStatusToFrontend(course.status),
|
|
preparation_items: course.preparation_items || []
|
|
}))
|
|
|
|
// 更新周视图中的课程指示器
|
|
this.updateWeekCourseIndicators()
|
|
|
|
console.log('课程数据加载成功:', this.dailyCourses)
|
|
} else {
|
|
console.warn('API返回错误,使用模拟数据:', response.msg)
|
|
// 如果API失败,使用模拟数据
|
|
this.loadMockCourseData()
|
|
}
|
|
} catch (error) {
|
|
console.error('获取课程安排失败:', error)
|
|
console.warn('API调用失败,使用模拟数据')
|
|
// 如果API调用失败,使用模拟数据
|
|
this.loadMockCourseData()
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
// 加载模拟课程数据(作为后备方案)
|
|
loadMockCourseData() {
|
|
const mockCourses = [
|
|
{
|
|
id: 1,
|
|
course_date: this.selectedDate,
|
|
start_time: '09:00',
|
|
end_time: '10:00',
|
|
duration: 60,
|
|
course_name: '基础体能训练',
|
|
course_description: '通过基础的体能训练动作,提升学员的身体素质,包括力量、耐力、协调性等方面的训练。',
|
|
coach_name: '张教练',
|
|
venue_name: '训练馆A',
|
|
status: 'scheduled',
|
|
preparation_items: ['运动服装', '运动鞋', '毛巾', '水杯']
|
|
},
|
|
{
|
|
id: 2,
|
|
course_date: this.selectedDate,
|
|
start_time: '14:00',
|
|
end_time: '15:30',
|
|
duration: 90,
|
|
course_name: '专项技能训练',
|
|
course_description: '针对特定运动项目进行专项技能训练,提高学员在该项目上的技术水平。',
|
|
coach_name: '李教练',
|
|
venue_name: '训练馆B',
|
|
status: 'completed',
|
|
preparation_items: ['专项器材', '护具', '运动服装']
|
|
}
|
|
]
|
|
this.dailyCourses = mockCourses
|
|
this.updateWeekCourseIndicators()
|
|
},
|
|
|
|
// 映射API状态到前端状态
|
|
mapApiStatusToFrontend(apiStatus) {
|
|
const statusMap = {
|
|
0: 'scheduled', // 待上课
|
|
1: 'completed', // 已完成
|
|
2: 'leave_requested', // 请假
|
|
3: 'cancelled' // 取消
|
|
}
|
|
return statusMap[apiStatus] || 'scheduled'
|
|
},
|
|
|
|
async loadWeeklyStats() {
|
|
try {
|
|
// 模拟获取本周统计数据
|
|
const mockStats = {
|
|
total_courses: 8,
|
|
completed_courses: 3,
|
|
scheduled_courses: 4,
|
|
cancelled_courses: 1
|
|
}
|
|
this.weeklyStats = mockStats
|
|
} catch (error) {
|
|
console.error('获取周统计失败:', error)
|
|
}
|
|
},
|
|
|
|
updateWeekCourseIndicators() {
|
|
// 更新周视图中每天是否有课程的指示器
|
|
this.weekDays.forEach(day => {
|
|
// 这里简化处理,实际应该查询每天的课程数据
|
|
day.hasCourse = day.date === this.selectedDate && this.dailyCourses.length > 0
|
|
})
|
|
},
|
|
|
|
viewCourseDetail(course) {
|
|
this.selectedCourse = course
|
|
this.showCoursePopup = true
|
|
},
|
|
|
|
closeCoursePopup() {
|
|
this.showCoursePopup = false
|
|
this.selectedCourse = null
|
|
},
|
|
|
|
async requestLeave() {
|
|
if (!this.selectedCourse) return
|
|
|
|
uni.showModal({
|
|
title: '确认请假',
|
|
content: '确定要为此课程申请请假吗?',
|
|
success: async (res) => {
|
|
if (res.confirm) {
|
|
try {
|
|
console.log('申请请假:', this.selectedCourse.id)
|
|
|
|
// 调用真实API
|
|
const response = await apiRoute.requestCourseLeave({
|
|
schedule_id: this.selectedCourse.id,
|
|
reason: '学员申请请假'
|
|
})
|
|
|
|
console.log('请假申请API响应:', response)
|
|
|
|
if (response.code === 1) {
|
|
uni.showToast({
|
|
title: '请假申请已提交',
|
|
icon: 'success'
|
|
})
|
|
|
|
// 更新课程状态
|
|
const courseIndex = this.dailyCourses.findIndex(c => c.id === this.selectedCourse.id)
|
|
if (courseIndex !== -1) {
|
|
this.dailyCourses[courseIndex].status = 'leave_requested'
|
|
}
|
|
|
|
this.closeCoursePopup()
|
|
} else {
|
|
uni.showToast({
|
|
title: response.msg || '请假申请失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('请假申请失败:', error)
|
|
uni.showToast({
|
|
title: '请假申请失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
})
|
|
},
|
|
|
|
// 工具方法
|
|
formatDateString(date) {
|
|
const year = date.getFullYear()
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
},
|
|
|
|
formatDateTime(dateString, timeString) {
|
|
const date = new Date(dateString)
|
|
const month = date.getMonth() + 1
|
|
const day = date.getDate()
|
|
const weekday = this.getWeekday(date.getDay())
|
|
return `${month}月${day}日 ${weekday} ${timeString}`
|
|
},
|
|
|
|
getWeekday(dayIndex) {
|
|
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
|
|
return weekdays[dayIndex]
|
|
},
|
|
|
|
getWeekStartDate(date) {
|
|
const start = new Date(date)
|
|
const day = start.getDay()
|
|
const diff = start.getDate() - day
|
|
start.setDate(diff)
|
|
return start
|
|
},
|
|
|
|
getStatusText(status) {
|
|
const statusMap = {
|
|
'scheduled': '待上课',
|
|
'completed': '已完成',
|
|
'cancelled': '已取消',
|
|
'leave_requested': '请假中'
|
|
}
|
|
return statusMap[status] || status
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.main_box {
|
|
background: #f8f9fa;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
// 自定义导航栏
|
|
.navbar_section {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: #29D3B4;
|
|
padding: 40rpx 32rpx 20rpx;
|
|
|
|
// 小程序端适配状态栏
|
|
// #ifdef MP-WEIXIN
|
|
padding-top: 80rpx;
|
|
// #endif
|
|
|
|
.navbar_back {
|
|
width: 60rpx;
|
|
|
|
.back_icon {
|
|
color: #fff;
|
|
font-size: 40rpx;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.navbar_title {
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.navbar_action {
|
|
width: 80rpx;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
|
|
.today_button {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 16rpx;
|
|
|
|
.today_text {
|
|
color: #fff;
|
|
font-size: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 学员信息
|
|
.student_info_section {
|
|
background: #fff;
|
|
padding: 24rpx 32rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.student_name {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.schedule_stats {
|
|
display: flex;
|
|
gap: 24rpx;
|
|
|
|
.stat_item {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 日历部分
|
|
.calendar_section {
|
|
background: #fff;
|
|
margin: 20rpx;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx 32rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
|
|
.calendar_header {
|
|
margin-bottom: 24rpx;
|
|
|
|
.month_controls {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 32rpx;
|
|
|
|
.control_button {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
background: #f8f9fa;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.current_period {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
min-width: 200rpx;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
|
|
.week_tabs {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
.week_tab {
|
|
flex: 1;
|
|
text-align: center;
|
|
padding: 16rpx 8rpx;
|
|
border-radius: 12rpx;
|
|
position: relative;
|
|
|
|
&.active {
|
|
background: #29D3B4;
|
|
color: #fff;
|
|
}
|
|
|
|
&.today {
|
|
background: rgba(41, 211, 180, 0.1);
|
|
|
|
&.active {
|
|
background: #29D3B4;
|
|
}
|
|
}
|
|
|
|
.tab_weekday {
|
|
font-size: 22rpx;
|
|
margin-bottom: 4rpx;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.tab_date {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.tab_indicator {
|
|
position: absolute;
|
|
bottom: 4rpx;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 6rpx;
|
|
height: 6rpx;
|
|
background: #ff4757;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 课程列表
|
|
.courses_section {
|
|
margin: 0 20rpx;
|
|
|
|
.loading_section, .empty_section {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 80rpx 32rpx;
|
|
text-align: center;
|
|
|
|
.loading_text, .empty_text {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.empty_icon {
|
|
font-size: 80rpx;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.empty_hint {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.courses_list {
|
|
.course_item {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx;
|
|
margin-bottom: 16rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20rpx;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
|
|
|
&.scheduled {
|
|
border-left: 4rpx solid #29D3B4;
|
|
}
|
|
|
|
&.completed {
|
|
background: #f8f9fa;
|
|
border-left: 4rpx solid #27ae60;
|
|
}
|
|
|
|
&.cancelled {
|
|
background: #f8f9fa;
|
|
border-left: 4rpx solid #e74c3c;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
&.leave_requested {
|
|
background: #f8f9fa;
|
|
border-left: 4rpx solid #f39c12;
|
|
}
|
|
|
|
.course_time {
|
|
min-width: 100rpx;
|
|
text-align: center;
|
|
|
|
.time_range {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 4rpx;
|
|
}
|
|
|
|
.time_duration {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.course_info {
|
|
flex: 1;
|
|
|
|
.course_name {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.course_details {
|
|
.detail_row {
|
|
display: flex;
|
|
margin-bottom: 6rpx;
|
|
|
|
.detail_label {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
min-width: 80rpx;
|
|
}
|
|
|
|
.detail_value {
|
|
font-size: 24rpx;
|
|
color: #333;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.course_status {
|
|
.status_badge {
|
|
font-size: 22rpx;
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 12rpx;
|
|
|
|
&.scheduled {
|
|
color: #29D3B4;
|
|
background: rgba(41, 211, 180, 0.1);
|
|
}
|
|
|
|
&.completed {
|
|
color: #27ae60;
|
|
background: rgba(39, 174, 96, 0.1);
|
|
}
|
|
|
|
&.cancelled {
|
|
color: #e74c3c;
|
|
background: rgba(231, 76, 60, 0.1);
|
|
}
|
|
|
|
&.leave_requested {
|
|
color: #f39c12;
|
|
background: rgba(243, 156, 18, 0.1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 课程详情弹窗
|
|
.course_popup {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 1000;
|
|
|
|
.popup_content {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
overflow: hidden;
|
|
|
|
.popup_header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 32rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.popup_title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.popup_close {
|
|
font-size: 48rpx;
|
|
color: #999;
|
|
font-weight: 300;
|
|
}
|
|
}
|
|
|
|
.popup_course_detail {
|
|
padding: 32rpx;
|
|
max-height: 60vh;
|
|
overflow-y: auto;
|
|
|
|
.detail_section {
|
|
margin-bottom: 32rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.section_title {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 16rpx;
|
|
padding-bottom: 8rpx;
|
|
border-bottom: 2rpx solid #29D3B4;
|
|
}
|
|
|
|
.info_grid {
|
|
.info_row {
|
|
display: flex;
|
|
margin-bottom: 12rpx;
|
|
|
|
.info_label {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
min-width: 120rpx;
|
|
}
|
|
|
|
.info_value {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.course_description {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.preparation_list {
|
|
.preparation_item {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
line-height: 1.5;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.popup_actions {
|
|
padding: 24rpx 32rpx;
|
|
display: flex;
|
|
gap: 16rpx;
|
|
border-top: 1px solid #f0f0f0;
|
|
|
|
fui-button {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|