Explorar o código

在线考试2022/05/20临时上线需求更改

wangliang %!s(int64=3) %!d(string=hai) anos
pai
achega
bd4c915587

+ 2 - 1
themis-admin/src/main/java/com/qmth/themis/admin/api/TEExamController.java

@@ -468,7 +468,8 @@ public class TEExamController {
                 examPropCountDto.get().setExamCount(list.get(1));
                 examPropCountDto.get().setAlreadyComplete(list.get(2));
             }
-            Integer notComplete = examPropCountDto.get().getAllCount() - examPropCountDto.get().getAlreadyComplete();
+            Integer notComplete = examPropCountDto.get().getAllCount() - examPropCountDto.get().getAlreadyComplete()
+                    - examPropCountDto.get().getExamCount() - examPropCountDto.get().getPrepareCount();
             BigDecimal completionRate = new BigDecimal(examPropCountDto.get().getAlreadyComplete())
                     .divide(new BigDecimal(examPropCountDto.get().getAllCount()), 2, BigDecimal.ROUND_HALF_UP)
                     .setScale(2, BigDecimal.ROUND_HALF_UP);

+ 29 - 0
themis-admin/src/main/java/com/qmth/themis/admin/api/TIeInvigilateController.java

@@ -249,6 +249,35 @@ public class TIeInvigilateController {
         return ResultUtil.ok(tOeExamRecordService.invigilatePageListHistory(new Page<>(pageNumber, pageSize), examId, examActivityId, roomCode, courseCode, status, breachStatus, finishType, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId()));
     }
 
+    @ApiOperation(value = "监考明细管理列表导出接口")
+    @RequestMapping(value = "/history/list/export", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "监考明细信息", response = InvigilateListHistoryBean.class)})
+    public void historyListExport(@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId,
+                                  @ApiParam(value = "考试场次id", required = false) @RequestParam(required = false) Long examActivityId,
+                                  @ApiParam(value = "虚拟考场代码", required = false) @RequestParam(required = false) String roomCode,
+                                  @ApiParam(value = "科目代码", required = false) @RequestParam(required = false) String courseCode,
+                                  @ApiParam(value = "考生状态", required = false) @RequestParam(required = false) String status,
+                                  @ApiParam(value = "违纪状态", required = false) @RequestParam(required = false) Integer breachStatus,
+                                  @ApiParam(value = "交卷方式", required = false) @RequestParam(required = false) String finishType,
+                                  @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
+                                  @ApiParam(value = "证件号", required = false) @RequestParam(required = false) String identity,
+                                  @ApiParam(value = "陌生人脸min", required = false) @RequestParam(required = false) Integer minMultipleFaceCount,
+                                  @ApiParam(value = "陌生人脸max", required = false) @RequestParam(required = false) Integer maxMultipleFaceCount,
+                                  @ApiParam(value = "异常处理min", required = false) @RequestParam(required = false) Integer minExceptionCount,
+                                  @ApiParam(value = "异常处理max", required = false) @RequestParam(required = false) Integer maxExceptionCount,
+                                  @ApiParam(value = "预警量min", required = false) @RequestParam(required = false) Integer minWarningCount,
+                                  @ApiParam(value = "预警量max", required = false) @RequestParam(required = false) Integer maxWarningCount) throws Exception {
+        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
+        AuthDto authDto = cacheService.addAccountAuthCache(tbUser.getId());
+        //如果有监考员角色,只能查看自己所监考的考场,巡考员和管理员则可以查看全部考场
+        Long userId = null;
+        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
+            userId = tbUser.getId();
+        }
+        List<InvigilateListHistoryBean> invigilateListHistoryBeanList = tOeExamRecordService.invigilatePageListHistoryExport(examId, examActivityId, roomCode, courseCode, status, breachStatus, finishType, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount, maxExceptionCount, minWarningCount, maxWarningCount, userId, tbUser.getOrgId());
+        ExportUtils.exportEXCEL("监考明细", InvigilateListHistoryBean.class, invigilateListHistoryBeanList, ServletUtil.getResponse());
+    }
+
     @ApiOperation(value = "实时监控台列表明细接口")
     @RequestMapping(value = "/list/detail", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "监考监控信息", response = InvigilateListDetailBean.class)})

+ 46 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/admin/InvigilateListHistoryBean.java

@@ -4,10 +4,12 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.themis.business.enums.ExamRecordStatusEnum;
 import com.qmth.themis.business.enums.FinishTypeEnum;
