新增教育管理模块前端界面和API

- 新增前端API接口:学期管理、课程班级管理、课程安排管理接口
- 新增通用选项配置接口:options.js,提供下拉选择数据
- 新增学期管理页面:semester/index.vue,提供学期的增删改查功能
- 新增课程班级管理页面:courseClass/index.vue,提供班级管理功能
- 集成Element UI组件实现表格、表单、分页等交互功能
- 实现前后端数据交互和状态管理
This commit is contained in:
Leo 2025-09-28 21:49:33 +08:00
parent 233bce0b25
commit df30b17846
6 changed files with 1652 additions and 0 deletions

View File

@ -0,0 +1,171 @@
import request from '@/utils/request'
/**
* 查询开课计划列表
* @param {Object} query 查询参数
*/
export function listCourseClass(query) {
return request({
url: '/education/courseClass/list',
method: 'get',
params: query
})
}
/**
* 查询开课计划详细
* @param {Number} classId 开课计划ID
*/
export function getCourseClass(classId) {
return request({
url: '/education/courseClass/' + classId,
method: 'get'
})
}
/**
* 新增开课计划
* @param {Object} data 开课计划数据
*/
export function addCourseClass(data) {
return request({
url: '/education/courseClass',
method: 'post',
data: data
})
}
/**
* 修改开课计划
* @param {Object} data 开课计划数据
*/
export function updateCourseClass(data) {
return request({
url: '/education/courseClass',
method: 'put',
data: data
})
}
/**
* 删除开课计划
* @param {Array} classIds 开课计划ID数组
*/
export function delCourseClass(classIds) {
return request({
url: '/education/courseClass/' + classIds,
method: 'delete'
})
}
/**
* 发布开课计划
* @param {Number} classId 开课计划ID
*/
export function publishCourseClass(classId) {
return request({
url: '/education/courseClass/publish/' + classId,
method: 'put'
})
}
/**
* 批量发布开课计划
* @param {Array} classIds 开课计划ID数组
*/
export function batchPublishCourseClass(classIds) {
return request({
url: '/education/courseClass/batchPublish',
method: 'put',
data: classIds
})
}
/**
* 停止选课
* @param {Number} classId 开课计划ID
*/
export function stopEnrollment(classId) {
return request({
url: '/education/courseClass/stopEnrollment/' + classId,
method: 'put'
})
}
/**
* 结课
* @param {Number} classId 开课计划ID
*/
export function finishCourse(classId) {
return request({
url: '/education/courseClass/finish/' + classId,
method: 'put'
})
}
/**
* 调整容量
* @param {Number} classId 开课计划ID
* @param {Number} newCapacity 新容量
*/
export function adjustCapacity(classId, newCapacity) {
return request({
url: '/education/courseClass/adjustCapacity/' + classId + '/' + newCapacity,
method: 'put'
})
}
/**
* 获取指定学期的开课计划
* @param {Number} semesterId 学期ID
*/
export function getCourseClassBySemester(semesterId) {
return request({
url: '/education/courseClass/semester/' + semesterId,
method: 'get'
})
}
/**
* 获取指定教师的开课计划
* @param {Number} teacherId 教师ID
*/
export function getCourseClassByTeacher(teacherId) {
return request({
url: '/education/courseClass/teacher/' + teacherId,
method: 'get'
})
}
/**
* 获取可选课的开课计划
*/
export function getEnrollableCourseClasses() {
return request({
url: '/education/courseClass/enrollable',
method: 'get'
})
}
/**
* 获取开课计划统计信息
* @param {Number} semesterId 学期ID
*/
export function getCourseClassStatistics(semesterId) {
return request({
url: '/education/courseClass/statistics/' + semesterId,
method: 'get'
})
}
/**
* 导出开课计划
* @param {Object} query 查询参数
*/
export function exportCourseClass(query) {
return request({
url: '/education/courseClass/export',
method: 'post',
params: query
})
}

View File

@ -0,0 +1,31 @@
import request from '@/utils/request'
/**
* 获取课程选项
*/
export function getCourseOptions() {
return request({
url: '/education/courseClass/courseOptions',
method: 'get'
})
}
/**
* 获取教师选项
*/
export function getTeacherOptions() {
return request({
url: '/education/courseClass/teacherOptions',
method: 'get'
})
}
/**
* 获取教室选项
*/
export function getClassroomOptions() {
return request({
url: '/education/courseClass/classroomOptions',
method: 'get'
})
}

