项目介绍 :

Spring Boot + SpringMVC + MyBatis Plus+ Mysql + druid + Vue 开发的前后端分离的在线考试系统

项目演示:
https://www.bilibili.com/video/BV1n1421Q7kf/?vd_source=11ac782881cbade0d1444685d3b0d4df

环境需要:
  1. 运行环境: 最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。
  2. IDE环境:Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以
  3. 数据库:MySql 5.7
  4. Maven:3.3以上
技术栈
前端

Vue、Axios、Element UI、Vue-Router、Vuex、ECharts

后端

Spring Boot、JWT、MyBatis-Plus、MySQL

功能结构
管理员角色:
  1. 首页
  2. 考试管理
  3. 题库管理
  4. 成绩查询
  5. 学生管理
  6. 教师管理
教师角色
  1. 首页
  2. 考试管理
  3. 题库管理
  4. 成绩查询
  5. 学生管理
学生角色
  1. 在线考试
  2. 试卷练习
  3. 留言
  4. 分数查看
项目预览
登录页

在这里插入图片描述

系统展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部分代码
package com.rabbiter.oes.controller;

import com.rabbiter.oes.entity.Admin;
import com.rabbiter.oes.entity.ApiResult;
import com.rabbiter.oes.serviceimpl.AdminServiceImpl;
import com.rabbiter.oes.util.ApiResultHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class AdminController {

    private AdminServiceImpl adminService;
    @Autowired
    public AdminController(AdminServiceImpl adminService){
        this.adminService = adminService;
    }

    @GetMapping("/admins")
    public ApiResult findAll(){
        System.out.println("查询全部");
        return ApiResultHandler.success(adminService.findAll());
    }

    @GetMapping("/admin/{adminId}")
    public ApiResult findById(@PathVariable("adminId") Integer adminId){
        System.out.println("根据ID查找");
        return ApiResultHandler.success(adminService.findById(adminId));
    }

    @DeleteMapping("/admin/{adminId}")
    public ApiResult deleteById(@PathVariable("adminId") Integer adminId){
        adminService.deleteById(adminId);
        return ApiResultHandler.success();
    }

    @PutMapping("/admin/{adminId}")
    public ApiResult update(@PathVariable("adminId") Integer adminId, Admin admin){
        return ApiResultHandler.success(adminService.update(admin));
    }

    @PostMapping("/admin")
    public ApiResult add(Admin admin){
        return ApiResultHandler.success(adminService.add(admin));
    }

    @GetMapping("/admin/resetPsw/{adminId}/{oldPsw}/{newPsw}")
    public ApiResult resetPsw(@PathVariable("adminId") Integer adminId, @PathVariable("newPsw") String newPsw, @PathVariable("oldPsw") String oldPsw) {
        return ApiResultHandler.success(adminService.resetPsw(adminId, newPsw, oldPsw));
    }
}

<!-- 用户登录界面 -->
<template>
    <div id="login">
        <div class="bg"></div>
        <el-row class="main-container">
            <el-col :lg="8" :xs="16" :md="10" :span="10">
                <div class="top" style="color: black">
                    <span class="el-icon-a-061 title"> 在线考试系统</span>
                </div>
                <br />
                <div class="bottom">
                    <div class="container">
                        <p class="title">账号登录</p>
                        <el-form :label-position="labelPosition" label-width="80px" :model="formLabelAlign">
                            <el-form-item label="用户名">
                                <el-input v-model.number="formLabelAlign.username" placeholder="请输入用户名"></el-input>
                            </el-form-item>
                            <el-form-item label="密码">
                                <el-input v-model="formLabelAlign.password" placeholder="请输入密码" type="password"></el-input>
                            </el-form-item>
                            <div class="submit">
                                <el-button type="primary" class="row-login" @click="login()">登录</el-button>
                            </div>
                            <!-- <div class="options">
                <p class="find"><a href="javascript:;">找回密码</a></p>
                <div class="register">
                  <span>没有账号?</span>
                  <span><a href="javascript:;">去注册</a></span>
                </div>
              </div> -->

                        </el-form>
                    </div>
                </div>
            </el-col>
        </el-row>
        <el-row class="footer">
            <el-col>
                <!-- <p class="msg2" style="color: black;">Copyright© 忧伤大白兔</p> -->
            </el-col>
        </el-row>
    </div>