+import com.qmth.themis.business.excel.ExcelProperty;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * @Description: 实时监控台视频返回对象
@@ -23,9 +25,11 @@ public class InvigilateListHistoryBean implements Serializable {
     private Integer seq;
 
     @ApiModelProperty(name = "考试批次名称")
+    @ExcelProperty(name = "批次", width = 30, index = 1)
     private String examName;
 
     @ApiModelProperty(name = "场次code")
+    @ExcelProperty(name = "场次", width = 30, index = 2)
     private String examActivityCode;
 
     @JsonSerialize(using = ToStringSerializer.class)
@@ -42,21 +46,26 @@ public class InvigilateListHistoryBean implements Serializable {
 
     @JsonSerialize(using = ToStringSerializer.class)
     @ApiModelProperty(name = "考试记录id")
+    @ExcelProperty(name = "考试ID", width = 30, index = 4)
     private Long examRecordId;
 
     @ApiModelProperty(name = "证件号")
+    @ExcelProperty(name = "证件号", width = 30, index = 5)
     private String identity;
 
     @ApiModelProperty(name = "虚拟考场代码")
     private String roomCode;
 
     @ApiModelProperty(name = "虚拟考场名称")
+    @ExcelProperty(name = "考场", width = 30, index = 3)
     private String roomName;
 
     @ApiModelProperty(name = "姓名")
+    @ExcelProperty(name = "姓名", width = 30, index = 6)
     private String name;
 
     @ApiModelProperty(name = "考生状态")
+    @ExcelProperty(name = "状态", width = 30, index = 9)
     private String status;
 
     @ApiModelProperty(name = "考生状态值")
@@ -65,27 +74,64 @@ public class InvigilateListHistoryBean implements Serializable {
     @ApiModelProperty(name = "交卷原因")
     private FinishTypeEnum finishType;
 
+    @ApiModelProperty(name = "交卷原因")
+    @ExcelProperty(name = "交卷方式", width = 30, index = 10)
+    private String finishTypeStr;
+
     @ApiModelProperty(name = "预警量")
+    @ExcelProperty(name = "预警数", width = 30, index = 13)
     private Integer warningCount;
 
     @ApiModelProperty(name = "陌生人脸")
+    @ExcelProperty(name = "陌生人脸", width = 30, index = 11)
     private Integer multipleFaceCount;
 
     @ApiModelProperty(name = "异常处理")
+    @ExcelProperty(name = "异常处理", width = 30, index = 12)
     private Integer exceptionCount;
 
     @ApiModelProperty(name = "是否违纪")
     private Integer breachStatus;
 
+    @ApiModelProperty(name = "是否违纪")
+    @ExcelProperty(name = "违纪", width = 30, index = 14)
+    private String breachStatusStr;
+
     @ApiModelProperty(name = "更新时间")
     private Long updateTime;
 
     @ApiModelProperty(name = "科目代码")
+    @ExcelProperty(name = "科目代码", width = 30, index = 8)
     private String courseCode;
 
     @ApiModelProperty(name = "联系电话")
+    @ExcelProperty(name = "联系电话", width = 30, index = 7)
     private String mobileNumber;
 
+    public String getBreachStatusStr() {
+        if (Objects.nonNull(breachStatus)) {
+            return breachStatus.intValue() == 1 ? "正常" : "违纪";
+        } else {
+            return breachStatusStr;
+        }
+    }
+
+    public void setBreachStatusStr(String breachStatusStr) {
+        this.breachStatusStr = breachStatusStr;
+    }
+
+    public String getFinishTypeStr() {
+        if (Objects.nonNull(finishType)) {
+            return finishType.getCode();
+        } else {
+            return finishTypeStr;
+        }
+    }
+
+    public void setFinishTypeStr(String finishTypeStr) {
+        this.finishTypeStr = finishTypeStr;
+    }
+
     public Integer getSeq() {
         return seq;
     }

+ 6 - 2
themis-business/src/main/java/com/qmth/themis/business/bean/admin/InvigilateListVideoBean.java

@@ -339,10 +339,14 @@ public class InvigilateListVideoBean implements Serializable {
             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)) {
+        } else if (statusCode != null && (Objects.equals(ExamRecordStatusEnum.ANSWERING, statusCode) || Objects.equals(ExamRecordStatusEnum.RESUME_PREPARE, statusCode) || Objects.equals(ExamRecordStatusEnum.BREAK_OFF, statusCode))) {
             return "考试中";
         } else {
-            return statusCode.getCode();
+            if (Objects.nonNull(statusCode)) {
+                return statusCode.getCode();
+            } else {
+                return "未参加考试";
+            }
         }
     }
 

+ 40 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java

@@ -316,6 +316,46 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
                                                                       @Param("userId") Long userId,
                                                                       @Param("orgId") Long orgId);
 
