From 423d03f416341fbaf559c61b9c17b9e14e17b5f3 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Tue, 11 Aug 2026 14:41:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=91=98=E5=B7=A5=E4=BF=A1=E6=81=AF=E7=AE=A1?= =?UTF-8?q?=E7=90=86,=20=E9=A1=B5=E9=9D=A2=E6=9F=A5=E8=AF=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/executor/OrgPersonnelExecutor.java | 47 +-- .../app/support/OrgPersonnelViewEnricher.java | 369 +++++++++++++++--- 2 files changed, 321 insertions(+), 95 deletions(-) diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/OrgPersonnelExecutor.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/OrgPersonnelExecutor.java index cfd32413..4f6abbab 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/OrgPersonnelExecutor.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/OrgPersonnelExecutor.java @@ -241,14 +241,11 @@ public class OrgPersonnelExecutor implements OrgPersonnelApi { PageResult pageResult = orgPersonnelDomainService.page(domainQuery); List records = pageResult.getRecords().stream() - .map(entity -> { - OrgPersonnelCO co = orgPersonnelConvertor.toCO(entity); - enrich(co); - return co; - }) + .map(orgPersonnelConvertor::toCO) .collect(java.util.stream.Collectors.toList()); - - fillCertsBatch(records); + if (orgPersonnelViewEnricher != null) { + orgPersonnelViewEnricher.enrichPersonnelBatch(records); + } return PageResponse.of(records, pageResult.getTotal()); } @@ -398,42 +395,6 @@ public class OrgPersonnelExecutor implements OrgPersonnelApi { } } - /** - * 批量查询证书并填充到CO列表中,一次查询后按人员分组分别设置注安证书和评价师证书 - */ - private void fillCertsBatch(List records) { - if (orgPersonnelCertDomainService == null || CollectionUtils.isEmpty(records)) { - return; - } - List personnelIds = records.stream() - .map(OrgPersonnelCO::getId) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - if (CollectionUtils.isEmpty(personnelIds)) { - return; - } - List certs = orgPersonnelCertDomainService.listByPersonnelIds(personnelIds); - if (CollectionUtils.isEmpty(certs)) { - return; - } - Map> certMap = certs.stream() - .collect(Collectors.groupingBy(OrgPersonnelCertEntity::getPersonnelId)); - for (OrgPersonnelCO co : records) { - List personCerts = certMap.get(co.getId()); - if (CollectionUtils.isEmpty(personCerts)) { - continue; - } - for (OrgPersonnelCertEntity cert : personCerts) { - OrgPersonnelCertCO certCO = orgPersonnelCertConvertor.entityToCO(cert); - if (CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER.getCode().equals(cert.getCertTypeCode())) { - co.setRegisteredSafetyEngineerCert(certCO); - } else if (CertTypeCodeEnum.EVALUATOR.getCode().equals(cert.getCertTypeCode())) { - co.setEvaluatorCert(certCO); - } - } - } - } - @Override public SingleResponse updateOriginFace(OrgPersonnelUpdateOriginFaceCmd cmd) { OrgPersonnelEntity existing = orgPersonnelDomainService.get(cmd.getId()); diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelViewEnricher.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelViewEnricher.java index 61b8c06a..52a64a4a 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelViewEnricher.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/support/OrgPersonnelViewEnricher.java @@ -1,25 +1,39 @@ package org.qinan.safetyeval.app.support; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.qinan.safetyeval.client.co.OrgPersonnelCO; +import org.qinan.safetyeval.client.co.OrgPersonnelCertCO; import org.qinan.safetyeval.client.co.OrgResignApplyCO; +import org.qinan.safetyeval.domain.constant.CertTypeCodeEnum; +import org.qinan.safetyeval.domain.constant.basic.IndustryEnum; +import org.qinan.safetyeval.domain.constant.basic.ProfessionalCapabilityEnum; import org.qinan.safetyeval.domain.entity.*; import org.qinan.safetyeval.domain.gateway.*; import org.qinan.safetyeval.domain.major.gateway.BasicDisciplineMajorGateway; import org.qinan.safetyeval.domain.major.model.BasicDisciplineMajorE; import org.qinan.safetyeval.domain.query.OrgPersonnelCertQuery; import org.qinan.safetyeval.domain.query.PageResult; -import org.qinan.safetyeval.domain.constant.basic.IndustryEnum; -import org.qinan.safetyeval.domain.constant.basic.ProfessionalCapabilityEnum; import org.qinan.safetyeval.domain.standards.gateway.IndustryProfessionalStandardsGateway; import org.qinan.safetyeval.domain.standards.model.IndustryProfessionalStandardsE; +import org.qinan.safetyeval.infrastructure.convertor.OrgPersonnelCertConvertor; +import org.qinan.safetyeval.infrastructure.dataobject.OrgDepartmentDO; +import org.qinan.safetyeval.infrastructure.dataobject.OrgPersonnelChangeDO; +import org.qinan.safetyeval.infrastructure.dataobject.OrgPositionDO; +import org.qinan.safetyeval.infrastructure.dataobject.OrgResignApplyDO; +import org.qinan.safetyeval.infrastructure.mapper.OrgDepartmentMapper; +import org.qinan.safetyeval.infrastructure.mapper.OrgPersonnelChangeMapper; +import org.qinan.safetyeval.infrastructure.mapper.OrgPositionMapper; +import org.qinan.safetyeval.infrastructure.mapper.OrgResignApplyMapper; +import org.qinan.safetyeval.infrastructure.persistence.domainobject.BasicDisciplineMajorDO; +import org.qinan.safetyeval.infrastructure.persistence.domainobject.IndustryProfessionalStandardsDO; +import org.qinan.safetyeval.infrastructure.persistence.mapper.BasicDisciplineMajorMapper; +import org.qinan.safetyeval.infrastructure.persistence.mapper.IndustryProfessionalStandardsMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; /** @@ -28,6 +42,8 @@ import java.util.stream.Collectors; @Component public class OrgPersonnelViewEnricher { + private static final int CERT_DISPLAY_LIMIT = 200; + @Autowired(required = false) private OrgDepartmentGateway orgDepartmentGateway; @@ -52,6 +68,27 @@ public class OrgPersonnelViewEnricher { @Autowired(required = false) private IndustryProfessionalStandardsGateway industryProfessionalStandardsGateway; + @Autowired(required = false) + private OrgDepartmentMapper orgDepartmentMapper; + + @Autowired(required = false) + private OrgPositionMapper orgPositionMapper; + + @Autowired(required = false) + private BasicDisciplineMajorMapper basicDisciplineMajorMapper; + + @Autowired(required = false) + private OrgPersonnelChangeMapper orgPersonnelChangeMapper; + + @Autowired(required = false) + private OrgResignApplyMapper orgResignApplyMapper; + + @Autowired(required = false) + private IndustryProfessionalStandardsMapper industryProfessionalStandardsMapper; + + @Autowired(required = false) + private OrgPersonnelCertConvertor orgPersonnelCertConvertor; + public void enrichPersonnel(OrgPersonnelCO co) { if (co == null) { return; @@ -77,57 +114,274 @@ public class OrgPersonnelViewEnricher { OrgPersonnelCertQuery certQuery = new OrgPersonnelCertQuery(); certQuery.setPersonnelId(co.getId()); certQuery.setPageNum(1L); - certQuery.setPageSize(200L); + certQuery.setPageSize((long) CERT_DISPLAY_LIMIT); PageResult certPage = orgPersonnelCertGateway.page(certQuery); - String certNames = certPage.getRecords().stream() - .map(OrgPersonnelCertEntity::getCertName) - .filter(StringUtils::hasText) - .collect(Collectors.joining("、")); - co.setCertNames(certNames); - // 构建能力汇总: "专业范围:专业能力;专业范围:专业能力" - // 当 professionalCapabilityCode 为空时,尝试通过 industryProfessionalStandardsId 查标准表获取 - List records = certPage.getRecords(); - Map standardsCodeCache = new HashMap<>(); - if (industryProfessionalStandardsGateway != null) { - records.stream() - .filter(c -> !StringUtils.hasText(c.getProfessionalCapabilityCode()) - && c.getIndustryProfessionalStandardsId() != null) - .map(OrgPersonnelCertEntity::getIndustryProfessionalStandardsId) - .distinct() - .forEach(sid -> { - IndustryProfessionalStandardsE standards = industryProfessionalStandardsGateway.getById(sid); - if (standards != null && StringUtils.hasText(standards.getProfessionalCapabilityCode())) { - standardsCodeCache.put(sid, standards.getProfessionalCapabilityCode()); - } - }); - } - String abilityNames = records.stream() - .filter(c -> StringUtils.hasText(c.getBusinessScope())) - .map(c -> { - String code = c.getProfessionalCapabilityCode(); - if (!StringUtils.hasText(code) && standardsCodeCache.containsKey(c.getIndustryProfessionalStandardsId())) { - code = standardsCodeCache.get(c.getIndustryProfessionalStandardsId()); - } - if (!StringUtils.hasText(code)) { - return null; - } - // 转换 code 为中文名称 - IndustryEnum industryEnum = IndustryEnum.ofCode(c.getBusinessScope()); - String scopeName = industryEnum != null ? industryEnum.getValue() : c.getBusinessScope(); - ProfessionalCapabilityEnum capEnum = ProfessionalCapabilityEnum.ofCode(code); - String capName = capEnum != null ? capEnum.getValue() : code; - return scopeName + ":" + capName; - }) - .filter(Objects::nonNull) - .collect(Collectors.joining(";")); - co.setAbilityNames(abilityNames); + applyCertDisplayFields(co, certPage.getRecords()); } enrichChangeSummary(co); } - if (co.getEmploymentStatusCode() == null) { - co.setEmploymentStatusCode(1); - co.setEmploymentStatusName("在职"); + applyEmploymentDefault(co); + } + + /** + * 分页列表批量 enrich,结果与逐条 {@link #enrichPersonnel(OrgPersonnelCO)} + 证书批量填充等价。 + */ + public void enrichPersonnelBatch(List records) { + if (CollectionUtils.isEmpty(records)) { + return; } + + Set deptIds = new HashSet<>(); + Set postIds = new HashSet<>(); + Set majorIds = new HashSet<>(); + List personnelIds = new ArrayList<>(); + for (OrgPersonnelCO co : records) { + if (co == null) { + continue; + } + if (co.getDeptId() != null) { + deptIds.add(co.getDeptId()); + } + if (co.getPostId() != null) { + postIds.add(co.getPostId()); + } + if (co.getBasicDisciplineMajorId() != null) { + majorIds.add(co.getBasicDisciplineMajorId()); + } + if (co.getId() != null) { + personnelIds.add(co.getId()); + } + } + + Map deptNameMap = loadDeptNameMap(deptIds); + Map postNameMap = loadPostNameMap(postIds); + Map majorNameMap = loadMajorNameMap(majorIds); + Map> certMap = loadCertMap(personnelIds); + Map changeCountMap = loadChangeCountMap(personnelIds); + Map> resignMap = loadResignMap(personnelIds); + Map standardsCodeCache = buildStandardsCodeCacheBatch(certMap.values().stream() + .flatMap(Collection::stream) + .collect(Collectors.toList())); + + for (OrgPersonnelCO co : records) { + if (co == null) { + continue; + } + if (co.getDeptId() != null) { + co.setDeptName(deptNameMap.get(co.getDeptId())); + } + if (co.getPostId() != null) { + co.setPostName(postNameMap.get(co.getPostId())); + } + if (co.getBasicDisciplineMajorId() != null) { + co.setBasicDisciplineMajorName(majorNameMap.get(co.getBasicDisciplineMajorId())); + } + if (co.getId() != null) { + List personCerts = certMap.getOrDefault(co.getId(), Collections.emptyList()); + applyCertDisplayFields(co, limitCertsForDisplay(personCerts), standardsCodeCache); + applyNestedCerts(co, personCerts); + co.setChangeCount(changeCountMap.getOrDefault(co.getId(), 0)); + applyResignDisplay(co, resignMap.get(co.getId())); + } + applyEmploymentDefault(co); + } + } + + private void applyCertDisplayFields(OrgPersonnelCO co, List records) { + applyCertDisplayFields(co, records, null); + } + + private void applyCertDisplayFields(OrgPersonnelCO co, List records, + Map standardsCodeCache) { + if (CollectionUtils.isEmpty(records)) { + co.setCertNames(""); + co.setAbilityNames(""); + return; + } + co.setCertNames(buildCertNames(records)); + if (standardsCodeCache == null) { + standardsCodeCache = buildStandardsCodeCache(records); + } + co.setAbilityNames(buildAbilityNames(records, standardsCodeCache)); + } + + private List limitCertsForDisplay(List certs) { + if (CollectionUtils.isEmpty(certs)) { + return Collections.emptyList(); + } + if (certs.size() <= CERT_DISPLAY_LIMIT) { + return certs; + } + return new ArrayList<>(certs.subList(0, CERT_DISPLAY_LIMIT)); + } + + private String buildCertNames(List records) { + return records.stream() + .map(OrgPersonnelCertEntity::getCertName) + .filter(StringUtils::hasText) + .collect(Collectors.joining("、")); + } + + private Map buildStandardsCodeCache(List records) { + Map standardsCodeCache = new HashMap<>(); + if (industryProfessionalStandardsGateway == null) { + return standardsCodeCache; + } + records.stream() + .filter(c -> !StringUtils.hasText(c.getProfessionalCapabilityCode()) + && c.getIndustryProfessionalStandardsId() != null) + .map(OrgPersonnelCertEntity::getIndustryProfessionalStandardsId) + .distinct() + .forEach(sid -> { + IndustryProfessionalStandardsE standards = industryProfessionalStandardsGateway.getById(sid); + if (standards != null && StringUtils.hasText(standards.getProfessionalCapabilityCode())) { + standardsCodeCache.put(sid, standards.getProfessionalCapabilityCode()); + } + }); + return standardsCodeCache; + } + + private String buildAbilityNames(List records, Map standardsCodeCache) { + return records.stream() + .filter(c -> StringUtils.hasText(c.getBusinessScope())) + .map(c -> { + String code = c.getProfessionalCapabilityCode(); + if (!StringUtils.hasText(code) && standardsCodeCache.containsKey(c.getIndustryProfessionalStandardsId())) { + code = standardsCodeCache.get(c.getIndustryProfessionalStandardsId()); + } + if (!StringUtils.hasText(code)) { + return null; + } + IndustryEnum industryEnum = IndustryEnum.ofCode(c.getBusinessScope()); + String scopeName = industryEnum != null ? industryEnum.getValue() : c.getBusinessScope(); + ProfessionalCapabilityEnum capEnum = ProfessionalCapabilityEnum.ofCode(code); + String capName = capEnum != null ? capEnum.getValue() : code; + return scopeName + ":" + capName; + }) + .filter(Objects::nonNull) + .collect(Collectors.joining(";")); + } + + private void applyNestedCerts(OrgPersonnelCO co, List personCerts) { + if (orgPersonnelCertConvertor == null || CollectionUtils.isEmpty(personCerts)) { + return; + } + for (OrgPersonnelCertEntity cert : personCerts) { + OrgPersonnelCertCO certCO = orgPersonnelCertConvertor.entityToCO(cert); + if (CertTypeCodeEnum.REGISTERED_SAFETY_ENGINEER.getCode().equals(cert.getCertTypeCode())) { + co.setRegisteredSafetyEngineerCert(certCO); + } else if (CertTypeCodeEnum.EVALUATOR.getCode().equals(cert.getCertTypeCode())) { + co.setEvaluatorCert(certCO); + } + } + } + + private Map loadDeptNameMap(Set deptIds) { + if (CollectionUtils.isEmpty(deptIds) || orgDepartmentMapper == null) { + return Collections.emptyMap(); + } + return orgDepartmentMapper.selectBatchIds(deptIds).stream() + .filter(Objects::nonNull) + .collect(Collectors.toMap(OrgDepartmentDO::getId, OrgDepartmentDO::getDeptName, (a, b) -> a)); + } + + private Map loadPostNameMap(Set postIds) { + if (CollectionUtils.isEmpty(postIds) || orgPositionMapper == null) { + return Collections.emptyMap(); + } + return orgPositionMapper.selectBatchIds(postIds).stream() + .filter(Objects::nonNull) + .collect(Collectors.toMap(OrgPositionDO::getId, OrgPositionDO::getPositionName, (a, b) -> a)); + } + + private Map loadMajorNameMap(Set majorIds) { + if (CollectionUtils.isEmpty(majorIds) || basicDisciplineMajorMapper == null) { + return Collections.emptyMap(); + } + return basicDisciplineMajorMapper.selectBatchIds(majorIds).stream() + .filter(Objects::nonNull) + .collect(Collectors.toMap(BasicDisciplineMajorDO::getId, BasicDisciplineMajorDO::getProfessionalName, (a, b) -> a)); + } + + private Map> loadCertMap(List personnelIds) { + if (CollectionUtils.isEmpty(personnelIds) || orgPersonnelCertGateway == null) { + return Collections.emptyMap(); + } + List certs = orgPersonnelCertGateway.listByPersonnelIds(personnelIds); + if (CollectionUtils.isEmpty(certs)) { + return Collections.emptyMap(); + } + return certs.stream().collect(Collectors.groupingBy(OrgPersonnelCertEntity::getPersonnelId)); + } + + private Map loadChangeCountMap(List personnelIds) { + if (CollectionUtils.isEmpty(personnelIds) || orgPersonnelChangeMapper == null) { + return Collections.emptyMap(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(OrgPersonnelChangeDO::getPersonnelId); + wrapper.in(OrgPersonnelChangeDO::getPersonnelId, personnelIds); + wrapper.eq(OrgPersonnelChangeDO::getDeleteEnum, "false"); + List changes = orgPersonnelChangeMapper.selectList(wrapper); + if (CollectionUtils.isEmpty(changes)) { + return Collections.emptyMap(); + } + return changes.stream() + .collect(Collectors.groupingBy(OrgPersonnelChangeDO::getPersonnelId, + Collectors.collectingAndThen(Collectors.counting(), Long::intValue))); + } + + private Map> loadResignMap(List personnelIds) { + if (CollectionUtils.isEmpty(personnelIds) || orgResignApplyMapper == null) { + return Collections.emptyMap(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(OrgResignApplyDO::getPersonnelId, personnelIds); + wrapper.eq(OrgResignApplyDO::getDeleteEnum, "false"); + wrapper.orderByDesc(OrgResignApplyDO::getApplyTime); + wrapper.orderByDesc(OrgResignApplyDO::getId); + List applies = orgResignApplyMapper.selectList(wrapper); + if (CollectionUtils.isEmpty(applies)) { + return Collections.emptyMap(); + } + Map> result = new LinkedHashMap<>(); + for (OrgResignApplyDO apply : applies) { + result.computeIfAbsent(apply.getPersonnelId(), key -> new ArrayList<>()).add(toResignEntity(apply)); + } + return result; + } + + private OrgResignApplyEntity toResignEntity(OrgResignApplyDO dataObject) { + OrgResignApplyEntity entity = new OrgResignApplyEntity(); + entity.setId(dataObject.getId()); + entity.setPersonnelId(dataObject.getPersonnelId()); + entity.setAuditStatusCode(dataObject.getAuditStatusCode()); + return entity; + } + + private Map buildStandardsCodeCacheBatch(List allCerts) { + Map standardsCodeCache = new HashMap<>(); + if (CollectionUtils.isEmpty(allCerts) || industryProfessionalStandardsMapper == null) { + return standardsCodeCache; + } + Set standardsIds = allCerts.stream() + .filter(c -> !StringUtils.hasText(c.getProfessionalCapabilityCode()) + && c.getIndustryProfessionalStandardsId() != null) + .map(OrgPersonnelCertEntity::getIndustryProfessionalStandardsId) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(standardsIds)) { + return standardsCodeCache; + } + List standardsList = industryProfessionalStandardsMapper.selectBatchIds(standardsIds); + if (CollectionUtils.isEmpty(standardsList)) { + return standardsCodeCache; + } + for (IndustryProfessionalStandardsDO standards : standardsList) { + if (standards != null && StringUtils.hasText(standards.getProfessionalCapabilityCode())) { + standardsCodeCache.put(standards.getId(), standards.getProfessionalCapabilityCode()); + } + } + return standardsCodeCache; } private void enrichChangeSummary(OrgPersonnelCO co) { @@ -135,6 +389,10 @@ public class OrgPersonnelViewEnricher { co.setChangeCount(changes != null ? changes.size() : 0); List applies = orgResignApplyGateway != null ? orgResignApplyGateway.listByPersonnelId(co.getId()) : null; + applyResignDisplay(co, applies); + } + + private void applyResignDisplay(OrgPersonnelCO co, List applies) { if (applies == null || applies.isEmpty()) { return; } @@ -146,6 +404,13 @@ public class OrgPersonnelViewEnricher { co.setResignAuditStatus(displayApply.getAuditStatusCode() != null ? displayApply.getAuditStatusCode() : 0); } + private void applyEmploymentDefault(OrgPersonnelCO co) { + if (co.getEmploymentStatusCode() == null) { + co.setEmploymentStatusCode(1); + co.setEmploymentStatusName("在职"); + } + } + public void enrichResignApply(OrgResignApplyCO co) { if (co == null) { return;