From 3d58397c554c8a31502f5eb0e7e6916f20bd686e Mon Sep 17 00:00:00 2001 From: wenjy Date: Wed, 12 Mar 2025 18:02:23 +0800 Subject: [PATCH] =?UTF-8?q?change=20-=20=E4=BF=AE=E6=94=B9=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E6=96=B9=E5=BC=8F=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E9=A1=B5=E9=9D=A2=E3=80=81=E5=8A=A0=E8=BD=BD=E6=95=88?= =?UTF-8?q?=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SlnMesnac.Ioc/DependencyConfigurator.cs | 150 ------------------ SlnMesnac.Ioc/SlnMesnac.Ioc.csproj | 18 --- SlnMesnac.Serilog/SerilogExtensions.cs | 11 +- SlnMesnac.WPF/App.xaml | 30 +++- SlnMesnac.WPF/App.xaml.cs | 125 ++++++++++++--- .../Attribute/RegisterAsSingletonAttribute.cs | 12 ++ .../Attribute/RegisterAsTransientAttribute.cs | 12 ++ .../Attribute/RequirePermissionAttribute.cs | 109 +++++++++++++ SlnMesnac.WPF/FodyWeavers.xml | 3 + SlnMesnac.WPF/MainWindow.xaml | 10 +- SlnMesnac.WPF/MainWindow.xaml.cs | 8 +- .../Page/Generate/GenerateControl.xaml | 2 +- .../Page/Generate/GenerateControl.xaml.cs | 8 +- SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml | 19 +++ .../Page/Loading/LoadingWindow.xaml.cs | 26 +++ SlnMesnac.WPF/Page/Login/LoginWindow.xaml | 58 +++++++ SlnMesnac.WPF/Page/Login/LoginWindow.xaml.cs | 54 +++++++ SlnMesnac.WPF/SlnMesnac.WPF.csproj | 24 ++- SlnMesnac.WPF/Startup.cs | 88 ---------- SlnMesnac.WPF/Templates/gif/loading.gif | Bin 0 -> 379180 bytes .../Templates/image/login-background.jpg | Bin 0 -> 145101 bytes SlnMesnac.WPF/ViewModel/Base/BaseViewModel.cs | 59 +++++++ .../Base/BaseViewModelAsPageQuery.cs | 75 +++++++++ .../Generate/GenerateControlViewModel.cs | 38 +++-- .../ViewModel/Login/LoginViewModel.cs | 52 ++++++ .../ViewModel/MainWindowViewModel.cs | 67 ++++---- SlnMesnac.sln | 16 +- .../Controllers/BaseMaterialInfoController.cs | 91 ----------- SlnMesnac/Controllers/BaseUserController.cs | 82 ---------- SlnMesnac/Controllers/JobController.cs | 61 ------- SlnMesnac/Program.cs | 32 ---- SlnMesnac/Properties/launchSettings.json | 30 ---- SlnMesnac/SlnMesnac.csproj | 24 --- SlnMesnac/Startup.cs | 121 -------------- SlnMesnac/appsettings.Development.json | 8 - SlnMesnac/appsettings.json | 15 -- 36 files changed, 695 insertions(+), 843 deletions(-) delete mode 100644 SlnMesnac.Ioc/DependencyConfigurator.cs delete mode 100644 SlnMesnac.Ioc/SlnMesnac.Ioc.csproj create mode 100644 SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs create mode 100644 SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs create mode 100644 SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs create mode 100644 SlnMesnac.WPF/FodyWeavers.xml create mode 100644 SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml create mode 100644 SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml.cs create mode 100644 SlnMesnac.WPF/Page/Login/LoginWindow.xaml create mode 100644 SlnMesnac.WPF/Page/Login/LoginWindow.xaml.cs delete mode 100644 SlnMesnac.WPF/Startup.cs create mode 100644 SlnMesnac.WPF/Templates/gif/loading.gif create mode 100644 SlnMesnac.WPF/Templates/image/login-background.jpg create mode 100644 SlnMesnac.WPF/ViewModel/Base/BaseViewModel.cs create mode 100644 SlnMesnac.WPF/ViewModel/Base/BaseViewModelAsPageQuery.cs create mode 100644 SlnMesnac.WPF/ViewModel/Login/LoginViewModel.cs delete mode 100644 SlnMesnac/Controllers/BaseMaterialInfoController.cs delete mode 100644 SlnMesnac/Controllers/BaseUserController.cs delete mode 100644 SlnMesnac/Controllers/JobController.cs delete mode 100644 SlnMesnac/Program.cs delete mode 100644 SlnMesnac/Properties/launchSettings.json delete mode 100644 SlnMesnac/SlnMesnac.csproj delete mode 100644 SlnMesnac/Startup.cs delete mode 100644 SlnMesnac/appsettings.Development.json delete mode 100644 SlnMesnac/appsettings.json diff --git a/SlnMesnac.Ioc/DependencyConfigurator.cs b/SlnMesnac.Ioc/DependencyConfigurator.cs deleted file mode 100644 index 5904b0d..0000000 --- a/SlnMesnac.Ioc/DependencyConfigurator.cs +++ /dev/null @@ -1,150 +0,0 @@ -using Autofac; -using SlnMesnac.Repository; -using SlnMesnac.Serilog; -using System.Reflection; -using TouchSocket.Sockets; - -#region << 版 本 注 释 >> -/*-------------------------------------------------------------------- -* 版权所有 (c) 2024 WenJY 保留所有权利。 -* CLR版本:4.0.30319.42000 -* 机器名称:LAPTOP-E0N2L34V -* 命名空间:SlnMesnac.Ioc -* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82 -* -* 创建者:WenJY -* 电子邮箱:wenjy@mesnac.com -* 创建时间:2024-03-27 21:58:35 -* 版本:V1.0.0 -* 描述: -* -*-------------------------------------------------------------------- -* 修改人: -* 时间: -* 修改说明: -* -* 版本:V1.0.0 -*--------------------------------------------------------------------*/ -#endregion << 版 本 注 释 >> -namespace SlnMesnac.Ioc -{ - /// - /// Utility class for configuring dependency injection. - /// - public static class DependencyConfigurator - { - /// - /// Configures dependency injection for the application. - /// - /// The Autofac container builder. - public static void Configure(ContainerBuilder builder) - { - //注入Repository - builder.RegisterGeneric(typeof(Repository<>)).As(typeof(Repository<>)); - RegisterImplementations(builder, Assembly.LoadFrom("SlnMesnac.Repository.dll")); - - //注入Plc - RegisterTypeTransient(builder, Assembly.LoadFrom("SlnMesnac.Plc.dll")); - - //注入Rfid - RegisterTypeTransient(builder, Assembly.LoadFrom("SlnMesnac.Rfid.dll")); - - //注入通用类 - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Common.dll")); - - //注入MQTT - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Mqtt.dll")); - - //注入TouchSocket - builder.RegisterType(typeof(TcpService)); - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.TouchSocket.dll")); - - //注入业务类 - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Business.dll")); - - //注入代码生成 - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Generate.dll")); - - //注入Serilog日志帮助类 - builder.RegisterType(typeof(SerilogHelper)).SingleInstance(); - } - - - /// - /// 自动注入接口实现 - /// - /// - /// - private static void RegisterImplementations(ContainerBuilder builder, Assembly assembly) - { - //自动注入仓储层的接口实现类 - var types = assembly.GetTypes() - .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType) - .ToList(); - - foreach (var type in types) - { - var interfaces = type.GetInterfaces(); - - foreach (var @interface in interfaces) - { - builder.RegisterType(type).As(@interface); - } - } - } - - /// - /// 自动注入自定义类、抽象类,设置为单例 - /// - /// - /// - private static void RegisterType(ContainerBuilder builder, Assembly assembly) - { - var types = assembly.GetTypes() - .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType) - .ToList(); - - foreach (var type in types) - { - var interfaces = type.GetInterfaces(); - var baseType = type.BaseType; - - #region 只注入抽象类 Delete By wenjy 2024-03-27 - //if (baseType != null && baseType.IsAbstract && baseType == typeof(PlcAbsractFactory)) - //{ - // builder.RegisterType(type); - //} - #endregion - - - if (!typeof(Delegate).IsAssignableFrom(type)) //不注入委托事件 - { - builder.RegisterType(type).SingleInstance(); - } - } - } - - /// - /// 自动注入自定义类,设置生命周期为每次解析返回新实例 - /// - /// - /// - private static void RegisterTypeTransient(ContainerBuilder builder, Assembly assembly) - { - var types = assembly.GetTypes() - .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType) - .ToList(); - - foreach (var type in types) - { - var interfaces = type.GetInterfaces(); - var baseType = type.BaseType; - - if (!typeof(Delegate).IsAssignableFrom(type)) - { - builder.RegisterType(type).AsSelf().InstancePerDependency(); - } - } - } - } -} diff --git a/SlnMesnac.Ioc/SlnMesnac.Ioc.csproj b/SlnMesnac.Ioc/SlnMesnac.Ioc.csproj deleted file mode 100644 index f9ed572..0000000 --- a/SlnMesnac.Ioc/SlnMesnac.Ioc.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/SlnMesnac.Serilog/SerilogExtensions.cs b/SlnMesnac.Serilog/SerilogExtensions.cs index f332ac4..87a5374 100644 --- a/SlnMesnac.Serilog/SerilogExtensions.cs +++ b/SlnMesnac.Serilog/SerilogExtensions.cs @@ -35,13 +35,10 @@ namespace SlnMesnac.Serilog /// public static class SerilogExtensions { - public static IApplicationBuilder UseSerilogExtensions(this IApplicationBuilder app) + public static void UseSerilogExtensions(this IServiceProvider service) { - //启用Serilog中间件 - app.UseSerilogRequestLogging(); - #region 通过配置文件读取日志存放位置 - var appConfig = app.ApplicationServices.GetService(); + var appConfig = service.GetService(); var logPath = $"{appConfig.logPath}/Logs/"; #endregion @@ -67,10 +64,6 @@ namespace SlnMesnac.Serilog .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Error")) .WriteTo.File(Path.Combine($"{logPath}/Error/", "Error.log"), rollingInterval: RollingInterval.Day)) .CreateLogger(); - - app.UseSerilogRequestLogging(); - - return app; } } } diff --git a/SlnMesnac.WPF/App.xaml b/SlnMesnac.WPF/App.xaml index 48f0a12..05764b6 100644 --- a/SlnMesnac.WPF/App.xaml +++ b/SlnMesnac.WPF/App.xaml @@ -1,14 +1,36 @@  + xmlns:local="clr-namespace:SlnMesnac.WPF"> - - + + + + + + + + + + + + + + + + + + diff --git a/SlnMesnac.WPF/App.xaml.cs b/SlnMesnac.WPF/App.xaml.cs index ec3de3a..3040fed 100644 --- a/SlnMesnac.WPF/App.xaml.cs +++ b/SlnMesnac.WPF/App.xaml.cs @@ -1,15 +1,16 @@ using Lierda.WPFHelper; -using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Serilog; using SlnMesnac.Config; using System; using System.Windows; -using Autofac.Extensions.DependencyInjection; -using SlnMesnac.Plc; -using System.Collections.Generic; -using SlnMesnac.Rfid; +using Microsoft.Extensions.Configuration; +using SlnMesnac.Extensions; +using SlnMesnac.Serilog; +using System.Reflection; +using TouchSocket.Sockets; +using SlnMesnac.WPF.Attribute; +using SlnMesnac.WPF.Page.Login; namespace SlnMesnac.WPF { @@ -22,9 +23,15 @@ namespace SlnMesnac.WPF private LierdaCracker cracker = new LierdaCracker(); public static IServiceProvider? ServiceProvider = null; + public new static App Current => (App)Application.Current; + // Startup事件 protected override async void OnStartup(StartupEventArgs e) { + + this.DispatcherUnhandledException += App_DispatcherUnhandledException; //全局异常处理 + + #region 进程判断,避免重复开启 bool ret; mutex = new System.Threading.Mutex(true, System.Diagnostics.Process.GetCurrentProcess().ProcessName, out ret); if (!ret) @@ -32,35 +39,96 @@ namespace SlnMesnac.WPF MessageBox.Show("应用程序已开启,禁止重复运行"); Environment.Exit(0); } + #endregion cracker.Cracker(100); //设置GC回收间隔 base.OnStartup(e); - var host = CreateHostBuilder(e.Args).Build();//生成宿主。 - ServiceProvider = host.Services; + // 设置ServiceCollection + var services = new ServiceCollection(); + ConfigureServices(services); // 配置服务 + + // 创建ServiceProvider + ServiceProvider = services.BuildServiceProvider(); - await host.StartAsync(); + // 配置Serilog和其他扩展 + ServiceProvider.UseSerilogExtensions(); - var appConfig = host.Services.GetService(); - var logPath = $"{appConfig.logPath}/Logs/{DateTime.UtcNow:yyyy-MM-dd}/"; - Log.Information($"系统初始化完成,日志存放路径:{appConfig.logPath}"); + var appConfig = ServiceProvider.GetService(); + Log.Information($"系统初始化完成,日志存放路径:{appConfig?.logPath}"); + + var loginWindow = ServiceProvider.GetRequiredService(); + loginWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen; + loginWindow.Show(); } + /// - /// CreateHostBuilder + /// ConfigureServices /// - /// - /// - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .UseSerilog() - .UseServiceProviderFactory(new AutofacServiceProviderFactory()) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + /// + private void ConfigureServices(IServiceCollection services) + { + // 注册AppConfig + services.AddSingleton(provider => + { + var configurationBuilder = new ConfigurationBuilder() + .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); + IConfiguration configuration = configurationBuilder.Build(); + var ap = configuration.GetSection("AppConfig").Get(); + return ap; + }); + + services.AddSingleton(typeof(SerilogHelper)); + + Assembly[] assemblies = { + Assembly.LoadFrom("SlnMesnac.Repository.dll"), + Assembly.LoadFrom("SlnMesnac.Plc.dll"), + Assembly.LoadFrom("SlnMesnac.Rfid.dll"), + Assembly.LoadFrom("SlnMesnac.Common.dll"), + Assembly.LoadFrom("SlnMesnac.TouchSocket.dll"), + Assembly.LoadFrom("SlnMesnac.Business.dll"), + Assembly.LoadFrom("SlnMesnac.Generate.dll") + }; + + services.Scan(scan => scan.FromAssemblies(assemblies) + .AddClasses() + .AsImplementedInterfaces() + .AsSelf() + .WithTransientLifetime()); + services.AddSingleton(typeof(TcpService)); + services.AddLogging(x => x.AddSerilog()); + + services.Scan(scan => scan + .FromAssemblyOf() + .AddClasses(classes => classes.WithAttribute()).AsSelf().WithSingletonLifetime()); + services.Scan(scan => scan + .FromAssemblyOf() + .AddClasses(classes => classes.WithAttribute()).AsSelf().WithTransientLifetime()); + + + // 注册ORM + services.AddSqlSugarSetup(); + + // 注册PLC工厂 + //services.AddPlcFactorySetup(); + + //services.AddJob(); + + // 注册 EventBus 服务 + //services.AddEventBus(builder => + //{ + // // 注册 ToDo 事件订阅者 + // builder.AddSubscriber(); + //}); + + + + + } // Exit事件 protected override void OnExit(ExitEventArgs e) @@ -72,6 +140,17 @@ namespace SlnMesnac.WPF // ... } + private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) + { + // 处理异常 + var info = e.Exception; + MessageBox.Show(e.Exception.Message); + Log.Error($"全局异常:{e.Exception.Message}", e.Exception); + + // 防止默认的崩溃行为 + e.Handled = true; + } + } } diff --git a/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs b/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs new file mode 100644 index 0000000..86eadf3 --- /dev/null +++ b/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.WPF.Attribute +{ + public class RegisterAsSingletonAttribute:System.Attribute + { + } +} diff --git a/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs b/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs new file mode 100644 index 0000000..037555d --- /dev/null +++ b/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.WPF.Attribute +{ + public class RegisterAsTransientAttribute:System.Attribute + { + } +} diff --git a/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs b/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs new file mode 100644 index 0000000..aaefe90 --- /dev/null +++ b/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs @@ -0,0 +1,109 @@ +using Microsoft.Extensions.DependencyInjection; +using Rougamo; +using Rougamo.Context; +using SlnMesnac.WPF.Page.Loading; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; + +#region << 版 本 注 释 >> +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:SlnMesnac.WPF.Attribute +* 唯一标识:fff40cb6-18aa-47e0-917c-1fa653e6f978 +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-12-30 10:19:41 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ +#endregion << 版 本 注 释 >> +namespace SlnMesnac.WPF.Attribute +{ + /// + /// 权限过滤 + /// + public class RequirePermissionAttribute : MoAttribute + { + private LoadingWindow loadingWindow; + private string _permissionName; + + public RequirePermissionAttribute(string permissionName) + { + _permissionName = permissionName; + + + } + public override void OnEntry(MethodContext context) + { + Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint)); + newWindowThread.SetApartmentState(ApartmentState.STA); // 设置为 STA 模式 + newWindowThread.IsBackground = true; // 设置为后台线程 + newWindowThread.Start(); + + bool hasPermission = CheckPermission(_permissionName); + + if (!hasPermission) + { + // 如果用户没有权限,抛出异常或采取其他措施 + throw new UnauthorizedAccessException("User does not have the required permission."); + } + + base.OnEntry(context); + } + + + public override void OnExit(MethodContext context) + { + Thread.Sleep(200); + if(loadingWindow != null) + { + loadingWindow.Dispatcher.Invoke(new Action(() => + { + loadingWindow.Close(); // 关闭窗口 + })); + } + + + base.OnExit(context); + } + + /// + /// 判断权限 + /// + /// + /// + private bool CheckPermission(string permissionName) + { + return true; + } + + private void ThreadStartingPoint() + { + Dispatcher.CurrentDispatcher.Invoke(new Action(() => + { + loadingWindow = App.ServiceProvider.GetService(); + loadingWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen; + loadingWindow.Topmost = true; + loadingWindow.Show(); + })); + + Dispatcher.Run(); + } + } +} diff --git a/SlnMesnac.WPF/FodyWeavers.xml b/SlnMesnac.WPF/FodyWeavers.xml new file mode 100644 index 0000000..a6a2edf --- /dev/null +++ b/SlnMesnac.WPF/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/SlnMesnac.WPF/MainWindow.xaml b/SlnMesnac.WPF/MainWindow.xaml index 150870a..95bca2c 100644 --- a/SlnMesnac.WPF/MainWindow.xaml +++ b/SlnMesnac.WPF/MainWindow.xaml @@ -61,11 +61,11 @@ -