【毕设】基于springboot+vue的在线考试报名系统


【毕设】基于springboot+vue的在线考试报名系统-026详细介绍,文章后半部分有 系统截图视频演示

一、选题意义

随着社会的进步和商品经济的不断发展,社会对劳动者和技术人员的知识和能力水平的要求越来越高。考试作为衡量人的能力的重要手段,在现代生活的地位进一步提高,并深入到社会各个方面,各种各样的学历考试、资格证书考试层出不穷。同时,Internet技术的发展是得考试的技术手段和载体发生了革命性的变化。Internet 的开放性和分布性的特点以及基于Internet 的巨大计算能力使得考试突破了时间和空间的限制。网络应用不断扩大,如远程教育和虚拟大学的出现等;使得基于Web的在线考试系统成为现实。基于Web的在线考试系统可以发挥网络的优势,建立大型、高效、共享的题库和实现随时随地的考试,降低考试成本,减少人为的干扰。减轻教师的负担,节约人力,物力,和财力。

二、系统概述

本系统采用前后端分离的开发模式,前端使用Vue.js框架进行开发,后端使用Spring Boot框架,数据库采用MySQL。
代码注释详细(示例):

<template>
	<div class="page_root" id="root_index">
		<div class="warp">
			<div class="container-fluid">
				<el-row>
					<el-col :span="4">
						<mm_label bg_color="bg_purple" icon="el-icon-user-solid" :url="url_user_count" unit="人"
								  title="用户数量"></mm_label>
					</el-col>
				</el-row>

				<el-row>
					<el-col v-if="user_group == '管理员' || $check_figure('/examination_results/table')" :span="8">
						<div class="card chart">
							<pieChart v-if="list_examination_results.length" id="list_examination_results" :list="list_examination_results" :title="'考试成绩统计'"></pieChart>
							<div v-if="!list_examination_results.length">考试成绩没有符合条件的数据</div>
						</div>
					</el-col>
				</el-row>
			</div>
		</div>
	</div>
</template>
<script>
	import mixin from "@/mixins/page.js";
	import pieChart from "@/components/charts/pie_chart";
	import barChart from "@/components/charts/bar_chart";
	import newBarChart from "@/components/charts/new_bar_chart";
	import lineChart from "@/components/charts/line_chart";
	import newLineChart from "@/components/charts/new_line_chart";
	import mm_label from "@/components/mm_label.vue";
	export default {
		mixins: [mixin],
		name: "Home",
		components: {
			pieChart,
			barChart,
			newBarChart,
			lineChart,
			newLineChart,
			mm_label
		},
		data() {
			return {
				isAdmin: false,
				recognitionType: "",
				activeName: "third",
				list_examination_results: [],
				url_user_count: "~/api/user/count?",
			};
		},
		created() {
			this.getUserInfo();
			// 执行考试成绩数据获取
			this.get_list_examination_results();
			
			
		},
		mounted() {},
		methods: {
			async get_nickname(list,flag){
				if (flag) {
					for (let i=0;i<list.length;i++){
						await this.$get(
								"~/api/user/get_obj?user_id="+list[i],
								null,
								(json) => {
									if (json.result) {
										list[i] = json.result.obj.nickname;
									}
								});
					}
				}else {
					for (let i=0;i<list.length;i++){
						await this.$get(
								"~/api/user/get_obj?user_id="+list[i].name,
								null,
								(json) => {
									if (json.result) {
										list[i].name = json.result.obj.nickname;
									}
								});
					}
				}
			},
			// 获取考试成绩统计图数据
			get_list_examination_results() {
				let data = {};
				let flag = false;
				let user_group = this.$store.state.user.user_group;
				let user_id = this.$store.state.user.user_id;
				if (user_group!='管理员'){
					if (user_group=="注册用户"){
						data.user_number = user_id;
					}
				}
				this.$get("~/api/examination_results/list_group?groupby=grade", data, (json) => {
					if (json.result) {
						var list = json.result.list;
						this.list_examination_results = list.map((o) => {
							return {
								name: o[1],
								value: o[0]
							};
						});
						if (flag){
							this.get_nickname(this.list_examination_results,false);
						}
					}
				});
			},
				getUserInfo(){
					let userGroup = window.localStorage.getItem('user_group');
						if(userGroup){
						let _userGroup =JSON.parse(userGroup);
						let _info = JSON.parse(_userGroup.value);
						this.isAdmin = _info["user_group"] == "管理员" ? true : false;
					}
			}

		},
		computed:{
			recognitionHeight(){
				if(this.recognitionType === "face"){
					return "1070px"
				}else{
					return "1180px"
				}
			},
			recognitionUrl(){
					if(this.recognitionType === "face"){
					return "https://www.sk-ai.com/Experience/face-compare"
				}else{
					return "https://www.sk-ai.com/Experience/recognition?type="
				}
			}
		}
	};
