diff --git a/BetterGenshinImpact/Model/Gear/Tasks/GearTrigger.cs b/BetterGenshinImpact/Model/Gear/Tasks/GearTrigger.cs
deleted file mode 100644
index 13fe5322..00000000
--- a/BetterGenshinImpact/Model/Gear/Tasks/GearTrigger.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace BetterGenshinImpact.Model.Gear.Tasks;
-
-///
-/// 为了和其他Trigger做区分,使用Gear(齿轮)来作为前缀命名调度器内定义的触发器
-///
-public class GearTrigger
-{
-
-}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskConverter.cs b/BetterGenshinImpact/Service/GearTask/GearTaskConverter.cs
new file mode 100644
index 00000000..14464144
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskConverter.cs
@@ -0,0 +1,329 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using BetterGenshinImpact.Model.Gear;
+using BetterGenshinImpact.Model.Gear.Tasks;
+using BetterGenshinImpact.Model.Gear.Parameter;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+
+namespace BetterGenshinImpact.Service;
+
+///
+/// 齿轮任务转换器,负责将 GearTaskData 转换为可执行的 BaseGearTask
+///
+public class GearTaskConverter
+{
+ private readonly ILogger _logger;
+ private readonly GearTaskFactory _taskFactory;
+
+ public GearTaskConverter(ILogger logger, GearTaskFactory taskFactory)
+ {
+ _logger = logger;
+ _taskFactory = taskFactory;
+ }
+
+ ///
+ /// 将 GearTaskDefinitionData 转换为可执行的任务列表
+ ///
+ /// 任务定义数据
+ /// 可执行的任务列表
+ public async Task> ConvertTaskDefinitionAsync(GearTaskDefinitionData taskDefinition)
+ {
+ if (taskDefinition?.RootTask == null)
+ {
+ throw new ArgumentException("任务定义或根任务不能为空");
+ }
+
+ var tasks = new List();
+
+ try
+ {
+ _logger.LogInformation("开始转换任务定义: {TaskDefinitionName}", taskDefinition.Name);
+
+ var rootTask = await ConvertTaskDataAsync(taskDefinition.RootTask);
+ tasks.Add(rootTask);
+
+ _logger.LogInformation("任务定义转换完成: {TaskDefinitionName}, 共 {TaskCount} 个任务",
+ taskDefinition.Name, CountTotalTasks(rootTask));
+
+ return tasks;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "转换任务定义失败: {TaskDefinitionName}", taskDefinition.Name);
+ throw;
+ }
+ }
+
+ ///
+ /// 将单个 GearTaskData 转换为 BaseGearTask(包括子任务)
+ ///
+ /// 任务数据
+ /// 父任务
+ /// 转换后的任务
+ public async Task ConvertTaskDataAsync(GearTaskData taskData, BaseGearTask? parent = null)
+ {
+ if (taskData == null)
+ {
+ throw new ArgumentNullException(nameof(taskData));
+ }
+
+ try
+ {
+ BaseGearTask task;
+
+ // 如果是目录类型或者任务被禁用,创建容器任务
+ if (taskData.IsDirectory || !taskData.IsEnabled)
+ {
+ task = new ContainerGearTask
+ {
+ Name = taskData.Name,
+ Type = taskData.TaskType ?? "container",
+ Enabled = taskData.IsEnabled,
+ Father = parent
+ };
+
+ _logger.LogDebug("创建容器任务: {TaskName} (IsDirectory: {IsDirectory}, IsEnabled: {IsEnabled})",
+ taskData.Name, taskData.IsDirectory, taskData.IsEnabled);
+ }
+ else
+ {
+ // 使用工厂创建具体的任务实例
+ task = await _taskFactory.CreateTaskAsync(taskData);
+ task.Father = parent;
+
+ _logger.LogDebug("创建具体任务: {TaskName} ({TaskType})", taskData.Name, taskData.TaskType);
+ }
+
+ // 递归处理子任务
+ if (taskData.Children?.Count > 0)
+ {
+ _logger.LogDebug("处理子任务: {TaskName}, 子任务数量: {ChildCount}",
+ taskData.Name, taskData.Children.Count);
+
+ foreach (var childData in taskData.Children)
+ {
+ try
+ {
+ var childTask = await ConvertTaskDataAsync(childData, task);
+ task.Children.Add(childTask);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "转换子任务失败: {ChildTaskName}, 父任务: {ParentTaskName}",
+ childData.Name, taskData.Name);
+
+ // 创建错误任务占位符
+ var errorTask = new ErrorGearTask(ex.Message)
+ {
+ Name = childData.Name,
+ Type = "error",
+ Enabled = false,
+ Father = task
+ };
+ task.Children.Add(errorTask);
+ }
+ }
+ }
+
+ return task;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "转换任务数据失败: {TaskName}", taskData.Name);
+
+ // 返回错误任务
+ return new ErrorGearTask(ex.Message)
+ {
+ Name = taskData.Name,
+ Type = "error",
+ Enabled = false,
+ Father = parent
+ };
+ }
+ }
+
+ ///
+ /// 验证任务数据的完整性
+ ///
+ /// 任务数据
+ /// 验证结果
+ public TaskValidationResult ValidateTaskData(GearTaskData taskData)
+ {
+ var result = new TaskValidationResult { IsValid = true };
+ var errors = new List();
+ var warnings = new List();
+
+ if (taskData == null)
+ {
+ errors.Add("任务数据不能为空");
+ result.IsValid = false;
+ }
+ else
+ {
+ // 验证基本属性
+ if (string.IsNullOrWhiteSpace(taskData.Name))
+ {
+ errors.Add("任务名称不能为空");
+ result.IsValid = false;
+ }
+
+ if (!taskData.IsDirectory && string.IsNullOrWhiteSpace(taskData.TaskType))
+ {
+ errors.Add("非目录任务必须指定类型");
+ result.IsValid = false;
+ }
+
+ // 验证任务类型
+ if (!string.IsNullOrWhiteSpace(taskData.TaskType) &&
+ !GearTaskFactory.IsTaskTypeSupported(taskData.TaskType))
+ {
+ errors.Add($"不支持的任务类型: {taskData.TaskType}");
+ result.IsValid = false;
+ }
+
+ // 验证参数
+ if (!taskData.IsDirectory && taskData.IsEnabled)
+ {
+ try
+ {
+ ValidateTaskParameters(taskData);
+ }
+ catch (Exception ex)
+ {
+ warnings.Add($"参数验证警告: {ex.Message}");
+ }
+ }
+
+ // 递归验证子任务
+ if (taskData.Children?.Count > 0)
+ {
+ foreach (var child in taskData.Children)
+ {
+ var childResult = ValidateTaskData(child);
+ if (!childResult.IsValid)
+ {
+ errors.AddRange(childResult.Errors.Select(e => $"子任务 '{child.Name}': {e}"));
+ result.IsValid = false;
+ }
+ warnings.AddRange(childResult.Warnings.Select(w => $"子任务 '{child.Name}': {w}"));
+ }
+ }
+ }
+
+ result.Errors = errors;
+ result.Warnings = warnings;
+ return result;
+ }
+
+ ///
+ /// 验证任务参数
+ ///
+ /// 任务数据
+ private void ValidateTaskParameters(GearTaskData taskData)
+ {
+ if (taskData.Parameters == null)
+ {
+ return;
+ }
+
+ // 根据任务类型验证参数
+ switch (taskData.TaskType?.ToLowerInvariant())
+ {
+ case "javascript":
+ ValidateJsonParameter(taskData.Parameters, "FolderName");
+ break;
+ case "pathing":
+ ValidateJsonParameter(taskData.Parameters, "Path");
+ break;
+ case "csharp":
+ case "csharpreflection":
+ ValidateJsonParameter(taskData.Parameters, "MethodPath");
+ break;
+ }
+ }
+
+ ///
+ /// 验证 JSON 参数中的必需字段
+ ///
+ private void ValidateJsonParameter(object parameters, string requiredField)
+ {
+ try
+ {
+ string json = parameters is string str ? str : JsonConvert.SerializeObject(parameters);
+ var obj = JsonConvert.DeserializeObject(json);
+
+ var property = typeof(T).GetProperty(requiredField);
+ if (property != null)
+ {
+ var value = property.GetValue(obj);
+ if (value == null || (value is string strValue && string.IsNullOrWhiteSpace(strValue)))
+ {
+ throw new ArgumentException($"缺少必需参数: {requiredField}");
+ }
+ }
+ }
+ catch (JsonException ex)
+ {
+ throw new ArgumentException($"参数 JSON 格式错误: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 统计任务总数(包括子任务)
+ ///
+ /// 根任务
+ /// 任务总数
+ private int CountTotalTasks(BaseGearTask task)
+ {
+ int count = 1;
+ if (task.Children?.Count > 0)
+ {
+ count += task.Children.Sum(CountTotalTasks);
+ }
+ return count;
+ }
+}
+
+///
+/// 任务验证结果
+///
+public class TaskValidationResult
+{
+ public bool IsValid { get; set; }
+ public List Errors { get; set; } = new();
+ public List Warnings { get; set; } = new();
+}
+
+///
+/// 容器任务,用于目录类型或禁用的任务
+///
+internal class ContainerGearTask : BaseGearTask
+{
+ public override async Task Run(CancellationToken ct)
+ {
+ // 容器任务本身不执行任何操作,只是作为子任务的容器
+ await Task.CompletedTask;
+ }
+}
+
+///
+/// 错误任务,用于转换失败的任务占位符
+///
+internal class ErrorGearTask : BaseGearTask
+{
+ private readonly string _errorMessage;
+
+ public ErrorGearTask(string errorMessage)
+ {
+ _errorMessage = errorMessage;
+ }
+
+ public override async Task Run(CancellationToken ct)
+ {
+ throw new InvalidOperationException($"任务转换失败: {_errorMessage}");
+ }
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskExecutionManager.cs b/BetterGenshinImpact/Service/GearTask/GearTaskExecutionManager.cs
new file mode 100644
index 00000000..dcde6029
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskExecutionManager.cs
@@ -0,0 +1,487 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using BetterGenshinImpact.Model.Gear.Tasks;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Microsoft.Extensions.Logging;
+
+namespace BetterGenshinImpact.Service;
+
+///
+/// 任务执行状态
+///
+public enum TaskExecutionStatus
+{
+ ///
+ /// 等待执行
+ ///
+ Pending,
+
+ ///
+ /// 正在执行
+ ///
+ Running,
+
+ ///
+ /// 执行完成
+ ///
+ Completed,
+
+ ///
+ /// 执行失败
+ ///
+ Failed,
+
+ ///
+ /// 已取消
+ ///
+ Cancelled,
+
+ ///
+ /// 已跳过
+ ///
+ Skipped
+}
+
+///
+/// 任务执行信息
+///
+public partial class TaskExecutionInfo : ObservableObject
+{
+ [ObservableProperty]
+ private string _taskName = string.Empty;
+
+ [ObservableProperty]
+ private string _taskType = string.Empty;
+
+ [ObservableProperty]
+ private TaskExecutionStatus _status = TaskExecutionStatus.Pending;
+
+ [ObservableProperty]
+ private DateTime _startTime;
+
+ [ObservableProperty]
+ private DateTime _endTime;
+
+ [ObservableProperty]
+ private TimeSpan _duration;
+
+ [ObservableProperty]
+ private string _errorMessage = string.Empty;
+
+ [ObservableProperty]
+ private double _progress;
+
+ [ObservableProperty]
+ private string _statusMessage = string.Empty;
+
+ public BaseGearTask? Task { get; set; }
+ public List Children { get; set; } = new();
+ public TaskExecutionInfo? Parent { get; set; }
+}
+
+///
+/// 齿轮任务执行管理器,负责管理任务执行状态和进度跟踪
+///
+public partial class GearTaskExecutionManager : ObservableObject
+{
+ private readonly ILogger _logger;
+ private readonly Dictionary _taskInfoMap = new();
+ private CancellationTokenSource? _cancellationTokenSource;
+
+ [ObservableProperty]
+ private TaskExecutionInfo? _rootTaskInfo;
+
+ [ObservableProperty]
+ private TaskExecutionInfo? _currentTaskInfo;
+
+ [ObservableProperty]
+ private bool _isExecuting;
+
+ [ObservableProperty]
+ private double _overallProgress;
+
+ [ObservableProperty]
+ private string _overallStatusMessage = string.Empty;
+
+ [ObservableProperty]
+ private int _totalTasks;
+
+ [ObservableProperty]
+ private int _completedTasks;
+
+ [ObservableProperty]
+ private int _failedTasks;
+
+ [ObservableProperty]
+ private int _skippedTasks;
+
+ public event EventHandler? TaskStarted;
+ public event EventHandler? TaskCompleted;
+ public event EventHandler? TaskFailed;
+ public event EventHandler? TaskSkipped;
+ public event EventHandler? ProgressChanged;
+
+ public GearTaskExecutionManager(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 开始执行任务并跟踪状态
+ ///
+ /// 根任务
+ /// 取消令牌
+ ///
+ public async Task ExecuteWithTrackingAsync(BaseGearTask rootTask, CancellationToken ct = default)
+ {
+ if (IsExecuting)
+ {
+ throw new InvalidOperationException("任务执行管理器正在运行中");
+ }
+
+ try
+ {
+ IsExecuting = true;
+ _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ct);
+
+ // 初始化执行信息
+ InitializeExecutionInfo(rootTask);
+
+ // 开始执行
+ await ExecuteTaskWithTrackingAsync(rootTask, _cancellationTokenSource.Token);
+
+ // 更新最终状态
+ UpdateOverallStatus();
+ }
+ catch (OperationCanceledException)
+ {
+ _logger.LogInformation("任务执行已取消");
+ OverallStatusMessage = "任务执行已取消";
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "任务执行过程中发生错误");
+ OverallStatusMessage = $"任务执行失败: {ex.Message}";
+ throw;
+ }
+ finally
+ {
+ IsExecuting = false;
+ _cancellationTokenSource?.Dispose();
+ _cancellationTokenSource = null;
+ }
+ }
+
+ ///
+ /// 取消任务执行
+ ///
+ public void CancelExecution()
+ {
+ if (IsExecuting && _cancellationTokenSource != null)
+ {
+ _logger.LogInformation("用户请求取消任务执行");
+ _cancellationTokenSource.Cancel();
+ OverallStatusMessage = "正在取消任务执行...";
+ }
+ }
+
+ ///
+ /// 初始化执行信息
+ ///
+ /// 根任务
+ private void InitializeExecutionInfo(BaseGearTask rootTask)
+ {
+ _taskInfoMap.Clear();
+ CompletedTasks = 0;
+ FailedTasks = 0;
+ SkippedTasks = 0;
+ OverallProgress = 0;
+
+ RootTaskInfo = CreateTaskExecutionInfo(rootTask);
+ TotalTasks = CountTotalTasks(rootTask);
+
+ OverallStatusMessage = "准备执行任务...";
+
+ _logger.LogInformation("初始化任务执行跟踪,总任务数: {TotalTasks}", TotalTasks);
+ }
+
+ ///
+ /// 创建任务执行信息
+ ///
+ /// 任务
+ /// 父任务信息
+ ///
+ private TaskExecutionInfo CreateTaskExecutionInfo(BaseGearTask task, TaskExecutionInfo? parent = null)
+ {
+ var info = new TaskExecutionInfo
+ {
+ TaskName = task.Name,
+ TaskType = task.Type,
+ Status = TaskExecutionStatus.Pending,
+ Task = task,
+ Parent = parent
+ };
+
+ _taskInfoMap[task] = info;
+
+ // 递归创建子任务信息
+ if (task.Children?.Count > 0)
+ {
+ foreach (var child in task.Children)
+ {
+ var childInfo = CreateTaskExecutionInfo(child, info);
+ info.Children.Add(childInfo);
+ }
+ }
+
+ return info;
+ }
+
+ ///
+ /// 执行任务并跟踪状态
+ ///
+ /// 要执行的任务
+ /// 取消令牌
+ ///
+ private async Task ExecuteTaskWithTrackingAsync(BaseGearTask task, CancellationToken ct)
+ {
+ if (!_taskInfoMap.TryGetValue(task, out var taskInfo))
+ {
+ _logger.LogWarning("未找到任务执行信息: {TaskName}", task.Name);
+ return;
+ }
+
+ CurrentTaskInfo = taskInfo;
+
+ // 检查任务是否启用
+ if (!task.Enabled)
+ {
+ await MarkTaskSkipped(taskInfo, "任务已禁用");
+ return;
+ }
+
+ try
+ {
+ // 开始执行任务
+ await StartTask(taskInfo);
+
+ // 执行当前任务
+ await task.Execute(ct);
+
+ // 执行子任务
+ if (task.Children?.Count > 0)
+ {
+ for (int i = 0; i < task.Children.Count; i++)
+ {
+ var child = task.Children[i];
+ await ExecuteTaskWithTrackingAsync(child, ct);
+
+ // 更新进度
+ var childProgress = (double)(i + 1) / task.Children.Count * 100;
+ taskInfo.Progress = childProgress;
+ UpdateOverallProgress();
+ }
+ }
+
+ // 完成任务
+ await CompleteTask(taskInfo);
+ }
+ catch (OperationCanceledException)
+ {
+ await MarkTaskCancelled(taskInfo);
+ throw;
+ }
+ catch (Exception ex)
+ {
+ await FailTask(taskInfo, ex);
+ throw;
+ }
+ }
+
+ ///
+ /// 开始执行任务
+ ///
+ /// 任务信息
+ private async Task StartTask(TaskExecutionInfo taskInfo)
+ {
+ taskInfo.Status = TaskExecutionStatus.Running;
+ taskInfo.StartTime = DateTime.Now;
+ taskInfo.StatusMessage = "正在执行...";
+
+ _logger.LogInformation("开始执行任务: {TaskName}", taskInfo.TaskName);
+
+ TaskStarted?.Invoke(this, taskInfo);
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// 完成任务
+ ///
+ /// 任务信息
+ private async Task CompleteTask(TaskExecutionInfo taskInfo)
+ {
+ taskInfo.Status = TaskExecutionStatus.Completed;
+ taskInfo.EndTime = DateTime.Now;
+ taskInfo.Duration = taskInfo.EndTime - taskInfo.StartTime;
+ taskInfo.Progress = 100;
+ taskInfo.StatusMessage = "执行完成";
+
+ CompletedTasks++;
+
+ _logger.LogInformation("任务执行完成: {TaskName}, 耗时: {Duration}ms",
+ taskInfo.TaskName, taskInfo.Duration.TotalMilliseconds);
+
+ TaskCompleted?.Invoke(this, taskInfo);
+ UpdateOverallProgress();
+
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// 任务执行失败
+ ///
+ /// 任务信息
+ /// 异常
+ private async Task FailTask(TaskExecutionInfo taskInfo, Exception exception)
+ {
+ taskInfo.Status = TaskExecutionStatus.Failed;
+ taskInfo.EndTime = DateTime.Now;
+ taskInfo.Duration = taskInfo.EndTime - taskInfo.StartTime;
+ taskInfo.ErrorMessage = exception.Message;
+ taskInfo.StatusMessage = $"执行失败: {exception.Message}";
+
+ FailedTasks++;
+
+ _logger.LogError(exception, "任务执行失败: {TaskName}", taskInfo.TaskName);
+
+ TaskFailed?.Invoke(this, taskInfo);
+ UpdateOverallProgress();
+
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// 标记任务为已跳过
+ ///
+ /// 任务信息
+ /// 跳过原因
+ private async Task MarkTaskSkipped(TaskExecutionInfo taskInfo, string reason)
+ {
+ taskInfo.Status = TaskExecutionStatus.Skipped;
+ taskInfo.StatusMessage = $"已跳过: {reason}";
+
+ SkippedTasks++;
+
+ _logger.LogInformation("任务已跳过: {TaskName}, 原因: {Reason}", taskInfo.TaskName, reason);
+
+ TaskSkipped?.Invoke(this, taskInfo);
+ UpdateOverallProgress();
+
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// 标记任务为已取消
+ ///
+ /// 任务信息
+ private async Task MarkTaskCancelled(TaskExecutionInfo taskInfo)
+ {
+ taskInfo.Status = TaskExecutionStatus.Cancelled;
+ taskInfo.EndTime = DateTime.Now;
+ taskInfo.Duration = taskInfo.EndTime - taskInfo.StartTime;
+ taskInfo.StatusMessage = "已取消";
+
+ _logger.LogInformation("任务已取消: {TaskName}", taskInfo.TaskName);
+
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// 更新整体进度
+ ///
+ private void UpdateOverallProgress()
+ {
+ if (TotalTasks > 0)
+ {
+ var processedTasks = CompletedTasks + FailedTasks + SkippedTasks;
+ OverallProgress = (double)processedTasks / TotalTasks * 100;
+
+ OverallStatusMessage = $"进度: {processedTasks}/{TotalTasks} (完成: {CompletedTasks}, 失败: {FailedTasks}, 跳过: {SkippedTasks})";
+
+ ProgressChanged?.Invoke(this, OverallProgress);
+ }
+ }
+
+ ///
+ /// 更新最终状态
+ ///
+ private void UpdateOverallStatus()
+ {
+ if (FailedTasks > 0)
+ {
+ OverallStatusMessage = $"执行完成,但有 {FailedTasks} 个任务失败";
+ }
+ else if (SkippedTasks > 0)
+ {
+ OverallStatusMessage = $"执行完成,跳过了 {SkippedTasks} 个任务";
+ }
+ else
+ {
+ OverallStatusMessage = "所有任务执行完成";
+ }
+ }
+
+ ///
+ /// 统计任务总数
+ ///
+ /// 根任务
+ /// 任务总数
+ private int CountTotalTasks(BaseGearTask task)
+ {
+ int count = 1;
+ if (task.Children?.Count > 0)
+ {
+ foreach (var child in task.Children)
+ {
+ count += CountTotalTasks(child);
+ }
+ }
+ return count;
+ }
+
+ ///
+ /// 获取任务执行统计信息
+ ///
+ /// 统计信息
+ public TaskExecutionStatistics GetStatistics()
+ {
+ return new TaskExecutionStatistics
+ {
+ TotalTasks = TotalTasks,
+ CompletedTasks = CompletedTasks,
+ FailedTasks = FailedTasks,
+ SkippedTasks = SkippedTasks,
+ OverallProgress = OverallProgress,
+ IsExecuting = IsExecuting
+ };
+ }
+}
+
+///
+/// 任务执行统计信息
+///
+public class TaskExecutionStatistics
+{
+ public int TotalTasks { get; set; }
+ public int CompletedTasks { get; set; }
+ public int FailedTasks { get; set; }
+ public int SkippedTasks { get; set; }
+ public double OverallProgress { get; set; }
+ public bool IsExecuting { get; set; }
+
+ public int ProcessedTasks => CompletedTasks + FailedTasks + SkippedTasks;
+ public double SuccessRate => TotalTasks > 0 ? (double)CompletedTasks / TotalTasks * 100 : 0;
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskExecutor.cs b/BetterGenshinImpact/Service/GearTask/GearTaskExecutor.cs
new file mode 100644
index 00000000..3bbcf3fc
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskExecutor.cs
@@ -0,0 +1,289 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Threading;
+using System.Threading.Tasks;
+using BetterGenshinImpact.Model.Gear;
+using BetterGenshinImpact.Model.Gear.Tasks;
+using BetterGenshinImpact.ViewModel.Pages.Component;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace BetterGenshinImpact.Service;
+
+///
+/// 齿轮任务执行器,负责从 JSON 数据解析任务并执行
+///
+public partial class GearTaskExecutor : ObservableObject
+{
+ private readonly ILogger _logger;
+ private readonly GearTaskStorageService _storageService;
+ private readonly GearTaskConverter _taskConverter;
+ private readonly GearTaskExecutionManager _executionManager;
+ private readonly IServiceProvider _serviceProvider;
+
+ [ObservableProperty]
+ private bool _isExecuting;
+
+ [ObservableProperty]
+ private string _currentTaskName = string.Empty;
+
+ [ObservableProperty]
+ private double _progress;
+
+ [ObservableProperty]
+ private string _statusMessage = string.Empty;
+
+ public GearTaskExecutor(
+ ILogger logger,
+ GearTaskStorageService storageService,
+ GearTaskConverter taskConverter,
+ GearTaskExecutionManager executionManager,
+ IServiceProvider serviceProvider)
+ {
+ _logger = logger;
+ _storageService = storageService;
+ _taskConverter = taskConverter;
+ _executionManager = executionManager;
+ _serviceProvider = serviceProvider;
+
+ // 订阅执行管理器事件
+ _executionManager.ProgressChanged += OnProgressChanged;
+ _executionManager.PropertyChanged += OnExecutionManagerPropertyChanged;
+ }
+
+ ///
+ /// 从 JSON 文件加载并执行任务定义
+ ///
+ /// 任务定义名称
+ /// 取消令牌
+ ///
+ public async Task ExecuteTaskDefinitionAsync(string taskDefinitionName, CancellationToken ct = default)
+ {
+ if (IsExecuting)
+ {
+ throw new InvalidOperationException("任务执行器正在运行中,请等待当前任务完成");
+ }
+
+ try
+ {
+ IsExecuting = true;
+ StatusMessage = "正在加载任务定义...";
+ Progress = 0;
+
+ // 从存储服务加载任务定义
+ var taskDefinitionViewModel = await _storageService.LoadTaskDefinitionAsync(taskDefinitionName);
+ if (taskDefinitionViewModel == null)
+ {
+ throw new ArgumentException($"未找到任务定义: {taskDefinitionName}");
+ }
+
+ if (taskDefinitionViewModel.RootTask == null)
+ {
+ throw new InvalidOperationException($"任务定义 '{taskDefinitionName}' 没有根任务");
+ }
+
+ _logger.LogInformation("开始执行任务定义: {TaskDefinitionName}", taskDefinitionName);
+
+ // 转换为可执行的任务
+ var rootTaskData = ConvertViewModelToData(taskDefinitionViewModel.RootTask);
+ var rootTask = await _taskConverter.ConvertTaskDataAsync(rootTaskData);
+
+ // 使用执行管理器执行任务
+ await _executionManager.ExecuteWithTrackingAsync(rootTask, ct);
+
+ StatusMessage = "任务执行完成";
+ Progress = 100;
+ _logger.LogInformation("任务定义执行完成: {TaskDefinitionName}", taskDefinitionName);
+ }
+ catch (OperationCanceledException)
+ {
+ StatusMessage = "任务执行已取消";
+ _logger.LogInformation("任务定义执行已取消: {TaskDefinitionName}", taskDefinitionName);
+ throw;
+ }
+ catch (Exception ex)
+ {
+ StatusMessage = $"任务执行失败: {ex.Message}";
+ _logger.LogError(ex, "执行任务定义时发生错误: {TaskDefinitionName}", taskDefinitionName);
+ throw;
+ }
+ finally
+ {
+ IsExecuting = false;
+ }
+ }
+
+ ///
+ /// 直接执行 GearTaskData
+ ///
+ /// 任务数据
+ /// 取消令牌
+ ///
+ public async Task ExecuteTaskDataAsync(GearTaskData taskData, CancellationToken ct = default)
+ {
+ if (IsExecuting)
+ {
+ throw new InvalidOperationException("任务执行器正在运行中,请等待当前任务完成");
+ }
+
+ try
+ {
+ IsExecuting = true;
+ StatusMessage = "正在执行任务...";
+ Progress = 0;
+
+ _logger.LogInformation("开始执行任务: {TaskName}", taskData.Name);
+
+ // 转换为可执行的任务
+ var executableTask = await _taskConverter.ConvertTaskDataAsync(taskData);
+
+ // 使用执行管理器执行任务
+ await _executionManager.ExecuteWithTrackingAsync(executableTask, ct);
+
+ StatusMessage = "任务执行完成";
+ Progress = 100;
+ _logger.LogInformation("任务执行完成: {TaskName}", taskData.Name);
+ }
+ catch (OperationCanceledException)
+ {
+ StatusMessage = "任务执行已取消";
+ _logger.LogInformation("任务执行已取消: {TaskName}", taskData.Name);
+ throw;
+ }
+ catch (Exception ex)
+ {
+ StatusMessage = $"任务执行失败: {ex.Message}";
+ _logger.LogError(ex, "执行任务时发生错误: {TaskName}", taskData.Name);
+ throw;
+ }
+ finally
+ {
+ IsExecuting = false;
+ }
+ }
+
+
+
+
+
+ ///
+ /// 停止当前执行的任务
+ ///
+ public void StopExecution()
+ {
+ if (IsExecuting)
+ {
+ StatusMessage = "正在停止任务执行...";
+ _logger.LogInformation("用户请求停止任务执行");
+ _executionManager.CancelExecution();
+ }
+ }
+
+ ///
+ /// 处理进度变化事件
+ ///
+ /// 事件发送者
+ /// 进度值
+ private void OnProgressChanged(object? sender, double progress)
+ {
+ Progress = progress;
+ }
+
+ ///
+ /// 处理执行管理器属性变化事件
+ ///
+ /// 事件发送者
+ /// 属性变化事件参数
+ private void OnExecutionManagerPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName)
+ {
+ case nameof(GearTaskExecutionManager.CurrentTaskInfo):
+ if (_executionManager.CurrentTaskInfo != null)
+ {
+ CurrentTaskName = _executionManager.CurrentTaskInfo.TaskName;
+ }
+ break;
+ case nameof(GearTaskExecutionManager.OverallStatusMessage):
+ StatusMessage = _executionManager.OverallStatusMessage;
+ break;
+ case nameof(GearTaskExecutionManager.IsExecuting):
+ IsExecuting = _executionManager.IsExecuting;
+ break;
+ }
+ }
+
+ ///
+ /// 获取执行统计信息
+ ///
+ /// 统计信息
+ public TaskExecutionStatistics GetExecutionStatistics()
+ {
+ return _executionManager.GetStatistics();
+ }
+
+ ///
+ /// 获取当前任务执行信息
+ ///
+ /// 当前任务信息
+ public TaskExecutionInfo? GetCurrentTaskInfo()
+ {
+ return _executionManager.CurrentTaskInfo;
+ }
+
+ ///
+ /// 获取根任务执行信息
+ ///
+ ///
+ public TaskExecutionInfo? GetRootTaskInfo()
+ {
+ return _executionManager.RootTaskInfo;
+ }
+
+ ///
+ /// 将 GearTaskViewModel 转换为 GearTaskData
+ ///
+ /// 视图模型
+ /// 任务数据
+ private GearTaskData ConvertViewModelToData(GearTaskViewModel viewModel)
+ {
+ var taskData = new GearTaskData
+ {
+ Name = viewModel.Name,
+ Description = viewModel.Description,
+ TaskType = viewModel.TaskType,
+ IsEnabled = viewModel.IsEnabled,
+ IsDirectory = viewModel.IsDirectory,
+ Parameters = viewModel.Parameters,
+ CreatedTime = viewModel.CreatedTime,
+ ModifiedTime = viewModel.ModifiedTime,
+ Priority = viewModel.Priority,
+ Tags = viewModel.Tags ?? string.Empty
+ };
+
+ // 递归转换子任务
+ if (viewModel.Children?.Count > 0)
+ {
+ taskData.Children = new List();
+ foreach (var child in viewModel.Children)
+ {
+ taskData.Children.Add(ConvertViewModelToData(child));
+ }
+ }
+
+ return taskData;
+ }
+}
+
+///
+/// 空任务实现,用于已禁用的任务
+///
+internal class EmptyGearTask : BaseGearTask
+{
+ public override Task Run(CancellationToken ct)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskExecutor_Usage.md b/BetterGenshinImpact/Service/GearTask/GearTaskExecutor_Usage.md
new file mode 100644
index 00000000..3fb2004e
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskExecutor_Usage.md
@@ -0,0 +1,329 @@
+# GearTaskExecutor 使用指南
+
+## 概述
+
+`GearTaskExecutor` 是一个强大的任务执行控制器,能够从 JSON 文件中解析并执行继承自 `BaseGearTask` 的不同类型任务。这些任务统一使用 `GearTaskData` 对象进行序列化。
+
+## 核心组件
+
+### 1. GearTaskExecutor
+主要的任务执行控制器,提供以下功能:
+- 从 JSON 文件加载任务定义
+- 执行任务并跟踪进度
+- 异常处理和日志记录
+- 任务状态管理
+
+### 2. GearTaskFactory
+任务工厂,根据任务类型创建对应的任务实例:
+- JavaScript 任务
+- Pathing 任务
+- C# 反射任务
+- KeyMouse 任务
+- Shell 任务
+
+### 3. GearTaskConverter
+任务转换器,将 `GearTaskData` 转换为可执行的 `BaseGearTask`:
+- 递归处理子任务
+- 参数验证
+- 错误处理
+
+### 4. GearTaskExecutionManager
+任务执行管理器,提供详细的执行状态跟踪:
+- 实时进度更新
+- 任务状态监控
+- 执行统计信息
+- 事件通知
+
+## 服务注册
+
+在 `App.xaml.cs` 中注册服务:
+
+```csharp
+// 方式1:使用扩展方法注册所有服务
+services.AddGearTaskServices();
+
+// 方式2:带配置选项注册
+services.AddGearTaskServices(options =>
+{
+ options.EnableVerboseLogging = true;
+ options.ContinueOnTaskFailure = false;
+ options.MaxConcurrentTasks = 1;
+});
+
+// 方式3:手动注册(如果需要自定义)
+services.AddSingleton();
+services.AddSingleton();
+services.AddSingleton();
+services.AddTransient();
+services.AddTransient();
+```
+
+## 基本使用
+
+### 1. 执行任务定义
+
+```csharp
+public class TaskExecutionViewModel : ObservableObject
+{
+ private readonly GearTaskExecutor _taskExecutor;
+
+ public TaskExecutionViewModel(GearTaskExecutor taskExecutor)
+ {
+ _taskExecutor = taskExecutor;
+ }
+
+ [RelayCommand]
+ private async Task ExecuteTaskDefinitionAsync(string taskDefinitionName)
+ {
+ try
+ {
+ await _taskExecutor.ExecuteTaskDefinitionAsync(taskDefinitionName);
+ }
+ catch (Exception ex)
+ {
+ // 处理异常
+ Debug.WriteLine($"任务执行失败: {ex.Message}");
+ }
+ }
+}
+```
+
+### 2. 直接执行任务数据
+
+```csharp
+[RelayCommand]
+private async Task ExecuteTaskDataAsync()
+{
+ var taskData = new GearTaskData
+ {
+ Name = "测试任务",
+ Type = "javascript",
+ IsEnabled = true,
+ Parameters = new JavascriptGearTaskParams
+ {
+ FolderName = "test-script",
+ Context = new { message = "Hello World" }
+ }
+ };
+
+ try
+ {
+ await _taskExecutor.ExecuteTaskDataAsync(taskData);
+ }
+ catch (Exception ex)
+ {
+ // 处理异常
+ }
+}
+```
+
+### 3. 监控执行进度
+
+```csharp
+public class TaskMonitorViewModel : ObservableObject
+{
+ private readonly GearTaskExecutor _taskExecutor;
+
+ [ObservableProperty]
+ private double _progress;
+
+ [ObservableProperty]
+ private string _currentTaskName = string.Empty;
+
+ [ObservableProperty]
+ private string _statusMessage = string.Empty;
+
+ public TaskMonitorViewModel(GearTaskExecutor taskExecutor)
+ {
+ _taskExecutor = taskExecutor;
+
+ // 绑定属性
+ _taskExecutor.PropertyChanged += OnTaskExecutorPropertyChanged;
+ }
+
+ private void OnTaskExecutorPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName)
+ {
+ case nameof(GearTaskExecutor.Progress):
+ Progress = _taskExecutor.Progress;
+ break;
+ case nameof(GearTaskExecutor.CurrentTaskName):
+ CurrentTaskName = _taskExecutor.CurrentTaskName;
+ break;
+ case nameof(GearTaskExecutor.StatusMessage):
+ StatusMessage = _taskExecutor.StatusMessage;
+ break;
+ }
+ }
+
+ [RelayCommand]
+ private void StopExecution()
+ {
+ _taskExecutor.StopExecution();
+ }
+}
+```
+
+### 4. 获取执行统计信息
+
+```csharp
+[RelayCommand]
+private void ShowStatistics()
+{
+ var stats = _taskExecutor.GetExecutionStatistics();
+
+ var message = $@"执行统计信息:
+总任务数: {stats.TotalTasks}
+已完成: {stats.CompletedTasks}
+失败: {stats.FailedTasks}
+跳过: {stats.SkippedTasks}
+成功率: {stats.SuccessRate:F1}%
+整体进度: {stats.OverallProgress:F1}%";
+
+ MessageBox.Show(message);
+}
+```
+
+## 支持的任务类型
+
+### 1. JavaScript 任务
+```json
+{
+ "name": "JavaScript 脚本任务",
+ "type": "javascript",
+ "isEnabled": true,
+ "parameters": {
+ "folderName": "my-script",
+ "context": {
+ "param1": "value1",
+ "param2": 123
+ }
+ }
+}
+```
+
+### 2. Pathing 任务
+```json
+{
+ "name": "路径任务",
+ "type": "pathing",
+ "isEnabled": true,
+ "parameters": {
+ "path": "path/to/route.json",
+ "pathingPartyConfig": {
+ "team": ["character1", "character2"]
+ }
+ }
+}
+```
+
+### 3. C# 反射任务
+```json
+{
+ "name": "C# 反射任务",
+ "type": "csharp",
+ "isEnabled": true,
+ "parameters": {
+ "methodPath": "MyNamespace.MyClass.MyMethod",
+ "parametersJson": "[\"param1\", 123, {\"key\": \"value\"}]"
+ }
+}
+```
+
+### 4. KeyMouse 任务
+```json
+{
+ "name": "键鼠录制任务",
+ "type": "keymouse",
+ "isEnabled": true,
+ "parameters": "path/to/macro.json"
+}
+```
+
+### 5. Shell 任务
+```json
+{
+ "name": "Shell 命令任务",
+ "type": "shell",
+ "isEnabled": true,
+ "parameters": {
+ "command": "echo Hello World",
+ "workingDirectory": "C:\\temp",
+ "timeout": 30000
+ }
+}
+```
+
+## 错误处理
+
+### 1. 任务验证
+```csharp
+public async Task ValidateTaskAsync(GearTaskData taskData)
+{
+ var converter = serviceProvider.GetRequiredService();
+ var result = converter.ValidateTaskData(taskData);
+
+ if (!result.IsValid)
+ {
+ foreach (var error in result.Errors)
+ {
+ Debug.WriteLine($"验证错误: {error}");
+ }
+ return false;
+ }
+
+ foreach (var warning in result.Warnings)
+ {
+ Debug.WriteLine($"验证警告: {warning}");
+ }
+
+ return true;
+}
+```
+
+### 2. 异常处理
+```csharp
+try
+{
+ await _taskExecutor.ExecuteTaskDefinitionAsync(taskName);
+}
+catch (ArgumentException ex)
+{
+ // 参数错误
+ MessageBox.Show($"参数错误: {ex.Message}");
+}
+catch (FileNotFoundException ex)
+{
+ // 文件未找到
+ MessageBox.Show($"文件未找到: {ex.Message}");
+}
+catch (OperationCanceledException)
+{
+ // 用户取消
+ MessageBox.Show("任务执行已取消");
+}
+catch (Exception ex)
+{
+ // 其他异常
+ MessageBox.Show($"执行失败: {ex.Message}");
+}
+```
+
+## 最佳实践
+
+1. **使用依赖注入**:通过构造函数注入 `GearTaskExecutor`
+2. **异步执行**:所有任务执行都应该使用 `async/await`
+3. **异常处理**:始终包装任务执行在 try-catch 块中
+4. **进度监控**:绑定执行器的属性来显示进度
+5. **资源清理**:在适当的时候取消任务执行
+6. **日志记录**:启用详细日志记录来调试问题
+7. **参数验证**:在执行前验证任务数据的完整性
+
+## 注意事项
+
+- 任务执行器是线程安全的,但同时只能执行一个任务
+- 子任务会按顺序执行,不支持并行执行
+- 禁用的任务会被跳过,但仍会处理其子任务
+- 任务失败会停止整个执行流程,除非配置为继续执行
+- 所有任务都支持取消操作
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskFactory.cs b/BetterGenshinImpact/Service/GearTask/GearTaskFactory.cs
new file mode 100644
index 00000000..f3390e5a
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskFactory.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Threading.Tasks;
+using BetterGenshinImpact.Model.Gear;
+using BetterGenshinImpact.Model.Gear.Tasks;
+using BetterGenshinImpact.Model.Gear.Parameter;
+using BetterGenshinImpact.Core.Config;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json;
+using System.IO;
+
+namespace BetterGenshinImpact.Service;
+
+///
+/// 齿轮任务工厂,根据任务类型和参数创建对应的任务实例
+///
+public class GearTaskFactory
+{
+ private readonly ILogger _logger;
+ private readonly IServiceProvider _serviceProvider;
+
+ public GearTaskFactory(ILogger logger, IServiceProvider serviceProvider)
+ {
+ _logger = logger;
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ /// 根据 GearTaskData 创建对应的任务实例
+ ///
+ /// 任务数据
+ /// 创建的任务实例
+ public async Task CreateTaskAsync(GearTaskData taskData)
+ {
+ if (string.IsNullOrWhiteSpace(taskData.TaskType))
+ {
+ throw new ArgumentException($"任务类型不能为空: {taskData.Name}");
+ }
+
+ try
+ {
+ var task = taskData.TaskType.ToLowerInvariant() switch
+ {
+ "javascript" => await CreateJavascriptTaskAsync(taskData),
+ "pathing" => await CreatePathingTaskAsync(taskData),
+ "csharp" or "csharpreflection" => await CreateCSharpReflectionTaskAsync(taskData),
+ "keymouse" => await CreateKeyMouseTaskAsync(taskData),
+ "shell" => await CreateShellTaskAsync(taskData),
+ _ => throw new NotSupportedException($"不支持的任务类型: {taskData.TaskType}")
+ };
+
+ // 设置基本属性
+ task.Name = taskData.Name;
+ task.Type = taskData.TaskType;
+ task.Enabled = taskData.IsEnabled;
+
+ _logger.LogDebug("成功创建任务实例: {TaskName} ({TaskType})", taskData.Name, taskData.TaskType);
+ return task;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "创建任务实例失败: {TaskName} ({TaskType})", taskData.Name, taskData.TaskType);
+ throw;
+ }
+ }
+
+ ///
+ /// 创建 JavaScript 任务
+ ///
+ private async Task CreateJavascriptTaskAsync(GearTaskData taskData)
+ {
+ var parameters = DeserializeParameters(taskData.Parameters);
+
+ if (string.IsNullOrWhiteSpace(parameters.FolderName))
+ {
+ throw new ArgumentException($"JavaScript 任务缺少 FolderName 参数: {taskData.Name}");
+ }
+
+ return new JavascriptGearTask(parameters);
+ }
+
+ ///
+ /// 创建路径任务
+ ///
+ private async Task CreatePathingTaskAsync(GearTaskData taskData)
+ {
+ var parameters = DeserializeParameters(taskData.Parameters);
+
+ if (string.IsNullOrWhiteSpace(parameters.Path))
+ {
+ throw new ArgumentException($"Pathing 任务缺少 Path 参数: {taskData.Name}");
+ }
+
+ return new PathingGearTask(parameters);
+ }
+
+ ///
+ /// 创建 C# 反射任务
+ ///
+ private async Task CreateCSharpReflectionTaskAsync(GearTaskData taskData)
+ {
+ var parameters = DeserializeParameters(taskData.Parameters);
+
+ if (string.IsNullOrWhiteSpace(parameters.MethodPath))
+ {
+ throw new ArgumentException($"C# 反射任务缺少 MethodPath 参数: {taskData.Name}");
+ }
+
+ return new CSharpReflectionGearTask(parameters);
+ }
+
+ ///
+ /// 创建键鼠任务
+ ///
+ private async Task CreateKeyMouseTaskAsync(GearTaskData taskData)
+ {
+ // KeyMouse 任务需要文件路径
+ string filePath = string.Empty;
+
+ if (taskData.Parameters != null)
+ {
+ // 尝试从参数中获取路径
+ if (taskData.Parameters is string pathStr)
+ {
+ filePath = pathStr;
+ }
+ else if (taskData.Parameters.ToString() is string paramStr)
+ {
+ // 尝试解析 JSON 对象中的路径
+ try
+ {
+ var paramObj = JsonConvert.DeserializeObject(paramStr);
+ filePath = paramObj?.Path?.ToString() ?? paramObj?.FilePath?.ToString() ?? string.Empty;
+ }
+ catch
+ {
+ filePath = paramStr; // 如果解析失败,直接使用字符串
+ }
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(filePath))
+ {
+ throw new ArgumentException($"KeyMouse 任务缺少文件路径参数: {taskData.Name}");
+ }
+
+ if (!File.Exists(filePath))
+ {
+ throw new FileNotFoundException($"KeyMouse 任务文件不存在: {filePath}");
+ }
+
+ return new KeyMouseGearTask(filePath);
+ }
+
+ ///
+ /// 创建 Shell 任务
+ ///
+ private async Task CreateShellTaskAsync(GearTaskData taskData)
+ {
+ ShellConfig? shellConfig = null;
+
+ if (taskData.Parameters != null)
+ {
+ try
+ {
+ shellConfig = DeserializeParameters(taskData.Parameters);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "解析 Shell 配置失败,使用默认配置: {TaskName}", taskData.Name);
+ shellConfig = new ShellConfig();
+ }
+ }
+
+ return new ShellGearTask(shellConfig);
+ }
+
+ ///
+ /// 反序列化参数对象
+ ///
+ /// 参数类型
+ /// 参数对象
+ /// 反序列化后的参数
+ private T DeserializeParameters(object? parameters) where T : class, new()
+ {
+ if (parameters == null)
+ {
+ return new T();
+ }
+
+ try
+ {
+ // 如果已经是目标类型,直接返回
+ if (parameters is T directCast)
+ {
+ return directCast;
+ }
+
+ // 尝试 JSON 反序列化
+ string json;
+ if (parameters is string jsonStr)
+ {
+ json = jsonStr;
+ }
+ else
+ {
+ json = JsonConvert.SerializeObject(parameters);
+ }
+
+ var result = JsonConvert.DeserializeObject(json);
+ return result ?? new T();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "反序列化参数失败,使用默认参数: {ParameterType}", typeof(T).Name);
+ return new T();
+ }
+ }
+
+ ///
+ /// 获取支持的任务类型列表
+ ///
+ /// 支持的任务类型
+ public static string[] GetSupportedTaskTypes()
+ {
+ return new[]
+ {
+ "javascript",
+ "pathing",
+ "csharp",
+ "csharpreflection",
+ "keymouse",
+ "shell"
+ };
+ }
+
+ ///
+ /// 检查任务类型是否受支持
+ ///
+ /// 任务类型
+ /// 是否支持
+ public static bool IsTaskTypeSupported(string taskType)
+ {
+ if (string.IsNullOrWhiteSpace(taskType))
+ return false;
+
+ var supportedTypes = GetSupportedTaskTypes();
+ return Array.Exists(supportedTypes, t =>
+ string.Equals(t, taskType, StringComparison.OrdinalIgnoreCase));
+ }
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTask/GearTaskServiceExtensions.cs b/BetterGenshinImpact/Service/GearTask/GearTaskServiceExtensions.cs
new file mode 100644
index 00000000..a175e316
--- /dev/null
+++ b/BetterGenshinImpact/Service/GearTask/GearTaskServiceExtensions.cs
@@ -0,0 +1,78 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace BetterGenshinImpact.Service;
+
+///
+/// 齿轮任务服务注册扩展方法
+///
+public static class GearTaskServiceExtensions
+{
+ ///
+ /// 注册齿轮任务相关服务
+ ///
+ /// 服务集合
+ /// 服务集合
+ public static IServiceCollection AddGearTaskServices(this IServiceCollection services)
+ {
+ // 注册核心服务
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddTransient();
+ services.AddTransient();
+
+ return services;
+ }
+
+ ///
+ /// 注册齿轮任务相关服务(带自定义配置)
+ ///
+ /// 服务集合
+ /// 配置选项
+ /// 服务集合
+ public static IServiceCollection AddGearTaskServices(this IServiceCollection services,
+ Action? configureOptions = null)
+ {
+ var options = new GearTaskServiceOptions();
+ configureOptions?.Invoke(options);
+
+ // 注册配置
+ services.AddSingleton(options);
+
+ // 注册核心服务
+ return services.AddGearTaskServices();
+ }
+}
+
+///
+/// 齿轮任务服务配置选项
+///
+public class GearTaskServiceOptions
+{
+ ///
+ /// 是否启用详细日志记录
+ ///
+ public bool EnableVerboseLogging { get; set; } = false;
+
+ ///
+ /// 任务执行超时时间(毫秒),0 表示无超时
+ ///
+ public int TaskExecutionTimeoutMs { get; set; } = 0;
+
+ ///
+ /// 是否在任务失败时继续执行后续任务
+ ///
+ public bool ContinueOnTaskFailure { get; set; } = false;
+
+ ///
+ /// 最大并发任务数,0 表示无限制
+ ///
+ public int MaxConcurrentTasks { get; set; } = 1;
+
+ ///
+ /// 任务存储路径,null 表示使用默认路径
+ ///
+ public string? TaskStoragePath { get; set; }
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Service/GearTaskStorageService.cs b/BetterGenshinImpact/Service/GearTask/GearTaskStorageService.cs
similarity index 100%
rename from BetterGenshinImpact/Service/GearTaskStorageService.cs
rename to BetterGenshinImpact/Service/GearTask/GearTaskStorageService.cs