diff --git a/BaseFrame.sln b/BaseFrame.sln
new file mode 100644
index 0000000..e46fe6b
--- /dev/null
+++ b/BaseFrame.sln
@@ -0,0 +1,55 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36221.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseFrame", "BaseFrame\BaseFrame.csproj", "{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logger", "Logger\Logger.csproj", "{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ORM", "ORM\ORM.csproj", "{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{D8209B91-D7D0-444B-B569-D3FA74D191DD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D9764D9-B4DA-43E2-A9D7-40A6C871A6B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D8209B91-D7D0-444B-B569-D3FA74D191DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D8209B91-D7D0-444B-B569-D3FA74D191DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D8209B91-D7D0-444B-B569-D3FA74D191DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D8209B91-D7D0-444B-B569-D3FA74D191DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {22BD9235-6581-454D-97D8-F4E932F80888}
+ EndGlobalSection
+EndGlobal
diff --git a/BaseFrame/App.xaml b/BaseFrame/App.xaml
new file mode 100644
index 0000000..363f5af
--- /dev/null
+++ b/BaseFrame/App.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BaseFrame/App.xaml.cs b/BaseFrame/App.xaml.cs
new file mode 100644
index 0000000..c3e560c
--- /dev/null
+++ b/BaseFrame/App.xaml.cs
@@ -0,0 +1,43 @@
+using BaseFrame.ViewModels;
+using BaseFrame.ViewModels.Dialogs;
+using BaseFrame.Views;
+using BaseFrame.Views.Dialogs;
+using Castle.DynamicProxy;
+using System.Configuration;
+using System.Data;
+using System.Reflection;
+using System.Windows;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace BaseFrame
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : PrismApplication
+ {
+ protected override Window CreateShell()
+ {
+ return Container.Resolve();
+ }
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ var regionManager = Container.Resolve();
+ regionManager.RequestNavigate("ShellViewManager", "MainView");
+ }
+ protected override void RegisterTypes(IContainerRegistry containerRegistry)
+ {
+ //注册视图
+ containerRegistry.RegisterForNavigation("MainView");
+ //注册弹窗
+ containerRegistry.RegisterDialog("MessageBox");
+
+
+ }
+
+
+ }
+
+}
diff --git a/BaseFrame/AssemblyInfo.cs b/BaseFrame/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/BaseFrame/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/BaseFrame/BaseFrame.csproj b/BaseFrame/BaseFrame.csproj
new file mode 100644
index 0000000..9be13d0
--- /dev/null
+++ b/BaseFrame/BaseFrame.csproj
@@ -0,0 +1,64 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
diff --git a/BaseFrame/Resources/Images/error.png b/BaseFrame/Resources/Images/error.png
new file mode 100644
index 0000000..de079d0
Binary files /dev/null and b/BaseFrame/Resources/Images/error.png differ
diff --git a/BaseFrame/Resources/Images/info.png b/BaseFrame/Resources/Images/info.png
new file mode 100644
index 0000000..8fed1fb
Binary files /dev/null and b/BaseFrame/Resources/Images/info.png differ
diff --git a/BaseFrame/Resources/Images/warning.png b/BaseFrame/Resources/Images/warning.png
new file mode 100644
index 0000000..1acd082
Binary files /dev/null and b/BaseFrame/Resources/Images/warning.png differ
diff --git a/BaseFrame/Resources/Styles/WindowStyle.xaml b/BaseFrame/Resources/Styles/WindowStyle.xaml
new file mode 100644
index 0000000..3bec5ec
--- /dev/null
+++ b/BaseFrame/Resources/Styles/WindowStyle.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs b/BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs
new file mode 100644
index 0000000..e2e19a6
--- /dev/null
+++ b/BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs
@@ -0,0 +1,122 @@
+using Common.PubEvent;
+using ControlzEx.Standard;
+using Prism.Commands;
+using Prism.Mvvm;
+using System.Windows.Input;
+
+namespace BaseFrame.ViewModels.Dialogs
+{
+ public class MessageBoxViewModel : BindableBase, IDialogAware
+ {
+ #region 属性
+
+ private string _Title;
+ public string Title
+ {
+ get => _Title;
+ set => SetProperty(ref _Title, value);
+ }
+
+ private string _Message = "";
+ public string Message
+ {
+ get => _Message;
+ set => SetProperty(ref _Message, value);
+ }
+
+ private string _Icon= $"pack://siteoforigin:,,,/Resources/Images/info.png";
+ public string Icon
+ {
+ get => _Icon;
+ set => SetProperty(ref _Icon, value);
+ }
+
+ private bool _ShowYes;
+ public bool ShowYes
+ {
+ get => _ShowYes;
+ set => SetProperty(ref _ShowYes, value);
+ }
+
+ private bool _ShowNo;
+ public bool ShowNo
+ {
+ get => _ShowNo;
+ set => SetProperty(ref _ShowNo, value);
+ }
+
+ private bool _ShowOk;
+ public bool ShowOk
+ {
+ get => _ShowOk;
+ set => SetProperty(ref _ShowOk, value);
+ }
+
+ private bool _ShowCancel;
+ public bool ShowCancel
+ {
+ get => _ShowCancel;
+ set => SetProperty(ref _ShowCancel, value);
+ }
+
+ #endregion
+
+ #region 命令
+ public ICommand YesCommand { get; set; }
+ public ICommand NoCommand { get; set; }
+ public ICommand OkCommand { get; set; }
+ public ICommand CancelCommand { get; set; }
+ #endregion
+
+ public DialogCloseListener RequestClose { get; set; }
+ private IEventAggregator _eventAggregator;
+ public MessageBoxViewModel(IEventAggregator eventAggregator)
+ {
+ _eventAggregator= eventAggregator;
+ YesCommand = new DelegateCommand(OnYes);
+ NoCommand = new DelegateCommand(OnNo);
+ OkCommand = new DelegateCommand(OnOk);
+ CancelCommand = new DelegateCommand(OnCancel);
+ }
+
+ private void CloseDialog(ButtonResult result)
+ {
+ var parameters = new DialogParameters();
+ RequestClose.Invoke(new DialogResult(result));
+ }
+
+ private void OnYes() => CloseDialog(ButtonResult.Yes);
+ private void OnNo() => CloseDialog(ButtonResult.No);
+ private void OnOk() => CloseDialog(ButtonResult.OK);
+ private void OnCancel() => CloseDialog(ButtonResult.Cancel);
+
+ #region Prism Dialog 规范
+ public bool CanCloseDialog() => true;
+
+ public void OnDialogClosed()
+ {
+ _eventAggregator.GetEvent().Publish(false);
+ }
+
+ public void OnDialogOpened(IDialogParameters parameters)
+ {
+ Title = parameters.GetValue("Title");
+ Message = parameters.GetValue("Message");
+ var iconKey = parameters.GetValue("Icon"); // info / error / warn
+ Icon = iconKey switch
+ {
+ "info" => $"pack://siteoforigin:,,,/Resources/Images/info.png",
+ "error" => $"pack://siteoforigin:,,,/Resources/Images/error.png",
+ "warn" => $"pack://siteoforigin:,,,/Resources/Images/warning.png",
+ _ => $"pack://siteoforigin:,,,/Resources/Images/info.png" // 默认
+ };
+
+
+ ShowYes = parameters.GetValue("ShowYes");
+ ShowNo = parameters.GetValue("ShowNo");
+ ShowOk = parameters.GetValue("ShowOk");
+ ShowCancel = parameters.GetValue("ShowCancel");
+ }
+ #endregion
+ }
+}
diff --git a/BaseFrame/ViewModels/MainViewModel.cs b/BaseFrame/ViewModels/MainViewModel.cs
new file mode 100644
index 0000000..f75c58c
--- /dev/null
+++ b/BaseFrame/ViewModels/MainViewModel.cs
@@ -0,0 +1,84 @@
+using Common.PubEvent;
+using Common.PubEvents;
+using NLog;
+using Prism.Dialogs;
+using Prism.Events;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace BaseFrame.ViewModels
+{
+ public class MainViewModel : BindableBase,INavigationAware,IDialogAware
+ {
+ #region 属性
+
+
+ #endregion
+ #region 命令
+ public ICommand testcommand { get; set; }
+
+
+ #endregion
+ public DialogCloseListener RequestClose { get; set; }
+ private IEventAggregator _eventAggregator;
+ private IDialogService _dialogService;
+ public MainViewModel(IEventAggregator eventAggregator, IDialogService dialogService)
+ {
+ _dialogService = dialogService;
+ _eventAggregator = eventAggregator;
+ testcommand = new DelegateCommand(test);
+
+ }
+ private void test()
+ {
+ //_eventAggregator.GetEvent().Publish(true);
+ //var parameters = new DialogParameters
+ //{
+ // { "Title", "提示" },
+ // { "Message", "操作成功!" },
+ // { "Icon", "info" },
+ // { "ShowOk", true }
+ //};
+ //_dialogService.ShowDialog("MessageBox",parameters);
+ }
+
+ #region 导航
+ public void OnNavigatedTo(NavigationContext navigationContext)
+ {
+
+ }
+
+ public bool IsNavigationTarget(NavigationContext navigationContext)
+ {
+ return true;
+ }
+
+ public void OnNavigatedFrom(NavigationContext navigationContext)
+ {
+
+ }
+ #endregion
+
+ #region 弹窗
+ public bool CanCloseDialog()
+ {
+ return true;
+ }
+
+ public void OnDialogClosed()
+ {
+
+ }
+
+ public void OnDialogOpened(IDialogParameters parameters)
+ {
+
+ }
+ #endregion
+ }
+}
diff --git a/BaseFrame/ViewModels/ShellViewModel.cs b/BaseFrame/ViewModels/ShellViewModel.cs
new file mode 100644
index 0000000..1a908bd
--- /dev/null
+++ b/BaseFrame/ViewModels/ShellViewModel.cs
@@ -0,0 +1,66 @@
+using BaseFrame.Views;
+using Common.PubEvents;
+using MaterialDesignThemes.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Input;
+
+namespace BaseFrame.ViewModels
+{
+ public class ShellViewModel : BindableBase
+ {
+ #region 属性
+ private bool _IsLeftDrawerOpen;
+
+ public bool IsLeftDrawerOpen
+ {
+ get => _IsLeftDrawerOpen;
+ set => SetProperty(ref _IsLeftDrawerOpen, value);
+ }
+
+ #endregion
+ #region 命令
+ public ICommand LeftDrawerOpenCommand { get; set; }
+ public ICommand MinimizeCommand { get; set; }
+ public ICommand MaximizeCommand { get; set; }
+ public ICommand CloseCommand { get; set; }
+ #endregion
+
+ private IEventAggregator _eventAggregator;
+ public ShellViewModel(IEventAggregator eventAggregator, IContainerProvider containerProvider)
+ {
+ _eventAggregator= eventAggregator;
+ LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
+ MinimizeCommand = new DelegateCommand(MinimizeWindow);
+ MaximizeCommand = new DelegateCommand(MaximizeWindow);
+ CloseCommand = new DelegateCommand(CloseWindow);
+ }
+
+ private void LeftDrawerOpen()
+ {
+ IsLeftDrawerOpen = true;
+ }
+ private void MinimizeWindow(Window window)
+ {
+ if (window != null)
+ window.WindowState = WindowState.Minimized;
+ }
+
+ private void MaximizeWindow(Window window)
+ {
+ if (window != null)
+ {
+ window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
+ }
+ }
+
+ private void CloseWindow(Window window)
+ {
+ window?.Close();
+ }
+ }
+}
diff --git a/BaseFrame/Views/Dialogs/MessageBoxView.xaml b/BaseFrame/Views/Dialogs/MessageBoxView.xaml
new file mode 100644
index 0000000..cc88cad
--- /dev/null
+++ b/BaseFrame/Views/Dialogs/MessageBoxView.xaml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BaseFrame/Views/Dialogs/MessageBoxView.xaml.cs b/BaseFrame/Views/Dialogs/MessageBoxView.xaml.cs
new file mode 100644
index 0000000..f685545
--- /dev/null
+++ b/BaseFrame/Views/Dialogs/MessageBoxView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+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 BaseFrame.Views.Dialogs
+{
+ ///
+ /// MessageBoxView.xaml 的交互逻辑
+ ///
+ public partial class MessageBoxView : UserControl
+ {
+ public MessageBoxView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/BaseFrame/Views/MainView.xaml b/BaseFrame/Views/MainView.xaml
new file mode 100644
index 0000000..53a67c0
--- /dev/null
+++ b/BaseFrame/Views/MainView.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/BaseFrame/Views/MainView.xaml.cs b/BaseFrame/Views/MainView.xaml.cs
new file mode 100644
index 0000000..64e7e78
--- /dev/null
+++ b/BaseFrame/Views/MainView.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+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 BaseFrame.Views
+{
+ ///
+ /// MainView.xaml 的交互逻辑
+ ///
+ public partial class MainView : UserControl
+ {
+ public MainView()
+ {
+ InitializeComponent();
+ }
+
+
+ }
+}
diff --git a/BaseFrame/Views/ProgressView.xaml b/BaseFrame/Views/ProgressView.xaml
new file mode 100644
index 0000000..326eda8
--- /dev/null
+++ b/BaseFrame/Views/ProgressView.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
diff --git a/BaseFrame/Views/ProgressView.xaml.cs b/BaseFrame/Views/ProgressView.xaml.cs
new file mode 100644
index 0000000..92c6591
--- /dev/null
+++ b/BaseFrame/Views/ProgressView.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+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.Shapes;
+
+namespace BaseFrame.Views
+{
+ ///
+ /// ProgressView.xaml 的交互逻辑
+ ///
+ public partial class ProgressView : UserControl
+ {
+ public ProgressView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/BaseFrame/Views/ShellView.xaml b/BaseFrame/Views/ShellView.xaml
new file mode 100644
index 0000000..803f778
--- /dev/null
+++ b/BaseFrame/Views/ShellView.xaml
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BaseFrame/Views/ShellView.xaml.cs b/BaseFrame/Views/ShellView.xaml.cs
new file mode 100644
index 0000000..a54f044
--- /dev/null
+++ b/BaseFrame/Views/ShellView.xaml.cs
@@ -0,0 +1,47 @@
+using Common.PubEvent;
+using Common.PubEvents;
+using Prism.Events;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+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.Shapes;
+
+namespace BaseFrame.Views
+{
+ ///
+ /// ShellView.xaml 的交互逻辑
+ ///
+ public partial class ShellView : Window
+ {
+ public ShellView(IEventAggregator eventAggregator)
+ {
+ InitializeComponent();
+ //注册等待消息窗口
+ eventAggregator.GetEvent().Subscribe(ShowWaiting);
+ //注册灰度遮罩层
+ eventAggregator.GetEvent().Subscribe(ShowOverlay);
+ }
+
+ private void ShowOverlay(bool arg)
+ {
+ DialogHost.IsOpen = arg;
+ }
+
+ private void ShowWaiting(bool arg)
+ {
+ DialogHost.IsOpen = arg;
+
+ if (DialogHost.IsOpen)
+ DialogHost.DialogContent = new ProgressView();
+ }
+ }
+}
diff --git a/Common/Common.csproj b/Common/Common.csproj
new file mode 100644
index 0000000..4457c23
--- /dev/null
+++ b/Common/Common.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net8.0-windows
+ enable
+ true
+ enable
+
+
+
+
+
+
+
diff --git a/Common/Converters/BooleanToVisibilityConverter.cs b/Common/Converters/BooleanToVisibilityConverter.cs
new file mode 100644
index 0000000..5790936
--- /dev/null
+++ b/Common/Converters/BooleanToVisibilityConverter.cs
@@ -0,0 +1,36 @@
+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 Common.Converters
+{
+ public class BooleanToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ bool input = value is bool b && b;
+ bool invert = parameter?.ToString()?.ToLower() == "invert";
+
+ if (invert)
+ input = !input;
+
+ return input ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ bool output = value is Visibility v && v == Visibility.Visible;
+ bool invert = parameter?.ToString()?.ToLower() == "invert";
+
+ if (invert)
+ output = !output;
+
+ return output;
+ }
+ }
+}
diff --git a/Common/PubEvent/OverlayEvent.cs b/Common/PubEvent/OverlayEvent.cs
new file mode 100644
index 0000000..f442676
--- /dev/null
+++ b/Common/PubEvent/OverlayEvent.cs
@@ -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 OverlayEvent : PubSubEvent
+ {
+ }
+}
diff --git a/Common/PubEvent/WaitingEvent.cs b/Common/PubEvent/WaitingEvent.cs
new file mode 100644
index 0000000..55914fe
--- /dev/null
+++ b/Common/PubEvent/WaitingEvent.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Common.PubEvents
+{
+ public class WaitingEvent: PubSubEvent
+ {
+ }
+}
diff --git a/Logger/Logger.csproj b/Logger/Logger.csproj
new file mode 100644
index 0000000..6b0ee50
--- /dev/null
+++ b/Logger/Logger.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/Logger/LoggerHelper.cs b/Logger/LoggerHelper.cs
new file mode 100644
index 0000000..365cbec
--- /dev/null
+++ b/Logger/LoggerHelper.cs
@@ -0,0 +1,42 @@
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Logger
+{
+ public static class LoggerHelper
+ {
+ public static readonly ILogger Logger = LogManager.GetLogger("InfoLogger");
+ public static readonly ILogger sqlLogger = LogManager.GetLogger("SqlLogger");
+
+ // 解析堆栈,找到项目文件路径和行号
+ public static string GetProjectStackLine(string stackTrace)
+ {
+ if (string.IsNullOrEmpty(stackTrace))
+ return "未知位置";
+
+ var lines = stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+
+ foreach (var line in lines)
+ {
+ // 匹配你项目的命名空间路径
+ if (line.Contains("BaseFrame"))
+ {
+ // 提取 "in 文件路径:line 行号"
+ var match = Regex.Match(line, @"in (.+?):line (\d+)");
+ if (match.Success)
+ {
+ return match.Value; // 返回类似 C:\...\MainViewModel.cs:line 37
+ }
+ return line.Trim();
+ }
+ }
+
+ return lines[0].Trim(); // 如果找不到就返回第一条
+ }
+ }
+}
diff --git a/Logger/Nlog.config b/Logger/Nlog.config
new file mode 100644
index 0000000..1b31316
--- /dev/null
+++ b/Logger/Nlog.config
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Model/Model.csproj b/Model/Model.csproj
new file mode 100644
index 0000000..fa71b7a
--- /dev/null
+++ b/Model/Model.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/ORM/DatabaseConfig.cs b/ORM/DatabaseConfig.cs
new file mode 100644
index 0000000..3df55bc
--- /dev/null
+++ b/ORM/DatabaseConfig.cs
@@ -0,0 +1,97 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ORM
+{
+ public static class DatabaseConfig
+ {
+ ///
+ /// 当前数据库类型
+ ///
+ public static DbType DbConnectionType { get; private set; }
+
+ ///
+ /// 数据库连接字符串
+ ///
+ public static string DbConnectionString { get; private set; }
+
+ ///
+ /// 默认 SQLite 文件路径(仅记录,不自动启用)
+ ///
+ public static string DefaultDbFilePath { get; private set; }
+
+ ///
+ /// 租户 Id
+ ///
+ public static int TenantId { get; private set; }
+
+ public static int SnowFlakeDatacenterId { get; private set; }
+ public static int SnowFlakeWorkId { get; private set; }
+
+ static DatabaseConfig()
+ {
+ InitDefaultDbPath(); // 只生成路径,不指定 DB 类型/连接
+ }
+
+ ///
+ /// 生成默认 DB 路径 EXE目录/SQLDB/Data.db
+ ///
+ private static void InitDefaultDbPath()
+ {
+ string baseDir = AppDomain.CurrentDomain.BaseDirectory;
+
+ string folder = Path.Combine(baseDir, "SQLDB");
+ if (!Directory.Exists(folder))
+ Directory.CreateDirectory(folder);
+
+ DefaultDbFilePath = Path.Combine(folder, "Data.db");
+ }
+
+ ///
+ /// 手动设置数据库连接
+ ///
+ public static void SetConnection(string conn, DbType dbType)
+ {
+ if (string.IsNullOrWhiteSpace(conn))
+ throw new Exception("数据库连接字符串为空");
+
+ DbConnectionString = conn;
+ DbConnectionType = dbType;
+ }
+
+ ///
+ /// 如果未 SetConnection,默认使用 SQLite + 默认路径
+ ///
+ public static void EnsureConnection()
+ {
+ if (string.IsNullOrEmpty(DbConnectionString))
+ {
+ DbConnectionString = $"Data Source={DefaultDbFilePath};";
+ DbConnectionType = DbType.Sqlite;
+ }
+ }
+
+ ///
+ /// 设置租户并计算雪花算法节点
+ ///
+ public static void SetTenant(int tenantId)
+ {
+ if (tenantId <= 10000)
+ throw new Exception("数据租户Id值需大于10000");
+
+ TenantId = tenantId;
+
+ int snowId = (tenantId - 10000) % 1024;
+
+ if (snowId is < 0 or > 1023)
+ throw new Exception("雪花算法机器码值范围0至1023");
+
+ SnowFlakeDatacenterId = snowId >> 5;
+ SnowFlakeWorkId = snowId & 31;
+ }
+ }
+}
diff --git a/ORM/ORM.csproj b/ORM/ORM.csproj
new file mode 100644
index 0000000..72f7a86
--- /dev/null
+++ b/ORM/ORM.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Service/Service.csproj b/Service/Service.csproj
new file mode 100644
index 0000000..7745202
--- /dev/null
+++ b/Service/Service.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+