Student Performance Management System for Web Course Design

Student performance management system based on Web course design

1. Experimental topic

Student Performance Management System

2. The purpose of the experiment

The course design of Web application technology is a comprehensive practical learning programming link for computer software engineering majors, and it is a comprehensive comprehensive exercise after learning the course "Internet and Web Programming". Its purpose is to promote our review and consolidation of computer software design knowledge, deepen our understanding of software design methods, software design techniques and design ideas, and use the learned software design knowledge and web engineering techniques to carry out comprehensive software design. Through this course design , I can master the methods of software design and the basic technology of object-oriented design, and can improve my comprehensive application ability in software development.

Through the design of this course, I have further mastered the application and learning of the front-end framework vue, the vue desktop component library elementui, and the back-end framework ssm. Apply the framework knowledge you have learned to practice.

Regarding the design of this system, the author finally finalized the design subject as the student performance management system out of the consideration of the following points:

All schools have an educational administration system that can add, delete, modify, and check student information, enter and view student grades, export tables, analyze individual grades and class grades, and display data. The educational administration system has become a teacher to understand and care about students and master the learning situation of the class Therefore, the student performance management system has its very important application value, and the use of the system itself requires the login of designated personnel to avoid malicious operations. The design of the student performance management system in this experiment is exactly Considering the above points and considering the necessary value and functions of the student performance management system, further development and design are carried out. This system has its expansion functions, but there are still deficiencies. The following is a detailed analysis of the system design process.

3. Overall design

3.1 Experimental requirements:

1. Add student function: name, student number, gender, date of birth. (Student number is automatically generated and unique).

2. Add the function of student grades: Everyone has four courses: Mathematics, Java, English, and Physical Education, and grades can be entered by course.

3. The function of searching for student grades according to the student ID: display the name, student ID and grades on the interface, and give a prompt message if the student ID does not exist.

4. The function of finding student grades according to the student's name (support fuzzy matching): and display the name, student number and grades on the interface. If there are multiple students with the same name, they will be displayed together. If the name does not exist, a prompt message will be given.

5. Support to draw a histogram distribution chart for each subject of a single student.

6. The modification and deletion function of student information: the student ID cannot be modified.

7. The function of generating a student learning report report: the report includes the student number, name, grades of each subject and the corresponding class average of the subject, the total grade and the average of the class's total grade, and the sorting results are output to an excel file.

Conceptual model of system function:

insert image description here

3.2 The technology stack used in this system:

Project management tool: Maven

Version control system: Git

Front-end technology: html, css, javascript, vue, elementui, Echarts

Front-end and back-end communication technology: axios

Web application server: Tomcat

Database technology: MySql

Backend technology: Spring, SpringMVC, Mybatis, JavaBean, EasyExcel

3.3 Programming tools used in this system

Code writing: IntelliJ IDEA 2020.1

Graphical database management tool: Navicat for MySQL

Database modeling tool: PowerDesigner

Web application server: Tomcat7.0

Project management tool: Maven

Code hosting service: gitee

3.4 Core Technology Introduction

Vue: Vue.js is a progressive framework for building user interfaces. Unlike other heavyweight frameworks, Vue is designed to be developed incrementally from the bottom up. Vue's core library only focuses on the view layer.

Axios: Axios is an HTTP client based on Promise for browsers and nodejs.

Spring: Spring is a lightweight Java development framework designed to solve the coupling problem between the business logic layer and other layers of enterprise-level application development.

SpringMVC: SpringMVC is a module of the Spring framework, which is a webframework module based on mvc. MVC is an architectural pattern of web-side services, namely model -view-controller.

MyBatis: MyBatis is an excellent persistence layer framework that supports custom SQL, stored procedures, and advanced mapping. MyBatis eliminates almost all JDBC code and the work of setting parameters and getting result sets. MyBatis can configure and map primitive types, interfaces and JavaPOJOs as records in the database through simple XML or annotations.

Echarts: A pure Javascript charting library that can run smoothly on PCs and mobile devices, and is compatible with most current browsers. Provide intuitive, vivid, interactive, and highly customizable data visualization charts.

EasyExcel: EasyExcel is a simple Java-based, memory- saving open source project for reading and writing Excel. In the case of saving memory as much as possible, it supports reading and writing Excel of 100 megabytes.

3.5 Module Introduction

Database conceptual data model design:

insert image description here

Database table design:

insert image description here

insert image description here

insert image description here

insert image description here

insert image description here

login module:
insert image description here

Home Module:
insert image description here
Student Information Inquiry Module:

insert image description here

Student achievement query module:

insert image description here
Student performance analysis module:
insert image description here

Modal box modules for creating new student information, entering student grades, viewing student grades, editing student information, etc.:

insert image description here
insert image description here
insert image description here

3.6 Design steps

1. Create a Maven project, add public static files, and write core configuration files such as web.xml

2. Write the ssm configuration file, use Mybatis reverse engineering to generate mapper files and entity classes, modify the mapper configuration file, and add a method to query student information with grades.

3. Introduce vue and elementui component library files, design the overall framework of the front-end page, use PageHelper to write the paging code of the back-end Controller control layer, and return json data normally.

4. Realize the function of querying student information by page and displaying it on the front page.

5. Realize the function of adding student information and deleting student information.

6. Realize the function of modifying student information. After clicking the edit button, the background data will be echoed to the edit modal box, and data verification can be performed to give prompt information.

7. Realize the function of entering student grades and checking students' personal grades on the student information query page. And realize the page of querying student grades, where students' grades can be modified.

8. Realize the common function of analyzing student grades and the average score of each subject in the class and generating a histogram of student grades, and encapsulate the code for updating the average score of each subject in the class into a function, perfecting the operation that may involve changes in the average score of the class The code uses the avg_grade database.

9. Beautify the front-end interface, and realize the function of login and registration, and design an interceptor so that users cannot access the system without logging in.

10. Realize displaying the learning status of the students in the class inquired on the student performance analysis page. The average total score of the students in the class is divided into 5 grades of excellent, good, medium, pass, and fail according to the score standards of each stage , and display the distribution of the number of students at each grade level on the front page in the form of a pie chart.

11. Realize the function of exiting the system. Once the exit system is clicked, the session data of the website will be eliminated, and the current page will be refreshed to enter the login interface. Users must log in to continue to access the system.

12. Realize the export of student information with student grades to an excel file.

4. Detailed design

4.1 Introduction to project resource directory:

insert image description here

insert image description here

4.2 Key code introduction

4.2.1 Create a Maven project and import related jar package dependencies

① ssm framework related jar package dependencies: spring-webmvc, spring-jdbc, spring-aspects, mybatis, mybatis-spring

② Database connection driver-related jar package dependencies: c3p0, mysql

③ Server plug-in dependency: tomcat7-maven-plugin

④ Other jar package dependencies: jstl, servlet-api, junit

⑤ The jar package dependencies that need to be used in the follow-up: mybatis-generator-core (mybatis reverse engineering), pagehelper (paging plug-in), spring-test, jackson-databind (supports returning json strings), hibernate-validator (JSR303 data verification support), log4j (log4j log file), easyexcel (export excel form).

