Design and implementation of an intelligent online examination system based on SpringBoot+Vue

Author's homepage: Programming Thousand Paper Cranes

About the author: Java, front-end, and Python have been developed for many years, and have worked as a senior engineer, project manager, and architect

Main content: Java project development, Python project development, university data and AI project development, MCU project design, interview technology arrangement, latest technology sharing

Favorites, likes, don't get lost, it's good to follow the author

Get the source code at the end of the article

Item number: BS-GX-064

Foreword:

With the rapid development of computer and network technology, Intranet applications are becoming more and more popular all over the world. Today's society is rapidly advancing towards an information society, and the role of information automation is also increasing. At present, there are various types of examinations at various levels, and their various tasks mainly rely on manual completion. For example, the registration of examinations requires candidates to go to the designated place to complete in order. Not only the procedures are complicated and troublesome, but also the work efficiency is very low. It will be affected by various factors such as weather and traffic. There are still many disadvantages in manual management. Due to inevitable human factors, data omissions and false positives are caused. Computer information management has many advantages such as large storage capacity and fast speed, and the processing information provided to us is timely and fast.

This system is based on the SpringBoot framework and is designed in B/S mode. The front-end page is developed with Vue.js and MySQL is used as the database. Use IDEA as a front-end and back-end development tool, and use mybatis to interact with the database as a database management tool.

Online exams can save the cost of printing test papers, reduce the burden on teachers for marking papers and score statistics, save educational resources, speed up the examination process, and give full play to the advantages of computers in information processing. Analysis of test questions and test results, etc., not only saves manpower, material resources and financial resources, but also improves labor efficiency. The online examination system far exceeds the limitations of the fixed time and fixed place examination mode of the traditional examination, and will bring great convenience to students and teachers. Online exams can save the cost of printing test papers, reduce the burden on teachers for marking papers and score statistics, save educational resources, speed up the examination process, and give full play to the advantages of computers in information processing. Analysis of test questions and test results, etc., not only saves manpower, material resources and financial resources, but also improves labor efficiency.

1. Environmental introduction

Locale: Java: jdk1.8

Database: Mysql: mysql5.7

Application server: Tomcat: tomcat8.5.31

Development tools: IDEA or eclipse

Development technology: Springboot+Vue

2. Project introduction

With the continuous development of computer technology and network technology, it is an inevitable trend in the future to use computers to assist teaching and improve the quality of education. Computers have penetrated into every aspect of daily work and life, and are our right-hand man for study and work. People in all walks of life use computers to do many, many complex tasks. Today, we use computers to research the intelligent online examination system and build a convenient platform for many college students and teachers. The examination system is an indispensable part of an educational unit, but people have always used traditional paper-based examinations and assessments. This examination and assessment method has many disadvantages, such as: low efficiency, poor confidentiality, and too long time, which will cause A large number of files and data have brought many difficulties to correcting, searching, updating and maintaining examination papers. The use of computers to test students has advantages that paper-based tests cannot achieve. The advantages of convenient search, high reliability, good confidentiality, long life and so on can greatly improve the efficiency of students' examinations. Of course, there are also some disadvantages in the use of computers in the examination system. In the process of researching the development and design of the examination system that separates teaching and examination, we also need to minimize the impact of the disadvantages.

The research content of this topic is to develop and design a separate examination system for teaching and examination in colleges and universities, so that teachers and students can conduct online examinations and study evaluations through the network.

This article aims to design and develop a set of intelligent online examination system based on Springboot. It analyzes the architecture of the intelligent online examination system in detail, establishes the relationship between each module, and discusses the question bank management, subject management, paper composition management, examination function, judgment and so on. The analysis, design, implementation, and testing of functional modules such as test paper function and score management complete a complete set of intelligent online examination system.

 The system designs two user roles: administrator (teacher) role and examinee (student) role. The administrator can enter the background management interface to manage users, test papers, tasks, subjects, grades, message center sending, log center management, etc. Students naturally enter the student interface to take corresponding exams , online answering, viewing wrong question sets and other operations. The functional block diagram of the system is shown in Figure 3-1.

