WANG 6 tahun lalu
induk
melakukan
9618ca7762

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

@@ -1,1199 +1,1210 @@
-package cn.com.qmth.examcloud.core.examwork.api.controller;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-import javax.persistence.criteria.Subquery;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-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.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import cn.com.qmth.examcloud.commons.base.exception.StatusException;
-import cn.com.qmth.examcloud.commons.base.helpers.DynamicEnum;
-import cn.com.qmth.examcloud.commons.base.helpers.DynamicEnumManager;
-import cn.com.qmth.examcloud.commons.base.util.JsonUtil;
-import cn.com.qmth.examcloud.commons.base.util.RegExpUtil;
-import cn.com.qmth.examcloud.commons.web.enums.DataExecutionStatus;
-import cn.com.qmth.examcloud.commons.web.helpers.page.PageInfo;
-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.basic.api.OrgCloudService;
-import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
-import cn.com.qmth.examcloud.core.basic.api.bean.OrgBean;
-import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
-import cn.com.qmth.examcloud.core.basic.api.request.GetOrgReq;
-import cn.com.qmth.examcloud.core.basic.api.request.GetStudentReq;
-import cn.com.qmth.examcloud.core.basic.api.response.GetOrgResp;
-import cn.com.qmth.examcloud.core.basic.api.response.GetStudentResp;
-import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamCourseGroupDomain;
-import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamDomain;
-import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamOrgSettingsDomain;
-import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseGroupRelationRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseGroupSettingsRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseRelationRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgPropertyRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgSettingsRepo;
-import cn.com.qmth.examcloud.core.examwork.dao.ExamPaperTypeRelationRepo;
-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.ExamCourseGroupRelationEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamCourseGroupSettingsEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamCourseRelationEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgPropertyEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgSettingsEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPaperTypeRelationEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamStudentEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
-import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
-import cn.com.qmth.examcloud.core.examwork.service.bean.ExamOrgSettingsInfo;
-import cn.com.qmth.examcloud.core.examwork.service.impl.ExamServiceImpl;
-import cn.com.qmth.examcloud.core.examwork.service.impl.ExamStudentServiceImpl;
-import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
-import cn.com.qmth.examcloud.core.oe.admin.api.request.CheckExamIsStartedReq;
-import cn.com.qmth.examcloud.core.oe.admin.api.response.CheckExamIsStartedResp;
-import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
-import cn.com.qmth.examcloud.task.api.request.SyncExamReq;
-import io.swagger.annotations.ApiOperation;
-
-/**
- * 重构
- *
- * @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;
-
-	@Autowired
-	ExamRepo examRepo;
-
-	@Autowired
-	ExamServiceImpl examService;
-
-	@Autowired
-	ExamStudentRepo examStudentRepo;
-
-	@Autowired
-	ExamStudentServiceImpl examStudentService;
-
-	@Autowired
-	ExamCourseGroupSettingsRepo examCourseGroupSettingsRepo;
-
-	@Autowired
-	ExamOrgSettingsRepo examOrgSettingsRepo;
-
-	@Autowired
-	ExamCourseGroupRelationRepo examCourseGroupRelationRepo;
-
-	@Autowired
-	OrgCloudService orgCloudService;
-
-	@Autowired
-	ExamOrgPropertyRepo examOrgPropertyRepo;
-
-	@Autowired
-	StudentCloudService studentCloudService;
-
-	@Autowired
-	ExamCourseRelationRepo examCourseRelationRepo;
-
-	@Autowired
-	ExamPaperTypeRelationRepo examPaperTypeRelationRepo;
-
-	@Autowired
-	ExamRecordCloudService examRecordCloudService;
-
-	@Autowired
-	DataSyncCloudService dataSyncCloudService;
-
-	@ApiOperation(value = "查询考试课程的试卷类型集合")
-	@GetMapping("queryExamCoursePaperTypeList")
-	public List<ExamPaperTypeRelationEntity> queryExamCoursePaperTypeList(
-			@RequestParam(required = true) Long examId,
-			@RequestParam(required = true) Long courseId) {
-
-		if (null == examId) {
-			throw new StatusException("E-001251", "examId is null");
-		}
-		if (null == courseId) {
-			throw new StatusException("E-001252", "courseId is null");
-		}
-		ExamEntity one = examRepo.findOne(examId);
-		if (null == one) {
-			throw new StatusException("E-001253", "examId is wrong");
-		}
-
-		validateRootOrgIsolation(one.getRootOrgId());
-
-		List<ExamPaperTypeRelationEntity> list = examPaperTypeRelationRepo
-				.findByExamIdAndCourseId(examId, courseId);
-
-		return list;
-	}
-
-	@ApiOperation(value = "查询考试的课程集合")
-	@GetMapping("queryExamCourseList")
-	public List<ExamCourseRelationEntity> getExamCourseList(
-			@RequestParam(required = true) Long examId, @RequestParam(required = false) String name,
-			@RequestParam(required = false) String level,
-			@RequestParam(required = false) Boolean enable) {
-
-		ExamEntity one = examRepo.findOne(examId);
-		if (null == one) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(one.getRootOrgId());
-
-		Specification<ExamCourseRelationEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-
-			predicates.add(cb.equal(root.get("examId"), examId));
-
-			Predicate pr1 = cb.like(root.get("courseName"), toSqlSearchPattern(name));
-			Predicate pr2 = cb.like(root.get("courseCode"), toSqlSearchPattern(name));
-
-			predicates.add(cb.or(pr1, pr2));
-
-			if (StringUtils.isNotBlank(level)) {
-				predicates.add(cb.equal(root.get("level"), toSqlSearchPattern(level)));
-			}
-
-			if (null != enable) {
-				predicates.add(cb.equal(root.get("courseEnable"), enable));
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		PageRequest pageRequest = new PageRequest(0, 50, new Sort(Direction.DESC, "updateTime"));
-
-		Page<ExamCourseRelationEntity> page = examCourseRelationRepo.findAll(specification,
-				pageRequest);
-
-		Iterator<ExamCourseRelationEntity> iterator = page.iterator();
-		List<ExamCourseRelationEntity> list = Lists.newArrayList();
-
-		while (iterator.hasNext()) {
-			ExamCourseRelationEntity next = iterator.next();
-			list.add(next);
-		}
-
-		return list;
-
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param curPage
-	 * @param pageSize
-	 * @param name
-	 * @param examType
-	 * @param enable
-	 * @return
-	 */
-	@ApiOperation(value = "分页查询考试批次")
-	@GetMapping("queryPage/{curPage}/{pageSize}")
-	public PageInfo<ExamDomain> queryPage(@PathVariable Integer curPage,
-			@PathVariable Integer pageSize, @RequestParam(required = false) String name,
-			@RequestParam(required = false) String examType,
-			@RequestParam(required = false) Boolean enable,
-			@RequestParam(required = false) String propertyKeys) {
-
-		User accessUser = getAccessUser();
-
-		Specification<ExamEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-			predicates.add(cb.equal(root.get("rootOrgId"), accessUser.getRootOrgId()));
-			if (StringUtils.isNotBlank(name)) {
-				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
-			}
-			if (null != enable) {
-				predicates.add(cb.equal(root.get("enable"), enable));
-			}
-			if (StringUtils.isNotBlank(examType)) {
-				predicates.add(cb.equal(root.get("examType"), ExamType.valueOf(examType)));
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		PageRequest pageRequest = new PageRequest(curPage, pageSize,
-				new Sort(Direction.DESC, "updateTime"));
-
-		Page<ExamEntity> page = examRepo.findAll(specification, pageRequest);
-
-		Iterator<ExamEntity> iterator = page.iterator();
-		List<ExamDomain> list = Lists.newArrayList();
-
-		List<String> propertyKeyList = null;
-		if (StringUtils.isNotBlank(propertyKeys)) {
-			propertyKeyList = RegExpUtil.findAll(propertyKeys, "\\w+");
-		}
-
-		while (iterator.hasNext()) {
-			ExamEntity next = iterator.next();
-			ExamDomain bean = new ExamDomain();
-			list.add(bean);
-
-			bean.setId(next.getId());
-			bean.setName(next.getName());
-			bean.setEnable(next.getEnable());
-			bean.setRootOrgId(next.getRootOrgId());
-			bean.setBeginTime(next.getBeginTime());
-			bean.setEndTime(next.getEndTime());
-			bean.setExamType(next.getExamType());
-			bean.setDuration(next.getDuration());
-			bean.setEnable(next.getEnable());
-			bean.setRemark(next.getRemark());
-			bean.setExamTimes(next.getExamTimes());
-			bean.setCreationTime(next.getCreationTime());
-			bean.setUpdateTime(next.getUpdateTime());
-
-			if (CollectionUtils.isNotEmpty(propertyKeyList)) {
-				Map<String, String> properties = getProperties(bean.getId(), propertyKeyList);
-				bean.setProperties(properties);
-			}
-		}
-
-		PageInfo<ExamDomain> ret = new PageInfo<ExamDomain>(page, list);
-		return ret;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param name
-	 * @param examTypes
-	 * @param enable
-	 * @param studentId
-	 *            筛选学生关联的考试
-	 * @return
-	 */
-	@ApiOperation(value = "查询考试批次")
-	@GetMapping("queryByNameLike")
-	public List<ExamDomain> query(@RequestParam(required = true) String name,
-			@RequestParam(required = false) String examTypes,
-			@RequestParam(required = false) Boolean enable,
-			@RequestParam(required = false) String propertyKeys,
-			@RequestParam(required = false) Long studentId,
-			@RequestParam(required = false) Long rootOrgId) {
-
-		if (null == rootOrgId) {
-			rootOrgId = getRootOrgId();
-		}
-		final Long finalRootOrgId = rootOrgId;
-
-		Specification<ExamEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-			predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
-			if (StringUtils.isNotBlank(name)) {
-				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
-			}
-			if (null != enable) {
-				predicates.add(cb.equal(root.get("enable"), enable));
-			}
-			if (StringUtils.isNotBlank(examTypes)) {
-				List<String> examTypeList = RegExpUtil.findAll(examTypes, "\\w+");
-
-				List<ExamType> etList = Lists.newArrayList();
-				for (String cur : examTypeList) {
-					etList.add(ExamType.valueOf(cur));
-				}
-
-				if (CollectionUtils.isNotEmpty(etList)) {
-					if (10 < examTypeList.size()) {
-						throw new StatusException("E-001120", "too many examTypes");
-					}
-					if (1 == examTypeList.size()) {
-						predicates.add(cb.equal(root.get("examType"), etList.get(0)));
-					} else {
-						predicates.add(root.get("examType").in(etList));
-					}
-				}
-			}
-
-			if (null != studentId) {
-				Subquery<ExamStudentEntity> subquery = query.subquery(ExamStudentEntity.class);
-				Root<ExamStudentEntity> subRoot = subquery.from(ExamStudentEntity.class);
-				subquery.select(subRoot.get("id"));
-				Predicate p1 = cb.equal(subRoot.get("studentId"), studentId);
-				Predicate p2 = cb.equal(subRoot.get("examId"), root.get("id"));
-				subquery.where(cb.and(p1, p2));
-				predicates.add(cb.exists(subquery));
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		PageRequest pageRequest = new PageRequest(0, 100, new Sort(Direction.DESC, "updateTime"));
-		Page<ExamEntity> page = examRepo.findAll(specification, pageRequest);
-
-		Iterator<ExamEntity> iterator = page.iterator();
-		List<ExamDomain> list = Lists.newArrayList();
-
-		List<String> propertyKeyList = null;
-		if (StringUtils.isNotBlank(propertyKeys)) {
-			propertyKeyList = RegExpUtil.findAll(propertyKeys, "\\w+");
-		}
-
-		while (iterator.hasNext()) {
-			ExamEntity next = iterator.next();
-			ExamDomain bean = new ExamDomain();
-			list.add(bean);
-
-			bean.setId(next.getId());
-			bean.setName(next.getName());
-			bean.setEnable(next.getEnable());
-			bean.setRootOrgId(next.getRootOrgId());
-			bean.setBeginTime(next.getBeginTime());
-			bean.setEndTime(next.getEndTime());
-			bean.setExamType(next.getExamType());
-
-			if (CollectionUtils.isNotEmpty(propertyKeyList)) {
-				Map<String, String> properties = getProperties(bean.getId(), propertyKeyList);
-				bean.setProperties(properties);
-			}
-		}
-
-		return list;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @param propertyKeys
-	 * @return
-	 */
-	private Map<String, String> getProperties(Long examId, List<String> propertyKeys) {
-		Map<String, String> map = Maps.newHashMap();
-		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
-
-		for (String key : propertyKeys) {
-			DynamicEnum de = manager.getByName(key);
-			ExamPropertyEntity one = examPropertyRepo.findByexamIdAndKeyId(examId, de.getId());
-			if (null != one) {
-				map.put(key, one.getValue());
-			}
-		}
-
-		return map;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "按ID查询考试批次", notes = "ID查询")
-	@GetMapping("{examId}")
-	public ExamDomain getExamById(@PathVariable Long examId) {
-		ExamEntity one = examRepo.findOne(examId);
-		if (null == one) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(one.getRootOrgId());
-
-		ExamDomain domain = new ExamDomain();
-		domain.setBeginTime(one.getBeginTime());
-		domain.setDuration(one.getDuration());
-		domain.setEnable(one.getEnable());
-		domain.setEndTime(one.getEndTime());
-		domain.setExamTimes(one.getExamTimes());
-		domain.setExamType(one.getExamType());
-		domain.setId(one.getId());
-		domain.setName(one.getName());
-		domain.setRemark(one.getRemark());
-		domain.setRootOrgId(one.getRootOrgId());
-		domain.setStarted(isStarted(one.getId()));
-		return domain;
-	}
-
-	/**
-	 * 是否开考
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	private boolean isStarted(Long examId) {
-		CheckExamIsStartedReq checkExamIsStartedReq = new CheckExamIsStartedReq();
-		checkExamIsStartedReq.setExamId(examId);
-		try {
-			CheckExamIsStartedResp checkExamIsStartedResp = examRecordCloudService
-					.checkExamIsStarted(checkExamIsStartedReq);
-			return checkExamIsStartedResp.getIsStarted();
-		} catch (Exception e) {
-			log.error("fail to rmi[oe.examRecordCloudService.checkExamIsStarted]", e);
-			return true;
-		}
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param domain
-	 * @return
-	 */
-	@ApiOperation(value = "新增考试批次", notes = "新增")
-	@PostMapping()
-	public ExamEntity addExam(@RequestBody ExamDomain domain) {
-		return saveExam(domain, DataExecutionStatus.CREATION);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param domain
-	 * @return
-	 */
-	@ApiOperation(value = "更新考试批次", notes = "更新")
-	@PutMapping()
-	public ExamEntity updateExam(@RequestBody ExamDomain domain) {
-		return saveExam(domain, DataExecutionStatus.UPDATE);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param domain
-	 * @return
-	 */
-	private ExamEntity saveExam(ExamDomain domain, DataExecutionStatus es) {
-		trim(domain, false);
-
-		User accessUser = getAccessUser();
-
-		ExamInfo examInfo = new ExamInfo();
-		examInfo.setBeginTime(domain.getBeginTime());
-		examInfo.setDuration(domain.getDuration());
-		examInfo.setEnable(domain.getEnable());
-		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());
-
-		Map<String, String> properties = domain.getProperties();
-		if (null == properties) {
-			properties = Maps.newHashMap();
-		}
-		examInfo.setProperties(properties);
-
-		ExamEntity saved = examService.saveExam(examInfo, es);
-
-		return saved;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "查询考试批次所有属性")
-	@GetMapping("allProperties/{examId}")
-	public Map<String, String> getAllExamProperties(@PathVariable Long examId) {
-
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		Map<String, String> map = Maps.newHashMap();
-		List<ExamPropertyEntity> list = examPropertyRepo.findByexamId(examId);
-		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
-		for (ExamPropertyEntity cur : list) {
-			DynamicEnum de = manager.getById(cur.getKeyId());
-			map.put(de.getName(), cur.getValue());
-		}
-
-		return map;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "查询考试批次单个属性")
-	@GetMapping("property/{examId}/{key}")
-	public String getExamProperty(@PathVariable Long examId, @PathVariable String key) {
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
-		DynamicEnum de = manager.getByName(key);
-		ExamPropertyEntity one = examPropertyRepo.findByexamIdAndKeyId(examId, de.getId());
-		if (null == one) {
-			return null;
-		}
-		return one.getValue();
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "查询考生考试批次单个属性")
-	@GetMapping("examOrgProperty/{examId}/{key}")
-	public String getExamOrgProperty(@PathVariable Long examId, @PathVariable String key) {
-		User accessUser = getAccessUser();
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		StudentBean student = getStudent(accessUser.getUserId());
-		Long orgId = student.getOrgId();
-
-		return examService.getOrgProperty(examId, orgId, key);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "查询考试批次机构属性")
-	@GetMapping("examOrgProperty/{examId}/{orgId}/{key}")
-	public String getExamOrgProperty(@PathVariable Long examId, @PathVariable Long orgId,
-			@PathVariable String key) {
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		if (null == orgId) {
-			throw new StatusException("E-001251", "orgId is null");
-		}
-
-		GetOrgReq getOrgReq = new GetOrgReq();
-		getOrgReq.setOrgId(orgId);
-		GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
-		validateRootOrgIsolation(getOrgResp.getOrg().getRootId());
-
-		return examService.getOrgProperty(examId, orgId, key);
-	}
-
-	@ApiOperation(value = "启用考试", notes = "启用考试")
-	@PutMapping("enable/{ids}")
-	public void enableUser(@PathVariable String ids) {
-		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		for (Long examId : examIds) {
-			ExamEntity exam = examRepo.findOne(examId);
-			exam.setEnable(true);
-			examRepo.save(exam);
-		}
-
-		for (Long examId : examIds) {
-			ExamEntity exam = examRepo.findOne(examId);
-			SyncExamReq req = new SyncExamReq();
-			req.setId(exam.getId());
-			req.setBeginTime(exam.getBeginTime());
-			req.setDuration(exam.getDuration());
-			req.setEnable(exam.getEnable());
-			req.setEndTime(exam.getEndTime());
-			req.setExamTimes(exam.getExamTimes());
-			req.setExamType(exam.getExamType().name());
-			req.setName(exam.getName());
-			req.setRemark(exam.getRemark());
-			req.setRootOrgId(exam.getRootOrgId());
-
-			GetOrgReq getOrgReq = new GetOrgReq();
-			getOrgReq.setOrgId(exam.getRootOrgId());
-			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
-			OrgBean rootOrg = getOrgResp.getOrg();
-			req.setRootOrgName(rootOrg.getName());
-
-			req.setSyncType("update");
-			dataSyncCloudService.syncExam(req);
-		}
-
-	}
-
-	@ApiOperation(value = "禁用考试", notes = "禁用考试")
-	@PutMapping("disable/{ids}")
-	public void disableUser(@PathVariable String ids) {
-		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		for (Long examId : examIds) {
-			ExamEntity exam = examRepo.findOne(examId);
-			exam.setEnable(false);
-			examRepo.save(exam);
-		}
-
-		for (Long examId : examIds) {
-			ExamEntity exam = examRepo.findOne(examId);
-			SyncExamReq req = new SyncExamReq();
-			req.setId(exam.getId());
-			req.setBeginTime(exam.getBeginTime());
-			req.setDuration(exam.getDuration());
-			req.setEnable(exam.getEnable());
-			req.setEndTime(exam.getEndTime());
-			req.setExamTimes(exam.getExamTimes());
-			req.setExamType(exam.getExamType().name());
-			req.setName(exam.getName());
-			req.setRemark(exam.getRemark());
-			req.setRootOrgId(exam.getRootOrgId());
-
-			GetOrgReq getOrgReq = new GetOrgReq();
-			getOrgReq.setOrgId(exam.getRootOrgId());
-			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
-			OrgBean rootOrg = getOrgResp.getOrg();
-			req.setRootOrgName(rootOrg.getName());
-
-			req.setSyncType("update");
-			dataSyncCloudService.syncExam(req);
-		}
-
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @param curPage
-	 * @param pageSize
-	 * @return
-	 */
-	@ApiOperation(value = "查询课程组集合", notes = "")
-	@GetMapping("getCourseGroupListByExamId/{examId}/{curPage}/{pageSize}")
-	public List<ExamCourseGroupDomain> getCourseGroupListByExamId(@PathVariable Long examId,
-			@PathVariable Integer curPage, @PathVariable Integer pageSize) {
-
-		Pageable pageable = new PageRequest(curPage - 1, pageSize, Sort.Direction.DESC,
-				"updateTime");
-		List<ExamCourseGroupSettingsEntity> groupList = examCourseGroupSettingsRepo
-				.findAllByExamId(examId, pageable);
-
-		List<ExamCourseGroupDomain> ret = Lists.newArrayList();
-
-		for (ExamCourseGroupSettingsEntity curCourseGroup : groupList) {
-			ExamCourseGroupDomain bean = new ExamCourseGroupDomain();
-			bean.setBeginTime(curCourseGroup.getBeginTime());
-			bean.setCreationTime(curCourseGroup.getCreationTime());
-			bean.setDescription(curCourseGroup.getDescription());
-			bean.setEndTime(curCourseGroup.getEndTime());
-			bean.setExamId(curCourseGroup.getExamId());
-			bean.setId(curCourseGroup.getId());
-			bean.setName(curCourseGroup.getName());
-			bean.setUpdateTime(curCourseGroup.getUpdateTime());
-
-			List<Long> courseIdList = Lists.newArrayList();
-			bean.setCourseIdList(courseIdList);
-
-			List<ExamCourseGroupRelationEntity> relationList = examCourseGroupRelationRepo
-					.findAllByGroupId(bean.getId());
-
-			for (ExamCourseGroupRelationEntity cur : relationList) {
-				courseIdList.add(cur.getCourseId());
-			}
-
-			ret.add(bean);
-		}
-
-		return ret;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @param courseId
-	 * @return
-	 */
-	@ApiOperation(value = "通过课程ID查询课程组集合", notes = "")
-	@GetMapping("getCourseGroupListByExamIdAndCourseId/{examId}/{courseId}")
-	public List<ExamCourseGroupDomain> getCourseGroupListByExamIdAndCourseId(
-			@PathVariable Long examId, @PathVariable Long courseId) {
-
-		List<ExamCourseGroupRelationEntity> relationList = examCourseGroupRelationRepo
-				.findAllByCourseIdAndExamId(courseId, examId);
-
-		List<Long> groupIdList = Lists.newArrayList();
-		for (ExamCourseGroupRelationEntity cur : relationList) {
-			Long groupId = cur.getGroupId();
-			groupIdList.add(groupId);
-		}
-
-		List<ExamCourseGroupSettingsEntity> groupList = examCourseGroupSettingsRepo
-				.findAllByIdInOrderByUpdateTimeDesc(groupIdList);
-
-		List<ExamCourseGroupDomain> ret = Lists.newArrayList();
-
-		for (ExamCourseGroupSettingsEntity curCourseGroup : groupList) {
-			ExamCourseGroupDomain bean = new ExamCourseGroupDomain();
-			bean.setBeginTime(curCourseGroup.getBeginTime());
-			bean.setCreationTime(curCourseGroup.getCreationTime());
-			bean.setDescription(curCourseGroup.getDescription());
-			bean.setEndTime(curCourseGroup.getEndTime());
-			bean.setExamId(curCourseGroup.getExamId());
-			bean.setId(curCourseGroup.getId());
-			bean.setName(curCourseGroup.getName());
-			bean.setUpdateTime(curCourseGroup.getUpdateTime());
-
-			List<Long> courseIdList = Lists.newArrayList();
-			bean.setCourseIdList(courseIdList);
-
-			List<ExamCourseGroupRelationEntity> curRelationList = examCourseGroupRelationRepo
-					.findAllByGroupId(bean.getId());
-
-			for (ExamCourseGroupRelationEntity cur : curRelationList) {
-				courseIdList.add(cur.getCourseId());
-			}
-		}
-
-		return ret;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param courseGroupBean
-	 * @param request
-	 */
-	@ApiOperation(value = "更新课程组", notes = "")
-	@PutMapping("courseGroup")
-	public void updateCourseGroup(@RequestBody ExamCourseGroupDomain courseGroupBean,
-			HttpServletRequest request) {
-
-		ExamCourseGroupSettingsEntity courseGroup = new ExamCourseGroupSettingsEntity();
-		courseGroup.setBeginTime(courseGroupBean.getBeginTime());
-		courseGroup.setCreationTime(courseGroupBean.getCreationTime());
-		courseGroup.setDescription(courseGroupBean.getDescription());
-		courseGroup.setEndTime(courseGroupBean.getEndTime());
-		courseGroup.setExamId(courseGroupBean.getExamId());
-		courseGroup.setId(courseGroupBean.getId());
-		courseGroup.setName(courseGroupBean.getName());
-		courseGroup.setUpdateTime(courseGroupBean.getUpdateTime());
-
-		examCourseGroupSettingsRepo.save(courseGroup);
-		List<Long> courseIdList = courseGroupBean.getCourseIdList();
-
-		List<ExamCourseGroupRelationEntity> relationList = Lists.newArrayList();
-
-		examCourseGroupRelationRepo.deleteByGroupId(courseGroup.getId());
-
-		for (Long cur : courseIdList) {
-			ExamCourseGroupRelationEntity relation = new ExamCourseGroupRelationEntity();
-			relation.setCourseId(cur);
-			relation.setExamId(courseGroupBean.getExamId());
-			relation.setGroupId(courseGroup.getId());
-			relationList.add(relation);
-		}
-		examCourseGroupRelationRepo.save(relationList);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param id
-	 */
-	@ApiOperation(value = "删除课程组", notes = "")
-	@DeleteMapping("courseGroup/{id}")
-	public void deleteCourseGroup(@PathVariable Long id) {
-		examCourseGroupSettingsRepo.delete(id);
-		examCourseGroupRelationRepo.deleteByGroupId(id);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param curPage
-	 * @param pageSize
-	 * @param examOrgDomain
-	 * @return
-	 */
-	@ApiOperation(value = "查询考试相关的学习中心设置", notes = "")
-	@GetMapping("getExamOrgSettingsList/{curPage}/{pageSize}")
-	public PageInfo<ExamOrgSettingsDomain> getExamOrgSettingsList(@PathVariable Integer curPage,
-			@PathVariable Integer pageSize, @ModelAttribute ExamOrgSettingsDomain examOrgDomain) {
-
-		Long examId = examOrgDomain.getExamId();
-		if (null == examOrgDomain.getExamId()) {
-			throw new StatusException("E-001210", "examId is null");
-		}
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		Specification<ExamOrgSettingsEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-
-			predicates.add(cb.equal(root.get("examId"), examOrgDomain.getExamId()));
-
-			if (null != examOrgDomain.getOrgId()) {
-				predicates.add(cb.equal(root.get("orgId"), examOrgDomain.getOrgId()));
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		Pageable pageable = new PageRequest(curPage, pageSize, Sort.Direction.DESC, "updateTime");
-		Page<ExamOrgSettingsEntity> page = examOrgSettingsRepo.findAll(specification, pageable);
-
-		Iterator<ExamOrgSettingsEntity> iterator = page.iterator();
-		List<ExamOrgSettingsDomain> domainList = Lists.newArrayList();
-
-		while (iterator.hasNext()) {
-			ExamOrgSettingsEntity next = iterator.next();
-			ExamOrgSettingsDomain bean = new ExamOrgSettingsDomain();
-			domainList.add(bean);
-
-			bean.setBeginTime(next.getBeginTime());
-			bean.setEndTime(next.getEndTime());
-			bean.setExamId(next.getExamId());
-			bean.setId(next.getId());
-			bean.setOrgId(next.getOrgId());
-			bean.setRootOrgId(next.getRootOrgId());
-			bean.setUpdateTime(next.getUpdateTime());
-
-			GetOrgReq getOrgReq = new GetOrgReq();
-			getOrgReq.setOrgId(bean.getOrgId());
-			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
-			OrgBean org = getOrgResp.getOrg();
-			bean.setOrgName(org.getName());
-			bean.setOrgCode(org.getCode());
-
-			List<ExamOrgPropertyEntity> propList = examOrgPropertyRepo
-					.findByexamIdAndOrgId(next.getExamId(), next.getOrgId());
-
-			Map<String, String> map = Maps.newHashMap();
-			DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
-			for (ExamOrgPropertyEntity cur : propList) {
-				DynamicEnum de = manager.getById(cur.getKeyId());
-				map.put(de.getName(), cur.getValue());
-			}
-
-			bean.setProperties(map);
-		}
-
-		PageInfo<ExamOrgSettingsDomain> ret = new PageInfo<ExamOrgSettingsDomain>();
-		ret.setList(domainList);
-		ret.setTotal(page.getTotalElements());
-		return ret;
-	}
-
-	@ApiOperation(value = "查询考生考试机构配置", notes = "")
-	@PostMapping("examOrgSettings/{examId}")
-	public ExamDomain getExamOrgSettings(@PathVariable Long examId) {
-		User accessUser = getAccessUser();
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		StudentBean student = getStudent(accessUser.getUserId());
-		Long orgId = student.getOrgId();
-
-		ExamOrgSettingsEntity examOrgEntity = examOrgSettingsRepo.findByExamIdAndOrgId(examId,
-				orgId);
-
-		ExamDomain domain = new ExamDomain();
-		domain.setBeginTime(examEntity.getBeginTime());
-		domain.setDuration(examEntity.getDuration());
-		domain.setEnable(examEntity.getEnable());
-		domain.setEndTime(examEntity.getEndTime());
-		domain.setExamTimes(examEntity.getExamTimes());
-		domain.setExamType(examEntity.getExamType());
-		domain.setId(examEntity.getId());
-		domain.setName(examEntity.getName());
-		domain.setRemark(examEntity.getRemark());
-		domain.setRootOrgId(examEntity.getRootOrgId());
-		domain.setStarted(examEntity.getBeginTime().before(new Date()));
-
-		if (null != examOrgEntity) {
-			domain.setBeginTime(examOrgEntity.getBeginTime());
-			domain.setEndTime(examOrgEntity.getEndTime());
-		}
-
-		return domain;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examOrg
-	 * @return
-	 */
-	@ApiOperation(value = "新增考试相关的学习中心设置", notes = "")
-	@PostMapping("examOrgSettings")
-	public ExamOrgSettingsEntity addExamOrgSettings(@RequestBody ExamOrgSettingsDomain domain) {
-		return saveExamOrgSettings(domain);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examOrg
-	 * @return
-	 */
-	@ApiOperation(value = "更新考试相关的学习中心设置", notes = "")
-	@PutMapping("examOrgSettings")
-	public ExamOrgSettingsEntity updateExamOrgSettings(@RequestBody ExamOrgSettingsDomain domain) {
-		return saveExamOrgSettings(domain);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param domain
-	 * @return
-	 */
-	private ExamOrgSettingsEntity saveExamOrgSettings(ExamOrgSettingsDomain domain) {
-		Long examId = domain.getExamId();
-
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		Long orgId = domain.getOrgId();
-
-		GetOrgReq getOrgReq = new GetOrgReq();
-		getOrgReq.setOrgId(orgId);
-		GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
-		OrgBean org = getOrgResp.getOrg();
-		org.getRootId();
-		validateRootOrgIsolation(org.getRootId());
-
-		User accessUser = getAccessUser();
-		ExamOrgSettingsInfo info = new ExamOrgSettingsInfo();
-		info.setId(domain.getId());
-		info.setBeginTime(domain.getBeginTime());
-		info.setEndTime(domain.getEndTime());
-		info.setExamId(domain.getExamId());
-		info.setOrgId(domain.getOrgId());
-		info.setRootOrgId(accessUser.getRootOrgId());
-
-		Map<String, String> properties = domain.getProperties();
-		if (null == properties) {
-			properties = Maps.newHashMap();
-		}
-		info.setProperties(domain.getProperties());
-
-		ExamOrgSettingsEntity ret = examService.saveExamOrg(info);
-		return ret;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @param orgId
-	 */
-	@ApiOperation(value = "删除考试相关的学习中心设置", notes = "")
-	@DeleteMapping("examOrg/{examId}/{orgId}")
-	public void deleteExamOrg(@PathVariable Long examId, @PathVariable Long orgId) {
-		ExamEntity examEntity = examRepo.findOne(examId);
-		if (null == examEntity) {
-			throw new StatusException("E-001250", "examId is wrong");
-		}
-		validateRootOrgIsolation(examEntity.getRootOrgId());
-
-		examOrgSettingsRepo.deleteByExamIdAndOrgId(examId, orgId);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param request
-	 * @param examId
-	 * @return
-	 */
-	@ApiOperation(value = "考试IP限制", notes = "")
-	@GetMapping("ipLimit/{examId}")
-	public Map<String, Object> ipLimit(HttpServletRequest request, @PathVariable Long examId) {
-		ExamEntity exam = examRepo.findOne(examId);
-		if (null == exam) {
-			throw new StatusException("E-001010", "考试不存在");
-		}
-
-		Map<String, Object> map = Maps.newHashMap();
-
-		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
-		ExamPropertyEntity ipLimitProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
-				manager.getByName("IP_LIMIT").getId());
-
-		Boolean ipLimit = null;
-		if (null != ipLimitProperty) {
-			ipLimit = "true".equalsIgnoreCase(ipLimitProperty.getValue());
-		}
-
-		if (null == ipLimit || !ipLimit) {
-			map.put("limited", false);
-			map.put("desc", "未配置IP限制");
-			return map;
-		}
-
-		String realIp = request.getHeader("x-forwarded-for");
-		if (StringUtils.isBlank(realIp)) {
-			realIp = request.getHeader("x-real-ip");
-		}
-		if (StringUtils.isBlank(realIp)) {
-			map.put("limited", true);
-			map.put("desc", "网络受限");
-			return map;
-		}
-		realIp = realIp.trim();
-
-		ExamPropertyEntity ipAddressesProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
-				manager.getByName("IP_ADDRESSES").getId());
-
-		String ipAddresses = null;
-		if (null != ipAddressesProperty) {
-			ipAddresses = ipAddressesProperty.getValue();
-		}
-
-		boolean limited = true;
-		if (StringUtils.isNotBlank(ipAddresses)) {
-			String[] arr = StringUtils.split(ipAddresses, ';');
-
-			for (String cur : arr) {
-				String ip = StringUtils.replace(cur.trim(), ".", "\\.");
-				ip = StringUtils.replace(ip, "*", "\\w+");
-				if (realIp.matches(ip)) {
-					limited = false;
-					map.put("desc", "IP段配置放行");
-					break;
-				}
-			}
-		}
-
-		User accessUser = getAccessUser();
-		StudentBean student = getStudent(accessUser.getUserId());
-		Long orgId = student.getOrgId();
-
-		if (limited) {
-			String key = "IP_" + orgId;
-			String value = redisClient.get(key, String.class);
-			if (null == value) {
-				map.put("desc", "无机构管理员登录");
-			} else {
-				@SuppressWarnings("unchecked")
-				Set<String> userKeyList = JsonUtil.fromJson(value, Set.class);
-
-				for (String userKey : userKeyList) {
-					User curUser = redisClient.get(userKey, User.class);
-					if (null != curUser) {
-						String clientIp = curUser.getClientIp();
-						if (null != clientIp) {
-							// IP取前三段
-							clientIp = clientIp.substring(0, clientIp.lastIndexOf(".") + 1);
-							if (realIp.startsWith(clientIp)) {
-								limited = false;
-								map.put("desc", "机构管理员[key=" + userKey + "]登录放行");
-								break;
-							}
-						}
-					}
-
-				}
-			}
-		}
-
-		map.put("limited", limited);
-
-		return map;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param studentId
-	 * @return
-	 */
-	private StudentBean getStudent(Long studentId) {
-		GetStudentReq req = new GetStudentReq();
-		req.setStudentId(studentId);
-		GetStudentResp resp = studentCloudService.getStudent(req);
-		StudentBean studentInfo = resp.getStudentInfo();
-		return studentInfo;
-	}
-
-}
+package cn.com.qmth.examcloud.core.examwork.api.controller;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.persistence.criteria.Subquery;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+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.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import cn.com.qmth.examcloud.commons.base.exception.StatusException;
+import cn.com.qmth.examcloud.commons.base.helpers.DynamicEnum;
+import cn.com.qmth.examcloud.commons.base.helpers.DynamicEnumManager;
+import cn.com.qmth.examcloud.commons.base.util.JsonUtil;
+import cn.com.qmth.examcloud.commons.base.util.RegExpUtil;
+import cn.com.qmth.examcloud.commons.web.enums.DataExecutionStatus;
+import cn.com.qmth.examcloud.commons.web.helpers.page.PageInfo;
+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.basic.api.OrgCloudService;
+import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
+import cn.com.qmth.examcloud.core.basic.api.bean.OrgBean;
+import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
+import cn.com.qmth.examcloud.core.basic.api.request.GetOrgReq;
+import cn.com.qmth.examcloud.core.basic.api.request.GetStudentReq;
+import cn.com.qmth.examcloud.core.basic.api.response.GetOrgResp;
+import cn.com.qmth.examcloud.core.basic.api.response.GetStudentResp;
+import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamCourseGroupDomain;
+import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamDomain;
+import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamOrgSettingsDomain;
+import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseGroupRelationRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseGroupSettingsRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamCourseRelationRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgPropertyRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamOrgSettingsRepo;
+import cn.com.qmth.examcloud.core.examwork.dao.ExamPaperTypeRelationRepo;
+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.ExamCourseGroupRelationEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamCourseGroupSettingsEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamCourseRelationEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgPropertyEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgSettingsEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPaperTypeRelationEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamStudentEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.enums.ExamType;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamOrgSettingsInfo;
+import cn.com.qmth.examcloud.core.examwork.service.impl.ExamServiceImpl;
+import cn.com.qmth.examcloud.core.examwork.service.impl.ExamStudentServiceImpl;
+import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
+import cn.com.qmth.examcloud.core.oe.admin.api.request.CheckExamIsStartedReq;
+import cn.com.qmth.examcloud.core.oe.admin.api.response.CheckExamIsStartedResp;
+import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
+import cn.com.qmth.examcloud.task.api.request.SyncExamReq;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * 重构
+ *
+ * @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;
+
+	@Autowired
+	ExamRepo examRepo;
+
+	@Autowired
+	ExamServiceImpl examService;
+
+	@Autowired
+	ExamStudentRepo examStudentRepo;
+
+	@Autowired
+	ExamStudentServiceImpl examStudentService;
+
+	@Autowired
+	ExamCourseGroupSettingsRepo examCourseGroupSettingsRepo;
+
+	@Autowired
+	ExamOrgSettingsRepo examOrgSettingsRepo;
+
+	@Autowired
+	ExamCourseGroupRelationRepo examCourseGroupRelationRepo;
+
+	@Autowired
+	OrgCloudService orgCloudService;
+
+	@Autowired
+	ExamOrgPropertyRepo examOrgPropertyRepo;
+
+	@Autowired
+	StudentCloudService studentCloudService;
+
+	@Autowired
+	ExamCourseRelationRepo examCourseRelationRepo;
+
+	@Autowired
+	ExamPaperTypeRelationRepo examPaperTypeRelationRepo;
+
+	@Autowired
+	ExamRecordCloudService examRecordCloudService;
+
+	@Autowired
+	DataSyncCloudService dataSyncCloudService;
+
+	@ApiOperation(value = "查询考试课程的试卷类型集合")
+	@GetMapping("queryExamCoursePaperTypeList")
+	public List<ExamPaperTypeRelationEntity> queryExamCoursePaperTypeList(
+			@RequestParam(required = true) Long examId,
+			@RequestParam(required = true) Long courseId) {
+
+		if (null == examId) {
+			throw new StatusException("E-001251", "examId is null");
+		}
+		if (null == courseId) {
+			throw new StatusException("E-001252", "courseId is null");
+		}
+		ExamEntity one = examRepo.findOne(examId);
+		if (null == one) {
+			throw new StatusException("E-001253", "examId is wrong");
+		}
+
+		validateRootOrgIsolation(one.getRootOrgId());
+
+		List<ExamPaperTypeRelationEntity> list = examPaperTypeRelationRepo
+				.findByExamIdAndCourseId(examId, courseId);
+
+		return list;
+	}
+
+	@ApiOperation(value = "查询考试的课程集合")
+	@GetMapping("queryExamCourseList")
+	public List<ExamCourseRelationEntity> getExamCourseList(
+			@RequestParam(required = true) Long examId, @RequestParam(required = false) String name,
+			@RequestParam(required = false) String level,
+			@RequestParam(required = false) Boolean enable) {
+
+		ExamEntity one = examRepo.findOne(examId);
+		if (null == one) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(one.getRootOrgId());
+
+		Specification<ExamCourseRelationEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+
+			predicates.add(cb.equal(root.get("examId"), examId));
+
+			Predicate pr1 = cb.like(root.get("courseName"), toSqlSearchPattern(name));
+			Predicate pr2 = cb.like(root.get("courseCode"), toSqlSearchPattern(name));
+
+			predicates.add(cb.or(pr1, pr2));
+
+			if (StringUtils.isNotBlank(level)) {
+				predicates.add(cb.equal(root.get("level"), toSqlSearchPattern(level)));
+			}
+
+			if (null != enable) {
+				predicates.add(cb.equal(root.get("courseEnable"), enable));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		PageRequest pageRequest = new PageRequest(0, 50, new Sort(Direction.DESC, "updateTime"));
+
+		Page<ExamCourseRelationEntity> page = examCourseRelationRepo.findAll(specification,
+				pageRequest);
+
+		Iterator<ExamCourseRelationEntity> iterator = page.iterator();
+		List<ExamCourseRelationEntity> list = Lists.newArrayList();
+
+		while (iterator.hasNext()) {
+			ExamCourseRelationEntity next = iterator.next();
+			list.add(next);
+		}
+
+		return list;
+
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param curPage
+	 * @param pageSize
+	 * @param name
+	 * @param examType
+	 * @param enable
+	 * @return
+	 */
+	@ApiOperation(value = "分页查询考试批次")
+	@GetMapping("queryPage/{curPage}/{pageSize}")
+	public PageInfo<ExamDomain> queryPage(@PathVariable Integer curPage,
+			@PathVariable Integer pageSize, @RequestParam(required = false) String name,
+			@RequestParam(required = false) String examType,
+			@RequestParam(required = false) Boolean enable,
+			@RequestParam(required = false) String propertyKeys) {
+
+		User accessUser = getAccessUser();
+
+		Specification<ExamEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+			predicates.add(cb.equal(root.get("rootOrgId"), accessUser.getRootOrgId()));
+			if (StringUtils.isNotBlank(name)) {
+				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+			}
+			if (null != enable) {
+				predicates.add(cb.equal(root.get("enable"), enable));
+			}
+			if (StringUtils.isNotBlank(examType)) {
+				predicates.add(cb.equal(root.get("examType"), ExamType.valueOf(examType)));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		PageRequest pageRequest = new PageRequest(curPage, pageSize,
+				new Sort(Direction.DESC, "updateTime"));
+
+		Page<ExamEntity> page = examRepo.findAll(specification, pageRequest);
+
+		Iterator<ExamEntity> iterator = page.iterator();
+		List<ExamDomain> list = Lists.newArrayList();
+
+		List<String> propertyKeyList = null;
+		if (StringUtils.isNotBlank(propertyKeys)) {
+			propertyKeyList = RegExpUtil.findAll(propertyKeys, "\\w+");
+		}
+
+		while (iterator.hasNext()) {
+			ExamEntity next = iterator.next();
+			ExamDomain bean = new ExamDomain();
+			list.add(bean);
+
+			bean.setId(next.getId());
+			bean.setName(next.getName());
+			bean.setEnable(next.getEnable());
+			bean.setRootOrgId(next.getRootOrgId());
+			bean.setBeginTime(next.getBeginTime());
+			bean.setEndTime(next.getEndTime());
+			bean.setExamType(next.getExamType());
+			bean.setDuration(next.getDuration());
+			bean.setEnable(next.getEnable());
+			bean.setRemark(next.getRemark());
+			bean.setExamTimes(next.getExamTimes());
+			bean.setCreationTime(next.getCreationTime());
+			bean.setUpdateTime(next.getUpdateTime());
+			bean.setExamLimit(next.getExamLimit());
+
+			if (CollectionUtils.isNotEmpty(propertyKeyList)) {
+				Map<String, String> properties = getProperties(bean.getId(), propertyKeyList);
+				bean.setProperties(properties);
+			}
+		}
+
+		PageInfo<ExamDomain> ret = new PageInfo<ExamDomain>(page, list);
+		return ret;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param name
+	 * @param examTypes
+	 * @param enable
+	 * @param studentId
+	 *            筛选学生关联的考试
+	 * @return
+	 */
+	@ApiOperation(value = "查询考试批次")
+	@GetMapping("queryByNameLike")
+	public List<ExamDomain> query(@RequestParam(required = true) String name,
+			@RequestParam(required = false) String examTypes,
+			@RequestParam(required = false) Boolean enable,
+			@RequestParam(required = false) String propertyKeys,
+			@RequestParam(required = false) Long studentId,
+			@RequestParam(required = false) Long rootOrgId) {
+
+		if (null == rootOrgId) {
+			rootOrgId = getRootOrgId();
+		}
+		final Long finalRootOrgId = rootOrgId;
+
+		Specification<ExamEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+			predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
+			if (StringUtils.isNotBlank(name)) {
+				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+			}
+			if (null != enable) {
+				predicates.add(cb.equal(root.get("enable"), enable));
+			}
+			if (StringUtils.isNotBlank(examTypes)) {
+				List<String> examTypeList = RegExpUtil.findAll(examTypes, "\\w+");
+
+				List<ExamType> etList = Lists.newArrayList();
+				for (String cur : examTypeList) {
+					etList.add(ExamType.valueOf(cur));
+				}
+
+				if (CollectionUtils.isNotEmpty(etList)) {
+					if (10 < examTypeList.size()) {
+						throw new StatusException("E-001120", "too many examTypes");
+					}
+					if (1 == examTypeList.size()) {
+						predicates.add(cb.equal(root.get("examType"), etList.get(0)));
+					} else {
+						predicates.add(root.get("examType").in(etList));
+					}
+				}
+			}
+
+			if (null != studentId) {
+				Subquery<ExamStudentEntity> subquery = query.subquery(ExamStudentEntity.class);
+				Root<ExamStudentEntity> subRoot = subquery.from(ExamStudentEntity.class);
+				subquery.select(subRoot.get("id"));
+				Predicate p1 = cb.equal(subRoot.get("studentId"), studentId);
+				Predicate p2 = cb.equal(subRoot.get("examId"), root.get("id"));
+				subquery.where(cb.and(p1, p2));
+				predicates.add(cb.exists(subquery));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		PageRequest pageRequest = new PageRequest(0, 100, new Sort(Direction.DESC, "updateTime"));
+		Page<ExamEntity> page = examRepo.findAll(specification, pageRequest);
+
+		Iterator<ExamEntity> iterator = page.iterator();
+		List<ExamDomain> list = Lists.newArrayList();
+
+		List<String> propertyKeyList = null;
+		if (StringUtils.isNotBlank(propertyKeys)) {
+			propertyKeyList = RegExpUtil.findAll(propertyKeys, "\\w+");
+		}
+
+		while (iterator.hasNext()) {
+			ExamEntity next = iterator.next();
+			ExamDomain bean = new ExamDomain();
+			list.add(bean);
+
+			bean.setId(next.getId());
+			bean.setName(next.getName());
+			bean.setEnable(next.getEnable());
+			bean.setRootOrgId(next.getRootOrgId());
+			bean.setBeginTime(next.getBeginTime());
+			bean.setEndTime(next.getEndTime());
+			bean.setExamType(next.getExamType());
+
+			if (CollectionUtils.isNotEmpty(propertyKeyList)) {
+				Map<String, String> properties = getProperties(bean.getId(), propertyKeyList);
+				bean.setProperties(properties);
+			}
+		}
+
+		return list;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @param propertyKeys
+	 * @return
+	 */
+	private Map<String, String> getProperties(Long examId, List<String> propertyKeys) {
+		Map<String, String> map = Maps.newHashMap();
+		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
+
+		for (String key : propertyKeys) {
+			DynamicEnum de = manager.getByName(key);
+			ExamPropertyEntity one = examPropertyRepo.findByexamIdAndKeyId(examId, de.getId());
+			if (null != one) {
+				map.put(key, one.getValue());
+			}
+		}
+
+		return map;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "按ID查询考试批次", notes = "ID查询")
+	@GetMapping("{examId}")
+	public ExamDomain getExamById(@PathVariable Long examId) {
+		ExamEntity one = examRepo.findOne(examId);
+		if (null == one) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(one.getRootOrgId());
+
+		ExamDomain domain = new ExamDomain();
+		domain.setBeginTime(one.getBeginTime());
+		domain.setDuration(one.getDuration());
+		domain.setEnable(one.getEnable());
+		domain.setEndTime(one.getEndTime());
+		domain.setExamTimes(one.getExamTimes());
+		domain.setExamType(one.getExamType());
+		domain.setId(one.getId());
+		domain.setName(one.getName());
+		domain.setRemark(one.getRemark());
+		domain.setRootOrgId(one.getRootOrgId());
+		domain.setStarted(isStarted(one.getId()));
+		return domain;
+	}
+
+	/**
+	 * 是否开考
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	private boolean isStarted(Long examId) {
+		CheckExamIsStartedReq checkExamIsStartedReq = new CheckExamIsStartedReq();
+		checkExamIsStartedReq.setExamId(examId);
+		try {
+			CheckExamIsStartedResp checkExamIsStartedResp = examRecordCloudService
+					.checkExamIsStarted(checkExamIsStartedReq);
+			return checkExamIsStartedResp.getIsStarted();
+		} catch (Exception e) {
+			log.error("fail to rmi[oe.examRecordCloudService.checkExamIsStarted]", e);
+			return true;
+		}
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
+	@ApiOperation(value = "新增考试批次", notes = "新增")
+	@PostMapping()
+	public ExamEntity addExam(@RequestBody ExamDomain domain) {
+		return saveExam(domain, DataExecutionStatus.CREATION);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
+	@ApiOperation(value = "更新考试批次", notes = "更新")
+	@PutMapping()
+	public ExamEntity updateExam(@RequestBody ExamDomain domain) {
+		return saveExam(domain, DataExecutionStatus.UPDATE);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
+	private ExamEntity saveExam(ExamDomain domain, DataExecutionStatus es) {
+		trim(domain, false);
+
+		User accessUser = getAccessUser();
+
+		ExamInfo examInfo = new ExamInfo();
+		examInfo.setBeginTime(domain.getBeginTime());
+		examInfo.setDuration(domain.getDuration());
+		examInfo.setEnable(domain.getEnable());
+		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());
+		examInfo.setExamLimit(domain.getExamLimit());
+
+		Map<String, String> properties = domain.getProperties();
+		if (null == properties) {
+			properties = Maps.newHashMap();
+		}
+		examInfo.setProperties(properties);
+
+		ExamEntity saved = examService.saveExam(examInfo, es);
+
+		return saved;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "查询考试批次所有属性")
+	@GetMapping("allProperties/{examId}")
+	public Map<String, String> getAllExamProperties(@PathVariable Long examId) {
+
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		Map<String, String> map = Maps.newHashMap();
+		List<ExamPropertyEntity> list = examPropertyRepo.findByexamId(examId);
+		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
+		for (ExamPropertyEntity cur : list) {
+			DynamicEnum de = manager.getById(cur.getKeyId());
+			map.put(de.getName(), cur.getValue());
+		}
+
+		return map;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "查询考试批次单个属性")
+	@GetMapping("property/{examId}/{key}")
+	public String getExamProperty(@PathVariable Long examId, @PathVariable String key) {
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
+		DynamicEnum de = manager.getByName(key);
+		ExamPropertyEntity one = examPropertyRepo.findByexamIdAndKeyId(examId, de.getId());
+		if (null == one) {
+			return null;
+		}
+		return one.getValue();
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "查询考生考试批次单个属性")
+	@GetMapping("examOrgProperty/{examId}/{key}")
+	public String getExamOrgProperty(@PathVariable Long examId, @PathVariable String key) {
+		User accessUser = getAccessUser();
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		StudentBean student = getStudent(accessUser.getUserId());
+		Long orgId = student.getOrgId();
+
+		return examService.getOrgProperty(examId, orgId, key);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "查询考试批次机构属性")
+	@GetMapping("examOrgProperty/{examId}/{orgId}/{key}")
+	public String getExamOrgProperty(@PathVariable Long examId, @PathVariable Long orgId,
+			@PathVariable String key) {
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		if (null == orgId) {
+			throw new StatusException("E-001251", "orgId is null");
+		}
+
+		GetOrgReq getOrgReq = new GetOrgReq();
+		getOrgReq.setOrgId(orgId);
+		GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
+		validateRootOrgIsolation(getOrgResp.getOrg().getRootId());
+
+		return examService.getOrgProperty(examId, orgId, key);
+	}
+
+	@ApiOperation(value = "启用考试", notes = "启用考试")
+	@PutMapping("enable/{ids}")
+	public void enableUser(@PathVariable String ids) {
+		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+				.collect(Collectors.toList());
+		for (Long examId : examIds) {
+			ExamEntity exam = examRepo.findOne(examId);
+			exam.setEnable(true);
+			examRepo.save(exam);
+		}
+
+		for (Long examId : examIds) {
+			ExamEntity exam = examRepo.findOne(examId);
+			SyncExamReq req = new SyncExamReq();
+			req.setId(exam.getId());
+			req.setBeginTime(exam.getBeginTime());
+			req.setDuration(exam.getDuration());
+			req.setEnable(exam.getEnable());
+			req.setEndTime(exam.getEndTime());
+			req.setExamTimes(exam.getExamTimes());
+			req.setExamType(exam.getExamType().name());
+			req.setName(exam.getName());
+			req.setRemark(exam.getRemark());
+			req.setRootOrgId(exam.getRootOrgId());
+
+			GetOrgReq getOrgReq = new GetOrgReq();
+			getOrgReq.setOrgId(exam.getRootOrgId());
+			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
+			OrgBean rootOrg = getOrgResp.getOrg();
+			req.setRootOrgName(rootOrg.getName());
+
+			req.setSyncType("update");
+			dataSyncCloudService.syncExam(req);
+		}
+
+	}
+
+	@ApiOperation(value = "禁用考试", notes = "禁用考试")
+	@PutMapping("disable/{ids}")
+	public void disableUser(@PathVariable String ids) {
+		List<Long> examIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+				.collect(Collectors.toList());
+		for (Long examId : examIds) {
+			ExamEntity exam = examRepo.findOne(examId);
+			exam.setEnable(false);
+			examRepo.save(exam);
+		}
+
+		for (Long examId : examIds) {
+			ExamEntity exam = examRepo.findOne(examId);
+			SyncExamReq req = new SyncExamReq();
+			req.setId(exam.getId());
+			req.setBeginTime(exam.getBeginTime());
+			req.setDuration(exam.getDuration());
+			req.setEnable(exam.getEnable());
+			req.setEndTime(exam.getEndTime());
+			req.setExamTimes(exam.getExamTimes());
+			req.setExamType(exam.getExamType().name());
+			req.setName(exam.getName());
+			req.setRemark(exam.getRemark());
+			req.setRootOrgId(exam.getRootOrgId());
+
+			GetOrgReq getOrgReq = new GetOrgReq();
+			getOrgReq.setOrgId(exam.getRootOrgId());
+			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
+			OrgBean rootOrg = getOrgResp.getOrg();
+			req.setRootOrgName(rootOrg.getName());
+
+			req.setSyncType("update");
+			dataSyncCloudService.syncExam(req);
+		}
+
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @param curPage
+	 * @param pageSize
+	 * @return
+	 */
+	@ApiOperation(value = "查询课程组集合", notes = "")
+	@GetMapping("getCourseGroupListByExamId/{examId}/{curPage}/{pageSize}")
+	public List<ExamCourseGroupDomain> getCourseGroupListByExamId(@PathVariable Long examId,
+			@PathVariable Integer curPage, @PathVariable Integer pageSize) {
+
+		Pageable pageable = new PageRequest(curPage - 1, pageSize, Sort.Direction.DESC,
+				"updateTime");
+		List<ExamCourseGroupSettingsEntity> groupList = examCourseGroupSettingsRepo
+				.findAllByExamId(examId, pageable);
+
+		List<ExamCourseGroupDomain> ret = Lists.newArrayList();
+
+		for (ExamCourseGroupSettingsEntity curCourseGroup : groupList) {
+			ExamCourseGroupDomain bean = new ExamCourseGroupDomain();
+			bean.setBeginTime(curCourseGroup.getBeginTime());
+			bean.setCreationTime(curCourseGroup.getCreationTime());
+			bean.setDescription(curCourseGroup.getDescription());
+			bean.setEndTime(curCourseGroup.getEndTime());
+			bean.setExamId(curCourseGroup.getExamId());
+			bean.setId(curCourseGroup.getId());
+			bean.setName(curCourseGroup.getName());
+			bean.setUpdateTime(curCourseGroup.getUpdateTime());
+
+			List<Long> courseIdList = Lists.newArrayList();
+			bean.setCourseIdList(courseIdList);
+
+			List<ExamCourseGroupRelationEntity> relationList = examCourseGroupRelationRepo
+					.findAllByGroupId(bean.getId());
+
+			for (ExamCourseGroupRelationEntity cur : relationList) {
+				courseIdList.add(cur.getCourseId());
+			}
+
+			ret.add(bean);
+		}
+
+		return ret;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @param courseId
+	 * @return
+	 */
+	@ApiOperation(value = "通过课程ID查询课程组集合", notes = "")
+	@GetMapping("getCourseGroupListByExamIdAndCourseId/{examId}/{courseId}")
+	public List<ExamCourseGroupDomain> getCourseGroupListByExamIdAndCourseId(
+			@PathVariable Long examId, @PathVariable Long courseId) {
+
+		List<ExamCourseGroupRelationEntity> relationList = examCourseGroupRelationRepo
+				.findAllByCourseIdAndExamId(courseId, examId);
+
+		List<Long> groupIdList = Lists.newArrayList();
+		for (ExamCourseGroupRelationEntity cur : relationList) {
+			Long groupId = cur.getGroupId();
+			groupIdList.add(groupId);
+		}
+
+		List<ExamCourseGroupSettingsEntity> groupList = examCourseGroupSettingsRepo
+				.findAllByIdInOrderByUpdateTimeDesc(groupIdList);
+
+		List<ExamCourseGroupDomain> ret = Lists.newArrayList();
+
+		for (ExamCourseGroupSettingsEntity curCourseGroup : groupList) {
+			ExamCourseGroupDomain bean = new ExamCourseGroupDomain();
+			bean.setBeginTime(curCourseGroup.getBeginTime());
+			bean.setCreationTime(curCourseGroup.getCreationTime());
+			bean.setDescription(curCourseGroup.getDescription());
+			bean.setEndTime(curCourseGroup.getEndTime());
+			bean.setExamId(curCourseGroup.getExamId());
+			bean.setId(curCourseGroup.getId());
+			bean.setName(curCourseGroup.getName());
+			bean.setUpdateTime(curCourseGroup.getUpdateTime());
+
+			List<Long> courseIdList = Lists.newArrayList();
+			bean.setCourseIdList(courseIdList);
+
+			List<ExamCourseGroupRelationEntity> curRelationList = examCourseGroupRelationRepo
+					.findAllByGroupId(bean.getId());
+
+			for (ExamCourseGroupRelationEntity cur : curRelationList) {
+				courseIdList.add(cur.getCourseId());
+			}
+		}
+
+		return ret;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param courseGroupBean
+	 * @param request
+	 */
+	@ApiOperation(value = "更新课程组", notes = "")
+	@PutMapping("courseGroup")
+	public void updateCourseGroup(@RequestBody ExamCourseGroupDomain courseGroupBean,
+			HttpServletRequest request) {
+
+		ExamCourseGroupSettingsEntity courseGroup = new ExamCourseGroupSettingsEntity();
+		courseGroup.setBeginTime(courseGroupBean.getBeginTime());
+		courseGroup.setCreationTime(courseGroupBean.getCreationTime());
+		courseGroup.setDescription(courseGroupBean.getDescription());
+		courseGroup.setEndTime(courseGroupBean.getEndTime());
+		courseGroup.setExamId(courseGroupBean.getExamId());
+		courseGroup.setId(courseGroupBean.getId());
+		courseGroup.setName(courseGroupBean.getName());
+		courseGroup.setUpdateTime(courseGroupBean.getUpdateTime());
+
+		examCourseGroupSettingsRepo.save(courseGroup);
+		List<Long> courseIdList = courseGroupBean.getCourseIdList();
+
+		List<ExamCourseGroupRelationEntity> relationList = Lists.newArrayList();
+
+		examCourseGroupRelationRepo.deleteByGroupId(courseGroup.getId());
+
+		for (Long cur : courseIdList) {
+			ExamCourseGroupRelationEntity relation = new ExamCourseGroupRelationEntity();
+			relation.setCourseId(cur);
+			relation.setExamId(courseGroupBean.getExamId());
+			relation.setGroupId(courseGroup.getId());
+			relationList.add(relation);
+		}
+		examCourseGroupRelationRepo.save(relationList);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param id
+	 */
+	@ApiOperation(value = "删除课程组", notes = "")
+	@DeleteMapping("courseGroup/{id}")
+	public void deleteCourseGroup(@PathVariable Long id) {
+		examCourseGroupSettingsRepo.delete(id);
+		examCourseGroupRelationRepo.deleteByGroupId(id);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param curPage
+	 * @param pageSize
+	 * @param examOrgDomain
+	 * @return
+	 */
+	@ApiOperation(value = "查询考试相关的学习中心设置", notes = "")
+	@GetMapping("getExamOrgSettingsList/{curPage}/{pageSize}")
+	public PageInfo<ExamOrgSettingsDomain> getExamOrgSettingsList(@PathVariable Integer curPage,
+			@PathVariable Integer pageSize, @ModelAttribute ExamOrgSettingsDomain examOrgDomain) {
+
+		Long examId = examOrgDomain.getExamId();
+		if (null == examOrgDomain.getExamId()) {
+			throw new StatusException("E-001210", "examId is null");
+		}
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		Specification<ExamOrgSettingsEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+
+			predicates.add(cb.equal(root.get("examId"), examOrgDomain.getExamId()));
+
+			if (null != examOrgDomain.getOrgId()) {
+				predicates.add(cb.equal(root.get("orgId"), examOrgDomain.getOrgId()));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		Pageable pageable = new PageRequest(curPage, pageSize, Sort.Direction.DESC, "updateTime");
+		Page<ExamOrgSettingsEntity> page = examOrgSettingsRepo.findAll(specification, pageable);
+
+		Iterator<ExamOrgSettingsEntity> iterator = page.iterator();
+		List<ExamOrgSettingsDomain> domainList = Lists.newArrayList();
+
+		while (iterator.hasNext()) {
+			ExamOrgSettingsEntity next = iterator.next();
+			ExamOrgSettingsDomain bean = new ExamOrgSettingsDomain();
+			domainList.add(bean);
+
+			bean.setBeginTime(next.getBeginTime());
+			bean.setEndTime(next.getEndTime());
+			bean.setExamId(next.getExamId());
+			bean.setId(next.getId());
+			bean.setOrgId(next.getOrgId());
+			bean.setRootOrgId(next.getRootOrgId());
+			bean.setUpdateTime(next.getUpdateTime());
+			bean.setExamLimit(next.getExamLimit());
+
+			GetOrgReq getOrgReq = new GetOrgReq();
+			getOrgReq.setOrgId(bean.getOrgId());
+			GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
+			OrgBean org = getOrgResp.getOrg();
+			bean.setOrgName(org.getName());
+			bean.setOrgCode(org.getCode());
+
+			List<ExamOrgPropertyEntity> propList = examOrgPropertyRepo
+					.findByexamIdAndOrgId(next.getExamId(), next.getOrgId());
+
+			Map<String, String> map = Maps.newHashMap();
+			DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
+			for (ExamOrgPropertyEntity cur : propList) {
+				DynamicEnum de = manager.getById(cur.getKeyId());
+				map.put(de.getName(), cur.getValue());
+			}
+
+			bean.setProperties(map);
+		}
+
+		PageInfo<ExamOrgSettingsDomain> ret = new PageInfo<ExamOrgSettingsDomain>();
+		ret.setList(domainList);
+		ret.setTotal(page.getTotalElements());
+		return ret;
+	}
+
+	@ApiOperation(value = "查询考生考试机构配置", notes = "")
+	@PostMapping("examOrgSettings/{examId}")
+	public ExamDomain getExamOrgSettings(@PathVariable Long examId) {
+		User accessUser = getAccessUser();
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		StudentBean student = getStudent(accessUser.getUserId());
+		Long orgId = student.getOrgId();
+
+		ExamOrgSettingsEntity examOrgEntity = examOrgSettingsRepo.findByExamIdAndOrgId(examId,
+				orgId);
+
+		ExamDomain domain = new ExamDomain();
+		domain.setBeginTime(examEntity.getBeginTime());
+		domain.setDuration(examEntity.getDuration());
+		domain.setEnable(examEntity.getEnable());
+		domain.setEndTime(examEntity.getEndTime());
+		domain.setExamTimes(examEntity.getExamTimes());
+		domain.setExamType(examEntity.getExamType());
+		domain.setId(examEntity.getId());
+		domain.setName(examEntity.getName());
+		domain.setRemark(examEntity.getRemark());
+		domain.setRootOrgId(examEntity.getRootOrgId());
+		domain.setStarted(examEntity.getBeginTime().before(new Date()));
+
+		if (null != examOrgEntity) {
+			if (null != examOrgEntity.getBeginTime()) {
+				domain.setBeginTime(examOrgEntity.getBeginTime());
+			}
+			if (null != examOrgEntity.getEndTime()) {
+				domain.setEndTime(examOrgEntity.getEndTime());
+			}
+			if (null != examOrgEntity.getExamLimit()) {
+				domain.setExamLimit(examOrgEntity.getExamLimit());
+			}
+		}
+
+		return domain;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examOrg
+	 * @return
+	 */
+	@ApiOperation(value = "新增考试相关的学习中心设置", notes = "")
+	@PostMapping("examOrgSettings")
+	public ExamOrgSettingsEntity addExamOrgSettings(@RequestBody ExamOrgSettingsDomain domain) {
+		return saveExamOrgSettings(domain);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examOrg
+	 * @return
+	 */
+	@ApiOperation(value = "更新考试相关的学习中心设置", notes = "")
+	@PutMapping("examOrgSettings")
+	public ExamOrgSettingsEntity updateExamOrgSettings(@RequestBody ExamOrgSettingsDomain domain) {
+		return saveExamOrgSettings(domain);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param domain
+	 * @return
+	 */
+	private ExamOrgSettingsEntity saveExamOrgSettings(ExamOrgSettingsDomain domain) {
+		Long examId = domain.getExamId();
+
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		Long orgId = domain.getOrgId();
+
+		GetOrgReq getOrgReq = new GetOrgReq();
+		getOrgReq.setOrgId(orgId);
+		GetOrgResp getOrgResp = orgCloudService.getOrg(getOrgReq);
+		OrgBean org = getOrgResp.getOrg();
+		org.getRootId();
+		validateRootOrgIsolation(org.getRootId());
+
+		User accessUser = getAccessUser();
+		ExamOrgSettingsInfo info = new ExamOrgSettingsInfo();
+		info.setId(domain.getId());
+		info.setBeginTime(domain.getBeginTime());
+		info.setEndTime(domain.getEndTime());
+		info.setExamId(domain.getExamId());
+		info.setOrgId(domain.getOrgId());
+		info.setExamLimit(domain.getExamLimit());
+		info.setRootOrgId(accessUser.getRootOrgId());
+
+		Map<String, String> properties = domain.getProperties();
+		if (null == properties) {
+			properties = Maps.newHashMap();
+		}
+		info.setProperties(domain.getProperties());
+
+		ExamOrgSettingsEntity ret = examService.saveExamOrgSettings(info);
+		return ret;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @param orgId
+	 */
+	@ApiOperation(value = "删除考试相关的学习中心设置", notes = "")
+	@DeleteMapping("examOrg/{examId}/{orgId}")
+	public void deleteExamOrg(@PathVariable Long examId, @PathVariable Long orgId) {
+		ExamEntity examEntity = examRepo.findOne(examId);
+		if (null == examEntity) {
+			throw new StatusException("E-001250", "examId is wrong");
+		}
+		validateRootOrgIsolation(examEntity.getRootOrgId());
+
+		examOrgSettingsRepo.deleteByExamIdAndOrgId(examId, orgId);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param request
+	 * @param examId
+	 * @return
+	 */
+	@ApiOperation(value = "考试IP限制", notes = "")
+	@GetMapping("ipLimit/{examId}")
+	public Map<String, Object> ipLimit(HttpServletRequest request, @PathVariable Long examId) {
+		ExamEntity exam = examRepo.findOne(examId);
+		if (null == exam) {
+			throw new StatusException("E-001010", "考试不存在");
+		}
+
+		Map<String, Object> map = Maps.newHashMap();
+
+		DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
+		ExamPropertyEntity ipLimitProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
+				manager.getByName("IP_LIMIT").getId());
+
+		Boolean ipLimit = null;
+		if (null != ipLimitProperty) {
+			ipLimit = "true".equalsIgnoreCase(ipLimitProperty.getValue());
+		}
+
+		if (null == ipLimit || !ipLimit) {
+			map.put("limited", false);
+			map.put("desc", "未配置IP限制");
+			return map;
+		}
+
+		String realIp = request.getHeader("x-forwarded-for");
+		if (StringUtils.isBlank(realIp)) {
+			realIp = request.getHeader("x-real-ip");
+		}
+		if (StringUtils.isBlank(realIp)) {
+			map.put("limited", true);
+			map.put("desc", "网络受限");
+			return map;
+		}
+		realIp = realIp.trim();
+
+		ExamPropertyEntity ipAddressesProperty = examPropertyRepo.findByexamIdAndKeyId(exam.getId(),
+				manager.getByName("IP_ADDRESSES").getId());
+
+		String ipAddresses = null;
+		if (null != ipAddressesProperty) {
+			ipAddresses = ipAddressesProperty.getValue();
+		}
+
+		boolean limited = true;
+		if (StringUtils.isNotBlank(ipAddresses)) {
+			String[] arr = StringUtils.split(ipAddresses, ';');
+
+			for (String cur : arr) {
+				String ip = StringUtils.replace(cur.trim(), ".", "\\.");
+				ip = StringUtils.replace(ip, "*", "\\w+");
+				if (realIp.matches(ip)) {
+					limited = false;
+					map.put("desc", "IP段配置放行");
+					break;
+				}
+			}
+		}
+
+		User accessUser = getAccessUser();
+		StudentBean student = getStudent(accessUser.getUserId());
+		Long orgId = student.getOrgId();
+
+		if (limited) {
+			String key = "IP_" + orgId;
+			String value = redisClient.get(key, String.class);
+			if (null == value) {
+				map.put("desc", "无机构管理员登录");
+			} else {
+				@SuppressWarnings("unchecked")
+				Set<String> userKeyList = JsonUtil.fromJson(value, Set.class);
+
+				for (String userKey : userKeyList) {
+					User curUser = redisClient.get(userKey, User.class);
+					if (null != curUser) {
+						String clientIp = curUser.getClientIp();
+						if (null != clientIp) {
+							// IP取前三段
+							clientIp = clientIp.substring(0, clientIp.lastIndexOf(".") + 1);
+							if (realIp.startsWith(clientIp)) {
+								limited = false;
+								map.put("desc", "机构管理员[key=" + userKey + "]登录放行");
+								break;
+							}
+						}
+					}
+
+				}
+			}
+		}
+
+		map.put("limited", limited);
+
+		return map;
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param studentId
+	 * @return
+	 */
+	private StudentBean getStudent(Long studentId) {
+		GetStudentReq req = new GetStudentReq();
+		req.setStudentId(studentId);
+		GetStudentResp resp = studentCloudService.getStudent(req);
+		StudentBean studentInfo = resp.getStudentInfo();
+		return studentInfo;
+	}
+
+}

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

@@ -1,202 +1,215 @@
-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 Date updateTime;
-
-	/**
-	 * 创建时间
-	 */
-	private Date creationTime;
-
-	/**
-	 * 是否开考
-	 */
-	private Boolean started;
-
-	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;
-	}
-
-	public Boolean getStarted() {
-		return started;
-	}
-
-	public void setStarted(Boolean started) {
-		this.started = started;
-	}
-
-	public Date getUpdateTime() {
-		return updateTime;
-	}
-
-	public void setUpdateTime(Date updateTime) {
-		this.updateTime = updateTime;
-	}
-
-	public Date getCreationTime() {
-		return creationTime;
-	}
-
-	public void setCreationTime(Date creationTime) {
-		this.creationTime = creationTime;
-	}
-
-}
+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 Date updateTime;
+
+	/**
+	 * 创建时间
+	 */
+	private Date creationTime;
+
+	/**
+	 * 是否开考
+	 */
+	private Boolean started;
+
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
+	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;
+	}
+
+	public Boolean getStarted() {
+		return started;
+	}
+
+	public void setStarted(Boolean started) {
+		this.started = started;
+	}
+
+	public Date getUpdateTime() {
+		return updateTime;
+	}
+
+	public void setUpdateTime(Date updateTime) {
+		this.updateTime = updateTime;
+	}
+
+	public Date getCreationTime() {
+		return creationTime;
+	}
+
+	public void setCreationTime(Date creationTime) {
+		this.creationTime = creationTime;
+	}
+
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
+}

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

@@ -53,10 +53,18 @@ public class ExamOrgSettingsDomain implements JsonSerializable {
 	 */
 	private Date endTime;
 
-	private Map<String, String> properties;
-
+	/**
+	 * 更新时间
+	 */
 	private Date updateTime;
 
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
+	private Map<String, String> properties;
+
 	public Long getId() {
 		return id;
 	}
@@ -137,4 +145,12 @@ public class ExamOrgSettingsDomain implements JsonSerializable {
 		this.updateTime = updateTime;
 	}
 
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
 }

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

@@ -137,6 +137,7 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 		examInfo.setName(req.getName());
 		examInfo.setRemark(req.getRemark());
 		examInfo.setRootOrgId(req.getRootOrgId());
+		examInfo.setExamLimit(req.getExamLimit());
 
 		Map<String, String> properties = req.getProperties();
 		examInfo.setProperties(properties);
@@ -190,6 +191,7 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 		bean.setName(exam.getName());
 		bean.setRemark(exam.getRemark());
 		bean.setRootOrgId(exam.getRootOrgId());
+		bean.setExamLimit(exam.getExamLimit());
 
 		Long orgId = req.getOrgId();
 		if (null != orgId) {
@@ -201,6 +203,9 @@ public class ExamCloudServiceProvider extends ControllerSupport implements ExamC
 			if (null != examOrgEntity.getEndTime()) {
 				bean.setEndTime(examOrgEntity.getEndTime());
 			}
+			if (null != examOrgEntity.getExamLimit()) {
+				bean.setExamLimit(examOrgEntity.getExamLimit());
+			}
 		}
 
 		return examResp;

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

@@ -84,6 +84,11 @@ public class ExamEntity extends JpaEntity {
 	 */
 	private Boolean examStudentLocked;
 
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
 	public Long getId() {
 		return id;
 	}
@@ -172,4 +177,12 @@ public class ExamEntity extends JpaEntity {
 		this.examStudentLocked = examStudentLocked;
 	}
 
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
 }

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

@@ -61,6 +61,11 @@ public class ExamOrgSettingsEntity extends JpaEntity {
 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	private Date endTime;
 
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
 	public Long getId() {
 		return id;
 	}
@@ -109,4 +114,12 @@ public class ExamOrgSettingsEntity extends JpaEntity {
 		this.endTime = endTime;
 	}
 
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
 }

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

@@ -1,47 +1,47 @@
-package cn.com.qmth.examcloud.core.examwork.service;
-
-import cn.com.qmth.examcloud.commons.web.enums.DataExecutionStatus;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
-import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgSettingsEntity;
-import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
-import cn.com.qmth.examcloud.core.examwork.service.bean.ExamOrgSettingsInfo;
-
-/**
- * 类注释
- *
- * @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, DataExecutionStatus es);
-
-	/**
-	 * 保存考试机构设置
-	 *
-	 * @author WANGWEI
-	 * @param examInfo
-	 * @return
-	 */
-	ExamOrgSettingsEntity saveExamOrg(ExamOrgSettingsInfo examOrgInfo);
-
-	/**
-	 * 查询机构属性
-	 *
-	 * @author WANGWEI
-	 * @param examId
-	 * @param orgId
-	 * @param key
-	 * @return
-	 */
-	String getOrgProperty(Long examId, Long orgId, String key);
-
-}
+package cn.com.qmth.examcloud.core.examwork.service;
+
+import cn.com.qmth.examcloud.commons.web.enums.DataExecutionStatus;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamEntity;
+import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgSettingsEntity;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamOrgSettingsInfo;
+
+/**
+ * 类注释
+ *
+ * @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, DataExecutionStatus es);
+
+	/**
+	 * 保存考试机构设置
+	 *
+	 * @author WANGWEI
+	 * @param examInfo
+	 * @return
+	 */
+	ExamOrgSettingsEntity saveExamOrgSettings(ExamOrgSettingsInfo examOrgInfo);
+
+	/**
+	 * 查询机构属性
+	 *
+	 * @author WANGWEI
+	 * @param examId
+	 * @param orgId
+	 * @param key
+	 * @return
+	 */
+	String getOrgProperty(Long examId, Long orgId, String key);
+
+}

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

@@ -67,6 +67,14 @@ public class ExamInfo implements JsonSerializable {
 	 */
 	private Long examTimes;
 
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
+	/**
+	 * 考试属性
+	 */
 	private Map<String, String> properties;
 
 	public Long getId() {
@@ -149,6 +157,14 @@ public class ExamInfo implements JsonSerializable {
 		this.examTimes = examTimes;
 	}
 
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
 	public Map<String, String> getProperties() {
 		return properties;
 	}

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

@@ -43,6 +43,11 @@ public class ExamOrgSettingsInfo implements JsonSerializable {
 	 */
 	private Date endTime;
 
+	/**
+	 * 是否禁止考试
+	 */
+	private Boolean examLimit;
+
 	private Map<String, String> properties;
 
 	public Long getId() {
@@ -93,6 +98,14 @@ public class ExamOrgSettingsInfo implements JsonSerializable {
 		this.endTime = endTime;
 	}
 
+	public Boolean getExamLimit() {
+		return examLimit;
+	}
+
+	public void setExamLimit(Boolean examLimit) {
+		this.examLimit = examLimit;
+	}
+
 	public Map<String, String> getProperties() {
 		return properties;
 	}

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

@@ -198,6 +198,9 @@ public class ExamServiceImpl implements ExamService {
 		if (null != examInfo.getExamTimes()) {
 			exam.setExamTimes(examInfo.getExamTimes());
 		}
+		if (null != examInfo.getExamLimit()) {
+			exam.setExamLimit(examInfo.getExamLimit());
+		}
 		exam.setName(examInfo.getName());
 		exam.setRemark(examInfo.getRemark());
 		exam.setRootOrgId(examInfo.getRootOrgId());
@@ -295,7 +298,7 @@ public class ExamServiceImpl implements ExamService {
 	 * com.qmth.examcloud.core.examwork.service.bean.ExamOrgInfo)
 	 */
 	@Override
-	public ExamOrgSettingsEntity saveExamOrg(ExamOrgSettingsInfo examOrgInfo) {
+	public ExamOrgSettingsEntity saveExamOrgSettings(ExamOrgSettingsInfo examOrgInfo) {
 		ExamOrgSettingsEntity examOrgEntity = null;
 
 		if (null == examOrgInfo.getId()) {
@@ -316,6 +319,7 @@ public class ExamServiceImpl implements ExamService {
 		examOrgEntity.setRootOrgId(examOrgInfo.getRootOrgId());
 		examOrgEntity.setExamId(examOrgInfo.getExamId());
 		examOrgEntity.setOrgId(examOrgInfo.getOrgId());
+		examOrgEntity.setExamLimit(examOrgInfo.getExamLimit());
 
 		Map<DynamicEnum, String> map = checkAndGetExamProperties(examOrgInfo.getProperties());