From a5f66f55b2c176e8504b8a077e00acfe2dfb4b00 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期五, 18 九月 2026 18:09:56 +0800
Subject: [PATCH] feat(生产报工): 报工完成按四类区分计数零件并分流质检入库

---
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |  554 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 460 insertions(+), 94 deletions(-)

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 9b967c4..ce9eee2 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -7,17 +7,21 @@
 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.alibaba.fastjson2.JSON;
+import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
+import com.ruoyi.approve.bean.vo.ApprovalTemplateVo;
+import com.ruoyi.approve.service.ApprovalInstanceService;
+import com.ruoyi.approve.service.ApprovalTemplateService;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.common.enums.TypeEnums;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.bean.dto.ProductStructureDto;
 import com.ruoyi.production.bean.dto.ProductionProductMainDto;
 import com.ruoyi.production.enums.ProductOrderStatusEnum;
 import com.ruoyi.production.mapper.*;
@@ -27,6 +31,10 @@
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.quality.mapper.*;
 import com.ruoyi.quality.pojo.*;
+import com.ruoyi.stock.pojo.StockInRecord;
+import com.ruoyi.stock.service.StockInRecordService;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.technology.mapper.TechnologyOperationMapper;
 import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
 import com.ruoyi.technology.pojo.TechnologyOperation;
@@ -41,6 +49,7 @@
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -54,6 +63,16 @@
 @AllArgsConstructor
 @Transactional(rollbackFor = Exception.class)
 public class ProductionProductMainServiceImpl extends ServiceImpl<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService {
+
+    /**
+     * 鐢熶骇鎶ュ伐澶х被锛氬彧鍖哄垎灏忔彁鐞�/澶ф彁鐞�/璐濇柉锛屼笉鍐嶅尯鍒嗛浂浠躲��
+     * key涓哄叆搴撹鑼冨�硷紝value涓轰骇鍝佸悕绉板尮閰嶅埆鍚嶏紙鐜板満鏁版嵁璐濇柉鍐欎綔鈥滆礉鍙糕�濓級銆�
+     */
+    private static final Map<String, List<String>> MAJOR_CATEGORY_PATTERNS = new LinkedHashMap<>() {{
+        put("灏忔彁鐞�", List.of("灏忔彁鐞�"));
+        put("澶ф彁鐞�", List.of("澶ф彁鐞�"));
+        put("璐濇柉", List.of("璐濇柉", "璐濆徃"));
+    }};
 
     private final ProductionProductMainMapper productionProductMainMapper;
     private final SysUserMapper userMapper;
@@ -69,16 +88,19 @@
     private final ProductionAccountMapper productionAccountMapper;
     private final ProductionOperationTaskMapper productionOperationTaskMapper;
     private final ProductionOrderMapper productionOrderMapper;
-    private final ProductionOrderBomMapper productionOrderBomMapper;
-    private final ProductionBomStructureMapper productionBomStructureMapper;
     private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
     private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
     private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
     private final TechnologyOperationMapper technologyOperationMapper;
+    private final ApprovalTemplateService approvalTemplateService;
+    private final ApprovalInstanceService approvalInstanceService;
     private final StockUtils stockUtils;
+    private final StockInRecordService stockInRecordService;
+    private final StockInventoryService stockInventoryService;
 
     @Override
     public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) {
+        // 鍒嗛〉鏌ヨ鐢熶骇鎶ュ伐涓昏〃
         IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
         fillOperationParamList(result.getRecords());
         return result;
@@ -86,20 +108,24 @@
 
     @Override
     public IPage<ProductionProductMainDto> pageProductionProductMain(Page page, ProductionProductMainDto productionProductMainDto) {
+        // 鍒嗛〉鏌ヨ鐢熶骇鎶ュ伐涓昏〃
         return listPageProductionProductMainDto(page, productionProductMainDto);
     }
 
     @Override
     public ProductionProductMainDto getProductionProductMainInfo(Long id) {
+        // 鑾峰彇鐢熶骇浜у搧涓昏〃璇︽儏
         return listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{
             setId(id);
         }}).getRecords().stream().findFirst().orElse(null);
     }
 
     private void fillOperationParamList(List<ProductionProductMainDto> recordList) {
+        // 濉厖宸ュ簭鍙傛暟鍒楄〃
         if (recordList == null || recordList.isEmpty()) {
             return;
         }
+        // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
         Set<Long> mainIdSet = recordList.stream()
                 .map(ProductionProductMainDto::getId)
                 .filter(Objects::nonNull)
@@ -109,6 +135,7 @@
             return;
         }
 
+        // 鏌ヨ骞跺噯澶囦笟鍔℃暟鎹�
         List<ProductionOrderRoutingOperationParam> paramList = productionOrderRoutingOperationParamMapper.selectList(
                 Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
                         .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, mainIdSet)
