From 88ae1e650fc2fc30928edfe8f3cc39108d8d1ccd Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期三, 06 五月 2026 15:44:26 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New_pro' into dev_New_pro

---
 src/main/java/com/ruoyi/framework/security/LoginUser.java                               |   96 ++++++----
 src/main/java/com/ruoyi/production/controller/ProductionOrderController.java            |    8 
 src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java    |   12 
 src/main/java/com/ruoyi/project/system/controller/SysLoginController.java               |   39 ++-
 src/main/java/com/ruoyi/project/system/domain/SysUser.java                              |   48 +++-
 src/main/resources/mapper/production/ProductionOrderMapper.xml                          |   10 +
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java                       |    3 
 doc/20260506_add_ai_enabled_to_sys_user.sql                                             |    2 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java |    5 
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                  |   67 +++++++
 doc/20260506_用户AI功能字段前端联调说明.md                                                          |   53 +++++
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java        |   62 +++---
 src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java             |   13 +
 src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java          |    2 
 src/main/resources/mapper/system/SysUserMapper.xml                                      |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java     |    8 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java         |   90 ++++++---
 src/main/java/com/ruoyi/production/service/ProductionOrderService.java                  |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java            |    2 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java               |    9 +
 20 files changed, 394 insertions(+), 140 deletions(-)