Figure 3-1 System function module diagram

Candidates can use the test paper to answer questions, do exercises, view test papers, and review their test results after the test, that is, related test records. The system collects the student's wrong question set, and students can also correct wrong questions. View, the user function use case diagram is shown in Figure 3-2.

Figure 3-2 User function use case diagram

The administrator logs in through the system's built-in account, and the administrator account can perform user management, question management, task management, education management, performance management, message center sending, and log center viewing for the background. The use case diagram of the administrator function is shown in Figure 3-3.

Figure 3-3 Administrator function use case diagram

This system has 7 functional modules including user module, login and registration module, examination function module, storage module, message push module, search module and background management module. The main functions are analyzed as follows:

1. User module function

Table 3-1 User module function description

function name

Functional description

user registration

Users enter the test system to register first

view personal information

Users modify their own information, such as avatar modification, etc.

change Password

Modify the user's login password

view news

Display a list of messages from other users

2. Log in to the registration module

Table 3-2 Functional description of the login registration module

function name

Functional description

role login

The user logs in to the foreground interface, and the administrator logs in to the background

register

Users need to register and manage specific accounts

3. Exam function modules

Table 3-3 Functional Description of Examination Function Modules

function name

Functional description

release test paper

Admin publishes exam papers

Subject list

Publish test subject type, such as Math or English

Exam type

Common practice test papers and regular release test papers

candidate exam

Candidates receive a message to take the exam

Candidate practice

Candidates can practice the practice papers usually issued by the teacher

4. Storage module

Table 3-4 Storage module function description

function name

Functional description

online storage

Utilize Qiniu cloud online storage

5. Message push module

Table 3-5 Functional description of message push module

function name

Functional description

send message

The administrator publishes a message to the user to notify the exam information

message reception

Users can receive information notifications from administrators

6. Search module

Table 3-6 Functional description of the search module

function name

Functional description

keyword search

Use the title of the analysis post as the keyword to search for the corresponding content

7. Background management module

Table 3-7 Functional description of background management module

function name

Functional description

role management

Modify and manage student and administrator list information

Volume management

Publish the test paper

task management

You can modify the task list and create tasks

subject management

Modify and manage subject list information

performance management

Inquiry about candidates' grades

Question bank management

You can create questions, query topic categories, and publish topics

Message Center

Modify the message list to send messages

8. Recommendation module

Table 3-8 Functional description of background management module

function name

Functional description

User Management

User information management. Query, modify and disable users

Share post management

Find and modify, or delete shared posts in the platform

notification management

Used to publish new notifications, modify and delete existing notifications

Report management

View and process reported information submitted by users

3.2.2 Performance requirements

This system is based on B/S architecture, and users access to obtain services through browsers. In order to ensure user experience, relatively stable performance is required.

1. Data accuracy

When the back-end program performs data addition, deletion, and modification operations, it does not support operation failure due to program reasons;

When the back-end program is adding data, it does not support multiple or repeated additions;

When the back-end program deletes data, it does not support multiple deleted data;

When the back-end program deletes data, it requires the associated data to be completely deleted. If it cannot be deleted, please give a reminder;

When the back-end program performs data modification, it also needs to maintain the corresponding accuracy.

Time characteristics:

When performing operations such as adding and deleting, the database response time is required to be within 2 seconds;

Login registration response time <= 3 seconds;

Web page refresh response time <= 2 seconds;

Data rendering response time <= 0.5 seconds;

Data refresh response time <= 0.5 seconds;

Response time for querying shared posts <= 1 second;

Popular recommendation response time <= 1 second;

2. Security

The back-end server requires the establishment of a safe and reliable firewall;

Ensure the security of back-end server services and prohibit anonymous access to services;

For the password data of candidates (students) or administrators (teachers) in the database, MD5 encryption is required.

