添加了NLog日志,并且配置了写入数据库,修改了Notification通知不使用依赖注入,而是使用Message的方式

This commit is contained in:
2025-06-23 13:42:02 +08:00
parent 32648ff89f
commit c978b92fff
17 changed files with 291 additions and 69 deletions

View File

@@ -3,6 +3,11 @@ using System.Data;
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using PMSWPF.Data;
using PMSWPF.Data.Entities;
using PMSWPF.Data.Repositories;
using PMSWPF.Services;
using PMSWPF.ViewModels;
@@ -21,59 +26,58 @@ namespace PMSWPF
public App()
{
var container = new ServiceCollection();
var nlog = LogManager.Setup().LoadConfigurationFromFile("Config/nlog.config").GetCurrentClassLogger();
container.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog();
});
container.AddSingleton<NavgatorServices>();
container.AddSingleton<DevicesRepositories>();
container.AddSingleton<IDeviceDialogService, DeviceDialogService>();
container.AddSingleton<INotificationService, GrowlNotificationService>();
container.AddSingleton<GrowlNotificationService>();
container.AddSingleton<MainViewModel>();
container.AddSingleton<HomeViewModel>();
container.AddSingleton<DevicesViewModel>();
container.AddSingleton<DataTransformViewModel>();
container.AddSingleton<MainView>(dp => new MainView()
{ DataContext = dp.GetRequiredService<MainViewModel>() });
container.AddSingleton<SettingViewModel>();
container.AddSingleton<SettingView>();
container.AddSingleton<MainView>();
container.AddSingleton<HomeView>();
container.AddSingleton<DevicesView>();
container.AddSingleton<DataTransformViewModel>();
Services = container.BuildServiceProvider();
// 启动服务
Services.GetRequiredService<GrowlNotificationService>();
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
CheckDb();
InitDB();
MainWindow = Services.GetRequiredService<MainView>();
MainWindow.Show();
}
private void CheckDb()
private void InitDB()
{
var _db = DbContext.GetInstance();
_db.DbMaintenance.CreateDatabase();
_db.CodeFirst.InitTables<DbNlog>();
_db.CodeFirst.InitTables<DbNlog>();
_db.CodeFirst.InitTables<DbDevice>();
_db.CodeFirst.InitTables<DbVariableTable>();
_db.CodeFirst.InitTables<DbDataVariable>();
_db.CodeFirst.InitTables<DbS7DataVariable>();
_db.CodeFirst.InitTables<DbUser>();
_db.CodeFirst.InitTables<DbMqtt>();
}
// [STAThread]
// static void Main(string[] args)
// {
// using IHost host = CreateHostBuilder(args).Build();
// host.Start();
// App app = new App();
// app.InitializeComponent();
// app.MainWindow = host.Services.GetRequiredService<MainView>();
// app.MainWindow.Visibility = Visibility.Visible;
// app.Run();
//
// }
//
// private static IHostBuilder CreateHostBuilder(string[] args)
// {
// return Host.CreateDefaultBuilder(args).ConfigureServices(services =>
// {
//
// services.AddHostedService<DemoBackgroundService>();
// services.AddSingleton<MainView>();
// services.AddSingleton<MainViewModel>();
// });
// }
}
}

