From 04dce61c02c10832665cdaf1aabf5b7e9b31da47 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期三, 21 一月 2026 16:17:19 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java           |   37 
 src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java                 |    7 
 src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java               |    3 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java          |   11 
 src/main/java/com/ruoyi/staff/mapper/StaffLeaveMapper.java                            |    5 
 src/main/java/com/ruoyi/project/system/domain/SysDept.java                            |   12 
 src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java                      |   37 +
 src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java                           |   39 +
 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/staff/dto/StaffLeaveDto.java                                  |   10 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java         |   40 -
 src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java                 |    4 
 src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java            |  100 ++++
 src/main/java/com/ruoyi/staff/service/AnalyticsService.java                           |   20 
 src/main/resources/mapper/staff/StaffOnJobMapper.xml                                  |   15 
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java                    |   41 +
 src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java                            |   14 
 src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java                        |   24 +
 src/main/java/com/ruoyi/quality/service/QualityReportService.java                     |   23 
 src/main/resources/mapper/quality/QualityTestStandardMapper.xml                       |    1 
 src/main/resources/mapper/staff/StaffLeaveMapper.xml                                  |   20 
 src/main/java/com/ruoyi/quality/controller/QualityReportController.java               |   62 ++
 src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java                          |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |   14 
 src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java                            |   18 
 src/main/java/com/ruoyi/staff/controller/AnalyticsController.java                     |   32 +
 src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java                      |   26 +
 src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java            |    8 
 src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java                       |   24 +
 src/main/resources/mapper/quality/QualityInspectMapper.xml                            |  290 ++++++++++++
 src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java                             |   19 
 src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java          |   10 
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java       |  102 ++++
 src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java                  |  145 ++++++
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                  |    7 
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java             |   28 +
 src/main/resources/mapper/system/SysDeptMapper.xml                                    |   23 
 38 files changed, 1,249 insertions(+), 93 deletions(-)

diff --git a/src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java b/src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java
index 44d3098..5c043fb 100644
--- a/src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java
+++ b/src/main/java/com/ruoyi/common/enums/StaffLeaveReason.java
@@ -25,4 +25,18 @@
     public String getInfo() {
         return info;
     }