3. Support software

(1) Client software:

Operating system: Linux, Windows 7/10;

Browsers: Chrome, Fire Fox, Edge.

(2) Server software:

Operating system: Windows Server 2012/2016, Windows 7/10, Linux;

Java version: 1.8;

Database version: MySQL5.7 or above;

Functions and services: Qiniu cloud storage service.

Three, system display

5.1 User Module

5.1.1 Registration and login

前端登录与注册页面由login.vue实现,用户信息由userInfo.vue实现。用户首先需要输入用户名和邮箱,之后点击发送验证码,前端会将用户名和邮箱通过/api/sendCode提交到后端。后端接受到数据之后,首先会验证邮箱是否符合格式,邮箱是否已经被注册,如果条件成立,则返回相关提示信息。否则将生成验证码,通过邮件发送至用户邮箱,同时将邮箱和验证码存储于session中。之后用户需要将其他信息填写完毕,并且输入验证码,点击注册,前端会通过/api/register接口将数据提交到后端。后端收到数据后,首先会通过提交信息的邮箱从session中读取之前存储的验证码并进行对比,如果不一致,则返回验证码无效提示信息,否则继续业务。之后会验证邮箱是否符合规范,以及是否被注册,如果验证通过,则后端调用服务层类userService的register方法添加用户,register方法首先会将用户的密码进行MD5加密,填充注册时间,用户状态等信息,然后通过持久层类userMapper的方法将用户信息提交至数据库。提交成功之将创建用户的文件仓库,通过调用fileStoreService的 createFileStore方法创建对应用户的文件仓库并提交到数据库。界面实现效果如图5-1所示。

完成注册之后用户就可以登录了。输入用户名和密码之后点击登录,前端会将携带用户名与密码通过/api/login接口提交至后端,后端调用服务层类userService的login方法来处理数据。首先会将用户的明文密码使用MD5加密,之后通过持久层类userMapper的方法去数据库中查询是否存在对应用户名的用户,然后对比密码是否正确,并返回相应结果至控制层。如果账户密码正确,则将查询到的用户数据存储于session中,并且生成token提交至数据库中。之后将提示信息与token返回至前端,前端会将token存储于cookie中,以保持登录状态。界面实现效果如图5-2所示。

用户完成登录之后,将跳转至网盘界面,同时通过/api/getTokenVerity接口验证token是否有效,然后通过/api/getLoggedUser接口向后端的session中获取当前登录用户信息,并存储于cookie中。

图5-1 注册界面

图5-2 登录界面

5.1.2 个人信息

用户信息页面由userinfo.vue实现。登入系统之后,用户可以通过右上角下拉菜单进入用户信息页面。前端会携带登录用户信息,通过/api/u/getUser接口向后端请求当前用户信息,前端返回信息之后会将用户信息渲染至页面上。界面实现效果如图5-3所示。

图5-3 个人信息界面

5.1.3 查看消息

修改密码需要输入原密码和新密码,点击确定之后前端会通过/api/u/ resetPass接口向后端发送请求,携带用户ID和新旧密码。后端收到请求之后会调用服务层类userService的resetPass方法来处理业务。首先会判断原密码是否正确,然后检查新旧密码是否一致,如果一致则返回提示信息,否则将新密码使用MD5加密之后提交至数据库,然后向前端返回成功更改提示信息。界面实现效果如图5-4所示。

图5-4 查看信息界面

5.2 登录模块

5.2.1 角色登录

网盘界面由files.vue实现。用户登入之后会跳转至网盘界面,用户可在此查看网盘内的文件并进行管理。点击文件夹即可查看对应文件夹,前端会向/api/f/getDir接口发出请求,携带文件仓库与目标文件夹参数,后端获取对应文件夹下目录的数据返回至前端,前端根据后端的数据重新渲染目录,并记录用户当前路径信息。点击上一级或根目录按钮,前端会读取存储的路径信息,通过/api/f/getDir接口向后端请求对应目录的数据并再次渲染,以返回上一级目录。界面实现效果如图5-7所示。

