From 38546f6eb1d3ea24e9124985aec0e7d714054727 Mon Sep 17 00:00:00 2001 From: luotaiqian <1147642922@qq.com> Date: Fri, 28 Aug 2026 16:38:05 +0800 Subject: [PATCH] bug fix --- .../InstitutionDashboardExecutor.java | 128 +++++++++++------- .../domain/gateway/EvalProjectGateway.java | 10 ++ .../gatewayimpl/EvalProjectGatewayImpl.java | 15 ++ 3 files changed, 104 insertions(+), 49 deletions(-) diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/institution/InstitutionDashboardExecutor.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/institution/InstitutionDashboardExecutor.java index 68e25c31..c7be5122 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/institution/InstitutionDashboardExecutor.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/institution/InstitutionDashboardExecutor.java @@ -1,9 +1,8 @@ package org.qinan.safetyeval.app.executor.institution; -import org.qinan.safetyeval.app.executor.support.EvalProjectNodeOverviewAssembler; +import com.alibaba.fastjson2.JSON; import org.qinan.safetyeval.client.api.institution.InstitutionDashboardApi; -import org.qinan.safetyeval.client.co.institution.EvalProjectNodeItemCO; -import org.qinan.safetyeval.client.co.institution.EvalProjectNodeOverviewCO; +import org.qinan.safetyeval.client.co.institution.ProjectNodeCO; import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardEvalTypeRatioCO; import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardIndustryStatCO; import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardNoticeCO; @@ -11,6 +10,7 @@ import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboard import org.qinan.safetyeval.client.co.institution.dashboard.InstitutionDashboardProjectNodeStatsCO; import org.qinan.safetyeval.client.dto.SingleResponse; import org.qinan.safetyeval.domain.constant.EvalTypeEnum; +import org.qinan.safetyeval.domain.constant.ProjectStageEnum; import org.qinan.safetyeval.domain.constant.basic.IndustryEnum; import org.qinan.safetyeval.domain.entity.EvalCustomerEntity; import org.qinan.safetyeval.domain.entity.EvalProjectEntity; @@ -27,11 +27,13 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -47,9 +49,6 @@ public class InstitutionDashboardExecutor implements InstitutionDashboardApi { @Resource private EvalProjectGateway evalProjectGateway; - @Resource - private EvalProjectNodeOverviewAssembler evalProjectNodeOverviewAssembler; - @Resource private SafetyMessageGateway safetyMessageGateway; @@ -81,52 +80,19 @@ public class InstitutionDashboardExecutor implements InstitutionDashboardApi { @Override public SingleResponse projectNodeStats() { - Long orgId = ThreadLocalUserInfoAdapter.getOrgId(); - List projects = listOrgProjects(orgId); - - int total = projects.size(); - int statutory = (int) projects.stream().filter(p -> Boolean.TRUE.equals(p.getIsStatutory())).count(); - - // 节点待办数(待办=节点状态为「未开始」) - LinkedHashMap pending = new LinkedHashMap<>(); - for (String code : NODE_DISPLAY.keySet()) { - pending.put(code, 0); + Long orgId = ThreadLocalUserInfoAdapter.getOrgId() ; + if (orgId == null) { + return SingleResponse.success(new InstitutionDashboardProjectNodeStatsCO()); } - for (EvalProjectEntity p : projects) { - try { - EvalProjectNodeOverviewCO ov = evalProjectNodeOverviewAssembler.buildForInstitution(p.getId()); - if (ov == null || ov.getNodes() == null) { - continue; - } - for (EvalProjectNodeItemCO n : ov.getNodes()) { - String code = n.getNodeCode(); - if (code != null && pending.containsKey(code) && "未开始".equals(n.getStatusName())) { - pending.put(code, pending.get(code) + 1); - } - } - } catch (Exception e) { - // 单项目装配异常忽略,保证其余节点统计可用 - } - } - - List nodeStats = new ArrayList<>(); - for (Map.Entry entry : NODE_DISPLAY.entrySet()) { - InstitutionDashboardProjectNodeStatsCO.NodeStat ns = new InstitutionDashboardProjectNodeStatsCO.NodeStat(); - ns.setNodeCode(entry.getKey()); - ns.setNodeName(entry.getValue()); - ns.setPendingCount(pending.getOrDefault(entry.getKey(), 0)); - nodeStats.add(ns); - } - - int archived = (int) projects.stream().filter(p -> Boolean.TRUE.equals(p.getArchiveFlag())).count(); - int delayed = (int) evalProjectGateway.countByOrgIdAndProgressStatus(orgId, "DELAY"); + // 只查询统计所需最小字段:id、project_node、plan_end_date、archive_flag、is_statutory + List projects = evalProjectGateway.listNodeStatFieldsByOrgId(orgId); InstitutionDashboardProjectNodeStatsCO co = new InstitutionDashboardProjectNodeStatsCO(); - co.setTotalProjects(total); - co.setStatutoryProjects(statutory); - co.setNodeStats(nodeStats); - co.setArchivedProjectCount(archived); - co.setDelayedProjectCount(delayed); + co.setTotalProjects(projects.size()); + co.setStatutoryProjects((int) projects.stream().filter(p -> Boolean.TRUE.equals(p.getIsStatutory())).count()); + co.setArchivedProjectCount((int) projects.stream().filter(p -> Objects.equals(p.getArchiveFlag(), 1)).count()); + co.setDelayedProjectCount(countDelayed(projects)); + co.setNodeStats(buildNodeStats(projects)); return SingleResponse.success(co); } @@ -249,6 +215,70 @@ public class InstitutionDashboardExecutor implements InstitutionDashboardApi { // ============================ 通用方法 ============================ + /** + * 统计各流程节点待办数(待办=project_node JSON 中该节点 state=0 未完成) + * + * @param projects 机构项目列表 + * @return 8 个节点的待办统计 + */ + private List buildNodeStats(List projects) { + LinkedHashMap pending = new LinkedHashMap<>(); + for (String code : NODE_DISPLAY.keySet()) { + pending.put(code, 0); + } + for (EvalProjectEntity p : projects) { + for (ProjectNodeCO n : parseNodes(p.getProjectNode())) { + ProjectStageEnum stage = ProjectStageEnum.fromVal(n.getType()); + if (stage != null && NODE_DISPLAY.containsKey(stage.getNode()) + && Integer.valueOf(0).equals(n.getState())) { + pending.put(stage.getNode(), pending.get(stage.getNode()) + 1); + } + } + } + + List nodeStats = new ArrayList<>(); + for (Map.Entry entry : NODE_DISPLAY.entrySet()) { + InstitutionDashboardProjectNodeStatsCO.NodeStat ns = new InstitutionDashboardProjectNodeStatsCO.NodeStat(); + ns.setNodeCode(entry.getKey()); + ns.setNodeName(entry.getValue()); + ns.setPendingCount(pending.getOrDefault(entry.getKey(), 0)); + nodeStats.add(ns); + } + return nodeStats; + } + + /** + * 解析 project_node JSON([{"type":"RISK_ANALYSIS","state":0}]),空值/异常返回空列表保证统计可用 + * + * @param projectNodeJson 节点进度 JSON 字符串 + * @return 节点列表 + */ + private List parseNodes(String projectNodeJson) { + if (projectNodeJson == null || projectNodeJson.isEmpty()) { + return new ArrayList<>(); + } + try { + List nodes = JSON.parseArray(projectNodeJson, ProjectNodeCO.class); + return nodes != null ? nodes : new ArrayList<>(); + } catch (Exception e) { + return new ArrayList<>(); + } + } + + /** + * 统计延期项目数(延期=计划结束日期早于今天且未归档) + * + * @param projects 机构项目列表 + * @return 延期项目数 + */ + private int countDelayed(List projects) { + LocalDate today = LocalDate.now(); + return (int) projects.stream() + .filter(p -> p.getPlanEndDate() != null && p.getPlanEndDate().isBefore(today) + && !Objects.equals(p.getArchiveFlag(), 1)) + .count(); + } + private List listOrgProjects(Long orgId) { EvalProjectQuery q = new EvalProjectQuery(); q.setOrgId(orgId); diff --git a/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/EvalProjectGateway.java b/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/EvalProjectGateway.java index 743d45f3..6839318a 100644 --- a/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/EvalProjectGateway.java +++ b/safety-eval-domain/src/main/java/org/qinan/safetyeval/domain/gateway/EvalProjectGateway.java @@ -4,6 +4,8 @@ import org.qinan.safetyeval.domain.entity.EvalProjectEntity; import org.qinan.safetyeval.domain.query.EvalProjectQuery; import org.qinan.safetyeval.domain.query.PageResult; +import java.util.List; + public interface EvalProjectGateway { EvalProjectEntity save(EvalProjectEntity entity); @@ -25,4 +27,12 @@ public interface EvalProjectGateway { void editProjectNode(Long projectId, String val); EvalProjectEntity findByControlledNumber(String controlledNumber); + + /** + * 按机构查询节点统计所需的最小字段集合(id、project_node、plan_end_date、archive_flag、is_statutory) + * + * @param orgId 机构id + * @return 项目实体列表(仅统计所需字段有值) + */ + List listNodeStatFieldsByOrgId(Long orgId); } diff --git a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/gatewayimpl/EvalProjectGatewayImpl.java b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/gatewayimpl/EvalProjectGatewayImpl.java index 44ac0783..529da2ff 100644 --- a/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/gatewayimpl/EvalProjectGatewayImpl.java +++ b/safety-eval-infrastructure/src/main/java/org/qinan/safetyeval/infrastructure/gatewayimpl/EvalProjectGatewayImpl.java @@ -142,6 +142,21 @@ public class EvalProjectGatewayImpl implements EvalProjectGateway { return dataObject == null ? null : evalProjectDoConvertor.convertDoToE(dataObject); } + @Override + public List listNodeStatFieldsByOrgId(Long orgId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + // 只取统计所需最小字段,减少查询与转换开销 + wrapper.select(EvalProjectDO::getId, EvalProjectDO::getProjectNode, EvalProjectDO::getPlanEndDate, + EvalProjectDO::getArchiveFlag, EvalProjectDO::getIsStatutory) + .eq(EvalProjectDO::getDeleteEnum, "false"); + if (orgId != null) { + wrapper.eq(EvalProjectDO::getOrgId, orgId); + } + return evalProjectMapper.selectList(wrapper).stream() + .map(evalProjectDoConvertor::convertDoToE) + .collect(Collectors.toList()); + } + @Override public void editProjectNode(Long projectId, String val) { EvalProjectDO evalProjectDO = evalProjectMapper.selectById(projectId);