@@ -208,6 +235,7 @@
 
     @Override
     public Boolean addProductMain(ProductionProductMainDto dto) {
+        // 鏂板鐢熶骇鎶ュ伐涓昏褰�
         Long taskId = resolveTaskId(dto);
         if (taskId == null) {
             throw new ServiceException("璇蜂紶鍏ョ敓浜у伐鍗旾D");
@@ -217,11 +245,13 @@
 
     @Override
     public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) {
+        // 淇濆瓨鐢熶骇鎶ュ伐涓昏褰�
         return addProductMain(productionProductMainDto);
     }
 
     @Override
     public Boolean removeProductMain(Long id) {
+        // 鍒犻櫎鐢熶骇鎶ュ伐涓昏褰�
         ProductionProductMain currentMain = productionProductMainMapper.selectById(id);
         if (currentMain == null) {
             return true;
@@ -230,10 +260,10 @@
     }
 
     private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) {
-        // 鎶ュ伐浠ヨ鍗曞伐搴忓揩鐓т负鍑嗭紝閬垮厤宸ヨ壓涓绘暟鎹彉鏇村悗褰卞搷鍘嗗彶宸ュ崟鎵ц銆�
+        // 鎸夌敓浜т换鍔℃柊澧炴姤宸ヤ富璁板綍
         Long taskId = resolveTaskId(dto);
         if (taskId == null) {
-            throw new ServiceException("productionOperationTaskId can not be null");
+            throw new ServiceException("鐢熶骇宸ュ崟ID涓嶈兘涓虹┖");
         }
         SysUser user = userMapper.selectUserById(dto.getUserId());
         ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId);
@@ -257,43 +287,58 @@
             throw new ServiceException("浜у搧瑙勬牸涓嶅瓨鍦�");
         }
 
+        // 鎶ュ伐瀹屾垚鏃跺璁℃暟鐨勯浂浠跺仛鍖哄垎锛氬悎鏍�/杞诲井杩斿伐/涓ラ噸杩斿伐/鎶ュ簾鍥涚被鏁伴噺銆�
+        BigDecimal qualifiedQty = defaultDecimal(dto.getQuantity());
+        BigDecimal reworkMinorQty = defaultDecimal(dto.getReworkMinorQty());
+        BigDecimal reworkMajorQty = defaultDecimal(dto.getReworkMajorQty());
+        BigDecimal scrapQtyInput = defaultDecimal(dto.getScrapQty());
+        if (qualifiedQty.compareTo(BigDecimal.ZERO) < 0
+                || reworkMinorQty.compareTo(BigDecimal.ZERO) < 0
+                || reworkMajorQty.compareTo(BigDecimal.ZERO) < 0
+                || scrapQtyInput.compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("鎶ュ伐鏁伴噺涓嶈兘涓鸿礋鏁�");
+        }
+        if (qualifiedQty.add(reworkMinorQty).add(reworkMajorQty).add(scrapQtyInput).compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("璇锋寜鍚堟牸/杞诲井杩斿伐/涓ラ噸杩斿伐/鎶ュ簾鍒嗙被濉啓闆朵欢鏁伴噺");
+        }
+
         ProductionProductMain productionProductMain = new ProductionProductMain();
         productionProductMain.setProductNo(generateProductNo());
+        productionProductMain.setMajorCategory(resolveMajorCategory(productModel));
         productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId());
         productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName());
         productionProductMain.setProductionOperationTaskId(taskId);
         productionProductMain.setStatus(0);
+        productionProductMain.setReportType(dto.getReportType() != null
+                ? dto.getReportType()
+                : deriveReportType(qualifiedQty, reworkMinorQty, reworkMajorQty, scrapQtyInput));
+        productionProductMain.setAuditStatus(dto.getAuditStatus() == null ? 0 : dto.getAuditStatus());
+        productionProductMain.setAuditRemark(dto.getAuditRemark());
+        productionProductMain.setWorkHour(dto.getWorkHour());
         productionProductMainMapper.insert(productionProductMain);
         syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId());
+        createReportApprovalInstance(productionProductMain);
 
-        List<ProductStructureDto> productStructureDtos = resolveInputStructures(
-                productionOrder.getId(), routingOperation, productModel.getId());
-       // 濡傛灉娌℃湁bom瀛愯妭鐐逛簡锛岄偅涔堟姇鍏ュ氨鏄粬鏈韩
-        if (productStructureDtos.isEmpty()) {
-            ProductStructureDto fallbackInput = new ProductStructureDto();
-            fallbackInput.setProductModelId(productModel.getId());
-            fallbackInput.setUnitQuantity(BigDecimal.ONE);
-            productStructureDtos.add(fallbackInput);
-        }
-        for (ProductStructureDto item : productStructureDtos) {
-            // 褰撳墠瀹炵幇鎸夊伐搴忔垚鍝佺洿鎺ヤ綔涓烘姇鍏ワ紝鍚庣画鑻ユ帴鍏ラ鏂欒褰曞彲鍦ㄨ繖閲屾浛鎹㈡潵婧愩��
-            ProductionProductInput productionProductInput = new ProductionProductInput();
-            productionProductInput.setProductionProductMainId(productionProductMain.getId());
-            productionProductInput.setProductMainId(productionProductMain.getId());
-            productionProductInput.setProductModelId(item.getProductModelId());
-            productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity())));
-            productionProductInput.setQuantity(productionProductInput.getInputQuantity());
-            productionProductInputMapper.insert(productionProductInput);
-        }
+        // 闇�姹傚彉鏇达細鐢熶骇鎶ュ伐涓嶅啀鎸夐浂浠讹紙BOM缁撴瀯锛夋媶鍒嗘姇鍏ワ紝鎶曞叆鍗虫湰娆℃姤宸ョ殑浜у搧鏈韩锛屾寜澶х被缁熻銆�
+        ProductionProductInput productionProductInput = new ProductionProductInput();
+        productionProductInput.setProductionProductMainId(productionProductMain.getId());
+        productionProductInput.setProductModelId(productModel.getId());
+        productionProductInput.setInputQuantity(qualifiedQty);
+        productionProductInput.setQuantity(qualifiedQty);
+        productionProductInputMapper.insert(productionProductInput);
 
         ProductionProductOutput productionProductOutput = new ProductionProductOutput();
         productionProductOutput.setProductionProductMainId(productionProductMain.getId());
