deason 2 年之前
父节点
当前提交
d650a5c085

+ 54 - 2
src/main/java/cn/com/qmth/examcloud/tool/service/export_student_answer_and_score_detail/ExportStudentAnswerAndScoreDetailTask.java

@@ -4,6 +4,8 @@ import cn.com.qmth.examcloud.tool.config.SysProperty;
 import cn.com.qmth.examcloud.tool.entity.TaskEntity;
 import cn.com.qmth.examcloud.tool.service.CommonService;
 import cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo.CourseVO;
+import cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo.ExamQuestionVO;
+import cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo.ExamRecordQuestionsVO;
 import cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo.ExamStudentScoreVO;
 import cn.com.qmth.examcloud.tool.utils.*;
 import cn.com.qmth.examcloud.tool.vo.Pager;
@@ -87,7 +89,8 @@ public class ExportStudentAnswerAndScoreDetailTask {
     private void export(Long examId, CourseVO course, User user, String tempDir) {
         List<ExamStudentScoreVO> examStudentScoreList = this.getExamStudentScoreList(user.getKey(), user.getToken(), examId, course.getCourseId());
 
-        //todo
+        // Excel动态列
+        List<String> dynamicExcelHeaders = new ArrayList<>();
 
         List<List<Object>> excelRows = new ArrayList<>();
         for (ExamStudentScoreVO vo : examStudentScoreList) {
@@ -106,9 +109,35 @@ public class ExportStudentAnswerAndScoreDetailTask {
                     vo.getSubjectiveScore(),
                     vo.getFinalExamScore());
             excelRows.add(rowValues);
+
+            if (vo.getExamRecordDataId() == null) {
+                // 跳过缺考的情况
+                log.info("identityNumber={} finished={} absent={}", vo.getIdentityNumber(), vo.getIsFinished(), vo.getIsAbsent());
+                continue;
+            }
+
+            // 获取考试试题作答记录
+            List<ExamQuestionVO> questions = this.getExamRecordQuestions(user.getKey(), user.getToken(), vo.getExamRecordDataId());
+
+            if (dynamicExcelHeaders.isEmpty()) {
+                for (ExamQuestionVO question : questions) {
+                    dynamicExcelHeaders.add(String.format("%s%s-%s作答", question.getQuestionType().getDesc(), question.getMainNumber(), question.getOrder()));
+                    dynamicExcelHeaders.add(String.format("%s%s-%s得分", question.getQuestionType().getDesc(), question.getMainNumber(), question.getOrder()));
+                }
+            }
+
+            // Excel动态列值
+            List<Object> dynamicColumnValues = new ArrayList<>();
+            for (ExamQuestionVO question : questions) {
+                dynamicColumnValues.add(question.getStudentAnswer());
+                dynamicColumnValues.add("0");
+            }
+            rowValues.addAll(dynamicColumnValues);
         }
 
         List<String> excelHeaders = Lists.newArrayList("学习中心", "课程代码", "课程名称", "课程层次", "是否缺考", "身份证号", "学号", "姓名", "年级", "专业", "客观总分", "主观总分", "总分");
+        excelHeaders.addAll(dynamicExcelHeaders);
+
         final String filePath = sysProperty.getDataDir() + "/" + tempDir + "/" + examId + "_" + course.getCourseCode() + ".xlsx";
         EasyExcel.write(filePath)
                 .head(ExcelHelper.buildHeaders(excelHeaders))
@@ -117,6 +146,29 @@ public class ExportStudentAnswerAndScoreDetailTask {
                 .sheet().doWrite(excelRows);
     }
 
+    /**
+     * 获取考试试题作答记录
+     */
+    private List<ExamQuestionVO> getExamRecordQuestions(String key, String token, Long examRecordDataId) {
+        Map<String, String> params = new HashMap<>();
+        params.put("examRecordDataId", String.valueOf(examRecordDataId));
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("key", key);
+        headers.put("token", token);
+
+        String url = sysProperty.getServerUrl() + "/api/ecs_oe_admin/examRecordQuestions/getExamRecordQuestions";
+        String json = HttpHelper.get(url, headers, params);
+
+        JsonMapper jsonMapper = new JsonMapper();
+        ExamRecordQuestionsVO examRecordQuestions = jsonMapper.parseJson(json, ExamRecordQuestionsVO.class);
+        if (examRecordQuestions == null || CollectionUtils.isEmpty(examRecordQuestions.getExamQuestionEntities())) {
+            return new ArrayList<>();
+        }
+
+        return examRecordQuestions.getExamQuestionEntities();
+    }
+
     /**
      * 获取考生成绩明细列表
      */
@@ -148,7 +200,7 @@ public class ExportStudentAnswerAndScoreDetailTask {
 
             sum += page.getContent().size();
             float rate = sum * 100f / page.getTotalElements();
-            log.info("已获取考生成绩明细数:{} 进度:{}%", sum, rate);
+            log.info("examId={} courseId={} 已获取考生成绩明细数:{} 进度:{}%", examId, courseId, sum, rate);
         }
 
         return all;

+ 45 - 0
src/main/java/cn/com/qmth/examcloud/tool/service/export_student_answer_and_score_detail/vo/AnswerType.java

@@ -0,0 +1,45 @@
+package cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo;
+
+/**
+ * 作答类型
+ */
+public enum AnswerType {
+
+    STRICT("S", "严格作答(可程序判分.如判断,单选...)"),
+
+    DIVERSIFIED_TEXT("DT", "多元化文本(不可程序判分.如非严格填空,简答...)"),
+
+    SINGLE_VIDEO("SV", "单个视频"),
+
+    SINGLE_AUDIO("SA", "单个音频"),
+
+    SINGLE_FILE("SF", "单个文件"),
+
+    SINGLE_PICTURE("SP", "单个照片"),
+
+    MULTIPLE_PICTURES("MP", "多个照片");
+
+    /**
+     * 简码
+     */
+    private String code;
+
+    /**
+     * 描述
+     */
+    private String desc;
+
+    AnswerType(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+}

+ 86 - 0
src/main/java/cn/com/qmth/examcloud/tool/service/export_student_answer_and_score_detail/vo/ExamQuestionVO.java

@@ -0,0 +1,86 @@
+package cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+@Getter
+@Setter
+public class ExamQuestionVO implements Serializable {
+
+    private static final long serialVersionUID = -6141069483774400912L;
+
+    private String id;
+
+    /**
+     * 考试记录Data Id
+     */
+    private Long examRecordDataId;
+
+    /**
+     * 大题号
+     */
+    private Integer mainNumber;
+
+    /**
+     * 原题ID
+     */
+    private String questionId;
+
+    /**
+     * 顺序
+     */
+    private Integer order;
+
+    /**
+     * 小题分数
+     */
+    private Double questionScore;
+
+    /**
+     * 小题类型
+     */
+    private QuestionType questionType;
+
+    /**
+     * 标准答案
+     */
+    private String correctAnswer;
+
+    /**
+     * 考生作答
+     */
+    private String studentAnswer;
+
+    /**
+     * 学生小题得分
+     */
+    private Double studentScore;
+
+    /**
+     * 是否作答
+     */
+    private Boolean isAnswer;
+
+    /**
+     * 是否标记
+     */
+    private Boolean isSign;
+
+    /**
+     * 选项排序值
+     */
+    private Integer[] optionPermutation;
+
+    /**
+     * 音频播放次数
+     */
+    private String audioPlayTimes;
+
+    /**
+     * 题目作答类型
+     */
+    private AnswerType answerType;
+
+}

+ 26 - 0
src/main/java/cn/com/qmth/examcloud/tool/service/export_student_answer_and_score_detail/vo/ExamRecordQuestionsVO.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Getter
+@Setter
+public class ExamRecordQuestionsVO implements Serializable {
+
+    private static final long serialVersionUID = -1688201571728312142L;
+
+    private String id;
+
+    private Long examRecordDataId;
+
+    private Date creationTime;
+
+    private List<ExamQuestionVO> examQuestionEntities;
+
+    private AnswerType answerType;
+
+}

+ 46 - 0
src/main/java/cn/com/qmth/examcloud/tool/service/export_student_answer_and_score_detail/vo/QuestionType.java

@@ -0,0 +1,46 @@
+package cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo;
+
+/**
+ * 题型
+ */
+public enum QuestionType {
+
+    /**
+     * 单选题
+     */
+    SINGLE_CHOICE("单选题"),
+
+    /**
+     * 多选题
+     */
+    MULTIPLE_CHOICE("多选题"),
+
+    /**
+     * 填空题
+     */
+    FILL_UP("填空题"),
+
+    /**
+     * 问答题
+     */
+    ESSAY("问答题"),
+
+    /**
+     * 判断题
+     */
+    TRUE_OR_FALSE("判断题");
+
+    /**
+     * 描述
+     */
+    private String desc;
+
+    QuestionType(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+}

+ 8 - 8
src/main/java/cn/com/qmth/examcloud/tool/utils/HttpHelper.java

@@ -18,9 +18,9 @@ public class HttpHelper {
 
     private static final Logger log = LoggerFactory.getLogger(HttpHelper.class);
 
-    public static String get(String url, Map<String, String> headers, Map<String, Object> params) {
+    public static String get(String url, Map<String, String> headers, Map<String, String> params) {
         String urlParams = toUrlParams(params);
-        log.info("[GET] {}, headers = {}, params = {}", url, headers, urlParams);
+        log.info("[GET] {}, headers: {}, params: {}", url, headers, urlParams);
 
         Request.Builder builder = new Request.Builder().get().url(url + "?" + urlParams);
         return call(url, headers, builder);
@@ -31,7 +31,7 @@ public class HttpHelper {
         if (MapUtils.isNotEmpty(params)) {
             jsonParams = new JsonMapper().toJson(params);
         }
-        log.info("[POST] {}, headers = {}, params = {}", url, headers, jsonParams);
+        log.info("[POST] {}, headers: {}, params: {}", url, headers, jsonParams);
 
         RequestBody requestBody = FormBody.create(jsonParams, MediaType.parse(Constants.CONTENT_TYPE_JSON));
         Request.Builder builder = new Request.Builder().post(requestBody).url(url);
@@ -53,22 +53,22 @@ public class HttpHelper {
                 return bodyStr;
             }
 
-            log.error("{}, response code = {}, body = {}", url, response.code(), bodyStr);
+            log.error("{}, response code: {}, body: {}", url, response.code(), bodyStr);
             throw new StatusException(bodyStr);
         } catch (IOException e) {
-            log.error("{}, error = {}", url, e.getMessage());
+            log.error("{}, error: {}", url, e.getMessage());
             throw new StatusException("接口调用失败!");
         }
     }
 
-    public static String toUrlParams(Map<String, Object> params) {
+    public static String toUrlParams(Map<String, String> params) {
         if (MapUtils.isEmpty(params)) {
             return "";
         }
 
         List<String> pair = new ArrayList<>();
-        for (Map.Entry<String, Object> entry : params.entrySet()) {
-            pair.add(entry.getKey() + "=" + urlEncode((String) entry.getValue()));
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            pair.add(entry.getKey() + "=" + urlEncode(entry.getValue()));
         }
 
         return StringUtils.join(pair, "&");