Răsfoiți Sursa

导出结果

xiatian 9 luni în urmă
părinte
comite
299ef219d3

+ 5 - 0
pom.xml

@@ -170,6 +170,11 @@
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
       </dependency>
+  		<dependency>
+            <groupId>com.github.albfernandez</groupId>
+            <artifactId>javadbf</artifactId>
+            <version>1.9.4</version>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 32 - 0
src/main/java/cn/com/qmth/scancentral/consumer/SliceDataExportConsumer.java

@@ -0,0 +1,32 @@
+package cn.com.qmth.scancentral.consumer;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.scancentral.service.SubjectService;
+import cn.com.qmth.scancentral.vo.subject.DataExportTaskVo;
+
+@Scope("prototype")
+@Service
+public class SliceDataExportConsumer implements Runnable {
+
+    private DataExportTaskVo vo;
+
+    @Autowired
+    private SubjectService subjectService;
+
+    @Override
+    public void run() {
+        subjectService.sliceDataExportDispose(vo);
+    }
+
+    public DataExportTaskVo getVo() {
+        return vo;
+    }
+
+    public void setVo(DataExportTaskVo vo) {
+        this.vo = vo;
+    }
+
+}

+ 50 - 0
src/main/java/cn/com/qmth/scancentral/controller/admin/SubjectController.java

@@ -2,6 +2,8 @@ package cn.com.qmth.scancentral.controller.admin;
 
 import java.util.List;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -10,9 +12,15 @@ import org.springframework.web.bind.annotation.RestController;
 
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.boot.core.exception.ParameterException;
+import com.qmth.boot.core.fss.store.FileStore;
 
 import cn.com.qmth.scancentral.controller.BaseController;
+import cn.com.qmth.scancentral.service.DataExportTaskService;
 import cn.com.qmth.scancentral.service.SubjectService;
+import cn.com.qmth.scancentral.util.Calculator;
+import cn.com.qmth.scancentral.vo.subject.DataExportProgressVo;
+import cn.com.qmth.scancentral.vo.subject.DataExportTaskVo;
 import cn.com.qmth.scancentral.vo.subject.ScanProgressVo;
 import cn.com.qmth.scancentral.vo.subject.SubjectBreachVo;
 import cn.com.qmth.scancentral.vo.subject.SubjectCustStatusVo;
@@ -29,6 +37,12 @@ public class SubjectController extends BaseController {
     @Autowired
     private SubjectService subjectService;
 
+    @Autowired
+    private FileStore fileStore;
+
+    @Autowired
+    private DataExportTaskService dataExportTaskService;
+
     @ApiOperation(value = "科目扫描进度查询")
     @PostMapping("scan/progress")
     public ScanProgressVo scanProgress(@RequestParam Long examId, @RequestParam(required = false) String subjectCode) {
@@ -52,4 +66,40 @@ public class SubjectController extends BaseController {
     public TaskIdVo answerDataExport(@RequestParam Long examId, @RequestParam String subjectCode) {
         return subjectService.answerDataExport(examId, subjectCode);
     }
+
+    @ApiOperation(value = "导出打包DBF")
+    @PostMapping("slice-data/export")
+    public TaskIdVo sliceDataExport(@RequestParam Long examId, @RequestParam String subjectCode) {
+        return subjectService.sliceDataExport(examId, subjectCode);
+    }
+
+    @ApiOperation(value = "导出扫描答案DBF、打包DBF下载进度查询")
+    @PostMapping("data/progress")
+    public DataExportProgressVo dataProgress(@RequestParam String taskId) {
+        DataExportTaskVo vo = dataExportTaskService.getTask(taskId);
+        if (vo == null) {
+            throw new ParameterException("未找到导出任务");
+        }
+        DataExportProgressVo ret = new DataExportProgressVo();
+        ret.setSuccess(vo.getSuccess());
+        ret.setErrMsg(vo.getErrMsg());
+        ret.setProgress(Calculator.percentageDouble(vo.getProgressCount(), vo.getTotalCount()));
+        return ret;
+    }
+
+    @ApiOperation(value = "扫描答案DBF、打包DBF下载")
+    @PostMapping("data/down")
+    public void dataDown(HttpServletResponse response, @RequestParam String taskId) throws Exception {
+        DataExportTaskVo vo = dataExportTaskService.getTask(taskId);
+        if (vo == null) {
+            throw new ParameterException("未找到导出任务");
+        }
+        if (vo.getSuccess() == null || !vo.getSuccess()) {
+            throw new ParameterException("导出任务失败");
+        }
+        if (vo.getTotalCount() != (vo.getProgressCount())) {
+            throw new ParameterException("导出任务未结束");
+        }
+        exportFile(vo.getFileName(), fileStore.read(vo.getFilePath()));
+    }
 }

+ 17 - 12
src/main/java/cn/com/qmth/scancentral/dao/StudentDao.java

@@ -35,16 +35,16 @@ public interface StudentDao extends BaseMapper<StudentEntity> {
     List<ExamSiteVo> listSiteByExamId(@Param("examId") Long examId);
 
     AbsentInfoVo absentInfo(@Param("examId") Long examId, @Param("groupType") String groupType,
-                            @Param("groupName") String groupName);
+            @Param("groupName") String groupName);
 
     List<String> absentQuerySummary(@Param("groupNameCol") String groupNameCol,
-                                    @Param("query") AbsentQueryDomain query);
+            @Param("query") AbsentQueryDomain query);
 
     IPage<AbsentQueryVo> absentQueryPage(Page<AbsentQueryVo> page, @Param("groupNameCol") String groupNameCol,
-                                         @Param("query") AbsentQueryDomain query);
+            @Param("query") AbsentQueryDomain query);
 
     List<AbsentQueryVo> absentExportList(Page<AbsentQueryVo> page, @Param("groupNameCol") String groupNameCol,
-                                         @Param("query") AbsentQueryDomain query);
+            @Param("query") AbsentQueryDomain query);
 
     IPage<AnswerQueryVo> queryPage(Page<AnswerQueryVo> page, @Param("query") AnswerQueryDomain query);
 