</script>

<style scoped="scoped">
	.chart {
		display: block;
		width: 100%;
		height: 400px;
		padding: 1rem;
		position: relative;
	}

	.el-col {
		padding: 0.5rem;
	}

	.card {
		overflow: hidden;
	}
	
	.iframe_box ,.iframe_box_change{
		width: 100%;
		height: 1180px;
		position: relative;
		margin-top: 25px;
	}
	.iframe_box_change{
		height: 580px;
		padding-top: 50px;
	}
.iframe_box	.iframe_box_content, .iframe_box_change .iframe_box_content{
	width: 100%;
	height: 100%;
}
.iframe_box_top{
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100px;
	font-size: 25px;
	line-height: 100px;
	background: #fff;
	z-index: 99999999;
	padding-left: 50px;
}
</style>


三、系统架构

前端架构:前端采用Vue.js框架,结合Element UI等UI组件库,实现页面的快速开发。通过Axios库与后端进行数据交互,实现数据的动态展示和更新。
后端架构:后端采用Spring Boot框架,利用其快速开发、易于集成的特点,实现业务逻辑的处理和数据的持久化。通过MyBatis或JPA等持久层框架与MySQL数据库进行交互,确保数据的准确性和安全性。
在这里插入图片描述

四、功能模块

(一)注册模块的实现

用户在填写数据的时候必须与注册页面上的验证相匹配否则会注册失败,注册页面的表单验证是通过验证的,用户名的长度必须在6到18之间,邮箱必须带有@符号,密码和密码确认必须相同,你输入的密码,系统会根据你输入密码的强度给出指定的值,电话号码和身份证号码必须要求输入格式与生活相符合,当你前台验证通过的时候你点击注册,表单会将你输入的值通过name值传递给后台并保存到数据库中。
用户注册流程图如下图所示。
在这里插入图片描述

用户注册逻辑代码如下:
/**
     * 注册
     * @param user
     * @return
     */
    @PostMapping("register")
    public Map<String, Object> signUp(@RequestBody User user) {
        // 查询用户
        Map<String, String> query = new HashMap<>();
        query.put("username",user.getUsername());
        List list = service.select(query, new HashMap<>()).getResultList();
        if (list.size()>0){
            return error(30000, "用户已存在");
        }
        user.setUserId(null);
        user.setPassword(service.encryption(user.getPassword()));
        service.save(user);
        return success(1);
}
/**
     * 用户ID:[0,8388607]用户获取其他与用户相关的数据
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Integer userId;

    /**
     * 账户状态:[0,10](1可用|2异常|3已冻结|4已注销)
     */

    @Basic
    @Column(name = "state")
    private Integer state;

    /**
     * 所在用户组:[0,32767]决定用户身份和权限
     */

    @Basic
    @Column(name = "user_group")
    private String userGroup;

    /**
     * 上次登录时间:
     */

    @Basic
    @Column(name = "login_time")
    /**
     * 用户ID:[0,8388607]用户获取其他与用户相关的数据
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Integer userId;

    /**
     * 账户状态:[0,10](1可用|2异常|3已冻结|4已注销)
     */

    @Basic
    @Column(name = "state")
    private Integer state;

    /**
     * 所在用户组:[0,32767]决定用户身份和权限
     */

    @Basic
    @Column(name = "user_group")
    private String userGroup;

    /**
     * 上次登录时间:
     */

    @Basic
    @Column(name = "login_time")
    @Basic
    @Column(name = "nickname")
    private String nickname;

    /**
     * 密码:[0,32]用户登录所需的密码,由6-16位数字或英文组成
     */

    @Basic
    @Column(name = "password")
    private String password;

    /**
     * 邮箱:[0,64]用户的邮箱,用于找回密码时或登录时
     */

    @Basic
    @Column(name = "email")
    private String email;

    /**
     * 邮箱认证:[0,1](0未认证|1审核中|2已认证)
     */

    @Basic
    @Column(name = "email_state")
    private Integer emailState;

    /**
     * 头像地址:[0,255]
     */

    @Basic
    @Column(name = "avatar")
    private String avatar;

    /**
     * 创建时间:
     */

    @Basic
    @Column(name = "create_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Timestamp createTime;

    @Basic
    @Transient
    private String code;
}