View File

@ -0,0 +1,201 @@
import request from '@/utils/request'
/**
* 查询开课节次安排列表
* @param {Object} query 查询参数
*/
export function listSchedule(query) {
return request({
url: '/education/schedule/list',
method: 'get',
params: query
})
}
/**
* 查询开课节次安排详细
* @param {Number} scheduleId 节次安排ID
*/
export function getSchedule(scheduleId) {
return request({
url: '/education/schedule/' + scheduleId,
method: 'get'
})
}
/**
* 新增开课节次安排
* @param {Object} data 节次安排数据
*/
export function addSchedule(data) {
return request({
url: '/education/schedule',
method: 'post',
data: data
})
}
/**
* 修改开课节次安排
* @param {Object} data 节次安排数据
*/
export function updateSchedule(data) {
return request({
url: '/education/schedule',
method: 'put',
data: data
})
}
/**
* 删除开课节次安排
* @param {Array} scheduleIds 节次安排ID数组
*/
export function delSchedule(scheduleIds) {
return request({
url: '/education/schedule/' + scheduleIds,
method: 'delete'
})
}
/**
* 根据开课ID查询节次安排
* @param {Number} classId 开课ID
*/
export function getScheduleByClassId(classId) {
return request({
url: '/education/schedule/class/' + classId,
method: 'get'
})
}
/**
* 根据开课ID删除节次安排
* @param {Number} classId 开课ID
*/
export function delScheduleByClassId(classId) {
return request({
url: '/education/schedule/class/' + classId,
method: 'delete'
})
}
/**
* 查询指定教室的课程安排
* @param {Number} classroomId 教室ID
* @param {Number} semesterId 学期ID
*/
export function getScheduleByClassroom(classroomId, semesterId) {
return request({
url: '/education/schedule/classroom/' + classroomId + '/' + semesterId,
method: 'get'
})
}
/**
* 查询指定教师的课程安排
* @param {Number} teacherId 教师ID
* @param {Number} semesterId 学期ID
*/
export function getScheduleByTeacher(teacherId, semesterId) {
return request({
url: '/education/schedule/teacher/' + teacherId + '/' + semesterId,
method: 'get'
})
}
/**
* 查询指定学期的所有课程安排
* @param {Number} semesterId 学期ID
*/
export function getScheduleBySemester(semesterId) {
return request({
url: '/education/schedule/semester/' + semesterId,
method: 'get'
})
}
/**
* 生成教室课表
* @param {Number} classroomId 教室ID
* @param {Number} semesterId 学期ID
*/
export function generateClassroomTimetable(classroomId, semesterId) {
return request({
url: '/education/schedule/timetable/classroom/' + classroomId + '/' + semesterId,
method: 'get'
})
}
/**
* 生成教师课表
* @param {Number} teacherId 教师ID
* @param {Number} semesterId 学期ID
*/
export function generateTeacherTimetable(teacherId, semesterId) {
return request({
url: '/education/schedule/timetable/teacher/' + teacherId + '/' + semesterId,
method: 'get'
})
}
/**
* 批量添加节次安排
* @param {Number} classId 开课ID
* @param {Array} scheduleList 节次安排列表
*/
export function batchAddSchedule(classId, scheduleList) {
return request({
url: '/education/schedule/batch/' + classId,
method: 'post',
data: scheduleList
})
}
/**
* 复制节次安排
* @param {Number} sourceClassId 源开课ID
* @param {Number} targetClassId 目标开课ID
*/
export function copySchedule(sourceClassId, targetClassId) {
return request({
url: '/education/schedule/copy/' + sourceClassId + '/' + targetClassId,
method: 'post'
})
}
/**
* 自动排课
* @param {Number} classId 开课ID
* @param {Number} semesterId 学期ID
* @param {Number} courseHours 课程学时
*/
export function autoSchedule(classId, semesterId, courseHours) {
return request({
url: '/education/schedule/auto/' + classId + '/' + semesterId + '/' + courseHours,
method: 'post'
})
}
/**
* 获取时间段统计信息
* @param {Number} semesterId 学期ID
*/
export function getScheduleStatistics(semesterId) {
return request({
url: '/education/schedule/statistics/' + semesterId,
method: 'get'
})
}
/**
* 导出节次安排
* @param {Object} query 查询参数
*/
export function exportSchedule(query) {
return request({
url: '/education/schedule/export',
method: 'post',
params: query
})
}

