16学生选课功能的开发

Views: 0

在设计数据库表的时候,当有某个字段需要(具体看自己的业务)跟其他模块的信息有所关联的时候,或者这个字段是跟角色相关的(可能不同的角色对这个模块看到的信息或者行为不一样)时候,该字段就要考虑关联了,我们可以设计为xxx_id

逻辑

选课入口:

学生登录系统后,可以看到可选课程列表(CourseService提供数据)

每门课程会显示:课程名称、授课教师、剩余名额等信息

选课核心流程:

学生点击”选课”按钮时,系统会做两个重要检查:

  1. 检查课程是否已满(通过比较课程总人数num和已选人数alreadyNum
  2. 检查该学生是否已经选过这门课(通过查询choice表)

选课成功的情况:

如果课程未满且学生未选过: 系统会在选课表(choice)中新增一条记录

同时把该课程的已选人数+1(更新course表)

选课失败的情况:

如果课程已满:提示”课程已经选满” 如果已经选过:提示”你已经选过这门课程”

关键代码位置:

选课逻辑主要在ChoiceService.javaadd()方法

课程信息查询在CourseService.java

前端选课页面在Choice.vue

简单来说就是:选课前检查名额和重复选课,通过检查就记录选课信息并更新课程人数。

创建数据库

CREATE TABLE `choice` (
 `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
 `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '课程名称',
 `teacher_id` int DEFAULT NULL COMMENT '授课教师',
 `student_id` int DEFAULT NULL COMMENT '学生信息',
 `course_id` int DEFAULT NULL COMMENT '课程ID',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='选课信息';

entity—Choice.java

创建实体类

public class Choice {
   private Integer id;
   private String name;
   private Integer studentId;
   private Integer teacherId;
   private String teacherName;
   private String studentName;
   private Integer courseId;

   public Integer getId() {
       return id;
  }

   public void setId(Integer id) {
       this.id = id;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }

   public Integer getStudentId() {
       return studentId;
  }

   public void setStudentId(Integer studentId) {
       this.studentId = studentId;
  }

   public Integer getTeacherId() {
       return teacherId;
  }

   public void setTeacherId(Integer teacherId) {
       this.teacherId = teacherId;
  }

   public String getTeacherName() {
       return teacherName;
  }

   public void setTeacherName(String teacherName) {
       this.teacherName = teacherName;
  }

   public String getStudentName() {
       return studentName;
  }

   public void setStudentName(String studentName) {
       this.studentName = studentName;
  }

   public Integer getCourseId() {
       return courseId;
  }

   public void setCourseId(Integer courseId) {
       this.courseId = courseId;
  }
}

前端

Manager.vue

<el-menu-item index="/choice">
 <el-icon><Reading /></el-icon>
 <span>选课信息</span>
</el-menu-item>

index.js

{ path: 'choice', component: () => import('@/views/manager/Choice.vue')},

Choice.vue

<template>
 <div>

   <div class="card" style="margin-bottom: 5px;">
     <el-input v-model="data.name" style="width: 300px; margin-right: 10px" placeholder="请输入课程名称查询"></el-input>
     <el-button type="primary" @click="load">查询</el-button>
     <el-button type="info" style="margin: 0 10px" @click="reset">重置</el-button>
   </div>

   <div class="card" style="margin-bottom: 5px">
     <el-table :data="data.tableData" stripe>
       <el-table-column label="课程名称" prop="name"></el-table-column>
       <el-table-column label="授课教师" prop="teacherName"></el-table-column>
       <el-table-column label="选课学生" prop="studentName"></el-table-column>
       <el-table-column label="操作" align="center" width="160" v-if ="data.user.role === 'ADMIN'">
         <template #default="scope" >
           <el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
   </div>

   <div class="card">
     <el-pagination background layout="prev, pager, next" v-model:page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total"/>
   </div>
 </div>
</template>

<script setup>
import request from "@/utils/request";
import {reactive} from "vue";
import {ElMessageBox, ElMessage} from "element-plus";


const data = reactive({
 user: JSON.parse(localStorage.getItem('system-user') || '{}'),// 获取当前登录的用户信息
 pageNum: 1,
 pageSize: 10,
 total: 0,
 formVisible: false,
 form: {},
 tableData: [],
 name: null,
 collegeDate: [],// 用于存储学院信息
 teacherDate: []// 用于存储教师信息
})

// 分页查询
const load = () => {
 let teacherId = null// 用于存储教师id
 if (data.user.role === 'TEACHER') {
   teacherId = data.user.id// 如果是教师,就查询自己的课程信息
}
 request.get('/choice/selectPage', {
   params: {
     pageNum: data.pageNum,
     pageSize: data.pageSize,
     name: data.name,
     teacherId: teacherId,// 如果是教师,就查询自己的课程信息
  }
}).then(res => {
   data.tableData = res.data?.list
   data.total = res.data?.total
})
}

// 删除
const handleDelete = (id) => {
 ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
   request.delete('/choice/deleteById/' + id).then(res => {
     if (res.code === '200') {
       load()
       ElMessage.success('操作成功')
    } else {
       ElMessage.error(res.msg)
    }
  })
}).catch(err => {})
}

