using System; using System.Collections.ObjectModel; using System.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using BetterGenshinImpact.Helpers.Extensions; using BetterGenshinImpact.Model; using BetterGenshinImpact.Model.Gear.Triggers; using BetterGenshinImpact.Service; using BetterGenshinImpact.Service.GearTask; using BetterGenshinImpact.View.Windows; using BetterGenshinImpact.ViewModel.Pages.Component; using Microsoft.Extensions.Logging; using Quartz; namespace BetterGenshinImpact.ViewModel.Windows.GearTask; /// /// 新增/编辑触发器对话框 ViewModel。 /// public partial class AddTriggerDialogViewModel : ObservableObject { private const string DefaultCronExpression = "1 0 4 * * ?"; private readonly GearTaskStorageService _storageService; private readonly ILogger _logger; [ObservableProperty] private string _dialogTitle = "新增触发器"; [ObservableProperty] private string _triggerName = string.Empty; [ObservableProperty] private TriggerType _selectedTriggerType = TriggerType.Timed; [ObservableProperty] private string _cronExpression = DefaultCronExpression; [ObservableProperty] private CronInputMode _selectedCronInputMode = CronInputMode.Preset; [ObservableProperty] private HotKey? _selectedHotkey; [ObservableProperty] private HotKeyTypeEnum _hotkeyType = HotKeyTypeEnum.KeyboardMonitor; /// /// 快捷键类型显示名称 /// public string HotkeyTypeName => HotkeyType.ToChineseName(); [ObservableProperty] private string _selectedTaskDefinitionName = string.Empty; [ObservableProperty] private bool _isEnabled = true; /// /// 触发器类型选择是否可用 /// [ObservableProperty] private bool _isTriggerTypeSelectionEnabled = true; /// /// 可用的触发器类型 /// public ObservableCollection> TriggerTypes { get; } = new() { EnumItem.Create(TriggerType.Timed), EnumItem.Create(TriggerType.Hotkey) }; /// /// Cron 输入模式 /// public ObservableCollection> CronInputModes { get; } = new() { EnumItem.Create(CronInputMode.Preset), EnumItem.Create(CronInputMode.Manual) }; /// /// 可用的任务定义列表 /// [ObservableProperty] private ObservableCollection _availableTaskDefinitions = new(); /// /// 请求关闭事件 /// public event EventHandler? RequestClose; /// /// 创建的触发器 /// public GearTriggerViewModel? CreatedTrigger { get; private set; } public AddTriggerDialogViewModel(GearTaskStorageService storageService, ILogger logger) { _storageService = storageService; _logger = logger; // 生成默认名称 GenerateDefaultName(); // 加载可用的任务定义 LoadAvailableTaskDefinitions(); } public AddTriggerDialogViewModel( GearTaskStorageService storageService, ILogger logger, TriggerType? predefinedType = null) : this(storageService, logger) { if (predefinedType.HasValue) { SelectedTriggerType = predefinedType.Value; IsTriggerTypeSelectionEnabled = false; } } public AddTriggerDialogViewModel( GearTaskStorageService storageService, ILogger logger, GearTriggerViewModel existingTrigger) : this(storageService, logger) { DialogTitle = "编辑触发器"; IsTriggerTypeSelectionEnabled = false; SelectedTriggerType = existingTrigger.TriggerType; TriggerName = existingTrigger.Name; IsEnabled = existingTrigger.IsEnabled; SelectedTaskDefinitionName = existingTrigger.TaskDefinitionName; CronExpression = existingTrigger.TriggerType == TriggerType.Timed ? existingTrigger.CronExpression ?? DefaultCronExpression : DefaultCronExpression; SelectedCronInputMode = existingTrigger.TriggerType == TriggerType.Timed ? CronInputMode.Manual : CronInputMode.Preset; SelectedHotkey = existingTrigger.TriggerType == TriggerType.Hotkey ? existingTrigger.Hotkey : null; HotkeyType = existingTrigger.TriggerType == TriggerType.Hotkey ? existingTrigger.HotkeyType : HotKeyTypeEnum.KeyboardMonitor; } /// /// 生成默认触发器名称 /// private void GenerateDefaultName() { var typeName = SelectedTriggerType == TriggerType.Timed ? "定时触发器" : "热键触发器"; TriggerName = $"{typeName} {DateTime.Now:MMdd_HHmm}"; } /// /// 加载可用的任务定义 /// private async void LoadAvailableTaskDefinitions() { try { AvailableTaskDefinitions.Clear(); // 从 GearTaskStorageService 加载所有任务定义 var taskDefinitions = await _storageService.LoadAllTaskDefinitionsAsync(); // 提取任务定义名称并添加到列表中 foreach (var taskDefinition in taskDefinitions) { if (!string.IsNullOrWhiteSpace(taskDefinition.Name)) { AvailableTaskDefinitions.Add(taskDefinition.Name); } } _logger.LogInformation("已加载 {Count} 个可用的任务定义", AvailableTaskDefinitions.Count); // 如果有任务定义,默认选择第一个 if (AvailableTaskDefinitions.Count > 0 && string.IsNullOrWhiteSpace(SelectedTaskDefinitionName)) { SelectedTaskDefinitionName = AvailableTaskDefinitions[0]; } } catch (Exception ex) { _logger.LogDebug(ex, "加载可用任务定义时发生错误"); // 发生错误时添加一个提示项 AvailableTaskDefinitions.Clear(); AvailableTaskDefinitions.Add("(无可用任务定义)"); } } /// /// 快捷键类型改变时的处理 /// partial void OnHotkeyTypeChanged(HotKeyTypeEnum value) { // 通知UI更新快捷键类型显示名称 OnPropertyChanged(nameof(HotkeyTypeName)); // 清空当前快捷键设置 SelectedHotkey = null; } /// /// 触发器类型改变时的处理 /// partial void OnSelectedTriggerTypeChanged(TriggerType value) { GenerateDefaultName(); } partial void OnSelectedCronInputModeChanged(CronInputMode value) { if (SelectedTriggerType == TriggerType.Timed && string.IsNullOrWhiteSpace(CronExpression)) { CronExpression = DefaultCronExpression; } } [RelayCommand] private void Confirm() { if (string.IsNullOrWhiteSpace(TriggerName)) { ThemedMessageBox.Error("请输入触发器名称", "保存失败"); return; } if (SelectedTriggerType == TriggerType.Timed && string.IsNullOrWhiteSpace(CronExpression)) { var message = SelectedCronInputMode == CronInputMode.Manual ? "请输入 Cron 表达式" : "请先完成定时选择"; ThemedMessageBox.Error(message, "保存失败"); return; } if (SelectedTriggerType == TriggerType.Timed && !IsValidCronExpression(CronExpression, out var cronErrorMessage)) { ThemedMessageBox.Error(cronErrorMessage, "Cron 表达式错误"); return; } if (SelectedTriggerType == TriggerType.Hotkey && SelectedHotkey == null) { ThemedMessageBox.Error("请选择热键", "保存失败"); return; } CreatedTrigger = new GearTriggerViewModel(TriggerName, SelectedTriggerType) { IsEnabled = IsEnabled, TaskDefinitionName = SelectedTaskDefinitionName, CronExpression = SelectedTriggerType == TriggerType.Timed ? CronExpression : null, Hotkey = SelectedTriggerType == TriggerType.Hotkey ? SelectedHotkey : null, HotkeyType = SelectedTriggerType == TriggerType.Hotkey ? HotkeyType : HotKeyTypeEnum.KeyboardMonitor }; RequestClose?.Invoke(this, true); } /// /// 取消创建 /// [RelayCommand] private void Cancel() { RequestClose?.Invoke(this, false); } /// /// 切换快捷键类型 /// [RelayCommand] private void SwitchHotKeyType() { HotkeyType = HotkeyType == HotKeyTypeEnum.GlobalRegister ? HotKeyTypeEnum.KeyboardMonitor : HotKeyTypeEnum.GlobalRegister; } /// /// 选择热键 /// [RelayCommand] private void SelectHotkey() { } private static bool IsValidCronExpression(string? cronExpression, out string errorMessage) { errorMessage = string.Empty; if (string.IsNullOrWhiteSpace(cronExpression)) { errorMessage = "Cron 表达式不能为空"; return false; } try { _ = new CronExpression(cronExpression); return true; } catch (FormatException ex) { errorMessage = $"Cron 表达式格式无效:{ex.Message}"; return false; } catch (Exception ex) { errorMessage = $"Cron 表达式校验失败:{ex.Message}"; return false; } } } public enum CronInputMode { [Description("可视化选择")] Preset, [Description("手动 Cron")] Manual }