mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-25 10:05:49 +08:00
新增地图追踪任务选择窗口及相关功能,支持任务选择和显示详细信息
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user