diff --git a/BaseFrame/App.xaml.cs b/BaseFrame/App.xaml.cs
deleted file mode 100644
index f2aa19b..0000000
--- a/BaseFrame/App.xaml.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using BaseFrame.ViewModels;
-using BaseFrame.ViewModels.Dialogs;
-using BaseFrame.Views;
-using BaseFrame.Views.Dialogs;
-using Castle.DynamicProxy;
-using ECCS.Views;
-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", "MonitorView");
- }
- protected override void RegisterTypes(IContainerRegistry containerRegistry)
- {
- //注册视图
- containerRegistry.RegisterForNavigation("MonitorView");
- containerRegistry.RegisterForNavigation("SettingView");
- containerRegistry.RegisterForNavigation("UpdateInfoView");
- //注册弹窗
- containerRegistry.RegisterDialog("MessageBox");
-
-
-
- }
-
-
- }
-
-}
diff --git a/BaseFrame/MultidimensionalTableConfig.cs b/BaseFrame/MultidimensionalTableConfig.cs
deleted file mode 100644
index 3a38b96..0000000
--- a/BaseFrame/MultidimensionalTableConfig.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using Newtonsoft.Json;
-using System;
-using System.IO;
-
-namespace ECCS
-{
- public sealed class MultidimensionalTableConfig
- {
- private static readonly object _lock = new();
- private static MultidimensionalTableConfig? _instance;
-
- ///
- /// 单例实例(首次访问自动从文件加载)
- ///
- public static MultidimensionalTableConfig Instance
- {
- get
- {
- lock (_lock)
- {
- if (_instance == null)
- {
- _instance = Load();
- }
- return _instance;
- }
- }
- }
-
- ///
- /// exe 目录下的 config.json
- ///
- [JsonIgnore]
- private static string ConfigFilePath =>
- Path.Combine(AppContext.BaseDirectory, "config.json");
-
- // ===== 配置项 =====
- public string AppToken { get; set; }
- public string DefaultTableId { get; set; }
- public bool DefaultTableIsDeleted { get; set; }
-
- ///
- /// 保存到 config.json
- ///
- public void Save()
- {
- var json = JsonConvert.SerializeObject(this, Formatting.Indented);
- File.WriteAllText(ConfigFilePath, json);
- }
-
- ///
- /// 从 config.json 加载
- ///
- private static MultidimensionalTableConfig Load()
- {
- if (!File.Exists(ConfigFilePath))
- {
- return new MultidimensionalTableConfig();
- }
-
- var json = File.ReadAllText(ConfigFilePath);
- return JsonConvert.DeserializeObject(json)
- ?? new MultidimensionalTableConfig();
- }
- }
-}
diff --git a/Common/DTOS/FeishuResponse.cs b/Common/DTOS/FeishuResponse.cs
deleted file mode 100644
index 69670c6..0000000
--- a/Common/DTOS/FeishuResponse.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using Newtonsoft.Json;
-
-
-namespace Common.DTOS
-{
- public class FeishuResponse
- {
- [JsonProperty("code")]
- public int Code { get; set; }
-
- [JsonProperty("msg")]
- public string Msg { get; set; }
-
- [JsonProperty("data")]
- public T Data { get; set; }
- }
-
- #region 创建多维表格返回数据
- public class CreateBitableAppData
- {
- [JsonProperty("app")]
- public AppInfo App { get; set; }
- }
-
- public class AppInfo
- {
- [JsonProperty("app_token")]
- public string AppToken { get; set; }
-
- [JsonProperty("default_table_id")]
- public string DefaultTableId { get; set; }
-
- [JsonProperty("folder_token")]
- public string FolderToken { get; set; }
-
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("url")]
- public string Url { get; set; }
- }
- #endregion
-
- #region 新增数据表返回数据
- public class CreateTableData
- {
- [JsonProperty("default_view_id")]
- public string DefaultViewId { get; set; }
-
- [JsonProperty("field_id_list")]
- public List FieldIdList { get; set; }
-
- [JsonProperty("table_id")]
- public string TableId { get; set; }
- }
-
- #endregion
-
- #region 查询数据表列表返回数据
-
- public class QueryTableListData
- {
- [JsonProperty("has_more")]
- public bool HasMore { get; set; }
-
- [JsonProperty("items")]
- public List Items { get; set; }
-
- [JsonProperty("page_token")]
- public string PageToken { get; set; }
-
- [JsonProperty("total")]
- public int Total { get; set; }
- }
-
- public class TableItem
- {
- [JsonProperty("name")]
- public string Name { get; set; }
-
- [JsonProperty("revision")]
- public int Revision { get; set; }
-
- [JsonProperty("table_id")]
- public string TableId { get; set; }
- }
-
- #endregion
-
- #region 更新或新增记录返回数据
-
- public class CreateRecordData
- {
- [JsonProperty("record")]
- public RecordInfo Record { get; set; }
- }
-
- public class RecordInfo
- {
- ///
- /// 字段数据(字段名 -> 值)
- ///
- [JsonProperty("fields")]
- public Dictionary Fields { get; set; }
-
- [JsonProperty("id")]
- public string Id { get; set; }
-
- [JsonProperty("record_id")]
- public string RecordId { get; set; }
- }
-
- #endregion
-
- #region 查询记录返回数据
- public class QueryRecordListData
- {
- [JsonProperty("has_more")]
- public bool HasMore { get; set; }
-
- [JsonProperty("items")]
- public List Items { get; set; }
-
- [JsonProperty("total")]
- public int Total { get; set; }
- }
-
- public class RecordItem
- {
- [JsonProperty("record_id")]
- public string RecordId { get; set; }
-
- [JsonProperty("fields")]
- public Dictionary Fields { get; set; }
- }
- #endregion
-
- #region 多行创建返回数据
- public class CreateRecordsRequest
- {
- [JsonProperty("records")]
- public List Records { get; set; }
- }
- public class CreateRecordItem
- {
- ///
- /// 字段数据(字段名 -> 值)
- ///
- [JsonProperty("fields")]
- public Dictionary Fields { get; set; }
- [JsonProperty("id")]
- public string Id { get; set; }
-
- [JsonProperty("record_id")]
- public string RecordId { get; set; }
-
- }
-
- #endregion
-}
diff --git a/Common/MiniDump.cs b/Common/MiniDump.cs
new file mode 100644
index 0000000..9abaa41
--- /dev/null
+++ b/Common/MiniDump.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Common
+{
+ public static class MiniDump
+ {
+ [Flags]
+ public enum Option : uint
+ {
+ Normal = 0x00000000,
+ WithDataSegs = 0x00000001,
+ WithFullMemory = 0x00000002,
+ WithHandleData = 0x00000004,
+ FilterMemory = 0x00000008,
+ ScanMemory = 0x00000010,
+ WithUnloadedModules = 0x00000020,
+ WithIndirectlyReferencedMemory = 0x00000040,
+ FilterModulePaths = 0x00000080,
+ WithProcessThreadData = 0x00000100,
+ WithPrivateReadWriteMemory = 0x00000200,
+ WithoutOptionalData = 0x00000400,
+ WithFullMemoryInfo = 0x00000800,
+ WithThreadInfo = 0x00001000,
+ WithCodeSegs = 0x00002000,
+ WithoutAuxiliaryState = 0x00004000,
+ WithFullAuxiliaryState = 0x00008000,
+ WithPrivateWriteCopyMemory = 0x00010000,
+ IgnoreInaccessibleMemory = 0x00020000,
+ ValidTypeFlags = 0x0003ffff,
+ }
+
+ enum ExceptionInfo
+ {
+ None,
+ Present
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
+ struct MiniDumpExceptionInformation
+ {
+ public uint ThreadId;
+ public IntPtr ExceptionPointers;
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool ClientPointers;
+ }
+
+ // MiniDumpWriteDump function declarations
+ [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
+ static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
+
+ [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
+ static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
+
+ [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
+ static extern uint GetCurrentThreadId();
+
+ static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo, Exception exception = null)
+ {
+ Process currentProcess = Process.GetCurrentProcess();
+ IntPtr currentProcessHandle = currentProcess.Handle;
+ uint currentProcessId = (uint)currentProcess.Id;
+
+ MiniDumpExceptionInformation exp;
+ exp.ThreadId = GetCurrentThreadId();
+ exp.ClientPointers = false;
+ exp.ExceptionPointers = IntPtr.Zero;
+
+ if (exceptionInfo == ExceptionInfo.Present && exception != null)
+ {
+ // Get exception pointers
+ exp.ExceptionPointers = Marshal.GetExceptionPointers();
+ }
+
+ // Write dump
+ bool result = exp.ExceptionPointers == IntPtr.Zero
+ ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
+ : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);
+
+ if (exception != null)
+ {
+
+ }
+
+ return result;
+ }
+
+
+
+ public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal, Exception exception = null)
+ {
+ var path = Path.Combine(Environment.CurrentDirectory, dmpPath);
+ var dir = Path.GetDirectoryName(path);
+ if (dir != null && !Directory.Exists(dir))
+ {
+ Directory.CreateDirectory(dir);
+ }
+
+ using (var fs = new FileStream(path, FileMode.Create))
+ {
+ return Write(fs.SafeFileHandle, dmpType, exception == null ? ExceptionInfo.None : ExceptionInfo.Present, exception);
+ }
+ }
+ }
+
+}
diff --git a/ECCS.sln b/LAEPS.sln
similarity index 88%
rename from ECCS.sln
rename to LAEPS.sln
index 947df38..c5a0c63 100644
--- a/ECCS.sln
+++ b/LAEPS.sln
@@ -3,8 +3,6 @@ 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}") = "ECCS", "BaseFrame\ECCS.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}"
@@ -15,16 +13,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{C769E6C6-55E9-40C3-A611-9EFAB101BE6A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LAEPS", "LAEPS\LAEPS.csproj", "{5EC9A233-D154-4B77-6911-063269A883E9}"
+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
@@ -45,6 +41,10 @@ Global
{C769E6C6-55E9-40C3-A611-9EFAB101BE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C769E6C6-55E9-40C3-A611-9EFAB101BE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C769E6C6-55E9-40C3-A611-9EFAB101BE6A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5EC9A233-D154-4B77-6911-063269A883E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5EC9A233-D154-4B77-6911-063269A883E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5EC9A233-D154-4B77-6911-063269A883E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5EC9A233-D154-4B77-6911-063269A883E9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/BaseFrame/App.xaml b/LAEPS/App.xaml
similarity index 95%
rename from BaseFrame/App.xaml
rename to LAEPS/App.xaml
index 363f5af..8e5c815 100644
--- a/BaseFrame/App.xaml
+++ b/LAEPS/App.xaml
@@ -1,7 +1,7 @@
-
diff --git a/LAEPS/App.xaml.cs b/LAEPS/App.xaml.cs
new file mode 100644
index 0000000..0135d1f
--- /dev/null
+++ b/LAEPS/App.xaml.cs
@@ -0,0 +1,69 @@
+using LAEPS.ViewModels;
+using LAEPS.ViewModels.Dialogs;
+using LAEPS.Views;
+using LAEPS.Views.Dialogs;
+using Castle.DynamicProxy;
+using LAEPS.Views;
+using System.Configuration;
+using System.Data;
+using System.Reflection;
+using System.Windows;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+using LAEPS.PubEvent;
+using Notifications.Wpf.Core;
+using Logger;
+using Common;
+
+namespace LAEPS
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : PrismApplication
+ {
+ protected override Window CreateShell()
+ {
+ //UI线程未捕获异常处理事件
+ this.DispatcherUnhandledException += OnDispatcherUnhandledException;
+ //Task线程内未捕获异常处理事件
+ TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
+ ////多线程异常
+ AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+ return Container.Resolve();
+ }
+ private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
+ {
+ //通常全局异常捕捉的都是致命信息
+ LoggerHelper.Error(e.Exception.Message,e.Exception.StackTrace);
+ }
+
+ private void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
+ {
+ LoggerHelper.Error(e.Exception.Message, e.Exception.StackTrace);
+ }
+
+ private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ //记录dump文件
+ Exception ex = e.ExceptionObject as Exception;
+ MiniDump.TryDump($"dumps\\Error_{DateTime.Now:yyyy-MM-dd HH-mm-ss-ms}.dmp", MiniDump.Option.WithFullMemory, ex);
+ }
+ protected override void OnInitialized()
+ {
+ var login=Container.Resolve();
+ login.Show();
+ }
+ protected override void RegisterTypes(IContainerRegistry containerRegistry)
+ {
+ //注册视图
+ containerRegistry.RegisterForNavigation("MainView");
+ containerRegistry.RegisterForNavigation("SettingView");
+ containerRegistry.RegisterForNavigation("UpdateInfoView");
+ //注册弹窗
+ containerRegistry.RegisterDialog("MessageBox");
+ // 注册通知管理器
+ INotificationManager NotificationManager = new NotificationManager();
+ containerRegistry.RegisterInstance(NotificationManager);
+ }
+ }
+}
diff --git a/BaseFrame/AssemblyInfo.cs b/LAEPS/AssemblyInfo.cs
similarity index 100%
rename from BaseFrame/AssemblyInfo.cs
rename to LAEPS/AssemblyInfo.cs
diff --git a/BaseFrame/Converters/BooleanToVisibilityConverter.cs b/LAEPS/Converters/BooleanToVisibilityConverter.cs
similarity index 97%
rename from BaseFrame/Converters/BooleanToVisibilityConverter.cs
rename to LAEPS/Converters/BooleanToVisibilityConverter.cs
index 52b6c7d..9d9a4d8 100644
--- a/BaseFrame/Converters/BooleanToVisibilityConverter.cs
+++ b/LAEPS/Converters/BooleanToVisibilityConverter.cs
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
-namespace BaseFrame.Converters
+namespace LAEPS.Converters
{
public class BooleanToVisibilityConverter : IValueConverter
{
diff --git a/LAEPS/Helpers/PasswordBoxHelper.cs b/LAEPS/Helpers/PasswordBoxHelper.cs
new file mode 100644
index 0000000..097041d
--- /dev/null
+++ b/LAEPS/Helpers/PasswordBoxHelper.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace LAEPS.Helpers
+{
+ public static class PasswordBoxHelper
+ {
+ public static readonly DependencyProperty PasswordProperty =
+ DependencyProperty.RegisterAttached(
+ "Password",
+ typeof(string),
+ typeof(PasswordBoxHelper),
+ new FrameworkPropertyMetadata(
+ string.Empty,
+ FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
+ OnPasswordPropertyChanged));
+
+ public static void SetPassword(DependencyObject d, string value)
+ => d.SetValue(PasswordProperty, value);
+
+ public static string GetPassword(DependencyObject d)
+ => (string)d.GetValue(PasswordProperty);
+
+ private static void OnPasswordPropertyChanged(
+ DependencyObject d,
+ DependencyPropertyChangedEventArgs e)
+ {
+ if (d is PasswordBox pb)
+ {
+ pb.PasswordChanged -= PasswordChanged;
+ if (pb.Password != (string)e.NewValue)
+ {
+ pb.Password = (string)e.NewValue;
+ }
+ pb.PasswordChanged += PasswordChanged;
+ }
+ }
+
+ private static void PasswordChanged(object sender, RoutedEventArgs e)
+ {
+ if (sender is PasswordBox pb)
+ {
+ SetPassword(pb, pb.Password);
+ }
+ }
+ }
+}
diff --git a/BaseFrame/ECCS.csproj b/LAEPS/LAEPS.csproj
similarity index 98%
rename from BaseFrame/ECCS.csproj
rename to LAEPS/LAEPS.csproj
index 9be13d0..881958b 100644
--- a/BaseFrame/ECCS.csproj
+++ b/LAEPS/LAEPS.csproj
@@ -38,6 +38,7 @@
+
diff --git a/LAEPS/PubEvent/LoginSuccessEvent.cs b/LAEPS/PubEvent/LoginSuccessEvent.cs
new file mode 100644
index 0000000..8a8edb9
--- /dev/null
+++ b/LAEPS/PubEvent/LoginSuccessEvent.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LAEPS.PubEvent
+{
+ public class LoginSuccessEvent:PubSubEvent
+ {
+ }
+}
diff --git a/BaseFrame/PubEvent/OverlayEvent.cs b/LAEPS/PubEvent/OverlayEvent.cs
similarity index 86%
rename from BaseFrame/PubEvent/OverlayEvent.cs
rename to LAEPS/PubEvent/OverlayEvent.cs
index 7060ba7..fe4a047 100644
--- a/BaseFrame/PubEvent/OverlayEvent.cs
+++ b/LAEPS/PubEvent/OverlayEvent.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace BaseFrame.PubEvent
+namespace LAEPS.PubEvent
{
public class OverlayEvent : PubSubEvent
{
diff --git a/BaseFrame/PubEvent/WaitingEvent.cs b/LAEPS/PubEvent/WaitingEvent.cs
similarity index 86%
rename from BaseFrame/PubEvent/WaitingEvent.cs
rename to LAEPS/PubEvent/WaitingEvent.cs
index d900f22..ab36f7f 100644
--- a/BaseFrame/PubEvent/WaitingEvent.cs
+++ b/LAEPS/PubEvent/WaitingEvent.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace BaseFrame.PubEvent
+namespace LAEPS.PubEvent
{
public class WaitingEvent : PubSubEvent
{
diff --git a/BaseFrame/Resources/Images/error.png b/LAEPS/Resources/Images/error.png
similarity index 100%
rename from BaseFrame/Resources/Images/error.png
rename to LAEPS/Resources/Images/error.png
diff --git a/BaseFrame/Resources/Images/info.png b/LAEPS/Resources/Images/info.png
similarity index 100%
rename from BaseFrame/Resources/Images/info.png
rename to LAEPS/Resources/Images/info.png
diff --git a/BaseFrame/Resources/Images/warning.png b/LAEPS/Resources/Images/warning.png
similarity index 100%
rename from BaseFrame/Resources/Images/warning.png
rename to LAEPS/Resources/Images/warning.png
diff --git a/BaseFrame/Resources/Styles/WindowStyle.xaml b/LAEPS/Resources/Styles/WindowStyle.xaml
similarity index 100%
rename from BaseFrame/Resources/Styles/WindowStyle.xaml
rename to LAEPS/Resources/Styles/WindowStyle.xaml
diff --git a/BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs b/LAEPS/ViewModels/Dialogs/MessageBoxViewModel.cs
similarity index 97%
rename from BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs
rename to LAEPS/ViewModels/Dialogs/MessageBoxViewModel.cs
index cb500c8..31c09b3 100644
--- a/BaseFrame/ViewModels/Dialogs/MessageBoxViewModel.cs
+++ b/LAEPS/ViewModels/Dialogs/MessageBoxViewModel.cs
@@ -1,11 +1,11 @@
-using BaseFrame.PubEvent;
+using LAEPS.PubEvent;
using ControlzEx.Standard;
-using ECCS.ViewModels;
+using LAEPS.ViewModels;
using Prism.Commands;
using Prism.Mvvm;
using System.Windows.Input;
-namespace BaseFrame.ViewModels.Dialogs
+namespace LAEPS.ViewModels.Dialogs
{
public class MessageBoxViewModel : DialogViewModelBase
{
diff --git a/LAEPS/ViewModels/LoginViewModel.cs b/LAEPS/ViewModels/LoginViewModel.cs
new file mode 100644
index 0000000..d577657
--- /dev/null
+++ b/LAEPS/ViewModels/LoginViewModel.cs
@@ -0,0 +1,40 @@
+using LAEPS.PubEvent;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace LAEPS.ViewModels
+{
+ public class LoginViewModel:BindableBase
+ {
+ #region 属性
+ private string _Password;
+ public string Password
+ {
+ get => _Password;
+ set => SetProperty(ref _Password, value);
+ }
+ private string _Account;
+ public string Account
+ {
+ get => _Account;
+ set => SetProperty(ref _Account, value);
+ }
+ #endregion
+ public ICommand LoginCommand { get; set; }
+ private IEventAggregator _eventAggregator;
+ public LoginViewModel(IContainerProvider containerProvider)
+ {
+ _eventAggregator = containerProvider.Resolve();
+ LoginCommand = new AsyncDelegateCommand(OnLogin);
+ }
+
+ private async Task OnLogin()
+ {
+ _eventAggregator.GetEvent().Publish();
+ }
+ }
+}
diff --git a/BaseFrame/ViewModels/MonitorViewModel.cs b/LAEPS/ViewModels/MainViewModel.cs
similarity index 61%
rename from BaseFrame/ViewModels/MonitorViewModel.cs
rename to LAEPS/ViewModels/MainViewModel.cs
index 20cb103..64a490a 100644
--- a/BaseFrame/ViewModels/MonitorViewModel.cs
+++ b/LAEPS/ViewModels/MainViewModel.cs
@@ -1,5 +1,6 @@
-using BaseFrame.PubEvent;
-using ECCS.ViewModels;
+using LAEPS.PubEvent;
+using LAEPS.ViewModels;
+using Logger;
using NLog;
using Prism.Dialogs;
using Prism.Events;
@@ -11,9 +12,9 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Input;
-namespace BaseFrame.ViewModels
+namespace LAEPS.ViewModels
{
- public class MonitorViewModel : NavigateViewModelBase
+ public class MainViewModel : NavigateViewModelBase
{
#region 属性
@@ -24,11 +25,14 @@ namespace BaseFrame.ViewModels
#endregion
- public MonitorViewModel(IContainerProvider containerProvider) : base(containerProvider)
+
+ public MainViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
-
-
+
}
+
+
+
#region 命令处理
diff --git a/BaseFrame/ViewModels/SettingViewModel.cs b/LAEPS/ViewModels/SettingViewModel.cs
similarity index 94%
rename from BaseFrame/ViewModels/SettingViewModel.cs
rename to LAEPS/ViewModels/SettingViewModel.cs
index 4c60100..c0b90a8 100644
--- a/BaseFrame/ViewModels/SettingViewModel.cs
+++ b/LAEPS/ViewModels/SettingViewModel.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace ECCS.ViewModels
+namespace LAEPS.ViewModels
{
public class SettingViewModel : NavigateViewModelBase
{
diff --git a/BaseFrame/ViewModels/ShellViewModel.cs b/LAEPS/ViewModels/ShellViewModel.cs
similarity index 73%
rename from BaseFrame/ViewModels/ShellViewModel.cs
rename to LAEPS/ViewModels/ShellViewModel.cs
index 24747f8..8bf4bc2 100644
--- a/BaseFrame/ViewModels/ShellViewModel.cs
+++ b/LAEPS/ViewModels/ShellViewModel.cs
@@ -1,6 +1,9 @@
-using BaseFrame.Views;
-
+using LAEPS.PubEvent;
+using LAEPS.Views;
using MaterialDesignThemes.Wpf;
+using Notifications.Wpf.Core;
+using Prism.Events;
+using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,7 +12,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
-namespace BaseFrame.ViewModels
+namespace LAEPS.ViewModels
{
public class ShellViewModel : BindableBase
{
@@ -29,29 +32,45 @@ namespace BaseFrame.ViewModels
public ICommand MaximizeCommand { get; set; }
public ICommand CloseCommand { get; set; }
public ICommand NavigateCommand { get; set; }
+ public ICommand LoadCommand { get; set; }
#endregion
private IEventAggregator _eventAggregator;
private IRegionManager _regionManager;
+ private IContainerProvider _containerProvider;
+ private INotificationManager _notificationManager;
public ShellViewModel( IContainerProvider containerProvider)
{
+ _containerProvider= containerProvider;
_eventAggregator = containerProvider.Resolve();
_regionManager = containerProvider.Resolve();
+ _notificationManager = containerProvider.Resolve();
LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
MinimizeCommand = new DelegateCommand(MinimizeWindow);
MaximizeCommand = new DelegateCommand(MaximizeWindow);
CloseCommand = new DelegateCommand(CloseWindow);
NavigateCommand = new DelegateCommand(Navigate);
-
+ LoadCommand = new DelegateCommand(Load);
+ //订阅登录成功事件
+ _eventAggregator.GetEvent().Subscribe(() =>
+ {
+ Application.Current.MainWindow.Show();
+ _regionManager.RequestNavigate("ShellViewManager", "MainView");
+ });
}
+
#region 命令处理
+ private void Load()
+ {
+ _notificationManager.ShowAsync(new NotificationContent { Title = "登录成功", Message = "", Type = NotificationType.Success });
+ }
private void Navigate(string content)
{
switch (content)
{
- case "监控界面":
- _regionManager.RequestNavigate("ShellViewManager", "MonitorView");
+ case "主界面":
+ _regionManager.RequestNavigate("ShellViewManager", "MainView");
break;
case "设置界面":
diff --git a/BaseFrame/ViewModels/UpdateInfoViewModel.cs b/LAEPS/ViewModels/UpdateInfoViewModel.cs
similarity index 95%
rename from BaseFrame/ViewModels/UpdateInfoViewModel.cs
rename to LAEPS/ViewModels/UpdateInfoViewModel.cs
index 54c3dd2..05a4dcd 100644
--- a/BaseFrame/ViewModels/UpdateInfoViewModel.cs
+++ b/LAEPS/ViewModels/UpdateInfoViewModel.cs
@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace ECCS.ViewModels
+namespace LAEPS.ViewModels
{
public class UpdateInfoViewModel : NavigateViewModelBase
{
diff --git a/BaseFrame/ViewModels/DialogViewModelBase.cs b/LAEPS/ViewModels/ViewModelBase/DialogViewModelBase.cs
similarity index 76%
rename from BaseFrame/ViewModels/DialogViewModelBase.cs
rename to LAEPS/ViewModels/ViewModelBase/DialogViewModelBase.cs
index a04a98c..885c041 100644
--- a/BaseFrame/ViewModels/DialogViewModelBase.cs
+++ b/LAEPS/ViewModels/ViewModelBase/DialogViewModelBase.cs
@@ -1,18 +1,21 @@
-using System;
+using Notifications.Wpf.Core;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace ECCS.ViewModels
+namespace LAEPS.ViewModels
{
public abstract class DialogViewModelBase : BindableBase,IDialogAware
{
- public IEventAggregator _eventAggregator;
public DialogCloseListener RequestClose { get; set; }
+ public IEventAggregator _eventAggregator;
+ private INotificationManager _notificationManager;
public DialogViewModelBase(IContainerProvider containerProvider)
{
_eventAggregator = containerProvider.Resolve();
+ _notificationManager = containerProvider.Resolve();
}
#region Dialog
diff --git a/BaseFrame/ViewModels/NavigateViewModelBase.cs b/LAEPS/ViewModels/ViewModelBase/NavigateViewModelBase.cs
similarity index 80%
rename from BaseFrame/ViewModels/NavigateViewModelBase.cs
rename to LAEPS/ViewModels/ViewModelBase/NavigateViewModelBase.cs
index e149c05..8629903 100644
--- a/BaseFrame/ViewModels/NavigateViewModelBase.cs
+++ b/LAEPS/ViewModels/ViewModelBase/NavigateViewModelBase.cs
@@ -1,21 +1,23 @@
-using System;
+using Notifications.Wpf.Core;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace ECCS.ViewModels
+namespace LAEPS.ViewModels
{
public abstract class NavigateViewModelBase : BindableBase, INavigationAware
{
public DialogCloseListener RequestClose { get; set; }
public IEventAggregator _eventAggregator;
public IDialogService _dialogService;
+ private INotificationManager _notificationManager;
public NavigateViewModelBase(IContainerProvider containerProvider)
{
_eventAggregator = containerProvider.Resolve();
_dialogService = containerProvider.Resolve();
-
+ _notificationManager = containerProvider.Resolve();
}
#region Navigation
diff --git a/BaseFrame/Views/Dialogs/MessageBoxView.xaml b/LAEPS/Views/Dialogs/MessageBoxView.xaml
similarity index 96%
rename from BaseFrame/Views/Dialogs/MessageBoxView.xaml
rename to LAEPS/Views/Dialogs/MessageBoxView.xaml
index 820701b..a486e26 100644
--- a/BaseFrame/Views/Dialogs/MessageBoxView.xaml
+++ b/LAEPS/Views/Dialogs/MessageBoxView.xaml
@@ -1,9 +1,9 @@
-
/// MessageBoxView.xaml 的交互逻辑
diff --git a/LAEPS/Views/LoginView.xaml b/LAEPS/Views/LoginView.xaml
new file mode 100644
index 0000000..4cb15e5
--- /dev/null
+++ b/LAEPS/Views/LoginView.xaml
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LAEPS/Views/LoginView.xaml.cs b/LAEPS/Views/LoginView.xaml.cs
new file mode 100644
index 0000000..4902938
--- /dev/null
+++ b/LAEPS/Views/LoginView.xaml.cs
@@ -0,0 +1,38 @@
+using LAEPS.PubEvent;
+using MahApps.Metro.Controls;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Text.RegularExpressions;
+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;
+using Path = System.IO.Path;
+
+namespace LAEPS.Views
+{
+ ///
+ /// Login.xaml 的交互逻辑
+ ///
+ public partial class LoginView : MetroWindow
+ {
+ public LoginView(IEventAggregator eventAggregator)
+ {
+ InitializeComponent();
+ //订阅登录成功事件
+ eventAggregator.GetEvent().Subscribe(() =>
+ {
+ this.Close();
+ });
+ }
+ }
+}
diff --git a/BaseFrame/Views/MonitorView.xaml b/LAEPS/Views/MainView.xaml
similarity index 91%
rename from BaseFrame/Views/MonitorView.xaml
rename to LAEPS/Views/MainView.xaml
index d704ee9..8c7b8c1 100644
--- a/BaseFrame/Views/MonitorView.xaml
+++ b/LAEPS/Views/MainView.xaml
@@ -1,4 +1,4 @@
-
-
+
diff --git a/BaseFrame/Views/MonitorView.xaml.cs b/LAEPS/Views/MainView.xaml.cs
similarity index 83%
rename from BaseFrame/Views/MonitorView.xaml.cs
rename to LAEPS/Views/MainView.xaml.cs
index 868f5eb..1fcbfd9 100644
--- a/BaseFrame/Views/MonitorView.xaml.cs
+++ b/LAEPS/Views/MainView.xaml.cs
@@ -13,14 +13,14 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace BaseFrame.Views
+namespace LAEPS.Views
{
///
/// MainView.xaml 的交互逻辑
///
- public partial class MonitorView : UserControl
+ public partial class MainView : UserControl
{
- public MonitorView()
+ public MainView()
{
InitializeComponent();
}
diff --git a/BaseFrame/Views/SettingView.xaml b/LAEPS/Views/SettingView.xaml
similarity index 92%
rename from BaseFrame/Views/SettingView.xaml
rename to LAEPS/Views/SettingView.xaml
index 4bd2b85..e945104 100644
--- a/BaseFrame/Views/SettingView.xaml
+++ b/LAEPS/Views/SettingView.xaml
@@ -1,4 +1,4 @@
-
/// SettingView.xaml 的交互逻辑
diff --git a/BaseFrame/Views/ShellView.xaml b/LAEPS/Views/ShellView.xaml
similarity index 86%
rename from BaseFrame/Views/ShellView.xaml
rename to LAEPS/Views/ShellView.xaml
index 59035b9..5ddea2f 100644
--- a/BaseFrame/Views/ShellView.xaml
+++ b/LAEPS/Views/ShellView.xaml
@@ -1,4 +1,4 @@
-
-
+
+
+
+
+
@@ -30,7 +34,7 @@
Margin="16"
Foreground="{DynamicResource PrimaryHueMidBrush}" />
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BaseFrame/Views/ShellView.xaml.cs b/LAEPS/Views/ShellView.xaml.cs
similarity index 96%
rename from BaseFrame/Views/ShellView.xaml.cs
rename to LAEPS/Views/ShellView.xaml.cs
index 37c458a..36b002a 100644
--- a/BaseFrame/Views/ShellView.xaml.cs
+++ b/LAEPS/Views/ShellView.xaml.cs
@@ -1,5 +1,4 @@
-using BaseFrame.PubEvent;
-
+using LAEPS.PubEvent;
using Prism.Events;
using System;
using System.Collections.Generic;
@@ -15,7 +14,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
-namespace BaseFrame.Views
+namespace LAEPS.Views
{
///
/// ShellView.xaml 的交互逻辑
diff --git a/BaseFrame/Views/UpdateInfoView.xaml b/LAEPS/Views/UpdateInfoView.xaml
similarity index 92%
rename from BaseFrame/Views/UpdateInfoView.xaml
rename to LAEPS/Views/UpdateInfoView.xaml
index de997aa..d49f995 100644
--- a/BaseFrame/Views/UpdateInfoView.xaml
+++ b/LAEPS/Views/UpdateInfoView.xaml
@@ -1,4 +1,4 @@
-
/// UpdateInfoView.xaml 的交互逻辑
diff --git a/Logger/LoggerHelper.cs b/Logger/LoggerHelper.cs
index 365cbec..f2b5646 100644
--- a/Logger/LoggerHelper.cs
+++ b/Logger/LoggerHelper.cs
@@ -13,6 +13,16 @@ namespace Logger
public static readonly ILogger Logger = LogManager.GetLogger("InfoLogger");
public static readonly ILogger sqlLogger = LogManager.GetLogger("SqlLogger");
+ public static void Error(string message, string stackTrace)
+ {
+ if (!string.IsNullOrEmpty(stackTrace))
+ {
+ string location = GetProjectStackLine(stackTrace);
+ message = $"{message} ({location})";
+ }
+
+ Logger.Error(message);
+ }
// 解析堆栈,找到项目文件路径和行号
public static string GetProjectStackLine(string stackTrace)
{
@@ -24,7 +34,7 @@ namespace Logger
foreach (var line in lines)
{
// 匹配你项目的命名空间路径
- if (line.Contains("BaseFrame"))
+ if (line.Contains("BOB"))
{
// 提取 "in 文件路径:line 行号"
var match = Regex.Match(line, @"in (.+?):line (\d+)");
@@ -38,5 +48,6 @@ namespace Logger
return lines[0].Trim(); // 如果找不到就返回第一条
}
+
}
}
diff --git a/Model/Entity/BaseEntity.cs b/Model/Entity/BaseEntity.cs
new file mode 100644
index 0000000..e04f252
--- /dev/null
+++ b/Model/Entity/BaseEntity.cs
@@ -0,0 +1,27 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Model.Entity
+{
+ public class BaseEntity
+ {
+ ///
+ /// 主键Id
+ ///
+ [SugarColumn(ColumnName = "id", ColumnDescription = "主键Id", IsPrimaryKey = true, CreateTableFieldSort = 0)]
+ public virtual long Id { get; set; }
+
+ ///
+ /// 删除状态
+ ///
+ [SugarColumn(ColumnName = "IsDel", ColumnDescription = "删除状态(0、未删除;1、已删除)", ColumnDataType = "tinyint", DefaultValue = "0", CreateTableFieldSort = 106)]
+ public virtual byte IsDel { get; set; }
+
+ [SugarColumn(ColumnName = "CreateTime")]
+ public DateTime CreateTime { get; set; }
+ }
+}
diff --git a/Model/Model.csproj b/Model/Model.csproj
index fa71b7a..b17c3e0 100644
--- a/Model/Model.csproj
+++ b/Model/Model.csproj
@@ -6,4 +6,12 @@
enable
+
+
+
+
+
+
+
+
diff --git a/ORM/DatabaseConfig.cs b/ORM/DatabaseConfig.cs
index 3df55bc..95b86c5 100644
--- a/ORM/DatabaseConfig.cs
+++ b/ORM/DatabaseConfig.cs
@@ -1,97 +1,132 @@
using SqlSugar;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+
+using System.IO;
+using System.Security.Cryptography;
namespace ORM
{
- public static class DatabaseConfig
+ public class DatabaseConfig
{
///
- /// 当前数据库类型
+ /// 数据库连接类型
///
public static DbType DbConnectionType { get; private set; }
///
- /// 数据库连接字符串
+ /// SQLite 数据库文件路径
///
public static string DbConnectionString { get; private set; }
///
- /// 默认 SQLite 文件路径(仅记录,不自动启用)
- ///
- public static string DefaultDbFilePath { get; private set; }
-
- ///
- /// 租户 Id
+ /// 数据租户Id
///
public static int TenantId { get; private set; }
+ ///
+ /// 雪花算法DatacenterId,值范围:0至31
+ ///
public static int SnowFlakeDatacenterId { get; private set; }
- public static int SnowFlakeWorkId { get; private set; }
-
- static DatabaseConfig()
- {
- InitDefaultDbPath(); // 只生成路径,不指定 DB 类型/连接
- }
///
- /// 生成默认 DB 路径 EXE目录/SQLDB/Data.db
+ /// 雪花算法WorkID,值范围:0至31
///
- private static void InitDefaultDbPath()
- {
- string baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ public static int SnowFlakeWorkId { get; private set; }
+ #region 不同数据库初始化方法
+ private static void InitSqlite()
+ {
+ DbConnectionType = DbType.Sqlite;
+ // 获取程序运行目录
+ string baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ // 确保 SQLDB 文件夹存在
string folder = Path.Combine(baseDir, "SQLDB");
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
- DefaultDbFilePath = Path.Combine(folder, "Data.db");
+ // 拼接数据库文件路径
+ string DBPath = Path.Combine(folder, "SQL.db");
+ DbConnectionString = $"Data Source={DBPath};Version=3;";
}
-
- ///
- /// 手动设置数据库连接
- ///
- public static void SetConnection(string conn, DbType dbType)
+ private static void InitMySql(string Server, int Port, string Database, string Uid,string Pwd)
{
- if (string.IsNullOrWhiteSpace(conn))
- throw new Exception("数据库连接字符串为空");
-
- DbConnectionString = conn;
- DbConnectionType = dbType;
+ DbConnectionType = DbType.MySql;
+ DbConnectionString =
+ $"Server={Server};Port={Port};Database={Database};Uid={Uid};Pwd={Pwd};";
}
-
- ///
- /// 如果未 SetConnection,默认使用 SQLite + 默认路径
- ///
- public static void EnsureConnection()
+ private static void InitSqlServer(string server,int port,string database,string user,string password)
{
- if (string.IsNullOrEmpty(DbConnectionString))
+ DbConnectionType = DbType.SqlServer;
+
+ DbConnectionString =
+ $"Data Source={server},{port};Initial Catalog={database};user={user};Password={password};";
+ }
+ private static void InitSqlServerLocalDb()
+ {
+ DbConnectionType = DbType.SqlServer;
+ string baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ // 确保 SQLDB 文件夹存在
+ string folder = Path.Combine(baseDir, "SQLDB");
+ if (!Directory.Exists(folder))
+ Directory.CreateDirectory(folder);
+
+ // 拼接数据库文件路径
+ string DBPath = Path.Combine(folder, "SQL.db");
+ DbConnectionString =$@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog={DBPath};Integrated Security=True;";
+ }
+ #endregion
+ ///
+ /// 设置数据库连接字符串(可手动覆盖)
+ ///
+ public static void SetDbConnection(string strConnection)
+ {
+ if (string.IsNullOrEmpty(strConnection))
{
- DbConnectionString = $"Data Source={DefaultDbFilePath};";
- DbConnectionType = DbType.Sqlite;
+ throw new Exception("数据库连接字符串为空");
}
+ DbConnectionString = strConnection;
}
///
- /// 设置租户并计算雪花算法节点
+ /// 设置数据租户Id
///
- public static void SetTenant(int tenantId)
+ public static void SetTenant(int nTenantId)
{
- if (tenantId <= 10000)
+ if (nTenantId <= 10000)
+ {
throw new Exception("数据租户Id值需大于10000");
+ }
+ TenantId = nTenantId;
+ SetSnowFlake((nTenantId - 10000) % 1024);
+ }
- TenantId = tenantId;
-
- int snowId = (tenantId - 10000) % 1024;
-
- if (snowId is < 0 or > 1023)
+ ///
+ /// 将指定数字转换为雪花算法DatacenterId和WorkID
+ ///
+ private static void SetSnowFlake(int nSnowFlakeId)
+ {
+ if (nSnowFlakeId > 1023 || nSnowFlakeId < 0)
+ {
throw new Exception("雪花算法机器码值范围0至1023");
-
- SnowFlakeDatacenterId = snowId >> 5;
- SnowFlakeWorkId = snowId & 31;
+ }
+ SnowFlakeDatacenterId = nSnowFlakeId >> 5;
+ SnowFlakeWorkId = nSnowFlakeId & 31;
+ }
+ ///
+ /// 检测数据库连接
+ ///
+ public static void CreateDatabaseAndCheckConnection(bool createDatabase = false, bool checkConnection = false)
+ {
+ //数据库不存在则创建数据库
+ if (createDatabase)
+ {
+ SqlSugarContext.DbContext.DbMaintenance.CreateDatabase();
+ }
+ // 检查数据库连接
+ if (checkConnection && !SqlSugarContext.DbContext.Ado.IsValidConnection())
+ {
+ throw new Exception("连接数据库失败");
+ }
}
}
}
diff --git a/ORM/ORM.csproj b/ORM/ORM.csproj
index 72f7a86..aa583b9 100644
--- a/ORM/ORM.csproj
+++ b/ORM/ORM.csproj
@@ -6,9 +6,7 @@
enable
-
-
-
+
diff --git a/ORM/SqlSugarContext.cs b/ORM/SqlSugarContext.cs
new file mode 100644
index 0000000..a5f383c
--- /dev/null
+++ b/ORM/SqlSugarContext.cs
@@ -0,0 +1,85 @@
+using Logger;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ORM
+{
+ public class SqlSugarContext
+ {
+ ///
+ /// SqlSugarScope单例模式
+ ///
+ public static readonly SqlSugarScope DbContext = new SqlSugarScope(
+ new ConnectionConfig()
+ {
+ DbType = DatabaseConfig.DbConnectionType,
+ ConnectionString = DatabaseConfig.DbConnectionString, // 连接符字串
+ //ConfigId = "Db1",//管理多个数据库
+ IsAutoCloseConnection = true, // 自动关闭连接
+ InitKeyType = InitKeyType.Attribute // 通过实体类上的特性初始化
+ },
+ db =>
+ {
+ // 执行超时时间,单位秒
+ db.Ado.CommandTimeOut = 30;
+
+ // 每次SQL执行前事件
+ db.Aop.OnLogExecuting = (sql, pars) =>
+ {
+#if DEBUG
+ // 确保 SQL 只通过 sqlLogger 记录
+ LoggerHelper.sqlLogger.Info("Executing SQL: {0} with parameters: {1}", sql, pars); // 使用 NLog 记录 SQL
+#endif
+ };
+
+ // SQL执行完
+ db.Aop.OnLogExecuted = (sql, pars) =>
+ {
+ // 执行时间超过1秒记录慢日志
+ if (db.Ado.SqlExecutionTime.TotalSeconds > 1)
+ {
+ LoggerHelper.sqlLogger.Warn("SQL Slow Execution. Time: {0}, File: {1}, Line: {2}, Method: {3}, SQL: {4}",
+ db.Ado.SqlExecutionTime.ToString(), // SQL 执行时间
+ db.Ado.SqlStackTrace.FirstFileName, // 代码 CS 文件名
+ db.Ado.SqlStackTrace.FirstLine, // 代码行数
+ db.Ado.SqlStackTrace.FirstMethodName, // 代码方法名
+ sql); // 使用 NLog 记录慢 SQL 日志
+ }
+ };
+
+ // SQL 报错
+ db.Aop.OnError = (exp) =>
+ {
+ // 确保 SQL 错误日志仅通过 sqlLogger 记录
+ LoggerHelper.sqlLogger.Error(exp, "SQL Error: {0}", exp.Sql); // 使用 NLog 记录 SQL 错误日志
+ };
+
+ // 数据过滤器:例如在新增数据时生成雪花 Id
+ db.Aop.DataExecuting = (oldValue, entityInfo) =>
+ {
+ // 新增操作
+ if (entityInfo.OperationType == DataFilterType.InsertByObject)
+ {
+ // 主键(long)赋值雪花 Id
+ if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
+ {
+ var id = ((dynamic)entityInfo.EntityValue).Id;
+ if (id == null || id == 0)
+ {
+ SnowFlakeSingle.WorkId = DatabaseConfig.SnowFlakeWorkId;
+ SnowFlakeSingle.DatacenterId = DatabaseConfig.SnowFlakeDatacenterId;
+ entityInfo.SetValue(SnowFlakeSingle.Instance.NextId());
+ }
+ }
+ }
+ };
+ }
+ );
+ }
+ }
+
+
diff --git a/ORM/SqlSugarRepository.cs b/ORM/SqlSugarRepository.cs
new file mode 100644
index 0000000..92512d3
--- /dev/null
+++ b/ORM/SqlSugarRepository.cs
@@ -0,0 +1,396 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ORM
+{
+ public partial class SqlSugarRepository : SimpleClient where TEntity : class, new()
+ {
+ ///
+ /// 实体集合
+ ///
+ public ISugarQueryable Entities => Context.Queryable();
+
+ ///
+ /// 构造函数
+ ///
+ public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
+ {
+ // 绑定数据库操作对象
+ Context = SqlSugarContext.DbContext;
+ // 备忘:GetConnectionScopeWithAttr会导致不能触发Aop.OnLogExecuting、Aop.OnLogExecuted等事件
+ // 详见:https://www.donet5.com/Home/Doc?typeId=2405(之2.1、方法说明)
+ // 详见:https://www.donet5.com/Home/Doc?typeId=2246(之2.2、根据特性获取)和(之4、多租户设置AOP)
+ // base.Context = SqlSugarContext.DbContext.GetConnectionScopeWithAttr();
+ // 根据特性获取,适合一个实体和库是一对一的情况
+ }
+
+
+ #region 查询
+ ///
+ /// 检查是否存在
+ ///
+ ///
+ ///
+ public bool IsExists(Expression> whereExpression)
+ {
+ return Entities.Any(whereExpression);
+ }
+
+ ///
+ /// 检查是否存在
+ ///
+ ///
+ ///
+ public async Task IsExistsAsync(Expression> whereExpression)
+ {
+ return await Entities.AnyAsync(whereExpression);
+ }
+
+ ///
+ /// 通过主键获取实体
+ ///
+ ///
+ ///
+ public TEntity Single(dynamic Id)
+ {
+ return Entities.InSingle(Id);
+ }
+
+ ///
+ /// 获取一个实体
+ ///
+ ///
+ ///
+ public TEntity Single(Expression> whereExpression)
+ {
+ return Entities.Single(whereExpression);
+ }
+
+ ///
+ /// 获取一个实体
+ ///
+ ///
+ ///
+ public Task SingleAsync(Expression> whereExpression)
+ {
+ return Entities.SingleAsync(whereExpression);
+ }
+
+ ///
+ /// 获取一个实体
+ ///
+ ///
+ ///
+ public TEntity FirstOrDefault(Expression> whereExpression)
+ {
+ return Entities.First(whereExpression);
+ }
+
+ ///
+ /// 获取一个实体
+ ///
+ ///
+ ///
+ public async Task FirstOrDefaultAsync(Expression> whereExpression)
+ {
+ return await Entities.FirstAsync(whereExpression);
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ public List ToList()
+ {
+ return Entities.ToList();
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ public Task> ToListAsync()
+ {
+ return Entities.ToListAsync();
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ ///
+ public List ToList(Expression> whereExpression)
+ {
+ return Entities.Where(whereExpression).ToList();
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ ///
+ public Task> ToListAsync(Expression> whereExpression)
+ {
+ return Entities.Where(whereExpression).ToListAsync();
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List ToList(Expression> whereExpression, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
+ {
+ return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToList();
+ }
+
+ ///
+ /// 获取列表
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Task> ToListAsync(Expression> whereExpression, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
+ {
+ return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
+ }
+ #endregion 查询
+
+
+ #region 新增
+ ///
+ /// 新增多条记录
+ ///
+ ///
+ ///
+ public int Insert(TEntity[] entities)
+ {
+ return Context.Insertable(entities).ExecuteCommand();
+ }
+
+ ///
+ /// 新增多条记录
+ ///
+ ///
+ ///
+ public Task InsertAsync(TEntity[] entities)
+ {
+ return Context.Insertable(entities).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 新增多条记录
+ ///
+ ///
+ ///
+ public int Insert(IEnumerable entities)
+ {
+ return Context.Insertable(entities.ToArray()).ExecuteCommand();
+ }
+
+ ///
+ /// 新增多条记录
+ ///
+ ///
+ ///
+ public Task InsertAsync(IEnumerable entities)
+ {
+ if (entities != null && entities.Any())
+ {
+ return Context.Insertable(entities.ToArray()).ExecuteCommandAsync();
+ }
+ return Task.FromResult(0);
+ }
+ #endregion 新增
+
+
+ #region 更新
+ ///
+ /// 更新单条记录指定列
+ ///
+ ///
+ ///
+ ///
+ public int Update(TEntity entity, object updateColumn)
+ {
+ return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
+ }
+
+ ///
+ /// 更新单条记录指定列
+ ///
+ ///
+ ///
+ ///
+ public Task UpdateAsync(TEntity entity, object updateColumn)
+ {
+ return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 更新单条记录指定列
+ ///
+ ///
+ ///
+ ///
+ ///
+ public int Update(TEntity entity, object updateColumn, Expression> whereExpression)
+ {
+ return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommand();
+ }
+
+ ///
+ /// 更新单条记录指定列
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Task UpdateAsync(TEntity entity, object updateColumn, Expression> whereExpression)
+ {
+ return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 更新多条记录
+ ///
+ ///
+ ///
+ public int Update(TEntity[] entities)
+ {
+ return Context.Updateable(entities).ExecuteCommand();
+ }
+
+ ///
+ /// 更新多条记录
+ ///
+ ///
+ ///
+ public Task UpdateAsync(TEntity[] entities)
+ {
+ return Context.Updateable(entities).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 更新多条记录指定列
+ ///
+ ///
+ ///
+ ///
+ public int Update(TEntity[] entities, object updateColumn)
+ {
+ return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
+ }
+
+ ///
+ /// 更新多条记录指定列
+ ///
+ ///
+ ///
+ ///
+ public Task UpdateAsync(TEntity[] entities, object updateColumn)
+ {
+ return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 合并指定更新列和附加更新列
+ ///
+ ///
+ ///
+ private string[] MergeUpdateColumns(object updateColumn)
+ {
+ List columnList = new List();
+ if (updateColumn.GetType() == typeof(string))
+ {
+ columnList.Add((string)updateColumn);
+ }
+ else if (updateColumn.GetType() == typeof(string[]))
+ {
+ columnList.AddRange((string[])updateColumn);
+ }
+ return columnList.ToArray();
+ }
+ #endregion 更新
+
+
+ #region 删除
+ ///
+ /// 删除一条记录
+ ///
+ ///
+ ///
+ public int Delete(object key)
+ {
+ return Context.Deleteable().In(key).ExecuteCommand();
+ }
+
+ ///
+ /// 删除一条记录
+ ///
+ ///
+ ///
+ public Task DeleteAsync(object key)
+ {
+ return Context.Deleteable().In(key).ExecuteCommandAsync();
+ }
+
+ ///
+ /// 删除多条记录
+ ///
+ ///
+ ///
+ public int Delete(object[] keys)
+ {
+ return Context.Deleteable().In(keys).ExecuteCommand();
+ }
+
+ ///
+ /// 删除多条记录
+ ///
+ ///
+ ///
+ public Task DeleteAsync(object[] keys)
+ {
+ return Context.Deleteable().In(keys).ExecuteCommandAsync();
+ }
+ #endregion 删除
+
+
+ #region 事务
+ ///
+ /// 开启事务
+ ///
+ public void BeginTran()
+ {
+ Context.Ado.BeginTran();
+ }
+
+ ///
+ /// 提交事务
+ ///
+ public void CommitTran()
+ {
+ Context.Ado.CommitTran();
+ }
+
+ ///
+ /// 回滚事务
+ ///
+ public void RollbackTran()
+ {
+ Context.Ado.RollbackTran();
+ }
+ #endregion 事务
+
+ }
+}
diff --git a/Service/APIService.cs b/Service/APIService.cs
deleted file mode 100644
index 48ab51d..0000000
--- a/Service/APIService.cs
+++ /dev/null
@@ -1,388 +0,0 @@
-using Common.DTOS;
-using NetTaste;
-using RestSharp;
-using SqlSugar;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Service
-{
- public class APIService
- {
-
- private static string Token = "Bearer u-cVaGe.hv160U5.zqxeyRKx11ifIR04iPjoayYQC00EXF";
- #region 表处理
- ///
- /// 初始化多维表格
- ///
- /// 表格名称
- public static FeishuResponse InitForm(string FormName)
- {
- try
- {
- var client = new RestClient("https://open.feishu.cn/open-apis/bitable/v1/apps");
- client.Timeout = -1;
- var request = new RestRequest(Method.POST);
- request.AddHeader("Content-Type", "application/json");
- request.AddHeader("Authorization", Token);
- request.AddParameter("application/json", ParameterType.RequestBody);
- request.AddJsonBody(new
- {
- folder_token = "",
- name = FormName
- });
- IRestResponse response = client.Execute(request);
- return Newtonsoft.Json.JsonConvert.DeserializeObject>(response.Content);
- }
- catch (Exception ex)
- {
- throw;
- }
-
- }
- ///
- /// 创建表
- ///
- /// 多维表格ID
- /// 表名称
- public static FeishuResponse AddTable(string FormID, string TableName)
- {
- try
- {
- var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables");
- client.Timeout = -1;
- var request = new RestRequest(Method.POST);
- request.AddHeader("Content-Type", "application/json");
- request.AddHeader("Authorization", Token);
- request.AddJsonBody(new
- {
- table = new
- {
- default_view_name = "默认的表格视图",
- name = TableName,
- fields = new object[]
- {
- new
- {
- field_name = "索引字段",
- type = 1
- },
- new
- {
- field_name = "单选",
- type = 3,
- ui_type = "SingleSelect",
- property = new
- {
- options = new[]
- {
- new { color = 0, name = "Enabled" },
- new { color = 1, name = "Disabled" },
- new { color = 2, name = "Draft" }
- }
- }
- }
- }
- }
- });
- request.AddParameter("application/json", ParameterType.RequestBody);
- IRestResponse response = client.Execute(request);
- return Newtonsoft.Json.JsonConvert.DeserializeObject>(response.Content);
- }
- catch (Exception ex)
- {
- throw;
- }
- }
- ///
- /// 删除表
- ///
- /// 多维表格ID
- /// 表ID
- public static FeishuResponse