@@ -70,40 +70,45 @@ public interface StudentDao extends BaseMapper<StudentEntity> {
 
     int getNeedUploadCount(@Param("examId") Long examId);
 
+    int countCetMarking(@Param("query") ExportCetMarkingQueryVo query);
+
     IPage<ExportCetVo> listCetMarkingPage(Page<ExportCetVo> page, @Param("query") ExportCetMarkingQueryVo query);
 
     ScanAnswerInfoVo getInfoCountByExam(@Param("examId") Long examId);
 
     List<AssignedCheckExport> exportAssignedCheckPage(Page<AssignedCheckExport> page,
-                                                      @Param("query") AssignedQueryDomain query);
+            @Param("query") AssignedQueryDomain query);
 
     IPage<AnswerQueryVo> queryAssignedCheckPage(Page<AnswerQueryVo> page, @Param("query") AssignedQueryDomain query);
 
     List<AnswerQueryVo> findUnCheck(@Param("examId") Long examId, @Param("pageNumber") int pageNumber,
-                                    @Param("pageSize") int pageSize, @Param("checkCount") int checkCount);
+            @Param("pageSize") int pageSize, @Param("checkCount") int checkCount);
 
     List<AnswerQueryVo> getAssignedCheckTaskHistory(@Param("id") Long id, @Param("pageSize") Long pageSize,
-                                                    @Param("userId") Long userId, @Param("examId") Long examId);
+            @Param("userId") Long userId, @Param("examId") Long examId);
 
     void updateAssignedCheckCount(@Param("id") Long id);
 
     List<SubjectScanProgressVo> scanProgress(@Param("examId") Long examId, @Param("subjectCode") String subjectCode);
 
     IPage<ExamRoomScannedVo> examRoomScannedPage(Page<ExamRoomScannedVo> page,
-                                                 @Param("req") ExamRoomScannedQuery query);
+            @Param("req") ExamRoomScannedQuery query);
 
     IPage<StudentPageVo> studentPage(Page<StudentPageVo> page, @Param("req") StudentPageQuery query);
 
     IPage<StudentVo> studentExport(Page<StudentVo> page, @Param("query") AnswerQueryDomain query);
 
     IPage<StudentExamRoomVo> studentExamRoomExport(Page<StudentExamRoomVo> page,
-                                                   @Param("query") AnswerQueryDomain query);
+            @Param("query") AnswerQueryDomain query);
 
-    List<Long> queryImageCheckWaitingList(@Param("examId") Long examId, @Param("startId") Long startId, @Param("batchSize") Integer batchSize);
+    List<Long> queryImageCheckWaitingList(@Param("examId") Long examId, @Param("startId") Long startId,
+            @Param("batchSize") Integer batchSize);
 
     List<ImageCheckVo> countImageCheck(@Param("examId") Long examId);
 
-    IPage<ImageCheckDetailVo> queryImageCheckDetail(Page<ImageCheckDetailVo> page, @Param("query") ImageCheckQuery query);
+    IPage<ImageCheckDetailVo> queryImageCheckDetail(Page<ImageCheckDetailVo> page,
+            @Param("query") ImageCheckQuery query);
 
-    List<AssignedCheckExamRoomExport> exportAssignedCheck(@Param("examId")Long examId, @Param("subjectCode")String subjectCode);
+    List<AssignedCheckExamRoomExport> exportAssignedCheck(@Param("examId") Long examId,
+            @Param("subjectCode") String subjectCode);
 }

