xiatian 2 سال پیش
والد
کامیت
a6efa53b4e

+ 1 - 0
db/init.sql

@@ -70,6 +70,7 @@ CREATE TABLE `mps_paper` (
   `course_id` bigint NOT NULL,
   `exam_id` bigint NOT NULL,
   `group_finish` bit(1) NOT NULL,
+  `struct_finish` bit(1) NOT NULL,
   `objective_score` double NOT NULL,
   `paper_type` varchar(255) COLLATE utf8_bin DEFAULT NULL,
   `school_id` bigint NOT NULL,

+ 27 - 11
src/main/java/cn/com/qmth/mps/controller/PaperController.java

@@ -20,10 +20,13 @@ import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.boot.core.collection.PageResult;
 
 import cn.com.qmth.mps.bean.ImportMsg;
-import cn.com.qmth.mps.bean.PaperGroup;
+import cn.com.qmth.mps.service.PaperDetailService;
+import cn.com.qmth.mps.service.PaperGroupService;
 import cn.com.qmth.mps.service.PaperService;
 import cn.com.qmth.mps.util.ResouceUtil;
+import cn.com.qmth.mps.vo.paper.GroupInfoVo;
 import cn.com.qmth.mps.vo.paper.GroupVo;
+import cn.com.qmth.mps.vo.paper.PaperGroupDomain;
 import cn.com.qmth.mps.vo.paper.PaperInfoVo;
 import cn.com.qmth.mps.vo.paper.PaperQuery;
 import cn.com.qmth.mps.vo.paper.PaperVo;
@@ -39,6 +42,12 @@ public class PaperController extends BaseController {
 
 	@Autowired
 	private PaperService paperService;
+	
+	@Autowired
+	private PaperGroupService paperGroupService;
+	
+	@Autowired
+	private PaperDetailService paperDetailService;
 
 	@PostMapping("import-course")
 	@ApiOperation(value = "导入科目")
@@ -91,36 +100,43 @@ public class PaperController extends BaseController {
 
 	@ApiOperation(value = "获取信息")
 	@RequestMapping(value = "info", method = RequestMethod.POST)
-	public PaperInfoVo info(@RequestParam Long id) {
-		return paperService.info(id, getAccessUser());
+	public PaperInfoVo info(@RequestParam Long paperId) {
+		return paperService.info(paperId, getAccessUser());
 	}
 
 	@ApiOperation(value = "试卷结构提交")
 	@RequestMapping(value = "struct/submit ", method = RequestMethod.POST)
-	public PaperVo structSubmit(@RequestBody StructDomain domain) {
-		return null;
+	public void structSubmit(@RequestBody StructDomain domain) {
+		paperDetailService.structSubmit(domain,getAccessUser());
 	}
 
 	@ApiOperation(value = "试卷结构暂存")
 	@RequestMapping(value = "struct/save ", method = RequestMethod.POST)
-	public PaperVo structSave(@RequestBody StructDomain domain) {
-		return null;
+	public void structSave(@RequestBody StructDomain domain) {
+		paperDetailService.structSave(domain,getAccessUser());
 	}
 
 	@ApiOperation(value = "获取分组列表")
 	@RequestMapping(value = "group/list", method = RequestMethod.POST)
 	public List<GroupVo> groupList(@RequestParam Long paperId) {
-		return null;
+		return paperGroupService.groupList(paperId,getAccessUser());
 	}
 
 	@ApiOperation(value = "获取分组信息")
 	@RequestMapping(value = "group/info", method = RequestMethod.POST)
-	public GroupVo groupInfo(@RequestParam Long paperId, @RequestParam Integer groupNumber) {
-		return null;
+	public GroupInfoVo groupInfo(@RequestParam Long paperId, @RequestParam Integer groupNumber) {
+		return paperGroupService.groupInfo(paperId,groupNumber,getAccessUser());
 	}
 
 	@ApiOperation(value = "保存分组信息")
 	@RequestMapping(value = "group/save", method = RequestMethod.POST)
-	public void groupInfo(@RequestBody PaperGroup domain) {
+	public void groupSave(@RequestBody PaperGroupDomain domain) {
+		paperGroupService.groupSave(domain,getAccessUser());
+	}
+	
+	@ApiOperation(value = "删除分组信息")
+	@RequestMapping(value = "group/delete", method = RequestMethod.POST)
+	public void groupDelete(@RequestParam Long paperId, @RequestParam Integer groupNumber) {
+		paperGroupService.groupDelete(paperId,groupNumber,getAccessUser());
 	}
 }

+ 9 - 0
src/main/java/cn/com/qmth/mps/entity/PaperEntity.java

@@ -20,6 +20,7 @@ public class PaperEntity extends AuditingEntity {
 	
 	private String paperType;
 	
+	private Boolean structFinish;
 	private Boolean groupFinish;
 
 	public Long getSchoolId() {
@@ -87,6 +88,14 @@ public class PaperEntity extends AuditingEntity {
 		this.groupFinish = groupFinish;
 	}
 
+	public Boolean getStructFinish() {
+		return structFinish;
+	}
+
+	public void setStructFinish(Boolean structFinish) {
+		this.structFinish = structFinish;
+	}
+
 	
 	
 }

+ 9 - 1
src/main/java/cn/com/qmth/mps/service/PaperDetailService.java

@@ -5,11 +5,19 @@ import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import cn.com.qmth.mps.bean.PaperDetail;
+import cn.com.qmth.mps.bean.User;
 import cn.com.qmth.mps.entity.PaperDetailEntity;
+import cn.com.qmth.mps.vo.paper.StructDomain;
 
 public interface PaperDetailService  extends IService<PaperDetailEntity> {
 
-	List<PaperDetail> getStructInfo(Long id);
+	List<PaperDetail> getStructInfo(Long paperId);
+
+	List<PaperDetailEntity> getByPaperId(Long paperId);
+
+	void structSave(StructDomain domain, User accessUser);
+
+	void structSubmit(StructDomain domain, User accessUser);
 
 
 

+ 7 - 0
src/main/java/cn/com/qmth/mps/service/PaperDetailUnitService.java

@@ -6,11 +6,18 @@ import java.util.Map;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import cn.com.qmth.mps.bean.PaperDetailUnit;
+import cn.com.qmth.mps.entity.PaperDetailEntity;
 import cn.com.qmth.mps.entity.PaperDetailUnitEntity;
 
 public interface PaperDetailUnitService  extends IService<PaperDetailUnitEntity> {
 
 	Map<Long, List<PaperDetailUnit>> getStructInfo(Long paperId);
 
+	Integer countByPaperId(Long paperId);
+
+	void clearByPaperId(Long paperId);
+
+	void saveUnit(PaperDetailEntity e, List<PaperDetailUnit> units);
+
 
 }

+ 14 - 0
src/main/java/cn/com/qmth/mps/service/PaperGroupService.java

@@ -7,8 +7,12 @@ import org.apache.ibatis.annotations.Param;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import cn.com.qmth.mps.bean.PaperGroup;
+import cn.com.qmth.mps.bean.User;
 import cn.com.qmth.mps.entity.PaperGroupEntity;
 import cn.com.qmth.mps.vo.paper.GroupCountVo;
+import cn.com.qmth.mps.vo.paper.GroupInfoVo;
+import cn.com.qmth.mps.vo.paper.GroupVo;
+import cn.com.qmth.mps.vo.paper.PaperGroupDomain;
 
 public interface PaperGroupService  extends IService<PaperGroupEntity> {
 
@@ -16,4 +20,14 @@ public interface PaperGroupService  extends IService<PaperGroupEntity> {
 
 	List<PaperGroup> getGroupInfo(Long paperId);
 
+	List<GroupVo> groupList(Long paperId, User accessUser);
+
+	GroupInfoVo groupInfo(Long paperId, Integer groupNumber, User accessUser);
+
+	void groupSave(PaperGroupDomain domain, User accessUser);
+
+	void groupDelete(Long paperId, Integer groupNumber, User accessUser);
+
+	Boolean existsGroup(Long paperId);
+
 }

+ 8 - 0
src/main/java/cn/com/qmth/mps/service/PaperGroupUnitService.java

@@ -6,9 +6,17 @@ import java.util.Map;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import cn.com.qmth.mps.bean.PaperGroupUnit;
+import cn.com.qmth.mps.entity.PaperGroupEntity;
 import cn.com.qmth.mps.entity.PaperGroupUnitEntity;
 
 public interface PaperGroupUnitService  extends IService<PaperGroupUnitEntity> {
 
 	Map<Long, List<PaperGroupUnit>> getGroupInfo(Long paperId);
+
+	void removeByPaperIdAndGroup(Long paperId, Long groupId);
+
+	void saveUnit(PaperGroupEntity group, List<PaperGroupUnit> groupUnits);
+
+	Integer countByPaperId(Long paperId);
+
 }

+ 177 - 1
src/main/java/cn/com/qmth/mps/service/impl/PaperDetailServiceImpl.java

@@ -6,25 +6,40 @@ import java.util.List;
 import java.util.Map;
 
 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.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.boot.core.exception.StatusException;
 
 import cn.com.qmth.mps.bean.PaperDetail;
 import cn.com.qmth.mps.bean.PaperDetailUnit;
+import cn.com.qmth.mps.bean.User;
 import cn.com.qmth.mps.dao.PaperDetailDao;
 import cn.com.qmth.mps.entity.PaperDetailEntity;
+import cn.com.qmth.mps.entity.PaperEntity;
+import cn.com.qmth.mps.enums.Role;
 import cn.com.qmth.mps.service.PaperDetailService;
 import cn.com.qmth.mps.service.PaperDetailUnitService;
+import cn.com.qmth.mps.service.PaperGroupService;
+import cn.com.qmth.mps.service.PaperService;
+import cn.com.qmth.mps.util.Calculator;
+import cn.com.qmth.mps.vo.paper.StructDomain;
 
 @Service
 public class PaperDetailServiceImpl extends ServiceImpl<PaperDetailDao, PaperDetailEntity>
 		implements PaperDetailService {
+	@Autowired
+	private PaperGroupService paperGroupService;
+	
 	@Autowired
 	private PaperDetailUnitService paperDetailUnitService;
+	@Autowired
+	private PaperService paperService;
 
 	@Override
 	public List<PaperDetail> getStructInfo(Long paperId) {
@@ -51,10 +66,171 @@ public class PaperDetailServiceImpl extends ServiceImpl<PaperDetailDao, PaperDet
 		return ret;
 	}
 
-	private List<PaperDetailEntity> getByPaperId(Long paperId) {
+	@Override
+	public List<PaperDetailEntity> getByPaperId(Long paperId) {
 		QueryWrapper<PaperDetailEntity> wrapper = new QueryWrapper<>();
 		LambdaQueryWrapper<PaperDetailEntity> lw = wrapper.lambda();
 		lw.eq(PaperDetailEntity::getPaperId, paperId);
 		return this.list(wrapper);
 	}
+
+	@Transactional
+	@Override
+	public void structSave(StructDomain domain, User user) {
+		if (domain.getPaperId() == null) {
+			throw new StatusException("试卷结构ID不能为空");
+		}
+		if (domain.getTotalScore() == null) {
+			throw new StatusException("试卷满分不能为空");
+		}
+		if (domain.getTotalScore()<=0) {
+			throw new StatusException("试卷满分必须大于0");
+		}
+		String total=domain.getTotalScore().toString();
+		if (total.indexOf(".")<total.length()-2) {
+			throw new StatusException("试卷满分只能有一位小数");
+		}
+		if (CollectionUtils.isEmpty(domain.getStructInfo())) {
+			throw new StatusException("大题信息不能为空");
+		}
+		for (PaperDetail u : domain.getStructInfo()) {
+			if (u.getNumber() == null || StringUtils.isBlank(u.getName())) {
+				throw new StatusException("大题号、大题名称不能为空");
+			}
+			if (CollectionUtils.isEmpty(u.getUnits())) {
+				throw new StatusException("小题信息不能为空");
+			}
+			for (PaperDetailUnit unit : u.getUnits()) {
+				if (unit.getNumber()== null ||unit.getScore()==null||unit.getScoreStep()==null) {
+					throw new StatusException("小题号、小题满分、给分间隔不能为空");
+				}
+				if (unit.getNumber()<=0) {
+					throw new StatusException("小题号必须大于0");
+				}
+				String score=unit.getScore().toString();
+				if (score.indexOf(".")<score.length()-2) {
+					throw new StatusException("小题满分只能有一位小数");
+				}
+				String scoreStep=unit.getScoreStep().toString();
+				if (scoreStep.indexOf(".")<scoreStep.length()-2) {
+					throw new StatusException("给分间隔只能有一位小数");
+				}
+			}
+		}
+		PaperEntity paper = paperService.getById(domain.getPaperId());
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		if (paper.getStructFinish()) {
+			throw new StatusException("试卷结构已提交,不能暂存");
+		}
+		clearPaperSruct(domain.getPaperId());
+		paper.setTotalScore(domain.getTotalScore());
+		paper.setSubjectiveScore(domain.getTotalScore());
+		paperService.updateById(paper);
+		for(PaperDetail pd:domain.getStructInfo()) {
+			PaperDetailEntity e=new PaperDetailEntity();
+			e.setName(pd.getName());
+			e.setNumber(pd.getNumber());
+			e.setPaperId(domain.getPaperId());
+			this.save(e);
+			paperDetailUnitService.saveUnit(e,pd.getUnits());
+		}
+	}
+	
+	private void clearPaperSruct(Long paperId) {
+		clearByPaperId(paperId);
+		paperDetailUnitService.clearByPaperId(paperId);
+	}
+	
+	private void clearByPaperId(Long paperId) {
+		QueryWrapper<PaperDetailEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperDetailEntity> lw = wrapper.lambda();
+		lw.eq(PaperDetailEntity::getPaperId, paperId);
+		this.remove(wrapper);
+	}
+	
+	@Transactional
+	@Override
+	public void structSubmit(StructDomain domain, User user) {
+		if (domain.getPaperId() == null) {
+			throw new StatusException("试卷结构ID不能为空");
+		}
+		if (domain.getTotalScore() == null) {
+			throw new StatusException("试卷满分不能为空");
+		}
+		if (domain.getTotalScore()<=0) {
+			throw new StatusException("试卷满分必须大于0");
+		}
+		String total=domain.getTotalScore().toString();
+		if (total.indexOf(".")<total.length()-2) {
+			throw new StatusException("试卷满分只能有一位小数");
+		}
+		if (CollectionUtils.isEmpty(domain.getStructInfo())) {
+			throw new StatusException("大题信息不能为空");
+		}
+		for (PaperDetail u : domain.getStructInfo()) {
+			if (u.getNumber() == null || StringUtils.isBlank(u.getName())) {
+				throw new StatusException("大题号、大题名称不能为空");
+			}
+			if (CollectionUtils.isEmpty(u.getUnits())) {
+				throw new StatusException("小题信息不能为空");
+			}
+			for (PaperDetailUnit unit : u.getUnits()) {
+				if (unit.getNumber()== null ||unit.getScore()==null||unit.getScoreStep()==null) {
+					throw new StatusException("小题号、小题满分、给分间隔不能为空");
+				}
+				if (unit.getNumber()<=0) {
+					throw new StatusException("小题号必须大于0");
+				}
+				String score=unit.getScore().toString();
+				if (score.indexOf(".")<score.length()-2) {
+					throw new StatusException("小题满分只能有一位小数");
+				}
+				String scoreStep=unit.getScoreStep().toString();
+				if (scoreStep.indexOf(".")<scoreStep.length()-2) {
+					throw new StatusException("给分间隔只能有一位小数");
+				}
+			}
+		}
+		checkTotalScore(domain);
+		PaperEntity paper = paperService.getById(domain.getPaperId());
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		if (paperGroupService.existsGroup(domain.getPaperId())) {
+			throw new StatusException("请先删除分组信息再提交试卷结构");
+		}
+		clearPaperSruct(domain.getPaperId());
+		paper.setTotalScore(domain.getTotalScore());
+		paper.setSubjectiveScore(domain.getTotalScore());
+		paper.setStructFinish(true);
+		paperService.updateById(paper);
+		for(PaperDetail pd:domain.getStructInfo()) {
+			PaperDetailEntity e=new PaperDetailEntity();
+			e.setName(pd.getName());
+			e.setNumber(pd.getNumber());
+			e.setPaperId(domain.getPaperId());
+			this.save(e);
+			paperDetailUnitService.saveUnit(e,pd.getUnits());
+		}
+	}
+	
+	public void checkTotalScore(StructDomain domain) {
+		double total=0.0;
+		for(PaperDetail detial:domain.getStructInfo()) {
+			for(PaperDetailUnit unit:detial.getUnits()) {
+				total=Calculator.add(total, unit.getScore(),1);
+			}
+		}
+		if(total!=domain.getTotalScore()) {
+			throw new StatusException("试卷满分与小题分不一致");
+		}
+	}
 }

+ 48 - 9
src/main/java/cn/com/qmth/mps/service/impl/PaperDetailUnitServiceImpl.java

@@ -7,6 +7,7 @@ import java.util.Map;
 
 import org.apache.commons.collections4.CollectionUtils;
 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;
@@ -14,26 +15,28 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import cn.com.qmth.mps.bean.PaperDetailUnit;
 import cn.com.qmth.mps.dao.PaperDetailUnitDao;
+import cn.com.qmth.mps.entity.PaperDetailEntity;
 import cn.com.qmth.mps.entity.PaperDetailUnitEntity;
 import cn.com.qmth.mps.service.PaperDetailUnitService;
 
 @Service
-public class PaperDetailUnitServiceImpl extends ServiceImpl<PaperDetailUnitDao, PaperDetailUnitEntity> implements PaperDetailUnitService {
+public class PaperDetailUnitServiceImpl extends ServiceImpl<PaperDetailUnitDao, PaperDetailUnitEntity>
+		implements PaperDetailUnitService {
 
 	@Override
 	public Map<Long, List<PaperDetailUnit>> getStructInfo(Long paperId) {
-		List<PaperDetailUnitEntity> list=getStructUnitInfo(paperId);
-		if(CollectionUtils.isEmpty(list)) {
+		List<PaperDetailUnitEntity> list = getStructUnitInfo(paperId);
+		if (CollectionUtils.isEmpty(list)) {
 			return null;
 		}
-		Map<Long, List<PaperDetailUnit>> ret=new HashMap<>();
-		for(PaperDetailUnitEntity e:list) {
-			List<PaperDetailUnit> tem=ret.get(e.getDetailId());
-			if(tem==null) {
-				tem=new ArrayList<>();
+		Map<Long, List<PaperDetailUnit>> ret = new HashMap<>();
+		for (PaperDetailUnitEntity e : list) {
+			List<PaperDetailUnit> tem = ret.get(e.getDetailId());
+			if (tem == null) {
+				tem = new ArrayList<>();
 				ret.put(e.getDetailId(), tem);
 			}
-			PaperDetailUnit vo=new PaperDetailUnit();
+			PaperDetailUnit vo = new PaperDetailUnit();
 			vo.setNumber(e.getNumber());
 			vo.setScore(vo.getScore());
 			vo.setScoreStep(e.getScoreStep());
@@ -49,4 +52,40 @@ public class PaperDetailUnitServiceImpl extends ServiceImpl<PaperDetailUnitDao,
 		lw.orderByAsc(PaperDetailUnitEntity::getNumber);
 		return this.list(wrapper);
 	}
+
+	@Override
+	public Integer countByPaperId(Long paperId) {
+		QueryWrapper<PaperDetailUnitEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperDetailUnitEntity> lw = wrapper.lambda();
+		lw.eq(PaperDetailUnitEntity::getPaperId, paperId);
+		return this.count(wrapper);
+	}
+
+	@Transactional
+	@Override
+	public void clearByPaperId(Long paperId) {
+		QueryWrapper<PaperDetailUnitEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperDetailUnitEntity> lw = wrapper.lambda();
+		lw.eq(PaperDetailUnitEntity::getPaperId, paperId);
+		this.remove(wrapper);
+
+	}
+
+	@Transactional
+	@Override
+	public void saveUnit(PaperDetailEntity detail, List<PaperDetailUnit> units) {
+		List<PaperDetailUnitEntity> ret=new ArrayList<>();
+		for(PaperDetailUnit u:units) {
+			PaperDetailUnitEntity e=new PaperDetailUnitEntity();
+			e.setDetailId(detail.getId());
+			e.setDetailNumber(detail.getNumber());
+			e.setObjective(false);
+			e.setNumber(u.getNumber());
+			e.setScore(u.getScore());
+			e.setScoreStep(u.getScoreStep());
+			e.setPaperId(detail.getPaperId());
+			ret.add(e);
+		}
+		this.saveBatch(ret);
+	}
 }

+ 200 - 6
src/main/java/cn/com/qmth/mps/service/impl/PaperGroupServiceImpl.java

@@ -2,29 +2,52 @@ package cn.com.qmth.mps.service.impl;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 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.boot.core.exception.StatusException;
 
+import cn.com.qmth.mps.bean.PaperDetail;
+import cn.com.qmth.mps.bean.PaperDetailUnit;
 import cn.com.qmth.mps.bean.PaperGroup;
 import cn.com.qmth.mps.bean.PaperGroupUnit;
+import cn.com.qmth.mps.bean.User;
 import cn.com.qmth.mps.dao.PaperGroupDao;
+import cn.com.qmth.mps.entity.PaperDetailEntity;
+import cn.com.qmth.mps.entity.PaperEntity;
 import cn.com.qmth.mps.entity.PaperGroupEntity;
+import cn.com.qmth.mps.enums.Role;
+import cn.com.qmth.mps.service.PaperDetailService;
+import cn.com.qmth.mps.service.PaperDetailUnitService;
 import cn.com.qmth.mps.service.PaperGroupService;
 import cn.com.qmth.mps.service.PaperGroupUnitService;
+import cn.com.qmth.mps.service.PaperService;
 import cn.com.qmth.mps.vo.paper.GroupCountVo;
+import cn.com.qmth.mps.vo.paper.GroupInfoVo;
+import cn.com.qmth.mps.vo.paper.GroupVo;
+import cn.com.qmth.mps.vo.paper.PaperGroupDomain;
 
 @Service
 public class PaperGroupServiceImpl extends ServiceImpl<PaperGroupDao, PaperGroupEntity> implements PaperGroupService {
 	@Autowired
 	private PaperGroupUnitService paperGroupUnitService;
+	@Autowired
+	private PaperService paperService;
+	@Autowired
+	private PaperDetailService paperDetailService;
+	@Autowired
+	private PaperDetailUnitService paperDetailUnitService;
+
 	@Override
 	public List<GroupCountVo> findGroupCount(List<Long> paperIds) {
 		return this.baseMapper.findGroupCount(paperIds);
@@ -37,22 +60,23 @@ public class PaperGroupServiceImpl extends ServiceImpl<PaperGroupDao, PaperGroup
 		if (CollectionUtils.isEmpty(es)) {
 			return ret;
 		}
-		Map<Long,PaperGroup> map=new HashMap<>();
-		for(PaperGroupEntity e:es) {
-			PaperGroup vo=new PaperGroup();
+		Map<Long, PaperGroup> map = new HashMap<>();
+		for (PaperGroupEntity e : es) {
+			PaperGroup vo = new PaperGroup();
 			vo.setNumber(e.getNumber());
 			map.put(e.getId(), vo);
 			ret.add(vo);
 		}
-		Map<Long,List<PaperGroupUnit>> units=paperGroupUnitService.getGroupInfo(paperId);
-		if (units==null||units.size()==0) {
+		Map<Long, List<PaperGroupUnit>> units = paperGroupUnitService.getGroupInfo(paperId);
+		if (units == null || units.size() == 0) {
 			return ret;
 		}
-		for(Long key:units.keySet()) {
+		for (Long key : units.keySet()) {
 			map.get(key).setGroupUnits(units.get(key));
 		}
 		return ret;
 	}
+
 	private List<PaperGroupEntity> getByPaperId(Long paperId) {
 		QueryWrapper<PaperGroupEntity> wrapper = new QueryWrapper<>();
 		LambdaQueryWrapper<PaperGroupEntity> lw = wrapper.lambda();
@@ -60,4 +84,174 @@ public class PaperGroupServiceImpl extends ServiceImpl<PaperGroupDao, PaperGroup
 		return this.list(wrapper);
 	}
 
+	@Override
+	public List<GroupVo> groupList(Long paperId, User user) {
+		PaperEntity paper = paperService.getById(paperId);
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		List<GroupVo> ret = new ArrayList<>();
+		List<PaperGroupEntity> es = getByPaperId(paperId);
+		if (CollectionUtils.isEmpty(es)) {
+			return ret;
+		}
+		Map<Long, GroupVo> map = new HashMap<>();
+		for (PaperGroupEntity e : es) {
+			GroupVo vo = new GroupVo();
+			vo.setNumber(e.getNumber());
+			vo.setGroupId(e.getId());
+			map.put(e.getId(), vo);
+			ret.add(vo);
+		}
+		Map<Long, List<PaperGroupUnit>> units = paperGroupUnitService.getGroupInfo(paperId);
+		List<PaperDetailEntity> des = paperDetailService.getByPaperId(paperId);
+		Map<Integer, PaperDetailEntity> detailMap = new HashMap<>();
+		for (PaperDetailEntity de : des) {
+			detailMap.put(de.getNumber(), de);
+		}
+		for (GroupVo vo : ret) {
+			List<PaperGroupUnit> unit = units.get(vo.getGroupId());
+			if (CollectionUtils.isNotEmpty(unit)) {
+				Set<Integer> set = new LinkedHashSet<>();
+				for (PaperGroupUnit u : unit) {
+					set.add(u.getDeatailNumber());
+				}
+				StringBuilder numSb = new StringBuilder();
+				StringBuilder nameSb = new StringBuilder();
+				for (Integer num : set) {
+					numSb.append(num).append(",");
+					nameSb.append(detailMap.get(num)).append(",");
+				}
+				vo.setDetailNumbers(numSb.substring(0, numSb.length() - 1));
+				vo.setDetailNames(nameSb.substring(0, nameSb.length() - 1));
+			}
+		}
+		return ret;
+	}
+
+	@Override
+	public GroupInfoVo groupInfo(Long paperId, Integer groupNumber, User user) {
+		PaperEntity paper = paperService.getById(paperId);
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		PaperGroupEntity e = this.getByPaperIdAndNumber(paperId, groupNumber);
+		if (e == null) {
+			return null;
+		}
+		GroupInfoVo vo = new GroupInfoVo();
+		vo.setNumber(e.getNumber());
+		Map<Long, List<PaperGroupUnit>> units = paperGroupUnitService.getGroupInfo(paperId);
+		vo.setGroupUnit(units.get(e.getId()));
+		return vo;
+	}
+
+	private PaperGroupEntity getByPaperIdAndNumber(Long paperId, Integer groupNumber) {
+		QueryWrapper<PaperGroupEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperGroupEntity> lw = wrapper.lambda();
+		lw.eq(PaperGroupEntity::getPaperId, paperId);
+		lw.eq(PaperGroupEntity::getNumber, groupNumber);
+		return this.getOne(wrapper);
+	}
+
+	@Transactional
+	@Override
+	public void groupSave(PaperGroupDomain domain, User user) {
+
+		if (domain.getPaperId() == null) {
+			throw new StatusException("试卷结构ID不能为空");
+		}
+		if (domain.getNumber() == null) {
+			throw new StatusException("分组号不能为空");
+		}
+		if (CollectionUtils.isEmpty(domain.getGroupUnits())) {
+			throw new StatusException("分组信息不能为空");
+		}
+		for (PaperGroupUnit u : domain.getGroupUnits()) {
+			if (u.getDeatailNumber() == null || u.getDetailUnitNumber() == null) {
+				throw new StatusException("大题号、小题号不能为空");
+			}
+		}
+		PaperEntity paper = paperService.getById(domain.getPaperId());
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		if (!paper.getStructFinish()) {
+			throw new StatusException("试卷结构未提交,不能设置分组");
+		}
+		groupDelete(domain.getPaperId(), domain.getNumber(), user);
+		PaperGroupEntity g = new PaperGroupEntity();
+		g.setNumber(domain.getNumber());
+		g.setPaperId(domain.getPaperId());
+		this.save(g);
+		List<PaperDetail> pds = paperDetailService.getStructInfo(domain.getPaperId());
+		if (CollectionUtils.isEmpty(pds)) {
+			throw new StatusException("试卷结构小题信息为空");
+		}
+		checkStruct(pds, domain.getGroupUnits());
+		paperGroupUnitService.saveUnit(g, domain.getGroupUnits());
+		if (paperGroupUnitService.countByPaperId(domain.getPaperId())
+				.equals(paperDetailUnitService.countByPaperId(domain.getPaperId()))) {
+			paper.setGroupFinish(true);
+			paperService.updateById(paper);
+		}
+	}
+
+	private void checkStruct(List<PaperDetail> pds, List<PaperGroupUnit> groupUnits) {
+		for (PaperGroupUnit groupUnit : groupUnits) {
+			checkStructExists(pds, groupUnit);
+		}
+	}
+
+	private void checkStructExists(List<PaperDetail> pds, PaperGroupUnit groupUnit) {
+		for (PaperDetail pd : pds) {
+			if (pd.getNumber().equals(groupUnit.getDeatailNumber())) {
+				for (PaperDetailUnit u : pd.getUnits()) {
+					if (u.getNumber().equals(groupUnit.getDetailUnitNumber())) {
+						return;
+					}
+				}
+			}
+		}
+		throw new StatusException(
+				"试卷结构中大题号:" + groupUnit.getDeatailNumber() + " 小题号:" + groupUnit.getDetailUnitNumber() + "不存在");
+	}
+
+	@Transactional
+	@Override
+	public void groupDelete(Long paperId, Integer groupNumber, User user) {
+		PaperEntity paper = paperService.getById(paperId);
+		if (paper == null) {
+			throw new StatusException("未找到试卷结构");
+		}
+		if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
+			throw new StatusException("没有权限");
+		}
+		PaperGroupEntity old = getByPaperIdAndNumber(paperId, groupNumber);
+		if (old == null) {
+			throw new StatusException("未找到分组信息");
+		}
+		this.removeById(old.getId());
+		paperGroupUnitService.removeByPaperIdAndGroup(paperId, old.getId());
+		paper.setGroupFinish(false);
+		paperService.updateById(paper);
+	}
+
+	@Override
+	public Boolean existsGroup(Long paperId) {
+		QueryWrapper<PaperGroupEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperGroupEntity> lw = wrapper.lambda();
+		lw.eq(PaperGroupEntity::getPaperId, paperId);
+		return this.count(wrapper)>0;
+	}
+
 }

+ 33 - 1
src/main/java/cn/com/qmth/mps/service/impl/PaperGroupUnitServiceImpl.java

@@ -7,6 +7,7 @@ import java.util.Map;
 
 import org.apache.commons.collections4.CollectionUtils;
 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;
@@ -14,6 +15,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import cn.com.qmth.mps.bean.PaperGroupUnit;
 import cn.com.qmth.mps.dao.PaperGroupUnitDao;
+import cn.com.qmth.mps.entity.PaperGroupEntity;
 import cn.com.qmth.mps.entity.PaperGroupUnitEntity;
 import cn.com.qmth.mps.service.PaperGroupUnitService;
 
@@ -47,5 +49,35 @@ public class PaperGroupUnitServiceImpl extends ServiceImpl<PaperGroupUnitDao, Pa
 		lw.orderByAsc(PaperGroupUnitEntity::getDetailUnitNumber);
 		return this.list(wrapper);
 	}
-
+	@Transactional
+	@Override
+	public void removeByPaperIdAndGroup(Long paperId, Long groupId) {
+		QueryWrapper<PaperGroupUnitEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperGroupUnitEntity> lw = wrapper.lambda();
+		lw.eq(PaperGroupUnitEntity::getPaperId, paperId);
+		lw.eq(PaperGroupUnitEntity::getGroupId, groupId);
+		this.remove(wrapper);
+	}
+	@Transactional
+	@Override
+	public void saveUnit(PaperGroupEntity group, List<PaperGroupUnit> groupUnits) {
+		List<PaperGroupUnitEntity> ret=new ArrayList<>();
+		for(PaperGroupUnit unit:groupUnits) {
+			PaperGroupUnitEntity e=new PaperGroupUnitEntity();
+			e.setPaperId(group.getPaperId());
+			e.setGroupId(group.getId());
+			e.setDetailNumber(unit.getDeatailNumber());
+			e.setDetailUnitNumber(unit.getDetailUnitNumber());
+			ret.add(e);
+		}
+		this.saveBatch(ret);
+	}
+	
+	@Override
+	public Integer countByPaperId(Long paperId) {
+		QueryWrapper<PaperGroupUnitEntity> wrapper = new QueryWrapper<>();
+		LambdaQueryWrapper<PaperGroupUnitEntity> lw = wrapper.lambda();
+		lw.eq(PaperGroupUnitEntity::getPaperId, paperId);
+		return this.count(wrapper);
+	}
 }

+ 63 - 0
src/main/java/cn/com/qmth/mps/util/Calculator.java

@@ -0,0 +1,63 @@
+package cn.com.qmth.mps.util;
+
+import java.math.BigDecimal;
+
+/**
+ * 计算器
+ *
+ * @author 
+ * @date 2019年7月30日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class Calculator {
+
+	public static double add(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.add(b2).doubleValue();
+
+	}
+	public static double add(double v1, double v2,int len) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.add(b2).setScale(len, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+	}
+
+	/**减法
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double subtract(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.subtract(b2).doubleValue();
+
+	}
+
+	/**乘法
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double multiply(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(v1);
+		BigDecimal b2 = new BigDecimal(v2);
+		return b1.multiply(b2).doubleValue();
+
+	}
+
+	/**除法
+	 * @param v1
+	 * @param v2
+	 * @param len
+	 * @return
+	 */
+	public static double divide(double v1, double v2, int len) {
+		BigDecimal b1 = new BigDecimal(v1);
+		BigDecimal b2 = new BigDecimal(v2);
+		return b1.divide(b2, len, BigDecimal.ROUND_HALF_UP).doubleValue();
+	}
+
+}

+ 26 - 0
src/main/java/cn/com/qmth/mps/vo/paper/GroupInfoVo.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.mps.vo.paper;
+
+import java.util.List;
+
+import cn.com.qmth.mps.bean.PaperGroupUnit;
+import io.swagger.annotations.ApiModelProperty;
+
+public class GroupInfoVo {
+	@ApiModelProperty("分组序号")
+	private Integer number;
+	@ApiModelProperty("分组信息")
+	private List<PaperGroupUnit> groupUnit;
+	public Integer getNumber() {
+		return number;
+	}
+	public void setNumber(Integer number) {
+		this.number = number;
+	}
+	public List<PaperGroupUnit> getGroupUnit() {
+		return groupUnit;
+	}
+	public void setGroupUnit(List<PaperGroupUnit> groupUnit) {
+		this.groupUnit = groupUnit;
+	}
+	
+}

+ 6 - 9
src/main/java/cn/com/qmth/mps/vo/paper/GroupVo.java

@@ -1,15 +1,12 @@
 package cn.com.qmth.mps.vo.paper;
 
-import java.util.List;
-
-import cn.com.qmth.mps.bean.PaperGroupUnit;
 import io.swagger.annotations.ApiModelProperty;
 
 public class GroupVo {
+	@ApiModelProperty("分组Id")
+	private Long groupId;
 	@ApiModelProperty("分组序号")
 	private Integer number;
-	@ApiModelProperty("分组信息")
-	private List<PaperGroupUnit> groupUnit;
 	@ApiModelProperty("大题号")
 	private String detailNumbers;
 	@ApiModelProperty("大题名称")
@@ -32,11 +29,11 @@ public class GroupVo {
 	public void setDetailNames(String detailNames) {
 		this.detailNames = detailNames;
 	}
-	public List<PaperGroupUnit> getGroupUnit() {
-		return groupUnit;
+	public Long getGroupId() {
+		return groupId;
 	}
-	public void setGroupUnit(List<PaperGroupUnit> groupUnit) {
-		this.groupUnit = groupUnit;
+	public void setGroupId(Long groupId) {
+		this.groupId = groupId;
 	}
 	
 }

+ 34 - 0
src/main/java/cn/com/qmth/mps/vo/paper/PaperGroupDomain.java

@@ -0,0 +1,34 @@
+package cn.com.qmth.mps.vo.paper;
+
+import java.util.List;
+
+import cn.com.qmth.mps.bean.PaperGroupUnit;
+import io.swagger.annotations.ApiModelProperty;
+
+public class PaperGroupDomain {
+	@ApiModelProperty("试卷结构ID")
+	private Long paperId;
+	@ApiModelProperty("分组序号")
+	private Integer number;
+	@ApiModelProperty("分组信息")
+	private List<PaperGroupUnit> groupUnits;
+	public Integer getNumber() {
+		return number;
+	}
+	public void setNumber(Integer number) {
+		this.number = number;
+	}
+	public List<PaperGroupUnit> getGroupUnits() {
+		return groupUnits;
+	}
+	public void setGroupUnits(List<PaperGroupUnit> groupUnits) {
+		this.groupUnits = groupUnits;
+	}
+	public Long getPaperId() {
+		return paperId;
+	}
+	public void setPaperId(Long paperId) {
+		this.paperId = paperId;
+	}
+	
+}

+ 8 - 0
src/main/java/cn/com/qmth/mps/vo/paper/PaperVo.java

@@ -26,6 +26,8 @@ public class PaperVo extends BaseEntity{
 	private Double totalScore;
 	@ApiModelProperty("主观总分")
 	private Double subjectiveScore;
+	@ApiModelProperty("试卷结构是否提交")
+	private Boolean structFinish;
 	@ApiModelProperty("分组是否完成")
 	private Boolean groupFinish;
 	@ApiModelProperty("分组数")
@@ -97,6 +99,12 @@ public class PaperVo extends BaseEntity{
 	public void setExamName(String examName) {
 		this.examName = examName;
 	}
+	public Boolean getStructFinish() {
+		return structFinish;
+	}
+	public void setStructFinish(Boolean structFinish) {
+		this.structFinish = structFinish;
+	}
 
 	
 	

+ 6 - 0
src/main/java/cn/com/qmth/mps/vo/paper/StructDomain.java

@@ -24,5 +24,11 @@ public class StructDomain {
 	public void setStructInfo(List<PaperDetail> structInfo) {
 		this.structInfo = structInfo;
 	}
+	public Double getTotalScore() {
+		return totalScore;
+	}
+	public void setTotalScore(Double totalScore) {
+		this.totalScore = totalScore;
+	}
 	
 }