SpringBoot+Vue轻松实现考试管理系统

简介

本系统基于 Spring Boot 搭建的方便易用、高颜值的教学管理平台,提供多租户、权限管理、考试、练习、在线学习等功能。主要功能为在线考试、练习、刷题,在线学习。课程内容支持图文、视频,考试类型支持考试、练习、问卷。

源码下载

网盘链接 密码8418

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

题型支持单选题、多选题、判断题、简答题、视频、语音,题目内容支持图文、视频等。支持题库、刷题功能。

本版本为 Spring Boot 版本,没有太多中间件依赖,使用、部署都非常方便,并且持续更新维护。

架构设计

在这里插入图片描述

功能概述

在这里插入图片描述

项目分 web 前台、后台管理、小程序三部分,前台、小程序主要提供考试功能,后台提供基础管理、考试管理功能。

web 前台主要功能:提供在线考试、课程学习、练习等功能。

后台主要功能:系统管理(单位管理、用户管理、部门管理、角色管理、菜单管理、操作日志、代码生成),考务管理(课程管理、考试管理、题库管理、成绩管理)。

部署指南

1. 新建数据库

我们可以使用 navicat 新建数据库,数据库名可以自定义,字符集和排序规则是确定的。

在这里插入图片描述

2. 运行 SQL 文件

我们导入源码中 init.sql 新建相关表,初始化数据。
在这里插入图片描述

3. 修改配置文件

我们把两个 yml 配置文件复制到 sg-user-service 目录中的 resource 目录中,按需进行修改,比如 MySQL 数据库用户名密码,redis 密码等。

4. 编译 jar 包

我们要检查电脑上是否安装 gradle,运行以下指令测试。

>gradle -v
------------------------------------------------------------
Gradle 8.5
------------------------------------------------------------

Build time:   2023-11-29 14:08:57 UTC        
Revision:     28aca86a7180baa17117e0e5ba01d8ea9feca598

Kotlin:       1.9.20
Groovy:       3.0.17
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          17.0.9 (Oracle Corporation 17.0.9+11-LTS-jvmci-23.0-b21)
OS:           Windows 11 10.0 amd64

我们直接在根目录下运行打包指令,并跳过测试。

gradle build -x test

生成的 jar 包在 build/libs 目录下,运行 java -jar xxx.jar,后端的部署就完成了。

5. 运行前端

我们再进入 frontend/sg-exam-app 目录,运行 npm install 下载依赖,下载完成后运行npm run dev 启动运行。

后台管理项目存放在 frontend/sg-exam-app-admin 目录,运行 pnpm install 下载依赖,下载完成后运行npm run dev 启动运行。

前端部署完成。

代码讲解

下面这段代码是用来展示后台首页数据,其中 userVo 用来查询用户数量,dto 返回给客户端做数据展示功能。

首页数据

/**
	 * 获取管控台首页数据
	 */
	@GetMapping
	@Operation(summary = "后台首页数据展示", description = "后台首页数据展示")
	public R<DashboardDto> dashboard() {
		String tenantCode = SysUtil.getTenantCode();
		DashboardDto dto = new DashboardDto();
		// 查询用户数量
		UserVo userVo = new UserVo();
		userVo.setTenantCode(tenantCode);
		dto.setOnlineUserNumber(userService.userCount(userVo).toString());
		// 租户数量
		dto.setTenantCount(tenantService.tenantCount().toString());
		// 查询考试数量
		ExaminationDashboardDto dashboardDto = examRecordService.findExamDashboardData(tenantCode);
		if (dashboardDto != null) {
			if (dashboardDto.getExaminationCount() != null) {
				dto.setExaminationNumber(dashboardDto.getExaminationCount().toString());
			}
			if (dashboardDto.getExamUserCount() != null) {
				dto.setExamUserNumber(dashboardDto.getExamUserCount().toString());
			}
			if (dashboardDto.getExaminationRecordCount() != null) {
				dto.setExaminationRecordNumber(dashboardDto.getExaminationRecordCount().toString());
			}
		}
		return R.success(dto);
	}

考试管理

这段代码是一个使用Java语言和Spring框架编写的RESTful API控制器。它定义了一系列的HTTP GET和POST请求方法,用于处理与考试信息管理相关的业务逻辑。下面是对这段代码的详细解释:

  1. @Slf4j:这是一个日志注解,用于在控制类中注入一个日志对象,方便记录日志。
  2. @AllArgsConstructor:这是一个Lombok注解,用于自动生成所有字段的构造函数。
  3. @Tag(name = "考试信息管理"):这是一个自定义注解,用于标记这个控制器属于哪个功能模块。
  4. @RestController:表示这是一个RESTful风格的控制器,它将返回JSON格式的数据。

