wangwei 6 жил өмнө
parent
commit
ce1b930996
14 өөрчлөгдсөн 1007 нэмэгдсэн , 850 устгасан
  1. 168 82
      examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/ExamController.java
  2. 2 2
      examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/ExamStudentController.java
  3. 160 0
      examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/bean/ExamDomain.java
  4. 37 20
      examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/provider/ExamCloudServiceProvider.java
  5. 113 0
      examcloud-core-examwork-base/src/main/java/cn/com/qmth/examcloud/core/examwork/base/enums/ExamProperty.java
  6. 7 14
      examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/ExamRepo.java
  7. 0 577
      examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/entity/Exam.java
  8. 159 0
      examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/entity/ExamEntity.java
  9. 24 0
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/ExamService.java
  10. 160 0
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/bean/ExamInfo.java
  11. 1 1
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamCourseService.java
  12. 0 141
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamService.java
  13. 168 0
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamServiceImpl.java
  14. 8 13
      examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamStudentServiceImpl.java

+ 168 - 82
examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/ExamController.java

@@ -22,8 +22,6 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.domain.Sort.Direction;
 import org.springframework.data.jpa.domain.Specification;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -45,28 +43,40 @@ import cn.com.qmth.examcloud.commons.web.redis.RedisClient;
 import cn.com.qmth.examcloud.commons.web.security.bean.User;
 import cn.com.qmth.examcloud.commons.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.core.examwork.api.controller.bean.CourseGroupBean;
+import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamDomain;
+import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
 import cn.com.qmth.examcloud.core.examwork.dao.CourseGroupRelationRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.CourseGroupRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamPropertyRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamStudentRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.CourseGroupEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.CourseGroupRelation;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
