From 307f6266c8fad7e2e1c9c9a9b3b8b0925c64710f Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期三, 21 一月 2026 09:54:24 +0800
Subject: [PATCH] feat: 质量管理-报表管理数据展示接口

---
 src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java |  100 ++++++++
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java         |   41 +++
 src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java             |   24 ++
 src/main/java/com/ruoyi/quality/service/QualityReportService.java          |   23 +
 src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java           |   26 ++
 src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java           |   37 +++
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java  |   28 ++
 src/main/java/com/ruoyi/quality/controller/QualityReportController.java    |   62 ++++
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java           |   29 ++
 src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java                |   39 +++
 src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java            |   24 ++
 src/main/resources/mapper/quality/QualityInspectMapper.xml                 |  284 +++++++++++++++++++++++
 12 files changed, 706 insertions(+), 11 deletions(-)

diff --git a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
index fa6820f..b3e7025 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
@@ -1,15 +1,12 @@
 package com.ruoyi.quality.controller;
 
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.quality.pojo.QualityTestStandardParam;
 import com.ruoyi.quality.service.QualityReportService;
-import com.ruoyi.quality.service.QualityTestStandardParamService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
 
 /**
  * <p>
@@ -19,6 +16,7 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-14 03:39:49
  */
+@Api(tags = "璐ㄩ噺绠$悊")
 @RestController
 @RequestMapping("/qualityReport")
 public class QualityReportController {
@@ -26,6 +24,58 @@
     @Autowired
     private QualityReportService qualityReportService;
 
+    /**
+     * 鑾峰彇妫�楠岀粺璁℃暟鎹�
+     */
+    @ApiOperation("鑾峰彇妫�楠岀粺璁℃暟鎹�")
+    @GetMapping("/getInspectStatistics")
+    public AjaxResult getInspectStatistics() {
+        return AjaxResult.success(qualityReportService.getInspectStatistics());
+    }
 
+    /**
+     * 鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�
+     */
+    @ApiOperation("鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�")
+    @GetMapping("/getPassRateStatistics")
+    public AjaxResult getPassRateStatistics() {
+        return AjaxResult.success(qualityReportService.getPassRateStatistics());
+    }
+
+    /**
+     * 鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�
+     */
+    @ApiOperation("鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�")
+    @GetMapping("/getMonthlyPassRateStatistics")
+    public AjaxResult getMonthlyPassRateStatistics(@RequestParam("year") String year) {
+        return AjaxResult.success(qualityReportService.getMonthlyPassRateStatistics(year));
+    }
+
+    /**
+     * 鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁
+     */
+    @ApiOperation("鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁")
+    @GetMapping("/getYearlyPassRateStatistics")
+    public AjaxResult getYearlyPassRateStatistics(@RequestParam("year") String year) {
+        return AjaxResult.success(qualityReportService.getYearlyPassRateStatistics(year));
+    }
+
+    /**
+     * 鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁
+     */
+    @ApiOperation("鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁")
+    @GetMapping("/getMonthlyCompletionDetails")
+    public AjaxResult getMonthlyCompletionDetails(@RequestParam("year") String year) {
+        return AjaxResult.success(qualityReportService.getMonthlyCompletionDetails(year));
+    }
+
+    /**
+     * 鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�
+     */
+    @ApiOperation("鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�")
+    @GetMapping("/getTopParameters")
+    public AjaxResult getTopParameters(@RequestParam("inspectType") Integer inspectType) {
+        return AjaxResult.success(qualityReportService.getTopParameters(inspectType));
+    }
 
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java b/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
new file mode 100644
index 0000000..9b39c94
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
@@ -0,0 +1,24 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.io.Serializable;
+
+@Data
+@ApiModel(value = "QualityInspectStatDto", description = "璐ㄩ噺妫�楠岀粺璁TO")
+public class QualityInspectStatDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)")
+    private Integer inspectType;
+
+    @ApiModelProperty(value = "鎬绘暟閲�")
+    private BigDecimal totalCount;
+
+    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    private BigDecimal completedCount;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
new file mode 100644
index 0000000..a89d25d
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
@@ -0,0 +1,29 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 璐ㄩ噺鏈堝害瀹屾垚鏄庣粏DTO
+ */
+@Data
+@ApiModel(value = "QualityMonthlyDetailDto", description = "璐ㄩ噺鏈堝害瀹屾垚鏄庣粏DTO")
+public class QualityMonthlyDetailDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鏈堜唤")
+    private String month;
+
+    @ApiModelProperty(value = "鍘熸潗鏂欐楠屽畬鎴愭暟")
+    private BigDecimal rawMaterialCount;
+
+    @ApiModelProperty(value = "杩囩▼妫�楠屽畬鎴愭暟")
+    private BigDecimal processCount;
+
+    @ApiModelProperty(value = "鍑哄巶妫�楠屽畬鎴愭暟")
+    private BigDecimal outgoingCount;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
new file mode 100644
index 0000000..9591a73
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
@@ -0,0 +1,41 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 璐ㄩ噺鏈堝害鍚堟牸鐜囩粺璁TO
+ */
+@Data
+@ApiModel(value = "QualityMonthlyPassRateDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囩粺璁TO")
+public class QualityMonthlyPassRateDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鏈堜唤(涓�鏈�, 浜屾湀...)")
+    private String month;
+
+    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)")
+    private Integer inspectType;
+
+    @ApiModelProperty(value = "鎬绘暟閲�")
+    private BigDecimal totalCount;
+
+    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    private BigDecimal completedCount;
+
+    @ApiModelProperty(value = "鍚堟牸鏁伴噺")
+    private BigDecimal qualifiedCount;
+
+    @ApiModelProperty(value = "涓嶅悎鏍兼暟閲�")
+    private BigDecimal unqualifiedCount;
+
+    @ApiModelProperty(value = "瀹屾垚鍗犳瘮")
+    private BigDecimal completionRate;
+
+    @ApiModelProperty(value = "鍚堟牸鐜囧崰姣�")
+    private BigDecimal passRate;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
new file mode 100644
index 0000000..0bdbc39
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
@@ -0,0 +1,28 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 璐ㄩ噺鏈堝害鍚堟牸鐜囧寘瑁匘TO锛堟寜鏈堝垎缁勶級
+ */
+@Data
+@ApiModel(value = "QualityMonthlyPassRateWrapperDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囧寘瑁匘TO锛堟寜鏈堝垎缁勶級")
+public class QualityMonthlyPassRateWrapperDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鏈堜唤")
+    private String month;
+
+    @ApiModelProperty(value = "鍘熸潗鏂欐楠屾暟鎹�")
+    private QualityPassRateDto rawMaterial;
+
+    @ApiModelProperty(value = "杩囩▼妫�楠屾暟鎹�")
+    private QualityPassRateDto process;
+
+    @ApiModelProperty(value = "鍑哄巶妫�楠屾暟鎹�")
+    private QualityPassRateDto outgoing;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java b/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
new file mode 100644
index 0000000..0675981
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 妫�楠屾寚鏍囩粺璁TO
+ */
+@Data
+@ApiModel(value = "QualityParameterStatDto", description = "妫�楠屾寚鏍囩粺璁TO")
+public class QualityParameterStatDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鎸囨爣鍚嶇О")
+    private String name;
+
+    @ApiModelProperty(value = "鏁伴噺")
+    private BigDecimal count;
+
+    @ApiModelProperty(value = "鐧惧垎姣�")
+    private BigDecimal percentage;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java b/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
new file mode 100644
index 0000000..354579e
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
@@ -0,0 +1,39 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 璐ㄩ噺鍚堟牸鐜囩粺璁TO
+ */
+@Data
+@ApiModel(value = "QualityPassRateDto", description = "璐ㄩ噺鍚堟牸鐜囩粺璁TO")
+public class QualityPassRateDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)")
+    private Integer inspectType;
+
+    @ApiModelProperty(value = "鎬绘暟閲�")
+    private BigDecimal totalCount;
+
+    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    private BigDecimal completedCount;
+
+    @ApiModelProperty(value = "鍚堟牸鏁伴噺")
+    private BigDecimal qualifiedCount;
+
+    @ApiModelProperty(value = "涓嶅悎鏍兼暟閲�")
+    private BigDecimal unqualifiedCount;
+
+    @ApiModelProperty(value = "瀹屾垚鍗犳瘮")
+    private BigDecimal completionRate;
+
+    @ApiModelProperty(value = "鍚堟牸鐜囧崰姣�")
+    private BigDecimal passRate;
+}
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java b/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
new file mode 100644
index 0000000..0be4e8b
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
@@ -0,0 +1,24 @@
+package com.ruoyi.quality.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 璐ㄦ鐑偣鎸囨爣缁熻缁撴灉DTO (鍗曠被鍨�)
+ */
+@Data
+@ApiModel(value = "QualityTopParameterDto", description = "璐ㄦ鐑偣鎸囨爣缁熻缁撴灉DTO (鍗曠被鍨�)")
+public class QualityTopParameterDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鎬绘娴嬮」娆℃暟閲�")
+    private BigDecimal totalCount;
+
+    @ApiModelProperty(value = "鎸囨爣缁熻鍒楄〃 (Top 4 + 鍏朵粬)")
+    private List<QualityParameterStatDto> list;
+}
diff --git a/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java b/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
index fdc57da..2958970 100644
--- a/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
+++ b/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
@@ -4,9 +4,14 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.quality.pojo.QualityTestStandard;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
+
+import com.ruoyi.quality.dto.QualityInspectStatDto;
+import com.ruoyi.quality.dto.QualityPassRateDto;
+import com.ruoyi.quality.dto.QualityMonthlyPassRateDto;
+import com.ruoyi.quality.dto.QualityMonthlyDetailDto;
+import com.ruoyi.quality.dto.QualityParameterStatDto;
 
 import java.util.List;
 