+ 1 - 1
src/main/java/cn/com/qmth/scancentral/service/MarkSiteService.java

@@ -19,6 +19,6 @@ public interface MarkSiteService extends IService<MarkSiteEntity> {
 
     void delete(Long id);
 
-    List<MarkSiteEntity> findByExam(Long examId);
+    List<MarkSiteEntity> findByExamAndSubject(Long examId, String subejctCode);
 
 }

+ 2 - 0
src/main/java/cn/com/qmth/scancentral/service/StudentService.java

@@ -195,4 +195,6 @@ public interface StudentService extends IService<StudentEntity> {
     List<AssignedCheckExamRoomExport> exportAssignedCheck(Long examId, String subjectCode);
 
     void resetAssignedCheck(Long examId, String subjectCode);
+
+    int countCetMarking(ExportCetMarkingQueryVo query);
 }

+ 4 - 0
src/main/java/cn/com/qmth/scancentral/service/SubjectService.java

@@ -42,4 +42,8 @@ public interface SubjectService extends IMppService<SubjectEntity> {
 
     void answerDataExportDispose(DataExportTaskVo vo);
 
+    TaskIdVo sliceDataExport(Long examId, String subjectCode);
+
+    void sliceDataExportDispose(DataExportTaskVo vo);
+
 }

+ 3 - 2
src/main/java/cn/com/qmth/scancentral/service/impl/DataExportTaskServiceImpl.java

@@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import org.springframework.stereotype.Service;
 
 import cn.com.qmth.scancentral.service.DataExportTaskService;
+import cn.com.qmth.scancentral.util.FileUtil;
 import cn.com.qmth.scancentral.vo.subject.DataExportTaskVo;
 
 @Service
@@ -38,8 +39,8 @@ public class DataExportTaskServiceImpl implements DataExportTaskService {
                 DataExportTaskVo vo = tasks.get(k);
                 if (vo != null) {
                     if (vo.getFilePath() != null) {
-                        File f = new File(vo.getFilePath());
-                        f.delete();
+                        File f = new File(vo.getFilePath()).getParentFile();
+                        FileUtil.deleteDirectory(f);
                     }
                     tasks.remove(k);
                 }

+ 2 - 1
src/main/java/cn/com/qmth/scancentral/service/impl/MarkSiteServiceImpl.java

@@ -88,10 +88,11 @@ public class MarkSiteServiceImpl extends ServiceImpl<MarkSiteDao, MarkSiteEntity
     }
 
     @Override
-    public List<MarkSiteEntity> findByExam(Long examId) {
+    public List<MarkSiteEntity> findByExamAndSubject(Long examId, String subejctCode) {
         QueryWrapper<MarkSiteEntity> wrapper = new QueryWrapper<>();
         LambdaQueryWrapper<MarkSiteEntity> lw = wrapper.lambda();
         lw.eq(MarkSiteEntity::getExamId, examId);
+        lw.eq(MarkSiteEntity::getSubjectCode, subejctCode);
         return this.list(wrapper);
     }
 

+ 10 - 2
src/main/java/cn/com/qmth/scancentral/service/impl/StudentServiceImpl.java

@@ -834,6 +834,14 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> i
         return baseMapper.countByQuery(query);
     }
 
