Pārlūkot izejas kodu

阅卷开放接口

xiatian 4 gadi atpakaļ
vecāks
revīzija
6c28d4c4b5
20 mainītis faili ar 617 papildinājumiem un 27 dzēšanām
  1. 33 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEOpenController.java
  2. 63 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/OpenRecordAnswerBean.java
  3. 99 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/OpenRecordNeedMarkBean.java
  4. 3 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamCourseMapper.java
  5. 7 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamAnswerMapper.java
  6. 4 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  7. 10 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamCourseService.java
  8. 4 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java
  9. 6 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEOpenService.java
  10. 5 0
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamAnswerService.java
  11. 3 0
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  12. 16 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamCourseServiceImpl.java
  13. 7 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java
  14. 236 8
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOpenServiceImpl.java
  15. 14 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamAnswerServiceImpl.java
  16. 53 16
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  17. 6 2
      themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamPaperImportTemplete.java
  18. 6 0
      themis-business/src/main/resources/mapper/TEExamCourseMapper.xml
  19. 20 1
      themis-business/src/main/resources/mapper/TOeExamAnswerMapper.xml
  20. 22 0
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

+ 33 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/TEOpenController.java

@@ -65,5 +65,38 @@ public class TEOpenController {
     	}
         return ResultUtil.ok(openService.examCourseQueryPage(examId, courseCode,hasPaper, pageNumber, pageSize));
     }
+    
+    @ApiOperation(value = "获取考试试卷详情")
+    @RequestMapping(value = "/exam/paper/detail", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "结果信息")})
+    public Result examPaperDetail(@ApiParam(value = "试卷id", required = true) @RequestParam Long paperId,
+                                     @ApiParam(value = "内容过滤卷", required = false) @RequestParam(required = false) String filter) {
+    	if(paperId==null) {
+    		throw new BusinessException("试卷id不能为空");
+    	}
+        return ResultUtil.ok(openService.examPaperDetail(paperId, filter));
+    }
+    
+    @ApiOperation(value = "待评卷考试记录查询")
+    @RequestMapping(value = "/exam/record/need_mark", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "结果信息")})
+    public Result examRecordNeedMark(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
+                                     @ApiParam(value = "内容过滤卷", required = false) @RequestParam(required = false) String courseCode,
+                                     @ApiParam(value = "考试记录ID大于此参数", required = true) @RequestParam Integer idGt,
+                                     @ApiParam(value = "数量(最大20)", required = true) @RequestParam Integer count) {
+    	if(examId==null) {
+    		throw new BusinessException("考试id不能为空");
+    	}
+    	if(idGt==null) {
+    		throw new BusinessException("idGt不能为空");
+    	}
+    	if(count==null) {
+    		throw new BusinessException("count不能为空");
+    	}
+    	if(count>20) {
+    		throw new BusinessException("count最大为20");
+    	}
+        return ResultUtil.ok(openService.examRecordNeedMark(examId, courseCode,idGt,count));
+    }
 
 }

+ 63 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/OpenRecordAnswerBean.java

@@ -0,0 +1,63 @@
+package com.qmth.themis.business.bean.backend;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("开放接口-待评卷考试记录答案")
+public class OpenRecordAnswerBean {
+
+	@ApiModelProperty("考试记录id")
+	private Long recordId;
+	
+	@ApiModelProperty("大题号")
+	private Integer mainNumber;
+
+	@ApiModelProperty("小题号")
+	private Integer subNumber;
+	
+	@ApiModelProperty("套题子题序号")
+	private Integer subIndex;
+	
+	@ApiModelProperty("作答")
+	private String answer;
+
+	public Long getRecordId() {
+		return recordId;
+	}
+
+	public void setRecordId(Long recordId) {
+		this.recordId = recordId;
+	}
+
+	public Integer getMainNumber() {
+		return mainNumber;
+	}
+
+	public void setMainNumber(Integer mainNumber) {
+		this.mainNumber = mainNumber;
+	}
+
+	public Integer getSubNumber() {
+		return subNumber;
+	}
+
+	public void setSubNumber(Integer subNumber) {
+		this.subNumber = subNumber;
+	}
+
+	public Integer getSubIndex() {
+		return subIndex;
+	}
+
+	public void setSubIndex(Integer subIndex) {
+		this.subIndex = subIndex;
+	}
+
+	public String getAnswer() {
+		return answer;
+	}
+
+	public void setAnswer(String answer) {
+		this.answer = answer;
+	}
+}