@@ -22,4 +27,34 @@
      * 鏍规嵁鐢熶骇涓昏〃ID鎵归噺鍒犻櫎杩囩▼妫�楠�
      */
     int deleteByProductMainIds(@Param("productMainIds") List<Long> productMainIds);
+
+    /**
+     * 鑾峰彇妫�楠岀粺璁℃暟鎹�
+     */
+    List<QualityInspectStatDto> getInspectStatistics();
+
+    /**
+     * 鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�
+     */
+    List<QualityPassRateDto> getPassRateStatistics();
+
+    /**
+     * 鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�
+     */
+    List<QualityMonthlyPassRateDto> getMonthlyPassRateStatistics(@Param("year") String year);
+
+    /**
+     * 鑾峰彇骞村害鍚堟牸鐜囩粺璁℃暟鎹�
+     */
+    List<QualityPassRateDto> getYearlyPassRateStatistics(@Param("year") String year);
+
+    /**
+     * 鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁
+     */
+    List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(@Param("year") String year);
+
+    /**
+     * 鑾峰彇鐑偣妫�娴嬫寚鏍� Top 4 + 鍏朵粬
+     */
+    List<QualityParameterStatDto> getTopParameters(@Param("inspectType") Integer inspectType);
 }
diff --git a/src/main/java/com/ruoyi/quality/service/QualityReportService.java b/src/main/java/com/ruoyi/quality/service/QualityReportService.java
index 4bc70f5..053359a 100644
--- a/src/main/java/com/ruoyi/quality/service/QualityReportService.java
+++ b/src/main/java/com/ruoyi/quality/service/QualityReportService.java
@@ -1,7 +1,13 @@
 package com.ruoyi.quality.service;
 
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.quality.dto.QualityInspectStatDto;
+import com.ruoyi.quality.dto.QualityPassRateDto;
+import com.ruoyi.quality.dto.QualityMonthlyDetailDto;
+import com.ruoyi.quality.dto.QualityParameterStatDto;
+import com.ruoyi.quality.dto.QualityMonthlyPassRateWrapperDto;
+import com.ruoyi.quality.dto.QualityTopParameterDto;
+
+import java.util.List;
 
 /**
  * <p>
@@ -11,6 +17,17 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-13 03:39:49
  */
