From ea51b55feb73883040ed8a87b5a4aeb0bf94bb5e Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期一, 15 十二月 2025 17:02:27 +0800
Subject: [PATCH] 修改出片任务分批进行

---
 mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java |  495 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 454 insertions(+), 41 deletions(-)

diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java b/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
index e2d0469..2362f2e 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/task/service/TaskExecutionEngine.java
@@ -676,21 +676,72 @@
                                 task.getTaskId(), device.getId());
                         return;
                     }
+                    // 宸插畬鎴�/澶辫触鐨勬楠や笉鍐嶅洖閫�鐘舵��
+                    if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())
+                            || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) {
+                        return;
+                    }
                     // 杩涚墖澶ц溅璁惧锛氬彧鏈夊湪鐪熸寮�濮嬪鐞嗘椂鎵嶈缃负RUNNING
+                    // 鍏堟鏌ュ崸杞珛璁惧鏄惁宸插畬鎴愶紝濡傛灉杩樺湪鎵ц涓紝涓嶅簲璇ュ紑濮嬪ぇ杞︾殑宸ヤ綔
+                    boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context);
+                    if (!transferCompleted) {
+                        // 鍗ц浆绔嬭繕鍦ㄦ墽琛屼腑锛岀瓑寰呭崸杞珛瀹屾垚
+                        if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+                            step.setStatus(TaskStepDetail.Status.PENDING.name());
+                            step.setSuccessMessage("绛夊緟鍗ц浆绔嬪畬鎴�");
+                            if (step.getStartTime() == null) {
+                                step.setStartTime(new Date());
+                            }
+                            taskStepDetailMapper.updateById(step);
+                            notificationService.notifyStepUpdate(task.getTaskId(), step);
+                        }
+                        log.debug("鍗ц浆绔嬭繕鍦ㄦ墽琛屼腑锛岃繘鐗囧ぇ杞︾瓑寰�: taskId={}, deviceId={}", 
+                                task.getTaskId(), device.getId());
+                        return;
+                    }
+                    
                     // 妫�鏌ユ槸鍚︽湁鍗ц浆绔嬩富浣撳凡杈撳嚭銆佸噯澶囦笂澶ц溅鐨勭幓鐠冧俊鎭�
                     List<String> readyGlassIds = getTransferReadyGlassIds(context);
                     
-                    // 濡傛灉褰撳墠娌℃湁鏂扮殑鐜荤拑锛屾棤璁烘楠ゆ槸鍚﹀凡杩涘叆RUNNING锛岄兘搴旇杞MES浠诲姟/纭鐘舵��
+                    // 濡傛灉褰撳墠娌℃湁鏂扮殑鐜荤拑锛屼絾鍗ц浆绔嬪凡瀹屾垚锛屽彲浠ヨ疆璇ES浠诲姟/纭鐘舵��
                     if (CollectionUtils.isEmpty(readyGlassIds)) {
-                        // 杞MES浠诲姟/纭锛岄伩鍏嶉敊杩嘙ES渚у悗鍐欏叆鐨勪换鍔�
-                        pollMesForVehicle(task, step, device, context);
-                        // 濡傛灉浠嶇劧娌℃湁鍗ц浆绔嬭緭鍑虹殑鐜荤拑锛屼繚鎸�/鏇存柊涓篜ENDING鎻愮ず
-                        if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())
-                                && !TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
-                            step.setStatus(TaskStepDetail.Status.PENDING.name());
-                            step.setSuccessMessage("绛夊緟鍗ц浆绔嬭緭鍑虹幓鐠�");
-                            taskStepDetailMapper.updateById(step);
-                            notificationService.notifyStepUpdate(task.getTaskId(), step);
+                        // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+                        @SuppressWarnings("unchecked")
+                        List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                        List<String> loadedGlassIds = getLoadedGlassIds(context);
+                        
+                        if (initialGlassIds != null && !initialGlassIds.isEmpty()) {
+                            // 濡傛灉鎵�鏈夊垵濮嬬幓鐠冮兘宸茶杞斤紝璇存槑宸茬粡澶勭悊瀹岋紝涓嶅簲璇ュ啀鍙樺洖绛夊緟
+                            if (loadedGlassIds != null && !loadedGlassIds.isEmpty() 
+                                    && loadedGlassIds.containsAll(initialGlassIds)) {
+                                // 鎵�鏈夌幓鐠冮兘宸茶杞斤紝淇濇寔RUNNING鐘舵�侊紝缁х画杞MES浠诲姟/纭
+                                if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
+                                    step.setStatus(TaskStepDetail.Status.RUNNING.name());
+                                    if (step.getStartTime() == null) {
+                                        step.setStartTime(new Date());
+                                    }
+                                    taskStepDetailMapper.updateById(step);
+                                    notificationService.notifyStepUpdate(task.getTaskId(), step);
+                                }
+                                pollMesForVehicle(task, step, device, context);
+                                return;
+                            }
+                        }
+                        
+                        // 濡傛灉澶ц溅宸茬粡瑁呰浇杩囩幓鐠冿紙RUNNING鐘舵�侊級锛岃疆璇ES浠诲姟/纭鐘舵��
+                        if (TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
+                            pollMesForVehicle(task, step, device, context);
+                        } else {
+                            // 濡傛灉杩樻病鏈夎杞借繃鐜荤拑锛岀瓑寰呭崸杞珛杈撳嚭
+                            if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+                                step.setStatus(TaskStepDetail.Status.PENDING.name());
+                                step.setSuccessMessage("绛夊緟鍗ц浆绔嬭緭鍑虹幓鐠�");
+                                if (step.getStartTime() == null) {
+                                    step.setStartTime(new Date());
+                                }
+                                taskStepDetailMapper.updateById(step);
+                                notificationService.notifyStepUpdate(task.getTaskId(), step);
+                            }
                         }
                         return;
                     }
