瀏覽代碼

监考已审列表

deason 11 月之前
父節點
當前提交
d81ae04a72

+ 13 - 9
examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamAuditController.java

@@ -15,8 +15,8 @@ import cn.com.qmth.examcloud.core.oe.admin.dao.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.admin.dao.entity.IllegallyTypeEntity;
 import cn.com.qmth.examcloud.core.oe.admin.service.AsyncExportService;
 import cn.com.qmth.examcloud.core.oe.admin.service.ExamAuditService;
+import cn.com.qmth.examcloud.core.oe.admin.service.ExamRecordAlreadyAuditService;
 import cn.com.qmth.examcloud.core.oe.admin.service.ExamRecordIllegallyService;
-import cn.com.qmth.examcloud.core.oe.admin.service.bean.UserDataRules;
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditExcel;
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditInfo;
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditQuery;
@@ -59,6 +59,9 @@ public class ExamAuditController extends ControllerSupport {
     @Autowired
     private ExamRecordIllegallyService examRecordIllegallyService;
 
+    @Autowired
+    private ExamRecordAlreadyAuditService examRecordAlreadyAuditService;
+
     @Autowired
     private ExamRecordDataRepo examRecordDataRepo;
 
@@ -73,14 +76,15 @@ public class ExamAuditController extends ControllerSupport {
     @ApiOperation(value = "查询“监考已审”列表(分页)")
     public Page<ExamAuditInfo> getExamAuditList(@RequestBody ExamAuditQuery query) {
         User user = getAccessUser();
-        query.setRootOrgId(user.getRootOrgId());
-        UserDataRules uds = new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
-        Page<ExamAuditInfo> examAuditList = examAuditService.getExamAuditList(uds, query);
+        UserDataRule courseRule = super.getUserDataRule(DataRuleType.COURSE);
+        UserDataRule orgRule = super.getUserDataRule(DataRuleType.ORG);
+
+        Page<ExamAuditInfo> page = examRecordAlreadyAuditService.getExamRecordAlreadyAuditList(query, courseRule, orgRule);
 
-        examAuditList.getContent().forEach(p -> {
+        page.getContent().forEach(p -> {
             p.setIdentityNumber(IdentityNumberHelper.conceal(user.getRootOrgId(), p.getIdentityNumber()));
         });
-        return examAuditList;
+        return page;
     }
 
 
@@ -101,12 +105,12 @@ public class ExamAuditController extends ControllerSupport {
         UserDataRule courseRule = super.getUserDataRule(DataRuleType.COURSE);
         UserDataRule orgRule = super.getUserDataRule(DataRuleType.ORG);
 
-        Page<ExamAuditInfo> examAuditList = examRecordIllegallyService.getExamRecordIllegallyList(query, courseRule, orgRule);
+        Page<ExamAuditInfo> page = examRecordIllegallyService.getExamRecordIllegallyList(query, courseRule, orgRule);
 
-        examAuditList.getContent().forEach(p -> {
+        page.getContent().forEach(p -> {
             p.setIdentityNumber(IdentityNumberHelper.conceal(user.getRootOrgId(), p.getIdentityNumber()));
         });
-        return examAuditList;
+        return page;
     }
 
     @DataRule(type = {DataRuleType.COURSE, DataRuleType.ORG})

+ 5 - 0
examcloud-core-oe-admin-base/src/main/java/cn/com/qmth/examcloud/core/oe/admin/base/Constants.java

@@ -59,4 +59,9 @@ public interface Constants {
      */
     long M_SIZE = 1048576;
 
+    /**
+     * 系统审核
+     */
+    String AUDIT_USER_NAME = "SYSTEM";
+
 }

+ 23 - 0
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/ExamRecordAlreadyAuditService.java

@@ -0,0 +1,23 @@
+package cn.com.qmth.examcloud.core.oe.admin.service;
+
+import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditExcel;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditInfo;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditQuery;
+import org.springframework.data.domain.Page;
+
+import java.util.List;
+
+public interface ExamRecordAlreadyAuditService {
+
+    /**
+     * 查询“监考已审”列表(分页)
+     */
+    Page<ExamAuditInfo> getExamRecordAlreadyAuditList(ExamAuditQuery query, UserDataRule courseRule, UserDataRule orgRule);
+
+    /**
+     * 查询“监考已审”列表(导出Excel)
+     */
+    List<ExamAuditExcel> getExamRecordAlreadyAuditListForExport(ExamAuditQuery query, UserDataRule courseRule, UserDataRule orgRule);
+
+}

+ 306 - 0
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordAlreadyAuditServiceImpl.java

@@ -0,0 +1,306 @@
+package cn.com.qmth.examcloud.core.oe.admin.service.impl;
+
+import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
+import cn.com.qmth.examcloud.commons.util.DateUtil;
+import cn.com.qmth.examcloud.core.oe.admin.base.Constants;
+import cn.com.qmth.examcloud.core.oe.admin.base.jpa.SpecUtils;
+import cn.com.qmth.examcloud.core.oe.admin.base.utils.Check;
+import cn.com.qmth.examcloud.core.oe.admin.dao.enums.AuditStatus;
+import cn.com.qmth.examcloud.core.oe.admin.dao.enums.CourseLevel;
+import cn.com.qmth.examcloud.core.oe.admin.dao.enums.IsSuccess;
+import cn.com.qmth.examcloud.core.oe.admin.dao.enums.SelectType;
+import cn.com.qmth.examcloud.core.oe.admin.service.ExamRecordAlreadyAuditService;
+import cn.com.qmth.examcloud.core.oe.admin.service.IllegallyTypeService;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditEntityConvert;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditExcel;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditInfo;
+import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditQuery;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
+import cn.com.qmth.examcloud.support.cache.bean.CourseCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExamSettingsCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExamStageCacheBean;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class ExamRecordAlreadyAuditServiceImpl implements ExamRecordAlreadyAuditService {
+
+    private static final Logger log = LoggerFactory.getLogger(ExamRecordAlreadyAuditServiceImpl.class);
+
+    @Autowired
+    private IllegallyTypeService illegallyTypeService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Override
+    public Page<ExamAuditInfo> getExamRecordAlreadyAuditList(ExamAuditQuery query, UserDataRule courseRule, UserDataRule orgRule) {
+        Check.isNull(query, "请求参数不能为空!");
+        Check.isNull(query.getExamId(), "请先选择考试!");
+
+        Pageable pageable = SpecUtils.buildPageable(query.getPageNo(), query.getPageSize());
+        if (courseRule.assertEmptyQueryResult() || orgRule.assertEmptyQueryResult()) {
+            return Page.empty(pageable);
+        }
+
+        int offset = (query.getPageNo() - 1) * query.getPageSize();
+        String countSql = this.queryExamRecordAlreadyAuditListSql(query, true, courseRule, orgRule);
+        String querySql = this.queryExamRecordAlreadyAuditListSql(query, false, courseRule, orgRule);
+        String pageSql = querySql + " limit " + offset + "," + query.getPageSize();
+        log.debug(pageSql);
+
+        Long totalElements = jdbcTemplate.queryForObject(countSql, Long.class);
+        if (totalElements == null || totalElements == 0) {
+            return Page.empty(pageable);
+        }
+
+        List<ExamAuditInfo> list = jdbcTemplate.query(pageSql, new BeanPropertyRowMapper(ExamAuditInfo.class));
+        if (CollectionUtils.isEmpty(list)) {
+            return Page.empty(pageable);
+        }
+
+        // 填充其它信息
+        this.fillOtherInfo(list, query.getExamId());
+
+        return new PageImpl<>(list, pageable, totalElements);
+    }
+
+    @Override
+    public List<ExamAuditExcel> getExamRecordAlreadyAuditListForExport(ExamAuditQuery query, UserDataRule courseRule, UserDataRule orgRule) {
+        Check.isNull(query, "请求参数不能为空!");
+        Check.isNull(query.getExamId(), "请先选择考试!");
+        query.setSelectType(SelectType.EXPORT);
+
+        if (courseRule.assertEmptyQueryResult() || orgRule.assertEmptyQueryResult()) {
+            return new ArrayList<>();
+        }
+
+        // 仅导出结果
+        String querySql = this.queryExamRecordAlreadyAuditListSql(query, false, courseRule, orgRule);
+        log.debug(querySql);
+        List<ExamAuditInfo> list = jdbcTemplate.query(querySql, new BeanPropertyRowMapper(ExamAuditInfo.class));
+
+        // 填充其它信息
+        this.fillOtherInfo(list, query.getExamId());
+
+        return ExamAuditEntityConvert.ofExcel(list);
+    }
+
+    private void fillOtherInfo(List<ExamAuditInfo> list, Long examId) {
+        ExamSettingsCacheBean examCache = CacheHelper.getExamSettings(examId);
+        Map<Long, String> orgMaps = new HashMap<>();
+        Map<Long, CourseCacheBean> courseMaps = new HashMap<>();
+        Map<Long, ExamStageCacheBean> examStageMaps = new HashMap<>();
+
+        Map<String, String> illegallyTypeMaps = illegallyTypeService.getIllegallyTypes(examCache.getRootOrgId());
+
+        for (ExamAuditInfo info : list) {
+            // 考试名称
+            info.setExamName(examCache.getName());
+
+            // 学习中心名称
+            String orgName = orgMaps.get(info.getOrgId());
+            if (orgName == null) {
+                orgName = CacheHelper.getOrg(info.getOrgId()).getName();
+                orgMaps.put(info.getOrgId(), orgName);
+            }
+            info.setOrgName(orgName);
+
+            // 课程信息
+            CourseCacheBean course = courseMaps.get(info.getCourseId());
+            if (course == null) {
+                course = CacheHelper.getCourse(info.getCourseId());
+                courseMaps.put(info.getCourseId(), course);
+            }
+            info.setCourseCode(course.getCode());
+            info.setCourseName(course.getName());
+            info.setCourseLevel(CourseLevel.getCourseLevel(course.getLevel()).getTitle());
+
+            // 场次信息
+            if (info.getExamStageId() != null) {
+                ExamStageCacheBean examStage = examStageMaps.get(info.getExamStageId());
+                if (examStage == null) {
+                    examStage = CacheHelper.getExamStage(examId, info.getExamStageId());
+                    examStageMaps.put(info.getExamStageId(), examStage);
+                }
+                info.setExamStageOrder(examStage.getStageOrder());
+                info.setStartTime(examStage.getStartTime());
+                info.setEndTime(examStage.getEndTime());
+                info.setExamStage(examStage.getStageOrder() + "("
+                        + DateUtil.format(examStage.getStartTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + "至"
+                        + DateUtil.format(examStage.getEndTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + ")");
+            }
+
+            // 违规类型名称
+            info.setDisciplineType(illegallyTypeMaps.get(info.getDisciplineType()));
+            info.setStatus(AuditStatus.getTitle(info.getStatus()));
+            IsSuccess result = IsSuccess.strToEnum(info.getFaceVerifyResult());
+            if (result != null) {
+                info.setFaceVerifyResult(result.getDesc());
+            }
+        }
+    }
+
+    private String queryExamRecordAlreadyAuditListSql(ExamAuditQuery query, boolean isCount
+            , UserDataRule courseRule, UserDataRule orgRule) {
+        StringBuilder sql = new StringBuilder();
+        if (isCount) {
+            sql.append(" select count(DISTINCT rd.id)");
+        } else {
+            sql.append(" select rd.id AS examRecordDataId,rd.exam_id,rd.exam_type,");
+            sql.append(" rd.course_id,rd.org_id,rd.exam_stage_id,rd.student_id,");
+            sql.append(" rd.exam_student_id,rd.student_code,rd.student_name,rd.identity_number,");
+            sql.append(" rd.start_time AS paperStartTime,rd.end_time AS paperSubmitTime,rd.exam_order,");
+            sql.append(" rd.face_total_count,rd.face_success_count,rd.face_failed_count,");
+            sql.append(" rd.face_success_percent,rd.face_stranger_count,rd.face_verify_result,");
+            sql.append(" rd.switch_screen_count,sco.objective_score,a.id,a.status,a.discipline_type,");
+            sql.append(" a.discipline_detail,a.audit_user_name,a.update_time AS paperAuditTime,");
+            sql.append(" (select GROUP_CONCAT(DISTINCT pr.source_ip) from ec_oe_exam_process_record pr")
+                    .append(" where pr.exam_record_data_id = rd.id) ip");
+        }
+
+        sql.append(" from ec_oe_exam_record_data rd ");
+        sql.append(" left join ec_oe_exam_audit a on a.exam_record_data_id = rd.id");
+        sql.append(" left join ec_oe_exam_score sco on sco.exam_record_data_id = rd.id");
+
+        sql.append(" where rd.exam_id = ").append(query.getExamId());
+        sql.append(" and rd.exam_record_status != 'EXAM_INVALID'");
+
+        sql.append(" and exists (");
+        sql.append(" select aa.exam_record_data_id from ec_oe_exam_audit aa");
+        sql.append(" where aa.exam_record_data_id = rd.id");
+        if (StringUtils.isNotBlank(query.getStatus())) {
+            sql.append(" and aa.status = '").append(query.getStatus()).append("'");
+        }
+        if (StringUtils.isNotBlank(query.getDisciplineType())) {
+            sql.append(" and aa.discipline_type = '").append(query.getDisciplineType()).append("'");
+        }
+        if (StringUtils.isNotBlank(query.getAuditStartTime()) && StringUtils.isNotBlank(query.getAuditEndTime())) {
+            sql.append(" and aa.update_time >= '").append(query.getAuditStartTime()).append("'");
+            sql.append(" and aa.update_time <= '").append(query.getAuditEndTime()).append("'");
+        }
+        if (StringUtils.isNotBlank(query.getAuditType())) {
+            if ("1".equals(query.getAuditType())) {
+                // 系统审核
+                sql.append(" and aa.audit_user_name = '").append(Constants.AUDIT_USER_NAME).append("'");
+            } else {
+                // 人工审核
+                if (StringUtils.isNotBlank(query.getAuditUserName())) {
+                    if (Constants.AUDIT_USER_NAME.equals(query.getAuditUserName())) {
+                        // 排除SYSTEM关键字
+                        sql.append(" and aa.audit_user_name != '").append(Constants.AUDIT_USER_NAME).append("'");
+                    }
+                    sql.append(" and aa.audit_user_name like '").append(query.getAuditUserName()).append("%'");
+                } else {
+                    sql.append(" and aa.audit_user_name != '").append(Constants.AUDIT_USER_NAME).append("'");
+                }
+            }
+        } else {
+            if (StringUtils.isNotBlank(query.getAuditUserName())) {
+                sql.append(" and aa.audit_user_name like '").append(query.getAuditUserName()).append("%'");
+            }
+        }
+        sql.append(" )");
+
+        if (query.getExamRecordDataId() != null) {
+            sql.append(" and rd.id = ").append(query.getExamRecordDataId());
+        }
+
+        if (courseRule.assertNeedQueryRefIds()) {
+            // 限定课程数据权限范围
+            if (query.getCourseId() != null) {
+                if (courseRule.getRefIds().contains(query.getCourseId())) {
+                    sql.append(" and rd.course_id = ").append(query.getCourseId());
+                } else {
+                    // 不在数据权限范围内,无效查询
+                    sql.append(" and rd.course_id = -1");
+                }
+            } else {
+                sql.append(" and rd.course_id in (").append(StringUtils.join(courseRule.getRefIds(), ",")).append(")");
+            }
+        } else {
+            // 未限定数据权限
+            if (query.getCourseId() != null) {
+                sql.append(" and rd.course_id = ").append(query.getCourseId());
+            }
+        }
+
+        if (orgRule.assertNeedQueryRefIds()) {
+            // 限定机构数据权限范围
+            if (query.getOrgId() != null) {
+                if (orgRule.getRefIds().contains(query.getOrgId())) {
+                    sql.append(" and rd.org_id = ").append(query.getOrgId());
+                } else {
+                    // 不在数据权限范围内,无效查询
+                    sql.append(" and rd.org_id = -1");
+                }
+            } else {
+                sql.append(" and rd.org_id in (").append(StringUtils.join(orgRule.getRefIds(), ",")).append(")");
+            }
+        } else {
+            // 未限定数据权限
+            if (query.getOrgId() != null) {
+                sql.append(" and rd.org_id = ").append(query.getOrgId());
+            }
+        }
+
+        if (query.getExamStageId() != null) {
+            sql.append(" and rd.exam_stage_id = ").append(query.getExamStageId());
+        }
+        if (StringUtils.isNotBlank(query.getCourseLevel())) {
+            sql.append(" and rd.course_level = '").append(query.getCourseLevel()).append("'");
+        }
+        if (StringUtils.isNotBlank(query.getIdentityNumber())) {
+            sql.append(" and rd.identity_number like '").append(query.getIdentityNumber()).append("%'");
+        }
+        if (StringUtils.isNotBlank(query.getStudentCode())) {
+            sql.append(" and rd.student_code like '").append(query.getStudentCode()).append("%'");
+        }
+        if (StringUtils.isNotBlank(query.getStudentName())) {
+            sql.append(" and rd.student_name like '").append(query.getStudentName()).append("%'");
+        }
+
+        if (query.getSwitchScreenCountStart() != null) {
+            sql.append(" and rd.switch_screen_count >= ").append(query.getSwitchScreenCountStart());
+        }
+        if (query.getSwitchScreenCountEnd() != null) {
+            sql.append(" and rd.switch_screen_count <= ").append(query.getSwitchScreenCountEnd());
+        }
+
+        if (StringUtils.isNotBlank(query.getStartTime()) && StringUtils.isNotBlank(query.getEndTime())) {
+            sql.append(" and rd.start_time >= '").append(query.getStartTime()).append("'");
+            sql.append(" and rd.start_time <= '").append(query.getEndTime()).append("'");
+        }
+
+        if (StringUtils.isNotBlank(query.getSubmitStartTime()) && StringUtils.isNotBlank(query.getSubmitEndTime())) {
+            sql.append(" and rd.end_time >= '").append(query.getSubmitStartTime()).append("'");
+            sql.append(" and rd.end_time <= '").append(query.getSubmitEndTime()).append("'");
+        }
+
+        if (!isCount) {
+            sql.append(" group by rd.id");
+
+            if (SelectType.EXPORT != query.getSelectType()) {
+                // sql.append(" order by rd.id desc");
+                sql.append(" order by rd.update_time desc");
+            }
+        }
+
+        return sql.toString();
+    }
+
+}

+ 18 - 0
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordIllegallyServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.com.qmth.examcloud.core.oe.admin.service.impl;
 
 import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
+import cn.com.qmth.examcloud.commons.util.DateUtil;
 import cn.com.qmth.examcloud.core.oe.admin.base.jpa.SpecUtils;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.admin.dao.enums.CourseLevel;
@@ -14,6 +15,7 @@ import cn.com.qmth.examcloud.core.oe.admin.service.bean.examaudit.ExamAuditQuery
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.CourseCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.ExamSettingsCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExamStageCacheBean;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -99,6 +101,7 @@ public class ExamRecordIllegallyServiceImpl implements ExamRecordIllegallyServic
         ExamSettingsCacheBean examCache = CacheHelper.getExamSettings(examId);
         Map<Long, String> orgMaps = new HashMap<>();
         Map<Long, CourseCacheBean> courseMaps = new HashMap<>();
+        Map<Long, ExamStageCacheBean> examStageMaps = new HashMap<>();
 
         Map<String, String> illegallyTypeMaps = illegallyTypeService.getIllegallyTypes(examCache.getRootOrgId());
 
@@ -124,6 +127,21 @@ public class ExamRecordIllegallyServiceImpl implements ExamRecordIllegallyServic
             info.setCourseName(course.getName());
             info.setCourseLevel(CourseLevel.getCourseLevel(course.getLevel()).getTitle());
 
+            // 场次信息
+            if (info.getExamStageId() != null) {
+                ExamStageCacheBean examStage = examStageMaps.get(info.getExamStageId());
+                if (examStage == null) {
+                    examStage = CacheHelper.getExamStage(examId, info.getExamStageId());
+                    examStageMaps.put(info.getExamStageId(), examStage);
+                }
+                info.setExamStageOrder(examStage.getStageOrder());
+                info.setStartTime(examStage.getStartTime());
+                info.setEndTime(examStage.getEndTime());
+                info.setExamStage(examStage.getStageOrder() + "("
+                        + DateUtil.format(examStage.getStartTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + "至"
+                        + DateUtil.format(examStage.getEndTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + ")");
+            }
+
             // 违规类型名称
             info.setDisciplineType(illegallyTypeMaps.get(info.getDisciplineType()));
         }