+ 99 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/OpenRecordNeedMarkBean.java

@@ -0,0 +1,99 @@
+package com.qmth.themis.business.bean.backend;
+
+import java.util.List;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("开放接口-待评卷考试记录")
+public class OpenRecordNeedMarkBean {
+
+	@ApiModelProperty(name = "考试记录id")
+    private Long id;
+
+	@ApiModelProperty(value = "证件号")
+    private String identity;
+
+    @ApiModelProperty(value = "姓名")
+    private String name;
+
+    @ApiModelProperty(value = "场次代码")
+    private String activityCode;
+
+    @ApiModelProperty(value = "课程名称")
+    private String courseName;
+
+    @ApiModelProperty(value = "试卷ID")
+    private Long paperId;
+    
+    @ApiModelProperty(value = "客观得分")
+    private Double objectiveScore;
+    
+    @ApiModelProperty(value = "作答结果")
+    private List<OpenRecordAnswerBean> answers;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public String getIdentity() {
+		return identity;
+	}
+
+	public void setIdentity(String identity) {
+		this.identity = identity;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getActivityCode() {
+		return activityCode;
+	}
+
+	public void setActivityCode(String activityCode) {
+		this.activityCode = activityCode;
+	}
+
+	public String getCourseName() {
+		return courseName;
+	}
+
+	public void setCourseName(String courseName) {
+		this.courseName = courseName;
+	}
+
+	public Long getPaperId() {
+		return paperId;
+	}
+
+	public void setPaperId(Long paperId) {
+		this.paperId = paperId;
+	}
+
+	public Double getObjectiveScore() {
+		return objectiveScore;
+	}
+
+	public void setObjectiveScore(Double objectiveScore) {
+		this.objectiveScore = objectiveScore;
+	}
+
+	public List<OpenRecordAnswerBean> getAnswers() {
+		return answers;
+	}
+
+	public void setAnswers(List<OpenRecordAnswerBean> answers) {
+		this.answers = answers;
+	}
+    
+}

+ 3 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamCourseMapper.java

@@ -1,5 +1,6 @@
 package com.qmth.themis.business.dao;
 
+import java.util.List;
 import java.util.Map;
 
 import org.apache.ibatis.annotations.Mapper;
@@ -37,4 +38,6 @@ public interface TEExamCourseMapper extends BaseMapper<TEExamCourse> {
     public TEExamCourse findByExamIdAndCourseCode(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 
 	public IPage<OpenExamCourseBean> examCourseQueryForOpen(IPage<OpenExamCourseBean> ipage,@Param("examId") Long examId, @Param("courseCode") String courseCode,@Param("hasPaper") Boolean hasPaper);
+
+	public List<TEExamCourse> findByExamId(@Param("examId") Long examId);
 }

+ 7 - 0
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamAnswerMapper.java

@@ -1,8 +1,13 @@
 package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.themis.business.bean.backend.OpenRecordAnswerBean;
 import com.qmth.themis.business.entity.TOeExamAnswer;
+
+import java.util.List;
+
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * @Description: 作答结果 Mapper 接口
@@ -14,4 +19,6 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface TOeExamAnswerMapper extends BaseMapper<TOeExamAnswer> {
 
+	List<OpenRecordAnswerBean> findByRecordIds(@Param("ids") List<Long> ids);
+
 }

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

@@ -17,6 +17,7 @@ import com.qmth.themis.business.bean.backend.InvigilateListProgressBean;
 import com.qmth.themis.business.bean.backend.InvigilateListProgressExcelBean;
 import com.qmth.themis.business.bean.backend.InvigilateListVideoBean;
 import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
+import com.qmth.themis.business.bean.backend.OpenRecordNeedMarkBean;
 import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamRecord;
 
@@ -341,4 +342,7 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
     public List<ExaminationMonitorHourWarnCountBean> getWarnTrend(@Param("startTime") Long startTime);
 
     public void updateHasAnswerFile(@Param("recordId") Long recordId, @Param("hasAnswerFile") Integer hasAnswerFile);
+
+	public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(@Param("examId") Long examId,@Param("courseCode") String courseCode,
+			@Param("idGt")Integer idGt,@Param("count")Integer count);
 }

+ 10 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamCourseService.java

@@ -1,11 +1,14 @@
 package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.bean.backend.OpenExamCourseBean;
 import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
 import com.qmth.themis.business.dto.response.TEExamCourseDto;
 import com.qmth.themis.business.entity.TEExamCourse;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -51,4 +54,11 @@ public interface TEExamCourseService extends IService<TEExamCourse> {
     void deleteExamCourseCacheBean(Long examId, String courseCode);
 
     TEExamCourse findByExamIdAndCourseCode(Long examId, String courseCode);
+
+
+	List<TEExamCourse> findByExamId(Long examId);
+
+
+	public IPage<OpenExamCourseBean> examCourseQueryForOpen(Page<OpenExamCourseBean> ipage, Long examId,
+			String courseCode, Boolean hasPaper);
 }

+ 4 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java

@@ -1,7 +1,9 @@
 package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.bean.backend.OpenExamBean;
 import com.qmth.themis.business.bean.exam.*;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.dto.MqDto;
@@ -199,6 +201,8 @@ public interface TEExamService extends IService<TEExam> {
 	void updateInvigilateMonitorStatus(InvigilateMonitorStatusEnum monitorStatus, Long examId);
 
 	void updateScoreStatus(ScoreStatusEnum scoreStatus, Long examId);
+
+	public IPage<OpenExamBean> examQueryForOpen(Page<OpenExamBean> ipage, Long examId, String examCode);
 	
 	
 }

+ 6 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEOpenService.java

@@ -1,5 +1,7 @@
 package com.qmth.themis.business.service;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.qmth.themis.business.bean.backend.OpenExamBean;
 import com.qmth.themis.business.bean.backend.OpenExamCourseBean;
@@ -10,4 +12,8 @@ public interface TEOpenService {
 
 	public IPage<OpenExamCourseBean> examCourseQueryPage(Long examId, String courseCode, Boolean hasPaper, int pageNumber, int pageSize);
 
+	public JSONObject examPaperDetail(Long paperId, String filter);
+
+	public JSONArray examRecordNeedMark(Long examId, String courseCode, Integer idGt, Integer count);
+
 }

+ 5 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamAnswerService.java

@@ -1,6 +1,9 @@
 package com.qmth.themis.business.service;
 
+import java.util.List;
+
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.bean.backend.OpenRecordAnswerBean;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 
 /**
@@ -12,4 +15,6 @@ import com.qmth.themis.business.entity.TOeExamAnswer;
  */
 public interface TOeExamAnswerService extends IService<TOeExamAnswer> {
 
+	List<OpenRecordAnswerBean> findByRecordIds(List<Long> ids);
+
 }

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

@@ -370,4 +370,7 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
     TOeExamRecord findOneByPaperId(Long paperId);
 
     TOeExamRecord findOneByExamId(Long examId, ExamRecordStatusEnum status);
+
+	public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examId, String courseCode, Integer idGt,
+			Integer count);
 }