+
+    /**
+     * 鏍规嵁code鑾峰彇鏋氫妇瀹炰緥
+     * @param code 绂昏亴鍘熷洜缂栫爜
+     * @return 瀵瑰簲鐨勬灇涓惧疄渚嬶紝鑻ユ湭鎵惧埌鍒欒繑鍥瀗ull
+     */
+    public static StaffLeaveReason getByCode(String code) {
+        for (StaffLeaveReason reason : StaffLeaveReason.values()) {
+            if (reason.getCode().equals(code)) {
+                return reason;
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
index c9d1268..2bdefa3 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.production.dto.ProductionProductMainDto;
+import com.ruoyi.production.pojo.ProductOrder;
 import com.ruoyi.production.pojo.ProductionProductMain;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -19,4 +20,11 @@
      * 鏍规嵁宸ュ崟ID鎵归噺鍒犻櫎鐢熶骇涓昏〃鏁版嵁
      */
     int deleteByWorkOrderIds(@Param("workOrderIds") List<Long> workOrderIds);
+
+    /**
+     * 鏍规嵁鎶ュ伐id鏌ヨ鐢熶骇璁㈠崟
+     * @param productMainId
+     * @return
+     */
+    ProductOrder getOrderByMainId(@Param("productMainId") Long productMainId);
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 67d8bba..5d1e454 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -75,6 +75,7 @@
 
     private QualityTestStandardParamMapper qualityTestStandardParamMapper;
     private QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
+    private QualityTestStandardMapper qualityTestStandardMapper;
 
     private QualityInspectParamMapper qualityInspectParamMapper;
 
@@ -189,12 +190,15 @@
         productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId());
         productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO);
         productionProductOutputMapper.insert(productionProductOutput);
+        /*鏂板璐ㄦ*/
         //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
         List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
         int inspectType = 1;
+        String process = productProcess.getName();//宸ュ簭
         if (productProcessRouteItem.getDragSort()==productProcessRouteItems.size()){
             //鏈�鍚庝竴閬撳伐搴忕敓鎴愬嚭鍘傛
             inspectType = 2;
+            process = null;
         }
         Product product = productMapper.selectById(productModel.getProductId());
         QualityInspect qualityInspect = new QualityInspect();
@@ -209,12 +213,12 @@
         qualityInspect.setProductMainId(productionProductMain.getId());
         qualityInspect.setProductModelId(productModel.getId());
         qualityInspectMapper.insert(qualityInspect);
-        List<QualityTestStandardBinding> qualityTestStandardBindings = qualityTestStandardBindingMapper.selectList(
-                new LambdaQueryWrapper<QualityTestStandardBinding>()
-                        .eq(QualityTestStandardBinding::getProductId, product.getId()));
-        if (qualityTestStandardBindings.size()>0){
+        List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType,process);
+        if (qualityTestStandard.size()>0){
+            qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+            qualityInspectMapper.updateById(qualityInspect);
             qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
-                    .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandardBindings.get(0).getTestStandardId()))
+                    .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandard.get(0).getId()))//榛樿鑾峰彇鏈�鏂扮殑
                     .forEach(qualityTestStandardParam -> {
                 QualityInspectParam param = new QualityInspectParam();
                 BeanUtils.copyProperties(qualityTestStandardParam, param);
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysDept.java b/src/main/java/com/ruoyi/project/system/domain/SysDept.java
index e2c6b2b..54e53a7 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysDept.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysDept.java
@@ -54,6 +54,9 @@
 
     /** 閮ㄩ棬缂栧彿 */
     private String deptNick;
+
+    /** 鍛樺伐鏁伴噺 */
+    private Integer staffCount;
     
     /** 瀛愰儴闂� */
     private List<SysDept> children = new ArrayList<SysDept>();
@@ -192,6 +195,14 @@
         this.deptNick = deptNick;
     }
 
+    public Integer getStaffCount() {
+        return staffCount;
+    }
+
+    public void setStaffCount(Integer staffCount) {
+        this.staffCount = staffCount;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -199,6 +210,7 @@
             .append("parentId", getParentId())
             .append("ancestors", getAncestors())
             .append("deptName", getDeptName())
+            .append("staffCount", getStaffCount())
             .append("orderNum", getOrderNum())
             .append("leader", getLeader())
             .append("phone", getPhone())
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index 9c115c0..257313f 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -108,6 +108,7 @@
     private final QualityInspectMapper qualityInspectMapper;
     private final QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
     private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private final QualityTestStandardMapper qualityTestStandardMapper;
     private final QualityInspectParamMapper qualityInspectParamMapper;
 
     private final ProcurementRecordMapper procurementRecordStorageMapper;
@@ -229,12 +230,12 @@
         qualityInspect.setUnit(saleProduct.getUnit());
         qualityInspect.setQuantity(saleProduct.getQuantity());
         qualityInspectMapper.insert(qualityInspect);
-        List<QualityTestStandardBinding> qualityTestStandardBindings = qualityTestStandardBindingMapper.selectList(
-                new LambdaQueryWrapper<QualityTestStandardBinding>()
-                        .eq(QualityTestStandardBinding::getProductId, saleProduct.getProductId()));
-        if (qualityTestStandardBindings.size()>0){
+        List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0,null);
+        if (qualityTestStandard.size()>0){
+            qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+            qualityInspectMapper.updateById(qualityInspect);
             qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
-                    .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandardBindings.get(0).getTestStandardId()))
+                    .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandard.get(0).getId()))
                     .forEach(qualityTestStandardParam -> {
                         QualityInspectParam param = new QualityInspectParam();
                         com.ruoyi.common.utils.bean.BeanUtils.copyProperties(qualityTestStandardParam, param);
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/controller/QualityUnqualifiedController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
index 7a42873..1cce084 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -86,5 +86,15 @@
         qualityUnqualifiedService.qualityUnqualifiedExport(response, qualityUnqualified);
     }
 
+    /**
+     * 涓嶅悎鏍肩鐞嗗鐞�
+     * @param qualityUnqualified
+     * @return
+     */
+    @PostMapping("/deal")
+    public AjaxResult deal(@RequestBody QualityUnqualified qualityUnqualified) {
+        return AjaxResult.success(qualityUnqualifiedService.deal(qualityUnqualified));
+    }
+
 
 }
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/pojo/QualityUnqualified.java b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
index 5636c2f..eaebece 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
@@ -133,5 +133,6 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-
+    @ApiModelProperty("鍏宠仈妫�娴媔d")
+    private Long inspectId;
 }
diff --git a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java b/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
index 3aed832..7cd7f79 100644
--- a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
+++ b/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
@@ -14,4 +14,7 @@
     IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified);
 
     void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified);
+
+    int deal(QualityUnqualified qualityUnqualified);
+
 }
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/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index 48b055b..1ae24e9 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -96,6 +96,7 @@
             List<QualityInspectParam> inspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId()));
             String text = inspectParams.stream().map(QualityInspectParam::getParameterItem).collect(Collectors.joining(","));
             qualityUnqualified.setDefectivePhenomena(text+"杩欎簺鎸囨爣涓瓨鍦ㄤ笉鍚堟牸");//涓嶅悎鏍肩幇璞�
+            qualityUnqualified.setInspectId(qualityInspect.getId());
             qualityUnqualifiedMapper.insert(qualityUnqualified);
         }
 
