【修改】 监控管理中学生分数不一致的问题

This commit is contained in:
dlaren
2025-08-19 15:20:40 +08:00
parent 59ae05442c
commit b25e354303
17 changed files with 235 additions and 203 deletions

View File

@@ -1,4 +1,5 @@
package pc.exam.pp.module.exam.controller.admin.monitor; package pc.exam.pp.module.exam.controller.admin.monitor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -8,6 +9,7 @@ import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.*; import jakarta.validation.*;
import jakarta.servlet.http.*; import jakarta.servlet.http.*;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
@@ -22,11 +24,14 @@ import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import pc.exam.pp.framework.excel.core.util.ExcelUtils; import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog; import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog;
import static pc.exam.pp.framework.apilog.core.enums.OperateTypeEnum.*; 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.controller.admin.monitor.vo.*;
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.monitor.MonitorDO;
import pc.exam.pp.module.exam.service.monitor.MonitorService; import pc.exam.pp.module.exam.service.monitor.MonitorService;
import static pc.exam.pp.module.infra.enums.ErrorCodeConstants.DEMO03_MONITOR_SESSION_EXISTS; import static pc.exam.pp.module.infra.enums.ErrorCodeConstants.DEMO03_MONITOR_SESSION_EXISTS;
import static pc.exam.pp.module.infra.enums.ErrorCodeConstants.DEMO03_MONITOR_TIME_EXISTS; import static pc.exam.pp.module.infra.enums.ErrorCodeConstants.DEMO03_MONITOR_TIME_EXISTS;
@@ -78,41 +83,39 @@ public class MonitorController {
@Operation(summary = "导出监控管理 Excel") @Operation(summary = "导出监控管理 Excel")
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)
public void exportMonitorExcel(@Valid MonitorPageReqVO pageReqVO, HttpServletResponse response) throws IOException { public void exportMonitorExcel(@Valid MonitorPageReqVO pageReqVO, HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<MonitorDO> list = monitorService.getMonitorPage(pageReqVO).getList(); List<MonitorDO> list = monitorService.getMonitorPage(pageReqVO).getList();
// 导出 Excel // 导出 Excel
ExcelUtils.write(response, "监控管理.xls", "数据", MonitorRespVO.class, ExcelUtils.write(response, "监控管理.xls", "数据", MonitorRespVO.class,
BeanUtils.toBean(list, MonitorRespVO.class)); BeanUtils.toBean(list, MonitorRespVO.class));
} }
@PostMapping("/stuMonitor") @PostMapping("/stuMonitor")
@Operation(summary = "学生端进入考试返回值") @Operation(summary = "学生端进入考试返回值")
public CommonResult getStuMonitor(@Valid @RequestBody StuMonitorPaperVo stuMonitorPaperVo) { public CommonResult<Long> getStuMonitor(@Valid @RequestBody StuMonitorPaperVo stuMonitorPaperVo) {
long stuMonitor = 0; long stuMonitor = 0;
try { try {
stuMonitor = monitorService.getStuMonitor(stuMonitorPaperVo); stuMonitor = monitorService.getStuMonitor(stuMonitorPaperVo);
} catch (RuntimeException e) { } catch (RuntimeException e) {
return error(1-001-606-001,e.getMessage()); return error(1_1_606_001, e.getMessage());
} }
if (stuMonitor>0) if (stuMonitor > 0) {
{
return success(stuMonitor); return success(stuMonitor);
}else { } else {
return error(DEMO03_MONITOR_TIME_EXISTS); return error(DEMO03_MONITOR_TIME_EXISTS);
} }
} }
@PostMapping("/stuMonitorQu") @PostMapping("/stuMonitorQu")
@Operation(summary = "学生端考试过程传试题") @Operation(summary = "学生端考试过程传试题")
public CommonResult<String> updateStuMonitor(@Valid @RequestBody StuMonitorQuVo stuMonitorQuVo) { public CommonResult<String> updateStuMonitor(@Valid @RequestBody StuMonitorQuVo stuMonitorQuVo) {
Boolean stuMonitor = monitorService.updateStuMonitor(stuMonitorQuVo); Boolean stuMonitor = monitorService.updateStuMonitor(stuMonitorQuVo);
if (!stuMonitor) if (!stuMonitor) {
{
return error(DEMO03_MONITOR_SESSION_EXISTS); return error(DEMO03_MONITOR_SESSION_EXISTS);
} }
return success("传值成功"); return success("传值成功");
} }
@PostMapping("/endMonitor") @PostMapping("/endMonitor")
@Operation(summary = "学生端结束考试返回值") @Operation(summary = "学生端结束考试返回值")
public void endStuMonitor(@Valid @RequestBody StuMonitorPaperEndVo stuMonitorPaperEndVo) { public void endStuMonitor(@Valid @RequestBody StuMonitorPaperEndVo stuMonitorPaperEndVo) {
@@ -123,15 +126,15 @@ public class MonitorController {
@GetMapping("/getPaperTaskList") @GetMapping("/getPaperTaskList")
@Operation(summary = "根据种类获得试卷任务") @Operation(summary = "根据种类获得试卷任务")
@Parameter(name = "id", description = "试卷种类", required = true, example = "1024") @Parameter(name = "id", description = "试卷种类", required = true, example = "1024")
public CommonResult getPaperTaskList(@RequestParam("id") String id) { public CommonResult<List<EducationPaperTask>> getPaperTaskList(@RequestParam("id") String id) {
return success(monitorService.getPaperTaskList(id)); return success(monitorService.getPaperTaskList(id));
} }
@PostMapping("/updateMonitorStatus") @PostMapping("/updateMonitorStatus")
@Operation(summary = "改变考生状态") @Operation(summary = "改变考生状态")
public CommonResult updateMonitorStatus(@Valid @RequestBody StuMonitorStatusVo stuMonitorStatusVo) { public CommonResult<Boolean> updateMonitorStatus(@Valid @RequestBody StuMonitorStatusVo stuMonitorStatusVo) {
return success(monitorService.updateMonitorStatus(stuMonitorStatusVo)); return success(monitorService.updateMonitorStatus(stuMonitorStatusVo));
} }
} }

View File

@@ -11,23 +11,17 @@ import com.alibaba.excel.annotation.*;
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class MonitorRespVO { public class MonitorRespVO {
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19828")
@ExcelProperty("主键id")
private String monitorId; private String monitorId;
@Schema(description = "用户账号", example = "芋艿")
@ExcelProperty("用户账号") @ExcelProperty("用户账号")
private String username; private String username;
@Schema(description = "用户姓名", example = "赵六")
@ExcelProperty("用户姓名") @ExcelProperty("用户姓名")
private String nickname; private String nickname;
@Schema(description = "班级", example = "芋艿")
@ExcelProperty("班级") @ExcelProperty("班级")
private String className; private String className;
@Schema(description = "考试状态", example = "2")
@ExcelProperty("考试状态") @ExcelProperty("考试状态")
private String examStatus; private String examStatus;
@@ -53,7 +47,7 @@ private String ip;
@Schema(description = "剩余时间") @Schema(description = "剩余时间")
@ExcelProperty("剩余时间") @ExcelProperty("剩余时间")
private LocalDateTime remainingTime; private String remainingTime;
@Schema(description = "创建时间") @Schema(description = "创建时间")
@ExcelProperty("创建时间") @ExcelProperty("创建时间")

View File

@@ -1,5 +1,6 @@
package pc.exam.pp.module.exam.dal.dataobject.monitor; package pc.exam.pp.module.exam.dal.dataobject.monitor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
@@ -69,5 +70,9 @@ public class MonitorDO extends BaseDO {
* 剩余时间 * 剩余时间
*/ */
private Long remainingTime; private Long remainingTime;
/**
* 临时ID
*/
private String temporaryId;
} }

View File

@@ -45,4 +45,9 @@ public class StuPaperFileDO extends TenantBaseDO {
* 判分详情,富文本格式 * 判分详情,富文本格式
*/ */
private String content; private String content;
/**
* 临时ID对应学生分数得ID
*/
private String temporaryId;
} }

View File

@@ -24,51 +24,52 @@ import java.util.Optional;
@Mapper @Mapper
public interface MonitorMapper extends BaseMapperX<MonitorDO> { public interface MonitorMapper extends BaseMapperX<MonitorDO> {
default PageResult<MonitorDO> selectPage(MonitorPageReqVO reqVO) { default PageResult<MonitorDO> selectPage(MonitorPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<MonitorDO>() return selectPage(reqVO, new LambdaQueryWrapperX<MonitorDO>()
.inIfPresent(MonitorDO::getMonitorId, Optional.ofNullable(reqVO.getMonitorId()).map(Arrays::asList).orElse(null)) .inIfPresent(MonitorDO::getMonitorId, Optional.ofNullable(reqVO.getMonitorId()).map(Arrays::asList).orElse(null))
.likeIfPresent(MonitorDO::getUsername, reqVO.getUsername()) .likeIfPresent(MonitorDO::getUsername, reqVO.getUsername())
.likeIfPresent(MonitorDO::getTaskId, reqVO.getTaskId()) .likeIfPresent(MonitorDO::getTaskId, reqVO.getTaskId())
.likeIfPresent(MonitorDO::getNickname, reqVO.getNickname()) .likeIfPresent(MonitorDO::getNickname, reqVO.getNickname())
.likeIfPresent(MonitorDO::getClassName, reqVO.getClassName()) .likeIfPresent(MonitorDO::getClassName, reqVO.getClassName())
.eqIfPresent(MonitorDO::getExamStatus, reqVO.getExamStatus()) .eqIfPresent(MonitorDO::getExamStatus, reqVO.getExamStatus())
.eqIfPresent(MonitorDO::getTaskType, reqVO.getTaskType()) .eqIfPresent(MonitorDO::getTaskType, reqVO.getTaskType())
.eqIfPresent(MonitorDO::getScore, reqVO.getScore()) .eqIfPresent(MonitorDO::getScore, reqVO.getScore())
.eqIfPresent(MonitorDO::getPaperNum, reqVO.getPaperNum()) .eqIfPresent(MonitorDO::getPaperNum, reqVO.getPaperNum())
.likeIfPresent(MonitorDO::getTaskName, reqVO.getTaskName()) .likeIfPresent(MonitorDO::getTaskName, reqVO.getTaskName())
.eqIfPresent(MonitorDO::getIp, reqVO.getIp()) .eqIfPresent(MonitorDO::getIp, reqVO.getIp())
.betweenIfPresent(MonitorDO::getRemainingTime, reqVO.getRemainingTime()) .betweenIfPresent(MonitorDO::getRemainingTime, reqVO.getRemainingTime())
.betweenIfPresent(MonitorDO::getCreateTime, reqVO.getCreateTime()) .betweenIfPresent(MonitorDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(MonitorDO::getCreateTime)); .orderByDesc(MonitorDO::getCreateTime));
} }
default void removeMonitorByStuIdAndTaskId(DeleteRequestVo vo) { default void removeMonitorByStuIdAndTaskId(DeleteRequestVo vo) {
if (vo.getStudentIds() == null || vo.getStudentIds().isEmpty() || vo.getTaskId() == null) { if (vo.getStudentIds() == null || vo.getStudentIds().isEmpty() || vo.getTaskId() == null) {
return; return;
}
LambdaQueryWrapperX<MonitorDO> query = new LambdaQueryWrapperX<MonitorDO>()
.in(MonitorDO::getStuId, vo.getStudentIds())
.eq(MonitorDO::getTaskId, vo.getTaskId());
delete(query);
} }
LambdaQueryWrapperX<MonitorDO> query = new LambdaQueryWrapperX<MonitorDO>()
.in(MonitorDO::getStuId, vo.getStudentIds())
.eq(MonitorDO::getTaskId, vo.getTaskId());
delete(query);
}
String selectByStuIdAndTaskIdTop(@Param("stuId")Long stuId, @Param("taskId") String taskId); String selectByStuIdAndTaskIdTop(@Param("stuId") Long stuId, @Param("taskId") String taskId);
String selectByStuIdAndTaskIdNew(Long stuId, String taskId); String selectByStuIdAndTaskIdNew(Long stuId, String taskId);
List<String> selectByStuIdAndTaskId(Long stuId); List<String> selectByStuIdAndTaskId(Long stuId);
List<String> selectStuIdByTaskId(String taskId); List<String> selectStuIdByTaskId(String taskId);
/** /**
* 查找授权点位 * 查找授权点位
* @return *
*/ * @return
List<TentSpecialy> selectTent(Long loginTenantId); */
List<TentSpecialy> selectTent(Long loginTenantId);
void deleteByTaskIds(@Param("taskIds") String[] taskIds); void deleteByTaskIds(@Param("taskIds") String[] taskIds);
void deleteByTaskId(String taskId); void deleteByTaskId(String taskId);
} }

View File

@@ -15,7 +15,7 @@ import java.util.List;
*/ */
@Mapper @Mapper
public interface StuPaperFileMapper extends BaseMapperX<StuPaperFileDO> { public interface StuPaperFileMapper extends BaseMapperX<StuPaperFileDO> {
List<StuPaperFileDO> findByStuIdAndPaperId(@Param("stuId") Long stuId, @Param("paperId") String paperId); List<StuPaperFileDO> findByStuIdAndPaperId(@Param("stuId") Long stuId, @Param("paperId") String paperId, @Param("temporaryId") String temporaryId);
List<StuPaperFileDO> findOneByStuIdAndPaperId(@Param("stuId")Long stuId, @Param("paperId")String paperId,@Param("type") int type); List<StuPaperFileDO> findOneByStuIdAndPaperId(@Param("stuId")Long stuId, @Param("paperId")String paperId,@Param("type") int type);
} }

View File

@@ -13,53 +13,58 @@ import java.util.List;
* *
* @author 管理员 * @author 管理员
*/ */
public interface MonitorService { public interface MonitorService {
/** /**
* 创建监控管理 * 创建监控管理
* *
* @param createReqVO 创建信息 * @param createReqVO 创建信息
* @return 编号 * @return 编号
*/ */
String createMonitor(@Valid MonitorSaveReqVO createReqVO); String createMonitor(@Valid MonitorSaveReqVO createReqVO);
/** /**
* 更新监控管理 * 更新监控管理
* *
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void updateMonitor(@Valid MonitorSaveReqVO updateReqVO); void updateMonitor(@Valid MonitorSaveReqVO updateReqVO);
/** /**
* 删除监控管理 * 删除监控管理
* *
* @param id 编号 * @param id 编号
*/ */
void deleteMonitor(String id); void deleteMonitor(String id);
/** /**
* 获得监控管理 * 获得监控管理
* *
* @param id 编号 * @param id 编号
* @return 监控管理 * @return 监控管理
*/ */
MonitorDO getMonitor(String id); MonitorDO getMonitor(String id);
/** /**
* 获得监控管理分页 * 获得监控管理分页
* *
* @param pageReqVO 分页查询 * @param pageReqVO 分页查询
* @return 监控管理分页 * @return 监控管理分页
*/ */
PageResult<MonitorDO> getMonitorPage(MonitorPageReqVO pageReqVO); PageResult<MonitorDO> getMonitorPage(MonitorPageReqVO pageReqVO);
//学生端进入考试返回值
long getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo) throws RuntimeException; //学生端进入考试返回值
//学生端考试过程传试题 long getStuMonitor(StuMonitorPaperVo stuMonitorPaperVo) throws RuntimeException;
Boolean updateStuMonitor(StuMonitorQuVo stuMonitorQuVo);
//学生端结束考试返回值 //学生端考试过程传试题
void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo); Boolean updateStuMonitor(StuMonitorQuVo stuMonitorQuVo);
//根据种类获得试卷任务
List<EducationPaperTask> getPaperTaskList(String id); //学生端结束考试返回值
//改变考生状态 void endStuMonitor(StuMonitorPaperEndVo stuMonitorPaperEndVo);
Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo);
//根据种类获得试卷任务
List<EducationPaperTask> getPaperTaskList(String id);
//改变考生状态
Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo);
} }

