完成执行逻辑
This commit is contained in:
parent
b69a469c89
commit
691d894a12
22
BOB/Converters/InverseBooleanConverter.cs
Normal file
22
BOB/Converters/InverseBooleanConverter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class InverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// null 视为 false,再取反 → true
|
||||
var b = value as bool?;
|
||||
return !(b ?? false);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var b = value as bool?;
|
||||
return !(b ?? false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class ParameterToGotoSettingStringConverter : IValueConverter
|
||||
{
|
||||
private GlobalVariables _globalVariables;
|
||||
public ParameterToGotoSettingStringConverter(GlobalVariables globalVariables)
|
||||
{
|
||||
_globalVariables= globalVariables;
|
||||
}
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Guid stepID && stepID == _globalVariables.SelectedStep!.ID)
|
||||
{
|
||||
if (_globalVariables.SelectedStep == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (_globalVariables.SelectedStep!.OKGotoStepID == null && _globalVariables.SelectedStep!.NGGotoStepID == null)
|
||||
{
|
||||
return "0/0";
|
||||
}
|
||||
else
|
||||
{
|
||||
string gotoString = "";
|
||||
if (_globalVariables.SelectedStep!.OKGotoStepID != null)
|
||||
{
|
||||
var OKGotoStep = _globalVariables.Program.StepCollection.FirstOrDefault(x => x.ID == _globalVariables.SelectedStep!.OKGotoStepID);
|
||||
if (OKGotoStep != null)
|
||||
{
|
||||
gotoString = OKGotoStep.Index.ToString() + "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
gotoString = "0/";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gotoString = "0/";
|
||||
}
|
||||
if (_globalVariables.SelectedStep!.NGGotoStepID != null)
|
||||
{
|
||||
var NGGotoStep = _globalVariables.Program.StepCollection.FirstOrDefault(x => x.ID == _globalVariables.SelectedStep!.NGGotoStepID);
|
||||
if (NGGotoStep != null)
|
||||
{
|
||||
gotoString += NGGotoStep.Index.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gotoString += "0";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gotoString += "0";
|
||||
}
|
||||
return gotoString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is string gotoSettingstring)
|
||||
{
|
||||
gotoSettingstring = gotoSettingstring.Replace(" ", "").Replace("/n", "").Replace("/r", "");
|
||||
if (gotoSettingstring == "0/0")
|
||||
{
|
||||
_globalVariables.SelectedStep!.OKGotoStepID = null;
|
||||
_globalVariables.SelectedStep!.NGGotoStepID = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = gotoSettingstring.Split("/");
|
||||
var okindex = System.Convert.ToInt32(list[0]);
|
||||
var ngindex = System.Convert.ToInt32(list[1]);
|
||||
if (okindex == 0)
|
||||
{
|
||||
_globalVariables.SelectedStep!.OKGotoStepID = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (okindex > _globalVariables.Program.StepCollection.Count)
|
||||
{
|
||||
throw new Exception("步骤序号超出最大值");
|
||||
}
|
||||
_globalVariables.SelectedStep!.OKGotoStepID = _globalVariables.Program.StepCollection.FirstOrDefault(x => x.Index == okindex)?.ID;
|
||||
}
|
||||
if (ngindex == 0)
|
||||
{
|
||||
_globalVariables.SelectedStep!.NGGotoStepID = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ngindex > _globalVariables.Program.StepCollection.Count)
|
||||
{
|
||||
throw new Exception("步骤序号超出最大值");
|
||||
}
|
||||
_globalVariables.SelectedStep!.NGGotoStepID = _globalVariables.Program.StepCollection.FirstOrDefault(x => x.Index == ngindex)?.ID;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"跳转表达式错误:{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return _globalVariables.SelectedStep!.ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using Common.Tools;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
@ -18,6 +19,7 @@ namespace BOB
|
||||
public class StepRunning
|
||||
{
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
|
||||
private readonly Dictionary<Guid, ParameterModel> tmpParameters = [];
|
||||
|
||||
@ -31,9 +33,10 @@ namespace BOB
|
||||
private bool SubSingleStep = false;
|
||||
|
||||
private Guid TestRoundID;
|
||||
public StepRunning(GlobalVariables globalVariables)
|
||||
public StepRunning(GlobalVariables globalVariables,IEventAggregator eventAggregator)
|
||||
{
|
||||
_globalVariables = globalVariables;
|
||||
_eventAggregator= eventAggregator;
|
||||
}
|
||||
public async Task<bool> ExecuteSteps(ProgramModel program, int depth = 0, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@ -108,7 +111,7 @@ namespace BOB
|
||||
{
|
||||
if (loopStack.Count == 0)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth);
|
||||
LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth:depth);
|
||||
step.Result = 2;
|
||||
index++;
|
||||
continue;
|
||||
@ -203,7 +206,8 @@ namespace BOB
|
||||
{
|
||||
_globalVariables.IsStop = true;
|
||||
_globalVariables.RunState = "运行";
|
||||
_globalVariables.RunIcon = PackIconKind.Play;
|
||||
_globalVariables.SingleStep = false;
|
||||
_eventAggregator.GetEvent<UpdateIconEvent>().Publish("Play");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,6 +219,7 @@ namespace BOB
|
||||
{
|
||||
try
|
||||
{
|
||||
if(_globalVariables.Program.StepCollection.Count>1)
|
||||
_globalVariables.SelectedStep = null;
|
||||
await Task.Delay(SystemConfig.Instance.PerformanceLevel);
|
||||
|
||||
@ -227,7 +232,7 @@ namespace BOB
|
||||
}
|
||||
if (targetType == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth);
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
@ -318,7 +323,7 @@ namespace BOB
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth);
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -342,7 +347,7 @@ namespace BOB
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth);
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
@ -350,7 +355,7 @@ namespace BOB
|
||||
bool isStaticMethod = method!.IsStatic;
|
||||
|
||||
// 如果是实例方法,需要创建实例
|
||||
if (!isMethod)
|
||||
if (!isStaticMethod)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -358,7 +363,7 @@ namespace BOB
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth);
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
}
|
||||
@ -396,7 +401,7 @@ namespace BOB
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth);
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
@ -448,7 +453,7 @@ namespace BOB
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth);
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
@ -496,7 +501,7 @@ namespace BOB
|
||||
step.Result = re ? 1 : 2;
|
||||
if (step.Result == 2)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth);
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,7 +509,7 @@ namespace BOB
|
||||
{
|
||||
if (!paraResult)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify("参数限值校验失败", depth);
|
||||
LoggerHelper.WarnWithNotify("参数限值校验失败", depth: depth);
|
||||
}
|
||||
step.Result = 2;
|
||||
}
|
||||
@ -129,6 +129,10 @@ namespace BOB.ViewModels
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(Node.Tag is SubProgramItem subProgram)
|
||||
{
|
||||
AddSubProgramToProgram(subProgram, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,7 +199,7 @@ namespace BOB.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var filePath in Directory.GetFiles(SystemConfig.Instance.SubProgramFilePath, "*.ats"))
|
||||
foreach (var filePath in Directory.GetFiles(SystemConfig.Instance.SubProgramFilePath, "*.bob"))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -470,45 +474,42 @@ namespace BOB.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
//private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var newStep = new StepModel
|
||||
// {
|
||||
// Name = subProgram.Name,
|
||||
// StepType = "子程序"
|
||||
// };
|
||||
// var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
|
||||
// var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
|
||||
// if (tmp != null)
|
||||
// {
|
||||
// if (tmp.Devices != null && tmp.Devices.Count > 0)
|
||||
// {
|
||||
// foreach (var device in tmp.Devices)
|
||||
// {
|
||||
private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
StepType = "子程序"
|
||||
};
|
||||
var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
|
||||
var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
|
||||
if (tmp != null)
|
||||
{
|
||||
if (tmp.Devices != null && tmp.Devices.Count > 0)
|
||||
{
|
||||
foreach (var device in tmp.Devices)
|
||||
{
|
||||
// _ = DeviceConnect.InitAndConnectDevice(tmp, device);
|
||||
// }
|
||||
// }
|
||||
// newStep.SubProgram = tmp;
|
||||
// }
|
||||
// 添加到程序
|
||||
// if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
|
||||
// {
|
||||
// Program.StepCollection.Insert(insertIndex, newStep);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Program.StepCollection.Add(newStep);
|
||||
// }
|
||||
|
||||
// ReOrderProgramList();
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Log.Error($"添加子程序失败: {subProgram.Name} - {ex.Message}");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
newStep.SubProgram = tmp;
|
||||
}
|
||||
if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.StepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加子程序失败: {subProgram.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoopStartStep(int insertIndex = -1)
|
||||
{
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -62,11 +63,13 @@ namespace BOB.ViewModels.Dialogs
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
public ICommand CancelCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ICommand SelectionChangedCommand { get; set; }
|
||||
public DeviceSettingViewModel(GlobalVariables globalVariables)
|
||||
public DeviceSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_globalVariables = globalVariables;
|
||||
CancelCommand = new DelegateCommand(Cancel);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
@ -183,11 +186,12 @@ namespace BOB.ViewModels.Dialogs
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Program = _globalVariables.Program;
|
||||
Mode = parameters.GetValue<string>("Mode");
|
||||
if(Mode == "ADD")
|
||||
|
||||
@ -100,6 +100,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Title = parameters.GetValue<string>("Title");
|
||||
Message = parameters.GetValue<string>("Message");
|
||||
var iconKey = parameters.GetValue<string>("Icon"); // info / error / warn
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -69,10 +70,12 @@ namespace BOB.ViewModels.Dialogs
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose{get;set;}
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
public ICommand CancelCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ParameterSettingViewModel(GlobalVariables globalVariables)
|
||||
public ParameterSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_globalVariables = globalVariables;
|
||||
CancelCommand = new DelegateCommand(Cancel);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
@ -112,11 +115,12 @@ namespace BOB.ViewModels.Dialogs
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Program =_globalVariables.Program;
|
||||
Mode = parameters.GetValue<string>("Mode");
|
||||
if (Mode == "ADD")
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
@ -16,18 +17,21 @@ namespace BOB.ViewModels
|
||||
get => _logs;
|
||||
set => SetProperty(ref _logs, value);
|
||||
}
|
||||
|
||||
public ICommand ClearLogCommand { get; set; }
|
||||
public LogAreaViewModel()
|
||||
{
|
||||
LoggerHelper.LogAdded += OnLogAdded;
|
||||
ClearLogCommand = new DelegateCommand(ClearLog);
|
||||
LoggerHelper.Progress = new System.Progress<(string message, string color,int depth)>(
|
||||
log =>
|
||||
{
|
||||
var brush = (Brush)new BrushConverter().ConvertFromString(log.color);
|
||||
Logs.Add(new LogItem(log.message, brush, log.depth));
|
||||
});
|
||||
}
|
||||
|
||||
// 方便外部添加日志
|
||||
public void OnLogAdded(string message, string color)
|
||||
private void ClearLog()
|
||||
{
|
||||
var brush = (Brush)new BrushConverter().ConvertFromString(color);
|
||||
Application.Current.Dispatcher.Invoke(() => Logs.Add(new LogItem { Message = message, Color = brush }));
|
||||
|
||||
Logs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,5 +40,12 @@ namespace BOB.ViewModels
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Brush Color { get; set; } = Brushes.Black;
|
||||
public int Depth { get; set; }
|
||||
public LogItem(string message, Brush color, int depth = 0)
|
||||
{
|
||||
Message = new string(' ', depth * 20) + message;
|
||||
Color = color;
|
||||
Depth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,13 +97,12 @@ namespace BOB.ViewModels
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
});
|
||||
|
||||
}
|
||||
@ -114,18 +113,16 @@ namespace BOB.ViewModels
|
||||
{
|
||||
{ "Mode", "ADD" }
|
||||
};
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -144,13 +141,13 @@ namespace BOB.ViewModels
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -164,13 +161,13 @@ namespace BOB.ViewModels
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using BOB.Models;
|
||||
using BOB.Views;
|
||||
using Common.PubEvent;
|
||||
using Common.PubEvents;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
@ -28,6 +29,13 @@ namespace BOB.ViewModels
|
||||
get => _IsLeftDrawerOpen;
|
||||
set => SetProperty(ref _IsLeftDrawerOpen, value);
|
||||
}
|
||||
private bool _IsTerminate=false;
|
||||
|
||||
public bool IsTerminate
|
||||
{
|
||||
get => _IsTerminate;
|
||||
set => SetProperty(ref _IsTerminate, value);
|
||||
}
|
||||
|
||||
public String RunState
|
||||
{
|
||||
@ -109,6 +117,17 @@ namespace BOB.ViewModels
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
SetDefaultCommand = new DelegateCommand(SetDefault);
|
||||
LoadCommand = new DelegateCommand(Load);
|
||||
_eventAggregator.GetEvent<UpdateIconEvent>().Subscribe(UpdateRunIcon);
|
||||
}
|
||||
|
||||
private void UpdateRunIcon(string obj)
|
||||
{
|
||||
RunIcon= obj switch
|
||||
{
|
||||
"Play" => PackIconKind.Play,
|
||||
"Pause" => PackIconKind.Pause,
|
||||
_ => RunIcon
|
||||
};
|
||||
}
|
||||
#region ToolBar命令
|
||||
private void Load()
|
||||
@ -206,10 +225,9 @@ namespace BOB.ViewModels
|
||||
{
|
||||
_globalVariables.CurrentFilePath = saveFileDialog.FileName;
|
||||
SaveProgramToFile(_globalVariables.CurrentFilePath);
|
||||
}
|
||||
|
||||
// 记录日志
|
||||
LoggerHelper.InfoWithNotify($"{_globalVariables.UserName} 另存为文件成功: {saveFileDialog.FileName}");
|
||||
}
|
||||
|
||||
}
|
||||
private void SaveProgramToFile(string filePath)
|
||||
@ -251,16 +269,29 @@ namespace BOB.ViewModels
|
||||
return;
|
||||
}
|
||||
SaveProgramToFile(_globalVariables.CurrentFilePath);
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "保存文件成功");
|
||||
|
||||
}
|
||||
private void Stop()
|
||||
{
|
||||
if (_globalVariables.IsStop == false)
|
||||
{
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行停止命令");
|
||||
IsTerminate = true;
|
||||
_globalVariables.IsStop = null;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_stepRunning.stepCTS.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void Resotration()
|
||||
{
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行复位命令");
|
||||
IsTerminate = false;
|
||||
currentExecutionTask = null;
|
||||
_stepRunning.stepCTS = new();
|
||||
_globalVariables.IsStop = null;
|
||||
_stepRunning.ResetAllStepStatus(_globalVariables.Program);
|
||||
}
|
||||
|
||||
private async void RunSingle()
|
||||
@ -274,11 +305,12 @@ namespace BOB.ViewModels
|
||||
if (_globalVariables.IsStop == null)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
if(currentExecutionTask==null)currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
await currentExecutionTask;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_globalVariables.IsStop = null;
|
||||
IsTerminate = true;
|
||||
}
|
||||
else if (_globalVariables.IsStop == true)
|
||||
{
|
||||
@ -299,11 +331,12 @@ namespace BOB.ViewModels
|
||||
if (_globalVariables.IsStop == null)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
if (currentExecutionTask == null) currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
await currentExecutionTask;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_globalVariables.IsStop = null;
|
||||
IsTerminate = true;
|
||||
}
|
||||
else if (_globalVariables.IsStop == true)
|
||||
{
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using Logger;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using SqlSugar.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
@ -39,16 +44,24 @@ namespace BOB.ViewModels
|
||||
#endregion
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
public ICommand CancelEditCommand { get; set; }
|
||||
public ICommand SaveStepCommand { get; set; }
|
||||
public SingleStepEditViewModel(GlobalVariables globalVariables,IEventAggregator eventAggregator)
|
||||
public SingleStepEditViewModel(GlobalVariables globalVariables,IEventAggregator eventAggregator,IDialogService dialogService)
|
||||
{
|
||||
_globalVariables= globalVariables;
|
||||
_eventAggregator= eventAggregator;
|
||||
_dialogService = dialogService;
|
||||
_eventAggregator.GetEvent<EditSetpEvent>().Subscribe(EditSingleSetp);
|
||||
CancelEditCommand = new DelegateCommand(CancelEdit);
|
||||
SaveStepCommand = new DelegateCommand(SaveStep);
|
||||
_eventAggregator.GetEvent<DeletedStepEvent>().Subscribe(DisposeSelectedStep);
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Subscribe(ParamsChanged);
|
||||
}
|
||||
|
||||
private void ParamsChanged()
|
||||
{
|
||||
CancelEdit();
|
||||
}
|
||||
|
||||
private void DisposeSelectedStep(Guid id)
|
||||
@ -74,10 +87,105 @@ namespace BOB.ViewModels
|
||||
if (index >= 0)
|
||||
{
|
||||
steps[index] = SelectedStep;
|
||||
if (steps[index].Method != null)
|
||||
{
|
||||
if (steps[index].StepType == "循环开始")
|
||||
{
|
||||
try
|
||||
{
|
||||
steps[index].LoopCount = Convert.ToInt32(SelectedStep.Method!.Parameters[0].Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("循环指令参数设置错误:类型转换失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].Method.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.Method!.Parameters[i];
|
||||
var originalParam = steps[index].Method.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _globalVariables.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
else if (steps[index].SubProgram != null)
|
||||
{
|
||||
if (SelectedStep.SubProgram.Parameters.Where(x => x.VariableName == null && x.IsUseVar == true).FirstOrDefault() != null)
|
||||
{
|
||||
var parameters1 = new DialogParameters
|
||||
{
|
||||
{ "Title", "警告" },
|
||||
{ "Message", "选中变量不得为空!" },
|
||||
{ "Icon", "warn" },
|
||||
{ "ShowOk", true },
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox",parameters1);
|
||||
return;
|
||||
}
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].SubProgram.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.SubProgram!.Parameters[i];
|
||||
var originalParam = steps[index].SubProgram.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _globalVariables.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private (Guid,Guid) GetOKNGGotoStepID(string GotoSettingString)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(GotoSettingString))
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
|
||||
var match = Regex.Match(GotoSettingString, @"^(\d+)\s*/\s*(\d+)$");
|
||||
if (match.Success)
|
||||
{
|
||||
int ok = int.Parse(match.Groups[1].Value);
|
||||
int ng = int.Parse(match.Groups[2].Value);
|
||||
|
||||
Guid okGuid = _globalVariables.Program.StepCollection.ElementAtOrDefault(ok-1)?.ID ?? Guid.Empty;
|
||||
Guid ngGuid = _globalVariables.Program.StepCollection.ElementAtOrDefault(ng-1)?.ID ?? Guid.Empty;
|
||||
|
||||
return (okGuid, ngGuid);
|
||||
}
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
}
|
||||
private void EditSingleSetp()
|
||||
{
|
||||
ID = _globalVariables.SelectedStep.ID;
|
||||
|
||||
@ -11,10 +11,16 @@
|
||||
|
||||
<Grid>
|
||||
<GroupBox Header="系统运行日志">
|
||||
<ListView FontWeight="DemiBold"
|
||||
<ListView x:Name="LogListView"
|
||||
FontWeight="DemiBold"
|
||||
ItemsSource="{Binding Logs}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
|
||||
<ListView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="清空日志"
|
||||
Command="{Binding ClearLogCommand}" />
|
||||
</ContextMenu>
|
||||
</ListView.ContextMenu>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Foreground="{Binding Color}"
|
||||
|
||||
@ -1,28 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using BOB.ViewModels;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// LogArea.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LogArea : UserControl
|
||||
{
|
||||
public LogArea()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 绑定 DataContext 后,订阅日志集合变化
|
||||
this.Loaded += (s, e) =>
|
||||
{
|
||||
if (DataContext is LogAreaViewModel vm)
|
||||
{
|
||||
vm.Logs.CollectionChanged += Logs_CollectionChanged;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void Logs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
// 每次新增日志,滚动到最后一条
|
||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
if (this.LogListView.Items.Count > 0)
|
||||
{
|
||||
this.LogListView.ScrollIntoView(this.LogListView.Items[^1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Topmost="false"
|
||||
xmlns:converter="clr-namespace:BOB.Converters"
|
||||
mc:Ignorable="d"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
WindowStyle="None"
|
||||
@ -23,7 +23,9 @@
|
||||
<i:InvokeCommandAction Command="{Binding LoadCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
|
||||
<Window.Resources>
|
||||
<converter:InverseBooleanConverter x:Key="InverseBooleanConverter" />
|
||||
</Window.Resources>
|
||||
<materialDesign:DrawerHost x:Name="MainDrawerHost"
|
||||
IsLeftDrawerOpen="{Binding IsLeftDrawerOpen, Mode=TwoWay}">
|
||||
|
||||
@ -146,6 +148,7 @@
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="运行"
|
||||
IsEnabled="{Binding IsTerminate, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Command="{Binding RunningCommand}"
|
||||
Foreground="White">
|
||||
<MenuItem.Icon>
|
||||
@ -156,6 +159,7 @@
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="单步执行"
|
||||
IsEnabled="{Binding IsTerminate, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Command="{Binding RunSingleCommand}"
|
||||
Foreground="White">
|
||||
<MenuItem.Icon>
|
||||
@ -176,6 +180,7 @@
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="复位"
|
||||
IsEnabled="{Binding IsTerminate}"
|
||||
Command="{Binding ResotrationCommand}"
|
||||
Foreground="White">
|
||||
<MenuItem.Icon>
|
||||
@ -241,15 +246,15 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="454*" />
|
||||
<ColumnDefinition Width="91*" />
|
||||
<ColumnDefinition Width="1375*" />
|
||||
<ColumnDefinition Width="57*" />
|
||||
<ColumnDefinition Width="1319*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentControl prism:RegionManager.RegionName="ShellViewManager"
|
||||
Grid.ColumnSpan="3" />
|
||||
Grid.ColumnSpan="4" />
|
||||
<Border x:Name="Overlay"
|
||||
Background="#40000000"
|
||||
Visibility="Collapsed"
|
||||
Panel.ZIndex="10"
|
||||
Grid.RowSpan="2"
|
||||
Grid.ColumnSpan="4" />
|
||||
</Grid>
|
||||
</materialDesign:DialogHost>
|
||||
|
||||
@ -325,7 +325,7 @@
|
||||
Margin="0,0,0,0"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Bottom"
|
||||
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.Program.Parameters}"
|
||||
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.Program.Parameters}"
|
||||
SelectedValue="{Binding VariableName}"
|
||||
SelectedValuePath="Name"
|
||||
Visibility="{Binding Category, Converter={StaticResource ParameterCategoryToVisibilityConverter}, ConverterParameter=Inverse}">
|
||||
|
||||
12
Common/PubEvent/ParamsChangedEvent.cs
Normal file
12
Common/PubEvent/ParamsChangedEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class ParamsChangedEvent:PubSubEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
12
Common/PubEvent/UpdateIconEvent.cs
Normal file
12
Common/PubEvent/UpdateIconEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class UpdateIconEvent: PubSubEvent<string>
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -13,22 +13,23 @@ namespace Logger
|
||||
{
|
||||
public static readonly ILogger Logger = LogManager.GetLogger("InfoLogger");
|
||||
public static readonly ILogger sqlLogger = LogManager.GetLogger("SqlLogger");
|
||||
// 日志事件,UI可以订阅
|
||||
|
||||
public static event Action<string, string>? LogAdded;
|
||||
|
||||
public static void InfoWithNotify(string message)
|
||||
public static IProgress<(string message, string color,int depth)> Progress { get; set; }
|
||||
static LoggerHelper()
|
||||
{
|
||||
Progress = new Progress<(string message, string color, int depth)>();
|
||||
}
|
||||
public static void InfoWithNotify(string message, int depth=0)
|
||||
{
|
||||
Logger.Info(message); // 写入 NLog
|
||||
NotifyUI(message, "lightblue"); // 触发UI显示
|
||||
NotifyUI(message, "blue", depth); // 触发UI显示
|
||||
}
|
||||
|
||||
public static void SuccessWithNotify(string message)
|
||||
public static void SuccessWithNotify(string message, int depth=0)
|
||||
{
|
||||
Logger.Info(message);
|
||||
NotifyUI(message, "lightgreen");
|
||||
NotifyUI(message, "lightgreen", depth);
|
||||
}
|
||||
public static void WarnWithNotify(string message, string stackTrace = null)
|
||||
public static void WarnWithNotify(string message, string stackTrace = null, int depth = 0)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stackTrace))
|
||||
{
|
||||
@ -37,10 +38,10 @@ namespace Logger
|
||||
}
|
||||
|
||||
Logger.Warn(message);
|
||||
NotifyUI(message, "orange");
|
||||
NotifyUI(message, "orange", depth);
|
||||
}
|
||||
|
||||
public static void ErrorWithNotify(string message, string stackTrace = null)
|
||||
public static void ErrorWithNotify(string message, string stackTrace = null, int depth = 0)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stackTrace))
|
||||
{
|
||||
@ -49,37 +50,11 @@ namespace Logger
|
||||
}
|
||||
|
||||
Logger.Error(message);
|
||||
NotifyUI(message, "red");
|
||||
NotifyUI(message, "red", depth);
|
||||
}
|
||||
public static void InfoWithNotify(string message,int depth)
|
||||
private static void NotifyUI(string message, string color, int depth)
|
||||
{
|
||||
Logger.Info(message); // 写入 NLog
|
||||
NotifyUI(message, "lightblue"); // 触发UI显示
|
||||
}
|
||||
|
||||
public static void SuccessWithNotify(string message, int depth )
|
||||
{
|
||||
Logger.Info(message);
|
||||
NotifyUI(message, "lightgreen");
|
||||
}
|
||||
public static void WarnWithNotify(string message, int depth )
|
||||
{
|
||||
|
||||
|
||||
Logger.Warn(message);
|
||||
NotifyUI(message, "orange");
|
||||
}
|
||||
|
||||
public static void ErrorWithNotify(string message, int depth )
|
||||
{
|
||||
|
||||
|
||||
Logger.Error(message);
|
||||
NotifyUI(message, "red");
|
||||
}
|
||||
private static void NotifyUI(string message, string color)
|
||||
{
|
||||
LogAdded?.Invoke(message,color);
|
||||
Progress.Report((message, color, depth));
|
||||
}
|
||||
// 解析堆栈,找到项目文件路径和行号
|
||||
public static string GetProjectStackLine(string stackTrace)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user