From 2eb261814a2407b3481dfe7b995c58d413a18cff Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 20 十月 2026 16:28:17 +0800
Subject: [PATCH] feat(quality): 质量监督/质量监控流程对齐程序文件并完善导入

---
 basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java                          |    7 +
 cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorService.java                      |    4 
 cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java           |  143 ++++++++++++++++++++---
 cnas-process/src/main/resources/mapper/QualitySuperviseDetailsRecordMapper.xml                       |    5 
 basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java                    |    6 +
 cnas-process/src/main/resources/static/daily-supervise-record.docx                                   |    0 
 cnas-process/src/main/java/com/ruoyi/process/pojo/QualityMonitorDetailsEvaluate.java                 |    8 +
 cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingDetailedServiceImpl.java |   28 ++++
 cnas-process/src/main/java/com/ruoyi/process/task/QualitySuperviseSchedule.java                      |    5 
 cnas-process/src/main/java/com/ruoyi/process/service/impl/QualityMonitorServiceImpl.java             |   39 -----
 cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorInspectionEvaluationService.java  |   20 +++
 cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java                    |    7 +
 basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java                 |   23 +++
 cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java              |   10 +
 cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java                 |   13 +
 15 files changed, 248 insertions(+), 70 deletions(-)

diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java
index 55c0845..08b9bf9 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java
@@ -193,6 +193,12 @@
         return Result.success(standardTreeService.selectTemplateBindings(standardTreeId));
     }
 
+    @Operation(summary = "鏍规嵁鏍囧噯鏂规硶鏌ヨ鏍囧噯缁戝畾鐨勫師濮嬭褰曟ā鏉�")
+    @GetMapping("/selectTemplateBindingsByStandardMethod")
+    public Result selectTemplateBindingsByStandardMethod(Integer standardMethodId) {
+        return Result.success(standardTreeService.selectTemplateBindingsByStandardMethod(standardMethodId));
+    }
+
     @Operation(summary = "淇濆瓨鏍囧噯缁戝畾鐨勫師濮嬭褰曟ā鏉�")
     @PostMapping("/saveTemplateBindings")
     public Result saveTemplateBindings(@RequestBody StandardTreeTemplateBindingDto dto) {
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java
index aca97aa..58373e4 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java
@@ -43,6 +43,13 @@
 
     List<StandardTreeTemplateBindingVo> selectTemplateBindings(Integer standardTreeId);
 
+    /**
+     * 鏍规嵁鏍囧噯鏂规硶鏌ヨ鏍囧噯搴撲腑宸茬粦瀹氱殑鍘熷璁板綍妯℃澘
+     * @param standardMethodId 鏍囧噯鏂规硶ID
+     * @return 宸茬粦瀹氱殑妯℃澘锛堝涓爣鍑嗗簱鑺傜偣缁戝畾鐨勬ā鏉夸細鍘婚噸鍚堝苟锛�
+     */
+    List<StandardTreeTemplateBindingVo> selectTemplateBindingsByStandardMethod(Integer standardMethodId);
+
     boolean saveTemplateBindings(StandardTreeTemplateBindingDto dto);
 
     List<TemplateInspectionItemDto> selectTemplateInspectionItems(Integer standardTreeId);
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
index 8b5ae45..159fcb0 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
@@ -419,6 +419,29 @@
     }
 
     @Override