@@ -778,15 +829,56 @@
                         // 鍙湁鍦ㄤ换鍔″凡寮�濮嬫墽琛岋紙鏈変换鍔¤褰曪級鏃舵墠妫�鏌ES纭
                         DevicePlcVO.OperationResult mesResult = null;
                         try {
-                            mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap());
+                            Map<String, Object> confirmParams = new HashMap<>();
+                            confirmParams.put("_taskContext", context);
+                            mesResult = handler.execute(device, "checkMesConfirm", confirmParams);
                         } catch (Exception e) {
                             log.warn("杩涚墖澶ц溅璁惧妫�鏌ES纭鐘舵�佸紓甯�: taskId={}, deviceId={}, error={}",
                                     task.getTaskId(), device.getId(), e.getMessage());
                         }
                         
+                        // 濡傛灉MES宸茬‘璁ゅ畬鎴愶紙mesConfirm=1锛夛紝妫�鏌ュ崸杞珛璁惧鐘舵�佸拰鐜荤拑淇℃伅
+                        // 濡傛灉鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鍙互鏍囪涓哄畬鎴�
+                        if (mesResult != null && mesResult.getData() != null) {
+                            Object completedFlag = mesResult.getData().get("completed");
+                            boolean mesConfirmed = false;
+                            if (completedFlag instanceof Boolean) {
+                                mesConfirmed = (Boolean) completedFlag;
+                            } else if (completedFlag != null) {
+                                mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag));
+                            }
+                            
+                            if (mesConfirmed) {
+                                // MES宸茬‘璁ゅ畬鎴愶紝妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+                                boolean transferCompletedForMes = isTransferDeviceCompleted(task.getTaskId(), context);
+                                if (transferCompletedForMes) {
+                                    // 妫�鏌ヤ换鍔′笂涓嬫枃涓殑鍒濆鐜荤拑ID鍜屽凡瑁呰浇鐨勭幓鐠僆D
+                                    @SuppressWarnings("unchecked")
+                                    List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                                    List<String> loadedGlassIds = getLoadedGlassIds(context);
+                                    
+                                    if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                            && loadedGlassIds != null && !loadedGlassIds.isEmpty()) {
+                                        // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+                                        boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds);
+                                        if (allGlassesLoaded) {
+                                            // 鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鏍囪涓哄畬鎴�
+                                            log.info("MES宸茬‘璁や笖鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冨凡瑁呰浇锛屼换鍔¤嚜鍔ㄥ畬鎴�: taskId={}, deviceId={}, initialCount={}, loadedCount={}",
+                                                    task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size());
+                                            // mesResult宸茬粡鍖呭惈completed=true锛屼笉闇�瑕佷慨鏀�
+                                        }
+                                    }
+                                } else {
+                                    // 鍗ц浆绔嬭繕鏈畬鎴愶紝涓嶅簲璇ユ爣璁颁负瀹屾垚
+                                    log.debug("MES宸茬‘璁や絾鍗ц浆绔嬫湭瀹屾垚锛岀瓑寰呭崸杞珛瀹屾垚: taskId={}, deviceId={}", 
+                                            task.getTaskId(), device.getId());
+                                }
+                            }
+                        }
+                        
                         // 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
                         if (mesResult != null) {
-                            updateStepStatusForVehicle(step, mesResult);
+                            updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
                             boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
                             updateTaskProgress(task, step.getStepOrder(), opSuccess);
                             if (!opSuccess) {
@@ -794,7 +886,7 @@
                                         DeviceCoordinationService.DeviceStatus.FAILED, context);
                             }
                         } else {
-                            updateStepStatusForVehicle(step, feedResult);
+                            updateStepStatusForVehicle(task.getTaskId(), step, feedResult);
                             boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess());
                             updateTaskProgress(task, step.getStepOrder(), opSuccess);
                             if (!opSuccess) {
@@ -843,11 +935,43 @@
                     // 妫�鏌ユ槸鍚︽湁宸插鐞嗙殑鐜荤拑淇℃伅锛堜粠澶х悊鐗囩鏉ョ殑锛�
                     List<String> processedGlassIds = getProcessedGlassIds(context);
                     boolean isRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus());
+                    boolean isCompleted = TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus());
                     
