feat 员工亲属关系
This commit is contained in:
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 员工亲属关系Excel导入导出对象
|
||||
@@ -46,68 +47,68 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
|
||||
@DictDropdown(dictType = "ccdi_indiv_gender")
|
||||
private String gender;
|
||||
|
||||
/** 出生日期 */
|
||||
@ExcelProperty(value = "出生日期", index = 4)
|
||||
@ColumnWidth(15)
|
||||
private Date birthDate;
|
||||
|
||||
/** 关系人证件类型 */
|
||||
@ExcelProperty(value = "关系人证件类型*", index = 4)
|
||||
@ExcelProperty(value = "关系人证件类型*", index = 5)
|
||||
@ColumnWidth(15)
|
||||
@DictDropdown(dictType = "ccdi_certificate_type")
|
||||
@Required
|
||||
private String relationCertType;
|
||||
|
||||
/** 关系人证件号码 */
|
||||
@ExcelProperty(value = "关系人证件号码*", index = 5)
|
||||
@ExcelProperty(value = "关系人证件号码*", index = 6)
|
||||
@ColumnWidth(20)
|
||||
@Required
|
||||
private String relationCertNo;
|
||||
|
||||
/** 手机号码1 */
|
||||
@ExcelProperty(value = "手机号码1", index = 6)
|
||||
@ExcelProperty(value = "手机号码1", index = 7)
|
||||
@ColumnWidth(15)
|
||||
private String mobilePhone1;
|
||||
|
||||
/** 手机号码2 */
|
||||
@ExcelProperty(value = "手机号码2", index = 7)
|
||||
@ExcelProperty(value = "手机号码2", index = 8)
|
||||
@ColumnWidth(15)
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 微信名称1 */
|
||||
@ExcelProperty(value = "微信名称1", index = 8)
|
||||
@ExcelProperty(value = "微信名称1", index = 9)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo1;
|
||||
|
||||
/** 微信名称2 */
|
||||
@ExcelProperty(value = "微信名称2", index = 9)
|
||||
@ExcelProperty(value = "微信名称2", index = 10)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo2;
|
||||
|
||||
/** 微信名称3 */
|
||||
@ExcelProperty(value = "微信名称3", index = 10)
|
||||
@ExcelProperty(value = "微信名称3", index = 11)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo3;
|
||||
|
||||
/** 详细联系地址 */
|
||||
@ExcelProperty(value = "详细联系地址", index = 11)
|
||||
@ExcelProperty(value = "详细联系地址", index = 12)
|
||||
@ColumnWidth(30)
|
||||
private String contactAddress;
|
||||
|
||||
/** 关系详细描述 */
|
||||
@ExcelProperty(value = "关系详细描述", index = 12)
|
||||
@ExcelProperty(value = "关系详细描述", index = 13)
|
||||
@ColumnWidth(30)
|
||||
private String relationDesc;
|
||||
|
||||
/** 生效日期 */
|
||||
@ExcelProperty(value = "生效日期", index = 13)
|
||||
@ExcelProperty(value = "生效日期", index = 14)
|
||||
@ColumnWidth(15)
|
||||
private String effectiveDate;
|
||||
private Date effectiveDate;
|
||||
|
||||
/** 失效日期 */
|
||||
@ExcelProperty(value = "失效日期", index = 14)
|
||||
@ExcelProperty(value = "失效日期", index = 15)
|
||||
@ColumnWidth(15)
|
||||
private String invalidDate;
|
||||
|
||||
/** 状态 */
|
||||
@ExcelProperty(value = "状态", index = 15)
|
||||
@ColumnWidth(10)
|
||||
private Integer status;
|
||||
private Date invalidDate;
|
||||
|
||||
/** 备注 */
|
||||
@ExcelProperty(value = "备注", index = 16)
|
||||
|
||||
138
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/enums/GenderEnum.java
Normal file
138
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/enums/GenderEnum.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package com.ruoyi.ccdi.enums;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 性别枚举
|
||||
* 用于性别中文标签与英文代码之间的转换
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
public enum GenderEnum {
|
||||
|
||||
/**
|
||||
* 男
|
||||
*/
|
||||
MALE("男", "M"),
|
||||
|
||||
/**
|
||||
* 女
|
||||
*/
|
||||
FEMALE("女", "F"),
|
||||
|
||||
/**
|
||||
* 其他
|
||||
*/
|
||||
OTHER("其他", "O");
|
||||
|
||||
private final String chineseLabel;
|
||||
private final String englishCode;
|
||||
|
||||
GenderEnum(String chineseLabel, String englishCode) {
|
||||
this.chineseLabel = chineseLabel;
|
||||
this.englishCode = englishCode;
|
||||
}
|
||||
|
||||
public String getChineseLabel() {
|
||||
return chineseLabel;
|
||||
}
|
||||
|
||||
public String getEnglishCode() {
|
||||
return englishCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据中文标签获取枚举
|
||||
*
|
||||
* @param chineseLabel 中文标签(男、女、其他)
|
||||
* @return 对应的枚举值
|
||||
* @throws IllegalArgumentException 如果标签无效
|
||||
*/
|
||||
public static GenderEnum fromChinese(String chineseLabel) {
|
||||
if (StringUtils.isEmpty(chineseLabel)) {
|
||||
throw new IllegalArgumentException("性别标签不能为空");
|
||||
}
|
||||
|
||||
for (GenderEnum gender : values()) {
|
||||
if (gender.chineseLabel.equals(chineseLabel)) {
|
||||
return gender;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("无效的性别标签: " + chineseLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据英文代码获取枚举
|
||||
*
|
||||
* @param englishCode 英文代码(M、F、O)
|
||||
* @return 对应的枚举值
|
||||
* @throws IllegalArgumentException 如果代码无效
|
||||
*/
|
||||
public static GenderEnum fromEnglish(String englishCode) {
|
||||
if (StringUtils.isEmpty(englishCode)) {
|
||||
throw new IllegalArgumentException("性别代码不能为空");
|
||||
}
|
||||
|
||||
for (GenderEnum gender : values()) {
|
||||
if (gender.englishCode.equals(englishCode)) {
|
||||
return gender;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("无效的性别代码: " + englishCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证性别值是否有效
|
||||
* 支持中文标签(男、女、其他)或英文代码(M、F、O)
|
||||
*
|
||||
* @param value 待验证的值
|
||||
* @return true-有效,false-无效
|
||||
*/
|
||||
public static boolean isValid(String value) {
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (GenderEnum gender : values()) {
|
||||
if (gender.chineseLabel.equals(value) || gender.englishCode.equals(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准化性别值
|
||||
* 输入中文标签或英文代码,统一返回英文代码
|
||||
*
|
||||
* @param input 输入值(中文或英文)
|
||||
* @return 英文代码(M、F、O)
|
||||
* @throws IllegalArgumentException 如果输入值无效
|
||||
*/
|
||||
public static String normalize(String input) {
|
||||
if (StringUtils.isEmpty(input)) {
|
||||
throw new IllegalArgumentException("性别值不能为空");
|
||||
}
|
||||
|
||||
// 先尝试按中文匹配
|
||||
for (GenderEnum gender : values()) {
|
||||
if (gender.chineseLabel.equals(input)) {
|
||||
return gender.englishCode;
|
||||
}
|
||||
}
|
||||
|
||||
// 再尝试按英文匹配(大写)
|
||||
String upperInput = input.toUpperCase().trim();
|
||||
for (GenderEnum gender : values()) {
|
||||
if (gender.englishCode.equals(upperInput)) {
|
||||
return gender.englishCode;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("无效的性别值: " + input + ",有效值为:男、女、其他 或 M、F、O");
|
||||
}
|
||||
}
|
||||
@@ -50,4 +50,14 @@ public interface CcdiStaffFmyRelationMapper extends BaseMapper<CcdiStaffFmyRelat
|
||||
* @return 插入行数
|
||||
*/
|
||||
int insertBatch(@Param("list") List<CcdiStaffFmyRelation> list);
|
||||
|
||||
/**
|
||||
* 批量查询已存在的员工亲属关系(用于导入唯一性校验)
|
||||
*
|
||||
* @param personIds 员工身份证号列表
|
||||
* @param relationCertNos 关系人证件号码列表
|
||||
* @return 已存在的记录列表
|
||||
*/
|
||||
List<CcdiStaffFmyRelation> selectExistingRelations(@Param("personIds") List<String> personIds,
|
||||
@Param("relationCertNos") List<String> relationCertNos);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.ruoyi.ccdi.domain.excel.CcdiStaffFmyRelationExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportResult;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportStatusVO;
|
||||
import com.ruoyi.ccdi.domain.vo.StaffFmyRelationImportFailureVO;
|
||||
import com.ruoyi.ccdi.enums.GenderEnum;
|
||||
import com.ruoyi.ccdi.mapper.CcdiStaffFmyRelationMapper;
|
||||
import com.ruoyi.ccdi.service.ICcdiStaffFmyRelationImportService;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
@@ -44,10 +45,38 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
||||
List<CcdiStaffFmyRelation> newRecords = new ArrayList<>();
|
||||
List<StaffFmyRelationImportFailureVO> failures = new ArrayList<>();
|
||||
|
||||
// 用于跟踪Excel文件内已处理的唯一键(personId + relationCertNo)
|
||||
// ========== 第一步:批量唯一性校验 ==========
|
||||
// 1. 提取Excel中所有的personId和relationCertNo
|
||||
Set<String> excelPersonIds = new HashSet<>();
|
||||
Set<String> excelRelationCertNos = new HashSet<>();
|
||||
for (CcdiStaffFmyRelationExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getPersonId())) {
|
||||
excelPersonIds.add(excel.getPersonId());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(excel.getRelationCertNo())) {
|
||||
excelRelationCertNos.add(excel.getRelationCertNo());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 批量查询数据库中已存在的记录
|
||||
Set<String> existingKeys = new HashSet<>();
|
||||
if (!excelPersonIds.isEmpty() && !excelRelationCertNos.isEmpty()) {
|
||||
List<CcdiStaffFmyRelation> existingRecords = relationMapper.selectExistingRelations(
|
||||
new ArrayList<>(excelPersonIds),
|
||||
new ArrayList<>(excelRelationCertNos)
|
||||
);
|
||||
|
||||
// 3. 构建已存在记录的唯一键集合(personId + relationCertNo)
|
||||
for (CcdiStaffFmyRelation existing : existingRecords) {
|
||||
String key = existing.getPersonId() + "|" + existing.getRelationCertNo();
|
||||
existingKeys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 第二步:处理数据 ==========
|
||||
// 用于跟踪Excel文件内已处理的唯一键
|
||||
Set<String> processedKeys = new HashSet<>();
|
||||
|
||||
// 分类数据
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiStaffFmyRelationExcel excel = excelList.get(i);
|
||||
|
||||
@@ -67,17 +96,22 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
||||
throw new RuntimeException(String.format("员工[%s]的关系人[%s]在导入文件中重复", excel.getPersonId(), excel.getRelationCertNo()));
|
||||
}
|
||||
|
||||
// 检查是否在数据库中已存在(批量校验的结果)
|
||||
if (existingKeys.contains(uniqueKey)) {
|
||||
throw new RuntimeException(String.format("员工[%s]的关系人[%s]已存在", excel.getPersonId(), excel.getRelationCertNo()));
|
||||
}
|
||||
|
||||
// 从已验证和转换过的addDTO创建relation对象
|
||||
CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
|
||||
BeanUtils.copyProperties(excel, relation);
|
||||
BeanUtils.copyProperties(addDTO, relation);
|
||||
|
||||
relation.setCreatedBy(userName);
|
||||
relation.setUpdatedBy(userName);
|
||||
relation.setIsEmpFamily(true);
|
||||
relation.setIsCustFamily(false);
|
||||
relation.setDataSource("IMPORT");
|
||||
if (relation.getStatus() == null) {
|
||||
relation.setStatus(1);
|
||||
}
|
||||
// 显式设置状态为有效(status=1)
|
||||
relation.setStatus(1);
|
||||
|
||||
newRecords.add(relation);
|
||||
processedKeys.add(uniqueKey);
|
||||
@@ -230,8 +264,14 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
||||
}
|
||||
|
||||
// 验证性别值(如果提供)
|
||||
if (StringUtils.isNotEmpty(addDTO.getGender()) && !addDTO.getGender().matches("^[MFO]$")) {
|
||||
throw new RuntimeException("性别只能是M、F或O");
|
||||
if (StringUtils.isNotEmpty(addDTO.getGender())) {
|
||||
try {
|
||||
// 使用GenderEnum进行标准化,支持中文(男、女、其他)和英文(M、F、O)
|
||||
String normalizedGender = GenderEnum.normalize(addDTO.getGender());
|
||||
addDTO.setGender(normalizedGender);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException("性别只能是:男、女、其他 或 M、F、O");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,4 +148,21 @@
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- 批量查询已存在的员工亲属关系(用于导入唯一性校验) -->
|
||||
<select id="selectExistingRelations" resultType="com.ruoyi.ccdi.domain.CcdiStaffFmyRelation">
|
||||
SELECT
|
||||
id, person_id, relation_type, relation_name, gender, birth_date,
|
||||
relation_cert_type, relation_cert_no
|
||||
FROM ccdi_staff_fmy_relation
|
||||
WHERE is_emp_family = 1
|
||||
AND person_id IN
|
||||
<foreach collection="personIds" item="personId" open="(" separator="," close=")">
|
||||
#{personId}
|
||||
</foreach>
|
||||
AND relation_cert_no IN
|
||||
<foreach collection="relationCertNos" item="relationCertNo" open="(" separator="," close=")">
|
||||
#{relationCertNo}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user