作为一名长期奋战在教育信息化一线的开发者,我深知传统手工排课给教务人员带来的痛苦。记得去年帮某高校升级系统时,看到教务处的老师还在用Excel表格手动排课,经常因为时间冲突不得不反复调整,一个学期的课表往往要折腾半个月才能定稿。这种低效的现状促使我开发了这套基于SpringBoot+Vue的课表管理系统。
这套系统采用前后端分离架构,后端使用SpringBoot提供RESTful API接口,前端基于Vue.js构建交互界面,数据库选用MySQL配合MyBatis实现数据持久化。系统最核心的价值在于实现了课表生成的自动化,通过智能算法自动检测时间、教室、教师等多维度的冲突,将原本需要数周的手工排课过程缩短到几分钟内完成。
选择SpringBoot作为后端框架主要基于以下几点考虑:
数据库选用MySQL 8.0版本,主要看中其:
Vue.js 3.x + Element Plus的组合为我们带来了:
特别值得一提的是,我们使用ECharts实现了课表的可视化展示,支持:
排课算法的核心逻辑如下:
java复制public class SchedulingAlgorithm {
// 基于贪心算法实现的基础排课
public List<Schedule> autoSchedule(List<Course> courses,
List<Teacher> teachers,
List<Classroom> classrooms) {
// 1. 按课程优先级排序(必修课优先)
courses.sort(Comparator.comparingInt(c ->
"必修".equals(c.getCourseType()) ? 0 : 1));
// 2. 遍历课程进行排课
List<Schedule> result = new ArrayList<>();
for (Course course : courses) {
// 3. 寻找合适的时间段和教室
for (int day = 1; day <= 7; day++) {
for (String slot : TIME_SLOTS) {
// 4. 检查冲突
if (!hasConflict(course, day, slot, teachers, classrooms)) {
// 5. 创建排课记录
Schedule schedule = new Schedule();
schedule.setCourseId(course.getId());
schedule.setWeekDay(day);
schedule.setTimeSlot(slot);
// ...其他属性设置
result.add(schedule);
break;
}
}
}
}
return result;
}
}
注意事项:实际项目中我们采用了更复杂的冲突检测算法,需要考虑:
- 教师同一时间段只能上一门课
- 教室容量需匹配课程人数
- 特殊课程对教室设备的要求
系统包含30+数据表,核心表结构如下:
sql复制CREATE TABLE `schedule_plan_data` (
`schedule_id` int NOT NULL AUTO_INCREMENT,
`course_id` int NOT NULL COMMENT '关联课程ID',
`teacher_id` int NOT NULL COMMENT '关联教师ID',
`classroom_code` varchar(20) NOT NULL COMMENT '教室编号',
`week_day` tinyint NOT NULL COMMENT '星期几(1-7)',
`time_slot` varchar(20) NOT NULL COMMENT '时间段',
`semester` varchar(50) NOT NULL COMMENT '学期',
`generate_time` datetime NOT NULL COMMENT '生成时间',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态(0未确认1已确认)',
PRIMARY KEY (`schedule_id`),
UNIQUE KEY `idx_unique` (`course_id`,`teacher_id`,`week_day`,`time_slot`,`semester`),
KEY `idx_teacher` (`teacher_id`,`semester`),
KEY `idx_classroom` (`classroom_code`,`semester`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
初期版本在高并发排课时出现数据不一致问题,解决方案:
java复制@Update("UPDATE schedule_plan_data SET status=#{status}, version=version+1
WHERE schedule_id=#{id} AND version=#{version}")
int updateWithVersion(Schedule schedule);
java复制public boolean tryScheduleLock(String lockKey, long expireTime) {
String value = UUID.randomUUID().toString();
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(lockKey, value, expireTime, TimeUnit.SECONDS);
return Boolean.TRUE.equals(result);
}
当处理全校课表(约5000+课程记录)时,最初版本的排课算法需要近10分钟。通过以下优化降至30秒内:
使用Vue+ECharts实现的周课表组件核心代码:
vue复制<template>
<div ref="chart" class="timetable-chart"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
props: ['scheduleData'],
mounted() {
this.initChart();
},
methods: {
initChart() {
const chart = echarts.init(this.$refs.chart);
const option = {
tooltip: { /*...*/ },
calendar: {
top: 'middle',
left: 'center',
/* 周视图配置 */
},
series: [{
type: 'custom',
renderItem: (params, api) => {
// 自定义渲染每个课程方块
return {
type: 'rect',
shape: {
x: api.value(0),
y: api.value(1),
width: api.value(2),
height: api.value(3)
},
style: {
fill: this.getCourseColor(api.value(4))
}
};
},
data: this.processScheduleData()
}]
};
chart.setOption(option);
}
}
};
</script>
推荐部署方案:
关键JVM参数配置示例:
code复制-server -Xms2g -Xmx2g -XX:MaxMetaspaceSize=512m
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
我们采用Prometheus+Grafana搭建监控系统,主要监控指标包括:
在实际使用中,我们发现系统还可以在以下方面进行增强:
一个特别实用的改进是增加了"临时调课"功能,允许教务人员在紧急情况下快速调整课表,系统会自动通知相关师生并处理由此产生的连锁影响。这个功能在疫情期间发挥了巨大作用,帮助学校快速应对各种突发情况。