-                    // 濡傛灉璁惧宸茬粡鍦ㄨ繍琛屼腑锛屽嵆浣挎病鏈夋柊鐜荤拑锛屼篃瑕佺户缁洃鎺ES浠诲姟鍜岀‘璁ょ姸鎬�
+                    // 鑾峰彇宸插嚭鐗囩殑鐜荤拑ID鍒楄〃锛堝湪鏂规硶寮�濮嬪澹版槑锛岄伩鍏嶉噸澶嶅畾涔夛級
+                    List<String> outboundGlassIds = getOutboundGlassIds(context);
+                    
+                    // 濡傛灉姝ラ宸插畬鎴愶紝妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸插嚭鐗�
+                    if (isCompleted) {
+                        @SuppressWarnings("unchecked")
+                        List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                        
+                        // 濡傛灉杩樻湁鏈嚭鐗囩殑鐜荤拑锛岄噸缃楠ょ姸鎬佷负RUNNING锛岀户缁瓑寰�
+                        if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                && (outboundGlassIds == null || !outboundGlassIds.containsAll(initialGlassIds))) {
+                            log.info("鍑虹墖澶ц溅姝ラ宸插畬鎴愶紝浣嗚繕鏈夋湭鍑虹墖鐨勭幓鐠冿紝閲嶇疆涓篟UNNING缁х画绛夊緟: taskId={}, deviceId={}, initialCount={}, outboundCount={}",
+                                    task.getTaskId(), device.getId(), 
+                                    initialGlassIds.size(), 
+                                    outboundGlassIds != null ? outboundGlassIds.size() : 0);
+                            step.setStatus(TaskStepDetail.Status.RUNNING.name());
+                            step.setEndTime(null); // 娓呴櫎缁撴潫鏃堕棿
+                            step.setSuccessMessage("绛夊緟鍓╀綑鐜荤拑鍑虹墖");
+                            taskStepDetailMapper.updateById(step);
+                            notificationService.notifyStepUpdate(task.getTaskId(), step);
+                            // 缁х画鎵ц鍚庣画閫昏緫锛屾鏌ユ槸鍚︽湁鏂扮殑宸插鐞嗙幓鐠�
+                        } else {
+                            // 鎵�鏈夌幓鐠冮兘宸插嚭鐗囷紝淇濇寔瀹屾垚鐘舵��
+                            log.debug("鍑虹墖澶ц溅鎵�鏈夌幓鐠冮兘宸插嚭鐗�: taskId={}, deviceId={}, initialCount={}, outboundCount={}",
+                                    task.getTaskId(), device.getId(), 
+                                    initialGlassIds != null ? initialGlassIds.size() : 0, 
+                                    outboundGlassIds != null ? outboundGlassIds.size() : 0);
+                            return;
+                        }
+                    }
+                    
+                    // 濡傛灉娌℃湁宸插鐞嗙幓鐠冿紝鍒欎笉搴斾富鍔ㄦ妸姝ラ鎷夊埌RUNNING锛屽彧淇濇寔宸茶繍琛岀姸鎬�
                     if (CollectionUtils.isEmpty(processedGlassIds)) {
-                        if (isRunning) {
-                            // 璁惧姝e湪杩愯涓紝鍏堟鏌ES浠诲姟锛岀劧鍚庣洃鎺ES纭鐘舵��
+                        if (isRunning || isCompleted) {
+                            // 宸茬粡鍦ㄨ繍琛岀殑鎯呭喌涓嬶紝缁х画杞MES浠诲姟/纭锛岄伩鍏嶉敊杩囩‘璁�
                             DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType());
                             if (handler != null) {
                                 Map<String, Object> logicParams = parseLogicParams(device);
@@ -856,9 +980,14 @@
                                 DevicePlcVO.OperationResult mesTaskResult = null;
                                 try {
                                     mesTaskResult = handler.execute(device, "checkMesTask", Collections.emptyMap());
-                                    if (mesTaskResult != null && Boolean.TRUE.equals(mesTaskResult.getSuccess())) {
-                                        log.info("鍑虹墖澶ц溅璁惧宸叉鏌ES浠诲姟骞跺紑濮嬫墽琛�: taskId={}, deviceId={}, message={}",
-                                                task.getTaskId(), device.getId(), mesTaskResult.getMessage());
+                                    if (mesTaskResult != null) {
+                                        if (Boolean.TRUE.equals(mesTaskResult.getSuccess())) {
+                                            log.info("鍑虹墖澶ц溅璁惧宸叉鏌ES浠诲姟骞跺紑濮嬫墽琛�: taskId={}, deviceId={}, message={}",
+                                                    task.getTaskId(), device.getId(), mesTaskResult.getMessage());
+                                        } else {
+                                            log.debug("鍑虹墖澶ц溅璁惧妫�鏌ES浠诲姟锛岀瓑寰呬腑: taskId={}, deviceId={}, message={}",
+                                                    task.getTaskId(), device.getId(), mesTaskResult.getMessage());
+                                        }
                                     }
                                 } catch (Exception e) {
                                     log.warn("鍑虹墖澶ц溅璁惧妫�鏌ES浠诲姟寮傚父: taskId={}, deviceId={}, error={}",
@@ -868,7 +997,9 @@
                                 // 鐒跺悗妫�鏌ES纭鐘舵�侊紙鍙湁鍦ㄤ换鍔″凡寮�濮嬫墽琛屾椂鎵嶆鏌ワ級
                                 DevicePlcVO.OperationResult mesResult = null;
                                 try {
-                                    mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap());
+                                    Map<String, Object> checkParams = new HashMap<>();
+                                    checkParams.put("_taskContext", context);
+                                    mesResult = handler.execute(device, "checkMesConfirm", checkParams);
                                 } catch (Exception e) {
                                     log.warn("鍑虹墖澶ц溅璁惧妫�鏌ES纭鐘舵�佸紓甯�: taskId={}, deviceId={}, error={}",
                                             task.getTaskId(), device.getId(), e.getMessage());
@@ -876,7 +1007,7 @@
                                 
                                 // 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
                                 if (mesResult != null) {
-                                    updateStepStatusForVehicle(step, mesResult);
+                                    updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
                                     boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
                                     updateTaskProgress(task, step.getStepOrder(), opSuccess);
                                     if (!opSuccess) {
@@ -885,10 +1016,10 @@
                                     }
                                 }
                             }
-                            return;
                         } else {
-                            // 娌℃湁鏁版嵁锛屼笖璁惧鏈繍琛岋紝淇濇寔PENDING鐘舵��
-                            if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+                            // 鏈繍琛屼笖娌℃湁宸插鐞嗙幓鐠冿紝淇濇寔PENDING
+                            if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())
+                                    && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
                                 step.setStatus(TaskStepDetail.Status.PENDING.name());
                                 step.setSuccessMessage("绛夊緟澶х悊鐗囩澶勭悊瀹屾垚");
                                 taskStepDetailMapper.updateById(step);
@@ -896,16 +1027,37 @@
                             }
                             log.debug("鍑虹墖澶ц溅璁惧瀹氭椂鍣細鏆傛棤宸插鐞嗙殑鐜荤拑淇℃伅: taskId={}, deviceId={}",
                                     task.getTaskId(), device.getId());
-                            return;
                         }
+                        return;
                     }
                     
                     log.debug("鍑虹墖澶ц溅璁惧瀹氭椂鍣ㄦ娴嬪埌宸插鐞嗙殑鐜荤拑淇℃伅: taskId={}, deviceId={}, glassCount={}",
                             task.getTaskId(), device.getId(), processedGlassIds.size());
+
+                    // 杩囨护鍑鸿繕鏈嚭鐗囩殑鐜荤拑锛堟敮鎸佸垎鎵瑰嚭鐗囷級
+                    // 閲嶆柊鑾峰彇宸插嚭鐗囩殑鐜荤拑ID鍒楄〃锛堝彲鑳藉湪涓婇潰鐨勯�昏緫涓凡鏇存柊锛�
+                    outboundGlassIds = getOutboundGlassIds(context);
+                    List<String> glassIdsToOutbound = new ArrayList<>();
+                    for (String glassId : processedGlassIds) {
+                        if (outboundGlassIds == null || !outboundGlassIds.contains(glassId)) {
+                            glassIdsToOutbound.add(glassId);
+                        }
+                    }
+                    
+                    // 濡傛灉娌℃湁闇�瑕佸嚭鐗囩殑鐜荤拑锛堥兘宸茬粡鍑虹墖杩囦簡锛夛紝缁х画绛夊緟鏂扮殑宸插鐞嗙幓鐠�
+                    if (glassIdsToOutbound.isEmpty()) {
+                        log.debug("鍑虹墖澶ц溅宸插鐞嗙殑鐜荤拑閮藉凡鍑虹墖锛岀瓑寰呮柊鐨勫凡澶勭悊鐜荤拑: taskId={}, deviceId={}",
+                                task.getTaskId(), device.getId());
+                        return;
+                    }
+                    
+                    log.debug("鍑虹墖澶ц溅鍑嗗鍑虹墖: taskId={}, deviceId={}, 寰呭嚭鐗囨暟閲�={}, 宸插嚭鐗囨暟閲�={}",
+                            task.getTaskId(), device.getId(), glassIdsToOutbound.size(), 
+                            outboundGlassIds != null ? outboundGlassIds.size() : 0);
                     
                     // 鎵ц鍑虹墖鎿嶄綔
                     Map<String, Object> checkParams = new HashMap<>();
-                    checkParams.put("glassIds", new ArrayList<>(processedGlassIds));
+                    checkParams.put("glassIds", glassIdsToOutbound);
                     checkParams.put("_taskContext", context);
                     
                     DeviceLogicHandler handler = handlerFactory.getHandler(device.getDeviceType());
@@ -932,9 +1084,17 @@
                                 notificationService.notifyStepUpdate(task.getTaskId(), step);
                             }
                             log.debug("鍑虹墖澶ц溅璁惧瀹氭椂鍣ㄦ墽琛屾垚鍔�: taskId={}, deviceId={}, glassCount={}",
-                                    task.getTaskId(), device.getId(), processedGlassIds.size());
-                            // 娓呯┖宸插鐞嗙殑鐜荤拑ID鍒楄〃锛堝凡澶勭悊锛�
-                            clearProcessedGlassIds(context);
+                                    task.getTaskId(), device.getId(), glassIdsToOutbound.size());
+                            // 璁板綍宸插嚭鐗囩殑鐜荤拑ID锛堝彧璁板綍鏈鍑虹墖鐨勭幓鐠冿級
+                            addOutboundGlassIds(context, glassIdsToOutbound);
+                            // 浠巔rocessedGlassIds涓Щ闄ゅ凡鍑虹墖鐨勭幓鐠冿紝淇濈暀鏈嚭鐗囩殑鐜荤拑
+                            processedGlassIds.removeAll(glassIdsToOutbound);
+                            // 濡傛灉杩樻湁鏈嚭鐗囩殑鐜荤拑锛屼笉娓呯┖processedGlassIds锛涘鏋滃叏閮ㄥ嚭鐗囦簡锛屾竻绌�
+                            if (processedGlassIds.isEmpty()) {
+                                clearProcessedGlassIds(context);
+                            } else {
+                                setProcessedGlassIds(context, processedGlassIds);
+                            }
                             
                             // feedGlass鎴愬姛鍚庯紝鍏堟鏌ES浠诲姟锛坈heckMesTask锛夋潵寮�濮嬫墽琛屼换鍔�
                             DevicePlcVO.OperationResult mesTaskResult = null;