4.2.2 Write spring, springmvc, mybatis configuration files

① Write the web.xml file

Write the code to start the spring container and create the applicationContext.xml file (mainly related to configuration and business logic). Configure the front controller of springmvc and create the dispatcherServlet-servlet.xml file. Configure character encoding filters.

② Configure springmvc

Configure springmvc (including the control of website jump logic) in dispatcherServlet-servlet.xml.

<!--    扫描控制器组件-->
    <context:component-scan base-package="com.shenshang" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

③ configure spring

Configure spring in applicationContext.xml, where the main configuration is related to business logic. Configure data sources, configure integration with mybatis, configure scanners, configure transaction managers, and enable annotation-based transactions.

④ configure mybatis

Copy the corresponding configuration template in the official document, write the global configuration file, including camel case naming rules and use the typeAliases tag to alias the Java type.

4.2.3 Use mybatis reverse engineering to modify the mapper configuration file

MyBatis Generator: MBG for short, is a code generator specially customized for MyBatis framework users, which can quickly generate corresponding mapping files, interfaces, and bean classes according to tables. Supports basic addition, deletion, modification and query, as well as QBC-style conditional query. However, the definition of complex SQL such as table connection and stored procedure needs to be written manually.

Use PowerDesigner to design the ER diagram of the database conceptual model, export it as a sql statement file, and run it in navicat to generate a table that automatically creates a foreign key relationship.

Refer to the example of using mybatis reverse engineering on the mybatis official website, create the mbg.xml file in the main project, copy the example code to mbg.xml, modify the mbg.xml file, configure the database connection, specify the location where JavgBean is generated, and specify sql Map the location where the mapper file is generated, specify the location where the dao interface is generated, and specify the generation strategy for each table. Find the Java Program in the Running MyBatis Generator on the mybatis official website, create MBGTest.java in the test folder test and run this code, reverse engineering to generate the specified file.

Since complex connection query sql statements need to be manually written, we modify the mapper file and write the sql statement of the connection table, so that we can directly call the method when writing the business logic method, and query the information of a single student with grades. list of students. After modifying the mapper file, create MapperTest.java in the test folder test to create an interface to test the operation database method in the implementation class, observe whether there are bugs, and further modify and improve the code.

4.2.4 Import static files and component library files, and test to return json data.

Create plugins and static packages in the webapp package, and introduce component library files such as vue, elementui and jquery and axios into it. Create the stuInfoController.java file in the Controller package, use the PageHelper paging plug-in, and test whether it can return json data.

@ResponseBody
@RequestMapping("/findPage")
public Msg getPageInfoWithJson(@RequestParam(value = "pn",defaultValue = "1")Integer pn){
    
    
    PageHelper.startPage(pn,5);
    List<Student> studentList = stuInfoService.getStudentList();
    PageInfo pageInfo = new PageInfo(studentList,5);
    return Msg.success().add("pageInfo",pageInfo);
}

4.2.5 Realize the function of querying student information by paging and displaying it on the front-end page

Write the front-end page code, refer to the elementui official document, add components, use v-model inside the input box component label to realize two-way data binding, such as query input box, input content in the input box, front-end v-model data binding Afterwards, a post request is sent through axios, the Controller layer uses the @RequestBody annotation for parameter mapping, gets the front-end parameters, creates the Service interface and Service implementation class, creates the Service entity class object and calls the internal method of the entity class to operate the database, and queries the student information list , and encapsulate the total information and data into a PageResult and return it to the Controller layer, and then return to the front end.

The Service interface to obtain student information implements the class method getStudentList():

public PageResult getStudentList(Integer currentPage, Integer pageSize, String queryString){
    
    
//        截取查询条件
    String[] queryList = queryString.split("-");
//        正则表达式判断字符串是否为数字
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    for (int i = 0; i < queryList.length; i++) {
    
    
        if (pattern.matcher(queryList[i]).matches() && !queryList[i].equals("")&& Integer.parseInt(queryList[i] <= 7)){
    
    //字符串是数字且不为空且不小于7
            int classId = Integer.parseInt(queryList[i]);//将该字符串转换成数字
            criteria = criteria.andClassidEqualTo(classId);//将班级id拼接到查询条件中
        }else if (!queryList[i].equals("")){
    
    
            criteria = criteria.andNameLike("%"+queryList[i]+"%");//将姓名拼接到查询条件
        }
    }
        PageHelper.startPage(currentPage,pageSize);
//        Page<Student> page = (Page<Student>) studentMapper.selectByExample(studentExample);
    Page<Student> page = (Page<Student>) studentMapper.selectByExampleWithGrade(studentExample);
    return new PageResult(page.getTotal(),page.getResult());
}

The front-end sends axios request to get the back-end data and assign parameters:

//分页查询学生信息
searchBtn(){
    
    
    // 使得查询按钮点下时都是从第一页开始显示数据
    this.pagination.currentPage = 1;
    //分页参数
    let param = {
    
    
        currentPage:this.pagination.currentPage,
        pageSize:this.pagination.pageSize,
        queryString:this.queryString.queryName+'-'+this.queryString.classSelected
    };
    // axios请求后台获取数据
    axios.post("/stuInfo/findPage",param).then((response)=>{
    
    
        // 为模型数据赋值,通过vue的双向数据绑定输出到页面
        this.tableData = response.data.rows;
        this.pagination.total = response.data.total;
    })
},

Note: The purpose of creating the PageResult entity class: to encapsulate the paging result class, and return the query data and paging bar information to the front end together.

4.2.6 Realize the function of adding student information

The overall logic is similar to the query logic. It should be noted that the form must be reset inside the pop-up modal box after clicking the Add button. Otherwise, the form will still retain the data and verification information left over from the last input, which will give users a bad experience. good. Furthermore, after clicking the OK button inside the new modal box, an axios request is sent, and the parameters passed in by the front end include student name, gender, class, birthday and other information. It must be noted that if you want to use the @RequestBody annotation to put json The data is automatically converted into the corresponding entity class. The parameters passed in by the front end must be the same as the corresponding attribute names in the entity class, otherwise the parameters received by the back end are empty. After the gender and birthday are converted into a unified data type in the database in the Service implementation class method body of the new student information, the insertSelective() method is called through the studentMapper to insert the database data.

The Service interface implementation class method add() of the new student information:

public void add(Student student) {
    
    
//        随机生成学号
    Random random = new Random();
    int sId = random.nextInt(5000) + 7;//学号
    student.setId(sId);
//        把参数中学生性别进行转换
    if (student.getSex().equals("1")){
    
    
        student.setSex("男");
    }else{
    
    
        student.setSex("女");
    }
//        设置学生生日格式为"xxx年xx月xx日"
    String birthday = student.getBirthday();
    String[] birthdaySplitList = birthday.split("-");
    student.setBirthday(birthdaySplitList[0]+"年"+birthdaySplitList[1]+"月"+birthdaySplitList[2]+"日");
//        调用函数新增学生信息
    studentMapper.insertSelective(student);
}

