A:增加缺失文件
This commit is contained in:
1 parent
cd4ffe2385
commit
b110c2a735
8 files changed
+307
-15
No files matched your search
@@ -0,0 +1,17 @@
|
||||
# 项目介绍
|
||||
这是一个网络管理项目,它用的是C#,网络信息使用ETW,并集成防火墙API,提供HTTP和WebSocket接口来实现数据的传递和接收,使用Sqlite作为底层数据库。使用Vue作为前端并通过WebView2套壳实现主页面渲染
|
||||
|
||||
|
||||
我所有的环境并非全部在默认位置安装,比如部分环境如 Git 之类的在 D:\Env 下
|
||||
|
||||
|
||||
你可以使用TODO.md 文档来管理你的任务,或者记录任何东西,里面的内容完全由你管理,我不会干预,如果有内容你可以直接清空,它就像你的草稿纸。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Data;
|
||||
using Common.Logger;
|
||||
using Dapper;
|
||||
|
||||
class CheckDbSchema
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
Log.Initialize();
|
||||
|
||||
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var dbPath = Path.Combine(appDataPath, "NetVizor", "netvizor.db");
|
||||
|
||||
Console.WriteLine($"检查数据库: {dbPath}");
|
||||
|
||||
if (!File.Exists(dbPath))
|
||||
{
|
||||
Console.WriteLine("❌ 数据库文件不存在");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var context = new NetVizorDbContext(dbPath);
|
||||
var connection = context.Connection;
|
||||
|
||||
Console.WriteLine("✓ 数据库连接成功");
|
||||
|
||||
// 检查所有表
|
||||
var tables = await connection.QueryAsync<string>(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
|
||||
|
||||
Console.WriteLine($"\n📋 现有表 ({tables.Count()}个):");
|
||||
foreach (var table in tables)
|
||||
{
|
||||
Console.WriteLine($" - {table}");
|
||||
}
|
||||
|
||||
// 检查聚合表是否存在
|
||||
var aggregationTables = new[]
|
||||
{
|
||||
"AppNetworkHourly", "AppNetworkDaily", "AppNetworkWeekly", "AppNetworkMonthly",
|
||||
"GlobalNetworkHourly", "GlobalNetworkDaily", "GlobalNetworkWeekly", "GlobalNetworkMonthly"
|
||||
};
|
||||
|
||||
Console.WriteLine("\n🔍 聚合表检查:");
|
||||
var missingTables = new List<string>();
|
||||
|
||||
foreach (var tableName in aggregationTables)
|
||||
{
|
||||
if (tables.Contains(tableName))
|
||||
{
|
||||
// 检查表结构
|
||||
var columns = await connection.QueryAsync<dynamic>(
|
||||
$"PRAGMA table_info({tableName})");
|
||||
|
||||
var columnNames = columns.Select(c => c.name.ToString()).ToArray();
|
||||
Console.WriteLine($" ✓ {tableName} (列: {string.Join(", ", columnNames)})");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" ❌ {tableName} - 缺失");
|
||||
missingTables.Add(tableName);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingTables.Count > 0)
|
||||
{
|
||||
Console.WriteLine($"\n⚠ 发现 {missingTables.Count} 个缺失的聚合表,需要运行数据库初始化");
|
||||
|
||||
// 运行初始化以创建缺失的表
|
||||
Console.WriteLine("\n🔄 正在创建缺失的聚合表...");
|
||||
await context.InitializeDatabaseAsync();
|
||||
Console.WriteLine("✓ 数据库表结构更新完成");
|
||||
|
||||
// 再次检查
|
||||
var updatedTables = await connection.QueryAsync<string>(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
|
||||
Console.WriteLine($"\n📋 更新后的表 ({updatedTables.Count()}个):");
|
||||
foreach (var table in updatedTables)
|
||||
{
|
||||
Console.WriteLine($" - {table}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("\n✅ 所有聚合表都已存在");
|
||||
}
|
||||
|
||||
// 检查数据数量
|
||||
Console.WriteLine("\n📊 数据统计:");
|
||||
var appNetworkCount = await connection.QuerySingleAsync<int>("SELECT COUNT(*) FROM AppNetwork");
|
||||
var globalNetworkCount = await connection.QuerySingleAsync<int>("SELECT COUNT(*) FROM GlobalNetwork");
|
||||
var appInfoCount = await connection.QuerySingleAsync<int>("SELECT COUNT(*) FROM AppInfo");
|
||||
|
||||
Console.WriteLine($" - AppNetwork: {appNetworkCount:N0} 条记录");
|
||||
Console.WriteLine($" - GlobalNetwork: {globalNetworkCount:N0} 条记录");
|
||||
Console.WriteLine($" - AppInfo: {appInfoCount:N0} 条记录");
|
||||
|
||||
// 检查聚合表数据
|
||||
foreach (var tableName in aggregationTables)
|
||||
{
|
||||
if (tables.Contains(tableName) || missingTables.Count == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var count = await connection.QuerySingleAsync<int>($"SELECT COUNT(*) FROM {tableName}");
|
||||
Console.WriteLine($" - {tableName}: {count:N0} 条记录");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($" - {tableName}: 查询失败 ({ex.Message})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ 错误: {ex.Message}");
|
||||
Console.WriteLine($"详细: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,12 +45,12 @@ public class AppSetting
|
||||
/// <summary>
|
||||
/// 文本颜色
|
||||
/// </summary>
|
||||
public string TextColor { get; set; } = "#FFFFFF";
|
||||
public string TextColor { get; set; } = "#000000";
|
||||
|
||||
/// <summary>
|
||||
/// 背景颜色
|
||||
/// </summary>
|
||||
public string BackgroundColor { get; set; } = "#000000";
|
||||
public string BackgroundColor { get; set; } = "#FFFFFF";
|
||||
|
||||
/// <summary>
|
||||
/// 透明度 (0-100)
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
using Data.Models;
|
||||
using Data.Repositories;
|
||||
|
||||
namespace Services;
|
||||
|
||||
public interface IAppSettingService
|
||||
{
|
||||
Task<AppSetting> GetSettingAsync();
|
||||
Task SaveSettingAsync(AppSetting setting);
|
||||
Task UpdateSettingAsync(AppSetting setting);
|
||||
Task InitializeDefaultSettingAsync();
|
||||
}
|
||||
|
||||
public class AppSettingService : IAppSettingService
|
||||
{
|
||||
private readonly IAppSettingRepository _repository;
|
||||
private AppSetting? _cachedSetting;
|
||||
private readonly object _lock = new object();
|
||||
|
||||
public AppSettingService(IAppSettingRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<AppSetting> GetSettingAsync()
|
||||
{
|
||||
if (_cachedSetting != null)
|
||||
return _cachedSetting;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cachedSetting != null)
|
||||
return _cachedSetting;
|
||||
}
|
||||
|
||||
var setting = await _repository.GetCurrentSettingAsync();
|
||||
if (setting == null)
|
||||
{
|
||||
await InitializeDefaultSettingAsync();
|
||||
setting = await _repository.GetCurrentSettingAsync();
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedSetting = setting;
|
||||
}
|
||||
|
||||
return setting ?? new AppSetting();
|
||||
}
|
||||
|
||||
public async Task SaveSettingAsync(AppSetting setting)
|
||||
{
|
||||
await _repository.SaveSettingAsync(setting);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedSetting = setting;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateSettingAsync(AppSetting setting)
|
||||
{
|
||||
await _repository.UpdateSettingAsync(setting);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedSetting = setting;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeDefaultSettingAsync()
|
||||
{
|
||||
var defaultSetting = new AppSetting
|
||||
{
|
||||
WindowX = 0,
|
||||
WindowY = 0,
|
||||
IsClickThrough = false,
|
||||
IsPositionLocked = false,
|
||||
SnapToScreen = false,
|
||||
ShowDetailedInfo = false,
|
||||
IsTopmost = false,
|
||||
TextColor = "#FFFFFF",
|
||||
BackgroundColor = "#000000",
|
||||
Opacity = 100,
|
||||
SpeedUnit = 1, // KB/s
|
||||
LayoutDirection = 0, // 横向
|
||||
ShowUnit = true,
|
||||
DoubleClickAction = 0, // None
|
||||
RunAsAdmin = false,
|
||||
AutoStart = false,
|
||||
ShowSpeedRanking = false,
|
||||
SpeedRankingCount = 3
|
||||
};
|
||||
|
||||
await _repository.SaveSettingAsync(defaultSetting);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedSetting = defaultSetting;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateCache()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedSetting = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,8 @@
|
||||
<Grid Margin="10,8">
|
||||
<StackPanel x:Name="MainPanel" Orientation="Vertical">
|
||||
<!-- Global Speed Panel -->
|
||||
<StackPanel x:Name="SpeedPanel" Orientation="Vertical">
|
||||
<StackPanel x:Name="SpeedPanel" Orientation="Vertical" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<!-- Upload Speed -->
|
||||
<Grid x:Name="UploadGrid">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -134,10 +135,10 @@
|
||||
FontWeight="Normal"
|
||||
Foreground="#666666"
|
||||
VerticalAlignment="Center"
|
||||
Width="70"
|
||||
Width="45"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextAlignment="Left"
|
||||
Margin="4,0,8,0" />
|
||||
Margin="4,0,1,0" />
|
||||
|
||||
<!-- Upload Speed -->
|
||||
<Grid Grid.Column="3">
|
||||
@@ -153,13 +154,13 @@
|
||||
FontSize="10" FontWeight="Normal"
|
||||
Foreground="#666666"
|
||||
VerticalAlignment="Center"
|
||||
Width="40"
|
||||
Width="35"
|
||||
TextAlignment="Right"
|
||||
FontFamily="Consolas" />
|
||||
</Grid>
|
||||
|
||||
<!-- Download Speed -->
|
||||
<Grid Grid.Column="4" Margin="8,0,0,0">
|
||||
<Grid Grid.Column="4" Margin="4,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -172,7 +173,7 @@
|
||||
FontSize="10" FontWeight="Normal"
|
||||
Foreground="#666666"
|
||||
VerticalAlignment="Center"
|
||||
Width="40"
|
||||
Width="35"
|
||||
TextAlignment="Right"
|
||||
FontFamily="Consolas" />
|
||||
</Grid>
|
||||
|
||||
@@ -114,11 +114,11 @@
|
||||
Unchecked="ShowUnitCheckBox_Changed" />
|
||||
<CheckBox x:Name="ShowTopListCheckBox" Content="显示网速排行榜" Margin="0,4,0,0"
|
||||
IsChecked="False" Checked="ShowTopListCheckBox_Changed"
|
||||
Unchecked="ShowTopListCheckBox_Changed" IsEnabled="False" />
|
||||
Unchecked="ShowTopListCheckBox_Changed" />
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<TextBlock Text="排行榜数量:" VerticalAlignment="Center" Margin="0,0,8,0" />
|
||||
<ComboBox x:Name="TopListCountComboBox" Width="80"
|
||||
SelectionChanged="TopListCountComboBox_SelectionChanged" IsEnabled="False">
|
||||
SelectionChanged="TopListCountComboBox_SelectionChanged">
|
||||
<ComboBoxItem Content="1" Tag="1" />
|
||||
<ComboBoxItem Content="2" Tag="2" />
|
||||
<ComboBoxItem Content="3" Tag="3" IsSelected="True" />
|
||||
|
||||
@@ -78,6 +78,9 @@ public partial class SettingsWindow : Window
|
||||
|
||||
private void LoadCurrentSettings()
|
||||
{
|
||||
Log.Info(
|
||||
$"开始加载设置,数据库中的值: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}");
|
||||
|
||||
// 加载当前设置到UI控件
|
||||
TextColorBox.Text = _settings.TextColor;
|
||||
BackgroundColorBox.Text = _settings.BackgroundColor;
|
||||
@@ -105,19 +108,26 @@ public partial class SettingsWindow : Window
|
||||
VerticalLayoutRadio.IsChecked = _settings.LayoutDirection == 1; // 1为纵向
|
||||
HorizontalLayoutRadio.IsChecked = _settings.LayoutDirection == 0; // 0为横向
|
||||
|
||||
Log.Info(
|
||||
$"布局方向设置: LayoutDirection={_settings.LayoutDirection}, VerticalLayoutRadio.IsChecked={VerticalLayoutRadio.IsChecked}, HorizontalLayoutRadio.IsChecked={HorizontalLayoutRadio.IsChecked}");
|
||||
|
||||
// 设置网速Top榜
|
||||
ShowTopListCheckBox.IsChecked = _settings.ShowNetworkTopList;
|
||||
Log.Info(
|
||||
$"设置ShowTopListCheckBox.IsChecked = {_settings.ShowNetworkTopList}, 实际值: {ShowTopListCheckBox.IsChecked}");
|
||||
|
||||
foreach (ComboBoxItem item in TopListCountComboBox.Items)
|
||||
{
|
||||
if (item.Tag.ToString() == _settings.NetworkTopListCount.ToString())
|
||||
{
|
||||
TopListCountComboBox.SelectedItem = item;
|
||||
Log.Info($"设置TopListCountComboBox选中项为: {_settings.NetworkTopListCount}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Info(
|
||||
$"加载网速排行榜设置: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}, IsHorizontal={_settings.LayoutDirection == 0}");
|
||||
$"加载网速排行榜设置完成: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}, IsHorizontal={_settings.LayoutDirection == 0}");
|
||||
|
||||
UpdateTopListAvailability();
|
||||
|
||||
@@ -268,6 +278,7 @@ public partial class SettingsWindow : Window
|
||||
|
||||
private void ShowTopListCheckBox_Changed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Log.Info($"ShowTopListCheckBox_Changed: IsChecked={ShowTopListCheckBox.IsChecked}");
|
||||
UpdateTopListCountVisibility();
|
||||
}
|
||||
|
||||
@@ -283,6 +294,9 @@ public partial class SettingsWindow : Window
|
||||
var isHorizontal = HorizontalLayoutRadio.IsChecked == true;
|
||||
ShowTopListCheckBox.IsEnabled = isHorizontal;
|
||||
|
||||
Log.Info(
|
||||
$"UpdateTopListAvailability: isHorizontal={isHorizontal}, ShowTopListCheckBox.IsEnabled={ShowTopListCheckBox.IsEnabled}");
|
||||
|
||||
UpdateTopListCountVisibility();
|
||||
}
|
||||
|
||||
@@ -292,6 +306,9 @@ public partial class SettingsWindow : Window
|
||||
|
||||
var isEnabled = ShowTopListCheckBox.IsEnabled && ShowTopListCheckBox.IsChecked == true;
|
||||
TopListCountComboBox.IsEnabled = isEnabled;
|
||||
|
||||
Log.Info(
|
||||
$"UpdateTopListCountVisibility: ShowTopListCheckBox.IsEnabled={ShowTopListCheckBox.IsEnabled}, ShowTopListCheckBox.IsChecked={ShowTopListCheckBox.IsChecked}, TopListCountComboBox.IsEnabled={TopListCountComboBox.IsEnabled}");
|
||||
}
|
||||
|
||||
private void DoubleClickActionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
@@ -396,6 +413,10 @@ public partial class SettingsWindow : Window
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Info("开始应用设置");
|
||||
Log.Info(
|
||||
$"应用前UI状态: ShowTopListCheckBox.IsChecked={ShowTopListCheckBox.IsChecked}, TopListCountComboBox.SelectedItem={(TopListCountComboBox.SelectedItem as ComboBoxItem)?.Tag}");
|
||||
|
||||
// 应用设置到AppSetting对象
|
||||
_settings.TextColor = TextColorBox.Text;
|
||||
_settings.BackgroundColor = BackgroundColorBox.Text;
|
||||
@@ -416,12 +437,18 @@ public partial class SettingsWindow : Window
|
||||
_settings.LayoutDirection = HorizontalLayoutRadio.IsChecked == true ? 0 : 1; // 0为横向,1为纵向
|
||||
|
||||
// 保存网速Top榜设置 - 只在横向布局时保存为true,纵向布局时保存实际的UI状态但应用时会被忽略
|
||||
_settings.ShowNetworkTopList = ShowTopListCheckBox.IsChecked == true;
|
||||
var selectedCount = ((ComboBoxItem)TopListCountComboBox.SelectedItem)?.Tag?.ToString() ?? "3";
|
||||
_settings.NetworkTopListCount = int.Parse(selectedCount);
|
||||
var uiShowTopList = ShowTopListCheckBox.IsChecked == true;
|
||||
var selectedCountTag = ((ComboBoxItem)TopListCountComboBox.SelectedItem)?.Tag?.ToString() ?? "3";
|
||||
var uiTopListCount = int.Parse(selectedCountTag);
|
||||
|
||||
Log.Info(
|
||||
$"保存网速排行榜设置: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}, IsHorizontal={HorizontalLayoutRadio.IsChecked}");
|
||||
$"准备保存: UI状态 ShowTopList={uiShowTopList}, Count={uiTopListCount}, 当前布局方向={_settings.LayoutDirection}");
|
||||
|
||||
_settings.ShowNetworkTopList = uiShowTopList;
|
||||
_settings.NetworkTopListCount = uiTopListCount;
|
||||
|
||||
Log.Info(
|
||||
$"保存到_settings: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}, IsHorizontal={HorizontalLayoutRadio.IsChecked}");
|
||||
|
||||
// 转换双击动作
|
||||
var selectedAction = ((ComboBoxItem)DoubleClickActionComboBox.SelectedItem)?.Tag?.ToString() ?? "None";
|
||||
@@ -443,9 +470,19 @@ public partial class SettingsWindow : Window
|
||||
// 设置更新时间
|
||||
_settings.UpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
|
||||
Log.Info(
|
||||
$"准备保存到数据库: ShowNetworkTopList={_settings.ShowNetworkTopList}, NetworkTopListCount={_settings.NetworkTopListCount}");
|
||||
|
||||
// 保存设置到数据库
|
||||
await DatabaseManager.SaveUserSettingsAsync(_settings);
|
||||
|
||||
Log.Info("数据库保存完成,开始验证");
|
||||
|
||||
// 验证保存结果
|
||||
var verifySettings = await DatabaseManager.GetUserSettingsAsync();
|
||||
Log.Info(
|
||||
$"验证保存结果: ShowNetworkTopList={verifySettings.ShowNetworkTopList}, NetworkTopListCount={verifySettings.NetworkTopListCount}");
|
||||
|
||||
// 通知NetView窗口应用新设置
|
||||
await ApplySettingsToNetView();
|
||||
|
||||
|
||||
Whitespace-only changes.
Reference in new issue
Block a user