wangliang 4 лет назад
Родитель
Сommit
14c8ea1173

+ 8 - 2
themis-business/src/main/java/com/qmth/themis/business/bean/backend/InvigilateListVideoBean.java

@@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * @Description: 实时监控台视频返回对象
@@ -312,10 +313,15 @@ public class InvigilateListVideoBean implements Serializable {
     }
 
     public String getStatus() {
-        if (statusCode != null) {
+        if (statusCode != null && Objects.equals(ExamRecordStatusEnum.FIRST_PREPARE, statusCode)) {
+            return "已待考";
+        } else if (statusCode != null && Objects.equals(ExamRecordStatusEnum.BREAK_OFF, statusCode)) {
+            return "通讯故障";
+        } else if (statusCode != null && Objects.equals(ExamRecordStatusEnum.ANSWERING, statusCode) || Objects.equals(ExamRecordStatusEnum.RESUME_PREPARE, statusCode)) {
+            return "考试中";
+        } else {
             return statusCode.getCode();
         }
-        return status;
     }
 
     public void setStatus(String status) {

+ 37 - 0
themis-business/src/main/java/com/qmth/themis/business/dto/ExcelDto.java

@@ -0,0 +1,37 @@
+package com.qmth.themis.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: excel动态通用dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/10/21
+ */
+public class ExcelDto implements Serializable {
+
+    @ApiModelProperty(name = "标题")
+    private String title;
+
+    @ApiModelProperty(name = "内容")
+    private String content;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+}

+ 15 - 3
themis-business/src/main/java/com/qmth/themis/business/dto/MarkResultSimpleExportDto.java

@@ -73,18 +73,30 @@ public class MarkResultSimpleExportDto implements Serializable {
     @ExcelNote(value = "总分")
     private String sumScore;
 
+    @ApiModelProperty(value = "考试记录ID")
+    @ExcelNotExport
+    private Long recordId;
+
     @ApiModelProperty(value = "试卷ID")
     @ExcelNotExport
-    private String paperId;
+    private Long paperId;
 
-    public String getPaperId() {
+    public Long getPaperId() {
         return paperId;
     }
 
-    public void setPaperId(String paperId) {
+    public void setPaperId(Long paperId) {
         this.paperId = paperId;
     }
 
+    public Long getRecordId() {
+        return recordId;
+    }
+
+    public void setRecordId(Long recordId) {
+        this.recordId = recordId;
+    }
+
     public String getRoomCode() {
         return roomCode;
     }

+ 15 - 3
themis-business/src/main/java/com/qmth/themis/business/dto/MarkResultStandardExportDto.java

@@ -73,18 +73,30 @@ public class MarkResultStandardExportDto implements Serializable{
     @ExcelNote(value = "总分")
     private String sumScore;
 
+    @ApiModelProperty(value = "考试记录ID")
+    @ExcelNotExport
+    private String recordId;
+
     @ApiModelProperty(value = "试卷ID")
     @ExcelNotExport
-    private String paperId;
+    private Long paperId;
 
-    public String getPaperId() {
+    public Long getPaperId() {
         return paperId;
     }
 
-    public void setPaperId(String paperId) {
+    public void setPaperId(Long paperId) {
         this.paperId = paperId;
     }
 
+    public String getRecordId() {
+        return recordId;
+    }
+
+    public void setRecordId(String recordId) {
+        this.recordId = recordId;
+    }
+
     public String getRoomCode() {
         return roomCode;
     }

+ 57 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/AnswerTypeEnum.java

@@ -0,0 +1,57 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * @Description: 题目类型 enum
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/10/21
+ */
+public enum AnswerTypeEnum {
+
+    A(1L, "A"),
+    B(2L, "B"),
+    C(3L, "C"),
+    D(4L, "D"),
+    E(5L, "E"),
+    F(6L, "F"),
+    G(7L, "G"),
+    H(8L, "H"),
+    I(9L, "I"),
+    J(10L, "J"),
+    K(11L, "K"),
+    L(12L, "L"),
+    M(13L, "M"),
+    N(14L, "N"),
+    O(15L, "O"),
+    P(16L, "P"),
+    Q(17L, "Q"),
+    R(18L, "R"),
+    S(19L, "S"),
+    T(20L, "T"),
+    U(21L, "U"),
+    V(22L, "V"),
+    W(23L, "W"),
+    X(24L, "X"),
+    Y(25L, "Y"),
+    Z(26L, "Z"),
+    TRUE(27L, "对"),
+    FALSE(28L, "错");
+
+    private Long type;
+
+    private String title;
+
+    private AnswerTypeEnum(Long type, String title) {
+        this.type = type;
+        this.title = title;
+    }
+
+    public Long getType() {
+        return type;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+}

+ 53 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/QuestionTypeEnum.java

@@ -0,0 +1,53 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * @Description: 题目类型 enum
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/10/21
+ */
+public enum QuestionTypeEnum {
+
+    /**
+     * 单选
+     */
+    SINGLE_ANSWER_QUESTION(1L, "单选题"),
+    /**
+     * 多选
+     */
+    MULTIPLE_ANSWER_QUESTION(2L, "多选题"),
+    /**
+     * 判断
+     */
+    BOOL_ANSWER_QUESTION(3L, "判断题"),
+    /**
+     * 填空
+     */
+    FILL_BLANK_QUESTION(4L, "填空题"),
+    /**
+     * 问答
+     */
+    TEXT_ANSWER_QUESTION(5L, "问答题"),
+    /**
+     * 套题
+     */
+    NESTED_ANSWER_QUESTION(6L, "套题");
+
+    private Long type;
+
+    private String title;
+
+    private QuestionTypeEnum(Long type, String title) {
+        this.type = type;
+        this.title = title;
+    }
+
+    public Long getType() {
+        return type;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+}

+ 42 - 0
themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskMarkResultStandardExportTemplete.java

@@ -1,14 +1,21 @@
 package com.qmth.themis.business.templete.impl;
 
 import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
 import com.qmth.themis.business.annotation.ExcelNotExport;
 import com.qmth.themis.business.annotation.ExcelNote;
+import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dto.ExcelDto;
 import com.qmth.themis.business.dto.MarkResultSimpleExportDto;
 import com.qmth.themis.business.dto.MarkResultStandardExportDto;
+import com.qmth.themis.business.entity.TOeExamAnswer;
+import com.qmth.themis.business.enums.QuestionTypeEnum;
+import com.qmth.themis.business.service.TEExamPaperService;
 import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.service.TOeExamAnswerService;
 import com.qmth.themis.business.templete.TaskExportCommon;
 import com.qmth.themis.business.templete.TaskExportTemplete;
 import com.qmth.themis.business.templete.service.TempleteLogicService;
@@ -47,6 +54,12 @@ public class TaskMarkResultStandardExportTemplete implements TaskExportTemplete
     @Resource
     TempleteLogicService templeteLogicService;
 
+    @Resource
+    TOeExamAnswerService tOeExamAnswerService;
+
+    @Resource
+    TEExamPaperService teExamPaperService;
+
     /**
      * 考场导出模版
      *
@@ -76,6 +89,35 @@ public class TaskMarkResultStandardExportTemplete implements TaskExportTemplete
             Gson gson = new Gson();
             List<MarkResultStandardExportDto> markResultStandardExportDtoList = gson.fromJson(gson.toJson(markResultSimpleExportDtoList), new TypeToken<List<MarkResultStandardExportDto>>() {
             }.getType());
+            Map<Long, ExcelDto> excelDtoMap = new HashMap<>();
+            Map<Long, Map<String, ObjectiveAnswerCacheBean>> paperObjectiveAnswerMap = new HashMap<>();
+            if (Objects.nonNull(markResultStandardExportDtoList) && markResultStandardExportDtoList.size() > 0) {
+                for (MarkResultStandardExportDto m : markResultStandardExportDtoList) {
+                    Map<String, ObjectiveAnswerCacheBean> objectiveAnswerCacheBeanMap = null;
+                    if (Objects.nonNull(m.getPaperId())) {//处理试卷
+                        if (!paperObjectiveAnswerMap.containsKey(m.getPaperId())) {
+                            objectiveAnswerCacheBeanMap = teExamPaperService.getObjectiveAnswerCacheBean(m.getPaperId());
+                            paperObjectiveAnswerMap.put(m.getPaperId(), objectiveAnswerCacheBeanMap);
+                        } else {
+                            objectiveAnswerCacheBeanMap = paperObjectiveAnswerMap.get(m.getPaperId());
+                        }
+                    } else {
+                        continue;
+                    }
+                    if (Objects.nonNull(m.getRecordId())) {//处理考生答案
+                        QueryWrapper<TOeExamAnswer> tOeExamAnswerQueryWrapper = new QueryWrapper<>();
+                        tOeExamAnswerQueryWrapper.lambda().eq(TOeExamAnswer::getExamRecordId, m.getRecordId());
+                        List<TOeExamAnswer> tOeExamAnswerList = tOeExamAnswerService.list(tOeExamAnswerQueryWrapper);
+                        for (TOeExamAnswer s : tOeExamAnswerList) {
+                            String questionsTitle = s.getMainNumber() + "_" + s.getSubNumber();
+                            if (Objects.nonNull(s.getAnswer())) {
+                                ObjectiveAnswerCacheBean objectiveAnswerCacheBean = objectiveAnswerCacheBeanMap.get(questionsTitle);
+//                                String questionType = QuestionTypeEnum.valueOf(Long.parseLong(objectiveAnswerCacheBean.getStructType())).getTitle();
+                            }
+                        }
+                    }
+                }
+            }
             boolean oss = (boolean) taskExportCommon.getOssEnv().get(SystemConstant.OSS);
             StringJoiner stringJoiner = new StringJoiner("");
             if (!oss) {

+ 4 - 2
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -299,6 +299,7 @@
 		ifnull(t.objectiveScore,0) as sumScore,
 		t.examId,
 		t.examActivityId,
+		t.recordId,
 		t.paperId,
 		0 as subjectiveScore
 		from
@@ -313,20 +314,21 @@
 		(select sum(toer.breach_status) from t_oe_exam_record toer
 		where toer.exam_student_id = tees.id and toer.breach_status = 0) as breachCount,
 		temp.objective_score as objectiveScore,
+		temp.id as recordId,
 		temp.paper_id as paperId
 		from
 		t_e_student tes
 		left join t_e_exam_student tees on
 		tees.student_id = tes.id
 		left join (select
-			max(toer.objective_score) as objective_score,toer.paper_id,toer.exam_student_id
+			max(toer.objective_score) as objective_score,toer.id,toer.exam_student_id,toer.paper_id
 			from
 			t_oe_exam_record toer
 			where
 			(toer.breach_status = 1
 			or breach_status is null)
 			and (toer.status = 'FINISHED'
-			or toer.status = 'PERSISTED') group by paper_id,exam_student_id) temp on temp.exam_student_id = tees.id
+			or toer.status = 'PERSISTED') group by toer.id,toer.paper_id,toer.exam_student_id) temp on temp.exam_student_id = tees.id
 		left join t_e_exam tee on
 		tee.id = tees.exam_id
 		left join t_e_exam_activity teea on

+ 126 - 126
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper
-	namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
+		namespace="com.qmth.themis.business.dao.TOeExamRecordMapper">
 
 	<select id="getUnFinishExam"
-		resultType="com.qmth.themis.business.dto.response.TEExamUnFinishDto">
+			resultType="com.qmth.themis.business.dto.response.TEExamUnFinishDto">
 		select
 		tee.id,
 		teea.id as examActivityId,
@@ -204,29 +204,29 @@
 	</sql>
 
 	<select id="invigilatePageList" resultType="com.qmth.themis.business.bean.backend.InvigilateListBean">
-        select
-        (@i := @i + 1) as seq,
-        t.*
-        from
-        (
-        <include refid="invigilatePageHead"/>
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and
-        tiiwi.approve_status = 0) as warningNew
+		select
+		(@i := @i + 1) as seq,
+		t.*
+		from
+		(
+		<include refid="invigilatePageHead"/>
+		,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and
+		tiiwi.approve_status = 0) as warningNew
 		,case
 		when tee.mode = 'ANYTIME' then SEC_TO_TIME(IFNULL(teea.max_duration_seconds, tee.max_duration_seconds) - t.duration_seconds)
 		when tee.mode = 'TOGETHER' and tee.force_finish = 1 then SEC_TO_TIME((IFNULL(teea.finish_time, tee.end_time) - unix_timestamp(current_timestamp()) * 1000) / 1000)
 		else SEC_TO_TIME(IFNULL(teea.max_duration_seconds, tee.max_duration_seconds) - t.duration_seconds)
 		end as remainTime
-        <include refid="invigilatePageMiddle"/>
+		<include refid="invigilatePageMiddle"/>
 		<include refid="invigilatePageFoot"/>
-        <if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
-            and t.paper_download = #{paperDownload}
-        </if>
+		<if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
+			and t.paper_download = #{paperDownload}
+		</if>
 		<if test="status == null or status == ''">
 			and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
 		</if>
-        ) t,
-        (SELECT @i := 0) as i
+		) t,
+		(SELECT @i := 0) as i
 		order by t.warningNew desc
 	</select>
 
@@ -268,9 +268,9 @@
 		end as remainTime
 		<include refid="invigilatePageMiddle" />
 		<where> 1 = 1
-		<if test="examId != null and examId != ''">
-			and t.exam_id = #{examId}
-		</if>
+			<if test="examId != null and examId != ''">
+				and t.exam_id = #{examId}
+			</if>
 			and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
 		</where>
 		ORDER BY RAND() LIMIT #{randomNum}
@@ -288,9 +288,9 @@
 		end as remainTime
 		<include refid="invigilatePageMiddle" />
 		<include refid="invigilatePageFoot" />
-			<if test="status == null or status == ''">
-				and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
-			</if>
+		<if test="status == null or status == ''">
+			and (t.status = 'FIRST_PREPARE' or t.status = 'ANSWERING' or t.status = 'BREAK_OFF' or t.status = 'RESUME_PREPARE')
+		</if>
 		) t,(SELECT @i := 0) as i
 		<where>
 			<if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
@@ -397,88 +397,88 @@
 	<update id="approveStatusListUpdate">
 		update t_ie_invigilate_warn_info tiiwi set tiiwi.approve_status = 1
 		where exists(
-			select t.warningId from(select
-			tiiwi.id as warningId,
-			tee.id as examId,
-			tee.name as examName,
-			teea.id as examActivityId,
-			tees.id as examStudentId,
-			teea.code as examActivityCode,
-			tees.room_code as roomCode,
-			tees.room_name as roomName,
-			toer.id as examRecordId,
-			tees.`identity`,
-			tees.name,
-			tees.course_code as courseCode,
-			tees.course_name as courseName,
-			toer.status as statusCode,
-			IFNULL(toer.warning_count,0) as warningCount,
-			IFNULL(toer.breach_status,1) as breachStatus,
-			toer.client_last_sync_time as updateTime,
-			tiiwi.approve_status as approveStatus
-			,(select count(1) from t_ie_invigilate_warn_info tiiwi where
-			tiiwi.exam_record_id = toer.id and tiiwi.`type` =
-			'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
-			,(select count(1) from t_ie_invigilate_exception_info tiiei where
-			tiiei.exam_record_id = toer.id) as exceptionCount
-			from t_ie_invigilate_warn_info tiiwi
-			left join t_e_exam tee on tee.id = tiiwi.exam_id
-			left join t_e_exam_activity teea on teea.id = tiiwi.exam_activity_id
-			inner join (select toer.id from t_oe_exam_record toer where EXISTS(select
-			tees.id from t_e_exam_student tees where EXISTS (select distinct
-			tbeiu.room_code from t_b_exam_invigilate_user tbeiu
-			where
-			<if test="userId != null and userId != ''">
-				tbeiu.user_id = #{userId} and
-			</if>
-			tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id)))
-			t on t.id = tiiwi.exam_record_id
-			left join t_oe_exam_record toer on toer.id = t.id
-			left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
-			<where>
-				<if test="examId != null and examId != ''">
-					and tiiwi.exam_id = #{examId}
-				</if>
-				<if test="examActivityId != null and examActivityId != ''">
-					and tiiwi.exam_activity_id = #{examActivityId}
-				</if>
-				<if test="roomCode != null and roomCode != ''">
-					and tees.room_code = #{roomCode}
-				</if>
-				<if test="approveStatus != null and approveStatus != '' or approveStatus == 0">
-					and tiiwi.approve_status = #{approveStatus}
-				</if>
-				<if test="name != null and name !=''">
-					and tees.name like CONCAT('%', #{name},'%')
-				</if>
-				<if test="identity != null and identity !=''">
-					and tees.identity like CONCAT('%', #{identity},'%')
-				</if>
-				<if test="maxWarningCount != null and maxWarningCount != '' or maxWarningCount == 0">
-					and toer.warning_count &lt;= #{maxWarningCount}
-				</if>
-				<if test="minWarningCount != null and minWarningCount != '' or minWarningCount == 0">
-					and toer.warning_count &gt;= #{minWarningCount}
-				</if>
-				and tee.enable = 1
-				and teea.enable = 1
-			</where>
-			) t
-			<where> 1 = 1
-				<if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
-					and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
-				</if>
-				<if test="maxMultipleFaceCount != null and maxMultipleFaceCount != '' or maxMultipleFaceCount == 0">
-					and t.multipleFaceCount &lt;= #{maxMultipleFaceCount}
-				</if>
-				<if test="minExceptionCount != null and minExceptionCount != '' or minExceptionCount == 0">
-					and t.exceptionCount &gt;= #{minExceptionCount}
-				</if>
-				<if test="maxExceptionCount != null and maxExceptionCount != '' or maxExceptionCount == 0">
-					and t.exceptionCount &lt;= #{maxExceptionCount}
-				</if>
-			</where>
-		 		 and t.warningId = tiiwi.id)
+		select t.warningId from(select
+		tiiwi.id as warningId,
+		tee.id as examId,
+		tee.name as examName,
+		teea.id as examActivityId,
+		tees.id as examStudentId,
+		teea.code as examActivityCode,
+		tees.room_code as roomCode,
+		tees.room_name as roomName,
+		toer.id as examRecordId,
+		tees.`identity`,
+		tees.name,
+		tees.course_code as courseCode,
+		tees.course_name as courseName,
+		toer.status as statusCode,
+		IFNULL(toer.warning_count,0) as warningCount,
+		IFNULL(toer.breach_status,1) as breachStatus,
+		toer.client_last_sync_time as updateTime,
+		tiiwi.approve_status as approveStatus
+		,(select count(1) from t_ie_invigilate_warn_info tiiwi where
+		tiiwi.exam_record_id = toer.id and tiiwi.`type` =
+		'FACE_COUNT_ERROR' and tiiwi.`level` = 'D8') as multipleFaceCount
+		,(select count(1) from t_ie_invigilate_exception_info tiiei where
+		tiiei.exam_record_id = toer.id) as exceptionCount
+		from t_ie_invigilate_warn_info tiiwi
+		left join t_e_exam tee on tee.id = tiiwi.exam_id
+		left join t_e_exam_activity teea on teea.id = tiiwi.exam_activity_id
+		inner join (select toer.id from t_oe_exam_record toer where EXISTS(select
+		tees.id from t_e_exam_student tees where EXISTS (select distinct
+		tbeiu.room_code from t_b_exam_invigilate_user tbeiu
+		where
+		<if test="userId != null and userId != ''">
+			tbeiu.user_id = #{userId} and
+		</if>
+		tbeiu.room_code = tees.room_code and toer.exam_student_id = tees.id)))
+		t on t.id = tiiwi.exam_record_id
+		left join t_oe_exam_record toer on toer.id = t.id
+		left join t_e_exam_student tees on tees.id = tiiwi.exam_student_id
+		<where>
+			<if test="examId != null and examId != ''">
+				and tiiwi.exam_id = #{examId}
+			</if>
+			<if test="examActivityId != null and examActivityId != ''">
+				and tiiwi.exam_activity_id = #{examActivityId}
+			</if>
+			<if test="roomCode != null and roomCode != ''">
+				and tees.room_code = #{roomCode}
+			</if>
+			<if test="approveStatus != null and approveStatus != '' or approveStatus == 0">
+				and tiiwi.approve_status = #{approveStatus}
+			</if>
+			<if test="name != null and name !=''">
+				and tees.name like CONCAT('%', #{name},'%')
+			</if>
+			<if test="identity != null and identity !=''">
+				and tees.identity like CONCAT('%', #{identity},'%')
+			</if>
+			<if test="maxWarningCount != null and maxWarningCount != '' or maxWarningCount == 0">
+				and toer.warning_count &lt;= #{maxWarningCount}
+			</if>
+			<if test="minWarningCount != null and minWarningCount != '' or minWarningCount == 0">
+				and toer.warning_count &gt;= #{minWarningCount}
+			</if>
+			and tee.enable = 1
+			and teea.enable = 1
+		</where>
+		) t
+		<where> 1 = 1
+			<if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
+				and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
+			</if>
+			<if test="maxMultipleFaceCount != null and maxMultipleFaceCount != '' or maxMultipleFaceCount == 0">
+				and t.multipleFaceCount &lt;= #{maxMultipleFaceCount}
+			</if>
+			<if test="minExceptionCount != null and minExceptionCount != '' or minExceptionCount == 0">
+				and t.exceptionCount &gt;= #{minExceptionCount}
+			</if>
+			<if test="maxExceptionCount != null and maxExceptionCount != '' or maxExceptionCount == 0">
+				and t.exceptionCount &lt;= #{maxExceptionCount}
+			</if>
+		</where>
+		and t.warningId = tiiwi.id)
 	</update>
 
 	<select id="invigilatePageProgressList" resultType="com.qmth.themis.business.bean.backend.InvigilateListProgressBean">
@@ -604,7 +604,7 @@
 		<include refid="invigilatePageHistoryFoot" />
 		<if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
 			<if test="breachStatus == 0">
-			 	and t.breach_status = #{breachStatus}
+				and t.breach_status = #{breachStatus}
 			</if>
 			<if test="breachStatus == 1">
 				and (t.breach_status = #{breachStatus} or t.breach_status is null)
@@ -686,7 +686,7 @@
 	<update id="updateObjectiveScore">
 		update t_oe_exam_record t set t.objective_score=#{score} where t.id=#{recordId}
 	</update>
-	
+
 	<select id="findOneByPaperId" resultType="com.qmth.themis.business.entity.TOeExamRecord">
 		select f.* from t_oe_exam_record f
 		where f.paper_id = #{paperId}
@@ -852,30 +852,30 @@
 		GROUP BY
 			FROM_UNIXTIME(w.create_time / 1000,'%H')
 	</select>
-	
+
 	<update id="updateHasAnswerFile">
 		update t_oe_exam_record t set t.has_answer_file=#{hasAnswerFile} where t.id=#{recordId}
 	</update>
-	
+
 	<select id="findExamRecordNeedMark" resultType="com.qmth.themis.business.bean.backend.OpenRecordNeedMarkBean">
-			SELECT
-				t.id,
-				f.identity,
-				f.NAME,
-				g.CODE activityCode,
-				f.course_code courseCode,
-				f.course_name courseName,
-				t.paper_id paperId,
-				t.objective_score objectiveScore
-			FROM
-				t_oe_exam_record t
-			LEFT JOIN t_e_exam_student f ON t.exam_student_id = f.id
-			LEFT JOIN t_e_exam_activity g ON t.exam_activity_id = g.id
-			where t.exam_id=#{examId} and t.id&gt;#{idGt} 
-			<if test="courseCode != null and courseCode != ''">
+		SELECT
+		t.id,
+		f.identity,
+		f.NAME,
+		g.CODE activityCode,
+		f.course_code courseCode,
+		f.course_name courseName,
+		t.paper_id paperId,
+		t.objective_score objectiveScore
+		FROM
+		t_oe_exam_record t
+		LEFT JOIN t_e_exam_student f ON t.exam_student_id = f.id
+		LEFT JOIN t_e_exam_activity g ON t.exam_activity_id = g.id
+		where t.exam_id=#{examId} and t.id&gt;#{idGt}
+		<if test="courseCode != null and courseCode != ''">
 			and f.course_code=#{courseCode}
-			</if>
-			order by t.id
-			limit #{count}
+		</if>
+		order by t.id
+		limit #{count}
 	</select>
 </mapper>

+ 10 - 1
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -23,12 +23,14 @@ import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
 import com.qmth.themis.exam.config.ExamConstant;
+import com.qmth.themis.exam.websocket.WebSocketOeServer;
 import io.swagger.annotations.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 @Api(tags = "考试Controller")
 @RestController
@@ -114,7 +116,14 @@ public class TEExamController {
         } else if (Objects.nonNull(status) && Objects.equals(ExamRecordStatusEnum.FIRST_PREPARE, status)) {
             ExamConstant.sendExamStopMsg(Long.valueOf(recordId), false);
         } else {
-            throw new BusinessException("考试状态出错");
+            if(Objects.nonNull(status)) {
+                throw new BusinessException("考试状态出错");
+            }
+        }
+        ConcurrentHashMap<Long, WebSocketOeServer> webSocketMap = WebSocketOeServer.getWebSocketMap();
+        WebSocketOeServer webSocketOeServer = webSocketMap.get(Long.parseLong(recordId));
+        if(Objects.nonNull(webSocketOeServer)){
+            webSocketOeServer.onClose();
         }
         return ResultUtil.ok(Collections.singletonMap(SystemConstant.SUCCESS, true));
     }