15. 开发成绩管理功能
SQL
CREATE TABLE `grade` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`course_id` int(11) DEFAULT NULL COMMENT '课程ID',
`student_id` int(11) DEFAULT NULL COMMENT '学生ID',
`score` double(10,1) DEFAULT NULL COMMENT '分数',
`comment` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评语',
`feedback` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '学生反馈',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成绩';
打分弹窗
<el-dialog width="35%" v-model="data.formVisible" title="成绩信息">
<el-form :model="data.gradeForm" label-width="100px" label-position="right" style="padding-right: 40px">
<el-form-item label="课程名称">
<el-input v-model="data.gradeForm.name" autocomplete="off" disabled />
</el-form-item>
<el-form-item label="分数">
<el-input v-model="data.gradeForm.score" autocomplete="off" />
</el-form-item>
<el-form-item label="评语">
<el-input type="textarea" v-model="data.gradeForm.comment" autocomplete="off" />
</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>
成绩查询的逻辑
注意要写 studentName、courseName Getter 和 Setter 方法
<?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.GradeMapper">
<select id="selectAll" resultType="com.example.entity.Grade">
select grade.*, student.name as studentName, course.name as courseName
from grade
left join student
on grade.student_id = student.id
left join course
on grade.course_id = course.id
<where>
<if test="studentName != null">and student.name like concat('%', #{studentName}, '%')</if>
<if test="courseName != null">and course.name like concat('%', #{courseName}, '%')</if>
<if test="studentId != null">and grade.student_id = #{studentId}</if>
</where>
order by id desc
</select>
</mapper>
成绩编辑的弹窗
<el-dialog width="35%" v-model="data.formVisible" title="反馈信息">
<el-form :model="data.form" label-width="100px" label-position="right" style="padding-right: 40px">
<el-form-item label="评分" v-if="data.user.role === 'ADMIN'">
<el-input v-model="data.form.score" autocomplete="off" />
</el-form-item>
<el-form-item label="评语" v-if="data.user.role === 'ADMIN'">
<el-input type="textarea" v-model="data.form.comment" autocomplete="off" />
</el-form-item>
<el-form-item label="反馈" v-if="data.user.role === 'STUDENT'">
<el-input type="textarea" v-model="data.form.feedback" autocomplete="off" />
</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>
成绩操作按钮需要判断角色

在管理员打分的时候要做个判断提醒

@Select("select * from grade where student_id = #{studentId} and course_id = #{courseId}")
Grade selectByCondition(Grade grade);
完整的成绩页面
<template>
<div>
<div class="card" style="margin-bottom: 10px">
<el-input style="width: 260px; margin-right: 10px" v-model="data.courseName" placeholder="请输入课程名称查询"
:prefix-icon="Search"/>
<el-input style="width: 260px; margin-right: 10px" v-model="data.studentName" placeholder="请输入学生名称查询"
:prefix-icon="Search"/>
<el-button type="primary" style="margin-left: 10px" @click="load">查询</el-button>
<el-button type="info" @click="reset">重置</el-button>
</div>
<div class="card" style="margin-bottom: 10px">
<div>
<el-table :data="data.tableData" style="width: 100%">
<el-table-column prop="id" label="序号" width="70"/>
<el-table-column prop="courseName" label="课程名称"/>
<el-table-column prop="studentName" label="学生名称"/>
<el-table-column prop="score" label="分数"/>
<el-table-column prop="comment" label="评语"/>
<el-table-column prop="feedback" label="反馈"/>
<el-table-column label="操作" width="180">
<template #default="scope">
<el-button type="primary" @click="handleEdit(scope.row)" v-if="data.user.role === 'ADMIN'">编辑</el-button>
<el-button type="danger" @click="del(scope.row.id)" v-if="data.user.role === 'ADMIN'">删除</el-button>
<el-button type="primary" @click="handleEdit(scope.row)" v-if="data.user.role === 'STUDENT'">反馈</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="card">
<el-pagination v-model:current-page="data.pageNum" v-model:page-size="data.pageSize"
@current-change="handelCurrentChange"
background layout="prev, pager, next" :total="data.total"/>
</div>
<el-dialog width="35%" v-model="data.formVisible" title="反馈信息">
<el-form :model="data.form" label-width="100px" label-position="right" style="padding-right: 40px">
<el-form-item label="评分" v-if="data.user.role === 'ADMIN'">
<el-input v-model="data.form.score" autocomplete="off" />
</el-form-item>
<el-form-item label="评语" v-if="data.user.role === 'ADMIN'">
<el-input type="textarea" v-model="data.form.comment" autocomplete="off" />
</el-form-item>
<el-form-item label="反馈" v-if="data.user.role === 'STUDENT'">
<el-input type="textarea" v-model="data.form.feedback" autocomplete="off" />
</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 {Search} from '@element-plus/icons-vue'
import request from "@/utils/request";
import {ElMessage, ElMessageBox} from "element-plus";
const data = reactive({
form: {},
courseName: '',
studentName: '',
tableData: [],
total: 0,
pageNum: 1, // 当前的页码
pageSize: 5, // 每页的个数
user: JSON.parse(localStorage.getItem('student-user') || '{}'),
formVisible: false
})
const load = () => {
let params = {
pageNum: data.pageNum,
pageSize: data.pageSize,
courseName: data.courseName,
studentName: data.studentName
}
if (data.user.role === 'STUDENT') { // 如果当前登录的是学生,那就查询自己的选课记录
params.studentId = data.user.id
}
request.get('/grade/selectPage', {
params: params
}).then(res => {
data.tableData = res.data?.list || []
data.total = res.data?.total || 0
})
}
// 调用方法获取后台数据
load()
const handelCurrentChange = () => {
// 当翻页的时候重新加载数据即可
load()
}
const reset = () => {
data.courseName = ''
data.studentName = ''
load()
}
const del = (id) => {
ElMessageBox.confirm('删除数据后无法恢复,您确认删除吗?', '删除确认', { type: 'warning' }).then(res => {
request.delete('/grade/delete/' + id).then(res => {
if (res.code === '200') {
load() // 重新获取数据
ElMessage.success("操作成功")
} else {
ElMessage.error(res.msg)
}
})
}).catch(res => {})
}
// 打分
const handleEdit = (row) => {
data.form = JSON.parse(JSON.stringify(row)) // 拷贝行数据到表单对象
data.formVisible = true
}
const save = () => {
request.put('/grade/update', data.form).then(res => {
if (res.code === '200') {
load()
data.formVisible = false // 关闭弹窗
ElMessage.success("操作成功")
} else {
ElMessage.error(res.msg)
}
})
}
</script>
完整的成绩接口
package com.example.controller;
import com.example.common.Result;
import com.example.entity.Grade;
import com.example.service.GradeService;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 成绩接口
*/
@RestController
@RequestMapping("/grade")
public class GradeController {
@Resource
GradeService gradeService;
@PostMapping("/add")
public Result add(@RequestBody Grade grade) {
gradeService.add(grade);
return Result.success();
}
@PutMapping("/update")
public Result update(@RequestBody Grade grade) {
gradeService.update(grade);
return Result.success();
}
/**
* 删除成绩
*/
@DeleteMapping("/delete/{id}")
public Result delete(@PathVariable Integer id) {
gradeService.deleteById(id);
return Result.success();
}
/**
* 分页条件查询课程
*/
@GetMapping("/selectPage")
public Result selectPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "5") Integer pageSize,
Grade grade) { // ?name=xx&no=xx
PageInfo<Grade> pageInfo = gradeService.selectPage(pageNum, pageSize, grade);
return Result.success(pageInfo);
}
}