新增地图追踪任务选择窗口及相关功能,支持任务选择和显示详细信息

This commit is contained in:
辉鸭蛋
2025-09-07 12:27:54 +08:00
parent baa5cad656
commit b370d76f8d
8 changed files with 1512 additions and 2 deletions

View File

@@ -0,0 +1,376 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Data;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using BetterGenshinImpact.Core.Script;
using BetterGenshinImpact.Helpers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using BetterGenshinImpact.Core.Config;
namespace BetterGenshinImpact.ViewModel.Windows.GearTask;
/// <summary>
/// 地图追踪任务选择窗口ViewModel
/// </summary>
public partial class PathingTaskSelectionViewModel : ViewModel
{
private readonly ILogger<PathingTaskSelectionViewModel> _logger = App.GetLogger<PathingTaskSelectionViewModel>();
/// <summary>
/// 地图追踪任务列表
/// </summary>
[ObservableProperty]
private ObservableCollection<PathingTaskInfo> _pathingTasks = new();
/// <summary>
/// 过滤后的地图追踪任务列表
/// </summary>
[ObservableProperty]
private ObservableCollection<PathingTaskInfo> _filteredPathingTasks = new();
/// <summary>
/// 当前选中的地图追踪任务
/// </summary>
[ObservableProperty]
private PathingTaskInfo? _selectedTask;
/// <summary>
/// 搜索关键词
/// </summary>
[ObservableProperty]
private string _searchKeyword = string.Empty;
/// <summary>
/// 显示模式true=显示到文件级别false=仅显示文件夹
/// </summary>
[ObservableProperty]
private bool _showFilesMode = true;
/// <summary>
/// 右侧显示的内容
/// </summary>
[ObservableProperty]
private string _displayContent = string.Empty;
/// <summary>
/// 右侧显示的内容类型JSON或README
/// </summary>
[ObservableProperty]
private string _displayContentType = string.Empty;
/// <summary>
/// 图标字典
/// </summary>
private Dictionary<string, string> _iconDictionary = new();
public PathingTaskSelectionViewModel()
{
// LoadIconDictionary();
LoadPathingTasks();
}
// /// <summary>
// /// 加载图标字典
// /// </summary>
// private void LoadIconDictionary()
// {
// try
// {
// var jsonContent = ResourceHelper.GetString("pack://application:,,,/Resources/Json/icons.json");
// if (string.IsNullOrEmpty(jsonContent))
// {
// return;
// }
// var iconArray = JsonConvert.DeserializeObject<JArray>(jsonContent);
// if (iconArray != null)
// {
// foreach (var item in iconArray)
// {
// var name = item["name"]?.ToString();
// var link = item["link"]?.ToString();
// if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(link))
// {
// _iconDictionary[name] = link;
// }
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogError(ex, "加载图标字典失败");
// }
// }
/// <summary>
/// 加载地图追踪任务
/// </summary>
private void LoadPathingTasks()
{
try
{
PathingTasks.Clear();
var pathingPath = Path.Combine(ScriptRepoUpdater.CenterRepoPath, "repo", "pathing");
if (!Directory.Exists(pathingPath))
{
_logger.LogWarning($"地图追踪任务目录不存在: {pathingPath}");
return;
}
// 加载根目录下的直接子项
LoadDirectChildrenFromDirectory(pathingPath, pathingPath, PathingTasks);
FilterTasks();
}
catch (Exception ex)
{
_logger.LogError(ex, "加载地图追踪任务失败");
}
}
/// <summary>
/// 从目录加载直接子项(用于构建层级结构)
/// </summary>
private void LoadDirectChildrenFromDirectory(string directoryPath, string rootPath, ObservableCollection<PathingTaskInfo> parentCollection)
{
try
{
// 加载文件夹
foreach (var dir in Directory.GetDirectories(directoryPath))
{
var taskInfo = new PathingTaskInfo(dir, rootPath)
{
IsDirectory = true
};
// 设置图标
SetTaskIcon(taskInfo);
// 加载README内容
LoadReadmeContent(taskInfo);
// 递归加载子目录到当前任务的Children集合中
LoadDirectChildrenFromDirectory(dir, rootPath, taskInfo.Children);
parentCollection.Add(taskInfo);
}
// 如果是显示文件模式加载JSON文件
if (ShowFilesMode)
{
foreach (var file in Directory.GetFiles(directoryPath, "*.json"))
{
var taskInfo = new PathingTaskInfo(file, rootPath)
{
IsDirectory = false
};
// 设置图标
SetTaskIcon(taskInfo);
// 加载JSON内容
LoadJsonContent(taskInfo);
parentCollection.Add(taskInfo);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"加载目录任务失败: {directoryPath}");
}
}
/// <summary>
/// 设置任务图标
/// </summary>
private void SetTaskIcon(PathingTaskInfo taskInfo)
{
// var fileName = Path.GetFileNameWithoutExtension(taskInfo.Name);
//
// if (_iconDictionary.TryGetValue(fileName, out var iconUrl))
// {
// taskInfo.IconUrl = iconUrl;
// taskInfo.UseSystemIcon = false;
// }
// else
// {
// taskInfo.UseSystemIcon = true;
// }
taskInfo.UseSystemIcon = true;
}
/// <summary>
/// 加载README内容
/// </summary>
private void LoadReadmeContent(PathingTaskInfo taskInfo)
{
try
{
if (taskInfo.IsDirectory)
{
var readmePath = Path.Combine(taskInfo.FullPath, "README.md");
if (File.Exists(readmePath))
{
taskInfo.ReadmeContent = File.ReadAllText(readmePath);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"加载README内容失败: {taskInfo.FullPath}");
}
}
/// <summary>
/// 加载JSON内容
/// </summary>
private void LoadJsonContent(PathingTaskInfo taskInfo)
{
try
{
if (!taskInfo.IsDirectory && taskInfo.FullPath.EndsWith(".json"))
{
var jsonContent = File.ReadAllText(taskInfo.FullPath);
// 格式化JSON
var jsonObject = JsonConvert.DeserializeObject(jsonContent);
taskInfo.JsonContent = JsonConvert.SerializeObject(jsonObject, Formatting.Indented);
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"加载JSON内容失败: {taskInfo.FullPath}");
taskInfo.JsonContent = "JSON格式错误";
}
}
/// <summary>
/// 过滤任务
/// </summary>
private void FilterTasks()
{
FilteredPathingTasks.Clear();
foreach (var task in PathingTasks)
{
var filteredTask = FilterTaskRecursively(task);
if (filteredTask != null)
{
FilteredPathingTasks.Add(filteredTask);
}
}
}
/// <summary>
/// 递归过滤任务(支持搜索所有子节点)
/// </summary>
private PathingTaskInfo? FilterTaskRecursively(PathingTaskInfo task)
{
// 检查当前节点是否匹配搜索条件
bool currentMatches = string.IsNullOrWhiteSpace(SearchKeyword) ||
task.Name.Contains(SearchKeyword, StringComparison.OrdinalIgnoreCase) ||
task.RelativePath.Contains(SearchKeyword, StringComparison.OrdinalIgnoreCase);
// 根据显示模式过滤
bool modeMatches = ShowFilesMode || task.IsDirectory;
// 创建新的任务对象用于显示
var filteredTask = new PathingTaskInfo
{
Name = task.Name,
FolderName = task.FolderName,
FullPath = task.FullPath,
IsDirectory = task.IsDirectory,
JsonContent = task.JsonContent,
ReadmeContent = task.ReadmeContent,
IconUrl = task.IconUrl,
UseSystemIcon = task.UseSystemIcon,
ParentPath = task.ParentPath,
RelativePath = task.RelativePath
};
// 递归处理子节点
bool hasMatchingChildren = false;
foreach (var child in task.Children)
{
var filteredChild = FilterTaskRecursively(child);
if (filteredChild != null)
{
filteredTask.Children.Add(filteredChild);
hasMatchingChildren = true;
}
}
// 如果当前节点匹配条件且符合显示模式,或者有匹配的子节点,则返回该节点
if ((currentMatches && modeMatches) || hasMatchingChildren)
{
return filteredTask;
}
return null;
}
/// <summary>
/// 当选中任务改变时
/// </summary>
partial void OnSelectedTaskChanged(PathingTaskInfo? value)
{
if (value == null)
{
DisplayContent = string.Empty;
DisplayContentType = string.Empty;
return;
}
if (value.IsDirectory)
{
DisplayContent = value.ReadmeContent;
DisplayContentType = "README";
}
else
{
DisplayContent = value.JsonContent;
DisplayContentType = "JSON";
}
}
/// <summary>
/// 当搜索关键词改变时
/// </summary>
partial void OnSearchKeywordChanged(string value)
{
FilterTasks();
}
/// <summary>
/// 当显示模式改变时
/// </summary>
partial void OnShowFilesModeChanged(bool value)
{
LoadPathingTasks();
}
/// <summary>
/// 刷新任务列表
/// </summary>
[RelayCommand]
private void RefreshTasks()
{
LoadPathingTasks();
}
/// <summary>
/// 切换显示模式
/// </summary>
[RelayCommand]
private void ToggleShowMode()
{
ShowFilesMode = !ShowFilesMode;
}
}