View File

@ -0,0 +1,113 @@
import request from '@/utils/request'
/**
* 查询学期信息列表
* @param {Object} query 查询参数
*/
export function listSemester(query) {
return request({
url: '/education/semester/list',
method: 'get',
params: query
})
}
/**
* 查询学期信息详细
* @param {Number} semesterId 学期ID
*/
export function getSemester(semesterId) {
return request({
url: '/education/semester/' + semesterId,
method: 'get'
})
}
/**
* 新增学期信息
* @param {Object} data 学期数据
*/
export function addSemester(data) {
return request({
url: '/education/semester',
method: 'post',
data: data
})
}
/**
* 修改学期信息
* @param {Object} data 学期数据
*/
export function updateSemester(data) {
return request({
url: '/education/semester',
method: 'put',
data: data
})
}
/**
* 删除学期信息
* @param {Array} semesterIds 学期ID数组
*/
export function delSemester(semesterIds) {
return request({
url: '/education/semester/' + semesterIds,
method: 'delete'
})
}
/**
* 发布学期
* @param {Number} semesterId 学期ID
*/
export function publishSemester(semesterId) {
return request({
url: '/education/semester/publish/' + semesterId,
method: 'put'
})
}
/**
* 归档学期
* @param {Number} semesterId 学期ID
*/
export function archiveSemester(semesterId) {
return request({
url: '/education/semester/archive/' + semesterId,
method: 'put'
})
}
/**
* 获取当前学期
*/
export function getCurrentSemester() {
return request({
url: '/education/semester/current',
method: 'get'
})
}
/**
* 获取可选课学期列表
*/
export function getEnrollableSemesters() {
return request({
url: '/education/semester/enrollable',
method: 'get'
})
}
/**
* 导出学期信息
* @param {Object} query 查询参数
*/
export function exportSemester(query) {
return request({
url: '/education/semester/export',
method: 'post',
params: query
})
}

View File