图5-5用户登录前台界面

图5-6 管理员登录后台界面

5.3 考试功能模块

5.3.1 发布试卷

回收站模块同样由files.vue实现用户在网盘界面删除的文件并非被真的删除了,而是移动到了回收站,这里展示的是用户文件仓库中,所有被标记为删除的文件与文件夹。选择一个或多个文件及文件夹之后,即可执行还原操作。

点击还原文件按钮后会显示路径选择窗口,选择文件夹存放的目录然后点击确定后前端调用/api/rf/recovery接口发送请求,将被还原的文件及文件夹信息传递至后端,后端调用服务层类recycleBinService的recycleOrRecovery方法处理业务。根据请求携带的文件及文件夹信息分别处理,首先与还原文件及文件夹数据的名称进行对比,若存在重名则返回提示信息,否则将对应文件对象重新设置为未回收状态并设置文件的新路径。而文件夹则会通过recycleFoldersFile方法并设置为还原模式进行进一步操作,以还原文件夹下所有的子文件夹以及文件。界面实现效果如图5-11所示。

图5-7发布试卷页面

5.3.2 学科列表

选择选择一个或多个文件及文件夹之后,即可删除选择的文件或文件夹,而清空操作则是直接删除对回收站下的所有文件。在回收站执行的删除的操作会删除FTP上的文件,彻底从系统中移除本文件。删除文件和清空回收站都调用/api/f/delete接口,如果执行删除操作,前端会将选择的文件及文件夹信息通过此接口发送的后端,如果是清空操作,前端则会将回收站所有的文件信息传递至后端。后端接受到请求与文件信息之后对文件及文件夹进行分别处理,文件夹通过调用服务层folderService类删除数据库信息。文件则调用服务层fileService类deleteFTPFIle方法进行处理。因为FTP上的一个物理文件很可能在逻辑上关联了多条数据库信息,如果贸然删除FTP上的物理文件可能导致其他保存了次文件的用户将无法下载该文件,所以deleteFTPFIle方法在删除文件之前首先会检查该文件是否有多个关联数据库条目。进入deleteFTPFIle方法后,首先通过文件ID获取文件对象,之后通过文件对象的FTP地址从数据库中查询文件,再通过文件ID从数据库中查找分享帖,如果查到到相同FTP路径的文件大于1,以及查找到存在分享此文件的分享帖,则仅从数据库中删除数据库信息,否则调用FtpUtil类删除FTP文件。

图5-7学科列表页面

5.3.3 考试种类

选择选择一个或多个文件及文件夹之后,即可删除选择的文件或文件夹,而清空操作则是直接删除对回收站下的所有文件。在回收站执行的删除的操作会删除FTP上的文件,彻底从系统中移除本文件。删除文件和清空回收站都调用/api/f/delete接口,如果执行删除操作,前端会将选择的文件及文件夹信息通过此接口发送的后端,如果是清空操作,前端则会将回收站所有的文件信息传递至后端。后端接受到请求与文件信息之后对文件及文件夹进行分别处理,文件夹通过调用服务层folderService类删除数据库信息。文件则调用服务层fileService类deleteFTPFIle方法进行处理。因为FTP上的一个物理文件很可能在逻辑上关联了多条数据库信息,如果贸然删除FTP上的物理文件可能导致其他保存了次文件的用户将无法下载该文件,所以deleteFTPFIle方法在删除文件之前首先会检查该文件是否有多个关联数据库条目。进入deleteFTPFIle方法后,首先通过文件ID获取文件对象,之后通过文件对象的FTP地址从数据库中查询文件,再通过文件ID从数据库中查找分享帖,如果查到到相同FTP路径的文件大于1,以及查找到存在分享此文件的分享帖,则仅从数据库中删除数据库信息,否则调用FtpUtil类删除FTP文件。

图5-8练习试卷页面

