框架优化
This commit is contained in:
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : PrismApplication
|
||||
{
|
||||
protected override Window CreateShell()
|
||||
{
|
||||
return Container.Resolve<ShellView>();
|
||||
}
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
var regionManager = Container.Resolve<IRegionManager>();
|
||||
regionManager.RequestNavigate("ShellViewManager", "MonitorView");
|
||||
}
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
//注册视图
|
||||
containerRegistry.RegisterForNavigation<MonitorView>("MonitorView");
|
||||
containerRegistry.RegisterForNavigation<SettingView>("SettingView");
|
||||
containerRegistry.RegisterForNavigation<UpdateInfoView>("UpdateInfoView");
|
||||
//注册弹窗
|
||||
containerRegistry.RegisterDialog<MessageBoxView, MessageBoxViewModel>("MessageBox");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 单例实例(首次访问自动从文件加载)
|
||||
/// </summary>
|
||||
public static MultidimensionalTableConfig Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = Load();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// exe 目录下的 config.json
|
||||
/// </summary>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
/// 保存到 config.json
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
File.WriteAllText(ConfigFilePath, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 config.json 加载
|
||||
/// </summary>
|
||||
private static MultidimensionalTableConfig Load()
|
||||
{
|
||||
if (!File.Exists(ConfigFilePath))
|
||||
{
|
||||
return new MultidimensionalTableConfig();
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(ConfigFilePath);
|
||||
return JsonConvert.DeserializeObject<MultidimensionalTableConfig>(json)
|
||||
?? new MultidimensionalTableConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Common.DTOS
|
||||
{
|
||||
public class FeishuResponse<T>
|
||||
{
|
||||
[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<string> 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<TableItem> 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
|
||||
{
|
||||
/// <summary>
|
||||
/// 字段数据(字段名 -> 值)
|
||||
/// </summary>
|
||||
[JsonProperty("fields")]
|
||||
public Dictionary<string, object> 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<RecordItem> 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<string, object> Fields { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 多行创建返回数据
|
||||
public class CreateRecordsRequest
|
||||
{
|
||||
[JsonProperty("records")]
|
||||
public List<CreateRecordItem> Records { get; set; }
|
||||
}
|
||||
public class CreateRecordItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 字段数据(字段名 -> 值)
|
||||
/// </summary>
|
||||
[JsonProperty("fields")]
|
||||
public Dictionary<string, object> Fields { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("record_id")]
|
||||
public string RecordId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
112
Common/MiniDump.cs
Normal file
112
Common/MiniDump.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,7 +1,7 @@
|
||||
<prism:PrismApplication x:Class="BaseFrame.App"
|
||||
<prism:PrismApplication x:Class="LAEPS.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BaseFrame"
|
||||
xmlns:local="clr-namespace:LAEPS"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/">
|
||||
<Application.Resources>
|
||||
69
LAEPS/App.xaml.cs
Normal file
69
LAEPS/App.xaml.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : PrismApplication
|
||||
{
|
||||
protected override Window CreateShell()
|
||||
{
|
||||
//UI线程未捕获异常处理事件
|
||||
this.DispatcherUnhandledException += OnDispatcherUnhandledException;
|
||||
//Task线程内未捕获异常处理事件
|
||||
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||
////多线程异常
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
return Container.Resolve<ShellView>();
|
||||
}
|
||||
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<LoginView>();
|
||||
login.Show();
|
||||
}
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
//注册视图
|
||||
containerRegistry.RegisterForNavigation<MainView>("MainView");
|
||||
containerRegistry.RegisterForNavigation<SettingView>("SettingView");
|
||||
containerRegistry.RegisterForNavigation<UpdateInfoView>("UpdateInfoView");
|
||||
//注册弹窗
|
||||
containerRegistry.RegisterDialog<MessageBoxView, MessageBoxViewModel>("MessageBox");
|
||||
// 注册通知管理器
|
||||
INotificationManager NotificationManager = new NotificationManager();
|
||||
containerRegistry.RegisterInstance<INotificationManager>(NotificationManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
52
LAEPS/Helpers/PasswordBoxHelper.cs
Normal file
52
LAEPS/Helpers/PasswordBoxHelper.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
<PackageReference Include="MaterialDesignThemes" Version="5.3.0" />
|
||||
<PackageReference Include="MaterialDesignThemes.MahApps" Version="5.3.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Notifications.Wpf.Core" Version="2.0.1" />
|
||||
<PackageReference Include="Prism.Unity" Version="9.0.537" />
|
||||
</ItemGroup>
|
||||
|
||||
12
LAEPS/PubEvent/LoginSuccessEvent.cs
Normal file
12
LAEPS/PubEvent/LoginSuccessEvent.cs
Normal file
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BaseFrame.PubEvent
|
||||
namespace LAEPS.PubEvent
|
||||
{
|
||||
public class OverlayEvent : PubSubEvent<bool>
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BaseFrame.PubEvent
|
||||
namespace LAEPS.PubEvent
|
||||
{
|
||||
public class WaitingEvent : PubSubEvent<bool>
|
||||
{
|
||||
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -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
|
||||
{
|
||||
40
LAEPS/ViewModels/LoginViewModel.cs
Normal file
40
LAEPS/ViewModels/LoginViewModel.cs
Normal file
@@ -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<IEventAggregator>();
|
||||
LoginCommand = new AsyncDelegateCommand(OnLogin);
|
||||
}
|
||||
|
||||
private async Task OnLogin()
|
||||
{
|
||||
_eventAggregator.GetEvent<LoginSuccessEvent>().Publish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 命令处理
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ECCS.ViewModels
|
||||
namespace LAEPS.ViewModels
|
||||
{
|
||||
public class SettingViewModel : NavigateViewModelBase
|
||||
{
|
||||
@@ -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<IEventAggregator>();
|
||||
_regionManager = containerProvider.Resolve<IRegionManager>();
|
||||
_notificationManager = containerProvider.Resolve<INotificationManager>();
|
||||
LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
|
||||
MinimizeCommand = new DelegateCommand<Window>(MinimizeWindow);
|
||||
MaximizeCommand = new DelegateCommand<Window>(MaximizeWindow);
|
||||
CloseCommand = new DelegateCommand<Window>(CloseWindow);
|
||||
NavigateCommand = new DelegateCommand<string>(Navigate);
|
||||
|
||||
LoadCommand = new DelegateCommand(Load);
|
||||
//订阅登录成功事件
|
||||
_eventAggregator.GetEvent<LoginSuccessEvent>().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 "设置界面":
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ECCS.ViewModels
|
||||
namespace LAEPS.ViewModels
|
||||
{
|
||||
public class UpdateInfoViewModel : NavigateViewModelBase
|
||||
{
|
||||
@@ -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<IEventAggregator>();
|
||||
_notificationManager = containerProvider.Resolve<INotificationManager>();
|
||||
}
|
||||
#region Dialog
|
||||
|
||||
@@ -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<IEventAggregator>();
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
|
||||
_notificationManager = containerProvider.Resolve<INotificationManager>();
|
||||
}
|
||||
|
||||
#region Navigation
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl x:Class="BaseFrame.Views.Dialogs.MessageBoxView"
|
||||
<UserControl x:Class="LAEPS.Views.Dialogs.MessageBoxView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BaseFrame.Views.Dialogs"
|
||||
xmlns:local="clr-namespace:LAEPS.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
@@ -13,7 +13,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BaseFrame.Views.Dialogs
|
||||
namespace LAEPS.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// MessageBoxView.xaml 的交互逻辑
|
||||
151
LAEPS/Views/LoginView.xaml
Normal file
151
LAEPS/Views/LoginView.xaml
Normal file
@@ -0,0 +1,151 @@
|
||||
<mah:MetroWindow xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:helpers="clr-namespace:LAEPS.Helpers"
|
||||
x:Class="LAEPS.Views.LoginView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
xmlns:local="clr-namespace:LAEPS.Views"
|
||||
mc:Ignorable="d"
|
||||
Title="学习交流平台"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Height="315"
|
||||
Width="420"
|
||||
ResizeMode="NoResize">
|
||||
|
||||
<Window.Resources>
|
||||
<Style TargetType="TextBox"
|
||||
BasedOn="{StaticResource MahApps.Styles.TextBox}">
|
||||
<Setter Property="FontSize"
|
||||
Value="14" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0,0,0,2" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="#E0E0E0" />
|
||||
<Setter Property="Padding"
|
||||
Value="5,8" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="PasswordBox"
|
||||
BasedOn="{StaticResource MahApps.Styles.PasswordBox}">
|
||||
<Setter Property="FontSize"
|
||||
Value="14" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0,0,0,2" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="#E0E0E0" />
|
||||
<Setter Property="Padding"
|
||||
Value="5,8" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button"
|
||||
BasedOn="{StaticResource MahApps.Styles.Button.Flat}">
|
||||
<Setter Property="FontSize"
|
||||
Value="15" />
|
||||
<Setter Property="FontWeight"
|
||||
Value="SemiBold" />
|
||||
<Setter Property="Foreground"
|
||||
Value="White" />
|
||||
<Setter Property="Background"
|
||||
Value="#2196F3" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Margin"
|
||||
Value="0,20,0,0" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 表单区域 -->
|
||||
<Border Grid.Row="0"
|
||||
Background="White"
|
||||
Margin="20,20,20,0"
|
||||
CornerRadius="5"
|
||||
BorderThickness="1"
|
||||
BorderBrush="#E0E0E0"
|
||||
Padding="30,20">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<Label Content="用户登录"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="15"
|
||||
Padding="3" />
|
||||
<StackPanel Grid.Row="1">
|
||||
|
||||
<!-- 用户名输入 -->
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="17">
|
||||
<materialDesign:PackIcon Kind="Account" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding Account}"
|
||||
mah:TextBoxHelper.Watermark="请输入账号"
|
||||
mah:TextBoxHelper.ClearTextButton="True"
|
||||
VerticalContentAlignment="Center"
|
||||
Width="180"
|
||||
Height="30"
|
||||
Padding="0" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 密码输入 -->
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="7">
|
||||
<materialDesign:PackIcon Kind="Lock"
|
||||
VerticalAlignment="Center" />
|
||||
<PasswordBox helpers:PasswordBoxHelper.Password="{Binding Password, Mode=TwoWay}"
|
||||
mah:TextBoxHelper.Watermark="请输入密码"
|
||||
mah:TextBoxHelper.ClearTextButton="True"
|
||||
VerticalContentAlignment="Center"
|
||||
Width="180"
|
||||
Height="30"
|
||||
Padding="0" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<Button Grid.Row="2"
|
||||
Command="{Binding LoginCommand}"
|
||||
Content="登 录"
|
||||
Width="120"
|
||||
Height="33"
|
||||
mah:ControlsHelper.CornerRadius="5">
|
||||
<Button.Effect>
|
||||
<DropShadowEffect BlurRadius="8"
|
||||
ShadowDepth="3"
|
||||
Opacity="0.5" />
|
||||
</Button.Effect>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 底部版权信息 -->
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="© 2025 大学生学习交流平台"
|
||||
Foreground="#777"
|
||||
FontSize="12"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,10" />
|
||||
</Grid>
|
||||
</mah:MetroWindow>
|
||||
38
LAEPS/Views/LoginView.xaml.cs
Normal file
38
LAEPS/Views/LoginView.xaml.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Login.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LoginView : MetroWindow
|
||||
{
|
||||
public LoginView(IEventAggregator eventAggregator)
|
||||
{
|
||||
InitializeComponent();
|
||||
//订阅登录成功事件
|
||||
eventAggregator.GetEvent<LoginSuccessEvent>().Subscribe(() =>
|
||||
{
|
||||
this.Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="BaseFrame.Views.MonitorView"
|
||||
<UserControl x:Class="LAEPS.Views.MainView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -13,14 +13,14 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BaseFrame.Views
|
||||
namespace LAEPS.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// MainView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MonitorView : UserControl
|
||||
public partial class MainView : UserControl
|
||||
{
|
||||
public MonitorView()
|
||||
public MainView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="ECCS.Views.SettingView"
|
||||
<UserControl x:Class="LAEPS.Views.SettingView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -13,7 +13,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ECCS.Views
|
||||
namespace LAEPS.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// SettingView.xaml 的交互逻辑
|
||||
@@ -1,4 +1,4 @@
|
||||
<Window x:Class="BaseFrame.Views.ShellView"
|
||||
<Window x:Class="LAEPS.Views.ShellView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -17,7 +17,11 @@
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome GlassFrameThickness="-1" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding LoadCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<materialDesign:DrawerHost x:Name="MainDrawerHost"
|
||||
IsLeftDrawerOpen="{Binding IsLeftDrawerOpen, Mode=TwoWay}">
|
||||
|
||||
@@ -30,7 +34,7 @@
|
||||
Margin="16"
|
||||
Foreground="{DynamicResource PrimaryHueMidBrush}" />
|
||||
<Separator Margin="0,0,0,8" />
|
||||
<Button Content="监控界面"
|
||||
<Button Content="主界面"
|
||||
Command="{Binding NavigateCommand}"
|
||||
CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
@@ -87,29 +91,9 @@
|
||||
<materialDesign:PackIcon Kind="Tools"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="系统设置"
|
||||
<MenuItem Header="注销登录"
|
||||
|
||||
Foreground="Black" />
|
||||
<MenuItem Header="数据"
|
||||
Foreground="Black">
|
||||
<MenuItem Header="数据查询"
|
||||
Foreground="Black" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="同星CAN"
|
||||
Foreground="Black">
|
||||
<MenuItem Header="连接/断开"
|
||||
Foreground="Black" />
|
||||
<MenuItem Header="通道映射"
|
||||
Foreground="Black" />
|
||||
<MenuItem Header="加载数据库"
|
||||
Foreground="Black" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="调试"
|
||||
Foreground="Black">
|
||||
<MenuItem Header="自动运行"
|
||||
Foreground="Black" />
|
||||
<MenuItem Header="清空数据库"
|
||||
Foreground="Black" />
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// ShellView.xaml 的交互逻辑
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="ECCS.Views.UpdateInfoView"
|
||||
<UserControl x:Class="LAEPS.Views.UpdateInfoView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -13,7 +13,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ECCS.Views
|
||||
namespace LAEPS.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// UpdateInfoView.xaml 的交互逻辑
|
||||
@@ -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(); // 如果找不到就返回第一条
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
27
Model/Entity/BaseEntity.cs
Normal file
27
Model/Entity/BaseEntity.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键Id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "id", ColumnDescription = "主键Id", IsPrimaryKey = true, CreateTableFieldSort = 0)]
|
||||
public virtual long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 删除状态
|
||||
/// </summary>
|
||||
[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; }
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,12 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DTOS\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前数据库类型
|
||||
/// 数据库连接类型
|
||||
/// </summary>
|
||||
public static DbType DbConnectionType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库连接字符串
|
||||
/// SQLite 数据库文件路径
|
||||
/// </summary>
|
||||
public static string DbConnectionString { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认 SQLite 文件路径(仅记录,不自动启用)
|
||||
/// </summary>
|
||||
public static string DefaultDbFilePath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户 Id
|
||||
/// 数据租户Id
|
||||
/// </summary>
|
||||
public static int TenantId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 雪花算法DatacenterId,值范围:0至31
|
||||
/// </summary>
|
||||
public static int SnowFlakeDatacenterId { get; private set; }
|
||||
public static int SnowFlakeWorkId { get; private set; }
|
||||
|
||||
static DatabaseConfig()
|
||||
{
|
||||
InitDefaultDbPath(); // 只生成路径,不指定 DB 类型/连接
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成默认 DB 路径 EXE目录/SQLDB/Data.db
|
||||
/// 雪花算法WorkID,值范围:0至31
|
||||
/// </summary>
|
||||
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;";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动设置数据库连接
|
||||
/// </summary>
|
||||
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};";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果未 SetConnection,默认使用 SQLite + 默认路径
|
||||
/// </summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// 设置数据库连接字符串(可手动覆盖)
|
||||
/// </summary>
|
||||
public static void SetDbConnection(string strConnection)
|
||||
{
|
||||
if (string.IsNullOrEmpty(strConnection))
|
||||
{
|
||||
DbConnectionString = $"Data Source={DefaultDbFilePath};";
|
||||
DbConnectionType = DbType.Sqlite;
|
||||
throw new Exception("数据库连接字符串为空");
|
||||
}
|
||||
DbConnectionString = strConnection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置租户并计算雪花算法节点
|
||||
/// 设置数据租户Id
|
||||
/// </summary>
|
||||
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)
|
||||
/// <summary>
|
||||
/// 将指定数字转换为雪花算法DatacenterId和WorkID
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 检测数据库连接
|
||||
/// </summary>
|
||||
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("连接数据库失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.206" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Logger\Logger.csproj" />
|
||||
|
||||
85
ORM/SqlSugarContext.cs
Normal file
85
ORM/SqlSugarContext.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// SqlSugarScope单例模式
|
||||
/// </summary>
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
396
ORM/SqlSugarRepository.cs
Normal file
396
ORM/SqlSugarRepository.cs
Normal file
@@ -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<TEntity> : SimpleClient<TEntity> where TEntity : class, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// 实体集合
|
||||
/// </summary>
|
||||
public ISugarQueryable<TEntity> Entities => Context.Queryable<TEntity>();
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
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<TEntity>();
|
||||
// 根据特性获取,适合一个实体和库是一对一的情况
|
||||
}
|
||||
|
||||
|
||||
#region 查询
|
||||
/// <summary>
|
||||
/// 检查是否存在
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsExists(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.Any(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> IsExistsAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await Entities.AnyAsync(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过主键获取实体
|
||||
/// </summary>
|
||||
/// <param name="Id"></param>
|
||||
/// <returns></returns>
|
||||
public TEntity Single(dynamic Id)
|
||||
{
|
||||
return Entities.InSingle(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个实体
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public TEntity Single(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.Single(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个实体
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.SingleAsync(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个实体
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.First(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个实体
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return await Entities.FirstAsync(whereExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<TEntity> ToList()
|
||||
{
|
||||
return Entities.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<List<TEntity>> ToListAsync()
|
||||
{
|
||||
return Entities.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.Where(whereExpression).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Entities.Where(whereExpression).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <param name="orderByExpression"></param>
|
||||
/// <param name="orderByType"></param>
|
||||
/// <returns></returns>
|
||||
public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
|
||||
{
|
||||
return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表
|
||||
/// </summary>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <param name="orderByExpression"></param>
|
||||
/// <param name="orderByType"></param>
|
||||
/// <returns></returns>
|
||||
public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
|
||||
{
|
||||
return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
|
||||
}
|
||||
#endregion 查询
|
||||
|
||||
|
||||
#region 新增
|
||||
/// <summary>
|
||||
/// 新增多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public int Insert(TEntity[] entities)
|
||||
{
|
||||
return Context.Insertable(entities).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> InsertAsync(TEntity[] entities)
|
||||
{
|
||||
return Context.Insertable(entities).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public int Insert(IEnumerable<TEntity> entities)
|
||||
{
|
||||
return Context.Insertable(entities.ToArray()).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> InsertAsync(IEnumerable<TEntity> entities)
|
||||
{
|
||||
if (entities != null && entities.Any())
|
||||
{
|
||||
return Context.Insertable(entities.ToArray()).ExecuteCommandAsync();
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
#endregion 新增
|
||||
|
||||
|
||||
#region 更新
|
||||
/// <summary>
|
||||
/// 更新单条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(TEntity entity, object updateColumn)
|
||||
{
|
||||
return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新单条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> UpdateAsync(TEntity entity, object updateColumn)
|
||||
{
|
||||
return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新单条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(TEntity entity, object updateColumn, Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新单条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <param name="whereExpression"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> UpdateAsync(TEntity entity, object updateColumn, Expression<Func<TEntity, bool>> whereExpression)
|
||||
{
|
||||
return Context.Updateable(entity).UpdateColumns(MergeUpdateColumns(updateColumn)).Where(whereExpression).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(TEntity[] entities)
|
||||
{
|
||||
return Context.Updateable(entities).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新多条记录
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> UpdateAsync(TEntity[] entities)
|
||||
{
|
||||
return Context.Updateable(entities).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新多条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(TEntity[] entities, object updateColumn)
|
||||
{
|
||||
return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新多条记录指定列
|
||||
/// </summary>
|
||||
/// <param name="entities"></param>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> UpdateAsync(TEntity[] entities, object updateColumn)
|
||||
{
|
||||
return Context.Updateable(entities).UpdateColumns(MergeUpdateColumns(updateColumn)).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并指定更新列和附加更新列
|
||||
/// </summary>
|
||||
/// <param name="updateColumn"></param>
|
||||
/// <returns></returns>
|
||||
private string[] MergeUpdateColumns(object updateColumn)
|
||||
{
|
||||
List<string> columnList = new List<string>();
|
||||
if (updateColumn.GetType() == typeof(string))
|
||||
{
|
||||
columnList.Add((string)updateColumn);
|
||||
}
|
||||
else if (updateColumn.GetType() == typeof(string[]))
|
||||
{
|
||||
columnList.AddRange((string[])updateColumn);
|
||||
}
|
||||
return columnList.ToArray();
|
||||
}
|
||||
#endregion 更新
|
||||
|
||||
|
||||
#region 删除
|
||||
/// <summary>
|
||||
/// 删除一条记录
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public int Delete(object key)
|
||||
{
|
||||
return Context.Deleteable<TEntity>().In(key).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除一条记录
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> DeleteAsync(object key)
|
||||
{
|
||||
return Context.Deleteable<TEntity>().In(key).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除多条记录
|
||||
/// </summary>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public int Delete(object[] keys)
|
||||
{
|
||||
return Context.Deleteable<TEntity>().In(keys).ExecuteCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除多条记录
|
||||
/// </summary>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public Task<int> DeleteAsync(object[] keys)
|
||||
{
|
||||
return Context.Deleteable<TEntity>().In(keys).ExecuteCommandAsync();
|
||||
}
|
||||
#endregion 删除
|
||||
|
||||
|
||||
#region 事务
|
||||
/// <summary>
|
||||
/// 开启事务
|
||||
/// </summary>
|
||||
public void BeginTran()
|
||||
{
|
||||
Context.Ado.BeginTran();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提交事务
|
||||
/// </summary>
|
||||
public void CommitTran()
|
||||
{
|
||||
Context.Ado.CommitTran();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回滚事务
|
||||
/// </summary>
|
||||
public void RollbackTran()
|
||||
{
|
||||
Context.Ado.RollbackTran();
|
||||
}
|
||||
#endregion 事务
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 表处理
|
||||
/// <summary>
|
||||
/// 初始化多维表格
|
||||
/// </summary>
|
||||
/// <param name="FormName">表格名称</param>
|
||||
public static FeishuResponse<CreateBitableAppData> 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<FeishuResponse<CreateBitableAppData>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建表
|
||||
/// </summary>
|
||||
/// <param name="FormName">多维表格ID</param>
|
||||
/// <param name="FormName">表名称</param>
|
||||
public static FeishuResponse<CreateTableData> 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<FeishuResponse<CreateTableData>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除表
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
public static FeishuResponse<object> DeleteTable(string FormID, string TabelID)
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TabelID}");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.DELETE);
|
||||
request.AddHeader("Authorization", Token);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<object>>(response.Content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获得表列表
|
||||
/// </summary>
|
||||
/// <param name="FormName">多维表格ID</param>
|
||||
/// <param name="FormName">分页数</param>
|
||||
/// <param name="FormName">表ID</param>
|
||||
public static FeishuResponse<QueryTableListData> GetTableList(string FormID, int PageSize, string TabelID = "")
|
||||
{
|
||||
RestClient client;
|
||||
if (TabelID == "")
|
||||
{
|
||||
client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables?page_size={PageSize}");
|
||||
}
|
||||
else
|
||||
{
|
||||
client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables?page_size={PageSize}&page_token={TabelID}");
|
||||
}
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.GET);
|
||||
request.AddHeader("Authorization", Token);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<QueryTableListData>>(response.Content);
|
||||
}
|
||||
#endregion
|
||||
#region 行处理
|
||||
|
||||
/// <summary>
|
||||
/// 添加一行记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
public static FeishuResponse<CreateRecordData> AddRecord(string FormID, string TableID)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.POST);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", Token);
|
||||
request.AddJsonBody(new
|
||||
{
|
||||
fields = new
|
||||
{
|
||||
单选 = "333",
|
||||
索引字段 = "拜访潜在客户"
|
||||
}
|
||||
});
|
||||
request.AddParameter("application/json", ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<CreateRecordData>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新一行记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
/// <param name="TabelID">记录ID</param>
|
||||
public static FeishuResponse<CreateRecordData> UpdateRecord(string FormID, string TableID, string RecordID)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/{RecordID}");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.PUT);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", Token);
|
||||
request.AddJsonBody(new
|
||||
{
|
||||
fields = new
|
||||
{
|
||||
单选 = "99",
|
||||
索引字段 = "mike"
|
||||
}
|
||||
});
|
||||
request.AddParameter("application/json", ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<CreateRecordData>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
/// <param name="TabelID">记录ID</param>
|
||||
public static FeishuResponse<object> DeleteRecord(string FormID, string TableID, string RecordID)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/{RecordID}");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.DELETE);
|
||||
request.AddHeader("Authorization", Token);
|
||||
var body = "";
|
||||
request.AddParameter("", body, ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<object>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
/// <param name="TabelID">分页数量</param>
|
||||
public static FeishuResponse<QueryRecordListData> GetRecord(string FormID, string TableID, int PageSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/search?page_size={PageSize}");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.POST);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", "Bearer u-dSpI1fRVp2jWi4Nyz0lIkal5i0n504UVMUaaYNy021um");
|
||||
var body = "{}";
|
||||
request.AddParameter("application/json", body, ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<QueryRecordListData>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 多行处理
|
||||
/// <summary>
|
||||
/// 添加多行记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
public static FeishuResponse<CreateRecordsRequest> AddMutipulRecords(string FormID, string TableID)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/batch_create");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.POST);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", Token);
|
||||
request.AddJsonBody(new
|
||||
{
|
||||
records = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
fields = new
|
||||
{
|
||||
单选 = "333",
|
||||
索引字段 = "拜访潜在客户1"
|
||||
}
|
||||
},
|
||||
new
|
||||
{
|
||||
fields = new
|
||||
{
|
||||
单选 = "333",
|
||||
索引字段 = "拜访潜在客户2"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
request.AddParameter("application/json", ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<CreateRecordsRequest>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新多行记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
/// <param name="FieldIDs">记录ID列表</param>
|
||||
public static FeishuResponse<CreateRecordsRequest> UpdateRecords(string FormID, string TableID, string[] FieldIDs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/batch_update");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.POST);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", Token);
|
||||
request.AddJsonBody(new
|
||||
{
|
||||
records = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
record_id=FieldIDs[0],
|
||||
fields = new
|
||||
{
|
||||
单选 = "333",
|
||||
索引字段 = "改拜访潜在客户1"
|
||||
}
|
||||
},
|
||||
new
|
||||
{
|
||||
record_id=FieldIDs[1],
|
||||
fields = new
|
||||
{
|
||||
单选 = "333",
|
||||
索引字段 = "改拜访潜在客户2"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
request.AddParameter("application/json", ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<CreateRecordsRequest>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除多行记录
|
||||
/// </summary>
|
||||
/// <param name="FormID">多维表格ID</param>
|
||||
/// <param name="TabelID">表ID</param>
|
||||
/// <param name="FieldIDs">记录ID列表</param>
|
||||
public static FeishuResponse<object> DeleteRecords(string FormID, string TableID, string[] FieldIDs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new RestClient($"https://open.feishu.cn/open-apis/bitable/v1/apps/{FormID}/tables/{TableID}/records/batch_delete");
|
||||
client.Timeout = -1;
|
||||
var request = new RestRequest(Method.POST);
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Authorization", Token);
|
||||
request.AddJsonBody(new
|
||||
{
|
||||
records = FieldIDs
|
||||
});
|
||||
request.AddParameter("application/json", ParameterType.RequestBody);
|
||||
IRestResponse response = client.Execute(request);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<FeishuResponse<object>>(response.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user