@@ -158,22 +159,26 @@
 
         }else if (qualityInspect.getInspectType() == 2) {
             //鏌ヨUnitPrice/TotalPrice
-            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectSalesLedgerProductByMainId(qualityInspect.getProductMainId());
-            ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
-            procurementRecordOutAdd.setType(2);
-            procurementRecordOutAdd.setTypeName("鐢熶骇鍑哄巶妫�楠屽悎鏍煎叆搴�");
-            procurementRecordOutAdd.setNickName(loginUser.getNickName());
-            List<Details> details = new ArrayList<>();
-            Details details1 = new Details();
-            details1.setInboundQuantity(qualityInspect.getQuantity());
-            details1.setId(Math.toIntExact(salesLedgerProduct.getId()));
-            details1.setUnitPrice(salesLedgerProduct.getTaxInclusiveUnitPrice());
-            details1.setTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice());
-            details1.setProductModelId(salesLedgerProduct.getProductModelId());
-            details.add(details1);
-            procurementRecordOutAdd.setDetails(details);
-            procurementRecordOutAdd.setQualityInspectId(qualityInspect.getId());
-            procurementRecordService.add(procurementRecordOutAdd);
+            if (ObjectUtils.isNull(qualityInspect.getProductMainId())){
+                //濡傛灉鏄墜鍔ㄦ柊澧炵殑鍑哄巶妫�
+            }else {
+                SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectSalesLedgerProductByMainId(qualityInspect.getProductMainId());
+                ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
+                procurementRecordOutAdd.setType(2);
+                procurementRecordOutAdd.setTypeName("鐢熶骇鍑哄巶妫�楠屽悎鏍煎叆搴�");
+                procurementRecordOutAdd.setNickName(loginUser.getNickName());
+                List<Details> details = new ArrayList<>();
+                Details details1 = new Details();
+                details1.setInboundQuantity(qualityInspect.getQuantity());
+                details1.setId(Math.toIntExact(salesLedgerProduct.getId()));
+                details1.setUnitPrice(salesLedgerProduct.getTaxInclusiveUnitPrice());
+                details1.setTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice());
+                details1.setProductModelId(salesLedgerProduct.getProductModelId());
+                details.add(details1);
+                procurementRecordOutAdd.setDetails(details);
+                procurementRecordOutAdd.setQualityInspectId(qualityInspect.getId());
+                procurementRecordService.add(procurementRecordOutAdd);
+            }
         }
         qualityInspect.setInspectState(1);//宸叉彁浜�
         return qualityInspectMapper.updateById(qualityInspect);
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/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
index a080dd3..796d798 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -1,10 +1,20 @@
 package com.ruoyi.quality.service.impl;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
+import com.ruoyi.production.mapper.ProductProcessRouteMapper;
+import com.ruoyi.production.mapper.ProductWorkOrderMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.pojo.*;
+import com.ruoyi.production.service.ProductOrderService;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
@@ -16,6 +26,9 @@
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 @AllArgsConstructor
@@ -23,6 +36,13 @@
 public class QualityUnqualifiedServiceImpl extends ServiceImpl<QualityUnqualifiedMapper, QualityUnqualified>  implements IQualityUnqualifiedService {
 
     private QualityUnqualifiedMapper qualityUnqualifiedMapper;
+    private IQualityInspectService qualityInspectService;
+    private ProductOrderService productOrderService;
+    private ProductionProductMainMapper productionProductMainMapper;
+    private ProductProcessRouteMapper productProcessRouteMapper;
+    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
+    private ProductWorkOrderMapper productWorkOrderMapper;
+
 
     @Override
     public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
@@ -35,4 +55,86 @@
         ExcelUtil<QualityUnqualified> util = new ExcelUtil<QualityUnqualified>(QualityUnqualified.class);
         util.exportExcel(response, qualityUnqualifieds, "涓嶅悎鏍肩鐞嗗鍑�");
     }
+
+    @Override
+    public int deal(QualityUnqualified qualityUnqualified) {
+        QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
+        QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
+        switch (qualityUnqualified.getDealResult()) {
+            case "杩斾慨":
+            case "杩斿伐":
+                //鍒ゆ柇璐ㄦ琛ㄦ槸鍚︽湁鐩稿叧鐨勬姤宸d,濡傛灉鏈夋姤宸d,閭d箞杩斿伐闇�瑕侀噸鏂板垱寤虹敓浜ц鍗曢噸鏂扮敓浜�
+                if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())){
+                    //杩斿伐闇�瑕侀噸鏂板垱寤虹敓浜ц鍗曢噸鏂扮敓浜�
+                    ProductOrder productOrder = productionProductMainMapper.getOrderByMainId(qualityInspect.getProductMainId());
+                    ProductOrder order = new ProductOrder();
+                    BeanUtils.copyProperties(productOrder, order);
+                    order.setId(null);
+                    order.setQuantity(unqualified.getQuantity());
+                    order.setCompleteQuantity(BigDecimal.ZERO);
+                    order.setStartTime(null);
+                    order.setEndTime(null);
+                    productOrderService.save(order);
+                    //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎涓昏〃
+                    ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectList(Wrappers.<ProductProcessRoute>lambdaQuery().eq(ProductProcessRoute::getProductOrderId,productOrder.getId()).orderByDesc(ProductProcessRoute::getId)).get(0);
+                    ProductProcessRoute newProcessRoute = new ProductProcessRoute();
+                    BeanUtils.copyProperties(productProcessRoute, newProcessRoute);
+                    newProcessRoute.setId(null);
+                    newProcessRoute.setProductOrderId(order.getId());
+                    productProcessRouteMapper.insert(newProcessRoute);
+                    //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎瀛愯〃
+                    List<ProductProcessRouteItem> processRouteItems = productProcessRouteItemMapper.selectList(new QueryWrapper<ProductProcessRouteItem>().lambda().eq(ProductProcessRouteItem::getProductRouteId, productProcessRoute.getId()));
+                    // 鐢熸垚褰撳墠鏃ユ湡鐨勫墠缂�锛氬勾鏈堟棩
+                    String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+                    for (ProductProcessRouteItem processRouteItem : processRouteItems) {
+                        ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
+                        BeanUtils.copyProperties(processRouteItem, productProcessRouteItem);
+                        productProcessRouteItem.setId(null);
+                        productProcessRouteItem.setProductRouteId(newProcessRoute.getId());
+                        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
+                        if (insert > 0) {
+                            // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
+                            QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
+                            queryWrapper.likeRight("work_order_no", datePrefix)
+                                    .orderByDesc("work_order_no")
+                                    .last("LIMIT 1");
+                            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
+                            int sequenceNumber = 1; // 榛樿搴忓彿
+                            if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
+                                String lastNo = lastWorkOrder.getWorkOrderNo().toString();
+                                if (lastNo.startsWith(datePrefix)) {
+                                    String seqStr = lastNo.substring(datePrefix.length());
+                                    try {
+                                        sequenceNumber = Integer.parseInt(seqStr) + 1;
+                                    } catch (NumberFormatException e) {
+                                        sequenceNumber = 1;
+                                    }
+                                }
+                            }
+                            // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
+                            String workOrderNoStr = String.format("%s%03d", datePrefix, sequenceNumber);
+                            ProductWorkOrder productWorkOrder = new ProductWorkOrder();
+                            productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
+                            productWorkOrder.setProductOrderId(order.getId());
+                            productWorkOrder.setPlanQuantity(order.getQuantity());
+                            productWorkOrder.setWorkOrderNo(workOrderNoStr);
+                            productWorkOrder.setStatus(1);
+                            productWorkOrderMapper.insert(productWorkOrder);
+                        }
+                    }
+                }
+                break;
+            case "鎶ュ簾":
+                break;
+            case "璁╂鏀捐":
+                //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
+                qualityInspect.setCheckResult("鍚堟牸");
+                qualityInspectService.submit(qualityInspect);
+                break;
+            default:
+                break;
+        }
+        qualityUnqualified.setInspectState(1);//宸插鐞�
+        return qualityUnqualifiedMapper.updateById(qualityUnqualified);
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index 4a9b51f..8fdf4f9 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -146,45 +146,7 @@
         // 2. 鎵ц鍒犻櫎鎿嶄綔
         int result = salesLedgerProductMapper.deleteBatchIds(Arrays.asList(ids));
         //鍒犻櫎瀵瑰簲鐨勭敓浜ц鍗�
-        //鎵归噺鏌ヨproductOrder
-        List<ProductOrder> productOrders = productOrderMapper.selectList(
-                new LambdaQueryWrapper<ProductOrder>()
-                        .in(ProductOrder::getProductModelId, ids)
-        );
-
-        if (!CollectionUtils.isEmpty(productOrders)) {
-            List<Long> orderIds = productOrders.stream()
-                    .map(ProductOrder::getId)
-                    .collect(Collectors.toList());
-
-            // 鎵归噺鏌ヨprocessRouteItems
-            List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList(
-                    new LambdaQueryWrapper<ProductProcessRouteItem>()
-                            .in(ProductProcessRouteItem::getProductOrderId, orderIds)
-            );
-
-            if (!CollectionUtils.isEmpty(allRouteItems)) {
-                List<Long> routeItemIds = allRouteItems.stream()
-                        .map(ProductProcessRouteItem::getId)
-                        .collect(Collectors.toList());
-
-                // 鎵归噺鍒犻櫎workOrder
-                productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
-                                .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds));
-            }
-
-            // 鎵归噺鍒犻櫎productProcessRouteItem
-            productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
-                            .in(ProductProcessRouteItem::getProductOrderId, orderIds));
-
-            // 鎵归噺鍒犻櫎productProcessRoute
-            productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>()
-                    .in(ProductProcessRoute::getProductOrderId, orderIds));
-
-            // 鎵归噺鍒犻櫎productOrder
-            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
-                    .in(ProductOrder::getProductModelId, ids));
-        }
+        deleteProductionData(Arrays.asList(ids));
 
         // 3. 瀵规瘡涓富琛↖D杩涜閲戦鏇存柊
         for (Long salesLedgerId : mainIds) {
diff --git a/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java b/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java
new file mode 100644
index 0000000..cfa802c
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java
@@ -0,0 +1,32 @@
+package com.ruoyi.staff.controller;
+
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.staff.service.AnalyticsService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/staff/analytics")
+public class AnalyticsController {
+
+    @Resource
+    private AnalyticsService analyticsService;
+
+    @GetMapping("/reason")
+    public AjaxResult staffLeaveReasonAnalytics() {
+        return AjaxResult.success(analyticsService.staffLeaveReasonAnalytics());
+    }
+
+    @GetMapping("/monthly_turnover_rate")
+    public AjaxResult getMonthlyTurnoverRateFor12Months() {
+        return AjaxResult.success(analyticsService.getMonthlyTurnoverRateFor12Months());
+    }
+
+    @GetMapping("/total_statistic")
+    public AjaxResult getTotalStatistic() {
+        return AjaxResult.success(analyticsService.getTotalStatistic());
+    }
+}
diff --git a/src/main/java/com/ruoyi/staff/dto/StaffLeaveDto.java b/src/main/java/com/ruoyi/staff/dto/StaffLeaveDto.java
index 7cdf48a..3685410 100644
--- a/src/main/java/com/ruoyi/staff/dto/StaffLeaveDto.java
+++ b/src/main/java/com/ruoyi/staff/dto/StaffLeaveDto.java
@@ -1,11 +1,8 @@
 package com.ruoyi.staff.dto;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.staff.pojo.StaffLeave;
 import lombok.Data;
-
-import java.util.Date;
 
 @Data
 public class StaffLeaveDto extends StaffLeave {
@@ -95,4 +92,11 @@
      */
     @Excel(name = "绱ф�ヨ仈绯讳汉鐢佃瘽", sort = 15)
     private String emergencyContactPhone;
+
+    private int count;
+
+    /**
+     * 绂昏亴鍘熷洜鏂囨湰
+     */
+    private String reasonText;
 }
diff --git a/src/main/java/com/ruoyi/staff/mapper/StaffLeaveMapper.java b/src/main/java/com/ruoyi/staff/mapper/StaffLeaveMapper.java
index e8d2854..170bbba 100644
--- a/src/main/java/com/ruoyi/staff/mapper/StaffLeaveMapper.java
+++ b/src/main/java/com/ruoyi/staff/mapper/StaffLeaveMapper.java
@@ -10,6 +10,7 @@
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.time.LocalDate;
 import java.util.List;
 
 
@@ -18,4 +19,8 @@
     IPage<StaffLeaveDto> staffLeaveListPage(Page page, @Param("c") StaffLeaveDto staffLeaveDto);
 
     List<StaffLeaveDto> staffLeaveList(@Param("c") StaffLeaveDto staffLeaveDto);
+
+    List<StaffLeaveDto> staffLeaveReasonAnalytics();
+
+    Integer countLeaveByMonth(@Param("monthStart") LocalDate monthStart, @Param("monthEnd") LocalDate monthEnd);
 }
