From 724a66c4d81783e20f914d10f5dc46c60d45d884 Mon Sep 17 00:00:00 2001 From: buaixuexideshitongxue <2936013465@qq.com> Date: Thu, 26 Mar 2026 16:54:16 +0800 Subject: [PATCH] =?UTF-8?q?fix--=E9=97=AE=E8=B4=A3=E4=BA=BA=E6=95=B0?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/datav/DatavServiceImpl.java | 293 ++---------- .../service/subDatav/SubDatavServiceImpl.java | 451 ++---------------- .../util/AccountabilityCountUtil.java | 222 +++++++++ 3 files changed, 284 insertions(+), 682 deletions(-) create mode 100644 src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java diff --git a/src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java b/src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java index ca56c89..0dd983f 100644 --- a/src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java @@ -1,6 +1,5 @@ package com.biutag.supervision.service.datav; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; @@ -17,19 +16,18 @@ import com.biutag.supervision.pojo.entity.mailbox.Mail; import com.biutag.supervision.pojo.entity.report.ReportProject; import com.biutag.supervision.pojo.param.*; import com.biutag.supervision.pojo.param.dataAudit.DataAuditQueryParam; -import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam; import com.biutag.supervision.pojo.request.datav.DataVRequest; import com.biutag.supervision.pojo.vo.*; import com.biutag.supervision.repository.dataAudit.DataAuditResourceService; import com.biutag.supervision.repository.dataCaseVerif.DataCaseVerifResourceService; import com.biutag.supervision.repository.dataPetitionComplaint.DataPetitionComplaintResourceService; import com.biutag.supervision.repository.negative.NegativeResourceService; -import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService; import com.biutag.supervision.repository.reportproject.ReportProjectResourceService; import com.biutag.supervision.repository.supExternalDepart.SupExternalDepartResourceService; import com.biutag.supervision.repository.supdepart.SupDepartResourceService; import com.biutag.supervision.service.DataPetition12337Service; import com.biutag.supervision.service.SuperviseReportService; +import com.biutag.supervision.util.AccountabilityCountUtil; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -102,13 +100,11 @@ public class DatavServiceImpl implements DatavService { @Resource private SuperviseReportService superviseReportService; - @Resource - private NegativeBlameResourceService negativeBlameResourceService; - @Resource private DataCaseVerifMapper dataCaseVerifMapper; - private static final String NO_BLAME = "不予追责"; + @Resource + private AccountabilityCountUtil accountabilityCountUtil; private static final BigDecimal WAN = new BigDecimal("10000"); @@ -409,14 +405,14 @@ public class DatavServiceImpl implements DatavService { List ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); List completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList(); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); VideoSuperviseCountVo overview = new VideoSuperviseCountVo(); overview.setTotal(negatives.size()); overview.setCompletionProblem((long) completedList.size()); overview.setDiscoverProblem((long) ssList.size()); - overview.setRelativeOrg(accountabilityCountResult.unitCount()); - overview.setRelativePer(accountabilityCountResult.personTotalCount()); + overview.setRelativeOrg(accountabilityCountResult.newUnitCount()); + overview.setRelativePer(accountabilityCountResult.newPersonTotalCount()); JSONObject data = new JSONObject().fluentPut("overview", overview); return Result.success(data); } @@ -437,14 +433,14 @@ public class DatavServiceImpl implements DatavService { List ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); List completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList(); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); VideoSuperviseMapIconVo videoSuperviseMapIconVo = new VideoSuperviseMapIconVo(); videoSuperviseMapIconVo.setName(fxsj.getShortName()); videoSuperviseMapIconVo.setDepartId(fxsj.getId()); videoSuperviseMapIconVo.setDiscoverProblem(ssList.size()); videoSuperviseMapIconVo.setCompletionProblem(completedList.size()); - videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.unitCount())); - videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.personTotalCount())); + videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.newUnitCount())); + videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.newPersonTotalCount())); videoSuperviseMapIconVoList.add(videoSuperviseMapIconVo); } videoSuperviseMapIconVoList.forEach(VideoSuperviseMapIconVo::initDefaultIfNull); @@ -585,7 +581,7 @@ public class DatavServiceImpl implements DatavService { superviseReportLambdaQueryWrapper.eq(SuperviseReport::getType, "1"); List superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); // 通报问题数 overView.setProblemNumber(negatives.size()); @@ -596,8 +592,8 @@ public class DatavServiceImpl implements DatavService { // 已办结 overView.setCompletedNumber((long) completedList.size()); // 问责单位数 - overView.setDepartNumber(accountabilityCountResult.unitCount()); - overView.setPersonNumber(accountabilityCountResult.personTotalCount()); + overView.setDepartNumber(accountabilityCountResult.newUnitCount()); + overView.setPersonNumber(accountabilityCountResult.newPersonTotalCount()); return Result.success(overView); } @@ -632,14 +628,14 @@ public class DatavServiceImpl implements DatavService { superviseReportLambdaQueryWrapper.in(CollectionUtil.isNotEmpty(allDepartIds), SuperviseReport::getCrtDepartId, allDepartIds); List superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); superviseMapIconVo.setDepartId(fxsj.getId()); superviseMapIconVo.setName(fxsj.getShortName()); superviseMapIconVo.setTotalPro(negatives.size()); superviseMapIconVo.setProcessingNumber(processingList.size()); superviseMapIconVo.setCompletedNumber(completedList.size()); - superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.unitCount())); - superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.personTotalCount())); + superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.newUnitCount())); + superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.newPersonTotalCount())); superviseMapIconVo.setReportNumber(String.valueOf(superviseReportList.size())); superviseTempMapVoList.add(superviseMapIconVo); } @@ -798,7 +794,7 @@ public class DatavServiceImpl implements DatavService { .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); //计算查实率(向上取整) Double verificationRate = 0.0; if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) { @@ -808,8 +804,8 @@ public class DatavServiceImpl implements DatavService { overview.setTotal(dataCaseVerifs.size() + jbNegatvieList.size()); overview.setConfirmed(ssNegative.size()); overview.setDealCasePro((long) negatives.size()); - overview.setPunishPre(accountabilityCountResult.personTotalCount()); - overview.setPunishOrg(accountabilityCountResult.unitCount()); + overview.setPunishPre(accountabilityCountResult.newPersonTotalCount()); + overview.setPunishOrg(accountabilityCountResult.newUnitCount()); overview.setRate(verificationRate); JSONObject res = new JSONObject().fluentPut("overview", overview); return Result.success(res); @@ -838,7 +834,7 @@ public class DatavServiceImpl implements DatavService { // 交办案件数 List jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList(); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); Double verificationRate = 0.0; if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) { @@ -851,8 +847,8 @@ public class DatavServiceImpl implements DatavService { caseVerificationMapVo.setTotal(dataCaseVerifs.size() + jbNegatvieList.size()); caseVerificationMapVo.setConfirmed(ssNegative.size()); caseVerificationMapVo.setDealCasePro(negatives.size()); - caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.personTotalCount())); - caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.unitCount())); + caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.newPersonTotalCount())); + caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.newUnitCount())); caseVerificationMapVo.setRate(verificationRate); caseVerificationMapList.add(caseVerificationMapVo); } @@ -893,7 +889,7 @@ public class DatavServiceImpl implements DatavService { } // 问责处理情况 - AccountabilityCountResult accountabilityCountResult = this.buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); Map dealResultDistribution = accountabilityCountResult.dealResultDistribution(); for (Map.Entry entry : dealResultDistribution.entrySet()) { EchartsVo echartsVo = new EchartsVo(); @@ -1064,21 +1060,14 @@ public class DatavServiceImpl implements DatavService { @Override public Result getResultCount(DataVRequest request) { - List resultCountArray = new ArrayList<>(); NegativeQueryParam negativeQueryParam = new NegativeQueryParam(); negativeQueryParam.setCrtTime(List.of(request.getBeginTime(), request.getEndTime())); negativeQueryParam.setProblemSourcesCode(GROUP_21_22_23_24_25); List negatives = negativeResourceService.query(negativeQueryParam); - BlameResult blameResult = this.buildBlameResult(negatives); - List negativeBlames = blameResult.personalBlames(); // 问责处理情况与统一统计口径保持一致:先拆分多处理结果,再按单项处理结果聚合。 - Map blames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .map(item -> item.substring(item.lastIndexOf('_') + 1)) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - for (Map.Entry entry : blames.entrySet()) { + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); + List resultCountArray = new ArrayList<>(); + for (Map.Entry entry : accountabilityCountResult.dealResultDistribution().entrySet()) { EchartsVo echartsVo = new EchartsVo(); echartsVo.setName(entry.getKey()); echartsVo.setValue(entry.getValue().intValue()); @@ -1115,7 +1104,7 @@ public class DatavServiceImpl implements DatavService { negativeQueryParam.setProblemSourcesCode(List.of(ZFTZSJ.getValue())); List negativeListData = negativeResourceService.query(negativeQueryParam); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData); BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney); BigDecimal zftzsjje = this.sumAmountInWan(reportProjects, ReportProject::getArchivingReduceMoney); @@ -1123,7 +1112,7 @@ public class DatavServiceImpl implements DatavService { auditOverview.setAuditAmount(zftzje); auditOverview.setAuditSjAmount(zftzsjje); auditOverview.setNegativeNumber(negativeListData.size()); - auditOverview.setAccountableNumber(accountabilityCountResult.personTotalCount()); + auditOverview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount()); } else { DataAuditQueryParam dataAuditQueryParam = new DataAuditQueryParam(); dataAuditQueryParam.setAuditTimeStart(toLocalDateTime(request.getBeginTime())); @@ -1135,14 +1124,14 @@ public class DatavServiceImpl implements DatavService { negativeQueryParam.setProblemSourcesCode(List.of(request.getAuditType())); List negativeListData = negativeResourceService.query(negativeQueryParam); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData); BigDecimal je = this.sumAmount(dataAuditList, DataAudit::getAuditAmount, new BigDecimal(1)); BigDecimal zsjje = this.sumAmount(dataAuditList, DataAudit::getIssueAmount, new BigDecimal(1)); auditOverview.setProjectNumber(BigDecimal.valueOf(dataAuditList.size())); auditOverview.setAuditAmount(je); auditOverview.setAuditSjAmount(zsjje); auditOverview.setNegativeNumber(negativeListData.size()); - auditOverview.setAccountableNumber(accountabilityCountResult.personTotalCount()); + auditOverview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount()); } JSONObject object = new JSONObject(); object.fluentPut("fxData", fxData); @@ -1198,7 +1187,7 @@ public class DatavServiceImpl implements DatavService { negativeQueryParam.setProblemSourcesCode(GROUP_27_28_29_30); List negativeListData = negativeResourceService.query(negativeQueryParam); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData); // 政府投资总金额 BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney); // 政府投资审减金额 @@ -1211,7 +1200,7 @@ public class DatavServiceImpl implements DatavService { overview.setAuditAmount(zftzje.add(qtsjje)); overview.setAuditSjAmount(zftzsjje.add(qtsjwtje)); overview.setNegativeNumber(negativeListData.size()); - overview.setAccountableNumber(accountabilityCountResult.personTotalCount()); + overview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount()); return Result.success(overview); } @@ -1249,7 +1238,7 @@ public class DatavServiceImpl implements DatavService { List negativeListData = negativeMapper.getNegativeListData(key, request.getBeginTime(), request.getEndTime(), GROUP_27_28_29_30); // 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData); // 政府投资总金额 BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney); // 政府投资审减金额 @@ -1263,7 +1252,7 @@ public class DatavServiceImpl implements DatavService { auditSuperviseMapIconVo.setAuditAmount(zftzje.add(qtsjje)); auditSuperviseMapIconVo.setAuditSjAmount(zftzsjje.add(qtsjwtje)); auditSuperviseMapIconVo.setNegativeNumber(negativeListData.size()); - auditSuperviseMapIconVo.setAccountableNumber(Math.toIntExact(accountabilityCountResult.personTotalCount())); + auditSuperviseMapIconVo.setAccountableNumber(Math.toIntExact(accountabilityCountResult.newPersonTotalCount())); auditSuperviseMapIconVoList.add(auditSuperviseMapIconVo); } JSONObject data = new JSONObject().fluentPut("auditSuperviseMapIconVoList", auditSuperviseMapIconVoList); @@ -1392,222 +1381,6 @@ public class DatavServiceImpl implements DatavService { - private static final Set NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责"); - - private record AccountabilityCountResult( - long personalCount, - long leaderCount, - long personTotalCount, - long unitCount, - Map dealResultDistribution, - // 新增:问责人数(blameName非空 + 处理结果非"不予追责") - long newPersonalCount, - // 新增:问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责") - long newLeaderCount, - // 新增:新问责总人数 - long newPersonTotalCount - ) {} - - private AccountabilityCountResult buildAccountabilityCountResult(List negatives) { - if (CollectionUtil.isEmpty(negatives)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L); - } - - List effectiveNegativeIds = negatives.stream() - .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) - || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())) - .map(Negative::getId) - .filter(StrUtil::isNotBlank) - .distinct() - .toList(); - - if (CollectionUtil.isEmpty(effectiveNegativeIds)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L); - } - - NegativeBlameQueryParam param = new NegativeBlameQueryParam(); - param.setNegativeIds(effectiveNegativeIds); - List negativeBlames = negativeBlameResourceService.query(param); - - if (CollectionUtil.isEmpty(negativeBlames)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L); - } - - long personalCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .distinct() - .count(); - - long leaderCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> StrUtil.isNotBlank(one.getLeadName())) - .flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getLeadName() + "_" + resultName)) - .distinct() - .count(); - - long unitCount = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .distinct() - .count(); - - // 统计处理结果分布(普通人员 + 领导) - Map dealResultDistribution = buildDealResultDistribution(negativeBlames); - - // 新增:问责人数(blameName非空 + 处理结果非"不予追责") - long newPersonalCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> !isNoAccountability(one.getHandleResultName())) - .count(); - - // 新增:问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责") - long newLeaderCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> StrUtil.isNotBlank(one.getLeadName())) - .filter(one -> !isNoAccountability(one.getLeadHandleResultName())) - .count(); - - // 新增:新问责总人数 - long newPersonTotalCount = newPersonalCount + newLeaderCount; - - return new AccountabilityCountResult( - personalCount, - leaderCount, - personalCount + leaderCount, - unitCount, - dealResultDistribution, - newPersonalCount, - newLeaderCount, - newPersonTotalCount - ); - } - - /** - * 构建处理结果分布统计(普通人员 + 领导) - * 与 buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致 - */ - private Map buildDealResultDistribution(List negativeBlames) { - // 统计普通人员处理结果(type=personal + blameName非空) - Map personalResults = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result)) - .distinct() - .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); - - // 统计领导处理结果(type=personal + blameName非空 + leadName非空) - Map leaderResults = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> StrUtil.isNotBlank(one.getLeadName())) - .flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream() - .map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result)) - .distinct() - .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); - - // 合并 - Map merged = new HashMap<>(personalResults); - leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum)); - return merged; - } - - private List splitValidAccountabilityResults(String raw) { - if (StrUtil.isBlank(raw)) { - return List.of(); - } - - return Arrays.stream(raw.split("[、,,]")) - .map(String::trim) - .filter(StrUtil::isNotBlank) - .filter(item -> !NO_ACCOUNTABILITY_SET.contains(item)) - .distinct() - .toList(); - } - - /** - * 判断问责情况是否全为"不予追责"(即没有有效的问责处理结果) - * @param raw 原始问责情况字符串 - * @return true表示全部为"不予追责",false表示有有效问责处理结果 - */ - private boolean isNoAccountability(String raw) { - if (StrUtil.isBlank(raw)) { - return true; - } - List results = Arrays.stream(raw.split("[、,,]")) - .map(String::trim) - .filter(StrUtil::isNotBlank) - .toList(); - // 如果拆分后为空,或者所有结果都是"不予追责",则返回true - if (results.isEmpty()) { - return true; - } - return results.stream().allMatch(item -> NO_ACCOUNTABILITY_SET.contains(item)); - } - - - - public record BlameResult( - List personalBlames, - List leadBlames, - List unitBlames - ) { - } - - public BlameResult buildBlameResult(List negativeListData) { - if (CollUtil.isEmpty(negativeListData)) { - return new BlameResult(List.of(), List.of(), List.of()); - } - // 1. 筛选有效 negative - List validNegatives = negativeListData.stream() - .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) - || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())) - .toList(); - if (CollUtil.isEmpty(validNegatives)) { - return new BlameResult(List.of(), List.of(), List.of()); - } - // 2. 查询问责数据 - NegativeBlameQueryParam param = new NegativeBlameQueryParam(); - param.setNegativeIds(validNegatives.stream() - .map(Negative::getId) - .toList()); - List negativeBlames = negativeBlameResourceService.query(param); - if (CollUtil.isEmpty(negativeBlames)) { - return new BlameResult(List.of(), List.of(), List.of()); - } - // 3. 个人问责 - List personalBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !NO_BLAME.equals(one.getHandleResultName())) - .toList(); - // 4. 领导问责(去重) - Set seenLead = new HashSet<>(); - List leadBlames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName())) - .filter(one -> !NO_BLAME.equals(one.getLeadHandleResultName())) - .filter(one -> seenLead.add( - one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName() - )) - .toList(); - // 5. 单位问责 - List unitBlames = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - return new BlameResult(personalBlames, leadBlames, unitBlames); - } - private LocalDateTime toLocalDateTime(Date date) { if (date == null) { return null; diff --git a/src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java b/src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java index 432af7d..7ffb64a 100644 --- a/src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java @@ -1,6 +1,5 @@ package com.biutag.supervision.service.subDatav; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; @@ -15,29 +14,23 @@ import com.biutag.supervision.pojo.dto.common.PieItem; import com.biutag.supervision.pojo.entity.*; import com.biutag.supervision.pojo.entity.mailbox.Mail; import com.biutag.supervision.pojo.param.*; -import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam; -import com.biutag.supervision.pojo.request.datav.DataVRequest; import com.biutag.supervision.pojo.request.subdatav.SubDataVRequest; import com.biutag.supervision.pojo.vo.*; import com.biutag.supervision.repository.dataPetitionComplaint.DataPetitionComplaintResourceService; import com.biutag.supervision.repository.mail.MailResourceService; import com.biutag.supervision.repository.negative.NegativeResourceService; -import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService; import com.biutag.supervision.repository.reportproject.ReportProjectResourceService; import com.biutag.supervision.repository.supExternalDepart.SupExternalDepartResourceService; import com.biutag.supervision.repository.supdepart.SupDepartResourceService; import com.biutag.supervision.service.DataPetition12337Service; import com.biutag.supervision.service.SuperviseReportService; -import com.biutag.supervision.service.datav.DatavServiceImpl; +import com.biutag.supervision.util.AccountabilityCountUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; -import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -92,18 +85,14 @@ public class SubDatavServiceImpl implements SubDatavService { @Resource private NegativeMapper negativeMapper; - - @Resource - private NegativeBlameResourceService negativeBlameResourceService; - @Resource private DataCaseVerifMapper dataCaseVerifMapper; @Resource private SuperviseReportService superviseReportService; - private static final String NO_BLAME = "不予追责"; - private static final Set NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责"); + @Resource + private AccountabilityCountUtil accountabilityCountUtil; private static final BigDecimal WAN = new BigDecimal("10000"); @@ -311,14 +300,14 @@ public class SubDatavServiceImpl implements SubDatavService { List ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); List completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList(); // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); VideoSuperviseCountVo overview = new VideoSuperviseCountVo(); overview.setTotal(negatives.size()); overview.setCompletionProblem((long) completedList.size()); overview.setDiscoverProblem((long) ssList.size()); - overview.setRelativeOrg(accountabilityCountResult.unitCount()); - overview.setRelativePer(accountabilityCountResult.personTotalCount()); + overview.setRelativeOrg(accountabilityCountResult.newUnitCount()); + overview.setRelativePer(accountabilityCountResult.newPersonTotalCount()); JSONObject data = new JSONObject().fluentPut("overview", overview); return Result.success(data); } @@ -342,41 +331,16 @@ public class SubDatavServiceImpl implements SubDatavService { List ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); List completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList(); - NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam(); - negativeBlameQueryParam.setNegativeIds(ssList.stream().map(Negative::getId).toList()); - List negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam); - - // 3. 个人问责 - List personalBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - // 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重) - Set seenLead = new HashSet<>(); - List leadBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName())) - .filter(one -> !"不予追责".equals(one.getLeadHandleResultName())) - .filter(one -> seenLead.add( - one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName() - )) - .toList(); - // 5. 单位问责 - List unitBlames = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - + // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); VideoSuperviseMapIconVo videoSuperviseMapIconVo = new VideoSuperviseMapIconVo(); videoSuperviseMapIconVo.setName(pcs.getShortName()); videoSuperviseMapIconVo.setDepartId(pcs.getId()); videoSuperviseMapIconVo.setDiscoverProblem(ssList.size()); videoSuperviseMapIconVo.setCompletionProblem(completedList.size()); - videoSuperviseMapIconVo.setRelativeOrg(unitBlames.size()); - videoSuperviseMapIconVo.setRelativePer(personalBlames.size() + leadBlames.size()); + videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.newUnitCount())); + videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.newPersonTotalCount())); videoSuperviseMapIconVoList.add(videoSuperviseMapIconVo); } @@ -509,15 +473,15 @@ public class SubDatavServiceImpl implements SubDatavService { superviseReportLambdaQueryWrapper.eq(SuperviseReport::getCrtDepartId, supDepart.getId()); List superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper); // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); SuperviseMapIconVo superviseMapIconVo = new SuperviseMapIconVo(); superviseMapIconVo.setName(supDepart.getShortName()); superviseMapIconVo.setDepartId(supDepart.getId()); superviseMapIconVo.setTotalPro(negatives.size()); superviseMapIconVo.setCompletedNumber(completedList.size()); superviseMapIconVo.setProcessingNumber(processingList.size()); - superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.personTotalCount())); - superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.unitCount())); + superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.newPersonTotalCount())); + superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.newUnitCount())); superviseMapIconVo.setReportNumber(String.valueOf(superviseReportList.size())); superviseTempMapVoList.add(superviseMapIconVo); } @@ -547,13 +511,13 @@ public class SubDatavServiceImpl implements SubDatavService { superviseReportLambdaQueryWrapper.in(CollectionUtil.isNotEmpty(allDepartIds), SuperviseReport::getCrtDepartId, allDepartIds); List superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper); // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 - AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); overView.setProblemNumber(negatives.size()); overView.setProcessingNumber((long) processingList.size()); overView.setCompletedNumber((long) completedList.size()); overView.setReportNumber((long) superviseReportList.size()); - overView.setDepartNumber(accountabilityCountResult.unitCount()); - overView.setPersonNumber(accountabilityCountResult.personTotalCount()); + overView.setDepartNumber(accountabilityCountResult.newUnitCount()); + overView.setPersonNumber(accountabilityCountResult.newPersonTotalCount()); return Result.success(new JSONObject().fluentPut("overview", overView)); } @@ -709,31 +673,8 @@ public class SubDatavServiceImpl implements SubDatavService { List ssNegative = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); // 交办案件数 List jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList(); - NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam(); - negativeBlameQueryParam.setNegativeIds(ssNegative.stream().map(Negative::getId).toList()); - List negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam); - - // 3. 个人问责 - List personalBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - // 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重) - Set seenLead = new HashSet<>(); - List leadBlames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName())) - .filter(one -> !"不予追责".equals(one.getLeadHandleResultName())) - .filter(one -> seenLead.add( - one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName() - )) - .toList(); - // 5. 单位问责 - List unitBlames = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); + // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); Double verificationRate = 0.0; if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) { @@ -744,8 +685,8 @@ public class SubDatavServiceImpl implements SubDatavService { overview.setTotal(dataCaseVerifs.size() + jbNegatvieList.size()); overview.setConfirmed(ssNegative.size()); overview.setDealCasePro((long) negatives.size()); - overview.setPunishPre((long) (personalBlames.size() + leadBlames.size())); - overview.setPunishOrg((long) unitBlames.size()); + overview.setPunishPre(accountabilityCountResult.newPersonTotalCount()); + overview.setPunishOrg(accountabilityCountResult.newUnitCount()); overview.setRate(verificationRate); JSONObject res = new JSONObject().fluentPut("overview", overview); return Result.success(res); @@ -772,33 +713,10 @@ public class SubDatavServiceImpl implements SubDatavService { List negatives = negativeMapper.getNegativeListData(pcs.getId(), request.getBeginTime(), request.getEndTime(), proCode); // 交办案件数 List jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList(); - // 问责情况 + // 属实问题 List ssNegative = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList(); - NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam(); - negativeBlameQueryParam.setNegativeIds(ssNegative.stream().map(Negative::getId).toList()); - List negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam); - - // 3. 个人问责 - List personalBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - // 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重) - Set seenLead = new HashSet<>(); - List leadBlames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName())) - .filter(one -> !"不予追责".equals(one.getLeadHandleResultName())) - .filter(one -> seenLead.add( - one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName() - )) - .toList(); - // 5. 单位问责 - List unitBlames = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); + // 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。 + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); int totalCaseCount = dataCaseVerifs.size() + jbNegatvieList.size(); double verificationRate = 0.0; @@ -813,8 +731,8 @@ public class SubDatavServiceImpl implements SubDatavService { caseVerificationMapVo.setTotal(dataCaseVerifs.size() + jbNegatvieList.size()); caseVerificationMapVo.setConfirmed(ssNegative.size()); caseVerificationMapVo.setDealCasePro(negatives.size()); - caseVerificationMapVo.setPunishPre(personalBlames.size() + leadBlames.size()); - caseVerificationMapVo.setPunishOrg(unitBlames.size()); + caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.newPersonTotalCount())); + caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.newUnitCount())); caseVerificationMapVo.setRate(verificationRate); caseVerificationMapList.add(caseVerificationMapVo); } @@ -855,7 +773,7 @@ public class SubDatavServiceImpl implements SubDatavService { } // 问责处理情况 - AccountabilityCountResult accountabilityCountResult = this.buildAccountabilityCountResult(negatives); + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); for (Map.Entry entry : accountabilityCountResult.dealResultDistribution().entrySet()) { EchartsVo echartsVo = new EchartsVo(); echartsVo.setName(entry.getKey()); @@ -1034,18 +952,11 @@ public class SubDatavServiceImpl implements SubDatavService { @Override public Result getSubOneResultCount( SubDataVRequest request) { - List resultCountArray = new ArrayList<>(); List negatives = negativeMapper.getNegativeListData(request.getDepartId(), request.getBeginTime(), request.getEndTime(), GROUP_21_22_23_24_25); - DatavServiceImpl.BlameResult blameResult = this.buildBlameResult(negatives); - List negativeBlames = blameResult.personalBlames(); // 问责处理情况与统一统计口径保持一致:先拆分多处理结果,再按单项处理结果聚合。 - Map blames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .map(item -> item.substring(item.lastIndexOf('_') + 1)) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - for (Map.Entry entry : blames.entrySet()) { + AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives); + List resultCountArray = new ArrayList<>(); + for (Map.Entry entry : accountabilityCountResult.dealResultDistribution().entrySet()) { EchartsVo echartsVo = new EchartsVo(); echartsVo.setName(entry.getKey()); echartsVo.setValue(entry.getValue().intValue()); @@ -1169,310 +1080,6 @@ public class SubDatavServiceImpl implements SubDatavService { .filter(e -> e.getValue() != null && e.getValue() > 0) .toList(); } - - - public record BlameResult( - List personalBlames, - List leadBlames - ) { - } - - /** - * 统一问责统计口径: - * 1. 仅统计核查属实、部分属实的问题; - * 2. 同一条问责记录中若包含多个处理结果,按分隔符拆分后分别计数; - * 3. 通过 negativeId + 问责对象 + 处理结果 去重,避免重复累计。 - */ - private record AccountabilityCountResult( - long personalCount, - long leaderCount, - long personTotalCount, - long unitCount, - Map dealResultDistribution - ) { - } - - /** - * 与 DatavServiceImpl 的问责人数、问责单位数统计逻辑保持一致,避免区县大屏与一级大屏口径不一致。 - */ - private AccountabilityCountResult buildAccountabilityCountResult(List negatives) { - if (CollectionUtil.isEmpty(negatives)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of()); - } - - List effectiveNegativeIds = negatives.stream() - .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) - || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())) - .map(Negative::getId) - .filter(StrUtil::isNotBlank) - .distinct() - .toList(); - - if (CollectionUtil.isEmpty(effectiveNegativeIds)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of()); - } - - NegativeBlameQueryParam param = new NegativeBlameQueryParam(); - param.setNegativeIds(effectiveNegativeIds); - List negativeBlames = negativeBlameResourceService.query(param); - - if (CollectionUtil.isEmpty(negativeBlames)) { - return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of()); - } - - long personalCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .distinct() - .count(); - - long leaderCount = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> StrUtil.isNotBlank(one.getLeadName())) - .flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getLeadName() + "_" + resultName)) - .distinct() - .count(); - - long unitCount = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName)) - .distinct() - .count(); - - // 统计处理结果分布(普通人员 + 领导) - Map dealResultDistribution = buildDealResultDistribution(negativeBlames); - - return new AccountabilityCountResult( - personalCount, - leaderCount, - personalCount + leaderCount, - unitCount, - dealResultDistribution - ); - } - - /** - * 构建处理结果分布统计(普通人员 + 领导) - * 与 buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致 - */ - private Map buildDealResultDistribution(List negativeBlames) { - // 统计普通人员处理结果(type=personal + blameName非空) - Map personalResults = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() - .map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result)) - .distinct() - .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); - - // 统计领导处理结果(type=personal + blameName非空 + leadName非空) - Map leaderResults = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getBlameName())) - .filter(one -> StrUtil.isNotBlank(one.getLeadName())) - .flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream() - .map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result)) - .distinct() - .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); - - // 合并 - Map merged = new HashMap<>(personalResults); - leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum)); - return merged; - } - - private List splitValidAccountabilityResults(String raw) { - if (StrUtil.isBlank(raw)) { - return List.of(); - } - - return Arrays.stream(raw.split("[、,,]")) - .map(String::trim) - .filter(StrUtil::isNotBlank) - .filter(item -> !NO_ACCOUNTABILITY_SET.contains(item)) - .distinct() - .toList(); - } - - public DatavServiceImpl.BlameResult buildBlameResult(List negativeListData) { - if (CollUtil.isEmpty(negativeListData)) { - return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of()); - } - // 1. 筛选有效 negative - List validNegatives = negativeListData.stream() - .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) - || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())) - .toList(); - if (CollUtil.isEmpty(validNegatives)) { - return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of()); - } - // 2. 查询问责数据 - NegativeBlameQueryParam param = new NegativeBlameQueryParam(); - param.setNegativeIds(validNegatives.stream() - .map(Negative::getId) - .toList()); - List negativeBlames = negativeBlameResourceService.query(param); - if (CollUtil.isEmpty(negativeBlames)) { - return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of()); - } - // 3. 个人问责 - List personalBlames = negativeBlames.stream() - .filter(one -> BlameType.personal.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !NO_BLAME.equals(one.getHandleResultName())) - .toList(); - // 4. 领导问责(去重) - Set seenLead = new HashSet<>(); - List leadBlames = negativeBlames.stream() - .filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName())) - .filter(one -> !NO_BLAME.equals(one.getLeadHandleResultName())) - .filter(one -> seenLead.add( - one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName() - )) - .toList(); - // 5. 单位问责 - List unitBlames = negativeBlames.stream() - .filter(one -> BlameType.department.name().equals(one.getType())) - .filter(one -> StrUtil.isNotBlank(one.getHandleResultName())) - .filter(one -> !"不予追责".equals(one.getHandleResultName())) - .toList(); - return new DatavServiceImpl.BlameResult(personalBlames, leadBlames, unitBlames); - } - - private LocalDateTime toLocalDateTime(Date date) { - if (date == null) { - return null; - } - return date.toInstant() - .atZone(ZoneId.systemDefault()) - .toLocalDateTime(); - } - - private long calculateRate(long numerator, long denominator) { - if (denominator == 0) { - return 0L; - } - return (numerator * 100 + denominator / 2) / denominator; - } - - private List buildAuditNegativeVoList(List departs, DataVRequest request) { - List result = new ArrayList<>(); - for (SupDepart depart : departs) { - List negativeListData = negativeMapper.getNegativeListData( - depart.getId(), - request.getBeginTime(), - request.getEndTime(), - List.of(request.getAuditType()) - ); - - long numerator = negativeListData.stream() - .filter(one -> "1".equals(one.getIsRectifyCode())) - .count(); - long denominator = negativeListData.size(); - AuditNegativeVo vo = new AuditNegativeVo(); - vo.setLabel(depart.getShortName()); - vo.setNumerator(numerator); - vo.setDenominator(denominator); - vo.setValue(calculateRate(numerator, denominator)); - result.add(vo); - } - return result.stream() - // 过滤没有问题数据的 - .filter(vo -> vo.getDenominator() > 0) - // 按整改率降序 - .sorted(Comparator.comparing(AuditNegativeVo::getValue).reversed()) - .toList(); - } - - - private BigDecimal sumAmount(List list, Function mapper, BigDecimal divisor) { - BigDecimal sum = list.stream() - .map(mapper) - .filter(Objects::nonNull) - .reduce(BigDecimal.ZERO, BigDecimal::add); - - if (divisor == null || BigDecimal.ONE.compareTo(divisor) == 0) { - return sum; - } - - return sum.divide(divisor, 2, RoundingMode.HALF_UP); - } - - private BigDecimal sumAmountInWan(List list, Function mapper) { - return list.stream() - .map(mapper) - .filter(Objects::nonNull) - .reduce(BigDecimal.ZERO, BigDecimal::add) - .divide(WAN, 2, RoundingMode.HALF_UP); - } - - - public Result mockData() { - List fxsj = new ArrayList<>(); - List jsdw = new ArrayList<>(); - - fxsj.add(build("城东派出所", "pcs_001", 15, 20, 8, 12)); - fxsj.add(build("城西派出所", "pcs_002", 10, 18, 6, 12)); - fxsj.add(build("开发区派出所", "pcs_003", 20, 30, 10, 20)); - - jsdw.add(build("刑侦大队", "team_001", 12, 15, 7, 8)); - jsdw.add(build("治安大队", "team_002", 8, 12, 5, 7)); - jsdw.add(build("网安大队", "team_003", 10, 25, 12, 13)); - - long total = Stream.concat(fxsj.stream(), jsdw.stream()) - .mapToLong(vo -> Long.parseLong(vo.getDenominator())) - .sum(); - - long completed = Stream.concat(fxsj.stream(), jsdw.stream()) - .mapToLong(vo -> Long.parseLong(vo.getNumerator())) - .sum(); - - long processing = total - completed; - - double rate = total == 0 ? 0.0 : - BigDecimal.valueOf(completed) - .multiply(BigDecimal.valueOf(100)) - .divide(BigDecimal.valueOf(total), 1, RoundingMode.HALF_UP) - .doubleValue(); - - DayTimeSuperviseVo overview = new DayTimeSuperviseVo(); - overview.setProTotal((int) total); - overview.setProcessingNumber(processing); - overview.setCompletedNumber(completed); - overview.setCompletedRate(rate); - - JSONObject data = new JSONObject() - .fluentPut("overview", overview) - .fluentPut("fxsjChangedRankList", fxsj) - .fluentPut("jsdwChangedRankList", jsdw); - - return Result.success(data); - } - - private RankVo build(String name, String id, int completed, int total, int city, int county) { - RankVo vo = new RankVo(); - vo.setLabel(name); - vo.setDepartId(id); - vo.setNumerator(String.valueOf(completed)); - vo.setDenominator(String.valueOf(total)); - vo.setCityNumber(String.valueOf(city)); - vo.setCountyNumber(String.valueOf(county)); - - String rate = BigDecimal.valueOf(completed) - .multiply(BigDecimal.valueOf(100)) - .divide(BigDecimal.valueOf(total), 1, RoundingMode.HALF_UP) - .toString(); - - vo.setRate(rate); - vo.setValue(rate); - return vo; - } // endregion diff --git a/src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java b/src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java new file mode 100644 index 0000000..932e7f3 --- /dev/null +++ b/src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java @@ -0,0 +1,222 @@ +package com.biutag.supervision.util; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.biutag.supervision.constants.enums.BlameType; +import com.biutag.supervision.constants.enums.CheckStatusEnum; +import com.biutag.supervision.pojo.entity.Negative; +import com.biutag.supervision.pojo.entity.NegativeBlame; +import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam; +import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 统一问责统计工具类 + * 用于计算问责人次、问责单位数等统计数据 + */ +@Component +public class AccountabilityCountUtil { + + @Resource + private NegativeBlameResourceService negativeBlameResourceService; + + private static final Set NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责"); + + /** + * 问责统计结果 + */ + public record AccountabilityCountResult( + long personalCount, + long leaderCount, + long personTotalCount, + long unitCount, + Map dealResultDistribution, + // 问责人数(blameName非空 + 处理结果非"不予追责") + long newPersonalCount, + // 问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责") + long newLeaderCount, + // 新问责总人数 + long newPersonTotalCount, + // 问责单位数(blameName非空 + 处理结果非"不予问责"且非"不予追责") + long newUnitCount + ) { + } + + /** + * 构建问责统计结果 + * 统一口径: + * 1. 仅统计核查属实、部分属实的问题; + * 2. 同一条问责记录中若包含多个处理结果,按分隔符拆分后分别计数; + * 3. 通过 negativeId + 问责对象 + 处理结果 去重,避免重复累计。 + */ + public AccountabilityCountResult buildAccountabilityCountResult(List negatives) { + if (CollectionUtil.isEmpty(negatives)) { + return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L); + } + + List effectiveNegativeIds = negatives.stream() + .filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) + || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())) + .map(Negative::getId) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + + if (CollectionUtil.isEmpty(effectiveNegativeIds)) { + return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L); + } + + NegativeBlameQueryParam param = new NegativeBlameQueryParam(); + param.setNegativeIds(effectiveNegativeIds); + List negativeBlames = negativeBlameResourceService.query(param); + + if (CollectionUtil.isEmpty(negativeBlames)) { + return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L); + } + + long personalCount = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> !isNoAccountability(one.getHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getBlameName()) + .distinct() + .count(); + + long leaderCount = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> StrUtil.isNotBlank(one.getLeadName())) + .filter(one -> !isNoAccountability(one.getLeadHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getLeadName()) + .distinct() + .count(); + + long unitCount = negativeBlames.stream() + .filter(one -> BlameType.department.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> !isNoAccountability(one.getHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getBlameName()) + .distinct() + .count(); + + // 统计处理结果分布(普通人员 + 领导) + Map dealResultDistribution = buildDealResultDistribution(negativeBlames); + + // 问责人数(blameName非空 + 处理结果非"不予追责") + // 同一个问题(negativeId)+ 同一个人(blameName)只算1次 + long newPersonalCount = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> !isNoAccountability(one.getHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getBlameName()) + .distinct() + .count(); + + // 问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责") + // 同一个问题(negativeId)+ 同一个领导(leadName)只算1次 + long newLeaderCount = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> StrUtil.isNotBlank(one.getLeadName())) + .filter(one -> !isNoAccountability(one.getLeadHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getLeadName()) + .distinct() + .count(); + + // 新问责总人数 + long newPersonTotalCount = newPersonalCount + newLeaderCount; + + // 问责单位数(blameName非空 + 处理结果非"不予问责"且非"不予追责") + // 同一个问题(negativeId)+ 同一个单位(blameName)只算1次 + long newUnitCount = negativeBlames.stream() + .filter(one -> BlameType.department.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> !isNoAccountability(one.getHandleResultName())) + .map(one -> one.getNegativeId() + "_" + one.getBlameName()) + .distinct() + .count(); + + return new AccountabilityCountResult( + personalCount, + leaderCount, + personalCount + leaderCount, + unitCount, + dealResultDistribution, + newPersonalCount, + newLeaderCount, + newPersonTotalCount, + newUnitCount + ); + } + + /** + * 构建处理结果分布统计(普通人员 + 领导) + * 与 buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致 + */ + private Map buildDealResultDistribution(List negativeBlames) { + // 统计普通人员处理结果(type=personal + blameName非空) + Map personalResults = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream() + .map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result)) + .distinct() + .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); + + // 统计领导处理结果(type=personal + blameName非空 + leadName非空) + Map leaderResults = negativeBlames.stream() + .filter(one -> BlameType.personal.name().equals(one.getType())) + .filter(one -> StrUtil.isNotBlank(one.getBlameName())) + .filter(one -> StrUtil.isNotBlank(one.getLeadName())) + .flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream() + .map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result)) + .distinct() + .collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting())); + + // 合并 + Map merged = new HashMap<>(personalResults); + leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum)); + return merged; + } + + private List splitValidAccountabilityResults(String raw) { + if (StrUtil.isBlank(raw)) { + return List.of(); + } + + return Arrays.stream(raw.split("[、,,]")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .filter(item -> !NO_ACCOUNTABILITY_SET.contains(item)) + .distinct() + .toList(); + } + + /** + * 判断问责情况是否全为"不予追责"(即没有有效的问责处理结果) + * + * @param raw 原始问责情况字符串 + * @return true表示全部为"不予追责",false表示有有效问责处理结果 + */ + private boolean isNoAccountability(String raw) { + if (StrUtil.isBlank(raw)) { + return true; + } + List results = Arrays.stream(raw.split("[、,,]")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .toList(); + if (results.isEmpty()) { + return true; + } + return results.stream().allMatch(item -> NO_ACCOUNTABILITY_SET.contains(item)); + } +}