+    public List<StandardTreeTemplateBindingVo> selectTemplateBindingsByStandardMethod(Integer standardMethodId) {
+        List<StandardTreeTemplateBindingVo> result = new ArrayList<>();
+        if (standardMethodId == null) {
+            return result;
+        }
+        List<StandardTree> trees = this.list(Wrappers.<StandardTree>lambdaQuery()
+                .eq(StandardTree::getStandardMethodId, standardMethodId)
+                .isNull(StandardTree::getSampleType)
+                .isNull(StandardTree::getModel)
+                .isNotNull(StandardTree::getSample)
+                .orderByAsc(StandardTree::getId));
+        Set<Integer> templateIds = new HashSet<>();
+        for (StandardTree tree : trees) {
+            for (StandardTreeTemplateBindingVo binding : selectTemplateBindings(tree.getId())) {
+                if (templateIds.add(binding.getTemplateId())) {
+                    result.add(binding);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean saveTemplateBindings(StandardTreeTemplateBindingDto dto) {
         if (dto == null || dto.getStandardTreeId() == null) {
diff --git a/cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingDetailedServiceImpl.java b/cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingDetailedServiceImpl.java
index 7c05355..eb6fa8a 100644
--- a/cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingDetailedServiceImpl.java
+++ b/cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingDetailedServiceImpl.java
@@ -57,7 +57,7 @@
             personTrainingDetailed.setPlanId(planId);
             personTrainingDetailed.setState(3);
 
-            personTrainingDetailed.setTrainingDate(i.getTrainingDate());
+            personTrainingDetailed.setTrainingDate(normalizeTrainingDate(i.getTrainingDate()));
 
 
             personTrainingDetailedList.add(personTrainingDetailed);
@@ -68,6 +68,32 @@
         }
     }
 
+    /**
+     * 鍩硅鏃堕棿缁熶竴鎴� yyyy-MM-dd銆�
+     * Excel 閲岃鑷姩璇嗗埆鎴愭棩鏈熺殑鍗曞厓鏍艰鍑烘潵鏄� 2026/3/15锛屾墜宸ュ綍鍏ョ殑鏄� 2026-03-15锛�
+     * 杩欓噷缁熶竴杞崲锛岄伩鍏嶅鍑烘椂鏍煎紡涓嶄竴鑷淬��
+     */
+    private String normalizeTrainingDate(String value) {
+        if (value == null || value.isBlank()) {
+            return value;
+        }
+        String text = value.trim().split("\\s+")[0]
+                .replace('骞�', '-').replace('鏈�', '-').replace("鏃�", "")
+                .replace('/', '-').replace('.', '-');
+        String[] parts = text.split("-");
+        if (parts.length == 3) {
+            try {
+                int year = Integer.parseInt(parts[0].trim());
+                int month = Integer.parseInt(parts[1].trim());
+                int day = Integer.parseInt(parts[2].trim());
+                return String.format("%04d-%02d-%02d", year, month, day);
+            } catch (NumberFormatException ignored) {
+                // 涓嶆槸鍙瘑鍒殑鏃ユ湡鏍煎紡锛屽師鏍蜂繚瀛�
+            }
+        }
+        return value.trim();
+    }
+
     @Override
     public void deleteAnnualPlanDetailTable(String ids) {
         String[] split = ids.split(",");
diff --git a/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java b/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
index 369546a..1430ed5 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
@@ -191,6 +191,16 @@
     }
 
     /**
+     * 琚洃鐫d汉鍛樼‘璁ょ洃鐫h褰�
+     * @return
+     */
+    @Operation(summary = "琚洃鐫d汉鍛樼‘璁ょ洃鐫h褰�")
+    @PostMapping("/confirmSuperviseRecord")
+    public Result confirmSuperviseRecord(@RequestBody QualitySuperviseDetailsRecord qualitySuperviseDetailsRecord){
+        return Result.success(qualitySuperviseService.confirmSuperviseRecord(qualitySuperviseDetailsRecord));
+    }
+
+    /**
      * 瀵煎嚭璐ㄩ噺鐩戠潱璇︽儏璁板綍琛�
      * @return
      */
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualityMonitorDetailsEvaluate.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualityMonitorDetailsEvaluate.java
index 622320e..6a92a3c 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualityMonitorDetailsEvaluate.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualityMonitorDetailsEvaluate.java
@@ -29,10 +29,16 @@
 
     @Schema(description = "鍏宠仈鐨勮川鎺ф楠屼换鍔D")
     private Integer insOrderId;
-    @Schema(description = "鐩戠潱鍛樼敤鎴稩D锛屼笌璇勪环浜哄垎寮�")
+    @Schema(description = "鐩戠潱鍛樼敤鎴稩D锛岄粯璁や负璁″垝涓寚瀹氱殑璇勪环浜�")
     private Integer supervisorUserId;
+    @Schema(description = "鐩戠潱鍛樺悕绉帮紝闈炴暟鎹簱瀛楁")
+    @TableField(exist = false)
+    private String supervisorName;
     @Schema(description = "琚洃鐫f娴嬪憳鐢ㄦ埛ID")
     private Integer inspectorUserId;
+    @Schema(description = "琚洃鐫f娴嬪憳鍚嶇О锛岄潪鏁版嵁搴撳瓧娈�")
+    @TableField(exist = false)
+    private String inspectorName;
     @Schema(description = "妫�娴嬫牱鍝佸悕绉�")
     private String sampleName;
     @Schema(description = "妫�娴嬫牱鍝佽鏍�")
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
index e652262..3f10ab6 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
@@ -14,7 +14,8 @@
  * @since 2024-11-07
  */
 @Data
-@TableName("cnas_quality_supervise_details_record")
+// autoResultMap: testing_process/supervision_evaluation 澶嶇敤浜嗗巻鍙插垪鍚�, 闇�瑕� MP 鑷姩鐢熸垚缁撴灉鏄犲皠
+@TableName(value = "cnas_quality_supervise_details_record", autoResultMap = true)
 @Schema(description = "璐ㄩ噺鐩戠潱璇︽儏璁板綍琛�")
 public class QualitySuperviseDetailsRecord {
 
@@ -51,8 +52,9 @@
     @Schema(description = "妫�娴嬫棩鏈�")
     private String testDate;
 
-    @Schema(description = "妫�娴嬭繃绋�")
-    private String testingProcess;
+    @Schema(description = "鐩戠潱鏂瑰紡(澶氶」椤垮彿鍒嗛殧)锛氭牳鏌ュ師濮嬭褰曞拰鎶ュ憡銆佺幇鍦虹洃鐫e疄闄呮搷浣滆繃绋嬬瓑")
+    @TableField("testing_process")
+    private String superviseMethod;
 
     @Schema(description = "鎯呭喌璁板綍")
     private String caseReload;
@@ -81,8 +83,9 @@
     @Schema(description = "妫�娴嬫姤鍛�")
     private String examiningReport;
 
-    @Schema(description = "鐩戠潱鎯呭喌璇勪环")
-    private String supervisionEvaluation;
+    @Schema(description = "琚洃鐫d汉鍛樼‘璁ゆ剰瑙�(绋嬪簭4.2.5)")
+    @TableField("supervision_evaluation")
+    private String confirmOpinion;
 
     @Schema(description = "涓嶅悎鏍煎鐞嗘剰瑙�")
     private String handlingAdvice;
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorInspectionEvaluationService.java b/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorInspectionEvaluationService.java
index f94a4e1..3b64429 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorInspectionEvaluationService.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorInspectionEvaluationService.java
@@ -61,6 +61,14 @@
             evaluation.setSampleName(detail.getSampleName());
             evaluation.setSampleSpec(detail.getSampleSpec());
         }
+        // 璇勪环璁板綍閲岀殑鈥滅洃鐫e憳鈥濆氨鏄鍒掍腑鎸囧畾鐨勨�滆瘎浠蜂汉鈥濓紝鏈繚瀛樿繃璇勪环鏃剁洿鎺ュ弽鏄捐瘎浠蜂汉
+        if (evaluation.getSupervisorUserId() == null) {
+            evaluation.setSupervisorUserId(detail.getEvaluatorUserId());
+        }
+        // 鍘嗗彶璇勪环璁板綍鍙兘娌℃湁淇濆瓨琚洃鐫d汉鍛橈紝鍥為��鍒拌鍒掓槑缁嗕腑鐨勬娴嬪憳
+        if (evaluation.getInspectorUserId() == null) {
+            evaluation.setInspectorUserId(detail.getInspectorUserId());
+        }
         List<QualityMonitorEvaluateResult> rows = evaluation.getDetailsEvaluateId() == null
                 ? List.of() : resultMapper.selectList(Wrappers.<QualityMonitorEvaluateResult>lambdaQuery()
                                                       .eq(QualityMonitorEvaluateResult::getDetailsEvaluateId, evaluation.getDetailsEvaluateId())
@@ -85,6 +93,15 @@
         }
         evaluation.setResultRows(rows);
         evaluation.setInspectionTaskState(task == null ? null : task.getInsState());
+        // 鐩戠潱鍛樸�佹娴嬪憳鍙兘涓嶅湪鍓嶇浜哄憳涓嬫媺鍒楄〃涓紙瑙掕壊鎴栫姸鎬佽杩囨护锛夛紝鍥炰紶鍚嶇О淇濊瘉鑳芥甯稿弽鏄�
+        if (evaluation.getSupervisorUserId() != null) {
+            var supervisor = userMapper.selectById(evaluation.getSupervisorUserId());
+            if (supervisor != null) evaluation.setSupervisorName(supervisor.getName());
+        }
+        if (evaluation.getInspectorUserId() != null) {
+            var inspector = userMapper.selectById(evaluation.getInspectorUserId());
+            if (inspector != null) evaluation.setInspectorName(inspector.getName());
+        }
         if (Integer.valueOf(1).equals(evaluation.getIsFinish())) {
             evaluation.setEvaluationEditReason("璇勪环宸叉壒鍑嗗綊妗o紝鍙兘鏌ョ湅");
         } else if (task == null) {
@@ -117,9 +134,8 @@
             throw new ErrorException("鍙湁鎸囧畾璇勪环浜哄彲浠ュ~鍐欒瘎浠�");
         if (input.getSupervisorUserId() == null
                 || input.getSupervisorUserId().equals(detail.getInspectorUserId())
-                || input.getSupervisorUserId().equals(detail.getEvaluatorUserId())
                 || userMapper.selectById(input.getSupervisorUserId()) == null)
-            throw new ErrorException("璇烽�夋嫨涓庢娴嬪憳銆佽瘎浠蜂汉涓嶅悓鐨勭洃鐫e憳");
+            throw new ErrorException("璇烽�夋嫨鐩戠潱鍛橈紙榛樿涓鸿鍒掕瘎浠蜂汉锛屼笉鑳戒笌妫�娴嬪憳鐩稿悓锛�");
         Long pendingCount = stateMapper.selectCount(Wrappers.<InsOrderState>lambdaQuery()
                 .eq(InsOrderState::getInsOrderId, task.getId()).ne(InsOrderState::getInsState, 5));
         if (pendingCount > 0) throw new ErrorException("鍘熷璁板綍澶嶆牳閫氳繃鍚庢墠鑳借瘎浠�");
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorService.java b/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorService.java
index 55182c4..c2ee587 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorService.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/QualityMonitorService.java
@@ -30,9 +30,9 @@
     /**
      * 瀵煎叆鐩戞帶璁″垝
      * @param file
-     * @return
+     * @return 瀵煎叆鍚庣敓鎴愮殑鑽夌璁″垝
      */
-    boolean importQualityMonitor(MultipartFile file, QualityMonitor qualityMonitor);
+    QualityMonitor importQualityMonitor(MultipartFile file, QualityMonitor qualityMonitor);
 
 
     /**
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java b/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
index 832f672..5de8b83 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
@@ -90,6 +90,13 @@
     boolean addSuperviseRecordOpinion(QualitySuperviseDetailsRecord qualitySuperviseDetailsRecord);
 
     /**
+     * 琚洃鐫d汉鍛樼‘璁ょ洃鐫h褰�(绋嬪簭4.2.5)
+     * @param qualitySuperviseDetailsRecord 鑷冲皯鍖呭惈 superviseDetailsId 鍜� confirmOpinion
+     * @return
+     */
+    boolean confirmSuperviseRecord(QualitySuperviseDetailsRecord qualitySuperviseDetailsRecord);
+
+    /**
      * 瀵煎嚭鐩戠潱璁板綍琛�
      * @param superviseDetailsId
      * @param response
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualityMonitorServiceImpl.java b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualityMonitorServiceImpl.java
index bf60509..e8f1d62 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualityMonitorServiceImpl.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualityMonitorServiceImpl.java
@@ -211,7 +211,7 @@
      * @return
      */
     @Override
-    public boolean importQualityMonitor(MultipartFile file, QualityMonitor monitor) {
+    public QualityMonitor importQualityMonitor(MultipartFile file, QualityMonitor monitor) {
         // 褰撳墠鐧诲綍鐢ㄦ埛
         Integer userId = SecurityUtils.getUserId().intValue();
         // 鏂囦欢鍚嶇О
@@ -226,39 +226,10 @@
         qualityMonitor.setWriteUserId(userId);
         qualityMonitor.setExamineUserId(monitor.getExamineUserId());
         qualityMonitor.setWriteTime(LocalDateTime.now());
-        qualityMonitor.setWorkflowStatus("PENDING_REVIEW");
+        // 瀵煎叆鍙敓鎴愯崏绋匡紝瀵煎叆鐨勮川鎺ч」鐩繕闇�瑕佽ˉ鍏ㄦ娴嬫爣鍑嗐�佹娴嬪憳绛変俊鎭紱
+        // 瀹℃牳閫氱煡鍦ㄧ紪鍒朵汉鐐瑰嚮鈥滄彁浜ゅ鏍糕�濇椂缁熶竴鍙戦�併��
+        qualityMonitor.setWorkflowStatus("DRAFT");
         baseMapper.insert(qualityMonitor);
-
-        User user = userMapper.selectById(userId);
-        // 娑堟伅鍙戦��
-        InformationNotification info = new InformationNotification();
-        // 鍙戦�佷汉
-        info.setCreateUser(user.getName());
-        info.setMessageType("6");
-        info.setTheme("CNAS璐ㄩ噺鐩戞帶璁″垝瀹℃牳閫氱煡");
-        info.setContent(fileName + "璐ㄩ噺鐩戞帶璁″垝寰呭鏍�");
-        info.setSenderId(userId);
-        // 鎺ユ敹浜�
-        info.setConsigneeId(monitor.getExamineUserId());
-        info.setJumpPath(MenuJumpPathConstants.QUALITY_MONITOR);
-        informationNotificationService.addInformationNotification(info);
-
-        // 鍙戦�佷紒涓氬井淇¢�氱煡
-        threadPoolTaskExecutor.execute(() -> {
-            // 鏌ヨ鍙戦�佷汉
-            User people = userMapper.selectById(monitor.getExamineUserId());
-            String message = "";
-            message += "CNAS璐ㄩ噺鐩戞帶璁″垝瀹℃牳閫氱煡";
-            message += "\n璇峰幓杩囩▼瑕佹眰-璐ㄩ噺鐩戞帶璁″垝";
-            message += "\n" + fileName + "璐ㄩ噺鐩戞帶璁″垝寰呭鏍�";
-            //鍙戦�佷紒涓氬井淇℃秷鎭�氱煡
-            try {
-                WxCpUtils.inform(people.getAccount(), message, null);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        });
-
 
         List<QualityMonitorDetails> detailsUploadList = new ArrayList<>();
 
@@ -303,7 +274,7 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-        return true;
+        return qualityMonitor;
     }
 
     /**
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
index 6219c17..87f9a83 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
@@ -56,6 +56,8 @@
 import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.Base64;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -178,8 +180,8 @@
                         throw new ErrorException("鏈壘鍒拌鐩戠潱鍛橈細" + superviseDetails.getSupervisee());
                     }
                     superviseDetails.setSupervisedUserId(user.getId());
-                    // 鏍煎紡鍖栨椂闂�
-                    superviseDetails.setSuperviseTime(detailsUpload.getSuperviseTime());
+                    // 缁熶竴鏃ユ湡鏍煎紡锛岄伩鍏� Excel 鎶� 2026-03-15 瀛樻垚 2026/3/15 鍚庢棤娉曡В鏋�
+                    superviseDetails.setSuperviseTime(normalizeSuperviseTime(detailsUpload.getSuperviseTime()));
 
                     detailsUploadList.add(superviseDetails);
                 }
@@ -432,6 +434,59 @@
     }
 
     /**
+     * 缁熶竴鐩戠潱鏃ユ湡鏍煎紡涓� yyyy.M锛�
+     * 2026-03-15 / 2026/3/15 / 2026.3.15 / 2026骞�3鏈�15鏃� -> 2026.3锛�
+     * 宸茬粡鏄� 2026.3 鎴� "3鏈堛��12鏈�" 绛夊啓娉曚繚鎸佸師鏍枫��
+     */
+    private static String normalizeSuperviseTime(String superviseTime) {
+        if (StringUtils.isBlank(superviseTime)) {
+            return superviseTime;
+        }
+        String text = superviseTime.trim();
+        Matcher matcher = Pattern.compile("^(\\d{4})\\s*[./骞�-]\\s*(\\d{1,2})(?:\\s*[./鏈�-]\\s*(\\d{1,2})\\s*鏃�?)?$")
+                .matcher(text);
+        if (matcher.matches()) {
+            int month = Integer.parseInt(matcher.group(2));
+            if (month >= 1 && month <= 12) {
+                return matcher.group(1) + "." + month;
+            }
+        }
+        return text;
+    }
+
+    /**
+     * 瑙f瀽鐩戠潱鏃ユ湡瀵瑰簲鐨勫勾鏈堬紝鍏煎鍘嗗彶鏁版嵁涓殑瀹屾暣鏃ユ湡鍐欐硶銆�
+     */
+    private static YearMonth parseSuperviseYearMonth(String superviseTime, String fallbackYear) {
+        if (StringUtils.isNotBlank(superviseTime)) {
+            String first = superviseTime.split("[銆�,锛�;锛沒+")[0].trim();
+            Matcher fullDate = Pattern.compile("(\\d{4})\\s*[./骞�-]\\s*(\\d{1,2})").matcher(first);
+            if (fullDate.find()) {
+                int month = Integer.parseInt(fullDate.group(2));
+                if (month >= 1 && month <= 12) {
+                    return YearMonth.of(Integer.parseInt(fullDate.group(1)), month);
+                }
+            }
+            // "3鏈堛��12鏈�" 杩欑被娌℃湁骞翠唤鐨勫啓娉曪紝浣跨敤璁″垝骞村害
+            Matcher monthOnly = Pattern.compile("^(\\d{1,2})").matcher(first);
+            if (monthOnly.find()) {
+                int month = Integer.parseInt(monthOnly.group(1));
+                if (month >= 1 && month <= 12) {
+                    int year = LocalDate.now().getYear();
+                    if (StringUtils.isNotBlank(fallbackYear)) {
+                        Matcher yearMatcher = Pattern.compile("(\\d{4})").matcher(fallbackYear);
+                        if (yearMatcher.find()) {
+                            year = Integer.parseInt(yearMatcher.group(1));
+                        }
+                    }
+                    return YearMonth.of(year, month);
+                }
+            }
+        }
+        return YearMonth.now();
+    }
+
+    /**
      * 鐩戠潱棰戞: 鎸夌洃鐫f椂闂翠腑鐨勬湀浠戒釜鏁拌绠�, 濡� "2026.3" -> "1娆�/骞�", "3鏈堛��12鏈�" -> "2娆�/骞�"
      */
     private static String buildSuperviseFrequency(String superviseTime) {
@@ -439,7 +494,7 @@
             return "";
         }
         int count = 0;
-        for (String part : superviseTime.split("[銆�,锛�;锛�/\\s]+")) {
+        for (String part : normalizeSuperviseTime(superviseTime).split("[銆�,锛�;锛�/\\s]+")) {
             if (part.matches(".*\\d.*")) {
                 count++;
             }
@@ -456,7 +511,7 @@
         }
         StringBuilder sb = new StringBuilder();
         for (String part : superviseTime.split("[銆�,锛�;锛沒+")) {
-            String s = part.trim();
+            String s = normalizeSuperviseTime(part.trim());
             if (s.isEmpty()) {
                 continue;
             }
@@ -491,9 +546,11 @@
         if (detailsRecord == null) {
             // 鏌ヨ璇︽儏淇℃伅
             QualitySuperviseDetails qualitySuperviseDetails = qualitySuperviseDetailsMapper.selectById(superviseDetailsId);
+            QualitySupervise qualitySupervise = baseMapper.selectById(qualitySuperviseDetails.getSuperviseId());
             // 鏌ヨ涓婁竴涓湀绗竴鏉$殑璁板綍淇℃伅, 鍒ゆ柇琚洃鐫d汉鍘诲彟澶栦竴涓�
-            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.M");
-            YearMonth yearMonth = YearMonth.parse(qualitySuperviseDetails.getSuperviseTime(), formatter);
+            // 鐩戠潱鏃ユ湡鍏煎 2026.3 / 2026-03-15 / 2026/3/15 / 2026骞�3鏈�15鏃� 绛夊啓娉�
+            YearMonth yearMonth = parseSuperviseYearMonth(qualitySuperviseDetails.getSuperviseTime(),
+                    qualitySupervise == null ? null : qualitySupervise.getSuperviseYear());
             YearMonth previousYearMonth = yearMonth.minusMonths(1);
 
             LocalDate startDate = previousYearMonth.atDay(1);
@@ -515,21 +572,17 @@
 
             String supervisor = null;
 
-            if (laseRecord != null) {
-                // 鏌ヨ璁″垝鑾峰彇鍙︿竴涓洃鐫e憳
-                QualitySupervise qualitySupervise = baseMapper.selectById(qualitySuperviseDetails.getSuperviseId());
-                if (StringUtils.isNotBlank(qualitySupervise.getRecordUserIds())) {
-                    List<String> recordUserIds = StrUtil.split(qualitySupervise.getRecordUserIds(), ',');
-                    List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery()
-                            .in(User::getId, recordUserIds));
-                    if (CollectionUtils.isNotEmpty(users) && users.size() == 2) {
-                        // 鍒ゆ柇鏄惁涓�鏍�, 涓�鏍疯幏鍙栧彟澶栦竴涓�
-                        if (users.get(0).getName().equals(laseRecord.getSupervisor())) {
-                            supervisor = users.get(1).getName();
-                        } else {
-                            supervisor = users.get(0).getName();
-                        }
-
+            // 璁″垝鎸囧畾鐨勭洃鐫e憳锛氶娆″~鍐欐椂榛樿甯﹀嚭绗竴浣嶏紱鏈変笂鏈堣褰曟椂涓や綅鐩戠潱鍛樹氦鏇�
+            if (qualitySupervise != null && StringUtils.isNotBlank(qualitySupervise.getRecordUserIds())) {
+                List<String> recordUserIds = StrUtil.split(qualitySupervise.getRecordUserIds(), ',');
+                List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery()
+                        .in(User::getId, recordUserIds));
+                if (CollectionUtils.isNotEmpty(users)) {
+                    if (laseRecord != null && users.size() > 1
+                            && users.get(0).getName().equals(laseRecord.getSupervisor())) {
+                        supervisor = users.get(1).getName();
+                    } else {
+                        supervisor = users.get(0).getName();
                     }
                 }
             }
@@ -643,6 +696,47 @@
     }
 
     /**
+     * 琚洃鐫d汉鍛樼‘璁ょ洃鐫h褰�(绋嬪簭4.2.5: 琚洃鐫e璞″鐩戠潱璁板綍鐪熷疄鎬ф彁鍑虹‘璁ゆ剰瑙�)
+     */
+    @Override
+    public boolean confirmSuperviseRecord(QualitySuperviseDetailsRecord input) {
+        if (input == null || input.getSuperviseDetailsId() == null) {
+            throw new ErrorException("缂哄皯鐩戠潱璇︾粏淇℃伅id");
+        }
+        QualitySuperviseDetailsRecord record = qualitySuperviseDetailsRecordMapper.selectOne(
+                Wrappers.<QualitySuperviseDetailsRecord>lambdaQuery()
+                        .eq(QualitySuperviseDetailsRecord::getSuperviseDetailsId, input.getSuperviseDetailsId())
+                        .last("limit 1"));
+        if (record == null) {
+            throw new ErrorException("鐩戠潱鍛樺皻鏈彁浜ょ洃鐫h褰曪紝鏃犳硶纭");
+        }
+        Integer userId = SecurityUtils.getUserId().intValue();
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            throw new ErrorException("褰撳墠鐢ㄦ埛涓嶅瓨鍦�");
+        }
+        // 鍙湁琚洃鐫d汉鍛樻湰浜烘墠鍙互纭
+        boolean isSupervisee = StrUtil.split(record.getTestMember(), '銆�').stream()
+                .map(String::trim)
+                .anyMatch(name -> name.equals(user.getName()));
+        if (!isSupervisee) {
+            QualitySuperviseDetails detail = qualitySuperviseDetailsMapper.selectById(input.getSuperviseDetailsId());
+            isSupervisee = detail != null && userId.equals(detail.getSupervisedUserId());
+        }
+        if (!isSupervisee) {
+            throw new ErrorException("鍙湁琚洃鐫d汉鍛樺彲浠ョ‘璁ょ洃鐫h褰�");
+        }
+        String opinion = StringUtils.isBlank(input.getConfirmOpinion())
+                ? "瀵圭洃鐫h褰曠湡瀹炴�ц〃绀鸿鍙��" : input.getConfirmOpinion().trim();
+        qualitySuperviseDetailsRecordMapper.update(null,
+                Wrappers.<QualitySuperviseDetailsRecord>lambdaUpdate()
+                        .eq(QualitySuperviseDetailsRecord::getSuperviseDetailsRecordId,
+                                record.getSuperviseDetailsRecordId())
+                        .set(QualitySuperviseDetailsRecord::getConfirmOpinion, opinion));
+        return true;
+    }
+
+    /**
      * 瀵煎嚭鐩戠潱璁板綍琛�(鏃ュ父鐩戠潱妫�鏌ヨ褰曡〃)
      * @param superviseDetailsId
      * @param response
@@ -670,6 +764,11 @@
                     put("qualityUrl", signatureOrTransparent(recordDto.getRatifyUserId()));
                     put("qualityDateStr", recordDto.getRatifyTime() != null ?
                             recordDto.getRatifyTime().format(RECORD_DATE_FORMATTER) : "");
+                    // 绋嬪簭4.2.5: 琚洃鐫d汉鍛樺鐩戠潱璁板綍鐪熷疄鎬х殑纭鎰忚, 鏈‘璁ゆ椂娌跨敤绾稿紶琛ㄧ殑榛樿琛ㄨ堪
+                    put("confirmOpinionText", StringUtils.isNotBlank(recordDto.getConfirmOpinion())
+                            ? recordDto.getConfirmOpinion() : "瀵圭洃鐫h褰曠湡瀹炴�ц〃绀鸿鍙��");
+                    put("superviseMethodText", StringUtils.isNotBlank(recordDto.getSuperviseMethod())
+                            ? recordDto.getSuperviseMethod() : "");
                 }});
 
         try {
@@ -690,7 +789,7 @@
     }
 
     /**
-     * 鐩戠潱鍐呭(9椤�, 鎸夌焊寮犺〃妯帓椤哄簭)
+     * 鐩戠潱鍐呭(9椤�, 涓庡彈鎺ц褰曡〃 LMSY-CX29-JL02 鐨勬í鎺掗『搴忋�佹枃瀛楀畬鍏ㄤ竴鑷�)
      */
     private static final String[] SUPERVISE_CONTENT_ITEMS = {
             "浜哄憳鎸佽瘉鍙婂煿璁�", "璁炬柦鍙婄幆澧冩潯浠�", "妫�娴嬫柟娉�",
diff --git a/cnas-process/src/main/java/com/ruoyi/process/task/QualitySuperviseSchedule.java b/cnas-process/src/main/java/com/ruoyi/process/task/QualitySuperviseSchedule.java
index 0d42e19..385b8a6 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/task/QualitySuperviseSchedule.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/task/QualitySuperviseSchedule.java
@@ -91,8 +91,9 @@
         List<QualitySuperviseDetails> qualitySuperviseDetails = qualitySuperviseDetailsMapper.selectList(Wrappers.<QualitySuperviseDetails>lambdaQuery()
                 .eq(QualitySuperviseDetails::getSuperviseTime, format));
 
-        // 鏍规嵁瀹氭湡鐩戠潱鍜屽姩鎬佺洃鐫e尯鍒�
-        Map<String, List<QualitySuperviseDetails>> superviseReasonMap = qualitySuperviseDetails.stream().collect(Collectors.groupingBy(QualitySuperviseDetails::getSuperviseReason));
+        // 鏍规嵁鐩戠潱鍘熷洜鍖哄垎(瀹氭湡鐩戠潱/鍔ㄦ�佺洃鐫�), 鐩戠潱鍘熷洜鍏佽鎵嬪伐濉啓鎴栦负绌�, 杩欓噷鍋氱┖鍊煎厹搴�
+        Map<String, List<QualitySuperviseDetails>> superviseReasonMap = qualitySuperviseDetails.stream()
+                .collect(Collectors.groupingBy(details -> StrUtil.nullToEmpty(details.getSuperviseReason())));
 
         // 鑾峰彇褰撴湀鏃ユ湡
         DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy骞碝M鏈�");
diff --git a/cnas-process/src/main/resources/mapper/QualitySuperviseDetailsRecordMapper.xml b/cnas-process/src/main/resources/mapper/QualitySuperviseDetailsRecordMapper.xml
index 1dd051f..fe2981c 100644
--- a/cnas-process/src/main/resources/mapper/QualitySuperviseDetailsRecordMapper.xml
+++ b/cnas-process/src/main/resources/mapper/QualitySuperviseDetailsRecordMapper.xml
@@ -4,7 +4,10 @@
 
     <!--瀵煎嚭鐩戠潱璁板綍琛�-->
     <select id="selectSuperviseDetailRecord" resultType="com.ruoyi.process.pojo.QualitySuperviseDetailsRecord">
-        select cqsdr.*
+        <!-- 澶嶇敤鍘嗗彶鍒� testing_process / supervision_evaluation锛宺esultType 鑷姩鏄犲皠闇�瑕佸埆鍚� -->
+        select cqsdr.*,
+               cqsdr.testing_process as supervise_method,
+               cqsdr.supervision_evaluation as confirm_opinion
         from cnas_quality_supervise_details_record cqsdr
         where cqsdr.supervise_details_id = #{superviseDetailsId}
     </select>
diff --git a/cnas-process/src/main/resources/static/daily-supervise-record.docx b/cnas-process/src/main/resources/static/daily-supervise-record.docx
index 79b52e9..a429545 100644
--- a/cnas-process/src/main/resources/static/daily-supervise-record.docx
+++ b/cnas-process/src/main/resources/static/daily-supervise-record.docx
Binary files differ

--
Gitblit v1.9.3