package cn.com.qmth.scancentral.controller.admin; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; 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.RestController; import org.springframework.web.multipart.MultipartFile; import com.qmth.boot.api.annotation.Aac; import com.qmth.boot.api.constant.ApiConstant; import com.qmth.boot.core.collection.PageResult; import com.qmth.boot.core.concurrent.service.ConcurrentService; import com.qmth.boot.core.exception.ReentrantException; import com.qmth.boot.core.exception.StatusException; import com.qmth.boot.tools.excel.ExcelWriter; import com.qmth.boot.tools.excel.enums.ExcelType; import com.qmth.boot.tools.excel.model.DataMap; import com.qmth.boot.tools.iterator.PageListIterator; import com.qmth.boot.tools.iterator.SingletonIterator; import cn.com.qmth.scancentral.bean.AbsentQueryDomain; import cn.com.qmth.scancentral.bean.AnswerQueryDomain; import cn.com.qmth.scancentral.controller.BaseController; import cn.com.qmth.scancentral.entity.ExamEntity; import cn.com.qmth.scancentral.entity.SubjectEntity; import cn.com.qmth.scancentral.enums.ExamStatus; import cn.com.qmth.scancentral.enums.ExamStatusCheckMode; import cn.com.qmth.scancentral.enums.GroupType; import cn.com.qmth.scancentral.enums.LockType; import cn.com.qmth.scancentral.exception.ParameterExceptions; import cn.com.qmth.scancentral.model.ManualAbsentImportDTO; import cn.com.qmth.scancentral.service.ExamService; import cn.com.qmth.scancentral.service.StudentService; import cn.com.qmth.scancentral.service.SubjectService; import cn.com.qmth.scancentral.task.thread.ExamStatusImportThread; import cn.com.qmth.scancentral.task.thread.ExamStatusResetThread; import cn.com.qmth.scancentral.util.ResouceUtil; import cn.com.qmth.scancentral.vo.AbsentInfoVo; import cn.com.qmth.scancentral.vo.AbsentManualImportVo; import cn.com.qmth.scancentral.vo.AbsentQueryVo; import cn.com.qmth.scancentral.vo.ExamStatusSaveVo; import cn.com.qmth.scancentral.vo.UpdateTimeVo; import cn.com.qmth.scancentral.vo.answerquery.AnswerQueryVo; import cn.com.qmth.scancentral.vo.student.StudentExamRoomVo; import cn.com.qmth.scancentral.vo.student.StudentVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import net.sf.json.JSONObject; @RestController @Api(tags = "缺考接口") @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/admin/check") @Aac(strict = false, auth = true) public class CheckController extends BaseController { @Autowired private StudentService studentService; @Resource private ConcurrentService concurrentService; @Autowired private ExamService examService; @Autowired private AsyncTaskExecutor taskExecutor; @Autowired private SubjectService subjectService; @ApiOperation(value = "缺考数据汇总") @PostMapping("absent/info") public AbsentInfoVo absentInfo(@RequestParam Long examId, @RequestParam(required = false) GroupType groupType, @RequestParam(required = false) String groupName) { return studentService.absentInfo(examId, groupType, groupName); } @ApiOperation(value = "查询缺考数据") @RequestMapping(value = "absent/query", method = RequestMethod.POST) public PageResult absentQuery(@Validated AbsentQueryDomain query) { return studentService.absentQuery(query); } @ApiOperation(value = "查询缺考数据标识") @RequestMapping(value = "absent/summary", method = RequestMethod.POST) public List absentSummary(@Validated AbsentQueryDomain query) { return studentService.absentSummary(query); } @ApiOperation(value = "导出缺考数据") @RequestMapping(value = "absent/export", method = RequestMethod.POST) public void absentExport(@Validated AbsentQueryDomain query, HttpServletResponse response) throws IOException { String fileName = URLEncoder.encode("缺考数据", "UTF-8"); response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx"); response.setContentType("application/vnd.ms-excel"); Map subjectMap = new HashMap<>(); PageListIterator iterator = new PageListIterator(100) { @Override public Collection getPageList(int pageNumber, int pageSize) { query.setPageNumber(pageNumber); query.setPageSize(pageSize); List list = studentService.absentExportList(query); List ret = new ArrayList<>(); if (CollectionUtils.isNotEmpty(list)) { for (AbsentQueryVo vo : list) { DataMap map = new DataMap(); if (GroupType.SUBJECT.equals(query.getGroupType())) { map.put("科目代码", vo.getGroupName()); map.put("科目名称", getSubjectName(subjectMap, vo.getGroupName(), query.getExamId())); } else { map.put(query.getGroupType().getName(), vo.getGroupName()); } map.put("考生总数", getStringVal(vo.getTotalCount())); map.put("已扫描", getStringVal(vo.getScannedCount())); map.put("未扫描", getStringVal(vo.getUnexistCount())); map.put("指定缺考", getStringVal(vo.getManualAbsentCount())); map.put("识别缺考", getStringVal(vo.getOmrAbsentCount())); map.put("缺考异常", getStringVal(vo.getAbsentSuspectCount())); ret.add(map); } } return ret; } }; String[] head; if (GroupType.SUBJECT.equals(query.getGroupType())) { head = new String[] { "科目代码", "科目名称", "考生总数", "已扫描", "未扫描", "指定缺考", "识别缺考", "缺考异常" }; } else { head = new String[] { query.getGroupType().getName(), "考生总数", "已扫描", "未扫描", "指定缺考", "识别缺考", "缺考异常" }; } ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX); writer.writeDataMaps("缺考核对", null, head, iterator); writer.output(response.getOutputStream()); } private String getSubjectName(Map subMap, String subjectCode, Long examId) { SubjectEntity subject = subMap.get(subjectCode); if (subMap.get(subjectCode) == null) { subject = subjectService.findByExamIdAndCode(examId, subjectCode); if (subject == null) { throw new StatusException("未找到科目信息:" + subjectCode); } subMap.put(subjectCode, subject); } return subject.getName(); } private String getStringVal(Integer val) { if (val == null) { return "0"; } return val.toString(); } @PostMapping("absent/manual/import") @ApiOperation(value = "导入指定缺考名单") public AbsentManualImportVo absentManualImport(@RequestParam Long examId, @RequestParam MultipartFile file) { return studentService.absentManualImport(examId, file); } @ApiOperation(value = "下载导入指定缺考名单模板") @PostMapping("absent/manual/template") public void getImportTemplate() throws IOException { ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX); writer.writeObjects("指定缺考名单", null, ManualAbsentImportDTO.class, new SingletonIterator<>(new ManualAbsentImportDTO())); exportFile("指定缺考名单导入模板.xlsx", writer); } @ApiOperation(value = "更新为指定缺考") @PostMapping("absent/manual/update") public UpdateTimeVo absentManualUpdate(@RequestParam Long examId, @RequestParam String subjectCode, @RequestParam String examNumber) { return studentService.absentManualUpdate(examId, subjectCode, examNumber); } @ApiOperation(value = "取消缺考标记嫌疑") @PostMapping("absent/suspect/remove") public UpdateTimeVo absentSuspectRemove(@RequestParam Long examId, @RequestParam String subjectCode, @RequestParam String examNumber) { return studentService.absentSuspectUpdate(examId, subjectCode, examNumber, false); } @ApiOperation(value = "缺考校验列表") @RequestMapping(value = "exam-status/list", method = RequestMethod.POST) public PageResult examStatusList(@Validated AnswerQueryDomain query) { return studentService.query(query); } @ApiOperation(value = "缺考校验按考生导出") @PostMapping(value = "exam-status/student/export") public void studentExport(@Validated AnswerQueryDomain query, HttpServletResponse response) throws IOException { String fileName = URLEncoder.encode("按考生导出", "UTF-8"); response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx"); response.setContentType("application/vnd.ms-excel"); ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX); PageListIterator iterator = new PageListIterator(5000) { @Override public Collection getPageList(int pageNumber, int pageSize) { query.setPageNumber(pageNumber); query.setPageSize(pageSize); return studentService.studentExportList(query); } }; writer.writeObjects("按考生导出", null, StudentVo.class, iterator); writer.output(response.getOutputStream()); } @ApiOperation(value = "缺考校验按考场导出") @PostMapping(value = "exam-status/exam-room/export") public void studentExamRoomExport(@Validated AnswerQueryDomain query, HttpServletResponse response) throws IOException { String fileName = URLEncoder.encode("按考场导出", "UTF-8"); response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx"); response.setContentType("application/vnd.ms-excel"); ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX); PageListIterator iterator = new PageListIterator(5000) { @Override public Collection getPageList(int pageNumber, int pageSize) { query.setPageNumber(pageNumber); query.setPageSize(pageSize); return studentService.studentExamRoomExportList(query); } }; writer.writeObjects("按考场导出", null, StudentExamRoomVo.class, iterator); writer.output(response.getOutputStream()); } @ApiOperation(value = "缺考校验提交") @RequestMapping(value = "exam-status/save", method = RequestMethod.POST) public ExamStatusSaveVo examStatusSave(@RequestParam Long id, @RequestParam ExamStatus examStatus) { studentService.updateExamStatus(id, examStatus); return ExamStatusSaveVo.create(examStatus); } @ApiOperation(value = "缺考校验导入模版下载") @PostMapping("exam-status/template") public void breachTemplate(HttpServletResponse response) { exportFile("缺考校验导入模板.txt", ResouceUtil.getStream("templates/absent-import.txt")); } @ApiOperation(value = "缺考校验导入") @RequestMapping(value = "exam-status/import", method = RequestMethod.POST) public JSONObject examStatusImportFile(@RequestParam Long examId, @RequestParam ExamStatusCheckMode mode, @RequestParam MultipartFile file) throws IOException { ExamEntity exam = examService.getById(examId); if (exam == null) { throw ParameterExceptions.EXAM_NOT_FOUND; } if (!concurrentService.isLocked(LockType.EXAM_STATUS_RESET + "-" + examId)) { taskExecutor.submit( new ExamStatusImportThread(examId, mode, file.getInputStream(), studentService, concurrentService)); } else { throw new ReentrantException("正在导入,请稍后再试"); } JSONObject result = new JSONObject(); result.put("updateTime", System.currentTimeMillis()); result.put("synching", true); return result; } @ApiOperation(value = "缺考校验导入状态") @RequestMapping(value = "exam-status/import/status", method = RequestMethod.POST) public Map examStatusImportStatus(@RequestParam Long examId) { ExamEntity exam = examService.getById(examId); if (exam == null) { throw ParameterExceptions.EXAM_NOT_FOUND; } Map result = new HashMap(); result.put("synching", concurrentService.isLocked(LockType.EXAM_STATUS_RESET + "-" + examId)); return result; } @ApiOperation(value = "缺考校验重新生成") @RequestMapping(value = "exam-status/reset", method = RequestMethod.POST) public JSONObject examStatusReset(@RequestParam Long examId, @RequestParam Integer examNumberFillCount) { ExamEntity exam = examService.getById(examId); if (exam == null) { throw ParameterExceptions.EXAM_NOT_FOUND; } if (!concurrentService.isLocked(LockType.EXAM_STATUS_RESET + "-" + examId)) { taskExecutor .submit(new ExamStatusResetThread(examId, examNumberFillCount, studentService, concurrentService)); } else { throw new ReentrantException("正在重新生成,请稍后再试"); } JSONObject result = new JSONObject(); result.put("updateTime", System.currentTimeMillis()); result.put("synching", true); return result; } @ApiOperation(value = "缺考校验重新生成状态") @RequestMapping(value = "exam-status/reset/status", method = RequestMethod.POST) public Map examStatusResetStatus(@RequestParam Long examId) { ExamEntity exam = examService.getById(examId); if (exam == null) { throw ParameterExceptions.EXAM_NOT_FOUND; } Map result = new HashMap(); result.put("synching", concurrentService.isLocked(LockType.EXAM_STATUS_RESET + "-" + examId)); return result; } @ApiOperation(value = "缺考校验查询概要") @RequestMapping(value = "exam-status/summary", method = RequestMethod.POST) public List examStatusSummary(@Validated AnswerQueryDomain query) { return studentService.summary(query); } }