@TOC
ssm337基于SSM框架的高校试题管理系统+vue
研究背景
随着中国的科技的不断进步,计算机发展也慢慢的越来越成熟,人们对计算机也是越来越更加的依赖,科研、教育慢慢用于计算机进行管理。从第一台计算机的产生,到现在计算机已经发展到我们无法想象。给我们的生活改变很多很多,给我们提供了把很多的方便,计算机已经融入到我们的生活中,和我们的生活息息相关。
我们经过对高校试题管理进行调查,发现了随着试题的不断增多,高校试题管理工作也越来越繁重和琐碎,容易出错,数据繁多,传统的高校试题管理模式面对大量试题信息,信息的及时更新等弊端凸显,传统的高校试题管理过度的依靠人力资源的记录,对于庞大的试题信息,显然只依靠人力,很难准确的处理好大量的数据,传统的管理模式不仅效率低,出错率高,对于高校试题管理带来了诸多不便,因此,传统的高校试题管理模式已经远远无法满足当今高校的发展需求,我们急需对高校试题管理体系进行变革,开发基于计算机平台的高校试题管理系统。现代化的利用计算机来进行高校试题管理很大程序上可以提高效率,人力方面也大大的节省,界面简单易操作,只要会计算机就可以快速的进行题库相关信息的管理。对经济方面也是很大的节省,其优点是显而易见的。
1.2设计原则
在开始开发项目之前,必须要先考虑项目的实用性、科学性,以及该项目是否能够真正让用户受益并尽可能的发挥项目的作用。因此,在开发前,通过以下几条原则对项目进行判断:
(1)可行性原则。项目需要保证经济可行性和技术可行性,这包括了项目在浏览端、服务端等方面上的经济和技术上是可以达成的。
(2)适应性原则。项目要保证可维护性和可扩展性,这是每个非短期项目都需要考虑的,并且不论是维护还是扩展,都必须要建立在适应用户的正常需求的基础上。
(3)安全性及保密性原则。要充分保证用户信息的安全性和保密性,不能因为开发上的疏忽,导致用户的信息泄露。
(4)系统工程原则。为了确保项目的整体性,在项目调查、项目分析、项目设计、项目开发的过程中,都需遵从项目工程的方法和步骤逐步进行。
(5)统一规划、分期实施、逐步完善原则。项目开发的过程中,要按照规划、分期实施,特别是要注意在项目开发过程中要有条理,从点到面,一步步完善,不要贪图进度,要循环渐进的对项目进行开发。
1.3论文的组织结构
第一章主要是简单的介绍下设计本网站的研究背景和设计原则,在这一章里主要是让大家了解下我的设计的前因后果,为接下来我的其它章节做铺垫。
第二章主要是介绍在设计过程中所涉及到的技术。
第三章主要是介绍下设计这个网站所需要的需求以及我们的功能需求分析,因为只有更好的分析清楚我们的功能需求才能更好的完成我们的设计。
第四章网站系统设计,主要介绍了网站结构的设计以及展示了数据库E-R图设计,这一章主要是为了能让大家更好的了解网站的一些基本设计信息。
第五章系统的实现,介绍了系统每个模块的设计与实现,让大家能清晰的了解系统的主要功能。
第六章系统的测试,这章主要是测试下各个部分每个功能是否能用,看下是否有错误。
第七章系统总结,进行系统最后的总结工作。
2 相关技术简介
2.1Java技术
Java是一种非常常用的编程语言,在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中,Java的身影无处不在,并且拥有旺盛的生命力。Java的跨平台能力十分强大,只需一次编译,任何地方都可以运行。除此之外,它还拥有简单的语法和实用的类库,让编程人员可以尽可能将精力集中在问题的求解上,并且许多开源项目和科研成果都是采用它实现的。
在1995年这一年的5月份,著名的Sun Microsystems公司在程序开发设计上面郑重推出一种面向对象开发的程序设计语言——Java,最开始的时候Java是由詹姆斯.高斯林这位伟大的JAVA之父来进行主导,但是在后来由于各种原因,让甲骨文公司这个针对商业程序创建了oracle大型数据库的公司收购了Java。Java的平台总共算下来有3个,分别为javaME和javaSE以及javaEE这3个java平台。下面将对其进行分别介绍。
(1)在电脑桌面程序的开发上面需要选择JavaME,这个用得也比较多。
(2)企业也会根据工作以及业务需要开发各种软件,那么就会选用JavcEE这个支持企业版软件的开发的Java平台,JavcEE主攻运用在企业领域上面的web应用,JavcEE也在javaSE的基础上获得了比如jsp技术 ,Servlet技术等程序开发技术的支持。
(3)现在生活中手机的普及化,也使得手机端这样的移动设备的软件的兴起,JavaME这个迷你版java平台就能运用于移动端的软件开发操作。
2.2B/S结构
此次设计的网络结构模式B/S结构(Browser/Server)。B/S架构也称为B/S模式,是一种服务器以及浏览器架构模式。B/S的工作模式都是先由浏览器请求,服务器再响应。B/S体系结构解决了异构系统中的连接难题,大大改善了系统的开放性,让系统的扩展和维护更加简单;同时,B/S体系结构操作也比较容易,界面全都为浏览器模式,容易分发数据的捕获程序。只要安装通用的浏览器(如WWW浏览器)就能通过Web服务器与数据库进行数据交互。此结构的好处之一在于由于它使用的统一的浏览器,使其可以在不同的地方且不需要用专门的软件进行操作,实现了不论你使用怎样的接入网的方式都可以对公共的数据进行调用和浏览。
相对于C/S模式,B/S模式是对C/S模式应用的扩展,B/S模式不用对不同的计算机安装不同应用程序,还有安全性的要求及对模式上手难度都比前者更好。B/S模式可以让客户机的压力大大减轻,工作的负荷被合理的分配了。
图2-1 B/S模式三层结构图
2.3MYSQL数据库
Mysql现隶属于Oracle公司,之前隶属于SUN公司,却是MySQL AB公司研发出来的数据库[5]。
MySQL数据库是一种开源的关系行数据库操作系统其使用的SQL语言是用来访问数据库较为标准的常用数据库操作语言。而且MySQL数据库体积较小易于安装、运行速度较快、所花费的成本较低搭载超文本预处理器接口与web服务器软件或服务可以组成良好的开发环境。
Mysql是当今最为热门的数据库之一,它是用于WEB应用程序的最佳RDBMS(关系数据库管理系统)应用程序。Mysql所使用的语言也是访问数据库最常用的语言,而且体积较小,速度较快,并且成本较低,所以本系统选择Mysql作为系统的数据库,许多中小型的网站一般都是选择Mysql作为网站的数据库。Mysql的数据库是存放在表中的,所以它的速度较快,而且也较为的灵活。MySQL操作起来十分简便,因为MySQL不是讲所有的数据堆放在一起,这样数据量大,查找起来需要的时间很多。它是将数据保存在不同的表中,这些表具有关联性,查找时直接从表中获取数据,这样大大提高了查找的速度。且MySQL是免费的,这对于大多数研发人员来说,是极大的诱惑。MySQL可以使用标准的sql数据语句,使用起来简单方便。
2.4 SSM框架
本高校试题管理系统基于Spring、SpringMVC、Mybatis框架进行开发设计。
Spring 框架是在2004年首次发布,之后出现了多次的重大修订。Spring框架是由七个不同的模块组成,分别是SpringCore、Spring AOP、Spring ORM、Spring DAO、Spring Web Flow、Spring Context和Spring Web MVC。这些模块提供不同的平台来开发不同的企业应用程序 ,本课题使用Spring Web MVC模块开发基于MVC的应用程序。
Spring Web MVC是基于Servlet API的原始Web框架,从一开始就包含在Spring 框架中。“Spring Web MVC”是该框架的正式名称,但通常被简称为“Spring MVC”。Spring MVC框架提供了模型模块-视图模块-控制器的架构和可用于直接开发的Web应用程序的现成组件。Spring MVC模式将应用程序的不同方面分开,使元素之间形成松散耦合。
MyBatis原名叫做iBatis属于持久层框架,消除了大部分JDBC代码和参数的设置以及结果集的检索。这个框架不仅支持普通SQL查询和存储过程,还支持高级的映射。MyBatis使用.xml和注解来做原始映射和配置,将接口和Java对象映射成数据库记录。
3 系统分析
3.1可行性分析
在进行可行性分析时,我们通常根据软件工程里方法,通过四个方面来进行分析,分别是技术、经济、操作和法律可行性。因此,在基于对目标系统的基本调查和研究后,对提出的基本方案进行可行性分析。
3.1.1技术可行性
本基于SSM框架的高校试题管理系统的设计与实现采用Java技术和MYSQL数据库进行开发设计,作为计算机专业学生,在学校期间就接触到许多关于编程方面的知识,当然也包括各种编程软件,对他们的了解度也比较系统,所以技术开发上面还是有一定把握。
3.1.2操作可行性
本系统操作页面简洁明了,操作极其容易,用户登陆后一眼便可看到自己所需要的信息,而管理员的操作也十分轻松便捷,只要操作人员具有一定的文字水平以及简单的逻辑思维,就可以轻松操作本系统,因此本系统在操作上是可行的。
3.1.3经济可行性
该系统的开发工具使用的都是免费的开发工具,且内容较为简单,一台计算机便可以开发出这个系统,且后期的维护,修改等对本系统的改动,都可以只通过一台计算机实现,因此开发该系统的成本在有计算机的情况下基本为0,所以本系统在经济上是可行的。
3.1.4法律可行性
本基于SSM框架的高校试题管理系统的设计与实现开发的所有技术资料都为合法,知识产权问题不会发生在开发过程中,而且没有抄袭其他相关系统,不会有侵犯版权的问题。所以在开发过程中不会涉及法律责任。
通过以上可行性分析得知,可以利用现有的技术和合理的成本开发出本网站,并且能够在遵守相关法律的基础上运行该系统。
3.2系统性能分析
(1)完整性分析
要求各种信息记录的完整性,内容不能为空,各种数据间联系应保持正确性,且相同的数据在不同记录中的一致性。
(2)系统运行速度分析
页面响应时问应该在3秒以内,最长不能超过4秒。
(3)界面分析
系统界面要求简单明了,容易操作,符合用户操作习惯。
(4)安全性分析
要充分保证系统的安全性、稳定性。要想对系统进行管理,必须经过正确的账号密码进行登录,否则无权进行管理。在具体实现中对不同的权限进行设定,不同权限的用户在系统中登陆后,不可以越级操作。
3.3系统功能分析
此基于SSM框架的高校试题管理系统的设计与实现功能分析主要分为管理员功能模块、教师功能模块和学生功能模块三大模块,下面详细介绍这三大模块的主要功能:
(1)管理员:管理员登陆后可对系统进行全面管理,管理员主要功能模块包括个人中心、学生管理、教师管理、试题管理、试卷管理以及考试管理,管理员实现了对系统信息的查看、添加、修改和删除的功能。管理员用例图如图3-1所示。
图3-1 管理员用例图
(2)学生:学生注册登录后主要功能模块包括个人中心、考试管理(试卷列表、考试记录和错题本)。
图3-2 学生用例图
(3)教师:教师学生登录后主要实现的功能模块包括个人中心、学生管理、试卷管理、试题管理以及考试管理。
图3-3 教师用例图
3.4系统流程分析
3.4.1注册流程
未有账号的学生和教师均可进行注册操作,注册流程如图3-4所示。
图3-4 用户注册流程图
3.4.2登录流程
登录模块主要满足了学生、教师以及管理员的权限登录,学生登录流程图如图3-5所示。
图 3-5 学生登录流程图
3.4.3添加信息流程
管理员、教师和学生登录后均可进行信息的添加操作,添加信息流程图如图3-6所示。
图3-6添加信息流程图
4 系统设计
4.1系统概要设计
基于SSM框架的高校试题管理系统的设计与实现主要分为管理员、教师和学生三个角色,系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示:
图4-1 系统工作原理图
4.2系统结构设计
系统架构的整体设计是一个将一个庞大的任务细分为多个小的任务的过程,这些小的任务分段完成后,组合在一起形成一个完整的任务。本基于SSM框架的高校试题管理系统的设计与实现主要包括学生功能模块、教师功能模块和管理员功能模块三大部分,系统结构设计如图4-2所示。
图4-2系统结构图
4.3 系统顺序图
(1)登陆顺序图
用户在登录时,首先进入系统登录窗口,用户需要输入用户名和密码,点击登录按钮进行登录操作,系统会以用户名和密码为参数在数据库中进行登录信息的验证,验证成功则登录成功,进入用户主界面。登录模块顺序图如图4-3所示。
图4-3 登录顺序图
(2)注册顺序图
未有账号的学生和教师均可进入注册界面进行注册操作,在注册界面输入注册信息,点击提交按钮,系统首先判断用户名是否存在,存在则提示重新输入,不存在则验证注册信息是否正确,正确则在数据库中添加注册数据,提示注册成功。用户注册模块顺序图如图4-4所示。
图4-4 注册顺序图
(3)修改密码顺序图
用户登录后可进入修改密码界面进行修改密码操作,在修改密码时,需要输入原始密码和新密码,系统会在数据库中进行原密码的验证,原密码正确则在数据库中添加修改数据,修改成功。修改密码顺序图如图4-5所示。
图4-5 修改密码顺序图
4.4数据库设计
4.4.1 数据库实体(E-R图)
E-R图是一种描述显示数据类型间的关系的数据描述方法,E-R图可以完整地映射出现实模型的关系。
实体联系模型反映出来的是现实世界中实体的相互间关联的关系,是用来在数据库设计过程中表示数据库系统结构的方法。它的思想是使用现有的数据模型来表现出目前项目实体间所具有的现实关联。E-R图是可以表示实体间相互关联的意义,直观反映出实体间的关联。
在为实体设计属性与关联的时候便可以确定实体间主外键的关联关系,实体所具有的延伸性。在E-R图中这些都能直观的显示出来。像这样将数据分类成组后,就会产生了与相关的分组所不同的信心,这样更加的易于用户进行观察和实际分析。本基于SSM框架的高校试题管理系统的设计与实现的E-R图如下所示:
(1)试卷实体属性E-R图如图4-6所示。
图4-6 试卷实体属性E-R图
(2)试题实体属性E-R图如图4-7所示。
图4-7 试题实体属性E-R图
(3)管理员实体属性E-R图如图4-8所示。
图4-8 管理员实体属性E-R图
(4)教师实体属性E-R图如图4-9所示。
图4-9 教师实体属性E-R图
(5)学生实体属性E-R图如图4-10所示。
图4-10 学生实体属性E-R图
4.4.2 数据库表设计
本基于SSM框架的高校试题管理系统的设计与实现采用了MYSQL数据库管理系统,各个表的设计结果如下:
表4-1 exampaper试卷信息表
字段名 | 数据类型 | 是否允许空 | 字段含义 |
---|---|---|---|
id | bigint(20) | NOT NULL | 编号 |
addtime | timestamp | NULL | 添加时间 |
name | varchar(200) | NULL | 试卷名称 |
time | int(11) | NULL | 考试时长 |
status | int(11) | NULL | 试卷状态 |
表4-2 examquestion试题信息表
字段名 | 数据类型 | 是否允许空 | 字段含义 |
---|---|---|---|
id | bigint(20) | NOT NULL | 编号 |
addtime | timestamp | NULL | 添加时间 |
paperid | bigint(20) | NULL | 试卷编号 |
papername | varchar(200) | NULL | 试卷名称 |
questionname` | varchar(200) | NULL | 试题名称 |
options | longtext | NULL | 选项 |
score | bigint(20) | NULL | 分值 |
answer | varchar(200) | NULL | 正确答案 |
analysis | longtext | NULL | 答案解析 |
type | bigint(20) | NULL | 试题类型 |
sequence | bigint(20) | NULL | 试题排序 |
表4-3 users管理员信息表
字段名 | 数据类型 | 是否允许空 | 字段含义 |
---|---|---|---|
id | bigint(20) | NOT NULL | 编号 |
username | varchar(100) | NULL | 用户名 |
password | varchar(100) | NULL | 密码 |
role | varchar(100) | NULL | 角色 |
addtime | timestamp | NULL | 添加时间 |
表4-4 jiaoshi教师信息表
字段名 | 数据类型 | 是否允许空 | 字段含义 |
---|---|---|---|
id | bigint(20) | NOT NULL | 编号 |
addtime | timestamp | NULL | 添加时间 |
jiaoshizhanghao | varchar(200) | NULL | 教师账号 |
mima | varchar(200) | NULL | 密码 |
jiaoshixingming | varchar(200) | NULL | 教师姓名 |
nianling | varchar(200) | NULL | 年龄 |
zhuanye | varchar(200) | NULL | 专业 |
banji | varchar(200) | NULL | 班级 |
xingbie | varchar(200) | NULL | 性别 |
shouji | varchar(200) | NULL | 手机 |
zhaopian | varchar(200) | NULL | 照片 |
表4-5 xuesheng学生信息表
字段名 | 数据类型 | 是否允许空 | 字段含义 |
---|---|---|---|
id | bigint(20) | NOT NULL | 编号 |
addtime | timestamp | NULL | 添加时间 |
xuehao | varchar(200) | NULL | 学号 |
mima | varchar(200) | NULL | 密码 |
xingming | varchar(200) | NULL | 姓名 |
xingbie | varchar(200) | NULL | 性别 |
nianling | int(11) | NULL | 年龄 |
shouji | varchar(200) | NULL | 手机 |
zhaopian | varchar(200) | NULL | 照片 |
5 系统的实现
5.1登录模块的实现
用户要想进入本系统必须进行管理操作,在登录界面输入用户名和密码,选择登录角色,点击登录按钮进行登录系统,系统登录界面展示如图5-1所示。
图5-1系统登录界面图
5.2学生功能模块的实现
5.2.1 学生注册界面
没有账号的学生可进行注册操作,学生注册界面展示如图5-2所示。
图5-2 学生注册界面图
5.2.2 试卷列表界面
学生登录后可查看试卷信息,并可选择试卷进行参与考试,试卷列表界面展示如图5-3所示。
图5-3 试卷列表界面图
5.2.3 考试界面
学生通过本平台可进行在线考试,考试界面展示如图5-4所示。
图5-4 考试界面图
5.2.4 考试记录界面
学生可查看个人已有考试记录信息,考试记录界面展示如图5-4所示。
图5-5 考试记录界面图
5.2.5 错题本界面
学生能够进入错题本界面查看个人错题信息,错题本界面展示如图5-6所示。
图5-6 错题本界面图
5.3管理员功能模块的实现
5.3.1 学生管理界面
管理在学生管理界面可查看所有学生信息,并可对其进行修改和删除操作,同时也可添加学生信息,学生管理界面展示如图5-7所示。
图5-7 学生管理界面图
5.3.2 教师管理界面
管理员可增删改查教师信息,教师管理界面展示如图5-8所示。
图5-8 教师管理界面图
5.4教师功能模块的实现
5.4.1 教师注册界面
没有账号的教师可进行注册操作,教师注册界面展示如图5-9所示。
图5-9 教师注册界面图
5.4.2 试卷管理界面
教师登录后可增删改查试卷信息,试卷管理界面如图5-10所示。
图5-10 试卷管理界面图
图5-11 添加试卷界面图
5.4.3 试题管理界面
教师可增删改查试题信息,试题管理界面展示如图5-12所示,添加试题界面展示如图5-13所示。
图5-12 试题管理界面图
图5-13 添加试题界面图
系统
CommonController.java
package com.controller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
import com.annotation.IgnoreAuth;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.MatchRequest;
import com.baidu.aip.util.Base64Util;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.entity.ConfigEntity;
import com.service.CommonService;
import com.service.ConfigService;
import com.utils.BaiduUtil;
import com.utils.FileUtil;
import com.utils.R;
/**
* 通用接口
*/
@RestController
public class CommonController{
@Autowired
private CommonService commonService;
@Autowired
private ConfigService configService;
private static AipFace client = null;
private static String BAIDU_DITU_AK = null;
@RequestMapping("/location")
public R location(String lng,String lat) {
if(BAIDU_DITU_AK==null) {
BAIDU_DITU_AK = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "baidu_ditu_ak")).getValue();
if(BAIDU_DITU_AK==null) {
return R.error("请在配置管理中正确配置baidu_ditu_ak");
}
}
Map<String, String> map = BaiduUtil.getCityByLonLat(BAIDU_DITU_AK, lng, lat);
return R.ok().put("data", map);
}
/**
* 人脸比对
*
* @param face1 人脸1
* @param face2 人脸2
* @return
*/
@RequestMapping("/matchFace")
public R matchFace(String face1, String face2,HttpServletRequest request) {
if(client==null) {
/*String AppID = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "AppID")).getValue();*/
String APIKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "APIKey")).getValue();
String SecretKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "SecretKey")).getValue();
String token = BaiduUtil.getAuth(APIKey, SecretKey);
if(token==null) {
return R.error("请在配置管理中正确配置APIKey和SecretKey");
}
client = new AipFace(null, APIKey, SecretKey);
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
}
JSONObject res = null;
try {
File file1 = new File(request.getSession().getServletContext().getRealPath("/upload")+"/"+face1);
File file2 = new File(request.getSession().getServletContext().getRealPath("/upload")+"/"+face2);
String img1 = Base64Util.encode(FileUtil.FileToByte(file1));
String img2 = Base64Util.encode(FileUtil.FileToByte(file2));
MatchRequest req1 = new MatchRequest(img1, "BASE64");
MatchRequest req2 = new MatchRequest(img2, "BASE64");
ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
requests.add(req1);
requests.add(req2);
res = client.match(requests);
System.out.println(res.get("result"));
} catch (FileNotFoundException e) {
e.printStackTrace();
return R.error("文件不存在");
} catch (IOException e) {
e.printStackTrace();
}
return R.ok().put("data", com.alibaba.fastjson.JSONObject.parse(res.get("result").toString()));
}
/**
* 获取table表中的column列表(联动接口)
* @param table
* @param column
* @return
*/
@IgnoreAuth
@RequestMapping("/option/{tableName}/{columnName}")
public R getOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName,String level,String parent) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("table", tableName);
params.put("column", columnName);
if(StringUtils.isNotBlank(level)) {
params.put("level", level);
}
if(StringUtils.isNotBlank(parent)) {
params.put("parent", parent);
}
List<String> data = commonService.getOption(params);
return R.ok().put("data", data);
}
/**
* 根据table中的column获取单条记录
* @param table
* @param column
* @return
*/
@IgnoreAuth
@RequestMapping("/follow/{tableName}/{columnName}")
public R getFollowByOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, @RequestParam String columnValue) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("table", tableName);
params.put("column", columnName);
params.put("columnValue", columnValue);
Map<String, Object> result = commonService.getFollowByOption(params);
return R.ok().put("data", result);
}
/**
* 修改table表的sfsh状态
* @param table
* @param map
* @return
*/
@RequestMapping("/sh/{tableName}")
public R sh(@PathVariable("tableName") String tableName, @RequestBody Map<String, Object> map) {
map.put("table", tableName);
commonService.sh(map);
return R.ok();
}
/**
* 获取需要提醒的记录数
* @param tableName
* @param columnName
* @param type 1:数字 2:日期
* @param map
* @return
*/
@IgnoreAuth
@RequestMapping("/remind/{tableName}/{columnName}/{type}")
public R remindCount(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName,
@PathVariable("type") String type,@RequestParam Map<String, Object> map) {
map.put("table", tableName);
map.put("column", columnName);
map.put("type", type);
if(type.equals("2")) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date remindStartDate = null;
Date remindEndDate = null;
if(map.get("remindstart")!=null) {
Integer remindStart = Integer.parseInt(map.get("remindstart").toString());
c.setTime(new Date());
c.add(Calendar.DAY_OF_MONTH,remindStart);
remindStartDate = c.getTime();
map.put("remindstart", sdf.format(remindStartDate));
}
if(map.get("remindend")!=null) {
Integer remindEnd = Integer.parseInt(map.get("remindend").toString());
c.setTime(new Date());
c.add(Calendar.DAY_OF_MONTH,remindEnd);
remindEndDate = c.getTime();
map.put("remindend", sdf.format(remindEndDate));
}
}
int count = commonService.remindCount(map);
return R.ok().put("count", count);
}
/**
* 单列求和
*/
@IgnoreAuth
@RequestMapping("/cal/{tableName}/{columnName}")
public R cal(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("table", tableName);
params.put("column", columnName);
Map<String, Object> result = commonService.selectCal(params);
return R.ok().put("data", result);
}
/**
* 分组统计
*/
@IgnoreAuth
@RequestMapping("/group/{tableName}/{columnName}")
public R group(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("table", tableName);
params.put("column", columnName);
List<Map<String, Object>> result = commonService.selectGroup(params);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for(Map<String, Object> m : result) {
for(String k : m.keySet()) {
if(m.get(k) instanceof Date) {
m.put(k, sdf.format((Date)m.get(k)));
}
}
}
return R.ok().put("data", result);
}
/**
* (按值统计)
*/
@IgnoreAuth
@RequestMapping("/value/{tableName}/{xColumnName}/{yColumnName}")
public R value(@PathVariable("tableName") String tableName, @PathVariable("yColumnName") String yColumnName, @PathVariable("xColumnName") String xColumnName) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("table", tableName);
params.put("xColumn", xColumnName);
params.put("yColumn", yColumnName);
List<Map<String, Object>> result = commonService.selectValue(params);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for(Map<String, Object> m : result) {
for(String k : m.keySet()) {
if(m.get(k) instanceof Date) {
m.put(k, sdf.format((Date)m.get(k)));
}
}
}
return R.ok().put("data", result);
}
}
UserServiceImpl.java
package com.service.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.dao.UserDao;
import com.entity.UserEntity;
import com.service.UserService;
import com.utils.PageUtils;
import com.utils.Query;
/**
* 系统用户
*/
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
Page<UserEntity> page = this.selectPage(
new Query<UserEntity>(params).getPage(),
new EntityWrapper<UserEntity>()
);
return new PageUtils(page);
}
@Override
public List<UserEntity> selectListView(Wrapper<UserEntity> wrapper) {
return baseMapper.selectListView(wrapper);
}
@Override
public PageUtils queryPage(Map<String, Object> params,
Wrapper<UserEntity> wrapper) {
Page<UserEntity> page =new Query<UserEntity>(params).getPage();
page.setRecords(baseMapper.selectListView(page,wrapper));
PageUtils pageUtil = new PageUtils(page);
return pageUtil;
}
}
ExamrecordServiceImpl.java
package com.service.impl;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.List;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.utils.PageUtils;
import com.utils.Query;
import com.dao.ExamrecordDao;
import com.entity.ExamrecordEntity;
import com.service.ExamrecordService;
import com.entity.vo.ExamrecordVO;
import com.entity.view.ExamrecordView;
@Service("examrecordService")
public class ExamrecordServiceImpl extends ServiceImpl<ExamrecordDao, ExamrecordEntity> implements ExamrecordService {
@Override
public PageUtils queryPageGroupBy(Map<String, Object> params, Wrapper<ExamrecordEntity> wrapper) {
Page<ExamrecordView> page =new Query<ExamrecordView>(params).getPage();
page.setRecords(baseMapper.selectGroupBy(page,wrapper));
PageUtils pageUtil = new PageUtils(page);
return pageUtil;
}
@Override
public PageUtils queryPage(Map<String, Object> params) {
Page<ExamrecordEntity> page = this.selectPage(
new Query<ExamrecordEntity>(params).getPage(),
new EntityWrapper<ExamrecordEntity>()
);
return new PageUtils(page);
}
@Override
public PageUtils queryPage(Map<String, Object> params, Wrapper<ExamrecordEntity> wrapper) {
Page<ExamrecordView> page =new Query<ExamrecordView>(params).getPage();
page.setRecords(baseMapper.selectListView(page,wrapper));
PageUtils pageUtil = new PageUtils(page);
return pageUtil;
}
@Override
public List<ExamrecordVO> selectListVO(Wrapper<ExamrecordEntity> wrapper) {
return baseMapper.selectListVO(wrapper);
}
@Override
public ExamrecordVO selectVO(Wrapper<ExamrecordEntity> wrapper) {
return baseMapper.selectVO(wrapper);
}
@Override
public List<ExamrecordView> selectListView(Wrapper<ExamrecordEntity> wrapper) {
return baseMapper.selectListView(wrapper);
}
@Override
public ExamrecordView selectView(Wrapper<ExamrecordEntity> wrapper) {
return baseMapper.selectView(wrapper);
}
}
question-add-or-update.vue
<template>
<div>
<el-form
class="detail-form-content"
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="80px"
>
<el-form-item label="选择试卷" prop="paperid">
<el-select @change="onPaperChange" v-model="ruleForm.paperid" placeholder="选择试卷">
<el-option
v-for="(item,index) in paperOptions"
v-bind:key="index"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="试题" prop="questionname">
<el-input
style="width:600px;"
type="textarea"
min="1"
v-model="ruleForm.questionname"
placeholder="试题"
clearable
></el-input>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select @change="typeChange" v-model="ruleForm.type" placeholder="类型">
<el-option label="单选题" value="0"></el-option>
<el-option label="多选题" value="1"></el-option>
<el-option label="判断题" value="2"></el-option>
<el-option label="填空题" value="3"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="ruleForm.type!=3&&ruleForm.type!=2" label="选项" prop="options">
<div class="options" v-for="(item,index) in options" v-bind:key="index">
{{item.text}}
<el-button size="mini" @click="deleteOptions(index)" type="warning" round>删除</el-button>
</div>
<el-button size="small" @click="addOptionsDialog" type="primary" round>添加选项</el-button>
</el-form-item>
<el-form-item v-if="ruleForm.type==0 && options.length>0" label="答案" prop="answer">
<el-select v-model="ruleForm.answer">
<el-option
:label="item.code"
:value="item.code"
v-for="(item,index) in options"
v-bind:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="ruleForm.type==1 && options.length>0" label="答案" prop="answer">
<el-select v-model="ruleForm.answer" multiple>
<el-option
:label="item.code"
:value="item.code"
v-for="(item,index) in options"
v-bind:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="ruleForm.type==2 && options.length>0" label="答案" prop="answer">
<el-select v-model="ruleForm.answer">
<el-option
:label="item.text"
:value="item.code"
v-for="(item,index) in options"
v-bind:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="ruleForm.type==3" label="答案" prop="answer">
<el-input v-model="ruleForm.answer" placeholder="答案" clearable></el-input>
</el-form-item>
<el-form-item label="分数" prop="score">
<el-input-number v-model="ruleForm.score" :min="1" :max="100" label="分数"></el-input-number>
</el-form-item>
<el-form-item label="分析" prop="analysis">
<el-input
style="width:600px;"
type="textarea"
min="1"
v-model="ruleForm.analysis"
placeholder="分析"
clearable
></el-input>
</el-form-item>
<el-form-item label="排序" prop="sequence">
<el-input-number v-model="ruleForm.sequence" :min="1" :max="20" label="排序"></el-input-number>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button @click="back()">取消</el-button>
</el-form-item>
</el-form>
<el-dialog title="添加选项" :visible.sync="addOptionsDialogVisiable" width="50%">
<el-form ref="dialogForm" :model="dialogForm" :rules="dialogRules" label-width="80px">
<el-form-item label="选项" prop="code">
<el-select v-model="dialogForm.code" placeholder="选项">
<el-option label="A" value="A"></el-option>
<el-option label="B" value="B"></el-option>
<el-option label="C" value="C"></el-option>
<el-option label="D" value="D"></el-option>
</el-select>
</el-form-item>
<el-form-item label="内容" prop="text">
<el-input type="textarea" min="1" v-model="dialogForm.text" placeholder="内容" clearable></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addOptionsDialogVisiable = false">取 消</el-button>
<el-button type="primary" @click="addOptions">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { isNumber } from "@/utils/validate";
export default {
data() {
var validateNumber = (rule, value, callback) => {
if (!isNumber(value)) {
callback(new Error("请输入数字"));
} else {
callback();
}
};
return {
ruleForm: {},
options: [],
addOptionsDialogVisiable: false,
dialogForm: {},
paperOptions: [],
dialogRules: {
text: [{ required: true, message: "请填写内容", trigger: "blur" }],
code: [{ required: true, message: "请选择选项", trigger: "blur" }]
},
rules: {
paperid: [{ required: true, message: "请选择试卷", trigger: "blur" }],
questionname: [
{ required: true, message: "试题内容不能为空", trigger: "blur" }
],
type: [{ required: true, message: "请选择试题类型", trigger: "blur" }],
sequence: [{ required: true, message: "排序不能为空", trigger: "blur" }],
analysis: [
{ required: true, message: "分析不能为空", trigger: "blur" }
],
score: [{ required: true, message: "分数不能为空", trigger: "blur" }]
}
};
},
props: ["parent"],
methods: {
// 初始化
init(id) {
if (id) {
this.info(id);
} else {
this.$http({
url: this.$api.exampaperpage,
method: "get",
params: {
page: 1,
limit: 999
}
}).then(({ data }) => {
if (data && data.code === 0) {
this.paperOptions = data.data.list;
}
});
this.ruleForm.created = new Date();
}
},
info(id) {
this.$http({
url: this.$api.exampaperpage,
method: "get",
params: {
page: 1,
limit: 999
}
}).then(({ data }) => {
if (data && data.code === 0) {
this.paperOptions = data.data.list;
this.$http({
url: `${this.$api.examquestioninfo}${id}`,
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.ruleForm = data.data;
this.ruleForm.type = this.ruleForm.type + "";
this.options = JSON.parse(this.ruleForm.options);
if (this.ruleForm.type == 1) {
this.ruleForm.answer = this.ruleForm.answer.split(",");
}
console.log(this.options);
} else {
this.$message.error(data.msg);
}
});
}
});
},
// 提交
onSubmit() {
console.log(this.ruleForm.answer);
// return;
if (!this.options && this.type != 3) {
this.$message.error("请设置选项");
return;
}
if (this.ruleForm.type == 1) {
this.ruleForm.answer = this.ruleForm.answer.join(",");
console.log(this.ruleForm.answer);
}
this.ruleForm.options = JSON.stringify(this.options);
this.$refs["ruleForm"].validate(valid => {
if (valid) {
this.$http({
url: `${
!this.ruleForm.id
? `${this.$api.examquestionsave}`
: `${this.$api.examquestionupdate}`
}`,
method: "post",
data: this.ruleForm
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.parent.showFlag = false;
this.parent.search();
}
});
} else {
this.$message.error(data.msg);
}
});
}
});
},
// 返回
back() {
this.parent.showFlag = false;
},
addOptionsDialog() {
this.addOptionsDialogVisiable = !this.addOptionsDialogVisiable;
},
addOptions() {
this.$refs["dialogForm"].validate(valid => {
if (valid) {
this.options.push({
text: this.dialogForm.code + "." + this.dialogForm.text,
code: this.dialogForm.code
});
this.dialogForm = {};
this.addOptionsDialogVisiable = !this.addOptionsDialogVisiable;
}
});
},
deleteOptions(index) {
console.log(index);
this.options.splice(index, 1);
},
onPaperChange(e) {
console.log(e);
for (let item of this.paperOptions) {
if (item.id == e) {
// console.log(item.name)
this.ruleForm.papername = item.name;
}
}
},
typeChange(e) {
console.log(e);
if (e == 2) {
this.options = [];
this.options.push({
text: "A.对",
code: "A"
});
this.options.push({
text: "B.错",
code: "B"
});
} else {
this.options = [];
}
}
}
};
</script>
<style lang="scss" scoped>
.editor {
height: 500px;
}
.options {
margin-bottom: 10px;
display: flex;
justify-content: space-between;
width: 200px;
}
</style>
声明
本博客适用于广泛的学术和教育用途,包括但不限于个人学习、开发设计,产品设计。仅供学习参考,旨在为读者提供深入理解和学术研究的材料。