From 497e040c81e75d6d00b51786b08764e2028ff7c0 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:00:17 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E5=91=98=E5=B7=A5=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E5=85=B3=E7=B3=BB=E5=AF=BC=E5=85=A5=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E5=8F=B7=E5=AD=98=E5=9C=A8=E6=80=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ffEnterpriseRelationImportServiceImpl.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java index a2f06f8..69cf3a9 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java @@ -1,12 +1,15 @@ package com.ruoyi.ccdi.service.impl; import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.ccdi.domain.CcdiBaseStaff; import com.ruoyi.ccdi.domain.CcdiStaffEnterpriseRelation; import com.ruoyi.ccdi.domain.dto.CcdiStaffEnterpriseRelationAddDTO; import com.ruoyi.ccdi.domain.excel.CcdiStaffEnterpriseRelationExcel; import com.ruoyi.ccdi.domain.vo.ImportResult; import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.StaffEnterpriseRelationImportFailureVO; +import com.ruoyi.ccdi.mapper.CcdiBaseStaffMapper; import com.ruoyi.ccdi.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.ccdi.service.ICcdiStaffEnterpriseRelationImportService; import com.ruoyi.ccdi.utils.ImportLogUtils; @@ -43,6 +46,9 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE @Resource private RedisTemplate redisTemplate; + @Resource + private CcdiBaseStaffMapper baseStaffMapper; + @Override @Async @Transactional @@ -55,6 +61,28 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); + // 批量验证员工身份证号是否存在 + Set excelPersonIds = excelList.stream() + .map(CcdiStaffEnterpriseRelationExcel::getPersonId) + .filter(StringUtils::isNotEmpty) + .collect(Collectors.toSet()); + + Set existingPersonIds = new HashSet<>(); + if (!excelPersonIds.isEmpty()) { + ImportLogUtils.logBatchQueryStart(log, taskId, "员工身份证号", excelPersonIds.size()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(CcdiBaseStaff::getIdCard) + .in(CcdiBaseStaff::getIdCard, excelPersonIds); + + List existingStaff = baseStaffMapper.selectList(wrapper); + existingPersonIds = existingStaff.stream() + .map(CcdiBaseStaff::getIdCard) + .collect(Collectors.toSet()); + + ImportLogUtils.logBatchQueryComplete(log, taskId, "员工身份证号", existingPersonIds.size()); + } + // 批量查询已存在的person_id + social_credit_code组合 ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工企业关系组合", excelList.size()); Set existingCombinations = getExistingCombinations(excelList); @@ -68,6 +96,13 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE CcdiStaffEnterpriseRelationExcel excel = excelList.get(i); try { + // 身份证号存在性检查 + if (!existingPersonIds.contains(excel.getPersonId())) { + throw new RuntimeException(String.format( + "第%d行: 身份证号[%s]不存在于员工信息表中", + i + 1, excel.getPersonId())); + } + // 转换为AddDTO进行验证 CcdiStaffEnterpriseRelationAddDTO addDTO = new CcdiStaffEnterpriseRelationAddDTO(); BeanUtils.copyProperties(excel, addDTO); From af7ec6f43dc1c8a80fe23cb5a437eef27ea5002d Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:09:47 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E8=BA=AB=E4=BB=BD?= =?UTF-8?q?=E8=AF=81=E5=8F=B7=E9=AA=8C=E8=AF=81=E9=A1=BA=E5=BA=8F=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E7=A9=BA=E6=8C=87=E9=92=88=E9=A3=8E=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将身份证号存在性检查移到基本数据验证之后 - 此时 personId 已确保不为空且格式正确 - 错误信息更准确,包含操作建议 --- ...diStaffEnterpriseRelationImportServiceImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java index 69cf3a9..070e204 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffEnterpriseRelationImportServiceImpl.java @@ -96,13 +96,6 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE CcdiStaffEnterpriseRelationExcel excel = excelList.get(i); try { - // 身份证号存在性检查 - if (!existingPersonIds.contains(excel.getPersonId())) { - throw new RuntimeException(String.format( - "第%d行: 身份证号[%s]不存在于员工信息表中", - i + 1, excel.getPersonId())); - } - // 转换为AddDTO进行验证 CcdiStaffEnterpriseRelationAddDTO addDTO = new CcdiStaffEnterpriseRelationAddDTO(); BeanUtils.copyProperties(excel, addDTO); @@ -110,6 +103,13 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE // 验证数据 validateRelationData(addDTO); + // 身份证号存在性检查(在基本验证之后) + if (!existingPersonIds.contains(excel.getPersonId())) { + throw new RuntimeException(String.format( + "第%d行: 身份证号[%s]不存在于员工信息表中,请先添加员工信息", + i + 1, excel.getPersonId())); + } + String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode(); CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation(); From 9776d76d1a5c1230fe04427e3c76d1ff0b960b2d Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:20:08 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=E5=91=98=E5=B7=A5=E4=BA=B2?= =?UTF-8?q?=E5=B1=9E=E5=85=B3=E7=B3=BB=E5=AF=BC=E5=85=A5=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E5=8F=B7=E5=AD=98=E5=9C=A8=E6=80=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...CcdiStaffFmyRelationImportServiceImpl.java | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffFmyRelationImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffFmyRelationImportServiceImpl.java index 2e1eb40..aff8d2a 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffFmyRelationImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffFmyRelationImportServiceImpl.java @@ -1,6 +1,8 @@ package com.ruoyi.ccdi.service.impl; import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.ccdi.domain.CcdiBaseStaff; import com.ruoyi.ccdi.domain.CcdiStaffFmyRelation; import com.ruoyi.ccdi.domain.dto.CcdiStaffFmyRelationAddDTO; import com.ruoyi.ccdi.domain.excel.CcdiStaffFmyRelationExcel; @@ -8,6 +10,7 @@ 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.CcdiBaseStaffMapper; import com.ruoyi.ccdi.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.ccdi.service.ICcdiStaffFmyRelationImportService; import com.ruoyi.ccdi.utils.ImportLogUtils; @@ -24,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * 员工亲属关系异步导入服务层处理 @@ -43,6 +47,9 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat @Resource private RedisTemplate redisTemplate; + @Resource + private CcdiBaseStaffMapper baseStaffMapper; + @Override @Async @Transactional @@ -55,14 +62,32 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); + // 批量验证员工身份证号是否存在 + Set excelPersonIds = excelList.stream() + .map(CcdiStaffFmyRelationExcel::getPersonId) + .filter(StringUtils::isNotEmpty) + .collect(Collectors.toSet()); + + Set existingPersonIds = new HashSet<>(); + if (!excelPersonIds.isEmpty()) { + ImportLogUtils.logBatchQueryStart(log, taskId, "员工身份证号", excelPersonIds.size()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(CcdiBaseStaff::getIdCard) + .in(CcdiBaseStaff::getIdCard, excelPersonIds); + + List existingStaff = baseStaffMapper.selectList(wrapper); + existingPersonIds = existingStaff.stream() + .map(CcdiBaseStaff::getIdCard) + .collect(Collectors.toSet()); + + ImportLogUtils.logBatchQueryComplete(log, taskId, "员工身份证号", existingPersonIds.size()); + } + // ========== 第一步:批量唯一性校验 ========== - // 1. 提取Excel中所有的personId和relationCertNo - Set excelPersonIds = new HashSet<>(); + // 1. 提取Excel中所有的relationCertNo(personId已在前面提取) Set 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()); } @@ -70,7 +95,7 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat // 2. 批量查询数据库中已存在的记录 Set existingKeys = new HashSet<>(); - if (!excelPersonIds.isEmpty() && !excelRelationCertNos.isEmpty()) { + if (!excelRelationCertNos.isEmpty()) { ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的亲属关系", excelList.size()); List existingRecords = relationMapper.selectExistingRelations( new ArrayList<>(excelPersonIds), @@ -100,6 +125,13 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat // 验证数据 validateRelationData(addDTO); + // 身份证号存在性检查(在基本验证之后) + if (!existingPersonIds.contains(excel.getPersonId())) { + throw new RuntimeException(String.format( + "第%d行: 身份证号[%s]不存在于员工信息表中,请先添加员工信息", + i + 1, excel.getPersonId())); + } + // 生成唯一键 String uniqueKey = excel.getPersonId() + "|" + excel.getRelationCertNo(); From 9e3609b8ad6489a4fc1ce5557f2ca083e3eca55d Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:31:31 +0800 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E8=B0=83=E5=8A=A8=E5=AF=BC=E5=85=A5=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BB=8E2=E6=AC=A1=E9=81=8D?= =?UTF-8?q?=E5=8E=86=E4=BC=98=E5=8C=96=E4=B8=BA1=E6=AC=A1=E9=81=8D?= =?UTF-8?q?=E5=8E=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CcdiStaffTransferImportServiceImpl.java | 105 +++++------------- 1 file changed, 27 insertions(+), 78 deletions(-) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java index 1368f86..a7feb06 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java @@ -65,8 +65,27 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); - // 批量验证员工ID是否存在 - Set existingStaffIds = batchValidateStaffIds(excelList, taskId, failures); + // 批量查询员工ID存在性 + Set excelStaffIds = excelList.stream() + .map(CcdiStaffTransferExcel::getStaffId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + Set existingStaffIds = new HashSet<>(); + if (!excelStaffIds.isEmpty()) { + ImportLogUtils.logBatchQueryStart(log, taskId, "员工ID", excelStaffIds.size()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(CcdiBaseStaff::getStaffId) + .in(CcdiBaseStaff::getStaffId, excelStaffIds); + + List existingStaff = baseStaffMapper.selectList(wrapper); + existingStaffIds = existingStaff.stream() + .map(CcdiBaseStaff::getStaffId) + .collect(Collectors.toSet()); + + ImportLogUtils.logBatchQueryComplete(log, taskId, "员工ID", existingStaffIds.size()); + } // 批量查询已存在的唯一键组合 ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的调动记录", excelList.size()); @@ -80,12 +99,13 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp for (int i = 0; i < excelList.size(); i++) { CcdiStaffTransferExcel excel = excelList.get(i); - // 跳过已在预验证阶段失败的记录 - if (isRowAlreadyFailed(excel, failures)) { - continue; - } - try { + // 员工ID存在性检查 + if (excel.getStaffId() != null && !existingStaffIds.contains(excel.getStaffId())) { + throw new RuntimeException(String.format( + "员工ID %s 不存在", excel.getStaffId())); + } + // 转换为AddDTO进行验证 CcdiStaffTransferAddDTO addDTO = new CcdiStaffTransferAddDTO(); BeanUtils.copyProperties(excel, addDTO); @@ -355,75 +375,4 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp return JSON.parseArray(JSON.toJSONString(failuresObj), StaffTransferImportFailureVO.class); } - - /** - * 批量验证员工ID是否存在 - * - * @param excelList Excel数据列表 - * @param taskId 任务ID - * @param failures 失败记录列表(会追加验证失败的记录) - * @return 存在的员工ID集合 - */ - private Set batchValidateStaffIds(List excelList, - String taskId, - List failures) { - // 1. 提取并去重员工ID - Set allStaffIds = excelList.stream() - .map(CcdiStaffTransferExcel::getStaffId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - if (allStaffIds.isEmpty()) { - return Collections.emptySet(); - } - - // 2. 批量查询存在的员工ID - ImportLogUtils.logBatchQueryStart(log, taskId, "员工ID", allStaffIds.size()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.select(CcdiBaseStaff::getStaffId) - .in(CcdiBaseStaff::getStaffId, allStaffIds); - - List existingStaff = baseStaffMapper.selectList(wrapper); - Set existingStaffIds = existingStaff.stream() - .map(CcdiBaseStaff::getStaffId) - .collect(Collectors.toSet()); - - ImportLogUtils.logBatchQueryComplete(log, taskId, "员工ID", existingStaffIds.size()); - - // 3. 预验证并标记不存在的员工ID - for (int i = 0; i < excelList.size(); i++) { - CcdiStaffTransferExcel excel = excelList.get(i); - Long staffId = excel.getStaffId(); - - if (staffId != null && !existingStaffIds.contains(staffId)) { - StaffTransferImportFailureVO failure = new StaffTransferImportFailureVO(); - BeanUtils.copyProperties(excel, failure); - failure.setErrorMessage(String.format("第%d行: 员工ID %s 不存在", i + 1, staffId)); - failures.add(failure); - - String keyData = String.format("员工ID=%s", staffId); - ImportLogUtils.logValidationError(log, taskId, i + 1, - failure.getErrorMessage(), keyData); - } - } - - return existingStaffIds; - } - - /** - * 检查某行数据是否已在失败列表中 - * - * @param excel Excel数据 - * @param failures 失败记录列表 - * @return true-已失败,false-未失败 - */ - private boolean isRowAlreadyFailed(CcdiStaffTransferExcel excel, - List failures) { - return failures.stream() - .anyMatch(f -> Objects.equals(f.getStaffId(), excel.getStaffId()) - && Objects.equals(f.getTransferDate(), excel.getTransferDate()) - && Objects.equals(f.getDeptIdBefore(), excel.getDeptIdBefore()) - && Objects.equals(f.getDeptIdAfter(), excel.getDeptIdAfter())); - } } From aaa62567354036ba4eaa8c7780a2f06f7516a8f7 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 15:48:30 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=E5=91=98=E5=B7=A5ID=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=A1=8C=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java index a7feb06..300606f 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffTransferImportServiceImpl.java @@ -103,7 +103,8 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp // 员工ID存在性检查 if (excel.getStaffId() != null && !existingStaffIds.contains(excel.getStaffId())) { throw new RuntimeException(String.format( - "员工ID %s 不存在", excel.getStaffId())); + "第%d行: 员工ID %s 不存在", + i + 1, excel.getStaffId())); } // 转换为AddDTO进行验证 From 29b541730b36413f9b91ba272d48a249556d44d2 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 11 Feb 2026 17:06:36 +0800 Subject: [PATCH 6/6] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E5=AF=BC?= =?UTF-8?q?=E5=85=A5API=E6=96=87=E6=A1=A3=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E5=8F=B7=E9=AA=8C=E8=AF=81=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新员工调动记录导入API文档,添加导入验证规则说明 - 新增员工实体关系导入API文档 - 新增员工亲属关系导入API文档 - 说明新增的身份证号存在性校验功能 - 记录性能优化(批量预验证、1次遍历) --- doc/api-docs/api/员工亲属关系导入API文档.md | 195 ++++++++++++++++++++ doc/api-docs/api/员工实体关系导入API文档.md | 178 ++++++++++++++++++ doc/api-docs/api/员工调动记录管理API文档.md | 15 ++ 3 files changed, 388 insertions(+) create mode 100644 doc/api-docs/api/员工亲属关系导入API文档.md create mode 100644 doc/api-docs/api/员工实体关系导入API文档.md diff --git a/doc/api-docs/api/员工亲属关系导入API文档.md b/doc/api-docs/api/员工亲属关系导入API文档.md new file mode 100644 index 0000000..2e56b2e --- /dev/null +++ b/doc/api-docs/api/员工亲属关系导入API文档.md @@ -0,0 +1,195 @@ +# 员工亲属关系导入 API 文档 + +## 概述 + +员工亲属关系导入模块提供员工亲属关系的批量导入功能。 + +**基础路径**: `/ccdi/staffFmyRelation` + +**权限标识前缀**: `ccdi:staffFmyRelation` + +**数据表**: `ccdi_cust_fmy_relation` + +**关联表**: +- `ccdi_base_staff` - 员工基础信息表(通过id_card关联) + +--- + +## API 接口 + +### 1. 异步导入员工亲属关系 + +**接口地址**: `POST /ccdi/staffFmyRelation/importData` + +**权限要求**: `ccdi:staffFmyRelation:import` + +**请求参数**: FormData + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| file | File | 是 | Excel文件 | +| updateSupport | Boolean | 否 | 是否更新已存在的记录(默认false) | + +**响应示例**: +```json +{ + "code": 200, + "msg": "导入任务已提交,正在后台处理", + "data": { + "taskId": "abc123-def456-ghi789", + "status": "PROCESSING", + "message": "导入任务已提交,正在后台处理" + } +} +``` + +**导入流程**: +1. 上传Excel文件 +2. 后台立即返回taskId +3. 使用taskId轮询查询导入状态 +4. 导入完成后查看失败记录(如有) + +**导入验证规则**: + +导入时会验证以下字段: + +| 字段名 | 验证规则 | 错误提示 | +|--------|---------|---------| +| 员工身份证号 | 必须在员工信息表(ccdi_base_staff)中存在 | "第N行: 身份证号[XXX]不存在于员工信息表中,请先添加员工信息" | +| 关系类型 | 不能为空,必须在字典中存在 | "第N行: 关系类型不能为空" | +| 关系人姓名 | 不能为空 | "第N行: 关系人姓名不能为空" | +| 关系人证件类型 | 不能为空 | "第N行: 关系人证件类型不能为空" | +| 关系人证件号码 | 不能为空 | "第N行: 关系人证件号码不能为空" | +| 手机号码1 | 如果填写,必须为有效手机号 | "第N行: 手机号码1格式不正确" | +| 手机号码2 | 如果填写,必须为有效手机号 | "第N行: 手机号码2格式不正确" | +| 性别 | 如果填写,必须是"男"、"女"、"其他"或"M"、"F"、"O" | "第N行: 性别只能是:男、女、其他 或 M、F、O" | + +**性能优化**: +- 采用批量预验证方式,仅1次数据库查询身份证号存在性 +- 批量查询已存在的身份证号+关系人证件号码组合,避免重复导入 + +--- + +### 2. 查询导入状态 + +**接口地址**: `GET /ccdi/staffFmyRelation/importStatus/{taskId}` + +**权限要求**: `ccdi:staffFmyRelation:import` + +**路径参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| taskId | String | 是 | 导入任务ID | + +**响应示例**: +```json +{ + "code": 200, + "msg": "查询成功", + "data": { + "taskId": "abc123-def456-ghi789", + "status": "COMPLETED", + "total": 100, + "successCount": 95, + "failureCount": 5, + "message": "导入完成" + } +} +``` + +**状态说明**: + +| 状态 | 说明 | +|------|------| +| PENDING | 等待处理 | +| PROCESSING | 处理中 | +| SUCCESS | 全部成功 | +| PARTIAL_SUCCESS | 部分成功 | +| FAILED | 处理失败 | + +--- + +### 3. 查询导入失败记录 + +**接口地址**: `GET /ccdi/staffFmyRelation/importFailures/{taskId}` + +**权限要求**: `ccdi:staffFmyRelation:import` + +**路径参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| taskId | String | 是 | 导入任务ID | + +**响应示例**: +```json +{ + "code": 200, + "msg": "查询成功", + "data": [ + { + "personId": "999999999999999999", + "relationType": "父亲", + "relationName": "张三", + "relationCertType": "身份证", + "relationCertNo": "110101195501017890", + "errorMessage": "第2行: 身份证号[999999999999999999]不存在于员工信息表中,请先添加员工信息", + "rowNumber": 2 + } + ] +} +``` + +**失败记录字段说明**: + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| personId | String | 员工身份证号 | +| relationType | String | 关系类型 | +| relationName | String | 关系人姓名 | +| relationCertType | String | 关系人证件类型 | +| relationCertNo | String | 关系人证件号码 | +| errorMessage | String | 错误信息 | +| rowNumber | Integer | Excel行号 | + +--- + +## Excel 模板字段说明 + +| 字段名 | 是否必填 | 说明 | +|--------|---------|------| +| 员工身份证号 | 是 | 必须在员工信息表中存在 | +| 关系类型 | 是 | 下拉选择字典 | +| 关系人姓名 | 是 | 不能为空 | +| 性别 | 否 | 下拉选择字典 | +| 出生日期 | 否 | 日期格式 | +| 关系人证件类型 | 是 | 下拉选择字典 | +| 关系人证件号码 | 是 | 不能为空 | +| 手机号码1 | 否 | 手机号格式 | +| 手机号码2 | 否 | 手机号格式 | +| 微信名称1-3 | 否 | 自由输入 | +| 详细联系地址 | 否 | 自由输入 | +| 关系详细描述 | 否 | 自由输入 | +| 生效日期 | 否 | 日期格式 | +| 失效日期 | 否 | 日期格式 | +| 备注 | 否 | 自由输入 | + +--- + +## 错误码说明 + +| 错误码 | 说明 | +|--------|------| +| 200 | 操作成功 | +| 401 | 未授权 | +| 403 | 无权限 | +| 500 | 服务器错误 | + +--- + +## 更新日志 + +**2026-02-11**: +- 新增员工身份证号存在性校验 +- 优化导入性能,采用批量预验证方式 diff --git a/doc/api-docs/api/员工实体关系导入API文档.md b/doc/api-docs/api/员工实体关系导入API文档.md new file mode 100644 index 0000000..6306b0d --- /dev/null +++ b/doc/api-docs/api/员工实体关系导入API文档.md @@ -0,0 +1,178 @@ +# 员工实体关系导入 API 文档 + +## 概述 + +员工实体关系导入模块提供员工与企业实体关系的批量导入功能。 + +**基础路径**: `/ccdi/staffEnterpriseRelation` + +**权限标识前缀**: `ccdi:staffEnterpriseRelation` + +**数据表**: `ccdi_cust_enterprise_relation` + +**关联表**: +- `ccdi_base_staff` - 员工基础信息表(通过id_card关联) + +--- + +## API 接口 + +### 1. 异步导入员工实体关系 + +**接口地址**: `POST /ccdi/staffEnterpriseRelation/importData` + +**权限要求**: `ccdi:staffEnterpriseRelation:import` + +**请求参数**: FormData + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| file | File | 是 | Excel文件 | +| updateSupport | Boolean | 否 | 是否更新已存在的记录(默认false) | + +**响应示例**: +```json +{ + "code": 200, + "msg": "导入任务已提交,正在后台处理", + "data": { + "taskId": "abc123-def456-ghi789", + "status": "PROCESSING", + "message": "导入任务已提交,正在后台处理" + } +} +``` + +**导入流程**: +1. 上传Excel文件 +2. 后台立即返回taskId +3. 使用taskId轮询查询导入状态 +4. 导入完成后查看失败记录(如有) + +**导入验证规则**: + +导入时会验证以下字段: + +| 字段名 | 验证规则 | 错误提示 | +|--------|---------|---------| +| 身份证号 | 必须在员工信息表(ccdi_base_staff)中存在 | "第N行: 身份证号[XXX]不存在于员工信息表中,请先添加员工信息" | +| 统一社会信用代码 | 必须为18位有效统一社会信用代码 | "第N行: 统一社会信用代码格式不正确" | +| 企业名称 | 不能为空,长度不超过200字符 | "第N行: 企业名称不能为空" 或 "企业名称长度不能超过200个字符" | + +**性能优化**: +- 采用批量预验证方式,仅1次数据库查询身份证号存在性 +- 批量查询已存在的身份证号+统一社会信用代码组合,避免重复导入 + +--- + +### 2. 查询导入状态 + +**接口地址**: `GET /ccdi/staffEnterpriseRelation/importStatus/{taskId}` + +**权限要求**: `ccdi:staffEnterpriseRelation:import` + +**路径参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| taskId | String | 是 | 导入任务ID | + +**响应示例**: +```json +{ + "code": 200, + "msg": "查询成功", + "data": { + "taskId": "abc123-def456-ghi789", + "status": "COMPLETED", + "total": 100, + "successCount": 95, + "failureCount": 5, + "message": "导入完成" + } +} +``` + +**状态说明**: + +| 状态 | 说明 | +|------|------| +| PENDING | 等待处理 | +| PROCESSING | 处理中 | +| SUCCESS | 全部成功 | +| PARTIAL_SUCCESS | 部分成功 | +| FAILED | 处理失败 | + +--- + +### 3. 查询导入失败记录 + +**接口地址**: `GET /ccdi/staffEnterpriseRelation/importFailures/{taskId}` + +**权限要求**: `ccdi:staffEnterpriseRelation:import` + +**路径参数**: + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| taskId | String | 是 | 导入任务ID | + +**响应示例**: +```json +{ + "code": 200, + "msg": "查询成功", + "data": [ + { + "personId": "999999999999999999", + "socialCreditCode": "91110000987654321X", + "enterpriseName": "测试企业", + "relationPersonPost": "总经理", + "errorMessage": "第2行: 身份证号[999999999999999999]不存在于员工信息表中,请先添加员工信息", + "rowNumber": 2 + } + ] +} +``` + +**失败记录字段说明**: + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| personId | String | 身份证号 | +| socialCreditCode | String | 统一社会信用代码 | +| enterpriseName | String | 企业名称 | +| relationPersonPost | String | 关联人在企业的职务 | +| errorMessage | String | 错误信息 | +| rowNumber | Integer | Excel行号 | + +--- + +## Excel 模板字段说明 + +| 字段名 | 是否必填 | 说明 | +|--------|---------|------| +| 身份证号 | 是 | 必须在员工信息表中存在 | +| 统一社会信用代码 | 是 | 18位有效统一社会信用代码 | +| 企业名称 | 是 | 长度不超过200字符 | +| 关联人在企业的职务 | 否 | 长度不超过100字符 | +| 补充说明 | 否 | 备注信息 | + +--- + +## 错误码说明 + +| 错误码 | 说明 | +|--------|------| +| 200 | 操作成功 | +| 401 | 未授权 | +| 403 | 无权限 | +| 500 | 服务器错误 | + +--- + +## 更新日志 + +**2026-02-11**: +- 新增员工身份证号存在性校验 +- 优化导入性能,采用批量预验证方式 diff --git a/doc/api-docs/api/员工调动记录管理API文档.md b/doc/api-docs/api/员工调动记录管理API文档.md index 8f1673d..a14c5a7 100644 --- a/doc/api-docs/api/员工调动记录管理API文档.md +++ b/doc/api-docs/api/员工调动记录管理API文档.md @@ -327,6 +327,21 @@ 3. 使用taskId轮询查询导入状态 4. 导入完成后查看失败记录(如有) +**导入验证规则**: + +导入时会验证以下字段: + +| 字段名 | 验证规则 | 错误提示 | +|--------|---------|---------| +| 员工ID | 必须在员工信息表(ccdi_base_staff)中存在 | "第N行: 员工ID XXX 不存在" | +| 调动前部门ID | 必须在部门表(sys_dept)中存在 | "第N行: 调动前部门ID XXX 不存在" | +| 调动后部门ID | 必须在部门表(sys_dept)中存在 | "第N行: 调动后部门ID XXX 不存在" | +| 调动日期 | 必须符合yyyy-MM-dd格式 | "第N行: 调动日期格式不正确" | + +**性能优化**: +- 采用批量预验证方式,仅1次数据库查询员工ID存在性 +- 从2次遍历优化为1次遍历,提升导入性能 + --- ### 9. 查询导入状态