// 重置
const reset = () => {
 data.name = null
 load()
}

const loadTeacher = () => {//查询所有教师信息
 request.get('/teacher/selectAll').then(res => {//调用后端接口查询所有教师信息
   if (res.code === '200') {//如果查询成功,将查询到的教师信息赋值给data.teacherDate
     data.teacherDate = res.data
  }else {//如果查询失败,提示用户
     ElMessage.error(res.msg)
  }
})
}

const loadCollege= () => {//查询所有学院信息
 request.get('/college/selectAll').then(res => {//调用后端接口查询所有学院信息
   if (res.code === '200') {//如果查询成功,将查询到的学院信息赋值给data.collegeDate
     data.collegeDate = res.data
     load()//查询课程信息
  }else {//如果查询失败,提示用户
     ElMessage.error(res.msg)
  }
})
}

load()
loadCollege()
loadTeacher()
</script>

Course.vue

<template #default="scope" v-else>
 <el-button type="primary" @click="ChoiceCouse(scope.row)" :disabled = "scope.row.num === scope.row.alreadyNum">选课</el-button>
 <!--点击选课按钮的时候会触发选课方法,传入的参数是scope.row,也就是当前行的数据-->
</template>
const ChoiceCouse = (row) => {//选课
 let courseData = JSON.parse(JSON.stringify(row))// 复制一份row的数据
 courseData.studentId = data.user.id// 将学生id赋值给courseData.studentId

 request.post('/choice/add', courseData).then(res => {//调用后端接口添加选课信息
   if (res.code === '200') {
     ElMessage.success('选课成功')
     load() // 刷新课程列表
  } else {//如果添加失败,提示用户
     ElMessage.error(res.msg)
  }
})
}

Controller— ChoiceController.java

/**
* 选课信息模块前端操作接口入口
* 拿到数据后,调用service层的方法,返回结果
* 前端调用接口时,需要传入参数,调用service层的方法,返回结果
**/
@RestController

@RequestMapping("/choice")
public class ChoiceController {
   @Resource
//   注入ChoiceService
   private ChoiceService choiceService;

   /**
    * 新增选课信息
    * */
   @PostMapping("/add")
   public Result add(@RequestBody Course course) {  // 修改参数类型为 Course
       choiceService.add(course);
       return Result.success();
  }

   /**
    * 更新选课信息
    */
   @PutMapping("/update")
   public Result update(@RequestBody Choice choice) {
       choiceService.updateById(choice);
       return Result.success();
  }

   /**
    * 删除选课信息
    */
   @DeleteMapping("/deleteById/{id}")
   public Result deleteById(@PathVariable Integer id) {
       choiceService.deleteById(id);
       return Result.success();
  }

   /**
    * 分页查询
    * */
   @GetMapping("selectPage")
   public Result selectPage(Choice choice,
                            @RequestParam(defaultValue = "1") Integer pageNum,
                            @RequestParam(defaultValue = "5") Integer pageSize){
//       调用service层的方法,返回结果
       PageInfo<Choice> pageInfo = choiceService.selectPage(choice,pageNum,pageSize);
//       总数
       return Result.success(pageInfo);
  }
   /**
    * 查询所有选课信息
    */
   @GetMapping("/selectAll")
   public Result selectAll(){
       List<Choice> list = choiceService.selectAll();
       return Result.success(list);
  }
}

Service

ChoiceService.java

/**
 * 选课模块业务逻辑接口
 * 要把数据往数据库里存,调用mapper层的方法,返回结果
 * 业务逻辑接口调用mapper层的方法,返回结果
 */