+ 16 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamCourseServiceImpl.java

@@ -13,7 +13,9 @@ import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.backend.OpenExamCourseBean;
 import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
 import com.qmth.themis.business.dao.TEExamCourseMapper;
 import com.qmth.themis.business.dao.TEExamPaperMapper;
@@ -136,4 +138,18 @@ public class TEExamCourseServiceImpl extends ServiceImpl<TEExamCourseMapper, TEE
         }
         return ret;
     }
+    
+    @Override
+    public List<TEExamCourse> findByExamId(Long examId) {
+        if (examId == null) {
+            throw new BusinessException("examId is null");
+        }
+        return teExamCourseMapper.findByExamId(examId);
+    }
+
+	@Override
+	public IPage<OpenExamCourseBean> examCourseQueryForOpen(Page<OpenExamCourseBean> ipage, Long examId,
+			String courseCode, Boolean hasPaper) {
+		return teExamCourseMapper.examCourseQueryForOpen(ipage, examId, courseCode, hasPaper);
+	}
 }

+ 7 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -37,7 +37,9 @@ import org.springframework.web.multipart.MultipartFile;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.backend.OpenExamBean;
 import com.qmth.themis.business.bean.exam.AnswerSubmitBean;
 import com.qmth.themis.business.bean.exam.AudioLeftPlayCountSubmitBean;
 import com.qmth.themis.business.bean.exam.ExamFileUploadBean;
