ソースを参照

merge from release_v4.0.1

deason 4 年 前
コミット
73fca83356
19 ファイル変更763 行追加227 行削除
  1. 11 4
      .gitignore
  2. 22 0
      examcloud-exchange-base/src/main/java/cn/com/qmth/examcloud/exchange/base/enums/QuestionCategory.java
  3. 28 0
      examcloud-exchange-base/src/main/java/cn/com/qmth/examcloud/exchange/base/processor/HttpMethodProcessorImpl.java
  4. 199 17
      examcloud-exchange-outer-api-provider/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/provider/ExamQuestionOuterServiceProvider.java
  5. 11 8
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/ExamQuestionOuterService.java
  6. 63 0
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectivePaperBean.java
  7. 105 0
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectivePaperQuestionBean.java
  8. 1 34
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectiveQuestionRecordBean.java
  9. 37 0
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/request/OuterGetSubjectivePaperReq.java
  10. 26 0
      examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/response/OuterGetSubjectivePaperResp.java
  11. 3 2
      examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/OutletPaperStructService.java
  12. 21 1
      examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/bean/OuterQuestionBean.java
  13. 17 0
      examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/FaceServiceImpl.java
  14. 97 23
      examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/OutletPaperStructServiceImpl.java
  15. 38 40
      examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/OutletScoreServiceImpl.java
  16. 1 1
      examcloud-exchange-starter/src/main/resources/application.properties
  17. 83 59
      examcloud-exchange-starter/src/main/resources/log4j2.xml
  18. 0 19
      jenkins-dev.sh
  19. 0 19
      jenkins-test.sh

+ 11 - 4
.gitignore

@@ -1,12 +1,19 @@
+*.class
+
+# Proguard folder generated by ide
 .project
 .classpath
 .settings
 target/
 .idea/
 *.iml
-*test/
-# Package Files #
-*.jar
-logs/
 
+# Log Files
+*.log
+*.class
 
+
+# Package Files #
+*.jar
+*.war
+*.ear

+ 22 - 0
examcloud-exchange-base/src/main/java/cn/com/qmth/examcloud/exchange/base/enums/QuestionCategory.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.examcloud.exchange.base.enums;
+
+/**
+ * @Description 题目分类
+ * @Author lideyin
+ * @Date 2020/6/23 18:04
+ * @Version 1.0
+ */
+public enum QuestionCategory {
+    /**
+     * 全部
+     */
+    ALL,
+    /**
+     * 主观题
+     */
+    SUBJECTIVE,
+    /**
+     * 客观题
+     */
+    OBJECTIVE
+}

+ 28 - 0
examcloud-exchange-base/src/main/java/cn/com/qmth/examcloud/exchange/base/processor/HttpMethodProcessorImpl.java

@@ -0,0 +1,28 @@
+package cn.com.qmth.examcloud.exchange.base.processor;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Component;
+
+import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
+import cn.com.qmth.examcloud.web.support.HttpMethodProcessor;
+
+@Component
+public class HttpMethodProcessorImpl implements HttpMethodProcessor {
+
+	@Override
+	public void beforeMethod(HttpServletRequest request, Object[] args) {
+
+	}
+
+	@Override
+	public void onSuccess(HttpServletRequest request, Object[] args, Object ret) {
+		ReportsUtil.sendReport(false);
+	}
+
+	@Override
+	public void onException(HttpServletRequest request, Object[] args, Throwable e) {
+		ReportsUtil.sendReport(true);
+	}
+
+}

+ 199 - 17
examcloud-exchange-outer-api-provider/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/provider/ExamQuestionOuterServiceProvider.java

@@ -2,21 +2,19 @@ package cn.com.qmth.examcloud.exchange.outer.api.provider;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
+import cn.com.qmth.examcloud.core.basic.api.CourseCloudService;
+import cn.com.qmth.examcloud.core.basic.api.bean.CourseBean;
+import cn.com.qmth.examcloud.core.basic.api.request.GetCourseReq;
 import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.PagedToBeMarkExamRecordBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.PagedToBeMarkSubjectiveAnswerBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.request.GetPagedToBeMarkExamRecordReq;
 import cn.com.qmth.examcloud.core.oe.admin.api.response.GetPagedToBeMarkExamRecordResp;
+import cn.com.qmth.examcloud.exchange.base.enums.QuestionCategory;
 import cn.com.qmth.examcloud.exchange.outer.api.ExamQuestionOuterService;
 import cn.com.qmth.examcloud.exchange.outer.api.bean.*;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetPaperStructReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetQuestionAnswerReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetSubjectivePaperStructReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetSubjectiveQuestionReq;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetPaperStructResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetQuestionAnswerResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetSubjectivePaperStructResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetSubjectiveQuestionResp;
+import cn.com.qmth.examcloud.exchange.outer.api.request.*;
+import cn.com.qmth.examcloud.exchange.outer.api.response.*;
 import cn.com.qmth.examcloud.exchange.outer.service.OutletPaperStructService;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterCourseBean;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterQuestionBean;
@@ -25,11 +23,14 @@ import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
 import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
 import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
 import cn.com.qmth.examcloud.question.commons.core.question.AnswerType;
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionStructure;
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionUnit;
 import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
 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.ExtractConfigPaperCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.QuestionAnswerCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.QuestionCacheBean;
 import cn.com.qmth.examcloud.support.enums.BlockType;
 import cn.com.qmth.examcloud.support.handler.richText.RichTextHandler;
 import cn.com.qmth.examcloud.support.handler.richText.RichTextHandlerFactory;
@@ -52,6 +53,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @Description 考试作答服务
@@ -72,6 +74,9 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
     @Autowired
     private OutletPaperStructService outletPaperStructService;
 
+    @Autowired
+    private CourseCloudService courseCloudService;
+
 
     @Override
     @ApiOperation(value = "获取主观题试卷结构", httpMethod = "POST")
@@ -99,7 +104,8 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
             paperStructList.add(paperStruct);
 
             // 根据考试和课程获取调卷规则下试卷的试题列表
-            List<OuterQuestionBean> questions = outletPaperStructService.getPaperStructQuestions(req.getExamId(), course.getCode());
+            List<OuterQuestionBean> questions = outletPaperStructService.getPaperStructQuestions(
+                    req.getExamId(), course.getCode(), QuestionCategory.SUBJECTIVE);
             if (CollectionUtils.isEmpty(questions)) {
                 // 当前考试和课程对应的调卷规则不存在时,则获取不到试卷试题
                 log.warn(String.format("getPaperStructQuestions is empty, examId = %s, courseCode = %s", req.getExamId(), course.getCode()));
@@ -193,6 +199,88 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
         return resp;
     }
 
