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

news2024/11/20 11:46:03

简介

本系统基于 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));
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法专题六:模拟

一.替换所有的问号 替换所有的问号 1.思路一 class Solution { public:string modifyString(string s) {for(int i0;i<s.size();i){if(s[i] ?){for(char j a ; j<z ; j){//1.注意数组越界if((i0 || s[i-1] ! j) && (is.size()-1 || s[i1] ! j)){s[i] j;brea…

为什么说上了金蝶、用友系统后,下一步是部署BI?

经常有些不熟悉BI工具的用户问我&#xff1a;金蝶、用友系统和BI工具与什么区别&#xff0c;为什么说上了金蝶、用友系统后&#xff0c;下一步就是部署BI&#xff1f;这两个系统工具的功能不重叠吗&#xff1f; 首先&#xff0c;要了解金蝶、用友系统和BI工具的各自作用。 金…

第10课 利用windows API捕获桌面图像并通过FFmpeg分享

在上一章&#xff0c;我们已经实现了一对一音视频对话功能。在实际应用中&#xff0c;我们常需要把自己的电脑桌面分享给他人以实现桌面共享功能&#xff0c;这种功能在视频会议、在线教学等场景中很常见&#xff0c;这种功能如何实现呢&#xff1f;这节课我们就来解决这个问题…

我的小学时代——一段充满乐趣与探索的旅程

我的小学时代——一段充满乐趣与探索的旅程 在我深深的回忆中&#xff0c;小学时代是一段无比珍贵且充满活力与探索的时光&#xff0c;那是我在梓潼路小学度过的五载黄金岁月&#xff0c;从1979年开始&#xff0c;我迈进了那扇标志着人生学习之旅起点的大门。 梓潼路小学作为一…

新一代爬取JavaScript渲染页面的利器-playwright(二)

接上文&#xff1a;新一代爬取JavaScript渲染页面的利器-playwright&#xff08;一&#xff09;   上文我们主要讲了Playwright的特点、安装、基本使用、代码生成的使用以及模拟移动端浏览&#xff0c;这篇我们主要讲下Playwright的选择器以及常见的操作方法。 6.选择器 我们…

使用PowerJob做任务调度模块

最近项目中使用了PowerJob做任务调度模块&#xff0c;感觉这个框架真香&#xff0c;今天我们就来深入了解一下新一代的定时任务框架——PowerJob&#xff01; 简介 PowerJob是基于java开发的企业级的分布式任务调度平台&#xff0c;与xxl-job一样&#xff0c;基于web页面实现…

宽压输入1.5KV隔离直流高压输出电源模块

GRC系列低成本小体积宽电压输入隔离高压模块电源&#xff0c;是一款业界的隔离稳压型DC-DC高电压转换器&#xff0c;可在宽范围波动的不稳定电压输入环境中运行&#xff0c;通过模块的内部调整电路可以生成隔离稳压的直流高电压输出。产品外壳采用铝壳喷塑防腐设计&#xff0c;…

RTU数据采集终端

在现代工业控制系统中&#xff0c;数据采集是一个至关重要的步骤。RTU(远程终端单元)作为一种常用的数据采集终端设备&#xff0c;不仅可以实现数据的采集和传输&#xff0c;还可以实现现场设备的远程监控和控制。 一、RTU数据采集终端的工作原理 RTU数据采集终端是一种将现场…

springboot社区养老服务系统设计与实现

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 研究背景 当…

Spring框架-入门(IOC,DI)

文章目录 Spring框架简介创建Spring项目理解IOC和DI&#xff1a;IOC控制反转示例pom.xmlPerson.javaapplicationContext.xmlPersonTest.java DI依赖注入传统的方式GreetingService.javaGreetingServiceImpl.javaGreetingTest.java 使用DI依赖注入GreetingService.javaGreetingS…

关于系统设计的一些思考

0.前言 当我们站在系统设计的起点&#xff0c;面对一个新的需求&#xff0c;我们该如何开始呢&#xff1f;这是许多处于系统分析与设计领域的新手常常思考的问题。有些人可能会误以为&#xff0c;只要掌握了诸如面向对象、统一建模语言、设计模式、微服务、Serverless、Servic…

电脑视频剪辑软件哪个好用

电脑视频剪辑软件是当今创作者不可或缺的工具之一&#xff0c;它们能够帮助我们在电脑上对视频进行编辑、剪辑、特效添加等操作&#xff0c;使我们的作品更加专业、精美。然而&#xff0c;在众多的视频剪辑软件中&#xff0c;该选择哪一个呢&#xff1f;本文将为你推荐2款非常好…

全网最细,接口+接口自动化测试面试题汇总(附回答)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、我们测试的接口…

vite 如何设置 pwa,让网页类似 app 那样运行,使用插件 vite-plugin-pwa

vite 如何设置 pwa&#xff0c;让网页类似 app 那样运行&#xff0c;使用插件 vite-plugin-pwa 一、概述 情况还是那么个情况&#xff0c;还是原来的项目 vue2 改为 vitetsvue3 遇到的问题&#xff0c;今天这个问题是如何 在 Vite 环境下设置 PWA。 PWA 就是网页应用可以像 a…

驱动芯片,预计未来几年将达到605亿美元的规模

驱动芯片是指驱动显示屏幕幕的芯片&#xff0c;其应用广泛&#xff0c;主要用于电脑、手机、电视、平板电脑和汽车等设备。全球驱动芯片市场分析&#xff1a; 据市场研究预测&#xff0c;未来几年内&#xff0c;全球驱动芯片市场将保持稳定增长&#xff0c;并达到605亿美元的规…

【萤火虫系列教程】2/5-Adobe Firefly 文字​生成​图像

文字​生成​图像 登录账号后&#xff0c;在主页点击文字生成图像的【生成】按钮&#xff0c;进入到文字生成图像 查看图像 在文字生成图像页面&#xff0c;可以看到别人生成的图像。 点击某个图像&#xff0c;就可以进入图像详情&#xff0c;可以看到文字描述。 生成图像 我…

电子化学品,预计2025年会增长到4302亿美元

电子化学品市场是一个庞大的细分市场&#xff0c;它包括了广泛的化学品种类&#xff0c;如涂料、塑料、精细化学品、农药和医药等。这个市场的发展相当迅速&#xff0c;下面我们将从全球市场和中国市场两个方面对其发展趋势进行分析。全球市场分析&#xff1a; 从全球市场的角度…

谷达冠楠:抖店创业初期需要注意哪些

随着互联网的发展&#xff0c;越来越多的人选择通过开设网店来实现创业梦想。而在众多的电商平台中&#xff0c;抖音小店因其独特的社交属性和巨大的流量优势&#xff0c;成为了许多人的首选。然而&#xff0c;抖店创业并非一帆风顺&#xff0c;初期需要注意的问题也不少。以下…

OHC堆外内存

JVM内存模型 先复习一波JVM的内存模型&#xff0c;线程共享的区域为堆、方法区|永久代&#xff0c;线程不共享的区域为栈、程序计数器。 对象创建的整体流程可以用一图描述 内存逃逸 逃逸分析是指分析指针动态范围的方法&#xff0c;它同编译器优化原理的指针分析和外形分析相…

小微企业是如何使用CRM辅助业务的?CRM功能汇总

小企业的成长取决于客户&#xff0c;因此实施有效的CRM管理系统至关重要。曾有数据机构调查发现&#xff0c;每支出1美元用于CRM&#xff0c;您的CRM将带来8、71美元的回报。难怪越来越多的企业实施CRM&#xff0c;因为它带来了高投资回报率。对小企业来说&#xff0c;CRM应该具…