bug fix
parent
a7b7764283
commit
3479407873
|
|
@ -1,6 +1,7 @@
|
|||
package org.qinan.safetyeval.app.support;
|
||||
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.IdcardUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
|
|
@ -11,11 +12,10 @@ import com.zcloud.gbscommon.utils.MD5;
|
|||
import com.zcloud.gbscommon.utils.Sm2Util;
|
||||
import org.qinan.safetyeval.client.co.OrgPersonnelImportErrorCO;
|
||||
import org.qinan.safetyeval.client.co.OrgPersonnelImportResultCO;
|
||||
import org.qinan.safetyeval.domain.constant.QualificationLevelEnum;
|
||||
import org.qinan.safetyeval.domain.entity.OrgDepartmentEntity;
|
||||
import org.qinan.safetyeval.domain.entity.OrgPersonnelCertEntity;
|
||||
import org.qinan.safetyeval.domain.entity.OrgPersonnelEntity;
|
||||
import org.qinan.safetyeval.domain.entity.OrgPositionEntity;
|
||||
import org.qinan.safetyeval.domain.entity.TitleCodeCo;
|
||||
import org.qinan.safetyeval.domain.exception.BizException;
|
||||
import org.qinan.safetyeval.domain.exception.ErrorCode;
|
||||
import org.qinan.safetyeval.domain.gateway.OrgDepartmentGateway;
|
||||
|
|
@ -38,14 +38,15 @@ import javax.annotation.Resource;
|
|||
import javax.validation.ConstraintViolation;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 基于 EasyExcel 的人员信息批量导入器。
|
||||
* <p>
|
||||
* 解析 Excel -> 批量校验部门/岗位名称并回填ID -> 校验账号重复并收集异常 -> 逐行落库。
|
||||
* 模板包含两个 sheet:sheet1「专职人员基础信息」、sheet2「专职人员能力信息」,
|
||||
* 解析后按 身份证号(为空时按姓名) 将能力信息关联到基础信息行;
|
||||
* 再批量校验部门/岗位名称并回填ID -> 校验账号重复并收集异常 -> 逐行落库。
|
||||
* </p>
|
||||
*
|
||||
* @author safety-eval
|
||||
|
|
@ -55,10 +56,6 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OrgPersonnelExcelImporter.class);
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter SLASH_DATE_FORMATTER =
|
||||
new DateTimeFormatterBuilder().appendPattern("yyyy/M/d").toFormatter();
|
||||
|
||||
@Resource
|
||||
private OrgDepartmentGateway orgDepartmentGateway;
|
||||
|
||||
|
|
@ -80,6 +77,8 @@ public class OrgPersonnelExcelImporter {
|
|||
@Resource
|
||||
private SystemRemote systemRemote;
|
||||
|
||||
public static final String YES = "是";
|
||||
|
||||
@Value("${def.password:a123456}")
|
||||
private String defPassword;
|
||||
@Value("${def.publicKey:0402df2195296d4062ac85ad766994d73e871b887e18efb9a9a06b4cebc72372869b7da6c347c129dee2b46a0f279ff066b01c76208c2a052af75977c722a2ccee}")
|
||||
|
|
@ -137,29 +136,32 @@ public class OrgPersonnelExcelImporter {
|
|||
// 5. 逐行转换、落库
|
||||
int successCount = 0;
|
||||
|
||||
|
||||
for (OrgPersonnelImportRow row : rows) {
|
||||
String account = trim(row.getAccount());
|
||||
String account = trim(row.getBasic().getAccount());
|
||||
|
||||
// 账号在库中已存在 -> 跳过该行,记录异常
|
||||
if (existingAccounts.contains(account)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), account, trim(row.getUserName()),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), account, trim(row.getBasic().getUserName()),
|
||||
"账号已存在,跳过该行"));
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
OrgPersonnelEntity entity = buildEntity(row, orgId, errors);
|
||||
if (entity == null) {
|
||||
OrgPersonnelEntity personnelEntity = buildOrgPersonnel(row, orgId, errors);
|
||||
if (personnelEntity == null) {
|
||||
// 行内枚举/数据校验未通过,已记录异常
|
||||
continue;
|
||||
}
|
||||
Long userId = addUserIfAbsentAndAppendRole(entity);
|
||||
entity.setId(userId);
|
||||
orgPersonnelDomainService.add(entity);
|
||||
List<OrgPersonnelCertEntity> personnelCertEntities = buildOrgPersonnelCert(row, orgId, errors, personnelEntity);
|
||||
|
||||
Long userId = addUserIfAbsentAndAppendRole(personnelEntity);
|
||||
personnelEntity.setId(userId);
|
||||
orgPersonnelDomainService.add(personnelEntity);
|
||||
successCount++;
|
||||
} catch (Exception ex) {
|
||||
LOGGER.warn("导入人员落库失败, rowIndex={}, account={}", row.getRowIndex(), account, ex);
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), account, trim(row.getUserName()),
|
||||
LOGGER.warn("导入人员落库失败, rowIndex={}, account={}", row.getBasic().getRowIndex(), account, ex);
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), account, trim(row.getBasic().getUserName()),
|
||||
"保存失败:" + ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
|
@ -169,6 +171,19 @@ public class OrgPersonnelExcelImporter {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param row row
|
||||
* @param orgId orgId
|
||||
* @param errors errors
|
||||
* @param personnelEntity personnelEntity
|
||||
* @return OrgPersonnelCertEntity
|
||||
*/
|
||||
private List<OrgPersonnelCertEntity> buildOrgPersonnelCert(OrgPersonnelImportRow row
|
||||
, Long orgId, List<OrgPersonnelImportErrorCO> errors, OrgPersonnelEntity personnelEntity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* addUserIfAbsentAndAppendRole
|
||||
*
|
||||
|
|
@ -192,40 +207,56 @@ public class OrgPersonnelExcelImporter {
|
|||
}
|
||||
|
||||
/**
|
||||
* 解析 Excel,过滤空行,并回填物理行号(从1开始,含表头,首条数据为第2行)。
|
||||
* 解析 Excel:分别读取 sheet1「专职人员基础信息」与 sheet2「专职人员能力信息」,
|
||||
* 能力信息按 身份证号(为空时按姓名) 关联到基础信息行;
|
||||
* 过滤空行并回填物理行号(从1开始,含表头,首条数据为第2行)。
|
||||
* <p>
|
||||
* 文件内手机号重复的行在此剔除,并生成提示放入 errors(空账号不参与去重)。
|
||||
* </p>
|
||||
*/
|
||||
private List<OrgPersonnelImportRow> parseRows(MultipartFile file, List<OrgPersonnelImportErrorCO> errors) {
|
||||
List<OrgPersonnelImportRow> raw;
|
||||
List<OrgPersonnelImportRow.BasicRow> basicRaw;
|
||||
List<OrgPersonnelImportRow.CapabilityRow> capabilityRaw;
|
||||
try {
|
||||
raw = EasyExcel.read(file.getInputStream())
|
||||
.head(OrgPersonnelImportRow.class)
|
||||
.sheet()
|
||||
// sheet1:专职人员基础信息
|
||||
basicRaw = EasyExcel.read(file.getInputStream())
|
||||
.head(OrgPersonnelImportRow.BasicRow.class)
|
||||
.sheet(0)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
// sheet2:专职人员能力信息
|
||||
capabilityRaw = EasyExcel.read(file.getInputStream())
|
||||
.head(OrgPersonnelImportRow.CapabilityRow.class)
|
||||
.sheet(1)
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("解析人员导入Excel失败", ex);
|
||||
throw new BizException(ErrorCode.ORG_PERSONNEL_IMPORT_PARSE_ERROR);
|
||||
}
|
||||
if (raw == null || raw.isEmpty()) {
|
||||
if (basicRaw == null || basicRaw.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<OrgPersonnelImportRow> rows = new ArrayList<>(raw.size());
|
||||
|
||||
Map<String, OrgPersonnelImportRow.CapabilityRow> capabilityMap = indexCapabilityRows(capabilityRaw);
|
||||
|
||||
List<OrgPersonnelImportRow> rows = new ArrayList<>(basicRaw.size());
|
||||
Set<String> seenAccounts = new HashSet<>();
|
||||
for (int i = 0; i < raw.size(); i++) {
|
||||
OrgPersonnelImportRow row = raw.get(i);
|
||||
if (row == null) {
|
||||
for (int i = 0; i < basicRaw.size(); i++) {
|
||||
OrgPersonnelImportRow.BasicRow basic = basicRaw.get(i);
|
||||
if (basic == null) {
|
||||
continue;
|
||||
}
|
||||
// 空行:账号与姓名均为空
|
||||
if (!StringUtils.hasText(trim(row.getAccount())) && !StringUtils.hasText(trim(row.getUserName()))) {
|
||||
if (!StringUtils.hasText(trim(basic.getAccount())) && !StringUtils.hasText(trim(basic.getUserName()))) {
|
||||
continue;
|
||||
}
|
||||
row.setRowIndex(i + 2);
|
||||
OrgPersonnelImportRow row = new OrgPersonnelImportRow();
|
||||
basic.setRowIndex(i + 2);
|
||||
row.setBasic(basic);
|
||||
row.setCapability(matchCapability(basic, capabilityMap));
|
||||
|
||||
// 字段校验:JSR-303 注解(必填、长度、手机号格式)+ 身份证号 + 日期格式
|
||||
// 字段校验:JSR-303 注解(必填、长度、手机号格式)+ 身份证号
|
||||
if (!validateRowFields(row, errors)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -238,13 +269,69 @@ public class OrgPersonnelExcelImporter {
|
|||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* sheet2 能力信息建立索引:优先身份证号,身份证号为空时按姓名;重复时保留首条并告警。
|
||||
*/
|
||||
private Map<String, OrgPersonnelImportRow.CapabilityRow> indexCapabilityRows(
|
||||
List<OrgPersonnelImportRow.CapabilityRow> capabilityRaw) {
|
||||
Map<String, OrgPersonnelImportRow.CapabilityRow> map = new LinkedHashMap<>();
|
||||
if (capabilityRaw == null || capabilityRaw.isEmpty()) {
|
||||
return map;
|
||||
}
|
||||
for (int i = 0; i < capabilityRaw.size(); i++) {
|
||||
OrgPersonnelImportRow.CapabilityRow capability = capabilityRaw.get(i);
|
||||
if (capability == null) {
|
||||
continue;
|
||||
}
|
||||
// 空行:姓名与身份证号均为空
|
||||
if (!StringUtils.hasText(trim(capability.getIdCardNo()))
|
||||
&& !StringUtils.hasText(trim(capability.getUserName()))) {
|
||||
continue;
|
||||
}
|
||||
capability.setRowIndex(i + 2);
|
||||
String key = capabilityKey(capability.getIdCardNo(), capability.getUserName());
|
||||
if (map.putIfAbsent(key, capability) != null) {
|
||||
LOGGER.warn("人员导入能力信息重复,key={},sheet2行号={},仅保留首条", key, capability.getRowIndex());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础信息行匹配能力信息:优先身份证号,其次姓名;未匹配返回 null。
|
||||
*/
|
||||
private OrgPersonnelImportRow.CapabilityRow matchCapability(OrgPersonnelImportRow.BasicRow basic,
|
||||
Map<String, OrgPersonnelImportRow.CapabilityRow> capabilityMap) {
|
||||
if (capabilityMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
OrgPersonnelImportRow.CapabilityRow capability =
|
||||
capabilityMap.get(capabilityKey(basic.getIdCardNo(), null));
|
||||
if (capability != null) {
|
||||
return capability;
|
||||
}
|
||||
return capabilityMap.get(capabilityKey(null, basic.getUserName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 能力信息索引键:身份证号优先(前缀 ID:),为空时使用姓名(前缀 NAME:)。
|
||||
*/
|
||||
private String capabilityKey(String idCardNo, String userName) {
|
||||
String idCard = trim(idCardNo);
|
||||
if (StringUtils.hasText(idCard)) {
|
||||
return "ID:" + idCard;
|
||||
}
|
||||
return "NAME:" + trim(userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段级校验:
|
||||
* <ol>
|
||||
* <li>JSR-303 注解校验({@link OrgPersonnelImportRow} 字段上的 @NotBlank/@Size/@Pattern),
|
||||
* <li>JSR-303 注解校验({@link OrgPersonnelImportRow.BasicRow} 字段上的 @NotBlank/@Size/@Pattern),
|
||||
* 覆盖必填、长度、手机号格式;</li>
|
||||
* <li>身份证号:使用 {@link IdcardUtil} 校验校验位与出生日期合法性;</li>
|
||||
* <li>日期字段:兼容 yyyy-MM-dd / yyyy/M/d 格式校验。</li>
|
||||
* <li>sheet2 能力信息({@link OrgPersonnelImportRow.CapabilityRow})JSR-303 注解校验 +
|
||||
* 身份证号格式校验(未匹配到能力信息时跳过),行号取 sheet2 行号;</li>
|
||||
* <li>身份证号:使用 {@link IdcardUtil} 校验校验位与出生日期合法性。</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param row 当前行
|
||||
|
|
@ -252,12 +339,12 @@ public class OrgPersonnelExcelImporter {
|
|||
* @return true 通过,false 失败(已记录异常)
|
||||
*/
|
||||
private boolean validateRowFields(OrgPersonnelImportRow row, List<OrgPersonnelImportErrorCO> errors) {
|
||||
Integer rowIndex = row.getRowIndex();
|
||||
String account = trim(row.getAccount());
|
||||
String userName = trim(row.getUserName());
|
||||
Integer rowIndex = row.getBasic().getRowIndex();
|
||||
String account = trim(row.getBasic().getAccount());
|
||||
String userName = trim(row.getBasic().getUserName());
|
||||
|
||||
// 1. JSR-303 注解校验:每字段仅取第一条违规,避免 @NotBlank+@Pattern 重复报错
|
||||
Set<ConstraintViolation<OrgPersonnelImportRow>> violations = validator.validate(row);
|
||||
// 1. JSR-303 注解校验(sheet1 基础信息):每字段仅取第一条违规,避免 @NotBlank+@Pattern 重复报错
|
||||
Set<ConstraintViolation<OrgPersonnelImportRow.BasicRow>> violations = validator.validate(row.getBasic());
|
||||
if (!violations.isEmpty()) {
|
||||
violations.stream()
|
||||
.collect(Collectors.toMap(
|
||||
|
|
@ -270,22 +357,40 @@ public class OrgPersonnelExcelImporter {
|
|||
return false;
|
||||
}
|
||||
|
||||
// 2. 身份证号格式校验(DB: id_card_no varchar(18))
|
||||
String idCardNo = trim(row.getIdCardNo());
|
||||
// 2. sheet2 能力信息校验(未匹配到能力信息时跳过),行号取 sheet2 行号,消息加前缀便于区分来源
|
||||
OrgPersonnelImportRow.CapabilityRow capability = row.getCapability();
|
||||
if (capability != null) {
|
||||
Set<ConstraintViolation<OrgPersonnelImportRow.CapabilityRow>> capabilityViolations =
|
||||
validator.validate(capability);
|
||||
if (!capabilityViolations.isEmpty()) {
|
||||
capabilityViolations.stream()
|
||||
.collect(Collectors.toMap(
|
||||
v -> v.getPropertyPath().toString(),
|
||||
v -> v,
|
||||
(a, b) -> a))
|
||||
.values()
|
||||
.forEach(v -> errors.add(new OrgPersonnelImportErrorCO(capability.getRowIndex(),
|
||||
account, userName, "能力信息:" + v.getMessage())));
|
||||
return false;
|
||||
}
|
||||
|
||||
// sheet2 身份证号格式校验(DB: id_card_no varchar(18))
|
||||
String capabilityIdCardNo = trim(capability.getIdCardNo());
|
||||
if (StringUtils.hasText(capabilityIdCardNo) && !IdcardUtil.isValidCard(capabilityIdCardNo)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(capability.getRowIndex(), account, userName,
|
||||
"能力信息:身份证号格式不正确,应为15或18位有效身份证号"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 身份证号格式校验(DB: id_card_no varchar(18))
|
||||
String idCardNo = trim(row.getBasic().getIdCardNo());
|
||||
if (StringUtils.hasText(idCardNo) && !IdcardUtil.isValidCard(idCardNo)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName,
|
||||
"身份证号格式不正确,应为15或18位有效身份证号"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 日期格式校验(DB: join_work_date date;出生日期由身份证号解析,不做校验)
|
||||
String joinWorkDate = trim(row.getJoinWorkDate());
|
||||
if (StringUtils.hasText(joinWorkDate) && parseDate(joinWorkDate) == null) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName,
|
||||
"参加工作时间格式不正确,应为yyyy-MM-dd或yyyy/M/d"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -299,9 +404,9 @@ public class OrgPersonnelExcelImporter {
|
|||
*/
|
||||
private boolean checkAccountDuplicate(OrgPersonnelImportRow row, Set<String> seenAccounts,
|
||||
List<OrgPersonnelImportErrorCO> errors) {
|
||||
String account = trim(row.getAccount());
|
||||
String account = trim(row.getBasic().getAccount());
|
||||
if (StringUtils.hasText(account) && !seenAccounts.add(account)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), account, trim(row.getUserName()),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), account, trim(row.getBasic().getUserName()),
|
||||
"账号在文件内重复,已剔除该行"));
|
||||
return false;
|
||||
}
|
||||
|
|
@ -322,13 +427,14 @@ public class OrgPersonnelExcelImporter {
|
|||
// 收集所有层级中不为空的部门名称
|
||||
Set<String> deptNames = new LinkedHashSet<>();
|
||||
for (OrgPersonnelImportRow row : rows) {
|
||||
row.setDeptNameLevel3(StrUtil.trim(row.getDeptNameLevel3()));
|
||||
row.setDeptNameLevel2(StrUtil.trim(row.getDeptNameLevel2()));
|
||||
row.setDeptNameLevel1(StrUtil.trim(row.getDeptNameLevel1()));
|
||||
OrgPersonnelImportRow.BasicRow basic = row.getBasic();
|
||||
basic.setDeptNameLevel3(StrUtil.trim(basic.getDeptNameLevel3()));
|
||||
basic.setDeptNameLevel2(StrUtil.trim(basic.getDeptNameLevel2()));
|
||||
basic.setDeptNameLevel1(StrUtil.trim(basic.getDeptNameLevel1()));
|
||||
|
||||
collectDeptName(deptNames, row.getDeptNameLevel1());
|
||||
collectDeptName(deptNames, row.getDeptNameLevel2());
|
||||
collectDeptName(deptNames, row.getDeptNameLevel3());
|
||||
collectDeptName(deptNames, basic.getDeptNameLevel1());
|
||||
collectDeptName(deptNames, basic.getDeptNameLevel2());
|
||||
collectDeptName(deptNames, basic.getDeptNameLevel3());
|
||||
}
|
||||
|
||||
List<OrgDepartmentEntity> orgDepartmentList = orgDepartmentGateway.listByOrgIdAndNames(orgId, deptNames);
|
||||
|
|
@ -360,7 +466,7 @@ public class OrgPersonnelExcelImporter {
|
|||
*/
|
||||
private Pair<Boolean, OrgDepartmentEntity> getL3(List<OrgPersonnelImportErrorCO> errors, OrgPersonnelImportRow row
|
||||
, Map<String, List<OrgDepartmentEntity>> nameMapList, OrgDepartmentEntity l2Dept) {
|
||||
String l3 = row.getDeptNameLevel3();
|
||||
String l3 = row.getBasic().getDeptNameLevel3();
|
||||
if (StrUtil.isBlank(l3)) {
|
||||
return Pair.of(true, null);
|
||||
}
|
||||
|
|
@ -368,7 +474,7 @@ public class OrgPersonnelExcelImporter {
|
|||
// l3 部门查询
|
||||
List<OrgDepartmentEntity> departmentEntities = nameMapList.get(l3);
|
||||
if (CollectionUtils.isEmpty(departmentEntities)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L3_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -383,7 +489,7 @@ public class OrgPersonnelExcelImporter {
|
|||
}
|
||||
}
|
||||
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
l2Dept.getDeptName() + "下"
|
||||
+ ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L3_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
|
|
@ -401,7 +507,7 @@ public class OrgPersonnelExcelImporter {
|
|||
*/
|
||||
private Pair<Boolean, OrgDepartmentEntity> getL2(List<OrgPersonnelImportErrorCO> errors
|
||||
, OrgPersonnelImportRow row, Map<String, List<OrgDepartmentEntity>> nameMapList, OrgDepartmentEntity l1Dept) {
|
||||
String l2 = row.getDeptNameLevel2();
|
||||
String l2 = row.getBasic().getDeptNameLevel2();
|
||||
if (StrUtil.isBlank(l2)) {
|
||||
return Pair.of(true, null);
|
||||
}
|
||||
|
|
@ -409,7 +515,7 @@ public class OrgPersonnelExcelImporter {
|
|||
// l2 部门查询
|
||||
List<OrgDepartmentEntity> departmentEntities = nameMapList.get(l2);
|
||||
if (CollectionUtils.isEmpty(departmentEntities)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L2_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -424,7 +530,7 @@ public class OrgPersonnelExcelImporter {
|
|||
}
|
||||
}
|
||||
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
l1Dept.getDeptName() + "下" + ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L2_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -439,9 +545,9 @@ public class OrgPersonnelExcelImporter {
|
|||
*/
|
||||
private static Pair<Boolean, OrgDepartmentEntity> getL1(List<OrgPersonnelImportErrorCO> errors, OrgPersonnelImportRow row
|
||||
, Map<String, List<OrgDepartmentEntity>> nameMapList) {
|
||||
String l1 = row.getDeptNameLevel1();
|
||||
String l1 = row.getBasic().getDeptNameLevel1();
|
||||
if (StrUtil.isBlank(l1)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L1_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -450,7 +556,7 @@ public class OrgPersonnelExcelImporter {
|
|||
// l1 部门查询
|
||||
List<OrgDepartmentEntity> departmentEntities = nameMapList.get(l1);
|
||||
if (CollectionUtils.isEmpty(departmentEntities)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L1_NOT_EXIST.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -458,7 +564,7 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
// 一级部门重复
|
||||
if (departmentEntities.size() > 1) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_DEPT_L1_REPEAT.getMessage()));
|
||||
row.setValidateFail(true);
|
||||
return Pair.of(false, null);
|
||||
|
|
@ -484,7 +590,7 @@ public class OrgPersonnelExcelImporter {
|
|||
if (row.getDeptId() != null) {
|
||||
deptIds.add(row.getDeptId());
|
||||
}
|
||||
String posName = trim(row.getPositionName());
|
||||
String posName = trim(row.getBasic().getPositionName());
|
||||
if (StringUtils.hasText(posName)) {
|
||||
positionNames.add(posName);
|
||||
}
|
||||
|
|
@ -501,9 +607,9 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
// 逐行校验:岗位名称为空或部门下岗位不存在 -> 记录异常并标记;校验通过则回填岗位ID
|
||||
for (OrgPersonnelImportRow row : rows) {
|
||||
String posName = trim(row.getPositionName());
|
||||
String posName = trim(row.getBasic().getPositionName());
|
||||
if (!StringUtils.hasText(posName)) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_POSITION_NOT_FOUND.getMessage()
|
||||
+ "(部门:" + row.getDeptDisplayName() + ")"));
|
||||
row.setValidateFail(true);
|
||||
|
|
@ -512,7 +618,7 @@ public class OrgPersonnelExcelImporter {
|
|||
String key = row.getDeptId() + "|" + posName;
|
||||
OrgPositionEntity pos = positionMap.get(key);
|
||||
if (pos == null) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_POSITION_NOT_FOUND.getMessage()
|
||||
+ ":" + posName + "(部门:" + row.getDeptDisplayName() + ")"));
|
||||
row.setValidateFail(true);
|
||||
|
|
@ -529,7 +635,7 @@ public class OrgPersonnelExcelImporter {
|
|||
*/
|
||||
private void validateAndFillMajor(List<OrgPersonnelImportRow> rows, List<OrgPersonnelImportErrorCO> errors) {
|
||||
Set<String> majorNames = rows.stream()
|
||||
.map(r -> trim(r.getMajor()))
|
||||
.map(r -> r.getCapability() == null ? null : trim(r.getCapability().getMajor()))
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
|
|
@ -544,13 +650,13 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
// 逐行校验:专业名称为空的行跳过;对照表中不存在的行记录异常并标记;校验通过则回填专业ID
|
||||
for (OrgPersonnelImportRow row : rows) {
|
||||
String name = trim(row.getMajor());
|
||||
String name = row.getCapability() == null ? null : trim(row.getCapability().getMajor());
|
||||
if (!StringUtils.hasText(name)) {
|
||||
continue;
|
||||
}
|
||||
BasicDisciplineMajorE major = majorMap.get(name);
|
||||
if (major == null) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), row.getAccount(), row.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getBasic().getRowIndex(), row.getBasic().getAccount(), row.getBasic().getUserName(),
|
||||
ErrorCode.ORG_PERSONNEL_IMPORT_MAJOR_NOT_FOUND.getMessage() + ":" + name));
|
||||
row.setValidateFail(true);
|
||||
continue;
|
||||
|
|
@ -561,7 +667,7 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
private Set<String> batchQueryExistingAccounts(List<OrgPersonnelImportRow> rows, Long orgId) {
|
||||
Set<String> accounts = rows.stream()
|
||||
.map(r -> trim(r.getAccount()))
|
||||
.map(r -> trim(r.getBasic().getAccount()))
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toSet());
|
||||
if (accounts.isEmpty()) {
|
||||
|
|
@ -575,16 +681,20 @@ public class OrgPersonnelExcelImporter {
|
|||
|
||||
/**
|
||||
* 行数据转换为实体;枚举无法识别等校验失败时记录异常并返回 null。
|
||||
* <p>基础信息取自 sheet1;毕业院校/所学专业/学历/注册安全工程师取自 sheet2 能力信息(可为空)。</p>
|
||||
*/
|
||||
private OrgPersonnelEntity buildEntity(OrgPersonnelImportRow row, Long orgId, List<OrgPersonnelImportErrorCO> errors) {
|
||||
private OrgPersonnelEntity buildOrgPersonnel(OrgPersonnelImportRow row, Long orgId, List<OrgPersonnelImportErrorCO> errors) {
|
||||
OrgPersonnelImportRow.BasicRow basic = row.getBasic();
|
||||
OrgPersonnelImportRow.CapabilityRow capability = row.getCapability();
|
||||
OrgPersonnelEntity entity = new OrgPersonnelEntity();
|
||||
entity.setId(IdUtil.getSnowflakeNextId());
|
||||
entity.setOrgId(orgId);
|
||||
entity.setDeptId(row.getDeptId());
|
||||
entity.setPostId(row.getPostId());
|
||||
entity.setBasicDisciplineMajorId(row.getBasicDisciplineMajorId());
|
||||
entity.setUserName(trim(row.getUserName()));
|
||||
entity.setAccount(trim(row.getAccount()));
|
||||
String idCardNo = trim(row.getIdCardNo());
|
||||
entity.setUserName(trim(basic.getUserName()));
|
||||
entity.setAccount(trim(basic.getAccount()));
|
||||
String idCardNo = trim(basic.getIdCardNo());
|
||||
entity.setIdCardNo(idCardNo);
|
||||
// 出生日期:不再从Excel导入,直接通过身份证号(Hutool)解析
|
||||
if (StringUtils.hasText(idCardNo)) {
|
||||
|
|
@ -593,21 +703,31 @@ public class OrgPersonnelExcelImporter {
|
|||
entity.setBirthDate(LocalDate.parse(birth, DateTimeFormatter.BASIC_ISO_DATE));
|
||||
}
|
||||
}
|
||||
entity.setJoinWorkDate(parseDate(trim(row.getJoinWorkDate())));
|
||||
entity.setGraduateSchool(trim(row.getGraduateSchool()));
|
||||
entity.setMajor(trim(row.getMajor()));
|
||||
entity.setCurrentAddress(trim(row.getCurrentAddress()));
|
||||
entity.setOfficeAddress(trim(row.getOfficeAddress()));
|
||||
entity.setWorkExperience(trim(row.getWorkExperience()));
|
||||
entity.setPublications(trim(row.getPublications()));
|
||||
entity.setAbilityDeclaration(trim(row.getAbilityDeclaration()));
|
||||
entity.setCurrentAddress(trim(basic.getCurrentAddress()));
|
||||
entity.setOfficeAddress(trim(basic.getOfficeAddress()));
|
||||
entity.setWorkExperience(trim(basic.getWorkExperience()));
|
||||
entity.setPublications(trim(basic.getPublications()));
|
||||
entity.setAbilityDeclaration(trim(basic.getAbilityDeclaration()));
|
||||
|
||||
// sheet2 能力信息(未匹配到能力信息的行为空)
|
||||
if (capability != null) {
|
||||
entity.setGraduateSchool(trim(capability.getGraduateSchool()));
|
||||
entity.setMajor(trim(capability.getMajor()));
|
||||
// 学历:名称取学历层次,类型/层次分别填入
|
||||
entity.setEducationCode(trim(capability.getEducationLevel()));
|
||||
entity.setEducationName(trim(capability.getEducationLevel()));
|
||||
entity.setEducationTypeName(trim(capability.getEducationType()));
|
||||
entity.setEducationTypeCode(trim(capability.getEducationType()));
|
||||
entity.setEducationLevelName(trim(capability.getEducationLevel()));
|
||||
entity.setEducationLevelCode(trim(capability.getEducationLevel()));
|
||||
}
|
||||
|
||||
// 性别:严格转换
|
||||
String genderText = trim(row.getGender());
|
||||
String genderText = trim(basic.getGender());
|
||||
if (StringUtils.hasText(genderText)) {
|
||||
ImportGenderEnum gender = ImportGenderEnum.fromText(genderText);
|
||||
if (gender == null) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), entity.getAccount(), entity.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(basic.getRowIndex(), entity.getAccount(), entity.getUserName(),
|
||||
"性别[" + genderText + "]无法识别,跳过该行"));
|
||||
row.setValidateFail(true);
|
||||
return null;
|
||||
|
|
@ -616,12 +736,12 @@ public class OrgPersonnelExcelImporter {
|
|||
entity.setGenderName(gender.getName());
|
||||
}
|
||||
|
||||
// 是否注册安全工程师:严格转换
|
||||
String registerText = trim(row.getRegisterEngineer());
|
||||
// 是否注册安全工程师:严格转换(sheet2)
|
||||
String registerText = capability == null ? null : trim(capability.getRegisterEngineer());
|
||||
if (StringUtils.hasText(registerText)) {
|
||||
ImportRegisterEngineerEnum register = ImportRegisterEngineerEnum.fromText(registerText);
|
||||
if (register == null) {
|
||||
errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), entity.getAccount(), entity.getUserName(),
|
||||
errors.add(new OrgPersonnelImportErrorCO(basic.getRowIndex(), entity.getAccount(), entity.getUserName(),
|
||||
"是否注册安全工程师[" + registerText + "]无法识别,跳过该行"));
|
||||
row.setValidateFail(true);
|
||||
return null;
|
||||
|
|
@ -629,64 +749,13 @@ public class OrgPersonnelExcelImporter {
|
|||
entity.setRegisterEngineerFlag(register.getCode());
|
||||
}
|
||||
|
||||
// 学历:兜底字典映射,匹配不到则原样存名称
|
||||
String educationText = trim(row.getEducation());
|
||||
entity.setEducationName(educationText);
|
||||
|
||||
// 职称:无字典,按分隔符拆分后原样存入(保留信息,待后续字典完善)
|
||||
entity.setTitleCodeArr(parseTitles(trim(row.getTitle())));
|
||||
entity.setJoinWorkDate(LocalDate.now().minusYears(basic.getIndustryWorkYears()));
|
||||
entity.setTechnicalDirectorFlag(YES.equals(basic.getTechnicalDirector()));
|
||||
entity.setProcessControlLeaderFlag(YES.equals(basic.getProcessControlLeader()));
|
||||
// 能力认证一/二、注安证书、评价师证书、高级工程师等
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<TitleCodeCo> parseTitles(String title) {
|
||||
if (!StringUtils.hasText(title)) {
|
||||
return null;
|
||||
}
|
||||
List<TitleCodeCo> list = Arrays.stream(title.split("[,,;;、]"))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::hasText)
|
||||
.map(t -> {
|
||||
TitleCodeCo co = new TitleCodeCo();
|
||||
co.setTitleCode(convertTitleToCode(t));
|
||||
return co;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return list.isEmpty() ? null : list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 职称文本转 code:按 QualificationLevelEnum 名称包含匹配(如"高级工程师"→SENIOR、"中级工程师"→MIDDLE、"初级"→JUNIOR),
|
||||
* 匹配不到则原样返回。
|
||||
*/
|
||||
private String convertTitleToCode(String titleText) {
|
||||
for (QualificationLevelEnum level : QualificationLevelEnum.values()) {
|
||||
if (titleText.contains(level.getName())) {
|
||||
return level.getCode();
|
||||
}
|
||||
}
|
||||
return titleText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期:兼容 yyyy-MM-dd 与 yyyy/M/d(如 1988-05-12、1988/5/12)等常见 Excel 格式。
|
||||
*/
|
||||
private LocalDate parseDate(String text) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = text.trim();
|
||||
try {
|
||||
return LocalDate.parse(trimmed, DATE_FORMATTER);
|
||||
} catch (Exception ignore) {
|
||||
// 继续尝试斜杠格式
|
||||
}
|
||||
try {
|
||||
return LocalDate.parse(trimmed, SLASH_DATE_FORMATTER);
|
||||
} catch (Exception ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String trim(String text) {
|
||||
return text == null ? null : text.trim();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,21 +3,24 @@ package org.qinan.safetyeval.app.support;
|
|||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 人员导入 Excel 行模型(按列下标映射,避免表头存在重名列)。
|
||||
* 人员导入 Excel 行模型(按列下标映射,避免表头存在重名列,如 sheet2 两列「证书编号」)。
|
||||
* <p>
|
||||
* 列顺序:一级部门 / 二级部门 / 三级部门 / 岗位 / 账号(手机号) / 姓名 / 性别 /
|
||||
* 身份证号 / 学历 / 毕业院校 / 所学专业 / 职称 / 参加工作时间 /
|
||||
* 是否注册安全工程师 / 现住地址 / 办公地址 / 主要学习工作经历 /
|
||||
* 出版学术专著、专利、获奖、发表学术论文等 / 自我申报的专业能力及认定方式。
|
||||
* <p>出生日期不再通过Excel导入,统一由身份证号解析。</p>
|
||||
* </p>
|
||||
* 模板包含两个 sheet:
|
||||
* <ul>
|
||||
* <li>sheet1「专职人员基础信息」-> {@link BasicRow};</li>
|
||||
* <li>sheet2「专职人员能力信息」-> {@link CapabilityRow},导入时按
|
||||
* 身份证号(为空时按姓名)关联到基础信息行,可能为空。</li>
|
||||
* </ul>
|
||||
* <p>出生日期不通过Excel导入,统一由身份证号解析。</p>
|
||||
* <p>
|
||||
* 部门按三级层级填写:一级部门为根,二级部门 parentId 指向一级部门,
|
||||
* 三级部门 parentId 指向二级部门;导入时校验层级关系,取最底层不为空的一级作为 deptId。
|
||||
|
|
@ -28,120 +31,253 @@ import javax.validation.constraints.Size;
|
|||
@Data
|
||||
public class OrgPersonnelImportRow {
|
||||
|
||||
@ExcelProperty(value = "一级部门", index = 0)
|
||||
private String deptNameLevel1;
|
||||
|
||||
@ExcelProperty(value = "二级部门", index = 1)
|
||||
private String deptNameLevel2;
|
||||
|
||||
@ExcelProperty(value = "三级部门", index = 2)
|
||||
private String deptNameLevel3;
|
||||
|
||||
@ExcelProperty(value = "岗位", index = 3)
|
||||
private String positionName;
|
||||
|
||||
@ExcelProperty(value = "账号", index = 4)
|
||||
@NotBlank(message = "账号不能为空")
|
||||
@Pattern(regexp = "^1\\d{10}$", message = "手机号格式不正确,应为11位数字且以1开头")
|
||||
@Size(max = 50, message = "账号长度不能超过50个字符")
|
||||
private String account;
|
||||
|
||||
@ExcelProperty(value = "姓名", index = 5)
|
||||
@NotBlank(message = "姓名不能为空")
|
||||
@Size(max = 50, message = "姓名长度不能超过50个字符")
|
||||
private String userName;
|
||||
|
||||
@ExcelProperty(value = "性别", index = 6)
|
||||
@Size(max = 10, message = "性别长度不能超过10个字符")
|
||||
private String gender;
|
||||
|
||||
@ExcelProperty(value = "身份证号", index = 7)
|
||||
@Size(max = 18, message = "身份证号长度不能超过18个字符")
|
||||
private String idCardNo;
|
||||
|
||||
@ExcelProperty(value = "学历", index = 8)
|
||||
@Size(max = 50, message = "学历长度不能超过50个字符")
|
||||
private String education;
|
||||
|
||||
@ExcelProperty(value = "毕业院校", index = 9)
|
||||
@Size(max = 200, message = "毕业院校长度不能超过200个字符")
|
||||
private String graduateSchool;
|
||||
|
||||
@ExcelProperty(value = "所学专业", index = 10)
|
||||
@Size(max = 100, message = "所学专业长度不能超过100个字符")
|
||||
private String major;
|
||||
|
||||
@ExcelProperty(value = "职称", index = 11)
|
||||
private String title;
|
||||
|
||||
@ExcelProperty(value = "参加工作时间", index = 12)
|
||||
private String joinWorkDate;
|
||||
|
||||
@ExcelProperty(value = "是否注册安全工程师", index = 13)
|
||||
private String registerEngineer;
|
||||
|
||||
@ExcelProperty(value = "现住地址", index = 14)
|
||||
@Size(max = 500, message = "现住地址长度不能超过500个字符")
|
||||
private String currentAddress;
|
||||
|
||||
@ExcelProperty(value = "办公地址", index = 15)
|
||||
@Size(max = 500, message = "办公地址长度不能超过500个字符")
|
||||
private String officeAddress;
|
||||
|
||||
@ExcelProperty(value = "主要学习工作经历", index = 16)
|
||||
private String workExperience;
|
||||
|
||||
@ExcelProperty(value = "出版学术专著、专利、获奖、发表学术论文等", index = 17)
|
||||
@Size(max = 1000, message = "出版学术专著等信息长度不能超过1000个字符")
|
||||
private String publications;
|
||||
|
||||
@ExcelProperty(value = "自我申报的专业能力及认定方式", index = 18)
|
||||
@Size(max = 1000, message = "自我申报的专业能力信息长度不能超过1000个字符")
|
||||
private String abilityDeclaration;
|
||||
/**
|
||||
* sheet1「专职人员基础信息」行数据。
|
||||
*/
|
||||
private BasicRow basic;
|
||||
|
||||
/**
|
||||
* EasyExcel 解析时记录的物理行号(从1开始,含表头),由导入器填充。
|
||||
* sheet2「专职人员能力信息」行数据(按身份证号/姓名关联,未匹配到时为空)。
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private Integer rowIndex;
|
||||
private CapabilityRow capability;
|
||||
|
||||
/**
|
||||
* 校验通过后回填的部门ID(非Excel列)。
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 校验通过后回填的岗位ID(非Excel列)。
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private Long postId;
|
||||
|
||||
/**
|
||||
* 校验通过后回填的学科基础专业对照表ID(非Excel列)。
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private Long basicDisciplineMajorId;
|
||||
|
||||
/**
|
||||
* 校验失败 true 失败 ,false 未失败
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private boolean validateFail;
|
||||
|
||||
/**
|
||||
* 返回最底层(最深一级)不为空的部门名称,用于错误提示。
|
||||
*/
|
||||
public String getDeptDisplayName() {
|
||||
if (StringUtils.hasText(deptNameLevel3)) {
|
||||
return deptNameLevel3.trim();
|
||||
if (basic == null) {
|
||||
return null;
|
||||
}
|
||||
if (StringUtils.hasText(deptNameLevel2)) {
|
||||
return deptNameLevel2.trim();
|
||||
if (StringUtils.hasText(basic.getDeptNameLevel3())) {
|
||||
return basic.getDeptNameLevel3().trim();
|
||||
}
|
||||
if (StringUtils.hasText(deptNameLevel1)) {
|
||||
return deptNameLevel1.trim();
|
||||
if (StringUtils.hasText(basic.getDeptNameLevel2())) {
|
||||
return basic.getDeptNameLevel2().trim();
|
||||
}
|
||||
if (StringUtils.hasText(basic.getDeptNameLevel1())) {
|
||||
return basic.getDeptNameLevel1().trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sheet1「专职人员基础信息」行模型。
|
||||
* <p>
|
||||
* 列顺序:一级部门 / 二级部门 / 三级部门 / 岗位 / 姓名 / 性别 / 本行业工作年限 /
|
||||
* 账号(系统登录账号) / 身份证号 / 现住地址 / 办公地址 / 是否技术负责人 /
|
||||
* 是否过程控制负责人 / 主要学习工作经历 /
|
||||
* 出版学术专著、专利、获奖、发表学术论文等 / 自我申报的专业能力及认定方式。
|
||||
* </p>
|
||||
*/
|
||||
@Data
|
||||
public static class BasicRow {
|
||||
|
||||
@ExcelProperty(value = "一级部门", index = 0)
|
||||
@NotBlank(message = "一级部门不能为空")
|
||||
@Size(max = 128, message = "一级部门名称最多120个字符")
|
||||
private String deptNameLevel1;
|
||||
|
||||
@ExcelProperty(value = "二级部门", index = 1)
|
||||
@Size(max = 128, message = "二级部门名称最多120个字符")
|
||||
private String deptNameLevel2;
|
||||
|
||||
@ExcelProperty(value = "三级部门", index = 2)
|
||||
@Size(max = 128, message = "三级部门最多120个字符")
|
||||
private String deptNameLevel3;
|
||||
|
||||
@ExcelProperty(value = "岗位", index = 3)
|
||||
@Size(max = 128, message = "岗位最多120个字符")
|
||||
private String positionName;
|
||||
|
||||
@ExcelProperty(value = "姓名", index = 4)
|
||||
@NotBlank(message = "姓名不能为空")
|
||||
@Size(max = 50, message = "姓名长度不能超过50个字符")
|
||||
private String userName;
|
||||
|
||||
@ExcelProperty(value = "性别", index = 5)
|
||||
@Size(max = 10, message = "性别长度不能超过10个字符")
|
||||
@NotBlank(message = "性别不能为空")
|
||||
private String gender;
|
||||
|
||||
@ExcelProperty(value = "本行业工作年限", index = 6)
|
||||
@NotNull(message = "本行业工作年限不能为空")
|
||||
@Range(min = 1, max = 200, message = "本行业工作年限1-200之间")
|
||||
private Integer industryWorkYears;
|
||||
|
||||
@ExcelProperty(value = "账号(系统登录账号)", index = 7)
|
||||
@NotBlank(message = "账号不能为空")
|
||||
@Pattern(regexp = "^1\\d{10}$", message = "手机号格式不正确,应为11位数字且以1开头")
|
||||
@Size(max = 50, message = "账号长度不能超过50个字符")
|
||||
private String account;
|
||||
|
||||
@ExcelProperty(value = "身份证号", index = 8)
|
||||
@Size(max = 18, message = "身份证号长度不能超过18个字符")
|
||||
@NotBlank(message = "身份证号不能为空")
|
||||
private String idCardNo;
|
||||
|
||||
@ExcelProperty(value = "现住地址", index = 9)
|
||||
@Size(max = 500, message = "现住地址长度不能超过500个字符")
|
||||
private String currentAddress;
|
||||
|
||||
@ExcelProperty(value = "办公地址", index = 10)
|
||||
@Size(max = 500, message = "办公地址长度不能超过500个字符")
|
||||
private String officeAddress;
|
||||
|
||||
@ExcelProperty(value = "是否技术负责人", index = 11)
|
||||
@Pattern(regexp = "^([是否])?$", message = "是否技术负责人仅允许:是、否")
|
||||
private String technicalDirector;
|
||||
|
||||
@ExcelProperty(value = "是否过程控制负责人", index = 12)
|
||||
@Pattern(regexp = "^([是否])?$", message = "是否过程控制负责人仅允许:是、否")
|
||||
private String processControlLeader;
|
||||
|
||||
@ExcelProperty(value = "主要学习工作经历", index = 13)
|
||||
@Size(max = 1024, message = "办公地址长度不能超过1024个字符")
|
||||
private String workExperience;
|
||||
|
||||
@ExcelProperty(value = "出版学术专著、专利、获奖、发表学术论文等", index = 14)
|
||||
@Size(max = 1000, message = "出版学术专著等信息长度不能超过1000个字符")
|
||||
private String publications;
|
||||
|
||||
@ExcelProperty(value = "自我申报的专业能力及认定方式", index = 15)
|
||||
@Size(max = 1000, message = "自我申报的专业能力信息长度不能超过1000个字符")
|
||||
private String abilityDeclaration;
|
||||
|
||||
/**
|
||||
* sheet1 的物理行号(从1开始,含表头),由导入器填充,用于错误提示。
|
||||
*/
|
||||
@ExcelIgnore
|
||||
private Integer rowIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sheet2「专职人员能力信息」行模型。
|
||||
* <p>
|
||||
* 列顺序:姓名 / 身份证号 / 能力认证一(认证行业、专业能力、来源) /
|
||||
* 能力认证二(认证行业、专业能力、来源) / 学历类型 / 毕业院校 / 学历层次 / 所学专业 /
|
||||
* 是否注册安全工程师 / 注安专业类别 / 注安等级 / 证书编号 / 执业证书编号 /
|
||||
* 是否评价师 / 评价师等级 / 证书编号 / 是否高级工程师 / 系列/专业。
|
||||
* </p>
|
||||
*/
|
||||
@Data
|
||||
public static class CapabilityRow {
|
||||
|
||||
@ExcelProperty(value = "姓名", index = 0)
|
||||
private String userName;
|
||||
|
||||
@ExcelProperty(value = "身份证号", index = 1)
|
||||
@Size(max = 18, message = "身份证号长度不能超过18个字符")
|
||||
@NotBlank(message = "身份证号不能为空")
|
||||
private String idCardNo;
|
||||
|
||||
@ExcelProperty(value = "能力认证一-认证行业", index = 2)
|
||||
@NotBlank(message = "能力认证一-认证行业不能为空")
|
||||
@Size(max = 64, message = "能力认证一-认证行业最多64个字符")
|
||||
private String cert1Industry;
|
||||
|
||||
@ExcelProperty(value = "能力认证一-专业能力", index = 3)
|
||||
@NotBlank(message = "能力认证一-专业能力不能为空")
|
||||
@Size(max = 64, message = "能力认证一-专业能力最多64个字符")
|
||||
private String cert1Ability;
|
||||
|
||||
@ExcelProperty(value = "能力认证一-来源", index = 4)
|
||||
@NotBlank(message = "能力认证一-来源不能为空")
|
||||
@Size(max = 128, message = "能力认证一-来源最多64个字符")
|
||||
private String cert1Source;
|
||||
|
||||
@ExcelProperty(value = "能力认证二-认证行业", index = 5)
|
||||
@Size(max = 64, message = "能力认证一-认证行业最多64个字符")
|
||||
private String cert2Industry;
|
||||
|
||||
@ExcelProperty(value = "能力认证二-专业能力", index = 6)
|
||||
@Size(max = 64, message = "能力认证一-专业能力最多64个字符")
|
||||
private String cert2Ability;
|
||||
|
||||
@ExcelProperty(value = "能力认证二-来源", index = 7)
|
||||
@Size(max = 128, message = "能力认证二-来源最多128个字符")
|
||||
private String cert2Source;
|
||||
|
||||
@ExcelProperty(value = "学历类型", index = 8)
|
||||
@NotBlank(message = "学历类型不能为空")
|
||||
@Size(max = 64, message ="学历类型最多64个字符")
|
||||
private String educationType;
|
||||
|
||||
@ExcelProperty(value = "毕业院校", index = 9)
|
||||
@Size(max = 200, message = "毕业院校长度不能超过200个字符")
|
||||
@NotBlank(message = "毕业院校不能为空")
|
||||
private String graduateSchool;
|
||||
|
||||
@ExcelProperty(value = "学历层次", index = 10)
|
||||
@NotBlank(message = "学历层次不能为空")
|
||||
private String educationLevel;
|
||||
|
||||
@ExcelProperty(value = "所学专业", index = 11)
|
||||
@Size(max = 100, message = "所学专业长度不能超过100个字符")
|
||||
@NotBlank(message = "所学专业不能为空")
|
||||
private String major;
|
||||
|
||||
@ExcelProperty(value = "是否注册安全工程师", index = 12)
|
||||
@Pattern(regexp = "^([是否])?$", message = "是否注册安全工程师仅允许:是、否")
|
||||
@NotBlank(message = "是否注册安全工程师不能为空")
|
||||
private String registerEngineer;
|
||||
|
||||
@ExcelProperty(value = "注安专业类别", index = 13)
|
||||
@Size(max = 100, message = "注安专业类别长度不能超过100个字符")
|
||||
private String registerEngineerCategory;
|
||||
|
||||
@ExcelProperty(value = "注安等级", index = 14)
|
||||
@Size(max = 100, message = "注安等级长度不能超过100个字符")
|
||||
private String registerEngineerLevel;
|
||||
|
||||
@ExcelProperty(value = "注安证书编号", index = 15)
|
||||
@Size(max = 64, message = "注安证书编号长度不能超过100个字符")
|
||||
private String registerEngineerCertNo;
|
||||
|
||||
@ExcelProperty(value = "执业证书编号", index = 16)
|
||||
@Size(max = 64, message = "执业证书编号长度不能超过100个字符")
|
||||
private String practiceCertNo;
|
||||
|
||||
@ExcelProperty(value = "是否评价师", index = 17)
|
||||
@Pattern(regexp = "^([是否])?$", message = "是否评价师仅允许:是、否")
|
||||
@NotBlank(message = "是否是否评价师不能为空")
|
||||
private String evaluator;
|
||||
|
||||
@ExcelProperty(value = "评价师等级", index = 18)
|
||||
@Size(max = 64, message = "评价师等级长度不能超过100个字符")
|
||||
private String evaluatorLevel;
|
||||
|
||||
@ExcelProperty(value = "评价师证书编号", index = 19)
|
||||
@Size(max = 64, message = "评价师证书编号长度不能超过100个字符")
|
||||
private String evaluatorCertNo;
|
||||
|
||||
@ExcelProperty(value = "是否高级工程师", index = 20)
|
||||
@Pattern(regexp = "^([是否])?$", message = "是否高级工程师仅允许:是、否")
|
||||
private String seniorEngineer;
|
||||
|
||||
@ExcelProperty(value = "高级工程师系列/专业", index = 21)
|
||||
private String seniorEngineerSeries;
|
||||
|
||||
@ExcelIgnore
|
||||
private Integer rowIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue