系统截图
、 视频演示
。 随着社会的进步和商品经济的不断发展,社会对劳动者和技术人员的知识和能力水平的要求越来越高。考试作为衡量人的能力的重要手段,在现代生活的地位进一步提高,并深入到社会各个方面,各种各样的学历考试、资格证书考试层出不穷。同时,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数据库进行数据的存储和管理。 前面可以分析到数据库中最重要的是学习资料信息,学生信息,模拟试题信息,同时存在考试信息和成绩信息。分析可以得到如下数据描述:
平台用户:用于记录用户的各种信息,包括学号、姓名、性别、手机、邮箱、照片等数据项。 管理员:记录管理员的登录信息。包括用户名,密码,权限等数据项。 考试:存放给考试的内容,包括试卷考试名称、考试日期、配图数据项。 在线考试报名:存储用户的考试报名信息。包括考试报名西悉尼、考试报名资料内容等数据项。 成绩。存储用户的试卷考试成绩信息。
在开发过程中,我们遵循了软件开发的最佳实践,进行了详细的需求分析、系统设计、编码实现和测试验证。通过单元测试、集成测试和系统测试,确保系统的稳定性和可靠性。
演示:https://pan.baidu.com/s/1_8GSmGJp7McTGq2BD5YpVQ?pwd=dpar
源码有偿获取,源码亲测可用、全网性价比最高,可咨询:mikenote
获取到的源码文件将包含:源码➕数据库➕环境配置教程➕项目技术开发文档➕系统项目框架讲解视频➕论文➕答辩PPT 如下图所示:
PPT
论文
讲解