子程序使用优化

This commit is contained in:
“hsc”
2026-08-07 13:46:11 +08:00
parent 57db6776b8
commit 80a2cbd80b
7 changed files with 306 additions and 15 deletions
+65 -1
View File
@@ -1,5 +1,6 @@
using DeviceCommand.Base;
using MaterialDesignThemes.Wpf;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -14,9 +15,72 @@ using UIShare.UIViewModel;
namespace UIShare.GlobalVariable
{
public class ScopedContext
public class ScopedContext : BindableBase
{
private static readonly Random _randomSeed = new Random();
#region
/// <summary>
/// 子程序导航栈:记录从根程序进入子程序的路径。
/// 每个台架(ScopedContext 实例)各自维护一个独立的栈,互不干扰。
/// </summary>
public Stack<ProgramVM> SubProgramNavigationStack { get; } = new();
private ProgramVM _currentProgram;
/// <summary>
/// 当前在 StepManager 中显示的程序(可能是根程序,也可能是某层子程序)。
/// UI 的 DataGrid 绑定此属性,而非直接绑定 Program。
/// </summary>
public ProgramVM CurrentProgram
{
get => _currentProgram;
set => SetProperty(ref _currentProgram, value);
}
private string _breadcrumbPath = "主程序";
/// <summary>
/// 面包屑导航路径,如 "主程序 > 连接流程 > 初始化"
/// </summary>
public string BreadcrumbPath
{
get => _breadcrumbPath;
set => SetProperty(ref _breadcrumbPath, value);
}
private bool _canGoBack;
/// <summary>
/// 是否可以返回上一级(导航栈不为空时为 true)
/// </summary>
public bool CanGoBack
{
get => _canGoBack;
set => SetProperty(ref _canGoBack, value);
}
/// <summary>
/// 清空导航栈,回到根程序界面
/// </summary>
public void ResetNavigation()
{
SubProgramNavigationStack.Clear();
CurrentProgram = Program;
BreadcrumbPath = "主程序";
CanGoBack = false;
}
/// <summary>
/// 根据栈状态刷新 CanGoBack
/// </summary>
public void UpdateCanGoBack() => CanGoBack = SubProgramNavigationStack.Count > 0;
/// <summary>
/// 当前导航深度(0 = 根程序,1 = 第一层子程序,以此类推)
/// </summary>
public int NavigationDepth => SubProgramNavigationStack.Count;
#endregion
public ProgramVM Program { get; set; } = new();
public String SelectedStepList { get; set; } = "主程序";
public string CurrentFilePath { get; set; }
+36
View File
@@ -2,6 +2,7 @@
using UIShare.PubEvent;
using Common.Tools;
using Logger;
using MaterialDesignThemes.Wpf;
using Model.Entity;
using Service.Interface;
@@ -181,7 +182,21 @@ namespace UIShare
_scopedContext.SingleStep = false;
}
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
// 发布进入子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Enter,
SubProgram = step.SubProgram,
StepName = step.Name
});
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
// 发布退出子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Exit
});
UpdateCurrentStepResult(step, true, stepSuccess, depth);
if (SubSingleStep)
{
@@ -239,6 +254,7 @@ namespace UIShare
tmpParameters.Clear();
TestRoundID = Guid.NewGuid();
}
int initialLoopStackCount = loopStack.Count;
foreach (var item in program.Parameters)
{
tmpParameters.TryAdd(item.ID, item);
@@ -356,7 +372,21 @@ namespace UIShare
_scopedContext.SingleStep = false;
}
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
// 发布进入子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Enter,
SubProgram = step.SubProgram,
StepName = step.Name
});
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
// 发布退出子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Exit
});
UpdateCurrentStepResult(step, true, stepSuccess, depth);
if (SubSingleStep)
{
@@ -403,9 +433,15 @@ namespace UIShare
_eventAggregator.GetEvent<RunSingalCompletedEvent>().Publish("Play");
}
await SaveStepRecordAsync(step, depth, false);
// 仅检查本层执行期间压入的循环是否全部弹出,不关心父程序遗留的循环上下文
}
}
bool finalResult = loopStack.Count == initialLoopStackCount && stepSuccess;
if (depth > 0) // 子程序
{
return finalResult;
}
return loopStack.Count == 0 && stepSuccess;
}
@@ -0,0 +1,34 @@
using Prism.Events;
using UIShare.UIViewModel;
namespace UIShare.PubEvent
{
/// <summary>
/// 子程序导航事件:运行时进入/退出子程序时发布,
/// StepsManagerViewModel 订阅后自动切换显示。
/// </summary>
public class SubProgramNavigateEvent : PubSubEvent<SubProgramNavigatePayload>
{
}
public class SubProgramNavigatePayload
{
/// <summary>目标台架的作用域标识</summary>
public string Scope { get; set; } = "";
/// <summary>Enter = 进入子程序,Exit = 退出回到上一级</summary>
public NavigateAction Action { get; set; }
/// <summary>进入时:子程序的 ProgramVM;退出时可为 null</summary>
public ProgramVM? SubProgram { get; set; }
/// <summary>子程序步骤的名称(用于面包屑显示)</summary>
public string? StepName { get; set; }
}
public enum NavigateAction
{
Enter,
Exit
}
}