+    /**
+     * 监考明细管理列表导出
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param courseCode
+     * @param status
+     * @param breachStatus
+     * @param finishType
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    public List<InvigilateListHistoryBean> invigilatePageListHistoryExport(Long examId,
+                                                                           Long examActivityId,
+                                                                           String roomCode,
+                                                                           String courseCode,
+                                                                           String status,
+                                                                           Integer breachStatus,
+                                                                           String finishType,
+                                                                           String name,
+                                                                           String identity,
+                                                                           Integer minMultipleFaceCount,
+                                                                           Integer maxMultipleFaceCount,
+                                                                           Integer minExceptionCount,
+                                                                           Integer maxExceptionCount,
+                                                                           Integer minWarningCount,
+                                                                           Integer maxWarningCount,
+                                                                           Long userId,
+                                                                           Long orgId);
+
     public List<Map<String, Object>> getDoneCount(@Param("orgId") Long orgId, @Param("examId") Long examId, @Param("activityId") Long activityId,
                                                   @Param("roomCode") String roomCode, @Param("courseCode") String courseCode);
 

+ 40 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java

@@ -343,6 +343,46 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
                                                                       Long userId,
                                                                       Long orgId);
 
+    /**
+     * 监考明细管理列表导出
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param courseCode
+     * @param status
+     * @param breachStatus
+     * @param finishType
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    public List<InvigilateListHistoryBean> invigilatePageListHistoryExport(Long examId,
+                                                                      Long examActivityId,
+                                                                      String roomCode,
+                                                                      String courseCode,
+                                                                      String status,
+                                                                      Integer breachStatus,
+                                                                      String finishType,
+                                                                      String name,
+                                                                      String identity,
+                                                                      Integer minMultipleFaceCount,
+                                                                      Integer maxMultipleFaceCount,
+                                                                      Integer minExceptionCount,
+                                                                      Integer maxExceptionCount,
+                                                                      Integer minWarningCount,
+                                                                      Integer maxWarningCount,
+                                                                      Long userId,
+                                                                      Long orgId);
+
 
     /**
      * 重新算分

+ 45 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -922,6 +922,51 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                         maxExceptionCount, minWarningCount, maxWarningCount, userId, orgId);
     }
 
+    /**
+     * 监考明细管理列表导出
+     *
+     * @param examId
+     * @param examActivityId
+     * @param roomCode
+     * @param courseCode
+     * @param status
+     * @param breachStatus
+     * @param finishType
+     * @param name
+     * @param identity
+     * @param minMultipleFaceCount
+     * @param maxMultipleFaceCount
+     * @param minExceptionCount
+     * @param maxExceptionCount
+     * @param minWarningCount
+     * @param maxWarningCount
+     * @param userId
+     * @param orgId
+     * @return
+     */
+    public List<InvigilateListHistoryBean> invigilatePageListHistoryExport(Long examId,
+                                                                           Long examActivityId,
+                                                                           String roomCode,
+                                                                           String courseCode,
+                                                                           String status,
+                                                                           Integer breachStatus,
+                                                                           String finishType,
+                                                                           String name,
+                                                                           String identity,
+                                                                           Integer minMultipleFaceCount,
+                                                                           Integer maxMultipleFaceCount,
+                                                                           Integer minExceptionCount,
+                                                                           Integer maxExceptionCount,
+                                                                           Integer minWarningCount,
+                                                                           Integer maxWarningCount,
+                                                                           Long userId,
+                                                                           Long orgId) {
+        return tOeExamRecordMapper
+                .invigilatePageListHistoryExport(examId, examActivityId, roomCode, courseCode, status, breachStatus,
+                        finishType, name, identity, minMultipleFaceCount, maxMultipleFaceCount, minExceptionCount,
+                        maxExceptionCount, minWarningCount, maxWarningCount, userId, orgId);
+    }
+
     /**
      * 重新算分
      */

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

@@ -39,10 +39,10 @@
 			and t.course_code = #{courseCode}
 		</if>
 		<if test="identity != null and identity != ''">