60
Config/nlog.config Normal file
View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info"
internalLogFile="internal-nlog.txt">
<targets>
<!-- 文件日志 -->
<target name="logfile"
xsi:type="File"
fileName="logs/${shortdate}.log"
layout="${longdate}|ThreadID=${threadid}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}"
archiveFileName="logs/archives/{#}.log"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="30"/>
<!-- 控制台日志 -->
<target name="logconsole"
xsi:type="Console"
layout="${date:format=HH\:mm\:ss} ${level} ${message}"/>
<!-- SQL Server 目标 -->
<!-- 异步写入日志到数据库 -->
<target name="database"
xsi:type="Database"
dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
connectionString="server=127.0.0.1;port=3306;user=root;password=Pgw15221236646; database=pmswpf; ">
<commandText>
INSERT INTO nlog (
LogTime, Level, ThreadID,ThreadName,Callsite,CallsiteLineNumber,Message,
Logger, Exception
) VALUES (
@LogTime, @Level,@ThreadID,@ThreadName,@Callsite,@CallsiteLineNumber,@Message,
@Logger, @Exception
)
</commandText>
<!-- 参数映射 -->
<parameter name="@LogTime" layout="${date:format=yyyy-MM-dd HH\:mm\:ss}" />
<parameter name="@Level" layout="${level}" />
<parameter name="@ThreadID" layout="${threadid}" dbType="Int32"/>
<parameter name="@ThreadName" layout="${threadname}" />
<parameter name="@Message" layout="${message}" />
<parameter name="@Callsite" layout="${callsite}" />
<parameter name="@CallsiteLineNumber" layout="${callsite-linenumber}" />
<parameter name="@Logger" layout="${logger}" />
<parameter name="@Exception" layout="${exception:format=ToString}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logconsole"/>
<logger name="*" minlevel="Info" writeTo="logfile"/>
<!-- 路由日志到数据库 -->
<logger name="*" minlevel="Info" writeTo="database" />
</rules>
</nlog>

View File

@@ -2,7 +2,7 @@
namespace PMSWPF.Data.Entities;
[SugarTable("Mqtt")]
public class DbMqtt
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//数据库是自增才配自增

32
Data/Entities/DbNlog.cs Normal file
View File

@@ -0,0 +1,32 @@
using SqlSugar;
namespace PMSWPF.Data.Entities;
[SugarTable("nlog")]
public class DbNlog
{
// INSERT INTO [dbo].[NLog] (
// [Application], [Logged], [Level], [ThreadID],[Message],
// [Logger], [Callsite], [Exception], [Url], [Action], [User]
// ) VALUES (
// @Application, @Logged, @Level,@ThreadID, @Message,
// @Logger, @Callsite, @Exception, @Url, @Action, @User
// )
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//数据库是自增才配自增
public int Id { get; set; }
public DateTime LogTime { get; set; }
public string Level { get; set; }
public int ThreadID { get; set; }
[SugarColumn(IsNullable = true)]
public string ThreadName { get; set; }
public string Logger { get; set; }
public string Callsite { get; set; }
public int CallsiteLineNumber { get; set; }
public string Message { get; set; }
[SugarColumn(IsNullable = true,ColumnDataType = "text")]
public string Exception { get; set; }
}

View File