图5-9时段页面

5.7 后台管理模块

后台管理模块为系统管理员提供了对系统中数据进行查询与管理的平台。后台管理页面仅对管理员用户开放,管理用用户即用户等级为9的用户。用户查看此页面以及子页面时,前端会通过/api/a/verityUserLevel接口携带当前用户ID向后端验证用户是否为管理员,然后才允许继续操作。否则跳转回登录页面。

5.7.1 角色管理

用户管理由userManage.vue实现。此页面用于对系统中的用户账户进行查询与管理。当管理员进入用户管理页面,前端首先会通过/api/a/getAll接口向后端发送请求,以获取所有的用户账户数据并返回至前端,前端收到数据之后分页渲染。界面实现效果如图5-20所示。

管理员可以通过页面操作按钮来查看用户信息,也可以通过搜索栏来查找指定用户的信息。在搜索栏中输入用户名,点击查找,前端便会通过/api/a/getUserByKeyWord接口将关键词传递至后端,后端接受请求之之后将查找到的数据返回至前端,前端再将数据渲染到页面上。

当管理点击新增按钮就会显示添加用户窗口,管理员填写完相关数据之后,点击确认,前端就会将该数据通过/api/a/addUser接口提交到数据库中。点击编辑按钮会打开与添加用户窗口一致的编辑用户窗口,前端会自动将被编辑用户的数据填入输入框,管理员只需更改需要更改的数据即可,点击提交前端会通过/api/a/updateUser接口将数据更新至数据库中。以上操作完成后,后端会返回成功信息至前端,前端再次获取更新后的用户数据并渲染用户信息列表。界面实现效果如图5-21所示。

当管理员点击某个用户账户信息上的禁用按钮时,前端会弹出提示框,询问管理员是否进行操作,点击确定,前端便会通过/api/a/UpdateStatus/接口禁用此账户。禁用后,该用户就无法使用此账户来登录系统。

图5-20 角色管理界面

5.7.2 组卷管理

分享管理由postsManage.vue实现分享管理页面用于管理系统中的分享帖。当管理员进入本页面,前端首先会通过/api/a/getAllPosts接口获取所有分享帖的数据,然后渲染到页面上。

此页面也提供了按照用户昵称来检索其对应分享帖的功能,在搜索栏输入用户昵称然后点击搜索,前端就会/api/a/searchPosts接口携带搜索内容传递至后端,后端接收请求后查找数据库中的对应内容,并返回至前端。前端收到数据之后渲染到页面上。界面实现效果如图5-22所示。

Shared posts are displayed on the page in the form of a list, and the administrator can click on the title of the post to enter the corresponding shared post. Or click the edit and delete buttons to operate on the post. When the edit button is clicked, the post editing window will be displayed, and the front end will automatically fill in the corresponding data of the post in the input box. After the administrator finishes editing, click the OK button and the front end will pass the post data to the back end through the /api/a/edit interface. The back end accepts the data and submits it to the database, and then returns a success message to the front end, and the front end requests a new one again. Post information and render to the page. The interface implementation effect is shown in Figure 5-23.

Click the delete button, and the front end will send a request to the backend with the post ID through the /api/a/deletePosts interface. After receiving the request, the backend will obtain the specific post object through the post ID, and then set the deleted attribute of the post object is true. Then through the addNotice method of the service layer method class noticeServer, send a notification that the post is deleted to the post of the deleted post. Then store the modified post object in the database and return a success message to the front end. After the front end receives the success message, it gets all the post information again to update the current page.

Figure 5-22 Volume management page

Figure 5-23 Post edit window

Fourth, the core code display

package com.zlf.exam.controller.student;

