题目的提交方法,增加时间判断,防止网络原因导致提交的不是最新答案

beetlsql3-dev
Mlxa0324 2 years ago
parent cecad09037
commit e8fd79f539

@ -369,6 +369,7 @@ ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_ques
ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_update_time datetime COMMENT '修改时间'; ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_update_time datetime COMMENT '修改时间';
ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_finish_time int(10) default 1 COMMENT '总用时(分钟)'; ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_finish_time int(10) default 1 COMMENT '总用时(分钟)';
ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_reply varchar(300) COMMENT '评语'; ALTER TABLE teacher_open_course_question_log ADD COLUMN teacher_open_course_question_log_reply varchar(300) COMMENT '评语';
ALTER TABLE teacher_open_course_question_log ADD COLUMN question_log_add_type varchar(50) COMMENT '题目添加类型(枚举 QuestionLogAddTypeEnum';
-- 通用的题目配置 -- 通用的题目配置
drop table if exists general_question_setting; drop table if exists general_question_setting;
@ -445,6 +446,7 @@ CREATE TABLE `general_question_log` (
`general_question_log_update_time` datetime COMMENT '修改时间', `general_question_log_update_time` datetime COMMENT '修改时间',
`general_question_log_finish_time` int(10) default 1 COMMENT '总用时(分钟)', `general_question_log_finish_time` int(10) default 1 COMMENT '总用时(分钟)',
`general_question_log_reply` varchar(300) default 1 COMMENT '评语', `general_question_log_reply` varchar(300) default 1 COMMENT '评语',
`question_log_add_type` varchar(50) COMMENT '题目添加类型(枚举 QuestionLogAddTypeEnum',
`org_id` bigint(20) DEFAULT NULL COMMENT '组织ID', `org_id` bigint(20) DEFAULT NULL COMMENT '组织ID',
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID', `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
PRIMARY KEY (`general_question_log_id`) USING BTREE PRIMARY KEY (`general_question_log_id`) USING BTREE

@ -26,6 +26,9 @@ import java.lang.reflect.Field;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static cn.jlw.util.excel.ExcelSelector.ID_SEPARATOR;
@Slf4j @Slf4j
public class ExcelUtil { public class ExcelUtil {
@ -311,4 +314,16 @@ public class ExcelUtil {
} }
return selectedMap; return selectedMap;
} }
public static <T extends Number> T longValuesOf(String text) {
return (T) Long.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
}
public static <T extends Number> T bigDecimalValuesOf(String text) {
return (T) Long.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
}
public static <T extends Number> T integerValuesOf(String text) {
return (T) Integer.valueOf(Objects.requireNonNull(text.split(ID_SEPARATOR)[1], text + "字段必须要有___ID:的分隔符"));
}
} }

@ -10,6 +10,7 @@ import org.beetl.sql.mapper.annotation.SqlResource;
import org.beetl.sql.mapper.annotation.Update; import org.beetl.sql.mapper.annotation.Update;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -55,5 +56,15 @@ public interface GeneralQuestionLogDao extends BaseMapper<GeneralQuestionLog> {
* @return * @return
*/ */
PageQuery<GeneralQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query); PageQuery<GeneralQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query);
/**
*
* @param questionSettingId ID
* @param questionSnapshotIds ID
* @param studentId ID
* @param addTime
* @return
*/
boolean validateQuestionLogAddTimeLatest(Long questionSettingId, String questionSnapshotIds, Long studentId, Date addTime);
} }

@ -9,6 +9,7 @@ import org.beetl.sql.mapper.annotation.SqlResource;
import org.beetl.sql.mapper.annotation.Update; import org.beetl.sql.mapper.annotation.Update;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List; import java.util.List;
/** /**
@ -60,4 +61,14 @@ public interface TeacherOpenCourseQuestionLogDao extends BaseMapper<TeacherOpenC
* @return * @return
*/ */
PageQuery<TeacherOpenCourseQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query); PageQuery<TeacherOpenCourseQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query);
/**
*
* @param questionSettingId ID
* @param questionSnapshotIds ID
* @param studentId ID
* @param addTime
* @return
*/
boolean validateQuestionLogAddTimeLatest(Long questionSettingId, String questionSnapshotIds, Long studentId, Date addTime);
} }