@@ -9,13 +9,23 @@ public class BaseRepositories
public BaseRepositories()
{
_db = DbContext.GetInstance();
_db.DbMaintenance.CreateDatabase();
CheckDbTables();
try
{
_db = DbContext.GetInstance();
// _db.DbMaintenance.CreateDatabase();
// CheckDbTables();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private void CheckDbTables()
{
if(!_db.DbMaintenance.IsAnyTable<DbNlog>())
_db.CodeFirst.InitTables<DbNlog>();
if(!_db.DbMaintenance.IsAnyTable<DbDevice>())
_db.CodeFirst.InitTables<DbDevice>();
if(!_db.DbMaintenance.IsAnyTable<DbVariableTable>())

View File

@@ -0,0 +1,14 @@
using CommunityToolkit.Mvvm.Messaging;
using PMSWPF.Enums;
using PMSWPF.Message;
namespace PMSWPF.Helper;
public class NotificationHelper
{
public static void ShowMessage(string msg, NotificationType notificationType=NotificationType.Info,bool isGlobal = false)
{
WeakReferenceMessenger.Default.Send<NotificationMessage>(
new NotificationMessage(msg, notificationType));
}
}

View File

@@ -0,0 +1,15 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
using PMSWPF.Enums;
namespace PMSWPF.Message;
public class NotificationMessage:ValueChangedMessage<string>
{
public NotificationType Type { get; set; }
public bool IsGlobal { get; set; }
public NotificationMessage(string msg,NotificationType type=NotificationType.Info,bool isGlobal=false) : base(msg)
{
this.Type = type;
this.IsGlobal = isGlobal;
}
}

View File

@@ -14,8 +14,16 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageReference Include="MySql.Data" Version="9.3.0" />
<PackageReference Include="NLog" Version="6.0.0" />
<PackageReference Include="NLog.Database" Version="6.0.0" />
<PackageReference Include="SqlSugarCore.MySql" Version="5.1.4.178" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.193" />
</ItemGroup>
<ItemGroup>
<None Update="Config\nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -1,11 +1,19 @@
using HandyControl.Controls;
using System.Windows.Interop;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using HandyControl.Controls;
using PMSWPF.Enums;
using PMSWPF.Message;
using Notification = PMSWPF.Models.Notification;
namespace PMSWPF.Services;
public class GrowlNotificationService : INotificationService
public class GrowlNotificationService :ObservableRecipient,IRecipient<NotificationMessage>
{
public GrowlNotificationService()
{
IsActive = true;
}
public void Show(Notification notification)
{
if (notification == null )
@@ -74,4 +82,9 @@ public class GrowlNotificationService : INotificationService
{
Show(new Notification(){Message = message,Type = type,IsGlobal = IsGlobal});
}
public void Receive(NotificationMessage message)
{
Show(message.Value,message.Type,message.IsGlobal);
}
}

6
Services/LogService.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace PMSWPF.Services;
public class LogService
{
}

View File

@@ -1,14 +1,17 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using HandyControl.Controls;
using HandyControl.Data;
using Microsoft.Extensions.Logging;
using PMSWPF.Data.Entities;
using PMSWPF.Data.Repositories;
using PMSWPF.Enums;
using PMSWPF.Excptions;
using PMSWPF.Extensions;
using PMSWPF.Helper;
using PMSWPF.Message;
using PMSWPF.Models;
using PMSWPF.Services;
using PMSWPF.ViewModels.Dialogs;
@@ -22,15 +25,16 @@ public partial class DevicesViewModel : ViewModelBase
{
private readonly IDeviceDialogService _deviceDialogService;
private readonly DevicesRepositories _devicesRepositories;
private readonly INotificationService _notificationService;
[ObservableProperty] private ObservableCollection<Device> _devices = new();
private readonly ILogger<DevicesViewModel> _logger;
[ObservableProperty]
private ObservableCollection<Device> _devices = new();
public DevicesViewModel(IDeviceDialogService deviceDialogService, DevicesRepositories devicesRepositories,
INotificationService notificationService)
public DevicesViewModel(IDeviceDialogService deviceDialogService, DevicesRepositories devicesRepositories,ILogger<DevicesViewModel> logger
)
{
_deviceDialogService = deviceDialogService;
_devicesRepositories = devicesRepositories;
_notificationService = notificationService;
_logger = logger;
}
public async Task OnLoadedAsync()
@@ -71,22 +75,29 @@ public partial class DevicesViewModel : ViewModelBase
{
// MessageBox.Show("Device added successfully");
await OnLoadedAsync();
_notificationService.Show($"设备添加成功:{device.Name}", NotificationType.Success);
var msg = $"设备添加成功:{device.Name}";
_logger.LogInformation(msg);
NotificationHelper.ShowMessage(msg, NotificationType.Success);
}
}
}
catch (DbExistException e)
{
_notificationService.Show($"设备添加失败:名称为{device?.Name}的设备已经存在。请更换是被名称", NotificationType.Error);
var msg = $"设备添加失败:名称为{device?.Name}的设备已经存在。请更换是被名称";
_logger.LogError(msg);
NotificationHelper.ShowMessage(msg, NotificationType.Error);
}
catch (Exception e)
{
_notificationService.Show($"添加设备的过程中发生错误:{e.Message}", NotificationType.Error);
var msg = $"添加设备的过程中发生错误:{e.Message}";
_logger.LogError(msg);
NotificationHelper.ShowMessage(msg, NotificationType.Success);
}
}
public override void OnLoaded()
public override async void OnLoaded()
{
OnLoadedAsync().Await((e) => { _deviceDialogService.ShowMessageDialog("", e.Message); }, () => { });
// OnLoadedAsync().Await((e) => { _deviceDialogService.ShowMessageDialog("", e.Message); }, () => { });
await OnLoadedAsync();
}
}

View File

@@ -7,7 +7,7 @@ using PMSWPF.Services;
namespace PMSWPF.ViewModels
{
partial class MainViewModel : ObservableRecipient, IRecipient<MyMessage>
public partial class MainViewModel : ObservableRecipient, IRecipient<MyMessage>
{
private readonly NavgatorServices _navgatorServices;

View File

@@ -0,0 +1,9 @@
namespace PMSWPF.ViewModels;
public class SettingViewModel:ViewModelBase
{
public override void OnLoaded()
{
}
}

View File

@@ -53,6 +53,16 @@
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Switch}" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Tag="Setting" Content="设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="关于">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Info}" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</ui:NavigationView.MenuItems>
@@ -65,25 +75,7 @@
</ui:NavigationView.AutoSuggestBox>
<ui:NavigationView.PaneFooter>
<StackPanel
x:Name="FooterStackPanel"
Margin="0"
Orientation="Vertical"
Visibility="Visible">
<ui:NavigationViewItem Content="设置">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
<ui:NavigationViewItem Content="关于">
<ui:NavigationViewItem.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Info}" />
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</StackPanel>
</ui:NavigationView.PaneFooter>
<Grid>
<ContentControl Content="{Binding CurrentViewModel}">
@@ -97,6 +89,9 @@
<DataTemplate DataType="{x:Type vm:DataTransformViewModel}">
<local:DataTransformView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SettingViewModel}">
<local:SettingView/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>