@@ -966,15 +1126,54 @@
                         // 鍙湁鍦ㄤ换鍔″凡寮�濮嬫墽琛岋紙鏈変换鍔¤褰曪級鏃舵墠妫�鏌ES纭
                         DevicePlcVO.OperationResult mesResult = null;
                         try {
-                            mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap());
+                            Map<String, Object> confirmParams = new HashMap<>();
+                            confirmParams.put("_taskContext", context);
+                            mesResult = handler.execute(device, "checkMesConfirm", confirmParams);
                         } catch (Exception e) {
                             log.warn("鍑虹墖澶ц溅璁惧妫�鏌ES纭鐘舵�佸紓甯�: taskId={}, deviceId={}, error={}",
                                     task.getTaskId(), device.getId(), e.getMessage());
                         }
                         
+                        // 瀵逛簬鍑虹墖澶ц溅锛岄渶瑕佹鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸插嚭鐗�
+                        // 濡傛灉MES杩斿洖completed=true锛屼絾杩樻湁鏈嚭鐗囩殑鐜荤拑锛屽垯涓嶅簲鏍囪涓哄畬鎴�
+                        if (mesResult != null && mesResult.getData() != null) {
+                            Object completedFlag = mesResult.getData().get("completed");
+                            boolean mesCompleted = false;
+                            if (completedFlag instanceof Boolean) {
+                                mesCompleted = (Boolean) completedFlag;
+                            } else if (completedFlag != null) {
+                                mesCompleted = "true".equalsIgnoreCase(String.valueOf(completedFlag));
+                            }
+                            
+                            // 濡傛灉MES杩斿洖completed=true锛屾鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸插嚭鐗�
+                            if (mesCompleted) {
+                                @SuppressWarnings("unchecked")
+                                List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                                // 閲嶆柊鑾峰彇宸插嚭鐗囩殑鐜荤拑ID鍒楄〃锛堝彲鑳藉湪涓婇潰鐨勯�昏緫涓凡鏇存柊锛�
+                                outboundGlassIds = getOutboundGlassIds(context);
+                                
+                                // 濡傛灉杩樻湁鏈嚭鐗囩殑鐜荤拑锛屼慨鏀筸esResult锛屽皢completed璁句负false
+                                if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                        && (outboundGlassIds == null || !outboundGlassIds.containsAll(initialGlassIds))) {
+                                    log.debug("鍑虹墖澶ц溅MES杩斿洖completed=true锛屼絾杩樻湁鏈嚭鐗囩殑鐜荤拑: taskId={}, deviceId={}, initialCount={}, outboundCount={}",
+                                            task.getTaskId(), device.getId(), 
+                                            initialGlassIds.size(), 
+                                            outboundGlassIds != null ? outboundGlassIds.size() : 0);
+                                    // 淇敼mesResult锛屽皢completed璁句负false锛屼繚鎸丷UNNING鐘舵��
+                                    Map<String, Object> modifiedData = new HashMap<>(mesResult.getData());
+                                    modifiedData.put("completed", false);
+                                    DevicePlcVO.OperationResult modifiedResult = new DevicePlcVO.OperationResult();
+                                    modifiedResult.setSuccess(mesResult.getSuccess());
+                                    modifiedResult.setMessage(mesResult.getMessage());
+                                    modifiedResult.setData(modifiedData);
+                                    mesResult = modifiedResult;
+                                }
+                            }
+                        }
+                        
                         // 鏇存柊姝ラ鐘舵�侊紙澶ц溅璁惧淇濇寔RUNNING锛岀洿鍒癕ES纭瀹屾垚鎴栦换鍔″彇娑堬級
                         if (mesResult != null) {
-                            updateStepStatusForVehicle(step, mesResult);
+                            updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
                             boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
                             updateTaskProgress(task, step.getStepOrder(), opSuccess);
                             if (!opSuccess) {
@@ -982,7 +1181,7 @@
                                         DeviceCoordinationService.DeviceStatus.FAILED, context);
                             }
                         } else {
-                            updateStepStatusForVehicle(step, feedResult);
+                            updateStepStatusForVehicle(task.getTaskId(), step, feedResult);
                             boolean opSuccess = Boolean.TRUE.equals(feedResult.getSuccess());
                             updateTaskProgress(task, step.getStepOrder(), opSuccess);
                             if (!opSuccess) {
@@ -1030,14 +1229,57 @@
                                 task.getTaskId(), device.getId());
                         return;
                     }
