|
@@ -25,6 +25,7 @@ import cn.com.qmth.examcloud.core.basic.api.response.GetOrgResp;
|
|
import cn.com.qmth.examcloud.core.basic.api.response.GetOrgsResp;
|
|
import cn.com.qmth.examcloud.core.basic.api.response.GetOrgsResp;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.CopyExamDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.CopyExamDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamDomain;
|
|
|
|
+import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamIpLimitDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamOrgSettingsDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.ExamOrgSettingsDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.StudentSpecialSettingsDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.api.controller.bean.StudentSpecialSettingsDomain;
|
|
import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
|
|
import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
|
|
@@ -58,10 +59,12 @@ import org.apache.commons.collections.CollectionUtils;
|
|
import org.apache.commons.fileupload.disk.DiskFileItem;
|
|
import org.apache.commons.fileupload.disk.DiskFileItem;
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.data.domain.*;
|
|
import org.springframework.data.domain.*;
|
|
import org.springframework.data.domain.Sort.Direction;
|
|
import org.springframework.data.domain.Sort.Direction;
|
|
import org.springframework.data.jpa.domain.Specification;
|
|
import org.springframework.data.jpa.domain.Specification;
|
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import org.springframework.web.multipart.commons.CommonsMultipartFile;
|
|
import org.springframework.web.multipart.commons.CommonsMultipartFile;
|
|
@@ -107,6 +110,9 @@ public class ExamController extends ControllerSupport {
|
|
@Autowired
|
|
@Autowired
|
|
ExamStudentRepo examStudentRepo;
|
|
ExamStudentRepo examStudentRepo;
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ ExamIpLimitRepo examIpLimitRepo;
|
|
|
|
+
|
|
@Autowired
|
|
@Autowired
|
|
ExamStudentServiceImpl examStudentService;
|
|
ExamStudentServiceImpl examStudentService;
|
|
|
|
|
|
@@ -140,6 +146,9 @@ public class ExamController extends ControllerSupport {
|
|
@Autowired
|
|
@Autowired
|
|
ExamSettingsCache examSettingsCache;
|
|
ExamSettingsCache examSettingsCache;
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ JdbcTemplate jdbcTemplate;
|
|
|
|
+
|
|
private static final String[] EXAM_ORG_SETTINGS_EXCEL_HEADER = new String[]{"学习中心ID", "学习中心代码",
|
|
private static final String[] EXAM_ORG_SETTINGS_EXCEL_HEADER = new String[]{"学习中心ID", "学习中心代码",
|
|
"学习中心名称", "是否可以考试(是/否)", "开始考试时间 yyyy-MM-dd hh:mm:ss", "结束考试时间 yyyy-MM-dd hh:mm:ss"};
|
|
"学习中心名称", "是否可以考试(是/否)", "开始考试时间 yyyy-MM-dd hh:mm:ss", "结束考试时间 yyyy-MM-dd hh:mm:ss"};
|
|
|
|
|
|
@@ -1051,7 +1060,7 @@ public class ExamController extends ControllerSupport {
|
|
/**
|
|
/**
|
|
* 方法注释
|
|
* 方法注释
|
|
*
|
|
*
|
|
- * @param examOrg
|
|
|
|
|
|
+ * @param domain
|
|
* @return
|
|
* @return
|
|
* @author WANGWEI
|
|
* @author WANGWEI
|
|
*/
|
|
*/
|
|
@@ -1065,7 +1074,7 @@ public class ExamController extends ControllerSupport {
|
|
/**
|
|
/**
|
|
* 方法注释
|
|
* 方法注释
|
|
*
|
|
*
|
|
- * @param examOrg
|
|
|
|
|
|
+ * @param domain
|
|
* @return
|
|
* @return
|
|
* @author WANGWEI
|
|
* @author WANGWEI
|
|
*/
|
|
*/
|
|
@@ -1385,6 +1394,107 @@ public class ExamController extends ControllerSupport {
|
|
return map;
|
|
return map;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @GetMapping("ipLimited/page/{curPage}/{pageSize}")
|
|
|
|
+ public PageInfo<ExamIpLimitDomain> ipLimited(@PathVariable Integer curPage, @PathVariable Integer pageSize,
|
|
|
|
+ Long examId, Integer limitType, String ip) {
|
|
|
|
+ PageInfo<ExamIpLimitEntity> pages = examService.pageIpLimited(curPage, pageSize, examId, limitType, ip);
|
|
|
|
+ PageInfo<ExamIpLimitDomain> pageInfo = new PageInfo<>();
|
|
|
|
+ List<ExamIpLimitDomain> list = new ArrayList<>();
|
|
|
|
+ pages.getList().forEach(e->{
|
|
|
|
+ ExamIpLimitDomain domain = new ExamIpLimitDomain();
|
|
|
|
+ BeanUtils.copyProperties(e,domain);
|
|
|
|
+ domain.setExamName(examRepo.getOne(examId).getName());
|
|
|
|
+ list.add(domain);
|
|
|
|
+ });
|
|
|
|
+ pageInfo.setList(list);
|
|
|
|
+ pageInfo.setTotal(pages.getTotal());
|
|
|
|
+ return pageInfo;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GetMapping("ipLimited/property/{examId}")
|
|
|
|
+ public Map<String,Boolean> ipLimitedProperty(@PathVariable Long examId) {
|
|
|
|
+ Map<String,Boolean> map = new HashMap<>();
|
|
|
|
+ map.put("totalLimit", getExamBooleanProperty(examId,49));
|
|
|
|
+ map.put("centerLimit",getExamBooleanProperty(examId,50));
|
|
|
|
+ return map;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @PutMapping("ipLimited/property/{examId}")
|
|
|
|
+ public void ipLimitedProperty(@PathVariable Long examId, @RequestBody Map<String,Boolean> map) {
|
|
|
|
+ updateExamProperty(examId,49,map.get("totalLimit"));
|
|
|
|
+ updateExamProperty(examId,50,map.get("centerLimit"));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateExamProperty(Long examId, Integer keyId, Object value) {
|
|
|
|
+ //虚拟摄像头进入待审核,且有虚拟摄像头的
|
|
|
|
+ String valueSql="update ec_e_exam_prop set value = '"+value+"'where exam_id ="+examId+" AND key_id="+keyId;
|
|
|
|
+ jdbcTemplate.update(valueSql);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GetMapping("ipLimited/{examId}")
|
|
|
|
+ public boolean ipLimited(HttpServletRequest request, @PathVariable Long examId) {
|
|
|
|
+ //是否开启Ip限制
|
|
|
|
+ ExamPropertyCacheBean ipLimitProperty = CacheHelper.getExamProperty(examId, "IP_LIMIT");
|
|
|
|
+ boolean ipLimited = ipLimitProperty!=null && StringUtil.isTrue(ipLimitProperty.getValue());
|
|
|
|
+ if (ipLimited) {
|
|
|
|
+ String realIp = request.getHeader("x-forwarded-for");
|
|
|
|
+ if (StringUtils.isBlank(realIp)) {
|
|
|
|
+ realIp = request.getHeader("x-real-ip");
|
|
|
|
+ }
|
|
|
|
+ realIp = realIp.trim();
|
|
|
|
+ //整体控制
|
|
|
|
+ boolean totalLimit = getExamBooleanProperty(examId,49);
|
|
|
|
+ if (totalLimit) {
|
|
|
|
+ //在白名单中
|
|
|
|
+ int count = examIpLimitRepo.countByExamIdAndLimitTypeAndIp(examId,"0",realIp);
|
|
|
|
+ if (count>0) {
|
|
|
|
+ //学习中心访问控制
|
|
|
|
+ boolean centerLimit = getExamBooleanProperty(examId,50);
|
|
|
|
+ if (centerLimit) {
|
|
|
|
+ User accessUser = getAccessUser();
|
|
|
|
+ StudentCacheBean studentCache = CacheHelper.getStudent(accessUser.getUserId());
|
|
|
|
+ Long orgId = studentCache.getOrgId();
|
|
|
|
+ String key = "IP_" + orgId;
|
|
|
|
+ String value = redisClient.get(key, String.class);
|
|
|
|
+ //机构是否在时间范围内登陆过
|
|
|
|
+ if (value != null) {
|
|
|
|
+ @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)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ //不在黑名单中
|
|
|
|
+ int count = examIpLimitRepo.countByExamIdAndLimitTypeAndIp(examId,"1",realIp);
|
|
|
|
+ return count != 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private boolean getExamBooleanProperty(Long examId,Integer keyId) {
|
|
|
|
+ //虚拟摄像头进入待审核,且有虚拟摄像头的
|
|
|
|
+ String valueSql="SELECT value FROM ec_e_exam_prop WHERE exam_id ="+examId+" AND key_id="+keyId;
|
|
|
|
+ List<Boolean> list = jdbcTemplate.query(valueSql, (rs, rowNum) -> rs.getBoolean("value"));
|
|
|
|
+ return !CollectionUtils.isEmpty(list) && list.get(0);
|
|
|
|
+ }
|
|
|
|
+
|
|
@ApiOperation(value = "是否可以微信作答", notes = "")
|
|
@ApiOperation(value = "是否可以微信作答", notes = "")
|
|
@GetMapping("weixinAnswerEnabled/{examId}")
|
|
@GetMapping("weixinAnswerEnabled/{examId}")
|
|
public Boolean weixinAnswerEnabled(@PathVariable Long examId) {
|
|
public Boolean weixinAnswerEnabled(@PathVariable Long examId) {
|