فهرست منبع

Merge remote-tracking branch 'origin/dev_v4.1.0' into dev_v4.1.0

deason 4 سال پیش
والد
کامیت
32550197ce

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

@@ -11,6 +11,7 @@ import cn.com.qmth.examcloud.api.commons.security.bean.UserType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.helpers.DynamicEnum;
 import cn.com.qmth.examcloud.commons.helpers.DynamicEnumManager;
+import cn.com.qmth.examcloud.commons.helpers.poi.ExcelReader;
 import cn.com.qmth.examcloud.commons.helpers.poi.ExcelWriter;
 import cn.com.qmth.examcloud.commons.util.*;
 import cn.com.qmth.examcloud.commons.util.DateUtil.DatePatterns;
@@ -31,6 +32,7 @@ import cn.com.qmth.examcloud.core.examwork.api.controller.bean.StudentSpecialSet
 import cn.com.qmth.examcloud.core.examwork.base.enums.ExamProperty;
 import cn.com.qmth.examcloud.core.examwork.dao.*;
 import cn.com.qmth.examcloud.core.examwork.dao.entity.*;
+import cn.com.qmth.examcloud.core.examwork.dao.enums.IpLimitType;
 import cn.com.qmth.examcloud.core.examwork.service.ExamService;
 import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
 import cn.com.qmth.examcloud.core.examwork.service.bean.ExamSpecialSettingsInfo;
@@ -41,6 +43,7 @@ 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.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.*;
+import cn.com.qmth.examcloud.support.enums.DataCategory;
 import cn.com.qmth.examcloud.support.privilege.PrivilegeDefine;
 import cn.com.qmth.examcloud.support.privilege.PrivilegeManager;
 import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