It should be noted that the front end needs to perform form verification. If the form verification fails to pass the confirmation button, a prompt message will be given, and the axios request cannot be sent. When the input form data meets the requirements and the confirmation button is clicked, the axios request will be sent after the call end method.

Added student information modal box form validation rules on the front end:

rules:{
    
    //学生信息表单校验规则
    stuName:[
        {
    
     required: true, message: '请输入姓名', trigger: 'blur' },
        {
    
     min :2,max :5,message: '输入姓名长度在2到5个字符' },
    ],
    stuSex:[
        {
    
     required: true, message: '性别必须选择', trigger: 'blur'}
    ],
    stuClass:[
        {
    
     required: true, message: '班级必须选择', trigger: 'blur'}
    ],
    stuBorn: [
        {
    
     required: true, message: '请输入出生日期', trigger: 'blur' },
    ]
},

Front-end reset form data and verification information method:

// 重置表单数据和表单校验信息
resetForm(){
    
    
    // 把模态框表单中数据清空
    this.modalBox.form = {
    
    
        // stuId: '',
        stuName: '',
        stuSex: '1',
        stuClass: '',
        stuBorn:''
    };
    // 清除上次校验效果
    this.$nextTick(()=>{
    
    //Dom没有加载完成,导致获取不到refs元素
        // 方法作用是当数据被修改后使用这个方法,会回调获取更新后的dom再渲染出来
        this.$refs['modalBox.form'].clearValidate(['stuName','stuSex','stuClass','stuBorn']);
    })
},

Click the OK button to verify whether the form input information meets the verification rules. If it is not satisfied, a prompt message will be given: the form data verification failed; if it is satisfied, an axios request will be sent, and the key code will be given in subsequent similar operations.

4.2.7 Realize the function of deleting student information

The first thing to note is that if the foreign key relationship between the grade table and the student table is not established correctly, a bug will occur when deleting student information. When the delete button is clicked, a prompt message should pop up to prompt the user whether to delete the student information whose student ID is xxx. When the user clicks OK, the student information of the specified student ID will be deleted. When the user clicks cancel, no operation will be performed. In addition, when the user clicks the OK button, the axios request is sent with only one parameter: the student number. The author got stuck for a long time when writing the delete function. The foreground transmits the student number parameters, and the background also uses the @RequestBody annotation to receive the parameters. As a result, the data obtained in the background has an extra equal sign, which is puzzling. I thought it was a problem with the data binding. After screening, I found that it was not bound After collecting a large amount of data, it was found that the reason for the different types of data transmission between the front and back ends. After collecting a lot of information, it is found that when the front end sends an axios request, the Content-Type inside the default request headers is application/x-www-form-urlencoded;charset=UTF-8, which is a key-value pair data Structure, during the transmission process, the json is regarded as the key, and the value is regarded as a null value, so there will be an extra equal sign when transmitted to the backend. It is necessary to set the request headers information when sending an axios request, and unify the data encoding received by the backend with the frontend settings to solve the problem.

The method code executed when the front-end code clicks the delete button:

// 删除按钮,点击删除单行数据
handleDelete(row) {
    
    
    this.$confirm('确定删除学号为'+row.id+'的学生信息吗?', '提示', {
    
    
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
    
    
       // 发送ajax请求,请求后台删除指定学号的学生信息
        axios.post("stuInfo/delete",row.id,{
    
    
            headers: {
    
    
                'Content-Type':'application/json'
            }
        }).then((response)=>{
    
    
            if (response.data.flag){
    
    
                // 删除成功
                this.$message({
    
    
                    message: response.data.message,
                    type: 'success'
                })
            }else{
    
    
                // 删除失败
                this.$message.error(response.data.message);
            }
        }).finally(()=>{
    
    
            // 重新获取删除后的分页数据
            this.searchBtn();
        })
    });
},

When the backend Controller layer receives parameters, it also needs to specify the format of the received data:

@RequestMapping(value = "/delete",produces = "application/json;charset=UTF-8")//指定接收数据的格式
public Result deleteStuInfo(@RequestBody String id){
    
    
    try {
    
    
        int sid = Integer.parseInt(id);
        stuInfoService.deleteById(sid);
    }catch (Exception e){
    
    
        e.printStackTrace();
        return new Result(false , MessageConstant.DELETE_STU_FAIL);
    }
    return new Result(true , MessageConstant.DELETE_STU_SUCCESS);
}

Then use the studentMapper entity class in the Service interface implementation class to call the deleteByPrimaryKey() method to delete the student information of the specified student number from the database.

4.2.8 Realize the function of modifying student information

The difference from other functions is that when the edit button is clicked, the edit modal box will pop up, and the student’s information needs to be echoed out in the edit modal box form. When echoing, it is necessary to pay attention to the different data storage formats of the front and back ends. To convert the data format, it is also necessary to verify the data in the edit modal box form. If the format is incorrect, a verification prompt message will be given. Only when the verification is passed can the modification be successful, and the specified student number in the database will be updated. Student Information. Click the edit button on the front end, change the value of dialogFormVisibleEdit to true to realize the display of the modal box, and then send axios to request the background data. Note that the parameter of the student ID is still passed at this time, and the request header information still needs to be set. And unify the data encoding received by the back end with the front end settings.

The echo data method code executed after the front end clicks the edit button:

// 表格中的编辑按钮
handleUpdate(row){
    
    
    // alert(row.id);
    // 发送请求获取目前行学生信息
    axios.post("/stuInfo/findById",row.id,{
    
    
        headers:{
    
    
            'Content-Type':'application/json'
        }
    }).then((response)=>{
    
    
        if (response.data.flag){
    
    
            // 显示出编辑模态框
            this.modalBox.dialogFormVisibleEdit = true;
            // 将数据回显到编辑模态框的表单中
            this.modalBox.editForm.stuId = response.data.data.id;
            this.modalBox.editForm.stuName = response.data.data.name;
            this.modalBox.editForm.stuSex = response.data.data.sex == "男"? '1':'0';
            this.modalBox.editForm.stuClass = response.data.data.classid;
            this.modalBox.editForm.stuBorn = response.data.data.birthday;
        }else{
    
    
            this.$message.error(response.data.message);
        }
    })
},

Because the front-end acquisition or reception is different from the data format stored in the database, it should be noted that the findById() method in the back-end Service interface implementation class needs to convert the format of the student information data of the specified student number in the queried database, and then return to the front-end exhibit:

public Student findById(Integer id) {
    
    
    Student student = studentMapper.selectByPrimaryKey(id);
//            把xx年xx月xx日格式的字符串转变成xx-xx-xx格式的字符串,便于在前端赋值给日期选择器
//            2014年01月10日
    String year = student.getBirthday().substring(0,4);
    String mouth = student.getBirthday().substring(5,7);
    String day = student.getBirthday().substring(8,10);
//            重新设置student类的birthday属性遵循xx-xx-xx的格式
    student.setBirthday(year+"-"+mouth+"-"+day);
    return student;
}