View File

@@ -38,6 +38,8 @@ import pc.exam.pp.module.exam.dal.mysql.specialty.ExamSpecialtyMapper;
import pc.exam.pp.module.exam.dal.mysql.student.StuPaperScoreMapper; import pc.exam.pp.module.exam.dal.mysql.student.StuPaperScoreMapper;
import pc.exam.pp.module.exam.dal.mysql.student.StuScoreVo; import pc.exam.pp.module.exam.dal.mysql.student.StuScoreVo;
import pc.exam.pp.module.exam.service.monitor.vo.*; import pc.exam.pp.module.exam.service.monitor.vo.*;
import pc.exam.pp.module.exam.service.paper.IEducationPaperParamService;
import pc.exam.pp.module.exam.service.stuPaperScore.StuPaperScoreService;
//import pc.exam.pp.module.infra.service.file.FileService; //import pc.exam.pp.module.infra.service.file.FileService;
import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception; import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -74,7 +76,9 @@ public class MonitorServiceImpl implements MonitorService {
@Resource @Resource
private ExamSpecialtyMapper examSpecialtyMapper; private ExamSpecialtyMapper examSpecialtyMapper;
@Resource @Resource
private StuPaperScoreMapper stuPaperScoreMapper; private StuPaperScoreService stuPaperScoreService;
@Resource
private IEducationPaperParamService educationPaperParamService;
// @Resource // @Resource
// private FileService fileService; // private FileService fileService;
@@ -140,27 +144,19 @@ public class MonitorServiceImpl implements MonitorService {
} }
// 构建授权数量映射specialtyId -> 授权个数 // 构建授权数量映射specialtyId -> 授权个数
Map<String, Integer> authMap = tentSpecialies.stream() Map<String, Integer> authMap = tentSpecialies.stream().collect(Collectors.toMap(TentSpecialy::getSpecialtyId, t -> {
.collect(Collectors.toMap( try {
TentSpecialy::getSpecialtyId, return Integer.parseInt(t.getPoints());
t -> { } catch (Exception e) {
try { return 0;
return Integer.parseInt(t.getPoints()); }
} catch (Exception e) { }));
return 0;
}
}
));
// 查询 exam_specialty 所有 sp_id -> parent_id 映射(用来判断是否为专业) // 查询 exam_specialty 所有 sp_id -> parent_id 映射(用来判断是否为专业)
List<IdParentPair> pairList = examSpecialtyMapper.selectAllIdToParent(loginTenantId); List<IdParentPair> pairList = examSpecialtyMapper.selectAllIdToParent(loginTenantId);
// 转换为 Map<String, String> // 转换为 Map<String, String>
Map<String, String> idToParentMap = pairList.stream() Map<String, String> idToParentMap = pairList.stream().collect(Collectors.toMap(p -> String.valueOf(p.getSpId()), p -> p.getParentId() == null ? null : String.valueOf(p.getParentId())));
.collect(Collectors.toMap(
p -> String.valueOf(p.getSpId()),
p -> p.getParentId() == null ? null : String.valueOf(p.getParentId())
));
// 分类授权:哪些是专业,哪些是课程 // 分类授权:哪些是专业,哪些是课程
Set<String> authSpecialtyIds = new HashSet<>(); Set<String> authSpecialtyIds = new HashSet<>();
@@ -210,8 +206,7 @@ public class MonitorServiceImpl implements MonitorService {
List<CourseInVo> courseList = educationPaperTaskMapper.selectPaperCountBypaperId(paperId); List<CourseInVo> courseList = educationPaperTaskMapper.selectPaperCountBypaperId(paperId);
//将 courseInVos 转为 Map便于通过 courseId 查询次数 //将 courseInVos 转为 Map便于通过 courseId 查询次数
Map<String, Integer> courseCountMap = courseInVos.stream() Map<String, Integer> courseCountMap = courseInVos.stream().collect(Collectors.toMap(CourseInVo::getCourseId, CourseInVo::getCounts, (a, b) -> b));
.collect(Collectors.toMap(CourseInVo::getCourseId, CourseInVo::getCounts, (a, b) -> b));
//校验当前试卷的每门课程是否超过授权限制 //校验当前试卷的每门课程是否超过授权限制
for (CourseInVo course : courseList) { for (CourseInVo course : courseList) {
@@ -318,9 +313,7 @@ public class MonitorServiceImpl implements MonitorService {
return 0; return 0;
} }
} }
//开启测评时长限制 没开启场次 -直接返回测评时长 //开启测评时长限制 没开启场次 -直接返回测评时长
if ("1".equals(educationPaperParam.getIsSession()) && "0".equals(educationPaperParam.getIsTime())) { if ("1".equals(educationPaperParam.getIsSession()) && "0".equals(educationPaperParam.getIsTime())) {
info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay());
@@ -330,7 +323,6 @@ public class MonitorServiceImpl implements MonitorService {
return (long) examTime.toLocalTime().toSecondOfDay(); return (long) examTime.toLocalTime().toSecondOfDay();
} }
return 0L; return 0L;
} }
@@ -341,8 +333,6 @@ public class MonitorServiceImpl implements MonitorService {
String key = "userCache:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId(); String key = "userCache:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId();
String keychoice = "keychoice:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId(); String keychoice = "keychoice:" + stuMonitorQuVo.getTaskId() + ":" + stuMonitorQuVo.getStuId();
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class);
if (info != null) { if (info != null) {
if (!("1".equals(info.getExamStatus()))) { if (!("1".equals(info.getExamStatus()))) {
return false; return false;
@@ -361,27 +351,47 @@ public class MonitorServiceImpl implements MonitorService {
EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperEndVo.getPaperId()); EducationPaper educationPaper = educationPaperMapper.selectEducationPaperByPaperId(stuMonitorPaperEndVo.getPaperId());
String taskId = educationPaper.getTaskId(); String taskId = educationPaper.getTaskId();
String key = "userCache:" + taskId + ":" + stuMonitorPaperEndVo.getStuId(); String key = "userCache:" + taskId + ":" + stuMonitorPaperEndVo.getStuId();
// double score = educationPaperMapper.selctStuScoreByStuIdAndPaperId(stuMonitorPaperEndVo.getStuId(), stuMonitorPaperEndVo.getPaperId()); // 获取学生分数
BigDecimal score = new BigDecimal(0); StuScoreVo stuScoreVo = stuPaperScoreService.getStuScore(Long.valueOf(stuMonitorPaperEndVo.getStuId()),
List<StuScoreVo> stuScoreVos = stuPaperScoreMapper.getStuScore(Long.valueOf(stuMonitorPaperEndVo.getStuId()), stuMonitorPaperEndVo.getPaperId(), stuMonitorPaperEndVo.getTemporaryId()); stuMonitorPaperEndVo.getPaperId(),
for (StuScoreVo scoreVo : stuScoreVos) { stuMonitorPaperEndVo.getTemporaryId());
score = score.add(scoreVo.getScore()); BigDecimal score = stuScoreVo.getScore();
}
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class);
info.setRemainingTime(0L); MonitorDO monitorDOs = null;
if (info != null) {
monitorDOs = getMonitor(info.getMonitorId());
}
if (info != null) {
info.setRemainingTime(0L);
}
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId);
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId);
if ("1".equals(educationPaperParam.getSaveGrades())) { if ("1".equals(educationPaperParam.getSaveGrades())) {
info.setScore(String.valueOf(score)); info.setScore(String.valueOf(score));
info.setTemporaryId(stuMonitorPaperEndVo.getTemporaryId());
} else { } else {
MonitorDO monitorDO = monitorMapper.selectById(info.getMonitorId()); MonitorDO monitorDO = monitorMapper.selectById(info.getMonitorId());
info.setScore(String.valueOf(score)); info.setScore(String.valueOf(score));
if (StringUtils.isNotBlank(monitorDO.getScore())) { if (StringUtils.isNotBlank(monitorDO.getScore())) {
try { try {
double oldScore = Double.parseDouble(monitorDO.getScore()); double oldScore = Double.parseDouble(monitorDO.getScore());
if (score.doubleValue()> oldScore) { if (score.doubleValue() > oldScore) {
info.setScore(String.valueOf(score)); info.setScore(String.valueOf(score));
info.setTemporaryId(stuMonitorPaperEndVo.getTemporaryId());
} else { } else {
// 保留旧的临时ID
if (monitorDOs != null) {
if (monitorDOs.getTemporaryId() != null) {
info.setTemporaryId(monitorDOs.getTemporaryId());
} else {
info.setTemporaryId(stuMonitorPaperEndVo.getTemporaryId());
}
} else {
// 如果没有旧的临时ID则使用新的
info.setTemporaryId(stuMonitorPaperEndVo.getTemporaryId());
}
info.setScore(monitorDO.getScore()); // 保留旧成绩 info.setScore(monitorDO.getScore()); // 保留旧成绩
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@@ -392,21 +402,16 @@ public class MonitorServiceImpl implements MonitorService {
// 如果没有旧成绩,则直接设置 // 如果没有旧成绩,则直接设置
info.setScore(String.valueOf(score)); info.setScore(String.valueOf(score));
} }
} }
//考试下的任务 结束改为 结束 其他为待考 //考试下的任务 结束改为 结束 其他为待考
if ("1".equals(educationPaperTask.getTaskType())) { if ("1".equals(educationPaperTask.getTaskType())) {
info.setExamStatus("2"); info.setExamStatus("2");
redisTemplate.delete(key); redisTemplate.delete(key);
} else { } else {
info.setExamStatus("0"); info.setExamStatus("0");
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info));
} }
monitorMapper.updateById(info); monitorMapper.updateById(info);
} }
@Override @Override
@@ -432,11 +437,7 @@ public class MonitorServiceImpl implements MonitorService {
Time examTime = educationPaperParam.getExamTime(); Time examTime = educationPaperParam.getExamTime();
if (info == null) { if (info == null) {
MonitorDO monitorDO1 = monitorMapper.selectOne( MonitorDO monitorDO1 = monitorMapper.selectOne(new QueryWrapper<MonitorDO>().eq("stu_id", stuId).eq("task_id", taskId));
new QueryWrapper<MonitorDO>()
.eq("stu_id", stuId)
.eq("task_id", taskId)
);
PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(stuId); PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(stuId);
String name = educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId); String name = educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId);
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId); EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId);
@@ -506,29 +507,23 @@ public class MonitorServiceImpl implements MonitorService {
} }
// 构建传入列表中的 specialtyId Set这些是传进来的 ID // 构建传入列表中的 specialtyId Set这些是传进来的 ID
Set<String> inputSpecialtyIds = inputList.stream() Set<String> inputSpecialtyIds = inputList.stream().map(TentSpecialy::getSpecialtyId).collect(Collectors.toSet());
.map(TentSpecialy::getSpecialtyId)
.collect(Collectors.toSet());
// 查询所有课程 -> 专业 的关系 // 查询所有课程 -> 专业 的关系
List<SpecialtyRelation> allRelations = examSpecialtyMapper.selectAllSpecialtyRelations(); List<SpecialtyRelation> allRelations = examSpecialtyMapper.selectAllSpecialtyRelations();
// 构建课程ID -> 父专业ID 的映射 // 构建课程ID -> 父专业ID 的映射
Map<String, String> courseToParentMap = allRelations.stream() Map<String, String> courseToParentMap = allRelations.stream().filter(r -> r.getParentId() != null).collect(Collectors.toMap(SpecialtyRelation::getSpId, SpecialtyRelation::getParentId));
.filter(r -> r.getParentId() != null)
.collect(Collectors.toMap(SpecialtyRelation::getSpId, SpecialtyRelation::getParentId));
// 开始过滤:只保留以下情况之一 // 开始过滤:只保留以下情况之一
return inputList.stream() return inputList.stream().filter(item -> {
.filter(item -> { String specialtyId = item.getSpecialtyId();
String specialtyId = item.getSpecialtyId(); String parentId = courseToParentMap.get(specialtyId);
String parentId = courseToParentMap.get(specialtyId); // 1. 如果这个是专业(它不是任何课程的 sp_id → 保留
// 1. 如果这个是专业(它不是任何课程的 sp_id → 保留 if (parentId == null) return true;
if (parentId == null) return true; // 2. 如果它是课程,但父级不在输入列表中 → 保留
// 2. 如果它是课程,但父级不在输入列表中 → 保留 return !inputSpecialtyIds.contains(parentId);
return !inputSpecialtyIds.contains(parentId); }).collect(Collectors.toList());
})
.collect(Collectors.toList());
} }

