log日志bug修改
This commit is contained in:
@@ -59,6 +59,10 @@ namespace ADP
|
||||
}
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// 配置全局日志分发器:按 CurrentScope 路由到对应 LogArea
|
||||
var globalInfo = Container.Resolve<GlobalInfo>();
|
||||
LoggerHelper.Progress = new ScopeLogDispatcher(globalInfo);
|
||||
|
||||
//初始化数据库
|
||||
//DatabaseConfig.SetTenant(10001);
|
||||
//DatabaseConfig.InitMySql("127.0.0.1",3306,"ADP","root","123456");
|
||||
|
||||
@@ -6,6 +6,7 @@ using Notifications.Wpf.Core;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
@@ -226,7 +227,7 @@ namespace ADP.ViewModels
|
||||
if (targetContext.RunState == "运行")
|
||||
{
|
||||
targetContext.SingleStep = false;
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 执行工位 [{runningScope}] 运行命令");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 运行命令");
|
||||
|
||||
targetContext.RunState = "暂停";
|
||||
targetContext.RunIcon = PackIconKind.Pause;
|
||||
@@ -252,7 +253,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"工位 [{runningScope}] 异常中止: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 异常中止: {ex.Message}");
|
||||
}
|
||||
|
||||
// 💡 测试正常完毕或取消:停止当前工位的 SW,并将最终时间固化到 RunningTime 字段中
|
||||
@@ -285,7 +286,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
else // 用户点击了暂停
|
||||
{
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 点击工位 [{runningScope}] 暂停命令");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 点击工位 [{runningScope}] 暂停命令");
|
||||
targetContext.SingleStep = true;
|
||||
targetContext.IsStop = true;
|
||||
targetContext.RunState = "运行";
|
||||
@@ -308,7 +309,7 @@ namespace ADP.ViewModels
|
||||
if (targetContext.RunState == "运行")
|
||||
{
|
||||
targetContext.SingleStep = true;
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 执行工位 [{runningScope}] 单步执行命令");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 单步执行命令");
|
||||
|
||||
targetContext.RunState = "暂停";
|
||||
targetContext.RunIcon = PackIconKind.Pause;
|
||||
@@ -334,7 +335,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"工位 [{runningScope}] 单步执行异常: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 单步执行异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 💡 单步单步完成后会被 StepRunning 挂起,在此暂时停止 SW
|
||||
@@ -378,7 +379,7 @@ namespace ADP.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 执行工位 [{runningScope}] 复位命令");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 复位命令");
|
||||
|
||||
_executionTasks.TryGetValue(runningScope, out var currentTask);
|
||||
_errorExecutionTasks.TryGetValue(runningScope, out var errorTask);
|
||||
@@ -428,7 +429,7 @@ namespace ADP.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 执行工位 [{runningScope}] 异常流程命令");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 异常流程命令");
|
||||
|
||||
// 💡 异常测试启动计时
|
||||
targetContext.SW.Start();
|
||||
@@ -445,7 +446,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"工位 [{runningScope}] 异常流程执行出错: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 异常流程执行出错: {ex.Message}");
|
||||
}
|
||||
|
||||
// 💡 异常测试结束停止计时
|
||||
@@ -479,7 +480,7 @@ namespace ADP.ViewModels
|
||||
{
|
||||
CurrentConfig.DefaultProgramFilePath = targetContext.CurrentFilePath;
|
||||
ConfigService.Save(CurrentConfig);
|
||||
LoggerHelper.SuccessWithNotify($"工位 [{runningScope}] 已成功将当前程序设为默认启动程序");
|
||||
LoggerHelper.SuccessWithNotify(runningScope, $"工位 [{runningScope}] 已成功将当前程序设为默认启动程序");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +506,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
targetContext.Program.Parameters.Add(item);
|
||||
}
|
||||
LoggerHelper.InfoWithNotify($"工位 [{runningScope}] 创建了空程序文件");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"工位 [{runningScope}] 创建了空程序文件");
|
||||
|
||||
// 如果当前正看着该工位,刷新 UI 显示
|
||||
if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
|
||||
@@ -539,7 +540,7 @@ namespace ADP.ViewModels
|
||||
// 确认文件存在
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"文件不存在: {filePath}");
|
||||
LoggerHelper.ErrorWithNotify(runningScope, $"文件不存在: {filePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -551,7 +552,7 @@ namespace ADP.ViewModels
|
||||
|
||||
if (program == null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"文件格式不正确或为空: {filePath}");
|
||||
LoggerHelper.WarnWithNotify(runningScope, $"文件格式不正确或为空: {filePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -571,7 +572,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
LoggerHelper.SuccessWithNotify($"工位 [{runningScope}] 成功打开文件: {filePath}");
|
||||
LoggerHelper.SuccessWithNotify(runningScope, $"工位 [{runningScope}] 成功打开文件: {filePath}");
|
||||
|
||||
// 💡 3. 安全调用异步复位,确保重置的是对应工位的数据
|
||||
// 注意:由于在 OnRestoration 内部第一行也做了快照拦截,
|
||||
@@ -580,7 +581,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"工位 [{runningScope}] 打开文件失败: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 打开文件失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -619,7 +620,7 @@ namespace ADP.ViewModels
|
||||
// 💡 3. 调用你的底层文件保存逻辑,传入快照工位的 Program 模型
|
||||
SaveProgramToFile(targetContext.CurrentFilePath, targetContext.Program);
|
||||
|
||||
LoggerHelper.InfoWithNotify($"{_globalInfo.UserName} 另存为文件成功: {saveFileDialog.FileName}");
|
||||
LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 另存为文件成功: {saveFileDialog.FileName}");
|
||||
|
||||
if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
|
||||
}
|
||||
@@ -644,7 +645,7 @@ namespace ADP.ViewModels
|
||||
|
||||
// 💡 3. 持久化当前快照工位的 Program
|
||||
SaveProgramToFile(targetContext.CurrentFilePath, targetContext.Program);
|
||||
LoggerHelper.SuccessWithNotify($"工位 [{runningScope}] 程序保存成功!");
|
||||
LoggerHelper.SuccessWithNotify(_globalInfo.CurrentScope,$"工位 [{runningScope}] 程序保存成功!");
|
||||
}
|
||||
|
||||
// 💡 辅助方法:建议将你的通用序列化落盘代码调整为接收 ProgramVM 参数,提高复用性
|
||||
@@ -657,7 +658,7 @@ namespace ADP.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"写入程序文件失败: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope,$"写入程序文件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,4 +10,10 @@
|
||||
<PackageReference Include="NLog" Version="6.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Nlog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -12,23 +12,23 @@ namespace Logger
|
||||
{
|
||||
public static readonly ILogger Logger = LogManager.GetLogger("InfoLogger");
|
||||
public static readonly ILogger sqlLogger = LogManager.GetLogger("SqlLogger");
|
||||
public static IProgress<(string message, string color, int depth)> Progress { get; set; }
|
||||
public static IProgress<(string scope, string message, string color, int depth)> Progress { get; set; }
|
||||
static LoggerHelper()
|
||||
{
|
||||
Progress = new Progress<(string message, string color, int depth)>();
|
||||
Progress = new Progress<(string scope, string message, string color, int depth)>();
|
||||
}
|
||||
public static void InfoWithNotify(string message, int depth = 0)
|
||||
{
|
||||
Logger.Info(message); // 写入 NLog
|
||||
NotifyUI(message, "blue", depth); // 触发UI显示
|
||||
}
|
||||
|
||||
public static void SuccessWithNotify(string message, int depth = 0)
|
||||
public static void InfoWithNotify(string scope, string message, int depth = 0)
|
||||
{
|
||||
Logger.Info(message);
|
||||
NotifyUI(message, "lightgreen", depth);
|
||||
NotifyUI(scope, message, "blue", depth);
|
||||
}
|
||||
public static void WarnWithNotify(string message, string stackTrace = null, int depth = 0)
|
||||
|
||||
public static void SuccessWithNotify(string scope, string message, int depth = 0)
|
||||
{
|
||||
Logger.Info(message);
|
||||
NotifyUI(scope, message, "lightgreen", depth);
|
||||
}
|
||||
public static void WarnWithNotify(string scope, string message, string stackTrace = null, int depth = 0)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stackTrace))
|
||||
{
|
||||
@@ -37,10 +37,10 @@ namespace Logger
|
||||
}
|
||||
|
||||
Logger.Warn(message);
|
||||
NotifyUI(message, "orange", depth);
|
||||
NotifyUI(scope, message, "orange", depth);
|
||||
}
|
||||
|
||||
public static void ErrorWithNotify(string message, string stackTrace = null, int depth = 0)
|
||||
public static void ErrorWithNotify(string scope, string message, string stackTrace = null, int depth = 0)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stackTrace))
|
||||
{
|
||||
@@ -49,11 +49,11 @@ namespace Logger
|
||||
}
|
||||
|
||||
Logger.Error(message);
|
||||
NotifyUI(message, "red", depth);
|
||||
NotifyUI(scope, message, "red", depth);
|
||||
}
|
||||
private static void NotifyUI(string message, string color, int depth)
|
||||
private static void NotifyUI(string scope, string message, string color, int depth)
|
||||
{
|
||||
Progress.Report((message, color, depth));
|
||||
Progress.Report((scope, message, color, depth));
|
||||
}
|
||||
|
||||
public static void Info(string message, int depth = 0)
|
||||
@@ -95,20 +95,18 @@ namespace Logger
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
// 匹配你项目的命名空间路径
|
||||
if (line.Contains("ADP"))
|
||||
{
|
||||
// 提取 "in 文件路径:line 行号"
|
||||
var match = Regex.Match(line, @"in (.+?):line (\d+)");
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Value; // 返回类似 C:\...\MainViewModel.cs:line 37
|
||||
return match.Value;
|
||||
}
|
||||
return line.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return lines[0].Trim(); // 如果找不到就返回第一条
|
||||
return lines[0].Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace MainModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LoggerHelper.ErrorWithNotify($"卸载机台 [{TestStatus}] 全局引用或资源失败: {ex.Message}");
|
||||
Logger.LoggerHelper.ErrorWithNotify(TestStatus, $"卸载机台 [{TestStatus}] 全局引用或资源失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -164,7 +164,7 @@ namespace MainModule.ViewModels
|
||||
|
||||
if (program == null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"文件格式不正确或为空: {filePath}");
|
||||
LoggerHelper.WarnWithNotify(_globalInfo.CurrentScope, $"文件格式不正确或为空: {filePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace MonitorModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"加载数据表失败:{ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope,$"加载数据表失败:{ex.Message}");
|
||||
StatusMessage = $"加载失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ namespace MonitorModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"查询失败:{ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(TestStatus,$"查询失败:{ex.Message}");
|
||||
StatusMessage = $"查询失败:{ex.Message}";
|
||||
ResultTable = new DataTable();
|
||||
TotalCount = 0;
|
||||
@@ -295,11 +295,11 @@ namespace MonitorModule.ViewModels
|
||||
WriteCsv(dlg.FileName, dt);
|
||||
|
||||
StatusMessage = $"导出完成:{dlg.FileName}({dt.Rows.Count} 行)";
|
||||
LoggerHelper.InfoWithNotify($"工位 [{TestStatus}] 导出 [{SelectedTable}] 至 {dlg.FileName},共 {dt.Rows.Count} 行");
|
||||
LoggerHelper.InfoWithNotify(TestStatus, $"工位 [{TestStatus}] 导出 [{SelectedTable}] 至 {dlg.FileName},共 {dt.Rows.Count} 行");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"导出失败:{ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(TestStatus, $"导出失败:{ex.Message}");
|
||||
StatusMessage = $"导出失败:{ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace SettingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LoggerHelper.ErrorWithNotify($"释放配置管理组件(SettingViewModel)资源失败: {ex.Message}");
|
||||
Logger.LoggerHelper.ErrorWithNotify(TestStatus,$"释放配置管理组件(SettingViewModel)资源失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
|
||||
LoggerHelper.WarnWithNotify(_globalInfo.CurrentScope, $"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"加载子程序错误: {filePath} - {ex.Message}");
|
||||
LoggerHelper.WarnWithNotify(_globalInfo.CurrentScope, $"加载子程序错误: {filePath} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,7 +317,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"加载类型错误: {assembly.FullName} - {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"加载类型错误: {assembly.FullName} - {ex.Message}");
|
||||
}
|
||||
|
||||
if (validTypes.Count > 0)
|
||||
@@ -504,7 +504,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加方法失败: {method.Name} - {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"添加方法失败: {method.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加子程序失败: {subProgram.Name} - {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"添加子程序失败: {subProgram.Name} - {ex.Message}"); ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
using UIShare.GlobalVariable;
|
||||
using Logger;
|
||||
using Prism.Ioc;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
public class LogAreaViewModel : NavigateViewModelBase, IDisposable
|
||||
{
|
||||
|
||||
|
||||
// 日志集合
|
||||
private ObservableCollection<LogItem> _logs = new();
|
||||
|
||||
@@ -23,20 +25,23 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
public ICommand ClearLogCommand { get; set; }
|
||||
|
||||
private readonly ScopedContext _scopedContext;
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
private IProgress<(string Message, Brush Color, int Depth)>? _logProgress;
|
||||
|
||||
public LogAreaViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
ClearLogCommand = new DelegateCommand(ClearLog);
|
||||
_scopedContext = containerProvider.Resolve<ScopedContext>();
|
||||
_globalInfo = containerProvider.Resolve<GlobalInfo>();
|
||||
|
||||
// 2. 保持原有逻辑,但请确保在 Dispose 中对其进行清理
|
||||
LoggerHelper.Progress = new System.Progress<(string message, string color, int depth)>(
|
||||
log =>
|
||||
{
|
||||
// 增加防御性代码:防止进入销毁流程时异步回调引发空引用异常
|
||||
if (Logs == null) return;
|
||||
|
||||
var brush = (Brush)new BrushConverter().ConvertFromString(log.color);
|
||||
Logs.Add(new LogItem(log.message, brush, log.depth));
|
||||
});
|
||||
// 创建本作用域专属的日志接收器并注册到 ScopedContext
|
||||
_logProgress = new Progress<(string Message, Brush Color, int Depth)>(log =>
|
||||
{
|
||||
if (Logs == null) return;
|
||||
Logs.Add(new LogItem(log.Message, log.Color, log.Depth));
|
||||
});
|
||||
_scopedContext.LogProgress = _logProgress;
|
||||
}
|
||||
|
||||
private void ClearLog()
|
||||
@@ -51,16 +56,22 @@ namespace TestingModule.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
LoggerHelper.Progress = null!;
|
||||
// 注销本作用域的日志接收器,避免 Dispose 后仍收到旧消息
|
||||
if (_scopedContext != null && _scopedContext.LogProgress == _logProgress)
|
||||
{
|
||||
_scopedContext.LogProgress = null;
|
||||
}
|
||||
_logProgress = null;
|
||||
|
||||
if (Logs != null)
|
||||
{
|
||||
Logs.Clear();
|
||||
Logs = null!;
|
||||
Logs = null!;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LoggerHelper.ErrorWithNotify($"释放日志组件(LogAreaViewModel)资源失败: {ex.Message}");
|
||||
Logger.LoggerHelper.ErrorWithNotify(_scopedContext != null ? _globalInfo.CurrentScope : "", $"释放日志组件(LogAreaViewModel)资源失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"打开设备编辑窗口 [{type}] 失败:{ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope, $"打开设备编辑窗口 [{type}] 失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
#endregion
|
||||
private ScopedContext _ScopedContext;
|
||||
private GlobalInfo _globalInfo;
|
||||
#region 命令
|
||||
public ICommand CancelEditCommand { get; set; }
|
||||
public ICommand SaveStepCommand { get; set; }
|
||||
@@ -54,6 +55,7 @@ namespace TestingModule.ViewModels
|
||||
public SingleStepEditViewModel(IContainerProvider containerProvider, ScopedContext scopedContext) : base(containerProvider)
|
||||
{
|
||||
_ScopedContext = scopedContext;
|
||||
_globalInfo=containerProvider.Resolve<GlobalInfo>();
|
||||
_eventAggregator.GetEvent<EditSetpEvent>().Subscribe(EditSingleStep);
|
||||
CancelEditCommand = new DelegateCommand(CancelEdit);
|
||||
SaveStepCommand = new DelegateCommand(SaveStep);
|
||||
@@ -100,7 +102,7 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
catch
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("循环指令参数设置错误:类型转换失败");
|
||||
LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope,"循环指令参数设置错误:类型转换失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace UIShare.GlobalVariable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"格子 [{title}] 配置加载失败: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(title, $"格子 [{title}] 配置加载失败: {ex.Message}");
|
||||
return new SystemConfig { Title = title };
|
||||
}
|
||||
}
|
||||
@@ -90,11 +90,11 @@ namespace UIShare.GlobalVariable
|
||||
});
|
||||
|
||||
File.WriteAllText(configPath, json);
|
||||
LoggerHelper.InfoWithNotify($"配置 [{config.Title}] 已保存。");
|
||||
LoggerHelper.InfoWithNotify(config.Title, $"配置 [{config.Title}] 已保存。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"配置 [{config.Title}] 保存失败: {ex.Message}");
|
||||
LoggerHelper.ErrorWithNotify(config.Title, $"配置 [{config.Title}] 保存失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace UIShare.GlobalVariable
|
||||
catch (Exception ex)
|
||||
{
|
||||
var inner = ex.InnerException?.Message ?? ex.Message;
|
||||
LoggerHelper.ErrorWithNotify($"设备 [{config.DeviceName}] 实例化失败:{inner}");
|
||||
LoggerHelper.ErrorWithNotify(_scopeName, $"设备 [{config.DeviceName}] 实例化失败:{inner}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,7 +288,7 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
if (info != null) info.IsConnected = false;
|
||||
var inner = ex.InnerException?.Message ?? ex.Message;
|
||||
LoggerHelper.ErrorWithNotify($"设备 [{name}/{conn}] 连接异常:{inner}");
|
||||
LoggerHelper.ErrorWithNotify(_scopeName, $"设备 [{name}/{conn}] 连接异常:{inner}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
41
UIShare/GlobalVariable/ScopeLogDispatcher.cs
Normal file
41
UIShare/GlobalVariable/ScopeLogDispatcher.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Logger;
|
||||
using System;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace UIShare.GlobalVariable
|
||||
{
|
||||
/// <summary>
|
||||
/// 作用域日志分发器:根据显式传入的 scope 参数把日志路由到对应
|
||||
/// <see cref="ScopedContext.LogProgress"/>,实现每个台架/作用域拥有独立 LogArea。
|
||||
/// </summary>
|
||||
public class ScopeLogDispatcher : IProgress<(string scope, string message, string color, int depth)>
|
||||
{
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
|
||||
public ScopeLogDispatcher(GlobalInfo globalInfo)
|
||||
{
|
||||
_globalInfo = globalInfo ?? throw new ArgumentNullException(nameof(globalInfo));
|
||||
}
|
||||
|
||||
public void Report((string scope, string message, string color, int depth) value)
|
||||
{
|
||||
var scope = value.scope;
|
||||
if (string.IsNullOrEmpty(scope)) return;
|
||||
|
||||
if (!_globalInfo.ContextDic.TryGetValue(scope, out var context)) return;
|
||||
if (context?.LogProgress == null) return;
|
||||
|
||||
Brush? brush = null;
|
||||
try
|
||||
{
|
||||
brush = (Brush)new BrushConverter().ConvertFromString(value.color);
|
||||
}
|
||||
catch
|
||||
{
|
||||
brush = Brushes.Black;
|
||||
}
|
||||
|
||||
context.LogProgress.Report((value.message, brush, value.depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using UIShare.UIViewModel;
|
||||
|
||||
namespace UIShare.GlobalVariable
|
||||
@@ -30,6 +31,10 @@ namespace UIShare.GlobalVariable
|
||||
public ParameterVM SelectedParameter { get; set; }
|
||||
|
||||
public List<IBaseInterface> DeviceList { get; set; } = new();
|
||||
|
||||
/// <summary>当前作用域的日志接收器,LogAreaViewModel 订阅此处实现按作用域隔离日志。</summary>
|
||||
public IProgress<(string Message, Brush Color, int Depth)>? LogProgress { get; set; }
|
||||
|
||||
// 【新增测试属性】:每个实例被 new 出来时独一无二的随机身份
|
||||
// 证 ID
|
||||
public int DebugRandomId { get; private set; }
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace UIShare
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("程序循环指令未闭合,请检查后重试");
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, "程序循环指令未闭合,请检查后重试");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ namespace UIShare
|
||||
};
|
||||
loopStack.Push(context);
|
||||
step.CurrentLoopCount = context.LoopCount;
|
||||
LoggerHelper.InfoWithNotify($"循环开始,共{context.LoopCount}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环开始,共{context.LoopCount}次", depth);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace UIShare
|
||||
{
|
||||
if (loopStack.Count == 0)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, "未匹配的循环结束指令", depth: depth);
|
||||
step.Result = 2;
|
||||
index++;
|
||||
continue;
|
||||
@@ -133,7 +133,7 @@ namespace UIShare
|
||||
{
|
||||
// 继续循环:跳转到循环开始后的第一条指令
|
||||
index = context.StartIndex + 1;
|
||||
LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,7 +141,7 @@ namespace UIShare
|
||||
loopStack.Pop();
|
||||
var loopStopwatch = loopStopwatchStack.Peek();
|
||||
index++;
|
||||
LoggerHelper.InfoWithNotify($"循环结束,共执行{context.LoopCount}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环结束,共执行{context.LoopCount}次", depth);
|
||||
if (depth == 0 && loopStopwatch.IsRunning)
|
||||
{
|
||||
loopStopwatch.Stop();
|
||||
@@ -168,7 +168,7 @@ namespace UIShare
|
||||
SubSingleStep = true;
|
||||
_scopedContext.SingleStep = false;
|
||||
}
|
||||
LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
|
||||
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
|
||||
UpdateCurrentStepResult(step, true, stepSuccess, depth);
|
||||
if (SubSingleStep)
|
||||
@@ -179,7 +179,7 @@ namespace UIShare
|
||||
}
|
||||
else if (step.Method != null)
|
||||
{
|
||||
LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
|
||||
await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken);
|
||||
stepSuccess = step.Result == 1;
|
||||
if (step.NGGotoStepID != null && !stepSuccess)
|
||||
@@ -188,7 +188,7 @@ namespace UIShare
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
if (step.OKGotoStepID != null && stepSuccess)
|
||||
@@ -197,7 +197,7 @@ namespace UIShare
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,7 +257,7 @@ namespace UIShare
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("程序循环指令未闭合,请检查后重试");
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, "程序循环指令未闭合,请检查后重试");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ namespace UIShare
|
||||
};
|
||||
loopStack.Push(context);
|
||||
step.CurrentLoopCount = context.LoopCount;
|
||||
LoggerHelper.InfoWithNotify($"循环开始({step.Name}),共{context.LoopCount}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环开始({step.Name}),共{context.LoopCount}次", depth);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace UIShare
|
||||
{
|
||||
if (loopStack.Count == 0)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth:depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, "未匹配的循环结束指令", depth:depth);
|
||||
step.Result = 2;
|
||||
index++;
|
||||
continue;
|
||||
@@ -302,7 +302,7 @@ namespace UIShare
|
||||
{
|
||||
// 继续循环:跳转到循环开始后的第一条指令
|
||||
index = context.StartIndex + 1;
|
||||
LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -310,7 +310,7 @@ namespace UIShare
|
||||
loopStack.Pop();
|
||||
var loopStopwatch = loopStopwatchStack.Peek();
|
||||
index++;
|
||||
LoggerHelper.InfoWithNotify($"循环结束,共执行{context.LoopCount}次", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"循环结束,共执行{context.LoopCount}次", depth);
|
||||
if (depth == 0 && loopStopwatch.IsRunning)
|
||||
{
|
||||
loopStopwatch.Stop();
|
||||
@@ -337,7 +337,7 @@ namespace UIShare
|
||||
SubSingleStep = true;
|
||||
_scopedContext.SingleStep = false;
|
||||
}
|
||||
LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
|
||||
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
|
||||
UpdateCurrentStepResult(step, true, stepSuccess, depth);
|
||||
if (SubSingleStep)
|
||||
@@ -348,7 +348,7 @@ namespace UIShare
|
||||
}
|
||||
else if (step.Method != null)
|
||||
{
|
||||
LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
|
||||
await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken);
|
||||
stepSuccess = step.Result == 1;
|
||||
if (step.NGGotoStepID != null && !stepSuccess)
|
||||
@@ -357,7 +357,7 @@ namespace UIShare
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
if (step.OKGotoStepID != null && stepSuccess)
|
||||
@@ -366,7 +366,7 @@ namespace UIShare
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,7 +408,7 @@ namespace UIShare
|
||||
}
|
||||
if (targetType == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
@@ -522,7 +522,7 @@ namespace UIShare
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth);
|
||||
LoggerHelper.WarnWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,7 +546,7 @@ namespace UIShare
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ namespace UIShare
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
}
|
||||
@@ -600,7 +600,7 @@ namespace UIShare
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
@@ -619,7 +619,7 @@ namespace UIShare
|
||||
paraResult = tmp.Item1;
|
||||
if (tmp.Item2 != null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify(tmp.Item2);
|
||||
LoggerHelper.WarnWithNotify(_systemConfig.Title, tmp.Item2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -628,19 +628,19 @@ namespace UIShare
|
||||
{
|
||||
if (!returnType.IsArray)
|
||||
{
|
||||
LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = {returnValue} ({returnType.Name})", depth);
|
||||
LoggerHelper.SuccessWithNotify(_systemConfig.Title, $"输出 [ {outputParam.Name} ] = {returnValue} ({returnType.Name})", depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (returnValue is IEnumerable enumerable)
|
||||
{
|
||||
var elements = enumerable.Cast<object>().Select(item => item?.ToString() ?? "null");
|
||||
LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = [ {string.Join(", ", elements)} ] ({returnType.Name})", depth);
|
||||
LoggerHelper.SuccessWithNotify(_systemConfig.Title, $"输出 [ {outputParam.Name} ] = [ {string.Join(", ", elements)} ] ({returnType.Name})", depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LoggerHelper.SuccessWithNotify($"指令 [ {step.Index} ] 执行成功", depth);
|
||||
LoggerHelper.SuccessWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行成功", depth);
|
||||
UpdateCurrentStepResult(step, paraResult: paraResult, depth: depth);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -649,7 +649,7 @@ namespace UIShare
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
LoggerHelper.ErrorWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
@@ -697,7 +697,7 @@ namespace UIShare
|
||||
step.Result = re ? 1 : 2;
|
||||
if (step.Result == 2)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth);
|
||||
LoggerHelper.WarnWithNotify(_systemConfig.Title, $"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,7 +705,7 @@ namespace UIShare
|
||||
{
|
||||
if (!paraResult)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify("参数限值校验失败", depth: depth);
|
||||
LoggerHelper.WarnWithNotify(_systemConfig.Title, "参数限值校验失败", depth: depth);
|
||||
}
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user