@@ -1342,4 +1344,9 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     public void updateScoreStatus(ScoreStatusEnum scoreStatus, Long examId) {
         teExamMapper.updateScoreStatus(scoreStatus, examId);
     }
+
+	@Override
+	public IPage<OpenExamBean> examQueryForOpen(Page<OpenExamBean> ipage, Long examId, String examCode) {
+		return teExamMapper.examQueryForOpen(ipage, examId, examCode);
+	}
 }

+ 236 - 8
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOpenServiceImpl.java

@@ -1,33 +1,67 @@
 package com.qmth.themis.business.service.impl;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
 import javax.annotation.Resource;
 
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.themis.business.bean.backend.OpenExamBean;
 import com.qmth.themis.business.bean.backend.OpenExamCourseBean;
-import com.qmth.themis.business.dao.TEExamCourseMapper;
-import com.qmth.themis.business.dao.TEExamMapper;
+import com.qmth.themis.business.bean.backend.OpenRecordAnswerBean;
+import com.qmth.themis.business.bean.backend.OpenRecordNeedMarkBean;
+import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
+import com.qmth.themis.business.config.SystemConfig;
+import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.entity.TEExam;
+import com.qmth.themis.business.entity.TEExamCourse;
+import com.qmth.themis.business.enums.InvigilateMonitorStatusEnum;
+import com.qmth.themis.business.service.TEExamCourseService;
+import com.qmth.themis.business.service.TEExamPaperService;
+import com.qmth.themis.business.service.TEExamService;
 import com.qmth.themis.business.service.TEOpenService;
