feat(wpf): 添加数据导入功能

This commit is contained in:
ssss
2026-07-03 10:49:23 +08:00
parent d1a89cb86a
commit 6e183f84e4
10 changed files with 314 additions and 21 deletions

View File

@@ -0,0 +1,149 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Win32;
using System.Collections.ObjectModel;
using WCTDataMiner.Core.Services;
namespace WCTDataMiner.Wpf.ViewModels;
/// <summary>
/// 数据导入 ViewModel
/// </summary>
public partial class ImportViewModel : ObservableObject
{
private readonly ParseService _parseService;
[ObservableProperty]
private string _selectedPath = "";
[ObservableProperty]
private bool _isRecursive;
[ObservableProperty]
private bool _isImporting;
[ObservableProperty]
private int _progressValue;
[ObservableProperty]
private string _statusMessage = "请选择日志文件或目录";
[ObservableProperty]
private ObservableCollection<ImportResultItem> _importResults = new();
public ImportViewModel(ParseService parseService)
{
_parseService = parseService;
}
[RelayCommand]
private void SelectFile()
{
var dialog = new OpenFileDialog
{
Title = "选择日志文件",
Filter = "日志文件 (*.log)|*.log|所有文件 (*.*)|*.*",
Multiselect = false
};
if (dialog.ShowDialog() == true)
{
SelectedPath = dialog.FileName;
StatusMessage = $"已选择文件: {System.IO.Path.GetFileName(SelectedPath)}";
}
}
[RelayCommand]
private void SelectFolder()
{
var dialog = new OpenFolderDialog
{
Title = "选择日志目录",
Multiselect = false
};
if (dialog.ShowDialog() == true)
{
SelectedPath = dialog.FolderName;
StatusMessage = $"已选择目录: {System.IO.Path.GetFileName(SelectedPath)}";
}
}
[RelayCommand]
private async Task ImportAsync()
{
if (string.IsNullOrEmpty(SelectedPath))
{
StatusMessage = "请先选择文件或目录";
return;
}
IsImporting = true;
ImportResults.Clear();
StatusMessage = "正在导入...";
try
{
if (System.IO.File.Exists(SelectedPath))
{
// 导入单个文件
var report = await _parseService.ParseFileAsync(SelectedPath);
ImportResults.Add(new ImportResultItem(report));
StatusMessage = $"导入完成: Qfod={report.QfodCount}, Ploss={report.PlossCount}, 错误={report.ErrorCount}";
}
else if (System.IO.Directory.Exists(SelectedPath))
{
// 导入目录
var reports = await _parseService.ParseDirectoryAsync(SelectedPath, IsRecursive);
int totalQfod = 0, totalPloss = 0, totalErrors = 0;
foreach (var report in reports)
{
ImportResults.Add(new ImportResultItem(report));
totalQfod += report.QfodCount;
totalPloss += report.PlossCount;
totalErrors += report.ErrorCount;
ProgressValue = (int)((double)ImportResults.Count / reports.Count * 100);
}
StatusMessage = $"导入完成: {reports.Count} 个文件, Qfod={totalQfod}, Ploss={totalPloss}, 错误={totalErrors}";
}
else
{
StatusMessage = "路径不存在";
}
}
catch (Exception ex)
{
StatusMessage = $"导入失败: {ex.Message}";
}
finally
{
IsImporting = false;
ProgressValue = 100;
}
}
}
/// <summary>
/// 导入结果项
/// </summary>
public class ImportResultItem
{
public string FileName { get; }
public int QfodCount { get; }
public int PlossCount { get; }
public int ErrorCount { get; }
public string Status { get; }
public bool IsSuccess { get; }
public ImportResultItem(ParseReport report)
{
FileName = report.FileName;
QfodCount = report.QfodCount;
PlossCount = report.PlossCount;
ErrorCount = report.ErrorCount;
IsSuccess = report.IsSuccess;
Status = report.IsSuccess ? "成功" : report.ErrorMessage ?? "失败";
}
}

View File

@@ -8,6 +8,9 @@ namespace WCTDataMiner.Wpf.ViewModels;
/// </summary>
public partial class MainViewModel : ObservableObject
{
private readonly ImportViewModel _importViewModel;
private readonly ScenarioListViewModel _scenarioListViewModel;
[ObservableProperty]
private ObservableObject _currentView = null!;
@@ -29,15 +32,23 @@ public partial class MainViewModel : ObservableObject
public List<string> TxSoftwares { get; } = new() { "全部", "hex2_1", "hex2_2" };
public List<string> RxTypes { get; } = new() { "全部", "iPhone15", "iPhone16", "Android" };
public MainViewModel()
public MainViewModel(ImportViewModel importViewModel, ScenarioListViewModel scenarioListViewModel)
{
_currentView = new ScenarioListViewModel();
_importViewModel = importViewModel;
_scenarioListViewModel = scenarioListViewModel;
_currentView = _scenarioListViewModel;
}
[RelayCommand]
private void NavigateToImport()
{
CurrentView = _importViewModel;
}
[RelayCommand]
private void NavigateToScenarios()
{
CurrentView = new ScenarioListViewModel();
CurrentView = _scenarioListViewModel;
}
[RelayCommand]
@@ -51,4 +62,4 @@ public partial class MainViewModel : ObservableObject
{
CurrentView = new QfodChartViewModel { ScenarioId = scenarioId };
}
}
}