+    @ApiOperation(value = "获取主观题试卷信息", httpMethod = "POST")
+    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = OuterGetSubjectivePaperResp.class),
+            @ApiResponse(code = 500, message = "系统异常(异常信息见响应体)", response = StatusResponse.class)})
+    @PostMapping("/getSubjectivePaper")
+    @Override
+    public OuterGetSubjectivePaperResp getSubjectivePaper(@RequestBody OuterGetSubjectivePaperReq req) {
+        Long examId = req.getExamId();
+        if (null == examId) {
+            throw new StatusException("105001", "考试id不允许为空");
+        }
+
+        String subjectCode = req.getSubjectCode();
+        if (StringUtils.isNullOrEmpty(subjectCode)) {
+            throw new StatusException("105002", "科目代码不允许为空");
+        }
+
+        CourseBean course = getCourse(examId, subjectCode);
+        if (null == course) {
+            throw new StatusException("105003", "找不到科目代码对应的科目信息");
+        }
+
+        OuterGetSubjectivePaperResp resp = new OuterGetSubjectivePaperResp();
+
+        //主观题试题信息
+        List<OuterQuestionBean> subjectiveQuestions = outletPaperStructService.getPaperStructQuestions(
+                req.getExamId(), course.getCode(), QuestionCategory.SUBJECTIVE);
+
+        if (null == subjectiveQuestions) {
+            throw new StatusException("105004", "当前科目无主观题");
+        }
+
+        OuterSubjectivePaperBean osb=new OuterSubjectivePaperBean();
+        osb.setExamId(examId);
+        osb.setSubjectCode(subjectCode);
+        osb.setSubjectName(course.getName());
+
+        List<OuterSubjectivePaperQuestionBean> subPaperQuesList=new ArrayList<>();
+        //所有试题信息
+        List<OuterQuestionBean> allQuestions = outletPaperStructService.getPaperStructQuestions(
+                req.getExamId(), course.getCode(), QuestionCategory.SUBJECTIVE);
+        RichTextHandler complexRichTextHandler = RichTextHandlerFactory.getHandler("complex");
+
+        for (OuterQuestionBean subQues : subjectiveQuestions) {
+            OuterSubjectivePaperQuestionBean subPaperQues=new OuterSubjectivePaperQuestionBean();
+            //获取指定小题的题干相关信息
+            QuestionCacheBean cachedQues = CacheHelper.getQuestion(examId, subjectCode, subQues.getPaperType(), subQues.getQuestionId());
+            String strAnswer=getCorrectAnswer(subQues.getSubNumber(), subQues.getQuestionId(), cachedQues, allQuestions);
+            String strParentBody=getParentBody(cachedQues);
+            String strBody=getBody(subQues.getSubNumber(), subQues.getQuestionId(), cachedQues, allQuestions);
+
+            subPaperQues.setAnswer(transferFrom(complexRichTextHandler.handle(strAnswer)));
+            subPaperQues.setParentBody(transferFrom(complexRichTextHandler.handle(strParentBody)));
+            subPaperQues.setBody(transferFrom(complexRichTextHandler.handle(strBody)));
+
+            subPaperQues.setMainNumber(subQues.getMainNumber());
+            subPaperQues.setSubNumber(subQues.getSubNumber());
+            subPaperQues.setQuestionId(subQues.getQuestionId());
+            subPaperQuesList.add(subPaperQues);
+        }
+        osb.setQuestions(subPaperQuesList);
+
+        resp.setSubjectivePaper(osb);
+
+        return resp;
+    }
+
+    /**
+     * 获取课程相关信息
+     *
+     * @param examId
+     * @param subjectCode
+     */
+    private CourseBean getCourse(Long examId, String subjectCode) {
+        ExamSettingsCacheBean examSettings = CacheHelper.getExamSettings(examId);
+        Long rootOrgId = examSettings.getRootOrgId();
+        GetCourseReq courseReq = new GetCourseReq();
+        courseReq.setRootOrgId(rootOrgId);
+        courseReq.setCode(subjectCode);
+        return courseCloudService.getCourse(courseReq).getCourseBean();
+    }
+
+
     @ApiOperation(value = "获取题目答案", httpMethod = "POST")
     @ApiResponses({@ApiResponse(code = 200, message = "成功", response = OuterGetQuestionAnswerResp.class),
             @ApiResponse(code = 500, message = "系统异常(异常信息见响应体)", response = StatusResponse.class)})
@@ -336,7 +424,6 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
     private List<OuterSubjectiveQuestionRecordBean> getSubjectives(Long examId,
                                                                    List<PagedToBeMarkSubjectiveAnswerBean> subjectiveAnswerList) {
         List<OuterSubjectiveQuestionRecordBean> resultList = new ArrayList<>();
-        RichTextHandler complexRichTextHandler = RichTextHandlerFactory.getHandler("complex");
 
         for (PagedToBeMarkSubjectiveAnswerBean pb : subjectiveAnswerList) {
             OuterSubjectiveQuestionRecordBean resultBean = new OuterSubjectiveQuestionRecordBean();
@@ -344,8 +431,6 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
             resultBean.setSubNumber(pb.getOrder());
             resultBean.setQuestionId(pb.getQuestionId());
 
-            resultBean.setAnswer(transferFrom(complexRichTextHandler.handle(pb.getAnswer())));
-
             //格式化学生答案
             String transformedAnswerType = getTransformedAnswerType(pb.getAnswerType(), pb.getQuestionType(), examId);
 
@@ -406,10 +491,7 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
 
             OuterSectionCollectionBean stuAnswerResult = transferFrom(formattedStudentAnswer);
 
-            resultBean.setStudentAnswer(stuAnswerResult);
-
-            resultBean.setBody(transferFrom(complexRichTextHandler.handle(pb.getBody())));
-            resultBean.setParentBody(transferFrom(complexRichTextHandler.handle(pb.getParentBody())));
+            resultBean.setAnswer(stuAnswerResult);
 
             resultList.add(resultBean);
         }
@@ -473,4 +555,104 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
 
         return "text";
     }