import com.zlf.exam.base.BaseApiController;
import com.zlf.exam.base.RestResponse;
import com.zlf.exam.domain.TaskExam;
import com.zlf.exam.domain.TaskExamCustomerAnswer;
import com.zlf.exam.domain.TextContent;
import com.zlf.exam.domain.User;
import com.zlf.exam.domain.enums.ExamPaperTypeEnum;
import com.zlf.exam.domain.task.TaskItemAnswerObject;
import com.zlf.exam.domain.task.TaskItemObject;
import com.zlf.exam.service.*;
import com.zlf.exam.utility.DateTimeUtil;
import com.zlf.exam.utility.JsonUtil;
import com.zlf.exam.viewmodel.student.dashboard.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController("StudentDashboardController")
@RequestMapping(value = "/api/student/dashboard")
public class DashboardController extends BaseApiController {

    private final UserService userService;
    private final ExamPaperService examPaperService;
    private final QuestionService questionService;
    private final TaskExamService taskExamService;
    private final TaskExamCustomerAnswerService taskExamCustomerAnswerService;
    private final TextContentService textContentService;

    @Autowired
    public DashboardController(UserService userService, ExamPaperService examPaperService, QuestionService questionService, TaskExamService taskExamService, TaskExamCustomerAnswerService taskExamCustomerAnswerService, TextContentService textContentService) {
        this.userService = userService;
        this.examPaperService = examPaperService;
        this.questionService = questionService;
        this.taskExamService = taskExamService;
        this.taskExamCustomerAnswerService = taskExamCustomerAnswerService;
        this.textContentService = textContentService;
    }

    @RequestMapping(value = "/index", method = RequestMethod.POST)
    public RestResponse<IndexVM> index() {
        IndexVM indexVM = new IndexVM();
        User user = getCurrentUser();

        PaperFilter fixedPaperFilter = new PaperFilter();
        fixedPaperFilter.setGradeLevel(user.getUserLevel());
        fixedPaperFilter.setExamPaperType(ExamPaperTypeEnum.Fixed.getCode());
        indexVM.setFixedPaper(examPaperService.indexPaper(fixedPaperFilter));

        PaperFilter timeLimitPaperFilter = new PaperFilter();
        timeLimitPaperFilter.setDateTime(new Date());
        timeLimitPaperFilter.setGradeLevel(user.getUserLevel());
        timeLimitPaperFilter.setExamPaperType(ExamPaperTypeEnum.TimeLimit.getCode());

        List<PaperInfo> limitPaper = examPaperService.indexPaper(timeLimitPaperFilter);
        List<PaperInfoVM> paperInfoVMS = limitPaper.stream().map(d -> {
            PaperInfoVM vm = modelMapper.map(d, PaperInfoVM.class);
            vm.setStartTime(DateTimeUtil.dateFormat(d.getLimitStartTime()));
            vm.setEndTime(DateTimeUtil.dateFormat(d.getLimitEndTime()));
            return vm;
        }).collect(Collectors.toList());
        indexVM.setTimeLimitPaper(paperInfoVMS);
        return RestResponse.ok(indexVM);
    }


    @RequestMapping(value = "/task", method = RequestMethod.POST)
    public RestResponse<List<TaskItemVm>> task() {
        User user = getCurrentUser();
        List<TaskExam> taskExams = taskExamService.getByGradeLevel(user.getUserLevel());
        if (taskExams.size() == 0) {
            return RestResponse.ok(new ArrayList<>());
        }
        List<Integer> tIds = taskExams.stream().map(taskExam -> taskExam.getId()).collect(Collectors.toList());
        List<TaskExamCustomerAnswer> taskExamCustomerAnswers = taskExamCustomerAnswerService.selectByTUid(tIds, user.getId());
        List<TaskItemVm> vm = taskExams.stream().map(t -> {
            TaskItemVm itemVm = new TaskItemVm();
            itemVm.setId(t.getId());
            itemVm.setTitle(t.getTitle());
            TaskExamCustomerAnswer taskExamCustomerAnswer = taskExamCustomerAnswers.stream()
                    .filter(tc -> tc.getTaskExamId().equals(t.getId())).findFirst().orElse(null);
            List<TaskItemPaperVm> paperItemVMS = getTaskItemPaperVm(t.getFrameTextContentId(), taskExamCustomerAnswer);
            itemVm.setPaperItems(paperItemVMS);
            return itemVm;
        }).collect(Collectors.toList());
        return RestResponse.ok(vm);
    }


