浏览代码

答题卡扫描结果保存

xiatian 1 年之前
父节点
当前提交
a40ececdf9
共有 16 个文件被更改,包括 505 次插入17 次删除
  1. 9 0
      distributed-print/src/main/java/com/qmth/distributed/print/api/mark/ScanAnswerBatchController.java
  2. 60 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerDomain.java
  3. 77 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerPage.java
  4. 82 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerPaper.java
  5. 32 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerSaveVo.java
  6. 17 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/entity/ScanStudentPaper.java
  7. 9 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/ScanBatchMapper.java
  8. 4 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkStudentService.java
  9. 6 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanBatchPaperService.java
  10. 10 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanBatchService.java
  11. 5 2
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanStudentPaperService.java
  12. 16 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkStudentServiceImpl.java
  13. 30 2
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanBatchPaperServiceImpl.java
  14. 118 10
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanBatchServiceImpl.java
  15. 10 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanStudentPaperServiceImpl.java
  16. 20 1
      teachcloud-mark/src/main/resources/mapper/ScanBatchMapper.xml

+ 9 - 0
distributed-print/src/main/java/com/qmth/distributed/print/api/mark/ScanAnswerBatchController.java

@@ -16,6 +16,8 @@ import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.BasicExam;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.util.ServletUtil;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerDomain;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerSaveVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateDomain;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchFinishVo;
@@ -59,4 +61,11 @@ public class ScanAnswerBatchController {
     public BatchFinishVo batchFinish(@RequestParam Long id) {
         return scanBatchService.batchFinish(id);
     }
+    
+    @ApiOperation(value = "答题卡扫描结果保存")
+    @RequestMapping(value = "save", method = RequestMethod.POST)
+    public AnswerSaveVo batchSave(@Validated @RequestBody AnswerDomain domain) {
+    	SysUser user = (SysUser) ServletUtil.getRequestUser();
+        return scanBatchService.batchSave(domain, user);
+    }
 }

+ 60 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerDomain.java

@@ -0,0 +1,60 @@
+package com.qmth.teachcloud.mark.bean.answerbatch;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+public class AnswerDomain {
+
+    @NotNull(message = "batchId不能为空")
+    private Long batchId;
+
+    @NotBlank(message = "studentCode不能为空")
+    private String studentCode;
+
+    @NotNull(message = "cardNumber不能为空")
+    @Min(value = 1, message = "cardNumber不能小于1")
+    private Integer cardNumber;
+
+    @Valid
+    @NotNull(message = "papers不能为空")
+    @Size(min = 1, message = "papers不能为空")
+    private List<AnswerPaper> papers;
+
+    public Long getBatchId() {
+        return batchId;
+    }
+
+    public void setBatchId(Long batchId) {
+        this.batchId = batchId;
+    }
+
+
+    public String getStudentCode() {
+		return studentCode;
+	}
+
+	public void setStudentCode(String studentCode) {
+		this.studentCode = studentCode;
+	}
+
+	public Integer getCardNumber() {
+        return cardNumber;
+    }
+
+    public void setCardNumber(Integer cardNumber) {
+        this.cardNumber = cardNumber;
+    }
+
+    public List<AnswerPaper> getPapers() {
+        return papers;
+    }
+
+    public void setPapers(List<AnswerPaper> papers) {
+        this.papers = papers;
+    }
+
+}

+ 77 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerPage.java

@@ -0,0 +1,77 @@
+package com.qmth.teachcloud.mark.bean.answerbatch;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+import com.qmth.teachcloud.mark.bean.ArrayResult;
+import com.qmth.teachcloud.mark.bean.BoolResult;
+
+public class AnswerPage {
+
+    @NotNull(message = "paper.page.index不能为空")
+    @Min(value = 1, message = "paper.page.index不能小于1")
+    private Integer index;
+
+    @NotBlank(message = "paper.page.sheetUri不能为空")
+    private String sheetUri;
+
+    private BoolResult absent;
+
+    private BoolResult breach;
+
+    private ArrayResult question;
+
+    private String recogData;
+
+    public Integer getIndex() {
+        return index;
+    }
+
+    public void setIndex(Integer index) {
+        this.index = index;
+    }
+
+    public BoolResult getAbsent() {
+        return absent;
+    }
+
+    public void setAbsent(BoolResult absent) {
+        this.absent = absent;
+    }
+
+    public BoolResult getBreach() {
+        return breach;
+    }
+
+    public void setBreach(BoolResult breach) {
+        this.breach = breach;
+    }
+
+
+    public ArrayResult getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(ArrayResult question) {
+        this.question = question;
+    }
+
+
+    public String getSheetUri() {
+        return sheetUri;
+    }
+
+    public void setSheetUri(String sheetUri) {
+        this.sheetUri = sheetUri;
+    }
+
+    public String getRecogData() {
+        return recogData;
+    }
+
+    public void setRecogData(String recogData) {
+        this.recogData = recogData;
+    }
+
+}