-			and t.identity like concat(#{identity},'%')
+			and t.identity like concat('%',#{identity},'%')
 		</if>
 		<if test="name != null and name != ''">
-			and t.name like concat(#{name},'%')
+			and t.name like concat('%',#{name},'%')
 		</if>
         order by f.exam_student_id
 	</select>
@@ -84,10 +84,10 @@
 			and t.course_code = #{courseCode}
 		</if>
 		<if test="identity != null and identity != ''">
-			and t.identity like concat(#{identity},'%')
+			and t.identity like concat('%',#{identity},'%')
 		</if>
 		<if test="name != null and name != ''">
-			and t.name like concat(#{name},'%')
+			and t.name like concat('%',#{name},'%')
 		</if>
         order by f.exam_student_id
 	</select>

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

@@ -263,10 +263,10 @@
             and t.course_code = #{courseCode}
         </if>
         <if test="identity != null and identity != ''">
-            and t.identity like concat(#{identity},'%')
+            and t.identity like concat('%',#{identity},'%')
         </if>
         <if test="name != null and name != ''">
-            and t.name like concat(#{name},'%')
+            and t.name like concat('%',#{name},'%')
         </if>
         GROUP BY f.exam_student_id
         order by f.exam_student_id

+ 83 - 14
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -266,17 +266,36 @@
 
     <select id="getExamDeficiencyPage"
             resultType="com.qmth.themis.business.bean.admin.ExamDeficiencyListBean">
-        select tee.name as examName,t.exam_id examId,t.exam_activity_id
-        examActivityId,t.room_code
-        roomCode,t.course_code courseCode,t.course_name
-        courseName,t.name,t.identity
-        ,t.room_name roomName,f.code as examActivityCode from
+        select
+        *
+        from
+        (
+        select
+        tee.name as examName,
+        t.exam_id examId,
+        t.exam_activity_id examActivityId,
+        t.room_code roomCode,
+        t.course_code courseCode,
+        t.course_name courseName,
+        t.name,
+        t.identity ,
+        t.room_name roomName,
+        f.code as examActivityCode,
+        t.id
+        from
         t_e_exam_student t
         left join t_e_exam_activity f on
-        t.exam_activity_id=f.id
-        join t_e_exam tee on tee.id = t.exam_id
-        where t.exam_id = #{examId} and
-        t.current_record_id is null
+        t.exam_activity_id = f.id
+        join t_e_exam tee on
+        tee.id = t.exam_id
+        where
+        NOT EXISTS(
+        select
+        toer.exam_student_id
+        from
+        t_oe_exam_record toer
+        where t.id = toer.exam_student_id)
+        and t.exam_id = #{examId}
         and t.exam_activity_id in
         <foreach collection="activityIds" item="acid" index="index"
                  open="(" close=")" separator=",">
@@ -292,12 +311,62 @@
             and t.course_code = #{courseCode}
         </if>
         <if test="identity != null and identity != ''">
-            and t.identity like concat(#{identity},'%')
+            and t.identity like concat('%',#{identity},'%')
+        </if>
+        <if test="name != null and name != ''">
+            and t.name like concat('%',#{name},'%')
+        </if>
+        union all
+        select
+        tee.name as examName,
+        t.exam_id examId,
+        t.exam_activity_id examActivityId,
+        t.room_code roomCode,
+        t.course_code courseCode,
+        t.course_name courseName,
+        t.name,
+        t.identity ,
+        t.room_name roomName,
+        f.code as examActivityCode,
+        t.id
+        from
+        t_oe_exam_record toer
+        join t_e_exam_student t on
+        t.id = toer.exam_student_id
+        and t.exam_id = toer.exam_id
+        and t.exam_activity_id = toer.exam_activity_id
+        join t_e_exam_activity f on
+        t.exam_activity_id = f.id
+        join t_e_exam tee on
+        tee.id = t.exam_id
+        where
+        toer.exam_id = #{examId}
+        and toer.exam_activity_id in
+        <foreach collection="activityIds" item="acid" index="index"
+                 open="(" close=")" separator=",">
+            #{acid}
+        </foreach>
+        <if test="activityId != null and activityId != ''">
+            and t.exam_activity_id = #{activityId}
+        </if>
+        <if test="roomCode != null and roomCode != ''">
+            and t.room_code =#{roomCode}
+        </if>
+        <if test="courseCode != null and courseCode != ''">
+            and t.course_code = #{courseCode}
+        </if>
+        <if test="identity != null and identity != ''">
+            and t.identity like concat('%',#{identity},'%')
         </if>
         <if test="name != null and name != ''">
-            and t.name like concat(#{name},'%')
+            and t.name like concat('%',#{name},'%')
         </if>
-        order by t.exam_activity_id,t.room_code
+        and toer.status = 'FIRST_PREPARE'
+        and (toer.first_start_time is null
+        or toer.first_prepare_time is null)) t
+        order by
+        t.examActivityId,
+        t.roomCode
     </select>
 
     <select id="getPageForStudentLog"
@@ -325,10 +394,10 @@
             and t.course_code = #{courseCode}
         </if>
         <if test="identity != null and identity != ''">
-            and t.identity like concat(#{identity},'%')
+            and t.identity like concat('%',#{identity},'%')
         </if>
         <if test="name != null and name != ''">
-            and t.name like concat(#{name},'%')
+            and t.name like concat('%',#{name},'%')
         </if>
         order by t.id
     </select>

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

@@ -38,10 +38,10 @@
 			and t.course_code = #{courseCode}
 		</if>
 		<if test="identity != null and identity != ''">
-			and t.identity like concat(#{identity},'%')
+			and t.identity like concat('%',#{identity},'%')
 		</if>
 		<if test="name != null and name != ''">
-			and t.name like concat(#{name},'%')
+			and t.name like concat('%',#{name},'%')
 		</if>
 		GROUP BY f.exam_student_id
 	</select>

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

@@ -136,7 +136,7 @@
             <if test="status != null and status != ''">
                 <choose>
                     <when test="status == 'EXAMING'">
-                        and (t.status = 'ANSWERING' or t.status = 'RESUME_PREPARE')
+                        and (t.status = 'ANSWERING' or t.status = 'RESUME_PREPARE' or t.status = 'BREAK_OFF')
                     </when>
                     <otherwise>
                         and t.status = #{status}
@@ -230,37 +230,127 @@
     </select>
 
     <select id="invigilatePageListVideo" resultType="com.qmth.themis.business.bean.admin.InvigilateListVideoBean">
+        select (@i := @i + 1) as seq,t.* from(
         select
-        (@i := @i + 1) as seq,
-        t.*
+        temp.*,
+        toer.id as examRecordId,
+        IFNULL(toer.paper_download,1) as paperDownload,
+        toer.status as statusCode,
+        TRUNCATE(toer.answer_progress,2) as progress,
+        IFNULL(toer.client_current_ip,'无') as clientCurrentIp,
+        IFNULL(toer.warning_count,0) as warningCount,
+        IFNULL(toer.breach_status,1) as breachStatus,
+        IFNULL(toer.client_websocket_status,'OFF_LINE') as clientWebsocketStatus,
+        toer.client_last_sync_time as updateTime,
+        toer.monitor_video_source as monitorVideoSource,
+        toer.monitor_record as monitorRecord,
+        toer.finish_type as finishType
+        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = toer.id and
+        tiiwi.approve_status = 0) as warningNew
         from
         (
-        <include refid="invigilatePageHead"/>
-        <!--,t.monitor_live_url as monitorLiveUrl-->
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and
-        tiiwi.approve_status = 0) as warningNew
-        <include refid="invigilatePageMiddle"/>
-        <include refid="invigilatePageFoot"/>
-        <if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
-            and t.paper_download = #{paperDownload}
+        select
+        distinct s.exam_id as examId,
+        tee.name as examName,
+        s.exam_activity_id as examActivityId,
+        teea.code as examActivityCode,
+        s.id as examStudentId,
+        s.identity,
+        s.room_code as roomCode,
+        s.room_name as roomName,
+        s.name,
+        s.course_name as courseName,
+        s.course_code as courseCode,
+        tes.mobile_number as mobileNumber
+        from
+        t_e_exam_student s
+        left join t_e_exam tee on
+        tee.id = s.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = s.exam_activity_id
+        left join t_e_student tes on
+        s.student_id = tes.id
+        WHERE
+        <choose>
+            <when test="status != null and status != '' and status == 'UN_FINISH'">
+                NOT EXISTS(
+            </when>
+            <otherwise>
+                EXISTS(
+            </otherwise>
+        </choose>
+        select
+        toer.exam_student_id
+        from
+        t_oe_exam_record toer
+        where
+        s.id = toer.exam_student_id)
+        <if test="examId != null and examId != ''">
+            and s.exam_id = #{examId}
         </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 test="userId != null and userId != ''">
+            and exists (select tbeiu.exam_id from t_b_exam_invigilate_user tbeiu
+            where tbeiu.user_id = #{userId}
+            and tbeiu.exam_id = s.exam_id and tbeiu.room_code = s.room_code)
         </if>
-        <if test="cameraMonitorStatus != null and cameraMonitorStatus != ''">
-            and t.camera_monitor_status = upper(#{cameraMonitorStatus})
+        <if test="orgId != null and orgId != ''">
+            and tee.org_id = #{orgId}
         </if>
-        <if test="screenMonitorStatus != null and screenMonitorStatus != ''">
-            and t.screen_monitor_status = upper(#{screenMonitorStatus})
+        <if test="examActivityId != null and examActivityId != ''">
+            and s.exam_activity_id = #{examActivityId}
         </if>
-        <if test="mobileFirstMonitorStatus != null and mobileFirstMonitorStatus != ''">
-            and t.mobile_first_monitor_status = upper(#{mobileFirstMonitorStatus})
+        <if test="roomCode != null and roomCode != ''">
+            and s.room_code = #{roomCode}
         </if>
-        <if test="mobileSecondMonitorStatus != null and mobileSecondMonitorStatus != ''">
-            and t.mobile_second_monitor_status = upper(#{mobileSecondMonitorStatus})
+        <if test="name != null and name !=''">
+            and s.name like CONCAT('%', #{name},'%')
         </if>
-        ) t,
+        <if test="identity != null and identity !=''">
+            and s.identity like CONCAT('%', #{identity},'%')
+        </if>
+        and teea.finish_time > unix_timestamp(current_timestamp()) * 1000
+        ) temp
+        left join t_oe_exam_record toer on
+        toer.exam_student_id = temp.examStudentId
+        <where> 1 = 1
+            <if test="status != null and status != '' and status != 'UN_FINISH'">
+                <choose>
+                    <when test="status == 'EXAMING'">
+                        and (toer.status = 'ANSWERING' or toer.status = 'RESUME_PREPARE' or toer.status = 'BREAK_OFF')
+                    </when>
+                    <otherwise>
+                        and toer.status = #{status}
+                    </otherwise>
+                </choose>
+            </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>
+            <if test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
+                and toer.client_websocket_status = #{clientWebsocketStatus}
+            </if>
+            <if test="paperDownload != null and paperDownload != '' or paperDownload == 0">
+                and toer.paper_download = #{paperDownload}
+            </if>
+            <if test="status == null or status == ''">
+                and (toer.status = 'FIRST_PREPARE' or toer.status = 'ANSWERING' or toer.status = 'BREAK_OFF' or toer.status = 'RESUME_PREPARE')
+            </if>
+            <if test="cameraMonitorStatus != null and cameraMonitorStatus != ''">
+                and toer.camera_monitor_status = upper(#{cameraMonitorStatus})
+            </if>
+            <if test="screenMonitorStatus != null and screenMonitorStatus != ''">
+                and toer.screen_monitor_status = upper(#{screenMonitorStatus})
+            </if>
+            <if test="mobileFirstMonitorStatus != null and mobileFirstMonitorStatus != ''">
+                and toer.mobile_first_monitor_status = upper(#{mobileFirstMonitorStatus})
+            </if>
+            <if test="mobileSecondMonitorStatus != null and mobileSecondMonitorStatus != ''">
+                and toer.mobile_second_monitor_status = upper(#{mobileSecondMonitorStatus})
+            </if>
+        </where>) t,
         (SELECT @i := 0) as i
         order by t.warningNew desc
     </select>
@@ -286,18 +376,114 @@
 
     <select id="invigilatePagePatrolList" resultType="com.qmth.themis.business.bean.admin.InvigilateListPatrolBean">
         select (@i := @i + 1) as seq,t.* from(
-        <include refid="invigilatePageHead"/>
-        ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = t.id) as exceptionCount
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
+        select
+        temp.*,
+        toer.id as examRecordId,
+        IFNULL(toer.paper_download,1) as paperDownload,
+        toer.status as statusCode,
+        TRUNCATE(toer.answer_progress,2) as progress,
+        IFNULL(toer.client_current_ip,'无') as clientCurrentIp,
+        IFNULL(toer.warning_count,0) as warningCount,
+        IFNULL(toer.breach_status,1) as breachStatus,
+        IFNULL(toer.client_websocket_status,'OFF_LINE') as clientWebsocketStatus,
+        toer.client_last_sync_time as updateTime,
+        toer.monitor_video_source as monitorVideoSource,
+        toer.monitor_record as monitorRecord,
+        toer.finish_type as finishType
+        ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = toer.id) as exceptionCount
+        ,(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
-        <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')
+        from
+        (
+        select
+        distinct s.exam_id as examId,
+        tee.name as examName,
+        s.exam_activity_id as examActivityId,
+        teea.code as examActivityCode,
+        s.id as examStudentId,
+        s.identity,
+        s.room_code as roomCode,
+        s.room_name as roomName,
+        s.name,
+        s.course_name as courseName,
+        s.course_code as courseCode,
+        tes.mobile_number as mobileNumber
+        from
+        t_e_exam_student s
+        left join t_e_exam tee on
+        tee.id = s.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = s.exam_activity_id
+        left join t_e_student tes on
+        s.student_id = tes.id
+        WHERE
+        <choose>
+            <when test="status != null and status != '' and status == 'UN_FINISH'">
+                NOT EXISTS(
+            </when>
+            <otherwise>
+                EXISTS(
+            </otherwise>
+        </choose>
+        select
+        toer.exam_student_id
+        from
+        t_oe_exam_record toer
+        where
+        s.id = toer.exam_student_id)
+        <if test="examId != null and examId != ''">
+            and s.exam_id = #{examId}
         </if>
-        ) t,(SELECT @i := 0) as i
-        <where>
+        <if test="userId != null and userId != ''">
+            and exists (select tbeiu.exam_id from t_b_exam_invigilate_user tbeiu
+            where tbeiu.user_id = #{userId}
+            and tbeiu.exam_id = s.exam_id and tbeiu.room_code = s.room_code)
+        </if>
+        <if test="orgId != null and orgId != ''">
+            and tee.org_id = #{orgId}
+        </if>
+        <if test="examActivityId != null and examActivityId != ''">
+            and s.exam_activity_id = #{examActivityId}
+        </if>
+        <if test="roomCode != null and roomCode != ''">
+            and s.room_code = #{roomCode}
+        </if>
+        <if test="name != null and name !=''">
+            and s.name like CONCAT('%', #{name},'%')
+        </if>
+        <if test="identity != null and identity !=''">
+            and s.identity like CONCAT('%', #{identity},'%')
+        </if>
+        and teea.finish_time > unix_timestamp(current_timestamp()) * 1000
+        ) temp
+        left join t_oe_exam_record toer on
+        toer.exam_student_id = temp.examStudentId
+        <where> 1 = 1
+            <if test="status != null and status != '' and status != 'UN_FINISH'">
+                <choose>
+                    <when test="status == 'EXAMING'">
+                        and (toer.status = 'ANSWERING' or toer.status = 'RESUME_PREPARE' or toer.status = 'BREAK_OFF')
+                    </when>
+                    <otherwise>
+                        and toer.status = #{status}
+                    </otherwise>
+                </choose>
+            </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>
+            <if test="clientWebsocketStatus != null and clientWebsocketStatus != ''">
+                and toer.client_websocket_status = #{clientWebsocketStatus}
+            </if>
+            <if test="status == null or status == ''">
+                and (toer.status = 'FIRST_PREPARE' or toer.status = 'ANSWERING' or toer.status = 'BREAK_OFF' or toer.status = 'RESUME_PREPARE')
+            </if>
+        </where>) t,
+        (SELECT @i := 0) as i
+        <where> 1 = 1
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
                 and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
             </if>
@@ -311,7 +497,7 @@
                 and t.exceptionCount &lt;= #{maxExceptionCount}
             </if>
         </where>
-        order by t.roomCode
+        order by t.roomCode desc
     </select>
 
     <select id="invigilatePageWarningList" resultType="com.qmth.themis.business.bean.admin.InvigilateListWarningBean">
@@ -379,7 +565,7 @@
             </if>
         </where>
         ) t,(SELECT @i := 0) as i
-        <where>
+        <where> 1 = 1
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
                 and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
             </if>
@@ -575,33 +761,133 @@
     </select>
 
     <select id="invigilatePageListHistory" resultType="com.qmth.themis.business.bean.admin.InvigilateListHistoryBean">
+        <include refid="invigilatePageListHistorySql" />
+    </select>
+
+    <sql id="invigilatePageListHistorySql">
         select (@i := @i + 1) as seq,t.* from(
-        <include refid="invigilatePageHead"/>
-        ,tes.mobile_number as mobileNumber
-        ,t.finish_type as finishType
-        ,(select count(1) from t_ie_invigilate_warn_info tiiwi where tiiwi.exam_record_id = t.id and tiiwi.`type` =
+        select
+        temp.*,
+        toer.id as examRecordId,
+        IFNULL(toer.paper_download,1) as paperDownload,
+        toer.status as statusCode,
+        TRUNCATE(toer.answer_progress,2) as progress,
+        IFNULL(toer.client_current_ip,'无') as clientCurrentIp,
+        IFNULL(toer.warning_count,0) as warningCount,
+        IFNULL(toer.breach_status,1) as breachStatus,
+        IFNULL(toer.client_websocket_status,'OFF_LINE') as clientWebsocketStatus,
+        toer.client_last_sync_time as updateTime,
+        toer.monitor_video_source as monitorVideoSource,
+        toer.monitor_record as monitorRecord,
+        toer.finish_type as finishType
+        ,(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 = t.id) as exceptionCount
-        <include refid="invigilatePageMiddle"/>
-        left join t_e_student tes on s.student_id = tes.id
-        <include refid="invigilatePageHistoryFoot"/>
-        <if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
-            <if test="breachStatus == 0">
-                and t.breach_status = #{breachStatus}
-            </if>
-            <if test="breachStatus == 1">
-                and (t.breach_status = #{breachStatus} or t.breach_status is null)
-            </if>
+        ,(select count(1) from t_ie_invigilate_exception_info tiiei where tiiei.exam_record_id = toer.id) as exceptionCount
+        from
+        (
+        select
+        distinct s.exam_id as examId,
+        tee.name as examName,
+        s.exam_activity_id as examActivityId,
+        teea.code as examActivityCode,
+        s.id as examStudentId,
+        s.identity,
+        s.room_code as roomCode,
+        s.room_name as roomName,
+        s.name,
+        s.course_name as courseName,
+        s.course_code as courseCode,
+        tes.mobile_number as mobileNumber
+        from
+        t_e_exam_student s
+        left join t_e_exam tee on
+        tee.id = s.exam_id
+        left join t_e_exam_activity teea on
+        teea.id = s.exam_activity_id
+        left join t_e_student tes on
+        s.student_id = tes.id
+        WHERE
+        <choose>
+            <when test="status != null and status != '' and status == 'UN_FINISH'">
+                NOT EXISTS(
+            </when>
+            <otherwise>
+                EXISTS(
+            </otherwise>
+        </choose>
+        select
+        toer.exam_student_id
+        from
+        t_oe_exam_record toer
+        where
+        s.id = toer.exam_student_id)
+        <if test="examId != null and examId != ''">
+            and s.exam_id = #{examId}
         </if>
-        <if test="finishType != null and finishType != ''">
-            and t.finish_type = #{finishType}
+        <if test="userId != null and userId != ''">
+            and exists (select tbeiu.exam_id from t_b_exam_invigilate_user tbeiu
+            where tbeiu.user_id = #{userId}
+            and tbeiu.exam_id = s.exam_id and tbeiu.room_code = s.room_code)
+        </if>
+        <if test="orgId != null and orgId != ''">
+            and tee.org_id = #{orgId}
+        </if>
+        <if test="examActivityId != null and examActivityId != ''">
+            and s.exam_activity_id = #{examActivityId}
+        </if>
+        <if test="roomCode != null and roomCode != ''">
+            and s.room_code = #{roomCode}
+        </if>
+        <if test="name != null and name !=''">
+            and s.name like CONCAT('%', #{name},'%')
+        </if>
+        <if test="identity != null and identity !=''">
+            and s.identity like CONCAT('%', #{identity},'%')
         </if>
         <if test="courseCode != null and courseCode != ''">
             and s.course_code like CONCAT('%', #{courseCode},'%')
         </if>
-        ) t,
+        ) temp
+        left join t_oe_exam_record toer on
+        toer.exam_student_id = temp.examStudentId
+        <where> 1 = 1
+            <if test="status != null and status != '' and status != 'UN_FINISH'">
+                <choose>
+                    <when test="status == 'EXAMING'">
+                        and (toer.status = 'ANSWERING' or toer.status = 'RESUME_PREPARE' or toer.status = 'BREAK_OFF')
+                    </when>
+                    <otherwise>
+                        and toer.status = #{status}
+                    </otherwise>
+                </choose>
+            </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>
+            <if test="breachStatus != null and breachStatus != '' or breachStatus == 0">
+                <if test="breachStatus == 0">
+                    and toer.breach_status = #{breachStatus}
+                </if>
+                <if test="breachStatus == 1">
+                    and (toer.breach_status = #{breachStatus} or toer.breach_status is null)
+                </if>
+            </if>
+            <if test="finishType != null and finishType != ''">
+                <choose>
+                    <when test="finishType == 'ALL'">
+                        and (toer.finish_type = 'MANUAL' or toer.finish_type = 'AUTO' or toer.finish_type = 'BREACH' or toer.finish_type = 'INTERRUPT')
+                    </when>
+                    <otherwise>
+                        and toer.finish_type = #{finishType}
+                    </otherwise>
+                </choose>
+            </if>
+        </where>) t,
         (SELECT @i := 0) as i
-        <where>
+        <where> 1 = 1
             <if test="minMultipleFaceCount != null and minMultipleFaceCount != '' or minMultipleFaceCount == 0">
                 and t.multipleFaceCount &gt;= #{minMultipleFaceCount}
             </if>
@@ -616,6 +902,10 @@
             </if>
         </where>
         order by t.roomCode
+    </sql>
+
+    <select id="invigilatePageListHistoryExport" resultType="com.qmth.themis.business.bean.admin.InvigilateListHistoryBean">
+        <include refid="invigilatePageListHistorySql" />
     </select>
 
     <select id="getDoneCount" resultType="java.util.Map">
@@ -1021,7 +1311,6 @@
             #{roomCode}
         </foreach>
         and t.STATUS = 'FIRST_PREPARE'
-        and t.client_websocket_status = 'ON_LINE'
         union all
         select
         count(1) as c
@@ -1035,8 +1324,9 @@
         <foreach collection="roomCodeSet" item="roomCode" index="index" open="(" close=")" separator=",">
             #{roomCode}
         </foreach>
-        and t.STATUS = 'ANSWERING'
-        and t.client_websocket_status = 'ON_LINE'
+        and ((t.STATUS = 'ANSWERING' and t.client_websocket_status = 'ON_LINE')
+           or t.STATUS = 'RESUME_PREPARE'
+           or t.STATUS = 'BREAK_OFF')
         union all
         select
         count(distinct t.exam_student_id) as c