+                    // 濡傛灉姝ラ宸茬粡瀹屾垚锛屼笉鍐嶅鐞�
+                    if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
+                        // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸插鐞嗗畬
+                        @SuppressWarnings("unchecked")
+                        List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                        List<String> processedGlassIds = getProcessedGlassIds(context);
+                        
+                        if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                && processedGlassIds != null && !processedGlassIds.isEmpty()
+                                && processedGlassIds.containsAll(initialGlassIds)) {
+                            // 鎵�鏈夌幓鐠冮兘宸插鐞嗗畬锛屼繚鎸佸畬鎴愮姸鎬�
+                            log.debug("澶х悊鐗囩璁惧宸插畬鎴愪笖鎵�鏈夌幓鐠冨凡澶勭悊: taskId={}, deviceId={}, initialCount={}, processedCount={}",
+                                    task.getTaskId(), device.getId(), initialGlassIds.size(), processedGlassIds.size());
+                            return;
+                        }
+                    }
+                    
                     // 澶х悊鐗囩璁惧锛氬彧鏈夊湪鐪熸寮�濮嬪鐞嗘椂鎵嶈缃负RUNNING
                     // 妫�鏌ユ槸鍚︽湁宸茶杞界殑鐜荤拑淇℃伅锛堜粠杩涚墖澶ц溅鏉ョ殑锛�
                     List<String> loadedGlassIds = getLoadedGlassIds(context);
                     if (CollectionUtils.isEmpty(loadedGlassIds)) {
-                        // 娌℃湁鏁版嵁锛屼繚鎸乄AITING鐘舵�佸拰PENDING姝ラ鐘舵��
+                        // 娌℃湁鏁版嵁锛屾鏌ユ槸鍚︽墍鏈夌幓鐠冮兘宸插鐞嗗畬
+                        @SuppressWarnings("unchecked")
+                        List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                        List<String> processedGlassIds = getProcessedGlassIds(context);
+                        
+                        if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                && processedGlassIds != null && !processedGlassIds.isEmpty()
+                                && processedGlassIds.containsAll(initialGlassIds)) {
+                            // 鎵�鏈夌幓鐠冮兘宸插鐞嗗畬锛屾爣璁颁负瀹屾垚
+                            if (!TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
+                                step.setStatus(TaskStepDetail.Status.COMPLETED.name());
+                                step.setSuccessMessage("鎵�鏈夌幓鐠冨凡澶勭悊瀹屾垚");
+                                if (step.getEndTime() == null) {
+                                    step.setEndTime(new Date());
+                                }
+                                if (step.getStartTime() != null && step.getEndTime() != null) {
+                                    step.setDurationMs(step.getEndTime().getTime() - step.getStartTime().getTime());
+                                }
+                                taskStepDetailMapper.updateById(step);
+                                notificationService.notifyStepUpdate(task.getTaskId(), step);
+                                checkAndCompleteTaskIfDone(step.getTaskId());
+                            }
+                            return;
+                        }
+                        
+                        // 娌℃湁鏁版嵁涓旀湭瀹屾垚锛屼繚鎸乄AITING鐘舵�佸拰PENDING姝ラ鐘舵��
                         deviceCoordinationService.syncDeviceStatus(device,
                                 DeviceCoordinationService.DeviceStatus.WAITING, context);
