07学生信息的管理

Views: 0

逻辑

逻辑和教师信息一样,所以可以直接复制教师信息

在数据库加上学生库,建立学生实体类就好了,前端更改一些配置,一些信息就好了,基本上都不需要改,后端内容只要把教师信息改为学生信息

要学会看报错信息

核心数据结构:

每个学员包含基本信息:ID、姓名、学号、所属学院、专业、年级等 可能还包含联系方式、学分信息等 主要功能:

增:添加新学员信息 删:删除学员信息 改:修改学员信息 查: 查看所有学员列表 按条件搜索 分页查看学员信息

前后端交互:

前端通过类似/Student/的接口与后端交互 管理页面可以查看学员列表并进行增删改查操作

学生信息数据库

CREATE TABLE `student` (
 `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
 `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '账号',
 `sex` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '性别',
 `avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '角色',
 `password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',
 `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '姓名',
 `role` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '角色',
 `code` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '学号',
 `college_id` int DEFAULT NULL COMMENT '学院ID',
 `score` int DEFAULT NULL COMMENT '学分',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生信息';

entitv

添加学生类

public class Student {
   private Integer id;
   private String username;
   private String password;
   private String name;
   private String sex;
   private String role;
   private String avatar;
   private String code;
   private Integer collegeId;
   private String collegeName;
   private Integer score;

   public Integer getId() {
       return id;
  }

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

   public String getUsername() {
       return username;
  }

   public void setUsername(String username) {
       this.username = username;
  }

   public String getPassword() {
       return password;
  }

   public void setPassword(String password) {
       this.password = password;
  }

   public String getName() {
       return name;
  }

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

   public String getSex() {
       return sex;
  }

   public void setSex(String sex) {
       this.sex = sex;
  }

   public String getRole() {
       return role;
  }

   public void setRole(String role) {
       this.role = role;
  }

   public String getAvatar() {
       return avatar;
  }

   public void setAvatar(String avatar) {
       this.avatar = avatar;
  }

   public String getCode() {
       return code;
  }

   public void setCode(String code) {
       this.code = code;
  }

   public Integer getScore() {
       return score;
  }

   public void setScore(Integer score) {
       this.score = score;
  }

   public Integer getCollegeId() {
       return collegeId;
  }

   public void setCollegeId(Integer collegeId) {
       this.collegeId = collegeId;
  }
   
   public String getCollegeName() {
       return collegeName;
  }
   public void setCollegeName(String collegeName) {
       this.collegeName = collegeName;
  }
}


学生信息

<el-menu-item index="/student">
 <el-icon><Avatar /></el-icon>
 <span>学生信息</span>
</el-menu-item>

配置路由,加一个student信息

{ path: 'student', component: () => import('@/views/manager/Student.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>

     <!-- 新增按钮 可以参考Student.vue里面的内容 -->
   <div class="card" style="margin-bottom: 5px">
     <div style="margin-bottom: 10px">
       <!-- 新增学生按钮,点击触发handleAdd方法 -->
       <el-button type="primary" @click="handleAdd">新增</el-button>

       <!--tableData 所有表格数据在里面,-->
       <el-table :data="data.tableData" stripe>
       <!--表格列,label是列的标题,prop是列的属性,prop要与后端保持一致,不然接收不到-->
         <el-table-column label="用户名" prop="username"></el-table-column>
         <el-table-column label="头像" prop="avatar">
           <!--头像列,scope是当前行的数据,scope.row.avatar是当前行的头像路径-->
           <template v-slot="scope">
             <!--scope图片组件,src是图片的路径,style是图片的样式,width是图片的宽度,height是图片的高度,border-radius是图片的圆角-->
             <el-image :src="scope.row.avatar" style="width: 40px; height: 40px; border-radius: 50%"></el-image>
           </template>
         </el-table-column>
         <el-table-column label="姓名" prop="name"></el-table-column>
         <el-table-column label="性别" prop="sex"></el-table-column>
         <el-table-column label="学号" prop="code"></el-table-column>
         <el-table-column label="所属学院" prop="college_id"></el-table-column>
         <el-table-column label="学分" prop="score"></el-table-column>
         <el-table-column label="角色" prop="role"></el-table-column>
         <el-table-column label="操作" align="center" width="160">
           <template #default="scope">
             <!--scope里面有row,row就是当前行的数据,scope.row.id就是当前行的id-->
             <el-button type="primary" @click="handleEdit(scope.row)">编辑</el-button>
             <el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
           </template>
         </el-table-column>
       </el-table>
     </div>
   </div>
<!--分页-->
   <div class="card">
<!-- prev上一页, pager当前页, next下一页,分页查询的页码, 每页显示的记录数, 总记录数, 分页查询的总记录数-->
     <el-pagination background layout="prev, pager, next" v-model:page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total" @current-change = "changePage"/>
   </div>

   <!-- 学生信息弹窗对话框 -->
   <el-dialog title="学生信息" width="40%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
     <!--prop v-model 里面要与后端保持一致不然接收不到   -->
     <el-form :model="data.form" label-width="100px" style="padding-right: 50px">
       <!--图片上传,上传成功后会调用handleImgSuccess方法,上传成功后会返回一个url,我们把这个url赋值给data.form.avatar-->
       <el-form-item label="头像" prop="avatar">
         <!--el-upload 上传组件,action是上传的地址,list-type是上传的类型,on-success是上传成功后的回调方法-->
         <el-upload :action="uploadUrl" list-type="picture" :on-success="handleImgSuccess">
           <!--el-button 按钮组件,type是按钮的类型,primary是主按钮-->
           <el-button type="primary">上传图片</el-button>
         </el-upload>
       </el-form-item>
       <el-form-item label="账号" prop="username">
         <el-input v-model="data.form.username" autocomplete="off" placeholder="请输入账号"/>
       </el-form-item>
       <el-form-item label="姓名" prop="name">
         <el-input v-model="data.form.name" autocomplete="off" placeholder="请输入姓名"/>
       </el-form-item>
       <el-form-item label="性别" prop="sex">
         <el-select v-model="data.form.sex" placeholder="请选择性别" style="width: 100%">
           <el-option label="男" value="男"></el-option>
           <el-option label="女" value="女"></el-option>
         </el-select>
       </el-form-item>
       <el-form-item label="学号" prop="code">
         <el-input v-model="data.form.code" autocomplete="off" placeholder="请输入学号"/>
       </el-form-item>
     </el-form>
     <!-- 弹窗取消,保存     -->
     <template #footer>
     <span class="dialog-footer">
       <el-button @click="data.formVisible = false">取 消</el-button>
       <el-button type="primary" @click="save">保 存</el-button>
     </span>
     </template>
   </el-dialog>
   </div>
</template>

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

//定义上传接口地址,这里是后端提供的接口地址
//VITE_BASE_URL是在.env.development文件中定义的,这里是开发环境的地址
// /files/upload是后端提供的接口地址
const uploadUrl = import.meta.env.VITE_BASE_URL + '/files/upload';

const data = reactive({
 // 学生信息弹窗对话框
 formVisible: false,
 // 学生信息表单数据
 form: {
},
 // 学生信息表格数据的数组,初始为空数组
 tableData: [],
 // 分页查询的页码
 pageNum: 1,
 // 分页查询的每页显示的记录数
 pageSize: 5,
 // 分页查询的总记录数,初始为0
 total: 0,
 // 学生姓名
 name: null,
});

const load = () => {
 // 调用后端接口查询学生信息
 // 这里可以使用axios或者其他请求库发送请求
 // 例如:axios.get('/api/student/selectPage', { params: { pageNum: data.pageNum, pageSize: data.pageSize } })
 request.get('/student/selectPage',{//请求路径
   params:{//查询条件
     pageNum: data.pageNum,//页码
     pageSize: data.pageSize,  //每页显示的记录数
     name: data.name,//学生姓名
  }
}
).then(res => {
   if (res.code === '200') {
     // 将查询到的学生信息数据赋值给tableData
     // res.data?.list 是一个数组,包含了查询到的学生信息数据
     // ?是一个可选链操作符,用于安全地访问对象的属性,如果对象为null或undefined,则不会抛出错误,而是返回undefined
     data.tableData = res.data?.list
     // 将查询到的总记录数赋值给total
     data.total = res.data?.total
  }else {
     // 查询失败,提示用户
     ElMessage.error(res.msg)
  }
})
}
// 分页查询,点击页码触发,改变页码,触发load()
const changePage = (pageNum) => {
 data.pageNum = pageNum //页码
 load()
}

// 新增学生按钮点击事件
const handleAdd = () => {
 // 清空学生信息表单数据
 data.form = {
}
 // 打开学生信息弹窗对话框
 data.formVisible = true
}

// 编辑学生按钮点击事件
const handleEdit = (row) => {
 // 将选中的学生信息数据赋值给学生信息表单数据
 // 这里可以使用JSON.parse(JSON.stringify(row))来深拷贝row对象,避免修改row对象时影响到tableData
 // 因为row是一个对象,而对象是引用类型,直接赋值给data.form会导致修改row时也会修改data.form,所以需要深拷贝
 // 将row对象转换为字符串,再转换为对象,这样就会创建一个新的对象,不会影响到原来的row对象
 data.form = JSON.parse(JSON.stringify(row))
 // 打开学生信息弹窗对话框
 data.formVisible = true
}

// 删除学生按钮点击事件
const handleDelete = (id) => {
 // 弹出确认框,提示用户是否确定删除
 // 如果用户点击确定,就调用后端接口删除学生信息
 // 如果用户点击取消,就不做任何操作
 ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
   // 调用后端接口删除学生信息
   // 这里可以使用axios或者其他请求库发送请求
   // 例如:axios.delete('/api/student/deleteById/' + id)
   request.delete('/student/deleteById/' + id).then(res => {
     // 提示用户删除成功或者失败
     if (res.code === '200') {
       ElMessage.success('操作成功')
       load()
    } else {
       ElMessage.error(res.msg)
    }
  })
}).catch(err => {})
}

// 新增保存按钮点击事件
const add = () => {
 // 调用后端接口保存学生信息
 // 这里可以使用axios或者其他请求库发送请求
 // 例如:axios.post('/api/student/add', data.form)
 request.post('/student/add', data.form).then(res => {
   if (res.code === '200') {
     // 保存成功,提示用户
     ElMessage.success('操作成功')
     // 重新加载学生信息
     load()
     // 关闭学生信息弹窗对话框
     data.formVisible = false

  }else {
     // 保存失败,提示用户
     ElMessage.error(res.msg)
  }
})
}
// 更新保存学生信息按钮点击事件
const update = () => {
//   调用后端接口更新学生信息
//   这里可以使用axios或者其他请求库发送请求
//   例如:axios.put('/api/student/update', data.form)
 request.put('/student/update', data.form).then(res => {
   if (res.code === '200') {
     // 更新成功,提示用户
     ElMessage.success('操作成功') //提示用户
     // 重新加载学生信息
     load()
  }else {
     // 更新失败,提示用户
     ElMessage.error(res.msg)
  }
})
}
// 保存学生信息按钮点击事件
const save = () => {
 // 判断学生信息表单数据是否有id属性
 // 如果有id属性,说明是编辑学生信息,调用更新学生信息接口
 // 如果没有id属性,说明是新增学生信息,调用新增学生信息接口
 // 三元运算符,如果data.form.id有值,就调用update(),否则调用add()
 data.form.id ? update() : add()
}

const reset = () => {
 // 重置查询条件
 data.name = null
 // 重新加载学生信息
 load()
}

//上传成功后调用的方法,把上传成功后的图片地址赋值给data.form.avatar
//res.data.url 是上传成功后的图片地址
const handleImgSuccess = (res) => {
 // res.data 是上传成功后的图片
 // 我们把这个地址赋值给data.form.avatar
 data.form.avatar = res.data
 //相当于和avatar绑定了
}

load()
</script>

后端

Controller—StudentController

/**
* 学生模块前端操作接口入口
* 拿到数据后,调用service层的方法,返回结果
* 前端调用接口时,需要传入参数,调用service层的方法,返回结果
**/
@RestController
@RequestMapping("/student")
public class StudentController {
   @Resource
   private StudentService studentService;

   /**
    * 新增学生
    * */
   @PostMapping("/add")
   public Result add(@RequestBody Student student){
       studentService.add(student);
       return Result.success();
  }

   /**
    * 更新学生
    */
   @PutMapping("/update")
   public Result update(@RequestBody Student student){
       studentService.updateById(student);
       return Result.success();
  }

   /**
    * 删除学生
    */
   @DeleteMapping("/deleteById/{id}")
   public Result deleteById(@PathVariable Integer id) {
       studentService.deleteById(id);
       return Result.success();
  }

   /**
    * 分页查询
    * */
   @GetMapping("selectPage")
   public Result selectPage(Student student,
                            @RequestParam(defaultValue = "1") Integer pageNum,
                            @RequestParam(defaultValue = "5") Integer pageSize){
       PageInfo<Student> pageInfo = studentService.selectPage(student,pageNum,pageSize);
       return Result.success(pageInfo);
  }
}

Service—StudentService 核心逻辑

/**
 * 学生模块业务逻辑接口
 * 要把数据往数据库里存,调用mapper层的方法,返回结果
 * 业务逻辑接口调用mapper层的方法,返回结果
 */
@Service
public class StudentService {
    //    注入StudentMapper
    @Resource
    private StudentMapper studentMapper;
    /**
     * 新增学生
     */
    public void add(Student student) {
        // 确保这里没有设置或使用student.setTitle()方法
        Student dbStudent = studentMapper.selectByUsername(student.getUsername());
        if (ObjectUtil.isNotEmpty(dbStudent)) {
            throw new CustomException("用户名已存在");
        }
        if(ObjectUtil.isEmpty(student.getPassword())){
            student.setPassword("123456");
        }
        student.setRole("STUDENT");
        student.setScore(0);
        studentMapper.insert(student);
    }
    /**
     * 分页查询
     */
    public PageInfo<Student> selectPage(Student student,Integer pageNum, Integer pageSize) {
        // ToDo 分页查询逻辑处理
        // 1. 分页查询学生信息
        // 2. 返回学生信息
        // 3. 如果没有学生信息,返回空列表
        // 4. 如果有学生信息,返回学生信息列表
        List<Student> list;//定义一个list集合
        PageHelper.startPage(pageNum,pageSize);//分页查询
        if(ObjectUtil.isNotEmpty(student.getName())){//如果name不为空,就按照name查询
            list = studentMapper.selectByName(student.getName());
        }else{//如果name为空,就查询所有学生信息
           list = studentMapper.selectAll();
        }
        return PageInfo.of(list);//返回学生信息列表
    }
​
    //根据id查询学生信息,返回一个student对象
    public void updateById(Student student) {//传入一个student对象
        studentMapper.updateById(student);//调用mapper层的方法,返回结果
    }
​
​
    //根据id删除学生信息
    public void deleteById(Integer id) {
        studentMapper.deleteById(id);
    }
}

Mapper—StudentMapper

@Mapper
public interface StudentMapper {
//   新增学生
   void insert(Student student);
   @Select("select * from student where username = #{username}")
   Student selectByUsername(String username);

   // 查询所有学生信息
   @Select("select * from student")
   List<Student> selectAll();

   // 根据学生姓名查询学生信息,模糊查询
   @Select("select * from student where name like concat('%',#{name},'%')")
   List<Student> selectByName(String name);


   void updateById(Student student);//更新学生信息

   // 根据id删除学生信息
   @Delete("delete from student where id = #{id}")
   void deleteById(Integer id);
}

StudentMapper.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.StudentMapper">
   <insert id="insert" parameterType="com.example.entity.Student" useGeneratedKeys="true">
      insert into student (username, password, name, sex, role, avatar, college_id, code, score)
      values (#{username}, #{password}, #{name}, #{sex}, #{role}, #{avatar}, #{collegeId}, #{code}, #{score})
   </insert>

   <update id="updateById" parameterType="com.example.entity.Student">
      update student
      set username = #{username}, password = #{password}, name = #{name},
          sex = #{sex}, college_id = #{collegeId}, role = #{role}, avatar = #{avatar},
          score = #{score}, code = #{code}
      where id = #{id}
   </update>
</mapper>

版权声明

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

发送评论 编辑评论


				
上一篇
下一篇