    private List<TaskItemPaperVm> getTaskItemPaperVm(Integer tFrameId, TaskExamCustomerAnswer taskExamCustomerAnswers) {
        TextContent textContent = textContentService.selectById(tFrameId);
        List<TaskItemObject> paperItems = JsonUtil.toJsonListObject(textContent.getContent(), TaskItemObject.class);

        List<TaskItemAnswerObject> answerPaperItems = null;
        if (null != taskExamCustomerAnswers) {
            TextContent answerTextContent = textContentService.selectById(taskExamCustomerAnswers.getTextContentId());
            answerPaperItems = JsonUtil.toJsonListObject(answerTextContent.getContent(), TaskItemAnswerObject.class);
        }


        List<TaskItemAnswerObject> finalAnswerPaperItems = answerPaperItems;
        return paperItems.stream().map(p -> {
                    TaskItemPaperVm ivm = new TaskItemPaperVm();
                    ivm.setExamPaperId(p.getExamPaperId());
                    ivm.setExamPaperName(p.getExamPaperName());
                    if (null != finalAnswerPaperItems) {
                        finalAnswerPaperItems.stream()
                                .filter(a -> a.getExamPaperId().equals(p.getExamPaperId()))
                                .findFirst()
                                .ifPresent(a -> {
                                    ivm.setExamPaperAnswerId(a.getExamPaperAnswerId());
                                    ivm.setStatus(a.getStatus());
                                });
                    }
                    return ivm;
                }
        ).collect(Collectors.toList());
    }
}
package com.zlf.exam.controller.student;

import com.github.pagehelper.PageInfo;
import com.zlf.exam.base.BaseApiController;
import com.zlf.exam.base.RestResponse;
import com.zlf.exam.domain.Message;
import com.zlf.exam.domain.MessageUser;
import com.zlf.exam.domain.User;
import com.zlf.exam.domain.UserEventLog;
import com.zlf.exam.domain.enums.RoleEnum;
import com.zlf.exam.domain.enums.UserStatusEnum;
import com.zlf.exam.event.UserEvent;
import com.zlf.exam.service.AuthenticationService;
import com.zlf.exam.service.MessageService;
import com.zlf.exam.service.UserEventLogService;
import com.zlf.exam.service.UserService;
import com.zlf.exam.utility.DateTimeUtil;
import com.zlf.exam.utility.PageInfoHelper;
import com.zlf.exam.viewmodel.student.user.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController("StudentUserController")
@RequestMapping(value = "/api/student/user")
public class UserController extends BaseApiController {

    private final UserService userService;
    private final UserEventLogService userEventLogService;
    private final MessageService messageService;
    private final AuthenticationService authenticationService;
    private final ApplicationEventPublisher eventPublisher;

    //后台登录代码
    @Autowired
    public UserController(UserService userService, UserEventLogService userEventLogService, MessageService messageService, AuthenticationService authenticationService, ApplicationEventPublisher eventPublisher) {
        this.userService = userService;
        this.userEventLogService = userEventLogService;
        this.messageService = messageService;
        this.authenticationService = authenticationService;
        this.eventPublisher = eventPublisher;
    }

    @RequestMapping(value = "/current", method = RequestMethod.POST)
    public RestResponse<UserResponseVM> current() {
        User user = getCurrentUser();
        UserResponseVM userVm = UserResponseVM.from(user);
        return RestResponse.ok(userVm);
    }