diff --git a/doc/20260506_add_ai_enabled_to_sys_user.sql b/doc/20260506_add_ai_enabled_to_sys_user.sql
new file mode 100644
index 0000000..7e7ee9d
--- /dev/null
+++ b/doc/20260506_add_ai_enabled_to_sys_user.sql
@@ -0,0 +1,2 @@
+alter table sys_user
+    add ai_enabled tinyint(1) not null default 0 comment '鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級';
diff --git "a/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md" "b/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..bce48d5
--- /dev/null
+++ "b/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
@@ -0,0 +1,53 @@
+# 鐢ㄦ埛 AI 鍔熻兘瀛楁鍓嶇鑱旇皟璇存槑
+
+## 鑳屾櫙
+
+鍚庣宸插湪鐢ㄦ埛琛ㄥ鍔犻殣钘忓瓧娈� `ai_enabled`锛岀敤浜庢爣璇嗙敤鎴锋槸鍚﹀紑閫� AI 鍔熻兘銆�  
+璇ュ瓧娈典笉寮�鏀剧粰鐢ㄦ埛璧勬枡缁存姢鎺ュ彛锛堜笉閫氳繃鐢ㄦ埛缂栬緫椤甸潰涓嬪彂/鍥炲啓锛夈��
+
+## 瀛楁瀹氫箟
+
+| 瀛楁 | 绫诲瀷 | 榛樿鍊� | 璇存槑 |
+| --- | --- | --- | --- |
+| ai_enabled | tinyint(1) | 0 | 鏄惁寮�閫� AI 鍔熻兘锛歚0`=鏈紑閫氾紝`1`=宸插紑閫� |
+
+## 鑱旇皟鎺ュ彛
+
+鐧诲綍鍚庤皟鐢細
+
+```http
+GET /getInfo
+```
+
+杩斿洖涓柊澧為《灞傚瓧娈� `aiEnabled`锛�
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "user": {
+    "userId": 1,
+    "userName": "admin"
+  },
+  "aiEnabled": 1,
+  "roles": [
+    "admin"
+  ],
+  "permissions": [
+    "*:*:*"
+  ]
+}
+```
+
+## 鍓嶇浣跨敤寤鸿
+
+1. 鐧诲綍鎴愬姛鍚庢寜鐜版湁娴佺▼璋冪敤 `/getInfo`銆�
+2. 浠庡搷搴旈《灞傝鍙� `aiEnabled`銆�
+3. 鍒ゅ畾閫昏緫寤鸿锛�
+   - `aiEnabled === 1`锛氬睍绀�/鏀惧紑 AI 鐩稿叧鍏ュ彛銆�
+   - 鍏朵粬鍊硷紙`0`銆乣null`銆乣undefined`锛夛細鎸夋湭寮�閫氬鐞嗐��
+
+## 缂撳瓨璇存槑
+
+- `aiEnabled` 宸叉斁鍏ョ櫥褰曠紦瀛樺璞★紙`LoginUser`锛夊苟闅� token 鐢熷懡鍛ㄦ湡绠$悊銆�
+- 缂撳瓨 key 鍓嶇紑锛歚login_tokens:`銆�
diff --git a/src/main/java/com/ruoyi/framework/security/LoginUser.java b/src/main/java/com/ruoyi/framework/security/LoginUser.java
index 168202f..330ae43 100644
--- a/src/main/java/com/ruoyi/framework/security/LoginUser.java
+++ b/src/main/java/com/ruoyi/framework/security/LoginUser.java
@@ -76,10 +76,15 @@
      */
     private Long tenantId;
 
-    /**
-     * 褰撳墠閮ㄩ棬id
-     */
+    /**
+     * 褰撳墠閮ㄩ棬id
+     */
     private Long currentDeptId;
+
+    /**
+     * 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級
+     */
+    private Integer aiEnabled;
 
     private String dataScope;
 
@@ -87,38 +92,42 @@
     {
     }
 
-    public LoginUser(SysUser user, Set<String> permissions)
-    {
-        this.user = user;
-        this.permissions = permissions;
-    }
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptId, SysUser user, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptId;
-        this.user = user;
-        this.permissions = permissions;
-    }
+    public LoginUser(Long userId, Long [] deptId, SysUser user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptId;
+        this.user = user;
+        this.permissions = permissions;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptIds;
-        this.user = user;
-        this.permissions = permissions;
-        this.tenantId = tenantId;
-    }
+    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptIds;
+        this.user = user;
+        this.permissions = permissions;
+        this.tenantId = tenantId;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId,Long currentDeptId, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptIds;
-        this.user = user;
-        this.permissions = permissions;
-        this.tenantId = tenantId;
-        this.currentDeptId = currentDeptId;
-    }
+    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId,Long currentDeptId, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptIds;
+        this.user = user;
+        this.permissions = permissions;
+        this.tenantId = tenantId;
+        this.currentDeptId = currentDeptId;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
     public Long getUserId()
     {
@@ -289,10 +298,11 @@
         return user;
     }
 
-    public void setUser(SysUser user)
-    {
-        this.user = user;
-    }
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
     @Override
     public Collection<? extends GrantedAuthority> getAuthorities()
@@ -320,6 +330,20 @@
         this.currentDeptId = currentDeptId;
     }
 
+    public Integer getAiEnabled() {
+        if (aiEnabled != null) {
+            return aiEnabled;
+        }
+        if (user != null && user.getAiEnabled() != null) {
+            return user.getAiEnabled();
+        }
+        return 0;
+    }
+
+    public void setAiEnabled(Integer aiEnabled) {
+        this.aiEnabled = aiEnabled;
+    }
+
     public String getDataScope() {
         return dataScope;
     }
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
index 4326c95..965cbf3 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -4,8 +4,10 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
+import java.time.LocalDate;
 
 @EqualsAndHashCode(callSuper = true)
 @Data
@@ -31,4 +33,15 @@
 
     @Schema(description = "瀹屾垚杩涘害")
     private BigDecimal completionStatus;
+
+    @Schema(description = "璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "寮�濮嬫棩鏈�")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startDate;
+
+    @Schema(description = "缁撴潫鏃ユ湡")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endDate;
 }
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
index decdc39..6c7c5a7 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
@@ -29,6 +29,15 @@
     @Schema(description = "宸ュ崟绫诲瀷 姝e父/杩斿伐杩斾慨")
     private String workOrderType;
 
+    @Schema(description = "鐢熶骇浠诲姟鏁�")
+    private Long productionTaskCount;
+
+    @Schema(description = "鑹搧鏁�")
+    private BigDecimal goodQuantity;
+
+    @Schema(description = "鎶ュ簾鏁伴噺")
+    private BigDecimal scrapQty;
+
     @Schema(description = "瀹屾垚杩涘害")
     private BigDecimal completionStatus;
 
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
index f3b48a6..1bb26a4 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
@@ -36,4 +36,7 @@
 
     @Schema(description = "瀹屾垚杩涘害")
     private BigDecimal completionStatus;
+
+    @Schema(description = "鏄惁宸查��鏂�")
+    private Boolean returned;
 }
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java
index ecbb0f2..2a0571d 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java
@@ -1,6 +1,5 @@
 package com.ruoyi.production.bean.vo;
 
-import com.ruoyi.production.pojo.ProductionOperationTask;
 import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
 import com.ruoyi.production.pojo.ProductionProductMain;
 import com.ruoyi.production.pojo.ProductionProductOutput;
@@ -13,54 +12,63 @@
 import java.util.List;
 
 @Data
-@Schema(name = "ProductionOrderWorkOrderDetailVo", description = "Production order work order/report/inspect detail")
+@Schema(name = "ProductionOrderWorkOrderDetailVo", description = "鐢熶骇杩芥函杩斿洖瀵硅薄")
 public class ProductionOrderWorkOrderDetailVo {
 
-    @Schema(description = "Production order info")
+    @Schema(description = "璁㈠崟")
     private ProductionOrderVo productionOrder;
 
-    @Schema(description = "Work order list")
+    @Schema(description = "宸ュ崟鏄庣粏鍒楄〃")
     private List<WorkOrderDetail> workOrderList;
 
     @Data
-    @Schema(name = "WorkOrderDetail", description = "Work order detail")
+    @Schema(name = "WorkOrderDetail", description = "宸ュ崟鏄庣粏")
     public static class WorkOrderDetail {
 
-        @Schema(description = "Work order info")
-        private ProductionOperationTask workOrder;
+        @Schema(description = "宸ュ崟淇℃伅")
+        private ProductionOperationTaskVo workOrder;
 
-        @Schema(description = "Report list under current work order")
+        @Schema(description = "鎶ュ伐璇︽儏鍒楄〃")
         private List<ReportDetail> reportList;
-    }
 
-    @Data
-    @Schema(name = "ReportDetail", description = "Production report detail")
-    public static class ReportDetail {
-
-        @Schema(description = "Report main info")
-        private ProductionProductMain reportMain;
-
-        @Schema(description = "Report output list")
-        private List<ProductionProductOutput> reportOutputList;
-
-        @Schema(description = "Report process param list")
-        private List<ProductionOrderRoutingOperationParam> reportParamList;
-
-        @Schema(description = "Inspect list under current report")
+        @Schema(description = "璐ㄦ璇︽儏鍒楄〃")
         private List<InspectDetail> inspectList;
     }
 
     @Data
-    @Schema(name = "InspectDetail", description = "Quality inspect detail")
+    @Schema(name = "ReportDetail", description = "鎶ュ伐璇︽儏")
+    public static class ReportDetail {
+
+        @Schema(description = "鎶ュ伐涓讳俊鎭�")
+        private ProductionProductMain reportMain;
+
+        @Schema(description = "鎶ュ伐浜у嚭鏄庣粏")
+        private List<ProductionProductOutput> reportOutputList;
+
+        @Schema(description = "鎶ュ伐宸ュ簭鍙傛暟")
+        private List<ProductionOrderRoutingOperationParam> reportParamList;
+    }
+
+    @Data
+    @Schema(name = "InspectDetail", description = "璐ㄦ璇︽儏")
     public static class InspectDetail {
 
-        @Schema(description = "Inspect main info")
+        @Schema(description = "鎶ュ伐ID")
+        private Long reportId;
+
+        @Schema(description = "鎶ュ伐鍗曞彿")
+        private String reportNo;
+
+        @Schema(description = "鎶ュ伐涓讳俊鎭�")
+        private ProductionProductMain reportMain;
+
+        @Schema(description = "璐ㄦ涓讳俊鎭�")
         private QualityInspect inspect;
 
-        @Schema(description = "Inspect param list")
+        @Schema(description = "璐ㄦ鎸囨爣鏄庣粏")
         private List<QualityInspectParam> inspectParamList;
 
-        @Schema(description = "Inspect attachment list")
+        @Schema(description = "璐ㄦ闄勪欢鍒楄〃")
         private List<QualityInspectFile> inspectFileList;
     }
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
index af6184a..56ed8c2 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -70,14 +70,16 @@
         return R.ok(productionOperationTaskService.assign(dto));
     }
 
-    /**
-     * 宸ュ崟娴佽浆鍗′笅杞�
-     * @param response
-     * @param dto
-     */
     @PostMapping("/down")
+    @Operation(summary = "宸ュ崟娴佽浆鍗′笅杞�")
     public void down(HttpServletResponse response, @RequestBody ProductionOperationTaskDto dto) {
         productionOperationTaskService.down(response, dto);
     }
 
+    @GetMapping("/getOperation")
+    @Operation(summary = "宸ュ簭璇︽儏鏌ヨ")
+    public R<List<ProductionOperationTaskVo>> getOperation(ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.getOperation(dto));
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
index 53a22a7..b5f7b97 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
@@ -84,10 +84,10 @@
         return R.ok(productionOrderService.pick(productionOrderId));
     }
 
-    @GetMapping("/workOrder/detail/{productionOrderId}")
-    @Operation(summary = "Query work orders/reports/inspects by production order id")
-    public R<ProductionOrderWorkOrderDetailVo> getWorkOrderReportInspectDetail(@PathVariable Long productionOrderId) {
-        return R.ok(productionOrderService.getWorkOrderReportInspectDetail(productionOrderId));
+    @GetMapping("/ordeDetail")
+    @Operation(summary = "鐢熶骇杩芥函")
+    public R<ProductionOrderWorkOrderDetailVo> getWorkOrderReportInspectDetail(ProductionOrderDto productionOrderDto) {
+        return R.ok(productionOrderService.getWorkOrderReportInspectDetail(productionOrderDto));
     }
 
     @Operation(summary = "鏇存柊璁㈠崟鐘舵��")
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
index 4349537..a09dd6f 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
@@ -41,4 +41,6 @@
                                                                            @Param("processIds") List<Long> processIds);
 
     ProductionOperationTaskDto getProductWorkOrderFlowCard(@Param("id") Long id);
+
+    List<ProductionOperationTaskVo> getOperation(@Param("c") ProductionOperationTaskDto dto);
 }
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
index 2735cc3..0945c6a 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -28,4 +28,6 @@
     boolean assign(ProductionOperationTaskDto dto);
 
     void down(HttpServletResponse response, ProductionOperationTaskDto dto);
+
+    List<ProductionOperationTaskVo> getOperation(ProductionOperationTaskDto dto);
 }
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
index 7e588dc..deeb0dd 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
@@ -32,7 +32,7 @@
 
     List<ProductionOrderPickVo> pick(Long productionOrderId);
 
-    ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(Long productionOrderId);
+    ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto productionOrderDto);
 
     int updateOrder(ProductionOrderDto productionOrderDto);
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
index aad1350..383193b 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -347,4 +347,9 @@
                 return null;
         }
     }
+
+    @Override
+    public List<ProductionOperationTaskVo> getOperation(ProductionOperationTaskDto dto) {
+        return baseMapper.getOperation(dto);
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
index 72a237e..f45c117 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
@@ -673,8 +673,8 @@
         if (dto.getProductModelId() == null) {
             throw new ServiceException("绗�" + rowNo + "鏉′骇鍝佽鏍糏D涓嶈兘涓虹┖");
         }
-        if (dto.getPickQuantity() == null || dto.getPickQuantity().compareTo(BigDecimal.ZERO) <= 0) {
-            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐暟閲忓繀椤诲ぇ浜�0");
+        if (dto.getPickQuantity() == null || dto.getPickQuantity().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐暟閲忎笉鑳藉皬浜�0");
         }
         if (dto.getPickType() != null && dto.getPickType() != PICK_TYPE_NORMAL && dto.getPickType() != PICK_TYPE_FEEDING) {
             throw new ServiceException("绗�" + rowNo + "鏉¢鏂欑被鍨嬪彧鑳芥槸1鎴�2");
@@ -688,8 +688,8 @@
         if (dto.getId() == null) {
             throw new ServiceException("绗�" + rowNo + "鏉¢鏂橧D涓嶈兘涓虹┖");
         }
-        if (dto.getFeedingQuantity() == null || dto.getFeedingQuantity().compareTo(BigDecimal.ZERO) <= 0) {
-            throw new ServiceException("绗�" + rowNo + "鏉℃湰娆¤ˉ鏂欐暟閲忓繀椤诲ぇ浜�0");
+        if (dto.getFeedingQuantity() == null || dto.getFeedingQuantity().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉℃湰娆¤ˉ鏂欐暟閲忎笉鑳藉皬浜�0");
         }
         if (!isFeedingPick(dto)) {
             throw new ServiceException("绗�" + rowNo + "鏉¤ˉ鏂欑被鍨嬪繀椤讳负2");
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
index 90c5e5c..9973d98 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -14,8 +14,10 @@
 import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.constant.StorageAttachmentConstants;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
 import com.ruoyi.production.bean.dto.ProductionOrderDto;
 import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
 import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
 import com.ruoyi.production.bean.vo.ProductionOrderVo;
 import com.ruoyi.production.bean.vo.ProductionPlanVo;
@@ -681,29 +683,33 @@
     }
 
     @Override
-    public ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(Long productionOrderId) {
-        if (productionOrderId == null) {
-            throw new ServiceException("productionOrderId can not be null");
-        }
+    public ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto dto) {
+        Long productionOrderId = resolveProductionOrderId(dto);
         ProductionOrderVo orderInfo = getProductionOrderInfo(productionOrderId);
         if (orderInfo == null) {
-            throw new ServiceException("production order not found");
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
         }
 
         ProductionOrderWorkOrderDetailVo detailVo = new ProductionOrderWorkOrderDetailVo();
         detailVo.setProductionOrder(orderInfo);
 
-        List<ProductionOperationTask> workOrderList = productionOperationTaskMapper.selectList(
-                Wrappers.<ProductionOperationTask>lambdaQuery()
-                        .eq(ProductionOperationTask::getProductionOrderId, productionOrderId)
-                        .orderByAsc(ProductionOperationTask::getId));
+        ProductionOperationTaskDto taskQuery = new ProductionOperationTaskDto();
+        taskQuery.setProductionOrderId(productionOrderId);
+        IPage<ProductionOperationTaskVo> workOrderPage = productionOperationTaskMapper.pageProductionOperationTask(
+                new Page<ProductionOperationTaskVo>(1, -1), taskQuery);
+        List<ProductionOperationTaskVo> workOrderList = workOrderPage == null || workOrderPage.getRecords() == null
+                ? Collections.emptyList()
+                : workOrderPage.getRecords().stream()
+                .filter(Objects::nonNull)
+                .sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder())))
+                .collect(Collectors.toList());
         if (workOrderList == null || workOrderList.isEmpty()) {
             detailVo.setWorkOrderList(Collections.emptyList());
             return detailVo;
         }
 
         List<Long> workOrderIdList = workOrderList.stream()
-                .map(ProductionOperationTask::getId)
+                .map(ProductionOperationTaskVo::getId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
         List<ProductionProductMain> reportMainList = workOrderIdList.isEmpty()
@@ -712,12 +718,12 @@
                 Wrappers.<ProductionProductMain>lambdaQuery()
                         .in(ProductionProductMain::getProductionOperationTaskId, workOrderIdList)
                         .orderByAsc(ProductionProductMain::getId));
-        Map<Long, List<ProductionProductMain>> reportMainMap = new LinkedHashMap<>();
+        Map<Long, List<ProductionProductMain>> reportMainByWorkOrderMap = new LinkedHashMap<>();
         for (ProductionProductMain reportMain : reportMainList) {
             if (reportMain == null || reportMain.getProductionOperationTaskId() == null) {
                 continue;
             }
-            reportMainMap.computeIfAbsent(reportMain.getProductionOperationTaskId(), k -> new ArrayList<>()).add(reportMain);
+            reportMainByWorkOrderMap.computeIfAbsent(reportMain.getProductionOperationTaskId(), key -> new ArrayList<>()).add(reportMain);
         }
 
         List<Long> reportMainIdList = reportMainList.stream()
@@ -766,7 +772,7 @@
                 if (inspect == null || inspect.getProductMainId() == null) {
                     continue;
                 }
-                inspectMap.computeIfAbsent(inspect.getProductMainId(), k -> new ArrayList<>()).add(inspect);
+                inspectMap.computeIfAbsent(inspect.getProductMainId(), key -> new ArrayList<>()).add(inspect);
             }
 
             List<Long> inspectIdList = inspectList.stream()
@@ -799,42 +805,44 @@
         }
 
         List<ProductionOrderWorkOrderDetailVo.WorkOrderDetail> workOrderDetailList = new ArrayList<>();
-        for (ProductionOperationTask workOrder : workOrderList) {
+        for (ProductionOperationTaskVo workOrder : workOrderList) {
             ProductionOrderWorkOrderDetailVo.WorkOrderDetail workOrderDetail = new ProductionOrderWorkOrderDetailVo.WorkOrderDetail();
             workOrderDetail.setWorkOrder(workOrder);
 
-            List<ProductionProductMain> workOrderReportMainList = reportMainMap.get(workOrder.getId());
-            if (workOrderReportMainList == null || workOrderReportMainList.isEmpty()) {
+            List<ProductionProductMain> workOrderReportMainList = reportMainByWorkOrderMap.getOrDefault(workOrder.getId(), Collections.emptyList());
+            if (workOrderReportMainList.isEmpty()) {
                 workOrderDetail.setReportList(Collections.emptyList());
+                workOrderDetail.setInspectList(Collections.emptyList());
                 workOrderDetailList.add(workOrderDetail);
                 continue;
             }
 
             List<ProductionOrderWorkOrderDetailVo.ReportDetail> reportDetailList = new ArrayList<>();
+            List<ProductionOrderWorkOrderDetailVo.InspectDetail> inspectDetailList = new ArrayList<>();
             for (ProductionProductMain reportMain : workOrderReportMainList) {
                 Long reportMainId = reportMain.getId();
+
                 ProductionOrderWorkOrderDetailVo.ReportDetail reportDetail = new ProductionOrderWorkOrderDetailVo.ReportDetail();
                 reportDetail.setReportMain(reportMain);
                 reportDetail.setReportOutputList(reportOutputMap.getOrDefault(reportMainId, Collections.emptyList()));
                 reportDetail.setReportParamList(reportParamMap.getOrDefault(reportMainId, Collections.emptyList()));
-
-                List<QualityInspect> reportInspectList = inspectMap.get(reportMainId);
-                if (reportInspectList == null || reportInspectList.isEmpty()) {
-                    reportDetail.setInspectList(Collections.emptyList());
-                } else {
-                    List<ProductionOrderWorkOrderDetailVo.InspectDetail> inspectDetailList = new ArrayList<>();
-                    for (QualityInspect inspect : reportInspectList) {
-                        ProductionOrderWorkOrderDetailVo.InspectDetail inspectDetail = new ProductionOrderWorkOrderDetailVo.InspectDetail();
-                        inspectDetail.setInspect(inspect);
-                        inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList()));
-                        inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList()));
-                        inspectDetailList.add(inspectDetail);
-                    }
-                    reportDetail.setInspectList(inspectDetailList);
-                }
                 reportDetailList.add(reportDetail);
+
+                List<QualityInspect> reportInspectList = inspectMap.getOrDefault(reportMainId, Collections.emptyList());
+                for (QualityInspect inspect : reportInspectList) {
+                    ProductionOrderWorkOrderDetailVo.InspectDetail inspectDetail = new ProductionOrderWorkOrderDetailVo.InspectDetail();
+                    inspectDetail.setReportId(reportMainId);
+                    inspectDetail.setReportNo(reportMain.getProductNo());
+                    inspectDetail.setReportMain(reportMain);
+                    inspectDetail.setInspect(inspect);
+                    inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList()));
+                    inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList()));
+                    inspectDetailList.add(inspectDetail);
+                }
             }
+
             workOrderDetail.setReportList(reportDetailList);
+            workOrderDetail.setInspectList(inspectDetailList);
             workOrderDetailList.add(workOrderDetail);
         }
 
@@ -842,6 +850,26 @@
         return detailVo;
     }
 
+    private Long resolveProductionOrderId(ProductionOrderDto dto) {
+        if (dto == null) {
+            throw new ServiceException("璇蜂紶鍏ョ敓浜ц鍗旾D鎴栫敓浜ц鍗曞彿");
+        }
+        if (dto.getId() != null) {
+            return dto.getId();
+        }
+        if (dto.getNpsNo() == null || dto.getNpsNo().trim().isEmpty()) {
+            throw new ServiceException("璇蜂紶鍏ョ敓浜ц鍗旾D鎴栫敓浜ц鍗曞彿");
+        }
+        ProductionOrder productionOrder = baseMapper.selectOne(
+                Wrappers.<ProductionOrder>lambdaQuery()
+                        .eq(ProductionOrder::getNpsNo, dto.getNpsNo().trim())
+                        .last("limit 1"));
+        if (productionOrder == null || productionOrder.getId() == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+        return productionOrder.getId();
+    }
+
     @Override
     public List<ProductionOrderPickVo> pick(Long productionOrderId) {
         if (productionOrderId == null) {
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
index ad9a8b3..e08c368 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
@@ -12,9 +12,10 @@
 import com.ruoyi.project.system.domain.SysMenu;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
-import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.service.ISysMenuService;
-import com.ruoyi.project.system.service.ISysUserDeptService;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.service.ISysMenuService;
+import com.ruoyi.project.system.service.ISysUserDeptService;
+import com.ruoyi.project.system.service.ISysUserService;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.ObjectUtils;
@@ -40,10 +41,11 @@
 {
     private SysLoginService loginService;
     private ISysMenuService menuService;
-    private SysPermissionService permissionService;
-    private TokenService tokenService;
-    private ISysUserDeptService userDeptService;
-    private SysDeptMapper sysDeptMapper;
+    private SysPermissionService permissionService;
+    private TokenService tokenService;
+    private ISysUserDeptService userDeptService;
+    private ISysUserService userService;
+    private SysDeptMapper sysDeptMapper;
 
     /**
      * 鐧诲綍鏂规硶
@@ -71,7 +73,17 @@
     public AjaxResult getInfo()
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        SysUser user = loginUser.getUser();
+        SysUser user = userService.selectUserById(loginUser.getUserId());
+        if (user == null)
+        {
+            user = loginUser.getUser();
+        }
+        else
+        {
+            loginUser.setUser(user);
+            loginUser.setAiEnabled(user.getAiEnabled());
+            tokenService.setLoginUser(loginUser);
+        }
         // 鑾峰彇褰撳墠鐧诲綍鍏徃
         Long tenantId = loginUser.getTenantId();
         if(null != tenantId){
@@ -90,11 +102,12 @@
             loginUser.setPermissions(permissions);
             tokenService.refreshToken(loginUser);
         }
-        AjaxResult ajax = AjaxResult.success();
-        ajax.put("user", user);
-        ajax.put("roles", roles);
-        ajax.put("permissions", permissions);
-        return ajax;
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("user", user);
+        ajax.put("aiEnabled", loginUser.getAiEnabled());
+        ajax.put("roles", roles);
+        ajax.put("permissions", permissions);
+        return ajax;
     }
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
index d75fcc0..515210e 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysUser.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.system.domain;
 
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.ruoyi.common.xss.Xss;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.common.xss.Xss;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type;
@@ -59,9 +60,13 @@
     @Excel(name = "璐﹀彿鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
     private String status;
 
-    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
-    private String delFlag;
-
+    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+    private String delFlag;
+
+    /** 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級 */
+    @JsonIgnore
+    private Integer aiEnabled;
+
     /** 鏈�鍚庣櫥褰旾P */
     @Excel(name = "鏈�鍚庣櫥褰旾P", type = Type.EXPORT)
     private String loginIp;
@@ -250,15 +255,25 @@
         this.status = status;
     }
 
-    public String getDelFlag()
-    {
-        return delFlag;
-    }
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
 
-    public void setDelFlag(String delFlag)
-    {
-        this.delFlag = delFlag;
-    }
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Integer getAiEnabled()
+    {
+        return aiEnabled;
+    }
+
+    public void setAiEnabled(Integer aiEnabled)
+    {
+        this.aiEnabled = aiEnabled;
+    }
 
     public String getLoginIp()
     {
@@ -373,9 +388,10 @@
             .append("sex", getSex())
             .append("avatar", getAvatar())
             .append("password", getPassword())
-            .append("status", getStatus())
-            .append("delFlag", getDelFlag())
-            .append("loginIp", getLoginIp())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("aiEnabled", getAiEnabled())
+            .append("loginIp", getLoginIp())
             .append("loginDate", getLoginDate())
             .append("createBy", getCreateBy())
             .append("createTime", getCreateTime())
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index 0ccb06f..577bcfd 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -29,7 +29,8 @@
                pm.model as model,
                pm.unit as unit,
                poro.operation_name as operationName,
-        ROUND(pot.complete_quantity / pot.plan_quantity * 100, 2) AS completionStatus,
+               IFNULL(scrapStat.scrapQty, 0) AS scrapQty,
+        ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus,
         CASE
             WHEN pot.work_order_no LIKE 'FG%' THEN '杩斿伐杩斾慨'
             ELSE '姝e父'
@@ -39,9 +40,19 @@
                  left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
                  left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
                  left join product p on pm.product_id = p.id
+                 left join (
+            select ppm.production_operation_task_id as taskId,
+                   sum(ifnull(ppo.scrap_qty, 0)) as scrapQty
+            from production_product_main ppm
+                     left join production_product_output ppo on ppo.production_product_main_id = ppm.id
+            group by ppm.production_operation_task_id
+        ) scrapStat on scrapStat.taskId = pot.id
         <where>
             <if test="c != null and c.id != null">
                 and pot.id = #{c.id}
+            </if>
+            <if test="c != null and c.npsNo != null">
+                and po.nps_no like concat('%', #{c.npsNo}, '%')
             </if>
             <if test="c != null and c.productionOrderId != null">
                 and pot.production_order_id = #{c.productionOrderId}
@@ -145,4 +156,58 @@
         WHERE pot.id = #{id}
     </select>
 
+    <select id="getOperation" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo">
+        select poro.operation_name as operationName,
+               count(pot.id) as productionTaskCount,
+               sum(ifnull(pot.plan_quantity, 0)) as planQuantity,
+               sum(ifnull(pot.complete_quantity, 0)) as completeQuantity,
+               sum(ifnull(pot.complete_quantity, 0)) as goodQuantity,
+               sum(ifnull(outputStat.scrapQty, 0)) as scrapQty,
+               round(
+                   case
+                       when sum(ifnull(pot.plan_quantity, 0)) = 0 then 0
+                       else (sum(ifnull(pot.complete_quantity, 0)) + sum(ifnull(outputStat.scrapQty, 0)))
+                           / sum(ifnull(pot.plan_quantity, 0)) * 100
+                       end,
+                   2
+               ) as completionStatus
+        from production_operation_task pot
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join (
+            select ppm.production_operation_task_id as taskId,
+                   sum(ifnull(ppo.scrap_qty, 0)) as scrapQty
+            from production_product_main ppm
+                     left join production_product_output ppo on ppo.production_product_main_id = ppm.id
+            group by ppm.production_operation_task_id
+        ) outputStat on outputStat.taskId = pot.id
+        <where>
+            <if test="c != null and c.startDate != null">
+                and date(pot.create_time) &gt;= #{c.startDate}
+            </if>
+            <if test="c != null and c.endDate != null">
+                and date(pot.create_time) &lt;= #{c.endDate}
+            </if>
+            <if test="c != null and c.planStartTime != null">
+                and pot.plan_start_time &gt;= #{c.planStartTime}
+            </if>
+            <if test="c != null and c.planEndTime != null">
+                and pot.plan_end_time &lt;= #{c.planEndTime}
+            </if>
+            <if test="c != null and c.productionOrderId != null">
+                and pot.production_order_id = #{c.productionOrderId}
+            </if>
+            <if test="c != null and c.productionOrderRoutingOperationId != null">
+                and pot.production_order_routing_operation_id = #{c.productionOrderRoutingOperationId}
+            </if>
+            <if test="c != null and c.status != null">
+                and pot.status = #{c.status}
+            </if>
+            <if test="c != null and c.processName != null and c.processName != ''">
+                and poro.operation_name like concat('%', #{c.processName}, '%')
+            </if>
+        </where>
+        group by poro.operation_name
+        order by min(poro.drag_sort), poro.operation_name
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
index 2ea7d33..1a304ef 100644
--- a/src/main/resources/mapper/production/ProductionOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -27,6 +27,7 @@
         <result column="productName" property="productName" />
         <result column="model" property="model" />
         <result column="processRouteCode" property="processRouteCode" />
+        <result column="returned" property="returned" />
     </resultMap>
 
     <sql id="ProductionOrderVoColumns">
@@ -52,7 +53,8 @@
         po.is_end_order as endOrder,
         tr.process_route_code as processRouteCode,
         ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
-        tb.bom_no as bomNo
+        tb.bom_no as bomNo,
+        pop_return.returned as returned
     </sql>
 
     <sql id="ProductionOrderVoFrom">
@@ -73,6 +75,12 @@
                  left join product p on pm.product_id = p.id
                  left join technology_routing tr on po.technology_routing_id = tr.id
                  left join technology_bom tb on tb.id = tr.bom_id
+                 left join (
+            select production_order_id as productionOrderId,
+                   if(max(case when ifnull(is_returned, 0) = 1 then 1 else 0 end) = 1, true, false) as returned
+            from production_order_pick
+            group by production_order_id
+        ) pop_return on pop_return.productionOrderId = po.id
     </sql>
 
     <sql id="ProductionOrderWhere">
diff --git a/src/main/resources/mapper/system/SysUserMapper.xml b/src/main/resources/mapper/system/SysUserMapper.xml
index e27a224..72da1a1 100644
--- a/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/src/main/resources/mapper/system/SysUserMapper.xml
@@ -15,6 +15,7 @@
         <result property="password"     column="password"     />
         <result property="status"       column="status"       />
         <result property="delFlag"      column="del_flag"     />
+        <result property="aiEnabled"    column="ai_enabled"   />
         <result property="loginIp"      column="login_ip"     />
         <result property="loginDate"    column="login_date"   />
         <result property="createBy"     column="create_by"    />
@@ -48,7 +49,7 @@
     </resultMap>
 
 	<sql id="selectUserVo">
-        select u.user_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
+        select u.user_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.ai_enabled, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,u.tenant_id
         from sys_user u
 		    left join sys_user_role ur on u.user_id = ur.user_id

--
Gitblit v1.9.3