博主介绍:👉全网个人号和企业号粉丝40W+,每年辅导几千名大学生较好的完成毕业设计,专注计算机软件领域的项目研发,不断的进行新技术的项目实战👈
⭐️热门专栏推荐订阅⭐️ 订阅收藏起来,防止下次找不到🔎上百套Python实战项目持续更新中
有需求的各位可以先收藏起来,还有大家在毕设选题,开题报告有疑惑的都可以找我,给你参考意见,需要开题模板的可以私信留言告诉我❤️文末获取源码联系❤️ ⚠️一定要先收藏⚠️
第4章 系统设计
4.1系统整体设计方案
在线智能题库管理系统的设计在体系结构模式的选择上还是比较青睐于用户层,功能层和数据层这样的三层结构,俗称B/S结构。这种结构模式在Internet兴起之后,大部分的应用程序都会将其作为首选结构设计模式。
(1)用户层:在线智能题库管理系统的使用人员通常在用户层登录系统,使用系统,对数据的输入和输出进行处理;
(2)功能层:在用户层和数据层的中间,就分布着功能层,功能层主要就是把用户的请求以SQL语句的方式来对数据库进行检索,最终将数据检索的结果传递给用户层;
(3)数据层:数据层主要就是实现对数据库的操作,一般都是增加,修改,删除,查找数据。每当数据层接收到来自上层的数据操作请求时,就会根据该指令去操作数据库,最终反馈给上层执行结果。
4.2功能结构设计
前面对在线智能题库管理系统的功能需求的分析只是大致的划分功能模块,接下来的工作就是对这些大致的功能进行细分。让在线智能题库管理系统的内容变得更具体,更丰富。
(1)管理员功能结构设计
图4.1展示的是管理员功能结构。系统将管理员的个人中心模块划分为个人信息管理与修改密码子模块,将基础数据管理功能划分为公告类型管理,科目管理子模块。将考试管理划分为考试记录,错题本子模块。
图4.1管理员功能结构
(2)学生功能结构设计
图4.2展示的是学生功能结构。系统将学生的个人中心模块划分为考场,我的考场分配,考试记录,错题表子模块。学生在线回答试卷,查看考试记录,查看所考试卷的错题信息,以及查看学生自己的考场分配信息等。
图4.2学生功能结构
4.3数据库设计
数据库的设计是对系统相关数据要求的具体设计。需要对各个对象进行数据类型具体化,比如每个表都要有自己的主键,有些关键性数据不可以直接采用删除操作,只能采用伪装删除的操作,比如专门设置一个字段就是删除标记字段,默认没删除就是0,如果已经删除则设置为1,这样如果有大量数据的删除,只需要更新相关字段的值就行,不需要大量的对磁盘进行删除操作,在性能上面有很大的提升。目前市场上主流的数据库基本上都符合设计的功能需求,但是一切要根据实际出发,首先开发使用的电脑是自己上学用的,那么首选对电脑性能要求没那么高的数据库,其次尽量使用自己曾经学习过的数据库,这样学习成本会降低,时间上就有空余的时间来安排其他事情。本系统通过数据库设计相关的分析,采用MySQL数据库。
4.3.1数据库概念设计
有一个专门用来描述数据库实体与参数之间的图叫做E-R图,E-R是英文缩写,经过多年的传播,已经变成了数据库实体之间联系的专业名字,一般都用缩写E-R图表示,不再采用英文全称。现实世界有很多相关的数据,如何应用到数据库存放就需要进行归类,实体与属性之间的关系不能混淆,一个实体可以有多个属性,一个属性可能对应多个实体,实体和属性之间的关系是需要用图的形式进行描述的,不然不直观。采用Visio画图工具来画E-R图是一种很明智的选择。Visio是专门用来画图的工具之一,内置了很多图形选项,画E-R图用Visio画是正确的,Visio画的图形可以进行保存,复制到其他地方还可以进行编辑,如果缺少某些属性可以直接用Visio打开进行修改,是非常方便的。接下来展示本系统的部分实体图以及实体关系E-R图。
4.3.2数据库物理设计
二维表是传统的用来记录相关表与属性之间关系的一种专业图表。表里面每个字段名称都是唯一的,代表当前表的某一个唯一的属性,如果有多个属性,那么就会多几个字段来进行描述。二维表的概念如下:
关键字:每个表建议有且只有一个主键,用来表达数据的专一性和唯一性。也可以通过设定的关键字与其他表进行关联。
元组:二维表显示数据有行与列的关系,行是可以增加的,列是提前设定好的,每一行数据成为元组。
属性:列的名称一般称为属性,也就是字段,比如一个正常人拥有的属性必然有姓名,性别,不管是姓名还是性别,都可以称之为属性。
关系:有列有行只是一张二维表的表达,这张二维表的名称就是行与列的关系,比如用户表,比如有用户账号的属性也就是列,用户的姓名属性也是列,用户属性都有成为元组,很多用户都在这个表里之间的关系成为用户表。
以上内容表示数据之间的关系,通过对数据进行分析和归纳,二维表用来描述和存储相关数据。在线智能题库管理系统数据表设计结果展示如下:
表4.1 试卷表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
exampaper_name | varchar(200) | 试卷名称 | 不允许空 |
exampaper_date | int(11) | 考试时长(分钟) | 允许空 |
exampaper_myscore | int(20) | 试卷总分数 | 不允许空 |
kemu_types | int(11) | 科目 | 允许空 |
exampaper_types | int(11) | 试卷状态 | 不允许空 |
zujuan_types | int(11) | 组卷方式 | 允许空 |
exampaper_delete | int(255) | 逻辑删除 | 允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.2 公告表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(11) | 主键 | 不允许空 |
gonggao_name | varchar(200) | 公告名称 | 允许空 |
gonggao_photo | varchar(200) | 公告图片 | 允许空 |
gonggao_types | int(11) | 公告类型 | 不允许空 |
insert_time | timestamp | 公告发布时间 | 允许空 |
gonggao_content | text | 公告详情 | 允许空 |
create_time | timestamp | 创建时间 | 允许空 |
表4.3 学生表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(11) | 主键 | 不允许空 |
username | varchar(200) | 账户 | 允许空 |
password | varchar(200) | 密码 | 允许空 |
yonghu_uuid_number | varchar(200) | 学生编号 | 允许空 |
yonghu_name | varchar(200) | 学生姓名 | 允许空 |
yonghu_phone | varchar(200) | 学生手机号 | 允许空 |
yonghu_id_number | varchar(200) | 学生身份证号 | 允许空 |
yonghu_photo | varchar(200) | 学生头像 | 允许空 |
sex_types | int(11) | 性别 | 允许空 |
yonghu_email | varchar(200) | 电子邮箱 | 允许空 |
create_time | timestamp | 创建时间 | 允许空 |
表4.4 试卷选题表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
exampaper_id | int(20) | 试卷 | 不允许空 |
examquestion_id | int(20) | 试题 | 不允许空 |
exampapertopic_number | int(20) | 试题分数 | 不允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.5 考试记录表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
examrecord_uuid_number | varchar(200) | 考试编号 | 允许空 |
yonghu_id | int(20) | 考试学生 | 不允许空 |
exampaper_id | int(20) | 所属试卷id(外键) | 不允许空 |
total_score | int(200) | 所得总分 | 允许空 |
insert_time | timestamp | 考试时间 | 不允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.6 答题详情表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
examredetails_uuid_number | varchar(200) | 试卷编号 | 允许空 |
yonghu_id | int(20) | 学生id | 不允许空 |
examquestion_id | int(20) | 试题id(外键) | 不允许空 |
examredetails_myanswer | varchar(200) | 考生答案 | 允许空 |
examredetails_myscore | int(20) | 试题得分 | 不允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.7 试题表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
examquestion_name | varchar(200) | 试题名称 | 允许空 |
kemu_types | int(11) | 科目 | 允许空 |
examquestion_options | longtext | 选项,json字符串 | 允许空 |
examquestion_answer | varchar(200) | 正确答案 | 允许空 |
examquestion_analysis | longtext | 答案解析 | 允许空 |
examquestion_types | int(20) | 试题类型 | 允许空 |
examquestion_sequence | int(20) | 试题排序,值越大排越前面 | 允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.8 错题表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(20) | 主键 | 不允许空 |
yonghu_id | int(20) | 学生id | 不允许空 |
exampaper_id | int(20) | 试卷(外键) | 不允许空 |
examquestion_id | int(20) | 试题id(外键) | 不允许空 |
examredetails_myanswer | varchar(200) | 考生作答 | 允许空 |
insert_time | timestamp | 记录时间 | 不允许空 |
create_time | timestamp | 创建时间 | 不允许空 |
表4.9 考场表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(11) | 主键 | 不允许空 |
kaochang_uuid_number | varchar(200) | 考场编号 | 允许空 |
kaochang_name | varchar(200) | 考场名称 | 允许空 |
kaochang_address | varchar(200) | 考场位置 | 允许空 |
kaochang_content | text | 考场介绍 | 允许空 |
insert_time | timestamp | 录入时间 | 允许空 |
create_time | timestamp | 创建时间 | 允许空 |
表4.10 考生考场分配表
字段 | 类型 | 说明 | 允许空 |
id (主键) | int(11) | 主键 | 不允许空 |
yonghu_id | int(11) | 学生 | 允许空 |
kaochang_id | int(11) | 考场 | 允许空 |
insert_time | timestamp | 分配时间 | 允许空 |
create_time | timestamp | 创建时间 | 允许空 |
表4.11 管理员表
字段 | 类型 | 说明 | 允许空 |
id (主键) | bigint(20) | 主键 | 不允许空 |
username | varchar(100) | 用户名 | 不允许空 |
password | varchar(100) | 密码 | 不允许空 |
role | varchar(100) | 角色 | 允许空 |
addtime | timestamp | 新增时间 | 不允许空 |
当需要描述系统具体实现的功能点的时候,一方面肯定是要用文字表达实现的功能,另一方面完全可以从系统的具体实现页面把可以用文字描述的操作界面以图片的形式放到文字的下方,这样的表达方式可谓之言之有物,更容易理解系统实现的功能部分。
5.1 管理员功能实现
5.1.1 考场管理
图5.1展示的是考场管理界面。
图5.1 考场管理界面
此界面展示了考场名称,考场位置等信息,每条考场信息的右侧区域都有可供管理员选择的操作,包括删除,修改等。
5.1.2 考场分配管理
图5.2展示的是考场分配管理界面。
图5.2 考场分配管理界面
此界面展示了考场名称,学生姓名,学生手机号,分配时间等信息,每条学生考场分配信息的右侧区域都会展示管理员可以进行的操作,包括删除,查看其详情,修改等。
5.1.3 试卷管理
图5.3展示的是试卷管理界面。
图5.3 试卷管理界面
此界面展示了考试时长,科目,组卷方式,试卷状态等信息。每条试卷信息的右侧区域都展示了可以让管理员操作的内容,比如设置考题,删除等。
代码实现
package com.controller;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.TokenEntity;
import com.entity.UserEntity;
import com.service.TokenService;
import com.service.UserService;
import com.utils.CommonUtil;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.ValidatorUtils;
/**
* 登录相关
*/
@RequestMapping("users")
@RestController
public class UserController{
@Autowired
private UserService userService;
@Autowired
private TokenService tokenService;
/**
* 登录
*/
@IgnoreAuth
@PostMapping(value = "/login")
public R login(String username, String password, String captcha, HttpServletRequest request) {
UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
if(user==null || !user.getPassword().equals(password)) {
return R.error("账号或密码不正确");
}
String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());
return R.ok().put("token", token);
}
/**
* 注册
*/
@IgnoreAuth
@PostMapping(value = "/register")
public R register(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
return R.error("用户已存在");
}
userService.insert(user);
return R.ok();
}
/**
* 退出
*/
@GetMapping(value = "logout")
public R logout(HttpServletRequest request) {
request.getSession().invalidate();
return R.ok("退出成功");
}
/**
* 密码重置
*/
@IgnoreAuth
@RequestMapping(value = "/resetPass")
public R resetPass(String username, HttpServletRequest request){
UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
if(user==null) {
return R.error("账号不存在");
}
user.setPassword("123456");
userService.update(user,null);
return R.ok("密码已重置为:123456");
}
/**
* 列表
*/
@RequestMapping("/page")
public R page(@RequestParam Map<String, Object> params,UserEntity user){
EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();
PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));
return R.ok().put("data", page);
}
/**
* 列表
*/
@RequestMapping("/list")
public R list( UserEntity user){
EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();
ew.allEq(MPUtil.allEQMapPre( user, "user"));
return R.ok().put("data", userService.selectListView(ew));
}
/**
* 信息
*/
@RequestMapping("/info/{id}")
public R info(@PathVariable("id") String id){
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* 获取用户的session用户信息
*/
@RequestMapping("/session")
public R getCurrUser(HttpServletRequest request){
Long id = (Long)request.getSession().getAttribute("userId");
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* 保存
*/
@PostMapping("/save")
public R save(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
return R.error("用户已存在");
}
userService.insert(user);
return R.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
public R update(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
UserEntity u = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername()));
if(u!=null && u.getId()!=user.getId() && u.getUsername().equals(user.getUsername())) {
return R.error("用户名已存在。");
}
userService.updateById(user);//全部更新
return R.ok();
}
/**
* 删除
*/
@RequestMapping("/delete")
public R delete(@RequestBody Long[] ids){
userService.deleteBatchIds(Arrays.asList(ids));
return R.ok();
}
}
源码获取
大家点赞、收藏、关注 ,让更多需要的同学看到
不同开发语言专栏推荐订阅:
👇下方有我的微信名片👇