</template>

<script>
import { mapState } from "vuex";
export default {
    name: "login",
    data () {
        return {
            role: 2,
            labelPosition: "left",
            formLabelAlign: {
                username: "",
                password: "",
            },
        };
    },
    methods: {
        //用户登录请求后台处理
        login () {
            if (
                this.formLabelAlign.username == undefined ||
                this.formLabelAlign.username == ""
            ) {
                this.$message("请输入用户名");
                return;
            }
            if (
                !/^\d+$/.test(this.formLabelAlign.username) ||
                this.formLabelAlign.username.toString().length > 10
            ) {
                this.$message("用户名有误");
                return;
            }
            if (this.formLabelAlign.password == "") {
                this.$message("请输入密码");
                return;
            }
            this.$axios({
                url: `/api/login`,
                method: "post",
                data: {
                    ...this.formLabelAlign,
                },
            }).then((res) => {
                let resData = res.data.data;
                if (resData != null) {
                    switch (resData.role) {
                        case "0": //管理员
                            this.$cookies.set("cname", resData.adminName);
                            this.$cookies.set("cid", resData.adminId);
                            this.$cookies.set("role", 0);
                            this.$router.push({ path: "/index" }); //跳转到首页
                            break;
                        case "1": //教师
                            this.$cookies.set("cname", resData.teacherName);
                            this.$cookies.set("cid", resData.teacherId);
                            this.$cookies.set("role", 1);
                            this.$router.push({ path: "/index" }); //跳转到教师用户
                            break;
                        case "2": //学生
                            this.$cookies.set("cname", resData.studentName);
                            this.$cookies.set("cid", resData.studentId);
                            this.$router.push({ path: "/student" });
                            break;
                    }
                }
                if (resData == null) {
                    //错误提示
                    this.$message({
                        showClose: true,
                        type: "error",
                        message: "用户名或者密码错误",
                    });
                }
            });
        },
        clickTag (key) {
            this.role = key;
        },
    },
    computed: mapState(["userInfo"]),
    mounted () { },
};
</script>

<style lang="less" scoped>
.remind {
    border-radius: 4px;
    padding: 10px 20px;
    display: flex;
    position: fixed;
    right: 20px;
    bottom: 50%;
    flex-direction: column;
    color: #606266;
    background-color: #fff;
    border-left: 4px solid #409eff;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.container {
    margin-bottom: 32px;
}
.container .el-radio-group {
    margin: 30px 0px;
}
a:link {
    color: #ff962a;
    text-decoration: none;
}
#login {
    font-size: 14px;
    color: #000;
    background-color: #fff;
}
#login .bg {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    overflow-y: auto;
    height: 100%;
    background: url("../../assets/img/loginbg.png") center top / cover no-repeat;
    background-color: #b6bccdd1 !important;
}
#login .main-container {
    display: flex;
    justify-content: center;
    align-items: center;
}
#login .main-container .top {
    margin-top: 100px;
    font-size: 30px;
    color: #ff962a;
    display: flex;
    justify-content: center;
}
#login .top .icon-kaoshi {
    font-size: 80px;
}
#login .top .title {
    margin-top: 20px;
}
#login .bottom {
    display: flex;
    justify-content: center;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#login .bottom .title {
    text-align: center;
    font-size: 30px;
}
.bottom .container .title {
    margin: 30px 0px;
}
.bottom .submit .row-login {
    width: 100%;
    background-color: #04468b;
    border-color: #04468b;
    margin: 20px 0px 10px 0px;
    padding: 15px 20px;
}
.bottom .submit {
    display: flex;
    justify-content: center;
}
.footer {
    margin-top: 50px;
    text-align: center;
}
.footer .msg1 {
    font-size: 18px;
    color: #fff;
    margin-bottom: 15px;
}
.footer .msg2 {
    font-size: 14px;
    color: #e3e3e3;
    margin-top: 70px;
}
.bottom .options {
    margin-bottom: 40px;
    color: #ff962a;
    display: flex;
    justify-content: space-between;
}
.bottom .options > a {
    color: #ff962a;
}
.bottom .options .register span:nth-child(1) {
    color: #8c8c8c;
}
</style>


创作不易,源码非无偿提供,需要获取源码的私信博主

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