-        productionProductOutput.setProductMainId(productionProductMain.getId());
         productionProductOutput.setProductModelId(productModel.getId());
         productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity()));
         productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty()));
+        productionProductOutput.setReworkMinorQty(reworkMinorQty);
+        productionProductOutput.setReworkMajorQty(reworkMajorQty);
         productionProductOutputMapper.insert(productionProductOutput);
-        BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
+        BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity());
+        BigDecimal scrapQty = defaultDecimal(productionProductOutput.getScrapQty());
+        BigDecimal productQty = reportQty;
+        String qualifiedBatchNo = null;
 
         List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList(
                 Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
@@ -332,9 +377,19 @@
                                 qualityInspectParamMapper.insert(param);
                             });
                 }
-            } else {
-                stockUtils.addStock(productModel.getId(), productQty,
-                        StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
+            } else if(isLastOperation){
+                //(鏈�鍚庝竴閬撳伐搴忔墠鍏ュ簱)
+                StockInventoryDto stockInventoryDto = new StockInventoryDto();
+                stockInventoryDto.setRecordId(productionProductMain.getId());
+                stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()));
+                stockInventoryDto.setQualitity(productQty);
+                stockInventoryDto.setProductModelId(productModel.getId());
+                stockInventoryService.addStockInRecordOnly(stockInventoryDto);
+                qualifiedBatchNo = resolveLatestStockInBatchNo(
+                        productionProductMain.getId(),
+                        StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(),
+                        productModel.getId(),
+                        "0");
             }
 
             productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty));
@@ -353,8 +408,10 @@
             if (ObjectUtils.isNull(productionOrder.getStartTime())) {
                 productionOrder.setStartTime(LocalDateTime.now());
             }
-            // 璁㈠崟鐘舵�佺敱鏈�鍚庝竴閬撳伐搴忕殑鍚堟牸浜у嚭鎺ㄥ姩锛岄伩鍏嶄腑闂村伐搴忔彁鍓嶅畬宸ャ��
-            productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode());
+            // 浠呭緟寮�濮嬬姸鎬佹墠鎺ㄨ繘鍒拌繘琛屼腑锛岄伩鍏嶉潪鏈亾宸ュ簭鎶ュ伐鏃惰鐩栧凡瀹屾垚鐘舵�併��
+            if (ProductOrderStatusEnum.WAIT.getCode().equals(productionOrder.getStatus())) {
+                productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode());
+            }
             if (isLastOperation) {
                 productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty));
                 if (productionOrder.getQuantity() != null
@@ -373,21 +430,249 @@
             }
             ProductionAccount productionAccount = new ProductionAccount();
             productionAccount.setProductionProductMainId(productionProductMain.getId());
-//            productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId());
-//            productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue());
             productionAccount.setSchedulingUserId(user == null ? null : user.getUserId());
             productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName());
             productionAccount.setFinishedNum(productQty);
-            productionAccount.setWorkHours(workHours);
+            productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null);
             productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName());
             productionAccount.setSchedulingDate(LocalDateTime.now());
-            productionAccountMapper.insert(productionAccount);
         }
