A:增加数据持久化

This commit is contained in:
jimmy committed 2025-08-09 10:00:20 +08:00
1 parent b110c2a735
commit 1023832c7b
7 files changed
+129 -39

No files matched your search

+12 -12
View File
@@ -72,12 +72,12 @@ public class NetVizorDbContext : IDisposable
IsPositionLocked INTEGER DEFAULT 0, IsPositionLocked INTEGER DEFAULT 0,
SnapToScreen INTEGER DEFAULT 0, SnapToScreen INTEGER DEFAULT 0,
ShowDetailedInfo INTEGER DEFAULT 0, ShowDetailedInfo INTEGER DEFAULT 0,
IsTopmost INTEGER DEFAULT 0, IsTopmost INTEGER DEFAULT 1,
TextColor TEXT DEFAULT '#FFFFFF', TextColor TEXT DEFAULT '#333333',
BackgroundColor TEXT DEFAULT '#000000', BackgroundColor TEXT DEFAULT '#F0FFFFFF',
Opacity INTEGER DEFAULT 100, Opacity INTEGER DEFAULT 94,
SpeedUnit INTEGER DEFAULT 1, SpeedUnit INTEGER DEFAULT 3,
LayoutDirection INTEGER DEFAULT 0, LayoutDirection INTEGER DEFAULT 1,
ShowUnit INTEGER DEFAULT 1, ShowUnit INTEGER DEFAULT 1,
DoubleClickAction INTEGER DEFAULT 0, DoubleClickAction INTEGER DEFAULT 0,
RunAsAdmin INTEGER DEFAULT 0, RunAsAdmin INTEGER DEFAULT 0,
@@ -308,12 +308,12 @@ public class NetVizorDbContext : IDisposable
IsPositionLocked INTEGER DEFAULT 0, IsPositionLocked INTEGER DEFAULT 0,
SnapToScreen INTEGER DEFAULT 0, SnapToScreen INTEGER DEFAULT 0,
ShowDetailedInfo INTEGER DEFAULT 0, ShowDetailedInfo INTEGER DEFAULT 0,
IsTopmost INTEGER DEFAULT 0, IsTopmost INTEGER DEFAULT 1,
TextColor TEXT DEFAULT '#FFFFFF', TextColor TEXT DEFAULT '#333333',
BackgroundColor TEXT DEFAULT '#000000', BackgroundColor TEXT DEFAULT '#F0FFFFFF',
Opacity INTEGER DEFAULT 100, Opacity INTEGER DEFAULT 94,
SpeedUnit INTEGER DEFAULT 1, SpeedUnit INTEGER DEFAULT 3,
LayoutDirection INTEGER DEFAULT 0, LayoutDirection INTEGER DEFAULT 1,
ShowUnit INTEGER DEFAULT 1, ShowUnit INTEGER DEFAULT 1,
DoubleClickAction INTEGER DEFAULT 0, DoubleClickAction INTEGER DEFAULT 0,
RunAsAdmin INTEGER DEFAULT 0, RunAsAdmin INTEGER DEFAULT 0,
@@ -33,12 +33,12 @@ public class AppSettingRepository : IAppSettingRepository
INSERT INTO AppSetting ( INSERT INTO AppSetting (
WindowX, WindowY, IsClickThrough, IsPositionLocked, SnapToScreen, ShowDetailedInfo, WindowX, WindowY, IsClickThrough, IsPositionLocked, SnapToScreen, ShowDetailedInfo,
IsTopmost, TextColor, BackgroundColor, Opacity, SpeedUnit, LayoutDirection, IsTopmost, TextColor, BackgroundColor, Opacity, SpeedUnit, LayoutDirection,
ShowUnit, DoubleClickAction, RunAsAdmin, AutoStart, UpdateTime ShowUnit, DoubleClickAction, RunAsAdmin, AutoStart, ShowNetworkTopList, NetworkTopListCount, UpdateTime
) )
VALUES ( VALUES (
@WindowX, @WindowY, @IsClickThrough, @IsPositionLocked, @SnapToScreen, @ShowDetailedInfo, @WindowX, @WindowY, @IsClickThrough, @IsPositionLocked, @SnapToScreen, @ShowDetailedInfo,
@IsTopmost, @TextColor, @BackgroundColor, @Opacity, @SpeedUnit, @LayoutDirection, @IsTopmost, @TextColor, @BackgroundColor, @Opacity, @SpeedUnit, @LayoutDirection,
@ShowUnit, @DoubleClickAction, @RunAsAdmin, @AutoStart, @UpdateTime @ShowUnit, @DoubleClickAction, @RunAsAdmin, @AutoStart, @ShowNetworkTopList, @NetworkTopListCount, @UpdateTime
)"; )";
var result = await _context.Connection.ExecuteAsync(sql, setting); var result = await _context.Connection.ExecuteAsync(sql, setting);
@@ -63,7 +63,7 @@ public class AppSettingRepository : IAppSettingRepository
TextColor = @TextColor, BackgroundColor = @BackgroundColor, Opacity = @Opacity, TextColor = @TextColor, BackgroundColor = @BackgroundColor, Opacity = @Opacity,
SpeedUnit = @SpeedUnit, LayoutDirection = @LayoutDirection, ShowUnit = @ShowUnit, SpeedUnit = @SpeedUnit, LayoutDirection = @LayoutDirection, ShowUnit = @ShowUnit,
DoubleClickAction = @DoubleClickAction, RunAsAdmin = @RunAsAdmin, DoubleClickAction = @DoubleClickAction, RunAsAdmin = @RunAsAdmin,
AutoStart = @AutoStart, UpdateTime = @UpdateTime AutoStart = @AutoStart, ShowNetworkTopList = @ShowNetworkTopList, NetworkTopListCount = @NetworkTopListCount, UpdateTime = @UpdateTime
WHERE Id = @Id"; WHERE Id = @Id";
return await _context.Connection.ExecuteAsync(sql, setting); return await _context.Connection.ExecuteAsync(sql, setting);
@@ -54,21 +54,21 @@ public class DataService : IDataService, IDisposable
if (setting == null) if (setting == null)
{ {
// 创建默认设置 // 创建默认设置 - 与 SettingsWindow.xaml 中的默认值保持一致
setting = new AppSetting setting = new AppSetting
{ {
WindowX = 100, WindowX = 0, // 0表示使用默认位置
WindowY = 100, WindowY = 0,
IsClickThrough = false, IsClickThrough = false,
IsPositionLocked = false, IsPositionLocked = false,
SnapToScreen = false, SnapToScreen = false,
ShowDetailedInfo = false, ShowDetailedInfo = false,
IsTopmost = false, IsTopmost = true, // 默认置顶
TextColor = "#FFFFFF", TextColor = "#333333", // 与SettingsWindow.xaml一致
BackgroundColor = "#000000", BackgroundColor = "#F0FFFFFF", // 与SettingsWindow.xaml一致
Opacity = 100, Opacity = 94, // 与SettingsWindow.xaml一致
SpeedUnit = 1, // KB/s SpeedUnit = 3, // Auto - 与SettingsWindow.xaml一致
LayoutDirection = 0, // 横向 LayoutDirection = 1, // 纵向 - 与SettingsWindow.xaml一致
ShowUnit = true, ShowUnit = true,
DoubleClickAction = 0, // None DoubleClickAction = 0, // None
RunAsAdmin = false, RunAsAdmin = false,
@@ -37,6 +37,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterfaceType_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F92cb821cac5045cbbf918dc41b2ea2ca26920_003Fa4_003F57cbd2f9_003FNetworkInterfaceType_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterfaceType_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F92cb821cac5045cbbf918dc41b2ea2ca26920_003Fa4_003F57cbd2f9_003FNetworkInterfaceType_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterface_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F9c72a65889eb40ae9d8e0f130d1572e0268a0_003F34_003F49f5e6ff_003FNetworkInterface_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterface_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F9c72a65889eb40ae9d8e0f130d1572e0268a0_003F34_003F49f5e6ff_003FNetworkInterface_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterface_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F92cb821cac5045cbbf918dc41b2ea2ca26920_003F35_003Fdb05c251_003FNetworkInterface_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterface_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F92cb821cac5045cbbf918dc41b2ea2ca26920_003F35_003Fdb05c251_003FNetworkInterface_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANullReferenceException_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F174cdfd56bcd471abff8d95d61867f0ec90938_003F0e_003Feeacf4a5_003FNullReferenceException_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5aeb6167299d4cfba30c86624130edbcc90938_003F1d_003F3ef0ca46_003FObject_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5aeb6167299d4cfba30c86624130edbcc90938_003F1d_003F3ef0ca46_003FObject_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcessModule_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa70eaad10e4f42d4a1f24ff3865c6c6252928_003Fec_003F0881d57a_003FProcessModule_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcessModule_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa70eaad10e4f42d4a1f24ff3865c6c6252928_003Fec_003F0881d57a_003FProcessModule_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcess_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0d82aa51d3914b469b94baa8bc2312c052910_003F11_003Fa7f7fe71_003FProcess_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcess_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0d82aa51d3914b469b94baa8bc2312c052910_003F11_003Fa7f7fe71_003FProcess_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
@@ -74,4 +75,4 @@
&lt;TestId&gt;NUnit3x::B3F481C9-B351-449C-AE2B-CDEC29BD5DCC::net8.0::Common.Test.NetworkInfoUtilTest.TestMonitorActiveInterfaceSpeed&lt;/TestId&gt;&#xD; &lt;TestId&gt;NUnit3x::B3F481C9-B351-449C-AE2B-CDEC29BD5DCC::net8.0::Common.Test.NetworkInfoUtilTest.TestMonitorActiveInterfaceSpeed&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD; &lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String> &lt;/SessionState&gt;</s:String>
</wpf:ResourceDictionary> </wpf:ResourceDictionary>
+4 -11
View File
@@ -50,24 +50,17 @@ public partial class App : System.Windows.Application
// 启动服务(如 WebSocket、HTTP、端口监听等) // 启动服务(如 WebSocket、HTTP、端口监听等)
StartMyServer(); StartMyServer();
// 获取用户设置并应用到NetView窗口 // 创建 NetView 窗口 - 让它自己处理设置加载和应用
try try
{ {
var userSettings = await DatabaseManager.GetUserSettingsAsync(); Log.Information("创建 NetView 窗口...");
Log.Information($"读取用户设置: 位置({userSettings.WindowX}, {userSettings.WindowY})");
// NetView 网络监看 - 应用用户设置的位置
var netView = new NetView(); var netView = new NetView();
netView.Left = userSettings.WindowX;
netView.Top = userSettings.WindowY;
netView.Show(); netView.Show();
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "应用用户设置失败,使用默认设置"); Log.Error(ex, "创建 NetView 窗口失败");
// 使用默认设置创建窗口 throw; // 重新抛出异常,因为这是关键组件
var netView = new NetView();
netView.Show();
} }
// Mouth(); // Mouth();
@@ -0,0 +1,93 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Shell.Models;
/// <summary>
/// 应用程序网速信息
/// </summary>
public class AppSpeedInfo : INotifyPropertyChanged
{
private int _processId;
private string _appName;
private string _uploadSpeed;
private string _downloadSpeed;
private double _uploadSpeedBytes;
private double _downloadSpeedBytes;
private string _iconPath;
/// <summary>
/// 进程ID
/// </summary>
public int ProcessId
{
get => _processId;
set { _processId = value; OnPropertyChanged(); }
}
/// <summary>
/// 应用程序名称
/// </summary>
public string AppName
{
get => _appName;
set { _appName = value; OnPropertyChanged(); }
}
/// <summary>
/// 上传速度文本
/// </summary>
public string UploadSpeed
{
get => _uploadSpeed;
set { _uploadSpeed = value; OnPropertyChanged(); }
}
/// <summary>
/// 下载速度文本
/// </summary>
public string DownloadSpeed
{
get => _downloadSpeed;
set { _downloadSpeed = value; OnPropertyChanged(); }
}
/// <summary>
/// 上传速度(字节/秒)
/// </summary>
public double UploadSpeedBytes
{
get => _uploadSpeedBytes;
set { _uploadSpeedBytes = value; OnPropertyChanged(); }
}
/// <summary>
/// 下载速度(字节/秒)
/// </summary>
public double DownloadSpeedBytes
{
get => _downloadSpeedBytes;
set { _downloadSpeedBytes = value; OnPropertyChanged(); }
}
/// <summary>
/// 总速度(字节/秒)
/// </summary>
public double TotalSpeedBytes => UploadSpeedBytes + DownloadSpeedBytes;
/// <summary>
/// 应用程序图标路径
/// </summary>
public string IconPath
{
get => _iconPath;
set { _iconPath = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
@@ -93,7 +93,8 @@ public partial class SettingsWindow : Window
0 => "Bytes", 0 => "Bytes",
1 => "KB", 1 => "KB",
2 => "MB", 2 => "MB",
_ => "Auto" 3 => "Auto",
_ => "Auto" // 默认为Auto
}; };
foreach (ComboBoxItem item in SpeedUnitComboBox.Items) foreach (ComboBoxItem item in SpeedUnitComboBox.Items)
{ {
@@ -424,13 +425,14 @@ public partial class SettingsWindow : Window
_settings.ShowUnit = ShowUnitCheckBox.IsChecked == true; _settings.ShowUnit = ShowUnitCheckBox.IsChecked == true;
// 转换速度单位 // 转换速度单位
var selectedUnit = ((ComboBoxItem)SpeedUnitComboBox.SelectedItem)?.Tag?.ToString() ?? "KB"; var selectedUnit = ((ComboBoxItem)SpeedUnitComboBox.SelectedItem)?.Tag?.ToString() ?? "Auto";
_settings.SpeedUnit = selectedUnit switch _settings.SpeedUnit = selectedUnit switch
{ {
"Bytes" => 0, "Bytes" => 0,
"KB" => 1, "KB" => 1,
"MB" => 2, "MB" => 2,
_ => 1 // 默认KB "Auto" => 3,
_ => 3 // 默认Auto
}; };
// 转换布局方向 // 转换布局方向
@@ -520,6 +522,7 @@ public partial class SettingsWindow : Window
0 => Shell.Models.SpeedUnit.Bytes, 0 => Shell.Models.SpeedUnit.Bytes,
1 => Shell.Models.SpeedUnit.KB, 1 => Shell.Models.SpeedUnit.KB,
2 => Shell.Models.SpeedUnit.MB, 2 => Shell.Models.SpeedUnit.MB,
3 => Shell.Models.SpeedUnit.Auto,
_ => Shell.Models.SpeedUnit.Auto _ => Shell.Models.SpeedUnit.Auto
}; };
netViewSettings.DoubleClickAction = _settings.DoubleClickAction switch netViewSettings.DoubleClickAction = _settings.DoubleClickAction switch