When clicking the OK button in the edit modal box, the form data needs to be verified first. Any input information in the input box that does not meet the verification rules cannot be submitted, and a prompt message will be given, even if no modification is made to the student information. Then the update method will still be executed in the background, but the student information is updated to the original information (that is, no modification is made). The code of the front-end form verification method is posted here, and other verification codes that need to be used are the same as here Similar to:

//编辑模态框中的确定更新按钮
handleEdit() {
    
    
    let param = {
    
    
        id:this.modalBox.editForm.stuId,
        name:this.modalBox.editForm.stuName,
        sex:this.modalBox.editForm.stuSex,
        classid:this.modalBox.editForm.stuClass,
        birthday: this.modalBox.editForm.stuBorn
    }
    // 校验表单数据
    this.$refs['modalBox.editForm'].validate((valid)=>{
    
    
        if (valid){
    
    
            // 校验成功,发送axios请求
            axios.post("stuInfo/update",param).then((response)=>{
    
    
                // 隐藏编辑模态框
                this.modalBox.dialogFormVisibleEdit = false;
                if (response.data.flag){
    
    
                    // 更新数据成功
                    this.$message({
    
    
                        message: response.data.message,
                        type: 'success'
                    });
                }else{
    
    
                    // 更新数据失败
                    this.$message.error(response.data.message);
                }
            }).finally(()=>{
    
    
                // 展示更新后的表格数据
                this.searchBtn();
            })
        }else{
    
    
            // 校验失败
            this.$message.error('表单校验数据失败');
            return false;
        }
    })
},

4.2.9 Realize the entry of student grades and the ability to view student grades on the student information management page

To realize this function, it should be noted that there is an operation column in the table on the front-end page, and there are two buttons for input and view in the operation column. When students have not entered their grades, the input button can be clicked, but the view button cannot be clicked. , after the student's grades have been entered, the view button can be clicked to view the student's grades, and the entry button is set to be unclickable to avoid repeated entry or check the grades to be empty. The implementation of this operation is mainly based on the flag value in the database s_stu table. When the student’s grades are not entered (after creating new student information), the flag value is null. At this time, when the entry button detects that the flag value is null, it is set to a clickable state , set the view button to unclickable state, when the student’s grades have been entered, set the flag value to 1, when the entry button detects that the flag value is 1, set the entry button to a non-clickable state, and set the view button to a clickable state. The code for the two buttons on the front end is as follows:

<el-button slot="reference" type="text" size="small" :disabled="scope.row.flag == 1? false:true">查看</el-button>
<el-button type="text" size="small" @click="gradeInput(scope.row)" :disabled="scope.row.flag == 1? true:false">录入</el-button>

After the input button is clicked, the modal box for entering grades will be displayed, the form data and verification information will be reset, and the acquired student ID will be assigned to the stuId in the form to facilitate data transfer later. When the OK button in the input modal box is clicked, the input content of the form needs to be verified, and the axios request can only be sent when the input result meets the verification rules, and the flag value of the student with the specified student number is set in the Service interface implementation class 1, and then insert the student's grades into the s_grade table.

The method code of the backend Service interface implementation class:

public void inputGrade(Grade grade) {
    
    
//        计算出该学生的总成绩
    Integer sum = grade.getMath()+grade.getJava()+grade.getEnglish()+grade.getPe();
    grade.setGradenum(sum);
//        把指定学号的学生信息的flag值置为1,表示该学生的成绩已经录入了
    Student student = studentMapper.selectByPrimaryKey(grade.getId());
    student.setFlag(1);
//        将数据更新到数据库中
    studentMapper.updateByPrimaryKeySelective(student);
    gradeMapper.insertSelective(grade);
}

After entering the student's grades, the view button on the front end will be set to a clickable state. At this time, clicking the view button will pop up a message prompt box to display the student's personal grades. The logic implementation is mainly implemented through the front-end code using the tags in elementui. Since the query method used by the back-end implementation class method for displaying paginated data is to query the list of students with grades, there is no need to request the back-end when viewing student grades on the front-end Data, just display the front-end parameter values ​​directly.

The code for viewing the results at the front end:

<el-table-column label="成绩" width="185">
    <template slot-scope="scope">
        <el-popover placement="right" width="200" trigger="click">
            <el-tag>学号:{
    
    {
    
    scope.row.id}}</el-tag>
            <el-tag type="success">姓名:{
    
    {
    
    scope.row.name}}</el-tag>
            <p><el-tag type="warning">数学成绩:{
    
    {
    
    scope.row.grade.math}}</el-tag></p>
            <p><el-tag type="warning">java成绩:{
    
    {
    
    scope.row.grade.java}}</el-tag></p>
            <p><el-tag type="warning">英语成绩:{
    
    {
    
    scope.row.grade.english}}</el-tag></p>
            <p><el-tag type="warning">体育成绩:{
    
    {
    
    scope.row.grade.pe}}</el-tag></p>
            <p><el-tag type="danger">总成绩:{
    
    {
    
    scope.row.grade.gradenum}}</el-tag></p>
            <el-button slot="reference" type="text" size="small" :disabled="scope.row.flag == 1? false:true">查看</el-button>
        </el-popover>
        <el-button type="text" size="small" @click="gradeInput(scope.row)" :disabled="scope.row.flag == 1? true:false">录入</el-button>
    </template>
</el-table-column>

4.2.10 Realize the function of querying student grades and modifying designated student grades

Create the gradeSearch.html file and add front-end components. The query function here is similar to the query function of student information. Both the front and back ends use query condition splicing. You can query student grades according to student number, name, and class, and the front end splices the query conditions , use the "-" symbol in the middle to connect, when the data is sent to the backend, use the split() method to cut the string, and then traverse the string array generated after cutting, and convert the student number and class strings into numbers , and then spliced ​​into the sql statement to operate the database. Here, the student number and class number are processed in the sql statement splicing. Since the class number and the student number can be converted into numbers, it is necessary to judge whether the value of the string array unit is the student number or the class number. The convention here is: The student number must be greater than 7, and the class number must not be greater than 7, so judge accordingly.

The code for implementing the class method of the backend Service interface:

public PageResult getStudentList(Integer currentPage, Integer pageSize, String queryString){
    
    
//        截取查询条件
    String[] queryList = queryString.split("-");
//        正则表达式判断字符串是否为数字
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    for (int i = 0; i < queryList.length; i++) {
    
    
        if (pattern.matcher(queryList[i]).matches() && !queryList[i].equals("")){
    
    //字符串是数字且不为空
            int tmp = Integer.parseInt(queryList[i]);
            if (tmp > 7){
    
    //说明tmp是学号
                int stuId = tmp;//把中间值赋值给学号
                criteria = criteria.andIdEqualTo(stuId);//把学号拼接到查询条件中
            }else{
    
    //说明tmp是班级号
                int classId = Integer.parseInt(queryList[i]);//将该字符串转换成数字
                criteria = criteria.andClassidEqualTo(classId);//将班级id拼接到查询条件中
            }
        }else if (!queryList[i].equals("")){
    
    
            criteria = criteria.andNameEqualTo(queryList[i]);//将姓名拼接到查询条件
        }
    }
    PageHelper.startPage(currentPage,pageSize);
    Page<Student> page = (Page<Student>) studentMapper.selectByExampleWithGrade(studentExample);
    return new PageResult(page.getTotal(),page.getResult());
}