@Service
public class ChoiceService {
    //    注入ChoiceMapper
    @Resource
    private ChoiceMapper choiceMapper;
    @Resource
    private CourseMapper courseMapper;
    /**
     * 新增选课
     */
    public void add(Course course) {
        //判断课程是否已经选满
        if(course.getNum().equals(course.getAlreadyNum())){//如果课程已经选满,就抛出异常
            throw new CustomException("课程已经选满");
        }
        //判断这个学生这门课程是否已经选过
        List<Choice> list = choiceMapper.selectByStudentIdAndCourseId(course.getStudentId(),course.getId());
        if(CollectionUtil.isNotEmpty(list)){
            throw new CustomException("你已经选过这门课程");//如果已经选过这门课程,就抛出异常
        }
        //往选课信息表中插入数据
        Choice choice = new Choice();//创建一个choice对象
        choice.setStudentId(course.getStudentId());//设置学生id
        choice.setCourseId(course.getId());//设置课程id
        choice.setTeacherId(course.getTeacherId());//设置教师id
        choice.setName(course.getName());//设置课程名称
        choiceMapper.insert(choice);//往选课信息表中插入数据
        //该门课程的已选人数加1
        course.setAlreadyNum(course.getAlreadyNum()+1);//已选人数加1
        courseMapper.updateById(course);//更新课程信息
    }
    /**
     * 分页查询
     */
    public PageInfo<Choice> selectPage(Choice choice,Integer pageNum, Integer pageSize) {
        // ToDo 分页查询逻辑处理
        // 1. 分页查询选课信息
        // 2. 返回选课信息
        // 3. 如果没有选课信息,返回空列表
        // 4. 如果有选课信息,返回选课信息列表
        List<Choice> list;//定义一个list集合
        PageHelper.startPage(pageNum,pageSize);//分页查询
        if(ObjectUtil.isNotEmpty(choice.getName())){//如果name不为空,就查询name对应的选课信息
            list = choiceMapper.selectByName(choice.getName());//查询name对应的选课信息
        }else{//如果name为空,就查询所有选课信息
           list = choiceMapper.selectAll();//查询所有选课信息
        }
        return PageInfo.of(list);//返回选课信息列表
    }
​
    //根据id查询选课信息,返回一个choice对象
    public void updateById(Choice choice) {//传入一个choice对象   前端传过来的choice对象
        choiceMapper.updateById(choice);//更新选课信息
    }
​
​
    //根据id删除选课信息
    public void deleteById(Integer id) {//传入一个id
        choiceMapper.deleteById(id);//删除选课信息
    }
    //查询所有选课信息
    public List<Choice> selectAll() {//返回一个list集合
        return choiceMapper.selectAll();//返回所有选课信息
    }
}

CourseService.java

/**
 * 课程模块业务逻辑接口
 * 要把数据往数据库里存,调用mapper层的方法,返回结果
 * 业务逻辑接口调用mapper层的方法,返回结果
 */
@Service
public class CourseService {
    //    注入CourseMapper
    @Resource
    private CourseMapper courseMapper;
    /**
     * 新增课程
     */
    public void add(Course course) {
        course.setAlreadyNum(0);//设置已选人数为0
        courseMapper.insert(course);//调用mapper层的方法,返回结果
    }
    /**
     * 分页查询
     */
    public PageInfo<Course> selectPage(Course course,Integer pageNum, Integer pageSize) {
        // ToDo 分页查询逻辑处理
        // 1. 分页查询课程信息
        // 2. 返回课程信息
        // 3. 如果没有课程信息,返回空列表
        // 4. 如果有课程信息,返回课程信息列表
        List<Course> list;//定义一个list集合
        PageHelper.startPage(pageNum,pageSize);//分页查询
        //表示当前登录是教师
        if(ObjectUtil.isNotEmpty(course.getTeacherId())){//如果teacherId不为空,就查询teacherId对应的课程信息
            Integer teacherId = course.getTeacherId();
            //如果name不为空,就查询name对应的课程信息,否则就查询所有课程信息
            if (ObjectUtil.isNotEmpty(course.getName())) {//如果name不为空,就查询name对应的课程信息
                list = courseMapper.selectByNameAndTeacherId(course.getName(),teacherId);
            } else {//如果name为空,就查询所有课程信息
                list = courseMapper.selectAllByTeacherId(teacherId);
            }
        }
        else {
            //如果name不为空,就查询name对应的课程信息,否则就查询所有课程信息
            if (ObjectUtil.isNotEmpty(course.getName())) {//如果name不为空,就查询name对应的课程信息
                list = courseMapper.selectByName(course.getName());
            } else {//如果name为空,就查询所有课程信息
                list = courseMapper.selectAll();
            }
        }
        return PageInfo.of(list);//返回课程信息列表
    }
​
    //根据id查询课程信息,返回一个course对象
    public void updateById(Course course) {//传入一个course对象
        courseMapper.updateById(course);//调用mapper层的方法,返回结果
    }
​
​
    //根据id删除课程信息
    public void deleteById(Integer id) {
        courseMapper.deleteById(id);
    }
    //查询所有课程信息
    public List<Course> selectAll() {
        return courseMapper.selectAll();
    }
}

