|
@@ -1,16 +1,13 @@
|
|
|
package cn.com.qmth.stmms.api.controller.admin;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
+import java.io.*;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
-import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
|
|
|
-import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
|
|
|
-import cn.com.qmth.stmms.common.domain.ApiUser;
|
|
|
-import cn.com.qmth.stmms.common.domain.WebUser;
|
|
|
-import cn.com.qmth.stmms.common.enums.LockType;
|
|
|
-import cn.com.qmth.stmms.common.enums.MarkStatus;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -18,28 +15,49 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.core.task.AsyncTaskExecutor;
|
|
|
+import org.springframework.data.domain.Sort;
|
|
|
import org.springframework.stereotype.Controller;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
-import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
+import com.aliyun.oss.common.utils.BinaryUtil;
|
|
|
import com.qmth.boot.core.collection.PageResult;
|
|
|
import com.qmth.boot.core.exception.StatusException;
|
|
|
-
|
|
|
+import com.qmth.boot.tools.io.ZipReader;
|
|
|
+
|
|
|
+import cn.com.qmth.stmms.admin.dto.ObjectiveQuestionDTO;
|
|
|
+import cn.com.qmth.stmms.admin.dto.QuestionDTO;
|
|
|
+import cn.com.qmth.stmms.admin.dto.SubjectQuestionDTO;
|
|
|
+import cn.com.qmth.stmms.admin.dto.SubjectiveQuestionDTO;
|
|
|
+import cn.com.qmth.stmms.admin.thread.ScoreCalculateThread;
|
|
|
+import cn.com.qmth.stmms.admin.thread.ScoreReportObjectiveThread;
|
|
|
+import cn.com.qmth.stmms.admin.thread.ScoreReportThread;
|
|
|
+import cn.com.qmth.stmms.admin.vo.StructFile;
|
|
|
+import cn.com.qmth.stmms.admin.vo.StructQuestion;
|
|
|
import cn.com.qmth.stmms.api.controller.BaseApiController;
|
|
|
-import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
|
|
|
+import cn.com.qmth.stmms.biz.common.domain.card.AnswerCardSubjectFile;
|
|
|
+import cn.com.qmth.stmms.biz.common.domain.card.AnswerCardSubjectItem;
|
|
|
+import cn.com.qmth.stmms.biz.common.domain.card.CardFile;
|
|
|
+import cn.com.qmth.stmms.biz.exam.model.*;
|
|
|
import cn.com.qmth.stmms.biz.exam.service.*;
|
|
|
+import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
|
|
|
import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
|
|
|
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
|
|
|
import cn.com.qmth.stmms.biz.file.service.FileService;
|
|
|
import cn.com.qmth.stmms.biz.lock.LockService;
|
|
|
import cn.com.qmth.stmms.biz.mark.service.MarkService;
|
|
|
import cn.com.qmth.stmms.biz.report.service.ReportService;
|
|
|
import cn.com.qmth.stmms.biz.utils.PageUtil;
|
|
|
import cn.com.qmth.stmms.common.annotation.Logging;
|
|
|
-import cn.com.qmth.stmms.common.enums.LogType;
|
|
|
+import cn.com.qmth.stmms.common.domain.ApiUser;
|
|
|
+import cn.com.qmth.stmms.common.enums.*;
|
|
|
+import cn.com.qmth.stmms.common.utils.ExportExcel;
|
|
|
+import cn.com.qmth.stmms.common.utils.ImportExcel;
|
|
|
import cn.com.qmth.stmms.common.utils.RequestUtils;
|
|
|
+import net.sf.json.JSONArray;
|
|
|
import net.sf.json.JSONObject;
|
|
|
|
|
|
@Controller("adminSubjectController")
|
|
@@ -149,7 +167,7 @@ public class SubjectController extends BaseApiController {
|
|
|
@Logging(menu = "科目设置修改", type = LogType.UPDATE)
|
|
|
@RequestMapping(value = "/update", method = RequestMethod.POST)
|
|
|
@ResponseBody
|
|
|
- public JSONObject save(RedirectAttributes redirectAttributes, HttpServletRequest request, ExamSubject subject) {
|
|
|
+ public JSONObject save(HttpServletRequest request, ExamSubject subject) {
|
|
|
ExamSubject previous = subjectService.find(getSessionExamId(request), subject.getCode());
|
|
|
if (previous == null) {
|
|
|
throw new StatusException("科目不存在");
|
|
@@ -178,4 +196,559 @@ public class SubjectController extends BaseApiController {
|
|
|
}
|
|
|
return result(true);
|
|
|
}
|
|
|
+
|
|
|
+ @RequestMapping(value = "/getPaperType", method = RequestMethod.POST)
|
|
|
+ @ResponseBody
|
|
|
+ public List<String> query(HttpServletRequest request, @RequestParam String subjectCode) {
|
|
|
+ int examId = getSessionExamId(request);
|
|
|
+ JSONArray array = new JSONArray();
|
|
|
+ List<String> list = this.questionService.getPaperType(examId, subjectCode);
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping(value = "/template", method = RequestMethod.POST)
|
|
|
+ public void importTemplate(HttpServletResponse response, @RequestParam Boolean objective) {
|
|
|
+ try {
|
|
|
+ String fileName = objective ? "客观题导入模板.xlsx" : "主观题导入模板.xlsx";
|
|
|
+ String title = objective ? "客观题数据" : "主观题数据";
|
|
|
+ List<QuestionDTO> list = new LinkedList<QuestionDTO>();
|
|
|
+ list.add(objective ? new ObjectiveQuestionDTO() : new SubjectiveQuestionDTO());
|
|
|
+ new ExportExcel(title, objective ? ObjectiveQuestionDTO.class : SubjectiveQuestionDTO.class, 2)
|
|
|
+ .setDataList(list).write(response, fileName).dispose();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ throw new StatusException("导入模板下载失败!失败信息:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "客观题统分", type = LogType.UPDATE)
|
|
|
+ @RequestMapping(value = "/calculate", method = RequestMethod.POST)
|
|
|
+ public JSONObject calculate(HttpServletRequest request, @RequestParam(required = false) String subjectCode) {
|
|
|
+ ApiUser wu = RequestUtils.getApiUser(request);
|
|
|
+ Exam exam = examService.findById(getSessionExamId(request));
|
|
|
+ if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
|
|
|
+ throw new StatusException("请选择正确的考试");
|
|
|
+ } else {
|
|
|
+ Set<String> subjectSet = new HashSet<String>();
|
|
|
+ // 整个考试加锁
|
|
|
+ boolean examLock = false;
|
|
|
+ if (subjectCode == null) {
|
|
|
+ subjectSet = getCalculateSubjectCodes(exam.getId());
|
|
|
+ examLock = true;
|
|
|
+ } else if (!lockService.isLocked(LockType.SCORE_CALCULATE, exam.getId(), subjectCode)) {
|
|
|
+ subjectSet.add(subjectCode);
|
|
|
+ }
|
|
|
+ if (!subjectSet.isEmpty()) {
|
|
|
+ ScoreCalculateThread thread = new ScoreCalculateThread(exam.getId(), subjectSet, lockService,
|
|
|
+ studentService, questionService, examService, subjectService, fileService, examLock);
|
|
|
+ taskExecutor.submit(thread);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Set<String> getCalculateSubjectCodes(Integer examId) {
|
|
|
+ List<ExamSubject> list = subjectService.list(examId);
|
|
|
+ Set<String> set = new HashSet<>();
|
|
|
+ for (ExamSubject subject : list) {
|
|
|
+ if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
|
|
|
+ set.add(subject.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return set;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "导出客/主观题", type = LogType.EXPORT)
|
|
|
+ @RequestMapping(value = "/export", method = RequestMethod.POST)
|
|
|
+ public void exportFile(HttpServletRequest request, HttpServletResponse response, @RequestParam Boolean objective) {
|
|
|
+ int examId = getSessionExamId(request);
|
|
|
+
|
|
|
+ Map<String, ExamSubject> subjectMap = new HashMap<String, ExamSubject>();
|
|
|
+ List<ExamSubject> subjectList = subjectService.list(examId);
|
|
|
+ for (ExamSubject subject : subjectList) {
|
|
|
+ subjectMap.put(subject.getCode(), subject);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, MarkGroup> groupMap = new HashMap<String, MarkGroup>();
|
|
|
+ List<MarkGroup> groupList = groupService.findByExam(examId);
|
|
|
+ for (MarkGroup group : groupList) {
|
|
|
+ groupMap.put(group.getSubjectCode() + "_" + group.getNumber(), group);
|
|
|
+ }
|
|
|
+ List<QuestionDTO> list = new LinkedList<QuestionDTO>();
|
|
|
+ ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
|
|
|
+ query.setExamId(examId);
|
|
|
+ query.setObjective(objective);
|
|
|
+ query.setSort(new Sort(Sort.Direction.ASC, "subjectCode", "paperType", "mainNumber", "subNumber"));
|
|
|
+ query.setPageNumber(1);
|
|
|
+ query.setPageSize(Integer.MAX_VALUE);
|
|
|
+ query = questionService.findByQuery(query);
|
|
|
+ for (ExamQuestion q : query.getResult()) {
|
|
|
+ list.add(objective ? new ObjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode()))
|
|
|
+ : new SubjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode()),
|
|
|
+ groupMap.get(q.getSubjectCode() + "_" + q.getGroupNumber())));
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ String fileName = objective ? "客观题数据.xlsx" : "主观题数据.xlsx";
|
|
|
+ String title = objective ? "客观题数据" : "主观题数据";
|
|
|
+ new ExportExcel(title, objective ? ObjectiveQuestionDTO.class : SubjectiveQuestionDTO.class, 2)
|
|
|
+ .setDataList(list).write(response, fileName).dispose();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ throw new StatusException("导出数据失败!失败信息:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "导入客/主观题", type = LogType.IMPORT_FILE)
|
|
|
+ @RequestMapping(value = "/import", method = RequestMethod.POST)
|
|
|
+ public JSONObject importFile(HttpServletRequest request, MultipartFile file, @RequestParam Boolean objective) {
|
|
|
+ int examId = getSessionExamId(request);
|
|
|
+
|
|
|
+ List<String> error = new LinkedList<String>();
|
|
|
+ Map<String, SubjectQuestionDTO> map = parseQuestion(file, examId, objective, error);
|
|
|
+ if (error.size() > 0) {
|
|
|
+ return result(StringUtils.join(error, "<br\\>"));
|
|
|
+ }
|
|
|
+ int success = 0;
|
|
|
+ for (SubjectQuestionDTO dto : map.values()) {
|
|
|
+ // 每次导入都需要重新统分
|
|
|
+ examService.updateObjectiveStatus(examId, ObjectiveStatus.WAITING);
|
|
|
+ ExamSubject subject = subjectService.find(examId, dto.getSubjectCode());
|
|
|
+ if (subject != null) {
|
|
|
+ Map<Integer, String> titleMap = new HashMap<>();
|
|
|
+ List<ExamQuestion> current = questionService.findByExamAndSubjectAndObjective(examId, subject.getCode(),
|
|
|
+ objective);
|
|
|
+ for (ExamQuestion question : current) {
|
|
|
+ titleMap.put(question.getMainNumber(), question.getMainTitle());
|
|
|
+ }
|
|
|
+ if (dto.validate(error, titleMap)) {
|
|
|
+ if (objective) {
|
|
|
+ questionService.deleteByExamAndSubjectAndObjective(examId, dto.getSubjectCode(), objective);
|
|
|
+ for (ExamQuestion question : dto.getQuestionList()) {
|
|
|
+ questionService.save(question);
|
|
|
+ }
|
|
|
+ subjectService.updateScore(examId, subject.getCode(), objective, dto.getTotalScore());
|
|
|
+ } else {
|
|
|
+ int questionCount = 0;
|
|
|
+ List<SelectiveGroup> list = selectiveGroupService.findByExamIdAndSubjectCode(examId,
|
|
|
+ subject.getCode());
|
|
|
+ Map<Integer, SelectiveGroup> selectiveMap = new HashMap<Integer, SelectiveGroup>();
|
|
|
+ for (SelectiveGroup selectiveGroup : list) {
|
|
|
+ selectiveMap.put(selectiveGroup.getMainNumber(), selectiveGroup);
|
|
|
+ }
|
|
|
+ for (ExamQuestion question : dto.getQuestionList()) {
|
|
|
+ ExamQuestion old = questionService
|
|
|
+ .findByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(examId,
|
|
|
+ subject.getCode(), objective, question.getMainNumber(),
|
|
|
+ question.getSubNumber());
|
|
|
+ if (old != null) {
|
|
|
+ if (old.getGroupNumber() != null) {
|
|
|
+ error.add("[" + subject.getCode() + "] 大题号" + question.getMainNumber() + " 小题号"
|
|
|
+ + question.getSubNumber() + "已有分组");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (selectiveMap.containsKey(question.getMainNumber())) {
|
|
|
+ error.add("[" + subject.getCode() + "] 大题号" + question.getMainNumber() + " 小题号"
|
|
|
+ + question.getSubNumber() + "已有选做题分组");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ old.setName(question.getName());
|
|
|
+ old.setTotalScore(question.getTotalScore());
|
|
|
+ old.setIntervalScore(question.getIntervalScore());
|
|
|
+ old.setTrackCount(question.getTrackCount());
|
|
|
+ questionService.save(old);
|
|
|
+ } else {
|
|
|
+ question.setGroupNumber(null);
|
|
|
+ questionService.save(question);
|
|
|
+ questionCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (questionCount > 0) {
|
|
|
+ studentService.updateSubjectiveStatusAndScore(examId, subject.getCode(),
|
|
|
+ SubjectiveStatus.UNMARK, 0, null);
|
|
|
+ inspectHistoryService.deleteByExamIdAndSubjectCode(examId, subject.getCode());
|
|
|
+ }
|
|
|
+ subjectService.updateScore(examId, subject.getCode(), objective,
|
|
|
+ questionService.sumTotalScore(examId, subject.getCode(), objective));
|
|
|
+ }
|
|
|
+ success++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ error.add("[" + dto.getSubjectCode() + "] 科目代码不存在;");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ error.add(0, success + "个科目导入成功;");
|
|
|
+ if (success > 0) {
|
|
|
+ subjectService.updateTotalScore(examId);
|
|
|
+ }
|
|
|
+ RequestUtils.setLog(request, success + "个科目导入成功;");
|
|
|
+ return result(StringUtils.join(error, "<br\\>"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, SubjectQuestionDTO> parseQuestion(MultipartFile file, int examId, boolean objective,
|
|
|
+ List<String> error) {
|
|
|
+ Map<String, SubjectQuestionDTO> map = new HashMap<String, SubjectQuestionDTO>();
|
|
|
+ try {
|
|
|
+ ImportExcel excel = new ImportExcel(file, 1, 0);
|
|
|
+ Class<? extends QuestionDTO> clazz = objective ? ObjectiveQuestionDTO.class : SubjectiveQuestionDTO.class;
|
|
|
+ if (!objective && !Arrays.equals(SUBJECTIVE_EXCEL_HEADER, excel.getHeaderName())) {
|
|
|
+ error.add("Excel表头错误");
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ if (objective && !Arrays.equals(OBJECTIVE_EXCEL_HEADER, excel.getHeaderName())) {
|
|
|
+ error.add("Excel表头错误");
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ List<? extends QuestionDTO> list = excel.getDataList(clazz);
|
|
|
+ if (list != null) {
|
|
|
+ for (QuestionDTO dto : list) {
|
|
|
+ String subjectCode = StringUtils.trimToNull(dto.getSubjectCode());
|
|
|
+ if (subjectCode != null) {
|
|
|
+ SubjectQuestionDTO subject = map.get(subjectCode);
|
|
|
+ if (subject == null) {
|
|
|
+ subject = new SubjectQuestionDTO(examId, subjectCode, objective);
|
|
|
+ map.put(subjectCode, subject);
|
|
|
+ }
|
|
|
+ subject.addQuestion(dto.transform());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("parse question excel error", e);
|
|
|
+ error.add("Excel文件解析失败");
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "导入主观题分组", type = LogType.IMPORT_FILE)
|
|
|
+ @RequestMapping(value = "/importGroup", method = RequestMethod.POST)
|
|
|
+ public JSONObject importGroupFile(HttpServletRequest request, MultipartFile file) {
|
|
|
+ int examId = getSessionExamId(request);
|
|
|
+ List<String> error = new LinkedList<String>();
|
|
|
+ Map<String, SubjectQuestionDTO> map = parseQuestion(file, examId, false, error);
|
|
|
+ if (error.size() > 0) {
|
|
|
+ return result(StringUtils.join(error, " "));
|
|
|
+ }
|
|
|
+ int success = 0;
|
|
|
+ for (SubjectQuestionDTO dto : map.values()) {
|
|
|
+ ExamSubject subject = subjectService.find(examId, dto.getSubjectCode());
|
|
|
+ if (subject != null) {
|
|
|
+ // 验证是否存在分组
|
|
|
+ List<MarkGroup> groups = groupService.findByExamAndSubject(examId, subject.getCode());
|
|
|
+ if (groups != null && groups.size() > 0) {
|
|
|
+ error.add("[" + subject.getCode() + "] 已存在分组");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (subject.isSelective()) {
|
|
|
+ error.add("[" + subject.getCode() + "] 已存在选做题分组");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Map<Integer, String> titleMap = new HashMap<>();
|
|
|
+ List<ExamQuestion> current = questionService.findByExamAndSubjectAndObjective(examId, subject.getCode(),
|
|
|
+ false);
|
|
|
+ for (ExamQuestion question : current) {
|
|
|
+ titleMap.put(question.getMainNumber(), question.getMainTitle());
|
|
|
+ }
|
|
|
+ if (dto.validate(error, titleMap) && dto.validateGroupNumber(error)
|
|
|
+ && dto.getQuestionList().size() == current.size()) {
|
|
|
+ int successGroup = 0;
|
|
|
+ for (MarkGroup group : dto.getGroups().values()) {
|
|
|
+ if (group.getImportQuestionList() != null) {
|
|
|
+ boolean validate = true;
|
|
|
+ List<ExamQuestion> questionGroup = new ArrayList<ExamQuestion>();
|
|
|
+ for (ExamQuestion question : group.getImportQuestionList()) {
|
|
|
+ ExamQuestion old = questionService
|
|
|
+ .findByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(examId,
|
|
|
+ subject.getCode(), false, question.getMainNumber(),
|
|
|
+ question.getSubNumber());
|
|
|
+ if (old == null) {
|
|
|
+ error.add("[" + group.getSubjectCode() + "_" + group.getNumber() + "] 分组有小题不存在");
|
|
|
+ validate = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ old.setGroupNumber(group.getNumber());
|
|
|
+ old.setArbitrateThreshold(question.getArbitrateThreshold());
|
|
|
+ questionGroup.add(old);
|
|
|
+ }
|
|
|
+ // 校验通过小题才保存
|
|
|
+ if (validate && !questionGroup.isEmpty()) {
|
|
|
+ questionService.save(questionGroup);
|
|
|
+ }
|
|
|
+ // 有题目的分组才保存
|
|
|
+ if (questionService.countByExamAndSubjectAndObjectiveAndGroupNumber(examId,
|
|
|
+ group.getSubjectCode(), false, group.getNumber()) != 0) {
|
|
|
+ BigDecimal totalScore = BigDecimal.ZERO;
|
|
|
+ for (ExamQuestion q : questionGroup) {
|
|
|
+ totalScore = totalScore.add(BigDecimal.valueOf(q.getTotalScore()));
|
|
|
+ }
|
|
|
+ group.setTotalScore(totalScore.doubleValue());
|
|
|
+ groupService.save(group);
|
|
|
+ studentService.updateSubjectiveStatusAndScore(examId, group.getSubjectCode(),
|
|
|
+ SubjectiveStatus.UNMARK, 0, null);
|
|
|
+ inspectHistoryService.deleteByExamIdAndSubjectCode(examId, subject.getCode());
|
|
|
+ successGroup++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (successGroup > 0) {
|
|
|
+ success++;
|
|
|
+ subjectService.updateTrialCount(examId, subject.getCode(), dto.getTrialCount());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ error.add("[" + dto.getSubjectCode() + "] 科目代码不存在;");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ error.add(0, success + "个科目导入成功;");
|
|
|
+ RequestUtils.setLog(request, success + "个科目导入成功;");
|
|
|
+ return result(StringUtils.join(error, " "));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "科目成绩分析计算", type = LogType.UPDATE)
|
|
|
+ @RequestMapping(value = "/report", method = RequestMethod.POST)
|
|
|
+ public JSONObject report(HttpServletRequest request, @RequestParam(required = false) String subjectCode) {
|
|
|
+ ApiUser wu = RequestUtils.getApiUser(request);
|
|
|
+ Exam exam = examService.findById(getSessionExamId(request));
|
|
|
+ if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
|
|
|
+ throw new StatusException("请选择正确的考试");
|
|
|
+ } else {
|
|
|
+ Set<String> subjectSet = new HashSet<String>();
|
|
|
+ // 整个考试加锁
|
|
|
+ boolean examLock = false;
|
|
|
+ if (subjectCode == null) {
|
|
|
+ examLock = true;
|
|
|
+ List<ExamSubject> list = subjectService.list(exam.getId());
|
|
|
+ for (ExamSubject subject : list) {
|
|
|
+ if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
|
|
|
+ subjectSet.add(subject.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (!lockService.isLocked(LockType.SCORE_CALCULATE, exam.getId(), subjectCode)) {
|
|
|
+ subjectSet.add(subjectCode);
|
|
|
+ }
|
|
|
+ if (!subjectSet.isEmpty()) {
|
|
|
+ Map<Integer, Set<String>> map = new HashMap<Integer, Set<String>>();
|
|
|
+ map.put(exam.getId(), subjectSet);
|
|
|
+ ScoreReportThread thread = new ScoreReportThread(map, reportService, examLock);
|
|
|
+ taskExecutor.submit(thread);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "客观题分析计算", type = LogType.UPDATE)
|
|
|
+ @RequestMapping(value = "/report/objective", method = RequestMethod.POST)
|
|
|
+ public JSONObject reportObjective(HttpServletRequest request) {
|
|
|
+ ApiUser wu = RequestUtils.getApiUser(request);
|
|
|
+ Exam exam = examService.findById(getSessionExamId(request));
|
|
|
+ if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
|
|
|
+ throw new StatusException("请选择正确的考试");
|
|
|
+ } else {
|
|
|
+ Set<String> subjectSet = new HashSet<String>();
|
|
|
+ // 整个考试加锁
|
|
|
+ boolean examLock = true;
|
|
|
+ List<ExamSubject> list = subjectService.list(exam.getId());
|
|
|
+ for (ExamSubject subject : list) {
|
|
|
+ if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
|
|
|
+ subjectSet.add(subject.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!subjectSet.isEmpty()) {
|
|
|
+ Map<Integer, Set<String>> map = new HashMap<Integer, Set<String>>();
|
|
|
+ map.put(exam.getId(), subjectSet);
|
|
|
+ ScoreReportObjectiveThread thread = new ScoreReportObjectiveThread(map, reportService, examLock);
|
|
|
+ taskExecutor.submit(thread);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Logging(menu = "导入数据包", type = LogType.IMPORT_FILE)
|
|
|
+ @RequestMapping(value = "/importData", method = RequestMethod.POST)
|
|
|
+ public JSONObject importData(HttpServletRequest request, MultipartFile file) {
|
|
|
+ int examId = getSessionExamId(request);
|
|
|
+ List<String> error = new ArrayList<String>();
|
|
|
+ try {
|
|
|
+ byte[] data = IOUtils.toByteArray(file.getInputStream());
|
|
|
+ File target = new File(tempFile + File.separator + "temp.zip");
|
|
|
+ target.getParentFile().mkdirs();
|
|
|
+ FileOutputStream ous = new FileOutputStream(target);
|
|
|
+ ous.write(data);
|
|
|
+ IOUtils.closeQuietly(ous);
|
|
|
+
|
|
|
+ ZipReader zipReader = new ZipReader(target);
|
|
|
+ for (String subjectCode : zipReader.list(false)) {
|
|
|
+ try {
|
|
|
+ if (subjectCode.equalsIgnoreCase("cards")) {
|
|
|
+ error = this.parseCard(examId, error, zipReader);
|
|
|
+ } else {
|
|
|
+ error = this.parseSubject(examId, subjectCode, error, zipReader);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("parse zip data error", e);
|
|
|
+ error.add("[" + subjectCode + "] 科目代码导入失败;");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ subjectService.updateCardType(examId);
|
|
|
+ target.delete();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("parse question excel error", e);
|
|
|
+ error.add("zip文件解析失败");
|
|
|
+ }
|
|
|
+ if (error.size() > 0) {
|
|
|
+ return result(StringUtils.join(error, " "));
|
|
|
+ }
|
|
|
+ return result(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> parseCard(int examId, List<String> error, ZipReader zipReader) throws IOException {
|
|
|
+ InputStream ins = zipReader.read("cards", "description.json");
|
|
|
+ List<AnswerCardSubjectFile> courseList = AnswerCardSubjectFile.parse(ins);
|
|
|
+ for (AnswerCardSubjectFile answerCardSubjectFile : courseList) {
|
|
|
+ try {
|
|
|
+ InputStream cardIns = zipReader.read("cards", answerCardSubjectFile.getCode() + ".json");
|
|
|
+ CardFile cardFile = CardFile.parse(cardIns);
|
|
|
+ if (cardFile.getPages().size() != 1 && cardFile.getPages().size() % 2 != 0) {
|
|
|
+ error.add("[" + answerCardSubjectFile.getCode() + "] 科目代码卡格式解析有误;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ byte[] out = cardFile.output();
|
|
|
+ String md5 = BinaryUtil.encodeMD5(out);
|
|
|
+ AnswerCard card = answerCardService.findByExamIdAndCode(examId, answerCardSubjectFile.getCode());
|
|
|
+ if (card == null) {
|
|
|
+ card = new AnswerCard();
|
|
|
+ card.setExamId(examId);
|
|
|
+ Integer number = answerCardService.findMaxNumberByExamId(examId) + 1;
|
|
|
+ card.setNumber(number);
|
|
|
+ card.setCode(answerCardSubjectFile.getCode());
|
|
|
+ }
|
|
|
+ card.setMd5(md5);
|
|
|
+ card.setNeedAdapte(true);
|
|
|
+ card.setSliceConfig(cardFile.getSliceConfig().toString());
|
|
|
+ card.setSinglePage(cardFile.getPages().size() == 1);
|
|
|
+ card.setPaperCount(card.getSinglePage() ? 1 : cardFile.getPages().size() / 2);
|
|
|
+ card.setSource(CardSource.WEB);
|
|
|
+ card.setUpdateTime(new Date());
|
|
|
+ List<String> asList = new ArrayList<String>();
|
|
|
+ List<ExamSubject> subjects = new ArrayList<ExamSubject>();
|
|
|
+ for (AnswerCardSubjectItem item : answerCardSubjectFile.getCourses()) {
|
|
|
+ ExamSubject subject = subjectService.find(examId, item.getCode());
|
|
|
+ if (subject == null) {
|
|
|
+ error.add("[" + item.getCode() + "] 科目代码不存在;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ if (answerCardService.hasSubject(examId, item.getCode(), item.getCode())) {
|
|
|
+ error.add("[" + item.getCode() + "] 科目代码已经绑定卡格式;");
|
|
|
+ return error;
|
|
|
+ } else {
|
|
|
+ asList.add(item.getCode());
|
|
|
+ subject.setSliceConfig(cardFile.getSliceConfig().toString());
|
|
|
+ subject.setCardType(FormatType.JSON);
|
|
|
+ subjects.add(subject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ answerCardService.save(card, asList);
|
|
|
+ fileService.uploadAnswerCard(new ByteArrayInputStream(out), md5, examId, card.getNumber());
|
|
|
+ for (ExamSubject examSubject : subjects) {
|
|
|
+ subjectService.save(examSubject);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("parse zip data error", e);
|
|
|
+ error.add("[" + answerCardSubjectFile.getCode() + "] 科目代码卡格式解析有误;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> parseSubject(int examId, String subjectCode, List<String> error, ZipReader zipReader)
|
|
|
+ throws Exception {
|
|
|
+ ExamSubject subject = subjectService.find(examId, subjectCode);
|
|
|
+ if (subject == null) {
|
|
|
+ error.add("[" + subjectCode + "] 科目代码不存在;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ if (subject.getTotalScore() != 0) {
|
|
|
+ error.add("[" + subjectCode + "] 科目代码已经存在题目;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ InputStream cardIns = zipReader.read(subjectCode, "card.json");
|
|
|
+ CardFile cardFile = CardFile.parse(cardIns);
|
|
|
+ if (cardFile.getPages().size() != 1 && cardFile.getPages().size() % 2 != 0) {
|
|
|
+ error.add("[" + subjectCode + "] 科目代码卡格式解析有误;");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ byte[] out = cardFile.output();
|
|
|
+ String md5 = BinaryUtil.encodeMD5(out);
|
|
|
+ AnswerCard card = answerCardService.findByExamIdAndSubjectCode(examId, subject.getCode(), CardSource.WEB);
|
|
|
+ if (card == null) {
|
|
|
+ card = new AnswerCard();
|
|
|
+ card.setExamId(examId);
|
|
|
+ Integer number = answerCardService.findMaxNumberByExamId(examId) + 1;
|
|
|
+ card.setNumber(number);
|
|
|
+ }
|
|
|
+ card.setMd5(md5);
|
|
|
+ card.setNeedAdapte(true);
|
|
|
+ card.setSliceConfig(cardFile.getSliceConfig().toString());
|
|
|
+ card.setSinglePage(cardFile.getPages().size() == 1);
|
|
|
+ card.setPaperCount(card.getSinglePage() ? 1 : cardFile.getPages().size() / 2);
|
|
|
+ card.setSource(CardSource.WEB);
|
|
|
+ card.setUpdateTime(new Date());
|
|
|
+ answerCardService.save(card, subjectCode);
|
|
|
+
|
|
|
+ fileService.uploadAnswerCard(new ByteArrayInputStream(out), md5, examId, card.getNumber());
|
|
|
+ subject.setSliceConfig(cardFile.getSliceConfig().toString());
|
|
|
+ subject.setCardType(FormatType.JSON);
|
|
|
+ subjectService.save(subject);
|
|
|
+
|
|
|
+ InputStream structIns = zipReader.read(subjectCode, "struct.json");
|
|
|
+ StructFile structFile = StructFile.parse(structIns);
|
|
|
+ if (!structFile.getObjective().isEmpty()) {
|
|
|
+ List<ExamQuestion> oList = new ArrayList<ExamQuestion>();
|
|
|
+ for (StructQuestion structQuestion : structFile.getObjective()) {
|
|
|
+ ExamQuestion q = structQuestion.transform();
|
|
|
+ q.setPaperType(structFile.getPaperType());
|
|
|
+ q.setExamId(examId);
|
|
|
+ q.setSubjectCode(subject.getCode());
|
|
|
+ q.setObjective(true);
|
|
|
+ oList.add(q);
|
|
|
+ }
|
|
|
+ questionService.save(oList);
|
|
|
+ examService.updateObjectiveStatus(examId, ObjectiveStatus.WAITING);
|
|
|
+ subjectService.updateScore(examId, subject.getCode(), true,
|
|
|
+ questionService.sumTotalScore(examId, subject.getCode(), true));
|
|
|
+ }
|
|
|
+ if (!structFile.getSubjective().isEmpty()) {
|
|
|
+ List<ExamQuestion> sList = new ArrayList<ExamQuestion>();
|
|
|
+ Map<Integer, Double> mainMap = new HashMap<Integer, Double>();
|
|
|
+ for (StructQuestion structQuestion : structFile.getSubjective()) {
|
|
|
+ ExamQuestion q = structQuestion.transform();
|
|
|
+ q.setPaperType(structFile.getPaperType());
|
|
|
+ q.setExamId(examId);
|
|
|
+ q.setSubjectCode(subject.getCode());
|
|
|
+ q.setObjective(false);
|
|
|
+ q.setGroupNumber(q.getMainNumber());
|
|
|
+ sList.add(q);
|
|
|
+ Double totalScore = mainMap.get(q.getMainNumber());
|
|
|
+ if (totalScore == null) {
|
|
|
+ mainMap.put(q.getMainNumber(), q.getTotalScore());
|
|
|
+ } else {
|
|
|
+ mainMap.put(q.getMainNumber(), totalScore + q.getTotalScore());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ questionService.save(sList);
|
|
|
+ for (Integer number : mainMap.keySet()) {
|
|
|
+ MarkGroup group = new MarkGroup(examId, subject.getCode(), number, null, mainMap.get(number), null,
|
|
|
+ null, null, null, null, 0, false, false, null, false);
|
|
|
+ group.setPicList(cardFile.getMarkConfigAdd(cardFile.getMarkConfig(number), 0.015));
|
|
|
+ groupService.save(group);
|
|
|
+ }
|
|
|
+ subjectService.updateScore(examId, subject.getCode(), false,
|
|
|
+ questionService.sumTotalScore(examId, subject.getCode(), false));
|
|
|
+ }
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
}
|