-public interface QualityReportService  {
+public interface QualityReportService {
 
+    List<QualityInspectStatDto> getInspectStatistics();
+
+    List<QualityPassRateDto> getPassRateStatistics();
+
+    List<QualityMonthlyPassRateWrapperDto> getMonthlyPassRateStatistics(String year);
+
+    List<QualityPassRateDto> getYearlyPassRateStatistics(String year);
+
+    List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(String year);
+
+    QualityTopParameterDto getTopParameters(Integer inspectType);
 }
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
index dfdfaf0..ee11f8e 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
@@ -1,9 +1,109 @@
 package com.ruoyi.quality.service.impl;
 
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.quality.dto.QualityPassRateDto;
+import com.ruoyi.quality.dto.QualityInspectStatDto;
+import com.ruoyi.quality.dto.QualityMonthlyPassRateDto;
+import com.ruoyi.quality.dto.QualityMonthlyDetailDto;
+import com.ruoyi.quality.dto.QualityParameterStatDto;
+import com.ruoyi.quality.dto.QualityMonthlyPassRateWrapperDto;
+import com.ruoyi.quality.dto.QualityTopParameterDto;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.service.QualityReportService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 
 @Service
 public class QualityReportServiceImpl implements QualityReportService {
+
+    @Autowired
+    private QualityInspectMapper qualityInspectMapper;
+
+    @Override
+    public List<QualityInspectStatDto> getInspectStatistics() {
+        return qualityInspectMapper.getInspectStatistics();
+    }
+
+    @Override
+    public List<QualityPassRateDto> getPassRateStatistics() {
+        return qualityInspectMapper.getPassRateStatistics();
+    }
+
+    @Override
+    public List<QualityMonthlyPassRateWrapperDto> getMonthlyPassRateStatistics(String year) {
+        if (StringUtils.isEmpty(year)) {
+            return new ArrayList<>();
+        }
+        List<QualityMonthlyPassRateDto> flatData = qualityInspectMapper.getMonthlyPassRateStatistics(year);
+
+        // 鎸夋湀浠藉垎缁勶紝骞朵繚鎸侀『搴�
+        Map<String, List<QualityMonthlyPassRateDto>> groupedByMonth = flatData.stream()
+                .collect(Collectors.groupingBy(QualityMonthlyPassRateDto::getMonth, LinkedHashMap::new, Collectors.toList()));
+
+        List<QualityMonthlyPassRateWrapperDto> result = new ArrayList<>();
+
+        groupedByMonth.forEach((month, dtos) -> {
+            QualityMonthlyPassRateWrapperDto wrapper = new QualityMonthlyPassRateWrapperDto();
+            wrapper.setMonth(month);
+
+            for (QualityMonthlyPassRateDto dto : dtos) {
+                QualityPassRateDto passRateDto = new QualityPassRateDto();
+                BeanUtils.copyProperties(dto, passRateDto);
+
+                if (dto.getInspectType() == 0) {
+                    wrapper.setRawMaterial(passRateDto);
+                } else if (dto.getInspectType() == 1) {
+                    wrapper.setProcess(passRateDto);
+                } else if (dto.getInspectType() == 2) {
+                    wrapper.setOutgoing(passRateDto);
+                }
+            }
+            result.add(wrapper);
+        });
+
+        return result;
+    }
+
+    @Override
+    public List<QualityPassRateDto> getYearlyPassRateStatistics(String year) {
+        if (StringUtils.isEmpty(year)) {
+            return new ArrayList<>();
+        }
+        return qualityInspectMapper.getYearlyPassRateStatistics(year);
+    }
+
+    @Override
+    public List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(String year) {
+        if (StringUtils.isEmpty(year)) {
+            return new ArrayList<>();
+        }
+        return qualityInspectMapper.getMonthlyCompletionDetails(year);
+    }
+
+    @Override
+    public QualityTopParameterDto getTopParameters(Integer inspectType) {
+        if (inspectType == null) {
+            return new QualityTopParameterDto();
+        }
+        List<QualityParameterStatDto> list = qualityInspectMapper.getTopParameters(inspectType);
+
+        BigDecimal total = list.stream()
+                .map(QualityParameterStatDto::getCount)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        QualityTopParameterDto result = new QualityTopParameterDto();
+        result.setTotalCount(total);
+        result.setList(list);
+
+        return result;
+    }
 }
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index 4e8a057..ba7e8b8 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -23,7 +23,7 @@
             AND check_time &gt;= DATE_FORMAT(#{qualityInspect.entryDateStart},'%Y-%m-%d')
         </if>
         <if test="qualityInspect.entryDateEnd != null and qualityInspect.entryDateEnd != '' ">
-            AND  check_time &lt;= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d')
+            AND check_time &lt;= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d')
         </if>
         ORDER BY check_time DESC
     </select>
@@ -55,4 +55,286 @@
         </foreach>
     </delete>
 
+    <select id="getInspectStatistics" resultType="com.ruoyi.quality.dto.QualityInspectStatDto">
+        SELECT 0                                                                                   AS inspectType,
+               COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1), 0) +
+               COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0), 0) AS totalCount,
+               COALESCE((SELECT SUM(inbound_num)
+                         FROM procurement_record_storage
+                         WHERE type = 1
+                           AND quality_inspect_id != 0
+                           AND quality_inspect_id IS NOT NULL), 0) +
+               COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0), 0) AS completedCount
+        UNION ALL
+        SELECT 1                                                   AS inspectType,
+               COALESCE((SELECT SUM(inbound_num)
+                         FROM procurement_record_storage
+                         WHERE type = 2
+                           AND sales_ledger_product_id = 0), 0)    AS totalCount,
+               COALESCE((SELECT SUM(inbound_num)
+                         FROM procurement_record_storage
+                         WHERE type = 2
+                           AND sales_ledger_product_id = 0
+                           AND quality_inspect_id != 0
+                           AND quality_inspect_id IS NOT NULL), 0) AS completedCount
+        UNION ALL
+        SELECT 2                                                   AS inspectType,
+               COALESCE((SELECT SUM(inbound_num)
+                         FROM procurement_record_storage
+                         WHERE type = 2
+                           AND sales_ledger_product_id != 0), 0)   AS totalCount,
+               COALESCE((SELECT SUM(inbound_num)
+                         FROM procurement_record_storage
+                         WHERE type = 2
+                           AND sales_ledger_product_id != 0
+                           AND quality_inspect_id != 0
+                           AND quality_inspect_id IS NOT NULL), 0) AS completedCount
+    </select>
+
+    <select id="getPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
+        SELECT t.inspectType,
+               COALESCE(prs.totalCount, 0)                                            AS totalCount,
+               COALESCE(qi.completedCount, 0)                                         AS completedCount,
+               COALESCE(qi.qualifiedCount, 0)                                         AS qualifiedCount,
+               COALESCE(qi.unqualifiedCount, 0)                                       AS unqualifiedCount,
+               IF(COALESCE(prs.totalCount, 0) = 0, 0,
+                  ROUND(COALESCE(qi.completedCount, 0) / prs.totalCount * 100, 2))    AS completionRate,
+               IF(COALESCE(qi.completedCount, 0) = 0, 0,
+                  ROUND(COALESCE(qi.qualifiedCount, 0) / qi.completedCount * 100, 2)) AS passRate
+        FROM (SELECT 0 AS inspectType
+              UNION ALL
+              SELECT 1
+              UNION ALL
+              SELECT 2) t
+                 LEFT JOIN (SELECT inspect_type,
+                                   SUM(quantity)                                 AS completedCount,
+                                   SUM(IF(check_result = '鍚堟牸', quantity, 0))   AS qualifiedCount,
+                                   SUM(IF(check_result = '涓嶅悎鏍�', quantity, 0)) AS unqualifiedCount
+                            FROM quality_inspect
+                            WHERE inspect_state = 1
+                            GROUP BY inspect_type) qi
+                           ON t.inspectType = qi.inspect_type
+                 LEFT JOIN (SELECT 0           AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1),
+                                            0) +
+                                   COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0),
+                                            0) AS totalCount
+                            UNION ALL
+                            SELECT 1                                                AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num)
+                                             FROM procurement_record_storage
+                                             WHERE type = 2
+                                               AND sales_ledger_product_id = 0), 0) AS totalCount
+                            UNION ALL
+                            SELECT 2                                                 AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num)
+                                             FROM procurement_record_storage
+                                             WHERE type = 2
+                                               AND sales_ledger_product_id != 0), 0) AS totalCount) prs
+                           ON t.inspectType = prs.inspectType
+        ORDER BY t.inspectType;
+    </select>
+
+    <select id="getMonthlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityMonthlyPassRateDto">
+        WITH RECURSIVE
+            months AS (SELECT 1 AS month_num
+                       UNION ALL
+                       SELECT month_num + 1
+                       FROM months
+                       WHERE month_num &lt; 12),
+            types AS (SELECT 0 AS inspectType
+                      UNION ALL
+                      SELECT 1
+                      UNION ALL
+                      SELECT 2),
+            base AS (SELECT m.month_num, t.inspectType
+                     FROM months m,
+                          types t),
+            qi_data AS (SELECT MONTH(check_time)                                               AS month_num,
+                               inspect_type,
+                               SUM(quantity)                                                   AS completedCount,
+                               SUM(CASE WHEN check_result = '鍚堟牸' THEN quantity ELSE 0 END)   AS qualifiedCount,
+                               SUM(CASE WHEN check_result = '涓嶅悎鏍�' THEN quantity ELSE 0 END) AS unqualifiedCount
+                        FROM quality_inspect
+                        WHERE YEAR(check_time) = #{year}
+                          AND inspect_state = 1
+                        GROUP BY MONTH(check_time), inspect_type),
+            prs_data AS (SELECT month_num,
+                                inspectType,
+                                SUM(totalCount) AS totalCount
+                         FROM (SELECT MONTH(create_time) AS month_num,
+                                      0                  AS inspectType,
+                                      inbound_num        AS totalCount
+                               FROM procurement_record_storage
+                               WHERE type = 1
+                                 AND YEAR(create_time) = #{year}
+                               UNION ALL
+                               SELECT MONTH(check_time) AS month_num,
+                                      0                 AS inspectType,
+                                      quantity          AS totalCount
+                               FROM quality_unqualified
+                               WHERE inspect_type = 0
+                                 AND YEAR(check_time) = #{year}
+                               UNION ALL
+                               SELECT MONTH(create_time) AS month_num,
+                                      CASE
+                                          WHEN sales_ledger_product_id = 0 THEN 1
+                                          ELSE 2
+                                          END            AS inspectType,
+                                      inbound_num        AS totalCount
+                               FROM procurement_record_storage
+                               WHERE type = 2
+                                 AND YEAR(create_time) = #{year}) sub
+                         GROUP BY month_num, inspectType)
+        SELECT CASE b.month_num
+                   WHEN 1 THEN '涓�鏈�'
+                   WHEN 2 THEN '浜屾湀'
+                   WHEN 3 THEN '涓夋湀'
+                   WHEN 4 THEN '鍥涙湀'
+                   WHEN 5 THEN '浜旀湀'
+                   WHEN 6 THEN '鍏湀'
+                   WHEN 7 THEN '涓冩湀'
+                   WHEN 8 THEN '鍏湀'
+                   WHEN 9 THEN '涔濇湀'
+                   WHEN 10 THEN '鍗佹湀'
+                   WHEN 11 THEN '鍗佷竴鏈�'
+                   WHEN 12 THEN '鍗佷簩鏈�'
+                   END                         AS month,
+               b.inspectType,
+               COALESCE(p.totalCount, 0)       AS totalCount,
+               COALESCE(q.completedCount, 0)   AS completedCount,
+               COALESCE(q.qualifiedCount, 0)   AS qualifiedCount,
+               COALESCE(q.unqualifiedCount, 0) AS unqualifiedCount,
+               CASE
+                   WHEN COALESCE(p.totalCount, 0) = 0 THEN 0
+                   ELSE ROUND(COALESCE(q.completedCount, 0) / p.totalCount * 100, 2)
+                   END                         AS completionRate,
+               CASE
+                   WHEN COALESCE(q.completedCount, 0) = 0 THEN 0
+                   ELSE ROUND(COALESCE(q.qualifiedCount, 0) / q.completedCount * 100, 2)
+                   END                         AS passRate
+        FROM base b
+                 LEFT JOIN qi_data q ON b.month_num = q.month_num AND b.inspectType = q.inspect_type
+                 LEFT JOIN prs_data p ON b.month_num = p.month_num AND b.inspectType = p.inspectType
+        ORDER BY b.month_num, b.inspectType
+    </select>
+
+    <select id="getYearlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
+        SELECT t.inspectType,
+               COALESCE(prs.totalCount, 0)      AS totalCount,
+               COALESCE(qi.completedCount, 0)   AS completedCount,
+               COALESCE(qi.qualifiedCount, 0)   AS qualifiedCount,
+               COALESCE(qi.unqualifiedCount, 0) AS unqualifiedCount,
+               CASE
+                   WHEN COALESCE(prs.totalCount, 0) = 0 THEN 0
+                   ELSE ROUND(COALESCE(qi.completedCount, 0) / prs.totalCount * 100, 2)
+                   END                          AS completionRate,
+               CASE
+                   WHEN COALESCE(qi.completedCount, 0) = 0 THEN 0
+                   ELSE ROUND(COALESCE(qi.qualifiedCount, 0) / qi.completedCount * 100, 2)
+                   END                          AS passRate
+        FROM (SELECT 0 AS inspectType
+              UNION ALL
+              SELECT 1
+              UNION ALL
+              SELECT 2) t
+                 LEFT JOIN (SELECT inspect_type,
+                                   SUM(quantity)                                                   AS completedCount,
+                                   SUM(CASE WHEN check_result = '鍚堟牸' THEN quantity ELSE 0 END)   AS qualifiedCount,
+                                   SUM(CASE WHEN check_result = '涓嶅悎鏍�' THEN quantity ELSE 0 END) AS unqualifiedCount
+                            FROM quality_inspect
+                            WHERE YEAR(check_time) = #{year}
+                              AND inspect_state = 1
+                            GROUP BY inspect_type) qi
+                           ON t.inspectType = qi.inspect_type
+                 LEFT JOIN (SELECT 0                                               AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num)
+                                             FROM procurement_record_storage
+                                             WHERE type = 1
+                                               AND YEAR(create_time) = #{year}), 0) +
+                                   COALESCE((SELECT SUM(quantity)
+                                             FROM quality_unqualified
+                                             WHERE inspect_type = 0
+                                               AND YEAR(check_time) = #{year}), 0) AS totalCount
+                            UNION ALL
+                            SELECT 1                                                AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num)
+                                             FROM procurement_record_storage
+                                             WHERE type = 2
+                                               AND sales_ledger_product_id = 0
+                                               AND YEAR(create_time) = #{year}), 0) AS totalCount
+                            UNION ALL
+                            SELECT 2                                                AS inspectType,
+                                   COALESCE((SELECT SUM(inbound_num)
+                                             FROM procurement_record_storage
+                                             WHERE type = 2
+                                               AND sales_ledger_product_id != 0
+                                               AND YEAR(create_time) = #{year}), 0) AS totalCount) prs
+                           ON t.inspectType = prs.inspectType
+        ORDER BY t.inspectType
+    </select>
+
+    <select id="getMonthlyCompletionDetails" resultType="com.ruoyi.quality.dto.QualityMonthlyDetailDto">
+        WITH RECURSIVE
+            months AS (SELECT 1 AS month_num
+                       UNION ALL
+                       SELECT month_num + 1
+                       FROM months
+                       WHERE month_num &lt; 12),
+            qi_data AS (SELECT MONTH(check_time)                                        AS month_num,
+                               SUM(CASE WHEN inspect_type = 0 THEN quantity ELSE 0 END) AS rawMaterialCount,
+                               SUM(CASE WHEN inspect_type = 1 THEN quantity ELSE 0 END) AS processCount,
+                               SUM(CASE WHEN inspect_type = 2 THEN quantity ELSE 0 END) AS outgoingCount
+                        FROM quality_inspect
+                        WHERE YEAR(check_time) = #{year}
+                          AND inspect_state = 1
+                        GROUP BY MONTH(check_time))
+        SELECT CASE m.month_num
+                   WHEN 1 THEN '涓�鏈�'
+                   WHEN 2 THEN '浜屾湀'
+                   WHEN 3 THEN '涓夋湀'
+                   WHEN 4 THEN '鍥涙湀'
+                   WHEN 5 THEN '浜旀湀'
+                   WHEN 6 THEN '鍏湀'
+                   WHEN 7 THEN '涓冩湀'
+                   WHEN 8 THEN '鍏湀'
+                   WHEN 9 THEN '涔濇湀'
+                   WHEN 10 THEN '鍗佹湀'
+                   WHEN 11 THEN '鍗佷竴鏈�'
+                   WHEN 12 THEN '鍗佷簩鏈�'
+                   END                         AS month,
+               COALESCE(d.rawMaterialCount, 0) AS rawMaterialCount,
+               COALESCE(d.processCount, 0)     AS processCount,
+               COALESCE(d.outgoingCount, 0)    AS outgoingCount
+        FROM months m
+                 LEFT JOIN qi_data d ON m.month_num = d.month_num
+        ORDER BY m.month_num
+    </select>
+
+    <select id="getTopParameters" resultType="com.ruoyi.quality.dto.QualityParameterStatDto">
+        WITH parameter_counts AS (SELECT qip.parameter_item AS name, COUNT(*) AS count
+                                  FROM quality_inspect_param qip
+                                           JOIN quality_inspect qi ON qip.inspect_id = qi.id
+                                  WHERE qi.inspect_type = #{inspectType}
+                                  GROUP BY qip.parameter_item),
+             total AS (SELECT SUM(count) as total_count
+                       FROM parameter_counts),
+             ranked AS (SELECT name, count, ROW_NUMBER() OVER (ORDER BY count DESC) as rn
+                        FROM parameter_counts)
+        SELECT name,
+               count,
+               CASE
+                   WHEN (SELECT total_count FROM total) = 0 THEN 0
+                   ELSE ROUND(count / (SELECT total_count FROM total) * 100, 2)
+                   END as percentage
+        FROM (SELECT name, count, rn
+              FROM ranked
+              WHERE rn &lt;= 4
+              UNION ALL
+              SELECT '鍏朵粬' as name, SUM(count) as count, 5 as rn
+              FROM ranked
+              WHERE rn &gt; 4
+              HAVING count &gt; 0) sub
+        ORDER BY rn
+    </select>
 </mapper>

--
Gitblit v1.9.3