Mapper

ChoiceMapper.java

注意:sql语句换行后面加空格

明确指定表名样MySQL就能明确知道我们要查询的是哪个表

@Mapper
public interface ChoiceMapper {
   //新增
   void insert(Choice choice);

   //查询所有
   @Select("select choice.*, course.name as courseName, teacher.name as teacherName, student.name as studentName " +
           "from choice " +
           "left join course on choice.course_id = course.id " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id")
   List<Choice> selectAll();

   //根据name查询
   @Select("select choice.*, course.name as courseName, teacher.name as teacherName,student.name as studentName " +
           "from choice " +
           "left join course on choice.course_id = course.id " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id " +
           "where choice.name like concat('%',#{name},'%')")
   //查询所有专业信息,并且把专业信息对应的学院名称也查询出来,并且把专业信息对应的教师名称也查询出来,并且模糊查询
   List<Choice> selectByName(String name);

   //修改
   void updateById(Choice choice);

   //删除
   @Delete("delete from choice where id = #{id}")
   void deleteById(Integer id);

   //根据name查询,并且根据teacherId查询   模糊查询
   @Select("select choice.*, course.name as courseName, teacher.name as teacherName,student.name as studentName " +
           "from choice " +
           "left join course on choice.course_id = course.id " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id " +  
           "where choice.name like concat('%',#{name},'%') and choice.teacher_id = #{teacherId}")  
   List<Choice> selectByNameAndTeacherId(@Param("name") String name, @Param("teacherId") Integer teacherId);

   //根据teacherId查询,并且把专业信息对应的学院名称也查询出来,把专业信息对应的教师名称也查询出来
   @Select("select choice.*, course.name as courseName,teacher.name as teacherName,student.name as studentName " +
           "from choice " +
           "left join course on choice.course_id = course.id " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id " +
           "where choice.teacher_id = #{teacherId}")
   List<Choice> selectAllByTeacherId(Integer teacherId);

   @Select("select * from choice where student_id = #{studentId} and course_id = #{courseId}")
   List<Choice> selectByStudentIdAndCourseId(@Param("studentId") Integer studentId, @Param("courseId") Integer courseId);

   @Select("select choice.*, teacher.name as teacherName,student.name as studentName " +
           "from choice " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id " +
           "where choice.name like concat('%',#{name},'%') and student_id = #{studentId}")
   List<Choice> selectByNameAndStudentId(@Param("name") String name, @Param("studentId") Integer studentId);


   @Select("select choice.*, teacher.name as teacherName,student.name as studentName " +
           "from choice " +
           "left join teacher on choice.teacher_id = teacher.id " +
           "left join student on choice.student_id = student.id " +  // 这里添加空格
           "where student_id = #{studentId} ")  // 修改查询条件为student_id
   List<Choice> selectAllByStudentId(Integer studentId);
}

ChoiceMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.ChoiceMapper">
   <insert id="insert" parameterType="com.example.entity.Choice" useGeneratedKeys="true">
      insert into choice (name, teacher_id, student_id,course_id)
      values (#{name}, #{teacherId}, #{studentId},#{courseId})
   </insert>

   <update id="updateById" parameterType="com.example.entity.Choice">
      update choice
      set name = #{name},
          student_id = #{studentId},
          teacher_id = #{teacherId},
          course_id = #{courseId}
      where id = #{id}
--             这里的id是实体类中的属性名,不是数据库中的字段名
   </update>
</mapper>

这个算是整个系统里面最难,最重要的一个逻辑之一吧,一定要仔细看!!!好好消化

版权声明

本网站名称:学海拾茜
本文链接:https://www.61lyf.top/16%e5%ad%a6%e7%94%9f%e9%80%89%e8%af%be%e5%8a%9f%e8%83%bd%e7%9a%84%e5%bc%80%e5%8f%91/
本网站的文章部分内容可能来源于网络,仅供学习与参考,如有侵权,请联系站长进行核实删除。
转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处并附带原文链接!!!
站长邮箱:cyg1900@outlook.com 或studygod825@qq.com ,如不方便留言可邮件联系。
暂无评论

发送评论 编辑评论


				
上一篇
下一篇