12 changed files with 1741 additions and 389 deletions
@ -0,0 +1,474 @@ |
|||||
|
<template> |
||||
|
<view class="add-schedule-container"> |
||||
|
<uni-nav-bar |
||||
|
title="添加课程安排" |
||||
|
left-icon="left" |
||||
|
fixed="true" |
||||
|
background-color="#292929" |
||||
|
color="#FFFFFF" |
||||
|
@clickLeft="goBack" |
||||
|
></uni-nav-bar> |
||||
|
|
||||
|
<view class="form-container"> |
||||
|
<fui-form> |
||||
|
<!-- 课程选择 --> |
||||
|
<fui-form-item label="课程" required> |
||||
|
<view class="selector-input" @click="showCoursePicker = true"> |
||||
|
<text>{{ selectedCourse ? selectedCourse.course_name : '请选择课程' }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showCoursePicker" |
||||
|
:options="courseOptions" |
||||
|
valueKey="id" |
||||
|
textKey="course_name" |
||||
|
@confirm="onCourseSelect" |
||||
|
@cancel="showCoursePicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 班级选择 --> |
||||
|
<fui-form-item label="班级"> |
||||
|
<view class="selector-input" @click="showClassPicker = true"> |
||||
|
<text>{{ selectedClass ? selectedClass.class_name : '请选择班级(可选)' }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showClassPicker" |
||||
|
:options="classOptions" |
||||
|
valueKey="id" |
||||
|
textKey="class_name" |
||||
|
@confirm="onClassSelect" |
||||
|
@cancel="showClassPicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 教练选择 --> |
||||
|
<fui-form-item label="授课教练" required> |
||||
|
<view class="selector-input" @click="showCoachPicker = true"> |
||||
|
<text>{{ selectedCoach ? selectedCoach.name : '请选择教练' }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showCoachPicker" |
||||
|
:options="coachOptions" |
||||
|
valueKey="id" |
||||
|
textKey="name" |
||||
|
@confirm="onCoachSelect" |
||||
|
@cancel="showCoachPicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 场地选择 --> |
||||
|
<fui-form-item label="上课场地" required> |
||||
|
<view class="selector-input" @click="showVenuePicker = true"> |
||||
|
<text>{{ selectedVenue ? selectedVenue.venue_name : '请选择场地' }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showVenuePicker" |
||||
|
:options="venueOptions" |
||||
|
valueKey="id" |
||||
|
textKey="venue_name" |
||||
|
@confirm="onVenueSelect" |
||||
|
@cancel="showVenuePicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 日期选择 --> |
||||
|
<fui-form-item label="上课日期" required> |
||||
|
<view class="selector-input" @click="showDatePicker = true"> |
||||
|
<text>{{ formData.course_date || '请选择日期' }}</text> |
||||
|
<fui-icon name="calendar" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-date-picker |
||||
|
:show="showDatePicker" |
||||
|
@confirm="onDateSelect" |
||||
|
@cancel="showDatePicker = false" |
||||
|
:value="formData.course_date" |
||||
|
></fui-date-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 时间选择 --> |
||||
|
<fui-form-item label="上课时间" required> |
||||
|
<view class="selector-input" @click="showTimePicker = true"> |
||||
|
<text>{{ formData.time_slot || '请选择时间段' }}</text> |
||||
|
<fui-icon name="time" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showTimePicker" |
||||
|
:options="timeSlotOptions" |
||||
|
valueKey="value" |
||||
|
textKey="text" |
||||
|
@confirm="onTimeSelect" |
||||
|
@cancel="showTimePicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 容量设置 --> |
||||
|
<fui-form-item label="课程容量" required> |
||||
|
<fui-input |
||||
|
type="number" |
||||
|
:value="formData.available_capacity" |
||||
|
placeholder="请输入课程容量" |
||||
|
@input="formData.available_capacity = $event" |
||||
|
></fui-input> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 备注信息 --> |
||||
|
<fui-form-item label="备注"> |
||||
|
<fui-textarea |
||||
|
:value="formData.remark" |
||||
|
placeholder="请输入备注信息(可选)" |
||||
|
@input="formData.remark = $event" |
||||
|
maxlength="200" |
||||
|
></fui-textarea> |
||||
|
</fui-form-item> |
||||
|
</fui-form> |
||||
|
|
||||
|
<!-- 提交按钮 --> |
||||
|
<view class="btn-container"> |
||||
|
<fui-button type="primary" @click="submitForm" :loading="submitting">创建课程安排</fui-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import api from '@/api/apiRoute.js'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
// 表单数据 |
||||
|
formData: { |
||||
|
course_id: '', |
||||
|
class_id: '', |
||||
|
coach_id: '', |
||||
|
venue_id: '', |
||||
|
course_date: '', |
||||
|
time_slot: '', |
||||
|
available_capacity: '', |
||||
|
remark: '' |
||||
|
}, |
||||
|
|
||||
|
// 选择器数据 |
||||
|
showCoursePicker: false, |
||||
|
showClassPicker: false, |
||||
|
showCoachPicker: false, |
||||
|
showVenuePicker: false, |
||||
|
showDatePicker: false, |
||||
|
showTimePicker: false, |
||||
|
|
||||
|
// 选项数据 |
||||
|
courseOptions: [], |
||||
|
classOptions: [], |
||||
|
coachOptions: [], |
||||
|
venueOptions: [], |
||||
|
timeSlotOptions: [], |
||||
|
|
||||
|
// 选中的数据对象 |
||||
|
selectedCourse: null, |
||||
|
selectedClass: null, |
||||
|
selectedCoach: null, |
||||
|
selectedVenue: null, |
||||
|
|
||||
|
// 状态标记 |
||||
|
submitting: false, |
||||
|
|
||||
|
// 预填充数据 |
||||
|
prefillDate: '', |
||||
|
prefillTime: '', |
||||
|
prefillTimeSlot: '' |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
onLoad(options) { |
||||
|
// 从路由参数获取预填充数据 |
||||
|
if (options.date) { |
||||
|
this.prefillDate = options.date; |
||||
|
this.formData.course_date = options.date; |
||||
|
} |
||||
|
|
||||
|
if (options.time) { |
||||
|
this.prefillTime = options.time; |
||||
|
} |
||||
|
|
||||
|
if (options.time_slot) { |
||||
|
this.prefillTimeSlot = options.time_slot; |
||||
|
this.formData.time_slot = options.time_slot; |
||||
|
} |
||||
|
|
||||
|
// 加载初始数据 |
||||
|
this.loadFilterOptions(); |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 返回上一页 |
||||
|
goBack() { |
||||
|
uni.navigateBack(); |
||||
|
}, |
||||
|
|
||||
|
// 加载选项数据 |
||||
|
async loadFilterOptions() { |
||||
|
uni.showLoading({ |
||||
|
title: '加载数据中...' |
||||
|
}); |
||||
|
|
||||
|
try { |
||||
|
const res = await api.getCourseScheduleFilterOptions(); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
// 设置课程选项 |
||||
|
this.courseOptions = res.data.courses || []; |
||||
|
|
||||
|
// 设置班级选项 |
||||
|
this.classOptions = res.data.classes || []; |
||||
|
|
||||
|
// 设置教练选项 |
||||
|
this.coachOptions = res.data.coaches || []; |
||||
|
|
||||
|
// 设置场地选项 |
||||
|
this.venueOptions = res.data.venues || []; |
||||
|
|
||||
|
// 生成时间段选项 |
||||
|
this.generateTimeSlotOptions(); |
||||
|
|
||||
|
// 如果有预填充时间段,设置选中的时间段 |
||||
|
if (this.prefillTimeSlot) { |
||||
|
this.formData.time_slot = this.prefillTimeSlot; |
||||
|
} |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '加载筛选选项失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('加载筛选选项失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '加载筛选选项失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
uni.hideLoading(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 生成时间段选项 |
||||
|
generateTimeSlotOptions() { |
||||
|
const timeSlots = []; |
||||
|
|
||||
|
// 早上时间段 |
||||
|
for (let hour = 8; hour < 12; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 下午时间段 |
||||
|
for (let hour = 12; hour < 18; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 晚上时间段 |
||||
|
for (let hour = 18; hour < 22; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
this.timeSlotOptions = timeSlots; |
||||
|
}, |
||||
|
|
||||
|
// 选择器处理方法 |
||||
|
onCourseSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.courseOptions.length) { |
||||
|
this.selectedCourse = this.courseOptions[index]; |
||||
|
this.formData.course_id = this.selectedCourse.id; |
||||
|
} |
||||
|
this.showCoursePicker = false; |
||||
|
}, |
||||
|
|
||||
|
onClassSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.classOptions.length) { |
||||
|
this.selectedClass = this.classOptions[index]; |
||||
|
this.formData.class_id = this.selectedClass.id; |
||||
|
} else { |
||||
|
this.selectedClass = null; |
||||
|
this.formData.class_id = ''; |
||||
|
} |
||||
|
this.showClassPicker = false; |
||||
|
}, |
||||
|
|
||||
|
onCoachSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.coachOptions.length) { |
||||
|
this.selectedCoach = this.coachOptions[index]; |
||||
|
this.formData.coach_id = this.selectedCoach.id; |
||||
|
} |
||||
|
this.showCoachPicker = false; |
||||
|
}, |
||||
|
|
||||
|
onVenueSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.venueOptions.length) { |
||||
|
this.selectedVenue = this.venueOptions[index]; |
||||
|
this.formData.venue_id = this.selectedVenue.id; |
||||
|
|
||||
|
// 如果场地有默认容量,设置容量 |
||||
|
if (this.selectedVenue.capacity) { |
||||
|
this.formData.available_capacity = this.selectedVenue.capacity; |
||||
|
} |
||||
|
} |
||||
|
this.showVenuePicker = false; |
||||
|
}, |
||||
|
|
||||
|
onDateSelect(e) { |
||||
|
this.formData.course_date = e.result; |
||||
|
this.showDatePicker = false; |
||||
|
}, |
||||
|
|
||||
|
onTimeSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.timeSlotOptions.length) { |
||||
|
this.formData.time_slot = this.timeSlotOptions[index].value; |
||||
|
} |
||||
|
this.showTimePicker = false; |
||||
|
}, |
||||
|
|
||||
|
// 表单验证 |
||||
|
validateForm() { |
||||
|
if (!this.formData.course_id) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择课程', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.coach_id) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择授课教练', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.venue_id) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择上课场地', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.course_date) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择上课日期', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.time_slot) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择上课时间', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.available_capacity) { |
||||
|
uni.showToast({ |
||||
|
title: '请输入课程容量', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// 提交表单 |
||||
|
async submitForm() { |
||||
|
if (!this.validateForm()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
this.submitting = true; |
||||
|
|
||||
|
try { |
||||
|
const res = await api.createCourseSchedule(this.formData); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
uni.showToast({ |
||||
|
title: '创建成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
|
||||
|
// 延迟返回,让用户看到成功提示 |
||||
|
setTimeout(() => { |
||||
|
uni.navigateBack(); |
||||
|
}, 1500); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '创建失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('创建课程安排失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '创建失败,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
this.submitting = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.add-schedule-container { |
||||
|
min-height: 100vh; |
||||
|
background-color: #18181c; |
||||
|
padding-top: 88rpx; |
||||
|
} |
||||
|
|
||||
|
.form-container { |
||||
|
padding: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.selector-input { |
||||
|
height: 80rpx; |
||||
|
background-color: #23232a; |
||||
|
border-radius: 8rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 0 24rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.btn-container { |
||||
|
margin-top: 60rpx; |
||||
|
padding: 0 30rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,497 @@ |
|||||
|
<template> |
||||
|
<view class="adjust-course-container"> |
||||
|
<uni-nav-bar |
||||
|
title="调整课程安排" |
||||
|
left-icon="left" |
||||
|
fixed="true" |
||||
|
background-color="#292929" |
||||
|
color="#FFFFFF" |
||||
|
@clickLeft="goBack" |
||||
|
></uni-nav-bar> |
||||
|
|
||||
|
<view class="form-container"> |
||||
|
<view v-if="loading" class="loading-container"> |
||||
|
<fui-loading></fui-loading> |
||||
|
<text class="loading-text">加载中...</text> |
||||
|
</view> |
||||
|
|
||||
|
<fui-form v-else> |
||||
|
<!-- 课程信息 --> |
||||
|
<view class="section-title">当前课程信息</view> |
||||
|
<view class="course-info-card"> |
||||
|
<view class="info-row"> |
||||
|
<text class="info-label">课程名称:</text> |
||||
|
<text class="info-value">{{ scheduleInfo.course_name }}</text> |
||||
|
</view> |
||||
|
<view class="info-row"> |
||||
|
<text class="info-label">上课日期:</text> |
||||
|
<text class="info-value">{{ scheduleInfo.course_date }}</text> |
||||
|
</view> |
||||
|
<view class="info-row"> |
||||
|
<text class="info-label">上课时间:</text> |
||||
|
<text class="info-value">{{ scheduleInfo.time_slot }}</text> |
||||
|
</view> |
||||
|
<view class="info-row"> |
||||
|
<text class="info-label">授课教练:</text> |
||||
|
<text class="info-value">{{ scheduleInfo.coach_name }}</text> |
||||
|
</view> |
||||
|
<view class="info-row"> |
||||
|
<text class="info-label">上课场地:</text> |
||||
|
<text class="info-value">{{ scheduleInfo.venue_name }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="section-title">调整后信息</view> |
||||
|
|
||||
|
<!-- 教练选择 --> |
||||
|
<fui-form-item label="授课教练"> |
||||
|
<view class="selector-input" @click="showCoachPicker = true"> |
||||
|
<text>{{ selectedCoach ? selectedCoach.name : scheduleInfo.coach_name }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showCoachPicker" |
||||
|
:options="coachOptions" |
||||
|
valueKey="id" |
||||
|
textKey="name" |
||||
|
@confirm="onCoachSelect" |
||||
|
@cancel="showCoachPicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 场地选择 --> |
||||
|
<fui-form-item label="上课场地"> |
||||
|
<view class="selector-input" @click="showVenuePicker = true"> |
||||
|
<text>{{ selectedVenue ? selectedVenue.venue_name : scheduleInfo.venue_name }}</text> |
||||
|
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showVenuePicker" |
||||
|
:options="venueOptions" |
||||
|
valueKey="id" |
||||
|
textKey="venue_name" |
||||
|
@confirm="onVenueSelect" |
||||
|
@cancel="showVenuePicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 日期选择 --> |
||||
|
<fui-form-item label="上课日期"> |
||||
|
<view class="selector-input" @click="showDatePicker = true"> |
||||
|
<text>{{ formData.course_date || scheduleInfo.course_date }}</text> |
||||
|
<fui-icon name="calendar" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-date-picker |
||||
|
:show="showDatePicker" |
||||
|
@confirm="onDateSelect" |
||||
|
@cancel="showDatePicker = false" |
||||
|
:value="formData.course_date || scheduleInfo.course_date" |
||||
|
></fui-date-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 时间选择 --> |
||||
|
<fui-form-item label="上课时间"> |
||||
|
<view class="selector-input" @click="showTimePicker = true"> |
||||
|
<text>{{ formData.time_slot || scheduleInfo.time_slot }}</text> |
||||
|
<fui-icon name="time" :size="32" color="#CCCCCC"></fui-icon> |
||||
|
</view> |
||||
|
<fui-picker |
||||
|
:show="showTimePicker" |
||||
|
:options="timeSlotOptions" |
||||
|
valueKey="value" |
||||
|
textKey="text" |
||||
|
@confirm="onTimeSelect" |
||||
|
@cancel="showTimePicker = false" |
||||
|
></fui-picker> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 容量设置 --> |
||||
|
<fui-form-item label="课程容量"> |
||||
|
<fui-input |
||||
|
type="number" |
||||
|
:value="formData.available_capacity || scheduleInfo.available_capacity" |
||||
|
placeholder="请输入课程容量" |
||||
|
@input="formData.available_capacity = $event" |
||||
|
></fui-input> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 调整原因 --> |
||||
|
<fui-form-item label="调整原因" required> |
||||
|
<fui-textarea |
||||
|
:value="formData.adjust_reason" |
||||
|
placeholder="请输入调整原因" |
||||
|
@input="formData.adjust_reason = $event" |
||||
|
maxlength="200" |
||||
|
></fui-textarea> |
||||
|
</fui-form-item> |
||||
|
|
||||
|
<!-- 提交按钮 --> |
||||
|
<view class="btn-container"> |
||||
|
<fui-button type="primary" @click="submitForm" :loading="submitting">确认调整</fui-button> |
||||
|
</view> |
||||
|
</fui-form> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import api from '@/api/apiRoute.js'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
// 状态标记 |
||||
|
loading: true, |
||||
|
submitting: false, |
||||
|
|
||||
|
// 课程ID |
||||
|
scheduleId: null, |
||||
|
|
||||
|
// 课程信息 |
||||
|
scheduleInfo: {}, |
||||
|
|
||||
|
// 表单数据 |
||||
|
formData: { |
||||
|
schedule_id: '', |
||||
|
coach_id: '', |
||||
|
venue_id: '', |
||||
|
course_date: '', |
||||
|
time_slot: '', |
||||
|
available_capacity: '', |
||||
|
adjust_reason: '' |
||||
|
}, |
||||
|
|
||||
|
// 选择器数据 |
||||
|
showCoachPicker: false, |
||||
|
showVenuePicker: false, |
||||
|
showDatePicker: false, |
||||
|
showTimePicker: false, |
||||
|
|
||||
|
// 选项数据 |
||||
|
coachOptions: [], |
||||
|
venueOptions: [], |
||||
|
timeSlotOptions: [], |
||||
|
|
||||
|
// 选中的数据对象 |
||||
|
selectedCoach: null, |
||||
|
selectedVenue: null |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
onLoad(options) { |
||||
|
if (options.id) { |
||||
|
this.scheduleId = options.id; |
||||
|
this.formData.schedule_id = options.id; |
||||
|
this.loadScheduleInfo(); |
||||
|
this.loadFilterOptions(); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: '参数错误', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
setTimeout(() => { |
||||
|
uni.navigateBack(); |
||||
|
}, 1500); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 返回上一页 |
||||
|
goBack() { |
||||
|
uni.navigateBack(); |
||||
|
}, |
||||
|
|
||||
|
// 加载课程安排信息 |
||||
|
async loadScheduleInfo() { |
||||
|
try { |
||||
|
const res = await api.getCourseScheduleInfo({ schedule_id: this.scheduleId }); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
this.scheduleInfo = res.data; |
||||
|
|
||||
|
// 初始化表单数据 |
||||
|
this.formData.coach_id = this.scheduleInfo.coach_id; |
||||
|
this.formData.venue_id = this.scheduleInfo.venue_id; |
||||
|
this.formData.course_date = this.scheduleInfo.course_date; |
||||
|
this.formData.time_slot = this.scheduleInfo.time_slot; |
||||
|
this.formData.available_capacity = this.scheduleInfo.available_capacity; |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '获取课程安排信息失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('获取课程安排信息失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '获取课程安排信息失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载选项数据 |
||||
|
async loadFilterOptions() { |
||||
|
try { |
||||
|
const res = await api.getCourseScheduleFilterOptions(); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
// 设置教练选项 |
||||
|
this.coachOptions = res.data.coaches || []; |
||||
|
|
||||
|
// 设置场地选项 |
||||
|
this.venueOptions = res.data.venues || []; |
||||
|
|
||||
|
// 生成时间段选项 |
||||
|
this.generateTimeSlotOptions(); |
||||
|
|
||||
|
// 找到当前选中的教练和场地 |
||||
|
this.findSelectedOptions(); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '加载筛选选项失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('加载筛选选项失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '加载筛选选项失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 查找当前选中的选项 |
||||
|
findSelectedOptions() { |
||||
|
// 查找当前教练 |
||||
|
if (this.scheduleInfo.coach_id) { |
||||
|
this.selectedCoach = this.coachOptions.find(coach => coach.id === this.scheduleInfo.coach_id); |
||||
|
} |
||||
|
|
||||
|
// 查找当前场地 |
||||
|
if (this.scheduleInfo.venue_id) { |
||||
|
this.selectedVenue = this.venueOptions.find(venue => venue.id === this.scheduleInfo.venue_id); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 生成时间段选项 |
||||
|
generateTimeSlotOptions() { |
||||
|
const timeSlots = []; |
||||
|
|
||||
|
// 早上时间段 |
||||
|
for (let hour = 8; hour < 12; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 下午时间段 |
||||
|
for (let hour = 12; hour < 18; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 晚上时间段 |
||||
|
for (let hour = 18; hour < 22; hour++) { |
||||
|
const startHour = hour.toString().padStart(2, '0'); |
||||
|
const endHour = (hour + 1).toString().padStart(2, '0'); |
||||
|
timeSlots.push({ |
||||
|
value: `${startHour}:00-${endHour}:00`, |
||||
|
text: `${startHour}:00-${endHour}:00` |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
this.timeSlotOptions = timeSlots; |
||||
|
}, |
||||
|
|
||||
|
// 选择器处理方法 |
||||
|
onCoachSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.coachOptions.length) { |
||||
|
this.selectedCoach = this.coachOptions[index]; |
||||
|
this.formData.coach_id = this.selectedCoach.id; |
||||
|
} |
||||
|
this.showCoachPicker = false; |
||||
|
}, |
||||
|
|
||||
|
onVenueSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.venueOptions.length) { |
||||
|
this.selectedVenue = this.venueOptions[index]; |
||||
|
this.formData.venue_id = this.selectedVenue.id; |
||||
|
|
||||
|
// 如果场地有默认容量,设置容量 |
||||
|
if (this.selectedVenue.capacity && !this.formData.available_capacity) { |
||||
|
this.formData.available_capacity = this.selectedVenue.capacity; |
||||
|
} |
||||
|
} |
||||
|
this.showVenuePicker = false; |
||||
|
}, |
||||
|
|
||||
|
onDateSelect(e) { |
||||
|
this.formData.course_date = e.result; |
||||
|
this.showDatePicker = false; |
||||
|
}, |
||||
|
|
||||
|
onTimeSelect(e) { |
||||
|
const index = e.index; |
||||
|
if (index >= 0 && index < this.timeSlotOptions.length) { |
||||
|
this.formData.time_slot = this.timeSlotOptions[index].value; |
||||
|
} |
||||
|
this.showTimePicker = false; |
||||
|
}, |
||||
|
|
||||
|
// 表单验证 |
||||
|
validateForm() { |
||||
|
// 检查是否有任何修改 |
||||
|
const hasChanges = this.formData.coach_id !== this.scheduleInfo.coach_id || |
||||
|
this.formData.venue_id !== this.scheduleInfo.venue_id || |
||||
|
this.formData.course_date !== this.scheduleInfo.course_date || |
||||
|
this.formData.time_slot !== this.scheduleInfo.time_slot || |
||||
|
this.formData.available_capacity !== this.scheduleInfo.available_capacity; |
||||
|
|
||||
|
if (!hasChanges) { |
||||
|
uni.showToast({ |
||||
|
title: '未进行任何修改', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!this.formData.adjust_reason) { |
||||
|
uni.showToast({ |
||||
|
title: '请输入调整原因', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}, |
||||
|
|
||||
|
// 提交表单 |
||||
|
async submitForm() { |
||||
|
if (!this.validateForm()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
this.submitting = true; |
||||
|
|
||||
|
try { |
||||
|
const res = await api.updateCourseSchedule(this.formData); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
uni.showToast({ |
||||
|
title: '调整成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
|
||||
|
// 延迟返回,让用户看到成功提示 |
||||
|
setTimeout(() => { |
||||
|
uni.navigateBack(); |
||||
|
}, 1500); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '调整失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('调整课程安排失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '调整失败,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
this.submitting = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.adjust-course-container { |
||||
|
min-height: 100vh; |
||||
|
background-color: #18181c; |
||||
|
padding-top: 88rpx; |
||||
|
} |
||||
|
|
||||
|
.form-container { |
||||
|
padding: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.loading-container { |
||||
|
height: 200rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.loading-text { |
||||
|
margin-top: 20rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #29d3b4; |
||||
|
margin: 30rpx 0 20rpx; |
||||
|
padding-bottom: 10rpx; |
||||
|
border-bottom: 1px solid #333; |
||||
|
} |
||||
|
|
||||
|
.course-info-card { |
||||
|
background-color: #23232a; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 20rpx; |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.info-row { |
||||
|
display: flex; |
||||
|
margin-bottom: 16rpx; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.info-label { |
||||
|
color: #999; |
||||
|
width: 160rpx; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.info-value { |
||||
|
color: #fff; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.selector-input { |
||||
|
height: 80rpx; |
||||
|
background-color: #23232a; |
||||
|
border-radius: 8rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 0 24rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.btn-container { |
||||
|
margin-top: 60rpx; |
||||
|
padding: 0 30rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,511 @@ |
|||||
|
<template> |
||||
|
<view class="sign-in-container"> |
||||
|
<uni-nav-bar |
||||
|
title="课程点名" |
||||
|
left-icon="left" |
||||
|
fixed="true" |
||||
|
background-color="#292929" |
||||
|
color="#FFFFFF" |
||||
|
@clickLeft="goBack" |
||||
|
></uni-nav-bar> |
||||
|
|
||||
|
<view class="content"> |
||||
|
<!-- 课程信息 --> |
||||
|
<view class="course-info-card" v-if="scheduleInfo"> |
||||
|
<view class="course-title">{{ scheduleInfo.course_name }}</view> |
||||
|
<view class="course-time">{{ scheduleInfo.course_date }} {{ scheduleInfo.time_slot }}</view> |
||||
|
<view class="course-detail"> |
||||
|
<view class="detail-item"> |
||||
|
<text class="detail-label">授课教练:</text> |
||||
|
<text class="detail-value">{{ scheduleInfo.coach_name }}</text> |
||||
|
</view> |
||||
|
<view class="detail-item"> |
||||
|
<text class="detail-label">上课场地:</text> |
||||
|
<text class="detail-value">{{ scheduleInfo.venue_name }}</text> |
||||
|
</view> |
||||
|
<view class="detail-item"> |
||||
|
<text class="detail-label">学员人数:</text> |
||||
|
<text class="detail-value">{{ studentList.length }}人</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 学员列表 --> |
||||
|
<view class="student-section"> |
||||
|
<view class="section-header"> |
||||
|
<view class="section-title">学员点名</view> |
||||
|
<view class="action-buttons"> |
||||
|
<fui-button type="primary" size="small" @click="checkAllStudents">全部签到</fui-button> |
||||
|
<fui-button type="danger" size="small" @click="uncheckAllStudents">全部取消</fui-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="empty-list" v-if="studentList.length === 0"> |
||||
|
<image src="/static/icon-img/empty.png" mode="aspectFit" class="empty-img"></image> |
||||
|
<text class="empty-text">暂无学员数据</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="student-list" v-else> |
||||
|
<view |
||||
|
class="student-item" |
||||
|
v-for="(student, index) in studentList" |
||||
|
:key="index" |
||||
|
@click="toggleStudentStatus(index)" |
||||
|
> |
||||
|
<view class="student-avatar"> |
||||
|
<image :src="student.avatar || '/static/icon-img/avatar.png'" mode="aspectFill"></image> |
||||
|
<view class="status-badge" :class="getStatusClass(student.status)"></view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="student-info"> |
||||
|
<text class="student-name">{{ student.name }}</text> |
||||
|
<text class="student-phone">{{ student.phone_number || '无联系电话' }}</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="status-container"> |
||||
|
<view class="status-select"> |
||||
|
<view |
||||
|
class="status-option" |
||||
|
:class="{ active: student.status === 1 }" |
||||
|
@click.stop="setStudentStatus(index, 1)" |
||||
|
> |
||||
|
已到 |
||||
|
</view> |
||||
|
<view |
||||
|
class="status-option" |
||||
|
:class="{ active: student.status === 2 }" |
||||
|
@click.stop="setStudentStatus(index, 2)" |
||||
|
> |
||||
|
请假 |
||||
|
</view> |
||||
|
<view |
||||
|
class="status-option" |
||||
|
:class="{ active: student.status === 0 }" |
||||
|
@click.stop="setStudentStatus(index, 0)" |
||||
|
> |
||||
|
未到 |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 点名备注 --> |
||||
|
<view class="remark-section"> |
||||
|
<view class="section-title">点名备注</view> |
||||
|
<fui-textarea |
||||
|
v-model="signInRemark" |
||||
|
placeholder="请输入点名备注(可选)" |
||||
|
maxlength="200" |
||||
|
></fui-textarea> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 提交按钮 --> |
||||
|
<view class="submit-btn"> |
||||
|
<fui-button type="primary" @click="submitSignIn" :loading="submitting">提交点名</fui-button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import api from '@/api/apiRoute.js'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
// 课程ID |
||||
|
scheduleId: null, |
||||
|
|
||||
|
// 课程信息 |
||||
|
scheduleInfo: null, |
||||
|
|
||||
|
// 学员列表 |
||||
|
studentList: [], |
||||
|
|
||||
|
// 点名备注 |
||||
|
signInRemark: '', |
||||
|
|
||||
|
// 提交状态 |
||||
|
submitting: false |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
onLoad(options) { |
||||
|
if (options.id) { |
||||
|
this.scheduleId = options.id; |
||||
|
this.loadScheduleInfo(); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: '参数错误', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
setTimeout(() => { |
||||
|
uni.navigateBack(); |
||||
|
}, 1500); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 返回上一页 |
||||
|
goBack() { |
||||
|
uni.navigateBack(); |
||||
|
}, |
||||
|
|
||||
|
// 加载课程安排信息 |
||||
|
async loadScheduleInfo() { |
||||
|
uni.showLoading({ |
||||
|
title: '加载中...' |
||||
|
}); |
||||
|
|
||||
|
try { |
||||
|
const res = await api.getCourseScheduleInfo({ schedule_id: this.scheduleId }); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
this.scheduleInfo = res.data; |
||||
|
|
||||
|
// 处理学员列表 |
||||
|
if (this.scheduleInfo.students && this.scheduleInfo.students.length > 0) { |
||||
|
this.studentList = [...this.scheduleInfo.students]; |
||||
|
} |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '获取课程安排信息失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('获取课程安排信息失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '获取课程安排信息失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
uni.hideLoading(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 获取学员状态样式 |
||||
|
getStatusClass(status) { |
||||
|
const statusMap = { |
||||
|
0: 'status-absent', |
||||
|
1: 'status-present', |
||||
|
2: 'status-leave' |
||||
|
}; |
||||
|
|
||||
|
return statusMap[status] || 'status-absent'; |
||||
|
}, |
||||
|
|
||||
|
// 切换学员状态 |
||||
|
toggleStudentStatus(index) { |
||||
|
const student = this.studentList[index]; |
||||
|
|
||||
|
// 状态循环:未到 -> 已到 -> 请假 -> 未到 |
||||
|
let newStatus = 0; |
||||
|
|
||||
|
if (student.status === 0) { |
||||
|
newStatus = 1; |
||||
|
} else if (student.status === 1) { |
||||
|
newStatus = 2; |
||||
|
} else { |
||||
|
newStatus = 0; |
||||
|
} |
||||
|
|
||||
|
this.setStudentStatus(index, newStatus); |
||||
|
}, |
||||
|
|
||||
|
// 设置学员状态 |
||||
|
setStudentStatus(index, status) { |
||||
|
if (index >= 0 && index < this.studentList.length) { |
||||
|
this.studentList[index].status = status; |
||||
|
|
||||
|
// 更新状态文本 |
||||
|
const statusTextMap = { |
||||
|
0: '待上课', |
||||
|
1: '已上课', |
||||
|
2: '请假' |
||||
|
}; |
||||
|
|
||||
|
this.studentList[index].status_text = statusTextMap[status]; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 全部签到 |
||||
|
checkAllStudents() { |
||||
|
this.studentList.forEach((student, index) => { |
||||
|
this.setStudentStatus(index, 1); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 全部取消 |
||||
|
uncheckAllStudents() { |
||||
|
this.studentList.forEach((student, index) => { |
||||
|
this.setStudentStatus(index, 0); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 提交点名 |
||||
|
async submitSignIn() { |
||||
|
// 准备提交数据 |
||||
|
const studentData = this.studentList.map(student => ({ |
||||
|
student_id: student.student_id, |
||||
|
resource_id: student.resource_id, |
||||
|
status: student.status |
||||
|
})); |
||||
|
|
||||
|
const submitData = { |
||||
|
schedule_id: this.scheduleId, |
||||
|
students: studentData, |
||||
|
remark: this.signInRemark |
||||
|
}; |
||||
|
|
||||
|
this.submitting = true; |
||||
|
|
||||
|
try { |
||||
|
// 使用API进行点名 |
||||
|
const res = await api.submitScheduleSignIn(submitData); |
||||
|
|
||||
|
if (res.code === 1) { |
||||
|
uni.showToast({ |
||||
|
title: '点名成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
|
||||
|
// 延迟返回 |
||||
|
setTimeout(() => { |
||||
|
uni.navigateBack(); |
||||
|
}, 1500); |
||||
|
} else { |
||||
|
uni.showToast({ |
||||
|
title: res.msg || '点名失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('点名失败:', error); |
||||
|
uni.showToast({ |
||||
|
title: '点名失败,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} finally { |
||||
|
this.submitting = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.sign-in-container { |
||||
|
min-height: 100vh; |
||||
|
background-color: #18181c; |
||||
|
padding-top: 88rpx; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
padding: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.course-info-card { |
||||
|
background-color: #23232a; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 24rpx; |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.course-title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #fff; |
||||
|
margin-bottom: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.course-time { |
||||
|
font-size: 26rpx; |
||||
|
color: #29d3b4; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.course-detail { |
||||
|
background-color: #2a2a2a; |
||||
|
border-radius: 8rpx; |
||||
|
padding: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.detail-item { |
||||
|
display: flex; |
||||
|
margin-bottom: 10rpx; |
||||
|
font-size: 26rpx; |
||||
|
|
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.detail-label { |
||||
|
color: #999; |
||||
|
width: 140rpx; |
||||
|
} |
||||
|
|
||||
|
.detail-value { |
||||
|
color: #fff; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.student-section { |
||||
|
background-color: #23232a; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 24rpx; |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.section-header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 30rpx; |
||||
|
font-weight: bold; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.action-buttons { |
||||
|
display: flex; |
||||
|
gap: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.student-list { |
||||
|
max-height: 600rpx; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.student-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
background-color: #2a2a2a; |
||||
|
border-radius: 8rpx; |
||||
|
padding: 16rpx; |
||||
|
margin-bottom: 16rpx; |
||||
|
|
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.student-avatar { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
border-radius: 40rpx; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
margin-right: 20rpx; |
||||
|
|
||||
|
image { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.status-badge { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
right: 0; |
||||
|
width: 24rpx; |
||||
|
height: 24rpx; |
||||
|
border-radius: 12rpx; |
||||
|
background-color: #999; |
||||
|
border: 2rpx solid #fff; |
||||
|
} |
||||
|
|
||||
|
.status-absent { |
||||
|
background-color: #ff3b30; |
||||
|
} |
||||
|
|
||||
|
.status-present { |
||||
|
background-color: #34c759; |
||||
|
} |
||||
|
|
||||
|
.status-leave { |
||||
|
background-color: #ff9500; |
||||
|
} |
||||
|
|
||||
|
.student-info { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.student-name { |
||||
|
font-size: 28rpx; |
||||
|
color: #fff; |
||||
|
margin-bottom: 6rpx; |
||||
|
} |
||||
|
|
||||
|
.student-phone { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.status-container { |
||||
|
margin-left: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.status-select { |
||||
|
display: flex; |
||||
|
gap: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.status-option { |
||||
|
padding: 8rpx 16rpx; |
||||
|
font-size: 24rpx; |
||||
|
border-radius: 30rpx; |
||||
|
background-color: #3a3a3a; |
||||
|
color: #fff; |
||||
|
|
||||
|
&.active { |
||||
|
background-color: #29d3b4; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.empty-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 60rpx 0; |
||||
|
|
||||
|
.empty-img { |
||||
|
width: 200rpx; |
||||
|
height: 200rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.empty-text { |
||||
|
font-size: 28rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.remark-section { |
||||
|
background-color: #23232a; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 24rpx; |
||||
|
margin-bottom: 40rpx; |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 30rpx; |
||||
|
font-weight: bold; |
||||
|
color: #fff; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.submit-btn { |
||||
|
margin-top: 40rpx; |
||||
|
padding-bottom: 40rpx; |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue