【新增】浏览器、mysql、文件夹判分,监控管理后台接口

This commit is contained in:
YOHO\20373
2025-05-05 00:01:11 +08:00
parent 3a0886b94a
commit a789277819
55 changed files with 3146 additions and 376 deletions

View File

@@ -41,5 +41,10 @@
<option name="name" value="huawei" />
<option name="url" value="https://mirrors.huaweicloud.com/repository/maven/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven-central" />
<option name="name" value="Maven Central Repository" />
<option name="url" value="https://repo1.maven.org/maven2/" />
</remote-repository>
</component>
</project>

8
answerLogBrower.txt Normal file
View File

@@ -0,0 +1,8 @@
=== 学生提交内容stu 目录) ===
-> 文件夹
文件名1.html -> 大小: 397103B, 隐藏: false, 可读: true, 可写: true
文件名2.html -> 大小: 397103B, 隐藏: false, 可读: true, 可写: true
=== 学生提交内容得分点 ===
考点文件名1.html -> 得分权值1-> 是否得分true
考点文件名2.html -> 得分权值1-> 是否得分true
考点百度一下,你就知道 -> 得分权值1-> 是否得分false

23
answerLogFile.txt Normal file
View File

@@ -0,0 +1,23 @@
=== 学生提交内容stu 目录) ===
-> 文件夹
AHEWL -> 文件夹
AHEWL\KMENS -> 文件夹
AHEWL\MENS.EXE -> 大小: 17B, 隐藏: false, 可读: true, 可写: true
BNPA -> 文件夹
BNPA\RONGHE.COM -> 大小: 17B, 隐藏: false, 可读: true, 可写: true
EDZK -> 文件夹
EDZK\RONGHE.COM -> 大小: 17B, 隐藏: false, 可读: true, 可写: true
HGACYL -> 文件夹
HGACYL\PLAY.MEM -> 大小: 17B, 隐藏: false, 可读: true, 可写: true
TING -> 文件夹
TING\XYU -> 文件夹
WUE -> 文件夹
WUE\PB6.txt -> 大小: 17B, 隐藏: false, 可读: true, 可写: false
XEPO -> 文件夹
=== 学生提交内容得分点 ===
HGACYL\RLQM.MEM -> 考察删除 -> 得分权值1-> 是否得分true
TING\XYU\AUTOE.BAT -> 考察删除 -> 得分权值1-> 是否得分true
AHEWL\KMENS -> 考察名称 -> 得分权值1-> 是否得分true
EDZK\RONGHE.COM -> 考察名称 -> 得分权值1-> 是否得分true
HGACYL\PLAY.MEM -> 考察名称 -> 得分权值1-> 是否得分true
WUE\PB6.txt -> 考察名称 -> 得分权值1-> 是否得分true

308
answerLogMysql.txt Normal file
View File

@@ -0,0 +1,308 @@
==================插入语句==================
表名t_team
✅新增语句得分: 4
==================更新语句==================
✅修改语句得分: 3
==================视图语句==================
执行视图 v_education_aad91eecf6954d24a249f86bd2271b17 的查询结果:
列名:
themeName
description
teamName
earnedScore
未来实验室
关闭核反应堆
穿梭队
325
未来实验室
破解AI主机的密码
穿梭队
225
未来实验室
修复电力系统
穿梭队
165
古墓谜影
打开青铜棺椁的暗锁
探险队
325
古墓谜影
破解八卦阵机关
探险队
210
古墓谜影
寻找古墓入口的玉佩
探险队
110
民国悬案
解开保险箱的摩斯密码
侦探队
310
民国悬案
调查凶案现场的日记本
侦探队
225
执行视图 v_education_2_742b43462b1e45d797daa825ed1bb490 的查询结果:
列名:
themeName
description
teamName
earnedScore
未来实验室
关闭核反应堆
穿梭队
325
未来实验室
破解AI主机的密码
穿梭队
225
未来实验室
修复电力系统
穿梭队
165
古墓谜影
打开青铜棺椁的暗锁
探险队
325
古墓谜影
破解八卦阵机关
探险队
210
古墓谜影
寻找古墓入口的玉佩
探险队
110
民国悬案
解开保险箱的摩斯密码
侦探队
310
民国悬案
调查凶案现场的日记本
侦探队
225
是否结果等价: true
✅等价视图语句得分为: 6
==================删除语句==================
提取出的表名: t_room
提取出的条件: roomId = 5
验证 SQL: SELECT COUNT(*) FROM t_room WHERE roomId = 5
验证通过:符合 DELETE 条件的记录已删除。
✅删除正确最终得分: 3
==================查找语句==================
执行考生答案的查询结果:
列名:
超时任务描述
实际得分
基础分
破解AI主机的密码
225
250
关闭核反应堆
325
350
指认真凶
0
400
执行正确答案的查询结果:
列名:
实际得分
超时任务描述
基础分
225
破解AI主机的密码
250
325
关闭核反应堆
350
0
指认真凶
400
是否结果等价: true
✅当前查询SQL得分为3
执行考生答案的查询结果:
列名:
任务描述
队伍名称
指认真凶
侦探队
执行正确答案的查询结果:
列名:
任务描述
队伍名称
指认真凶
侦探队
是否结果等价: true
✅当前查询SQL得分为3
==================触发器语句==================
考生答案与标准答案语句内容一致(忽略格式)
✅触发器得分点8
==================储存过程==================
测试语句CALL pro_getMaxScore('古墓');
测试语句CALL pro_getMaxScore('古墓');
执行 SQL 语句时发生错误: PROCEDURE pro_getMaxScore already exists
==== 标准答案 ====
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
==== 考生答案 ====
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
两个结果集内容一致(不考虑顺序)!
考生答案与标准答案语句结果为:true
✅存储过程得分9
==================插入语句==================
表名t_team
✅新增语句得分: 4
==================更新语句==================
✅修改语句得分: 3
==================视图语句==================
执行视图 v_education_61a0be43eafd4ddeb267eab989db482d 的查询结果:
列名:
themeName
description
teamName
earnedScore
未来实验室
关闭核反应堆
穿梭队
325
未来实验室
破解AI主机的密码
穿梭队
225
未来实验室
修复电力系统
穿梭队
165
古墓谜影
打开青铜棺椁的暗锁
探险队
325
古墓谜影
破解八卦阵机关
探险队
210
古墓谜影
寻找古墓入口的玉佩
探险队
110
民国悬案
解开保险箱的摩斯密码
侦探队
310
民国悬案
调查凶案现场的日记本
侦探队
225
执行视图 v_education_2_13a7c1a8c1d540a4ab247934fbd5b46d 的查询结果:
列名:
themeName
description
teamName
earnedScore
未来实验室
关闭核反应堆
穿梭队
325
未来实验室
破解AI主机的密码
穿梭队
225
未来实验室
修复电力系统
穿梭队
165
古墓谜影
打开青铜棺椁的暗锁
探险队
325
古墓谜影
破解八卦阵机关
探险队
210
古墓谜影
寻找古墓入口的玉佩
探险队
110
民国悬案
解开保险箱的摩斯密码
侦探队
310
民国悬案
调查凶案现场的日记本
侦探队
225
是否结果等价: true
✅等价视图语句得分为: 6
==================删除语句==================
提取出的表名: t_room
提取出的条件: roomId = 5
验证 SQL: SELECT COUNT(*) FROM t_room WHERE roomId = 5
验证通过:符合 DELETE 条件的记录已删除。
✅删除正确最终得分: 3
==================查找语句==================
执行考生答案的查询结果:
列名:
超时任务描述
实际得分
基础分
破解AI主机的密码
225
250
关闭核反应堆
325
350
指认真凶
0
400
执行正确答案的查询结果:
列名:
实际得分
超时任务描述
基础分
225
破解AI主机的密码
250
325
关闭核反应堆
350
0
指认真凶
400
是否结果等价: true
✅当前查询SQL得分为3
执行考生答案的查询结果:
列名:
任务描述
队伍名称
指认真凶
侦探队
执行正确答案的查询结果:
列名:
任务描述
队伍名称
指认真凶
侦探队
是否结果等价: true
✅当前查询SQL得分为3
==================触发器语句==================
考生答案与标准答案语句内容一致(忽略格式)
✅触发器得分点8
==================储存过程==================
测试语句CALL pro_getMaxScore('古墓');
测试语句CALL pro_getMaxScore('古墓');
执行 SQL 语句时发生错误: PROCEDURE pro_getMaxScore already exists
==== 标准答案 ====
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
==== 考生答案 ====
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
{队伍名称=探险队, 房间名称=古墓谜影, 总用时=51, 总得分=645}
两个结果集内容一致(不考虑顺序)!
考生答案与标准答案语句结果为:true
✅存储过程得分9

View File