View File

@@ -1,6 +1,9 @@
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.Extensions.Logging;
using PMSWPF.Message;
using PMSWPF.ViewModels;
namespace PMSWPF.Views
@@ -10,14 +13,24 @@ namespace PMSWPF.Views
/// </summary>
public partial class MainView : Window
{
private readonly ILogger<MainView> _logger;
public MainView()
public MainView(MainViewModel viewModel, ILogger<MainView> logger)
{
InitializeComponent();
_logger = logger;
InitializeComponent();
this.DataContext=viewModel;
_logger.LogInformation("主界面加载成功");
}
/// <summary>
/// 左边菜单项被点击的事件,切换右边的视图
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
NavigationViewItem? item = args.SelectedItem as NavigationViewItem;
@@ -26,15 +39,24 @@ namespace PMSWPF.Views
{
case "Home":
mainViewModel.NavgateTo<HomeViewModel>();
_logger.LogInformation("导航到到主页面");
break;
case "Devices":
mainViewModel.NavgateTo<DevicesViewModel>();
_logger.LogInformation("导航到到设备页面");
break;
case "DataTransform":
mainViewModel.NavgateTo<DataTransformViewModel>();
_logger.LogInformation("导航到到数据转换页面");
break;
case "Setting":
mainViewModel.NavgateTo<SettingViewModel>();
_logger.LogInformation("导航到到设备页面");
break;
default:
mainViewModel.NavgateTo<HomeViewModel>();
_logger.LogInformation("没有设置Tag,默认导航到主页面。");
break;
}

12
Views/SettingView.xaml Normal file
View File

@@ -0,0 +1,12 @@
<UserControl x:Class="PMSWPF.Views.SettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PMSWPF.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
</Grid>
</UserControl>

11
Views/SettingView.xaml.cs Normal file
View File

@@ -0,0 +1,11 @@
using System.Windows.Controls;
namespace PMSWPF.Views;
public partial class SettingView : UserControl
{
public SettingView()
{
InitializeComponent();
}
}