+    @Override
+    public int countCetMarking(ExportCetMarkingQueryVo query) {
+        if (query.getExamId() == null) {
+            throw new ParameterException("examId不能为空");
+        }
+        return baseMapper.countCetMarking(query);
+    }
+
     @Override
     public List<ImportStudentVo> findByQuery(ImportStudentQueryVo query) {
         if (query.getExamId() == null) {
@@ -2585,7 +2593,7 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> i
 
     @Override
     public List<AssignedCheckExamRoomExport> exportAssignedCheck(Long examId, String subjectCode) {
-        return baseMapper.exportAssignedCheck(examId,subjectCode);
+        return baseMapper.exportAssignedCheck(examId, subjectCode);
     }
 
     @Override
@@ -2604,7 +2612,7 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> i
                 student.setAbsentSuspect(false);
                 student.setAssignedCheckCount(1);
                 saveOrUpdate(student);
-//                assignedCheckHistoryService.deleteByStudentId(student.getId(),Role.AUDITOR);
+                // assignedCheckHistoryService.deleteByStudentId(student.getId(),Role.AUDITOR);
             } finally {
                 concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
             }

+ 307 - 84
src/main/java/cn/com/qmth/scancentral/service/impl/SubjectServiceImpl.java

@@ -1,10 +1,13 @@
 package cn.com.qmth.scancentral.service.impl;
 
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -16,7 +19,7 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -27,6 +30,9 @@ import org.springframework.transaction.annotation.Transactional;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
+import com.linuxense.javadbf.DBFDataType;
+import com.linuxense.javadbf.DBFField;
+import com.linuxense.javadbf.DBFWriter;
 import com.qmth.boot.core.exception.ParameterException;
 import com.qmth.boot.core.exception.StatusException;
 import com.qmth.boot.core.fss.store.FileStore;
@@ -36,22 +42,25 @@ import cn.com.qmth.scancentral.bean.ImportSubjectDomain;
 import cn.com.qmth.scancentral.bean.SubjectConfigDomain;
 import cn.com.qmth.scancentral.bean.User;
 import cn.com.qmth.scancentral.consumer.AnswerDataExportConsumer;
+import cn.com.qmth.scancentral.consumer.SliceDataExportConsumer;
 import cn.com.qmth.scancentral.dao.SubjectDao;
+import cn.com.qmth.scancentral.entity.ExamEntity;
 import cn.com.qmth.scancentral.entity.MarkSiteEntity;
 import cn.com.qmth.scancentral.entity.SubjectEntity;
 import cn.com.qmth.scancentral.enums.ExamStatus;
 import cn.com.qmth.scancentral.service.BatchPaperService;
 import cn.com.qmth.scancentral.service.DataExportTaskService;
+import cn.com.qmth.scancentral.service.ExamService;
 import cn.com.qmth.scancentral.service.FileService;
 import cn.com.qmth.scancentral.service.MarkSiteService;
 import cn.com.qmth.scancentral.service.StudentService;
 import cn.com.qmth.scancentral.service.SubjectService;
 import cn.com.qmth.scancentral.support.SpringContextHolder;
 import cn.com.qmth.scancentral.util.Calculator;
+import cn.com.qmth.scancentral.util.DateUtil;
 import cn.com.qmth.scancentral.util.FileUtil;
 import cn.com.qmth.scancentral.vo.ExportCetMarkingQueryVo;
 import cn.com.qmth.scancentral.vo.ExportCetVo;
-import cn.com.qmth.scancentral.vo.ImportStudentQueryVo;
 import cn.com.qmth.scancentral.vo.SubjectConfigVo;
 import cn.com.qmth.scancentral.vo.examinfo.SubjectConfig;
 import cn.com.qmth.scancentral.vo.subject.DataExportTaskVo;
@@ -68,6 +77,9 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
 
     private static ExecutorService exec;
 
+    @Autowired
+    private ExamService examService;
+
     @Autowired
     private StudentService studentService;
 
@@ -292,9 +304,10 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
 
     @Override
     public TaskIdVo answerDataExport(Long examId, String subjectCode) {
-        ImportStudentQueryVo sreq = new ImportStudentQueryVo();
-        sreq.setExamId(examId);
-        int scount = studentService.countByQuery(sreq);
+        ExportCetMarkingQueryVo req = new ExportCetMarkingQueryVo();
+        req.setExamId(examId);
+        req.setSubjectCode(subjectCode);
+        int scount = studentService.countCetMarking(req);
         if (scount == 0) {
             throw new StatusException("没有考生信息");
         }
@@ -304,7 +317,6 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
         vo.setSubjectCode(subjectCode);
         vo.setSuccess(true);
         vo.setProgress(0.0);
-        vo.setFileName("扫描答案.dbf");
         AnswerDataExportConsumer com = SpringContextHolder.getBean(AnswerDataExportConsumer.class);
         com.setVo(vo);
         exec.execute(com);
@@ -312,33 +324,57 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
         return TaskIdVo.create(vo.getTaskId());
     }
 
+    @Override
+    public TaskIdVo sliceDataExport(Long examId, String subjectCode) {
+        ExportCetMarkingQueryVo req = new ExportCetMarkingQueryVo();
+        req.setExamId(examId);
+        req.setSubjectCode(subjectCode);
+        int scount = studentService.countCetMarking(req);
+        if (scount == 0) {
+            throw new StatusException("没有考生信息");
+        }
+        DataExportTaskVo vo = new DataExportTaskVo();
+        vo.setTotalCount(scount);
+        vo.setExamId(examId);
+        vo.setSubjectCode(subjectCode);
+        vo.setSuccess(true);
+        vo.setProgress(0.0);
+        SliceDataExportConsumer com = SpringContextHolder.getBean(SliceDataExportConsumer.class);
+        com.setVo(vo);
+        exec.execute(com);
+        dataExportTaskService.addTask(vo);
+        return TaskIdVo.create(vo.getTaskId());
+    }
+
     @Override
     public void answerDataExportDispose(DataExportTaskVo vo) {
-        File[] files = null;
         try {
             File temDir = new File("temp/" + FastUUID.get() + "/");
             temDir.mkdirs();
+            File dbf = new File(temDir.getAbsolutePath() + "/answer-data.dbf");
+            dbf.createNewFile();
             ExportCetMarkingQueryVo req = new ExportCetMarkingQueryVo();
             req.setExamId(vo.getExamId());
+            req.setSubjectCode(vo.getSubjectCode());
             req.setPageSize(100000);
             int pageNumber = 0;
             req.setPageNumber(pageNumber);
             Set<String> examNumbers = new HashSet<>();
-            Map<String, MarkSiteEntity> cms = readCetMarking(vo.getExamId());
+            Map<String, MarkSiteEntity> cms = readCetMarking(vo.getExamId(), vo.getSubjectCode());
+            Map<String, String> breachMap = breachMap(vo.getExamId(), vo.getSubjectCode());
+            Map<String, String> custStatusMap = custStatusMap(vo.getExamId(), vo.getSubjectCode());
             while (true) {
                 req.setPageNumber(++pageNumber);
                 List<ExportCetVo> list = studentService.exportCetData(req);
                 if (CollectionUtils.isEmpty(list)) {
                     break;
                 }
-                exportAnswer(examNumbers, temDir, list, cms, vo);
-            }
-            files = temDir.listFiles();
-            if (files.length > 0) {
-                File zip = new File(temDir.getAbsolutePath() + "/answer-data.zip");
-                FileUtil.dozip(zip, files);
-                vo.setFilePath(zip.getAbsolutePath());
+                exportAnswer(examNumbers, breachMap, custStatusMap, dbf, list, cms, vo);
             }
+            ExamEntity exam = examService.getById(vo.getExamId());
+            SubjectEntity subejct = this.findByExamIdAndCode(vo.getExamId(), vo.getSubjectCode());
+            vo.setFileName(subejct.getName() + "_" + exam.getScanSite() + "_OMR.dbf");
+            vo.setFilePath(dbf.getAbsolutePath());
         } catch (StatusException e) {
             vo.setSuccess(false);
             vo.setErrMsg(e.getMessage());
@@ -346,53 +382,263 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
             vo.setSuccess(false);
             vo.setErrMsg("系统异常");
             log.error("导出扫描答案DBF异常", e);
+        }
+    }
+
+    private void exportAnswer(Set<String> examNumbers, Map<String, String> breachMap, Map<String, String> custStatusMap,
+            File dbf, List<ExportCetVo> list, Map<String, MarkSiteEntity> cms, DataExportTaskVo vo)
+            throws FileNotFoundException {
+        FileOutputStream fos = null;
+        DBFWriter writer = null;
+        try {
+            DBFField fields[] = new DBFField[11];
+
+            fields[0] = new DBFField();
+            fields[0].setName("Zkzh");
+            fields[0].setType(DBFDataType.CHARACTER);
+            fields[0].setLength(15);
+
+            fields[1] = new DBFField();
+            fields[1].setName("Xm");
+            fields[1].setType(DBFDataType.CHARACTER);
+            fields[1].setLength(30);
+
+            fields[2] = new DBFField();
+            fields[2].setName("Qk");
+            fields[2].setType(DBFDataType.NUMERIC);
+            fields[2].setLength(4);
+
+            fields[3] = new DBFField();
+            fields[3].setName("Km_h");
+            fields[3].setType(DBFDataType.NUMERIC);
+            fields[3].setLength(4);
+
+            fields[4] = new DBFField();
+            fields[4].setName("Smda");
+            fields[4].setType(DBFDataType.CHARACTER);
+            fields[4].setLength(100);
+
+            fields[5] = new DBFField();
+            fields[5].setName("Yc1");
+            fields[5].setType(DBFDataType.NUMERIC);
+            fields[5].setLength(4);
+
+            fields[6] = new DBFField();
+            fields[6].setName("Yc2");
+            fields[6].setType(DBFDataType.NUMERIC);
+            fields[6].setLength(4);
+
+            fields[7] = new DBFField();
+            fields[7].setName("Wi");
+            fields[7].setType(DBFDataType.NUMERIC);
+            fields[7].setLength(2);
+
+            fields[8] = new DBFField();
+            fields[8].setName("Barcode");
+            fields[8].setType(DBFDataType.CHARACTER);
+            fields[8].setLength(6);
+
+            fields[9] = new DBFField();
+            fields[9].setName("Pjd");
+            fields[9].setType(DBFDataType.CHARACTER);
+            fields[9].setLength(2);
+
+            fields[10] = new DBFField();
+            fields[10].setName("Kszt");
+            fields[10].setType(DBFDataType.CHARACTER);
+            fields[10].setLength(2);
+
+            fos = new FileOutputStream(dbf);
+            writer = new DBFWriter(fos, Charset.defaultCharset());
+            writer.setFields(fields);
+            for (ExportCetVo data : list) {
+                if (examNumbers.contains(data.getExamNumber())) {
+                    continue;
+                }
+                vo.setProgressCount(vo.getProgressCount() + 1);
+                examNumbers.add(data.getExamNumber());
+                Object[] rowData = new Object[11];
+                rowData[0] = data.getExamNumber();
+                rowData[1] = data.getName();
+                if (ExamStatus.ABSENT.equals(data.getExamStatus())) {
+                    rowData[2] = 1;
+                } else {
+                    rowData[2] = 0;
+                }
+                rowData[3] = getIntFromString(data.getSubjectCode());
+                rowData[4] = data.getAnswer();
+                rowData[5] = data.getCardFirst();
+                rowData[6] = data.getCardSecond();
+                String breach = breachMap.get(data.getExamNumber());
+                rowData[7] = StringUtils.isBlank(breach) ? 0 : getIntFromString(breach);
+                rowData[8] = data.getPaperType();
+                int subjectCode = Integer.valueOf(data.getExamNumber().substring(9, 10));
+                String markingCode;
+                if (subjectCode >= 3 && subjectCode <= 9) {
+                    markingCode = "88";
+                } else {
+                    if (ExamStatus.ABSENT.equals(data.getExamStatus()) || "000000".equals(data.getPaperType())
+                            || "999999".equals(data.getPaperType())) {
+                        markingCode = "00";
+                    } else {
+                        int site = Integer.valueOf(data.getExamNumber().substring(10, 13));
+                        MarkSiteEntity cm = cms.get(data.getSubjectCode() + "-" + data.getPaperType());
+                        if (cm == null) {
+                            throw new StatusException("未找到评卷点数据,SubjectCode:" + data.getSubjectCode() + " PaperType:"
+                                    + data.getPaperType());
+                        }
+                        if (site % 2 == 0) {
+                            markingCode = cm.getEvenNumber();
+                        } else {
+                            markingCode = cm.getOddNumber();
+                        }
+                    }
+                }
+                rowData[9] = markingCode;
+                String custStatus = custStatusMap.get(data.getExamNumber());
+                rowData[10] = StringUtils.isBlank(custStatus) ? "0" : custStatus;
+                writer.addRecord(rowData);
+            }
         } finally {
-            if (files != null && files.length > 0) {
-                for (File file : files) {
-                    FileUtil.deleteDirectory(file);
+            if (writer != null) {
+                writer.close();
+            }
+            try {
+                if (fos != null) {
+                    fos.close();
                 }
+            } catch (IOException e) {
             }
         }
     }
 
-    private void exportAnswer(Set<String> examNumbers, File temDir, List<ExportCetVo> list,
-            Map<String, MarkSiteEntity> cms, DataExportTaskVo vo) {
-        Map<String, List<String>> subjects = new HashMap<>();
-        for (ExportCetVo data : list) {
-            String key = data.getSubjectCode() + "-" + data.getExamNumber();
-            if (examNumbers.contains(key)) {
-                continue;
+    private Map<String, String> breachMap(Long examId, String subjectCode) throws Exception {
+        Map<String, String> ret = new HashMap<>();
+        String path = fileService.getBreachUri(examId, subjectCode);
+        if (fileStore.exist(path)) {
+            List<String> list = IOUtils.readLines(fileStore.read(path), "utf-8");
+            if (CollectionUtils.isNotEmpty(list)) {
+                for (int i = 1; i < list.size(); i++) {
+                    String[] ss = list.get(i).split(",");
+                    ret.put(ss[0].trim(), ss[2].trim());
+                }
             }
-            vo.setProgressCount(vo.getProgressCount() + 1);
-            examNumbers.add(key);
-            List<String> line = new ArrayList<>();
-            line.add(data.getExamNumber());
-            line.add(data.getName());
-            if (ExamStatus.ABSENT.equals(data.getExamStatus())) {
-                line.add("1");
-            } else {
-                line.add("0");
+        }
+        return ret;
+    }
+
+    private Map<String, String> custStatusMap(Long examId, String subjectCode) throws Exception {
+        Map<String, String> ret = new HashMap<>();
+        String path = fileService.getCustStatusUri(examId, subjectCode);
+        if (fileStore.exist(path)) {
+            List<String> list = IOUtils.readLines(fileStore.read(path), "utf-8");
+            if (CollectionUtils.isNotEmpty(list)) {
+                for (int i = 1; i < list.size(); i++) {
+                    String[] ss = list.get(i).split(",");
+                    ret.put(ss[0].trim(), ss[2].trim());
+                }
             }
-            line.add(data.getSubjectCode());
-            line.add(data.getAnswer());
-            line.add(data.getCardFirst() + "");
-            line.add(data.getCardSecond() + "");
-            line.add(StringUtils.isBlank(data.getBreachCode()) ? "0" : data.getBreachCode());
-            line.add(data.getPaperType());
-            int subjectCode = Integer.valueOf(data.getExamNumber().substring(9, 10));
-            String markingCode;
-            if (subjectCode >= 3 && subjectCode <= 9) {
-                markingCode = "88";
-            } else {
-                if (ExamStatus.ABSENT.equals(data.getExamStatus()) || "000000".equals(data.getPaperType())
+        }
+        return ret;
+    }
+
+    private Integer getIntFromString(String v) {
+        if (v == null) {
+            return null;
+        }
+        return Integer.valueOf(v);
+    }
+
+    private Map<String, MarkSiteEntity> readCetMarking(Long examId, String subejctCode) {
+        Map<String, MarkSiteEntity> ret = new HashMap<>();
+        List<MarkSiteEntity> list = markSiteService.findByExamAndSubject(examId, subejctCode);
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (MarkSiteEntity e : list) {
+                ret.put(e.getPaperType(), e);
+            }
+        }
+        return ret;
+    }
+
+    @Override
+    public void sliceDataExportDispose(DataExportTaskVo vo) {
+        try {
+            File temDir = new File("temp/" + FastUUID.get() + "/");
+            temDir.mkdirs();
+            File dbf = new File(temDir.getAbsolutePath() + "/slice-data.dbf");
+            dbf.createNewFile();
+            ExportCetMarkingQueryVo req = new ExportCetMarkingQueryVo();
+            req.setExamId(vo.getExamId());
+            req.setSubjectCode(vo.getSubjectCode());
+            req.setPageSize(100000);
+            int pageNumber = 0;
+            req.setPageNumber(pageNumber);
+            Set<String> examNumbers = new HashSet<>();
+            Map<String, MarkSiteEntity> cms = readCetMarking(vo.getExamId(), vo.getSubjectCode());
+            while (true) {
+                req.setPageNumber(++pageNumber);
+                List<ExportCetVo> list = studentService.exportCetData(req);
+                if (CollectionUtils.isEmpty(list)) {
+                    break;
+                }
+                exportSlice(examNumbers, dbf, list, cms, vo);
+            }
+            ExamEntity exam = examService.getById(vo.getExamId());
+            vo.setFileName(exam.getScanSite() + "_" + vo.getTotalCount() + "_"
+                    + DateUtil.format(new Date(), DateUtil.DatePatterns.YYYYMMDDHH) + ".dbf");
+            vo.setFilePath(dbf.getAbsolutePath());
+        } catch (StatusException e) {
+            vo.setSuccess(false);
+            vo.setErrMsg(e.getMessage());
+        } catch (Exception e) {
+            vo.setSuccess(false);
+            vo.setErrMsg("系统异常");
+            log.error("导出打包DBF异常", e);
+        }
+    }
+
+    private void exportSlice(Set<String> examNumbers, File dbf, List<ExportCetVo> list, Map<String, MarkSiteEntity> cms,
+            DataExportTaskVo vo) throws FileNotFoundException {
+        FileOutputStream fos = null;
+        DBFWriter writer = null;
+        try {
+            DBFField fields[] = new DBFField[3];
+
+            fields[0] = new DBFField();
+            fields[0].setName("Zkzh");
+            fields[0].setType(DBFDataType.CHARACTER);
+            fields[0].setLength(15);
+
+            fields[1] = new DBFField();
+            fields[1].setName("Xm");
+            fields[1].setType(DBFDataType.CHARACTER);
+            fields[1].setLength(2);
+
+            fields[2] = new DBFField();
+            fields[2].setName("Qk");
+            fields[2].setType(DBFDataType.CHARACTER);
+            fields[2].setLength(254);
+
+            fos = new FileOutputStream(dbf);
+            writer = new DBFWriter(fos, Charset.defaultCharset());
+            writer.setFields(fields);
+            for (ExportCetVo data : list) {
+                if (examNumbers.contains(data.getExamNumber())) {
+                    continue;
+                }
+                vo.setProgressCount(vo.getProgressCount() + 1);
+                examNumbers.add(data.getExamNumber());
+                String markingCode;
+                if ("888888".equals(data.getPaperType())) {
+                    markingCode = "88";
+                } else if (ExamStatus.ABSENT.equals(data.getExamStatus()) || "000000".equals(data.getPaperType())
                         || "999999".equals(data.getPaperType())) {
                     markingCode = "00";
                 } else {
                     int site = Integer.valueOf(data.getExamNumber().substring(10, 13));
-                    MarkSiteEntity cm = cms.get(data.getSubjectCode() + "-" + data.getPaperType());
+                    MarkSiteEntity cm = cms.get(data.getPaperType());
                     if (cm == null) {
-                        throw new StatusException(
-                                "未找到评卷点数据,SubjectCode:" + data.getSubjectCode() + " PaperType:" + data.getPaperType());
+                        throw new StatusException("未找到考点数据,PaperType:" + data.getPaperType());
                     }
                     if (site % 2 == 0) {
                         markingCode = cm.getEvenNumber();
@@ -400,45 +646,22 @@ public class SubjectServiceImpl extends MppServiceImpl<SubjectDao, SubjectEntity
                         markingCode = cm.getOddNumber();
                     }
                 }
+                Object[] rowData = new Object[3];
+                rowData[0] = data.getExamNumber();
+                rowData[1] = markingCode;
+                rowData[2] = StringUtils.join(data.getSliceImageInfo(), ";");
+                writer.addRecord(rowData);
             }
-            line.add(markingCode);
-            List<String> lines = subjects.get(data.getSubjectCode());
-            if (lines == null) {
-                lines = new ArrayList<>();
-                subjects.put(data.getSubjectCode(), lines);
-            }
-            lines.add(StringUtils.join(line, ","));
-        }
-        writeResult(subjects, temDir, "answer-data.txt");
-    }
-
-    private void writeResult(Map<String, List<String>> subjects, File rootDir, String fileName) {
-        for (String k : subjects.keySet()) {
-            File file = new File(rootDir.getAbsolutePath() + "/" + k + "/" + fileName);
-            file.getParentFile().mkdirs();
-            if (!file.exists()) {
-                try {
-                    file.createNewFile();
-                } catch (IOException e) {
-                    throw new StatusException("", e);
-                }
+        } finally {
+            if (writer != null) {
+                writer.close();
             }
             try {
-                FileUtils.writeLines(file, StandardCharsets.UTF_8.name(), subjects.get(k), true);
+                if (fos != null) {
+                    fos.close();
+                }
             } catch (IOException e) {
-                throw new StatusException("文件处理出错", e);
-            }
-        }
-    }
-
-    private Map<String, MarkSiteEntity> readCetMarking(Long examId) {
-        Map<String, MarkSiteEntity> ret = new HashMap<>();
-        List<MarkSiteEntity> list = markSiteService.findByExam(examId);
-        if (CollectionUtils.isNotEmpty(list)) {
-            for (MarkSiteEntity e : list) {
-                ret.put(e.getSubjectCode() + "-" + e.getPaperType(), e);
             }
         }
-        return ret;
     }
 }

+ 11 - 0
src/main/java/cn/com/qmth/scancentral/util/Calculator.java

@@ -242,4 +242,15 @@ public class Calculator {
     public static String percentage(double v1, double v2) {
         return percentage(v1, v2, null);
     }
+
+    public static Double percentageDouble(Integer v1, Integer v2) {
+        if (v1 == null || v2 == null || v2 == 0) {
+            return null;
+        }
+        BigDecimal b1 = BigDecimal.valueOf(v1);
+        BigDecimal b2 = BigDecimal.valueOf(v2);
+        BigDecimal b3 = BigDecimal.valueOf(100);
+        return b1.multiply(b3).divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+    }
 }

+ 10 - 0
src/main/java/cn/com/qmth/scancentral/vo/ExportCetMarkingQueryVo.java

@@ -6,6 +6,8 @@ public class ExportCetMarkingQueryVo extends PagerQuery {
 
     private Long examId;
 
+    private String subjectCode;
+
     public Long getExamId() {
         return examId;
     }
@@ -14,4 +16,12 @@ public class ExportCetMarkingQueryVo extends PagerQuery {
         this.examId = examId;
     }
 
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
 }

+ 14 - 0
src/main/resources/mapper/StudentMapper.xml

@@ -276,10 +276,24 @@
         select t.*
         from sc_student t
         where t.exam_id = #{query.examId}
+        <if test="query.subjectCode != null and query.subjectCode !=''">
+            and t.subject_code=#{query.subjectCode}
+        </if>
           and t.status = 'SCANNED'
           and t.file_upload_status = 'UPLOADED'
         order by t.id
     </select>
+    
+    <select id="countCetMarking" resultType="int">
+        select count(1)
+        from sc_student t
+        where t.exam_id = #{query.examId}
+        <if test="query.subjectCode != null and query.subjectCode !=''">
+            and t.subject_code=#{query.subjectCode}
+        </if>
+        and t.status = 'SCANNED'
+        and t.file_upload_status = 'UPLOADED'
+    </select>
 
     <select id="getInfoCountByExam" resultType="cn.com.qmth.scancentral.vo.ScanAnswerInfoVo">
         select count(1)                                               as totalCount,