|
|
@@ -1,10 +1,13 @@
|
|
|
package org.springblade.system.user.service.impl;
|
|
|
|
|
|
+import com.alibaba.excel.EasyExcel;
|
|
|
+import com.alibaba.excel.read.metadata.ReadSheet;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.alibaba.nacos.common.utils.StringUtils;
|
|
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
@@ -35,6 +38,8 @@ import org.springblade.core.tool.utils.*;
|
|
|
import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
|
|
|
import org.springblade.manager.entity.*;
|
|
|
import org.springblade.manager.feign.ContractClient;
|
|
|
+import org.springblade.manager.feign.ProjectAssignmentUserClient;
|
|
|
+import org.springblade.manager.feign.SaveUserInfoByProjectClient;
|
|
|
import org.springblade.manager.vo.PrivateTreeVO;
|
|
|
import org.springblade.manager.vo.PrivateTreeVO2;
|
|
|
import org.springblade.manager.vo.WbsTreeContractLazyQueryInfoVO;
|
|
|
@@ -45,12 +50,13 @@ import org.springblade.system.cache.DictCache;
|
|
|
import org.springblade.system.cache.ParamCache;
|
|
|
import org.springblade.system.cache.SysCache;
|
|
|
import org.springblade.system.entity.Dept;
|
|
|
+import org.springblade.system.entity.Role;
|
|
|
import org.springblade.system.entity.Tenant;
|
|
|
import org.springblade.system.enums.DictEnum;
|
|
|
import org.springblade.system.feign.ISysClient;
|
|
|
import org.springblade.system.user.bean.NodeVO;
|
|
|
import org.springblade.system.user.cache.UserCache;
|
|
|
-import org.springblade.system.user.dto.UserDTO;
|
|
|
+import org.springblade.system.user.dto.*;
|
|
|
import org.springblade.system.user.entity.*;
|
|
|
import org.springblade.system.user.enums.UserEnum;
|
|
|
import org.springblade.system.user.excel.UserExcel;
|
|
|
@@ -69,15 +75,24 @@ import org.springblade.system.user.wrapper.UserWrapper;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.dao.DataAccessException;
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
|
|
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
import org.springframework.jdbc.core.SingleColumnRowMapper;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.FileNotFoundException;
|
|
|
+import java.io.IOException;
|
|
|
+import java.sql.PreparedStatement;
|
|
|
+import java.sql.SQLException;
|
|
|
+import java.text.ParseException;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
|
@@ -85,6 +100,7 @@ import java.util.concurrent.CountDownLatch;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
import java.util.function.Function;
|
|
|
+import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
|
@@ -115,6 +131,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|
|
private final JdbcTemplate jdbcTemplate;
|
|
|
@Autowired
|
|
|
StringRedisTemplate redisTemplate;
|
|
|
+ @Autowired
|
|
|
+ private SaveUserInfoByProjectClient saveUserInfoByProjectClient;
|
|
|
|
|
|
|
|
|
@Override
|
|
|
@@ -2358,4 +2376,800 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|
|
return R.data(information);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public R importUserNew(MultipartFile file) {
|
|
|
+ List<UserImporterNew> finalUserList = new ArrayList<>();
|
|
|
+ List<ImportUserLog>logs=new ArrayList<>();
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ String importTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
+ Long importId= SnowFlakeUtil.getId();
|
|
|
+ Long importUser=AuthUtil.getUserId();
|
|
|
+ List<User> insertUserList=new ArrayList<>();
|
|
|
+ List<UserDept> insertUserDeptList=new ArrayList<>();
|
|
|
+ List<SaveUserInfoByProjectDTO> insertUserInfoByProjectList=new ArrayList<>();
|
|
|
+ List<User>updateUserList=new ArrayList<>();
|
|
|
+ List<SaveUserInfoByProjectDTO>updateUserInfoByProjectList=new ArrayList<>();
|
|
|
+ try {
|
|
|
+ // 1. 获取所有sheet元数据
|
|
|
+ List<ReadSheet> allSheets = EasyExcel.read(file.getInputStream())
|
|
|
+ .head(ExcelUserTemp.class)
|
|
|
+ .build()
|
|
|
+ .excelExecutor()
|
|
|
+ .sheetList();
|
|
|
+ // 遍历每个Sheet,逐个读取并处理数据
|
|
|
+ for (ReadSheet sheet : allSheets) {
|
|
|
+ System.out.printf("开始读取Sheet:%s(索引:%d)%n", sheet.getSheetName(), sheet.getSheetNo());
|
|
|
+
|
|
|
+ List<ExcelUserTemp> sheetData = EasyExcel.read(file.getInputStream())
|
|
|
+ .head(ExcelUserTemp.class)
|
|
|
+ .sheet(sheet.getSheetNo())
|
|
|
+ .headRowNumber(2)
|
|
|
+ .doReadSync();
|
|
|
+
|
|
|
+ UserImporterNew currentUser = null;
|
|
|
+ List<ImportPorjectInfoDTO> tempProjectList = new ArrayList<>();
|
|
|
+ String currentProjectId = ""; // 新增:存储当前用户的“基准项目ID”(继承自新用户行)
|
|
|
+
|
|
|
+ for (ExcelUserTemp row : sheetData) {
|
|
|
+ if (!isCoreFieldEmpty(row)) {
|
|
|
+ // 处理上一个用户
|
|
|
+ if (currentUser != null) {
|
|
|
+ currentUser.setProjectInfoList(tempProjectList);
|
|
|
+ finalUserList.add(currentUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化新用户
|
|
|
+ currentUser = initUserImporterNew(row);
|
|
|
+ tempProjectList = new ArrayList<>();
|
|
|
+ // 新用户行的projectId作为基准ID
|
|
|
+ currentProjectId = Objects.nonNull(row.getProjectId()) ? row.getProjectId().trim() : "";
|
|
|
+
|
|
|
+ // 生成新用户行的项目DTO
|
|
|
+ ImportPorjectInfoDTO projectDTO = buildPorjectInfoDTO(row, currentProjectId);
|
|
|
+ if (projectDTO != null) {
|
|
|
+ tempProjectList.add(projectDTO);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 补充行:继承当前基准项目ID
|
|
|
+ if (currentUser != null) {
|
|
|
+ // 若补充行有新的projectId(如王三5的补充行),更新基准ID
|
|
|
+ if (Objects.nonNull(row.getProjectId()) && !row.getProjectId().trim().isEmpty()) {
|
|
|
+ currentProjectId = row.getProjectId().trim();
|
|
|
+ }
|
|
|
+ // 生成DTO(传入基准projectId)
|
|
|
+ ImportPorjectInfoDTO projectDTO = buildPorjectInfoDTO(row, currentProjectId);
|
|
|
+ if (projectDTO != null) {
|
|
|
+ if (!isProjectDuplicate(tempProjectList, projectDTO)) {
|
|
|
+ tempProjectList.add(projectDTO);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理最后一个用户
|
|
|
+ if (currentUser != null) {
|
|
|
+ currentUser.setProjectInfoList(tempProjectList);
|
|
|
+ finalUserList.add(currentUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String file_path = FileUtils.getSysLocalFileUrl();
|
|
|
+ String filePath = file_path + "/importExcel/" + importId + ".xlsx";
|
|
|
+ try {
|
|
|
+ // 创建目录(如果不存在)
|
|
|
+ File directory = new File(file_path + "/importExcel/");
|
|
|
+ if (!directory.exists()) {
|
|
|
+ directory.mkdirs();
|
|
|
+ }
|
|
|
+ // 保存文件
|
|
|
+ file.transferTo(new File(filePath));
|
|
|
+ } catch (IOException e) {
|
|
|
+ // 处理异常
|
|
|
+ throw new ServiceException("文件保存失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ // 5. 后续业务逻辑(批量保存等)
|
|
|
+ if (!finalUserList.isEmpty()) {
|
|
|
+ //查出所有的部门名
|
|
|
+ List<Dept>deptNames=jdbcTemplate.query("select id,dept_name from blade_dept where is_deleted=0",new BeanPropertyRowMapper<>(Dept.class));
|
|
|
+ //查出所有的角色名
|
|
|
+ List<Role>roleNamesSG=jdbcTemplate.query("select id,role_name from blade_role where parent_id=(select id from blade_role where role_name='施工方' and is_deleted=0 limit 1)",new BeanPropertyRowMapper<>(Role.class));
|
|
|
+ List<Role>roleNamesJL=jdbcTemplate.query("select id,role_name from blade_role where parent_id=(select id from blade_role where role_name='监理方' and is_deleted=0 limit 1)",new BeanPropertyRowMapper<>(Role.class));
|
|
|
+ List<Role>roleNamesYZ=jdbcTemplate.query("select id,role_name from blade_role where parent_id=(select id from blade_role where role_name='业主方' and is_deleted=0 limit 1)",new BeanPropertyRowMapper<>(Role.class));
|
|
|
+ Map<String,List<Role>> roleMap= new HashMap<>();
|
|
|
+ roleMap.put("3",roleNamesSG);
|
|
|
+ roleMap.put("2",roleNamesJL);
|
|
|
+ roleMap.put("1",roleNamesYZ);
|
|
|
+ //查出所有的项目的合同段名
|
|
|
+ // 查出所有的项目的合同段名
|
|
|
+ Set<String> projectIdSet = finalUserList.stream()
|
|
|
+ .filter(user -> user.getProjectInfoList() != null) // 过滤掉projectInfoList为null的用户
|
|
|
+ .flatMap(user -> user.getProjectInfoList().stream()) // 展平所有项目列表
|
|
|
+ .filter(project -> project.getProjectId() != null && !project.getProjectId().trim().isEmpty()) // 过滤掉projectId为null或空的项目
|
|
|
+ .map(project -> project.getProjectId().trim()) // 提取并trim projectId
|
|
|
+ .collect(Collectors.toSet()); // 收集到Set中去重
|
|
|
+ List<String>projectIds=contractClient.queryProjectIds(projectIdSet);
|
|
|
+ //根据项目id查询合同段
|
|
|
+ Map<String,List<ContractInfo>> contractNamesMap=new HashMap<>();
|
|
|
+ if(!projectIds.isEmpty()){
|
|
|
+ for (String projectId : projectIds) {
|
|
|
+ List<ContractInfo>contractNames=contractClient.queryContractNamesListByProjectId(projectId);
|
|
|
+ contractNamesMap.put(projectId,contractNames);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (UserImporterNew userImporterNew : finalUserList) {
|
|
|
+ if(!userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ userImporterNew.getProjectInfoList().removeIf(o->StringUtils.isEmpty(o.getProjectId())||StringUtils.isEmpty(o.getContractInfo()));
|
|
|
+ }
|
|
|
+ //首先 根据账号查询用户
|
|
|
+ //账号为null
|
|
|
+ if(StringUtil.isEmpty(userImporterNew.getAccount())){
|
|
|
+ //姓名不为null
|
|
|
+ if(!StringUtil.isEmpty(userImporterNew.getRealName())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),userImporterNew.getRealName()+"的账号为空",importTime,importId,importUser,file.getOriginalFilename());
|
|
|
+ logs.add(log);
|
|
|
+ }else {
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"账号姓名都为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ User user=this.getOne(new QueryWrapper<User>().lambda().eq(User::getAccount,userImporterNew.getAccount()));
|
|
|
+ //账号不存在 则新增
|
|
|
+ if(user==null){
|
|
|
+ //前置条件判断
|
|
|
+ /**
|
|
|
+ * 验证姓名
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(userImporterNew.getRealName())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"姓名为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证手机号
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(userImporterNew.getPhone())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"手机号为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ boolean b = isValidChinesePhoneNumber(userImporterNew.getPhone());
|
|
|
+ if(!b){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"手机号格式错误",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证身份证号
|
|
|
+ */
|
|
|
+ if(!StringUtil.isEmpty(userImporterNew.getIdNumber())) {
|
|
|
+ boolean b = isValidIdCard(userImporterNew.getIdNumber());
|
|
|
+ if(!b){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"身份证号格式错误",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证用户平台
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(userImporterNew.getUserType())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"用户平台为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ String userType = userImporterNew.getUserType();
|
|
|
+ List<String> types = new ArrayList<>();
|
|
|
+ if (userType != null && !userType.isEmpty()) {
|
|
|
+ Pattern pattern = Pattern.compile("\\d+");
|
|
|
+ java.util.regex.Matcher matcher = pattern.matcher(userType);
|
|
|
+ while (matcher.find()) {
|
|
|
+ types.add(matcher.group());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //判断是否只包含1,2,3,7
|
|
|
+ Set<String> allowedTypes = new HashSet<>(Arrays.asList("1", "2", "3", "7"));
|
|
|
+ boolean isValid = types.stream().allMatch(allowedTypes::contains);
|
|
|
+ if(!isValid){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"用户平台格式错误",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ userImporterNew.setUserType(String.join(",", types));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证部门
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(userImporterNew.getDeptName())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属部门为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ Optional<Dept> dept = deptNames.stream().filter(deptName -> !StringUtil.isEmpty(deptName.getDeptName()) && deptName.getDeptName().equals(userImporterNew.getDeptName())).findFirst();
|
|
|
+ if(!dept.isPresent()){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属部门不存在",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ userImporterNew.setDeptId(dept.get().getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //如果部门信息全都为null 就跳过验证
|
|
|
+ if(userImporterNew.getProjectInfoList()!=null&& !userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ List<ImportPorjectInfoDTO> projectInfoList = userImporterNew.getProjectInfoList();
|
|
|
+ for (ImportPorjectInfoDTO dto : projectInfoList) {
|
|
|
+ /**
|
|
|
+ * 验证项目信息
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getProjectId())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属项目为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ if(!projectIds.contains(dto.getProjectId())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属项目Id:"+dto.getProjectId()+",没找到对应的项目",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证合同段
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getContractInfo())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"合同段名称/编号为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ List<ContractInfo> contractInfos = contractNamesMap.get(dto.getProjectId());
|
|
|
+ Optional<ContractInfo> nameOptional = contractInfos.stream().filter(c -> !StringUtil.isEmpty(c.getContractName()) && c.getContractName().equals(dto.getContractInfo())).findFirst();
|
|
|
+ Optional<ContractInfo> numberOptional = contractInfos.stream().filter(c -> !StringUtil.isEmpty(c.getContractNumber()) && c.getContractNumber().equals(dto.getContractInfo())).findFirst();
|
|
|
+ if(!(nameOptional.isPresent()||numberOptional.isPresent())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"合同段名称/编号不存在:"+dto.getContractInfo(),importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ if(nameOptional.isPresent()){
|
|
|
+ dto.setContractId(nameOptional.get().getId());
|
|
|
+ }else {
|
|
|
+ dto.setContractId(numberOptional.get().getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证所属方
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getOwner())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属方为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ String owner = dto.getOwner();
|
|
|
+ if(!(owner.equals("1")||owner.equals("2")||owner.equals("3"))){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属方格式错误",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证岗位
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getRoleName())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"角色为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ }else {
|
|
|
+ List<Role> roles = roleMap.get(dto.getOwner());
|
|
|
+ Optional<Role> role = roles.stream().filter(r -> r.getRoleName().equals(dto.getRoleName())).findFirst();
|
|
|
+ if (role.isPresent()) {
|
|
|
+ dto.setRoleId(role.get().getId());
|
|
|
+ } else {
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"角色不存在",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //验证完毕 开始新增
|
|
|
+ if(!userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ userImporterNew.getProjectInfoList().removeIf(dto -> dto.getStatus()==1);
|
|
|
+ }
|
|
|
+ String roleIds = "";
|
|
|
+ if(!userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ if (userImporterNew.getProjectInfoList() != null) {
|
|
|
+ roleIds = userImporterNew.getProjectInfoList().stream()
|
|
|
+ .filter(dto -> dto.getRoleId() != null)
|
|
|
+ .map(dto -> String.valueOf(dto.getRoleId())) // 显式转换为字符串
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 用户账号表
|
|
|
+ */
|
|
|
+ User insertUser=new User();
|
|
|
+ insertUser.setId(SnowFlakeUtil.getId());
|
|
|
+ insertUser.setTenantId(AuthUtil.getTenantId());
|
|
|
+ insertUser.setAccount(userImporterNew.getAccount());
|
|
|
+ insertUser.setUserType(userImporterNew.getUserType());
|
|
|
+ insertUser.setPassword(DigestUtil.encrypt(userImporterNew.getPassword()));
|
|
|
+ insertUser.setPlaintextPassword(userImporterNew.getPassword());
|
|
|
+ insertUser.setName(userImporterNew.getRealName());
|
|
|
+ insertUser.setRealName(userImporterNew.getRealName());
|
|
|
+ insertUser.setIdNumber(userImporterNew.getIdNumber());
|
|
|
+ insertUser.setPhone(userImporterNew.getPhone());
|
|
|
+ insertUser.setRoleId(roleIds);
|
|
|
+ insertUser.setDeptId(userImporterNew.getDeptId()+"");
|
|
|
+ insertUser.setStatus("是".equals(userImporterNew.getStatus()) ? 1 : 0);
|
|
|
+ insertUser.setAccCode(userImporterNew.getAccCode());
|
|
|
+ insertUserList.add(insertUser);
|
|
|
+ /**
|
|
|
+ * 用户部门表
|
|
|
+ */
|
|
|
+ UserDept userDept = new UserDept();
|
|
|
+ userDept.setUserId(insertUser.getId());
|
|
|
+ userDept.setDeptId(userImporterNew.getDeptId());
|
|
|
+ insertUserDeptList.add(userDept);
|
|
|
+ /**
|
|
|
+ * 项目分配用户关系表
|
|
|
+ */
|
|
|
+ if(!userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ List<ImportPorjectInfoDTO> projectInfoList = userImporterNew.getProjectInfoList();
|
|
|
+ for (ImportPorjectInfoDTO info : projectInfoList) {
|
|
|
+ SaveUserInfoByProjectDTO dto = new SaveUserInfoByProjectDTO();
|
|
|
+ dto.setId(SnowFlakeUtil.getId());
|
|
|
+ dto.setProjectId(info.getProjectId());
|
|
|
+ dto.setContractId(info.getContractId()+"");
|
|
|
+ dto.setRoleId(info.getRoleId()+"");
|
|
|
+ dto.setUserId(insertUser.getId()+"");
|
|
|
+ dto.setStatus(1);
|
|
|
+ insertUserInfoByProjectList.add(dto);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ //账号存在 则更新
|
|
|
+ //模板上姓名和数据库的姓名相同则修改
|
|
|
+ if(!StringUtil.isEmpty(userImporterNew.getRealName())){
|
|
|
+ if(user.getRealName().equals(userImporterNew.getRealName())){
|
|
|
+ //拿到项目和合同段
|
|
|
+ //如果部门信息全都为null 就跳过验证
|
|
|
+ if(userImporterNew.getProjectInfoList()!=null&& !userImporterNew.getProjectInfoList().isEmpty()){
|
|
|
+ List<ImportPorjectInfoDTO> projectInfoList = userImporterNew.getProjectInfoList();
|
|
|
+ for (ImportPorjectInfoDTO dto : projectInfoList) {
|
|
|
+ /**
|
|
|
+ * 验证项目信息
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getProjectId())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属项目为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ if(!projectIds.contains(dto.getProjectId())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属项目Id:"+dto.getProjectId()+",没找到对应的项目",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证合同段
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getContractInfo())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"合同段名称/编号为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ List<ContractInfo> contractInfos = contractNamesMap.get(dto.getProjectId());
|
|
|
+ Optional<ContractInfo> nameOptional = contractInfos.stream().filter(c -> !StringUtil.isEmpty(c.getContractName()) && c.getContractName().equals(dto.getContractInfo())).findFirst();
|
|
|
+ Optional<ContractInfo> numberOptional = contractInfos.stream().filter(c -> !StringUtil.isEmpty(c.getContractNumber()) && c.getContractNumber().equals(dto.getContractInfo())).findFirst();
|
|
|
+ if(!(nameOptional.isPresent()||numberOptional.isPresent())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"合同段名称/编号不存在:"+dto.getContractInfo(),importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ if(nameOptional.isPresent()){
|
|
|
+ dto.setContractId(nameOptional.get().getId());
|
|
|
+ }else {
|
|
|
+ dto.setContractId(numberOptional.get().getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证所属方
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getOwner())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属方为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }else {
|
|
|
+ String owner = dto.getOwner();
|
|
|
+ if(!(owner.equals("1")||owner.equals("2")||owner.equals("3"))){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"所属方格式错误",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 验证岗位
|
|
|
+ */
|
|
|
+ if(StringUtil.isEmpty(dto.getRoleName())){
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"角色为空",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ }else {
|
|
|
+ List<Role> roles = roleMap.get(dto.getOwner());
|
|
|
+ Optional<Role> role = roles.stream().filter(r -> r.getRoleName().equals(dto.getRoleName())).findFirst();
|
|
|
+ if (role.isPresent()) {
|
|
|
+ dto.setRoleId(role.get().getId());
|
|
|
+ } else {
|
|
|
+ ImportUserLog log=new ImportUserLog(SnowFlakeUtil.getId(),userImporterNew.getAccount(),userImporterNew.getRealName(),"角色不存在",importTime,importId,importUser,filePath);
|
|
|
+ logs.add(log);
|
|
|
+ dto.setStatus(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (userImporterNew.getProjectInfoList() != null && !userImporterNew.getProjectInfoList().isEmpty()) {
|
|
|
+ for (ImportPorjectInfoDTO dto : userImporterNew.getProjectInfoList()) {
|
|
|
+ String sql = "select * from m_project_assignment_user where user_id=" + user.getId() + " and contract_id=" + dto.getContractId();
|
|
|
+ List<SaveUserInfoByProjectDTO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(SaveUserInfoByProjectDTO.class));
|
|
|
+ if (query.isEmpty()) {
|
|
|
+ SaveUserInfoByProjectDTO projectdto = new SaveUserInfoByProjectDTO();
|
|
|
+ projectdto.setId(SnowFlakeUtil.getId());
|
|
|
+ projectdto.setProjectId(dto.getProjectId());
|
|
|
+ projectdto.setContractId(dto.getContractId() + "");
|
|
|
+ projectdto.setRoleId(dto.getRoleId() + "");
|
|
|
+ projectdto.setUserId(user.getId() + "");
|
|
|
+ projectdto.setStatus(1);
|
|
|
+ insertUserInfoByProjectList.add(projectdto);
|
|
|
+ user.setRoleId(user.getRoleId()+","+dto.getRoleId());
|
|
|
+ user.setStatus("是".equals(userImporterNew.getStatus()) ? 1 : 0);
|
|
|
+ updateUserList.add(user);
|
|
|
+ } else {
|
|
|
+ SaveUserInfoByProjectDTO projectdto = query.get(0);
|
|
|
+ projectdto.setRoleId(dto.getRoleId() + "");
|
|
|
+ updateUserInfoByProjectList.add(projectdto);
|
|
|
+ user.setRoleId(user.getRoleId()+","+dto.getRoleId());
|
|
|
+ user.setStatus("是".equals(userImporterNew.getStatus()) ? 1 : 0);
|
|
|
+ updateUserList.add(user);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!insertUserList.isEmpty()){
|
|
|
+ this.saveBatch(insertUserList);
|
|
|
+ }
|
|
|
+ if(!insertUserDeptList.isEmpty()){
|
|
|
+ userDeptService.saveBatch(insertUserDeptList);
|
|
|
+ }
|
|
|
+ if(!insertUserInfoByProjectList.isEmpty()){
|
|
|
+ saveUserInfoByProjectClient.insertUserInfoBatch(insertUserInfoByProjectList);
|
|
|
+ }
|
|
|
+ if(!updateUserInfoByProjectList.isEmpty()){
|
|
|
+ saveUserInfoByProjectClient.updateUserInfoBatch(updateUserInfoByProjectList);
|
|
|
+ }
|
|
|
+ if(!updateUserList.isEmpty()){
|
|
|
+ for (User user : updateUserList) {
|
|
|
+ String sql="select role_id from m_project_assignment_user where user_id="+user.getId()+" and is_deleted=0";
|
|
|
+ List<String> roleIds = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
|
|
|
+ String roleId = user.getRoleId();
|
|
|
+ if (!StringUtil.isEmpty(roleId)) {
|
|
|
+ // 按逗号分割,去重后再重新拼接
|
|
|
+ List<String> roleIdList = Arrays.asList(roleId.split(","));
|
|
|
+ List<String> distinctRoleIds = roleIdList.stream().distinct().collect(Collectors.toList());
|
|
|
+ roleId = String.join(",", distinctRoleIds);
|
|
|
+ }
|
|
|
+ user.setRoleId(roleIds.isEmpty() ? roleId : String.join(",", roleIds));
|
|
|
+ }
|
|
|
+ this.updateBatchById(updateUserList);
|
|
|
+ }
|
|
|
+ if(!logs.isEmpty()){
|
|
|
+ this.saveUserImportLogs(logs);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return R.fail("导入失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ if(logs.size()>0){
|
|
|
+ return R.fail("导入失败:" + logs.size() + "条记录导入失败");
|
|
|
+ }
|
|
|
+ return R.success("导入成功,共新增:" + insertUserList.size() + "条有效记录,更新:"+updateUserInfoByProjectList.size()+"条记录");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存用户导入日志
|
|
|
+ * @param logs
|
|
|
+ */
|
|
|
+ private void saveUserImportLogs(List<ImportUserLog> logs) {
|
|
|
+ if (logs == null || logs.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String sql = "INSERT INTO blade_import_user_log " +
|
|
|
+ "(id, account, name, message, import_time, import_id, import_user, file_path) " +
|
|
|
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
|
|
+ jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
|
|
|
+ @Override
|
|
|
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
|
|
|
+ ImportUserLog log = logs.get(i);
|
|
|
+ ps.setObject(1, log.getId()); // id
|
|
|
+ ps.setString(2, log.getAccount()); // account
|
|
|
+ ps.setString(3, log.getName()); // name
|
|
|
+ ps.setString(4, log.getMessage()); // message
|
|
|
+ ps.setString(5, log.getImportTime()); // import_time
|
|
|
+ ps.setObject(6, log.getImportId()); // import_id
|
|
|
+ ps.setObject(7, log.getImportUser()); // import_user
|
|
|
+ ps.setString(8, log.getFilePath()); // file_path
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public int getBatchSize() {
|
|
|
+ return logs.size();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化UserImporterNew:赋值核心字段+处理默认值
|
|
|
+ * @param row Excel行数据
|
|
|
+ * @return 初始化后的UserImporterNew
|
|
|
+ */
|
|
|
+ private UserImporterNew initUserImporterNew(ExcelUserTemp row) {
|
|
|
+ UserImporterNew user = new UserImporterNew();
|
|
|
+ // 处理默认值:密码默认"user123456",登录状态默认"是"
|
|
|
+ String defaultPwd = Objects.isNull(row.getPassword()) || row.getPassword().trim().isEmpty()
|
|
|
+ ? "user123456"
|
|
|
+ : row.getPassword().trim();
|
|
|
+ String defaultStatus = Objects.isNull(row.getStatus()) || row.getStatus().trim().isEmpty()
|
|
|
+ ? "是"
|
|
|
+ : row.getStatus().trim();
|
|
|
+
|
|
|
+ // 赋值核心用户字段(trim避免空格问题)
|
|
|
+ user.setAccount(Objects.nonNull(row.getAccount()) ? row.getAccount().trim() : "");
|
|
|
+ user.setPassword(defaultPwd);
|
|
|
+ user.setRealName(Objects.nonNull(row.getRealName()) ? row.getRealName().trim() : "");
|
|
|
+ user.setUserType(Objects.nonNull(row.getUserType()) ? row.getUserType().trim() : "");
|
|
|
+ user.setPhone(Objects.nonNull(row.getPhone()) ? row.getPhone().trim() : "");
|
|
|
+ user.setIdNumber(Objects.nonNull(row.getIdNumber()) ? row.getIdNumber().trim() : "");
|
|
|
+ user.setDeptName(Objects.nonNull(row.getDeptName()) ? row.getDeptName().trim() : "");
|
|
|
+ user.setAccCode(Objects.nonNull(row.getAccCode()) ? row.getAccCode().trim() : "");
|
|
|
+ user.setStatus(defaultStatus);
|
|
|
+ user.setDeptId(null);
|
|
|
+ return user;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 构建PorjectInfoDTO:补充行继承基准projectId
|
|
|
+ * @param row Excel行数据
|
|
|
+ * @param baseProjectId 基准项目ID(新用户行的projectId)
|
|
|
+ * @return 有效DTO(projectId非空)
|
|
|
+ */
|
|
|
+ private ImportPorjectInfoDTO buildPorjectInfoDTO(ExcelUserTemp row, String baseProjectId) {
|
|
|
+ // 优先用行内projectId,为空则用基准ID
|
|
|
+ String projectId = Objects.nonNull(row.getProjectId()) ? row.getProjectId().trim() : baseProjectId;
|
|
|
+ // 基准ID也为空则视为无效
|
|
|
+ if (projectId.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ ImportPorjectInfoDTO dto = new ImportPorjectInfoDTO();
|
|
|
+ dto.setProjectId(projectId);
|
|
|
+ dto.setContractInfo(Objects.nonNull(row.getContractInfo()) ? row.getContractInfo().trim() : "");
|
|
|
+ dto.setOwner(Objects.nonNull(row.getOwner()) ? row.getOwner().trim() : "");
|
|
|
+ dto.setRoleName(Objects.nonNull(row.getRoleName()) ? row.getRoleName().trim() : "");
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 判断项目是否重复:按「项目ID+合同段」组合去重
|
|
|
+ * @param projectList 已存在的项目列表
|
|
|
+ * @param newDTO 新项目DTO
|
|
|
+ * @return true=重复,false=不重复
|
|
|
+ */
|
|
|
+ private boolean isProjectDuplicate(List<ImportPorjectInfoDTO> projectList, ImportPorjectInfoDTO newDTO) {
|
|
|
+ for (ImportPorjectInfoDTO existDTO : projectList) {
|
|
|
+ // 项目ID和合同段均相同 → 视为重复
|
|
|
+ boolean isSameProjectId = existDTO.getProjectId().equals(newDTO.getProjectId());
|
|
|
+ boolean isSameContract = existDTO.getContractInfo().equals(newDTO.getContractInfo());
|
|
|
+ if (isSameProjectId && isSameContract) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 判断核心字段是否为空:用于识别「新用户行」vs「补充行」
|
|
|
+ * 核心字段:登录账号+用户姓名+手机号码(至少一个非空即为新用户行)
|
|
|
+ * @param row Excel行数据
|
|
|
+ * @return true=核心字段全空(补充行),false=核心字段有值(新用户行)
|
|
|
+ */
|
|
|
+ private boolean isCoreFieldEmpty(ExcelUserTemp row) {
|
|
|
+ return (Objects.isNull(row.getAccount()) || row.getAccount().trim().isEmpty())
|
|
|
+ && (Objects.isNull(row.getRealName()) || row.getRealName().trim().isEmpty())
|
|
|
+ && (Objects.isNull(row.getPhone()) || row.getPhone().trim().isEmpty());
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 判断中国大陆手机号格式是否正确
|
|
|
+ *
|
|
|
+ * @param phoneNumber 手机号
|
|
|
+ * @return true表示格式正确,false表示格式错误
|
|
|
+ */
|
|
|
+ public static boolean isValidChinesePhoneNumber(String phoneNumber) {
|
|
|
+ if (phoneNumber == null || phoneNumber.length() != 11) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用正则表达式匹配手机号格式
|
|
|
+ String regex = "^1[3-9]\\d{9}$";
|
|
|
+ return phoneNumber.matches(regex);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断身份证格式是否正确
|
|
|
+ *
|
|
|
+ * @param idCard 身份证号码
|
|
|
+ * @return true表示格式正确,false表示格式错误
|
|
|
+ */
|
|
|
+ public static boolean isValidIdCard(String idCard) {
|
|
|
+ if (idCard == null || idCard.trim().isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ idCard = idCard.trim();
|
|
|
+
|
|
|
+ // 长度验证
|
|
|
+ if (idCard.length() == 15) {
|
|
|
+ return isValidIdCard15(idCard);
|
|
|
+ } else if (idCard.length() == 18) {
|
|
|
+ return isValidIdCard18(idCard);
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证15位身份证号码
|
|
|
+ *
|
|
|
+ * @param idCard 15位身份证号码
|
|
|
+ * @return true表示格式正确,false表示格式错误
|
|
|
+ */
|
|
|
+ private static boolean isValidIdCard15(String idCard) {
|
|
|
+ // 15位身份证号码为纯数字
|
|
|
+ if (!Pattern.matches("\\d{15}", idCard)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证出生日期
|
|
|
+ String birthDay = "19" + idCard.substring(6, 12); // 15位身份证年份默认为19XX年
|
|
|
+ return isValidDate(birthDay, "yyyyMMdd");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证18位身份证号码
|
|
|
+ *
|
|
|
+ * @param idCard 18位身份证号码
|
|
|
+ * @return true表示格式正确,false表示格式错误
|
|
|
+ */
|
|
|
+ private static boolean isValidIdCard18(String idCard) {
|
|
|
+ // 18位身份证号码前17位为数字,最后一位为数字或X
|
|
|
+ if (!Pattern.matches("\\d{17}[\\dXx]", idCard)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证地址码(简单验证前两位)
|
|
|
+ String areaCode = idCard.substring(0, 2);
|
|
|
+ if (!AREA_CODES.contains(areaCode)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证出生日期
|
|
|
+ String birthDay = idCard.substring(6, 14);
|
|
|
+ if (!isValidDate(birthDay, "yyyyMMdd")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证校验码
|
|
|
+ return checkIdCard18(idCard);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证日期格式是否正确
|
|
|
+ *
|
|
|
+ * @param date 日期字符串
|
|
|
+ * @param format 日期格式
|
|
|
+ * @return true表示日期格式正确,false表示日期格式错误
|
|
|
+ */
|
|
|
+ private static boolean isValidDate(String date, String format) {
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
|
|
|
+ sdf.setLenient(false); // 严格模式,不允许不合理的日期
|
|
|
+ try {
|
|
|
+ sdf.parse(date);
|
|
|
+ // 检查年份范围(例如:1900年至今)
|
|
|
+ Calendar calendar = new GregorianCalendar();
|
|
|
+ calendar.setTime(sdf.parse(date));
|
|
|
+ int year = calendar.get(Calendar.YEAR);
|
|
|
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
|
|
|
+ return year >= 1900 && year <= currentYear;
|
|
|
+ } catch (ParseException e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证18位身份证号码的校验码
|
|
|
+ *
|
|
|
+ * @param idCard 18位身份证号码
|
|
|
+ * @return true表示校验码正确,false表示校验码错误
|
|
|
+ */
|
|
|
+ private static boolean checkIdCard18(String idCard) {
|
|
|
+ char[] idCardArray = idCard.toCharArray();
|
|
|
+ int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
|
|
+ char[] validate = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
|
|
|
+ int sum = 0;
|
|
|
+
|
|
|
+ for (int i = 0; i < 17; i++) {
|
|
|
+ sum += (idCardArray[i] - '0') * weight[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ int mod = sum % 11;
|
|
|
+ char validateCode = validate[mod];
|
|
|
+
|
|
|
+ return Character.toUpperCase(idCardArray[17]) == validateCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 简化的省份代码列表(前两位)
|
|
|
+ private static final java.util.Set<String> AREA_CODES = new java.util.HashSet<>();
|
|
|
+ static {
|
|
|
+ AREA_CODES.add("11"); // 北京
|
|
|
+ AREA_CODES.add("12"); // 天津
|
|
|
+ AREA_CODES.add("13"); // 河北
|
|
|
+ AREA_CODES.add("14"); // 山西
|
|
|
+ AREA_CODES.add("15"); // 内蒙古
|
|
|
+ AREA_CODES.add("21"); // 辽宁
|
|
|
+ AREA_CODES.add("22"); // 吉林
|
|
|
+ AREA_CODES.add("23"); // 黑龙江
|
|
|
+ AREA_CODES.add("31"); // 上海
|
|
|
+ AREA_CODES.add("32"); // 江苏
|
|
|
+ AREA_CODES.add("33"); // 浙江
|
|
|
+ AREA_CODES.add("34"); // 安徽
|
|
|
+ AREA_CODES.add("35"); // 福建
|
|
|
+ AREA_CODES.add("36"); // 江西
|
|
|
+ AREA_CODES.add("37"); // 山东
|
|
|
+ AREA_CODES.add("41"); // 河南
|
|
|
+ AREA_CODES.add("42"); // 湖北
|
|
|
+ AREA_CODES.add("43"); // 湖南
|
|
|
+ AREA_CODES.add("44"); // 广东
|
|
|
+ AREA_CODES.add("45"); // 广西
|
|
|
+ AREA_CODES.add("46"); // 海南
|
|
|
+ AREA_CODES.add("50"); // 重庆
|
|
|
+ AREA_CODES.add("51"); // 四川
|
|
|
+ AREA_CODES.add("52"); // 贵州
|
|
|
+ AREA_CODES.add("53"); // 云南
|
|
|
+ AREA_CODES.add("54"); // 西藏
|
|
|
+ AREA_CODES.add("61"); // 陕西
|
|
|
+ AREA_CODES.add("62"); // 甘肃
|
|
|
+ AREA_CODES.add("63"); // 青海
|
|
|
+ AREA_CODES.add("64"); // 宁夏
|
|
|
+ AREA_CODES.add("65"); // 新疆
|
|
|
+ AREA_CODES.add("71"); // 台湾
|
|
|
+ AREA_CODES.add("81"); // 香港
|
|
|
+ AREA_CODES.add("82"); // 澳门
|
|
|
+ AREA_CODES.add("91"); // 国外
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|