+ 82 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerPaper.java

@@ -0,0 +1,82 @@
+package com.qmth.teachcloud.mark.bean.answerbatch;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import com.qmth.boot.core.exception.ParameterException;
+import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
+import com.qmth.teachcloud.mark.entity.ScanPaperPage;
+
+public class AnswerPaper {
+
+    @NotNull(message = "paper.number不能为空")
+    @Min(value = 1, message = "paper.number不能小于1")
+    private Integer number;
+
+    @NotNull(message = "paper.assigned不能为空")
+    private Boolean assigned;
+
+    @Valid
+    @NotNull(message = "paper.pages不能为空")
+    @Size(min = 1, message = "paper.pages不能为空")
+    private List<AnswerPage> pages;
+
+    public Integer getNumber() {
+        return number;
+    }
+
+    public void setNumber(Integer number) {
+        this.number = number;
+    }
+
+    public Boolean getAssigned() {
+        return assigned;
+    }
+
+    public void setAssigned(Boolean assigned) {
+        this.assigned = assigned;
+    }
+
+    public List<AnswerPage> getPages() {
+        return pages;
+    }
+
+    public void setPages(List<AnswerPage> pages) {
+        this.pages = pages;
+    }
+
+    /**
+     * 根据卡格式定义验证页数
+     *
+     * @param answerCard
+     */
+    public void answerCardValidate(ScanAnswerCard answerCard) {
+        if (answerCard.getSinglePage() && getPages().size() != 1) {
+            throw new ParameterException("卡格式页数不一致");
+        }
+        if (!answerCard.getSinglePage() && getPages().size() != 2) {
+            throw new ParameterException("卡格式页数不一致");
+        }
+    }
+
+    public List<ScanPaperPage> buildPageList() {
+        List<ScanPaperPage> list = new ArrayList<>();
+        for (AnswerPage answerPage : pages) {
+        	ScanPaperPage page = new ScanPaperPage();
+            page.setPageIndex(answerPage.getIndex());
+            page.setSheetPath(answerPage.getSheetUri());
+            page.setAbsent(answerPage.getAbsent());
+            page.setBreach(answerPage.getBreach());
+            page.setQuestion(answerPage.getQuestion());
+            page.setRecogData(answerPage.getRecogData());
+            list.add(page);
+        }
+        return list;
+    }
+
+}

+ 32 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/answerbatch/AnswerSaveVo.java

@@ -0,0 +1,32 @@
+package com.qmth.teachcloud.mark.bean.answerbatch;
+
+public class AnswerSaveVo {
+
+    private Integer scanCount;
+
+    private Long updateTime;
+
+    public static AnswerSaveVo create(Integer scanCount) {
+        AnswerSaveVo vo = new AnswerSaveVo();
+        vo.setScanCount(scanCount);
+        vo.setUpdateTime(System.currentTimeMillis());
+        return vo;
+    }
+
+    public Integer getScanCount() {
+        return scanCount;
+    }
+
+    public void setScanCount(Integer scanCount) {
+        this.scanCount = scanCount;
+    }
+
+    public Long getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Long updateTime) {
+        this.updateTime = updateTime;
+    }
+
+}

+ 17 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/entity/ScanStudentPaper.java