-        if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) {
-            stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(),
-                    StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
+        if (scrapQty.compareTo(BigDecimal.ZERO) > 0) {
+            stockUtils.addUnStockWithBatchNo(
+                    productModel.getId(),
+                    scrapQty,
+                    StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(),
+                    productionProductMain.getId(),
+                    qualifiedBatchNo);
         }
+        // 鍖哄垎鍑虹殑杩斿伐闆朵欢鐢熸垚涓嶅悎鏍煎搧寰呭鐞嗗崟锛岃繘鍏ヤ笉鍚堟牸鍝佺鐞嗙殑鎶ュ伐澶勭悊闂幆銆�
+        createReworkUnqualifiedRecords(productionProductMain, productModel, reworkMinorQty, reworkMajorQty);
         return true;
+    }
+
+    private Integer deriveReportType(BigDecimal qualifiedQty, BigDecimal reworkMinorQty,
+                                     BigDecimal reworkMajorQty, BigDecimal scrapQty) {
+        if (qualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
+            return 0;
+        }
+        if (reworkMinorQty.compareTo(BigDecimal.ZERO) > 0) {
+            return 1;
+        }
+        if (reworkMajorQty.compareTo(BigDecimal.ZERO) > 0) {
+            return 2;
+        }
+        if (scrapQty.compareTo(BigDecimal.ZERO) > 0) {
+            return 3;
+        }
+        return 0;
+    }
+
+    private void createReworkUnqualifiedRecords(ProductionProductMain productionProductMain,
+                                                ProductModel productModel,
+                                                BigDecimal reworkMinorQty,
+                                                BigDecimal reworkMajorQty) {
+        if (reworkMinorQty.compareTo(BigDecimal.ZERO) <= 0 && reworkMajorQty.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        Product product = productMapper.selectById(productModel.getProductId());
+        if (product == null) {
+            throw new ServiceException("浜у搧涓嶅瓨鍦紝鏃犳硶鐢熸垚鎶ュ伐杩斿伐寰呭鐞嗗崟");
+        }
+        if (reworkMinorQty.compareTo(BigDecimal.ZERO) > 0) {
+            insertReworkUnqualified(productionProductMain, product, productModel, reworkMinorQty, 0);
+        }
+        if (reworkMajorQty.compareTo(BigDecimal.ZERO) > 0) {
+            insertReworkUnqualified(productionProductMain, product, productModel, reworkMajorQty, 1);
+        }
+    }
+
+    private void insertReworkUnqualified(ProductionProductMain productionProductMain,
+                                         Product product,
+                                         ProductModel productModel,
+                                         BigDecimal quantity,
+                                         int dealType) {
+        QualityUnqualified qualityUnqualified = new QualityUnqualified();
+        qualityUnqualified.setInspectType(1);
+        qualityUnqualified.setInspectState(0);
+        qualityUnqualified.setCheckTime(new Date());
+        qualityUnqualified.setCheckName(productionProductMain.getUserName());
+        qualityUnqualified.setProductId(product.getId());
+        qualityUnqualified.setProductName(product.getProductName());
+        qualityUnqualified.setModel(productModel.getModel());
+        qualityUnqualified.setUnit(productModel.getUnit());
+        qualityUnqualified.setQuantity(quantity);
+        qualityUnqualified.setProductModelId(productModel.getId());
+        qualityUnqualified.setProductMainId(productionProductMain.getId());
+        qualityUnqualified.setDefectivePhenomena("鐢熶骇鎶ュ伐銆�" + productionProductMain.getProductNo()
+                + "銆戣鏁板尯鍒�-" + (dealType == 0 ? "杞诲井杩斿伐" : "涓ラ噸杩斿伐"));
+        qualityUnqualified.setDealType(dealType);
+        qualityUnqualified.setDealResult("鎶ュ伐");
+        qualityUnqualifiedMapper.insert(qualityUnqualified);
+    }
+
+    private void createReportApprovalInstance(ProductionProductMain productionProductMain) {
+        if (productionProductMain == null || productionProductMain.getId() == null) {
+            return;
+        }
+        ApprovalTemplateVo templateVo = approvalTemplateService.getEnabledTemplateByBusinessType(
+                TypeEnums.PRODUCTION_REPORT_APPROVAL.getCode()
+        );
+        if (templateVo == null) {
+            throw new ServiceException("璇峰厛閰嶇疆鎶ュ伐瀹℃壒妯℃澘");
+        }
+        ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
+        approvalInstanceDto.setTemplateId(templateVo.getId());
+        approvalInstanceDto.setTemplateName(templateVo.getTemplateName());
+        approvalInstanceDto.setBusinessId(productionProductMain.getId());
+        approvalInstanceDto.setBusinessType(TypeEnums.PRODUCTION_REPORT_APPROVAL.getCode());
+        approvalInstanceDto.setTitle(productionProductMain.getProductNo());
+        approvalInstanceDto.setApplicantId(productionProductMain.getUserId());
+        approvalInstanceDto.setApplicantName(productionProductMain.getUserName());
+        approvalInstanceDto.setApplyTime(LocalDateTime.now());
+        approvalInstanceDto.setStatus("PENDING");
+        approvalInstanceDto.setFormConfig(JSON.toJSONString(buildReportApprovalFormConfig(productionProductMain)));
+        approvalInstanceService.add(approvalInstanceDto);
+    }
+
+    private Map<String, Object> buildReportApprovalFormConfig(ProductionProductMain productionProductMain) {
+        Map<String, Object> formConfig = new LinkedHashMap<>();
+        formConfig.put("summaryPlaceholder", "鎶ュ伐瀹℃壒");
+        formConfig.put("approvalType", "production_report");
+
+        ProductionOperationTask task = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId());
+        ProductionProductOutput output = productionProductOutputMapper.selectOne(
+                Wrappers.<ProductionProductOutput>lambdaQuery()
+                        .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId())
+                        .last("limit 1"));
+        BigDecimal schedulingNum = task == null ? BigDecimal.ZERO : defaultDecimal(task.getPlanQuantity());
+        BigDecimal finishedNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getQuantity());
+        BigDecimal scrapQty = output == null ? BigDecimal.ZERO : defaultDecimal(output.getScrapQty());
+        BigDecimal reworkMinorNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getReworkMinorQty());
+        BigDecimal reworkMajorNum = output == null ? BigDecimal.ZERO : defaultDecimal(output.getReworkMajorQty());
+        BigDecimal pendingNum = schedulingNum.subtract(finishedNum);
+        if (pendingNum.compareTo(BigDecimal.ZERO) < 0) {
+            pendingNum = BigDecimal.ZERO;
+        }
+
+        List<Map<String, Object>> fields = new ArrayList<>();
+        fields.add(buildReportField("productNo", "鎶ュ伐鍗曞彿", "text", productionProductMain.getProductNo()));
+        fields.add(buildReportField("userName", "鎶ュ伐浜哄憳", "text", productionProductMain.getUserName()));
+        fields.add(buildReportField("teamInfo", "鐝粍淇℃伅", "text", productionProductMain.getUserName()));
+        fields.add(buildReportField("workOrderNo", "宸ュ崟缂栧彿", "text", resolveWorkOrderNo(productionProductMain.getProductionOperationTaskId())));
+        fields.add(buildReportField("schedulingNum", "鎺掍骇鏁伴噺", "number", schedulingNum));
+        fields.add(buildReportField("pendingNum", "寰呯敓浜ф暟閲�", "number", pendingNum));
+        fields.add(buildReportField("finishedNum", "鍚堟牸鏁伴噺", "number", finishedNum));
+        fields.add(buildReportField("reworkMinorQty", "杞诲井杩斿伐鏁伴噺", "number", reworkMinorNum));
+        fields.add(buildReportField("reworkMajorQty", "涓ラ噸杩斿伐鏁伴噺", "number", reworkMajorNum));
+        fields.add(buildReportField("scrapQty", "鎶ュ簾鏁伴噺", "number", scrapQty));
+        fields.add(buildReportField("reportType", "鎶ュ伐缁撴灉", "select", resolveReportTypeLabel(productionProductMain.getReportType())));
+        fields.add(buildReportField("workHour", "宸ユ椂", "number", productionProductMain.getWorkHour()));
+        fields.add(buildReportField("auditStatus", "瀹℃牳鐘舵��", "select", resolveAuditStatusLabel(productionProductMain.getAuditStatus())));
+        fields.add(buildReportField("auditRemark", "瀹℃牳鎰忚", "textarea", productionProductMain.getAuditRemark()));
+        formConfig.put("fields", fields);
+
+        Map<String, Object> formPayload = new LinkedHashMap<>();
+        formPayload.put("productNo", productionProductMain.getProductNo());
+        formPayload.put("userName", productionProductMain.getUserName());
+        formPayload.put("teamInfo", productionProductMain.getUserName());
+        formPayload.put("workOrderNo", resolveWorkOrderNo(productionProductMain.getProductionOperationTaskId()));
+        formPayload.put("schedulingNum", schedulingNum);
+        formPayload.put("pendingNum", pendingNum);
+        formPayload.put("finishedNum", finishedNum);
+        formPayload.put("scrapQty", scrapQty);
+        formPayload.put("reworkMinorQty", reworkMinorNum);
+        formPayload.put("reworkMajorQty", reworkMajorNum);
+        formPayload.put("reportType", resolveReportTypeLabel(productionProductMain.getReportType()));
+        formPayload.put("workHour", productionProductMain.getWorkHour());
+        formPayload.put("auditStatus", resolveAuditStatusLabel(productionProductMain.getAuditStatus()));
+        formPayload.put("auditRemark", productionProductMain.getAuditRemark());
+        formConfig.put("formPayload", formPayload);
+        return formConfig;
+    }
+
+    private Map<String, Object> buildReportField(String key, String label, String type, Object defaultValue) {
+        Map<String, Object> field = new LinkedHashMap<>();
+        field.put("key", key);
+        field.put("label", label);
+        field.put("type", type);
+        field.put("required", Boolean.FALSE);
+        field.put("defaultValue", defaultValue);
+        return field;
+    }
+
+    private String resolveWorkOrderNo(Long productionOperationTaskId) {
+        if (productionOperationTaskId == null) {
+            return null;
+        }
+        ProductionOperationTask task = productionOperationTaskMapper.selectById(productionOperationTaskId);
+        if (task != null && task.getWorkOrderNo() != null) {
+            return task.getWorkOrderNo();
+        }
+        if (task == null || task.getProductionOrderRoutingOperationId() == null) {
+            return null;
+        }
+        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(task.getProductionOrderRoutingOperationId());
+        if (routingOperation == null || routingOperation.getProductionOrderId() == null) {
+            return null;
+        }
+        ProductionOrder productionOrder = productionOrderMapper.selectById(routingOperation.getProductionOrderId());
+        return productionOrder == null ? null : productionOrder.getNpsNo();
+    }
+
+    private String resolveReportTypeLabel(Integer reportType) {
+        if (reportType == null) {
+            return "鈥�";
+        }
+        switch (reportType) {
+            case 0:
+                return "鍚堟牸";
+            case 1:
+                return "杞诲井杩斿伐";
+            case 2:
+                return "涓ラ噸杩斿伐";
+            case 3:
+                return "鎶ュ簾";
+            default:
+                return "鈥�";
+        }
+    }
+
+    private String resolveAuditStatusLabel(Integer auditStatus) {
+        if (auditStatus == null) {
+            return "寰呭鏍�";
+        }
+        switch (auditStatus) {
+            case 0:
+                return "寰呭鏍�";
+            case 1:
+                return "瀹℃牳閫氳繃";
+            case 2:
+                return "瀹℃牳涓嶉�氳繃";
+            default:
+                return "鈥�";
+        }
+    }
+
+    private String resolveLatestStockInBatchNo(Long recordId,
+                                               String recordType,
+                                               Long productModelId,
+                                               String stockType) {
+        if (recordId == null || productModelId == null) {
+            return null;
+        }
+        StockInRecord stockInRecord = stockInRecordService.getOne(
+                Wrappers.<StockInRecord>lambdaQuery()
+                        .eq(StockInRecord::getRecordId, recordId)
+                        .eq(StockInRecord::getRecordType, recordType)
+                        .eq(StockInRecord::getProductModelId, productModelId)
+                        .eq(StockInRecord::getType, stockType)
+                        .orderByDesc(StockInRecord::getId)
+                        .last("limit 1"),
+                false);
+        if (stockInRecord == null) {
+            throw new ServiceException("鏈壘鍒板搴旂殑鍏ュ簱鐢宠璁板綍");
+        }
+        return stockInRecord.getBatchNo();
     }
 
     private void syncOperationParamInputValue(ProductionProductMainDto dto,
@@ -455,75 +740,68 @@
         return target;
     }
 
