using MainShell.Common; using MainShell.EventArgsFolder; using MainShell.Process; using Stylet; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MW.WorkFlow; namespace MainShell.ProcessResult { public class ProcessResultManager { private readonly MachineState _machineState; private readonly IEventAggregator _eventAggregator; /// /// 流程运行状态记录(仅在自动模式下持久化) /// public ProcessFlowState FlowState { get; } = new ProcessFlowState(); /// /// 基板定位的业务结果数据(始终持久化) /// public SubstratePositionProcessResult SubstratePositionResult { get; } = new SubstratePositionProcessResult(); /// /// 芯片定位的业务结果数据(始终持久化) /// public DiePositionProcessResult DiePositionResult { get; } = new DiePositionProcessResult(); /// /// 基板测高的业务结果数据(始终持久化) /// public SubstrateHeightMeasureProcessResult SubstrateHeightMeasureResult { get; } = new SubstrateHeightMeasureProcessResult(); /// /// 精度复检的业务结果数据(始终持久化) /// public DieRecheckProcessResult DieRecheckResult { get; } = new DieRecheckProcessResult(); /// /// 首页统计与条码展示状态(始终持久化) /// public ProductionDashboardState DashboardState { get; } = new ProductionDashboardState(); /// /// 准备区状态(用于恢复前一致性校验) /// public PreparationAreaProcessState PreparationAreaState { get; } = new PreparationAreaProcessState(); private readonly AutoProductionResumeValidator _resumeValidator = new AutoProductionResumeValidator(); /// /// 当前芯片使用位状态 /// public CurrentChipProcessState CurrentChipState { get; } = new CurrentChipProcessState(); /// /// 自动流程运行态 /// public AutoProductionRuntimeState AutoProductionRuntimeState { get; } = new AutoProductionRuntimeState(); public ProcessResultManager(MachineState machineState, IEventAggregator eventAggregator) { _machineState = machineState ?? throw new ArgumentNullException(nameof(machineState)); _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator)); // 构造时读取一次 ReloadAll(); } public void UpdateFlowState(string workflowName, string parentActivityName, string activityName, ProcessExecutionStatus status, string errorMessage = null) { FlowState.WorkflowName = workflowName; FlowState.ParentActivityName = parentActivityName; FlowState.CurrentActivityName = activityName; FlowState.Status = status.ToString(); FlowState.ErrorMessage = errorMessage; FlowState.LastUpdateTime = DateTime.Now; if (ShouldPersistFlowState(workflowName)) { FlowState.Write(); } _eventAggregator.Publish(new ProcessFlowStateChangedEventArgs { WorkflowName = workflowName, ParentActivityName = parentActivityName, CurrentActivityName = activityName, Status = status, ErrorMessage = errorMessage }); } public void UpdateFlowState(string workflowName, string parentActivityName, string activityName, string status, string errorMessage = null) { ProcessExecutionStatus parsed; if (!Enum.TryParse(status, true, out parsed)) { parsed = ProcessExecutionStatus.Unknown; } UpdateFlowState(workflowName, parentActivityName, activityName, parsed, errorMessage); } public void UpdateExecutionPointer(WorkflowExecutionPointer executionPointer) { if (executionPointer == null) { return; } FlowState.WorkflowName = executionPointer.WorkflowName; FlowState.ParentActivityName = executionPointer.FlowName; FlowState.CurrentActivityName = executionPointer.ActivityName; FlowState.CurrentStepId = executionPointer.CurrentStepId; FlowState.NextStepId = executionPointer.NextStepId; FlowState.LastUpdateTime = executionPointer.UpdatedAt == default(DateTime) ? DateTime.Now : executionPointer.UpdatedAt; if (ShouldPersistFlowState(executionPointer.WorkflowName)) { FlowState.Write(); } } public void ReportWorkflowFault(WorkflowFaultInfo faultInfo) { if (faultInfo == null) { return; } FlowState.WorkflowName = faultInfo.WorkflowName; FlowState.ParentActivityName = faultInfo.FlowName; FlowState.CurrentActivityName = faultInfo.ActivityName; FlowState.CurrentStepId = faultInfo.CurrentStepId; FlowState.NextStepId = faultInfo.CurrentStepId; FlowState.Status = ProcessExecutionStatus.Faulted.ToString(); FlowState.ErrorMessage = faultInfo.ErrorMessage; FlowState.LastUpdateTime = faultInfo.OccurredAt == default(DateTime) ? DateTime.Now : faultInfo.OccurredAt; if (ShouldPersistFlowState(faultInfo.WorkflowName)) { FlowState.Write(); } _eventAggregator.Publish(new ProcessFlowStateChangedEventArgs { WorkflowName = faultInfo.WorkflowName, ParentActivityName = faultInfo.FlowName, CurrentActivityName = faultInfo.ActivityName, Status = ProcessExecutionStatus.Faulted, ErrorMessage = faultInfo.ErrorMessage }); } public bool TryGetResumeStepId(string workflowName, out string resumeStepId) { resumeStepId = null; if (string.IsNullOrWhiteSpace(workflowName) || !string.Equals(FlowState.WorkflowName, workflowName, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(FlowState.NextStepId)) { return false; } if (string.Equals(FlowState.Status, ProcessExecutionStatus.Completed.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(FlowState.Status, ProcessExecutionStatus.Canceled.ToString(), StringComparison.OrdinalIgnoreCase)) { return false; } if (!_resumeValidator.IsStateConsistentForResume(FlowState.NextStepId, PreparationAreaState, CurrentChipState)) { FlowState.ErrorMessage = _resumeValidator.BuildResumeValidationError(FlowState.NextStepId, PreparationAreaState, CurrentChipState); FlowState.LastUpdateTime = DateTime.Now; if (ShouldPersistFlowState(workflowName)) { FlowState.Write(); } return false; } resumeStepId = FlowState.NextStepId; return true; } public void SaveSubstratePositionResult() { SubstratePositionResult.Write(); } public void SaveDiePositionResult() { DiePositionResult.Write(); } public void SaveSubstrateHeightMeasureResult() { SubstrateHeightMeasureResult.Write(); } public void SaveDieRecheckResult() { DieRecheckResult.Write(); } public void SaveDashboardState() { DashboardState.Write(); } public void SavePreparationAreaState(ChipPreparationStateSnapshot snapshot) { if (snapshot == null) { return; } PreparationAreaState.Status = snapshot.Status; PreparationAreaState.ActiveRequestId = snapshot.ActiveRequestId; PreparationAreaState.RecipeName = snapshot.RecipeName; PreparationAreaState.SourceStepId = snapshot.SourceStepId; PreparationAreaState.CurrentStage = snapshot.CurrentStage; PreparationAreaState.ErrorMessage = snapshot.ErrorMessage; PreparationAreaState.LastUpdatedTime = snapshot.LastUpdatedTime; PreparationAreaState.CurrentAction = snapshot.CurrentAction; PreparationAreaState.HasPreparedChip = snapshot.IsChipLoaded; PreparationAreaState.Write(); } public void SaveCurrentChipState(CurrentChipLifecycleState chipState) { CurrentChipState.State = chipState; CurrentChipState.LastUpdatedTime = DateTime.Now; CurrentChipState.Write(); } public void SaveAutoProductionRuntimeState(AutoProductionRuntimeState runtimeState) { if (runtimeState == null) { return; } AutoProductionRuntimeState.CurrentSubstratePendingCount = runtimeState.CurrentSubstratePendingCount; AutoProductionRuntimeState.CurrentSubstrateProcessedCount = runtimeState.CurrentSubstrateProcessedCount; AutoProductionRuntimeState.CurrentChipRemainingCount = runtimeState.CurrentChipRemainingCount; AutoProductionRuntimeState.TransferNeedsRecheck = runtimeState.TransferNeedsRecheck; AutoProductionRuntimeState.TransferChipExhausted = runtimeState.TransferChipExhausted; AutoProductionRuntimeState.LastUpdatedTime = runtimeState.LastUpdatedTime; AutoProductionRuntimeState.Write(); } /// /// 强制从磁盘重新加载所有状态和结果数据 /// 在启动或恢复自动流程前调用,确保获取到最新的(可能是手动操作产生的)结果数据 /// public void ReloadAll() { // 1. 读取断点状态(决定从哪一步开始) FlowState.Read(); // 2. 读取业务结果(决定流程所需的数据上下文) // 无论之前是手动还是自动写入的,这里统一读取最新值 SubstratePositionResult.Read(); DiePositionResult.Read(); SubstrateHeightMeasureResult.Read(); DieRecheckResult.Read(); // 3. 首页运行数据 DashboardState.Read(); // 4. 准备区状态 PreparationAreaState.Read(); // 5. 当前芯片使用位状态 CurrentChipState.Read(); // 6. 自动流程运行态 AutoProductionRuntimeState.Read(); // 后续如果有其他结果类(如 WaferMapResult),也在这里读取 // WaferMapResult.Read(); } private bool ShouldPersistFlowState(string workflowName) { return _machineState.CurrentMode == MachineMode.Auto || string.Equals(workflowName, ProcessFlowName.AutoProduction, StringComparison.OrdinalIgnoreCase); } } }