@ -0,0 +1,743 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="班级编号" prop="classCode">
<el-input
v-model="queryParams.classCode"
placeholder="请输入班级编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="课程名称" prop="courseName">
<el-input
v-model="queryParams.courseName"
placeholder="请输入课程名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="教师姓名" prop="teacherName">
<el-input
v-model="queryParams.teacherName"
placeholder="请输入教师姓名"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option
v-for="dict in dict.type.edu_course_class_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['education:courseClass:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['education:courseClass:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['education:courseClass:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-video-play"
size="mini"
:disabled="multiple"
@click="handleBatchPublish"
v-hasPermi="['education:courseClass:publish']"
>批量发布</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['education:courseClass:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="courseClassList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="班级编号" align="center" prop="classCode" />
<el-table-column label="课程编码" align="center" prop="courseCode" />
<el-table-column label="课程名称" align="center" prop="courseName" />
<el-table-column label="教师姓名" align="center" prop="teacherName" />
<el-table-column label="学期名称" align="center" prop="semesterName" />
<el-table-column label="容量" align="center" prop="capacity" />
<el-table-column label="已选人数" align="center" prop="enrolledCount">
<template slot-scope="scope">
<el-tag :type="scope.row.enrolledCount >= scope.row.capacity ? 'danger' : 'success'">
{{ scope.row.enrolledCount || 0 }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="选课率" align="center">
<template slot-scope="scope">
<el-progress
:percentage="Math.round((scope.row.enrolledCount || 0) / scope.row.capacity * 100)"
:color="getProgressColor(scope.row.enrolledCount, scope.row.capacity)"
:stroke-width="6"
/>
</template>
</el-table-column>
<el-table-column label="上课时间" align="center">
<template slot-scope="scope">
<span>{{ scope.row.weekday }} {{ scope.row.timeSlot }}</span>
</template>
</el-table-column>
<el-table-column label="教室" align="center" prop="classroomName" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.edu_course_class_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<el-dropdown size="mini">
<el-button size="mini" type="primary">
操作<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
icon="el-icon-edit"
@click.native="handleUpdate(scope.row)"
v-hasPermi="['education:courseClass:edit']"
>修改</el-dropdown-item>
<el-dropdown-item
icon="el-icon-time"
@click.native="handleSchedule(scope.row)"
v-hasPermi="['education:schedule:list']"
>节次安排</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.status == '0'"
icon="el-icon-video-play"
@click.native="handlePublish(scope.row)"
v-hasPermi="['education:courseClass:publish']"
>发布</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.status == '1'"
icon="el-icon-setting"
@click.native="handleAdjustCapacity(scope.row)"
v-hasPermi="['education:courseClass:capacity']"
>调整容量</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.status == '1'"
icon="el-icon-circle-close"
@click.native="handleStopEnrollment(scope.row)"
v-hasPermi="['education:courseClass:edit']"
>停止选课</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.status == '1' || scope.row.status == '2'"
icon="el-icon-finished"
@click.native="handleFinish(scope.row)"
v-hasPermi="['education:courseClass:edit']"
>结课</el-dropdown-item>
<el-dropdown-item
icon="el-icon-delete"
@click.native="handleDelete(scope.row)"
v-hasPermi="['education:courseClass:remove']"
>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改开课计划对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<!-- 基础信息选择 -->
<el-row>
<el-col :span="12">
<el-form-item label="课程" prop="courseId">
<el-select v-model="form.courseId" placeholder="请选择课程" filterable style="width: 100%">
<el-option
v-for="course in courseOptions"
:key="course.courseId"
:label="`${course.courseName}(${course.courseCode})`"
:value="course.courseId">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="学期" prop="semesterId">
<el-select v-model="form.semesterId" placeholder="请选择学期" style="width: 100%">
<el-option
v-for="semester in semesterOptions"
:key="semester.semesterId"
:label="semester.semesterName"
:value="semester.semesterId">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="授课教师" prop="teacherId">
<el-select v-model="form.teacherId" placeholder="请选择教师" filterable style="width: 100%">
<el-option
v-for="teacher in teacherOptions"
:key="teacher.teacherId"
:label="`${teacher.realName}(${teacher.teacherNo})`"
:value="teacher.teacherId">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="授课教室" prop="classroomId">
<el-select v-model="form.classroomId" placeholder="请选择教室" clearable style="width: 100%">
<el-option
v-for="classroom in classroomOptions"
:key="classroom.classroomId"
:label="classroom.classroomName"
:value="classroom.classroomId">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 班级配置信息 -->
<el-row>
<el-col :span="12">
<el-form-item label="班级编号" prop="classCode">
<el-input v-model="form.classCode" placeholder="请输入班级编号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="容量上限" prop="capacity">
<el-input-number v-model="form.capacity" :min="1" :max="300" placeholder="请输入容量上限" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="选课人数上限" prop="enrollLimit">
<el-input-number v-model="form.enrollLimit" :min="0" placeholder="0表示同容量上限" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="已选人数" prop="enrolledCount">
<el-input-number v-model="form.enrolledCount" :min="0" :disabled="true" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="选课开始时间" prop="enrollStartTime">
<el-date-picker
v-model="form.enrollStartTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择选课开始时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="选课结束时间" prop="enrollEndTime">
<el-date-picker
v-model="form.enrollEndTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择选课结束时间">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="开课日期" prop="teachStartDate">
<el-date-picker
v-model="form.teachStartDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择开课日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结课日期" prop="teachEndDate">
<el-date-picker
v-model="form.teachEndDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择结课日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="上课星期" prop="weekday">
<el-select v-model="form.weekday" placeholder="请选择上课星期">
<el-option label="周一" value="周一" />
<el-option label="周二" value="周二" />
<el-option label="周三" value="周三" />
<el-option label="周四" value="周四" />
<el-option label="周五" value="周五" />
<el-option label="周六" value="周六" />
<el-option label="周日" value="周日" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上课节次" prop="timeSlot">
<el-select v-model="form.timeSlot" placeholder="请选择上课节次">
<el-option label="第1-2节" value="第1-2节" />
<el-option label="第3-4节" value="第3-4节" />
<el-option label="第5-6节" value="第5-6节" />
<el-option label="第7-8节" value="第7-8节" />
<el-option label="第9-10节" value="第9-10节" />
<el-option label="第11-12节" value="第11-12节" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 调整容量对话框 -->
<el-dialog title="调整容量" :visible.sync="capacityOpen" width="400px" append-to-body>
<el-form ref="capacityForm" :model="capacityForm" :rules="capacityRules" label-width="100px">
<el-form-item label="当前容量" prop="currentCapacity">
<el-input v-model="capacityForm.currentCapacity" :disabled="true" />
</el-form-item>
<el-form-item label="已选人数" prop="enrolledCount">
<el-input v-model="capacityForm.enrolledCount" :disabled="true" />
</el-form-item>
<el-form-item label="新容量" prop="newCapacity">
<el-input-number
v-model="capacityForm.newCapacity"
:min="capacityForm.enrolledCount"
:max="500"
placeholder="请输入新容量"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitCapacityForm"> </el-button>
<el-button @click="cancelCapacity"> </el-button>
</div>
</el-dialog>
<!-- 节次安排对话框 -->
<el-dialog title="节次安排" :visible.sync="scheduleOpen" width="900px" append-to-body>
<div v-if="scheduleData.length > 0">
<el-table :data="scheduleData" border>
<el-table-column label="星期" align="center" prop="weekdayName" />
<el-table-column label="节次" align="center" prop="periodName" />
<el-table-column label="上课周次" align="center" prop="weeks" />
<el-table-column label="教室" align="center" prop="classroomName" />
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
</div>
<div v-else class="no-data">
<el-empty description="暂无节次安排数据"></el-empty>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listCourseClass,
getCourseClass,
delCourseClass,
addCourseClass,
updateCourseClass,
publishCourseClass,
batchPublishCourseClass,
stopEnrollment,
finishCourse,
adjustCapacity
} from "@/api/education/courseClass"
import { getScheduleByClassId } from "@/api/education/schedule"
import { listSemester } from "@/api/education/semester"
import { getCourseOptions, getTeacherOptions, getClassroomOptions } from "@/api/education/options"
export default {
name: "CourseClass",
dicts: ['edu_course_class_status'],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
courseClassList: [],
//
courseOptions: [],
semesterOptions: [],
teacherOptions: [],
classroomOptions: [],
//
title: "",
//
open: false,
//
capacityOpen: false,
//
scheduleOpen: false,
//
scheduleData: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
courseId: null,
semesterId: null,
teacherId: null,
classCode: null,
capacity: null,
enrollLimit: null,
enrolledCount: null,
classroomId: null,
enrollStartTime: null,
enrollEndTime: null,
teachStartDate: null,
teachEndDate: null,
weekday: null,
timeSlot: null,
status: null,
courseName: null,
courseCode: null,
teacherName: null,
semesterName: null
},
//
form: {},
//
capacityForm: {},
//
rules: {
courseId: [
{ required: true, message: "课程不能为空", trigger: "change" }
],
semesterId: [
{ required: true, message: "学期不能为空", trigger: "change" }
],
teacherId: [
{ required: true, message: "授课教师不能为空", trigger: "change" }
],
classCode: [
{ required: true, message: "班级编号不能为空", trigger: "blur" }
],
capacity: [
{ required: true, message: "容量上限不能为空", trigger: "blur" }
]
},
//
capacityRules: {
newCapacity: [
{ required: true, message: "新容量不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
this.loadOptions();
},
methods: {
/** 查询开课计划列表 */
getList() {
this.loading = true;
listCourseClass(this.queryParams).then(response => {
this.courseClassList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 获取课程选项 */
getCourseOptions() {
getCourseOptions().then(response => {
this.courseOptions = response.data;
});
},
/** 获取学期选项 */
getSemesterOptions() {
listSemester().then(response => {
this.semesterOptions = response.rows;
});
},
/** 获取教师选项 */
getTeacherOptions() {
getTeacherOptions().then(response => {
this.teacherOptions = response.data;
});
},
/** 获取教室选项 */
getClassroomOptions() {
getClassroomOptions().then(response => {
this.classroomOptions = response.data;
});
},
/** 加载所有选项数据 */
loadOptions() {
this.getCourseOptions();
this.getSemesterOptions();
this.getTeacherOptions();
this.getClassroomOptions();
},
//
getProgressColor(enrolled, capacity) {
const rate = (enrolled || 0) / capacity;
if (rate < 0.5) {
return '#67C23A';
} else if (rate < 0.8) {
return '#E6A23C';
} else {
return '#F56C6C';
}
},
//
cancel() {
this.open = false;
this.reset();
},
//
cancelCapacity() {
this.capacityOpen = false;
this.capacityForm = {};
},
//
reset() {
this.form = {
classId: null,
courseId: null,
semesterId: null,
teacherId: null,
classCode: null,
capacity: 50,
enrollLimit: null,
enrolledCount: 0,
classroomId: null,
enrollStartTime: null,
enrollEndTime: null,
teachStartDate: null,
teachEndDate: null,
weekday: null,
timeSlot: null,
status: "0",
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.classId)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.loadOptions();
this.open = true;
this.title = "添加开课计划";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.loadOptions();
const classId = row.classId || this.ids
getCourseClass(classId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改开课计划";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.classId != null) {
updateCourseClass(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addCourseClass(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const classIds = row.classId || this.ids;
this.$modal.confirm('是否确认删除开课计划编号为"' + classIds + '"的数据项?').then(function() {
return delCourseClass(classIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 发布按钮操作 */
handlePublish(row) {
this.$modal.confirm('是否确认发布开课计划"' + row.classCode + '"?发布后学生可以选课。').then(function() {
return publishCourseClass(row.classId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("发布成功");
}).catch(() => {});
},
/** 批量发布按钮操作 */
handleBatchPublish() {
if (this.ids.length === 0) {
this.$modal.msgError("请选择要发布的开课计划");
return;
}
this.$modal.confirm('是否确认批量发布选中的开课计划?').then(() => {
return batchPublishCourseClass(this.ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("批量发布成功");
}).catch(() => {});
},
/** 停止选课按钮操作 */
handleStopEnrollment(row) {
this.$modal.confirm('是否确认停止开课计划"' + row.classCode + '"的选课?').then(function() {
return stopEnrollment(row.classId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("已停止选课");
}).catch(() => {});
},
/** 结课按钮操作 */
handleFinish(row) {
this.$modal.confirm('是否确认结课"' + row.classCode + '"?结课后无法再选课。').then(function() {
return finishCourse(row.classId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("结课成功");
}).catch(() => {});
},
/** 调整容量按钮操作 */
handleAdjustCapacity(row) {
this.capacityForm = {
classId: row.classId,
currentCapacity: row.capacity,
enrolledCount: row.enrolledCount || 0,
newCapacity: row.capacity
};
this.capacityOpen = true;
},
/** 提交容量调整 */
submitCapacityForm() {
this.$refs["capacityForm"].validate(valid => {
if (valid) {
adjustCapacity(this.capacityForm.classId, this.capacityForm.newCapacity).then(response => {
this.$modal.msgSuccess("容量调整成功");
this.capacityOpen = false;
this.getList();
});
}
});
},
/** 节次安排按钮操作 */
handleSchedule(row) {
this.scheduleData = [];
this.scheduleOpen = true;
getScheduleByClassId(row.classId).then(response => {
this.scheduleData = response.data || [];
});
},
/** 导出按钮操作 */
handleExport() {
this.download('education/courseClass/export', {
...this.queryParams
}, `courseClass_${new Date().getTime()}.xlsx`)
}
}
};
</script>
<style scoped>
.no-data {
text-align: center;
padding: 40px;
}
</style>

View File

@ -0,0 +1,393 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="学期编码" prop="semesterCode">
<el-input
v-model="queryParams.semesterCode"
placeholder="请输入学期编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="学期名称" prop="semesterName">
<el-input
v-model="queryParams.semesterName"
placeholder="请输入学期名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option
v-for="dict in dict.type.edu_semester_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['education:semester:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['education:semester:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['education:semester:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['education:semester:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="semesterList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="学期ID" align="center" prop="semesterId" />
<el-table-column label="学期编码" align="center" prop="semesterCode" />
<el-table-column label="学期名称" align="center" prop="semesterName" />
<el-table-column label="教学开始日期" align="center" prop="startDate" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="教学结束日期" align="center" prop="endDate" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="选课开始时间" align="center" prop="enrollStartTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.enrollStartTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="选课结束时间" align="center" prop="enrollEndTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.enrollEndTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.edu_semester_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['education:semester:edit']"
>修改</el-button>
<el-button
v-if="scope.row.status == '0'"
size="mini"
type="text"
icon="el-icon-video-play"
@click="handlePublish(scope.row)"
v-hasPermi="['education:semester:publish']"
>发布</el-button>
<el-button
v-if="scope.row.status == '1'"
size="mini"
type="text"
icon="el-icon-folder"
@click="handleArchive(scope.row)"
v-hasPermi="['education:semester:archive']"
>归档</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['education:semester:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改学期信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="学期编码" prop="semesterCode">
<el-input v-model="form.semesterCode" placeholder="请输入学期编码2024-2025-1" />
</el-form-item>
<el-form-item label="学期名称" prop="semesterName">
<el-input v-model="form.semesterName" placeholder="请输入学期名称2024-2025学年第一学期" />
</el-form-item>
<el-form-item label="教学开始日期" prop="startDate">
<el-date-picker clearable
v-model="form.startDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择教学开始日期">
</el-date-picker>
</el-form-item>
<el-form-item label="教学结束日期" prop="endDate">
<el-date-picker clearable
v-model="form.endDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择教学结束日期">
</el-date-picker>
</el-form-item>
<el-form-item label="选课开始时间" prop="enrollStartTime">
<el-date-picker clearable
v-model="form.enrollStartTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择选课开始时间">
</el-date-picker>
</el-form-item>
<el-form-item label="选课结束时间" prop="enrollEndTime">
<el-date-picker clearable
v-model="form.enrollEndTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择选课结束时间">
</el-date-picker>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listSemester, getSemester, delSemester, addSemester, updateSemester, publishSemester, archiveSemester } from "@/api/education/semester"
export default {
name: "Semester",
dicts: ['edu_semester_status'],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
semesterList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
semesterCode: null,
semesterName: null,
startDate: null,
endDate: null,
enrollStartTime: null,
enrollEndTime: null,
status: null,
},
//
form: {},
//
rules: {
semesterCode: [
{ required: true, message: "学期编码不能为空", trigger: "blur" }
],
semesterName: [
{ required: true, message: "学期名称不能为空", trigger: "blur" }
],
startDate: [
{ required: true, message: "教学开始日期不能为空", trigger: "blur" }
],
endDate: [
{ required: true, message: "教学结束日期不能为空", trigger: "blur" }
],
enrollStartTime: [
{ required: true, message: "选课开始时间不能为空", trigger: "blur" }
],
enrollEndTime: [
{ required: true, message: "选课结束时间不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
},
methods: {
/** 查询学期信息列表 */
getList() {
this.loading = true;
listSemester(this.queryParams).then(response => {
this.semesterList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
semesterId: null,
semesterCode: null,
semesterName: null,
startDate: null,
endDate: null,
enrollStartTime: null,
enrollEndTime: null,
status: "0",
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.semesterId)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加学期信息";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const semesterId = row.semesterId || this.ids
getSemester(semesterId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改学期信息";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.semesterId != null) {
updateSemester(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addSemester(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const semesterIds = row.semesterId || this.ids;
this.$modal.confirm('是否确认删除学期信息编号为"' + semesterIds + '"的数据项?').then(function() {
return delSemester(semesterIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 发布按钮操作 */
handlePublish(row) {
this.$modal.confirm('是否确认发布学期"' + row.semesterName + '"?发布后将开放选课功能。').then(function() {
return publishSemester(row.semesterId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("发布成功");
}).catch(() => {});
},
/** 归档按钮操作 */
handleArchive(row) {
this.$modal.confirm('是否确认归档学期"' + row.semesterName + '"?归档后将无法再进行选课。').then(function() {
return archiveSemester(row.semesterId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("归档成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('education/semester/export', {
...this.queryParams
}, `semester_${new Date().getTime()}.xlsx`)
}
}
};
</script>