View File

@@ -16,7 +16,7 @@ import java.util.List;
*/ */
public interface StuPaperFileService { public interface StuPaperFileService {
List<StuPaperFileDO> findByStuIDAndPaperId(Long stuID, String paperID); List<StuPaperFileDO> findByStuIDAndPaperId(Long stuID, String paperID, String temporaryId);
void insertStuPaperFile(StuPaperFileDO stuPaperFileDO); void insertStuPaperFile(StuPaperFileDO stuPaperFileDO);

View File

@@ -21,8 +21,8 @@ public class StuPaperFileServiceImpl implements StuPaperFileService {
private StuPaperFileMapper stuPaperFileMapper; private StuPaperFileMapper stuPaperFileMapper;
@Override @Override
public List<StuPaperFileDO> findByStuIDAndPaperId(Long stuID, String paperID) { public List<StuPaperFileDO> findByStuIDAndPaperId(Long stuID, String paperID, String temporaryId) {
return stuPaperFileMapper.findByStuIdAndPaperId(stuID, paperID); return stuPaperFileMapper.findByStuIdAndPaperId(stuID, paperID, temporaryId);
} }
@Override @Override

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pc.exam.pp.module.exam.dal.mysql.monitor.MonitorMapper"> <mapper namespace="pc.exam.pp.module.exam.dal.mysql.monitor.MonitorMapper">
<resultMap type="TentSpecialy" id="TentSpecialyResult"> <resultMap type="TentSpecialy" id="TentSpecialyResult">
<result property="id" column="id" /> <result property="id" column="id"/>
<result property="specialtyId" column="specialty_id" /> <result property="specialtyId" column="specialty_id"/>
<result property="points" column="points" /> <result property="points" column="points"/>
<result property="tenantId" column="tenant_id" /> <result property="tenantId" column="tenant_id"/>
</resultMap> </resultMap>
<update id="deleteByTaskIds"> <update id="deleteByTaskIds">
UPDATE exam_monitor UPDATE exam_monitor
@@ -21,36 +21,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="deleteByTaskId"> <update id="deleteByTaskId">
UPDATE exam_monitor UPDATE exam_monitor
SET deleted = '2' SET deleted = '2'
WHERE task_id =#{taskId} WHERE task_id = #{taskId}
</update> </update>
<select id="selectByStuIdAndTaskIdTop" resultType="java.lang.String"> <select id="selectByStuIdAndTaskIdTop" resultType="java.lang.String">
select score from exam_monitor where stu_id =#{stuId} and task_id=#{taskId} ORDER BY score DESC select score
LIMIT 1 from exam_monitor
where stu_id = #{stuId}
and task_id = #{taskId}
ORDER BY score DESC LIMIT 1
</select> </select>
<select id="selectByStuIdAndTaskIdNew" resultType="java.lang.String"> <select id="selectByStuIdAndTaskIdNew" resultType="java.lang.String">
select score from exam_monitor where stu_id =#{stuId} and task_id=#{taskId} ORDER BY create_time DESC select score
LIMIT 1 from exam_monitor
where stu_id = #{stuId}
and task_id = #{taskId}
ORDER BY create_time DESC LIMIT 1
</select> </select>
<select id="selectByStuIdAndTaskId" resultType="java.lang.String"> <select id="selectByStuIdAndTaskId" resultType="java.lang.String">
select task_id from exam_monitor where stu_id = #{stuId} and exam_status !='2' select task_id
from exam_monitor
where stu_id = #{stuId}
and exam_status !='2'
</select> </select>
<select id="selectStuIdByTaskId" resultType="java.lang.String"> <select id="selectStuIdByTaskId" resultType="java.lang.String">
select stu_id from exam_monitor where task_id =#{taskId} and deleted ='0' and exam_status ='0' select stu_id
from exam_monitor
where task_id = #{taskId}
and deleted = '0'
and exam_status = '0'
</select> </select>
<select id="selectTent" resultMap="TentSpecialyResult"> <select id="selectTent" resultMap="TentSpecialyResult">
SELECT SELECT ets.*,
ets.*, es.sp_name AS name
es.sp_name AS name FROM exam_tenant_specialty ets
FROM LEFT JOIN
exam_tenant_specialty ets exam_specialty es
LEFT JOIN ON
exam_specialty es ets.specialty_id = es.sp_id
ON WHERE ets.tenant_id = #{loginTenantId}
ets.specialty_id = es.sp_id
WHERE
ets.tenant_id = #{loginTenantId}
</select> </select>

View File

@@ -9,11 +9,19 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/ 文档可见https://www.iocoder.cn/MyBatis/x-plugins/
--> -->
<select id="findByStuIdAndPaperId" resultType="pc.exam.pp.module.exam.dal.dataobject.student.StuPaperFileDO"> <select id="findByStuIdAndPaperId" resultType="pc.exam.pp.module.exam.dal.dataobject.student.StuPaperFileDO">
SELECT * FROM exam_stu_paper_fileurl WHERE stu_id = #{stuId} AND paper_id = #{paperId} SELECT *
FROM exam_stu_paper_fileurl
WHERE stu_id = #{stuId}
AND paper_id = #{paperId}
AND temporary_id = #{temporaryId}
</select> </select>
<select id="findOneByStuIdAndPaperId" <select id="findOneByStuIdAndPaperId"
resultType="pc.exam.pp.module.exam.dal.dataobject.student.StuPaperFileDO"> resultType="pc.exam.pp.module.exam.dal.dataobject.student.StuPaperFileDO">
SELECT * FROM exam_stu_paper_fileurl WHERE stu_id = #{stuId} AND paper_id = #{paperId} and type =#{type} SELECT *
FROM exam_stu_paper_fileurl
WHERE stu_id = #{stuId}
AND paper_id = #{paperId}
and type = #{type}
</select> </select>
</mapper> </mapper>

View File

@@ -75,12 +75,12 @@ public interface ErrorCodeConstants {
ErrorCode DEMO03_PAPER_SESSION_EXISTS = new ErrorCode(1_001_401_001, "请开启考场设置!"); ErrorCode DEMO03_PAPER_SESSION_EXISTS = new ErrorCode(1_001_401_001, "请开启考场设置!");
// ========== 试卷方案 1-001-901-900 ========== // ========== 试卷方案 1-001-901-900 ==========
ErrorCode DEMO03_PAPER_TASK_DEL_EXISTS = new ErrorCode(1-001-901-901, "该方案下已有试卷不能删除!"); ErrorCode DEMO03_PAPER_TASK_DEL_EXISTS = new ErrorCode(1_001_901_901, "该方案下已有试卷不能删除!");
ErrorCode DEMO03_PAPER_TASK_ADD_EXISTS = new ErrorCode(1-001-901-901, "该方案下已有试卷不能新增!"); ErrorCode DEMO03_PAPER_TASK_ADD_EXISTS = new ErrorCode(1_001_901_901, "该方案下已有试卷不能新增!");
ErrorCode DEMO03_PAPER_SCHEMES_ADD_EXISTS = new ErrorCode(1-001-902-902, "该方案下已有相同的题型!"); ErrorCode DEMO03_PAPER_SCHEMES_ADD_EXISTS = new ErrorCode(1_001_902_902, "该方案下已有相同的题型!");
// ========== 监控管理 1-001-606-000 ========== // ========== 监控管理 1-001-606-000 ==========
ErrorCode DEMO03_MONITOR_TIME_EXISTS = new ErrorCode(1-001-606-001, "该考试不在考场时间范围内!"); ErrorCode DEMO03_MONITOR_TIME_EXISTS = new ErrorCode(1_001_606_001, "该考试不在考场时间范围内!");
ErrorCode DEMO03_MONITOR_SESSION_EXISTS = new ErrorCode(1-001-606-002, "考生状态未在考试中!请联系管理员"); ErrorCode DEMO03_MONITOR_SESSION_EXISTS = new ErrorCode(1_001_606_002, "考生状态未在考试中!请联系管理员");
} }

View File

@@ -71,7 +71,7 @@ public class FileController {
public CommonResult<String> uploadStuFile(StuFileUploadReqVO uploadReqVO) throws Exception { public CommonResult<String> uploadStuFile(StuFileUploadReqVO uploadReqVO) throws Exception {
MultipartFile file = uploadReqVO.getFile(); MultipartFile file = uploadReqVO.getFile();
String path = uploadReqVO.getPath(); String path = uploadReqVO.getPath();
return success(fileService.createStuFile(uploadReqVO.getStuId(), uploadReqVO.getPaperId(), file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); return success(fileService.createStuFile(uploadReqVO.getStuId(), uploadReqVO.getPaperId(), uploadReqVO.getTemporaryId(), file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
} }
@GetMapping("/{configId}/get/**") @GetMapping("/{configId}/get/**")

View File

@@ -22,4 +22,7 @@ public class StuFileUploadReqVO {
@Schema(description = "试卷ID") @Schema(description = "试卷ID")
private String paperId; private String paperId;
@Schema(description = "临时ID每次做题都会变")
private String temporaryId;
} }

View File

@@ -36,10 +36,11 @@ public interface FileService {
* *
* @param name 文件名称 * @param name 文件名称
* @param path 文件路径 * @param path 文件路径
* @param temporaryId 临时ID
* @param content 文件内容 * @param content 文件内容
* @return 文件路径 * @return 文件路径
*/ */
String createStuFile(Long stuId, String paperId, String name, String path, byte[] content); String createStuFile(Long stuId, String paperId, String temporaryId, String name, String path, byte[] content);
/** /**
* 创建文件 * 创建文件

View File

@@ -78,7 +78,7 @@ public class FileServiceImpl implements FileService {
@Override @Override
@SneakyThrows @SneakyThrows
public String createStuFile(Long stuId, String paperId, String name, String path, byte[] content) { public String createStuFile(Long stuId, String paperId, String temporaryId, String name, String path, byte[] content) {
// 计算默认的 path 名 // 计算默认的 path 名
String type = FileTypeUtils.getMineType(content, name); String type = FileTypeUtils.getMineType(content, name);
if (StrUtil.isEmpty(path)) { if (StrUtil.isEmpty(path)) {
@@ -88,7 +88,6 @@ public class FileServiceImpl implements FileService {
if (StrUtil.isEmpty(name)) { if (StrUtil.isEmpty(name)) {
name = path; name = path;
} }
// 上传到文件存储器 // 上传到文件存储器
FileClient client = fileConfigService.getMasterFileClient(); FileClient client = fileConfigService.getMasterFileClient();
Assert.notNull(client, "客户端(master) 不能为空"); Assert.notNull(client, "客户端(master) 不能为空");
@@ -105,19 +104,22 @@ public class FileServiceImpl implements FileService {
fileMapper.insert(file); fileMapper.insert(file);
// 需要更新学生表 // 需要更新学生表
// 1、先查询学生试卷 是否已经存在数据 // 1、先查询学生试卷 是否已经存在数据
List<StuPaperFileDO> stuPaperFileDOList = stuPaperFileService.findByStuIDAndPaperId(stuId, paperId); List<StuPaperFileDO> stuPaperFileDOList = stuPaperFileService.findByStuIDAndPaperId(stuId, paperId, temporaryId);
StuPaperFileDO stuPaperFileDO = null; StuPaperFileDO stuPaperFileDO = null;
// 如果查询出来数据得话,需要进行替换
for (StuPaperFileDO fileUrl : stuPaperFileDOList) { for (StuPaperFileDO fileUrl : stuPaperFileDOList) {
if (fileUrl.getType() == 0) { if (fileUrl.getType() == 0) {
stuPaperFileDO = fileUrl; stuPaperFileDO = fileUrl;
} }
} }
// 如果没有查询到,需要新增
if (stuPaperFileDO == null) { if (stuPaperFileDO == null) {
// 说明没有上传过,需要新增进去 // 说明没有上传过,需要新增进去
StuPaperFileDO stuPaperFile = new StuPaperFileDO(); StuPaperFileDO stuPaperFile = new StuPaperFileDO();
stuPaperFile.setPaperId(paperId); stuPaperFile.setPaperId(paperId);
stuPaperFile.setStuId(stuId); stuPaperFile.setStuId(stuId);
stuPaperFile.setUrl(url); stuPaperFile.setUrl(url);
stuPaperFile.setTemporaryId(temporaryId);
stuPaperFile.setType(0); stuPaperFile.setType(0);
stuPaperFileService.insertStuPaperFile(stuPaperFile); stuPaperFileService.insertStuPaperFile(stuPaperFile);
} else { } else {