-                        if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())) {
+                        if (!TaskStepDetail.Status.PENDING.name().equals(step.getStatus())
+                                && !TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())) {
                             step.setStatus(TaskStepDetail.Status.PENDING.name());
                             step.setSuccessMessage("绛夊緟杩涚墖澶ц溅瑁呰浇鐜荤拑");
                             taskStepDetailMapper.updateById(step);
@@ -1056,7 +1298,17 @@
                     Long processStartTime = getProcessStartTime(context);
                     if (processStartTime == null) {
                         // 绗竴娆℃娴嬪埌鐜荤拑锛岃褰曞紑濮嬪鐞嗘椂闂�
-                        setProcessStartTime(context, System.currentTimeMillis());
+                        long now = System.currentTimeMillis();
+                        setProcessStartTime(context, now);
+                        // 琛ラ綈姝ラ鐨勫紑濮嬫椂闂翠笌鐘舵�侊紝纭繚鍓嶇鑰楁椂姝e父鏄剧ず
+                        if (!TaskStepDetail.Status.RUNNING.name().equals(step.getStatus())) {
+                            step.setStatus(TaskStepDetail.Status.RUNNING.name());
+                        }
+                        if (step.getStartTime() == null) {
+                            step.setStartTime(new Date(now));
+                        }
+                        taskStepDetailMapper.updateById(step);
+                        notificationService.notifyStepUpdate(task.getTaskId(), step);
                         log.debug("澶х悊鐗囩璁惧寮�濮嬪鐞�: taskId={}, deviceId={}, glassCount={}, processTime={}s",
                                 task.getTaskId(), device.getId(), loadedGlassIds.size(), processTimeSeconds);
                         return;
@@ -1082,6 +1334,17 @@
                     // 鏇存柊姝ラ鐘舵��
                     step.setStatus(TaskStepDetail.Status.COMPLETED.name());
                     step.setErrorMessage(null);
+                    // 璁板綍缁撴潫鏃堕棿涓庤�楁椂
+                    if (step.getEndTime() == null) {
+                        step.setEndTime(new Date());
+                    }
+                    if (step.getStartTime() == null) {
+                        // 濡傛灉寮�濮嬫椂闂寸己澶憋紝鐢ㄥ鐞嗗紑濮嬫椂闂存垨缁撴潫鏃堕棿鍏滃簳
+                        step.setStartTime(new Date(processStartTime));
+                    }
+                    if (step.getStartTime() != null && step.getEndTime() != null) {
+                        step.setDurationMs(step.getEndTime().getTime() - step.getStartTime().getTime());
+                    }
                     step.setOutputData(toJson(Collections.singletonMap("glassIds", loadedGlassIds)));
                     taskStepDetailMapper.updateById(step);
                     // 澶х悊鐗囩瀹屾垚鍚庡皾璇曡嚜鍔ㄦ敹灏炬暣涓换鍔�
@@ -1141,7 +1404,14 @@
      */
     private void setLoadedGlassIds(TaskExecutionContext context, List<String> glassIds) {
         if (context != null) {
-            context.getSharedData().put("loadedGlassIds", new ArrayList<>(glassIds));
+            // 绱姞璁板綍锛岄伩鍏嶅悗缁� containsAll 鍒ゆ柇鍥犺鐩栦涪澶卞巻鍙茬幓鐠冭�屽洖閫�涓虹瓑寰�
+            List<String> merged = new ArrayList<>(getLoadedGlassIds(context)); // 纭繚鍙彉
+            if (glassIds != null) {
+                merged.addAll(glassIds);
+            }
+            // 鍘婚噸
+            List<String> distinct = merged.stream().distinct().collect(java.util.stream.Collectors.toList());
+            context.getSharedData().put("loadedGlassIds", distinct);
         }
     }
     
@@ -1184,6 +1454,33 @@
     private void clearProcessedGlassIds(TaskExecutionContext context) {
         if (context != null) {
             context.getSharedData().put("processedGlassIds", new ArrayList<>());
+        }
+    }
+    
+    /**
+     * 鑾峰彇宸插嚭鐗囩殑鐜荤拑ID鍒楄〃
+     */
+    @SuppressWarnings("unchecked")
+    private List<String> getOutboundGlassIds(TaskExecutionContext context) {
+        if (context == null) {
+            return Collections.emptyList();
+        }
+        Object glassIds = context.getSharedData().get("outboundGlassIds");
+        if (glassIds instanceof List) {
+            return new ArrayList<>((List<String>) glassIds);
+        }
+        return Collections.emptyList();
+    }
+    
+    /**
+     * 娣诲姞宸插嚭鐗囩殑鐜荤拑ID鍒楄〃
+     */
+    private void addOutboundGlassIds(TaskExecutionContext context, List<String> glassIds) {
+        if (context != null && glassIds != null && !glassIds.isEmpty()) {
+            List<String> existing = getOutboundGlassIds(context);
+            Set<String> allOutbound = new HashSet<>(existing);
+            allOutbound.addAll(glassIds);
+            context.getSharedData().put("outboundGlassIds", new ArrayList<>(allOutbound));
         }
     }
     
@@ -1438,6 +1735,9 @@
         }
         step.setOutputData(toJson(result));
         taskStepDetailMapper.updateById(step);
+        if (StringUtils.hasText(step.getTaskId())) {
+            notificationService.notifyStepUpdate(step.getTaskId(), step);
+        }
     }
     
     /**
@@ -1508,8 +1808,14 @@
     /**
      * 鏇存柊澶ц溅璁惧姝ラ鐘舵�侊紙淇濇寔RUNNING锛岀洿鍒版墜鍔ㄥ仠姝㈡垨浠诲姟鍙栨秷锛涘け璐ユ椂鏍囪涓篎AILED锛�
      */