@ -4,6 +4,7 @@ import com.ibeetl.admin.core.annotation.Dict;
import com.ibeetl.admin.core.entity.BaseEntity; import com.ibeetl.admin.core.entity.BaseEntity;
import com.ibeetl.admin.core.util.ValidateConfig; import com.ibeetl.admin.core.util.ValidateConfig;
import com.ibeetl.jlw.enums.GeneralResourcesQuestionLogTypeEnum; import com.ibeetl.jlw.enums.GeneralResourcesQuestionLogTypeEnum;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.beetl.sql.annotation.entity.AssignID; import org.beetl.sql.annotation.entity.AssignID;
@ -59,6 +60,10 @@ public class GeneralQuestionLog extends BaseEntity{
@Dict(type="global_status") @Dict(type="global_status")
private Integer generalQuestionLogStatus ; private Integer generalQuestionLogStatus ;
// 题目提交类型
private QuestionLogAddTypeEnum questionLogAddType;
//学生ID //学生ID

@ -7,8 +7,9 @@ import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.ibeetl.admin.core.annotation.Dict; import com.ibeetl.admin.core.annotation.Dict;
import com.ibeetl.admin.core.entity.BaseEntity; import com.ibeetl.admin.core.entity.BaseEntity;
import com.ibeetl.admin.core.util.ValidateConfig; import com.ibeetl.admin.core.util.ValidateConfig;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.beetl.sql.annotation.entity.AssignID; import org.beetl.sql.annotation.entity.AssignID;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@ -20,11 +21,12 @@ import static cn.jlw.util.excel.ExcelSelector.ID_SEPARATOR;
* --线 * --线
* gen by Spring Boot2 Admin 2022-10-26 * gen by Spring Boot2 Admin 2022-10-26
*/ */
@ToString @Builder
@AllArgsConstructor
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
@EqualsAndHashCode(callSuper=false) @EqualsAndHashCode(callSuper=false)
@HeadFontStyle(fontName = "仿宋", fontHeightInPoints = 12) @HeadFontStyle(fontName = "仿宋", fontHeightInPoints = 12)
public class TeacherOpenCourseMergeResourcesQuestion extends BaseEntity{ public class TeacherOpenCourseMergeResourcesQuestion extends BaseEntity {
//ID //ID
@NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class) @NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class)

@ -0,0 +1,106 @@
package com.ibeetl.jlw.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.ibeetl.admin.core.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import static cn.jlw.util.excel.ExcelUtil.*;
/**
* --线
* @author lx
*/
@Data
@ExcelIgnoreUnannotated
@EqualsAndHashCode(callSuper=false)
public class TeacherOpenCourseMergeResourcesQuestionImport extends BaseEntity {
//ID
private String teacherOpenCourseMergeResourcesQuestionId ;
//开课ID
private String teacherOpenCourseId ;
//课程章节ID
private String teacherOpenCourseMergeCourseInfoId ;
//题型(1单选 2多选 3判断 4填空 5分析)
private String questionType ;
//分值
private String questionScore ;
//题干
private String questionStem ;
//选项A
private String questionOptionA ;
//选项B
private String questionOptionB ;
//选项C
private String questionOptionC ;
//选项D
private String questionOptionD ;
//选项E
private String questionOptionE ;
//答案(单选是一个 多选是多个 判断是对错)
private String questionAnswer ;
//解析
private String questionAnalysis ;
//题目状态 1上架 2下架
private String questionStatus ;
//后台用户ID
private String userId ;
//组织机构ID
private String orgId ;
/**
*
* @param importPojo
* @return
*/
public static TeacherOpenCourseMergeResourcesQuestion pojo(TeacherOpenCourseMergeResourcesQuestionImport importPojo) {
return TeacherOpenCourseMergeResourcesQuestion.builder()
.teacherOpenCourseMergeCourseInfoId(longValuesOf(importPojo.getTeacherOpenCourseMergeCourseInfoId()))
.teacherOpenCourseId(longValuesOf(importPojo.getTeacherOpenCourseId()))
.questionType(integerValuesOf(importPojo.getTeacherOpenCourseId()))
.questionScore(bigDecimalValuesOf(importPojo.getTeacherOpenCourseId()))
.questionStem(importPojo.getQuestionStem())
.questionOptionA(importPojo.getQuestionOptionA())
.questionOptionB(importPojo.getQuestionOptionB())
.questionOptionC(importPojo.getQuestionOptionC())
.questionOptionD(importPojo.getQuestionOptionD())
.questionOptionE(importPojo.getQuestionOptionE())
.questionAnswer(importPojo.getQuestionAnswer())
.questionAnalysis(importPojo.getQuestionAnalysis())
.questionStatus(1)
.build();
}
}

@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.ibeetl.admin.core.annotation.Dict; import com.ibeetl.admin.core.annotation.Dict;
import com.ibeetl.admin.core.entity.BaseEntity; import com.ibeetl.admin.core.entity.BaseEntity;
import com.ibeetl.admin.core.util.ValidateConfig; import com.ibeetl.admin.core.util.ValidateConfig;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.enums.ResourcesQuestionTypeEnum; import com.ibeetl.jlw.enums.ResourcesQuestionTypeEnum;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -57,6 +58,10 @@ public class TeacherOpenCourseQuestionLog extends BaseEntity {
@Dict(type="global_status") @Dict(type="global_status")
private Integer teacherOpenCourseQuestionLogStatus ; private Integer teacherOpenCourseQuestionLogStatus ;
// 题目提交类型
private QuestionLogAddTypeEnum questionLogAddType;
//学生ID //学生ID

@ -0,0 +1,57 @@
package com.ibeetl.jlw.entity.dto;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import lombok.Data;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.Map;
import java.util.TreeSet;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.PRE_SUBMIT;
/**
* <p>
* GeneralTeacherOpenCourse
*
* </p>
*
* @author mlx
* @date 2022/11/27
* @modified
*/
@Data
public class QuestionLogAddDTO {
/**
* ID
*/
@NotNull(message = "题目配置ID")
private Long questionSettingId;
/**
* <ID, []> {"10086": ["D", "A", "B", "A"]}
* questionLogMapvalue,Key
*/
@NotEmpty(message = "提交答案不能为空")
private Map<String, TreeSet<String>> questionLogMap;
/**
*
*/
@NotNull(message = "提交时间不能为空")
private Date addTime;
/**
*
*/
@Nullable
private QuestionLogAddTypeEnum questionLogAddType;
public QuestionLogAddDTO() {
// 默认值
setQuestionLogAddType(PRE_SUBMIT);
}
}

@ -0,0 +1,22 @@
package com.ibeetl.jlw.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.beetl.sql.annotation.entity.EnumMapping;
/**
*
* @author lx
*/
@Getter
@AllArgsConstructor
@EnumMapping("name")
public enum QuestionLogAddTypeEnum {
FINALLY_SUBMIT("最终提交"),
PRE_SUBMIT("预提交");
private String text;
}

@ -18,6 +18,8 @@ import com.ibeetl.admin.core.web.JsonReturnCode;
import com.ibeetl.jlw.dao.GeneralQuestionLogDao; import com.ibeetl.jlw.dao.GeneralQuestionLogDao;
import com.ibeetl.jlw.dao.StudentDao; import com.ibeetl.jlw.dao.StudentDao;
import com.ibeetl.jlw.entity.*; import com.ibeetl.jlw.entity.*;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.web.query.GeneralQuestionLogQuery; import com.ibeetl.jlw.web.query.GeneralQuestionLogQuery;
import com.ibeetl.jlw.web.query.GeneralQuestionSettingQuery; import com.ibeetl.jlw.web.query.GeneralQuestionSettingQuery;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -473,12 +475,12 @@ public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLo
* *
* *
* *
* @param questionLogMap <ID, []> {"10086": ["D", "A", "B", "A"]} * @param questionLogAddDTO
* @param questionSettingId ID
*/ */
public void insertQuestionLog( public void insertQuestionLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO) {
@NotEmpty(message = "请上传题目快照ID和答案") Map<String, TreeSet<String>> questionLogMap,
@NotNull(message = "通用题目配置ID不能为空") final Long questionSettingId) { Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, TreeSet<String>> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询学生身份 // 查询学生身份
final Student student = getStudent(); final Student student = getStudent();
@ -487,7 +489,7 @@ public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLo
GeneralQuestionSetting info = generalQuestionSettingService.getInfo(questionSettingId); GeneralQuestionSetting info = generalQuestionSettingService.getInfo(questionSettingId);
Assert.notNull(info, "题目配置ID有误"); Assert.notNull(info, "题目配置ID有误");
// 校验时间 // 校验当前时间是否在考试的时间段
generalQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId); generalQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId);
switch(info.getGeneralQuestionSettingType()) { switch(info.getGeneralQuestionSettingType()) {
@ -499,7 +501,7 @@ public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLo
case CHAPTER_EXERCISE: case CHAPTER_EXERCISE:
case EXAM: case EXAM:
case HOMEWORK_QUESTION:{ case HOMEWORK_QUESTION:{
addQuestionRelatedLog(questionLogMap, questionSettingId, student); addQuestionRelatedLog(questionLogAddDTO, student);
} break; } break;
} }
} }
@ -527,11 +529,16 @@ public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLo
* *
* *
* *
* @param questionLogMap * @param questionLogAddDTO
* @param questionSettingId * @param student
* @param student
*/ */
private void addQuestionRelatedLog(Map<String, TreeSet<String>> questionLogMap, Long questionSettingId, Student student) { private void addQuestionRelatedLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO, Student student) {
// 参数获取
QuestionLogAddTypeEnum addType = questionLogAddDTO.getQuestionLogAddType();
Date addTime = questionLogAddDTO.getAddTime(); Long studentId = student.getStudentId();
Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, TreeSet<String>> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询符合条件的日志表 // 查询符合条件的日志表
String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ","); String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ",");
@ -547,31 +554,50 @@ public class GeneralQuestionLogService extends CoreBaseService<GeneralQuestionLo
Assert.notEmpty(logList, "未查询到题目信息!"); Assert.notEmpty(logList, "未查询到题目信息!");
// 当前时间 // 当前时间, 存储要更新的题目日志集合
Date now = new Date(); Date now = new Date(); List<GeneralQuestionLog> updateList = new ArrayList<>();
// 处理答案和分数 // 处理答案和分数
logList.forEach(questionLog -> { logList.forEach(questionLog -> {
// 这里判断题目只允许做一次,禁止二次提交 // 验证最新的提交时间,防止网络延迟
Assert.isNull(questionLog.getGeneralQuestionLogUpdateTime(), if (!validateQuestionLogAddTimeLatest(questionSettingId, questionLog.getGeneralResourcesQuestionSnapshotId().toString(), studentId, addTime)) {
"题目名称:{} 题目禁止重复提交!", questionLog.getQuestionStem()); return;
}
Assert.isTrue(!questionLog.getQuestionLogAddType().equals(addType), "无法再次提交答案,题目已完成!");
// 学生提交的答案 // 学生提交的答案
String answersText = join(questionLogMap.get(questionLog.getGeneralResourcesQuestionSnapshotId()).toArray(), ","); String answersText = join(questionLogMap.get(questionLog.getGeneralResourcesQuestionSnapshotId()).toArray(), ",");
questionLog.setGeneralQuestionLogAnswer(answersText);
// 是否是正确答案 // 是否是正确答案
Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText); Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText);
// 计算该题目学生的得分情况 // 计算该题目学生的得分情况
questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : BigDecimal.valueOf(0)); questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : BigDecimal.valueOf(0));
// 完成时间
long finishTime = DateUtil.between(questionLog.getGeneralQuestionLogAddTime(), now, MINUTE);
// 填充属性
questionLog.setGeneralQuestionLogUpdateTime(now); questionLog.setGeneralQuestionLogUpdateTime(now);
long finishTime = DateUtil.between(questionLog.getGeneralQuestionLogAddTime(), now, MINUTE);
questionLog.setGeneralQuestionLogFinishTime(finishTime); questionLog.setGeneralQuestionLogFinishTime(finishTime);
questionLog.setGeneralQuestionLogAnswer(answersText);
questionLog.setQuestionLogAddType(addType);
updateList.add(questionLog);
}); });
// 学生做的题目的答案与日志关联 // 学生做的题目的答案与日志关联
updateBatchTemplate(logList); updateBatchTemplate(updateList);
}
/**
*
* @param questionSettingId ID
* @param questionSnapshotIds ID
* @param studentId ID
* @param addTime
* @return
*/
private boolean validateQuestionLogAddTimeLatest(@NotNull(message = "开课题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapshotIds,
@NotNull(message = "学生ID不能为空") Long studentId,
@NotNull(message = "提交时间不能为空!") Date addTime) {
return generalQuestionLogDao.validateQuestionLogAddTimeLatest(questionSettingId, questionSnapshotIds, studentId, addTime);
} }
/** /**

@ -17,6 +17,8 @@ import com.ibeetl.jlw.dao.ResourcesQuestionSnapshotDao;
import com.ibeetl.jlw.dao.StudentDao; import com.ibeetl.jlw.dao.StudentDao;
import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionLogDao; import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionLogDao;
import com.ibeetl.jlw.entity.*; import com.ibeetl.jlw.entity.*;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogQuery; import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionSettingQuery; import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionSettingQuery;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -42,6 +44,7 @@ import static cn.hutool.core.date.DateUnit.MINUTE;
import static cn.hutool.core.util.ArrayUtil.join; import static cn.hutool.core.util.ArrayUtil.join;
import static cn.jlw.util.CacheUserUtil.getStudent; import static cn.jlw.util.CacheUserUtil.getStudent;
import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUserId; import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUserId;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.FINALLY_SUBMIT;
import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.EXAM; import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.EXAM;
import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.groupingBy;
@ -275,12 +278,12 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
* *
* *
* *
* @param questionLogMap <ID, []> {"10086": ["D", "A", "B", "A"]} * @param questionLogAddDTO
* @param questionSettingId ID
*/ */
public void insertQuestionLog( public void insertQuestionLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO) {
@NotEmpty(message = "请上传题目快照ID和答案") Map<String, TreeSet<String>> questionLogMap,
@NotNull(message = "开课题目配置ID不能为空") final Long questionSettingId) { Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, TreeSet<String>> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询学生身份 // 查询学生身份
final Student student = getStudent(); final Student student = getStudent();
@ -289,7 +292,7 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
TeacherOpenCourseQuestionSetting info = teacherOpenCourseQuestionSettingService.getInfo(questionSettingId); TeacherOpenCourseQuestionSetting info = teacherOpenCourseQuestionSettingService.getInfo(questionSettingId);
Assert.notNull(info, "题目配置ID有误"); Assert.notNull(info, "题目配置ID有误");
// 校验时间 // 校验当前时间是否在考试的时间段
teacherOpenCourseQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId); teacherOpenCourseQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId);
switch(info.getTeacherOpenCourseQuestionSettingType()) { switch(info.getTeacherOpenCourseQuestionSettingType()) {
@ -301,7 +304,7 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
case CHAPTER_EXERCISE: case CHAPTER_EXERCISE:
case EXAM: case EXAM:
case HOMEWORK_QUESTION:{ case HOMEWORK_QUESTION:{
addQuestionRelatedLog(questionLogMap, questionSettingId, student); addQuestionRelatedLog(questionLogAddDTO, student);
} break; } break;
} }
} }
@ -320,6 +323,8 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
query.setTeacherOpenCourseQuestionSettingId(questionSettingId); query.setTeacherOpenCourseQuestionSettingId(questionSettingId);
query.setTeacherOpenCourseQuestionLogUpdateTime(new Date()); query.setTeacherOpenCourseQuestionLogUpdateTime(new Date());
query.setTeacherOpenCourseQuestionLogStatus(1); query.setTeacherOpenCourseQuestionLogStatus(1);
// 附件作业,只有一题,所有默认是全部提交的方式
query.setQuestionLogAddType(FINALLY_SUBMIT);
query.setOrgId(student.getOrgId()); query.setOrgId(student.getOrgId());
query.setUserId(student.getUserId()); query.setUserId(student.getUserId());
query.setStudentId(student.getStudentId()); query.setStudentId(student.getStudentId());
@ -330,11 +335,17 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
* *
* *
* *
* @param questionLogMap * @param questionLogAddDTO
* @param questionSettingId * @param student
* @param student
*/ */
private void addQuestionRelatedLog(Map<String, TreeSet<String>> questionLogMap, Long questionSettingId, Student student) { private void addQuestionRelatedLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO, final Student student) {
// 参数获取
QuestionLogAddTypeEnum addType = questionLogAddDTO.getQuestionLogAddType();
Date addTime = questionLogAddDTO.getAddTime(); Long studentId = student.getStudentId();
Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, TreeSet<String>> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询符合条件的日志表 // 查询符合条件的日志表
String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ","); String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ",");
@ -350,33 +361,55 @@ public class TeacherOpenCourseQuestionLogService extends CoreBaseService<Teacher
Assert.notEmpty(logList, "未查询到题目信息!"); Assert.notEmpty(logList, "未查询到题目信息!");
// 当前时间 // 当前时间, 存储要更新的题目日志集合
Date now = new Date(); Date now = new Date(); List<TeacherOpenCourseQuestionLog> updateList = new ArrayList<>();
// 处理答案和分数 // 处理答案和分数
logList.forEach(questionLog -> { logList.forEach(questionLog -> {
// 这里判断题目只允许做一次,禁止二次提交 // 验证最新的提交时间,防止网络延迟
Assert.isNull(questionLog.getTeacherOpenCourseQuestionLogUpdateTime(), if (!validateQuestionLogAddTimeLatest(questionSettingId, questionLog.getResourcesQuestionSnapshotId().toString(), studentId, addTime)) {
"题目名称:{} 题目禁止重复提交!", questionLog.getQuestionStem()); return;
}
Assert.isTrue(!questionLog.getQuestionLogAddType().equals(addType), "无法再次提交答案,题目已完成!");
// 学生提交的答案 // 学生提交的答案
String answersText = join(questionLogMap.get(questionLog.getResourcesQuestionSnapshotId()).toArray(), ","); String answersText = join(questionLogMap.get(questionLog.getResourcesQuestionSnapshotId()).toArray(), ",");
questionLog.setTeacherOpenCourseQuestionLogAnswer(answersText);
// 是否是正确答案 // 是否是正确答案
Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText); Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText);
// 完成时间
long finishTime = DateUtil.between(questionLog.getTeacherOpenCourseQuestionLogAddTime(), now, MINUTE);
// 填充属性
questionLog.setTeacherOpenCourseQuestionLogAnswer(answersText);
// 计算该题目学生的得分情况 // 计算该题目学生的得分情况
questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : BigDecimal.valueOf(0)); questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : BigDecimal.valueOf(0));
questionLog.setTeacherOpenCourseQuestionLogUpdateTime(now); questionLog.setTeacherOpenCourseQuestionLogUpdateTime(now);
long finishTime = DateUtil.between(questionLog.getTeacherOpenCourseQuestionLogAddTime(), now, MINUTE);
questionLog.setTeacherOpenCourseQuestionLogFinishTime(finishTime); questionLog.setTeacherOpenCourseQuestionLogFinishTime(finishTime);
questionLog.setQuestionLogAddType(addType);
// 只添加可以更新的数据
updateList.add(questionLog);
}); });
// 批量插入错题集错题库方法内部自带分数判断。内部方法更新log中的错题标记。 // 批量插入错题集错题库方法内部自带分数判断。内部方法更新log中的错题标记。
teacherOpenCourseQuestionLogWrongService.insertBatchByQuestionLogList(logList); teacherOpenCourseQuestionLogWrongService.insertBatchByQuestionLogList(logList);
// 学生做的题目的答案与日志关联 // 学生做的题目的答案与日志关联
updateBatchTemplate(logList); updateBatchTemplate(updateList);
}
/**
*
* @param questionSettingId ID
* @param questionSnapshotIds ID
* @param studentId ID
* @param addTime
* @return
*/
private boolean validateQuestionLogAddTimeLatest(@NotNull(message = "开课题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapshotIds,
@NotNull(message = "学生ID不能为空") Long studentId,
@NotNull(message = "提交时间不能为空!") Date addTime) {
return teacherOpenCourseQuestionLogDao.validateQuestionLogAddTimeLatest(questionSettingId, questionSnapshotIds, studentId, addTime);
} }
/** /**

@ -18,6 +18,7 @@ import com.ibeetl.admin.core.web.query.PageParam;
import com.ibeetl.jlw.entity.FileEntity; import com.ibeetl.jlw.entity.FileEntity;
import com.ibeetl.jlw.entity.GeneralQuestionLog; import com.ibeetl.jlw.entity.GeneralQuestionLog;
import com.ibeetl.jlw.entity.Student; import com.ibeetl.jlw.entity.Student;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.service.GeneralQuestionLogService; import com.ibeetl.jlw.service.GeneralQuestionLogService;
import com.ibeetl.jlw.web.query.GeneralQuestionLogQuery; import com.ibeetl.jlw.web.query.GeneralQuestionLogQuery;
import com.ibeetl.jlw.web.query.GeneralQuestionLogScoreDetailsInfoQuery; import com.ibeetl.jlw.web.query.GeneralQuestionLogScoreDetailsInfoQuery;
@ -107,23 +108,15 @@ public class GeneralQuestionLogController{
* - * -
* <li> </li> * <li> </li>
* *
* @param questionLogMap * @param questionLogAddDTO
* <ID, []> {"10086": ["D", "A", "B", "A"]}
* questionLogMapvalue,Key
* @param questionSettingId ID
* @param coreUser Service * @param coreUser Service
* @return * @return
*/ */
@PostMapping(API + "/addQuestionLog.do") @PostMapping(API + "/addQuestionLog.do")
@ResponseBody @ResponseBody
public JsonResult addQuestionLog( public JsonResult addQuestionLog(@RequestBody QuestionLogAddDTO questionLogAddDTO, @SCoreUser CoreUser coreUser) {
@RequestBody
Map<String, TreeSet<String>> questionLogMap,
Long questionSettingId,
@SCoreUser
CoreUser coreUser) {
Assert.isTrue(coreUser.isStudent(), "非学生身份,无法提交!"); Assert.isTrue(coreUser.isStudent(), "非学生身份,无法提交!");
generalQuestionLogService.insertQuestionLog(questionLogMap, questionSettingId); generalQuestionLogService.insertQuestionLog(questionLogAddDTO);
return JsonResult.success(); return JsonResult.success();
} }

