diff --git a/PMSWPF.Tests/NotificationHelperTests.cs b/PMSWPF.Tests/NotificationHelperTests.cs new file mode 100644 index 0000000..d76f8b8 --- /dev/null +++ b/PMSWPF.Tests/NotificationHelperTests.cs @@ -0,0 +1,99 @@ +using NLog; +using NLog.Config; +using NLog.Targets; +using NUnit.Framework; +using PMSWPF.Helper; +using System; +using System.Linq; + +namespace PMSWPF.Tests +{ + [TestFixture] + public class NotificationHelperTests + { + private MemoryTarget _memoryTarget; + // private Logger _logger; // 声明一个 Logger 变量 - 这个不再需要了 + + [SetUp] + public void Setup() + { + // 1. 加载外部的 nlog.config 文件 + LogManager.LoadConfiguration("nlog.config"); + + // 2. 获取当前加载的配置 + var config = LogManager.Configuration; + + // 3. 创建 MemoryTarget + _memoryTarget = new MemoryTarget("testMemoryTarget") + { + // 捕获消息、级别、异常和 MDC 数据 + Layout + = "${message}|${level}|${exception:format=tostring}|${mdlc:item=CallerFilePath}|${mdlc:item=CallerParentLineNumber}" + }; + + // 4. 将 MemoryTarget 添加到配置中 + config.AddTarget(_memoryTarget); + + // 5. 定义一个规则,将所有日志路由到 MemoryTarget + // 注意:这里我们添加一个新的规则,确保日志也发送到 MemoryTarget + config.AddRule(LogLevel.Trace, LogLevel.Fatal, _memoryTarget); + + // 6. 重新应用配置,以包含新的 MemoryTarget 和规则 + LogManager.Configuration = config; + + // 7. 清空 MemoryTarget 中的日志 + _memoryTarget.Logs.Clear(); + } + + [TearDown] + public void Teardown() + { + // 在每个测试结束后,重置 NLog 配置,避免影响其他测试 + LogManager.Configuration = null; + // 清除 _memoryTarget 引用,以满足静态分析工具的建议 + _memoryTarget.Dispose(); + _memoryTarget = null; + } + + [Test] + public void ShowException_ShouldLogErrorWithExceptionAndCallerInfo() + { + // Arrange + // var testMessage = "这是一个测试异常消息"; + // var innerException = new InvalidOperationException("内部操作失败"); + // var testException = new Exception("外部异常", innerException); + // var expectedCallerFilePath = "D:\\CShap\\PMSWPF\\Tests\\NotificationHelperTests.cs"; // 模拟调用文件路径 + // var expectedCallerLineNumber = 49; // 模拟调用行号 (根据实际测试代码行数调整) + + // Act + // 调用 ShowException 方法,并传入模拟的异常和调用信息 + // NotificationHelper.ShowException(testMessage, testException, expectedCallerFilePath, expectedCallerLineNumber); + + NlogHelper.Info("info"); + NlogHelper.Warn("warn"); + NlogHelper.Trace("trace"); + NlogHelper.Error("hello"); + + // Assert + Assert.That(_memoryTarget.Logs.Count, Is.EqualTo(1), "应该只记录一条日志"); + + var logEntry = _memoryTarget.Logs[0]; + + // 验证日志消息 + // Assert.That(logEntry, Does.Contain(testMessage), "日志消息应该包含测试消息"); + // + // // 验证日志级别 + // Assert.That(logEntry, Does.Contain("|Error|"), "日志级别应该是 Error"); + // + // // 验证异常信息 + // Assert.That(logEntry, Does.Contain(testException.Message), "日志应该包含外部异常消息"); + // Assert.That(logEntry, Does.Contain(innerException.Message), "日志应该包含内部异常消息"); + // Assert.That(logEntry, Does.Contain(nameof(InvalidOperationException)), "日志应该包含内部异常类型"); + // Assert.That(logEntry, Does.Contain(nameof(Exception)), "日志应该包含外部异常类型"); + // + // // 验证 CallerFilePath 和 CallerParentLineNumber + // Assert.That(logEntry, Does.Contain($"|{expectedCallerFilePath}|"), "日志应该包含 CallerFilePath"); + // Assert.That(logEntry, Does.Contain($"|{expectedCallerLineNumber}"), "日志应该包含 CallerParentLineNumber"); + } + } +} \ No newline at end of file diff --git a/ViewModels/DevicesViewModel.cs b/ViewModels/DevicesViewModel.cs index 870521a..fa4f185 100644 --- a/ViewModels/DevicesViewModel.cs +++ b/ViewModels/DevicesViewModel.cs @@ -77,8 +77,7 @@ public partial class DevicesViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"添加设备的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"添加设备的过程中发生错误:{e}"); + NotificationHelper.ShowError($"添加设备的过程中发生错误:{e.Message}", e); } } @@ -112,8 +111,7 @@ public partial class DevicesViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"删除设备的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"删除设备的过程中发生错误:{e}"); + NotificationHelper.ShowError($"删除设备的过程中发生错误:{e.Message}", e); } } @@ -146,8 +144,7 @@ public partial class DevicesViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"编辑设备的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"编辑设备的过程中发生错误:{e}"); + NotificationHelper.ShowError($"编辑设备的过程中发生错误:{e.Message}", e); } } } \ No newline at end of file diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 51b4613..96f1eca 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -134,9 +134,7 @@ public partial class MainViewModel : ViewModelBase catch (Exception e) { await db.RollbackTranAsync(); - // 捕获并记录所有未预料的异常 - _logger.LogError($"添加变量表时出现了未预期的错误:{e}"); - NotificationHelper.ShowMessage($"添加变量表时出现了错误:{e.Message}", NotificationType.Error); + NotificationHelper.ShowError($"添加变量表时出现了错误:{e.Message}", e); } } @@ -198,8 +196,7 @@ public partial class MainViewModel : ViewModelBase } catch (Exception e) { - _logger.LogError($"菜单切换是出现了错误:{e}"); - NotificationHelper.ShowMessage($"菜单切换是出现了错误:{e.Message}", NotificationType.Error); + NotificationHelper.ShowError($"菜单切换时出现了错误:{e.Message}", e); } } } \ No newline at end of file diff --git a/ViewModels/MqttsViewModel.cs b/ViewModels/MqttsViewModel.cs index 2b4ac6d..4d6ad2d 100644 --- a/ViewModels/MqttsViewModel.cs +++ b/ViewModels/MqttsViewModel.cs @@ -70,8 +70,7 @@ public partial class MqttsViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"添加MQTT的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"添加MQTT的过程中发生错误:{e}"); + NotificationHelper.ShowError($"添加MQTT的过程中发生错误:{e.Message}", e); } } @@ -98,8 +97,7 @@ public partial class MqttsViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"删除MQTT的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"删除MQTT的过程中发生错误:{e}"); + NotificationHelper.ShowError($"删除MQTT的过程中发生错误:{e.Message}", e); } } @@ -123,8 +121,7 @@ public partial class MqttsViewModel : ViewModelBase } catch (Exception e) { - NotificationHelper.ShowMessage($"编辑MQTT的过程中发生错误:{e.Message}", NotificationType.Error); - _logger.LogError($"编辑MQTT的过程中发生错误:{e}"); + NotificationHelper.ShowError($"编辑MQTT的过程中发生错误:{e.Message}", e); } } diff --git a/ViewModels/VariableTableViewModel.cs b/ViewModels/VariableTableViewModel.cs index 8dfa127..fa74ed7 100644 --- a/ViewModels/VariableTableViewModel.cs +++ b/ViewModels/VariableTableViewModel.cs @@ -140,9 +140,7 @@ partial class VariableTableViewModel : ViewModelBase } catch (Exception e) { - string msg = $"编辑变量的过程中发生了不可预期的错误:"; - Logger.Error(msg + e); - NotificationHelper.ShowMessage(msg + e.Message, NotificationType.Error); + NotificationHelper.ShowError($"编辑变量的过程中发生了不可预期的错误:{e.Message}", e); } } @@ -182,9 +180,7 @@ partial class VariableTableViewModel : ViewModelBase } catch (Exception e) { - string msg = $"从TIA导入变量的过程中发生了不可预期的错误:"; - Logger.Error(msg + e); - NotificationHelper.ShowMessage(msg + e.Message, NotificationType.Error); + NotificationHelper.ShowError($"从TIA导入变量的过程中发生了不可预期的错误:{e.Message}", e); } @@ -211,9 +207,7 @@ partial class VariableTableViewModel : ViewModelBase } catch (Exception e) { - string msg = $"添加变量的过程中发生了不可预期的错误:"; - Logger.Error(msg + e); - NotificationHelper.ShowMessage(msg + e.Message, NotificationType.Error); + NotificationHelper.ShowError($"添加变量的过程中发生了不可预期的错误:{e.Message}", e); } } @@ -253,9 +247,7 @@ partial class VariableTableViewModel : ViewModelBase } catch (Exception e) { - string msg = $"删除变量的过程中发生了不可预期的错误:"; - Logger.Error(msg + e); - NotificationHelper.ShowMessage(msg + e.Message, NotificationType.Error); + NotificationHelper.ShowError($"删除变量的过程中发生了不可预期的错误:{e.Message}", e); } } @@ -319,8 +311,7 @@ partial class VariableTableViewModel : ViewModelBase } catch (Exception ex) { - Logger.Error(ex, "添加MQTT服务器到变量时发生错误。"); - NotificationHelper.ShowMessage($"添加MQTT服务器失败: {ex.Message}", NotificationType.Error); + NotificationHelper.ShowError($"添加MQTT服务器失败: {ex.Message}", ex); } } diff --git a/Views/Dialogs/MqttSelectionDialog.xaml.cs b/Views/Dialogs/MqttSelectionDialog.xaml.cs new file mode 100644 index 0000000..d7e0909 --- /dev/null +++ b/Views/Dialogs/MqttSelectionDialog.xaml.cs @@ -0,0 +1,30 @@ +using iNKORE.UI.WPF.Modern.Controls; +using PMSWPF.Models; +using PMSWPF.ViewModels.Dialogs; + +namespace PMSWPF.Views.Dialogs; + +public partial class MqttSelectionDialog : ContentDialog +{ + public MqttSelectionDialog(MqttSelectionDialogViewModel viewModel) + { + InitializeComponent(); + DataContext = viewModel; + } + + private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + // 在这里可以添加一些验证逻辑,例如确保选择了MQTT服务器 + var viewModel = (MqttSelectionDialogViewModel)DataContext; + if (viewModel.SelectedMqtt == null) + { + args.Cancel = true; // 取消关闭对话框 + // 可以显示一个警告消息 + } + } + + private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + // 用户点击取消,不需要额外处理 + } +} \ No newline at end of file diff --git a/Views/Dialogs/PollLevelDialog.xaml.cs b/Views/Dialogs/PollLevelDialog.xaml.cs new file mode 100644 index 0000000..cbef3dd --- /dev/null +++ b/Views/Dialogs/PollLevelDialog.xaml.cs @@ -0,0 +1,14 @@ +using iNKORE.UI.WPF.Modern.Controls; +using PMSWPF.ViewModels.Dialogs; + +namespace PMSWPF.Views.Dialogs +{ + public partial class PollLevelDialog : ContentDialog + { + public PollLevelDialog(PollLevelDialogViewModel viewModel) + { + InitializeComponent(); + DataContext = viewModel; + } + } +} diff --git a/Views/MqttServerDetailView.xaml.cs b/Views/MqttServerDetailView.xaml.cs new file mode 100644 index 0000000..a9533be --- /dev/null +++ b/Views/MqttServerDetailView.xaml.cs @@ -0,0 +1,19 @@ +using System.Windows.Controls; +using Microsoft.Extensions.DependencyInjection; +using PMSWPF.ViewModels; + +namespace PMSWPF.Views +{ + /// + /// MqttServerDetailView.xaml 的交互逻辑 + /// + public partial class MqttServerDetailView : UserControl + { + + public MqttServerDetailView() + { + InitializeComponent(); + } + + } +}