-    private void updateStepStatusForVehicle(TaskStepDetail step, DevicePlcVO.OperationResult result) {
+    private void updateStepStatusForVehicle(String taskId, TaskStepDetail step, DevicePlcVO.OperationResult result) {
         if (step == null || result == null) {
+            return;
+        }
+        // 濡傛灉姝ラ宸茬粡澶勪簬瀹屾垚鎴栧け璐ョ姸鎬侊紝鍒欎笉鍐嶈閲嶅鏇存柊锛堥槻姝㈢姸鎬佸弽澶嶅垏鎹級
+        if (TaskStepDetail.Status.COMPLETED.name().equals(step.getStatus())
+                || TaskStepDetail.Status.FAILED.name().equals(step.getStatus())) {
+            log.debug("姝ラ宸插畬鎴愭垨澶辫触锛屼笉鍐嶆洿鏂扮姸鎬�: stepId={}, status={}", step.getId(), step.getStatus());
             return;
         }
         boolean success = Boolean.TRUE.equals(result.getSuccess());
@@ -1546,16 +1852,20 @@
         
         if (success && !completed) {
             // 鎴愬姛浣嗘湭瀹屾垚锛氭牴鎹畐aiting鐘舵�佸喅瀹氭樉绀轰负绛夊緟杩樻槸鎵ц涓�
-            if (waiting) {
+            // 娉ㄦ剰锛氬鏋滄楠ゅ凡缁忔槸RUNNING鐘舵�侊紙璇存槑宸茬粡瑁呰浇杩囩幓鐠冿級锛屼笉搴旇鏀瑰洖PENDING
+            boolean isAlreadyRunning = TaskStepDetail.Status.RUNNING.name().equals(step.getStatus());
+            if (waiting && !isAlreadyRunning) {
+                // 鍙湁鍦ㄨ繕娌℃湁寮�濮嬭繍琛屾椂锛屾墠璁剧疆涓篜ENDING
                 step.setStatus(TaskStepDetail.Status.PENDING.name());
             } else {
+                // 濡傛灉宸茬粡杩愯杩囷紝鎴栬�呬笉鏄瓑寰呯姸鎬侊紝淇濇寔鎴栬缃负RUNNING
                 step.setStatus(TaskStepDetail.Status.RUNNING.name());
             }
             String message = result.getMessage();
             if (!StringUtils.hasText(message) && waiting) {
                 message = "澶ц溅璁惧绛夊緟涓�" + (StringUtils.hasText(waitingReason) ? "锛�" + waitingReason + "锛�" : "");
             }
-            step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting ? "澶ц溅璁惧绛夊緟涓�" : "澶ц溅璁惧杩愯涓�"));
+            step.setSuccessMessage(StringUtils.hasText(message) ? message : (waiting && !isAlreadyRunning ? "澶ц溅璁惧绛夊緟涓�" : "澶ц溅璁惧杩愯涓�"));
             step.setErrorMessage(null);
             if (step.getStartTime() != null) {
                 step.setDurationMs(now.getTime() - step.getStartTime().getTime());
@@ -1589,6 +1899,8 @@
 
         step.setOutputData(toJson(result));
         taskStepDetailMapper.updateById(step);
+        // 閫氱煡鍓嶇姝ラ鐘舵�佸凡鏇存柊
+        notificationService.notifyStepUpdate(taskId, step);
     }
 
     /**
@@ -1623,15 +1935,56 @@
             // 鐒跺悗妫�鏌ES纭鐘舵��
             DevicePlcVO.OperationResult mesResult = null;
             try {
-                mesResult = handler.execute(device, "checkMesConfirm", Collections.emptyMap());
+                Map<String, Object> checkParams = new HashMap<>();
+                checkParams.put("_taskContext", context);
+                mesResult = handler.execute(device, "checkMesConfirm", checkParams);
             } catch (Exception e) {
                 log.warn("澶ц溅璁惧妫�鏌ES纭鐘舵�佸紓甯�: taskId={}, deviceId={}, error={}",
                         task.getTaskId(), device.getId(), e.getMessage());
             }
 
+            // 濡傛灉MES宸茬‘璁ゅ畬鎴愶紙mesConfirm=1锛夛紝妫�鏌ュ崸杞珛璁惧鐘舵�佸拰鐜荤拑淇℃伅
+            // 濡傛灉鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鍙互鏍囪涓哄畬鎴�
+            if (mesResult != null && mesResult.getData() != null) {
+                Object completedFlag = mesResult.getData().get("completed");
+                boolean mesConfirmed = false;
+                if (completedFlag instanceof Boolean) {
+                    mesConfirmed = (Boolean) completedFlag;
+                } else if (completedFlag != null) {
+                    mesConfirmed = "true".equalsIgnoreCase(String.valueOf(completedFlag));
+                }
+                
+                if (mesConfirmed) {
+                    // MES宸茬‘璁ゅ畬鎴愶紝妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+                    boolean transferCompleted = isTransferDeviceCompleted(task.getTaskId(), context);
+                    if (transferCompleted) {
+                        // 妫�鏌ヤ换鍔′笂涓嬫枃涓殑鍒濆鐜荤拑ID鍜屽凡瑁呰浇鐨勭幓鐠僆D
+                        @SuppressWarnings("unchecked")
+                        List<String> initialGlassIds = (List<String>) context.getSharedData().get("initialGlassIds");
+                        List<String> loadedGlassIds = getLoadedGlassIds(context);
+                        
+                        if (initialGlassIds != null && !initialGlassIds.isEmpty() 
+                                && loadedGlassIds != null && !loadedGlassIds.isEmpty()) {
+                            // 妫�鏌ユ槸鍚︽墍鏈夊垵濮嬬幓鐠冮兘宸茶杞�
+                            boolean allGlassesLoaded = loadedGlassIds.containsAll(initialGlassIds);
+                            if (allGlassesLoaded) {
+                                // 鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冮兘宸茶杞斤紝鏍囪涓哄畬鎴�
+                                log.info("MES宸茬‘璁や笖鍗ц浆绔嬪凡瀹屾垚涓旀墍鏈夌幓鐠冨凡瑁呰浇锛屼换鍔¤嚜鍔ㄥ畬鎴�: taskId={}, deviceId={}, initialCount={}, loadedCount={}",
+                                        task.getTaskId(), device.getId(), initialGlassIds.size(), loadedGlassIds.size());
+                                // mesResult宸茬粡鍖呭惈completed=true锛屼笉闇�瑕佷慨鏀�
+                            }
+                        }
+                    } else {
+                        // 鍗ц浆绔嬭繕鏈畬鎴愶紝涓嶅簲璇ユ爣璁颁负瀹屾垚
+                        log.debug("MES宸茬‘璁や絾鍗ц浆绔嬫湭瀹屾垚锛岀瓑寰呭崸杞珛瀹屾垚: taskId={}, deviceId={}", 
+                                task.getTaskId(), device.getId());
+                    }
+                }
+            }
+
             // 鏇存柊姝ラ鐘舵��
             if (mesResult != null) {
-                updateStepStatusForVehicle(step, mesResult);
+                updateStepStatusForVehicle(task.getTaskId(), step, mesResult);
                 boolean opSuccess = Boolean.TRUE.equals(mesResult.getSuccess());
                 updateTaskProgress(task, step.getStepOrder(), opSuccess);
                 if (!opSuccess) {
@@ -2455,6 +2808,66 @@
         }
     }
 
+    /**
+     * 妫�鏌ュ崸杞珛璁惧鏄惁宸插畬鎴�
+     * 杩斿洖true琛ㄧず鍗ц浆绔嬪凡瀹屾垚锛圕OMPLETED锛夛紝鍙互鍒ゆ柇澶ц溅鏄惁瀹屾垚
+     * 杩斿洖false琛ㄧず鍗ц浆绔嬭繕鍦ㄨ繍琛屼腑锛圧UNNING锛夋垨绛夊緟涓紙PENDING锛夛紝涓嶅簲璇ユ爣璁板ぇ杞︿负瀹屾垚
+     */
+    private boolean isTransferDeviceCompleted(String taskId, TaskExecutionContext context) {
+        if (taskId == null || context == null) {
+            return false;
+        }
+        try {
+            // 浠庝笂涓嬫枃涓幏鍙栬澶囧垪琛�
+            @SuppressWarnings("unchecked")
+            List<DeviceConfig> devices = (List<DeviceConfig>) context.getSharedData().get("devices");
+            if (devices == null || devices.isEmpty()) {
+                return false;
+            }
+            
+            // 鏌ユ壘鍗ц浆绔嬭澶�
+            DeviceConfig transferDevice = null;
+            for (DeviceConfig device : devices) {
+                if (DeviceConfig.DeviceType.WORKSTATION_TRANSFER.equals(device.getDeviceType())) {
+                    transferDevice = device;
+                    break;
+                }
+            }
+            
+            if (transferDevice == null) {
+                // 娌℃湁鍗ц浆绔嬭澶囷紝杩斿洖true锛堜笉褰卞搷鍒ゆ柇锛�
+                return true;
+            }
+            
+            // 鏌ユ壘鍗ц浆绔嬭澶囩殑姝ラ锛堝簲璇ュ彧鏈変竴涓楠わ級
+            List<TaskStepDetail> transferSteps = taskStepDetailMapper.selectList(
+                Wrappers.<TaskStepDetail>lambdaQuery()
+                    .eq(TaskStepDetail::getTaskId, taskId)
+                    .eq(TaskStepDetail::getDeviceId, transferDevice.getId())
+                    .orderByDesc(TaskStepDetail::getStepOrder)
+                    .last("LIMIT 1")
+            );
+            
+            if (transferSteps == null || transferSteps.isEmpty()) {
+                // 娌℃湁鎵惧埌姝ラ锛岃繑鍥瀎alse锛堝崸杞珛鍙兘杩樻病寮�濮嬶級
+                return false;
+            }
+            
+            // 妫�鏌ユ楠ょ姸鎬侊細鍙湁COMPLETED鎵嶇畻瀹屾垚锛孯UNNING鎴朠ENDING閮戒笉绠楀畬鎴�
+            TaskStepDetail transferStep = transferSteps.get(0);
+            String status = transferStep.getStatus();
+            boolean isCompleted = TaskStepDetail.Status.COMPLETED.name().equals(status);
+            
+            log.debug("妫�鏌ュ崸杞珛璁惧鐘舵��: taskId={}, deviceId={}, status={}, isCompleted={}", 
+                    taskId, transferDevice.getId(), status, isCompleted);
+            
+            return isCompleted;
+        } catch (Exception e) {
+            log.warn("妫�鏌ュ崸杞珛璁惧鐘舵�佸け璐�: taskId={}", taskId, e);
+            return false;
+        }
+    }
+
     private String determineOperation(DeviceConfig device, Map<String, Object> params) {
         if (params != null && params.containsKey("operation")) {
             Object op = params.get("operation");

--
Gitblit v1.8.0