diff --git a/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java b/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
index 1451487..5bd15e4 100644
--- a/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
+++ b/src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java
@@ -8,6 +8,7 @@
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.time.LocalDate;
 import java.util.List;
 
 @Mapper
@@ -16,4 +17,19 @@
     IPage<StaffOnJobDto> staffOnJobListPage(Page page, @Param("staffOnJob") StaffOnJob staffOnJob);
 
     List<StaffOnJobDto> staffOnJobList(@Param("staffOnJob") StaffOnJob staffOnJob);
-}
+
+    /**
+     * 缁熻鎸囧畾鏃ユ湡鐨勫湪鑱屽憳宸ユ暟
+     * @param date 鏃ユ湡
+     * @return 鍦ㄨ亴鍛樺伐鏁�
+     */
+    Integer countOnJobStaffByDate(@Param("date") LocalDate date);
+
+    /**
+     * 缁熻鎸囧畾鏈堜唤鐨勬柊鍏ヨ亴鍛樺伐鏁�
+     * @param monthStart 鏈堜唤寮�濮嬫棩鏈�
+     * @param monthEnd 鏈堜唤缁撴潫鏃ユ湡
+     * @return 鏂板叆鑱屽憳宸ユ暟
+     */
+    Integer countNewHireByMonth(@Param("monthStart") LocalDate monthStart, @Param("monthEnd") LocalDate monthEnd);
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/staff/service/AnalyticsService.java b/src/main/java/com/ruoyi/staff/service/AnalyticsService.java
new file mode 100644
index 0000000..ee8ff83
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/AnalyticsService.java
@@ -0,0 +1,20 @@
+package com.ruoyi.staff.service;
+
+import com.ruoyi.staff.dto.StaffLeaveDto;
+import com.ruoyi.staff.vo.MonthlyTurnoverRateVo;
+import com.ruoyi.staff.vo.TotalTurnoverRateVo;
+
+import java.util.List;
+
+public interface AnalyticsService {
+
+    List<StaffLeaveDto> staffLeaveReasonAnalytics();
+
+    List<MonthlyTurnoverRateVo> getMonthlyTurnoverRateFor12Months();
+
+    /**
+     * 鏌ヨ鎬绘祦鍔ㄧ巼銆佹祦澶辩巼浠ュ強鍦ㄨ亴鍛樺伐鏁�
+     * @return 鎬荤粺璁$粨鏋�
+     */
+    TotalTurnoverRateVo getTotalStatistic();
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
new file mode 100644
index 0000000..13a440c
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
@@ -0,0 +1,145 @@
+package com.ruoyi.staff.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.StaffLeaveReason;
+import com.ruoyi.staff.dto.StaffLeaveDto;
+import com.ruoyi.staff.mapper.StaffLeaveMapper;
+import com.ruoyi.staff.mapper.StaffOnJobMapper;
+import com.ruoyi.staff.pojo.StaffLeave;
+import com.ruoyi.staff.service.AnalyticsService;
+import com.ruoyi.staff.vo.MonthlyTurnoverRateVo;
+import com.ruoyi.staff.vo.TotalTurnoverRateVo;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+@AllArgsConstructor
+@Service
+public class AnalyticsServiceImpl extends ServiceImpl<StaffLeaveMapper, StaffLeave> implements AnalyticsService {
+    @Autowired
+    private StaffLeaveMapper staffLeaveMapper;
+
+    @Autowired
+    private StaffOnJobMapper staffOnJobMapper;
+
+    @Override
+    public List<StaffLeaveDto> staffLeaveReasonAnalytics() {
+        List<StaffLeaveDto> result = staffLeaveMapper.staffLeaveReasonAnalytics();
+        result.forEach(dto -> {
+            String reasonCode = dto.getReason();
+            StaffLeaveReason reasonEnum = StaffLeaveReason.getByCode(reasonCode);
+            if (reasonEnum != null) {
+                dto.setReasonText(reasonEnum.getInfo());
+            } else {
+                dto.setReasonText("鏈煡鍘熷洜");
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public List<MonthlyTurnoverRateVo> getMonthlyTurnoverRateFor12Months() {
+        List<MonthlyTurnoverRateVo> result = new ArrayList<>();
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
+
+        // 璁$畻杩�12涓湀鐨勬暟鎹�
+        for (int i = 11; i >= 0; i--) {
+            LocalDate currentMonth = now.minusMonths(i);
+            LocalDate monthStart = currentMonth.withDayOfMonth(1);
+            LocalDate monthEnd = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth());
+
+            MonthlyTurnoverRateVo vo = new MonthlyTurnoverRateVo();
+            vo.setMonth(currentMonth.format(monthFormatter));
+            vo.setMonthStartDate(monthStart);
+            vo.setMonthEndDate(monthEnd);
+
+            // 鏈堝垵鍛樺伐鏁帮紙涓婃湀鏈湪鑱屽憳宸ユ暟锛�
+            LocalDate lastMonthEnd = monthStart.minusDays(1);
+            Integer beginMonthStaffCount = staffOnJobMapper.countOnJobStaffByDate(lastMonthEnd);
+            vo.setBeginMonthStaffCount(beginMonthStaffCount != null ? beginMonthStaffCount : 0);
+
+            // 鏈堟湯鍛樺伐鏁�
+            Integer endMonthStaffCount = staffOnJobMapper.countOnJobStaffByDate(monthEnd);
+            vo.setEndMonthStaffCount(endMonthStaffCount != null ? endMonthStaffCount : 0);
+
+            // 鏈堝害鍏ヨ亴鍛樺伐鏁�
+            Integer newHireCount = staffOnJobMapper.countNewHireByMonth(monthStart, monthEnd);
+            vo.setNewHireCount(newHireCount != null ? newHireCount : 0);
+
+            // 鏈堝害绂昏亴鍛樺伐鏁�
+            Integer leaveCount = staffLeaveMapper.countLeaveByMonth(monthStart, monthEnd);
+            vo.setLeaveCount(leaveCount != null ? leaveCount : 0);
+
+            // 璁$畻娴佸け鐜囷細娴佸け鐜� = 鏈堝害绂昏亴鍛樺伐鏁� / 鏈堝垵鍛樺伐鏁� * 100%
+            Double turnoverRate = 0.0;
+            if (vo.getBeginMonthStaffCount() > 0) {
+                turnoverRate = (double) vo.getLeaveCount() / vo.getBeginMonthStaffCount() * 100;
+                // 淇濈暀涓や綅灏忔暟
+                turnoverRate = Math.round(turnoverRate * 100.0) / 100.0;
+            }
+            vo.setTurnoverRate(turnoverRate);
+
+            // 璁$畻娴佸姩鐜囷細娴佸姩鐜� = (鏈堝害鍏ヨ亴鍛樺伐鏁� + 鏈堝害绂昏亴鍛樺伐鏁�) / 鏈堝垵鍛樺伐鏁� * 100%
+            Double flowRate = 0.0;
+            if (vo.getBeginMonthStaffCount() > 0) {
+                flowRate = (double) (vo.getNewHireCount() + vo.getLeaveCount()) / vo.getBeginMonthStaffCount() * 100;
+                // 淇濈暀涓や綅灏忔暟
+                flowRate = Math.round(flowRate * 100.0) / 100.0;
+            }
+            vo.setFlowRate(flowRate);
+
+            result.add(vo);
+        }
+
+        return result;
+    }
+
+    @Override
+    public TotalTurnoverRateVo getTotalStatistic() {
+        TotalTurnoverRateVo result = new TotalTurnoverRateVo();
+        LocalDate now = LocalDate.now();
+
+        // 鑾峰彇褰撳墠鍦ㄨ亴鍛樺伐鏁�
+        Integer currentOnJobCount = staffOnJobMapper.countOnJobStaffByDate(now);
+        result.setCurrentOnJobCount(currentOnJobCount);
+
+        // 鑾峰彇鏈湀鐨勫紑濮嬪拰缁撴潫鏃ユ湡
+        LocalDate monthStartDate = now.withDayOfMonth(1);
+        LocalDate monthEndDate = now.withDayOfMonth(now.lengthOfMonth());
+
+        // 鑾峰彇鏈堝垵鍛樺伐鏁帮紙鍗充笂鏈堟湯鍛樺伐鏁帮級
+        Integer beginMonthStaffCount = staffOnJobMapper.countOnJobStaffByDate(monthStartDate.minusDays(1));
+
+        // 鑾峰彇鏈湀鏂板叆鑱屽憳宸ユ暟
+        Integer newHireCount = staffOnJobMapper.countNewHireByMonth(monthStartDate, monthEndDate);
+
+        // 鑾峰彇鏈湀绂昏亴鍛樺伐鏁�
+        Integer leaveCount = staffLeaveMapper.countLeaveByMonth(monthStartDate, monthEndDate);
+
+        // 璁$畻鎬绘祦鍔ㄧ巼 = (鍏ヨ亴浜烘暟 + 绂昏亴浜烘暟) / 鏈堝垵鍛樺伐鏁� * 100%
+        Double totalFlowRate = 0.0;
+        if (beginMonthStaffCount > 0) {
+            totalFlowRate = (double) (newHireCount + leaveCount) / beginMonthStaffCount * 100;
+            // 淇濈暀涓や綅灏忔暟
+            totalFlowRate = Math.round(totalFlowRate * 100.0) / 100.0;
+        }
+        result.setTotalFlowRate(totalFlowRate);
+
+        // 璁$畻鎬绘祦澶辩巼 = 绂昏亴浜烘暟 / 鏈堝垵鍛樺伐鏁� * 100%
+        Double totalTurnoverRate = 0.0;
+        if (beginMonthStaffCount > 0) {
+            totalTurnoverRate = (double) leaveCount / beginMonthStaffCount * 100;
+            // 淇濈暀涓や綅灏忔暟
+            totalTurnoverRate = Math.round(totalTurnoverRate * 100.0) / 100.0;
+        }
+        result.setTotalTurnoverRate(totalTurnoverRate);
+
+        return result;
+    }
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
index 2d30dc5..ff8faa5 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -11,6 +11,7 @@
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.staff.service.StaffLeaveService;
 import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.staff.pojo.StaffLeave;
 import org.springframework.transaction.annotation.Transactional;
@@ -23,8 +24,10 @@
 @AllArgsConstructor
 @Service
 public class StaffLeaveServiceImpl extends ServiceImpl<StaffLeaveMapper, StaffLeave> implements StaffLeaveService {
+    @Autowired
     private StaffLeaveMapper staffLeaveMapper;
 
+    @Autowired
     private StaffOnJobMapper staffOnJobMapper;
 
     //鏂板绂昏亴鍒楄〃鍒嗛〉鏌ヨ
@@ -97,6 +100,5 @@
         ExcelUtil<StaffLeaveDto> util = new ExcelUtil<StaffLeaveDto>(StaffLeaveDto.class);
         util.exportExcel(response, staffLeaves, "鍛樺伐绂昏亴瀵煎嚭");
     }
-
 }
 
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
index 6fb0cd0..9756f33 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
@@ -23,6 +23,7 @@
 import lombok.AllArgsConstructor;
 
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -39,12 +40,14 @@
 @Service
 public class StaffOnJobServiceImpl extends ServiceImpl<StaffOnJobMapper, StaffOnJob>  implements IStaffOnJobService {
 
-
+    @Autowired
     private StaffOnJobMapper staffOnJobMapper;
-
+    @Autowired
     private SysPostMapper sysPostMapper;
 
+    @Autowired
     private StaffContractMapper staffContractMapper;
+    @Autowired
     private StaffLeaveMapper staffLeaveMapper;
 
 
diff --git a/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java b/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java
new file mode 100644
index 0000000..90f9c69
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java
@@ -0,0 +1,39 @@
+package com.ruoyi.staff.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+/**
+ * 鏈堝害鍛樺伐娴佸姩鐜囧拰娴佸け鐜囩粺璁O
+ */
+@Data
+public class MonthlyTurnoverRateVo {
+    @ApiModelProperty("鏈堜唤")
+    private String month;
+
+    @ApiModelProperty("鏈堝垵鍛樺伐鏁�")
+    private Integer beginMonthStaffCount;
+
+    @ApiModelProperty("鏈堟湯鍛樺伐鏁�")
+    private Integer endMonthStaffCount;
+
+    @ApiModelProperty("鏈堝害鍏ヨ亴鍛樺伐鏁�")
+    private Integer newHireCount;
+
+    @ApiModelProperty("鏈堝害绂昏亴鍛樺伐鏁�")
+    private Integer leaveCount;
+
+    @ApiModelProperty("娴佸け鐜�(%)")
+    private Double turnoverRate;
+
+    @ApiModelProperty("娴佸姩鐜�(%)")
+    private Double flowRate;
+
+    @ApiModelProperty("鏈堜唤寮�濮嬫棩鏈�")
+    private LocalDate monthStartDate;
+
+    @ApiModelProperty("鏈堜唤缁撴潫鏃ユ湡")
+    private LocalDate monthEndDate;
+}
diff --git a/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java b/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java
new file mode 100644
index 0000000..49d2f42
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java
@@ -0,0 +1,19 @@
+package com.ruoyi.staff.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 鍛樺伐鎬绘祦鍔ㄧ巼銆佹祦澶辩巼鍙婂湪鑱屽憳宸ユ暟缁熻VO
+ */
+@Data
+public class TotalTurnoverRateVo {
+    @ApiModelProperty("鎬绘祦鍔ㄧ巼(%)")
+    private Double totalFlowRate;
+
+    @ApiModelProperty("鎬绘祦澶辩巼(%)")
+    private Double totalTurnoverRate;
+
+    @ApiModelProperty("褰撳墠鍦ㄨ亴鍛樺伐鏁�")
+    private Integer currentOnJobCount;
+}
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index 1d98782..11cd348 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -48,6 +48,13 @@
         order by ppm.id
 
     </select>
+    <select id="getOrderByMainId" resultType="com.ruoyi.production.pojo.ProductOrder">
+        select po.*
+        from product_order po
+        left join  product_work_order pwo on po.id = pwo.product_order_id
+        left join production_product_main pm on work_order_id=pwo.id
+        where pm.id=#{productMainId}
+    </select>
 
     <delete id="deleteByWorkOrderIds" parameterType="java.util.List">
         DELETE FROM production_product_main
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index 4e8a057..8058455 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,292 @@
         </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,
+                                         SUM(COALESCE(qi.quantity, 0)) AS count
+                                  FROM quality_inspect qi
+                                           JOIN quality_inspect_param qip ON qip.inspect_id = qi.id
+                                  WHERE qi.inspect_type = #{inspectType}
+                                  GROUP BY qip.parameter_item),
+             ranked AS (SELECT name,
+                               count,
+                               ROW_NUMBER() OVER (ORDER BY count DESC) AS rn
+                        FROM parameter_counts),
+             total AS (SELECT SUM(count) AS total_count
+                       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 SUM(count) &gt; 0) t
+        ORDER BY rn
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
index cd3fb66..b9ad8ed 100644
--- a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
+++ b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
@@ -30,5 +30,6 @@
         <if test="process!='' and process!=null">
             and pp.name = #{process}
         </if>
+        order by qts.id desc
     </select>
 </mapper>
diff --git a/src/main/resources/mapper/staff/StaffLeaveMapper.xml b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
index c3faf41..4637ff0 100644
--- a/src/main/resources/mapper/staff/StaffLeaveMapper.xml
+++ b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
@@ -61,4 +61,24 @@
             AND soj.staff_name LIKE CONCAT('%',#{c.staffName},'%')
         </if>
     </select>
+
+    <select id="staffLeaveReasonAnalytics" resultType="com.ruoyi.staff.dto.StaffLeaveDto">
+        SELECT
+        staff_leave.reason as reason,
+        COUNT(*) as count
+        FROM staff_leave
+        LEFT JOIN
+        staff_on_job soj ON soj.id = staff_leave.staff_on_job_id
+        where 1=1
+        GROUP BY staff_leave.reason
+    </select>
+
+    <!-- 缁熻鎸囧畾鏈堜唤鐨勭鑱屽憳宸ユ暟 -->
+    <select id="countLeaveByMonth" resultType="java.lang.Integer">
+        SELECT COUNT(*)
+        FROM staff_leave sl
+        LEFT JOIN staff_on_job soj ON sl.staff_on_job_id = soj.id
+        WHERE DATE_FORMAT(sl.create_time, '%Y-%m-%d') BETWEEN #{monthStart} AND #{monthEnd}
+        AND soj.staff_state = 0
+    </select>
 </mapper>
diff --git a/src/main/resources/mapper/staff/StaffOnJobMapper.xml b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
index a43bb37..75ae5ef 100644
--- a/src/main/resources/mapper/staff/StaffOnJobMapper.xml
+++ b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
@@ -43,4 +43,19 @@
             AND staff_name LIKE CONCAT('%',#{staffOnJob.staffName},'%')
         </if>
     </select>
+    <!-- 缁熻鎸囧畾鏃ユ湡鐨勫湪鑱屽憳宸ユ暟 -->
+    <select id="countOnJobStaffByDate" resultType="java.lang.Integer">
+        SELECT COUNT(*)
+        FROM staff_on_job
+        WHERE staff_state = 1
+        AND DATE_FORMAT(create_time, '%Y-%m-%d') &lt;= #{date}
+    </select>
+
+    <!-- 缁熻鎸囧畾鏈堜唤鐨勬柊鍏ヨ亴鍛樺伐鏁� -->
+    <select id="countNewHireByMonth" resultType="java.lang.Integer">
+        SELECT COUNT(*)
+        FROM staff_on_job
+        WHERE staff_state = 1
+        AND DATE_FORMAT(create_time, '%Y-%m-%d') BETWEEN #{monthStart} AND #{monthEnd}
+    </select>
 </mapper>
diff --git a/src/main/resources/mapper/system/SysDeptMapper.xml b/src/main/resources/mapper/system/SysDeptMapper.xml
index 5c6310a..afc1130 100644
--- a/src/main/resources/mapper/system/SysDeptMapper.xml
+++ b/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -20,32 +20,37 @@
 		<result property="createTime" column="create_time" />
 		<result property="updateBy"   column="update_by"   />
 		<result property="updateTime" column="update_time" />
+		<result property="staffCount" column="staff_count" />
 	</resultMap>
 	
 	<sql id="selectDeptVo">
         select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time 
         from sys_dept d
     </sql>
-    
+
 	<select id="selectDeptList" parameterType="com.ruoyi.project.system.domain.SysDept" resultMap="SysDeptResult">
-        <include refid="selectDeptVo"/>
-        where d.del_flag = '0'
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time,
+		count(distinct soj.id) as staff_count
+		from sys_dept d
+		left join staff_on_job soj on soj.sys_dept_id = d.dept_id and soj.staff_state = '1'
+		where d.del_flag = '0'
 		<if test="deptId != null and deptId != 0">
-			AND dept_id = #{deptId}
+			AND d.dept_id = #{deptId}
 		</if>
-        <if test="parentId != null and parentId != 0">
-			AND parent_id = #{parentId}
+		<if test="parentId != null and parentId != 0">
+			AND d.parent_id = #{parentId}
 		</if>
 		<if test="deptName != null and deptName != ''">
-			AND dept_name like concat('%', #{deptName}, '%')
+			AND d.dept_name like concat('%', #{deptName}, '%')
 		</if>
 		<if test="status != null and status != ''">
-			AND status = #{status}
+			AND d.status = #{status}
 		</if>
 		<!-- 鏁版嵁鑼冨洿杩囨护 -->
 		${params.dataScope}
+		group by d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time
 		order by d.parent_id, d.order_num
-    </select>
+	</select>
     
     <select id="selectDeptListByRoleId" resultType="Long">
 		select d.dept_id

--
Gitblit v1.9.3