Files
better-genshin-impact/BetterGenshinImpact/ViewModel/Pages/GearTaskListPageViewModel.cs
2025-09-06 16:29:25 +08:00

506 lines
17 KiB
C#

using System.Collections.ObjectModel;
using System.Text.Json;
using BetterGenshinImpact.Model;
using BetterGenshinImpact.ViewModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Windows;
using System.Linq;
using System;
using BetterGenshinImpact.ViewModel.Pages.Component;
using BetterGenshinImpact.Service;
using System.Threading.Tasks;
using System.Collections.Specialized;
using GongSolutions.Wpf.DragDrop;
namespace BetterGenshinImpact.ViewModel.Pages;
/// <summary>
/// 任务列表页面ViewModel
/// </summary>
public partial class GearTaskListPageViewModel : ViewModel
{
private readonly ILogger<GearTaskListPageViewModel> _logger;
private readonly GearTaskStorageService _storageService;
/// <summary>
/// 任务定义列表(左侧)
/// </summary>
[ObservableProperty]
private ObservableCollection<GearTaskDefinitionViewModel> _taskDefinitions = new();
/// <summary>
/// 当前选中的任务定义
/// </summary>
[ObservableProperty]
private GearTaskDefinitionViewModel? _selectedTaskDefinition;
/// <summary>
/// 当前任务树根节点(右侧)
/// </summary>
[ObservableProperty]
private GearTaskViewModel _currentTaskTreeRoot = new();
/// <summary>
/// 当前选中的任务节点
/// </summary>
[ObservableProperty]
private GearTaskViewModel? _selectedTaskNode;
/// <summary>
/// 可用的任务类型
/// </summary>
public ObservableCollection<string> AvailableTaskTypes { get; } = new()
{
"采集任务",
"战斗任务",
"传送任务",
"交互任务",
"等待任务",
"脚本任务",
"条件任务",
"循环任务",
"组合任务"
};
public GearTaskListPageViewModel(ILogger<GearTaskListPageViewModel> logger, GearTaskStorageService storageService)
{
_logger = logger;
_storageService = storageService;
InitializeData();
// 监听集合变化,实现自动保存
TaskDefinitions.CollectionChanged += OnTaskDefinitionsChanged;
// 监听当前任务树根节点的子集合变化,用于拖拽后自动保存
CurrentTaskTreeRoot.Children.CollectionChanged += OnCurrentTaskTreeChanged;
}
/// <summary>
/// 任务定义集合变化时的处理
/// </summary>
private async void OnTaskDefinitionsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
// 当集合发生变化时,可以在这里处理自动保存等逻辑
// 例如:保存到配置文件等
}
/// <summary>
/// 当前任务树集合变化时的处理(用于拖拽后自动保存)
/// </summary>
private async void OnCurrentTaskTreeChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (SelectedTaskDefinition != null)
{
try
{
SelectedTaskDefinition.ModifiedTime = DateTime.Now;
await _storageService.SaveTaskDefinitionAsync(SelectedTaskDefinition);
_logger.LogInformation("任务树根级别结构变化,已自动保存任务定义 '{TaskName}'", SelectedTaskDefinition.Name);
}
catch (Exception ex)
{
_logger.LogError(ex, "自动保存任务定义 {TaskName} 时发生错误", SelectedTaskDefinition.Name);
}
}
}
/// <summary>
/// 初始化数据
/// </summary>
private async void InitializeData()
{
try
{
// 从 JSON 文件加载任务定义
var loadedTasks = await _storageService.LoadAllTaskDefinitionsAsync();
// 按order字段排序
var sortedTasks = loadedTasks.OrderBy(t => t.Order).ToList();
foreach (var task in sortedTasks)
{
TaskDefinitions.Add(task);
// 为每个任务定义设置属性变化监听
SetupTaskDefinitionPropertyChanged(task);
}
// 如果没有加载到任何任务,创建一个示例任务
if (TaskDefinitions.Count == 0)
{
await CreateSampleTaskAsync();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "初始化任务数据时发生错误");
// 发生错误时创建示例任务
await CreateSampleTaskAsync();
}
}
/// <summary>
/// 创建示例任务
/// </summary>
private async Task CreateSampleTaskAsync()
{
var sampleTask = new GearTaskDefinitionViewModel("示例任务组", "这是一个示例任务组");
if (sampleTask.RootTask != null)
{
sampleTask.RootTask.AddChild(new GearTaskViewModel("采集任务1") { TaskType = "采集任务", Description = "采集莲花" });
sampleTask.RootTask.AddChild(new GearTaskViewModel("战斗任务1") { TaskType = "战斗任务", Description = "击败史莱姆" });
var subGroup = new GearTaskViewModel("子任务组", true);
subGroup.AddChild(new GearTaskViewModel("传送任务1") { TaskType = "传送任务", Description = "传送到蒙德" });
subGroup.AddChild(new GearTaskViewModel("交互任务1") { TaskType = "交互任务", Description = "与NPC对话" });
sampleTask.RootTask.AddChild(subGroup);
}
TaskDefinitions.Add(sampleTask);
SetupTaskDefinitionPropertyChanged(sampleTask);
// 保存示例任务到文件
await _storageService.SaveTaskDefinitionAsync(sampleTask);
}
/// <summary>
/// 选中任务定义时的处理
/// </summary>
partial void OnSelectedTaskDefinitionChanged(GearTaskDefinitionViewModel? value)
{
// 清除之前选中项的状态
foreach (var task in TaskDefinitions)
{
task.IsSelected = false;
}
// 设置当前选中项
if (value != null)
{
value.IsSelected = true;
}
// 先解除之前的事件绑定
CurrentTaskTreeRoot.Children.CollectionChanged -= OnCurrentTaskTreeChanged;
// 设置当前任务树根节点
if (value?.RootTask != null)
{
CurrentTaskTreeRoot = value.RootTask;
}
else
{
CurrentTaskTreeRoot = new GearTaskViewModel();
}
// 重新绑定事件
CurrentTaskTreeRoot.Children.CollectionChanged += OnCurrentTaskTreeChanged;
}
/// <summary>
/// 选择任务定义命令
/// </summary>
[RelayCommand]
private void SelectTaskDefinition(GearTaskDefinitionViewModel? taskDefinition)
{
SelectedTaskDefinition = taskDefinition;
}
/// <summary>
/// 添加新的任务定义
/// </summary>
[RelayCommand]
private async Task AddTaskDefinition()
{
var newTask = new GearTaskDefinitionViewModel($"新任务组 {TaskDefinitions.Count + 1}", "新创建的任务组");
// 设置新任务的order为当前最大值+1
newTask.Order = TaskDefinitions.Count > 0 ? TaskDefinitions.Max(t => t.Order) + 1 : 0;
TaskDefinitions.Add(newTask);
SetupTaskDefinitionPropertyChanged(newTask);
SelectedTaskDefinition = newTask;
// 自动保存到文件
await _storageService.SaveTaskDefinitionAsync(newTask);
}
/// <summary>
/// 删除任务定义
/// </summary>
[RelayCommand]
private async Task DeleteTaskDefinition(GearTaskDefinitionViewModel? taskDefinition)
{
if (taskDefinition == null) return;
var result = MessageBox.Show($"确定要删除任务定义 '{taskDefinition.Name}' 吗?", "确认删除",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
var taskName = taskDefinition.Name;
TaskDefinitions.Remove(taskDefinition);
if (SelectedTaskDefinition == taskDefinition)
{
SelectedTaskDefinition = TaskDefinitions.FirstOrDefault();
}
// 删除对应的 JSON 文件
await _storageService.DeleteTaskDefinitionAsync(taskName);
}
}
/// <summary>
/// 重命名任务定义
/// </summary>
[RelayCommand]
private async Task RenameTaskDefinition(GearTaskDefinitionViewModel? taskDefinition)
{
if (taskDefinition == null) return;
// 这里可以弹出重命名对话框,暂时简单处理
var newName = "新名称"; // 简化处理,实际应该弹出输入框
if (!string.IsNullOrWhiteSpace(newName) && newName != taskDefinition.Name)
{
var oldName = taskDefinition.Name;
taskDefinition.Name = newName;
taskDefinition.ModifiedTime = DateTime.Now;
if (taskDefinition.RootTask != null)
{
taskDefinition.RootTask.Name = newName;
}
// 重命名对应的 JSON 文件
await _storageService.RenameTaskDefinitionAsync(oldName, newName);
}
}
/// <summary>
/// 添加任务节点
/// </summary>
[RelayCommand]
private async Task AddTaskNode(string? taskType = null)
{
if (SelectedTaskDefinition?.RootTask == null) return;
var newTask = new GearTaskViewModel($"新任务 {DateTime.Now:HHmmss}")
{
TaskType = taskType ?? AvailableTaskTypes.First(),
Description = "新创建的任务"
};
// 如果有选中的节点,则在选中节点下新增
// 如果未选择节点,则在根节点下直接新增
var targetParent = SelectedTaskNode ?? SelectedTaskDefinition.RootTask;
targetParent.AddChild(newTask);
// 展开父节点
targetParent.IsExpanded = true;
SelectedTaskDefinition.ModifiedTime = DateTime.Now;
// 自动保存到文件
await _storageService.SaveTaskDefinitionAsync(SelectedTaskDefinition);
}
/// <summary>
/// 添加任务组
/// </summary>
[RelayCommand]
private async Task AddTaskGroup()
{
if (SelectedTaskDefinition?.RootTask == null) return;
var newGroup = new GearTaskViewModel($"新任务组 {DateTime.Now:HHmmss}", true)
{
Description = "新创建的任务组"
};
// 如果有选中的节点,则在选中节点下新增
// 如果未选择节点,则在根节点下直接新增
var targetParent = SelectedTaskNode ?? SelectedTaskDefinition.RootTask;
targetParent.AddChild(newGroup);
// 展开父节点
targetParent.IsExpanded = true;
SelectedTaskDefinition.ModifiedTime = DateTime.Now;
// 自动保存到文件
await _storageService.SaveTaskDefinitionAsync(SelectedTaskDefinition);
}
/// <summary>
/// 删除任务节点
/// </summary>
[RelayCommand]
private async Task DeleteTaskNode(GearTaskViewModel? taskNode)
{
if (taskNode == null || SelectedTaskDefinition?.RootTask == null) return;
var result = MessageBox.Show($"确定要删除任务 '{taskNode.Name}' 吗?", "确认删除",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
RemoveTaskFromTree(SelectedTaskDefinition.RootTask, taskNode);
SelectedTaskDefinition.ModifiedTime = DateTime.Now;
// 自动保存到文件
await _storageService.SaveTaskDefinitionAsync(SelectedTaskDefinition);
}
}
/// <summary>
/// 从树中移除任务节点
/// </summary>
private bool RemoveTaskFromTree(GearTaskViewModel parent, GearTaskViewModel target)
{
if (parent.Children.Contains(target))
{
parent.RemoveChild(target);
return true;
}
foreach (var child in parent.Children)
{
if (RemoveTaskFromTree(child, target))
{
return true;
}
}
return false;
}
/// <summary>
/// 保存所有任务定义到JSON文件
/// </summary>
[RelayCommand]
private async Task SaveToJson()
{
try
{
foreach (var taskDefinition in TaskDefinitions)
{
await _storageService.SaveTaskDefinitionAsync(taskDefinition);
}
_logger.LogInformation("所有任务定义已保存到JSON文件");
MessageBox.Show("保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
_logger.LogError(ex, "保存任务定义到JSON文件时发生错误");
MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// 从JSON文件重新加载所有任务定义
/// </summary>
[RelayCommand]
private async Task LoadFromJson()
{
try
{
TaskDefinitions.Clear();
var loadedTasks = await _storageService.LoadAllTaskDefinitionsAsync();
foreach (var task in loadedTasks)
{
TaskDefinitions.Add(task);
SetupTaskDefinitionPropertyChanged(task);
}
_logger.LogInformation("从JSON文件重新加载了 {Count} 个任务定义", loadedTasks.Count);
MessageBox.Show($"加载成功!共加载 {loadedTasks.Count} 个任务定义", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
_logger.LogError(ex, "从JSON文件加载任务定义时发生错误");
MessageBox.Show($"加载失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// 为任务定义设置属性变化监听器,实现自动保存
/// </summary>
private void SetupTaskDefinitionPropertyChanged(GearTaskDefinitionViewModel taskDefinition)
{
taskDefinition.PropertyChanged += async (sender, e) =>
{
if (sender is GearTaskDefinitionViewModel task)
{
try
{
await _storageService.SaveTaskDefinitionAsync(task);
}
catch (Exception ex)
{
_logger.LogError(ex, "自动保存任务定义 {TaskName} 时发生错误", task.Name);
}
}
};
// 为根任务及其所有子任务设置监听器
if (taskDefinition.RootTask != null)
{
SetupTaskPropertyChangeListener(taskDefinition.RootTask, taskDefinition);
}
}
/// <summary>
/// 递归为任务及其子任务设置属性变化监听器
/// </summary>
private void SetupTaskPropertyChangeListener(GearTaskViewModel task, GearTaskDefinitionViewModel parentDefinition)
{
task.PropertyChanged += async (sender, e) =>
{
try
{
parentDefinition.ModifiedTime = DateTime.Now;
await _storageService.SaveTaskDefinitionAsync(parentDefinition);
}
catch (Exception ex)
{
_logger.LogError(ex, "自动保存任务定义 {TaskName} 时发生错误", parentDefinition.Name);
}
};
// 为子任务设置监听器
foreach (var child in task.Children)
{
SetupTaskPropertyChangeListener(child, parentDefinition);
}
// 监听子任务集合变化
task.Children.CollectionChanged += async (sender, e) =>
{
if (e.NewItems != null)
{
foreach (GearTaskViewModel newTask in e.NewItems)
{
SetupTaskPropertyChangeListener(newTask, parentDefinition);
}
}
// 任何集合变化都触发保存(包括拖拽重排序)
try
{
parentDefinition.ModifiedTime = DateTime.Now;
await _storageService.SaveTaskDefinitionAsync(parentDefinition);
_logger.LogInformation("任务树结构变化,已自动保存任务定义 '{TaskName}'", parentDefinition.Name);
}
catch (Exception ex)
{
_logger.LogError(ex, "自动保存任务定义 {TaskName} 时发生错误", parentDefinition.Name);
}
};
}
/// <summary>
/// 刷新当前任务树显示
/// </summary>
}