智慧教务系统UniApp前端项目(使用中2025-0517)
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.
 
 
 
 
 

490 lines
11 KiB

<template>
<view class="detail-root">
<view class="header">
<view class="title">课程安排详情</view>
<view class="date">日期{{ course_info.course_date }} {{course_info.time_slot}}</view>
</view>
<view class="section">
<view class="section-title">学员列表</view>
<view class="student-list" v-if="course_info && course_info.available_capacity">
<!-- 显示已安排的学员 -->
<view
v-for="(stu, idx) in students"
:key="idx"
class="student-item"
@tap="viewStudent(stu)"
>
<view class="avatar">{{ stu.name && stu.name.charAt(0) }}</view>
<view class="info">
<view class="name">{{ stu.name }}</view>
<view class="desc">{{ getStatusText(stu.status) }}</view>
</view>
</view>
<!-- 显示空位 -->
<view
v-for="index in emptySeats"
:key="index"
class="student-item empty"
@tap="addStudent($event, index)"
>
<view class="avatar empty-avatar">+</view>
<view class="info">
<view class="name">空位</view>
<view class="desc">点击添加学员</view>
</view>
</view>
</view>
<!-- 没有数据时的占位区域 -->
<view class="empty-placeholder" v-else>
<image src="/static/icon-img/empty.png" mode="aspectFit"></image>
<text>暂无课程数据</text>
</view>
</view>
<!-- 请假原因弹窗 -->
<fui-modal ref="leaveReasonModal" :buttons="[]" width="600" title="请假申请">
<view class="leave-form">
<view class="leave-label">请假原因</view>
<view class="leave-input">
<fui-textarea v-model="leaveReason" placeholder="请输入请假原因" :isCounter="true" :maxlength="200" :minHeight="200" :isAutoHeight="true"></fui-textarea>
</view>
<view class="leave-buttons">
<fui-button background="#434544" color="#fff" borderColor="#666" btnSize="medium" @tap="$refs.leaveReasonModal.close()">取消</fui-button>
<fui-button background="#29d3b4" color="#fff" btnSize="medium" @tap="submitLeaveRequest">提交</fui-button>
</view>
</view>
</fui-modal>
</view>
</template>
<script>
import apiRoute from '@/api/apiRoute.js';
export default {
data() {
return {
course_id:'',
course_info:[],
date: '',
students: [
// {
// name: '张三',
// desc: '已签到'
// },
// {
// name: '李四',
// desc: '未签到'
// },
],
resource_id:'',
leaveReason: '', // 请假原因
currentStudent: null, // 当前操作的学生
emptySeats: [] // 空位数组
};
},
onLoad(query) {
console.log('onLoad 参数:', query);
this.course_id = query.id || '';
this.resource_id = query.resource_id
console.log('初始化参数 - course_id:', this.course_id, 'resource_id:', this.resource_id);
this.courseInfo();
},
methods: {
viewStudent(stu){
console.log(stu, this.course_info);
// 判断学员类型
if (stu.person_type === 'customer_resource') {
// 如果是客户资源,弹出确认取消课程的弹窗
uni.showModal({
title: '取消课程',
content: `是否取消学员 ${stu.name} 的课程?`,
success: async (res) => {
if (res.confirm) {
// 用户点击确定,调用schedule_del接口
try {
uni.showLoading({
title: '处理中...'
});
const params = {
resources_id: stu.resources_id,
id: this.course_info.id
};
const result = await apiRoute.schedule_del(params);
uni.hideLoading();
if (result.code === 1) {
uni.showToast({
title: '取消课程成功',
icon: 'success'
});
// 刷新数据
await this.courseInfo();
} else {
uni.showToast({
title: result.msg || '取消课程失败',
icon: 'none'
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '操作失败,请重试',
icon: 'none'
});
console.error('取消课程失败:', error);
}
}
}
});
} else if (stu.person_type === 'student') {
// 如果是学生,弹出请假原因输入框
this.$refs.leaveReasonModal.open();
this.currentStudent = stu; // 保存当前操作的学生信息
}
},
getStatusText(status) {
const statusMap = {
0: '待上课',
1: '已上课',
2: '请假'
};
return statusMap[status] || status;
},
async scheduleList() {
try {
console.log('开始获取学员列表, schedule_id:', this.course_id);
let res = await apiRoute.scheduleList({
'schedule_id': this.course_id
})
console.log('学员列表响应:', res);
if (res.code === 1 && Array.isArray(res.data)) {
// 确保学员列表按照位置排序
this.students = res.data.sort((a, b) => {
// 如果有position字段,按position排序
if (a.position !== undefined && b.position !== undefined) {
return parseInt(a.position) - parseInt(b.position);
}
// 否则按照ID排序
return a.id - b.id;
});
} else {
this.students = [];
}
// 更新可用容量
this.updateAvailableCapacity();
return this.students;
} catch (error) {
console.error('获取学员列表失败:', error);
this.students = [];
return [];
}
},
async courseInfo() {
try {
console.log('开始获取课程信息, id:', this.course_id);
let res = await apiRoute.courseInfo({
'id': this.course_id
})
console.log('课程信息响应:', res);
if (res.code === 1 && res.data) {
this.course_info = res.data;
// 获取学员列表
await this.scheduleList();
// 计算可用容量
this.updateAvailableCapacity();
} else {
uni.showToast({
title: res.msg || '获取课程信息失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取课程信息失败:', error);
uni.showToast({
title: '获取课程信息失败',
icon: 'none'
});
}
},
// 更新可用容量
updateAvailableCapacity() {
// 确保course_info和students都已加载
if (!this.course_info || !this.students) return;
console.log('更新可用容量 - 课程总容量:', this.course_info.available_capacity, '学员数量:', this.students.length);
// 计算已占用的位置数
const occupiedSeats = this.students.length;
// 获取课程总容量
const totalCapacity = parseInt(this.course_info.available_capacity) || 0;
// 计算可用容量
this.course_info.available_capacity = Math.max(0, totalCapacity - occupiedSeats);
console.log('计算后的可用容量:', this.course_info.available_capacity);
// 初始化空位数组
this.emptySeats = [];
for (let i = 1; i <= this.course_info.available_capacity; i++) {
this.emptySeats.push(i);
}
},
async addStudent(e, index) {
console.log('添加学员到位置:', index);
const data = {
'resources_id': this.resource_id,
'person_type': 'customer_resource',
'schedule_id': this.course_id,
'course_date': this.course_info.course_date,
'time_slot': this.course_info.time_slot,
'position': index // 添加位置信息
};
try {
uni.showLoading({
title: '添加中...'
});
let res = await apiRoute.addSchedule(data)
uni.hideLoading();
if(res.code == 1){
uni.showToast({
title: '添加成功',
icon: 'success'
});
// 刷新数据并更新可用容量
await this.courseInfo();
}else{
uni.showToast({
title: res.msg || '添加失败',
icon: 'none'
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '添加失败',
icon: 'none'
});
console.error('添加学员失败:', error);
}
},
// 提交请假申请
submitLeaveRequest() {
if (!this.leaveReason.trim()) {
uni.showToast({
title: '请填写请假原因',
icon: 'none'
});
return;
}
// 调用请假接口
uni.showLoading({
title: '提交中...'
});
// 构建请假参数
const params = {
resources_id: this.currentStudent.resources_id,
id: this.course_info.id,
remark: this.leaveReason
};
// 调用请假接口
apiRoute.schedule_del(params)
.then(res => {
uni.hideLoading();
if (res.code === 1) {
uni.showToast({
title: '请假申请提交成功',
icon: 'success'
});
this.$refs.leaveReasonModal.close();
this.leaveReason = ''; // 清空请假原因
// 刷新数据并更新可用容量
this.courseInfo().then(() => {
// 确保数据刷新后更新可用容量
this.updateAvailableCapacity();
});
} else {
uni.showToast({
title: res.msg || '请假申请提交失败',
icon: 'none'
});
}
})
.catch(err => {
uni.hideLoading();
uni.showToast({
title: '请假申请提交失败,请重试',
icon: 'none'
});
console.error('请假申请提交失败:', err);
});
},
},
};
</script>
<style lang="less" scoped>
.detail-root {
background: #232323;
min-height: 100vh;
padding-bottom: 30rpx;
}
.header {
padding: 40rpx 30rpx 20rpx 30rpx;
.title {
color: #fff;
font-size: 36rpx;
font-weight: bold;
}
.date {
color: #29d3b4;
font-size: 26rpx;
margin-top: 10rpx;
}
}
.section {
margin: 30rpx;
background: #434544;
border-radius: 16rpx;
padding: 30rpx 20rpx;
}
.section-title {
color: #ffd86b;
font-size: 28rpx;
margin-bottom: 20rpx;
}
.student-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.student-item {
background: #333;
border-radius: 12rpx;
display: flex;
align-items: center;
padding: 18rpx 24rpx;
min-width: 260rpx;
.avatar {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: #29d3b4;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
margin-right: 18rpx;
}
.info {
.name {
color: #fff;
font-size: 28rpx;
}
.desc {
color: #bdbdbd;
font-size: 22rpx;
margin-top: 4rpx;
}
}
&.empty {
border: 2rpx dashed #ffd86b;
background: #232323;
.avatar.empty-avatar {
background: #ffd86b;
color: #232323;
font-size: 36rpx;
}
.info .name {
color: #ffd86b;
}
.info .desc {
color: #ffd86b;
}
}
}
// 请假弹窗样式
.leave-form {
padding: 20rpx;
.leave-label {
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
}
.leave-input {
margin-bottom: 30rpx;
}
.leave-buttons {
display: flex;
justify-content: space-between;
gap: 20rpx;
.fui-button {
flex: 1;
}
}
}
/* 空数据占位区域样式 */
.empty-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
image {
width: 200rpx;
height: 200rpx;
margin-bottom: 20rpx;
}
text {
color: #999;
font-size: 28rpx;
}
}
</style>