diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiBaseStaffImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiBaseStaffImportServiceImpl.java index e99c97a..2a8f968 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiBaseStaffImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiBaseStaffImportServiceImpl.java @@ -10,9 +10,12 @@ import com.ruoyi.ccdi.domain.vo.ImportResult; import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.mapper.CcdiBaseStaffMapper; import com.ruoyi.ccdi.service.ICcdiBaseStaffImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.IdCardUtil; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -31,6 +34,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiBaseStaffImportServiceImpl.class); + @Resource private CcdiBaseStaffMapper baseStaffMapper; @@ -40,13 +45,21 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi @Override @Async public void importBaseStaffAsync(List excelList, Boolean isUpdateSupport, String taskId) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "员工基础信息", excelList.size(), "系统"); + List newRecords = new ArrayList<>(); List updateRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的员工ID和身份证号 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工ID", excelList.size()); Set existingIds = getExistingStaffIds(excelList); Set existingIdCards = getExistingIdCards(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "员工ID", existingIds.size()); + ImportLogUtils.logBatchQueryComplete(log, taskId, "身份证号", existingIdCards.size()); // 用于跟踪Excel文件内已处理的主键 Set processedStaffIds = new HashSet<>(); @@ -99,28 +112,46 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi processedIdCards.add(excel.getIdCard()); } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size() + updateRecords.size(), failures.size()); + } catch (Exception e) { ImportFailureVO failure = new ImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("员工ID=%s, 姓名=%s, 身份证号=%s", + excel.getStaffId(), excel.getName(), excel.getIdCard()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 批量更新已有数据(先删除再插入) if (!updateRecords.isEmpty() && isUpdateSupport) { + ImportLogUtils.logBatchOperationStart(log, taskId, "更新", + (updateRecords.size() + 499) / 500, 500); baseStaffMapper.insertOrUpdateBatch(updateRecords); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:baseStaff:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:baseStaff:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -131,6 +162,11 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus("baseStaff", taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "员工基础信息", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } /** diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryEntityImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryEntityImportServiceImpl.java index 28900b7..9289c95 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryEntityImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryEntityImportServiceImpl.java @@ -9,8 +9,11 @@ import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.IntermediaryEntityImportFailureVO; import com.ruoyi.ccdi.mapper.CcdiEnterpriseBaseInfoMapper; import com.ruoyi.ccdi.service.ICcdiIntermediaryEntityImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -32,6 +35,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediaryEntityImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiIntermediaryEntityImportServiceImpl.class); + @Resource private CcdiEnterpriseBaseInfoMapper entityMapper; @@ -44,11 +49,18 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar public void importEntityAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "实体中介", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的统一社会信用代码 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的统一社会信用代码", excelList.size()); Set existingCreditCodes = getExistingCreditCodes(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "统一社会信用代码", existingCreditCodes.size()); // 用于检测Excel内部的重复ID Set excelProcessedIds = new HashSet<>(); @@ -81,20 +93,36 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar excelProcessedIds.add(excel.getSocialCreditCode()); // 标记为已处理 } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { failures.add(createFailureVO(excel, e.getMessage())); + + // 记录验证失败日志 + String keyData = String.format("机构名称=%s, 统一社会信用代码=%s", + excel.getEnterpriseName(), excel.getSocialCreditCode()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:intermediary-entity:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:intermediary-entity:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -105,6 +133,11 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "实体中介", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } @Override diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryPersonImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryPersonImportServiceImpl.java index 7f3b1e2..d403fc1 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryPersonImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryPersonImportServiceImpl.java @@ -9,9 +9,12 @@ import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.IntermediaryPersonImportFailureVO; import com.ruoyi.ccdi.mapper.CcdiBizIntermediaryMapper; import com.ruoyi.ccdi.service.ICcdiIntermediaryPersonImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.IdCardUtil; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -33,6 +36,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediaryPersonImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiIntermediaryPersonImportServiceImpl.class); + @Resource private CcdiBizIntermediaryMapper intermediaryMapper; @@ -45,11 +50,18 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar public void importPersonAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "个人中介", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的证件号 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的证件号", excelList.size()); Set existingPersonIds = getExistingPersonIds(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "证件号", existingPersonIds.size()); // 用于检测Excel内部的重复ID Set excelProcessedIds = new HashSet<>(); @@ -81,20 +93,36 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar excelProcessedIds.add(excel.getPersonId()); // 标记为已处理 } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { failures.add(createFailureVO(excel, e.getMessage())); + + // 记录验证失败日志 + String keyData = String.format("姓名=%s, 证件号码=%s", + excel.getName(), excel.getPersonId()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:intermediary:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:intermediary:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -105,6 +133,11 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "个人中介", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } @Override diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java index 6bf1b82..756568b 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java @@ -9,8 +9,11 @@ import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.PurchaseTransactionImportFailureVO; import com.ruoyi.ccdi.mapper.CcdiPurchaseTransactionMapper; import com.ruoyi.ccdi.service.ICcdiPurchaseTransactionImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -33,6 +36,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTransactionImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiPurchaseTransactionImportServiceImpl.class); + @Resource private CcdiPurchaseTransactionMapper transactionMapper; @@ -43,11 +48,18 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr @Async @Transactional public void importTransactionAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "采购交易信息", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的采购事项ID + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的采购事项ID", excelList.size()); Set existingIds = getExistingPurchaseIds(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "采购事项ID", existingIds.size()); // 用于跟踪Excel文件内已处理的采购事项ID Set processedIds = new HashSet<>(); @@ -80,23 +92,39 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr processedIds.add(excel.getPurchaseId()); // 标记为已处理 } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { PurchaseTransactionImportFailureVO failure = new PurchaseTransactionImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("采购事项ID=%s, 采购类别=%s, 标的物=%s", + excel.getPurchaseId(), excel.getPurchaseCategory(), excel.getSubjectName()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:purchaseTransaction:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:purchaseTransaction:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -107,6 +135,11 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "采购交易信息", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } /** 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 9ccfc4d..a2f06f8 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 @@ -9,8 +9,11 @@ import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.StaffEnterpriseRelationImportFailureVO; import com.ruoyi.ccdi.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.ccdi.service.ICcdiStaffEnterpriseRelationImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -32,6 +35,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffEnterpriseRelationImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiStaffEnterpriseRelationImportServiceImpl.class); + @Resource private CcdiStaffEnterpriseRelationMapper relationMapper; @@ -42,11 +47,18 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE @Async @Transactional public void importRelationAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "员工实体关系", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的person_id + social_credit_code组合 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工企业关系组合", excelList.size()); Set existingCombinations = getExistingCombinations(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "员工企业关系组合", existingCombinations.size()); // 用于跟踪Excel文件内已处理的组合 Set processedCombinations = new HashSet<>(); @@ -92,23 +104,39 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE processedCombinations.add(combination); // 标记为已处理 } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { StaffEnterpriseRelationImportFailureVO failure = new StaffEnterpriseRelationImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("身份证号=%s, 统一社会信用代码=%s, 企业名称=%s", + excel.getPersonId(), excel.getSocialCreditCode(), excel.getEnterpriseName()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:staffEnterpriseRelation:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:staffEnterpriseRelation:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -119,6 +147,11 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "员工实体关系", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } /** 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 2127687..2e1eb40 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 @@ -10,8 +10,11 @@ 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.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -32,6 +35,8 @@ import java.util.concurrent.TimeUnit; @EnableAsync public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelationImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiStaffFmyRelationImportServiceImpl.class); + @Resource private CcdiStaffFmyRelationMapper relationMapper; @@ -42,6 +47,11 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat @Async @Transactional public void importRelationAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "员工亲属关系", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); @@ -61,6 +71,7 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat // 2. 批量查询数据库中已存在的记录 Set existingKeys = new HashSet<>(); if (!excelPersonIds.isEmpty() && !excelRelationCertNos.isEmpty()) { + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的亲属关系", excelList.size()); List existingRecords = relationMapper.selectExistingRelations( new ArrayList<>(excelPersonIds), new ArrayList<>(excelRelationCertNos) @@ -71,6 +82,7 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat String key = existing.getPersonId() + "|" + existing.getRelationCertNo(); existingKeys.add(key); } + ImportLogUtils.logBatchQueryComplete(log, taskId, "亲属关系", existingKeys.size()); } // ========== 第二步:处理数据 ========== @@ -116,23 +128,39 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat newRecords.add(relation); processedKeys.add(uniqueKey); + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { StaffFmyRelationImportFailureVO failure = new StaffFmyRelationImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("员工身份证号=%s, 关系人=%s(%s)", + excel.getPersonId(), excel.getRelationName(), excel.getRelationCertNo()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:staffFmyRelation:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:staffFmyRelation:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -143,6 +171,11 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "员工亲属关系", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } /** diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffRecruitmentImportServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffRecruitmentImportServiceImpl.java index 1911e4d..cc3b307 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffRecruitmentImportServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffRecruitmentImportServiceImpl.java @@ -11,9 +11,12 @@ import com.ruoyi.ccdi.domain.vo.RecruitmentImportFailureVO; import com.ruoyi.ccdi.enums.AdmitStatus; import com.ruoyi.ccdi.mapper.CcdiStaffRecruitmentMapper; import com.ruoyi.ccdi.service.ICcdiStaffRecruitmentImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.utils.IdCardUtil; import com.ruoyi.common.utils.StringUtils; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -35,6 +38,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitmentImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiStaffRecruitmentImportServiceImpl.class); + @Resource private CcdiStaffRecruitmentMapper recruitmentMapper; @@ -47,11 +52,18 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm public void importRecruitmentAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "招聘信息", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的招聘项目编号 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的招聘项目编号", excelList.size()); Set existingRecruitIds = getExistingRecruitIds(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "招聘项目编号", existingRecruitIds.size()); // 用于检测Excel内部的重复ID Set excelProcessedIds = new HashSet<>(); @@ -84,23 +96,39 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm excelProcessedIds.add(excel.getRecruitId()); // 标记为已处理 } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { RecruitmentImportFailureVO failure = new RecruitmentImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("招聘项目编号=%s, 项目名称=%s, 应聘人员=%s", + excel.getRecruitId(), excel.getRecruitName(), excel.getCandName()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:recruitment:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:recruitment:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -111,6 +139,11 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "招聘信息", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } @Override 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 b55b94e..73adc72 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 @@ -10,11 +10,14 @@ import com.ruoyi.ccdi.domain.vo.ImportStatusVO; import com.ruoyi.ccdi.domain.vo.StaffTransferImportFailureVO; import com.ruoyi.ccdi.mapper.CcdiStaffTransferMapper; import com.ruoyi.ccdi.service.ICcdiStaffTransferImportService; +import com.ruoyi.ccdi.utils.ImportLogUtils; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.mapper.SysDeptMapper; import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; @@ -36,6 +39,8 @@ import java.util.stream.Collectors; @EnableAsync public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImportService { + private static final Logger log = LoggerFactory.getLogger(CcdiStaffTransferImportServiceImpl.class); + @Resource private CcdiStaffTransferMapper transferMapper; @@ -49,11 +54,18 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp @Async @Transactional public void importTransferAsync(List excelList, String taskId, String userName) { + long startTime = System.currentTimeMillis(); + + // 记录导入开始 + ImportLogUtils.logImportStart(log, taskId, "员工调动记录", excelList.size(), userName); + List newRecords = new ArrayList<>(); List failures = new ArrayList<>(); // 批量查询已存在的唯一键组合 + ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的调动记录", excelList.size()); Set existingKeys = getExistingTransferKeys(excelList); + ImportLogUtils.logBatchQueryComplete(log, taskId, "调动记录", existingKeys.size()); // 用于检测Excel内部的重复键 Set excelProcessedKeys = new HashSet<>(); @@ -98,23 +110,40 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp excelProcessedKeys.add(uniqueKey); } + // 记录进度 + ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(), + newRecords.size(), failures.size()); + } catch (Exception e) { StaffTransferImportFailureVO failure = new StaffTransferImportFailureVO(); BeanUtils.copyProperties(excel, failure); failure.setErrorMessage(e.getMessage()); failures.add(failure); + + // 记录验证失败日志 + String keyData = String.format("员工ID=%s, 调动类型=%s, 调动日期=%s, 调动前部门ID=%s, 调动后部门ID=%s", + excel.getStaffId(), excel.getTransferType(), excel.getTransferDate(), + excel.getDeptIdBefore(), excel.getDeptIdAfter()); + ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData); } } // 批量插入新数据 if (!newRecords.isEmpty()) { + ImportLogUtils.logBatchOperationStart(log, taskId, "插入", + (newRecords.size() + 499) / 500, 500); saveBatch(newRecords, 500); } // 保存失败记录到Redis if (!failures.isEmpty()) { - String failuresKey = "import:staffTransfer:" + taskId + ":failures"; - redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + try { + String failuresKey = "import:staffTransfer:" + taskId + ":failures"; + redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS); + ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size()); + } catch (Exception e) { + ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e); + } } ImportResult result = new ImportResult(); @@ -125,6 +154,11 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp // 更新最终状态 String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; updateImportStatus(taskId, finalStatus, result); + + // 记录导入完成 + long duration = System.currentTimeMillis() - startTime; + ImportLogUtils.logImportComplete(log, taskId, "员工调动记录", + excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); } /** diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/utils/ImportLogUtils.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/utils/ImportLogUtils.java new file mode 100644 index 0000000..2c725b5 --- /dev/null +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/utils/ImportLogUtils.java @@ -0,0 +1,248 @@ +package com.ruoyi.ccdi.utils; + +import org.slf4j.Logger; + +/** + * 导入日志工具类 + * 提供统一的日志格式和进度计算 + * + * @author ruoyi + * @date 2026-02-11 + */ +public class ImportLogUtils { + + /** + * 记录导入开始 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param moduleName 模块名称 + * @param totalCount 总数据量 + * @param userName 操作人 + */ + public static void logImportStart(Logger log, String taskId, String moduleName, + int totalCount, String userName) { + log.info("[任务ID: {}] 开始异步导入{},数据量: {}条,操作人: {}", + taskId, moduleName, totalCount, userName); + } + + /** + * 记录批量查询开始 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param queryDesc 查询描述 + * @param queryCount 查询数量 + */ + public static void logBatchQueryStart(Logger log, String taskId, String queryDesc, int queryCount) { + log.info("[任务ID: {}] 批量查询{},查询数量: {}个", taskId, queryDesc, queryCount); + } + + /** + * 记录批量查询完成 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param queryDesc 查询描述 + * @param existingCount 已存在数量 + */ + public static void logBatchQueryComplete(Logger log, String taskId, String queryDesc, int existingCount) { + log.info("[任务ID: {}] 查询完成,已存在{}条", taskId, queryDesc, existingCount); + } + + /** + * 记录进度(智能判断是否需要输出) + * 每100条或每10%输出一次 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param current 当前处理数 + * @param total 总数 + * @param success 成功数 + * @param failure 失败数 + */ + public static void logProgress(Logger log, String taskId, int current, int total, + int success, int failure) { + if (current <= 0) { + return; + } + + // 每100条或每10%输出一次进度 + boolean shouldLog = (current % 100 == 0) || + (current * 10 / total > (current - 1) * 10 / total) || + (current == total); + + if (shouldLog) { + int progress = current * 100 / total; + log.info("[任务ID: {}] 数据处理进度: {}/{} ({}%), 成功: {}条, 失败: {}条", + taskId, current, total, progress, success, failure); + } + } + + /** + * 记录数据验证失败 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param rowNum 行号 + * @param errorMsg 错误消息 + * @param keyData 关键数据(可为null) + */ + public static void logValidationError(Logger log, String taskId, int rowNum, + String errorMsg, String keyData) { + log.warn("[任务ID: {}] [第{}行] 数据验证失败: {}", taskId, rowNum, errorMsg); + if (keyData != null && !keyData.isEmpty()) { + log.warn("[任务ID: {}] 失败数据详情: {}", taskId, keyData); + } + } + + /** + * 记录批量操作开始 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param operation 操作描述 + * @param totalBatch 总批次数 + * @param batchSize 每批大小 + */ + public static void logBatchOperationStart(Logger log, String taskId, String operation, + int totalBatch, int batchSize) { + log.info("[任务ID: {}] 开始批量{},总批次: {}, 每批: {}条", + taskId, operation, totalBatch, batchSize); + } + + /** + * 记录单个批次操作 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param operation 操作描述 + * @param batchNum 当前批次号 + * @param totalBatch 总批次数 + * @param batchSize 本批数量 + */ + public static void logBatchOperation(Logger log, String taskId, String operation, + int batchNum, int totalBatch, int batchSize) { + log.info("[任务ID: {}] 执行批次 {}/{}, 本批数量: {}条", + taskId, batchNum, totalBatch, batchSize); + } + + /** + * 记录单个批次完成 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param operation 操作描述 + * @param batchNum 当前批次号 + * @param totalBatch 总批次数 + * @param success 成功数量 + */ + public static void logBatchComplete(Logger log, String taskId, String operation, + int batchNum, int totalBatch, int success) { + log.info("[任务ID: {}] 批次 {}/{} {}完成,成功: {}条", + taskId, batchNum, totalBatch, operation, success); + } + + /** + * 记录Redis缓存操作 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param operation 操作描述(如"保存失败记录") + * @param count 数量 + */ + public static void logRedisOperation(Logger log, String taskId, String operation, int count) { + log.debug("[任务ID: {}] {}到Redis,数量: {}条", taskId, operation, count); + } + + /** + * 记录Redis缓存异常 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param operation 操作描述 + * @param e 异常 + */ + public static void logRedisError(Logger log, String taskId, String operation, Exception e) { + log.error("[任务ID: {}] {}到Redis失败,不影响导入结果", taskId, operation, e); + } + + /** + * 记录导入完成 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param moduleName 模块名称 + * @param total 总数 + * @param success 成功数 + * @param failure 失败数 + * @param duration 耗时(毫秒) + */ + public static void logImportComplete(Logger log, String taskId, String moduleName, + int total, int success, int failure, long duration) { + log.info("[任务ID: {}] {}导入完成!总数: {}条, 成功: {}条, 失败: {}条, 耗时: {}ms", + taskId, moduleName, total, success, failure, duration); + + // 如果有失败,记录失败汇总 + if (failure > 0) { + log.warn("[任务ID: {}] 导入完成,但有{}条数据失败,请查看失败记录详情", taskId, failure); + } + } + + /** + * 记录异常 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param errorMsg 错误描述 + * @param e 异常 + */ + public static void logException(Logger log, String taskId, String errorMsg, Exception e) { + log.error("[任务ID: {}] {}", taskId, errorMsg, e); + } + + /** + * 记录事务回滚 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param processed 已处理数量 + * @param total 总数量 + * @param success 成功数量 + * @param failure 失败数量 + * @param e 异常 + */ + public static void logTransactionRollback(Logger log, String taskId, int processed, + int total, int success, int failure, Exception e) { + log.error("[任务ID: {}] 导入失败,事务已回滚。已处理: {}/{}条", taskId, processed, total, e); + log.error("[任务ID: {}] 回滚前统计 - 新增: {}条, 失败: {}条", taskId, success, failure); + } + + /** + * 记录唯一性冲突 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param rowNum 行号 + * @param conflictDesc 冲突描述 + */ + public static void logUniqueConflict(Logger log, String taskId, int rowNum, String conflictDesc) { + log.warn("[任务ID: {}] [第{}行] {}", taskId, rowNum, conflictDesc); + } + + /** + * 记录失败原因统计 + * + * @param log 日志记录器 + * @param taskId 任务ID + * @param errorStats 错误统计Map + */ + public static void logErrorStatistics(Logger log, String taskId, java.util.Map errorStats) { + if (errorStats != null && !errorStats.isEmpty()) { + String statsStr = errorStats.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue() + "条") + .collect(java.util.stream.Collectors.joining(", ")); + log.warn("[任务ID: {}] 失败原因统计: {}", taskId, statsStr); + } + } +}