错误程序子程序优化
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UIShare.UIViewModel;
|
||||
|
||||
namespace UIShare.GlobalVariable
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个 Tab(主程序 / 错误程序)的子程序导航状态。
|
||||
/// 主程序和错误程序各自持有一个独立实例,互不干扰。
|
||||
/// </summary>
|
||||
public class ProgramNavigationState : BindableBase
|
||||
{
|
||||
/// <summary>是否为错误程序 Tab</summary>
|
||||
public bool IsErrorTab { get; set; }
|
||||
|
||||
public Stack<ProgramVM> NavigationStack { get; } = new();
|
||||
|
||||
private ProgramVM _currentProgram;
|
||||
public ProgramVM CurrentProgram
|
||||
{
|
||||
get => _currentProgram;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _currentProgram, value))
|
||||
RaisePropertyChanged(nameof(DisplaySteps));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DataGrid 实际绑定的步骤集合。
|
||||
/// 根程序 + 错误 Tab → ErrorStepCollection;其他情况 → StepCollection。
|
||||
/// </summary>
|
||||
public ObservableCollection<StepVM> DisplaySteps
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CurrentProgram == null)
|
||||
return new ObservableCollection<StepVM>();
|
||||
// 在根程序且是错误 Tab → 显示错误步骤集合
|
||||
if (NavigationStack.Count == 0 && IsErrorTab)
|
||||
return CurrentProgram.ErrorStepCollection;
|
||||
// 其他情况(主 Tab 或已进入子程序)→ 显示正常步骤集合
|
||||
return CurrentProgram.StepCollection;
|
||||
}
|
||||
}
|
||||
|
||||
private string _breadcrumbPath = "主程序";
|
||||
public string BreadcrumbPath
|
||||
{
|
||||
get => _breadcrumbPath;
|
||||
set => SetProperty(ref _breadcrumbPath, value);
|
||||
}
|
||||
|
||||
private bool _canGoBack;
|
||||
public bool CanGoBack
|
||||
{
|
||||
get => _canGoBack;
|
||||
set => SetProperty(ref _canGoBack, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用根程序初始化导航状态
|
||||
/// </summary>
|
||||
public void Initialize(ProgramVM rootProgram, string label)
|
||||
{
|
||||
NavigationStack.Clear();
|
||||
CurrentProgram = rootProgram;
|
||||
BreadcrumbPath = label;
|
||||
CanGoBack = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空导航栈,回到根程序
|
||||
/// </summary>
|
||||
public void Reset(ProgramVM rootProgram, string label)
|
||||
{
|
||||
NavigationStack.Clear();
|
||||
CurrentProgram = rootProgram;
|
||||
BreadcrumbPath = label;
|
||||
CanGoBack = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据栈状态刷新 CanGoBack
|
||||
/// </summary>
|
||||
public void UpdateCanGoBack() => CanGoBack = NavigationStack.Count > 0;
|
||||
}
|
||||
}
|
||||
@@ -19,66 +19,29 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
private static readonly Random _randomSeed = new Random();
|
||||
|
||||
#region 子程序导航栈(台架隔离)
|
||||
#region 子程序导航(主程序 / 错误程序各自独立)
|
||||
|
||||
/// <summary>主程序 Tab 的导航状态</summary>
|
||||
public ProgramNavigationState MainNav { get; } = new();
|
||||
|
||||
/// <summary>错误程序 Tab 的导航状态</summary>
|
||||
public ProgramNavigationState ErrorNav { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 子程序导航栈:记录从根程序进入子程序的路径。
|
||||
/// 每个台架(ScopedContext 实例)各自维护一个独立的栈,互不干扰。
|
||||
/// 根据当前选中的 Tab 返回对应的导航状态
|
||||
/// </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);
|
||||
}
|
||||
public ProgramNavigationState ActiveNav =>
|
||||
SelectedStepList == "错误程序" ? ErrorNav : MainNav;
|
||||
|
||||
/// <summary>
|
||||
/// 清空导航栈,回到根程序界面
|
||||
/// 重置两个 Tab 的导航栈,回到根程序
|
||||
/// </summary>
|
||||
public void ResetNavigation()
|
||||
{
|
||||
SubProgramNavigationStack.Clear();
|
||||
CurrentProgram = Program;
|
||||
BreadcrumbPath = "主程序";
|
||||
CanGoBack = false;
|
||||
MainNav.Reset(Program, "主程序");
|
||||
ErrorNav.Reset(Program, "错误程序");
|
||||
}
|
||||
|
||||
/// <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();
|
||||
@@ -109,6 +72,7 @@ namespace UIShare.GlobalVariable
|
||||
public int DebugRandomId { get; private set; }
|
||||
public ScopedContext()
|
||||
{
|
||||
ErrorNav.IsErrorTab = true;
|
||||
lock (_randomSeed)
|
||||
{
|
||||
// 每次诞生一个新上下文,就在 10000 到 99999 之间随机摇一个数
|
||||
|
||||
@@ -69,11 +69,11 @@ namespace UIShare
|
||||
tmpParameters.Clear();
|
||||
TestRoundID = Guid.NewGuid();
|
||||
}
|
||||
int initialLoopStackCount = loopStack.Count;
|
||||
foreach (var item in program.Parameters)
|
||||
{
|
||||
tmpParameters.TryAdd(item.ID, item);
|
||||
}
|
||||
|
||||
while (index < program.ErrorStepCollection.Count)
|
||||
{
|
||||
if (_disposed || cancellationToken.IsCancellationRequested)
|
||||
@@ -188,14 +188,16 @@ namespace UIShare
|
||||
Scope = _systemConfig.Title,
|
||||
Action = NavigateAction.Enter,
|
||||
SubProgram = step.SubProgram,
|
||||
StepName = step.Name
|
||||
StepName = step.Name,
|
||||
IsErrorProgram = true
|
||||
});
|
||||
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
|
||||
// 发布退出子程序导航事件
|
||||
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
|
||||
{
|
||||
Scope = _systemConfig.Title,
|
||||
Action = NavigateAction.Exit
|
||||
Action = NavigateAction.Exit,
|
||||
IsErrorProgram = true
|
||||
});
|
||||
UpdateCurrentStepResult(step, true, stepSuccess, depth);
|
||||
if (SubSingleStep)
|
||||
@@ -238,7 +240,12 @@ namespace UIShare
|
||||
await SaveStepRecordAsync(step, depth, true);
|
||||
}
|
||||
}
|
||||
bool finalResult = loopStack.Count == initialLoopStackCount && stepSuccess;
|
||||
|
||||
if (depth > 0) // 子程序
|
||||
{
|
||||
return finalResult;
|
||||
}
|
||||
return loopStack.Count == 0 && stepSuccess;
|
||||
}
|
||||
public async Task<bool> ExecuteSteps(ProgramVM program, int depth = 0, CancellationToken cancellationToken = default)
|
||||
|
||||
@@ -24,6 +24,9 @@ namespace UIShare.PubEvent
|
||||
|
||||
/// <summary>子程序步骤的名称(用于面包屑显示)</summary>
|
||||
public string? StepName { get; set; }
|
||||
|
||||
/// <summary>是否为错误程序 Tab 的导航(默认 false = 主程序 Tab)</summary>
|
||||
public bool IsErrorProgram { get; set; }
|
||||
}
|
||||
|
||||
public enum NavigateAction
|
||||
|
||||
Reference in New Issue
Block a user