In the front-end page of gradeSearch.html, you can modify the grades of the specified students in each subject. Click the edit button to pop up the edit grade modal box. Before popping up the modal box, you need to clear the form data and reset the form verification information. You also need to The form data is echoed and verified, and the data that meets the specified verification rules can be sent to the backend. The form data that does not meet the verification rules cannot be submitted, and a prompt message will be given after clicking the OK button. It should be noted that the edit button also determines whether the edit button can be clicked by judging the flag value in the s_stu table, and sets the score edit button of the student who has not entered the score (flag value is null) to an unclickable state.

The implementation class method of the back-end Service interface will update the grade of the specified student:

public void update(Grade grade) {
    
    
    int sum = grade.getMath()+grade.getJava()+grade.getEnglish()+grade.getPe();
    grade.setGradenum(sum);
    gradeMapper.updateByPrimaryKey(grade);
//        根据学生学号查询出该学生所在班级
    Integer sid = grade.getId();
    Student student = studentMapper.selectByPrimaryKey(sid);
    Integer classid = student.getClassid();
    updateAvgClassGrade.updateAvgGrade(classid);
}

4.2.11 Realize the analysis of student performance and the average score of each subject in the class and generate a histogram

html file, add front-end components, this page only implements the function of analyzing students’ grades by specifying student numbers, because it can ensure that the student numbers are not repeated, if there is a phenomenon of duplicate names, it is impossible to query and analyze the performance histogram of students with the same name, that is Because the number of histograms is uncertain and the front-end page will be stretched due to querying the students with the same name through the name, so the student's grades can only be analyzed by querying the student number and the corresponding histogram is generated. Here, the icon library of Javascript is used. Echarts. After clicking the query button, if the student number entered in the input box is empty, no operation will be performed; if the input content is not empty, an axios request will be sent, and the request parameter is the student number entered. At this time, it should be noted that it still needs to Set the request header headers information, and unify the data encoding received by the backend with the frontend settings. After the student number is transmitted to the backend, the backend queries the information of a single student with the specified student number and grades and returns it to the frontend. If the data obtained by the frontend is empty, it means that the queried student number does not exist, and then assigns idIsNull to true , and give a prompt message that the student number does not exist, indicating that no further requests will be sent to obtain the average grade of each subject in the class of the student (because the student does not exist, the class must not exist); if the data obtained by the front end is not empty , then assign values ​​to the parameters of the front-end two-way binding to generate the column in the column chart, and then send axios request again to obtain the average grade of each subject in the class of the student (if the idIsNull value is false, it indicates that the student number exists), the input parameter is the class number of the student, after the backend gets the parameter, it creates and injects the entity class avgGradeMapper, calls the selectByPrimaryKey() method through the avgGradeMapper entity class to query the average grade of each subject of the specified class in the avg_grade table, and The query result is returned to the front-end, and the front-end assigns the two-way binding data to generate the polyline in the column chart. The code here has been improved and updated. The first generation version here is to query the list of all students with grades in this class through the student's class number, calculate the average of each subject in the class and the average of the total grade, and then return to the front end. After thinking about the current When creating new student information and entering student grades, when modifying a student's grade, or when deleting a student's information, the average value of each subject and the average grade of the class may change, and the code of the first version makes the avg_grade table useless at all Therefore, the author encapsulates the code for calculating the average value of each subject in the class and the average score of the total score into a method separately, and in the Serv that may affect the class score

The method code for calculating class grades encapsulated by the backend:

public void updateAvgGrade(int classId) {
    
    
    //更新该学生班级的各科平均成绩
    Integer mathSum = 0,javaSum = 0,englishSum = 0,peSum = 0,gradeNumSum = 0;
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    criteria.andClassidEqualTo(classId);
    List<Student> students = studentMapper.selectByExampleWithGrade(studentExample);
//        循环遍历这个班级的每个学生,算出各科平均分
    for(Student stu : students) {
    
    //因为存在没录入成绩的学生,所以不能直接累加
        if (stu.getGrade().getMath() != null) mathSum += stu.getGrade().getMath();
        if (stu.getGrade().getJava() != null) javaSum += stu.getGrade().getJava();
        if (stu.getGrade().getEnglish() != null) englishSum += stu.getGrade().getEnglish();
        if (stu.getGrade().getPe() != null) peSum += stu.getGrade().getPe();
        if (stu.getGrade().getGradenum() != null) gradeNumSum += stu.getGrade().getGradenum();
    }
    int studentSize = students.size();//班级的学生总数
    float math = (float)mathSum / studentSize;//班级的数学成绩平均分
    float java = (float)javaSum / studentSize;//班级的java成绩平均分
    float english = (float)englishSum / studentSize;//班级的英语成绩平均分
    float pe = (float)peSum / studentSize;//班级的体育成绩平均分
    float gradeNum = (float)gradeNumSum / studentSize;//班级的总成绩平均分
//        把班级平均数封装成对象
    avgGrade gradeAvgClass = new avgGrade(classId,math,java,english,pe,gradeNum);
    avgGradeMapper.updateByPrimaryKey(gradeAvgClass);
}

It should be noted that when the input student ID is not empty and the input student ID exists, the front end will send two axios requests in succession. It needs to be distinguished between continuous sending and simultaneous sending. The class number of the student to be queried must be obtained before sending The second axios request, because the second axios request takes the student's class number as a parameter. Other situations involving some input values ​​being empty and student IDs not existing have been discussed above and will not be repeated here.

The method code executed after the front end clicks the query button:

gradeAnalysis(){
    
    
    if (this.queryStr.queryId == undefined || this.queryStr.queryId == null || this.queryStr.queryId == '') return false;
    axios.post("stuAnalysis/searchById",this.queryStr.queryId,{
    
    //发送请求根据学生学号查询其成绩
        headers:{
    
    
            'Content-Type':'application/json'
        }
    }).then((response)=>{
    
    
        this.showOutPutBtn = true;
        if (response.data.flag){
    
    
            if (response.data.data == null){
    
    
                this.idIsNull = true;//该学号不存在,设置标志值以至于判断是否发送第二个请求
                this.$message.error('学号不存在');
                // 清空柱状图数据
                this.resetCharts();
                this.initCharts();//初始化图表
                return false;//终止请求
            }else{
    
    
                this.queryResult.stuId = response.data.data.id + "";
                this.queryResult.stuName = response.data.data.name + "";
                this.queryResult.stuClass = response.data.data.classid + "";
                this.queryResult.gradeMath = response.data.data.grade.math + "";
                this.queryResult.gradeJava = response.data.data.grade.java + "";
                this.queryResult.gradeEnglish = response.data.data.grade.english + "";
                this.queryResult.gradePE = response.data.data.grade.pe + "";
                this.queryResult.gradeNum = response.data.data.grade.gradenum + "";
                this.$message({
    
    
                    message: response.data.message,
                    type: 'success',
                })
            }
        }else{
    
    
            this.$message.error(response.data.message);
        }
    }).then(()=>{
    
    
        if (this.idIsNull == true){
    
    //如果学号为空
            this.idIsNull = false;//重新赋值,方便下次查询
        }else{
    
    
            // 发送axios请求查询该学生所在班级的各科平均分
            axios.post("stuAnalysis/avgByClassId",this.queryResult.stuClass,{
    
    
                headers:{
    
    
                    'Content-Type':'application/json'
                }
            }).then((response)=>{
    
    
                this.showOutPutBtn = !response.data.flag;
                this.queryResult.avgMath = response.data.data.avgMath + "";
                this.queryResult.avgJava = response.data.data.avgJava + "";
                this.queryResult.avgPE = response.data.data.avgPe + "";
                this.queryResult.avgEnglish = response.data.data.avgEnglish + "";
                this.queryResult.avgGradeNum = response.data.data.avgNumber + "";
            }).finally(()=>{
    
    
                this.initCharts();//初始化柱状图表
                this.initPieCharts();//初始化饼状图表
            })
        }
    })
},