接下来是部分方法的解释:

  • canStart:这个方法通过GET请求方式,提供查询是否能开始考试的功能。它接受一个Long类型的参数id,表示考试的ID。方法内部会查询该ID对应的考试信息,并检查考试是否已经开始,以及是否有结束时间限制。
  • examination:这个方法通过GET请求方式,提供根据考试ID获取考试信息的功能。
  • detail:这个方法通过GET请求方式,提供根据考试ID获取考试详细信息的功能。
  • getMembers:这个方法通过GET请求方式,提供根据考试ID获取考试成员ID的功能。
  • anonymousUserGet:这个方法通过GET请求方式,提供根据考试ID获取考试信息的功能,但是这个方法专门为匿名用户设计。
@Slf4j
@AllArgsConstructor
@Tag(name = "考试信息管理")
@RestController
@RequestMapping("/v1/examination")
public class ExaminationController extends BaseController {

	private final IExaminationService examinationService;

	private final IExamPermissionService examPermissionService;

	@GetMapping("canStart")
	@Operation(summary = "查询是否能开始考试", description = "查询是否能开始考试")
	public R<Boolean> canStart(@RequestParam Long id) {
		boolean canStart = false;
		Examination examination = examinationService.get(id);
		if (examination != null) {
			if (examination.getStartTime() != null && examination.getEndTime() != null) {
				long currentMillis = System.currentTimeMillis();
				canStart = ((currentMillis > examination.getStartTime().getTime()) && (
						examination.getEndTime().getTime() > currentMillis));
			} else {
				// 没有限制考试时间
				canStart = true;
			}
		}
		return R.success(canStart);
	}

	@GetMapping("/{id}")
	@Operation(summary = "获取考试信息", description = "根据考试 ID 获取考试信息")
	public R<Examination> examination(@PathVariable Long id) {
		return R.success(examinationService.get(id));
	}

	@GetMapping("/{id}/detail")
	@Operation(summary = "获取考试详细信息", description = "根据考试 id 获取考试详细信息")
	public R<ExaminationDto> detail(@PathVariable Long id) {
		return R.success(examinationService.getDetail(id));
	}

	@GetMapping("/{id}/getMembers")
	@Operation(summary = "获取考试成员 ID", description = "根据考试 ID 获取考试成员 ID")
	public R<MemberDto> getMembers(@PathVariable Long id) {
		return R.success(examPermissionService.getMembers(ExamConstant.PERMISSION_TYPE_EXAM, id));
	}

	@GetMapping("/anonymousUser/{id}")
	@Operation(summary = "获取考试信息", description = "根据考试 id 获取考试详细信息")
	public R<Examination> anonymousUserGet(@PathVariable Long id) {
		return R.success(examinationService.get(id));
	}

	@GetMapping("examinationList")
	@Operation(summary = "获取考试列表")
	public R<PageInfo<ExaminationDto>> examinationList(@RequestParam Map<String, Object> condition,
			@RequestParam(value = PAGE, required = false, defaultValue = PAGE_DEFAULT) int pageNum,
			@RequestParam(value = PAGE_SIZE, required = false, defaultValue = PAGE_SIZE_DEFAULT) int pageSize) {
		return R.success(examinationService.examinationList(condition, pageNum, pageSize));
	}

	@GetMapping("userExaminationList")
	@Operation(summary = "获取用户有权限的考试列表")
	public R<PageInfo<ExaminationDto>> userExaminationList(@RequestParam Map<String, Object> condition,
			@RequestParam(value = PAGE, required = false, defaultValue = PAGE_DEFAULT) int pageNum,
			@RequestParam(value = PAGE_SIZE, required = false, defaultValue = PAGE_SIZE_DEFAULT) int pageSize) {
		return R.success(examinationService.userExaminationList(condition, pageNum, pageSize));
	}

	@RequestMapping("subjectList")
	@Operation(summary = "获取题目列表")
	public R<PageInfo<SubjectDto>> subjectList(@RequestParam Map<String, Object> condition,
			@RequestParam(value = PAGE, required = false, defaultValue = PAGE_DEFAULT) int pageNum,
			@RequestParam(value = PAGE_SIZE, required = false, defaultValue = PAGE_SIZE_DEFAULT) int pageSize,
			SubjectDto subjectDto) {
		return R.success(examinationService.findSubjectPageById(subjectDto, condition, pageNum, pageSize));
	}

	@PostMapping
	@Operation(summary = "创建考试", description = "创建考试")
	@SgLog(value = "创建考试", operationType = OperationType.INSERT)
	public R<Boolean> add(@RequestBody @Valid ExaminationDto examinationDto) {
		examinationDto.setCommonValue();
		return R.success(examinationService.insertExamination(examinationDto) > 0);
	}