@ -9,7 +9,6 @@ import cn.jlw.Interceptor.RFile;
import cn.jlw.Interceptor.SCoreUser; import cn.jlw.Interceptor.SCoreUser;
import cn.jlw.util.ToolUtils; import cn.jlw.util.ToolUtils;
import cn.jlw.util.excel.ExcelUtil; import cn.jlw.util.excel.ExcelUtil;
import cn.jlw.util.excel.MyExcelCellDataListener;
import cn.jlw.validate.ValidateConfig; import cn.jlw.validate.ValidateConfig;
import com.ibeetl.admin.core.annotation.Function; import com.ibeetl.admin.core.annotation.Function;
import com.ibeetl.admin.core.entity.CoreUser; import com.ibeetl.admin.core.entity.CoreUser;
@ -18,6 +17,7 @@ import com.ibeetl.admin.core.util.TimeTool;
import com.ibeetl.admin.core.web.JsonResult; import com.ibeetl.admin.core.web.JsonResult;
import com.ibeetl.jlw.entity.FileEntity; import com.ibeetl.jlw.entity.FileEntity;
import com.ibeetl.jlw.entity.TeacherOpenCourseMergeResourcesQuestion; import com.ibeetl.jlw.entity.TeacherOpenCourseMergeResourcesQuestion;
import com.ibeetl.jlw.entity.TeacherOpenCourseMergeResourcesQuestionImport;
import com.ibeetl.jlw.service.TeacherOpenCourseMergeResourcesQuestionService; import com.ibeetl.jlw.service.TeacherOpenCourseMergeResourcesQuestionService;
import com.ibeetl.jlw.web.query.TeacherOpenCourseMergeResourcesQuestionQuery; import com.ibeetl.jlw.web.query.TeacherOpenCourseMergeResourcesQuestionQuery;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ -51,6 +51,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import static cn.jlw.util.CacheUserUtil.getStudent; import static cn.jlw.util.CacheUserUtil.getStudent;
import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUser; import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUser;
@ -505,11 +506,12 @@ public class TeacherOpenCourseMergeResourcesQuestionController extends BaseContr
Assert.notNull(getUser(), "请登录后再操作"); Assert.notNull(getUser(), "请登录后再操作");
Assert.isNull(getStudent(), "学生无法访问该接口"); Assert.isNull(getStudent(), "学生无法访问该接口");
MyExcelCellDataListener<TeacherOpenCourseMergeResourcesQuestion> myExcelCellDataListener = new MyExcelCellDataListener();
// 输出 Excel // 输出 Excel
ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestion.class, myExcelCellDataListener); List<TeacherOpenCourseMergeResourcesQuestionImport> list =
ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestionImport.class);
List<TeacherOpenCourseMergeResourcesQuestion> options = myExcelCellDataListener.getData(); // 类型转换
List<TeacherOpenCourseMergeResourcesQuestion> options = list.stream()
.map(TeacherOpenCourseMergeResourcesQuestionImport::pojo).collect(Collectors.toList());
for (Object option : options) { for (Object option : options) {
System.out.println(option); System.out.println(option);

@ -13,6 +13,7 @@ import com.ibeetl.admin.core.web.JsonResult;
import com.ibeetl.admin.core.web.query.PageParam; import com.ibeetl.admin.core.web.query.PageParam;
import com.ibeetl.jlw.entity.Student; import com.ibeetl.jlw.entity.Student;
import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionLog; import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionLog;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.service.TeacherOpenCourseQuestionLogService; import com.ibeetl.jlw.service.TeacherOpenCourseQuestionLogService;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogQuery; import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogScoreDetailsInfoQuery; import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogScoreDetailsInfoQuery;
@ -109,23 +110,15 @@ public class TeacherOpenCourseQuestionLogController {
* - * -
* <li> </li> * <li> </li>
* *
* @param questionLogMap * @param questionLogAddDTO
* <ID, []> {"10086": ["D", "A", "B", "A"]}
* questionLogMapvalue,Key
* @param questionSettingId ID
* @param coreUser Service * @param coreUser Service
* @return * @return
*/ */
@PostMapping(API + "/addQuestionLog.do") @PostMapping(API + "/addQuestionLog.do")
@ResponseBody @ResponseBody
public JsonResult addQuestionLog( public JsonResult addQuestionLog(@RequestBody QuestionLogAddDTO questionLogAddDTO, @SCoreUser CoreUser coreUser) {
@RequestBody
Map<String, TreeSet<String>> questionLogMap,
Long questionSettingId,
@SCoreUser
CoreUser coreUser) {
Assert.isTrue(coreUser.isStudent(), "非学生身份,无法提交!"); Assert.isTrue(coreUser.isStudent(), "非学生身份,无法提交!");
teacherOpenCourseQuestionLogService.insertQuestionLog(questionLogMap, questionSettingId); teacherOpenCourseQuestionLogService.insertQuestionLog(questionLogAddDTO);
return JsonResult.success(); return JsonResult.success();
} }

@ -5,6 +5,7 @@ import com.ibeetl.admin.core.annotation.Query;
import com.ibeetl.admin.core.web.query.PageParam; import com.ibeetl.admin.core.web.query.PageParam;
import com.ibeetl.jlw.entity.GeneralQuestionLog; import com.ibeetl.jlw.entity.GeneralQuestionLog;
import com.ibeetl.jlw.enums.GeneralResourcesQuestionLogTypeEnum; import com.ibeetl.jlw.enums.GeneralResourcesQuestionLogTypeEnum;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -42,6 +43,8 @@ public class GeneralQuestionLogQuery extends PageParam {
private Date generalQuestionLogAddTime; private Date generalQuestionLogAddTime;
@Query(name = "状态1正常 2删除", display = true,type=Query.TYPE_DICT,dict="global_status") @Query(name = "状态1正常 2删除", display = true,type=Query.TYPE_DICT,dict="global_status")
private Integer generalQuestionLogStatus; private Integer generalQuestionLogStatus;
@Query(name = "题目提交类型", display = false)
private QuestionLogAddTypeEnum questionLogAddType;
@Query(name = "学生ID", display = false) @Query(name = "学生ID", display = false)
private Long studentId; private Long studentId;
@Query(name = "学生得分", display = false) @Query(name = "学生得分", display = false)
@ -121,6 +124,7 @@ public class GeneralQuestionLogQuery extends PageParam {
pojo.setGeneralQuestionLogUpdateTime(this.getGeneralQuestionLogUpdateTime()); pojo.setGeneralQuestionLogUpdateTime(this.getGeneralQuestionLogUpdateTime());
pojo.setGeneralQuestionLogFinishTime(this.getGeneralQuestionLogFinishTime()); pojo.setGeneralQuestionLogFinishTime(this.getGeneralQuestionLogFinishTime());
pojo.setGeneralQuestionLogReply(this.getGeneralQuestionLogReply()); pojo.setGeneralQuestionLogReply(this.getGeneralQuestionLogReply());
pojo.setQuestionLogAddType(this.getQuestionLogAddType());
pojo.setOrgId(this.getOrgId()); pojo.setOrgId(this.getOrgId());
pojo.setUserId(this.getUserId()); pojo.setUserId(this.getUserId());
return pojo; return pojo;

@ -4,6 +4,7 @@ import cn.jlw.validate.ValidateConfig;
import com.ibeetl.admin.core.annotation.Query; import com.ibeetl.admin.core.annotation.Query;
import com.ibeetl.admin.core.web.query.PageParam; import com.ibeetl.admin.core.web.query.PageParam;
import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionLog; import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionLog;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -36,6 +37,8 @@ public class TeacherOpenCourseQuestionLogQuery extends PageParam {
private Date teacherOpenCourseQuestionLogAddTime; private Date teacherOpenCourseQuestionLogAddTime;
@Query(name = "状态1正常 2删除", display = true,type=Query.TYPE_DICT,dict="global_status") @Query(name = "状态1正常 2删除", display = true,type=Query.TYPE_DICT,dict="global_status")
private Integer teacherOpenCourseQuestionLogStatus; private Integer teacherOpenCourseQuestionLogStatus;
@Query(name = "题目提交类型", display = false)
private QuestionLogAddTypeEnum questionLogAddType;
@Query(name = "学生ID", display = false) @Query(name = "学生ID", display = false)
private Long studentId; private Long studentId;
@Query(name = "组织ID", display = false) @Query(name = "组织ID", display = false)
@ -149,6 +152,7 @@ public class TeacherOpenCourseQuestionLogQuery extends PageParam {
pojo.setTeacherOpenCourseQuestionLogUpdateTime(this.getTeacherOpenCourseQuestionLogUpdateTime()); pojo.setTeacherOpenCourseQuestionLogUpdateTime(this.getTeacherOpenCourseQuestionLogUpdateTime());
pojo.setTeacherOpenCourseQuestionLogFinishTime(this.getTeacherOpenCourseQuestionLogFinishTime()); pojo.setTeacherOpenCourseQuestionLogFinishTime(this.getTeacherOpenCourseQuestionLogFinishTime());
pojo.setTeacherOpenCourseQuestionLogReply(this.getTeacherOpenCourseQuestionLogReply()); pojo.setTeacherOpenCourseQuestionLogReply(this.getTeacherOpenCourseQuestionLogReply());
pojo.setQuestionLogAddType(this.getQuestionLogAddType());
return pojo; return pojo;
} }

@ -1221,4 +1221,19 @@ getQuestionLogScoreDetailsInfo
ta.student_sn, ta.student_sn,
ta.class_id, ta.class_id,
tb.class_name tb.class_name
) tz ) tz
validateQuestionLogAddTimeLatest
===
* 验证前端传递过来的添加时间是否是最新的
select
if(t.general_question_log_update_time is null, true, t.general_question_log_update_time < #addTime#)
from
general_question_log t
where 1 = 1
and t.general_question_setting_id = #questionSettingId#
and FIND_IN_SET(t.general_resources_question_snapshot_id, #questionSnapshotIds#)
and t.student_id = #studentId#
and t.general_question_log_status = 1
order by general_question_log_add_time desc
limit 1

@ -732,3 +732,19 @@ getQuestionLogScoreDetailsInfo
ta.class_id, ta.class_id,
tb.class_name tb.class_name
) tz ) tz
validateQuestionLogAddTimeLatest
===
* 验证前端传递过来的添加时间是否是最新的
select
if(t.teacher_open_course_question_log_update_time is null, true, t.teacher_open_course_question_log_update_time < #addTime#)
from
teacher_open_course_question_log t
where 1 = 1
and t.teacher_open_course_question_setting_id = #questionSettingId#
and FIND_IN_SET(t.resources_question_snapshot_id, #questionSnapshotIds#)
and t.student_id = #studentId#
and t.teacher_open_course_question_log_status = 1
order by teacher_open_course_question_log_add_time desc
limit 1

Loading…
Cancel
Save