(二)登录模块的实现

主要由两部分组成,登录前的登录界面以及登录后的用户功能界面。登录界面,要求用户输入用户名和密码,当用户名和密码其中一个输入为空时,给出提示“用户名,密码不能为空”。获取用户名和密码后到数据库中查找,如果用户名存在,以及对应的密码正确,则登录成功,否则登录失败。登录失败后给出提示,并把焦点停在文本框中。登录成功后将该次会话的全局变量username设置为用户名。登录成功后进入会员的功能模块,主要有会员基本信息修改,已经发布模拟考试信息管理,发布信息,和退出功能。退出功能是清除全局变量username的值,并跳回到首页。
登录流程图如下图所示。
在这里插入图片描述
用户登录的逻辑代码如下所示。

/**
     * 登录
     * @param data
     * @param httpServletRequest
     * @return
     */
    @PostMapping("login")
    public Map<String, Object> login(@RequestBody Map<String, String> data, HttpServletRequest httpServletRequest) {
        log.info("[执行登录接口]");

        String username = data.get("username");
        String email = data.get("email");
        String phone = data.get("phone");
        String password = data.get("password");

        List resultList = null;
        Map<String, String> map = new HashMap<>();
        if(username != null && "".equals(username) == false){
            map.put("username", username);
            resultList = service.select(map, new HashMap<>()).getResultList();
        }
        else if(email != null && "".equals(email) == false){
            map.put("email", email);
            resultList = service.select(map, new HashMap<>()).getResultList();
        }
        else if(phone != null && "".equals(phone) == false){
            map.put("phone", phone);
            resultList = service.select(map, new HashMap<>()).getResultList();
        }else{
            return error(30000, "账号或密码不能为空");
        }
        if (resultList == null || password == null) {

 return error(30000, "账号或密码不能为空");
        }
        //判断是否有这个用户
        if (resultList.size()<=0){
            return error(30000,"用户不存在");
        }

        User byUsername = (User) resultList.get(0);


        Map<String, String> groupMap = new HashMap<>();
        groupMap.put("name",byUsername.getUserGroup());
        List groupList = userGroupService.select(groupMap, new HashMap<>()).getResultList();
        if (groupList.size()<1){
            return error(30000,"用户组不存在");
        }

        UserGroup userGroup = (UserGroup) groupList.get(0);

        //查询用户审核状态
        if (!StringUtils.isEmpty(userGroup.getSourceTable())){
            String sql = "select examine_state from "+ userGroup.getSourceTable() +" WHERE user_id = " + byUsername.getUserId();
            String res = String.valueOf(service.runCountSql(sql).getSingleResult());
            if (res==null){
                return error(30000,"用户不存在");
            }
            if (!res.equals("已通过")){
                return error(30000,"该用户审核未通过");
}
        }

        //查询用户状态
        if (byUsername.getState()!=1){
            return error(30000,"用户非可用状态,不能登录");
        }

        String md5password = service.encryption(password);
        if (byUsername.getPassword().equals(md5password)) {
            // 存储Token到数据库
            AccessToken accessToken = new AccessToken();
            accessToken.setToken(UUID.randomUUID().toString().replaceAll("-", ""));
            accessToken.setUser_id(byUsername.getUserId());
            tokenService.save(accessToken);

            // 返回用户信息
            JSONObject user = JSONObject.parseObject(JSONObject.toJSONString(byUsername));
            user.put("token", accessToken.getToken());
            JSONObject ret = new JSONObject();
            ret.put("obj",user);
            return success(ret);
        } else {
            return error(30000, "账号或密码不正确");
        }
}

(三)用户资料修改模块的实现

用户登录/注册成功之后可以修改自己的基本信息。修改页面的表单中每一个input的name值都要与实体类中的参数相匹配,在用户点击修改页面的时候,如果改后用户名与数据库里面重复了,页面会提示该用户名已经存在了,否则通过Id来查询用户,并将用户的信息修改为表单提交的数据。

(四)考试信息推荐列表管理模块的实现