	@PutMapping("{id}")
	@Operation(summary = "更新考试信息", description = "根据考试 ID 更新考试的基本信息")
	@SgLog(value = "更新考试", operationType = OperationType.UPDATE)
	public R<Boolean> update(@PathVariable Long id, @RequestBody @Valid ExaminationDto examinationDto) {
		examinationDto.setId(id);
		examinationDto.setCommonValue();
		return R.success(examinationService.updateExamination(examinationDto) > 0);
	}

	@DeleteMapping("{id}")
	@Operation(summary = "删除考试", description = "根据 ID 删除考试")
	@SgLog(value = "删除考试", operationType = OperationType.DELETE)
	public R<Boolean> delete(@PathVariable Long id) {
		Examination examination = examinationService.get(id);
		if (examination != null) {
			examination.setCommonValue();
			return R.success(examinationService.delete(examination) > 0);
		}
		return R.success(Boolean.FALSE);
	}

	@PostMapping("deleteAll")
	@Operation(summary = "批量删除考试", description = "根据考试 id 批量删除考试")
	@SgLog(value = "删除考试", operationType = OperationType.DELETE)
	public R<Boolean> deleteAll(@RequestBody Long[] ids) {
		return R.success(examinationService.deleteAll(ids) > 0);
	}

	@GetMapping("nexSubjectNo/{id}")
	@Operation(summary = "获取下一题的序号")
	public R<Integer> nexSubjectNo(@PathVariable Long id) {
		return R.success(examinationService.nextSubjectNo(id));
	}

	@PostMapping("batchAddSubjects/{id}")
	@Operation(summary = "批量添加题目")
	@SgLog(value = "批量添加题目", operationType = OperationType.INSERT)
	public R<Boolean> batchAddSubjects(@PathVariable Long id, @RequestBody List<SubjectDto> subjects) {
		return R.success(examinationService.batchAddSubjects(id, subjects));
	}

