Explorar o código

添加身份证隐私模式代码

lideyin %!s(int64=5) %!d(string=hai) anos
pai
achega
cf9b3029a5

+ 576 - 577
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java

@@ -12,6 +12,7 @@ import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 import javax.persistence.criteria.Subquery;
 
+import cn.com.qmth.examcloud.support.helper.IdentityNumberHelper;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -70,590 +71,588 @@ import io.swagger.annotations.ApiOperation;
 @RequestMapping("${$rmp.ctr.basic}/student")
 public class StudentController extends ControllerSupport {
 
-	@Autowired
-	StudentRepo studentRepo;
-
-	@Autowired
-	StudentCodeRepo studentCodeRepo;
-
-	@Autowired
-	SystemProperties systemConfig;
-
-	@Autowired
-	StudentService studentService;
-
-	@Autowired
-	UserRepo userRepo;
-
-	@Autowired
-	OrgRepo orgRepo;
-
-	@Autowired
-	DataSyncCloudService dataSyncCloudService;
-
-	@Autowired
-	StudentCache studentCache;
-
-	private static final String[] EXCEL_HEADER = new String[]{"ID", "姓名", "学号", "身份证", "学习中心代码",
-			"学习中心名称"};
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param name
-	 * @param studentCode
-	 * @param identityNumber
-	 * @param curPage
-	 * @param pageSize
-	 * @return
-	 */
-	@ApiOperation(value = "查询学生分页数据", notes = "分页")
-	@GetMapping("studentPage/{curPage}/{pageSize}")
-	public PageInfo<StudentDomain> getStudentPage(@PathVariable Integer curPage,
-			@PathVariable Integer pageSize, @RequestParam String name,
-			@RequestParam String studentCode, @RequestParam String identityNumber,
-			@RequestParam(required = false) Long rootOrgId,
-			@RequestParam(required = false) Long orgId,
-			@RequestParam(required = false) BooleanSelect hasPhoto) {
-
-		User accessUser = getAccessUser();
-		if (null == rootOrgId) {
-			rootOrgId = accessUser.getRootOrgId();
-		}
-
-		validateRootOrgIsolation(rootOrgId);
-
-		final Long finalRootOrgId = rootOrgId;
-
-		Specification<StudentEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-			predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
-
-			if (StringUtils.isNotEmpty(name)) {
-				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
-			}
-			if (StringUtils.isNotEmpty(identityNumber)) {
-				predicates.add(
-						cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
-			}
-			if (null != hasPhoto) {
-				Boolean hasPhotoBoolean = hasPhoto.getBoolean();
-				if (null != hasPhotoBoolean) {
-					if (hasPhotoBoolean) {
-						predicates.add(cb.isNotNull(root.get("photoPath")));
-					} else {
-						predicates.add(cb.isNull(root.get("photoPath")));
-					}
-				}
-			}
-
-			if (StringUtils.isNotEmpty(studentCode)) {
-				Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
-				Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
-				subquery.select(subRoot.get("id"));
-				Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
-				Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
-				subquery.where(cb.and(p1, p2));
-				predicates.add(cb.exists(subquery));
-			}
-
-			Boolean orgStudentData = PrivilegeManager.judge(finalRootOrgId,
-					accessUser.getRoleList(), OrgStudentData.CODE);
-			Boolean allStudentData = PrivilegeManager.judge(finalRootOrgId,
-					accessUser.getRoleList(), AllStudentData.CODE);
-
-			// 学习中心过滤
-			if (isSuperAdmin()) {
-				if (null != orgId) {
-					predicates.add(cb.equal(root.get("orgId"), orgId));
-				}
-			} else if (allStudentData) {
-				if (null != orgId) {
-					predicates.add(cb.equal(root.get("orgId"), orgId));
-				}
-			} else {
-				if (orgStudentData) {
-					if (hasRole(RoleMeta.LC_USER)) {
-						UserEntity user = GlobalHelper.getEntity(userRepo, accessUser.getUserId(),
-								UserEntity.class);
-						if (null != user.getOrgId()) {
-							predicates.add(cb.equal(root.get("orgId"), user.getOrgId()));
-						} else {
-							predicates.add(cb.equal(root.get("orgId"), -1));
-						}
-					} else {
-						predicates.add(cb.equal(root.get("orgId"), -1));
-					}
-				} else {
-					predicates.add(cb.equal(root.get("orgId"), -1));
-				}
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		PageRequest pageRequest = PageRequest.of(curPage, pageSize,
-				new Sort(Direction.DESC, "updateTime", "id"));
-
-		Page<StudentEntity> studentList = studentRepo.findAll(specification, pageRequest);
-
-		Iterator<StudentEntity> iterator = studentList.iterator();
-
-		List<StudentDomain> studentDomainList = Lists.newArrayList();
+    @Autowired
+    StudentRepo studentRepo;
+
+    @Autowired
+    StudentCodeRepo studentCodeRepo;
+
+    @Autowired
+    SystemProperties systemConfig;
+
+    @Autowired
+    StudentService studentService;
+
+    @Autowired
+    UserRepo userRepo;
+
+    @Autowired
+    OrgRepo orgRepo;
+
+    @Autowired
+    DataSyncCloudService dataSyncCloudService;
+
+    @Autowired
+    StudentCache studentCache;
+
+    private static final String[] EXCEL_HEADER = new String[]{"ID", "姓名", "学号", "身份证", "学习中心代码",
+            "学习中心名称"};
+
+    /**
+     * 方法注释
+     *
+     * @param name
+     * @param studentCode
+     * @param identityNumber
+     * @param curPage
+     * @param pageSize
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "查询学生分页数据", notes = "分页")
+    @GetMapping("studentPage/{curPage}/{pageSize}")
+    public PageInfo<StudentDomain> getStudentPage(@PathVariable Integer curPage,
+                                                  @PathVariable Integer pageSize, @RequestParam String name,
+                                                  @RequestParam String studentCode, @RequestParam String identityNumber,
+                                                  @RequestParam(required = false) Long rootOrgId,
+                                                  @RequestParam(required = false) Long orgId,
+                                                  @RequestParam(required = false) BooleanSelect hasPhoto) {
+
+        User accessUser = getAccessUser();
+        if (null == rootOrgId) {
+            rootOrgId = accessUser.getRootOrgId();
+        }
+
+        validateRootOrgIsolation(rootOrgId);
+
+        final Long finalRootOrgId = rootOrgId;
+
+        Specification<StudentEntity> specification = (root, query, cb) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
+
+            if (StringUtils.isNotEmpty(name)) {
+                predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+            }
+            if (StringUtils.isNotEmpty(identityNumber)) {
+                predicates.add(
+                        cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
+            }
+            if (null != hasPhoto) {
+                Boolean hasPhotoBoolean = hasPhoto.getBoolean();
+                if (null != hasPhotoBoolean) {
+                    if (hasPhotoBoolean) {
+                        predicates.add(cb.isNotNull(root.get("photoPath")));
+                    } else {
+                        predicates.add(cb.isNull(root.get("photoPath")));
+                    }
+                }
+            }
+
+            if (StringUtils.isNotEmpty(studentCode)) {
+                Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
+                Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
+                subquery.select(subRoot.get("id"));
+                Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
+                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
+                subquery.where(cb.and(p1, p2));
+                predicates.add(cb.exists(subquery));
+            }
+
+            Boolean orgStudentData = PrivilegeManager.judge(finalRootOrgId,
+                    accessUser.getRoleList(), OrgStudentData.CODE);
+            Boolean allStudentData = PrivilegeManager.judge(finalRootOrgId,
+                    accessUser.getRoleList(), AllStudentData.CODE);
+
+            // 学习中心过滤
+            if (isSuperAdmin()) {
+                if (null != orgId) {
+                    predicates.add(cb.equal(root.get("orgId"), orgId));
+                }
+            } else if (allStudentData) {
+                if (null != orgId) {
+                    predicates.add(cb.equal(root.get("orgId"), orgId));
+                }
+            } else {
+                if (orgStudentData) {
+                    if (hasRole(RoleMeta.LC_USER)) {
+                        UserEntity user = GlobalHelper.getEntity(userRepo, accessUser.getUserId(),
+                                UserEntity.class);
+                        if (null != user.getOrgId()) {
+                            predicates.add(cb.equal(root.get("orgId"), user.getOrgId()));
+                        } else {
+                            predicates.add(cb.equal(root.get("orgId"), -1));
+                        }
+                    } else {
+                        predicates.add(cb.equal(root.get("orgId"), -1));
+                    }
+                } else {
+                    predicates.add(cb.equal(root.get("orgId"), -1));
+                }
+            }
+
+            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+        };
+
+        PageRequest pageRequest = PageRequest.of(curPage, pageSize,
+                new Sort(Direction.DESC, "updateTime", "id"));
+
+        Page<StudentEntity> studentList = studentRepo.findAll(specification, pageRequest);
+
+        Iterator<StudentEntity> iterator = studentList.iterator();
+
+        List<StudentDomain> studentDomainList = Lists.newArrayList();
 
 //		String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
 //		if (StringUtils.isBlank(upyunDomain)) {
 //			throw new StatusException("560111", "property[$upyun.site.1.domain] is not configured");
 //		}
 
-		while (iterator.hasNext()) {
-			StudentEntity next = iterator.next();
-			StudentDomain bean = new StudentDomain();
-			bean.setId(next.getId());
-			bean.setName(next.getName());
-			bean.setRootOrgId(next.getRootOrgId());
-			bean.setUpdateTime(next.getUpdateTime());
-			bean.setCreationTime(next.getCreationTime());
-			bean.setEnable(next.getEnable());
-			List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
-					.findByStudentId(next.getId());
-			List<String> studentCodeList = Lists.newArrayList();
-			for (StudentCodeEntity cur : studentCodeEntityList) {
-				studentCodeList.add(cur.getStudentCode());
-			}
-			bean.setStudentCodeList(studentCodeList);
-			bean.setStudentCodesStr(StringUtils.join(studentCodeList, "<br />"));
-
-			bean.setIdentityNumber(next.getIdentityNumber());
-			if (StringUtils.isNotBlank(next.getPhotoPath())) {
+        while (iterator.hasNext()) {
+            StudentEntity next = iterator.next();
+            StudentDomain bean = new StudentDomain();
+            bean.setId(next.getId());
+            bean.setName(next.getName());
+            bean.setRootOrgId(next.getRootOrgId());
+            bean.setUpdateTime(next.getUpdateTime());
+            bean.setCreationTime(next.getCreationTime());
+            bean.setEnable(next.getEnable());
+            List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
+                    .findByStudentId(next.getId());
+            List<String> studentCodeList = Lists.newArrayList();
+            for (StudentCodeEntity cur : studentCodeEntityList) {
+                studentCodeList.add(cur.getStudentCode());
+            }
+            bean.setStudentCodeList(studentCodeList);
+            bean.setStudentCodesStr(StringUtils.join(studentCodeList, "<br />"));
+
+            bean.setIdentityNumber(IdentityNumberHelper.conceal(next.getRootOrgId(), next.getIdentityNumber()));
+            if (StringUtils.isNotBlank(next.getPhotoPath())) {
 //				bean.setPhotoPath(
 //						UrlUtil.joinUrl(upyunDomain, "student_base_photo", next.getPhotoPath()));
-				//通用存储
-				bean.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", next.getPhotoPath())));
-			}
-			bean.setPhoneNumber(next.getPhoneNumber());
-			bean.setSecurityPhone(next.getSecurityPhone());
-			bean.setRemark(next.getRemark());
-
-			bean.setOrgId(next.getOrgId());
-			if (null != bean.getOrgId()) {
-				OrgEntity org = GlobalHelper.getEntity(orgRepo, Long.valueOf(bean.getOrgId()),
-						OrgEntity.class);
-				if (null != org) {
-					bean.setOrgName(org.getName());
-					bean.setOrgCode(org.getCode());
-				}
-			}
-
-			studentDomainList.add(bean);
-		}
-
-		PageInfo<StudentDomain> ret = new PageInfo<StudentDomain>();
-		ret.setList(studentDomainList);
-		ret.setTotal(studentList.getTotalElements());
-		return ret;
-
-	}
-
-	@ApiOperation(value = "导出学生", notes = "")
-	@GetMapping("export")
-	public void exportStudents(@RequestParam String name, @RequestParam String studentCode,
-			@RequestParam String identityNumber, @RequestParam(required = false) Long rootOrgId,
-			@RequestParam(required = false) Long orgId,
-			@RequestParam(required = false) BooleanSelect hasPhoto) {
-
-		User accessUser = getAccessUser();
-		if (null == rootOrgId) {
-			rootOrgId = accessUser.getRootOrgId();
-		}
-
-		validateRootOrgIsolation(rootOrgId);
-
-		final Long finalRootOrgId = rootOrgId;
-
-		Specification<StudentEntity> specification = (root, query, cb) -> {
-			List<Predicate> predicates = new ArrayList<>();
-			predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
-
-			if (StringUtils.isNotEmpty(name)) {
-				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
-			}
-			if (StringUtils.isNotEmpty(identityNumber)) {
-				predicates.add(
-						cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
-			}
-			if (null != hasPhoto) {
-				Boolean hasPhotoBoolean = hasPhoto.getBoolean();
-				if (null != hasPhotoBoolean) {
-					if (hasPhotoBoolean) {
-						predicates.add(cb.isNotNull(root.get("photoPath")));
-					} else {
-						predicates.add(cb.isNull(root.get("photoPath")));
-					}
-				}
-			}
-
-			if (StringUtils.isNotEmpty(studentCode)) {
-				Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
-				Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
-				subquery.select(subRoot.get("id"));
-				Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
-				Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
-				subquery.where(cb.and(p1, p2));
-				predicates.add(cb.exists(subquery));
-			}
-
-			Boolean orgStudentData = PrivilegeManager.judge(finalRootOrgId,
-					accessUser.getRoleList(), OrgStudentData.CODE);
-			Boolean allStudentData = PrivilegeManager.judge(finalRootOrgId,
-					accessUser.getRoleList(), AllStudentData.CODE);
-
-			// 学习中心过滤
-			if (isSuperAdmin()) {
-				if (null != orgId) {
-					predicates.add(cb.equal(root.get("orgId"), orgId));
-				}
-			} else if (allStudentData) {
-				if (null != orgId) {
-					predicates.add(cb.equal(root.get("orgId"), orgId));
-				}
-			} else {
-				if (orgStudentData) {
-					if (hasRole(RoleMeta.LC_USER)) {
-						UserEntity user = GlobalHelper.getEntity(userRepo, accessUser.getUserId(),
-								UserEntity.class);
-						if (null != user.getOrgId()) {
-							predicates.add(cb.equal(root.get("orgId"), user.getOrgId()));
-						} else {
-							predicates.add(cb.equal(root.get("orgId"), -1));
-						}
-					} else {
-						predicates.add(cb.equal(root.get("orgId"), -1));
-					}
-				} else {
-					predicates.add(cb.equal(root.get("orgId"), -1));
-				}
-			}
-
-			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
-		};
-
-		long count = studentRepo.count(specification);
-		if (100000 < count) {
-			throw new StatusException("520200", "数据量超过100000,无法导出");
-		}
-
-		List<StudentEntity> studentList = studentRepo.findAll(specification,
-				new Sort(Direction.DESC, "updateTime"));
-
-		List<Object[]> datas = Lists.newArrayList();
-
-		for (StudentEntity cur : studentList) {
-			String orgCode = null;
-			String orgName = null;
-			if (null != cur.getOrgId()) {
-				OrgEntity org = GlobalHelper.getEntity(orgRepo, Long.valueOf(cur.getOrgId()),
-						OrgEntity.class);
-				if (null != org) {
-					orgCode = org.getCode();
-					orgName = org.getName();
-				}
-			}
-
-			List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
-					.findByStudentId(cur.getId());
-			List<String> studentCodeList = Lists.newArrayList();
-			for (StudentCodeEntity sc : studentCodeEntityList) {
-				studentCodeList.add(sc.getStudentCode());
-			}
-
-			datas.add(
-					new Object[]{cur.getId(), cur.getName(), StringUtils.join(studentCodeList, ";"),
-							cur.getIdentityNumber(), orgCode, orgName});
-		}
-
-		String filePath = systemConfig.getTempDataDir() + File.separator
-				+ System.currentTimeMillis() + ".xlsx";
-		File file = new File(filePath);
-
-		ExcelWriter.write(EXCEL_HEADER, new Class[]{Long.class, String.class, String.class,
-				String.class, String.class, String.class}, datas, new File(filePath));
-
-		exportFile("学生-" + getRootOrgId() + ".xlsx", file);
-
-		FileUtils.deleteQuietly(file);
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param ids
-	 * @return
-	 */
-	@ApiOperation(value = "启用学生")
-	@PutMapping("enable/{ids}")
-	@Transactional
-	public List<String> enableStudent(@PathVariable String ids) {
-		List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		List<String> ret = Lists.newArrayList();
-		for (Long cur : studentIds) {
-			StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
-			s.setEnable(true);
-			studentRepo.save(s);
-			ret.add(s.getId() + ":" + s.getName());
-		}
-		for (Long cur : studentIds) {
-			studentCache.remove(cur);
-		}
-		return ret;
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param ids
-	 * @return
-	 */
-	@ApiOperation(value = "禁用学生")
-	@PutMapping("disable/{ids}")
-	@Transactional
-	public List<String> disableStudent(@PathVariable String ids) {
-		List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		List<String> ret = Lists.newArrayList();
-		for (Long cur : studentIds) {
-			StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
-			s.setEnable(false);
-			studentRepo.save(s);
-			ret.add(s.getId() + ":" + s.getName());
-		}
-		for (Long cur : studentIds) {
-			studentCache.remove(cur);
-		}
-		return ret;
-	}
-
-	@ApiOperation(value = "重置学生密码", notes = "重置学生密码")
-	@PutMapping("resetPass/{ids}")
-	@Transactional
-	public void resetPassword(@PathVariable String ids) {
-		List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		for (Long cur : studentIds) {
-			StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
-			if (null == s) {
-				throw new StatusException("450110", "学生不存在");
-			}
-			String identityNumber = s.getIdentityNumber();
-			if (StringUtils.isNotEmpty(identityNumber)
-					&& identityNumber.matches("[0-9a-zA-Z]{6,}")) {
-				s.setPassword(StringUtils.substring(identityNumber, -6, identityNumber.length()));
-			} else {
-				s.setPassword(BasicConsts.DEFAULT_PASSWORD);
-			}
-			s.setUpdateTime(new Date());
-			studentRepo.save(s);
-		}
-	}
-
-	@ApiOperation(value = "重置机构下所有学生密码", notes = "重置机构下所有学生密码")
-	@PutMapping("resetPasswordByOrgId/{orgId}")
-	@Transactional
-	public void resetPasswordByOrgId(@PathVariable Long orgId) {
-		OrgEntity org = GlobalHelper.getPresentEntity(orgRepo, orgId, OrgEntity.class);
-
-		validateRootOrgIsolation(org.getRootId());
-
-		List<StudentEntity> stuentList = studentRepo.findByOrgId(org.getId());
-		for (StudentEntity s : stuentList) {
-			String identityNumber = s.getIdentityNumber();
-			if (StringUtils.isNotEmpty(identityNumber)
-					&& identityNumber.matches("[0-9a-zA-Z]{6,}")) {
-				s.setPassword(StringUtils.substring(identityNumber, -6, identityNumber.length()));
-			} else {
-				s.setPassword(BasicConsts.DEFAULT_PASSWORD);
-			}
-			s.setUpdateTime(new Date());
-			studentRepo.save(s);
-		}
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param newPassword
-	 * @param request
-	 * @return
-	 */
-	@ApiOperation(value = "修改学生密码", notes = "修改密码")
-	@PutMapping("password/direct")
-	@Transactional
-	public Long updateStudentPassword(@RequestParam("newPassword") String newPassword) {
-		User accessUser = getAccessUser();
-		if (StringUtils.isEmpty(newPassword)) {
-			throw new StatusException("450201", "新密码为空");
-		}
-
-		if (!newPassword.matches("[a-zA-Z0-9]{6,18}")) {
-			throw new StatusException("450203", "密码必须是6至18位字母或数字");
-		}
-
-		StudentEntity s = GlobalHelper.getEntity(studentRepo, accessUser.getUserId(),
-				StudentEntity.class);
-		s.setPassword(newPassword);
-		studentRepo.save(s);
-		return s.getId();
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param password
-	 * @param newPassword
-	 * @param request
-	 * @return
-	 */
-	@ApiOperation(value = "修改学生密码", notes = "修改密码")
-	@PutMapping("password")
-	@Transactional
-	public Long updateStudentPassword(@RequestParam("password") String password,
-			@RequestParam("newPassword") String newPassword) {
-		User accessUser = getAccessUser();
-		if (StringUtils.isEmpty(password)) {
-			throw new StatusException("450110", "旧密码为空");
-		}
-		if (StringUtils.isEmpty(newPassword)) {
-			throw new StatusException("450111", "新密码为空");
-		}
-		if (!newPassword.matches("[a-zA-Z0-9]{6,18}")) {
-			throw new StatusException("450111", "密码必须是6至18位字母或数字");
-		}
-
-		StudentEntity s = GlobalHelper.getEntity(studentRepo, accessUser.getUserId(),
-				StudentEntity.class);
-
-		if (StringUtils.isNotBlank(s.getPassword()) && !s.getPassword().equals(password)) {
-			throw new StatusException("450111", "当前密码错误");
-		}
-		s.setPassword(newPassword);
-		studentRepo.save(s);
-		return s.getId();
-	}
-
-	/**
-	 * 查询学生
-	 *
-	 * @author WANGWEI
-	 * @param identityNumber
-	 * @param studentCode
-	 * @param securityPhone
-	 * @return
-	 */
-	@ApiOperation(value = "查询学生")
-	@GetMapping("getStudentInfoBySession")
-	public StudentInfo getStudentInfoBySession() {
-		User accessUser = getAccessUser();
-		Long rootOrgId = accessUser.getRootOrgId();
-		Long studentId = accessUser.getUserId();
-
-		StudentCacheBean s = CacheHelper.getStudent(studentId);
-
-		OrgCacheBean org = CacheHelper.getOrg(s.getOrgId());
-		OrgCacheBean rootOrg = CacheHelper.getOrg(rootOrgId);
-
-		StudentInfo info = new StudentInfo();
-
-		info.setEnable(s.getEnable());
-		info.setId(s.getId());
-		info.setIdentityNumber(s.getIdentityNumber());
-		info.setName(s.getName());
-		info.setOrgCode(org.getCode());
-		info.setOrgId(org.getId());
-		info.setOrgName(org.getName());
-		info.setPhoneNumber(s.getPhoneNumber());
-		info.setPhotoPath(s.getPhotoPath());
-		info.setRemark(s.getRemark());
-		info.setRootOrgId(rootOrgId);
-		info.setRootOrgName(rootOrg.getName());
-		info.setSecurityPhone(s.getSecurityPhone());
-		info.setStudentCodeList(s.getStudentCodeList());
-
-		return info;
-	}
-
-	@ApiOperation(value = "查询学生")
-	@GetMapping("getStudentInfo")
-	public StudentInfo getStudentInfo(@RequestParam(required = false) Long rootOrgId,
-			@RequestParam(required = false) Long studentId,
-			@RequestParam(required = false) String identityNumber,
-			@RequestParam(required = false) String studentCode,
-			@RequestParam(required = false) String securityPhone) {
-		if (null == rootOrgId) {
-			rootOrgId = getRootOrgId();
-		} else {
-			validateRootOrgIsolation(rootOrgId);
-		}
-
-		StudentInfo studentInfo = studentService.getStudentInfo(rootOrgId, studentId,
-				identityNumber, studentCode, securityPhone);
-		return studentInfo;
-	}
-
-	@ApiOperation(value = "解绑学号", notes = "")
-	@PostMapping("unbindStudentCode")
-	@Transactional
-	public List<Long> unbindStudentCode(@RequestParam(required = false) String studentCode,
-			@RequestParam(required = false) String identityNumber,
-			@RequestParam(required = true) Long rootOrgId) {
-
-		if (null == rootOrgId) {
-			rootOrgId = getRootOrgId();
-		} else {
-			OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, rootOrgId, OrgEntity.class);
-			if (null == rootOrg) {
-				throw new StatusException("450110", "rootOrgId is wrong");
-			}
-			validateRootOrgIsolation(rootOrgId);
-		}
-
-		List<Long> studentIdList = studentService.unbindStudentCode(rootOrgId, studentCode,
-				identityNumber);
-
-		for (Long cur : studentIdList) {
-			studentCache.remove(cur);
-		}
-
-		return studentIdList;
-	}
-
-	@ApiOperation(value = "解绑安全手机", notes = "")
-	@PutMapping("unbindSecurityPhone/{ids}")
-	@Transactional
-	public void unbindSecurityPhone(@PathVariable String ids) {
-		List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
-				.collect(Collectors.toList());
-		for (Long cur : studentIds) {
-			StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
-			if (null == s) {
-				throw new StatusException("450110", "学生不存在");
-			}
-			validateRootOrgIsolation(s.getRootOrgId());
-		}
-
-		for (Long cur : studentIds) {
-			studentService.unbindSecurityPhone(cur);
-		}
-
-		for (Long cur : studentIds) {
-			studentCache.remove(cur);
-		}
-
-	}
+                //通用存储
+                bean.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", next.getPhotoPath())));
+            }
+            bean.setPhoneNumber(next.getPhoneNumber());
+            bean.setSecurityPhone(next.getSecurityPhone());
+            bean.setRemark(next.getRemark());
+
+            bean.setOrgId(next.getOrgId());
+            if (null != bean.getOrgId()) {
+                OrgEntity org = GlobalHelper.getEntity(orgRepo, Long.valueOf(bean.getOrgId()),
+                        OrgEntity.class);
+                if (null != org) {
+                    bean.setOrgName(org.getName());
+                    bean.setOrgCode(org.getCode());
+                }
+            }
+
+            studentDomainList.add(bean);
+        }
+
+        PageInfo<StudentDomain> ret = new PageInfo<StudentDomain>();
+        ret.setList(studentDomainList);
+        ret.setTotal(studentList.getTotalElements());
+        return ret;
+
+    }
+
+    @ApiOperation(value = "导出学生", notes = "")
+    @GetMapping("export")
+    public void exportStudents(@RequestParam String name, @RequestParam String studentCode,
+                               @RequestParam String identityNumber, @RequestParam(required = false) Long rootOrgId,
+                               @RequestParam(required = false) Long orgId,
+                               @RequestParam(required = false) BooleanSelect hasPhoto) {
+
+        User accessUser = getAccessUser();
+        if (null == rootOrgId) {
+            rootOrgId = accessUser.getRootOrgId();
+        }
+
+        validateRootOrgIsolation(rootOrgId);
+
+        final Long finalRootOrgId = rootOrgId;
+
+        Specification<StudentEntity> specification = (root, query, cb) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            predicates.add(cb.equal(root.get("rootOrgId"), finalRootOrgId));
+
+            if (StringUtils.isNotEmpty(name)) {
+                predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+            }
+            if (StringUtils.isNotEmpty(identityNumber)) {
+                predicates.add(
+                        cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
+            }
+            if (null != hasPhoto) {
+                Boolean hasPhotoBoolean = hasPhoto.getBoolean();
+                if (null != hasPhotoBoolean) {
+                    if (hasPhotoBoolean) {
+                        predicates.add(cb.isNotNull(root.get("photoPath")));
+                    } else {
+                        predicates.add(cb.isNull(root.get("photoPath")));
+                    }
+                }
+            }
+
+            if (StringUtils.isNotEmpty(studentCode)) {
+                Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
+                Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
+                subquery.select(subRoot.get("id"));
+                Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
+                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
+                subquery.where(cb.and(p1, p2));
+                predicates.add(cb.exists(subquery));
+            }
+
+            Boolean orgStudentData = PrivilegeManager.judge(finalRootOrgId,
+                    accessUser.getRoleList(), OrgStudentData.CODE);
+            Boolean allStudentData = PrivilegeManager.judge(finalRootOrgId,
+                    accessUser.getRoleList(), AllStudentData.CODE);
+
+            // 学习中心过滤
+            if (isSuperAdmin()) {
+                if (null != orgId) {
+                    predicates.add(cb.equal(root.get("orgId"), orgId));
+                }
+            } else if (allStudentData) {
+                if (null != orgId) {
+                    predicates.add(cb.equal(root.get("orgId"), orgId));
+                }
+            } else {
+                if (orgStudentData) {
+                    if (hasRole(RoleMeta.LC_USER)) {
+                        UserEntity user = GlobalHelper.getEntity(userRepo, accessUser.getUserId(),
+                                UserEntity.class);
+                        if (null != user.getOrgId()) {
+                            predicates.add(cb.equal(root.get("orgId"), user.getOrgId()));
+                        } else {
+                            predicates.add(cb.equal(root.get("orgId"), -1));
+                        }
+                    } else {
+                        predicates.add(cb.equal(root.get("orgId"), -1));
+                    }
+                } else {
+                    predicates.add(cb.equal(root.get("orgId"), -1));
+                }
+            }
+
+            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+        };
+
+        long count = studentRepo.count(specification);
+        if (100000 < count) {
+            throw new StatusException("520200", "数据量超过100000,无法导出");
+        }
+
+        List<StudentEntity> studentList = studentRepo.findAll(specification,
+                new Sort(Direction.DESC, "updateTime"));
+
+        List<Object[]> datas = Lists.newArrayList();
+
+        for (StudentEntity cur : studentList) {
+            String orgCode = null;
+            String orgName = null;
+            if (null != cur.getOrgId()) {
+                OrgEntity org = GlobalHelper.getEntity(orgRepo, Long.valueOf(cur.getOrgId()),
+                        OrgEntity.class);
+                if (null != org) {
+                    orgCode = org.getCode();
+                    orgName = org.getName();
+                }
+            }
+
+            List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
+                    .findByStudentId(cur.getId());
+            List<String> studentCodeList = Lists.newArrayList();
+            for (StudentCodeEntity sc : studentCodeEntityList) {
+                studentCodeList.add(sc.getStudentCode());
+            }
+
+            datas.add(
+                    new Object[]{cur.getId(), cur.getName(), StringUtils.join(studentCodeList, ";"),
+                            cur.getIdentityNumber(), orgCode, orgName});
+        }
+
+        String filePath = systemConfig.getTempDataDir() + File.separator
+                + System.currentTimeMillis() + ".xlsx";
+        File file = new File(filePath);
+
+        ExcelWriter.write(EXCEL_HEADER, new Class[]{Long.class, String.class, String.class,
+                String.class, String.class, String.class}, datas, new File(filePath));
+
+        exportFile("学生-" + getRootOrgId() + ".xlsx", file);
+
+        FileUtils.deleteQuietly(file);
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param ids
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "启用学生")
+    @PutMapping("enable/{ids}")
+    @Transactional
+    public List<String> enableStudent(@PathVariable String ids) {
+        List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+                .collect(Collectors.toList());
+        List<String> ret = Lists.newArrayList();
+        for (Long cur : studentIds) {
+            StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
+            s.setEnable(true);
+            studentRepo.save(s);
+            ret.add(s.getId() + ":" + s.getName());
+        }
+        for (Long cur : studentIds) {
+            studentCache.remove(cur);
+        }
+        return ret;
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param ids
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "禁用学生")
+    @PutMapping("disable/{ids}")
+    @Transactional
+    public List<String> disableStudent(@PathVariable String ids) {
+        List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+                .collect(Collectors.toList());
+        List<String> ret = Lists.newArrayList();
+        for (Long cur : studentIds) {
+            StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
+            s.setEnable(false);
+            studentRepo.save(s);
+            ret.add(s.getId() + ":" + s.getName());
+        }
+        for (Long cur : studentIds) {
+            studentCache.remove(cur);
+        }
+        return ret;
+    }
+
+    @ApiOperation(value = "重置学生密码", notes = "重置学生密码")
+    @PutMapping("resetPass/{ids}")
+    @Transactional
+    public void resetPassword(@PathVariable String ids) {
+        List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+                .collect(Collectors.toList());
+        for (Long cur : studentIds) {
+            StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
+            if (null == s) {
+                throw new StatusException("450110", "学生不存在");
+            }
+            String identityNumber = s.getIdentityNumber();
+            if (StringUtils.isNotEmpty(identityNumber)
+                    && identityNumber.matches("[0-9a-zA-Z]{6,}")) {
+                s.setPassword(StringUtils.substring(identityNumber, -6, identityNumber.length()));
+            } else {
+                s.setPassword(BasicConsts.DEFAULT_PASSWORD);
+            }
+            s.setUpdateTime(new Date());
+            studentRepo.save(s);
+        }
+    }
+
+    @ApiOperation(value = "重置机构下所有学生密码", notes = "重置机构下所有学生密码")
+    @PutMapping("resetPasswordByOrgId/{orgId}")
+    @Transactional
+    public void resetPasswordByOrgId(@PathVariable Long orgId) {
+        OrgEntity org = GlobalHelper.getPresentEntity(orgRepo, orgId, OrgEntity.class);
+
+        validateRootOrgIsolation(org.getRootId());
+
+        List<StudentEntity> stuentList = studentRepo.findByOrgId(org.getId());
+        for (StudentEntity s : stuentList) {
+            String identityNumber = s.getIdentityNumber();
+            if (StringUtils.isNotEmpty(identityNumber)
+                    && identityNumber.matches("[0-9a-zA-Z]{6,}")) {
+                s.setPassword(StringUtils.substring(identityNumber, -6, identityNumber.length()));
+            } else {
+                s.setPassword(BasicConsts.DEFAULT_PASSWORD);
+            }
+            s.setUpdateTime(new Date());
+            studentRepo.save(s);
+        }
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param newPassword
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "修改学生密码", notes = "修改密码")
+    @PutMapping("password/direct")
+    @Transactional
+    public Long updateStudentPassword(@RequestParam("newPassword") String newPassword) {
+        User accessUser = getAccessUser();
+        if (StringUtils.isEmpty(newPassword)) {
+            throw new StatusException("450201", "新密码为空");
+        }
+
+        if (!newPassword.matches("[a-zA-Z0-9]{6,18}")) {
+            throw new StatusException("450203", "密码必须是6至18位字母或数字");
+        }
+
+        StudentEntity s = GlobalHelper.getEntity(studentRepo, accessUser.getUserId(),
+                StudentEntity.class);
+        s.setPassword(newPassword);
+        studentRepo.save(s);
+        return s.getId();
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param password
+     * @param newPassword
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "修改学生密码", notes = "修改密码")
+    @PutMapping("password")
+    @Transactional
+    public Long updateStudentPassword(@RequestParam("password") String password,
+                                      @RequestParam("newPassword") String newPassword) {
+        User accessUser = getAccessUser();
+        if (StringUtils.isEmpty(password)) {
+            throw new StatusException("450110", "旧密码为空");
+        }
+        if (StringUtils.isEmpty(newPassword)) {
+            throw new StatusException("450111", "新密码为空");
+        }
+        if (!newPassword.matches("[a-zA-Z0-9]{6,18}")) {
+            throw new StatusException("450111", "密码必须是6至18位字母或数字");
+        }
+
+        StudentEntity s = GlobalHelper.getEntity(studentRepo, accessUser.getUserId(),
+                StudentEntity.class);
+
+        if (StringUtils.isNotBlank(s.getPassword()) && !s.getPassword().equals(password)) {
+            throw new StatusException("450111", "当前密码错误");
+        }
+        s.setPassword(newPassword);
+        studentRepo.save(s);
+        return s.getId();
+    }
+
+    /**
+     * 查询学生
+     *
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "查询学生")
+    @GetMapping("getStudentInfoBySession")
+    public StudentInfo getStudentInfoBySession() {
+        User accessUser = getAccessUser();
+        Long rootOrgId = accessUser.getRootOrgId();
+        Long studentId = accessUser.getUserId();
+
+        StudentCacheBean s = CacheHelper.getStudent(studentId);
+
+        OrgCacheBean org = CacheHelper.getOrg(s.getOrgId());
+        OrgCacheBean rootOrg = CacheHelper.getOrg(rootOrgId);
+
+        StudentInfo info = new StudentInfo();
+
+        info.setEnable(s.getEnable());
+        info.setId(s.getId());
+        info.setIdentityNumber(s.getIdentityNumber());
+        info.setName(s.getName());
+        info.setOrgCode(org.getCode());
+        info.setOrgId(org.getId());
+        info.setOrgName(org.getName());
+        info.setPhoneNumber(s.getPhoneNumber());
+        info.setPhotoPath(s.getPhotoPath());
+        info.setRemark(s.getRemark());
+        info.setRootOrgId(rootOrgId);
+        info.setRootOrgName(rootOrg.getName());
+        info.setSecurityPhone(s.getSecurityPhone());
+        info.setStudentCodeList(s.getStudentCodeList());
+
+        return info;
+    }
+
+    @ApiOperation(value = "查询学生")
+    @GetMapping("getStudentInfo")
+    public StudentInfo getStudentInfo(@RequestParam(required = false) Long rootOrgId,
+                                      @RequestParam(required = false) Long studentId,
+                                      @RequestParam(required = false) String identityNumber,
+                                      @RequestParam(required = false) String studentCode,
+                                      @RequestParam(required = false) String securityPhone) {
+        if (null == rootOrgId) {
+            rootOrgId = getRootOrgId();
+        } else {
+            validateRootOrgIsolation(rootOrgId);
+        }
+
+        StudentInfo studentInfo = studentService.getStudentInfo(rootOrgId, studentId,
+                identityNumber, studentCode, securityPhone);
+        if (null != studentInfo) {
+            studentInfo.setIdentityNumber(IdentityNumberHelper.conceal(rootOrgId, studentInfo.getIdentityNumber()));
+        }
+        return studentInfo;
+    }
+
+    @ApiOperation(value = "解绑学号", notes = "")
+    @PostMapping("unbindStudentCode")
+    @Transactional
+    public List<Long> unbindStudentCode(@RequestParam(required = false) String studentCode,
+                                        @RequestParam(required = false) String identityNumber,
+                                        @RequestParam(required = true) Long rootOrgId) {
+
+        if (null == rootOrgId) {
+            rootOrgId = getRootOrgId();
+        } else {
+            OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, rootOrgId, OrgEntity.class);
+            if (null == rootOrg) {
+                throw new StatusException("450110", "rootOrgId is wrong");
+            }
+            validateRootOrgIsolation(rootOrgId);
+        }
+
+        List<Long> studentIdList = studentService.unbindStudentCode(rootOrgId, studentCode,
+                identityNumber);
+
+        for (Long cur : studentIdList) {
+            studentCache.remove(cur);
+        }
+
+        return studentIdList;
+    }
+
+    @ApiOperation(value = "解绑安全手机", notes = "")
+    @PutMapping("unbindSecurityPhone/{ids}")
+    @Transactional
+    public void unbindSecurityPhone(@PathVariable String ids) {
+        List<Long> studentIds = Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
+                .collect(Collectors.toList());
+        for (Long cur : studentIds) {
+            StudentEntity s = GlobalHelper.getEntity(studentRepo, cur, StudentEntity.class);
+            if (null == s) {
+                throw new StatusException("450110", "学生不存在");
+            }
+            validateRootOrgIsolation(s.getRootOrgId());
+        }
+
+        for (Long cur : studentIds) {
+            studentService.unbindSecurityPhone(cur);
+        }
+
+        for (Long cur : studentIds) {
+            studentCache.remove(cur);
+        }
+
+    }
 
 }

+ 6 - 0
examcloud-core-basic-starter/src/main/resources/org-properties.xml

@@ -120,4 +120,10 @@
 		<desc>学生端版本</desc>
 		<valueType>STRING</valueType>
 	</enum>
+	<enum>
+		<id>20</id>
+		<name>ID_NUMBER_PRIVATE_MODE</name>
+		<desc>证件号隐私模式</desc>
+		<valueType>BOOLEAN</valueType>
+	</enum>
 </enums>