@@ -152,6 +155,8 @@ public class ExamController extends ControllerSupport {
     private static final String[] EXAM_ORG_SETTINGS_EXCEL_HEADER = new String[]{"学习中心ID", "学习中心代码",
             "学习中心名称", "是否可以考试(是/否)", "开始考试时间 yyyy-MM-dd hh:mm:ss", "结束考试时间 yyyy-MM-dd hh:mm:ss"};
 
+    private static final String[] EXCEL_IP_LIMIT_HEADER = new String[]{"IP地址", "限制类型"};
+
     @ApiOperation(value = "查询考试课程的试卷类型集合")
     @GetMapping("queryExamCoursePaperTypeList")
     public List<ExamPaperTypeRelationEntity> queryExamCoursePaperTypeList(
@@ -211,7 +216,7 @@ public class ExamController extends ControllerSupport {
             return cb.and(predicates.toArray(new Predicate[predicates.size()]));
         };
 
-        PageRequest pageRequest = PageRequest.of(0, 50, Sort.by(Direction.DESC, "updateTime"));
+        PageRequest pageRequest = PageRequest.of(0, 50, new Sort(Direction.DESC, "updateTime"));
 
         Page<ExamCourseRelationEntity> page = examCourseRelationRepo.findAll(specification,
                 pageRequest);
@@ -1411,6 +1416,23 @@ public class ExamController extends ControllerSupport {
         return pageInfo;
     }
 
+    @PostMapping("ipLimited")
+    public void save(@RequestBody ExamIpLimitEntity entity) {
+        examIpLimitRepo.save(entity);
+    }
+
+    @DeleteMapping("ipLimited/{ids}")
+    public void delete(@PathVariable String ids) {
+        List<Long> ipIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+                .collect(Collectors.toList());
+        examIpLimitRepo.deleteByIds(ipIds);
+    }
+
+    @DeleteMapping("ipLimited/all/{examId}")
+    public void delete(@PathVariable Long examId) {
+        examIpLimitRepo.deleteAllByExamId(examId);
+    }
+
     @GetMapping("ipLimited/property/{examId}")
     public Map<String,Boolean> ipLimitedProperty(@PathVariable Long examId) {
         Map<String,Boolean> map = new HashMap<>();
@@ -1431,6 +1453,152 @@ public class ExamController extends ControllerSupport {
         jdbcTemplate.update(valueSql);
     }
 
+    @ApiOperation(value = "导入考试ip限制", notes = "导入")
+    @PostMapping("ipLimited/import")
+    public Map<String, Object> importExamIpLimit(@RequestParam Long examId,
+                                  @RequestParam CommonsMultipartFile file) {
+        DiskFileItem item = (DiskFileItem) file.getFileItem();
+        File storeLocation = item.getStoreLocation();
+        List<String[]> lineList;
+        try {
+            lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(storeLocation), 1, 2);
+        } catch (Exception e) {
+            throw new StatusException("100110", "Excel 解析失败");
+        }
+        if (CollectionUtils.isEmpty(lineList)) {
+            throw new StatusException("100111", "Excel无内容");
+        }
+
+        if (10001 < lineList.size()) {
+            throw new StatusException("100112", "数据行数不能超过10000");
+        }
+        List<Map<String, Object>> failRecords = Collections
+                .synchronizedList(new ArrayList<>());
+
+        List<ExamIpLimitEntity> list = Lists.newArrayList();
+
+        for (int i = 0; i < lineList.size(); i++) {
+            String[] line = lineList.get(i);
+            if (0 == i) {
+                if (headerError(line)) {
+                    throw new StatusException("100111", "Excel表头错误");
+                }
+                continue;
+            }
+
+            boolean hasError = false;
+            StringBuilder msg = new StringBuilder();
+
+            ExamIpLimitEntity entity = new ExamIpLimitEntity();
+            entity.setExamId(examId);
+
+            String ip = line[0];
+
+            if (StringUtils.isBlank(ip)) {
+                msg.append("  IP地址不能为空");
+                hasError = true;
+            }
+            entity.setIp(ip);
+
+            if (StringUtils.isBlank(line[1])) {
+                msg.append("  限制类型不能为空");
+                hasError = true;
+            }
+            Integer type = null;
+            IpLimitType ipLimitType = IpLimitType.formByType(line[1]);
+            if(ipLimitType==null){
+                msg.append("  不符合格式的限制类型");
+                hasError = true;
+            } else {
+                type = ipLimitType.getId();
+            }
+            entity.setLimitType(type);
+
+            Date date = new Date();
+            entity.setCreationTime(date);
+            entity.setUpdateTime(date);
+
+            if (hasError) {
+                Map<String, Object> map = Maps.newHashMap();
+                map.put("lineNum", i+1);
+                map.put("msg", msg);
+                failRecords.add(map);
+            } else {
+                list.add(entity);
+            }
+        }
+
+        Map<String, Object> map = Maps.newHashMap();
+        map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
+        map.put("failRecords", failRecords);
+
+        if (CollectionUtils.isNotEmpty(failRecords)) {
+            map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
+            map.put("failRecords", failRecords);
+            return map;
+        } else {
+            examIpLimitRepo.saveAll(list);
+        }
+        return map;
+    }
+
+    @ApiOperation(value = "导出Ip限制")
+    @GetMapping("ipLimited/export")
+    public void export(Long examId, Integer limitType, String ip) {
+        Specification<ExamIpLimitEntity> spec = (root, query, cb) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            if(examId!=null){
+                predicates.add(cb.equal(root.get("examId"), examId));
+            }
+            if(limitType!=null){
+                predicates.add(cb.equal(root.get("limitType"), limitType));
+            }
+            if(StringUtils.isNotBlank(ip)){
+                predicates.add(cb.like(root.get("ip"), "%"+ip+"%"));
+            }
+            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+        };
+
+
+        long count = examIpLimitRepo.count(spec);
+        if (100000 < count) {
+            throw new StatusException("620200", "数据量过大,无法导出");
+        }
+
+        List<ExamIpLimitEntity> list = examIpLimitRepo.findAll(spec);
+
+        List<Object[]> datas = Lists.newArrayList();
+
+        for (ExamIpLimitEntity cur : list) {
+            IpLimitType ipLimitType = IpLimitType.formById(cur.getLimitType());
+            String type = ipLimitType == null ? "" : ipLimitType.getName();
+            datas.add(new Object[]{cur.getIp(), type});
+        }
+
+        String filePath = systemConfig.getTempDataDir() + File.separator
+                + System.currentTimeMillis() + ".xlsx";
+        File file = new File(filePath);
+
+        ExcelWriter.write(EXCEL_IP_LIMIT_HEADER, new Class[]{String.class, String.class}, datas,
+                new File(filePath));
+
+        exportFile("Ip访问限制列表-" + getRootOrgId() + ".xlsx", file);
+
+        FileUtils.deleteQuietly(file);
+    }
+
+    private boolean headerError(String[] header) {
+        for (int i = 0; i < EXCEL_IP_LIMIT_HEADER.length; i++) {
+            if (null == header[i]) {
+                return true;
+            }
+            if (!EXCEL_IP_LIMIT_HEADER[i].equals(header[i].trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @GetMapping("ipLimited/{examId}")
     public boolean ipLimited(HttpServletRequest request, @PathVariable Long examId) {
         //是否开启Ip限制

+ 7 - 0
examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/ExamIpLimitRepo.java

@@ -6,6 +6,8 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
 
+import java.util.List;
+
 public interface ExamIpLimitRepo extends JpaRepository<ExamIpLimitEntity, Long>,
 			QueryByExampleExecutor<ExamIpLimitEntity>, JpaSpecificationExecutor<ExamIpLimitEntity> {
 
@@ -13,4 +15,9 @@ public interface ExamIpLimitRepo extends JpaRepository<ExamIpLimitEntity, Long>,
 			"AND t.limit_type = ?2 AND 3? REGEXP t.ip ",nativeQuery = true)
 	int countByExamIdAndLimitTypeAndIp(Long examId, String limitType, String ip);
 
+	@Query(value = "delete from ec_e_exam_ip_limit where id in ?1 ",nativeQuery = true)
+    void deleteByIds(List<Long> ipIds);
+
+	@Query(value = "delete from ec_e_exam_ip_limit where exam_id = ?1 ",nativeQuery = true)
+	void deleteAllByExamId(Long examId);
 }

+ 74 - 0
examcloud-core-examwork-dao/src/main/java/cn/com/qmth/examcloud/core/examwork/dao/enums/IpLimitType.java

@@ -0,0 +1,74 @@
+package cn.com.qmth.examcloud.core.examwork.dao.enums;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * description
+ *
+ * @author qinchao
+ * @date 2021/4/14 16:28
+ */
+public enum IpLimitType {
+    /**
+     * 允许访问
+     */
+    Has_access(0, "允许访问"),
+    /**
+     * 禁止访问
+     */
+    No_Access(1, "允许访问");
+
+    private Integer id;
+
+    private String name;
+
+    private IpLimitType() {
+    }
+
+    private IpLimitType(Integer id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public static IpLimitType formById(Integer id) {
+        if (id == null) {
+            return null;
+        }
+        for (IpLimitType type : IpLimitType.values()) {
+            if (type.getId().equals(id)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public static IpLimitType formByType(String type) {
+        if (StringUtils.isBlank(type)) {
+            return null;
+        }
+        for (IpLimitType ipLimitType : IpLimitType.values()) {
+            if (type.equals(ipLimitType.name())) {
+                return ipLimitType;
+            }
+        }
+        return null;
+    }
+
+}
+