In addition, the front-end code here uses Javascirpt's icon library Echarts. This technology is only briefly introduced in this report. This report also involves the basic usage of Echarts, so it will not be elaborated. The front end assigns the two-way bound data after getting the grades of each subject of the students and the average grade of the student's class, and finally executes the initialization of the histogram. In the body of the initCharts() method, first obtains the specified box div of the histogram and initializes the myChart data , and then specify the configuration items and data of the column chart, and then use the configuration items and data just specified to display them on the chart.

The code of the initCharts() method for initializing the bar chart at the front end:

initCharts(){
    
    
    this.myChart = echarts.init(document.getElementById('chartBox'));

    // 指定柱状图表的配置项和数据
    let option = {
    
    
        title: {
    
    
            text: this.queryResult.stuClass + '班的' + this.queryResult.stuName + '成绩分析柱状图',
        },
        tooltip: {
    
    },
        legend: {
    
    
            data: ['分数','班级平均分'],
        },
        xAxis: {
    
    
            data: ['数学', 'Java', '英语', '体育'],
        },
        yAxis: [
            {
    
    
                name: '分值',
                min: 0,
                max: 100,
            },
        ],
        series: [
            {
    
    
                name: '分数',
                type: 'bar',
                data: [
                    this.queryResult.gradeMath,
                    this.queryResult.gradeJava,
                    this.queryResult.gradeEnglish,
                    this.queryResult.gradePE,
                ],
                itemStyle: {
    
    
                    normal: {
    
    
                        color: '#4ad2ff',
                    }
                }
            },
            {
    
    
                name: '班级平均分',
                type: 'line',
                data: [
                    this.queryResult.avgMath,
                    this.queryResult.avgJava,
                    this.queryResult.avgEnglish,
                    this.queryResult.avgPE,
                ],
                itemStyle: {
    
    
                    normal: {
    
    
                        color: '#ffa500',
                    }
                }
            }
        ]
    };
    // 使用刚指定的配置项和数据显示图表
    this.myChart.setOption(option);
},

4.2.12 Beautify the front-end interface and use the interceptor to realize the login and registration function

In the early stage, the author mainly focused on the realization of the front-end and back-end business logic, and did not over-beautify the page elements, but only added the necessary components. Then the author made an update on the page beautification, and implemented the login and registration function through the interceptor. For the beautification of the front-end page, the author mainly uses the logo artifact website to generate the project logo, uses the colorspace web page to generate a more beautiful gradient color, and adds components to make the user name avatar in the upper right corner of the web page, and a drop-down menu pops up after clicking. Find the beautiful front-end code for login and registration, import and modify it, and replace it with the theme I like. From this, the front-end page of login and registration, the overall color tone of the webpage, and the beautiful interface are all preliminarily completed.

In the login.html file, click the login button to execute the login method and send an axios request. The parameter passed in is the user name entered by the user. In the implementation class method of the backend Service interface, the selectByPrimaryKey() method is called through loginUserMapper to find the key in the database. If the password corresponding to the user name is empty, it means that the user name or password does not exist. If the found password does not match the password entered by the user, it means that the user entered the wrong password. Otherwise, the password is correct to log in to the system. The .open('http://localhost:81/main.html','_self'); statement opens the main.html page in the current window.

The login method code executed by clicking the login button on the front end:

login(){
    
    
   let param = {
    
    
      username: this.user.userName,
      password: this.user.passWord,
   }
   axios.post("/login/checkPwd" , param).then((response)=>{
    
    
      if (response.data.flag){
    
    //登录成功
         this.$message({
    
    
            message: response.data.message,
            type: 'success'
         });
         location.reload();//刷新当前页面
      }else {
    
    //账号或密码错误
         this.$message.error( response.data.message );
      }
   })
},

So far, only a simple page jump has been realized after the login is successful. In fact, the login and registration page can be skipped directly. When the system is not logged in, directly enter the main.html URL to access the system, so that the login and registration function at this time is completely lost. Significance, so it is necessary to use interceptors to further improve the login and registration functions.

Interceptor function: When the user does not log in to the system and wants to skip the login registration page and directly access the system, even if the user enters the specific URL of main.html, the resource of main.html still cannot be accessed, and the system will automatically jump after clicking to access Go to the login registration page. Create an interceptor package and create a new LoginInterceptor.java file in the package. This interceptor entity class needs to implement the HandlerInterceptor interface and implement the interface method preHandle(). This method will be executed before the page that needs to be intercepted is accessed, and the session is obtained through the request inside the method body. Domain, if the value corresponding to "user" in the session domain is empty, it means that the user is not logged in. At this time, all pages except the login registration page and some static resources are intercepted; if the obtained "user" in the session domain "The corresponding value is not empty, indicating that the user has already logged in, and the session value of the user's login is stored in the system, and the page will not be intercepted at this time. At this time, after judging that the login is successful in the login Controller layer method, store the user in the form of a key-value pair in the session domain through the setAttribute() method, indicating that the user has logged in.

Backend interceptor method code:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
    HttpSession session = request.getSession();
    if (session.getAttribute("user") != null){
    
    
        //用户已登录不拦截
        return true;
    }else {
    
    
//            拦截后进入登录页面
        response.sendRedirect(request.getContextPath() + "/login.html");
        return false;
    }
}

In addition, you need to configure the interceptor in dispatcherServlet-servlet.xml (springmvc configuration file), specify the files that need to be intercepted and the files that do not need to be intercepted, and perform interceptor entity class mapping. Only the interceptor is configured in the configuration file After that, the interceptor can really work.

The configuration of the interceptor in the dispatcherServlet-servlet.xml file:

<mvc:interceptors>
    <mvc:interceptor>
<!--            拦截所有mvc控制器-->
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login.html"/>
        <mvc:exclude-mapping path="/static/**"/>
        <mvc:exclude-mapping path="/plugins/**"/>
        <mvc:exclude-mapping path="/login/**"/>
        <bean class="com.shenshang.manager.interceptor.LoginInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