+import com.qmth.themis.business.service.TOeExamAnswerService;
+import com.qmth.themis.business.service.TOeExamRecordService;
+import com.qmth.themis.common.exception.BusinessException;
+import com.qmth.themis.common.util.FileUtil;
 
 @Service
 public class TEOpenServiceImpl implements TEOpenService {
 
     @Resource
-    TEExamMapper teExamMapper;
+    TEExamService examService;
+    
+    @Resource
+    TEExamCourseService examCourseService;
+    
+    @Resource
+    TEExamPaperService examPaperService;
     
     @Resource
-    TEExamCourseMapper examCourseMapper;
+    TOeExamRecordService examRecordService;
+    
+    @Resource
+    TOeExamAnswerService examAnswerService;
 	
 	
 	@Override
 	public IPage<OpenExamBean> examQueryPage(Long examId, String examCode, int pageNumber, int pageSize) {
 		Page<OpenExamBean> ipage = new Page<>(pageNumber, pageSize);
-        ipage.addOrder(OrderItem.desc("t.create_time"));
-		return teExamMapper.examQueryForOpen(ipage, examId, examCode);
+        ipage.addOrder(OrderItem.desc("t.id"));
+		return examService.examQueryForOpen(ipage, examId, examCode);
 	}
 
 
@@ -35,8 +69,202 @@ public class TEOpenServiceImpl implements TEOpenService {
 	public IPage<OpenExamCourseBean> examCourseQueryPage(Long examId, String courseCode, Boolean hasPaper,
 			int pageNumber, int pageSize) {
 		Page<OpenExamCourseBean> ipage = new Page<>(pageNumber, pageSize);
-        ipage.addOrder(OrderItem.desc("t.create_time"));
-		return examCourseMapper.examCourseQueryForOpen(ipage, examId,courseCode, hasPaper);
+        ipage.addOrder(OrderItem.desc("t.id"));
+		return examCourseService.examCourseQueryForOpen(ipage, examId,courseCode, hasPaper);
 	}
 
+
+	@Override
+	public JSONObject examPaperDetail(Long paperId, String filter) {
+		String tempDir = SystemConstant.TEMP_FILES_DIR;
+		String dir = tempDir + "/" + uuid() + "/";
+		File dfile = new File(dir);
+		
+		try {
+			ExamPaperCacheBean paper=examPaperService.getExamPaperCacheBean(paperId);
+			if(paper==null) {
+				throw new BusinessException("未找到试卷信息");
+			}
+			checkExam(paper.getExamId());
+			dfile.mkdirs();
+			String paperPath = paper.getPaperViewPath();
+			String anwserPath = paper.getAnswerPath();
+			SystemConfig systemConfig = SpringContextHolder.getBean(SystemConfig.class);
+			File paperFile = new File(dir + uuid() + ".json");
+			File anwserFile = new File(dir + uuid() + ".json");
+			FileUtil.saveUrlAsFile(systemConfig.getProperty("aliyun.oss.url") + "/"+paperPath, paperFile);
+			FileUtil.saveUrlAsFile(systemConfig.getProperty("aliyun.oss.url") + "/"+anwserPath, anwserFile);
+			JSONObject answerJson = JSONObject.parseObject(FileUtil.readFileContent(anwserFile));
+			JSONArray answerdetails = answerJson.getJSONArray("details");
+			JSONObject structJson = JSONObject.parseObject(FileUtil.readFileContent(paperFile));
+			structJson.put("id", paperId);
+			structJson.put("code", paper.getCode());
+			JSONArray structdetails = structJson.getJSONArray("details");
+			for (int i = 0; i < answerdetails.size(); i++) {
+				JSONArray answerdetailquestions = answerdetails.getJSONObject(i).getJSONArray("questions");
+				JSONArray structdetailquestions = structdetails.getJSONObject(i).getJSONArray("questions");
+				for (int j = 0; j < structdetailquestions.size(); j++) {
+					JSONObject answerquestion = answerdetailquestions.getJSONObject(j);
+					JSONObject structquestion = structdetailquestions.getJSONObject(j);
+					if("objective".equals(filter)) {
+						if (structquestion.getInteger("structType").intValue() == 1
+								|| structquestion.getInteger("structType").intValue() == 2
+									|| structquestion.getInteger("structType").intValue() == 3) {
+							if(structquestion.getInteger("structType").intValue() == 3) {
+								structquestion.put("answer", answerquestion.getBoolean("answer"));
+							}else {
+								structquestion.put("answer", answerquestion.getJSONArray("answer"));
+							}
+						}else {
+							if (structquestion.getInteger("structType").intValue() == 6) {
+								JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
+								JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
+								for (int k = 0; k < structsubQuestions.size(); k++) {
+									JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
+									JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
+									if (structsubquestion.getInteger("structType").intValue() == 1
+											|| structsubquestion.getInteger("structType").intValue() == 2
+												|| structsubquestion.getInteger("structType").intValue() == 3) {
+										if (structsubquestion.getInteger("structType").intValue() == 3) {
+											structsubquestion.put("answer", answersubquestion.getBoolean("answer"));
+										}else {
+											structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
+										}
+									}else {
+										structsubQuestions.remove(k);
+										k--;
+									}
+								}
+							}else {
+								structdetailquestions.remove(j);
+								j--;
+							}
+						}
+						
+					}else if("subjective".equals(filter)) {
+						if (structquestion.getInteger("structType").intValue() != 1
+								&& structquestion.getInteger("structType").intValue() != 2
+									&& structquestion.getInteger("structType").intValue() != 3) {
+							structquestion.put("answer", answerquestion.getJSONArray("answer"));
+						}else {
+							if (structquestion.getInteger("structType").intValue() == 6) {
+								JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
+								JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
+								for (int k = 0; k < structsubQuestions.size(); k++) {
+									JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
+									JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
+									if (structsubquestion.getInteger("structType").intValue() != 1
+											&& structsubquestion.getInteger("structType").intValue() != 2
+												&& structsubquestion.getInteger("structType").intValue() != 3) {
+										structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
+									}else {
+										structsubQuestions.remove(k);
+										k--;
+									}
+								}
+							}else {
+								structdetailquestions.remove(j);
+								j--;
+							}
+						}
+					}else {
+						if (structquestion.getInteger("structType").intValue() != 6) {
+							if(structquestion.getInteger("structType").intValue() == 3) {
+								structquestion.put("answer", answerquestion.getBoolean("answer"));
+							}else {
+								structquestion.put("answer", answerquestion.getJSONArray("answer"));
+							}
+						}else {
+							JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
+							JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
+							for (int k = 0; k < structsubQuestions.size(); k++) {
+								JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
+								JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
+								if (structsubquestion.getInteger("structType").intValue() == 3) {
+									structsubquestion.put("answer", answersubquestion.getBoolean("answer"));
+								}else {
+									structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
+								}
+							}
+						}
+					}
+					
+				}
+			}
+			return structJson;
+		} finally {
+			FileUtil.deleteFolder(dir);
+		}
+	}
+	private String uuid() {
+		return UUID.randomUUID().toString().replaceAll("-", "");
+	}
+	
+	private void checkExam(Long examId) {
+		TEExam exam=examService.getById(examId);
+		if(exam==null) {
+			throw new BusinessException("未找到考试信息");
+		}
+		if(exam.getEnable()==null||exam.getEnable().intValue()==0) {
+			throw new BusinessException("考试批次已禁用");
+		}
+		if(!InvigilateMonitorStatusEnum.FINISHED.equals(exam.getMonitorStatus())) {
+			throw new BusinessException("考试批次监考未结束");
+		}
+		List<TEExamCourse> courses=examCourseService.findByExamId(examId);
+		if(courses==null||courses.size()==0) {
+			throw new BusinessException("考试批次下没有课程");
+		}
+		for(TEExamCourse course:courses) {
+			if(course.getHasAnswer()==null||course.getHasAnswer().intValue()==0) {
+				throw new BusinessException("考试批次下标答未齐全");
+			}
+		}
+	}
+
+
+	@Override
+	public JSONArray examRecordNeedMark(Long examId, String courseCode, Integer idGt,
+			Integer count) {
+		checkExam(examId);
+		List<OpenRecordNeedMarkBean> list=examRecordService.findExamRecordNeedMark(examId,courseCode,idGt,count);
+		if(list==null||list.size()==0) {
+			return null;
+		}
+		List<Long> ids = list.stream().map(dto -> dto.getId()).collect(Collectors.toList());
+		List<OpenRecordAnswerBean> answers=examAnswerService.findByRecordIds(ids);
+		Map<Long,Integer> map=new HashMap<>();
+		for(int i=0;i<list.size();i++) {
+			map.put(list.get(i).getId(), i);
+		}
+		for(OpenRecordAnswerBean anwser:answers) {
+			OpenRecordNeedMarkBean mark=list.get(map.get(anwser.getRecordId()));
+			List<OpenRecordAnswerBean> ans=mark.getAnswers();
+			if(ans==null) {
+				ans=new ArrayList<OpenRecordAnswerBean>();
+				mark.setAnswers(ans);
+			}
+			ans.add(anwser);
+		}
+		JSONArray  ja = JSONArray.parseArray(JSONArray.toJSONString(list));
+		for(int i=0;i<ja.size();i++) {
+			JSONObject job=ja.getJSONObject(i);
+			JSONArray answersJa=job.getJSONArray("answers");
+			if(answersJa!=null) {
+				for(int j=0;j<answersJa.size();j++) {
+					JSONObject answersJob=answersJa.getJSONObject(j);
+					answersJob.remove("recordId");
+					String answerStr=answersJob.getString("answer");
+					if(StringUtils.isNotBlank(answerStr)) {
+						if(answerStr.toLowerCase().startsWith("true")||answerStr.toLowerCase().startsWith("false")) {
+							answersJob.put("answer", Boolean.getBoolean(answerStr.replaceAll("\n","")));
+						}else {
+							answersJob.put("answer", answersJob.getJSONArray("answer"));
+						}
+					}
+				}
+			}
+		}
+		return ja;
+	}
 }

+ 14 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamAnswerServiceImpl.java

@@ -1,9 +1,15 @@
 package com.qmth.themis.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.bean.backend.OpenRecordAnswerBean;
 import com.qmth.themis.business.dao.TOeExamAnswerMapper;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.service.TOeExamAnswerService;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+
 import org.springframework.stereotype.Service;
 
 /**
@@ -16,4 +22,12 @@ import org.springframework.stereotype.Service;
 @Service
 public class TOeExamAnswerServiceImpl extends ServiceImpl<TOeExamAnswerMapper, TOeExamAnswer> implements TOeExamAnswerService {
 
+	@Resource
+	TOeExamAnswerMapper examAnswerMapper;
+	
+	@Override
+	public List<OpenRecordAnswerBean> findByRecordIds(List<Long> ids) {
+		return examAnswerMapper.findByRecordIds(ids);
+	}
+
 }

+ 53 - 16
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -1,13 +1,44 @@
 package com.qmth.themis.business.service.impl;
 
+import java.io.File;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.themis.business.bean.backend.*;
+import com.qmth.themis.business.bean.backend.InvigilateListBean;
+import com.qmth.themis.business.bean.backend.InvigilateListHistoryBean;
+import com.qmth.themis.business.bean.backend.InvigilateListPatrolBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressExcelBean;
+import com.qmth.themis.business.bean.backend.InvigilateListVideoBean;
+import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
+import com.qmth.themis.business.bean.backend.OpenRecordNeedMarkBean;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
-import com.qmth.themis.business.cache.bean.*;
+import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
+import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentPaperStructCacheBean;
+import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -16,25 +47,25 @@ import com.qmth.themis.business.dto.MqDto;
 import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.enums.ExamRecordFieldEnum;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.ExamTypeEnum;
+import com.qmth.themis.business.enums.LivenessTypeEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.enums.ObjectiveScorePolicyEnum;
+import com.qmth.themis.business.enums.VerifyExceptionEnum;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEExamActivityService;
+import com.qmth.themis.business.service.TEExamPaperService;
+import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TOeExamAnswerService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.util.FileUtil;
 import com.qmth.themis.common.util.SimpleBeanUtil;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.io.File;
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.*;
 
 /**
  * @Description: 考试记录 服务实现类
@@ -808,4 +839,10 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     public TOeExamRecord findOneByExamId(Long examId, ExamRecordStatusEnum status) {
         return tOeExamRecordMapper.findOneByExamId(examId, status==null?null:status.name());
     }
+
+	@Override
+	public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examId, String courseCode, Integer idGt,
+			Integer count) {
+		return tOeExamRecordMapper.findExamRecordNeedMark(examId,courseCode,idGt,count);
+	}
 }

+ 6 - 2
themis-business/src/main/java/com/qmth/themis/business/templete/impl/TaskExamPaperImportTemplete.java

@@ -311,12 +311,16 @@ public class TaskExamPaperImportTemplete implements TaskImportTemplete {
 					JSONObject structquestion = structdetailquestions.getJSONObject(j);
 					JSONObject body = structquestion.getJSONObject("body");
 					disposeQuestionBodyUrl(rootDir, body, paper.getId(), attachmentDir);
+					JSONArray options = structquestion.getJSONArray("options");
+					disposeQuestionOptionsUrl(rootDir, options, paper.getId(), attachmentDir);
 					if (structquestion.getInteger("structType").intValue() == 6) {
 						JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
 						for (int k = 0; k < structsubQuestions.size(); k++) {
 							JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
-								JSONArray options = structsubquestion.getJSONArray("options");
-								disposeQuestionOptionsUrl(rootDir, options, paper.getId(), attachmentDir);
+								JSONObject subbody = structsubquestion.getJSONObject("body");
+								disposeQuestionBodyUrl(rootDir, subbody, paper.getId(), attachmentDir);
+								JSONArray suboptions = structsubquestion.getJSONArray("options");
+								disposeQuestionOptionsUrl(rootDir, suboptions, paper.getId(), attachmentDir);
 						}
 					}
 				}

+ 6 - 0
themis-business/src/main/resources/mapper/TEExamCourseMapper.xml

@@ -99,4 +99,10 @@
 		</if>
 	</select>
 	
+	<select id="findByExamId"
+		resultType="com.qmth.themis.business.entity.TEExamCourse">
+		select * from t_e_exam_course t
+		where t.exam_id=#{examId}
+	</select>
+	
 </mapper>

+ 20 - 1
themis-business/src/main/resources/mapper/TOeExamAnswerMapper.xml

@@ -1,5 +1,24 @@
 <?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.TOeExamAnswerMapper">
+<mapper
+	namespace="com.qmth.themis.business.dao.TOeExamAnswerMapper">
 
+	<select id="findByRecordIds"
+		resultType="com.qmth.themis.business.bean.backend.OpenRecordAnswerBean">
+		SELECT
+		t.exam_record_id recordId,
+		t.main_number mainNumber,
+		t.sub_number
+		subNumber,
+		t.sub_index subIndex,
+		t.answer
+		FROM
+		t_oe_exam_answer t
+		WHERE t.exam_record_id in
+		<foreach collection="ids" item="rid"
+			index="index" open="(" close=")" separator=",">
+			#{rid}
+		</foreach>
+		order by t.id
+	</select>
 </mapper>

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

@@ -856,4 +856,26 @@
 	<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 != ''">
+			and f.course_code=#{courseCode}
+			</if>
+			order by t.id
+			limit #{count}
+	</select>
 </mapper>