    //后台注册代码
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public RestResponse register(@RequestBody @Valid UserRegisterVM model) {
        User existUser = userService.getUserByUserName(model.getUserName());
        if (null != existUser) {
            return new RestResponse<>(2, "用户已存在");
        }
        User user = modelMapper.map(model, User.class);
        String encodePwd = authenticationService.pwdEncode(model.getPassword());
        user.setUserUuid(UUID.randomUUID().toString());
        user.setPassword(encodePwd);
        user.setRole(RoleEnum.STUDENT.getCode());
        user.setStatus(UserStatusEnum.Enable.getCode());
        user.setLastActiveTime(new Date());
        user.setCreateTime(new Date());
        user.setDeleted(false);
        userService.insertByFilter(user);
        UserEventLog userEventLog = new UserEventLog(user.getId(), user.getUserName(), user.getRealName(), new Date());
        userEventLog.setContent("欢迎 " + user.getUserName() + " 注册来到在线考试系统");
        eventPublisher.publishEvent(new UserEvent(userEventLog));
        return RestResponse.ok();
    }


    //后台个人信息更新代码
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public RestResponse update(@RequestBody @Valid UserUpdateVM model) {
        if (StringUtils.isBlank(model.getBirthDay())) {
            model.setBirthDay(null);
        }
        User user = userService.selectById(getCurrentUser().getId());
        modelMapper.map(model, user);
        user.setModifyTime(new Date());
        userService.updateByIdFilter(user);
        UserEventLog userEventLog = new UserEventLog(user.getId(), user.getUserName(), user.getRealName(), new Date());
        userEventLog.setContent(user.getUserName() + " 更新了个人资料");
        eventPublisher.publishEvent(new UserEvent(userEventLog));
        return RestResponse.ok();
    }

    @RequestMapping(value = "/log", method = RequestMethod.POST)
    public RestResponse<List<UserEventLogVM>> log() {
        User user = getCurrentUser();
        List<UserEventLog> userEventLogs = userEventLogService.getUserEventLogByUserId(user.getId());
        List<UserEventLogVM> userEventLogVMS = userEventLogs.stream().map(d -> {
            UserEventLogVM vm = modelMapper.map(d, UserEventLogVM.class);
            vm.setCreateTime(DateTimeUtil.dateFormat(d.getCreateTime()));
            return vm;
        }).collect(Collectors.toList());
        return RestResponse.ok(userEventLogVMS);
    }

    @RequestMapping(value = "/message/page", method = RequestMethod.POST)
    public RestResponse<PageInfo<MessageResponseVM>> messagePageList(@RequestBody MessageRequestVM messageRequestVM) {
        messageRequestVM.setReceiveUserId(getCurrentUser().getId());
        PageInfo<MessageUser> messageUserPageInfo = messageService.studentPage(messageRequestVM);
        List<Integer> ids = messageUserPageInfo.getList().stream().map(d -> d.getMessageId()).collect(Collectors.toList());
        List<Message> messages = ids.size() != 0 ? messageService.selectMessageByIds(ids) : null;
        PageInfo<MessageResponseVM> page = PageInfoHelper.copyMap(messageUserPageInfo, e -> {
            MessageResponseVM vm = modelMapper.map(e, MessageResponseVM.class);
            messages.stream().filter(d -> e.getMessageId().equals(d.getId())).findFirst().ifPresent(message -> {
                vm.setTitle(message.getTitle());
                vm.setContent(message.getContent());
                vm.setSendUserName(message.getSendUserName());
            });
            vm.setCreateTime(DateTimeUtil.dateFormat(e.getCreateTime()));
            return vm;
        });
        return RestResponse.ok(page);
    }

    @RequestMapping(value = "/message/unreadCount", method = RequestMethod.POST)
    public RestResponse unReadCount() {
        Integer count = messageService.unReadCount(getCurrentUser().getId());
        return RestResponse.ok(count);
    }

    @RequestMapping(value = "/message/read/{id}", method = RequestMethod.POST)
    public RestResponse read(@PathVariable Integer id) {
        messageService.read(id);
        return RestResponse.ok();
    }

}

V. Project Summary

Guess you like

Origin blog.csdn.net/BS009/article/details/132079081