@@ -0,0 +1,33 @@
package pc.exam.pp.module.exam.controller.admin.getpoints;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.exam.service.getpoints.ExamGetPointsService;
import java.io.IOException;
@RestController
@RequestMapping("/exam/getopints")
public class GetPointsController {
@Autowired
private ExamGetPointsService examGetPointsService;
/**
* 得出文件操作考点
* @return 得分
*/
@PostMapping("/get_filePoint")
//todo 后期需要素材文件和答案文件的 父目录 如D:/exam/3/shucai,D:/exam/3/win
public CommonResult get_file_point() throws IOException {
return CommonResult.success(examGetPointsService.get_file_point());
}
@PostMapping("/get_mysql_point")
//todo 后期需要素材文件和答案文件的 父目录 如D:/exam/3/shucai,D:/exam/3/win
public CommonResult get_mysql_point() throws IOException {
return CommonResult.success(examGetPointsService.get_mysql_point());
}
}

View File

@@ -0,0 +1,109 @@
package pc.exam.pp.module.exam.controller.admin.monitor;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.io.IOException;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import static pc.exam.pp.framework.common.pojo.CommonResult.error;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog;
import static pc.exam.pp.framework.apilog.core.enums.OperateTypeEnum.*;
import pc.exam.pp.module.exam.controller.admin.monitor.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
import pc.exam.pp.module.exam.service.monitor.MonitorService;
@Tag(name = "管理后台 - 监控管理")
@RestController
@RequestMapping("/exam/monitor")
@Validated
public class MonitorController {
@Resource
private MonitorService monitorService;
@PostMapping("/create")
@Operation(summary = "创建监控管理")
public CommonResult<String> createMonitor(@Valid @RequestBody MonitorSaveReqVO createReqVO) {
return success(monitorService.createMonitor(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新监控管理")
public CommonResult<Boolean> updateMonitor(@Valid @RequestBody MonitorSaveReqVO updateReqVO) {
monitorService.updateMonitor(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除监控管理")
@Parameter(name = "id", description = "编号", required = true)
public CommonResult<Boolean> deleteMonitor(@RequestParam("id") String id) {
monitorService.deleteMonitor(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得监控管理")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<MonitorRespVO> getMonitor(@RequestParam("id") String id) {
MonitorDO monitor = monitorService.getMonitor(id);
return success(BeanUtils.toBean(monitor, MonitorRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得监控管理分页")
public CommonResult<PageResult<MonitorRespVO>> getMonitorPage(@Valid MonitorPageReqVO pageReqVO) {
PageResult<MonitorDO> pageResult = monitorService.getMonitorPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, MonitorRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出监控管理 Excel")
@ApiAccessLog(operateType = EXPORT)
public void exportMonitorExcel(@Valid MonitorPageReqVO pageReqVO, HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<MonitorDO> list = monitorService.getMonitorPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "监控管理.xls", "数据", MonitorRespVO.class,
BeanUtils.toBean(list, MonitorRespVO.class));
}
@PostMapping("/stuMonitor")
@Operation(summary = "学生端进入考试返回值")
public CommonResult<String> getStuMonitor(@Valid @RequestBody StuMonitorPaperVo stuMonitorPaperVo) {
Boolean stuMonitor = monitorService.getStuMonitor(stuMonitorPaperVo);
if (stuMonitor)
{
return success("进入考试成功");
}
return error(100_200_300,"不在考试时间范围内!");
}
@PostMapping("/stuMonitorQu")
@Operation(summary = "学生端考试过程传试题")
public void updateStuMonitor(@Valid @RequestBody StuMonitorQuVo stuMonitorQuVo) {
monitorService.updateStuMonitor(stuMonitorQuVo);
}
@PostMapping("/endMonitor")
@Operation(summary = "学生端结束考试返回值")
public void endStuMonitor(@Valid @RequestBody StuMonitorPaperEndVo stuMonitorPaperEndVo) {
monitorService.endStuMonitor(stuMonitorPaperEndVo);
}
}

View File

@@ -0,0 +1,51 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import pc.exam.pp.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 监控管理分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MonitorPageReqVO extends PageParam {
@Schema(description = "用户账号", example = "芋艿")
private String username;
@Schema(description = "用户姓名", example = "赵六")
private String nickname;
@Schema(description = "班级", example = "芋艿")
private String className;
@Schema(description = "考试状态", example = "2")
private String examStatus;
@Schema(description = "成绩")
private String score;
@Schema(description = "试卷编号")
private String paperNum;
@Schema(description = "场次", example = "赵六")
private String taskName;
@Schema(description = "机器ip")
private String ip;
@Schema(description = "剩余时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] remainingTime;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,58 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 监控管理 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MonitorRespVO {
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19828")
@ExcelProperty("主键id")
private String monitorId;
@Schema(description = "用户账号", example = "芋艿")
@ExcelProperty("用户账号")
private String username;
@Schema(description = "用户姓名", example = "赵六")
@ExcelProperty("用户姓名")
private String nickname;
@Schema(description = "班级", example = "芋艿")
@ExcelProperty("班级")
private String className;
@Schema(description = "考试状态", example = "2")
@ExcelProperty("考试状态")
private String examStatus;
@Schema(description = "成绩")
@ExcelProperty("成绩")
private String score;
@Schema(description = "试卷编号")
@ExcelProperty("试卷编号")
private String paperNum;
@Schema(description = "场次", example = "赵六")
@ExcelProperty("场次")
private String taskName;
@Schema(description = "机器ip")
@ExcelProperty("机器ip")
private String ip;
@Schema(description = "剩余时间")
@ExcelProperty("剩余时间")
private LocalDateTime remainingTime;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,43 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import jakarta.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 监控管理新增/修改 Request VO")
@Data
public class MonitorSaveReqVO {
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19828")
private String monitorId;
@Schema(description = "用户账号", example = "芋艿")
private String username;
@Schema(description = "用户姓名", example = "赵六")
private String nickname;
@Schema(description = "班级", example = "芋艿")
private String className;
@Schema(description = "考试状态", example = "2")
private String examStatus;
@Schema(description = "成绩")
private String score;
@Schema(description = "试卷编号")
private String paperNum;
@Schema(description = "场次", example = "赵六")
private String taskName;
@Schema(description = "机器ip")
private String ip;
@Schema(description = "剩余时间")
private LocalDateTime remainingTime;
}

View File

@@ -0,0 +1,14 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 监控管理 学生结束考试 Request VO")
@Data
public class StuMonitorPaperEndVo {
private String stuId;
private String score;
private String taskId;
}

View File

@@ -0,0 +1,18 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 监控管理 学生进入考试 Request VO")
@Data
public class StuMonitorPaperVo {
private String stuId;
private String paperId;
private String ip;
private String taskId;
}

View File

@@ -0,0 +1,24 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import jdk.dynalink.linker.LinkerServices;
import lombok.Data;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperScheme;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class StuMonitorQuVo {
private String stuId;
private String paperId;
private String taskId;
private List<EducationPaperSchemeMap> paperSchemeMaps; // 使用自定义类
private String score;
@Data
public static class EducationPaperSchemeMap {
private EducationPaperScheme educationPaperScheme;
private Map<String, Boolean> questionResultMap;
}
}

View File

@@ -5,9 +5,12 @@ import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.module.exam.controller.admin.paper.dto.SessionParamDto;
import pc.exam.pp.module.exam.controller.admin.paper.dto.StatusDto;
import pc.exam.pp.module.exam.controller.admin.paper.vo.EducationPaperSessionVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperTask;
import pc.exam.pp.module.exam.service.paper.IEducationPaperSessionService;
import java.util.Date;
@@ -32,9 +35,9 @@ public class EducationPaperSessionController
* 查询试卷场次列表
*/
@GetMapping("/list")
public CommonResult list(EducationPaperSession educationPaperSession)
public CommonResult<PageResult<EducationPaperSession>> list(EducationPaperSessionVo educationPaperSessionVo)
{
List<EducationPaperSession> list = educationPaperSessionService.selectEducationPaperSessionList(educationPaperSession);
PageResult<EducationPaperSession> list = educationPaperSessionService.selectEducationPaperSessionList(educationPaperSessionVo);
return CommonResult.success(list);
}

View File

@@ -0,0 +1,52 @@
package pc.exam.pp.module.exam.controller.admin.paper.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import pc.exam.pp.framework.common.pojo.PageParam;
import java.util.Date;
@Schema(description = "试卷场次vo")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class EducationPaperSessionVo extends PageParam {
/** 主键ID */
private String sessionId;
/** 试卷任务ID */
// @Excel(name = "试卷任务ID")
private String taskId;
/** 批次 */
// @Excel(name = "批次")
private String batch;
/** 考试开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
// @Excel(name = "考试开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/** 考试结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//@Excel(name = "考试结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/** 开始考试前分钟,允许入场 */
// @Excel(name = "开始考试前分钟,允许入场")
private String allowEntry;
/** 开始考试后分钟,禁止入场 */
// @Excel(name = "开始考试后分钟,禁止入场")
private String endAllowEntry;
/** 开始考试后分钟,允许交卷 */
// @Excel(name = "开始考试后分钟,允许交卷")
private String allowSubmission;
/** 0启用1不启 */
// @Excel(name = "0启用1不启")
private String status;
}

View File

@@ -31,6 +31,7 @@ public class EducationPaper extends TenantBaseDO
// @Excel(name = "试卷任务ID")
private String taskId;
private String num;
/** 使用次数 */
// @Excel(name = "使用次数")
private String counts;

View File

@@ -1,6 +1,7 @@
package pc.exam.pp.module.exam.dal.dataobject;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -32,6 +33,9 @@ public class EducationPaperScheme
// @Excel(name = "方案ID")
private String taskId;
//题型标题别名
private String quTitle;
/** 题型 */
// @Excel(name = "题型")
private String spName;
@@ -56,6 +60,8 @@ public class EducationPaperScheme
// @Excel(name = "每题分数")
private String quScores;
private String sort;
@TableField(exist = false)
private List<String> keyword;

View File

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.experimental.Accessors;
import org.joda.time.DateTime;
import java.util.Date;
@@ -34,12 +35,12 @@ public class EducationPaperSession
private String batch;
/** 考试开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
// @Excel(name = "考试开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/** 考试结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
//@Excel(name = "考试结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date endTime;

View File

@@ -31,7 +31,7 @@ public class ExamQuestion extends TenantBaseDO {
/** 题库id */
// @Excel(name = "题库id")
private String quBankId;
private String quBankId;
/** 题库名称 */
// @Excel(name = "题库名称")

View File

@@ -3,8 +3,10 @@ package pc.exam.pp.module.exam.dal.dataobject;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
@@ -18,6 +20,8 @@ import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
@TableName(value = "exam_question_keyword", autoResultMap = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ExamQuestionKeyword
{
private static final long serialVersionUID = 1L;

View File

@@ -1,42 +1,16 @@
package pc.exam.pp.module.exam.dal.dataobject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PaperListResponseVo {
private List<String> paperId; // 试卷列表
private Map<String, String> paperId; // 试卷ID和名称键值对
private Set<String> selectedIds; // 已选试卷 ID 列表
public PaperListResponseVo() {
}
public PaperListResponseVo(List<String> paperId, Set<String> selectedIds) {
this.paperId = paperId;
this.selectedIds = selectedIds;
}
public List<String> getPaperId() {
return paperId;
}
public void setPaperId(List<String> paperId) {
this.paperId = paperId;
}
public Set<String> getSelectedIds() {
return selectedIds;
}
public void setSelectedIds(Set<String> selectedIds) {
this.selectedIds = selectedIds;
}
@Override
public String toString() {
return "PaperListResponseVo{" +
"paperId=" + paperId +
", selectedIds=" + selectedIds +
'}';
}
}

View File

@@ -0,0 +1,67 @@
package pc.exam.pp.module.exam.dal.dataobject.monitor;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
/**
* 监控管理 DO
*
* @author 管理员
*/
@TableName("exam_monitor")
@KeySequence("exam_monitor_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MonitorDO extends BaseDO {
/**
* 主键id
*/
@TableId(type = IdType.INPUT)
private String monitorId;
/**
* 用户账号
*/
private String username;
/**
* 用户姓名
*/
private String nickname;
/**
* 班级
*/
private String className;
/**
* 考试状态
*/
private String examStatus;
/**
* 成绩
*/
private String score;
/**
* 试卷编号
*/
private String paperNum;
/**
* 场次
*/
private String taskName;
/**
* 机器ip
*/
private String ip;
/**
* 剩余时间
*/
private Long remainingTime;
}

View File

@@ -0,0 +1,34 @@
package pc.exam.pp.module.exam.dal.mysql.monitor;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
import org.apache.ibatis.annotations.Mapper;
import pc.exam.pp.module.exam.controller.admin.monitor.vo.MonitorPageReqVO;
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
/**
* 监控管理 Mapper
*
* @author 管理员
*/
@Mapper
public interface MonitorMapper extends BaseMapperX<MonitorDO> {
default PageResult<MonitorDO> selectPage(MonitorPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<MonitorDO>()
.likeIfPresent(MonitorDO::getUsername, reqVO.getUsername())
.likeIfPresent(MonitorDO::getNickname, reqVO.getNickname())
.likeIfPresent(MonitorDO::getClassName, reqVO.getClassName())
.eqIfPresent(MonitorDO::getExamStatus, reqVO.getExamStatus())
.eqIfPresent(MonitorDO::getScore, reqVO.getScore())
.eqIfPresent(MonitorDO::getPaperNum, reqVO.getPaperNum())
.likeIfPresent(MonitorDO::getTaskName, reqVO.getTaskName())
.eqIfPresent(MonitorDO::getIp, reqVO.getIp())
.betweenIfPresent(MonitorDO::getRemainingTime, reqVO.getRemainingTime())
.betweenIfPresent(MonitorDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(MonitorDO::getCreateTime));
}
}

View File

@@ -105,7 +105,7 @@ public interface EducationPaperMapper extends BaseMapperX<EducationPaper>
List<String> selectPaperByTaskIdAndRoll(@Param("taskId")String taskId);
List<String> getPaperByTaskIdByType(String taskId);
List<EducationPaper> getPaperByTaskIdByType(String taskId);
String getSelectPaperIdBySchemeIds(String row);
@@ -117,5 +117,9 @@ public interface EducationPaperMapper extends BaseMapperX<EducationPaper>
int changeStatus(@Param("paperId") String paperId
,@Param("status") String status);
int selectCountPaperList();
}

View File

@@ -4,7 +4,13 @@ import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
import pc.exam.pp.module.exam.controller.admin.paper.vo.EducationPaperSessionVo;
import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperTaskPageVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperTask;
/**
* 试卷场次Mapper接口
@@ -13,7 +19,7 @@ import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
* @date 2025-04-17
*/
@Mapper
public interface EducationPaperSessionMapper
public interface EducationPaperSessionMapper extends BaseMapperX<EducationPaperSession>
{
/**
* 查询试卷场次
@@ -29,7 +35,7 @@ public interface EducationPaperSessionMapper
* @param educationPaperSession 试卷场次
* @return 试卷场次集合
*/
public List<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSession educationPaperSession);
/**
* 新增试卷场次
@@ -70,4 +76,18 @@ public interface EducationPaperSessionMapper
int changeStatus(@Param("sessionId") String sessionId
,@Param("status") String status);
default PageResult<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSessionVo pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<EducationPaperSession>()
.likeIfPresent(EducationPaperSession::getStatus , pageReqVO.getStatus())
.likeIfPresent(EducationPaperSession::getBatch , pageReqVO.getBatch())
.likeIfPresent(EducationPaperSession::getEndAllowEntry , pageReqVO.getEndAllowEntry())
.likeIfPresent(EducationPaperSession::getTaskId , pageReqVO.getTaskId())
.likeIfPresent(EducationPaperSession::getAllowSubmission , pageReqVO.getAllowSubmission())
.likeIfPresent(EducationPaperSession::getAllowEntry , pageReqVO.getAllowEntry())
);
}
}

View File

@@ -105,4 +105,8 @@ public interface EducationPaperTaskMapper extends BaseMapperX<EducationPaperTask
boolean changeStatus(@Param("taskId")String taskId,@Param("status") String status);
String selectEducationPaperTaskNameByid(String taskId);
String selectStuClassNameByClassId(Long classId);
}

View File

@@ -69,4 +69,6 @@ public interface SysFileMapper
public List<SysFileUpload> selectSysFileByQuid(String quId);
List<SysFileUpload> selectSysFileByQuidIN(String quId);
}

View File

@@ -0,0 +1,15 @@
package pc.exam.pp.module.exam.service.getpoints;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import java.io.IOException;
import java.util.List;
public interface ExamGetPointsService {
List<ExamQuestionAnswer> get_file_point() throws IOException;
List<ExamQuestionAnswer> get_mysql_point();
}

View File

@@ -0,0 +1,62 @@
package pc.exam.pp.module.exam.service.getpoints;
import org.springframework.stereotype.Service;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.exam.utils.file.GetDifferencesBetweenFolders;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Service
public class ExamGetPointsServiceImpl implements ExamGetPointsService{
static final String BASE_DIR = "D:/exam/3/";
@Override
public List<ExamQuestionAnswer> get_file_point() throws IOException {
List<ExamQuestionAnswer> answerList = new ArrayList<>();
AtomicInteger sortCounter = new AtomicInteger(1); // 计数器
String path1 = BASE_DIR + "shucai";
String path2 = BASE_DIR + "win";
// 获取 shucai 和 win 文件夹的差异
Map<String, String> differences = GetDifferencesBetweenFolders.getDifferencesBetweenFolders(path1, path2);
List<ExamQuestionAnswer> formattedDifferences = differences.entrySet().stream()
.map(entry -> {
String key = entry.getKey();
String value = entry.getValue();
ExamQuestionAnswer answer = new ExamQuestionAnswer();
answer.setContent(key); // 设置文件路径
answer.setScoreRate("1");
//这里设置answer的排序按照循环次数来
answer.setSort(String.valueOf(sortCounter.getAndIncrement())); // 按顺序设置排序值
if (value.startsWith("仅存在于 "+path1)) {
answer.setContentIn("考察删除");
} else if (value.startsWith("仅存在于 "+path2)) {
answer.setContentIn("考察名称");
} else if (value.startsWith("属性不同")) {
answer.setContentIn("考察属性");
// answer.setContent(key + " -> " + value.split(" vs ")[1]); // 设置属性信息
}
return answer;
})
.sorted(Comparator.comparingInt(answer -> Integer.parseInt(answer.getSort()))) // 按 sort 排序
.collect(Collectors.toList());
answerList.addAll(formattedDifferences);
return answerList;
}
@Override
public List<ExamQuestionAnswer> get_mysql_point() {
return null;
}
}

View File

@@ -0,0 +1,59 @@
package pc.exam.pp.module.exam.service.monitor;
import jakarta.validation.*;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.module.exam.controller.admin.monitor.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
/**
* 监控管理 Service 接口
*
* @author 管理员
*/
public interface MonitorService {
/**
* 创建监控管理
*
* @param createReqVO 创建信息
* @return 编号
*/
String createMonitor(@Valid MonitorSaveReqVO createReqVO);
/**
* 更新监控管理
*
* @param updateReqVO 更新信息
*/
void updateMonitor(@Valid MonitorSaveReqVO updateReqVO);
/**
* 删除监控管理
*
* @param id 编号
*/
void deleteMonitor(String id);
/**
* 获得监控管理
*
* @param id 编号
* @return 监控管理
*/
MonitorDO getMonitor(String id);
/**
* 获得监控管理分页
*
* @param pageReqVO 分页查询
* @return 监控管理分页
*/
PageResult<MonitorDO> getMonitorPage(MonitorPageReqVO pageReqVO);
Boolean getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo);
void updateStuMonitor(StuMonitorQuVo stuMonitorQuVo);
void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo);
}

View File

@@ -0,0 +1,226 @@
package pc.exam.pp.module.exam.service.monitor;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.excel.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.json.JsonUtils;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.exam.controller.admin.monitor.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.*;
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
import pc.exam.pp.module.exam.dal.mysql.monitor.MonitorMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.*;
import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper;
import pc.exam.pp.module.exam.utils.uuid.IdUtils;
import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception;
import static pc.exam.pp.module.system.enums.ErrorCodeConstants.MONITOR_NOT_EXISTS;
/**
* 监控管理 Service 实现类
*
* @author 管理员
*/
@Service
@Validated
public class MonitorServiceImpl implements MonitorService {
@Autowired
private RedisTemplate redisTemplate;
@Resource
private MonitorMapper monitorMapper;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private ExamQuestionMapper examQuestionMapper;
@Resource
private EducationPaperMapper educationPaperMapper;
@Resource
private EducationPaperPersonMapper educationPaperPersonMapper;
@Resource
private EducationPaperTaskMapper educationPaperTaskMapper;
@Resource
private EducationPaperParamMapper educationPaperParamMapper;
@Resource
private EducationPaperSessionMapper educationPaperSessionMapper;
@Override
public String createMonitor(MonitorSaveReqVO createReqVO) {
// 插入
MonitorDO monitor = BeanUtils.toBean(createReqVO, MonitorDO.class);
monitorMapper.insert(monitor);
// 返回
return monitor.getMonitorId();
}
@Override
public void updateMonitor(MonitorSaveReqVO updateReqVO) {
// 校验存在
validateMonitorExists(updateReqVO.getMonitorId());
// 更新
MonitorDO updateObj = BeanUtils.toBean(updateReqVO, MonitorDO.class);
monitorMapper.updateById(updateObj);
}
@Override
public void deleteMonitor(String id) {
// 校验存在
validateMonitorExists(id);
// 删除
monitorMapper.deleteById(id);
}
private void validateMonitorExists(String id) {
if (monitorMapper.selectById(id) == null) {
throw exception(MONITOR_NOT_EXISTS);
}
}
@Override
public MonitorDO getMonitor(String id) {
return monitorMapper.selectById(id);
}
@Override
public PageResult<MonitorDO> getMonitorPage(MonitorPageReqVO pageReqVO) {
return monitorMapper.selectPage(pageReqVO);
}
@Override
public Boolean getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo) {
String key = "userCache:"+stuMonitorPaperVo.getTaskId()+":" + stuMonitorPaperVo.getStuId();
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class);
if (StringUtils.isNotBlank(stuMonitorPaperVo.getPaperId())){
EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperVo.getPaperId());
info.setPaperNum(educationPaper.getNum());
}
info.setExamStatus("1");
info.setIp(stuMonitorPaperVo.getIp());
if (info.getRemainingTime()==null){
stringRedisTemplate.opsForValue().set("userCache:"+stuMonitorPaperVo.getTaskId()+":"+stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info));
monitorMapper.insert(info);
return true;
}else {
EducationPaperPerson educationPaperPerson = educationPaperPersonMapper.selectByTaskIdAndPersonId(stuMonitorPaperVo.getTaskId(), stuMonitorPaperVo.getStuId());
EducationPaperSession educationPaperSession = educationPaperSessionMapper.selectEducationPaperSessionBySessionId(educationPaperPerson.getSessionId());
//结束时间
Date endTime = educationPaperSession.getEndTime();
//开始时间
Date startTime = educationPaperSession.getStartTime();
//开始考试前分钟,允许入场
String allowEntry = educationPaperSession.getAllowEntry();
//开始考试后分钟,禁止入场
String endAllowEntry = educationPaperSession.getEndAllowEntry();
LocalDateTime now = LocalDateTime.now();
LocalDateTime start = DateUtil.toLocalDateTime(startTime);
LocalDateTime end = DateUtil.toLocalDateTime(endTime);
// 考试开始前允许入场时间(分钟)
int allowEntryMin = Integer.parseInt(allowEntry);
// 考试开始后允许入场时间(分钟)
int endAllowEntryMin = Integer.parseInt(endAllowEntry);
// 入场允许范围: [start , end + endAllowEntryMin]
LocalDateTime entryEnd = end.plusMinutes(endAllowEntryMin);
boolean isWithinEntryTime = now.isAfter(start) && now.isBefore(entryEnd);
System.out.println("是否在允许入场时间段内:" + isWithinEntryTime);
if (isWithinEntryTime){
long remainingSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(),
DateUtil.toLocalDateTime(endTime));
info.setRemainingTime(remainingSeconds > 0 ? remainingSeconds : 0);
stringRedisTemplate.opsForValue().set("userCache:"+stuMonitorPaperVo.getTaskId()+":"+stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info), remainingSeconds, TimeUnit.SECONDS);
monitorMapper.updateById(info);
return true;
}else {
return false;
}
}
}
@Override
public void updateStuMonitor(StuMonitorQuVo stuMonitorQuVo) {
String key = "userCache:"+stuMonitorQuVo.getTaskId()+":" + stuMonitorQuVo.getStuId();
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class);
if (info != null) {
AtomicInteger totalScore = new AtomicInteger(); // 用于累加总分
// 记录答题结果
List<StuMonitorQuVo.EducationPaperSchemeMap> paperSchemeMaps = stuMonitorQuVo.getPaperSchemeMaps();
for (StuMonitorQuVo.EducationPaperSchemeMap paperSchemeMap : paperSchemeMaps) {
EducationPaperScheme educationPaperScheme = paperSchemeMap.getEducationPaperScheme();
Map<String, Boolean> questionResultMap = paperSchemeMap.getQuestionResultMap();
questionResultMap.forEach((quId, value) -> {
if (value) {
System.out.println("QuestionId: " + quId + ", boolean: " + value);
String quScores = educationPaperScheme.getQuScores();
int score = Integer.parseInt(quScores); // 转换为 int 类型的分数
totalScore.addAndGet(score); // 累加到总分
}
});
}
// 更新成绩这里假设一题10分
info.setScore(String.valueOf(totalScore));
// 更新缓存
redisTemplate.opsForValue().set(key, info);
// monitorMapper.updateById(info);
}
}
@Override
public void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo) {
String key = "userCache:" + stuMonitorPaperEndVo.getTaskId()+":" +stuMonitorPaperEndVo.getStuId();
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class);
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(stuMonitorPaperEndVo.getTaskId());
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(stuMonitorPaperEndVo.getTaskId());
if ("1".equals(educationPaperParam.getSaveGrades())){
info.setScore(stuMonitorPaperEndVo.getScore());
}else {
MonitorDO monitorDO = monitorMapper.selectById(info.getMonitorId());
if (Integer.parseInt(monitorDO.getScore()) <Integer.parseInt(stuMonitorPaperEndVo.getScore())){
info.setScore(stuMonitorPaperEndVo.getScore());
}
}
//练习下的任务 结束改为 代考
if ("0".equals(educationPaperTask.getStatus())){
info.setExamStatus("0");
}else {
info.setExamStatus("2");
redisTemplate.delete(key);
}
monitorMapper.updateById(info);
}
}

View File

@@ -1,25 +1,40 @@
package pc.exam.pp.module.exam.service.paper;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import com.alibaba.excel.util.StringUtils;
import jakarta.annotation.Resource;
import org.apache.poi.hssf.record.DVALRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.json.JsonUtils;
import pc.exam.pp.module.exam.controller.admin.paper.dto.PersonRepDto;
import pc.exam.pp.module.exam.controller.admin.paper.vo.DeleteRequestVo;
import pc.exam.pp.module.exam.controller.admin.paper.vo.SessionStuPageReqVO;
import pc.exam.pp.module.exam.controller.admin.paper.vo.StudentSessionReqVO;
import pc.exam.pp.module.exam.controller.admin.student.vo.StudentPageReqVO;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperPerson;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperTask;
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
import pc.exam.pp.module.exam.dal.dataobject.student.StudentDO;
import pc.exam.pp.module.exam.dal.mysql.monitor.MonitorMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperPersonMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperSessionMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperTaskMapper;
import pc.exam.pp.module.exam.dal.mysql.student.StudentMapper;
import pc.exam.pp.module.exam.utils.uuid.IdUtils;
import pc.exam.pp.module.system.api.user.dto.AdminUserRespDTO;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -33,10 +48,16 @@ public class EducationPaperPersonServiceImpl implements IEducationPaperPersonSer
{
@Autowired
private EducationPaperPersonMapper educationPaperPersonMapper;
@Autowired
private EducationPaperTaskMapper educationPaperTaskMapper;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Autowired
private EducationPaperSessionMapper educationPaperSessionMapper;
@Resource
private MonitorMapper monitorMapper;
@Autowired
private RedisTemplate redisTemplate;
/**
* 查询试卷人员分配
*
@@ -147,8 +168,58 @@ public class EducationPaperPersonServiceImpl implements IEducationPaperPersonSer
existing.setSessionId(sessionId);
existing.setBatch(batch);
educationPaperPersonMapper.updateByTaskIdAndStuId(existing);
//todo 本来没有设置考场的,这里要更新缓存的 剩余时间
EducationPaperSession educationPaperSession = educationPaperSessionMapper.selectEducationPaperSessionBySessionId(sessionId);
String key = "userCache:" + taskId+":"+studentId;
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key),MonitorDO.class);
if (info!=null){
Date startTime = educationPaperSession.getStartTime();
Date endTime = educationPaperSession.getEndTime();
LocalDateTime start = Instant.ofEpochMilli(startTime.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
LocalDateTime end = Instant.ofEpochMilli(endTime.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
long remainingSeconds = ChronoUnit.SECONDS.between(start, end);
info.setRemainingTime(remainingSeconds);
}
// 更新缓存
redisTemplate.opsForValue().set(key, info);
monitorMapper.updateById(info);
} else if (existing == null) {
String name= educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId);
EducationPaperPerson educationPaperPerson=new EducationPaperPerson();
String key = "userCache:" + taskId+":"+studentId;
PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(studentId);
String uuid = IdUtils.simpleUUID();
MonitorDO info = new MonitorDO();
info.setMonitorId(uuid);
info.setUsername(personRepDto.getUsername());
info.setNickname(personRepDto.getNickname());
//设置学生班级
if (StringUtils.isNotBlank(personRepDto.getClassId().toString())){
String className=educationPaperTaskMapper.selectStuClassNameByClassId(personRepDto.getClassId());
info.setClassName(className);
}
info.setExamStatus("0");
info.setScore("0");
info.setPaperNum("");
info.setTaskName(name);
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info));
monitorMapper.insert(info);
educationPaperPerson.setPersonId(studentId);
educationPaperPerson.setSessionId(sessionId);
educationPaperPerson.setBatch(batch);
@@ -172,11 +243,21 @@ public class EducationPaperPersonServiceImpl implements IEducationPaperPersonSer
@Override
public int removeSessionStu(StudentSessionReqVO reqVO) {
List<String> studentIds = reqVO.getStudentIds();
for (String studentId : studentIds) {
String key = "userCache:" + reqVO.getTaskId()+":"+studentId;
redisTemplate.delete(key);
}
return educationPaperPersonMapper.removeSessionStu(reqVO);
}
@Override
public int removeTaskStu(DeleteRequestVo deleteRequestVo) {
List<String> studentIds = deleteRequestVo.getStudentIds();
for (String studentId : studentIds) {
String key = "userCache:" + deleteRequestVo.getTaskId()+":"+studentId;
redisTemplate.delete(key);
}
return educationPaperPersonMapper.removeTaskStu(deleteRequestVo);
}

View File

@@ -6,10 +6,12 @@ import pc.exam.pp.module.exam.controller.admin.paper.vo.ExamPaperVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperQu;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperScheme;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
import pc.exam.pp.module.exam.dal.dataobject.SysFileUpload;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperQuMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperSchemeMapper;
import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper;
import pc.exam.pp.module.exam.dal.mysql.question.SysFileMapper;
import java.util.List;
@@ -30,6 +32,8 @@ public class EducationPaperQuServiceImpl implements IEducationPaperQuService
private ExamQuestionMapper examQuestionMapper;
@Autowired
private EducationPaperSchemeMapper educationPaperSchemeMapper;
@Autowired
private SysFileMapper sysFileMapper;
/**
* 查询试卷试题
*
@@ -108,6 +112,14 @@ public class EducationPaperQuServiceImpl implements IEducationPaperQuService
List<String> quIds =educationPaperQuMapper.selectPaperQuByPaperId(paperId);
List<ExamQuestion> examQuestionList=examQuestionMapper.selectExamQuestionListByQuIds(quIds);
if (examQuestionList!=null&&examQuestionList.size()>0){
for (ExamQuestion examQuestion : examQuestionList) {
//查找原始和素材试题文件
List<SysFileUpload> sysFileUploads =sysFileMapper.selectSysFileByQuidIN(examQuestion.getQuId());
examQuestion.setFileUploads(sysFileUploads);
}
}
String taskid=educationPaperMapper.selectTaskIdByPaperId(paperId);
List<EducationPaperScheme> educationPaperSchemeList= educationPaperSchemeMapper.selectEducationPaperTaskByTaskId(taskid);

View File

@@ -148,11 +148,19 @@ public class EducationPaperServiceImpl implements IEducationPaperService
examQuestionIds.addAll(quId);
}
int number=educationPaperMapper.selectCountPaperList();
// 格式化为8位不足前面补0
String formattedNumber = String.format("%08d", number);
//构建试卷
EducationPaper educationPaper =new EducationPaper();
String uuid = IdUtils.simpleUUID();
educationPaper.setPaperId(uuid);
educationPaper.setTaskId(taskid);
educationPaper.setNum(formattedNumber);
educationPaper.setTenantId(TenantContextHolder.getRequiredTenantId());
educationPaperMapper.insertEducationPaper(educationPaper);
@@ -213,8 +221,15 @@ public class EducationPaperServiceImpl implements IEducationPaperService
//构建返回对象
PaperListResponseVo paperListResponseVo=new PaperListResponseVo();
//查找该方案所有的试卷
List<String> paperByTaskIdByType = educationPaperMapper.getPaperByTaskIdByType(taskId);
paperListResponseVo.setPaperId(paperByTaskIdByType);
List<EducationPaper> paperByTaskIdByType = educationPaperMapper.getPaperByTaskIdByType(taskId);
Map<String, String> paperMap = new HashMap<>();
if (paperByTaskIdByType!=null&&paperByTaskIdByType.size()>0){
for (EducationPaper educationPaper : paperByTaskIdByType) {
paperMap.put(educationPaper.getPaperId(),educationPaper.getNum());
}
}
paperListResponseVo.setPaperId(paperMap);
//
Set<String> selectedIds =new HashSet<>();
//根据选中的方案,查找选中方案下已分配的试卷

View File

@@ -2,6 +2,8 @@ package pc.exam.pp.module.exam.service.paper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.module.exam.controller.admin.paper.vo.EducationPaperSessionVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperPersonMapper;
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperSessionMapper;
@@ -41,7 +43,7 @@ public class EducationPaperSessionServiceImpl implements IEducationPaperSessionS
* @return 试卷场次
*/
@Override
public List<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSession educationPaperSession)
public PageResult<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSessionVo educationPaperSession)
{
return educationPaperSessionMapper.selectEducationPaperSessionList(educationPaperSession);
}