@@ -36,7 +36,23 @@ public class ScanStudentPaper implements Serializable {
 
     private Long updateTime;
 
-    public Long getStudentId() {
+    
+    
+    public ScanStudentPaper(Long studentId, Integer paperIndex, Long paperId) {
+		super();
+		this.studentId = studentId;
+		this.paperIndex = paperIndex;
+		this.paperId = paperId;
+	}
+
+
+	public ScanStudentPaper() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+
+    
+	public Long getStudentId() {
         return studentId;
     }
 

+ 9 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/ScanBatchMapper.java

@@ -1,6 +1,9 @@
 package com.qmth.teachcloud.mark.mapper;
 
 import com.qmth.teachcloud.mark.entity.ScanBatch;
+
+import org.apache.ibatis.annotations.Param;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
@@ -13,4 +16,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface ScanBatchMapper extends BaseMapper<ScanBatch> {
 
+	void updateAssignedCount(@Param("id") Long id);
+
+	void updateScanCount(@Param("id") Long id);
+
+	Integer findStudentCountByBatch(@Param("batchId")Long batchId);
+
 }

+ 4 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkStudentService.java

@@ -7,6 +7,7 @@ import javax.validation.constraints.NotNull;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.teachcloud.common.entity.BasicExam;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamCheckInfoVo;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamInfoVo;
@@ -14,6 +15,7 @@ import com.qmth.teachcloud.mark.dto.mark.score.SheetUrlDto;
 import com.qmth.teachcloud.mark.dto.mark.score.StudentObjectiveDetailDto;
 import com.qmth.teachcloud.mark.dto.mark.score.StudentScoreDetailDto;
 import com.qmth.teachcloud.mark.entity.MarkStudent;
+import com.qmth.teachcloud.mark.entity.ScanStudentPaper;
 
 /**
  * <p>
@@ -58,4 +60,6 @@ public interface MarkStudentService extends IService<MarkStudent> {
     List<MarkStudent> listUnMarkTaskStudent(Long examId, String paperNumber, Integer groupNumber, int pageSize);
 
     boolean saveUploadStudent(MarkStudent student);
+
+	void updateStudentAndPaper(SysUser user, Long studentId, List<ScanStudentPaper> studentPaperList);
 }

+ 6 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanBatchPaperService.java

@@ -1,6 +1,8 @@
 package com.qmth.teachcloud.mark.service;
 
+import com.qmth.teachcloud.mark.entity.ScanBatch;
 import com.qmth.teachcloud.mark.entity.ScanBatchPaper;
+import com.qmth.teachcloud.mark.entity.ScanPaper;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 /**
@@ -13,4 +15,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface ScanBatchPaperService extends IService<ScanBatchPaper> {
 
+	ScanBatchPaper findByBatchIdAndStudentIdAndPaperNumber(Long batchId, Long studentId, Integer paperIndex);
+
+	void update(ScanBatch batch, ScanPaper paper, Long studentId, Integer paperNumber);
+
 }

+ 10 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanBatchService.java

@@ -1,6 +1,8 @@
 package com.qmth.teachcloud.mark.service;
 
 import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerDomain;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerSaveVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateDomain;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchFinishVo;
@@ -21,4 +23,12 @@ public interface ScanBatchService extends IService<ScanBatch> {
 
 	BatchFinishVo batchFinish(Long id);
 
+	AnswerSaveVo batchSave(AnswerDomain domain, SysUser user);
+
+	void updateAssignedCount(Long id);
+
+	void updateScanCount(Long id);
+
+	Integer findStudentCountByBatch(Long batchId);
+
 }

+ 5 - 2
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanStudentPaperService.java

@@ -1,10 +1,11 @@
 package com.qmth.teachcloud.mark.service;
 
-import com.qmth.teachcloud.mark.entity.ScanStudentPaper;
-
 import java.util.List;
 
+import javax.validation.constraints.NotNull;
+
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.mark.entity.ScanStudentPaper;
 
 /**
  * <p>
@@ -20,4 +21,6 @@ public interface ScanStudentPaperService extends IService<ScanStudentPaper> {
 
 	ScanStudentPaper findByPaperId(Long paperId);
 
+	void removeByStudentId(@NotNull Long studentId);
+
 }

+ 16 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkStudentServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.core.exception.ParameterException;
 import com.qmth.teachcloud.common.entity.BasicExam;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.enums.ScanStatus;
 import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
@@ -403,4 +404,19 @@ public class MarkStudentServiceImpl extends ServiceImpl<MarkStudentMapper, MarkS
         student.setObjectiveScore(info.getObjectiveScore());
         student.setScoreList(info.getScoreList(), true);
     }
+    
+    @Override
+    @Transactional
+    public void updateStudentAndPaper(@NotNull SysUser user, @NotNull Long id,
+            @NotNull List<ScanStudentPaper> studentPaperList) {
+        for (ScanStudentPaper studentPaper : studentPaperList) {
+            studentPaper.setStudentId(id);
+        }
+        // 清空原有绑定关系
+        studentPaperService.removeByStudentId(id);
+        // 保存绑定关系
+        studentPaperService.saveOrUpdateBatch(studentPaperList);
+        // 更新考生状态
+        updateStudentByPaper(user.getId(), id, true);
+    }
 }

+ 30 - 2
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanBatchPaperServiceImpl.java

@@ -1,10 +1,16 @@
 package com.qmth.teachcloud.mark.service.impl;
 
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.mark.entity.ScanBatch;
 import com.qmth.teachcloud.mark.entity.ScanBatchPaper;
+import com.qmth.teachcloud.mark.entity.ScanPaper;
 import com.qmth.teachcloud.mark.mapper.ScanBatchPaperMapper;
 import com.qmth.teachcloud.mark.service.ScanBatchPaperService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
 
 /**
  * <p>
@@ -17,4 +23,26 @@ import org.springframework.stereotype.Service;
 @Service
 public class ScanBatchPaperServiceImpl extends ServiceImpl<ScanBatchPaperMapper, ScanBatchPaper> implements ScanBatchPaperService {
 
+    @Override
+    public ScanBatchPaper findByBatchIdAndStudentIdAndPaperNumber(Long batchId, Long studentId, Integer paperIndex) {
+        QueryWrapper<ScanBatchPaper> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<ScanBatchPaper> lw = wrapper.lambda();
+        lw.eq(ScanBatchPaper::getBatchId, batchId);
+        lw.eq(ScanBatchPaper::getStudentId, studentId);
+        lw.eq(ScanBatchPaper::getPaperIndex, paperIndex);
+        return baseMapper.selectOne(wrapper);
+    }
+    
+    @Override
+    @Transactional
+    public void update(ScanBatch batch, ScanPaper paper, Long studentId, Integer paperNumber) {
+    	ScanBatchPaper batchPaperEntity = new ScanBatchPaper();
+        batchPaperEntity.setBatchId(batch.getId());
+        batchPaperEntity.setStudentId(studentId);
+        batchPaperEntity.setPaperIndex(paperNumber);
+        batchPaperEntity.setPaperId(paper.getId());
+        batchPaperEntity.setCardNumber(paper.getCardNumber());
+        batchPaperEntity.setAssigned(paper.getAssigned());
+        saveOrUpdate(batchPaperEntity);
+    }
 }

+ 118 - 10
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanBatchServiceImpl.java

@@ -4,13 +4,18 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.boot.core.concurrent.service.ConcurrentService;
 import com.qmth.boot.core.exception.ParameterException;
 import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerDomain;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerPaper;
+import com.qmth.teachcloud.mark.bean.answerbatch.AnswerSaveVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateDomain;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchCreateVo;
 import com.qmth.teachcloud.mark.bean.answerbatch.BatchFinishVo;
@@ -18,11 +23,18 @@ import com.qmth.teachcloud.mark.bean.answerbatch.Paper;
 import com.qmth.teachcloud.mark.bean.answerbatch.Rescan;
 import com.qmth.teachcloud.mark.bean.scanpaper.PaperVo;
 import com.qmth.teachcloud.mark.entity.MarkStudent;
+import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
 import com.qmth.teachcloud.mark.entity.ScanBatch;
+import com.qmth.teachcloud.mark.entity.ScanBatchPaper;
+import com.qmth.teachcloud.mark.entity.ScanPaper;
 import com.qmth.teachcloud.mark.entity.ScanPaperPage;
+import com.qmth.teachcloud.mark.entity.ScanStudentPaper;
 import com.qmth.teachcloud.mark.enums.BatchStatus;
+import com.qmth.teachcloud.mark.enums.LockType;
 import com.qmth.teachcloud.mark.mapper.ScanBatchMapper;
 import com.qmth.teachcloud.mark.service.MarkStudentService;
+import com.qmth.teachcloud.mark.service.ScanAnswerCardService;
+import com.qmth.teachcloud.mark.service.ScanBatchPaperService;
 import com.qmth.teachcloud.mark.service.ScanBatchService;
 import com.qmth.teachcloud.mark.service.ScanPaperPageService;
 import com.qmth.teachcloud.mark.service.ScanPaperService;
@@ -38,6 +50,8 @@ import com.qmth.teachcloud.mark.service.ScanPaperService;
 @Service
 public class ScanBatchServiceImpl extends ServiceImpl<ScanBatchMapper, ScanBatch> implements ScanBatchService {
 
+    @Autowired
+    private ConcurrentService concurrentService;
 	@Autowired
 	private MarkStudentService markStudentService;
 	
@@ -46,6 +60,12 @@ public class ScanBatchServiceImpl extends ServiceImpl<ScanBatchMapper, ScanBatch
 	
 	@Autowired
 	private ScanPaperPageService scanPaperPageService;
+	
+	@Autowired
+	private ScanBatchPaperService scanBatchPaperService;
+	
+	@Autowired
+	private ScanAnswerCardService scanAnswerCardService;
 
 	@Transactional
 	@Override
@@ -115,19 +135,107 @@ public class ScanBatchServiceImpl extends ServiceImpl<ScanBatchMapper, ScanBatch
 	@Transactional
 	@Override
 	public BatchFinishVo batchFinish(Long id) {
-		ScanBatch entity = this.getById(id);
-        if (entity == null) {
-            throw new ParameterException("批次不存在");
-        }
-        if (BatchStatus.FINISH.equals(entity.getStatus())) {
-            throw new ParameterException("批次已经完成");
-        }
-		entity.setStatus(BatchStatus.FINISH);
-        this.saveOrUpdate(entity);
+		ScanBatch batch = checkBatchStatus(getById(id));
+		batch.setStatus(BatchStatus.FINISH);
+        this.saveOrUpdate(batch);
         BatchFinishVo vo = new BatchFinishVo();
-        vo.setStatus(entity.getStatus());
+        vo.setStatus(batch.getStatus());
         vo.setUpdateTime(System.currentTimeMillis());
         return vo;
 	}
 
+	@Transactional
+	@Override
+	public AnswerSaveVo batchSave(AnswerDomain domain, SysUser user) {
+		ScanBatch batch = checkBatchStatus(getById(domain.getBatchId()));
+        String studentCode = domain.getStudentCode();
+        MarkStudent student = markStudentService.findByExamIdAndCoursePaperIdAndStudentCode(batch.getExamId(),
+        		batch.getCoursePaperId(), studentCode);
+		if (student == null) {
+			throw new ParameterException("未找到考生信息:" + studentCode);
+		}
+		ScanAnswerCard answerCard = scanAnswerCardService.findByExamAndNumber(batch.getExamId(), domain.getCardNumber());
+        if (answerCard == null) {
+            throw new ParameterException("卡格式信息未找到");
+        }
+        if (!StringUtils.equals(batch.getPackageCode(), student.getPackageCode())) {
+            throw new ParameterException("与批次卷袋号不一致");
+        }
+        boolean studentAssigned = false;
+        List<ScanStudentPaper> studentPaperList = new ArrayList<>();
+        for (AnswerPaper answerPaper : domain.getPapers()) {
+            // 验证page数量
+            answerPaper.answerCardValidate(answerCard);
+            Integer paperNumber = answerPaper.getNumber();
+            ScanPaper paper = findOrCreatePaper(batch, student, paperNumber, user);
+            // 设置paper属性
+            paper.setExamId(batch.getExamId());
+            paper.setCardNumber(answerCard.getNumber());
+            paper.setNumber(paperNumber);
+            paper.setMismatch(false);
+            paper.setQuestionFilled(false);
+            paper.setAssigned(answerPaper.getAssigned());
+            // 保存paper与page到数据库
+            scanPaperService.savePaperAndPages(paper, answerPaper.buildPageList());
+            // 记录paper与batch关联关系
+            scanBatchPaperService.update(batch, paper, student.getId(), paperNumber);
+            // 创建student与paper的关联关系
+            studentPaperList.add(new ScanStudentPaper(student.getId(), paperNumber, paper.getId()));
+            studentAssigned = studentAssigned || paper.getAssigned();
+        }
+        // 更新批次统计数量
+        updateAssignedCount(batch.getId());
+        updateScanCount(batch.getId());
+        // 没有人工绑定的情况下,直接更新考生扫描状态
+        if (!studentAssigned) {
+            concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
+            try {
+            	markStudentService.updateStudentAndPaper(user, student.getId(), studentPaperList);
+            } finally {
+                concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
+            }
+        }
+        return AnswerSaveVo.create(findStudentCountByBatch(batch.getId()));
+	}
+	
+    @Override
+    public Integer findStudentCountByBatch(Long batchId) {
+        return baseMapper.findStudentCountByBatch(batchId);
+    }
+    
+    @Transactional
+    @Override
+    public void updateAssignedCount(Long id) {
+        baseMapper.updateAssignedCount(id);
+    }
+    @Transactional
+    @Override
+    public void updateScanCount(Long id) {
+        baseMapper.updateScanCount(id);
+    }
+    private ScanPaper findOrCreatePaper(ScanBatch batch, MarkStudent student, Integer paperNumber, SysUser user) {
+    	ScanPaper paper = null;
+        // 尝试重用已有paper对象
+    	ScanBatchPaper batchPaper = scanBatchPaperService
+                .findByBatchIdAndStudentIdAndPaperNumber(batch.getId(), student.getId(), paperNumber);
+        if (batchPaper != null) {
+            paper = scanPaperService.getById(batchPaper.getPaperId());
+        }
+        // 构造全新paper对象
+        if (paper == null) {
+            paper = new ScanPaper();
+            paper.setCreateTime(System.currentTimeMillis());
+            paper.setCreatorId(user.getId());
+        }
+        return paper;
+    }
+    private ScanBatch checkBatchStatus(ScanBatch b) {
+        if (b == null) {
+            throw new ParameterException("批次未找到");
+        }
+        if (BatchStatus.FINISH.equals(b.getStatus())) {
+            throw new ParameterException("批次已经完成");
+        }
+        return b;
+    }
 }

+ 10 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanStudentPaperServiceImpl.java

@@ -3,6 +3,7 @@ package com.qmth.teachcloud.mark.service.impl;
 import java.util.List;
 
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -39,5 +40,13 @@ public class ScanStudentPaperServiceImpl extends ServiceImpl<ScanStudentPaperMap
 		lw.eq(ScanStudentPaper::getPaperId, paperId);
 		return baseMapper.selectOne(wrapper);
 	}
-
+	
+    @Transactional
+    @Override
+    public void removeByStudentId(Long studentId) {
+        QueryWrapper<ScanStudentPaper> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<ScanStudentPaper> lw = wrapper.lambda();
+        lw.eq(ScanStudentPaper::getStudentId, studentId);
+        this.baseMapper.delete(wrapper);
+    }
 }

+ 20 - 1
teachcloud-mark/src/main/resources/mapper/ScanBatchMapper.xml

@@ -17,5 +17,24 @@
         <result column="update_time" property="updateTime" />
         <result column="course_paper_id" property="coursePaperId" />
     </resultMap>
-
+	<update id="updateAssignedCount">
+		UPDATE scan_batch t
+		SET t.assigned_count = (select count(distinct bp.student_id)
+		from scan_batch_paper bp
+		where bp.batch_id = #{id}
+		and bp.assigned = 1)
+		WHERE t.id = #{id}
+	</update>
+	<update id="updateScanCount">
+		UPDATE scan_batch t
+		SET t.scan_count =
+		(select count(distinct bp.student_id) from scan_batch_paper bp where
+		bp.batch_id = #{id})
+		where t.id = #{id}
+	</update>
+	<select id="findStudentCountByBatch" resultType="int">
+		SELECT count(distinct bp.student_id)
+		FROM scan_batch_paper bp
+		WHERE bp.batch_id = #{batchId}
+	</select>
 </mapper>