package cn.com.qmth.stmms.mark; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import net.sf.json.JSONObject; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; 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.ModelAndView; import cn.com.qmth.stmms.biz.exam.model.Exam; import cn.com.qmth.stmms.biz.exam.model.ExamSubject; import cn.com.qmth.stmms.biz.exam.model.MarkGroup; import cn.com.qmth.stmms.biz.exam.model.Marker; import cn.com.qmth.stmms.biz.exam.service.ExamService; import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService; import cn.com.qmth.stmms.biz.exam.service.MarkGroupService; import cn.com.qmth.stmms.biz.exam.service.MarkerService; import cn.com.qmth.stmms.biz.lock.LockService; import cn.com.qmth.stmms.biz.mark.model.MarkLibrary; import cn.com.qmth.stmms.biz.mark.model.MarkResult; import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem; import cn.com.qmth.stmms.biz.mark.model.ProblemType; import cn.com.qmth.stmms.biz.mark.model.Task; import cn.com.qmth.stmms.biz.mark.model.TrialHistory; import cn.com.qmth.stmms.biz.mark.model.TrialLibrary; import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery; import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService; import cn.com.qmth.stmms.biz.mark.service.MarkService; import cn.com.qmth.stmms.biz.mark.service.ProblemTypeService; import cn.com.qmth.stmms.biz.mark.service.TaskService; import cn.com.qmth.stmms.biz.mark.service.TrialService; import cn.com.qmth.stmms.common.controller.BaseController; import cn.com.qmth.stmms.common.enums.ExamType; import cn.com.qmth.stmms.common.enums.LibraryStatus; import cn.com.qmth.stmms.common.enums.LockType; import cn.com.qmth.stmms.common.enums.MarkMode; import cn.com.qmth.stmms.common.enums.MarkStatus; import cn.com.qmth.stmms.common.utils.RequestUtils; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @Controller @RequestMapping("/mark") public class MarkController extends BaseController { private static Logger log = LoggerFactory.getLogger(MarkController.class); @Autowired private ExamSubjectService subjectService; @Autowired private TrialService trialService; @Autowired private MarkerService markerService; @Autowired private MarkLibraryService libraryService; @Autowired private TaskService taskService; @Autowired private MarkService markService; @Autowired private ExamService examService; @Autowired private MarkGroupService groupService; @Autowired private LockService lockService; @Autowired private ProblemTypeService problemTypeService; @Value("${slice.image.server}") private String sliceServer; @Value("${sheet.image.server}") private String sheetServer; @Value("${card.server}") private String cardServer; @Value("${marker.forceMode}") private String forceMarkMode; @Value("${json.server}") private String jsonServer; @RequestMapping(value = "/reset", method = RequestMethod.GET) public ModelAndView reset(HttpServletRequest request) { Marker marker = RequestUtils.getWebUser(request).getMarker(); ModelAndView modelAndView = new ModelAndView("modules/mark/reset"); modelAndView.addObject("marker", marker); return modelAndView; } @RequestMapping(value = "/reset", method = RequestMethod.POST) public ModelAndView reset(HttpServletRequest request, Marker marker) { Marker current = RequestUtils.getWebUser(request).getMarker(); current.setName(marker.getName()); current.setPassword(marker.getPassword()); current.setLastLoginIp(request.getRemoteAddr()); current.setLastLoginTime(new Date()); markerService.save(current); return new ModelAndView("redirect:/mark/index"); } @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, @RequestParam(value = "mode", required = false) String mode) { Marker marker = RequestUtils.getWebUser(request).getMarker(); ModelAndView modelAndView = getMarkModeView(marker, MarkMode.findByName(mode)); preProcess(marker, modelAndView); return modelAndView; } private ModelAndView getMarkModeView(Marker marker, MarkMode mode) { // 多媒体阅卷 Exam exam = examService.findById(marker.getExamId()); boolean forceMode = false; MarkMode sysMode = MarkMode.findByName(forceMarkMode); MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); if (ExamType.MULTI_MEDIA.equals(exam.getType())) { ModelAndView view = new ModelAndView("modules/mark/markJson"); view.addObject("forceMode", false); view.addObject("sheetView", false); view.addObject("isFormal", group.getStatus() == MarkStatus.FORMAL); return view; } if (sysMode != null) { // 全局配置的强制评卷模式 mode = sysMode; forceMode = true; } else { // 没有全局配置,优先从大题配置取强制评卷模式 if (group != null && group.getMarkMode() != null) { mode = group.getMarkMode(); forceMode = true; } // 否则取评卷员当前记录的评卷模式 if (mode == null) { mode = marker.getMode(); } if (mode == null) { mode = MarkMode.COMMON; } if (marker.getMode() != mode) { marker.setMode(mode); markerService.save(marker); } } ModelAndView view = new ModelAndView(mode == MarkMode.TRACK ? "modules/mark/markTrack" : "modules/mark/markNew"); view.addObject("forceMode", forceMode); view.addObject("sheetView", group.isSheetView()); view.addObject("isFormal", group.getStatus() == MarkStatus.FORMAL); return view; } @RequestMapping("/logout") public ModelAndView logout(HttpServletRequest request) { releaseMarker(RequestUtils.getWebUser(request).getMarker()); return new ModelAndView("redirect:/logout"); } /** * 进入评卷界面后的通用预处理 * * @param marker * @param session * @param modelAndView * @param modelAndView */ private void preProcess(Marker marker, ModelAndView modelAndView) { modelAndView.addObject("sliceServer", sliceServer); modelAndView.addObject("sheetServer", sheetServer); modelAndView.addObject("cardServer", cardServer); modelAndView.addObject("jsonServer", jsonServer); modelAndView.addObject("marker", marker); ExamSubject subject = subjectService.find(marker.getExamId(), marker.getSubjectCode()); modelAndView.addObject("subject", subject); Exam exam = examService.findById(marker.getExamId()); modelAndView.addObject("forceSpecialTag", exam.isForceSpecialTag()); modelAndView.addObject("defaultSetting", StringUtils.trimToNull(marker.getMarkSetting())); String sheetConfig = ""; if (StringUtils.isNotBlank(subject.getSheetConfig())) { sheetConfig = buildPictureConfig(subject.getSheetConfig()); } else if (StringUtils.isNotBlank(exam.getSheetConfig())) { sheetConfig = buildPictureConfig(exam.getSheetConfig()); } modelAndView.addObject("sheetConfig", sheetConfig); releaseMarker(marker); List problemTypes = problemTypeService.findByExamId(marker.getExamId()); ObjectMapper mapper = new ObjectMapper(); try { modelAndView.addObject("problemTypes", mapper.writeValueAsString(problemTypes)); } catch (JsonProcessingException e) { log.error("MarkController-问题类型获取出错", e); } } @RequestMapping("/clear") @ResponseBody public void clear(HttpServletRequest request) { releaseMarker(RequestUtils.getWebUser(request).getMarker()); } @RequestMapping("/status") @ResponseBody public JSONObject status(HttpServletRequest request) { JSONObject status = new JSONObject(); Marker marker = RequestUtils.getWebUser(request).getMarker(); ExamSubject subject = subjectService.find(marker.getExamId(), marker.getSubjectCode()); MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); if (subject == null || group == null || group.getStatus() == MarkStatus.FINISH) { status.accumulate("valid", false); return status; } long totalCount = 0; long personCount = 0; long markedCount = 0; long exceptionCount = 0; long topCount = 0; if (group.getStatus() == MarkStatus.FORMAL) { topCount = marker.getTopCount() != null ? marker.getTopCount() : 0; MarkLibrarySearchQuery query = new MarkLibrarySearchQuery(); query.setExamId(marker.getExamId()); query.setSubjectCode(marker.getSubjectCode()); query.setGroupNumber(marker.getGroupNumber()); totalCount = libraryService.countByQuery(query); query.setMarkerId(marker.getId()); personCount = libraryService.countByQuery(query); query.setMarkerId(0); query.addStatus(LibraryStatus.MARKED); query.addStatus(LibraryStatus.INSPECTED); query.addStatus(LibraryStatus.ARBITRATED); markedCount = libraryService.countByQuery(query); query.clearStatus(); query.addStatus(LibraryStatus.WAIT_ARBITRATE); query.addStatus(LibraryStatus.PROBLEM); exceptionCount = libraryService.countByQuery(query); } else if (group.getStatus() == MarkStatus.TRIAL) { totalCount = trialService.countLibrary(group.getExamId(), group.getSubjectCode(), group.getNumber()); personCount = trialService.countMarkerHistory(marker.getId()); markedCount = personCount; } status.accumulate("personCount", personCount); status.accumulate("totalCount", totalCount); status.accumulate("markedCount", markedCount); status.accumulate("exceptionCount", exceptionCount); status.accumulate("valid", totalCount > 0); status.accumulate("topCount", topCount); return status; } @RequestMapping("/gettask") @ResponseBody public Task getTask(HttpServletRequest request) { Marker marker = RequestUtils.getWebUser(request).getMarker(); Task task = null; try { lockService.watch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); lockService.watch(LockType.MARKER, marker.getId()); MarkGroup group = groupService .findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); if (group == null) { task = new Task(); task.setExist(false); task.setMessage("mark.control.task.not.exist"); } else if (group.getStatus() == MarkStatus.FINISH) { task = new Task(); task.setExist(false); task.setMessage("mark.control.task.finish"); } else if (group.getStatus() == MarkStatus.TRIAL) { task = getTrialTask(marker); } else if (group.getStatus() == MarkStatus.FORMAL) { task = getFormalTask(marker); } if (task == null) { task = new Task(); task.setExist(false); task.setMessage("mark.control.task.null"); } } catch (Exception e) { log.error("get task error", e); } finally { lockService.unwatch(LockType.MARKER, marker.getId()); lockService.unwatch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); } return task; } private Task getFormalTask(Marker marker) { int retry = 1; Task task = null; while (task == null) { List list = new ArrayList(); // 需要判断评卷员是否绑定了班级 list = libraryService.findUnMarked(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(), marker.getId(), marker.getClassCount() != null && marker.getClassCount() > 0, retry, 20); if (list.isEmpty()) { break; } for (MarkLibrary library : list) { if (markService.applyLibrary(library, marker)) { task = taskService.build(library); break; } } if (task == null) { retry++; } } return task; } private Task getTrialTask(Marker marker) { int retry = 1; Task task = null; while (task == null) { List list = trialService.findUnMarkedLibrary(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(), marker.getId(), retry, 10); if (list.isEmpty()) { break; } for (TrialLibrary library : list) { if (markService.applyLibrary(library, marker)) { task = taskService.build(library, null); break; } } retry++; } return task; } @RequestMapping(value = "/savetask", method = RequestMethod.POST) @ResponseBody public JSONObject saveTask(HttpServletRequest request, @RequestBody MarkResult markResult) { JSONObject result = new JSONObject(); Marker marker = RequestUtils.getWebUser(request).getMarker(); boolean success = false; try { lockService.watch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); lockService.watch(LockType.STUDENT, markResult.getStudentId()); lockService.watch(LockType.MARKER, marker.getId()); lockService.waitlock(LockType.GROUP_LIBRARY, markResult.getStudentId(), marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); success = markService.submitTask(markResult, marker); } catch (Exception e) { success = false; log.error("save task error", e); } finally { lockService.unlock(LockType.GROUP_LIBRARY, markResult.getStudentId(), marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); lockService.unwatch(LockType.MARKER, marker.getId()); lockService.unwatch(LockType.STUDENT, markResult.getStudentId()); lockService.unwatch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); } result.accumulate("success", success); result.accumulate("status", status(request)); if (!success) { result.accumulate("message", "mark.control.tsak.error"); } return result; } @RequestMapping("/gethistory") @ResponseBody public Object history(HttpServletRequest request, @RequestParam int pageNumber, @RequestParam int pageSize, @RequestParam String order, @RequestParam String sort, @RequestParam(required = false, defaultValue = "false") Boolean isTag, @RequestParam(required = false) Integer studentId) throws Exception { Marker marker = RequestUtils.getWebUser(request).getMarker(); List list = new ArrayList<>(); Direction d = Direction.DESC; Sort querySort = null; if (sort.equals("asc")) { d = Direction.ASC; } if (order.equals("time")) { querySort = new Sort(d, "markerTime"); } else if (order.equals("studentId")) { querySort = new Sort(d, "studentId"); } else if (order.equals("score")) { querySort = new Sort(d, "markerScore"); } MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber()); if (group != null && group.getStatus() == MarkStatus.FORMAL) { // 正评查找已给分的评卷任务 MarkLibrarySearchQuery query = new MarkLibrarySearchQuery(); query.setExamId(marker.getExamId()); query.setSubjectCode(marker.getSubjectCode()); query.setMarkerId(marker.getId()); query.addStatus(LibraryStatus.MARKED); query.addStatus(LibraryStatus.INSPECTED); query.setGroupNumber(marker.getGroupNumber()); query.setPageNumber(pageNumber); query.setPageSize(pageSize); if (querySort != null) { query.setSort(querySort); } else { query.orderByMarkerTimeDesc(); } if (studentId != null) { query.setStudentId(studentId); } list = taskService.findByQuery(query); for (Task task : list) { task.setPrevious(true); } } else if (group != null && group.getStatus() == MarkStatus.TRIAL) { // 试评查找给分历史记录 List historyList = new ArrayList(); if (studentId != null) { historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(), marker.getId(), studentId, pageNumber, pageSize, querySort); } else { historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(), marker.getId(), pageNumber, pageSize, querySort, null); } for (TrialHistory history : historyList) { TrialLibrary library = trialService.findLibrary(history.getLibraryId()); if (library != null) { Task task = taskService.build(library, history); task.setPrevious(true); list.add(task); } } } return list; } @RequestMapping("/change-name") @ResponseBody public JSONObject changeName(HttpServletRequest request, @RequestParam String name, @RequestParam(required = false) String password) { Marker marker = RequestUtils.getWebUser(request).getMarker(); JSONObject result = new JSONObject(); marker.setName(name); if (StringUtils.isNotEmpty(password)) { marker.setPassword(password); } marker = markerService.save(marker); result.accumulate("success", marker != null); if (marker != null) { result.accumulate("name", marker.getName()); } return result; } @RequestMapping("/update-setting") @ResponseBody public JSONObject updateSetting(HttpServletRequest request, @RequestParam String setting) { Marker marker = RequestUtils.getWebUser(request).getMarker(); JSONObject result = new JSONObject(); markerService .updateMarkSetting(marker.getId(), StringEscapeUtils.unescapeHtml(StringUtils.trimToNull(setting))); result.accumulate("success", true); return result; } private void releaseMarker(Marker marker) { if (marker == null) { return; } try { lockService.waitlock(LockType.MARKER, marker.getId()); markService.releaseByMarker(marker); } catch (Exception e) { log.error("release marker error", e); } finally { lockService.unlock(LockType.MARKER, marker.getId()); } } protected String buildPictureConfig(String sheetConfig) { String json = ""; if (StringUtils.isNotBlank(sheetConfig)) { try { ObjectMapper mapper = new ObjectMapper(); json = mapper.writeValueAsString(PictureConfigItem.parse(sheetConfig)); } catch (JsonProcessingException e) { e.printStackTrace(); } } return json; } }