View File

@@ -1,6 +1,8 @@
package pc.exam.pp.module.exam.service.paper;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.module.exam.controller.admin.paper.vo.EducationPaperSessionVo;
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
import java.util.List;
@@ -27,7 +29,7 @@ public interface IEducationPaperSessionService
* @param educationPaperSession 试卷场次
* @return 试卷场次集合
*/
public List<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSession educationPaperSession);
PageResult<EducationPaperSession> selectEducationPaperSessionList(EducationPaperSessionVo educationPaperSession);
/**
* 新增试卷场次

View File

@@ -7,6 +7,7 @@
<resultMap type="EducationPaper" id="EducationPaperResult">
<result property="paperId" column="paper_id" />
<result property="taskId" column="task_id" />
<result property="num" column="num" />
<result property="counts" column="counts" />
<result property="rollUp" column="roll_up" />
<result property="isAb" column="is_ab" />
@@ -47,7 +48,7 @@
<sql id="selectEducationPaperVo">
select paper_id, task_id, counts, roll_up, is_ab, status ,create_time,update_time,creator,updater ,deleted from education_paper
select paper_id, task_id, num,counts, roll_up, is_ab, status ,create_time,update_time,creator,updater ,deleted from education_paper
</sql>
@@ -103,8 +104,8 @@ select task_id from education_paper where paper_id=#{paperId}
<select id="selectPaperByTaskIdAndRoll" resultType="java.lang.String">
select paper_id from education_paper where task_id=#{taskId} and deleted ='0'
</select>
<select id="getPaperByTaskIdByType" resultType="java.lang.String">
select paper_id from education_paper where task_id=#{taskId} and status ='0' and deleted ='0' and roll_up IS NOT NULL
<select id="getPaperByTaskIdByType" resultMap="EducationPaperResult">
select * from education_paper where task_id=#{taskId} and status ='0' and deleted ='0' and roll_up IS NOT NULL
</select>
<select id="getSelectPaperIdBySchemeIds" resultType="java.lang.String">
@@ -115,6 +116,9 @@ select task_id from education_paper where paper_id=#{paperId}
<include refid="selectEducationPaperVo"/>
where task_id =#{taskId} and deleted ='0'
</select>
<select id="selectCountPaperList" resultType="java.lang.Integer">
select count(*) from education_paper
</select>
<insert id="insertEducationPaper" parameterType="EducationPaper">
@@ -122,6 +126,7 @@ select task_id from education_paper where paper_id=#{paperId}
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="paperId != null">paper_id,</if>
<if test="taskId != null">task_id,</if>
<if test="num != null">num,</if>
<if test="counts != null">counts,</if>
<if test="rollUp != null">roll_up,</if>
<if test="isAb != null">is_ab,</if>
@@ -136,6 +141,7 @@ select task_id from education_paper where paper_id=#{paperId}
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="paperId != null">#{paperId},</if>
<if test="taskId != null">#{taskId},</if>
<if test="num != null">#{num},</if>
<if test="counts != null">#{counts},</if>
<if test="rollUp != null">#{rollUp},</if>
<if test="isAb != null">#{isAb},</if>
@@ -149,10 +155,10 @@ select task_id from education_paper where paper_id=#{paperId}
</trim>
</insert>
<insert id="insertEducationPaperList">
INSERT INTO education_paper (paper_id, task_id, counts, roll_up, is_ab, status ) VALUES
INSERT INTO education_paper (paper_id, task_id,num ,counts, roll_up, is_ab, status ) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.paperId}, #{item.taskId}, #{item.counts}, #{item.rollUp}, #{item.isAb}, #{item.status}
#{item.paperId}, #{item.taskId}, #{item.num},#{item.counts}, #{item.rollUp}, #{item.isAb}, #{item.status}
)
</foreach>
</insert>

View File

@@ -7,6 +7,7 @@
<resultMap type="EducationPaperScheme" id="EducationPaperSchemeResult">
<result property="schemeId" column="scheme_id" />
<result property="taskId" column="task_id" />
<result property="quTitle" column="qu_title" />
<result property="spName" column="sp_name" />
<result property="quLevel" column="qu_level" />
<result property="keywords" column="keywords" />
@@ -14,10 +15,11 @@
<result property="quNumbers" column="qu_numbers" />
<result property="quScores" column="qu_scores" />
<result property="subtotalScore" column="subtotal_score" />
<result property="sort" column="sort" />
</resultMap>
<sql id="selectEducationPaperSchemeVo">
select scheme_id, task_id, sp_name, qu_level, keywords, point_names, qu_numbers, qu_scores, subtotal_score from education_paper_scheme
select scheme_id, task_id,qu_title,sp_name, qu_level, keywords, point_names, qu_numbers, qu_scores, subtotal_score,sort from education_paper_scheme
</sql>
<select id="selectEducationPaperSchemeList" parameterType="EducationPaperScheme" resultMap="EducationPaperSchemeResult">
@@ -32,6 +34,7 @@
<if test="quScores != null and quScores != ''"> and qu_scores = #{quScores}</if>
<if test="subtotalScore != null and subtotalScore != ''"> and subtotal_score = #{subtotalScore}</if>
</where>
order by sort asc
</select>
<select id="selectEducationPaperSchemeBySchemeId" parameterType="String" resultMap="EducationPaperSchemeResult">
@@ -47,6 +50,7 @@
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="schemeId != null">scheme_id,</if>
<if test="taskId != null">task_id,</if>
<if test="quTitle != null">qu_title,</if>
<if test="spName != null">sp_name,</if>
<if test="quLevel != null">qu_level,</if>
<if test="keywords != null">keywords,</if>
@@ -54,10 +58,12 @@
<if test="quNumbers != null">qu_numbers,</if>
<if test="quScores != null">qu_scores,</if>
<if test="subtotalScore != null">subtotal_score,</if>
<if test="sort != null">sort,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="schemeId != null">#{schemeId},</if>
<if test="taskId != null">#{taskId},</if>
<if test="quTitle != null">#{quTitle},</if>
<if test="spName != null">#{spName},</if>
<if test="quLevel != null">#{quLevel},</if>
<if test="keywords != null">#{keywords},</if>
@@ -65,13 +71,14 @@
<if test="quNumbers != null">#{quNumbers},</if>
<if test="quScores != null">#{quScores},</if>
<if test="subtotalScore != null">#{subtotalScore},</if>
<if test="sort != null">#{sort},</if>
</trim>
</insert>
<insert id="insertEducationPaperSchemeList">
INSERT INTO education_paper_scheme (scheme_id, task_id, sp_name, qu_level, keywords, point_names, qu_numbers, qu_scores, subtotal_score) VALUES
INSERT INTO education_paper_scheme (scheme_id, task_id, qu_title,sp_name, qu_level, keywords, point_names, qu_numbers, qu_scores, subtotal_score,sort) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.schemeId}, #{item.taskId}, #{item.spName}, #{item.quLevel}, #{item.keywords}, #{item.pointNames}, #{item.quNumbers}, #{item.quScores}, #{item.subtotalScore}
#{item.schemeId}, #{item.taskId}, #{item.quTitle},#{item.spName}, #{item.quLevel}, #{item.keywords}, #{item.pointNames}, #{item.quNumbers}, #{item.quScores}, #{item.subtotalScore}, #{item.sort}
)
</foreach>
</insert>
@@ -80,6 +87,7 @@
update education_paper_scheme
<trim prefix="SET" suffixOverrides=",">
<if test="taskId != null">task_id = #{taskId},</if>
<if test="quTitle != null">qu_title = #{quTitle},</if>
<if test="spName != null">sp_name = #{spName},</if>
<if test="quLevel != null">qu_level = #{quLevel},</if>
<if test="keywords != null">keywords = #{keywords},</if>
@@ -87,6 +95,7 @@
<if test="quNumbers != null">qu_numbers = #{quNumbers},</if>
<if test="quScores != null">qu_scores = #{quScores},</if>
<if test="subtotalScore != null">subtotal_score = #{subtotalScore},</if>
<if test="subtotalScore != null">sort = #{sort},</if>
</trim>
where scheme_id = #{schemeId}
</update>

View File

@@ -21,20 +21,7 @@
select session_id, task_id, batch, start_time, end_time, allow_entry, end_allow_entry, allow_submission, status, paper_id from education_paper_session
</sql>
<select id="selectEducationPaperSessionList" parameterType="EducationPaperSession" resultMap="EducationPaperSessionResult">
<include refid="selectEducationPaperSessionVo"/>
<where>
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
<if test="batch != null and batch != ''"> and batch LIKE CONCAT('%', #{batch}, '%')</if>
<if test="startTime != null "> and start_time = #{startTime}</if>
<if test="endTime != null "> and end_time = #{endTime}</if>
<if test="allowEntry != null and allowEntry != ''"> and allow_entry = #{allowEntry}</if>
<if test="endAllowEntry != null and endAllowEntry != ''"> and end_allow_entry = #{endAllowEntry}</if>
<if test="allowSubmission != null and allowSubmission != ''"> and allow_submission = #{allowSubmission}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="paperId != null and paperId != ''"> and paper_id = #{paperId}</if>
</where>
</select>
<select id="selectEducationPaperSessionBySessionId" parameterType="String" resultMap="EducationPaperSessionResult">
<include refid="selectEducationPaperSessionVo"/>

View File

@@ -107,6 +107,12 @@
)
</if>
</select>
<select id="selectEducationPaperTaskNameByid" resultType="java.lang.String">
select task_name from education_paper_task where task_id=#{taskId}
</select>
<select id="selectStuClassNameByClassId" resultType="java.lang.String">
select name from exam_class where id=#{classId}
</select>
<insert id="insertEducationPaperTask" parameterType="EducationPaperTask">

View File

@@ -89,8 +89,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="content != null">content,</if>
<if test="contentText != null">content_text,</if>
<if test="analysis != null">analysis,</if>
<if test="deptId != null">dept_id,</if>
<if test="userId != null">user_id,</if>
<if test="pointNames != null">point_names,</if>
<if test="keywords != null">keywords,</if>
<if test="manual != null">manual,</if>
@@ -115,8 +113,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="content != null">#{content},</if>
<if test="contentText != null">#{contentText},</if>
<if test="analysis != null">#{analysis},</if>
<if test="deptId != null">#{deptId},</if>
<if test="userId != null">#{userId},</if>
<if test="pointNames != null">#{pointNames},</if>
<if test="keywords != null">#{keywords},</if>
<if test="manual != null">#{manual},</if>

View File

@@ -33,6 +33,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="quId != null "> and qu_id = #{quId}</if>
</where>
</select>
<select id="selectSysFileByQuidIN" resultMap="SysFileResult">
<include refid="selectSysFileVo"/>
<where>
<if test="quId != null "> and qu_id = #{quId}</if>
</where>
and (file_type = '0' or file_type ='1')
</select>
<insert id="insertSysFile" parameterType="SysFileUpload">
insert into sys_file

View File

@@ -7,6 +7,9 @@ import org.springframework.web.bind.annotation.RestController;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.judgement.controller.service.mysql.IMysqlServerice;
import java.io.IOException;
import java.sql.SQLException;
@RestController
@RequestMapping("/tool/Mysql")
public class MysqlController {
@@ -16,12 +19,14 @@ public class MysqlController {
@Autowired
private IMysqlServerice mysqlServerice;
/**
* Mysql判分
* @return 得分
*/
@PostMapping("/run_judgement")
public CommonResult run_C_code() {
public CommonResult run_C_code() throws SQLException, IOException {
return CommonResult.success(mysqlServerice.Judgement());
}

View File

@@ -20,22 +20,14 @@ public class WindowsFileController {
@Autowired
private IFileServerice fileServerice;
/**
* 得出文件操作考点
* @return 得分
*/
// @PostMapping("/get_filePoint")
//todo 后期需要素材文件和答案文件的 父目录 如D:/exam/3/shucai,D:/exam/3/win
public CommonResult get_file_point() throws IOException {
return CommonResult.success(fileServerice.get_file_point());
}
/**
* 文件操作题判分
* @return 判分
*/
@PostMapping("/run_file")
@PostMapping("/run_judgement")
public CommonResult run_file_point() throws IOException {
//"权值得分比重"
return CommonResult.success(fileServerice.run_file_point());

View File

@@ -4,8 +4,10 @@ import org.springframework.stereotype.Service;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.judgement.controller.utils.brower.BookmarkChecker;
import pc.exam.pp.module.judgement.controller.utils.brower.BookmarkDeleter;
import pc.exam.pp.module.judgement.controller.utils.file.GetDifferencesBetweenFolders;
import pc.exam.pp.module.exam.utils.file.GetDifferencesBetweenFolders;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -14,6 +16,7 @@ import java.util.Map;
@Service
public class BrowserServericeImpl implements IBrowserServerice {
static String answerLogPath = "answerLogBrower.txt"; // 文件路径
//考生试题文件夹
static final String BASE_DIR = "D:/exam/4/";
//谷歌浏览器
@@ -51,6 +54,12 @@ public class BrowserServericeImpl implements IBrowserServerice {
//根据路径,得到考生答题文件集合
Map<String, String> stuFiles = GetDifferencesBetweenFolders.listFilesAndFoldersWithAttributes(Paths.get(BASE_DIR));
// 输出学生提交的内容
appendToFile(answerLogPath,"=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> appendToFile(answerLogPath,key + " -> " + value));
appendToFile(answerLogPath,"=== 学生提交内容得分点 ===");
// 对比学生提交内容与试题得分点
//这里指挥判断存在文件夹的得分点
Integer studentScore = compareStuAndTestFiles(answerList, stuFiles);
@@ -96,13 +105,29 @@ public class BrowserServericeImpl implements IBrowserServerice {
// 如果正确,则累加总分
if (isCorrect) {
totalScore += currentScore;
System.out.println(answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,"考点"+answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}else {
System.out.println(answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,"考点"+answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}
}
//返回累加的得分点
return totalScore;
}
/**
* 将指定内容追加写入到指定文件中。
*
* @param filePath 文件路径
* @param content 要写入的内容
*/
public static void appendToFile(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
writer.write(content);
writer.newLine(); // 可选:添加换行符
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -2,8 +2,10 @@ package pc.exam.pp.module.judgement.controller.service.file;
import org.springframework.stereotype.Service;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import pc.exam.pp.module.judgement.controller.utils.file.GetDifferencesBetweenFolders;
import pc.exam.pp.module.exam.utils.file.GetDifferencesBetweenFolders;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -17,41 +19,7 @@ import java.util.stream.Collectors;
@Service
public class FileServericeImpl implements IFileServerice {
static final String BASE_DIR = "D:/exam/3/";
@Override
public List<ExamQuestionAnswer> get_file_point() throws IOException {
List<ExamQuestionAnswer> answerList = new ArrayList<>();
AtomicInteger sortCounter = new AtomicInteger(1); // 计数器
String path1 = BASE_DIR + "shucai";
String path2 = BASE_DIR + "win";
// 获取 shucai 和 win 文件夹的差异
Map<String, String> differences = GetDifferencesBetweenFolders.getDifferencesBetweenFolders(path1, path2);
List<ExamQuestionAnswer> formattedDifferences = differences.entrySet().stream()
.map(entry -> {
String key = entry.getKey();
String value = entry.getValue();
ExamQuestionAnswer answer = new ExamQuestionAnswer();
answer.setContent(key); // 设置文件路径
answer.setScoreRate("1");
//这里设置answer的排序按照循环次数来
answer.setSort(String.valueOf(sortCounter.getAndIncrement())); // 按顺序设置排序值
if (value.startsWith("仅存在于 "+path1)) {
answer.setContentIn("考察删除");
} else if (value.startsWith("仅存在于 "+path2)) {
answer.setContentIn("考察名称");
} else if (value.startsWith("属性不同")) {
answer.setContentIn("考察属性");
// answer.setContent(key + " -> " + value.split(" vs ")[1]); // 设置属性信息
}
return answer;
})
.sorted(Comparator.comparingInt(answer -> Integer.parseInt(answer.getSort()))) // 按 sort 排序
.collect(Collectors.toList());
answerList.addAll(formattedDifferences);
return answerList;
}
static String answerLogPath = "answerLogFile.txt"; // 文件路径
@Override
public String run_file_point() throws IOException {
@@ -68,9 +36,12 @@ public class FileServericeImpl implements IFileServerice {
Map<String, String> stuFiles = GetDifferencesBetweenFolders.listFilesAndFoldersWithAttributes(Paths.get( stuPath));
// 输出学生提交的内容
System.out.println("\n=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> System.out.println(key + " -> " + value));
System.out.println("\n=== 学生提交内容得分点 ===");
appendToFile(answerLogPath,"=== 学生提交内容stu 目录) ===");
stuFiles.forEach((key, value) -> appendToFile(answerLogPath,key + " -> " + value));
appendToFile(answerLogPath,"=== 学生提交内容得分点 ===");
// 对比学生提交内容与试题得分点
Integer studentScore = compareStuAndTestFiles(answerList, stuFiles);
@@ -113,14 +84,28 @@ public class FileServericeImpl implements IFileServerice {
// 如果正确,则累加总分
if (isCorrect) {
totalScore += currentScore;
System.out.println(answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}else {
System.out.println(answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
appendToFile(answerLogPath,answer.getContent() + " -> " + answer.getContentIn() + " -> 得分权值:" + answer.getScoreRate()+"-> 是否得分:"+isCorrect);
}
}
//返回累加的总分
return totalScore;
}
/**
* 将指定内容追加写入到指定文件中。
*
* @param filePath 文件路径
* @param content 要写入的内容
*/
public static void appendToFile(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
writer.write(content);
writer.newLine(); // 可选:添加换行符
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -9,7 +9,7 @@ import java.util.List;
public interface IFileServerice {
List<ExamQuestionAnswer> get_file_point() throws IOException;
String run_file_point() throws IOException;

View File

@@ -1,8 +1,18 @@
package pc.exam.pp.module.judgement.controller.service.mysql;
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestionAnswer;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public interface IMysqlServerice {
int Judgement();
AtomicInteger Judgement() throws IOException, SQLException;
}

View File

@@ -29,11 +29,14 @@ public class MySQLExporterUtil {
}
try (Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
FileWriter writer = new FileWriter(outputFile)) {
// 连接数据库
switchDatabase(conn);
// 导出表结构
exportTables(conn, writer);
// 导出视图结构
exportViews(conn, writer);
// 导出存储过程
exportProcedures(conn, writer);
System.out.println("导出成功!文件路径: " + outputFile);
} catch (Exception e) {
e.printStackTrace();
@@ -119,5 +122,23 @@ public class MySQLExporterUtil {
}
}
private void exportProcedures(Connection conn, FileWriter writer) throws SQLException, IOException {
DatabaseMetaData meta = conn.getMetaData();
try (ResultSet procedures = meta.getProcedures(databaseName, null, "%")) {
while (procedures.next()) {
String procedureName = procedures.getString("PROCEDURE_NAME");
writer.write(getCreateProcedureSQL(conn, procedureName) + ";\n\n");
}
}
}
private String getCreateProcedureSQL(Connection conn, String procedureName) throws SQLException {
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SHOW CREATE PROCEDURE " + procedureName)) {
if (rs.next()) {
return rs.getString("Create Procedure");
}
return "";
}
}
}

View File

@@ -4,6 +4,10 @@ import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -16,13 +20,38 @@ public class SqlFileProcessor {
public static Map<String, List<String>> processSqlFile(String filePath) throws IOException {
List<String> sqlStatements = readSQLFromFile(filePath);
//查找语句
List<String> selectStatements = new ArrayList<>();
//删除语句
List<String> delStatements = new ArrayList<>();
//视图
List<String> viewStatements = new ArrayList<>();
//其他(建表,新增。修改)
List<String> otherStatements = new ArrayList<>();
//触发器
List<String> triggerStatements = new ArrayList<>();
//存储过程
List<String> procedureStatements = new ArrayList<>();
for (String sql : sqlStatements) {
if (sql.trim().toUpperCase().startsWith("SELECT")) {
selectStatements.add(sql);
} else {
}else if ( sql.toUpperCase().contains("TRIGGER")) {
triggerStatements.add(sql);
}
else if ( sql.toUpperCase().contains("PROCEDURE")) {
procedureStatements.add(sql);
}
else if (sql.trim().toUpperCase().startsWith("DELETE")){
delStatements.add(sql);
}else if (sql.trim().replaceAll("\\s+", " ").matches("(?i)^CREATE( OR REPLACE)?( ALGORITHM\\s*=\\s*\\w+)?( DEFINER\\s*=\\s*[`\"'\\w@%\\.]+)?( SQL SECURITY \\w+)? VIEW\\b.*")) {
// 把视图语句加到 viewStatements 集合里
viewStatements.add(sql);
}
else
{
otherStatements.add(sql);
}
}
@@ -30,44 +59,61 @@ public class SqlFileProcessor {
Map<String, List<String>> result = new HashMap<>();
result.put("SELECT", selectStatements);
result.put("OTHER", otherStatements);
result.put("TRIGGER", triggerStatements);
result.put("PROCEDURE", procedureStatements);
result.put("VIEW", viewStatements);
result.put("DELETE", delStatements);
return result;
}
private static List<String> readSQLFromFile(String filePath) throws IOException {
List<String> sqlStatements = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"))) {
StringBuilder sqlStatement = new StringBuilder();
String line;
boolean insideBlockComment = false;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.contains("/*")) {
insideBlockComment = true;
line = line.split("/\\*")[0].trim();
}
if (line.contains("*/")) {
insideBlockComment = false;
line = line.split("\\*/")[1].trim();
}
List<String> lines = readFileAutoCharset(filePath);
List<String> sqlList = parseSql(lines);
if (line.startsWith("--") || line.isEmpty() || insideBlockComment) {
continue;
}
sqlStatement.append(line).append(" ");
if (line.endsWith(";")) {
sqlStatements.add(sqlStatement.toString().trim());
sqlStatement.setLength(0);
}
for (String sql : sqlList) {
System.out.println(sql);
}
if (sqlStatement.length() > 0) {
sqlStatements.add(sqlStatement.toString().trim());
}
return sqlList;
}
// 自动识别 UTF-8 or GBK
private static List<String> readFileAutoCharset(String filePath) throws IOException {
try {
// 优先尝试 UTF-8
return Files.readAllLines(Paths.get(filePath), Charset.forName("UTF-8"));
} catch (MalformedInputException e) {
// 如果UTF-8失败再尝试GBK
System.out.println("文件不是UTF-8编码尝试使用GBK编码读取...");
return Files.readAllLines(Paths.get(filePath), Charset.forName("GBK"));
}
return sqlStatements;
}
// 解析SQL去掉注释只保留SQL语句
private static List<String> parseSql(List<String> lines) {
List<String> sqlList = new ArrayList<>();
StringBuilder currentSql = new StringBuilder();
for (String line : lines) {
line = line.trim();
if (line.startsWith("--")) {
// 遇到新的注释(比如 -- 1.先把之前的SQL收进去
if (currentSql.length() > 0) {
sqlList.add(currentSql.toString().trim());
currentSql.setLength(0);
}
continue; // 注释行不用管
}
// 累加 SQL 内容
currentSql.append(line).append("\n");
}
if (currentSql.length() > 0) {
sqlList.add(currentSql.toString().trim());
}
return sqlList;
}
}

View File

@@ -0,0 +1,39 @@
package pc.exam.pp.module.judgement.domain;
public class SqlExecutionResult {
private String sqlStatement;
private String backupFile;
private boolean isValid;
public SqlExecutionResult(String sqlStatement, String backupFile) {
this.sqlStatement = sqlStatement;
this.backupFile = backupFile;
this.isValid = false; // 默认执行完后再判断
}
public String getSqlStatement() {
return sqlStatement;
}
public String getBackupFile() {
return backupFile;
}
public boolean isValid() {
return isValid;
}
public void setValid(boolean valid) {
isValid = valid;
}
@Override
public String toString() {
return "SqlExecutionResult{" +
"sqlStatement='" + sqlStatement + '\'' +
", backupFile='" + backupFile + '\'' +
", isValid=" + isValid +
'}';
}
}

View File

@@ -183,4 +183,7 @@ public interface ErrorCodeConstants {
ErrorCode WORD_PARENT_ERROR = new ErrorCode(1_002_030_004, "不能设置自己为父WORD节点");
ErrorCode WORD_NOT_ENABLE = new ErrorCode(1_002_030_006, "WORD节点({})不处于开启状态,不允许选择");
ErrorCode WORD_PARENT_IS_CHILD = new ErrorCode(1_002_030_007, "不能设置自己的子WORD节点为父WORD节点");
ErrorCode MONITOR_NOT_EXISTS = new ErrorCode(1_003_301_001, "id为空");
}

View File

@@ -44,14 +44,14 @@ spring:
primary: master
datasource:
master:
url: jdbc:mysql://47.101.60.131:3306/pc-exam?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: pc-exam
password: YGsyBWH3KdGpz8C7
url: jdbc:mysql://127.0.0.1:3306/pc-exam?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: root
password: 123
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://47.101.60.131:3306/pc-exam?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: pc-exam
password: YGsyBWH3KdGpz8C7
url: jdbc:mysql://127.0.0.1:3306/pc-exam?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: root
password: 123
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data:

View File

@@ -345,7 +345,6 @@ exam:
- education_paper_qu
- education_paper_scheme
- education_paper_session
- exam_specialty
ignore-caches:
- user_role_ids
- permission_menu_ids