From 1e48fb8cf3dd72dba07d1dfb5e9dc7a6af8878f1 Mon Sep 17 00:00:00 2001 From: luotaiqian <1147642922@qq.com> Date: Tue, 11 Aug 2026 14:06:50 +0800 Subject: [PATCH] bug fix --- .../support/OrgPersonnelExcelImporter.java | 164 +++++------------- .../app/support/OrgPersonnelImportRow.java | 18 ++ 2 files changed, 63 insertions(+), 119 deletions(-) diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java index 849a3629..a29f5f00 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelExcelImporter.java @@ -3,10 +3,8 @@ package org.qinan.safetyeval.app.support; import cn.hutool.core.lang.Pair; import cn.hutool.core.util.IdcardUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.validation.ValidationUtil; import com.alibaba.excel.EasyExcel; import com.jjb.saas.framework.auth.utils.AuthContext; -import com.jjb.saas.framework.core.utils.ValidatorUtils; import com.jjb.saas.system.client.user.request.RoleDeptAddCmd; import com.jjb.saas.system.client.user.request.UserAddCmd; import com.zcloud.gbscommon.utils.MD5; @@ -34,10 +32,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import org.springframework.validation.ValidationUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.validation.ConstraintViolation; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -61,12 +59,12 @@ public class OrgPersonnelExcelImporter { private static final DateTimeFormatter SLASH_DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern("yyyy/M/d").toFormatter(); - /** 手机号格式:11位纯数字、1开头 */ - private static final String MOBILE_PHONE_REGEX = "^1\\d{10}$"; - @Resource private OrgDepartmentGateway orgDepartmentGateway; + @Resource + private javax.validation.Validator validator; + @Resource private OrgPositionGateway orgPositionGateway; @@ -227,12 +225,12 @@ public class OrgPersonnelExcelImporter { } row.setRowIndex(i + 2); - // 账号(手机号)校验:必填、格式、文件内去重 - if (!validateAccount(row, seenAccounts, errors)) { + // 字段校验:JSR-303 注解(必填、长度、手机号格式)+ 身份证号 + 日期格式 + if (!validateRowFields(row, errors)) { continue; } - // 字段级校验:必填、长度、格式 - if (!validateRowFields(row, errors)) { + // 账号文件内去重 + if (!checkAccountDuplicate(row, seenAccounts, errors)) { continue; } rows.add(row); @@ -241,48 +239,13 @@ public class OrgPersonnelExcelImporter { } /** - * 校验账号(手机号):必填、格式、文件内去重。 - * - * @param row 当前行 - * @param seenAccounts 已出现的账号集合(用于文件内去重) - * @param errors 异常收集列表 - * @return true 通过,false 失败(已记录异常) - */ - private boolean validateAccount(OrgPersonnelImportRow row, Set seenAccounts, - List errors) { - Integer rowIndex = row.getRowIndex(); - String account = trim(row.getAccount()); - String userName = trim(row.getUserName()); - - // 账号必填(DB: account NOT NULL) - if (!StringUtils.hasText(account)) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "账号不能为空")); - return false; - } - // 手机号格式校验:11位纯数字、1开头 - if (!account.matches(MOBILE_PHONE_REGEX)) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, - "手机号格式不正确,应为11位数字且以1开头")); - return false; - } - // 文件内去重 - if (!seenAccounts.add(account)) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, - "账号在文件内重复,已剔除该行")); - return false; - } - return true; - } - - /** - * 校验行数据的各字段:必填、长度、格式/类型。 - *

- * 覆盖直接存入数据库的字段,校验规则依据 {@code org_personnel} 表结构: - *

+ * 字段级校验: + *
    + *
  1. JSR-303 注解校验({@link OrgPersonnelImportRow} 字段上的 @NotBlank/@Size/@Pattern), + * 覆盖必填、长度、手机号格式;
  2. + *
  3. 身份证号:使用 {@link IdcardUtil} 校验校验位与出生日期合法性;
  4. + *
  5. 日期字段:兼容 yyyy-MM-dd / yyyy/M/d 格式校验。
  6. + *
* * @param row 当前行 * @param errors 异常收集列表 @@ -293,17 +256,21 @@ public class OrgPersonnelExcelImporter { String account = trim(row.getAccount()); String userName = trim(row.getUserName()); - // 姓名:必填(DB: user_name varchar(50) NOT NULL) - if (!StringUtils.hasText(userName)) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "姓名不能为空")); - return false; - } - if (userName.length() > 50) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "姓名长度不能超过50个字符")); + // 1. JSR-303 注解校验:每字段仅取第一条违规,避免 @NotBlank+@Pattern 重复报错 + Set> violations = validator.validate(row); + if (!violations.isEmpty()) { + violations.stream() + .collect(Collectors.toMap( + v -> v.getPropertyPath().toString(), + v -> v, + (a, b) -> a)) + .values() + .forEach(v -> errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, + v.getMessage()))); return false; } - // 身份证号:可选,格式校验(DB: id_card_no varchar(18)) + // 2. 身份证号格式校验(DB: id_card_no varchar(18)) String idCardNo = trim(row.getIdCardNo()); if (StringUtils.hasText(idCardNo) && !IdcardUtil.isValidCard(idCardNo)) { errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, @@ -311,22 +278,13 @@ public class OrgPersonnelExcelImporter { return false; } - // 性别名称:最大10(DB: gender_name varchar(10)) - String gender = trim(row.getGender()); - if (StringUtils.hasText(gender) && gender.length() > 10) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "性别长度不能超过10个字符")); - return false; - } - - // 出生日期:日期格式校验(DB: birth_date date) + // 3. 日期格式校验(DB: birth_date / join_work_date date) String birthDate = trim(row.getBirthDate()); if (StringUtils.hasText(birthDate) && parseDate(birthDate) == null) { errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "出生日期格式不正确,应为yyyy-MM-dd或yyyy/M/d")); return false; } - - // 参加工作时间:日期格式校验(DB: join_work_date date) String joinWorkDate = trim(row.getJoinWorkDate()); if (StringUtils.hasText(joinWorkDate) && parseDate(joinWorkDate) == null) { errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, @@ -334,57 +292,25 @@ public class OrgPersonnelExcelImporter { return false; } - // 学历名称:最大50(DB: education_name varchar(50)) - String education = trim(row.getEducation()); - if (StringUtils.hasText(education) && education.length() > 50) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "学历长度不能超过50个字符")); + return true; + } + + /** + * 账号文件内去重(空账号不参与去重)。 + * + * @param row 当前行 + * @param seenAccounts 已出现的账号集合 + * @param errors 异常收集列表 + * @return true 通过,false 重复(已记录异常) + */ + private boolean checkAccountDuplicate(OrgPersonnelImportRow row, Set seenAccounts, + List errors) { + String account = trim(row.getAccount()); + if (StringUtils.hasText(account) && !seenAccounts.add(account)) { + errors.add(new OrgPersonnelImportErrorCO(row.getRowIndex(), account, trim(row.getUserName()), + "账号在文件内重复,已剔除该行")); return false; } - - // 毕业院校:最大200(DB: graduate_school varchar(200)) - String graduateSchool = trim(row.getGraduateSchool()); - if (StringUtils.hasText(graduateSchool) && graduateSchool.length() > 200) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "毕业院校长度不能超过200个字符")); - return false; - } - - // 所学专业:最大100(DB: major varchar(100)) - String major = trim(row.getMajor()); - if (StringUtils.hasText(major) && major.length() > 100) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "所学专业长度不能超过100个字符")); - return false; - } - - // 现住地址:最大500(DB: current_address varchar(500)) - String currentAddress = trim(row.getCurrentAddress()); - if (StringUtils.hasText(currentAddress) && currentAddress.length() > 500) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "现住地址长度不能超过500个字符")); - return false; - } - - // 办公地址:最大500(DB: office_address varchar(500)) - String officeAddress = trim(row.getOfficeAddress()); - if (StringUtils.hasText(officeAddress) && officeAddress.length() > 500) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, "办公地址长度不能超过500个字符")); - return false; - } - - // 出版学术专著等:最大1000(DB: publications varchar(1000)) - String publications = trim(row.getPublications()); - if (StringUtils.hasText(publications) && publications.length() > 1000) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, - "出版学术专著等信息长度不能超过1000个字符")); - return false; - } - - // 自我申报专业能力:最大1000(DB: ability_declaration varchar(1000)) - String abilityDeclaration = trim(row.getAbilityDeclaration()); - if (StringUtils.hasText(abilityDeclaration) && abilityDeclaration.length() > 1000) { - errors.add(new OrgPersonnelImportErrorCO(rowIndex, account, userName, - "自我申报的专业能力信息长度不能超过1000个字符")); - return false; - } - return true; } diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java index 12ff85a4..d79be9a4 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelImportRow.java @@ -5,6 +5,10 @@ import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; import org.springframework.util.StringUtils; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + /** * 人员导入 Excel 行模型(按列下标映射,避免表头存在重名列)。 *

@@ -36,27 +40,37 @@ public class OrgPersonnelImportRow { 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) private String birthDate; @ExcelProperty(value = "身份证号", index = 8) + @Size(max = 18, message = "身份证号长度不能超过18个字符") private String idCardNo; @ExcelProperty(value = "学历", index = 9) + @Size(max = 50, message = "学历长度不能超过50个字符") private String education; @ExcelProperty(value = "毕业院校", index = 10) + @Size(max = 200, message = "毕业院校长度不能超过200个字符") private String graduateSchool; @ExcelProperty(value = "所学专业", index = 11) + @Size(max = 100, message = "所学专业长度不能超过100个字符") private String major; @ExcelProperty(value = "职称", index = 12) @@ -69,18 +83,22 @@ public class OrgPersonnelImportRow { private String registerEngineer; @ExcelProperty(value = "现住地址", index = 15) + @Size(max = 500, message = "现住地址长度不能超过500个字符") private String currentAddress; @ExcelProperty(value = "办公地址", index = 16) + @Size(max = 500, message = "办公地址长度不能超过500个字符") private String officeAddress; @ExcelProperty(value = "主要学习工作经历", index = 17) private String workExperience; @ExcelProperty(value = "出版学术专著、专利、获奖、发表学术论文等", index = 18) + @Size(max = 1000, message = "出版学术专著等信息长度不能超过1000个字符") private String publications; @ExcelProperty(value = "自我申报的专业能力及认定方式", index = 19) + @Size(max = 1000, message = "自我申报的专业能力信息长度不能超过1000个字符") private String abilityDeclaration; /**