From 06d65d9843f305ed8cc1da27d0fc75c28de02c88 Mon Sep 17 00:00:00 2001 From: buaixuexideshitongxue <2936013465@qq.com> Date: Wed, 11 Mar 2026 22:45:46 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A0=94=E5=88=A4=E5=88=86=E6=9E=90--step8?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../work/NegativeReportController.java | 26 ++- .../pojo/dto/report/OverviewSection.java | 3 + .../ReportAccountabilityStatsRequestDTO.java | 4 + .../ReportAccountabilityStatsResponseDTO.java | 7 +- .../BusinessLineDetailSection.java | 3 + .../BusinessLinePersonRankItem.java | 4 + .../businessLine/BusinessLineRankItem.java | 3 + .../closed/ClosedStatsCalcRequestDTO.java | 4 + .../ReportProblemTypeStatsRequestDTO.java | 24 ++ .../ReportProblemTypeStatsResponseDTO.java | 24 ++ .../pojo/param/NegativeQueryParam.java | 3 + .../pojo/param/PoliceQueryParam.java | 3 + .../supervision/pojo/vo/NegativeQueryVo.java | 3 + .../supdepart/SupDepartResourceService.java | 22 ++ .../service/NegativeQueryService.java | 7 +- .../service/NegativeTaskService.java | 29 +++ .../supervision/service/SupPoliceService.java | 5 +- .../negativeReport/NegativeReportService.java | 3 + .../NegativeReportServiceImpl.java | 138 ++++++++++-- .../report/ReportProblemTypeStatsService.java | 14 ++ ...eportAccountabilitySectionServiceImpl.java | 3 + .../ReportAccountabilityStatsServiceImpl.java | 8 +- .../ReportBusinessLineSectionServiceImpl.java | 206 +++--------------- .../impl/ReportClosedStatsServiceImpl.java | 28 ++- .../report/impl/ReportDataServiceImpl.java | 12 + .../ReportOverviewSectionServiceImpl.java | 61 +++++- .../ReportProblemTypeStatsServiceImpl.java | 102 +++++++++ .../supervision/util/ReportTrendUtil.java | 45 ++++ ...审一体化平台研判分析报告.docx | Bin 15897 -> 21933 bytes 29 files changed, 572 insertions(+), 222 deletions(-) create mode 100644 src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsRequestDTO.java create mode 100644 src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsResponseDTO.java create mode 100644 src/main/java/com/biutag/supervision/service/report/ReportProblemTypeStatsService.java create mode 100644 src/main/java/com/biutag/supervision/service/report/impl/ReportProblemTypeStatsServiceImpl.java diff --git a/src/main/java/com/biutag/supervision/controller/work/NegativeReportController.java b/src/main/java/com/biutag/supervision/controller/work/NegativeReportController.java index c268a6d..fd2279f 100644 --- a/src/main/java/com/biutag/supervision/controller/work/NegativeReportController.java +++ b/src/main/java/com/biutag/supervision/controller/work/NegativeReportController.java @@ -1,28 +1,48 @@ package com.biutag.supervision.controller.work; +import com.biutag.supervision.common.UserContextHolder; +import com.biutag.supervision.pojo.Result; +import com.biutag.supervision.pojo.entity.NegativeTask; +import com.biutag.supervision.pojo.model.UserAuth; import com.biutag.supervision.pojo.param.NegativeQueryParam; +import com.biutag.supervision.service.NegativeTaskService; import com.biutag.supervision.service.negativeReport.NegativeReportService; import io.swagger.v3.oas.annotations.Operation; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.io.UnsupportedEncodingException; - +@Slf4j @RequiredArgsConstructor @RequestMapping("negative") @RestController public class NegativeReportController { private final NegativeReportService negativeReportService; + private final NegativeTaskService negativeTaskService; + @Deprecated @Operation(summary = "生成研判分析报告") @PostMapping("/generateReport") - public void generateReport(@RequestBody NegativeQueryParam request, HttpServletResponse response) throws UnsupportedEncodingException { + public void generateReport(@RequestBody NegativeQueryParam request, HttpServletResponse response) { negativeReportService.generateReport(request, response); } + @Operation(summary = "生成研判分析报告任务") + @PostMapping("/export/report") + public Result generateReport(@RequestBody NegativeQueryParam request) { + request.setCurrent(1); + request.setSize(1000000); + UserAuth currentUser = UserContextHolder.getCurrentUser(); + request.setCurrentUser(currentUser); + NegativeTask negativeTask = negativeTaskService.saveReportTask(request); + negativeReportService.exportReport(request, negativeTask.getId()); + + return Result.success(); + } + } diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/OverviewSection.java b/src/main/java/com/biutag/supervision/pojo/dto/report/OverviewSection.java index f9cec7c..f336018 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/OverviewSection.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/OverviewSection.java @@ -76,6 +76,9 @@ public class OverviewSection { @Schema(description = "问责问题数", example = "5") private Integer accountabilityProblemTotal; + @Schema(description = "问责率 问责问题条数/办结的条数") + private BigDecimal accountabilityNegativeRate; + @Schema(description = "问责总人次", example = "58") private Integer accountabilityTotal; diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsRequestDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsRequestDTO.java index 7aa7bb8..cd3bbad 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsRequestDTO.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsRequestDTO.java @@ -1,5 +1,6 @@ package com.biutag.supervision.pojo.dto.report.accountability; +import com.biutag.supervision.pojo.model.UserAuth; import com.biutag.supervision.pojo.vo.NegativeQueryVo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; @@ -27,5 +28,8 @@ public class ReportAccountabilityStatsRequestDTO { @Schema(description = "原始问题列表") private List negativeQueryVoList; + private UserAuth currentUser; + + } \ No newline at end of file diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsResponseDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsResponseDTO.java index b6acb1b..29c88a0 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsResponseDTO.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/accountability/ReportAccountabilityStatsResponseDTO.java @@ -9,6 +9,7 @@ import lombok.Setter; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,12 +49,12 @@ public class ReportAccountabilityStatsResponseDTO { private List unitBlames = new ArrayList<>(); @Schema(description = "问责人员TOP3") - private List topPersons; + private List topPersons = new ArrayList<>(); @Schema(description = "个人问责类型次数map") - private Map personalTypeCountMap; + private Map personalTypeCountMap = new HashMap<>(); @Schema(description = "单位问责类型次数map") - private Map unitTypeCountMap; + private Map unitTypeCountMap = new HashMap<>(); } \ No newline at end of file diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineDetailSection.java b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineDetailSection.java index 82f53d5..f54a6e4 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineDetailSection.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineDetailSection.java @@ -40,6 +40,9 @@ public class BusinessLineDetailSection { @Schema(description = "查实率") private BigDecimal verifiedRate; + @Schema(description = "问责问题条数") + private int accountabilityNegativeCount; + @Schema(description = "问责总次数") private Integer accountabilityTotal; diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLinePersonRankItem.java b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLinePersonRankItem.java index 3089920..060aae5 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLinePersonRankItem.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLinePersonRankItem.java @@ -13,6 +13,10 @@ import java.math.BigDecimal; @NoArgsConstructor public class BusinessLinePersonRankItem { + + @Schema(description = "序号") + private Integer orderNo; + @Schema(description = "人员姓名") private String personName; diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineRankItem.java b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineRankItem.java index 83a968c..484b005 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineRankItem.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/businessLine/BusinessLineRankItem.java @@ -15,6 +15,9 @@ import java.math.BigDecimal; @NoArgsConstructor public class BusinessLineRankItem { + @Schema(description = "序号") + private Integer orderNo; + @Schema(description = "名称,如 执法程序问题 / 某某派出所") private String name; diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/closed/ClosedStatsCalcRequestDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/report/closed/ClosedStatsCalcRequestDTO.java index 619b82c..54d2365 100644 --- a/src/main/java/com/biutag/supervision/pojo/dto/report/closed/ClosedStatsCalcRequestDTO.java +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/closed/ClosedStatsCalcRequestDTO.java @@ -2,7 +2,9 @@ package com.biutag.supervision.pojo.dto.report.closed; import com.biutag.supervision.pojo.vo.NegativeQueryVo; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import java.util.ArrayList; @@ -11,6 +13,8 @@ import java.util.List; @Getter @Setter @Schema(description = "办结统计计算请求DTO") +@AllArgsConstructor +@NoArgsConstructor public class ClosedStatsCalcRequestDTO { @Schema(description = "待统计的问题数据列表") diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsRequestDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsRequestDTO.java new file mode 100644 index 0000000..8e2eb02 --- /dev/null +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsRequestDTO.java @@ -0,0 +1,24 @@ +package com.biutag.supervision.pojo.dto.report.problemType; + +import com.biutag.supervision.pojo.vo.NegativeQueryVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @ClassName ReportProblemTypeStatsRequestDTO + * @Description TODO + * @Author shihao + * @Date 2026/3/11 14:39 + */ +@Getter +@Setter +@Schema(description = "问题统计请求DTO") +public class ReportProblemTypeStatsRequestDTO { + + @Schema(description = "原始问题列表") + private List negativeQueryVoList; + +} diff --git a/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsResponseDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsResponseDTO.java new file mode 100644 index 0000000..314d9b4 --- /dev/null +++ b/src/main/java/com/biutag/supervision/pojo/dto/report/problemType/ReportProblemTypeStatsResponseDTO.java @@ -0,0 +1,24 @@ +package com.biutag.supervision.pojo.dto.report.problemType; + +import com.biutag.supervision.pojo.dto.report.businessLine.BusinessLineRankItem; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @ClassName ReportProblemTypeStatsResponseDTO + * @Description TODO + * @Author shihao + * @Date 2026/3/11 14:42 + */ +@Getter +@Setter +@Schema(description = "问题统计响应DTO") +public class ReportProblemTypeStatsResponseDTO { + + @Schema(description = "问题类型TOP列表") + private List topProblemTypes; + +} diff --git a/src/main/java/com/biutag/supervision/pojo/param/NegativeQueryParam.java b/src/main/java/com/biutag/supervision/pojo/param/NegativeQueryParam.java index a2a4f7f..4569db6 100644 --- a/src/main/java/com/biutag/supervision/pojo/param/NegativeQueryParam.java +++ b/src/main/java/com/biutag/supervision/pojo/param/NegativeQueryParam.java @@ -2,6 +2,7 @@ package com.biutag.supervision.pojo.param; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.annotation.TableField; +import com.biutag.supervision.pojo.model.UserAuth; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; @@ -116,6 +117,8 @@ public class NegativeQueryParam extends BasePage { @TableField("issuingDepartName") private String issuingDepartName; + private UserAuth currentUser; + public NegativeQueryParam newQueryParam() { NegativeQueryParam target = new NegativeQueryParam(); diff --git a/src/main/java/com/biutag/supervision/pojo/param/PoliceQueryParam.java b/src/main/java/com/biutag/supervision/pojo/param/PoliceQueryParam.java index cccc0a2..0677d5e 100644 --- a/src/main/java/com/biutag/supervision/pojo/param/PoliceQueryParam.java +++ b/src/main/java/com/biutag/supervision/pojo/param/PoliceQueryParam.java @@ -1,5 +1,6 @@ package com.biutag.supervision.pojo.param; +import com.biutag.supervision.pojo.model.UserAuth; import lombok.Getter; import lombok.Setter; @@ -25,4 +26,6 @@ public class PoliceQueryParam extends BasePage { private List idCodes; //启动or private Boolean isOr; + + private UserAuth currentUser; } diff --git a/src/main/java/com/biutag/supervision/pojo/vo/NegativeQueryVo.java b/src/main/java/com/biutag/supervision/pojo/vo/NegativeQueryVo.java index 789d7b5..466e481 100644 --- a/src/main/java/com/biutag/supervision/pojo/vo/NegativeQueryVo.java +++ b/src/main/java/com/biutag/supervision/pojo/vo/NegativeQueryVo.java @@ -209,4 +209,7 @@ public class NegativeQueryVo { @Schema(description = "核查结论code") private String checkStatusCode; + @Schema(description = "二级部门ID") + private String secondInvolveDepartId; + } diff --git a/src/main/java/com/biutag/supervision/repository/supdepart/SupDepartResourceService.java b/src/main/java/com/biutag/supervision/repository/supdepart/SupDepartResourceService.java index b322d84..acf209c 100644 --- a/src/main/java/com/biutag/supervision/repository/supdepart/SupDepartResourceService.java +++ b/src/main/java/com/biutag/supervision/repository/supdepart/SupDepartResourceService.java @@ -123,5 +123,27 @@ public class SupDepartResourceService extends BaseDAO { .collect(Collectors.toSet()); } + /** + * 查询所有二级单位,返回 id -> shortName + */ + public Map getAllSecondDepartNameMap() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SupDepart::getLevel, "2"); + + List secondDeparts = supDepartMapper.selectList(wrapper); + if (CollectionUtil.isEmpty(secondDeparts)) { + return Collections.emptyMap(); + } + + return secondDeparts.stream() + .filter(depart -> StrUtil.isNotBlank(depart.getId())) + .collect(Collectors.toMap( + SupDepart::getId, + SupDepart::getShortName, + (a, b) -> a, + LinkedHashMap::new + )); + } + } diff --git a/src/main/java/com/biutag/supervision/service/NegativeQueryService.java b/src/main/java/com/biutag/supervision/service/NegativeQueryService.java index 57cbe4a..bfa3acd 100644 --- a/src/main/java/com/biutag/supervision/service/NegativeQueryService.java +++ b/src/main/java/com/biutag/supervision/service/NegativeQueryService.java @@ -37,7 +37,10 @@ public class NegativeQueryService { private final SupDepartService departService; public Page page(NegativeQueryParam param) { - UserAuth user = UserContextHolder.getCurrentUser(); + UserAuth user = param.getCurrentUser(); + if (user == null) { + user = UserContextHolder.getCurrentUser(); + } if (!AppConstants.USER_TYPE_SUPER.equals(user.getUserType()) && (user.getRoleCodes().isEmpty() || user.getAuthSources().isEmpty() || user.getAuthDepartIds().isEmpty())) { return new Page().setTotal(0).setRecords(new ArrayList<>()); } @@ -212,7 +215,7 @@ public class NegativeQueryService { NegativeQueryVo vo = new NegativeQueryVo(); BeanUtils.copyProperties(item, vo); if (Objects.nonNull(item.getFirstDistributeTime()) && !ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())) { - vo.setRemainingDuration(TimeUtil.getRemainingDuration(item.getFirstDistributeTime(), item.getMaxSignDuration(), item.getMaxHandleDuration(), item.getExtensionDays(), item.getFlowKey())); +// vo.setRemainingDuration(TimeUtil.getRemainingDuration(item.getFirstDistributeTime(), item.getMaxSignDuration(), item.getMaxHandleDuration(), item.getExtensionDays(), item.getFlowKey())); } return vo; }).toList(); diff --git a/src/main/java/com/biutag/supervision/service/NegativeTaskService.java b/src/main/java/com/biutag/supervision/service/NegativeTaskService.java index 1f560b2..1ee8dbb 100644 --- a/src/main/java/com/biutag/supervision/service/NegativeTaskService.java +++ b/src/main/java/com/biutag/supervision/service/NegativeTaskService.java @@ -18,6 +18,7 @@ import com.biutag.supervision.pojo.dto.*; import com.biutag.supervision.pojo.entity.*; import com.biutag.supervision.pojo.model.ModelClueTaskDepartModel; import com.biutag.supervision.pojo.model.UserAuth; +import com.biutag.supervision.pojo.param.NegativeQueryParam; import com.biutag.supervision.pojo.param.NegativeTaskQueryParam; import com.biutag.supervision.pojo.vo.ExportNegativeBlameLeaderVo; import com.biutag.supervision.pojo.vo.ExportNegativeBlameVo; @@ -33,6 +34,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -87,6 +90,32 @@ public class NegativeTaskService extends ServiceImpl data, String negativeTaskId) { List suspectProblem = dictDataService.listByDictType("suspectProblem"); diff --git a/src/main/java/com/biutag/supervision/service/SupPoliceService.java b/src/main/java/com/biutag/supervision/service/SupPoliceService.java index 806d5e1..9b8285d 100644 --- a/src/main/java/com/biutag/supervision/service/SupPoliceService.java +++ b/src/main/java/com/biutag/supervision/service/SupPoliceService.java @@ -33,7 +33,10 @@ public class SupPoliceService extends ServiceImpl { public Page page(PoliceQueryParam param) { QueryWrapper queryWrapper = new QueryWrapper<>(); - UserAuth user = UserContextHolder.getCurrentUser(); + UserAuth user = param.getCurrentUser(); + if (user == null) { + user = UserContextHolder.getCurrentUser(); + } // 权限 if (!AppConstants.USER_TYPE_SUPER.equals(user.getUserType()) && !user.getRoleCodes().contains(RoleCodeEnum.FIRST_ADMIN.getCode())) { if (user.getAuthDepartIds().isEmpty() || user.getRoleCodes().isEmpty()) { diff --git a/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportService.java b/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportService.java index dc83acc..e302ce8 100644 --- a/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportService.java +++ b/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportService.java @@ -1,9 +1,12 @@ package com.biutag.supervision.service.negativeReport; +import com.biutag.supervision.pojo.model.UserAuth; import com.biutag.supervision.pojo.param.NegativeQueryParam; import jakarta.servlet.http.HttpServletResponse; public interface NegativeReportService { void generateReport(NegativeQueryParam request, HttpServletResponse response); + + void exportReport(NegativeQueryParam request, String id); } diff --git a/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportServiceImpl.java b/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportServiceImpl.java index 5809329..0db55ab 100644 --- a/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/negativeReport/NegativeReportServiceImpl.java @@ -1,7 +1,12 @@ package com.biutag.supervision.service.negativeReport; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.biutag.supervision.constants.enums.NegativeTaskStatusEnum; import com.biutag.supervision.pojo.dto.report.ReportViewModel; +import com.biutag.supervision.pojo.entity.NegativeTask; import com.biutag.supervision.pojo.param.NegativeQueryParam; +import com.biutag.supervision.service.FileService; +import com.biutag.supervision.service.NegativeTaskService; import com.biutag.supervision.service.report.ReportDataService; import com.deepoove.poi.XWPFTemplate; import io.swagger.v3.oas.annotations.media.Schema; @@ -10,12 +15,16 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; /** * @ClassName NegativeReportServiceImpl @@ -32,49 +41,136 @@ public class NegativeReportServiceImpl implements NegativeReportService { private final ReportDataService reportDataService; + private final NegativeTaskService negativeTaskService; + + private final FileService fileService; + public void generateReport(NegativeQueryParam request, HttpServletResponse response) { request.setCurrent(1); request.setSize(1000000); - // 你要返回的模板路径 + log.info("开始生成报告, crtTime={}, request={}", request.getCrtTime(), request); + String templatePath = "static/templates/督审一体化平台研判分析报告.docx"; ClassPathResource resource = new ClassPathResource(templatePath); + if (!resource.exists()) { - // 资源不存在,返回 404 + log.warn("报告模板不存在, templatePath={}", templatePath); response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.setContentType("application/json;charset=UTF-8"); try { response.getWriter().write("{\"message\":\"模板文件不存在: " + templatePath + "\"}"); - } catch (IOException ignored) {} + } catch (IOException ignored) { + } return; } - // 1) 准备模板变量(含图表) - ReportViewModel vm = reportDataService.buildViewModel(request); - // 2) 响应头(docx 正确类型) + String downloadName = "督审一体化平台研判分析报告.docx"; String encoded = URLEncoder.encode(downloadName, StandardCharsets.UTF_8).replaceAll("\\+", "%20"); String contentDisposition = "attachment; filename=\"" + encoded + "\"; filename*=UTF-8''" + encoded; - response.reset(); - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Disposition", contentDisposition); - response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); - response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); - response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - - // 3) 关键:compile + render + write(不要 StreamUtils.copy) try (InputStream in = resource.getInputStream(); - XWPFTemplate template = XWPFTemplate.compile(in).render(vm); - ServletOutputStream out = response.getOutputStream()) { + XWPFTemplate template = XWPFTemplate.compile(in); + ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + + ReportViewModel vm = reportDataService.buildViewModel(request); + + template.render(vm); + + template.write(bos); + byte[] bytes = bos.toByteArray(); + log.info("报告生成完成,准备输出, size={} bytes", bytes.length); + + response.reset(); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Disposition", contentDisposition); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + response.setContentLengthLong(bytes.length); - template.write(out); + ServletOutputStream out = response.getOutputStream(); + out.write(bytes); out.flush(); + log.info("报告下载成功, fileName={}, size={} bytes", downloadName, bytes.length); } catch (Exception e) { log.error("生成/下载报告失败", e); - // 如果你们有统一异常处理,可以直接抛出去 - // throw new RuntimeException("生成报告失败", e); + if (!response.isCommitted()) { + try { + response.reset(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"message\":\"生成报告失败\"}"); + } catch (IOException ioException) { + log.error("回写失败响应异常", ioException); + } + } + } + } + + + + @Async + public void exportReport(NegativeQueryParam request, String negativeTaskId) { + try { + byte[] bytes = buildReportBytes(request); + + String filePath = fileService.upload( + new ByteArrayInputStream(bytes), + bytes.length, + ".docx" + ); + + negativeTaskService.update( + new LambdaUpdateWrapper() + .eq(NegativeTask::getId, negativeTaskId) + .set(NegativeTask::getStatus, NegativeTaskStatusEnum.SUCCESS.getValue()) + .set(NegativeTask::getFilePath, filePath) + .set(NegativeTask::getUpdTime, LocalDateTime.now()) + ); + + log.info("报告任务成功, taskId={}, filePath={}", negativeTaskId, filePath); + } catch (Exception e) { + log.error("报告任务失败, taskId={}", negativeTaskId, e); + + negativeTaskService.update( + new LambdaUpdateWrapper() + .eq(NegativeTask::getId, negativeTaskId) + .set(NegativeTask::getStatus, NegativeTaskStatusEnum.FAIL.getValue()) + .set(NegativeTask::getUpdTime, LocalDateTime.now()) + ); + } + } + + + public byte[] buildReportBytes(NegativeQueryParam request) { + request.setCurrent(1); + request.setSize(1000000); + log.info("开始生成报告, crtTime={}, request={}", request.getCrtTime(), request); + + String templatePath = "static/templates/督审一体化平台研判分析报告.docx"; + ClassPathResource resource = new ClassPathResource(templatePath); + + if (!resource.exists()) { + throw new RuntimeException("报告模板不存在: " + templatePath); + } + + try (InputStream in = resource.getInputStream(); + XWPFTemplate template = XWPFTemplate.compile(in); + ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + + ReportViewModel vm = reportDataService.buildViewModel(request); + template.render(vm); + + template.write(bos); + byte[] bytes = bos.toByteArray(); + + log.info("报告生成完成, size={} bytes", bytes.length); + return bytes; + } catch (Exception e) { + throw new RuntimeException("生成报告失败", e); } } } diff --git a/src/main/java/com/biutag/supervision/service/report/ReportProblemTypeStatsService.java b/src/main/java/com/biutag/supervision/service/report/ReportProblemTypeStatsService.java new file mode 100644 index 0000000..d4856cf --- /dev/null +++ b/src/main/java/com/biutag/supervision/service/report/ReportProblemTypeStatsService.java @@ -0,0 +1,14 @@ +package com.biutag.supervision.service.report; + +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsRequestDTO; +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsResponseDTO; + +public interface ReportProblemTypeStatsService { + + /** + * 计算问题类型相关 + * @param reportProblemTypeStatsRequestDTO + * @return + */ + ReportProblemTypeStatsResponseDTO calculateProblemTypeStats(ReportProblemTypeStatsRequestDTO reportProblemTypeStatsRequestDTO); +} diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilitySectionServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilitySectionServiceImpl.java index a3b4ea1..206ea94 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilitySectionServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilitySectionServiceImpl.java @@ -42,6 +42,7 @@ public class ReportAccountabilitySectionServiceImpl implements ReportAccountabil List currentList = negativeQueryService.page(currentQueryParam).getRecords(); ReportAccountabilityStatsRequestDTO statsRequestDTO = new ReportAccountabilityStatsRequestDTO(); statsRequestDTO.setNegativeQueryVoList(currentList); + statsRequestDTO.setCurrentUser(currentQueryParam.getCurrentUser()); ReportAccountabilityStatsResponseDTO statsResponseDTO = reportAccountabilityStatsService.calculateAccountabilityStats(statsRequestDTO); AccountabilityOverviewSection section = new AccountabilityOverviewSection(); section.setPeriodStart(periodStart); @@ -65,6 +66,7 @@ public class ReportAccountabilitySectionServiceImpl implements ReportAccountabil List currentList = negativeQueryService.page(currentQueryParam).getRecords(); ReportAccountabilityStatsRequestDTO statsRequestDTO = new ReportAccountabilityStatsRequestDTO(); statsRequestDTO.setNegativeQueryVoList(currentList); + statsRequestDTO.setCurrentUser(currentQueryParam.getCurrentUser()); ReportAccountabilityStatsResponseDTO statsResponseDTO = reportAccountabilityStatsService.calculateAccountabilityStats(statsRequestDTO); AccountabilityUnitSection section = new AccountabilityUnitSection(); section.setTotalCount(statsResponseDTO.getUnit()); @@ -102,6 +104,7 @@ public class ReportAccountabilitySectionServiceImpl implements ReportAccountabil List currentList = negativeQueryService.page(currentQueryParam).getRecords(); ReportAccountabilityStatsRequestDTO statsRequestDTO = new ReportAccountabilityStatsRequestDTO(); statsRequestDTO.setNegativeQueryVoList(currentList); + statsRequestDTO.setCurrentUser(currentQueryParam.getCurrentUser()); ReportAccountabilityStatsResponseDTO statsResponseDTO = reportAccountabilityStatsService.calculateAccountabilityStats(statsRequestDTO); AccountabilityPersonalSection section = new AccountabilityPersonalSection(); section.setTotalCount(statsResponseDTO.getPersonal()); diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilityStatsServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilityStatsServiceImpl.java index 078509e..b769aff 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilityStatsServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportAccountabilityStatsServiceImpl.java @@ -27,6 +27,7 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @Service @@ -152,7 +153,7 @@ public class ReportAccountabilityStatsServiceImpl implements ReportAccountabilit ); // 11. 计算问责人员TOP3 - List topPersons = calculateTopPersons(personalBlames); + List topPersons = calculateTopPersons(personalBlames, requestDTO); // 问责率 responseDTO.setAccountabilityNegativeRate(accountabilityNegativeRate); @@ -211,7 +212,7 @@ public class ReportAccountabilityStatsServiceImpl implements ReportAccountabilit /** * 计算问责人员TOP3 */ - private List calculateTopPersons(List personalBlames) { + private List calculateTopPersons(List personalBlames, ReportAccountabilityStatsRequestDTO requestDTO) { if (CollUtil.isEmpty(personalBlames)) { return Collections.emptyList(); } @@ -223,6 +224,7 @@ public class ReportAccountabilityStatsServiceImpl implements ReportAccountabilit (v1, v2) -> v1, LinkedHashMap::new )); + AtomicInteger index = new AtomicInteger(1); return personalBlames.stream() .collect(Collectors.groupingBy( blame -> String.join("|", @@ -238,6 +240,7 @@ public class ReportAccountabilityStatsServiceImpl implements ReportAccountabilit PoliceQueryParam policeQueryParam = new PoliceQueryParam(); policeQueryParam.setEmpNo(blame.getBlameEmpNo()); + policeQueryParam.setCurrentUser(requestDTO.getCurrentUser()); List records = supPoliceService.page(policeQueryParam).getRecords(); String unitName = "未知"; String identityName = "未知"; @@ -247,6 +250,7 @@ public class ReportAccountabilityStatsServiceImpl implements ReportAccountabilit } return BusinessLinePersonRankItem.builder() + .orderNo(index.getAndIncrement()) .personName(blame.getBlameName()) .unitName(unitName) .identityName(identityName) diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportBusinessLineSectionServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportBusinessLineSectionServiceImpl.java index 679d311..8e94feb 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportBusinessLineSectionServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportBusinessLineSectionServiceImpl.java @@ -11,18 +11,18 @@ import com.biutag.supervision.pojo.dto.report.base.ReportBaseQueryResponseDTO; import com.biutag.supervision.pojo.dto.report.businessLine.*; import com.biutag.supervision.pojo.dto.report.closed.ClosedStatsCalcRequestDTO; import com.biutag.supervision.pojo.dto.report.closed.ClosedStatsCalcResponseDTO; +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsRequestDTO; +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsResponseDTO; import com.biutag.supervision.pojo.entity.NegativeBlame; import com.biutag.supervision.pojo.entity.NegativeProblemRelation; import com.biutag.supervision.pojo.param.NegativeQueryParam; import com.biutag.supervision.pojo.vo.DictProblemSourceTree; import com.biutag.supervision.pojo.vo.NegativeQueryVo; +import com.biutag.supervision.repository.supdepart.SupDepartResourceService; import com.biutag.supervision.service.NegativeProblemRelationService; import com.biutag.supervision.service.NegativeQueryService; import com.biutag.supervision.service.SupDictProblemSourceService; -import com.biutag.supervision.service.report.ReportAccountabilityStatsService; -import com.biutag.supervision.service.report.ReportBaseQueryService; -import com.biutag.supervision.service.report.ReportBusinessLineSectionService; -import com.biutag.supervision.service.report.ReportClosedStatsService; +import com.biutag.supervision.service.report.*; import com.biutag.supervision.util.ChartRenderUtil; import com.biutag.supervision.util.ReportTrendUtil; import com.deepoove.poi.data.PictureRenderData; @@ -31,6 +31,7 @@ import com.deepoove.poi.data.Pictures; import jakarta.annotation.Resource; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.annotations.One; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -55,8 +56,12 @@ public class ReportBusinessLineSectionServiceImpl implements ReportBusinessLineS @Resource private ReportAccountabilityStatsService reportAccountabilityStatsService; + + @Resource - private NegativeProblemRelationService negativeProblemRelationService; + private ReportProblemTypeStatsService reportProblemTypeStatsService; + + @Override public BusinessLineOverviewSection buildBusinessLineOverviewSection(ReportBusinessLineSectionRequestDTO requestDTO) { @@ -190,69 +195,41 @@ public class ReportBusinessLineSectionServiceImpl implements ReportBusinessLineS // 问责统计 ReportAccountabilityStatsRequestDTO statsRequestDTO = new ReportAccountabilityStatsRequestDTO(); statsRequestDTO.setNegativeQueryVoList(lineList); + statsRequestDTO.setCurrentUser(request.getCurrentUser()); ReportAccountabilityStatsResponseDTO accountabilityStats = reportAccountabilityStatsService.calculateAccountabilityStats(statsRequestDTO); + section.setAccountabilityNegativeCount(accountabilityStats.getAccountabilityNegativeCount()); section.setAccountabilityTotal(accountabilityStats.getTotal()); section.setAccountabilityRate(accountabilityStats.getAccountabilityNegativeRate()); section.setPersonalAccountabilityCount(accountabilityStats.getPersonal()); section.setDepartmentAccountabilityCount(accountabilityStats.getUnit()); //问题类型 TOP3 -// Set collect = lineList.stream().map(NegativeQueryVo::getId).collect(Collectors.toSet()); -// List negativeProblemRelations = negativeProblemRelationService.list(collect); -// // 1. 分组统计,value为所有数据的List -// Map> groupedMap = negativeProblemRelations.stream() -// .collect(Collectors.groupingBy( -// relation -> relation.getOneLevelContent() + -// relation.getTwoLevelContent() + -// relation.getThreeLevelContent() -// )); -// // 2. 按List大小(数量)降序排序 -// List>> sortedList = groupedMap.entrySet().stream() -// .sorted((entry1, entry2) -> Integer.compare(entry2.getValue().size(), entry1.getValue().size())) -// .collect(Collectors.toList()); -// section.setTopProblemTypes(topProblemTypes); - + ReportProblemTypeStatsRequestDTO reportProblemTypeStatsRequestDTO = new ReportProblemTypeStatsRequestDTO(); + reportProblemTypeStatsRequestDTO.setNegativeQueryVoList(lineList); + ReportProblemTypeStatsResponseDTO reportProblemTypeStatsResponseDTO = reportProblemTypeStatsService.calculateProblemTypeStats(reportProblemTypeStatsRequestDTO); + section.setTopProblemTypes(reportProblemTypeStatsResponseDTO.getTopProblemTypes()); // 重点单位 TOP3 section.setTopUnits(closedStats.getTopUnits().stream().limit(3).toList()); // 重点人员 TOP3 section.setTopPersons(accountabilityStats.getTopPersons().stream().limit(3).toList()); - - - int currentCount = totalIssued; - int momCount = momGroup.getOrDefault(fatherBusinessLineName, Collections.emptyList()).size(); - int yoyCount = yoyGroup.getOrDefault(fatherBusinessLineName, Collections.emptyList()).size(); - section.setMomRate(ReportTrendUtil.calcRate(currentCount, momCount)); - section.setMomTrend(ReportTrendUtil.calcTrend(currentCount, momCount)); - section.setYoyRate(ReportTrendUtil.calcRate(currentCount, yoyCount)); - section.setYoyTrend(ReportTrendUtil.calcTrend(currentCount, yoyCount)); + BigDecimal currentVerifiedRate = closedStats.getVerifiedRate(); + ClosedStatsCalcRequestDTO momRequestDTO = new ClosedStatsCalcRequestDTO(); + momRequestDTO.setNegativeQueryVoList(momGroup.getOrDefault(fatherBusinessLineName, Collections.emptyList())); + ClosedStatsCalcResponseDTO momClosedStats = reportClosedStatsService.calculateClosedStats(momRequestDTO); + ClosedStatsCalcRequestDTO yoyRequestDTO = new ClosedStatsCalcRequestDTO(); + yoyRequestDTO.setNegativeQueryVoList(yoyGroup.getOrDefault(fatherBusinessLineName, Collections.emptyList())); + ClosedStatsCalcResponseDTO yoyClosedStats = reportClosedStatsService.calculateClosedStats(yoyRequestDTO); + BigDecimal momVerifiedRate = momClosedStats.getVerifiedRate(); + BigDecimal yoyVerifiedRate = yoyClosedStats.getVerifiedRate(); + section.setMomRate(ReportTrendUtil.calcDiff(currentVerifiedRate, momVerifiedRate)); + section.setMomTrend(ReportTrendUtil.calcTrend(currentVerifiedRate, momVerifiedRate)); + section.setYoyRate(ReportTrendUtil.calcDiff(currentVerifiedRate, yoyVerifiedRate)); + section.setYoyTrend(ReportTrendUtil.calcTrend(currentVerifiedRate, yoyVerifiedRate)); result.add(section); } log.info("条线明细计算结束======================================================================================="); return result; } - /** - * 根据问题名称、数量、占比构建排名项 - */ - private BusinessLineRankItem buildRankItem(String name, Integer count, String rate) { - BusinessLineRankItem item = new BusinessLineRankItem(); - item.setName(name); - item.setCount(count); - item.setRate(new BigDecimal(rate)); - return item; - } - - /** - * 根据人员、单位、身份、数量、占比构建人员排名项 - */ - private BusinessLinePersonRankItem buildPersonRankItem(String personName, String unitName, String identityName, Integer count, String rate) { - BusinessLinePersonRankItem item = new BusinessLinePersonRankItem(); - item.setPersonName(personName); - item.setUnitName(unitName); - item.setIdentityName(identityName); - item.setCount(count); - item.setRate(new BigDecimal(rate)); - return item; - } /** * 根据子级问题来源ID,解析父级业务条线名称 @@ -270,27 +247,6 @@ public class ReportBusinessLineSectionServiceImpl implements ReportBusinessLineS : StrUtil.blankToDefault(child.getLabel(), "未归类"); } - /** - * 根据问题来源ID获取当前节点名称 - */ - private String leafProblemLabel(String problemSourceCode, Map idMap) { - if (StrUtil.isBlank(problemSourceCode)) { - return "未归类"; - } - DictProblemSourceTree node = idMap.get(problemSourceCode); - if (node == null || StrUtil.isBlank(node.getLabel())) { - return "未归类"; - } - return node.getLabel(); - } - - /** - * 安全计算占比字符串 - */ - private String safePercentString(int numerator, int denominator) { - return ReportTrendUtil.percent(numerator, denominator).toPlainString(); - } - /** * 阿拉伯数字序号转中文序号 */ @@ -302,108 +258,8 @@ public class ReportBusinessLineSectionServiceImpl implements ReportBusinessLineS return String.valueOf(index); } - /** - * 构建重点人员TOP3 - */ - private List buildTopPersons(List lineList, int totalIssued) { - Map personAggMap = new LinkedHashMap<>(); - - for (NegativeQueryVo vo : lineList) { - String personName = readStringByGetter(vo, - "getInvolvePersonName", - "getPersonName", - "getPoliceName", - "getHandlePersonName", - "getName"); - - if (StrUtil.isBlank(personName)) { - continue; - } - - String unitName = firstNotBlank( - readStringByGetter(vo, "getInvolveDepartName"), - readStringByGetter(vo, "getUnitName"), - readStringByGetter(vo, "getDepartName"), - "未知单位" - ); - - String identityName = firstNotBlank( - readStringByGetter(vo, "getIdentityName"), - readStringByGetter(vo, "getInvolveIdentityName"), - readStringByGetter(vo, "getPoliceTypeName"), - readStringByGetter(vo, "getUserTypeName"), - "未知身份" - ); - - String key = personName + "||" + unitName + "||" + identityName; - PersonAgg agg = personAggMap.computeIfAbsent(key, k -> { - PersonAgg x = new PersonAgg(); - x.setPersonName(personName); - x.setUnitName(unitName); - x.setIdentityName(identityName); - x.setCount(0); - return x; - }); - agg.setCount(agg.getCount() + 1); - } - - return personAggMap.values().stream() - .sorted(Comparator.comparing(PersonAgg::getCount).reversed()) - .limit(3) - .map(one -> buildPersonRankItem( - one.getPersonName(), - one.getUnitName(), - one.getIdentityName(), - one.getCount(), - safePercentString(one.getCount(), totalIssued) - )) - .toList(); - } - - /** - * 通过反射按顺序读取字符串属性 - */ - private String readStringByGetter(Object target, String... getterNames) { - if (target == null || getterNames == null) { - return null; - } - for (String getterName : getterNames) { - try { - java.lang.reflect.Method method = target.getClass().getMethod(getterName); - Object value = method.invoke(target); - if (value instanceof String str && StrUtil.isNotBlank(str)) { - return str; - } - } catch (Exception ignored) { - } - } - return null; - } - - /** - * 返回第一个非空白字符串 - */ - private String firstNotBlank(String... values) { - if (values == null) { - return null; - } - for (String value : values) { - if (StrUtil.isNotBlank(value)) { - return value; - } - } - return null; - } - - /** - * 重点人员聚合对象 - */ - @Data - private static class PersonAgg { - private String personName; - private String unitName; - private String identityName; - private int count; + private BigDecimal defaultZero(BigDecimal value) { + return value == null ? BigDecimal.ZERO : value; } } diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportClosedStatsServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportClosedStatsServiceImpl.java index 3990754..8254f41 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportClosedStatsServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportClosedStatsServiceImpl.java @@ -7,18 +7,25 @@ import com.biutag.supervision.pojo.dto.report.businessLine.BusinessLineRankItem; import com.biutag.supervision.pojo.dto.report.closed.ClosedStatsCalcRequestDTO; import com.biutag.supervision.pojo.dto.report.closed.ClosedStatsCalcResponseDTO; import com.biutag.supervision.pojo.vo.NegativeQueryVo; +import com.biutag.supervision.repository.supdepart.SupDepartResourceService; import com.biutag.supervision.service.report.ReportClosedStatsService; import com.biutag.supervision.util.ReportTrendUtil; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @Service public class ReportClosedStatsServiceImpl implements ReportClosedStatsService { + @Resource + private SupDepartResourceService supDepartResourceService; + @Override public ClosedStatsCalcResponseDTO calculateClosedStats(ClosedStatsCalcRequestDTO requestDTO) { @@ -50,17 +57,32 @@ public class ReportClosedStatsServiceImpl implements ReportClosedStatsService { // 4. 计算重点单位 TOP3(已办结且部门名称不为空) + Map allSecondDepartNameMap = supDepartResourceService.getAllSecondDepartNameMap(); + AtomicInteger index = new AtomicInteger(1); List topUnits = closedList.stream() - .filter(one -> StrUtil.isNotBlank(one.getInvolveDepartName())) - .collect(Collectors.groupingBy(NegativeQueryVo::getInvolveDepartName, Collectors.counting())) + .filter(one -> StrUtil.isNotBlank(one.getSecondInvolveDepartId())) + .collect(Collectors.groupingBy(NegativeQueryVo::getSecondInvolveDepartId, Collectors.counting())) .entrySet().stream() + .filter(e -> StrUtil.isNotBlank(allSecondDepartNameMap.get(e.getKey()))) .sorted((a, b) -> Long.compare(b.getValue(), a.getValue())) .map(e -> new BusinessLineRankItem( - e.getKey(), + index.getAndIncrement(), + allSecondDepartNameMap.get(e.getKey()), e.getValue().intValue(), ReportTrendUtil.percent(e.getValue().intValue(), closedList.size()) )) .toList(); +// List topUnits = closedList.stream() +// .filter(one -> StrUtil.isNotBlank(one.getInvolveDepartName())) +// .collect(Collectors.groupingBy(NegativeQueryVo::getInvolveDepartName, Collectors.counting())) +// .entrySet().stream() +// .sorted((a, b) -> Long.compare(b.getValue(), a.getValue())) +// .map(e -> new BusinessLineRankItem( +// e.getKey(), +// e.getValue().intValue(), +// ReportTrendUtil.percent(e.getValue().intValue(), closedList.size()) +// )) +// .toList(); ClosedStatsCalcResponseDTO responseDTO = new ClosedStatsCalcResponseDTO(); responseDTO.setClosedCount(closedList.size()); diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportDataServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportDataServiceImpl.java index 091ef5f..40d166d 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportDataServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportDataServiceImpl.java @@ -28,18 +28,24 @@ public class ReportDataServiceImpl implements ReportDataService { // 仅负责报表各模块编排,不承载具体统计逻辑 @Override public ReportViewModel buildViewModel(NegativeQueryParam request) { + + long start = System.currentTimeMillis(); + String periodStart = TimeUtil.formatDate(request.getCrtTime().get(0)); String periodEnd = TimeUtil.formatDate(request.getCrtTime().get(1)); ReportViewModel vm = new ReportViewModel(); vm.setPeriodStart(periodStart); vm.setPeriodEnd(periodEnd); // 总体概览 + long overviewStart = System.currentTimeMillis(); ReportOverviewSectionRequestDTO overviewRequestDTO = new ReportOverviewSectionRequestDTO(); overviewRequestDTO.setNegativeQueryParam(request); overviewRequestDTO.setPeriodStart(periodStart); overviewRequestDTO.setPeriodEnd(periodEnd); vm.setOverviewSection(reportOverviewSectionService.buildOverviewSection(overviewRequestDTO)); + log.info("总体概览耗时:{} ms", System.currentTimeMillis() - overviewStart); // 业务条线 + long businessStart = System.currentTimeMillis(); ReportBusinessLineSectionRequestDTO businessLineRequestDTO = new ReportBusinessLineSectionRequestDTO(); businessLineRequestDTO.setNegativeQueryParam(request); businessLineRequestDTO.setPeriodStart(periodStart); @@ -48,13 +54,17 @@ public class ReportDataServiceImpl implements ReportDataService { vm.setBusinessLineOverviewSection(reportBusinessLineSectionService.buildBusinessLineOverviewSection(businessLineRequestDTO)); // 条线明细 vm.setBusinessLineDetailSections(reportBusinessLineSectionService.buildBusinessLineDetailSections(businessLineRequestDTO)); + log.info("业务条线耗时:{} ms", System.currentTimeMillis() - businessStart); // 单位查处情况总览 + long unitStart = System.currentTimeMillis(); ReportUnitInvestigationSectionRequestDTO unitRequestDTO = new ReportUnitInvestigationSectionRequestDTO(); unitRequestDTO.setNegativeQueryParam(request); unitRequestDTO.setPeriodStart(periodStart); unitRequestDTO.setPeriodEnd(periodEnd); vm.setUnitInvestigationOverviewSection(reportUnitInvestigationSectionService.buildUnitInvestigationOverviewSection(unitRequestDTO)); + log.info("单位查处耗时:{} ms", System.currentTimeMillis() - unitStart); // 问责情况 + long accountabilityStart = System.currentTimeMillis(); ReportAccountabilitySectionRequestDTO accountabilityRequestDTO = new ReportAccountabilitySectionRequestDTO(); accountabilityRequestDTO.setNegativeQueryParam(request); accountabilityRequestDTO.setPeriodStart(periodStart); @@ -62,6 +72,8 @@ public class ReportDataServiceImpl implements ReportDataService { vm.setAccountabilityOverviewSection(reportAccountabilitySectionService.buildAccountabilityOverviewSection(accountabilityRequestDTO)); vm.setAccountabilityUnitDetailSection(reportAccountabilitySectionService.buildAccountabilityUnitDetailSection(accountabilityRequestDTO)); vm.setAccountabilityPersonOverviewSection(reportAccountabilitySectionService.buildAccountabilityPersonalOverviewSection(accountabilityRequestDTO)); + log.info("问责统计耗时:{} ms", System.currentTimeMillis() - accountabilityStart); + log.info("报表整体生成耗时:{} ms", System.currentTimeMillis() - start); // System.out.println(1/0); return vm; } diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportOverviewSectionServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportOverviewSectionServiceImpl.java index b286146..2670dce 100644 --- a/src/main/java/com/biutag/supervision/service/report/impl/ReportOverviewSectionServiceImpl.java +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportOverviewSectionServiceImpl.java @@ -1,5 +1,6 @@ package com.biutag.supervision.service.report.impl; +import cn.hutool.core.util.StrUtil; import com.biutag.supervision.pojo.dto.report.OverviewSection; import com.biutag.supervision.pojo.dto.report.accountability.ReportAccountabilityStatsRequestDTO; import com.biutag.supervision.pojo.dto.report.accountability.ReportAccountabilityStatsResponseDTO; @@ -10,6 +11,7 @@ import com.biutag.supervision.pojo.dto.report.closed.ClosedStatsCalcResponseDTO; import com.biutag.supervision.pojo.dto.report.overview.ReportOverviewSectionRequestDTO; import com.biutag.supervision.pojo.param.NegativeQueryParam; import com.biutag.supervision.pojo.vo.NegativeQueryVo; +import com.biutag.supervision.repository.supdepart.SupDepartResourceService; import com.biutag.supervision.service.report.ReportAccountabilityStatsService; import com.biutag.supervision.service.report.ReportBaseQueryService; import com.biutag.supervision.service.report.ReportClosedStatsService; @@ -55,6 +57,9 @@ public class ReportOverviewSectionServiceImpl implements ReportOverviewSectionSe @Resource private ReportClosedStatsService reportClosedStatsService; + @Resource + private SupDepartResourceService supDepartResourceService; + /** * 构建总体概览数据 * @@ -96,9 +101,9 @@ public class ReportOverviewSectionServiceImpl implements ReportOverviewSectionSe ClosedStatsCalcResponseDTO yoyClosedStats = calculateClosedStats(yoyList); // 4. 问责统计 - ReportAccountabilityStatsResponseDTO currentAccountabilityStats = calculateAccountabilityStats(currentList); - ReportAccountabilityStatsResponseDTO momAccountabilityStats = calculateAccountabilityStats(momList); - ReportAccountabilityStatsResponseDTO yoyAccountabilityStats = calculateAccountabilityStats(yoyList); + ReportAccountabilityStatsResponseDTO currentAccountabilityStats = calculateAccountabilityStats(currentList,requestDTO); + ReportAccountabilityStatsResponseDTO momAccountabilityStats = calculateAccountabilityStats(momList, requestDTO); + ReportAccountabilityStatsResponseDTO yoyAccountabilityStats = calculateAccountabilityStats(yoyList, requestDTO); // 5. 环比/同比基础值 int currentTotal = currentList.size(); @@ -139,36 +144,67 @@ public class ReportOverviewSectionServiceImpl implements ReportOverviewSectionSe overviewSection.setVerifiedAndBasicallyVerifiedCount(currentClosedStats.getVerifiedCount() + currentClosedStats.getBasicallyVerifiedCount()); // 查实率 + log.info("设置查实率前原始数据,currentVerifiedRate={}, momVerifiedRate={}, yoyVerifiedRate={}", currentVerifiedRate, momVerifiedRate, yoyVerifiedRate); overviewSection.setVerifiedRate(currentVerifiedRate); - overviewSection.setVerifiedMomRate(ReportTrendUtil.calcRate(currentVerifiedRate, momVerifiedRate)); + overviewSection.setVerifiedMomRate(ReportTrendUtil.calcAbsDiff(currentVerifiedRate, momVerifiedRate)); overviewSection.setVerifiedMomTrend(ReportTrendUtil.calcTrend(currentVerifiedRate, momVerifiedRate)); - overviewSection.setVerifiedYoyRate(ReportTrendUtil.calcRate(currentVerifiedRate, yoyVerifiedRate)); + overviewSection.setVerifiedYoyRate(ReportTrendUtil.calcAbsDiff(currentVerifiedRate, yoyVerifiedRate)); overviewSection.setVerifiedYoyTrend(ReportTrendUtil.calcTrend(currentVerifiedRate, yoyVerifiedRate)); // 问责统计 + log.info("设置问责统计前原始数据,accountabilityProblemTotal={}, currentAccountabilityTotal={}, personalAccountability={}, unitAccountability={}, momAccountabilityTotal={}, yoyAccountabilityTotal={}", + currentAccountabilityStats.getAccountabilityNegativeCount(), + currentAccountabilityTotal, + currentAccountabilityStats.getPersonal(), + currentAccountabilityStats.getUnit(), + momAccountabilityTotal, + yoyAccountabilityTotal); overviewSection.setAccountabilityProblemTotal(currentAccountabilityStats.getAccountabilityNegativeCount()); + overviewSection.setAccountabilityNegativeRate(currentAccountabilityStats.getAccountabilityNegativeRate()); overviewSection.setAccountabilityTotal(currentAccountabilityTotal); overviewSection.setPersonalAccountability(currentAccountabilityStats.getPersonal()); overviewSection.setUnitAccountability(currentAccountabilityStats.getUnit()); - overviewSection.setAccountabilityMomRate(ReportTrendUtil.calcRate(currentAccountabilityTotal, momAccountabilityTotal)); + overviewSection.setAccountabilityMomRate(ReportTrendUtil.calcAbsDiff(currentAccountabilityStats.getAccountabilityNegativeRate(), momAccountabilityStats.getAccountabilityNegativeRate())); overviewSection.setAccountabilityMomTrend(ReportTrendUtil.calcTrend(currentAccountabilityTotal, momAccountabilityTotal)); - overviewSection.setAccountabilityYoyRate(ReportTrendUtil.calcRate(currentAccountabilityTotal, yoyAccountabilityTotal)); + overviewSection.setAccountabilityYoyRate(ReportTrendUtil.calcAbsDiff(momAccountabilityStats.getAccountabilityNegativeRate(), yoyAccountabilityStats.getAccountabilityNegativeRate())); overviewSection.setAccountabilityYoyTrend(ReportTrendUtil.calcTrend(currentAccountabilityTotal, yoyAccountabilityTotal)); // 集中问题(基于属实 + 基本属实) - Map.Entry problemEntry = ReportTrendUtil.topBy( + List> problemRankList = ReportTrendUtil.rankBy( NegativeQueryVo::getProblemSources, currentClosedStats.getVerifiedList(), currentClosedStats.getBasicallyVerifiedList() ); - overviewSection.setTopProblemProject(problemEntry != null ? problemEntry.getKey() : null); + List> problemRankListTop3 = problemRankList.stream().limit(3).toList(); + String topProblemProject = ""; + for (Map.Entry stringLongEntry : problemRankListTop3) { + topProblemProject += stringLongEntry.getKey() +"、"; + } + if (StrUtil.isNotBlank(topProblemProject)) { + topProblemProject = StrUtil.removeSuffix(topProblemProject, "、"); + } // 重点关注单位(基于属实 + 基本属实) - Map.Entry departEntry = ReportTrendUtil.topBy(NegativeQueryVo::getInvolveDepartName, + List> departRankList = ReportTrendUtil.rankBy( + NegativeQueryVo::getSecondInvolveDepartId, currentClosedStats.getVerifiedList(), currentClosedStats.getBasicallyVerifiedList() ); - overviewSection.setTopProblemUnit(departEntry != null ? departEntry.getKey() : null); + Map allSecondDepartNameMap = supDepartResourceService.getAllSecondDepartNameMap(); + List> departRankListTop3 = departRankList.stream().limit(3).toList(); + String topProblemUnit = ""; + for (Map.Entry stringLongEntry : departRankListTop3) { + String departName = allSecondDepartNameMap.get(stringLongEntry.getKey()); + if (StrUtil.isNotBlank(departName)) { + topProblemUnit += departName + "、"; + } + } + if (StrUtil.isNotBlank(topProblemUnit)) { + topProblemUnit = StrUtil.removeSuffix(topProblemUnit, "、"); + } + + overviewSection.setTopProblemProject(topProblemProject); + overviewSection.setTopProblemUnit(topProblemUnit); log.info("总览数据计算结束======================================================================================="); return overviewSection; } @@ -183,9 +219,10 @@ public class ReportOverviewSectionServiceImpl implements ReportOverviewSectionSe /** * 统一计算问责统计 */ - private ReportAccountabilityStatsResponseDTO calculateAccountabilityStats(List list) { + private ReportAccountabilityStatsResponseDTO calculateAccountabilityStats(List list, ReportOverviewSectionRequestDTO reportOverviewSectionRequestDTO) { ReportAccountabilityStatsRequestDTO requestDTO = new ReportAccountabilityStatsRequestDTO(); requestDTO.setNegativeQueryVoList(list); + requestDTO.setCurrentUser(reportOverviewSectionRequestDTO.getNegativeQueryParam().getCurrentUser()); return reportAccountabilityStatsService.calculateAccountabilityStats(requestDTO); } diff --git a/src/main/java/com/biutag/supervision/service/report/impl/ReportProblemTypeStatsServiceImpl.java b/src/main/java/com/biutag/supervision/service/report/impl/ReportProblemTypeStatsServiceImpl.java new file mode 100644 index 0000000..8fdf924 --- /dev/null +++ b/src/main/java/com/biutag/supervision/service/report/impl/ReportProblemTypeStatsServiceImpl.java @@ -0,0 +1,102 @@ +package com.biutag.supervision.service.report.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.biutag.supervision.constants.enums.ProcessingStatusEnum; +import com.biutag.supervision.pojo.dto.report.accountability.ReportAccountabilityStatsResponseDTO; +import com.biutag.supervision.pojo.dto.report.businessLine.BusinessLineRankItem; +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsRequestDTO; +import com.biutag.supervision.pojo.dto.report.problemType.ReportProblemTypeStatsResponseDTO; +import com.biutag.supervision.pojo.entity.NegativeProblemRelation; +import com.biutag.supervision.pojo.vo.NegativeQueryVo; +import com.biutag.supervision.service.NegativeProblemRelationService; +import com.biutag.supervision.service.report.ReportProblemTypeStatsService; +import com.biutag.supervision.util.ReportTrendUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * @ClassName ReportProblemTypeStatsServiceImpl + * @Description ReportProblemTypeStatsServiceImpl + * @Author shihao + * @Date 2026/3/11 14:37 + */ +@Service +@Slf4j +public class ReportProblemTypeStatsServiceImpl implements ReportProblemTypeStatsService { + + + @Resource + private NegativeProblemRelationService negativeProblemRelationService; + + @Override + public ReportProblemTypeStatsResponseDTO calculateProblemTypeStats(ReportProblemTypeStatsRequestDTO requestDTO) { + ReportProblemTypeStatsResponseDTO responseDTO = new ReportProblemTypeStatsResponseDTO(); + if (requestDTO == null || CollUtil.isEmpty(requestDTO.getNegativeQueryVoList())) { + return responseDTO; + } + // 1. 过滤办结问题 + List closedNegativeList = requestDTO.getNegativeQueryVoList().stream() + .filter(one -> ProcessingStatusEnum.completed.name().equals(one.getProcessingStatus())) + .toList(); + if (CollUtil.isEmpty(closedNegativeList)) { + return responseDTO; + } + // 2. 查询问题类型关联数据 + Set negativeIds = closedNegativeList.stream() + .map(NegativeQueryVo::getId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + List relationList = negativeProblemRelationService.list(negativeIds); + if (CollUtil.isEmpty(relationList)) { + return responseDTO; + } + // 3. 按问题ID去重,每个问题只保留一条问题类型记录 + List distinctRelationList = relationList.stream() + .collect(Collectors.collectingAndThen( + Collectors.toMap( + NegativeProblemRelation::getNegativeId, + relation -> relation, + (first, second) -> first + ), + map -> new ArrayList<>(map.values()) + )); + + // 4. 按问题类型分组统计数量 + Map problemTypeCountMap = distinctRelationList.stream() + .collect(Collectors.groupingBy( + this::buildProblemTypeName, + Collectors.counting() + )); + // 5. 取TOP3 + AtomicInteger index = new AtomicInteger(1); + List topProblemTypes = problemTypeCountMap.entrySet().stream() + .sorted((a, b) -> Long.compare(b.getValue(), a.getValue())) + .limit(3) + .map(entry -> new BusinessLineRankItem( + index.getAndIncrement(), + entry.getKey(), + entry.getValue().intValue(), + ReportTrendUtil.percent(entry.getValue().intValue(), distinctRelationList.size()) + )) + .toList(); + responseDTO.setTopProblemTypes(topProblemTypes); + return responseDTO; + } + + /** + * 构建问题类型展示名称:一级-二级-三级 + */ + private String buildProblemTypeName(NegativeProblemRelation relation) { + return String.join("/", + Objects.toString(relation.getOneLevelContent(), ""), + Objects.toString(relation.getTwoLevelContent(), ""), + Objects.toString(relation.getThreeLevelContent(), "") + ); + } +} diff --git a/src/main/java/com/biutag/supervision/util/ReportTrendUtil.java b/src/main/java/com/biutag/supervision/util/ReportTrendUtil.java index 28633f8..90562e5 100644 --- a/src/main/java/com/biutag/supervision/util/ReportTrendUtil.java +++ b/src/main/java/com/biutag/supervision/util/ReportTrendUtil.java @@ -107,6 +107,26 @@ public class ReportTrendUtil { return TrendEnum.STABLE; } + + @SafeVarargs + public static List> rankBy(Function mapper, List... lists) { + return Arrays.stream(lists) + .filter(Objects::nonNull) + .flatMap(List::stream) + .map(mapper) + .filter(Objects::nonNull) + .collect(Collectors.groupingBy( + Function.identity(), + Collectors.counting() + )) + .entrySet() + .stream() + .sorted((a, b) -> Long.compare(b.getValue(), a.getValue())) + .toList(); + } + + + @SafeVarargs public static Map.Entry topBy(Function mapper, List... lists) { @@ -124,5 +144,30 @@ public class ReportTrendUtil { .orElse(null); } + /** + * 计算百分比差值 + * 例如: + * 上月64%,本月40%,结果=-24.00 + */ + public static BigDecimal calcDiff(BigDecimal current, BigDecimal prev) { + if (current == null) { + current = BigDecimal.ZERO; + } + if (prev == null) { + prev = BigDecimal.ZERO; + } + + return current.subtract(prev).setScale(2, RoundingMode.HALF_UP); + } + + /** + * 计算百分比绝对变化值 + * 例如: + * 上月64%,本月40%,结果=24.00 + */ + public static BigDecimal calcAbsDiff(BigDecimal current, BigDecimal prev) { + return calcDiff(current, prev).abs().setScale(2, RoundingMode.HALF_UP); + } + } diff --git a/src/main/resources/static/templates/督审一体化平台研判分析报告.docx b/src/main/resources/static/templates/督审一体化平台研判分析报告.docx index dcd537fa762e430670ded58074f77700450b2adc..dacb4595238fe7c9082da7b6426461cd0367d2e4 100644 GIT binary patch delta 18451 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 Lr?UbX0U#a#10Jlb delta 12502 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 D5T}S9