4.2.13 Realize the pie chart function of analyzing the grades of students in the class

The author believes that a single histogram that includes the individual grades of the students and the average grades of each subject in the class cannot show the gradient of the overall grades of the students in the class. At the same time, I also want to be more proficient in the use of Echarts, so as to expand and realize the ability to display and query the class of the students The pie chart of the students' learning situation, the function of the pie chart: the average total score of the students in this class is divided into 5 grades of excellent, good, medium, pass, and fail according to the score standards of each stage, and the grades of each grade The distribution of the number of students in is displayed on the front page in the form of a pie chart. The business logic of the front-end is similar to the business logic of generating the histogram. I won’t go into details here. The front-end code still includes sending the axios request to get the background data, then assigning values, and initializing the pie chart to display on the page. The only thing that needs to be paid attention to on the front-end The point is that when the query button is clicked, the method of analyzing the pie chart and the histogram is executed at the same time, between the two simultaneous execution methods at the front-end query button @click="gradeAnalysis(),classAnalysis()" Join with commas. The parameter passed when sending the axios request in the classAnalysis() method is the input student ID. After obtaining the student number of the front-end student in the back-end Service interface implementation class method, first query the individual student information corresponding to the student number, obtain the class the student is in, and query all the students with grades in this class through the class number List, after defining and initializing the counters of each level, traverse the list of students, calculate the average score of each student's total grade, judge which grade range the student is in according to the average score of the total grade of the student, and add one to the counter of the corresponding grade range, Finally, the value of the obtained counter is instantiated through the constructor and returned to the front end. After the front end gets the data, it is assigned to the two-way bound data, which is displayed in the form of a pie chart.

Backend Service interface implementation class method code:

public GradeRank rankById(String id) {
    
    
    Integer excellent = 0, good = 0, middle = 0, passed = 0, unPass = 0;
    int sid = Integer.parseInt(id);
    Student student = studentMapper.selectByPrimaryKey(sid);
    if (student == null) return null;
    Integer classid = student.getClassid();
    StudentExample studentExample = new StudentExample();
    StudentExample.Criteria criteria = studentExample.createCriteria();
    criteria.andClassidEqualTo(classid);
    List<Student> students = studentMapper.selectByExampleWithGrade(studentExample);
    for (Student stu : students) {
    
    
        if (stu.getFlag() == null) continue;
        float avgGradeNum = (float)stu.getGrade().getGradenum() / 4;//学生总分平均分
        if (avgGradeNum >= 60 && avgGradeNum < 70) passed++;//及格人数自增1
        else if(avgGradeNum >= 70 && avgGradeNum < 80) middle++;//中等人数自增1
        else if(avgGradeNum >=80 && avgGradeNum < 90) good++;//良好人数自增1
        else if(avgGradeNum >= 90 && avgGradeNum <= 100) excellent++;//优秀人数自增1
        else unPass++;//不及格人数自增1
    }
    return new GradeRank(excellent , good , middle , passed , unPass);
}

4.2.14 Realize the function of exiting the system

Once the user clicks to exit the system, the data in the session domain of the website will be deleted, and the current page will be refreshed. Since the interceptor detects that there is no user login data in the current session domain, after refreshing the page, it will intercept the main.html page and enter the login On the registration page, users need to log in and register before they can access system resources. When the user clicks the exit system button, the front end executes the handleComment() method. This method is a built-in method of the drop-down box label in elementui. When this method is clicked, the command value in the clicked label is obtained, and the method body is judged when it is obtained. When the value of the command is equal to "b" (the command value corresponding to exiting the system is "b"), send an axios request, and use the session.removeAttribute() statement at the Controller layer of the exiting system to clear the user login information stored in the session domain . After clearing successfully, the body of the front-end method will use the window.open('http://localhost:81/login.html'); statement to jump to the login page, you can test and enter the URL of main.html, and find that the access system is internal resources, it will still automatically jump to login.html, and the interceptor will take effect.

Exit the controller layer method body code of the system:

@RequestMapping("/exitSystem")
public Result exitSystem(@RequestBody Integer id , HttpSession session){
    
    
    try{
    
    
        session.removeAttribute("user");
        return new Result( true , MessageConstant.EXIT_SYSTEM_SUCCESS );
    }catch (Exception e){
    
    
        e.printStackTrace();
        return new Result( false , MessageConstant.EXIT_SYSTEM_FAIL );
    }
}

4.2.15 Realize the export of student information with grades to an excel file

First, you need to import the related dependencies of EasyExcel into the pom.xml file. After clicking the export report button, the front end sends an axios request, and the incoming parameter is the set of query results. The parameter received by the Controller layer is the entity class OutPutExcel that has the same object attributes as the incoming data type of the front end. Each attribute in the entity class is preceded by Add the attribute @ExcelProperty, the value in this attribute corresponds to the header name in the generated Excel table, and the index value in the annotation is used to specify the order of appearance of the header names, with the smaller index first and the larger index later. In the Controller layer, call the interface entity class method through stuAnalysisService, specify the path to export the excel file in the Service interface entity class method, store the received parameter outPutExcel into the array, and then write the array into the excel file.

The code for implementing the class method of the backend Service interface:

public void pushExcel(OutPutExcel outPutExcel) {
    
    
//        指定导出excel文件的路径
    String fileName = filename;//此处的filename要换成指定的文件路径
//        存放对象的数组
    List<OutPutExcel> gradeCharts = new ArrayList<OutPutExcel>();
    gradeCharts.add(outPutExcel);
//        将数组写入到excel表格中去
    EasyExcel.write(fileName , OutPutExcel.class).sheet("个人成绩报表").doWrite(gradeCharts);
}

What you need to pay attention to in the front-end code here is that the button to export the report will be set to the clickable state only after the result is queried. If no information is queried, the button to export the report will not be clickable.

5. Experimental results and analysis

In the end, the project took shape. No bugs have been found in the student performance management system. The project has realized all the basic functions in the task guide. In addition, the author has expanded many functions as extra points for this project. But this project also has deficiencies, which will be analyzed together here.

Project function innovation and expansion points:

①The modal box form for adding student information uses various types of input boxes such as radio boxes, multi-select boxes, and date selectors. Compared with some forms that only use input boxes that can be entered, this type can Better constrain user input. For example, the use of the date picker, the input box of elementui's built-in date picker type will change the time that can be selected with the calendar, and the author handles it at the front end, so that the date greater than the current day cannot be selected. The date picker will change as the system date changes, reducing the complicated and complicated background verification code.