-    private List<ProductStructureDto> resolveInputStructures(Long productionOrderId,
-                                                             ProductionOrderRoutingOperation routingOperation,
-                                                             Long outputProductModelId) {
-        if (productionOrderId == null || routingOperation == null || routingOperation.getTechnologyOperationId() == null) {
-            return new ArrayList<>();
+    /**
+     * 闇�姹傦細鐢熶骇鎶ュ伐鍙尯鍒嗕骇鍝佸ぇ绫伙紙灏忔彁鐞�/澶ф彁鐞�/璐濇柉锛夛紝涓嶅啀鍖哄垎闆朵欢銆�
+     * 浠庝骇鍑轰骇鍝佽嚜韬悕绉板紑濮嬫部浜у搧鏍戝悜涓婂仛鍏抽敭瀛楀尮閰嶏紝鍛戒腑鍗冲彇瀵瑰簲瑙勮寖澶х被锛涙湭鍛戒腑杩斿洖 null銆�
+     * 浜у搧鏍戦《灞備负鈥滄垚鍝�/鍗婃垚鍝�/鍘熸枡鈥濈瓑搴撳瓨鍒嗙被锛屼笉鑳界洿鎺ュ綋浣滃ぇ绫伙紝鍥犳蹇呴』鑷簳鍚戜笂鍙栫涓�涓懡涓殑灞傜骇銆�
+     */
+    private String resolveMajorCategory(ProductModel productModel) {
+        if (productModel == null || productModel.getProductId() == null) {
+            return null;
         }
-        ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
-                Wrappers.<ProductionOrderBom>lambdaQuery()
-                        .eq(ProductionOrderBom::getProductionOrderId, productionOrderId)
-                        .orderByDesc(ProductionOrderBom::getId)
-                        .last("limit 1"));
-        if (orderBom == null || orderBom.getId() == null) {
-            return new ArrayList<>();
-        }
-
-        List<ProductionBomStructure> bomNodeList = productionBomStructureMapper.selectList(
-                Wrappers.<ProductionBomStructure>lambdaQuery()
-                        .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
-                        .orderByAsc(ProductionBomStructure::getId));
-        if (bomNodeList.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        Map<Long, ProductionBomStructure> nodeMap = bomNodeList.stream()
-                .filter(item -> item != null && item.getId() != null)
-                .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
-        Long currentOutputModelId = routingOperation.getProductModelId() != null
-                ? routingOperation.getProductModelId()
-                : outputProductModelId;
-
-        Map<Long, BigDecimal> unitQtyByProductModel = new LinkedHashMap<>();
-        for (ProductionBomStructure node : bomNodeList) {
-            if (node == null || node.getParentId() == null || node.getProductModelId() == null) {
-                continue;
+        Product product = productMapper.selectById(productModel.getProductId());
+        Set<Long> visited = new LinkedHashSet<>();
+        while (product != null && visited.add(product.getId())) {
+            String category = matchMajorCategory(product.getProductName());
+            if (category != null) {
+                return category;
             }
-            if (!Objects.equals(node.getTechnologyOperationId(), routingOperation.getTechnologyOperationId())) {
-                continue;
+            if (product.getParentId() == null || product.getParentId() == 0L) {
+                break;
             }
-            ProductionBomStructure parent = nodeMap.get(node.getParentId());
-            if (parent == null || !Objects.equals(parent.getProductModelId(), currentOutputModelId)) {
-                continue;
-            }
-            unitQtyByProductModel.merge(node.getProductModelId(), defaultDecimal(node.getUnitQuantity()), BigDecimal::add);
+            product = productMapper.selectById(product.getParentId());
         }
+        return null;
+    }
 
-        List<ProductStructureDto> result = new ArrayList<>();
-        for (Map.Entry<Long, BigDecimal> entry : unitQtyByProductModel.entrySet()) {
-            if (entry.getValue().compareTo(BigDecimal.ZERO) <= 0) {
-                continue;
-            }
-            ProductStructureDto item = new ProductStructureDto();
-            item.setProductModelId(entry.getKey());
-            item.setUnitQuantity(entry.getValue());
-            result.add(item);
+    static String matchMajorCategory(String productName) {
+        if (productName == null || productName.isEmpty()) {
+            return null;
         }
-        return result;
+        // 鐞寸洅/鐞村绛夐厤浠跺悕绉板彲鑳藉甫鈥滆礉鍙糕�濈瓑瀛楁牱锛堝 SA璐濆徃濂楋級锛屾帓闄ゅ悗閬垮厤璇綊澶х被銆�
+        if (productName.contains("鐞寸洅") || productName.contains("鐞村") || productName.contains("寮撶洅")) {
+            return null;
+        }
+        for (Map.Entry<String, List<String>> entry : MAJOR_CATEGORY_PATTERNS.entrySet()) {
+            for (String alias : entry.getValue()) {
+                if (productName.contains(alias)) {
+                    return entry.getKey();
+                }
+            }
+        }
+        return null;
     }
 
     private Boolean removeProductMainByProductionTask(ProductionProductMain productionProductMain) {
-        // 鍒犻櫎鎶ュ伐闇�瑕佸悓姝ュ洖婊氳川妫�銆佸簱瀛樸�佸伐鏃舵牳绠楀拰璁㈠崟/宸ュ崟杩涘害銆�
+        // 鎸夌敓浜т换鍔″洖婊氬苟鍒犻櫎鎶ュ伐涓昏褰�
         List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
                 Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, productionProductMain.getId()));
+        // 鍙傛暟涓庡墠缃潯浠舵牎楠�
         if (qualityInspects.size() > 0) {
             List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(
                     Wrappers.<QualityUnqualified>lambdaQuery()
+        // 閬嶅巻澶勭悊鏁版嵁骞剁粍瑁呯粨鏋�
                             .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList())));
             if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) {
                 throw new ServiceException("璇ユ潯鎶ュ伐宸茬粡涓嶅悎鏍煎鐞嗕簡锛屼笉鍏佽鍒犻櫎");
             }
+        }
+        // 鎶ュ伐璁℃暟鍖哄垎鐩存帴浜х敓鐨勮繑宸ュ緟澶勭悊鍗曪細宸插鐞嗙殑涓嶅厑璁稿垹闄ゆ姤宸ワ紝鏈鐞嗙殑闅忔姤宸ヤ竴骞跺垹闄ゃ��
+        List<QualityUnqualified> reworkUnqualifieds = qualityUnqualifiedMapper.selectList(
+                Wrappers.<QualityUnqualified>lambdaQuery()
+                        .eq(QualityUnqualified::getProductMainId, productionProductMain.getId()));
+        if (reworkUnqualifieds.stream().anyMatch(q -> Integer.valueOf(1).equals(q.getInspectState()))) {
+            throw new ServiceException("璇ユ潯鎶ュ伐鐨勮繑宸ラ浂浠跺凡鍋氫笉鍚堟牸澶勭悊锛屼笉鍏佽鍒犻櫎");
         }
         ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(
                 Wrappers.<ProductionProductOutput>lambdaQuery()
@@ -534,8 +812,8 @@
 
         ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId());
         if (productionOperationTask != null && productionProductOutput != null) {
-            BigDecimal validQuantity = defaultDecimal(productionProductOutput.getQuantity()).subtract(defaultDecimal(productionProductOutput.getScrapQty()));
-            productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(validQuantity));
+            BigDecimal reportQuantity = defaultDecimal(productionProductOutput.getQuantity());
+            productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(reportQuantity));
             productionOperationTask.setActualEndTime(null);
             if (defaultDecimal(productionOperationTask.getCompleteQuantity()).compareTo(BigDecimal.ZERO) <= 0) {
                 productionOperationTask.setCompleteQuantity(BigDecimal.ZERO);
@@ -544,6 +822,7 @@
             } else {
                 productionOperationTask.setStatus(3);
             }
+        // 鎸佷箙鍖栨垨杈撳嚭澶勭悊缁撴灉
             productionOperationTaskMapper.updateById(productionOperationTask);
 
             ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId());