如果考试信息推荐列表数据的信息需要修改,管理员可以通过查询考试信息推荐列表数据的基本信息来查询考试信息推荐列表数据,查询考试信息推荐列表数据是通过ajax技术来进行查询的,需要传递考试信息推荐列表数据的标题、编号等参数然后在返回到该页面中,可以选中要修改或删除的那条信息,如果选中了超过一条数据,页面会挑一个窗口提醒只能选择一条数,如果没有选中数据会挑一个窗口题型必须选择一条数据。当选择确认修改的时候,后台会根据传过来的id到数据库查询,并将结果返回到修改页面中,可以在修改页面中修改刚刚选中的信息当点击确认的时候from表单会将修改的数据提交到后台并保存到数据库中,就是说如果提交的数据数据库中存在就修改,否则就保存。

其他功能实现

论文里都有详细描述,这里就不一一赘述了!
在这里插入图片描述

五、数据库设计

在这里插入图片描述

本系统采用MySQL数据库进行数据的存储和管理。
前面可以分析到数据库中最重要的是学习资料信息,学生信息,模拟试题信息,同时存在考试信息和成绩信息。分析可以得到如下数据描述:

平台用户:用于记录用户的各种信息,包括学号、姓名、性别、手机、邮箱、照片等数据项。
管理员:记录管理员的登录信息。包括用户名,密码,权限等数据项。
考试:存放给考试的内容,包括试卷考试名称、考试日期、配图数据项。
在线考试报名:存储用户的考试报名信息。包括考试报名西悉尼、考试报名资料内容等数据项。
成绩。存储用户的试卷考试成绩信息。

  • 数据库概念设计
    根据前面的数据流程图,结合系统的功能模块设计,设计出符合系统的各信息实体。
    系统ER图如下图所示。
    在这里插入图片描述
  • 数据库表设计
    在线考试报名系统所拥有的数据表有以下:学生信息表,考试资讯信息表,考试报名表,考试安排表,考试成绩表。
    由于数据表较多,只展示系统主要数据表,如下表所示。
    在这里插入图片描述

六、系统实现与测试

在开发过程中,我们遵循了软件开发的最佳实践,进行了详细的需求分析、系统设计、编码实现和测试验证。通过单元测试、集成测试和系统测试,确保系统的稳定性和可靠性。

系统页面一览

管理后台

在这里插入图片描述

用户前台

在这里插入图片描述

服务后端

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

视频演示

演示:https://pan.baidu.com/s/1_8GSmGJp7McTGq2BD5YpVQ?pwd=dpar

七、总结与展望

源码有偿获取,源码亲测可用、全网性价比最高,可咨询:mikenote

获取到的源码文件将包含:源码➕数据库➕环境配置教程➕项目技术开发文档➕系统项目框架讲解视频➕论文➕答辩PPT
如下图所示:
在这里插入图片描述
PPT
在这里插入图片描述
论文
在这里插入图片描述

讲解
在这里插入图片描述

  • 30
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《基于springboot vue在线考试系统》的选题分析: 随着互联网的不断发展和应用,线上考试系统的需求也越来越大。基于SpringBootVue在线考试系统,是一种快速部署、可靠稳定的在线考试解决方案。 该系统的主要功能包括:用户登录、组织管理、试卷管理、题目管理、考试管理、成绩统计等。用户可通过注册登录系统,参与指定的考试系统管理员可以进行组织管理,创建不同的考试组织,添加考试科目和试卷。题目管理功能可以用于添加、修改和删除考题。考试管理功能可以设置考试时间、考试规则以及监考人员信息。考试完成后,系统可以自动统计用户的考试成绩,并根据成绩进行排名。 选该题目的原因有以下几点: 1. 需求广泛:随着在线教育的兴起,线上考试需求越来越大。该系统可以满足学校、培训机构、企业等多种机构的在线考试需求。 2. 技术有优势:SpringBootVue是当前流行的开发框架,具有简洁、灵活、高效等特点,能够快速实现系统的开发和部署。 3. 功能完善:该系统设计了完整的考试流程,包括试卷管理、题目管理、考试管理以及成绩统计等功能,能够满足不同场景下的考试需求。 4. 扩展性强:基于SpringBootVue的开发,系统可以方便地进行二次开发和定制化,满足特定需求。 5. 用户体验好:Vue作为一种轻量级的框架,能够提供良好的用户界面和用户交互体验。 综上所述,《基于springboot vue在线考试系统》具有较大的市场潜力和发展前景,也具备一定的竞争优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MIKE笔记(同名B站)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值