-import cn.com.qmth.examcloud.core.examwork.service.impl.ExamService;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+import cn.com.qmth.examcloud.core.examwork.service.impl.ExamServiceImpl;
 import cn.com.qmth.examcloud.core.examwork.service.impl.ExamStudentServiceImpl;
 import io.swagger.annotations.ApiOperation;
 
 /**
- * 考试服务API Created by songyue on 17/1/13.
+ * 重构
+ *
+ * @author WANGWEI
+ * @date 2018年8月17日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
  */
 @Transactional
 @RestController
 @RequestMapping("${$rmp.ctr.examwork}/exam")
 public class ExamController extends ControllerSupport {
 
+	@Autowired
+	ExamPropertyRepo examPropertyRepo;
+
 	@Autowired
 	RedisClient redisClient;
 
@@ -74,7 +84,7 @@ public class ExamController extends ControllerSupport {
 	ExamRepo examRepo;
 
 	@Autowired
-	ExamService examService;
+	ExamServiceImpl examService;
 
 	@Autowired
 	ExamStudentRepo examStudentRepo;
@@ -91,26 +101,44 @@ public class ExamController extends ControllerSupport {
 	@Autowired
 	CourseGroupRelationRepo courseGroupRelationRepo;
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examCriteria
+	 * @param curPage
+	 * @param pageSize
+	 * @return
+	 */
 	@ApiOperation(value = "查询所有考试批次", notes = "分页带查询")
 	@GetMapping("all/{curPage}/{pageSize}")
-	public Page<Exam> getAllExam(HttpServletRequest request, @ModelAttribute Exam examCriteria,
+	public Page<ExamEntity> getAllExam(@ModelAttribute ExamEntity examCriteria,
 			@PathVariable Integer curPage, @PathVariable Integer pageSize) {
 		User accessUser = getAccessUser();
 		examCriteria.setRootOrgId(accessUser.getRootOrgId());
-		Page<Exam> page = examService.getAllExam(examCriteria,
+
+		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
+		Example<ExamEntity> examExample = Example.of(examCriteria, exampleMatcher);
+		return examRepo.findAll(examExample,
 				new PageRequest(curPage, pageSize, new Sort(Direction.DESC, "updateTime")));
-		return page;
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examCriteria
+	 * @return
+	 */
 	@ApiOperation(value = "查询所有考试批次(包含有效)", notes = "不分页带查询")
 	@GetMapping("all")
-	public List<Exam> getEnableExam(HttpServletRequest request, @ModelAttribute Exam examCriteria) {
+	public List<ExamEntity> getEnableExam(@ModelAttribute ExamEntity examCriteria) {
 		User accessUser = getAccessUser();
-
 		examCriteria.setRootOrgId(accessUser.getRootOrgId());
 		examCriteria.setEnable(true);
-		List<Exam> list = examService.getAllExam(examCriteria);
-		return list;
+		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
+		Example<ExamEntity> examExample = Example.of(examCriteria, exampleMatcher);
+		return examRepo.findAll(examExample, new Sort(Direction.DESC, "id"));
 	}
 
 	/**
@@ -122,14 +150,14 @@ public class ExamController extends ControllerSupport {
 	 */
 	@ApiOperation(value = "查询考试批次(包含有效、无效)")
 	@GetMapping("queryByName")
-	public List<Exam> queryByName(@RequestParam(required = false) String name) {
+	public List<ExamEntity> queryByName(@RequestParam(required = false) String name) {
 
 		if (StringUtils.isBlank(name)) {
-			List<Exam> list = Lists.newArrayList();
+			List<ExamEntity> list = Lists.newArrayList();
 			return list;
 		}
 
-		Specification<Exam> specification = (root, query, cb) -> {
+		Specification<ExamEntity> specification = (root, query, cb) -> {
 			List<Predicate> predicates = new ArrayList<>();
 			predicates.add(cb.equal(root.get("rootOrgId"), getRootOrgId()));
 			predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
@@ -137,109 +165,153 @@ public class ExamController extends ControllerSupport {
 			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
 		};
 		Sort sort = new Sort(Direction.DESC, "updateTime");
-		List<Exam> page = examRepo.findAll(specification, sort);
+		List<ExamEntity> page = examRepo.findAll(specification, sort);
 
 		return page;
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param rootOrgId
+	 * @param examType
+	 * @return
+	 */
 	@ApiOperation(value = "根据机构ID和考试类型查询所有有效考试批次", notes = "根据机构ID和考试类型查询所有有效考试批次")
 	@GetMapping("rootOrgId/{rootOrgId}/{examType}")
-	public List<Exam> getEnableExamByRootOrgId(@PathVariable Long rootOrgId,
+	public List<ExamEntity> getEnableExamByRootOrgId(@PathVariable Long rootOrgId,
 			@PathVariable String examType) {
-		Exam examCriteria = new Exam();
+		ExamEntity examCriteria = new ExamEntity();
 		examCriteria.setRootOrgId(rootOrgId);
 		if (StringUtils.isNotBlank(examType)) {
 			examCriteria.setExamType(ExamType.valueOf(examType));
 		}
 		examCriteria.setEnable(true);
-		List<Exam> list = examService.getAllExam(examCriteria);
-		return list;
+
+		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
+		Example<ExamEntity> examExample = Example.of(examCriteria, exampleMatcher);
+		return examRepo.findAll(examExample, new Sort(Direction.DESC, "id"));
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examCriteria
+	 * @return
+	 */
 	@ApiOperation(value = "查询所有考试批次(包含有效无效)", notes = "不分页带查询")
 	@GetMapping("all/both")
-	public List<Exam> getAllExam(@ModelAttribute Exam examCriteria) {
+	public List<ExamEntity> getAllExam(@ModelAttribute ExamEntity examCriteria) {
 		examCriteria.setRootOrgId(getRootOrgId());
 		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
-		Example<Exam> examExample = Example.of(examCriteria, exampleMatcher);
+		Example<ExamEntity> examExample = Example.of(examCriteria, exampleMatcher);
 		return examRepo.findAll(examExample, new Sort(Direction.DESC, "id"));
 	}
 
-	@ApiOperation(value = "根据名称查询考试批次(包含有效)", notes = "不分页带查询")
-	@GetMapping("name")
-	public List<Exam> getEnableExamByName(HttpServletRequest request,
-			@ModelAttribute Exam examCriteria) {
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param name
+	 * @return
+	 */
+	@ApiOperation(value = "根据名称查询考试批次(包含有效)")
+	@GetMapping("{name}")
+	public ExamEntity getEnableExamByName(@PathVariable String name) {
 		User accessUser = getAccessUser();
-		if (accessUser != null) {
-			examCriteria.setRootOrgId(accessUser.getRootOrgId());
+		ExamEntity one = examRepo.findByNameAndRootOrgId(name, accessUser.getRootOrgId());
+		if (null == one) {
+			throw new StatusException("E-001004", "考试不存在");
 		}
-		examCriteria.setEnable(true);
-		List<Exam> list = examService.findByNameAndRootOrgId(examCriteria.getName(),
-				examCriteria.getRootOrgId());
-		return list;
+		if (!one.getEnable()) {
+			throw new StatusException("E-001004", "考试被禁用");
+		}
+		return one;
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
 	@ApiOperation(value = "按ID查询考试批次", notes = "ID查询")
-	@GetMapping("{id}")
-	public ResponseEntity<Exam> getExamById(@PathVariable Long id) {
-		return new ResponseEntity<Exam>(examService.getExamById(id), HttpStatus.OK);
+	@GetMapping("{examId}")
+	public ExamEntity getExamById(@PathVariable Long examId) {
+		ExamEntity one = examRepo.findOne(examId);
+		return one;
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
 	@ApiOperation(value = "新增考试批次", notes = "新增")
 	@PostMapping()
-	public Exam addExam(@RequestBody Exam exam) {
-		trim(exam);
+	public ExamEntity addExam(@RequestBody ExamDomain domain) {
+		trim(domain, true);
 
-		if (null == exam.getExamType()) {
-			throw new StatusException("E-001005", "考试类型为空");
-		}
+		User accessUser = getAccessUser();
 
-		if (null != exam.getBeforeExamRemark() && exam.getBeforeExamRemark().length() > 250000) {
-			throw new StatusException("E-001002", "考前说明内容过大");
-		}
-		if (null != exam.getAfterExamRemark() && exam.getAfterExamRemark().length() > 250000) {
-			throw new StatusException("E-001002", "考后说明内容过大");
-		}
-		if (null != exam.getCheatingRemark() && exam.getCheatingRemark().length() > 250000) {
-			throw new StatusException("E-001002", "作弊说明内容过大");
-		}
+		ExamInfo examInfo = new ExamInfo();
 
-		User accessUser = getAccessUser();
+		examInfo.setBeginTime(domain.getBeginTime());
+		examInfo.setDuration(domain.getDuration());
+		examInfo.setEnable(true);
+		examInfo.setEndTime(domain.getEndTime());
+		examInfo.setExamTimes(domain.getExamTimes());
+		examInfo.setExamType(domain.getExamType());
+		examInfo.setId(domain.getId());
+		examInfo.setName(domain.getName());
+		examInfo.setRemark(domain.getRemark());
+		examInfo.setRootOrgId(accessUser.getRootOrgId());
 
-		exam.setRootOrgId(accessUser.getRootOrgId());
-		exam.setCanStuDel(true);
-		if (!examService.checkExamName(exam)) {
-			throw new StatusException("E-001001", "考试名称已存在,请重新填写");
-		}
-		Exam ret = examService.insertExam(exam);
-		return ret;
+		Map<String, String> properties = domain.getProperties();
+		examInfo.setProperties(properties);
+
+		ExamEntity saved = examService.saveExam(examInfo);
+
+		return saved;
 	}
 
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
 	@ApiOperation(value = "更新考试批次", notes = "更新")
 	@PutMapping()
-	public Exam updateExam(@RequestBody Exam exam) {
-		trim(exam);
+	public ExamEntity updateExam(@RequestBody ExamDomain domain) {
+		trim(domain, true);
 
-		if (null == exam.getExamType()) {
-			throw new StatusException("E-001005", "考试类型为空");
-		}
+		User accessUser = getAccessUser();
 
-		if (!examService.checkExamName(exam)) {
-			throw new StatusException("E-001001", "考试名称已存在,请重新填写");
-		}
+		ExamInfo examInfo = new ExamInfo();
+		examInfo.setBeginTime(domain.getBeginTime());
+		examInfo.setDuration(domain.getDuration());
+		examInfo.setEnable(true);
+		examInfo.setEndTime(domain.getEndTime());
+		examInfo.setExamTimes(domain.getExamTimes());
+		examInfo.setExamType(domain.getExamType());
+		examInfo.setId(domain.getId());
+		examInfo.setName(domain.getName());
+		examInfo.setRemark(domain.getRemark());
+		examInfo.setRootOrgId(accessUser.getRootOrgId());
 
-		if (null != exam.getBeforeExamRemark() && exam.getBeforeExamRemark().length() > 250000) {
-			throw new StatusException("E-001002", "考前说明内容过大");
-		}
-		if (null != exam.getAfterExamRemark() && exam.getAfterExamRemark().length() > 250000) {
-			throw new StatusException("E-001002", "考后说明内容过大");
-		}
-		if (null != exam.getCheatingRemark() && exam.getCheatingRemark().length() > 250000) {
-			throw new StatusException("E-001002", "作弊说明内容过大");
-		}
+		Map<String, String> properties = domain.getProperties();
+		examInfo.setProperties(properties);
 
-		Exam ret = examService.saveExam(exam);
-		return ret;
+		ExamEntity saved = examService.saveExam(examInfo);
+
+		return saved;
 	}
 
 	/**
@@ -264,7 +336,7 @@ public class ExamController extends ControllerSupport {
 		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
 				.collect(Collectors.toList());
 		for (Long examId : examIds) {
-			Exam exam = examRepo.findOne(examId);
+			ExamEntity exam = examRepo.findOne(examId);
 			exam.setEnable(true);
 			examRepo.save(exam);
 		}
@@ -276,7 +348,7 @@ public class ExamController extends ControllerSupport {
 		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
 				.collect(Collectors.toList());
 		for (Long examId : examIds) {
-			Exam exam = examRepo.findOne(examId);
+			ExamEntity exam = examRepo.findOne(examId);
 			exam.setEnable(false);
 			examRepo.save(exam);
 		}
@@ -439,13 +511,21 @@ public class ExamController extends ControllerSupport {
 	@ApiOperation(value = "考试IP限制", notes = "")
 	@GetMapping("ipLimit/{examId}")
 	public Map<String, Object> ipLimit(HttpServletRequest request, @PathVariable Long examId) {
-		Exam exam = examRepo.findOne(examId);
+		ExamEntity exam = examRepo.findOne(examId);
 		if (null == exam) {
 			throw new StatusException("E-001010", "考试不存在");
 		}
 
 		Map<String, Object> map = Maps.newHashMap();
-		Boolean ipLimit = exam.getIpLimit();
+
+		ExamPropertyEntity ipLimitProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
+				ExamProperty.IP_LIMIT.getKeyId());
+
+		Boolean ipLimit = null;
+		if (null != ipLimitProperty) {
+			ipLimit = "true".equalsIgnoreCase(ipLimitProperty.getValue());
+		}
+
 		if (null == ipLimit || !ipLimit) {
 			map.put("limited", false);
 			map.put("desc", "未配置IP限制");
@@ -463,7 +543,13 @@ public class ExamController extends ControllerSupport {
 		}
 		realIp = realIp.trim();
 
-		String ipAddresses = exam.getIpAddresses();
+		ExamPropertyEntity ipAddressesProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
+				ExamProperty.IP_ADDRESSES.getKeyId());
+
+		String ipAddresses = null;
+		if (null != ipAddressesProperty) {
+			ipAddresses = ipAddressesProperty.getValue();
+		}
 
 		boolean limited = true;
 		if (StringUtils.isNotBlank(ipAddresses)) {

+ 2 - 2
examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/ExamStudentController.java

@@ -50,7 +50,7 @@ import cn.com.qmth.examcloud.core.basic.api.response.InsertOrUpdateStudentResp;
 import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamStudentDomain;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamStudentRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamStudentEntity;
 import cn.com.qmth.examcloud.core.examwork.service.ExamStudentService;
 import cn.com.qmth.examcloud.core.examwork.service.bean.ExamStudentInfo;
@@ -167,7 +167,7 @@ public class ExamStudentController extends ControllerSupport {
 		List<ExamStudentDomain> ret = Lists.newArrayList();
 
 		for (ExamStudentEntity cur : examStudents) {
-			Exam exam = examRepo.findOne(cur.getExamId());
+			ExamEntity exam = examRepo.findOne(cur.getExamId());
 			GetCourseReq req = new GetCourseReq();
 			req.setId(cur.getCourseId());
 			GetCourseResp getCourseResp = courseCloudService.getCourse(req);

+ 160 - 0
examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/controller/bean/ExamDomain.java

@@ -0,0 +1,160 @@
+package cn.com.qmth.examcloud.core.examwork.api.controller.bean;
+
+import java.util.Date;
+import java.util.Map;
+
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.validation.constraints.NotNull;
+
+import cn.com.qmth.examcloud.commons.web.cloud.api.JsonSerializable;
+import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
+
+/**
+ * 类注释
+ *
+ * @author WANGWEI
+ * @date 2018年8月17日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class ExamDomain implements JsonSerializable {
+
+	private static final long serialVersionUID = 4009839764353162256L;
+
+	private Long id;
+
+	/**
+	 * 顶级机构Id
+	 */
+	private Long rootOrgId;
+
+	/**
+	 * 考试批次开始时间
+	 */
+	private Date beginTime;
+
+	/**
+	 * 考试批次结束时间
+	 */
+	private Date endTime;
+
+	/**
+	 * 考试名称
+	 */
+	@NotNull
+	private String name;
+
+	/**
+	 * 考试类型
+	 */
+	@Enumerated(EnumType.STRING)
+	private ExamType examType;
+
+	/**
+	 * 考试时长
+	 */
+	private Integer duration;
+
+	private Boolean enable;
+
+	/**
+	 * 考试备注
+	 */
+	private String remark;
+
+	/**
+	 * 考试次数
+	 */
+	private Long examTimes;
+
+	private Map<String, String> properties;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
+	public Date getBeginTime() {
+		return beginTime;
+	}
+
+	public void setBeginTime(Date beginTime) {
+		this.beginTime = beginTime;
+	}
+
+	public Date getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(Date endTime) {
+		this.endTime = endTime;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public ExamType getExamType() {
+		return examType;
+	}
+
+	public void setExamType(ExamType examType) {
+		this.examType = examType;
+	}
+
+	public Integer getDuration() {
+		return duration;
+	}
+
+	public void setDuration(Integer duration) {
+		this.duration = duration;
+	}
+
+	public Boolean getEnable() {
+		return enable;
+	}
+
+	public void setEnable(Boolean enable) {
+		this.enable = enable;
+	}
+
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+	public Long getExamTimes() {
+		return examTimes;
+	}
+
+	public void setExamTimes(Long examTimes) {
+		this.examTimes = examTimes;
+	}
+
+	public Map<String, String> getProperties() {
+		return properties;
+	}
+
+	public void setProperties(Map<String, String> properties) {
+		this.properties = properties;
+	}
+
+}

+ 37 - 20
examcloud-core-examwork-api-provider/src/main/java/cn/com/qmth/examcloud/core/examwork/api/provider/ExamCloudServiceProvider.java

@@ -1,5 +1,7 @@
 package cn.com.qmth.examcloud.core.examwork.api.provider;
 
+import java.util.Map;
+
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -13,10 +15,11 @@ import cn.com.qmth.examcloud.commons.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamPropertyRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
-import cn.com.qmth.examcloud.core.examwork.service.impl.ExamService;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+import cn.com.qmth.examcloud.core.examwork.service.impl.ExamServiceImpl;
 import cn.com.qmth.examcloud.examwork.api.ExamCloudService;
 import cn.com.qmth.examcloud.examwork.api.bean.ExamBean;
 import cn.com.qmth.examcloud.examwork.api.request.GetExamPropertyReq;
@@ -43,7 +46,7 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 	private static final long serialVersionUID = 6850508158980856785L;
 
 	@Autowired
-	private ExamService examService;
+	private ExamServiceImpl examService;
 
 	@Autowired
 	ExamRepo examRepo;
@@ -55,20 +58,31 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 	@PostMapping("saveExam")
 	@Override
 	public SaveExamResp saveExam(@RequestBody SaveExamReq req) {
-		Exam exam = new Exam();
-		exam.setEnable(true);
-		exam.setName(req.getName());
-		exam.setRemark(req.getRemark());
-		exam.setDuration(req.getDuration());
-		exam.setExamType(ExamType.valueOf(req.getExamType()));
-		exam.setBeginTime(req.getBeginTime());
-		exam.setEndTime(req.getEndTime());
-		exam.setRootOrgId(req.getRootOrgId());
-		exam.setCanStuDel(true);
-		if (!examService.checkExamName(exam)) {
-			throw new StatusException("E-002001", "考试名称已存在,请重新填写");
+		ExamInfo examInfo = new ExamInfo();
+
+		examInfo.setBeginTime(req.getBeginTime());
+		examInfo.setDuration(req.getDuration());
+		examInfo.setEnable(true);
+		examInfo.setEndTime(req.getEndTime());
+		examInfo.setExamTimes(req.getExamTimes());
+
+		ExamType et = null;
+		try {
+			et = ExamType.valueOf(req.getExamType());
+		} catch (Exception e) {
+			throw new StatusException("E-001004", "考试类型错误");
 		}
-		Exam saved = examService.insertExam(exam);
+
+		examInfo.setExamType(et);
+		examInfo.setId(req.getId());
+		examInfo.setName(req.getName());
+		examInfo.setRemark(req.getRemark());
+		examInfo.setRootOrgId(req.getRootOrgId());
+
+		Map<String, String> properties = req.getProperties();
+		examInfo.setProperties(properties);
+
+		ExamEntity saved = examService.saveExam(examInfo);
 
 		SaveExamResp resp = new SaveExamResp();
 		resp.setExamId(saved.getId());
@@ -88,7 +102,7 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 		if (null != id && StringUtils.isNotBlank(name)) {
 			throw new StatusException("E-002003", "id,name不能都不为空");
 		}
-		Exam exam = null;
+		ExamEntity exam = null;
 
 		if (null != id) {
 			exam = examRepo.findOne(id);
@@ -129,9 +143,12 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 
 		ExamProperty prop = ExamProperty.valueOf(key);
 
-		ExamPropertyEntity entity = new ExamPropertyEntity();
-		entity.setExamId(examId);
-		entity.setKeyId(prop.getKeyId());
+		ExamPropertyEntity entity = examPropertyRepo.findByexamIdAndKeyId(examId, prop.getKeyId());
+		if (null == entity) {
+			entity = new ExamPropertyEntity();
+			entity.setExamId(examId);
+			entity.setKeyId(prop.getKeyId());
+		}
 		entity.setValue(value);
 
 		ExamPropertyEntity saved = examPropertyRepo.save(entity);

+ 113 - 0
examcloud-core-examwork-base/src/main/java/cn/com/qmth/examcloud/core/examwork/base/enums/ExamProperty.java

@@ -9,6 +9,119 @@ package cn.com.qmth.examcloud.core.examwork.base.enums;
  */
 public enum ExamProperty {
 
+	/**
+	 * IP白名单
+	 */
+	IP_ADDRESSES(29L, "IP白名单"),
+	/**
+	 * 是否IP限制
+	 */
+	IP_LIMIT(28L, "是否IP限制"),
+	/**
+	 * 活体检测结束分钟数
+	 */
+	FACE_VERIFY_END_MINUTE(27L, "活体检测结束分钟数"),
+	/**
+	 * 活体检测开始分钟数
+	 */
+	FACE_VERIFY_START_MINUTE(26L, "活体检测开始分钟数"),
+	/**
+	 * 是否开启人脸活体检测
+	 */
+	IS_FACE_VERIFY(25L, "是否开启人脸活体检测"),
+	/**
+	 * 阅卷方式
+	 */
+	MARKING_TYPE(24L, "阅卷方式"),
+	/**
+	 * 预警阈值
+	 */
+	WARN_THRESHOLD(23L, "预警阈值"),
+	/**
+	 * 抓拍间隔
+	 */
+	SNAPSHOT_INTERVAL(21L, "抓拍间隔"),
+	/**
+	 * 进入考试是否验证人脸识别(强制、非强制)
+	 */
+	IS_FACE_CHECK(21L, "进入考试是否验证人脸识别(强制、非强制)"),
+	/**
+	 * 是否启用人脸识别
+	 */
+	IS_FACE_ENABLE(20L, "是否启用人脸识别"),
+	/**
+	 * 套题补充说明
+	 */
+	nestedAnswerRemark(19L, "套题补充说明"),
+	/**
+	 * 问答题补充说明
+	 */
+	TEXT_ANSWER_REMARK(18L, "问答题补充说明"),
+	/**
+	 * 填空题补充说明
+	 */
+	FILL_BLANK_REMARK(17L, "填空题补充说明"),
+	/**
+	 * 判断题补充说明
+	 */
+	BOOL_ANSWER_REMARK(16L, "判断题补充说明"),
+	/**
+	 * 多选题补充说明
+	 */
+	MUTIPLE_ANSWER_REMARK(15L, "多选题补充说明"),
+	/**
+	 * 单选题补充说明
+	 */
+	SINGLE_ANSWER_REMARK(14L, "单选题补充说明"),
+	/**
+	 * 填空题补充说明是否可填
+	 */
+	FILL_BLANK_EDIT(13L, "填空题补充说明是否可填"),
+	/**
+	 * 判断题补充说明是否可填
+	 */
+	BOOL_EDIT(12L, "判断题补充说明是否可填"),
+	/**
+	 * 多选题补充说明是否可填
+	 */
+	MUTIPLE_EDIT(11L, "多选题补充说明是否可填"),
+	/**
+	 * 单选题补充说明是否可填
+	 */
+	SINGLE_EDIT(10L, "单选题补充说明是否可填"),
+	/**
+	 * 练习模式
+	 */
+	PRACTICE_TYPE(9L, "练习模式"),
+	/**
+	 * 作弊说明
+	 */
+	CHEATING_REMARK(8L, "作弊说明"),
+	/**
+	 * 是否展示作弊
+	 */
+	SHOW_CHEATING_REMARK(7L, "是否展示作弊"),
+	/**
+	 * 考后说明
+	 */
+	AFTER_EXAM_REMARK(6L, "考后说明"),
+	/**
+	 * 考前说明
+	 */
+	BEFORE_EXAM_REMARK(5L, "考前说明"),
+	/**
+	 * 断点续考时间(秒)
+	 */
+	EXAM_RECONNECT_TIME(4L, "断点续考时间(秒)"),
+	/**
+	 * 交卷冻结时间
+	 */
+	FREEZE_TIME(3L, "交卷冻结时间"),
+	/**
+	 * 是否入学考试
+	 */
+	IS_ENTRANCE_EXAM(2L, "是否入学考试"),
+
 	/**
 	 * 发布成绩
 	 */

+ 7 - 14
examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/ExamRepo.java

@@ -4,24 +4,21 @@ import java.util.List;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
-import org.springframework.transaction.annotation.Transactional;
 
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 
 public interface ExamRepo
 		extends
-			JpaRepository<Exam, Long>,
-			QueryByExampleExecutor<Exam>,
-			JpaSpecificationExecutor<Exam> {
+			JpaRepository<ExamEntity, Long>,
+			QueryByExampleExecutor<ExamEntity>,
+			JpaSpecificationExecutor<ExamEntity> {
 
-	List<Exam> findByRootOrgId(Long rootOrgId);
+	List<ExamEntity> findByRootOrgId(Long rootOrgId);
 
-	List<Exam> findByIdIn(List<Long> ids);
+	List<ExamEntity> findByIdIn(List<Long> ids);
 
-	List<Exam> findByNameAndRootOrgId(String name, Long rootOrgId);
+	ExamEntity findByNameAndRootOrgId(String name, Long rootOrgId);
 
 	Long countByName(String name);
 
@@ -31,8 +28,4 @@ public interface ExamRepo
 
 	Long countByNameAndRootOrgIdAndIdNot(String name, Long rootOrgId, Long id);
 
-	@Transactional
-	@Modifying
-	@Query("update Exam e set e.canStuDel = false where e.id = ?1")
-	void canNotDel(Long id);
 }

+ 0 - 577
examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/entity/Exam.java

@@ -1,577 +0,0 @@
-package cn.com.qmth.examcloud.core.examwork.dao.entity;
-
-import java.util.Date;
-
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.Lob;
-import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
-
-import org.springframework.format.annotation.DateTimeFormat;
-
-import cn.com.qmth.examcloud.commons.web.jpa.JpaEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
-import cn.com.qmth.examcloud.core.examwork.dao.enums.MarkingType;
-import cn.com.qmth.examcloud.core.examwork.dao.enums.PracticeType;
-
-/**
- * Created by songyue on 17/1/13.
- */
-@Entity
-@Table(name = "ecs_exam")
-public class Exam extends JpaEntity {
-
-	private static final long serialVersionUID = 4009839764353162256L;
-
-	@Id
-	@GeneratedValue
-	private Long id;
-
-	/**
-	 * 顶级机构Id
-	 */
-	private Long rootOrgId;
-
-	/**
-	 * 考试批次开始时间
-	 */
-	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-	private Date beginTime;
-
-	/**
-	 * 考试批次结束时间
-	 */
-	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-	private Date endTime;
-
-	/**
-	 * 考试名称
-	 */
-	@NotNull
-	private String name;
-
-	/**
-	 * 考试类型
-	 */
-	@Enumerated(EnumType.STRING)
-	private ExamType examType;
-
-	/**
-	 * 是否入学考试
-	 */
-	private Boolean isEntranceExam;
-
-	/**
-	 * 考试时长
-	 */
-	private Integer duration;
-
-	/**
-	 * 冻结时间
-	 */
-	private Integer freezeTime;
-
-	/**
-	 * 考试状态
-	 */
-	private String status;
-
-	private Boolean enable;
-
-	/**
-	 * 考试备注
-	 */
-	private String remark;
-
-	/**
-	 * 考试次数
-	 */
-	private Long examTimes;
-
-	/**
-	 * 断点续考时间(秒)
-	 */
-	private Long examReconnectTime;
-
-	/**
-	 * 考前说明
-	 */
-	@Lob
-	private String beforeExamRemark;
-
-	/**
-	 * 考后说明
-	 */
-	@Lob
-	private String afterExamRemark;
-
-	/**
-	 * 作弊说明
-	 */
-	@Lob
-	private String cheatingRemark;
-
-	/**
-	 * 是否展示作弊
-	 */
-	private Boolean showCheatingRemark;
-
-	/**
-	 * 是否显示成绩
-	 */
-	private String isObjScoreView;
-
-	/**
-	 * 练习模式
-	 */
-	@Enumerated(EnumType.STRING)
-	private PracticeType practiceType;
-
-	/**
-	 * 单选题补充说明是否可填
-	 */
-	private Boolean singleEdit;
-
-	/**
-	 * 多选题补充说明是否可填
-	 */
-	private Boolean mutipleEdit;
-
-	/**
-	 * 判断题补充说明是否可填
-	 */
-	private Boolean boolEdit;
-
-	/**
-	 * 填空题补充说明是否可填
-	 */
-	private Boolean fillBlankEdit;
-
-	/**
-	 * 单选题补充说明
-	 */
-	private String singleAnswerRemark;
-
-	/**
-	 * 多选题补充说明
-	 */
-	private String mutipleAnswerRemark;
-
-	/**
-	 * 判断题补充说明
-	 */
-	private String boolAnswerRemark;
-
-	/**
-	 * 填空题补充说明
-	 */
-	private String fillBlankRemark;
-
-	/**
-	 * 问答题补充说明
-	 */
-	private String textAnswerRemark;
-
-	/**
-	 * 套题补充说明
-	 */
-	private String nestedAnswerRemark;
-
-	/**
-	 * 是否启用人脸识别
-	 */
-	private String isFaceEnable;
-
-	/**
-	 * 进入考试是否验证人脸识别(强制、非强制)
-	 */
-	private String isFaceCheck;
-
-	/**
-	 * 抓拍间隔
-	 */
-	private Double snapshotInterval;
-
-	/**
-	 * 预警阈值
-	 */
-	private Double warnThreshold;
-
-	/**
-	 * 阅卷方式
-	 */
-	@Enumerated(EnumType.STRING)
-	private MarkingType markingType;
-
-	/**
-	 * 学生是否可以删除
-	 */
-	@NotNull
-	private Boolean canStuDel;
-
-	/**
-	 * 是否开启人脸活体检测
-	 */
-	private Boolean isFaceVerify;
-
-	/**
-	 * 活体检测开始分钟数
-	 */
-	private Integer faceVerifyStartMinute;
-
-	/**
-	 * 活体检测结束分钟数
-	 */
-	private Integer faceVerifyEndMinute;
-
-	/**
-	 * 是否IP限制
-	 */
-	private Boolean ipLimit;
-
-	/**
-	 * IP白名单
-	 */
-	private String ipAddresses;
-
-	public Long getId() {
-		return id;
-	}
-
-	public void setId(Long id) {
-		this.id = id;
-	}
-
-	public Long getRootOrgId() {
-		return rootOrgId;
-	}
-
-	public void setRootOrgId(Long rootOrgId) {
-		this.rootOrgId = rootOrgId;
-	}
-
-	public Date getBeginTime() {
-		return beginTime;
-	}
-
-	public void setBeginTime(Date beginTime) {
-		this.beginTime = beginTime;
-	}
-
-	public Date getEndTime() {
-		return endTime;
-	}
-
-	public void setEndTime(Date endTime) {
-		this.endTime = endTime;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public ExamType getExamType() {
-		return examType;
-	}
-
-	public void setExamType(ExamType examType) {
-		this.examType = examType;
-	}
-
-	public Integer getDuration() {
-		return duration;
-	}
-
-	public void setDuration(Integer duration) {
-		this.duration = duration;
-	}
-
-	public Integer getFreezeTime() {
-		return freezeTime;
-	}
-
-	public void setFreezeTime(Integer freezeTime) {
-		this.freezeTime = freezeTime;
-	}
-
-	public String getStatus() {
-		return status;
-	}
-
-	public void setStatus(String status) {
-		this.status = status;
-	}
-
-	public String getRemark() {
-		return remark;
-	}
-
-	public void setRemark(String remark) {
-		this.remark = remark;
-	}
-
-	public Long getExamTimes() {
-		return examTimes;
-	}
-
-	public void setExamTimes(Long examTimes) {
-		this.examTimes = examTimes;
-	}
-
-	public Long getExamReconnectTime() {
-		return examReconnectTime;
-	}
-
-	public void setExamReconnectTime(Long examReconnectTime) {
-		this.examReconnectTime = examReconnectTime;
-	}
-
-	public String getBeforeExamRemark() {
-		return beforeExamRemark;
-	}
-
-	public void setBeforeExamRemark(String beforeExamRemark) {
-		this.beforeExamRemark = beforeExamRemark;
-	}
-
-	public String getAfterExamRemark() {
-		return afterExamRemark;
-	}
-
-	public void setAfterExamRemark(String afterExamRemark) {
-		this.afterExamRemark = afterExamRemark;
-	}
-
-	public String getIsObjScoreView() {
-		return isObjScoreView;
-	}
-
-	public void setIsObjScoreView(String isObjScoreView) {
-		this.isObjScoreView = isObjScoreView;
-	}
-
-	public PracticeType getPracticeType() {
-		return practiceType;
-	}
-
-	public void setPracticeType(PracticeType practiceType) {
-		this.practiceType = practiceType;
-	}
-
-	public String getSingleAnswerRemark() {
-		return singleAnswerRemark;
-	}
-
-	public void setSingleAnswerRemark(String singleAnswerRemark) {
-		this.singleAnswerRemark = singleAnswerRemark;
-	}
-
-	public String getMutipleAnswerRemark() {
-		return mutipleAnswerRemark;
-	}
-
-	public void setMutipleAnswerRemark(String mutipleAnswerRemark) {
-		this.mutipleAnswerRemark = mutipleAnswerRemark;
-	}
-
-	public String getBoolAnswerRemark() {
-		return boolAnswerRemark;
-	}
-
-	public void setBoolAnswerRemark(String boolAnswerRemark) {
-		this.boolAnswerRemark = boolAnswerRemark;
-	}
-
-	public String getFillBlankRemark() {
-		return fillBlankRemark;
-	}
-
-	public void setFillBlankRemark(String fillBlankRemark) {
-		this.fillBlankRemark = fillBlankRemark;
-	}
-
-	public String getTextAnswerRemark() {
-		return textAnswerRemark;
-	}
-
-	public void setTextAnswerRemark(String textAnswerRemark) {
-		this.textAnswerRemark = textAnswerRemark;
-	}
-
-	public String getNestedAnswerRemark() {
-		return nestedAnswerRemark;
-	}
-
-	public void setNestedAnswerRemark(String nestedAnswerRemark) {
-		this.nestedAnswerRemark = nestedAnswerRemark;
-	}
-
-	public String getIsFaceEnable() {
-		return isFaceEnable;
-	}
-
-	public void setIsFaceEnable(String isFaceEnable) {
-		this.isFaceEnable = isFaceEnable;
-	}
-
-	public String getIsFaceCheck() {
-		return isFaceCheck;
-	}
-
-	public void setIsFaceCheck(String isFaceCheck) {
-		this.isFaceCheck = isFaceCheck;
-	}
-
-	public Double getSnapshotInterval() {
-		return snapshotInterval;
-	}
-
-	public void setSnapshotInterval(Double snapshotInterval) {
-		this.snapshotInterval = snapshotInterval;
-	}
-
-	public Double getWarnThreshold() {
-		return warnThreshold;
-	}
-
-	public void setWarnThreshold(Double warnThreshold) {
-		this.warnThreshold = warnThreshold;
-	}
-
-	public MarkingType getMarkingType() {
-		return markingType;
-	}
-
-	public void setMarkingType(MarkingType markingType) {
-		this.markingType = markingType;
-	}
-
-	public Boolean getEnable() {
-		return enable;
-	}
-
-	public void setEnable(Boolean enable) {
-		this.enable = enable;
-	}
-
-	public Boolean getSingleEdit() {
-		return singleEdit;
-	}
-
-	public void setSingleEdit(Boolean singleEdit) {
-		this.singleEdit = singleEdit;
-	}
-
-	public Boolean getMutipleEdit() {
-		return mutipleEdit;
-	}
-
-	public void setMutipleEdit(Boolean mutipleEdit) {
-		this.mutipleEdit = mutipleEdit;
-	}
-
-	public Boolean getBoolEdit() {
-		return boolEdit;
-	}
-
-	public void setBoolEdit(Boolean boolEdit) {
-		this.boolEdit = boolEdit;
-	}
-
-	public Boolean getFillBlankEdit() {
-		return fillBlankEdit;
-	}
-
-	public void setFillBlankEdit(Boolean fillBlankEdit) {
-		this.fillBlankEdit = fillBlankEdit;
-	}
-
-	public Boolean getCanStuDel() {
-		return canStuDel;
-	}
-
-	public void setCanStuDel(Boolean canStuDel) {
-		this.canStuDel = canStuDel;
-	}
-
-	public Boolean getEntranceExam() {
-		return isEntranceExam;
-	}
-
-	public void setEntranceExam(Boolean entranceExam) {
-		isEntranceExam = entranceExam;
-	}
-
-	public Boolean getIsEntranceExam() {
-		return isEntranceExam;
-	}
-
-	public void setIsEntranceExam(Boolean isEntranceExam) {
-		this.isEntranceExam = isEntranceExam;
-	}
-
-	public Boolean getIsFaceVerify() {
-		return isFaceVerify;
-	}
-
-	public void setIsFaceVerify(Boolean isFaceVerify) {
-		this.isFaceVerify = isFaceVerify;
-	}
-
-	public Integer getFaceVerifyStartMinute() {
-		return faceVerifyStartMinute;
-	}
-
-	public void setFaceVerifyStartMinute(Integer faceVerifyStartMinute) {
-		this.faceVerifyStartMinute = faceVerifyStartMinute;
-	}
-
-	public Integer getFaceVerifyEndMinute() {
-		return faceVerifyEndMinute;
-	}
-
-	public void setFaceVerifyEndMinute(Integer faceVerifyEndMinute) {
-		this.faceVerifyEndMinute = faceVerifyEndMinute;
-	}
-
-	public String getCheatingRemark() {
-		return cheatingRemark;
-	}
-
-	public void setCheatingRemark(String cheatingRemark) {
-		this.cheatingRemark = cheatingRemark;
-	}
-
-	public Boolean getShowCheatingRemark() {
-		return showCheatingRemark;
-	}
-
-	public void setShowCheatingRemark(Boolean showCheatingRemark) {
-		this.showCheatingRemark = showCheatingRemark;
-	}
-
-	public Boolean getIpLimit() {
-		return ipLimit;
-	}
-
-	public void setIpLimit(Boolean ipLimit) {
-		this.ipLimit = ipLimit;
-	}
-
-	public String getIpAddresses() {
-		return ipAddresses;
-	}
-
-	public void setIpAddresses(String ipAddresses) {
-		this.ipAddresses = ipAddresses;
-	}
-
-}

+ 159 - 0
examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/entity/ExamEntity.java

@@ -0,0 +1,159 @@
+package cn.com.qmth.examcloud.core.examwork.dao.entity;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Index;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+import org.springframework.format.annotation.DateTimeFormat;
+
+import cn.com.qmth.examcloud.commons.web.jpa.JpaEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
+
+/**
+ * Created by songyue on 17/1/13.
+ */
+@Entity
+@Table(name = "EC_E_EXAM", indexes = {
+		@Index(name = "IDX_E_E_001001", columnList = "rootOrgId,name", unique = true)})
+public class ExamEntity extends JpaEntity {
+
+	private static final long serialVersionUID = 4009839764353162256L;
+
+	@Id
+	@GeneratedValue
+	private Long id;
+
+	/**
+	 * 顶级机构Id
+	 */
+	private Long rootOrgId;
+
+	/**
+	 * 考试批次开始时间
+	 */
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date beginTime;
+
+	/**
+	 * 考试批次结束时间
+	 */
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date endTime;
+
+	/**
+	 * 考试名称
+	 */
+	@NotNull
+	private String name;
+
+	/**
+	 * 考试类型
+	 */
+	@Enumerated(EnumType.STRING)
+	private ExamType examType;
+
+	/**
+	 * 考试时长
+	 */
+	private Integer duration;
+
+	private Boolean enable;
+
+	/**
+	 * 考试备注
+	 */
+	private String remark;
+
+	/**
+	 * 考试次数
+	 */
+	private Long examTimes;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
+	public Date getBeginTime() {
+		return beginTime;
+	}
+
+	public void setBeginTime(Date beginTime) {
+		this.beginTime = beginTime;
+	}
+
+	public Date getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(Date endTime) {
+		this.endTime = endTime;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public ExamType getExamType() {
+		return examType;
+	}
+
+	public void setExamType(ExamType examType) {
+		this.examType = examType;
+	}
+
+	public Integer getDuration() {
+		return duration;
+	}
+
+	public void setDuration(Integer duration) {
+		this.duration = duration;
+	}
+
+	public Boolean getEnable() {
+		return enable;
+	}
+
+	public void setEnable(Boolean enable) {
+		this.enable = enable;
+	}
+
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+	public Long getExamTimes() {
+		return examTimes;
+	}
+
+	public void setExamTimes(Long examTimes) {
+		this.examTimes = examTimes;
+	}
+
+}

+ 24 - 0
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/ExamService.java

@@ -0,0 +1,24 @@
+package cn.com.qmth.examcloud.core.examwork.service;
+
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+
+/**
+ * 类注释
+ *
+ * @author WANGWEI
+ * @date 2018年8月17日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public interface ExamService {
+
+	/**
+	 * 保存考试
+	 *
+	 * @author WANGWEI
+	 * @param examInfo
+	 * @return
+	 */
+	ExamEntity saveExam(ExamInfo examInfo);
+
+}

+ 160 - 0
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/bean/ExamInfo.java

@@ -0,0 +1,160 @@
+package cn.com.qmth.examcloud.core.examwork.service.bean;
+
+import java.util.Date;
+import java.util.Map;
+
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.validation.constraints.NotNull;
+
+import cn.com.qmth.examcloud.commons.web.cloud.api.JsonSerializable;
+import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
+
+/**
+ * 类注释
+ *
+ * @author WANGWEI
+ * @date 2018年8月17日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class ExamInfo implements JsonSerializable {
+
+	private static final long serialVersionUID = 4009839764353162256L;
+
+	private Long id;
+
+	/**
+	 * 顶级机构Id
+	 */
+	private Long rootOrgId;
+
+	/**
+	 * 考试批次开始时间
+	 */
+	private Date beginTime;
+
+	/**
+	 * 考试批次结束时间
+	 */
+	private Date endTime;
+
+	/**
+	 * 考试名称
+	 */
+	@NotNull
+	private String name;
+
+	/**
+	 * 考试类型
+	 */
+	@Enumerated(EnumType.STRING)
+	private ExamType examType;
+
+	/**
+	 * 考试时长
+	 */
+	private Integer duration;
+
+	private Boolean enable;
+
+	/**
+	 * 考试备注
+	 */
+	private String remark;
+
+	/**
+	 * 考试次数
+	 */
+	private Long examTimes;
+
+	private Map<String, String> properties;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
+	public Date getBeginTime() {
+		return beginTime;
+	}
+
+	public void setBeginTime(Date beginTime) {
+		this.beginTime = beginTime;
+	}
+
+	public Date getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(Date endTime) {
+		this.endTime = endTime;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public ExamType getExamType() {
+		return examType;
+	}
+
+	public void setExamType(ExamType examType) {
+		this.examType = examType;
+	}
+
+	public Integer getDuration() {
+		return duration;
+	}
+
+	public void setDuration(Integer duration) {
+		this.duration = duration;
+	}
+
+	public Boolean getEnable() {
+		return enable;
+	}
+
+	public void setEnable(Boolean enable) {
+		this.enable = enable;
+	}
+
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+	public Long getExamTimes() {
+		return examTimes;
+	}
+
+	public void setExamTimes(Long examTimes) {
+		this.examTimes = examTimes;
+	}
+
+	public Map<String, String> getProperties() {
+		return properties;
+	}
+
+	public void setProperties(Map<String, String> properties) {
+		this.properties = properties;
+	}
+
+}

+ 1 - 1
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamCourseService.java

@@ -2,7 +2,7 @@ package cn.com.qmth.examcloud.core.examwork.service.impl;
 
 import cn.com.qmth.examcloud.core.examwork.dao.bean.ExamCourseCriteria;
 import cn.com.qmth.examcloud.core.examwork.dao.bean.ExamCourseDTO;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;

+ 0 - 141
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamService.java

@@ -1,141 +0,0 @@
-package cn.com.qmth.examcloud.core.examwork.service.impl;
-
-import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.contains;
-
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.data.domain.ExampleMatcher;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import cn.com.qmth.examcloud.commons.base.exception.StatusException;
-import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgTimeRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
-
-/**
- * 考试批次服务类 Created by songyue on 17/1/13.
- */
-@Service
-public class ExamService {
-	@Autowired
-	ExamRepo examRepo;
-
-	@Autowired
-	ExamStudentServiceImpl examStudentService;
-
-	@Autowired
-	ExamOrgTimeRepo examOrgTimeRepo;
-
-	@Autowired
-	OrgCloudService orgCloudService;
-
-	/**
-	 * 获取所有考试批次(分页)
-	 * 
-	 * @param examCriteria
-	 * @param pageable
-	 * @return
-	 */
-	public Page<Exam> getAllExam(Exam examCriteria, Pageable pageable) {
-		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
-		Example<Exam> examExample = Example.of(examCriteria, exampleMatcher);
-		return examRepo.findAll(examExample, pageable);
-	}
-
-	/**
-	 * 获取所有考试批次
-	 * 
-	 * @param examCriteria
-	 * @return
-	 * @return
-	 */
-	public List<Exam> getAllExam(Exam examCriteria) {
-		ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", contains());
-		Example<Exam> examExample = Example.of(examCriteria, exampleMatcher);
-		return examRepo.findAll(examExample, new Sort(Direction.DESC, "id"));
-	}
-
-	/**
-	 * 按ID获取考试批次
-	 * 
-	 * @param examId
-	 * @return
-	 */
-	public Exam getExamById(Long examId) {
-		return examRepo.findOne(examId);
-	}
-
-	/**
-	 * 保存考试批次
-	 * 
-	 * @param exam
-	 * @return
-	 */
-	public Exam saveExam(Exam exam) {
-		Exam newExam = examRepo.save(exam);
-		return newExam;
-	}
-
-	@Transactional
-	public Exam insertExam(Exam exam) {
-		return examRepo.save(exam);
-	}
-
-	/**
-	 * 删除考试批次
-	 * 
-	 * @param ids
-	 * @return
-	 */
-	@Transactional
-	public void deleteExam(List<Long> ids) {
-		List<Exam> exams = examRepo.findByIdIn(ids);
-		for (Exam exam : exams) {
-			// 删除考生
-			if (exam.getCanStuDel()) {
-				// 删除学习中心考试时间
-				examOrgTimeRepo.deleteByExamId(exam.getId());
-				examStudentService.deleteExamStudentsByExamId(exam.getId());
-				examRepo.delete(exam);
-			} else {
-				throw new StatusException("", "[ " + exam.getName() + " ] 已经开始,不能删除");
-			}
-		}
-	}
-
-	public boolean checkExamName(Exam exam) {
-		if (exam.getId() != null) {
-			if (examRepo.countByNameAndRootOrgIdAndIdNot(exam.getName(), exam.getRootOrgId(),
-					exam.getId()) > 0) {
-				return false;
-			} else {
-				return true;
-			}
-		} else {
-			if (examRepo.countByNameAndRootOrgId(exam.getName(), exam.getRootOrgId()) > 0) {
-				return false;
-			} else {
-				return true;
-			}
-		}
-	}
-
-	public Exam findExamByNameAndRootOrgId(String examName, Long rootOrgId) {
-		Exam exam = new Exam();
-		exam.setName(examName);
-		exam.setRootOrgId(rootOrgId);
-		return examRepo.findOne(Example.of(exam));
-	}
-
-	public List<Exam> findByNameAndRootOrgId(String name, Long rootOrgId) {
-		return examRepo.findByNameAndRootOrgId(name, rootOrgId);
-	}
-}

+ 168 - 0
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamServiceImpl.java

@@ -0,0 +1,168 @@
+package cn.com.qmth.examcloud.core.examwork.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.stereotype.Service;
+
+import com.google.common.collect.Maps;
+
+import cn.com.qmth.examcloud.commons.base.exception.StatusException;
+import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
+import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgTimeRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamPropertyRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
+import cn.com.qmth.examcloud.core.examwork.service.ExamService;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+
+/**
+ * 类注释
+ *
+ * @author WANGWEI
+ * @date 2018年8月17日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+@Service
+public class ExamServiceImpl implements ExamService {
+	@Autowired
+	ExamRepo examRepo;
+
+	@Autowired
+	ExamStudentServiceImpl examStudentService;
+
+	@Autowired
+	ExamOrgTimeRepo examOrgTimeRepo;
+
+	@Autowired
+	OrgCloudService orgCloudService;
+
+	@Autowired
+	ExamPropertyRepo examPropertyRepo;
+
+	/**
+	 * 删除考试批次
+	 * 
+	 * @param ids
+	 * @return
+	 */
+	public void deleteExam(List<Long> ids) {
+		List<ExamEntity> exams = examRepo.findByIdIn(ids);
+		for (ExamEntity exam : exams) {
+			if (exam.getBeginTime().before(new Date())) {
+				throw new StatusException("", "[ " + exam.getName() + " ] 已经开考,不能删除");
+			}
+			// 删除学习中心考试时间
+			examOrgTimeRepo.deleteByExamId(exam.getId());
+			examStudentService.deleteExamStudentsByExamId(exam.getId());
+			examRepo.delete(exam);
+		}
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examName
+	 * @param rootOrgId
+	 * @return
+	 */
+	public ExamEntity findExamByNameAndRootOrgId(String examName, Long rootOrgId) {
+		ExamEntity exam = new ExamEntity();
+		exam.setName(examName);
+		exam.setRootOrgId(rootOrgId);
+		return examRepo.findOne(Example.of(exam));
+	}
+
+	/*
+	 * 实现
+	 *
+	 * @author WANGWEI
+	 * 
+	 * @see
+	 * cn.com.qmth.examcloud.core.examwork.service.ExamService#saveExam(cn.com.
+	 * qmth.examcloud.core.examwork.service.bean.ExamInfo)
+	 */
+	@Override
+	public ExamEntity saveExam(ExamInfo examInfo) {
+
+		ExamEntity exam = new ExamEntity();
+		exam.setBeginTime(examInfo.getBeginTime());
+		exam.setDuration(examInfo.getDuration());
+		exam.setEnable(examInfo.getEnable());
+		exam.setEndTime(examInfo.getEndTime());
+		exam.setExamTimes(examInfo.getExamTimes());
+		exam.setExamType(examInfo.getExamType());
+		exam.setId(examInfo.getId());
+		exam.setName(examInfo.getName());
+		exam.setRemark(examInfo.getRemark());
+		exam.setRootOrgId(examInfo.getRootOrgId());
+
+		Map<String, String> properties = examInfo.getProperties();
+		Map<ExamProperty, String> map = Maps.newHashMap();
+		for (Entry<String, String> entry : properties.entrySet()) {
+			String key = entry.getKey();
+			String value = entry.getValue();
+			if (StringUtils.isBlank(value)) {
+				continue;
+			}
+			ExamProperty ep = null;
+			try {
+				ep = ExamProperty.valueOf(key);
+			} catch (Exception e) {
+				throw new StatusException("E-001004", "考试属性错误");
+			}
+			map.put(ep, value.trim());
+		}
+
+		if (null == exam.getExamType()) {
+			throw new StatusException("E-001005", "考试类型为空");
+		}
+
+		String beforeExamRemark = map.get(ExamProperty.BEFORE_EXAM_REMARK);
+		if (null != beforeExamRemark && beforeExamRemark.length() > 250000) {
+			throw new StatusException("E-001002", "考前说明内容过大");
+		}
+
+		String afterExamRemark = map.get(ExamProperty.AFTER_EXAM_REMARK);
+		if (null != afterExamRemark && afterExamRemark.length() > 250000) {
+			throw new StatusException("E-001002", "考后说明内容过大");
+		}
+
+		String cheatingRemark = map.get(ExamProperty.CHEATING_REMARK);
+		if (null != cheatingRemark && cheatingRemark.length() > 250000) {
+			throw new StatusException("E-001002", "作弊说明内容过大");
+		}
+
+		ExamEntity findOne = examRepo.findByNameAndRootOrgId(exam.getName(), exam.getRootOrgId());
+		if (null != findOne && !findOne.getId().equals(exam.getId())) {
+			throw new StatusException("E-001001", "考试名称已存在");
+		}
+
+		ExamEntity saved = examRepo.save(exam);
+
+		for (Entry<ExamProperty, String> entry : map.entrySet()) {
+			ExamProperty prop = entry.getKey();
+			String value = entry.getValue();
+			ExamPropertyEntity entity = examPropertyRepo.findByexamIdAndKeyId(saved.getId(),
+					prop.getKeyId());
+			if (null == entity) {
+				entity = new ExamPropertyEntity();
+				entity.setExamId(saved.getId());
+				entity.setKeyId(prop.getKeyId());
+			}
+			entity.setValue(value);
+
+			examPropertyRepo.save(entity);
+		}
+
+		return saved;
+	}
+}

+ 8 - 13
examcloud-core-examwork-service/src/main/java/cn/com/qmth/examcloud/core/examwork/service/impl/ExamStudentServiceImpl.java

@@ -3,7 +3,6 @@ package cn.com.qmth.examcloud.core.examwork.service.impl;
 import java.util.Date;
 import java.util.List;
 
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -26,7 +25,7 @@ import cn.com.qmth.examcloud.core.basic.api.response.SaveCourseResp;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgTimeRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamRepo;
 import cn.com.qmth.examcloud.core.examwork.dao.ExamStudentRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.Exam;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamStudentEntity;
 import cn.com.qmth.examcloud.core.examwork.service.ExamStudentService;
 import cn.com.qmth.examcloud.core.examwork.service.bean.ExamStudentInfo;
@@ -86,9 +85,9 @@ public class ExamStudentServiceImpl implements ExamStudentService {
 	 */
 	@Override
 	public void deleteExamStudentsByExamId(Long examId) {
-		Exam exam = examRepo.findOne(examId);
+		ExamEntity exam = examRepo.findOne(examId);
 		// 已经开考
-		if (exam.getBeginTime().after(new Date())) {
+		if (exam.getBeginTime().before(new Date())) {
 			throw new StatusException("E-150113", "该考试已开始,不能删除");
 		}
 		examStudentRepo.deleteByExamId(examId);
@@ -121,21 +120,17 @@ public class ExamStudentServiceImpl implements ExamStudentService {
 			throw new StatusException("E-100001", "rootOrgId is wrong");
 		}
 
-		Exam exam = null;
+		ExamEntity exam = null;
 		Long examId = examStudentInfo.getExamId();
 		if (null == examId) {
 			String examName = examStudentInfo.getExamName();
 			if (StringUtils.isBlank(examName)) {
 				throw new StatusException("E-100002", "examId & examName are both blank");
 			}
-			List<Exam> examList = examRepo.findByNameAndRootOrgId(examName, rootOrgId);
-			if (CollectionUtils.isEmpty(examList)) {
+			exam = examRepo.findByNameAndRootOrgId(examName, rootOrgId);
+			if (null == exam) {
 				throw new StatusException("E-100005", "考试不存在");
 			}
-			if (1 < examList.size()) {
-				throw new StatusException("E-100005", "考试名称对应多个考试");
-			}
-			exam = examList.get(0);
 		} else {
 			exam = examRepo.findOne(examId);
 		}
@@ -168,8 +163,8 @@ public class ExamStudentServiceImpl implements ExamStudentService {
 		SaveCourseResp saveCourseResp = courseCloudService.saveCourse(saveCourseReq);
 		CourseBean courseBean = saveCourseResp.getCourseBean();
 
-		ExamStudentEntity examStudent = examStudentRepo.findByExamIdAndStudentIdAndCourseId(exam.getId(),
-				studentInfo.getId(), courseBean.getId());
+		ExamStudentEntity examStudent = examStudentRepo.findByExamIdAndStudentIdAndCourseId(
+				exam.getId(), studentInfo.getId(), courseBean.getId());
 
 		if (null == examStudent) {
 			examStudent = new ExamStudentEntity();