②The table on the student information query page contains an operation column, where the administrator can enter and view the student's grades, and the entry and view buttons are also set to be clickable and unclickable according to whether the student's grades have been entered, so as to avoid The administrator repeatedly enters the student information, and also prevents the administrator from displaying a blank prompt box when viewing the student's grades. The entry button is set up here, which is different from the traditional name input and entry of grades. It is mainly for administrators to check which students have not entered grades. After entering grades, they can directly view student grades on the student information page. error. So far, the student grade query page seems redundant (because the student grades can already be obtained through the student information query page), but on the grade query page, the grades of multiple students can be viewed together, and after entering the class as the query condition, you can also You can view the grades of multiple students in a class, and compare the grades of different students intuitively, and the student grade query page also has the function of modifying a student's grades. For students with incorrect grades, you can use this page to Directly modify the student's grades. It can be seen that the student's grades query page is not redundant, but the two pages affect each other and are related to each other.

③ After clicking the edit button on the student information query page and the student achievement query page, a similar modal box will pop up, and this modal box has been echoed with data, because if there is no data echo, it will lead to no The reference data of the original information is easy to cause modification errors.

④ Both the student information query page and the student performance query page use the class number as one of the query conditions. The purpose is to query all student information and all student grades of the specified class by entering the class number. This point is not required in the task guide. The author thinks that this can give users the option to narrow the query scope from the professional scope to the class scope, so this function has been expanded.

⑤On the student performance analysis page, the author processed the export report button. Only under the premise that there is returned data in the background, the export report button is clickable, which prevents the student from entering the student number from being unable to be queried. When the export button is clicked, there is no response, an error is reported when the click is clicked, and the value of a header column in the generated excel table is empty.

⑥On the student performance analysis page, after the backend queries the student information with the specified student number and grades, the front end obtains the student's class number, and passes the class number as the parameter of the second axios request, so that it can be used in the background again Calculate the average grade of each subject in the class and transmit it to the front end, and display it in the form of a line chart, and the line chart and the column chart are on one graph, which is convenient for the administrator to compare the average score of each subject between the students and their class , you can easily find out the subjects in which the students lowered the average grade of the class.

⑦On the student performance analysis page, after entering the student number and clicking the query button, the method of analyzing the histogram of student performance and the method of analyzing the pie chart of class performance will be executed at the same time. The reason why the pie chart is considered is that it is difficult to It reflects the overall level of the students in the class, and it is impossible to judge the gradient of the students in the class (that is, it is impossible to know whether there are more or less students who are good at learning, more or less students who are learning in the middle, and how many students are failing). The function of the pie chart can well reflect the gradient situation of the students in the class, and can be fed back to the administrator about the overall learning atmosphere of the class.

⑧Implemented the login and registration function. This function is not required in the task guide. The author believes that a good system must have the login and registration function. If users who have not logged in can enter the URL to access system resources, Then the system loses the minimum confidentiality and security. Logging in and registering is the first line of defense for system security.

⑨The function of exiting the system has been realized, which is not required in the task guide, but the implementation of exiting the system can facilitate users to log in again, or switch accounts to log in. If the function of exiting the system is not realized, the interceptor will take effect next time The only option is to clear the browser cache or restart the server, which is not good for the user experience, and the confidentiality of the user's account cannot be guaranteed.

Disadvantages of project functionality:

① On the student performance analysis page, after querying the student performance analysis histogram and class performance pie chart, you can click the export report button at this time. After clicking the button, a prompt message "successfully exported the student performance report" will be given, and the excel file The save path is already specified in the project. This is not very good for the user experience. It would be better if the user can specify the path to save the file.

② On the login registration page, when the registration button is clicked, the registration is simply to enter the user name and new password, and the user name and password that meet the verification rules will be inserted into the database table, and there is no input box for re-entering the new password, so It will lead to the problem that the user may press the wrong password when registering the account, resulting in the problem of not being able to log in when logging in. In fact, the logic of re-entering the password is very simple, as long as the background verification is completed and the front-end prompt information is given.

③The system does not implement the function of changing the password. The author thinks that this function is very similar to the logic of the edit button in the project. I think there is no need to write it again, so the function of changing the password has not been implemented. The user enters the registered email or mobile phone number, and when registering an account and changing the password, it will be sent to the user's mailbox or send a text message, which is more secure.

④ When building a database table, the login table s_login has only simple information such as user name and password, which is too little, making it impossible for the personal center to do so, because there are too few data about users that can be echoed (only account number and password ), and there is no need to echo the account number and password. In fact, when building the table, you can add some information that the administrator can choose to enter (such as avatar, gender, age, personalized signature, etc.), so that the personal center can be integrated After the function is made, you can also modify the avatar or something.

⑤Even though the author has tried to beautify the front-end page as much as possible, I feel that the front-end page is still not very beautiful. In addition, the version of elementui that may be introduced is too low, which makes some icons in the current version of the elementui component library unusable.

The above is the author's self-evaluation on the project of this course design after reviewing the entire project. The project has many innovations and some deficiencies, but all the basic functions in the task guide have been realized. Afterwards, if you have an idea, you will realize more expansion functions and innovation points, and then improve the deficiencies.

6. Summary and experience

In this course design, the author realized a simple front-end and back-end separation project-student performance management system through vue+ssm technology. Although this system is a relatively traditional old-fashioned project, the realization of the project is of great significance. In addition, it can train students' thinking about the addition, deletion, modification, and query of database data. It can also consolidate the knowledge of the ssm framework learned. A good understanding of the benefits of front-end and back-end separation. It can also make students realize that the front-end and back-end frameworks are much more convenient than directly writing javascript, jsp, jquery, servlet, etc., and feel the convenience of using the framework.

It can be seen that in the process of course design, the author has realized some expansion functions that are not mandatory in the task guide. Think about how to improve the update system from the user's point of view. And this system also has some imperfections, which is also a common thing in projects, and projects are constantly polished. The end of the course design does not mean the end of the project, and the system will always be updated when there are ideas in the future.

In addition, before the author was keen to consolidate the learning of new knowledge points by watching online class videos through demos, but often found that the results were minimal. In the process of following the teacher to do the project step by step, it may be clear about a certain knowledge point at that time. , but two weeks after the completion of the project, I may feel very unfamiliar with the project again, which shows that I have not mastered the knowledge points used in the project. And this course design is completely done by myself. I realized that only the codes that I typed out line by line can keep the knowledge points in my mind for a long time. Quickly forget, it may take a long time to write codes and start projects by yourself, but this process is a process of discovering and correcting problems, and it is also a process of rapid progress. When solving practical problems in the project, I tried my best to complete the demo, but I really couldn’t understand it. If you have no idea, you can check the source code to learn. If you still don’t understand the source code, you can use online courses to understand it.

In this course design, the author is indeed more proficient in the use of vue and ssm frameworks, and has a little understanding of the underlying logic of the framework implementation, but it is still not deep enough. The author believes that the study of the framework should be in-depth, and the ssm framework can be regarded as a After learning the template framework, after employment, the company may have its own technical framework. On the premise of being very proficient in the underlying logic of the ssm framework, it will be easier to migrate to learning the company framework.

The above is the summary and experience of this course design. I have a feeling when I write it. I should practice more in logistics thinking and pay more attention to the ability of hands-on practice. Keep in mind: what is done on paper is always superficial, and you must do it yourself if you know it.

Guess you like

Origin blog.csdn.net/qq_54162207/article/details/125219175