	@PostMapping("randomAddSubjects/{id}")
	@Operation(summary = "随机添加题目")
	@SgLog(value = "随机添加题目", operationType = OperationType.INSERT)
	public R<Boolean> randomAddSubjects(@PathVariable Long id, @RequestBody RandomSubjectDto params) {
		return R.success(examinationService.randomAddSubjects(id, params));
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/296763.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

程序性能优化全能手册

本文聊一个程序员都会关注的问题&#xff1a;性能。 当大家谈到“性能”时&#xff0c;你首先想到的会是什么&#xff1f; 是每次请求需要多长时间才能返回&#xff1f; 是每秒钟能够处理多少次请求&#xff1f; 还是程序的CPU和内存使用率高不高&#xff1f; 这些问题基本上…

专业实习day3、4(路由器做内网访问公网)

专业实习 代码 display ip interface brief 显示当前设备下所有接口IP undo IP地址支持覆盖&#xff0c;但是正常的命令不能覆盖必须undo&#xff08;删除&#xff09;掉 un in en 在做配置的过程中&#xff0c;设备系统一般都会出现一些提示或者告警之类的东西&#xff0c;从…

打造私域流量的知识付费小程序saas租户平台

当今信息爆炸的时代&#xff0c;知识管理已经成为了每个人必须面对的问题。然而&#xff0c;市面上的知识付费平台大多数都是通用的&#xff0c;无法满足个性化需求。 因此&#xff0c;明理信息科技提供了一款专属定制的适合个人的知识付费平台。核心产品能力如下&#xff1a;…

【kettle】pdi/data-integration 集成kerberos认证连接hdfs、hive或spark thriftserver

一、背景 kerberos认证是比较底层的认证&#xff0c;掌握好了用起来比较简单。 kettle完成kerberos认证后会存储认证信息在jvm中&#xff0c;之后直接连接hive就可以了无需提供额外的用户信息。 spark thriftserver本质就是通过hive jdbc协议连接并运行spark sql任务。 二、…

第12课 利用openCV检测物体是否运动了

FFmpeg与openCV绝对是绝配。前面我们已经基本熟悉了FFmpeg的工作流程&#xff0c;这一章我们重点来看看openCV。 在前面&#xff0c;我们已经使用openCV打开过摄像头并在MFC中显示图像&#xff0c;但openCV能做的要远超你的想像&#xff0c;比如可以用它来实现人脸检测、车牌识…

服务号怎么改为订阅号

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;很多小伙伴想把服务号改为订阅号&#xff0c;但是不知道改了之后具体有什么作用&#xff0c;今天跟大家具体讲解一下。首先我们知道服务号一个月只能发四次文章&#xff0c;但是订阅号每天都可以发…

GLTF编辑器设置3D纺织纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图是一种纹理映射技术&#xff0c;通过改变顶点的位置来模拟细…

掌握人像抠图的艺术:从工具到技巧,完美处理每一细节

在图像的编辑长河中&#xff0c;抠图仿佛一把神奇的画笔&#xff0c;能从画布中提取出我们想要的每一笔&#xff0c;使之与其他画面完美交融。而人像抠图&#xff0c;作为其分支&#xff0c;对精细度的要求更为严格。这需要我们精心提取出人像&#xff0c;使之边缘清晰、无多余…

函数图像化

函数图像化 在进行模型提取时&#xff0c;往往会需要选择拟合的函数&#xff0c;因此&#xff0c;了解函数的图像对于模型拟合提取有益&#xff0c;以下是常见的一些函数的曲线 1 二次函数 常见的耳二次函数曲线&#xff0c;转换x与y数量级差异仅一个数量级&#xff0c; 2 三…

DragonEnglish:COCA20000+单词+释义

去年的时候接触到了 COCA20000 单词&#xff0c;对这种给单词特定顺序的方式蛮感兴趣的。因为我当时接触的版本只有单词或者单词释义的版本&#xff0c;所以我直接通过各种方式给它搭配了音标例句发音&#xff0c;然后每100个切割成1份&#xff0c;分成了 202 个文件来学习&…

C# visual studio COM创建及调用

1.visual studuio操作 1.1visual Studio创建类库项目ClassLibrary1。 1.1.1ClassLibrary1项目Class1.cs内容如下&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.T…

加密的手机号如何模糊查询?

1 一次加载到内存 实现这个功能&#xff0c;我们第一个想到的办法可能是&#xff1a;把个人隐私数据一次性加载到内存中缓存起来&#xff0c;然后在内存中先解密&#xff0c;然后在代码中实现模糊搜索的功能。 这样做的好处是&#xff1a;实现起来比较简单&#xff0c;成本非常…

实习记录留存

0.前提 实习结束了我留个档方便以后查看 校内实习玩具_哔哩哔哩_bilibili 不如这个爽 带兄弟们飙车_哔哩哔哩_bilibili

无心剑七绝《未晚斋》

七绝未晚斋 倏忽半世莫伤怀 醉爱夕阳未晚斋 汉韵唐风情不尽 东华曼舞咏云台 2024年1月6日 新韵四开平韵 《未晚斋》这首诗&#xff0c;作者无心剑以其独特的笔触&#xff0c;描绘出了一幅宁静、淡雅的画面。诗中表达了对生活的热爱和对美好时光的珍惜。 首句“倏忽半世莫伤…

2024阿里云域名优惠口令更新了吗?在哪领取?

2024年阿里云域名优惠口令&#xff0c;com域名续费优惠口令“com批量注册更享优惠”&#xff0c;cn域名续费优惠口令“cn注册多个价格更优”&#xff0c;cn域名注册优惠口令“互联网上的中国标识”&#xff0c;阿里云优惠口令是域名专属的优惠码&#xff0c;可用于域名注册、续…

安装Keras用于影像分割

conda create -n tfkeras2024 python3.9.18 activate tfkeras2024 pip install tensorflow-gpu2.9.0 pip install keras pip install scipy pip install ipykernel ipython python -m ipykernel install --name tfkeras2024 删除环境conda remove -n tfkeras2024 --all

java基于ssm框架的博客系统的开发论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

【2023 CSIG垂直领域大模型】大模型时代,如何完成IDP智能文档处理领域的OCR大一统?

目录 一、像素级OCR统一模型&#xff1a;UPOCR1.1、为什么提出UPOCR&#xff1f;1.2、UPOCR是什么?1.2.1、Unified Paradigm 统一范式1.2.2、Unified Architecture统一架构1.2.3、Unified Training Strategy 统一训练策略 1.3、UPOCR效果如何&#xff1f; 二、OCR大一统模型前…

diffusers加速文生图速度;stable-diffusion、PixArt-α

参考: https://pytorch.org/blog/accelerating-generative-ai-3/ https://colab.research.google.com/drive/1jZ5UZXk7tcpTfVwnX33dDuefNMcnW9ME?usp=sharing#scrollTo=jueYhY5YMe22 大概GPU资源8G-16G;另外模型资源下载慢可以在国内镜像:https://aifasthub.com/ 1、加速…

机器学习股票崩盘预测模型(企业建模_论文科研)AI model for stock crash prediction

对齐颗粒度&#xff0c;打通股票崩盘底层逻辑&#xff0c;形成一套组合拳&#xff0c;形成信用评级机制良性生态圈&#xff0c;重振股市信心&#xff01;--中国股市新展望&#xff01;By Toby&#xff01;2024.1.3 综合介绍 股票崩盘&#xff0c;是指证券市场上由于某种原因&a…