+
+    /**
+     * 获取套题的主题干
+     *
+     * @param cachedQues
+     * @return
+     */
+    private String getParentBody(QuestionCacheBean cachedQues) {
+
+        DefaultQuestionStructure questionStructure = cachedQues.getDefaultQuestion().getMasterVersion();
+
+        //如果主题干不为空,则认为是套题
+        return questionStructure.getBody();
+    }
+
+    /**
+     * 获取当前小题的题干
+     *
+     * @param curSubNumber       当前小题号
+     * @param questionId         原小题id
+     * @param cachedQues         带题干的试卷结构
+     * @param subjectiveQuesList 主观题集合
+     * @return
+     */
+    private String getBody(Integer curSubNumber, String questionId,
+                           QuestionCacheBean cachedQues, List<OuterQuestionBean> subjectiveQuesList) {
+        DefaultQuestionStructure questionStructure = cachedQues.getDefaultQuestion().getMasterVersion();
+
+        //body为空,则说明当前小题为非套题(即questionUnitList集合大小为1),可直接返回小题题干
+        if (StringUtils.isNullOrEmpty(questionStructure.getBody())) {
+            return questionStructure.getQuestionUnitList().get(0).getBody();
+        }
+
+        //同一questionId的主观题集合(不带题干)
+        List<OuterQuestionBean> noBodySubjectiveQuesList = subjectiveQuesList.stream().
+                filter(p -> p.getQuestionId().equals(questionId)).collect(Collectors.toList());
+
+        //同一questionId的主观题集合(带题干)
+        List<DefaultQuestionUnit> haveBodySubjectiveQuesList = questionStructure.getQuestionUnitList().stream()
+                .filter(p -> QuestionType.FILL_UP == p.getQuestionType() || QuestionType.ESSAY == p.getQuestionType())
+                .collect(Collectors.toList());
+
+        for (int i = 0; i < noBodySubjectiveQuesList.size(); i++) {
+            //如果小题号相同,则根据相同索引从带题干的集合中取出对应的小题题干
+            if (noBodySubjectiveQuesList.get(i).getSubNumber().intValue() == curSubNumber.intValue()) {
+                return haveBodySubjectiveQuesList.get(i).getBody();
+            }
+        }
+
+        return "";
+    }
+
+    /**
+     * 获取当前小题的标准答案
+     *
+     * @param curSubNumber       当前小题号
+     * @param questionId         原小题id
+     * @param cachedQues         带题干的试卷结构
+     * @param allEqList 所有作答集合
+     * @return
+     */
+    private String getCorrectAnswer(Integer curSubNumber, String questionId,
+                                    QuestionCacheBean cachedQues, List<OuterQuestionBean> allEqList) {
+        QuestionAnswerCacheBean questionAnswerCache = CacheHelper.getQuestionAnswer(questionId);
+        List<String> rightAnswerList = questionAnswerCache.getRightAnswers();
+        DefaultQuestionStructure questionStructure = cachedQues.getDefaultQuestion().getMasterVersion();
+
+
+        //body为空,则说明当前小题为非套题(rightAnswerList集合大小为1),可直接返回
+        if (StringUtils.isNullOrEmpty(questionStructure.getBody())) {
+            return rightAnswerList.get(0);
+        }
+
+
+        //同一questionId的主观题集合(不带题干,有小题号)
+        List<OuterQuestionBean> noBodySubjectiveQuesList = allEqList.stream().
+                filter(p -> p.getQuestionId().equals(questionId)).collect(Collectors.toList());
+
+        for (int i = 0; i < noBodySubjectiveQuesList.size(); i++) {
+            //如果小题号相同,则根据相同索引从带题干的集合中取出对应的小题题干
+            if (noBodySubjectiveQuesList.get(i).getSubNumber().intValue() == curSubNumber.intValue()) {
+                return rightAnswerList.get(i);
+            }
+        }
+
+        return "";
+    }
+
+    public static void main(String[] args) {
+        String str1 ="111";
+        String str2 ="222";
+        String str3 ="111111";
+        String str4 ="222222";
+        String str5 ="222222dfsdffsd234234234234rwefsfsdfsdfaasfdsadfasdfsad";
+        String str6 ="222222dfsdffsd234234234239rwefsfsdfsdfaasfdsadfasdfsad";
+        System.out.println("1001110101011100111001101110101110100100001000000111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".length());
+        System.out.println("9D5CE6EBA420717BE7E7D308B11F8207681B066C951D68F3994D19828F342474".length());
+        System.out.println(String.format("str1=%s,str2=%s,str3=%s,str4=%s,str5=%s,str6=%s",
+                str1.hashCode(),str2.hashCode(),str3.hashCode(),str4.hashCode(),str5.hashCode(),str6.hashCode()));
+    }
 }

+ 11 - 8
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/ExamQuestionOuterService.java

@@ -1,14 +1,8 @@
 package cn.com.qmth.examcloud.exchange.outer.api;
 
 import cn.com.qmth.examcloud.api.commons.EnterpriseService;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetPaperStructReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetQuestionAnswerReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetSubjectivePaperStructReq;
-import cn.com.qmth.examcloud.exchange.outer.api.request.OuterGetSubjectiveQuestionReq;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetPaperStructResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetQuestionAnswerResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetSubjectivePaperStructResp;
-import cn.com.qmth.examcloud.exchange.outer.api.response.OuterGetSubjectiveQuestionResp;
+import cn.com.qmth.examcloud.exchange.outer.api.request.*;
+import cn.com.qmth.examcloud.exchange.outer.api.response.*;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
@@ -40,6 +34,14 @@ public interface ExamQuestionOuterService extends EnterpriseService {
      */
     OuterGetSubjectiveQuestionResp getSubjectiveQuestion(OuterGetSubjectiveQuestionReq req);
 
+    /**
+     * 获取主观题试卷信息
+     *
+     * @param req
+     * @return
+     */
+    OuterGetSubjectivePaperResp getSubjectivePaper(OuterGetSubjectivePaperReq req);
+
     /**
      * 获取题目答案
      *
@@ -50,6 +52,7 @@ public interface ExamQuestionOuterService extends EnterpriseService {
 
     /**
      * 获取试卷结构(题库中的原始试卷结构)
+     *
      * @param req
      * @return
      */

+ 63 - 0
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectivePaperBean.java

@@ -0,0 +1,63 @@
+package cn.com.qmth.examcloud.exchange.outer.api.bean;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.List;
+
+/**
+ * @Description 主观题试卷信息实体
+ * @Author lideyin
+ * @Date 2020/6/23 15:08
+ * @Version 1.0
+ */
+@ApiModel(value = "OuterSubjectivePaperBean", description = "主观题试卷信息实体")
+public class OuterSubjectivePaperBean implements JsonSerializable{
+
+	private static final long serialVersionUID = -861207406409903426L;
+
+	@ApiModelProperty(value = "考试ID", example = "1", required = true)
+	private Long examId;
+
+	@ApiModelProperty(value = "科目代码", example = "XX", required = true)
+	private String subjectCode;
+
+	@ApiModelProperty(value = "科目名称", example = "XX", required = true)
+	private String subjectName;
+
+	@ApiModelProperty(value = "主观题集合", example = "[]", required = true)
+	private List<OuterSubjectivePaperQuestionBean> questions;
+
+	public Long getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+
+	public String getSubjectCode() {
+		return subjectCode;
+	}
+
+	public void setSubjectCode(String subjectCode) {
+		this.subjectCode = subjectCode;
+	}
+
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public List<OuterSubjectivePaperQuestionBean> getQuestions() {
+		return questions;
+	}
+
+	public void setQuestions(List<OuterSubjectivePaperQuestionBean> questions) {
+		this.questions = questions;
+	}
+}

+ 105 - 0
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectivePaperQuestionBean.java

@@ -0,0 +1,105 @@
+package cn.com.qmth.examcloud.exchange.outer.api.bean;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description 主观题实体
+ * @Author lideyin
+ * @Date 2020/3/30 16:05
+ * @Version 1.0
+ */
+@ApiModel(value = "OuterSubjectivePaperQuestionBean", description = "主观题实体")
+public class OuterSubjectivePaperQuestionBean implements JsonSerializable{
+
+	private static final long serialVersionUID = -861207406409903426L;
+
+	@ApiModelProperty(value = "大题号", example = "1", required = true)
+	private Integer mainNumber;
+
+//	@ApiModelProperty(value = "大题名称", example = "XX", required = true)
+//	private String mainTitle;
+
+	@ApiModelProperty(value = "小题号", example = "XX", required = true)
+	private Integer subNumber;
+
+//	@ApiModelProperty(value = "小题分", example = "1", required = true)
+//	private Double totalScore;
+
+	@ApiModelProperty(value = "试题id,String,一个套题共用一个questionId", example = "1", required = true)
+	private String questionId;
+
+	@ApiModelProperty(value = "标准答案", example = "{}", required = false)
+	private OuterSectionCollectionBean answer;
+
+	@ApiModelProperty(value = "题干", example = "{}", required = true)
+	private OuterSectionCollectionBean body;
+
+	@ApiModelProperty(value = "父题干", example = "{}", required = false)
+	private OuterSectionCollectionBean parentBody;
+
+	public Integer getMainNumber() {
+		return mainNumber;
+	}
+
+	public void setMainNumber(Integer mainNumber) {
+		this.mainNumber = mainNumber;
+	}
+
+//	public String getMainTitle() {
+//		return mainTitle;
+//	}
+//
+//	public void setMainTitle(String mainTitle) {
+//		this.mainTitle = mainTitle;
+//	}
+
+	public Integer getSubNumber() {
+		return subNumber;
+	}
+
+	public void setSubNumber(Integer subNumber) {
+		this.subNumber = subNumber;
+	}
+
+//	public Double getTotalScore() {
+//		return totalScore;
+//	}
+//
+//	public void setTotalScore(Double totalScore) {
+//		this.totalScore = totalScore;
+//	}
+
+	public String getQuestionId() {
+		return questionId;
+	}
+
+	public void setQuestionId(String questionId) {
+		this.questionId = questionId;
+	}
+
+	public OuterSectionCollectionBean getAnswer() {
+		return answer;
+	}
+
+	public void setAnswer(OuterSectionCollectionBean answer) {
+		this.answer = answer;
+	}
+
+	public OuterSectionCollectionBean getBody() {
+		return body;
+	}
+
+	public void setBody(OuterSectionCollectionBean body) {
+		this.body = body;
+	}
+
+	public OuterSectionCollectionBean getParentBody() {
+		return parentBody;
+	}
+
+	public void setParentBody(OuterSectionCollectionBean parentBody) {
+		this.parentBody = parentBody;
+	}
+}

+ 1 - 34
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/bean/OuterSubjectiveQuestionRecordBean.java

@@ -23,17 +23,8 @@ public class OuterSubjectiveQuestionRecordBean implements JsonSerializable{
 	@ApiModelProperty(value = "试题id,String,一个套题共用一个questionId", example = "1", required = true)
 	private String questionId;
 
-	@ApiModelProperty(value = "标准答案", example = "{}", required = false)
-	private OuterSectionCollectionBean answer;
-
 	@ApiModelProperty(value = "学生答案", example = "{}", required = false)
-	private OuterSectionCollectionBean studentAnswer;
-
-	@ApiModelProperty(value = "题干", example = "{}", required = true)
-	private OuterSectionCollectionBean body;
-
-	@ApiModelProperty(value = "父题干", example = "{}", required = false)
-	private OuterSectionCollectionBean parentBody;
+	private OuterSectionCollectionBean answer;
 
 	public Integer getMainNumber() {
 		return mainNumber;
@@ -66,28 +57,4 @@ public class OuterSubjectiveQuestionRecordBean implements JsonSerializable{
 	public void setAnswer(OuterSectionCollectionBean answer) {
 		this.answer = answer;
 	}
-
-	public OuterSectionCollectionBean getStudentAnswer() {
-		return studentAnswer;
-	}
-
-	public void setStudentAnswer(OuterSectionCollectionBean studentAnswer) {
-		this.studentAnswer = studentAnswer;
-	}
-
-	public OuterSectionCollectionBean getBody() {
-		return body;
-	}
-
-	public void setBody(OuterSectionCollectionBean body) {
-		this.body = body;
-	}
-
-	public OuterSectionCollectionBean getParentBody() {
-		return parentBody;
-	}
-
-	public void setParentBody(OuterSectionCollectionBean parentBody) {
-		this.parentBody = parentBody;
-	}
 }

+ 37 - 0
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/request/OuterGetSubjectivePaperReq.java

@@ -0,0 +1,37 @@
+package cn.com.qmth.examcloud.exchange.outer.api.request;
+
+import cn.com.qmth.examcloud.api.commons.exchange.EnterpriseRequest;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description 获取主观题试卷请求类
+ * @Author lideyin
+ * @Date 2020/6/23 15:25
+ * @Version 1.0
+ */
+public class OuterGetSubjectivePaperReq extends EnterpriseRequest {
+
+	private static final long serialVersionUID = 8892205616387684966L;
+
+	@ApiModelProperty(value = "考试ID", example = "128", required = true)
+	private Long examId;
+
+	@ApiModelProperty(value = "科目代码", example = "128", required = true)
+	private String subjectCode;
+
+	public Long getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+
+	public String getSubjectCode() {
+		return subjectCode;
+	}
+
+	public void setSubjectCode(String subjectCode) {
+		this.subjectCode = subjectCode;
+	}
+}

+ 26 - 0
examcloud-exchange-outer-api/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/response/OuterGetSubjectivePaperResp.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.examcloud.exchange.outer.api.response;
+
+import cn.com.qmth.examcloud.api.commons.exchange.EnterpriseResponse;
+import cn.com.qmth.examcloud.exchange.outer.api.bean.OuterSubjectivePaperBean;
+
+import java.util.List;
+
+/**
+ * @Description 获取主观题试卷信息响应类
+ * @Author lideyin
+ * @Date 2020/6/23 15:07
+ * @Version 1.0
+ */
+public class OuterGetSubjectivePaperResp extends EnterpriseResponse {
+    private static final long serialVersionUID = -3599160726204259551L;
+
+    private OuterSubjectivePaperBean subjectivePaper;
+
+    public OuterSubjectivePaperBean getSubjectivePaper() {
+        return subjectivePaper;
+    }
+
+    public void setSubjectivePaper(OuterSubjectivePaperBean subjectivePaper) {
+        this.subjectivePaper = subjectivePaper;
+    }
+}

+ 3 - 2
examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/OutletPaperStructService.java

@@ -7,6 +7,7 @@
 
 package cn.com.qmth.examcloud.exchange.outer.service;
 
+import cn.com.qmth.examcloud.exchange.base.enums.QuestionCategory;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterCourseBean;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterQuestionBean;
 
@@ -21,7 +22,7 @@ public interface OutletPaperStructService {
      * @param courseCode 课程代码
      * @return 列表
      */
-    List<OuterQuestionBean> getPaperStructQuestions(Long examId, String courseCode);
+    List<OuterQuestionBean> getPaperStructQuestions(Long examId, String courseCode, QuestionCategory questionCategory);
 
     /**
      * 获取考试相关联的课程列表
@@ -31,4 +32,4 @@ public interface OutletPaperStructService {
      */
     List<OuterCourseBean> getExamCourses(Long examId);
 
-}
+}

+ 21 - 1
examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/bean/OuterQuestionBean.java

@@ -17,6 +17,10 @@ public class OuterQuestionBean implements JsonSerializable {
 
     private Double totalScore; //小题分
 
+    private String questionId;//题目id
+
+    private String paperType;//卷型
+
     public Integer getMainNumber() {
         return mainNumber;
     }
@@ -48,4 +52,20 @@ public class OuterQuestionBean implements JsonSerializable {
     public void setTotalScore(Double totalScore) {
         this.totalScore = totalScore;
     }
-}
+
+    public String getQuestionId() {
+        return questionId;
+    }
+
+    public void setQuestionId(String questionId) {
+        this.questionId = questionId;
+    }
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+}

+ 17 - 0
examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/FaceServiceImpl.java

@@ -23,6 +23,8 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Maps;
 
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.api.commons.security.bean.UserType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
@@ -38,9 +40,14 @@ import cn.com.qmth.examcloud.core.basic.api.request.SaveStudentFaceReq;
 import cn.com.qmth.examcloud.core.basic.api.response.GetStudentResp;
 import cn.com.qmth.examcloud.core.basic.api.response.GetUsableFacesetListResp;
 import cn.com.qmth.examcloud.exchange.outer.service.FaceService;
+import cn.com.qmth.examcloud.reports.commons.bean.OperateReport;
+import cn.com.qmth.examcloud.reports.commons.enums.OperateContent;
+import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
 import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
 import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
 import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
+import cn.com.qmth.examcloud.web.support.ServletUtil;
 import cn.com.qmth.examcloud.web.upyun.UpyunService;
 
 /**
@@ -115,6 +122,16 @@ public class FaceServiceImpl implements FaceService {
 		request.setPhotoTreatyPath(pi.getRelativePath());
 
 		faceCloudService.saveStudentFace(request);
+		
+		//操作日志
+		User accessUser = (User) ServletUtil.getRequest()
+                .getAttribute(HttpServletRequestAttribute.$_ACCESS_USER.name());
+		Long operateUserId=null;
+        if (null != accessUser) {
+        	operateUserId=accessUser.getUserId();
+        }
+        ReportsUtil.report(new OperateReport(rootOrgId, operateUserId,student.getId(), null, UserType.COMMON,
+        		OperateContent.STUDENT_PHOTO_IMPORT.getDesc()));
 
 	}
 

+ 97 - 23
examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/OutletPaperStructServiceImpl.java

@@ -7,10 +7,12 @@
 
 package cn.com.qmth.examcloud.exchange.outer.service.impl;
 
+import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.oe.admin.api.ExamCourseCloudService;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.ExamCourseBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.request.GetExamCourseReq;
 import cn.com.qmth.examcloud.core.oe.admin.api.response.GetExamCourseResp;
+import cn.com.qmth.examcloud.exchange.base.enums.QuestionCategory;
 import cn.com.qmth.examcloud.exchange.outer.service.OutletPaperStructService;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterCourseBean;
 import cn.com.qmth.examcloud.exchange.outer.service.bean.OuterQuestionBean;
@@ -42,36 +44,46 @@ public class OutletPaperStructServiceImpl implements OutletPaperStructService {
     /**
      * 根据考试和课程获取调卷规则下试卷的试题列表
      *
-     * @param examId     考试ID
-     * @param courseCode 课程代码
+     * @param examId           考试ID
+     * @param courseCode       课程代码
+     * @param questionCategory 题目分类
      * @return
      */
     @Override
-    public List<OuterQuestionBean> getPaperStructQuestions(Long examId, String courseCode) {
-        try {
-            // 获取题库调卷规则
-            ExtractConfigCacheBean extractConfig = CacheHelper.getExtractConfig(examId, courseCode);
-            if (extractConfig == null || CollectionUtils.isEmpty(extractConfig.getDetails())) {
-                // 调卷规则不存在
-                return new ArrayList<>();
-            }
+    public List<OuterQuestionBean> getPaperStructQuestions(Long examId, String courseCode, QuestionCategory questionCategory) {
+        // 获取题库调卷规则
+        ExtractConfigCacheBean extractConfig = CacheHelper.getExtractConfig(examId, courseCode);
+        if (extractConfig == null || CollectionUtils.isEmpty(extractConfig.getDetails())) {
+            // 调卷规则不存在
+            return new ArrayList<>();
+        }
 
-            // 默认选取调卷规则中的任意一份试卷
-            ExtractConfigDetailCacheBean examPaper = extractConfig.getDetails().get(0);
-            log.info(examPaper.getPaperId() + " - " + examPaper.getGroupCode());
+        //需求调整20200904:考试下某课程存在多套试卷时,直接给出错误提示,101444这个错误码有外部使用,不要随便修改
+        if (extractConfig.getDetails().size() > 1) {
+            throw new StatusException("101444", String.format("当前考试课程代码为:%s的试卷规则中存在多套试卷",courseCode));
+        }
 
-            // 获取当前的试卷结构
-            ExtractConfigPaperCacheBean extractConfigPaper = CacheHelper.getExtractConfigPaper(examId, courseCode, examPaper.getGroupCode(), examPaper.getPaperId());
-            List<DefaultQuestionGroup> questionGroupList = extractConfigPaper.getDefaultPaper().getQuestionGroupList();
+        // 默认选取调卷规则中的任意一份试卷
+        ExtractConfigDetailCacheBean examPaper = extractConfig.getDetails().get(0);
+        log.info(examPaper.getPaperId() + " - " + examPaper.getGroupCode());
 
-            return this.parseSubjectiveQuestions(questionGroupList);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-            return new ArrayList<>();
+        // 获取当前的试卷结构
+        ExtractConfigPaperCacheBean extractConfigPaper = CacheHelper.getExtractConfigPaper(examId, courseCode, examPaper.getGroupCode(), examPaper.getPaperId());
+        List<DefaultQuestionGroup> questionGroupList = extractConfigPaper.getDefaultPaper().getQuestionGroupList();
+
+        if (QuestionCategory.SUBJECTIVE.equals(questionCategory)) {
+            return this.parseSubjectiveQuestions(questionGroupList, examPaper.getGroupCode());
         }
+
+        if (QuestionCategory.OBJECTIVE.equals(questionCategory)) {
+            return this.parseObjectiveQuestions(questionGroupList, examPaper.getGroupCode());
+        }
+
+        //默认返回全部
+        return this.parseQuestions(questionGroupList, examPaper.getGroupCode());
     }
 
-    private List<OuterQuestionBean> parseSubjectiveQuestions(List<DefaultQuestionGroup> questionGroupList) {
+    private List<OuterQuestionBean> parseSubjectiveQuestions(List<DefaultQuestionGroup> questionGroupList, String paperType) {
         log.info("parseSubjectiveQuestions start...");
 
         List<OuterQuestionBean> subjectiveQuestions = new ArrayList<>();
@@ -91,7 +103,8 @@ public class OutletPaperStructServiceImpl implements OutletPaperStructService {
                         subjectiveQuestion.setMainTitle(String.format("第%s大题", mainNumber));
                         subjectiveQuestion.setSubNumber(subNumber);
                         subjectiveQuestion.setTotalScore(questionUnitWrapper.getQuestionScore());
-
+                        subjectiveQuestion.setQuestionId(questionWrapper.getQuestionId());
+                        subjectiveQuestion.setPaperType(paperType);
                         subjectiveQuestions.add(subjectiveQuestion);
                     }
                 }
@@ -101,6 +114,67 @@ public class OutletPaperStructServiceImpl implements OutletPaperStructService {
         return subjectiveQuestions;
     }
 
+    private List<OuterQuestionBean> parseObjectiveQuestions(List<DefaultQuestionGroup> questionGroupList, String paperType) {
+        log.info("parseObjectiveQuestions start...");
+
+        List<OuterQuestionBean> objectiveQuestions = new ArrayList<>();
+
+        int order = 0;
+        for (int i = 0; i < questionGroupList.size(); i++) {
+            DefaultQuestionGroup group = questionGroupList.get(i);
+
+            for (DefaultQuestionStructureWrapper questionWrapper : group.getQuestionWrapperList()) {
+                for (DefaultQuestionUnitWrapper questionUnitWrapper : questionWrapper.getQuestionUnitWrapperList()) {
+                    int mainNumber = i + 1, subNumber = ++order;
+
+                    if (QuestionType.SINGLE_CHOICE == questionUnitWrapper.getQuestionType() ||
+                            QuestionType.MULTIPLE_CHOICE == questionUnitWrapper.getQuestionType() ||
+                            QuestionType.TRUE_OR_FALSE == questionUnitWrapper.getQuestionType()) {
+                        // 只封装客观题信息
+                        OuterQuestionBean objectiveQuestion = new OuterQuestionBean();
+                        objectiveQuestion.setMainNumber(mainNumber);
+                        objectiveQuestion.setMainTitle(String.format("第%s大题", mainNumber));
+                        objectiveQuestion.setSubNumber(subNumber);
+                        objectiveQuestion.setTotalScore(questionUnitWrapper.getQuestionScore());
+                        objectiveQuestion.setQuestionId(questionWrapper.getQuestionId());
+                        objectiveQuestion.setPaperType(paperType);
+                        objectiveQuestions.add(objectiveQuestion);
+                    }
+                }
+            }
+        }
+
+        return objectiveQuestions;
+    }
+
+    private List<OuterQuestionBean> parseQuestions(List<DefaultQuestionGroup> questionGroupList, String paperType) {
+        log.info("parseQuestions start...");
+
+        List<OuterQuestionBean> questions = new ArrayList<>();
+
+        int order = 0;
+        for (int i = 0; i < questionGroupList.size(); i++) {
+            DefaultQuestionGroup group = questionGroupList.get(i);
+
+            for (DefaultQuestionStructureWrapper questionWrapper : group.getQuestionWrapperList()) {
+                for (DefaultQuestionUnitWrapper questionUnitWrapper : questionWrapper.getQuestionUnitWrapperList()) {
+                    int mainNumber = i + 1, subNumber = ++order;
+                    // 只封装客观题信息
+                    OuterQuestionBean question = new OuterQuestionBean();
+                    question.setMainNumber(mainNumber);
+                    question.setMainTitle(String.format("第%s大题", mainNumber));
+                    question.setSubNumber(subNumber);
+                    question.setTotalScore(questionUnitWrapper.getQuestionScore());
+                    question.setQuestionId(questionWrapper.getQuestionId());
+                    question.setPaperType(paperType);
+                    questions.add(question);
+                }
+            }
+        }
+
+        return questions;
+    }
+
     /**
      * 获取考试相关联的课程列表
      *
@@ -130,4 +204,4 @@ public class OutletPaperStructServiceImpl implements OutletPaperStructService {
         }
     }
 
-}
+}

+ 38 - 40
examcloud-exchange-outer-service/src/main/java/cn/com/qmth/examcloud/exchange/outer/service/impl/OutletScoreServiceImpl.java

@@ -54,19 +54,19 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 
 	@Autowired
 	private ExamCloudService examCloudService;
-	
+
 	@Autowired
 	private ExamScoreCloudService examScoreCloudService;
-	
+
 	@Autowired
 	private ExamRecordCloudService examRecordCloudService;
-	
+
 	@Autowired
 	private OeExamStudentCloudService oeExamStudentCloudService;
-	
+
 	@Autowired
 	private ExamScoreDataCloudService examScoreDataCloudService;
-	
+
 	/**
 	 * examStuRemark不再使用  2018-10-15 chenken
 	 */
@@ -75,19 +75,19 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		if(StringUtils.isBlank(examCode) || rootOrgId == null){
 			return null;
 		}
-		
+
 		GetExamReq getExamReq = new GetExamReq();
 		getExamReq.setCode(examCode);
 		getExamReq.setRootOrgId(rootOrgId);
 		GetExamResp getExamResp = examCloudService.getExam(getExamReq);
 		Long examId = getExamResp.getId();
-		
+
 		FindExamStudentInfoReq req = new FindExamStudentInfoReq();
 		req.setFindStudentType(FindStudentType.BY_EXAMID);
 		FindStudentBean findStudentBean = new FindStudentBean();
 		findStudentBean.setExamId(examId);
 		req.setFindStudentBean(findStudentBean);
-		
+
 		FindExamStudentInfoResp findExamStudentInfoResp = oeExamStudentCloudService.findExamStudentInfoBy(req);
 		List<OeExamStudentBean> examStudentBeans = findExamStudentInfoResp.getExamStudents();
 		//List<ExamStudent> examStudents = outletScoreDao.findExamStudents(examId);
@@ -99,20 +99,20 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		if(identityNumbers==null||identityNumbers.size()==0||rootOrgId == null){
 			return null;
 		}
-		
+
 		FindExamStudentInfoReq req = new FindExamStudentInfoReq();
 		req.setFindStudentType(FindStudentType.BY_IDENTITYNUMBERS_AND_ROOTORGID);
 		FindStudentBean findStudentBean = new FindStudentBean();
 		findStudentBean.setRootOrgId(rootOrgId);
 		findStudentBean.setIdentityNumbers(identityNumbers);
 		req.setFindStudentBean(findStudentBean);
-		
+
 		FindExamStudentInfoResp findExamStudentInfoResp = oeExamStudentCloudService.findExamStudentInfoBy(req);
 		List<OeExamStudentBean> examStudentBeans = findExamStudentInfoResp.getExamStudents();
 		//List<ExamStudent> examStudents = outletScoreDao.findExamStudents(identityNumbers,examOrgId);
 		return getExamStudentsScore(examStudentBeans);
 	}
-	
+
 	@Override
 	public List<OutletScore> queryExamScoreBy(Long rootOrgId, String examCode, String courseCode, List<String> studentCodes) throws Exception {
 		GetExamReq getExamReq = new GetExamReq();
@@ -120,14 +120,14 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		getExamReq.setRootOrgId(rootOrgId);
 		GetExamResp getExamResp = examCloudService.getExam(getExamReq);
 		Long examId = getExamResp.getId();
-		
+
 		FindExamStudentInfoReq req = new FindExamStudentInfoReq();
 		req.setFindStudentType(FindStudentType.BY_EXAMID_AND_STUDENTCODES);
 		FindStudentBean findStudentBean = new FindStudentBean();
 		findStudentBean.setExamId(examId);
 		findStudentBean.setStudentCodes(studentCodes);
 		req.setFindStudentBean(findStudentBean);
-		
+
 		FindExamStudentInfoResp findExamStudentInfoResp = oeExamStudentCloudService.findExamStudentInfoBy(req);
 		List<OeExamStudentBean> examStudentBeans = findExamStudentInfoResp.getExamStudents();
 		examStudentBeans = examStudentBeans.stream().filter(o->{
@@ -136,27 +136,27 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		//List<ExamStudent> examStudents = outletScoreDao.findExamStudents(examId,courseCode,studentCodes);
 		return getExamStudentsScore(examStudentBeans);
 	}
-	
+
 	private List<OutletScore> getExamStudentsScore(List<OeExamStudentBean> examStudents) throws Exception{
 		if(examStudents == null){
 			return null;
 		}
 		List<OutletScore> outletScoreList = new ArrayList<OutletScore>();
-		
+
 		for(OeExamStudentBean examStudent:examStudents){
 			OutletScore outletScore = new OutletScore(examStudent);
 			outletScore = findExamData(outletScore,examStudent);
-			
+
 			GetExamReq getExamReq = new GetExamReq();
 			getExamReq.setId(outletScore.getExamId());
 			GetExamResp getExamResp = examCloudService.getExam(getExamReq);
 			outletScore.setExamName(getExamResp.getExamBean().getName());
-			
+
 			outletScoreList.add(outletScore);
 		}
 		return outletScoreList;
 	}
-	
+
 	private OutletScore findExamData(OutletScore outletScore,OeExamStudentBean examStudent) throws Exception{
 		QueryExamRecordForSelectScoreReq req = new QueryExamRecordForSelectScoreReq();
 		req.setExamStudentId(examStudent.getExamStudentId());
@@ -180,7 +180,7 @@ public class OutletScoreServiceImpl implements OutletScoreService{
         setFinalExamScoreAndEndTime(isFinished,outletScore,examRecordList,markingType);
         return outletScore;
     }
-	
+
 	/**
 	 * 1.设置最终成绩
 	 * 2.设置考试结束时间
@@ -200,7 +200,7 @@ public class OutletScoreServiceImpl implements OutletScoreService{
     		req.setExamScoreId(examScore.getId());
     		QueryExamRecordForSelectScoreResp resp = examRecordCloudService.queryExamRecordForSelectScoreByScoreId(req);
     		List<ExamRecordForSelectScore> examRecordForSelectScoreList = resp.getExamRecordForSelectScoreList();
-            
+
     		ExamRecordForSelectScore examRecord = examRecordForSelectScoreList.get(0);
             if(examRecord != null){
             	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -215,20 +215,18 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 
 	/**
 	 * 查询并计算最终成绩
-	 * @param isFinished
-	 * @param examRecordList
 	 * @param markingType
 	 */
 	private ExamScoreBean finalExamScore(List<ExamRecordForSelectScore> examRecordAllList,String markingType) {
     	//第一次过滤考试记录:正常结束或者被系统处理的
     	List<ExamRecordForSelectScore> firstFilterExamRecordList = examRecordAllList.stream().filter(examRecord->{
-    		return  examRecord.getStatus().equals(ExamRecordStatus.EXAM_END.name())|| 
+    		return  examRecord.getStatus().equals(ExamRecordStatus.EXAM_END.name())||
     				examRecord.getStatus().equals(ExamRecordStatus.EXAM_OVERDUE.name());
     	}).collect(Collectors.toList());
-    	
+
         if (firstFilterExamRecordList != null && firstFilterExamRecordList.size()>0) {
         	/**
-        	 * 第二次过滤考试记录:过滤出有效的考试记录 
+        	 * 第二次过滤考试记录:过滤出有效的考试记录
         	 * 1.没有违纪的
         	 * 2.没有警告的或有警告已审核通过的
         	 */
@@ -236,7 +234,7 @@ public class OutletScoreServiceImpl implements OutletScoreService{
                 return !examRecord.getIsIllegality() &&
                 		(!examRecord.getIsWarn() || (examRecord.getIsWarn() && examRecord.getIsAudit()));
             });
-            
+
             List<ExamRecordForSelectScore> secondFilterExamRecords = secondFilterExamRecordStream.collect(Collectors.toList());
             if(secondFilterExamRecords == null|| secondFilterExamRecords.size() == 0){
             	return null;
@@ -246,13 +244,13 @@ public class OutletScoreServiceImpl implements OutletScoreService{
             for(int i = 0;i<secondFilterExamRecords.size();i++){
             	examRecordIds.add(secondFilterExamRecords.get(i).getExamRecordDataId());
             }
-            
+
             QueryExamScoreReq queryExamScoreReq = new QueryExamScoreReq();
             queryExamScoreReq.setExamRecordDataIds(examRecordIds);
             QueryExamScoreResp resp = examScoreCloudService.queryExamScore(queryExamScoreReq);
-            
+
             List<ExamScoreBean> effectiveExamScoreList = resp.getExamScoreBeans();
-            
+
             //全部评阅规则或客观分最高规则:取总分最高
             if(markingType.equals(MarkingType.ALL.name())||markingType.equals(MarkingType.OBJECT_SCORE_MAX.name())){
 				List<ExamScoreBean> examScores = effectiveExamScoreList
@@ -310,18 +308,18 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		getExamReq.setRootOrgId(rootOrgId);
 		GetExamResp getExamResp = examCloudService.getExam(getExamReq);
 		Long examId = getExamResp.getId();
-		
+
 		FindExamStudentInfoReq req = new FindExamStudentInfoReq();
 		req.setFindStudentType(FindStudentType.BY_EXAMID_AND_IDENTITYNUMBERS);
 		FindStudentBean findStudentBean = new FindStudentBean();
 		findStudentBean.setExamId(examId);
 		findStudentBean.setIdentityNumbers(identityNumbers);
 		req.setFindStudentBean(findStudentBean);
-		
+
 		FindExamStudentInfoResp findExamStudentInfoResp = oeExamStudentCloudService.findExamStudentInfoBy(req);
 		List<OeExamStudentBean> examStudentBeans = findExamStudentInfoResp.getExamStudents();
-		
-		
+
+
 		//List<ExamStudent> examStudents = outletScoreDao.findExamStudents(examId,identityNumbers);
 		return getExamStudentsScore(examStudentBeans);
 	}
@@ -331,13 +329,13 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		if(rootOrgId == null || examCode == null || studentCode == null || courseCode == null){
 			return null;
 		}
-		
+
 		GetExamReq getExamReq = new GetExamReq();
 		getExamReq.setCode(examCode);
 		getExamReq.setRootOrgId(rootOrgId);
 		GetExamResp getExamResp = examCloudService.getExam(getExamReq);
 		Long examId = getExamResp.getId();
-		
+
 		FindExamScoreDataReq findExamScoreDataReq = new FindExamScoreDataReq();
 		findExamScoreDataReq.setExamId(examId);
 		findExamScoreDataReq.setStudentCode(studentCode);
@@ -349,22 +347,22 @@ public class OutletScoreServiceImpl implements OutletScoreService{
 		examScoreDataList = examScoreDataList.stream().filter(o->{
 			return o.getCourseCode().indexOf(courseCode)>-1;
 		}).collect(Collectors.toList());
-		
-		List<OutletScore> outletScoreList = new ArrayList<OutletScore>();		
+
+		List<OutletScore> outletScoreList = new ArrayList<OutletScore>();
 		for(ExamScoreDataBean examScoreData:examScoreDataList){
 			OutletScore outletScore = new OutletScore();
-			
+
 			outletScore.setExamName(examCode);
 			outletScore.setCourseCode(courseCode);
 			outletScore.setCourseName(examScoreData.getCourseName());
-			
+
 			outletScore.setStudentCode(examScoreData.getStudentCode());
 			outletScore.setStudentName(examScoreData.getStudentName());
 			outletScore.setIdentityNumber(examScoreData.getIdentityNumber());
 			outletScore.setTotalScore(examScoreData.getTotalScore());
 			outletScore.setObjectiveScore(examScoreData.getObjectiveScore());
 			outletScore.setSubjectiveScore(examScoreData.getSubjectiveScore());
-			
+
 			String startTime = DateUtil.format(examScoreData.getStartTime(),DatePatterns.CHINA_DEFAULT);
 			outletScore.setStartTime(startTime);
 			if(examScoreData.getEndTime()!=null){

+ 1 - 1
examcloud-exchange-starter/src/main/resources/application.properties

@@ -1,6 +1,6 @@
 spring.profiles.active=dev
 
 examcloud.startup.startupCode=8007
-examcloud.startup.configCenterHost=127.0.0.1
+examcloud.startup.configCenterHost=192.168.10.39
 examcloud.startup.configCenterPort=9999
 examcloud.startup.appCode=EX

+ 83 - 59
examcloud-exchange-starter/src/main/resources/log4j2.xml

@@ -1,62 +1,86 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Configuration status="WARN" monitorInterval="30">
 
-	<Properties>
-		<Property name="commonLevel" value="${sys:log.commonLevel}" />
-	</Properties>
-
-	<Appenders>
-		<!-- 控制台 日志 -->
-		<Console name="Console" target="SYSTEM_OUT">
-			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}| %level | %X{TRACE_ID} - %X{CALLER} | %m | %l%n" />
-		</Console>
-		<!-- debug 日志 -->
-		<RollingFile name="DEBUG_APPENDER" fileName="./logs/debug/debug.log" filePattern="./logs/debug/debug-%d{yyyy.MM.dd.HH}-%i.log">
-			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}| %level | %X{TRACE_ID} - %X{CALLER} | %m | %l%n" />
-			<Policies>
-				<TimeBasedTriggeringPolicy interval="1" />
-				<SizeBasedTriggeringPolicy size="100 MB" />
-			</Policies>
-			<DefaultRolloverStrategy max="10000">
-				<Delete basePath="./logs/debug" maxDepth="1">
-					<IfFileName glob="debug-*.log">
-						<IfAccumulatedFileSize exceeds="2 GB" />
-					</IfFileName>
-				</Delete>
-			</DefaultRolloverStrategy>
-		</RollingFile>
-		<!-- 接口日志 -->
-		<RollingFile name="INTERFACE_APPENDER" fileName="./logs/interface/interface.log" filePattern="./logs/interface/interface-%d{yyyy.MM.dd.HH}-%i.log">
-			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}| %level | %X{TRACE_ID} - %X{CALLER} | %m%n" />
-			<Policies>
-				<TimeBasedTriggeringPolicy interval="1" />
-				<SizeBasedTriggeringPolicy size="100 MB" />
-			</Policies>
-			<DefaultRolloverStrategy max="10000">
-				<Delete basePath="./logs/interface" maxDepth="1">
-					<IfFileName glob="interface-*.log">
-						<IfAccumulatedFileSize exceeds="10 GB" />
-					</IfFileName>
-				</Delete>
-			</DefaultRolloverStrategy>
-		</RollingFile>
-	</Appenders>
-
-	<Loggers>
-		<Logger name="cn.com.qmth" level="${commonLevel}" additivity="false">
-			<AppenderRef ref="DEBUG_APPENDER" />
-			<AppenderRef ref="Console" />
-		</Logger>
-
-		<Logger name="INTERFACE_LOGGER" level="INFO" additivity="false">
-			<AppenderRef ref="INTERFACE_APPENDER" />
-			<AppenderRef ref="Console" />
-		</Logger>
-
-		<Root level="INFO">
-			<AppenderRef ref="Console" />
-			<AppenderRef ref="DEBUG_APPENDER" />
-		</Root>
-	</Loggers>
-
-</Configuration>
+    <Properties>
+        <Property name="commonLevel" value="${sys:log.commonLevel}"/>
+        <Property name="logPattern">
+            %d{yyyy-MM-dd HH:mm:ss.SSS} | %clr{%level} | %X{TRACE_ID} %X{CALLER} | %clr{%c{1.1}:%L}{cyan} | %m%n
+        </Property>
+    </Properties>
+
+    <Appenders>
+        <!-- 控制台 日志 -->
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
+        </Console>
+
+        <!-- debug 日志 -->
+        <RollingFile name="DEBUG_APPENDER"
+                     fileName="./logs/debug/debug.log"
+                     filePattern="./logs/debug/debug-%d{yyyy.MM.dd.HH}-%i.log">
+            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
+            <Policies>
+                <TimeBasedTriggeringPolicy interval="1" modulate="false"/>
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+            </Policies>
+            <DefaultRolloverStrategy max="1000">
+                <Delete basePath="./logs/debug" maxDepth="1">
+                    <IfFileName glob="debug-*.log">
+                        <IfAccumulatedFileSize exceeds="2 GB"/>
+                    </IfFileName>
+                </Delete>
+            </DefaultRolloverStrategy>
+        </RollingFile>
+
+        <!-- 接口日志 -->
+        <RollingFile name="INTERFACE_APPENDER" fileName="./logs/interface/interface.log"
+                     filePattern="./logs/interface/interface-%d{yyyy.MM.dd.HH}-%i.log">
+            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
+            <Policies>
+                <TimeBasedTriggeringPolicy interval="1" modulate="false"/>
+                <SizeBasedTriggeringPolicy size="100 MB"/>
+            </Policies>
+            <DefaultRolloverStrategy max="1000">
+                <Delete basePath="./logs/interface" maxDepth="1">
+                    <IfFileName glob="interface-*.log">
+                        <IfAccumulatedFileSize exceeds="10 GB"/>
+                    </IfFileName>
+                </Delete>
+            </DefaultRolloverStrategy>
+        </RollingFile>
+    </Appenders>
+
+    <Loggers>
+        <logger name="springfox.documentation" level="ERROR"/>
+        <logger name="org.springframework" level="ERROR"/>
+        <logger name="org.hibernate" level="ERROR"/>
+        <logger name="org.apache" level="ERROR"/>
+        <logger name="org.quartz" level="ERROR"/>
+        <logger name="org.docx4j" level="ERROR"/>
+        <logger name="cn.afterturn" level="ERROR"/>
+        <logger name="com.netflix" level="ERROR"/>
+        <logger name="com.aliyun" level="ERROR"/>
+        <logger name="io.lettuce" level="ERROR"/>
+        <logger name="io.netty" level="ERROR"/>
+
+        <!--<logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
+        <!--<logger name="org.springframework.data.mongodb" level="DEBUG"/>-->
+        <!--<logger name="org.springframework.data.redis" level="DEBUG"/>-->
+
+        <Logger name="cn.com.qmth" level="${commonLevel}" additivity="false">
+            <AppenderRef ref="DEBUG_APPENDER"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+
+        <Logger name="INTERFACE_LOGGER" level="${commonLevel}" additivity="false">
+            <AppenderRef ref="INTERFACE_APPENDER"/>
+            <AppenderRef ref="Console"/>
+        </Logger>
+
+        <Root level="${commonLevel}">
+            <AppenderRef ref="Console"/>
+            <AppenderRef ref="DEBUG_APPENDER"/>
+        </Root>
+    </Loggers>
+
+</Configuration>

+ 0 - 19
jenkins-dev.sh

@@ -1,19 +0,0 @@
-#!/bin/bash
-pwd
-
-rm -rf ~/project/examcloud/examcloud-exchange-distribution.zip
-rm -rf ~/project/examcloud/examcloud-exchange/lib/
-rm -rf ~/project/examcloud/examcloud-exchange/config/
-
-cp examcloud-exchange-starter/target/examcloud-exchange-distribution.zip ~/project/examcloud/
-
-cd  ~/project/examcloud/
-unzip -o examcloud-exchange-distribution.zip
-
-cd examcloud-exchange
-echo "--spring.profiles.active=dev --examcloud.startup.configCenterHost=localhost" > start.args
-echo "-server -Xms512m -Xmx512m  -XX:-UseGCOverheadLimit" > start.vmoptions
-
-bash stop.sh
-BUILD_ID=DONTKILLME
-bash start.sh jenkins

+ 0 - 19
jenkins-test.sh

@@ -1,19 +0,0 @@
-#!/bin/bash
-pwd
-
-rm -rf ~/project/examcloud/examcloud-exchange-distribution.zip
-rm -rf ~/project/examcloud/examcloud-exchange/lib/
-rm -rf ~/project/examcloud/examcloud-exchange/config/
-
-cp examcloud-exchange-starter/target/examcloud-exchange-distribution.zip ~/project/examcloud/
-
-cd  ~/project/examcloud/
-unzip -o examcloud-exchange-distribution.zip
-
-cd examcloud-exchange
-echo "--spring.profiles.active=test --examcloud.startup.configCenterHost=localhost" > start.args
-echo "-server -Xms512m -Xmx512m  -XX:-UseGCOverheadLimit" > start.vmoptions
-
-bash stop.sh
-BUILD_ID=DONTKILLME
-bash start.sh jenkins