@@ -556,7 +835,7 @@
                                 .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId()));
                 boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size());
                 if (isLastOperation) {
-                    BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(validQuantity);
+                    BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(reportQuantity);
                     productionOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty);
                     productionOrder.setEndTime(null);
                 }
@@ -570,6 +849,8 @@
             }
         }
 
+        qualityUnqualifiedMapper.delete(new LambdaQueryWrapper<QualityUnqualified>()
+                .eq(QualityUnqualified::getProductMainId, productionProductMain.getId()));
         qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
                 .eq(QualityInspect::getProductMainId, productionProductMain.getId())).forEach(q -> {
             qualityInspectParamMapper.delete(new LambdaQueryWrapper<QualityInspectParam>()
@@ -584,7 +865,7 @@
         productionOrderRoutingOperationParamMapper.delete(
                 Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
                         .eq(ProductionOrderRoutingOperationParam::getProductionProductMainId, productionProductMain.getId()));
-        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
         stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
         stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
         productionProductMainMapper.deleteById(productionProductMain.getId());
@@ -592,6 +873,7 @@
     }
 
     private String generateProductNo() {
+        // 鐢熸垚涓嬩竴涓敓浜т骇鍝佺紪鍙�
         String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
         QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
         queryWrapper.select("MAX(product_no) as maxNo").likeRight("product_no", datePrefix);
@@ -614,18 +896,102 @@
     }
 
     private BigDecimal defaultDecimal(BigDecimal value) {
+        // 灏嗙┖鏁伴噺鍏滃簳涓�0锛岄伩鍏嶇┖鎸囬拡寮傚父
         return value == null ? BigDecimal.ZERO : value;
     }
 
     private Long resolveTaskId(ProductionProductMainDto dto) {
+        // 浠庡叆鍙備腑瑙f瀽鐢熶骇宸ュ崟ID骞舵牎楠�
         if (dto == null) {
             return null;
         }
         return dto.getProductionOperationTaskId();
     }
 
+    private boolean isCountingWageReport(ProductionProductMain productionProductMain) {
+        return productionProductMain != null
+                && productionProductMain.getAuditStatus() != null
+                && productionProductMain.getAuditStatus() == 1
+                && productionProductMain.getReportType() != null
+                && (productionProductMain.getReportType() == 0 || productionProductMain.getReportType() == 1);
+    }
+
+    private boolean isExcludedFromWage(ProductionProductMain productionProductMain) {
+        return productionProductMain != null
+                && productionProductMain.getReportType() != null
+                && productionProductMain.getReportType() != 0
+                && productionProductMain.getReportType() != 1;
+    }
+
+    @Override
+    public Boolean auditProductMain(ProductionProductMainDto productionProductMainDto) {
+        if (productionProductMainDto == null || productionProductMainDto.getId() == null) {
+            throw new ServiceException("鍙傛暟閿欒");
+        }
+        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productionProductMainDto.getId());
+        if (productionProductMain == null) {
+            throw new ServiceException("鎶ュ伐涓嶅瓨鍦�");
+        }
+        Integer auditStatus = productionProductMainDto.getAuditStatus();
+        if (auditStatus == null) {
+            throw new ServiceException("瀹℃牳鐘舵�佷笉鑳戒负绌�");
+        }
+        productionProductMain.setAuditStatus(auditStatus);
+        productionProductMain.setAuditRemark(productionProductMainDto.getAuditRemark());
+        productionProductMainMapper.updateById(productionProductMain);
+        productionAccountMapper.delete(new LambdaQueryWrapper<ProductionAccount>()
+                .eq(ProductionAccount::getProductionProductMainId, productionProductMain.getId()));
+        if (auditStatus == 1 && !isExcludedFromWage(productionProductMain)) {
+            rebuildProductionAccount(productionProductMain);
+        }
+        return true;
+    }
+
+    private void rebuildProductionAccount(ProductionProductMain productionProductMain) {
+        if (productionProductMain == null || productionProductMain.getId() == null) {
+            return;
+        }
+        ProductionProductOutput output = productionProductOutputMapper.selectOne(
+                Wrappers.<ProductionProductOutput>lambdaQuery()
+                        .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId())
+                        .last("limit 1"));
+        if (output == null) {
+            return;
+        }
+        ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId());
+        if (productionOperationTask == null) {
+            return;
+        }
+        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId());
+        if (routingOperation == null) {
+            return;
+        }
+        ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId());
+        if (productionOrder == null) {
+            return;
+        }
+        TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId());
+        TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null
+                : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId());
+        SysUser user = userMapper.selectUserById(productionProductMain.getUserId());
+        BigDecimal productQty = defaultDecimal(output.getQuantity());
+        if (productQty.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        ProductionAccount productionAccount = new ProductionAccount();
+        productionAccount.setProductionProductMainId(productionProductMain.getId());
+        productionAccount.setSchedulingUserId(user == null ? productionProductMain.getUserId() : user.getUserId());
+        productionAccount.setSchedulingUserName(user == null ? productionProductMain.getUserName() : user.getNickName());
+        productionAccount.setFinishedNum(productQty);
+        productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null);
+        productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName());
+        productionAccount.setSchedulingDate(LocalDateTime.now());
+        productionAccountMapper.insert(productionAccount);
+    }
+
     @Override
     public ArrayList<Long> listMain(List<Long> idList) {
+        // 鏌ヨ涓昏〃ID闆嗗悎
         return productionProductMainMapper.listMain(idList);
     }
 }

--
Gitblit v1.9.3