From 95a1cc3dfa6d8feb3dfd3dde03ca0f8b35293dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Thu, 2 Oct 2025 22:49:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A7=A6=E5=8F=91=E5=99=A8?= =?UTF-8?q?=E4=B8=8E=E6=8C=81=E4=B9=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/App.xaml.cs | 2 + .../GearTask/GearTriggerStorageService.cs | 236 ++++++++++++++++++ .../View/Pages/GearTriggerPage.xaml | 48 +++- .../Windows/GearTask/AddTriggerDialog.xaml | 127 ++++++++++ .../Windows/GearTask/AddTriggerDialog.xaml.cs | 85 +++++++ .../Pages/Component/GearTriggerViewModel.cs | 7 +- .../Pages/GearTriggerPageViewModel.cs | 99 +++++++- .../GearTask/AddTriggerDialogViewModel.cs | 217 ++++++++++++++++ 8 files changed, 808 insertions(+), 13 deletions(-) create mode 100644 BetterGenshinImpact/Service/GearTask/GearTriggerStorageService.cs create mode 100644 BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml create mode 100644 BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml.cs create mode 100644 BetterGenshinImpact/ViewModel/Windows/GearTask/AddTriggerDialogViewModel.cs diff --git a/BetterGenshinImpact/App.xaml.cs b/BetterGenshinImpact/App.xaml.cs index e0721eae..9a44d107 100644 --- a/BetterGenshinImpact/App.xaml.cs +++ b/BetterGenshinImpact/App.xaml.cs @@ -12,6 +12,7 @@ using BetterGenshinImpact.Helpers.Extensions; using BetterGenshinImpact.Helpers.Win32; using BetterGenshinImpact.Hutao; using BetterGenshinImpact.Service; +using BetterGenshinImpact.Service.GearTask; using BetterGenshinImpact.Service.Interface; using BetterGenshinImpact.Service.Notification; using BetterGenshinImpact.Service.Notifier; @@ -159,6 +160,7 @@ public partial class App : Application services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); diff --git a/BetterGenshinImpact/Service/GearTask/GearTriggerStorageService.cs b/BetterGenshinImpact/Service/GearTask/GearTriggerStorageService.cs new file mode 100644 index 00000000..44b97929 --- /dev/null +++ b/BetterGenshinImpact/Service/GearTask/GearTriggerStorageService.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using BetterGenshinImpact.Model; +using BetterGenshinImpact.Model.Gear; +using BetterGenshinImpact.ViewModel.Pages.Component; +using BetterGenshinImpact.Model.Gear.Triggers; +using BetterGenshinImpact.Service.GearTask.Model; + +namespace BetterGenshinImpact.Service.GearTask; + +/// +/// 齿轮触发器存储服务,负责触发器数据的 JSON 持久化 +/// +public class GearTriggerStorageService +{ + private readonly ILogger _logger; + private readonly string _triggerStoragePath; + private readonly string _triggerFilePath; + private readonly JsonSerializerSettings _jsonSettings; + + public GearTriggerStorageService(ILogger logger) + { + _logger = logger; + _triggerStoragePath = GearTaskPaths.TaskTriggerPath; + _triggerFilePath = Path.Combine(_triggerStoragePath, "triggers.json"); + + // 确保目录存在 + Directory.CreateDirectory(_triggerStoragePath); + + // 配置 JSON 序列化设置 + _jsonSettings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + DateFormatString = "yyyy-MM-dd HH:mm:ss", + NullValueHandling = NullValueHandling.Ignore + }; + } + + /// + /// 保存所有触发器到 JSON 文件 + /// + /// 定时触发器列表 + /// 快捷键触发器列表 + /// + public async Task SaveTriggersAsync(IEnumerable timedTriggers, IEnumerable hotkeyTriggers) + { + try + { + var triggerData = new GearTriggerCollectionData + { + TimedTriggers = new List(), + HotkeyTriggers = new List() + }; + + // 转换定时触发器 + foreach (var trigger in timedTriggers) + { + triggerData.TimedTriggers.Add(ConvertToData(trigger)); + } + + // 转换快捷键触发器 + foreach (var trigger in hotkeyTriggers) + { + triggerData.HotkeyTriggers.Add(ConvertToData(trigger)); + } + + var json = JsonConvert.SerializeObject(triggerData, _jsonSettings); + await File.WriteAllTextAsync(_triggerFilePath, json); + + _logger.LogInformation("触发器数据已保存到 {FilePath},定时触发器: {TimedCount},快捷键触发器: {HotkeyCount}", + _triggerFilePath, triggerData.TimedTriggers.Count, triggerData.HotkeyTriggers.Count); + } + catch (Exception ex) + { + _logger.LogError(ex, "保存触发器数据时发生错误"); + throw; + } + } + + /// + /// 从 JSON 文件加载所有触发器 + /// + /// + public async Task<(List TimedTriggers, List HotkeyTriggers)> LoadTriggersAsync() + { + var timedTriggers = new List(); + var hotkeyTriggers = new List(); + + try + { + if (!File.Exists(_triggerFilePath)) + { + _logger.LogInformation("触发器数据文件不存在,返回空列表: {FilePath}", _triggerFilePath); + return (timedTriggers, hotkeyTriggers); + } + + var json = await File.ReadAllTextAsync(_triggerFilePath); + var triggerData = JsonConvert.DeserializeObject(json, _jsonSettings); + + if (triggerData == null) + { + _logger.LogWarning("无法反序列化触发器数据文件: {FilePath}", _triggerFilePath); + return (timedTriggers, hotkeyTriggers); + } + + // 转换定时触发器 + if (triggerData.TimedTriggers != null) + { + foreach (var data in triggerData.TimedTriggers) + { + var viewModel = ConvertToViewModel(data); + if (viewModel != null) + { + timedTriggers.Add(viewModel); + } + } + } + + // 转换快捷键触发器 + if (triggerData.HotkeyTriggers != null) + { + foreach (var data in triggerData.HotkeyTriggers) + { + var viewModel = ConvertToViewModel(data); + if (viewModel != null) + { + hotkeyTriggers.Add(viewModel); + } + } + } + + _logger.LogInformation("触发器数据已从 {FilePath} 加载,定时触发器: {TimedCount},快捷键触发器: {HotkeyCount}", + _triggerFilePath, timedTriggers.Count, hotkeyTriggers.Count); + } + catch (Exception ex) + { + _logger.LogError(ex, "加载触发器数据时发生错误"); + } + + return (timedTriggers, hotkeyTriggers); + } + + /// + /// 将 ViewModel 转换为数据模型 + /// + private GearTriggerData ConvertToData(GearTriggerViewModel viewModel) + { + return new GearTriggerData + { + Name = viewModel.Name, + IsEnabled = viewModel.IsEnabled, + TriggerType = viewModel.TriggerType.ToString(), + CronExpression = viewModel.CronExpression, + Hotkey = viewModel.Hotkey?.ToString() ?? string.Empty, + TaskDefinitionName = viewModel.TaskDefinitionName, + CreatedTime = DateTime.Now, + ModifiedTime = DateTime.Now + }; + } + + /// + /// 将数据模型转换为 ViewModel + /// + private GearTriggerViewModel? ConvertToViewModel(GearTriggerData data) + { + try + { + if (!Enum.TryParse(data.TriggerType, out var triggerType)) + { + _logger.LogWarning("无效的触发器类型: {TriggerType}", data.TriggerType); + return null; + } + + var viewModel = new GearTriggerViewModel(data.Name, triggerType) + { + IsEnabled = data.IsEnabled, + CronExpression = data.CronExpression, + Hotkey = string.IsNullOrEmpty(data.Hotkey) ? null : HotKey.FromString(data.Hotkey), + TaskDefinitionName = data.TaskDefinitionName + }; + + return viewModel; + } + catch (Exception ex) + { + _logger.LogError(ex, "转换触发器数据时发生错误: {TriggerName}", data.Name); + return null; + } + } +} + +/// +/// 触发器集合数据模型,用于 JSON 序列化 +/// +public class GearTriggerCollectionData +{ + [JsonProperty("timed_triggers")] + public List TimedTriggers { get; set; } = new(); + + [JsonProperty("hotkey_triggers")] + public List HotkeyTriggers { get; set; } = new(); +} + +/// +/// 触发器数据模型,用于 JSON 序列化 +/// +public class GearTriggerData +{ + [JsonProperty("name")] + public string Name { get; set; } = string.Empty; + + [JsonProperty("is_enabled")] + public bool IsEnabled { get; set; } = true; + + [JsonProperty("trigger_type")] + public string TriggerType { get; set; } = string.Empty; + + [JsonProperty("cron_expression")] + public string CronExpression { get; set; } = string.Empty; + + [JsonProperty("hotkey")] + public string Hotkey { get; set; } = string.Empty; + + [JsonProperty("task_definition_name")] + public string TaskDefinitionName { get; set; } = string.Empty; + + [JsonProperty("created_time")] + public DateTime CreatedTime { get; set; } = DateTime.Now; + + [JsonProperty("modified_time")] + public DateTime ModifiedTime { get; set; } = DateTime.Now; +} \ No newline at end of file diff --git a/BetterGenshinImpact/View/Pages/GearTriggerPage.xaml b/BetterGenshinImpact/View/Pages/GearTriggerPage.xaml index 0d7437dd..dde35955 100644 --- a/BetterGenshinImpact/View/Pages/GearTriggerPage.xaml +++ b/BetterGenshinImpact/View/Pages/GearTriggerPage.xaml @@ -276,16 +276,36 @@ + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml.cs b/BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml.cs new file mode 100644 index 00000000..3a6940e5 --- /dev/null +++ b/BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml.cs @@ -0,0 +1,85 @@ +using System; +using System.Windows; +using BetterGenshinImpact.Helpers.Ui; +using BetterGenshinImpact.ViewModel.Windows.GearTask; +using BetterGenshinImpact.ViewModel.Pages.Component; +using Microsoft.Extensions.DependencyInjection; +using BetterGenshinImpact.Service; +using Microsoft.Extensions.Logging; + +namespace BetterGenshinImpact.View.Windows.GearTask; + +public partial class AddTriggerDialog +{ + public AddTriggerDialogViewModel ViewModel { get; } + + public AddTriggerDialog(AddTriggerDialogViewModel viewModel) + { + ViewModel = viewModel; + DataContext = ViewModel; + + InitializeComponent(); + + ViewModel.RequestClose += OnRequestClose; + this.SourceInitialized += OnSourceInitialized; + this.Loaded += OnLoaded; + } + + private void OnSourceInitialized(object? sender, EventArgs e) + { + // 应用与主窗口相同的背景主题 + WindowHelper.TryApplySystemBackdrop(this); + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + // 自动聚焦到名称输入框 + TriggerNameTextBox.Focus(); + TriggerNameTextBox.SelectAll(); + } + + private void OnRequestClose(object? sender, bool result) + { + DialogResult = result; + Close(); + } + + /// + /// 显示新增触发器对话框 + /// + /// 如果用户点击确定返回创建的触发器ViewModel,否则返回null + public static AddTriggerDialogViewModel? ShowAddTriggerDialog() + { + // 使用依赖注入获取 ViewModel + var storageService = App.GetRequiredService(); + var logger = App.GetRequiredService>(); + var viewModel = new AddTriggerDialogViewModel(storageService, logger); + + var dialog = new AddTriggerDialog(viewModel) + { + Owner = Application.Current.MainWindow + }; + var result = dialog.ShowDialog(); + return result == true ? dialog.ViewModel : null; + } + + /// + /// 显示新增触发器对话框,指定触发器类型 + /// + /// 预定义的触发器类型 + /// 如果用户点击确定返回创建的触发器ViewModel,否则返回null + public static AddTriggerDialogViewModel? ShowAddTriggerDialog(TriggerType predefinedType) + { + // 使用依赖注入获取 ViewModel + var storageService = App.GetRequiredService(); + var logger = App.GetRequiredService>(); + var viewModel = new AddTriggerDialogViewModel(storageService, logger, predefinedType); + + var dialog = new AddTriggerDialog(viewModel) + { + Owner = Application.Current.MainWindow + }; + var result = dialog.ShowDialog(); + return result == true ? dialog.ViewModel : null; + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/ViewModel/Pages/Component/GearTriggerViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/Component/GearTriggerViewModel.cs index 770d2e3c..74c4daff 100644 --- a/BetterGenshinImpact/ViewModel/Pages/Component/GearTriggerViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/Component/GearTriggerViewModel.cs @@ -1,9 +1,10 @@ using System; using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.ComponentModel; +using System.ComponentModel; +using System.Linq; using BetterGenshinImpact.Model.Gear.Triggers; -using BetterGenshinImpact.Model.Gear.Tasks; using BetterGenshinImpact.Model; +using CommunityToolkit.Mvvm.ComponentModel; namespace BetterGenshinImpact.ViewModel.Pages.Component; @@ -107,10 +108,12 @@ public enum TriggerType /// /// 定时触发 /// + [Description("定时触发")] Timed, /// /// 热键触发 /// + [Description("热键触发")] Hotkey } \ No newline at end of file diff --git a/BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs index 9dee3d8a..dfce0a19 100644 --- a/BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs @@ -5,11 +5,19 @@ using BetterGenshinImpact.ViewModel.Pages.Component; using BetterGenshinImpact.Model.Gear.Triggers; using BetterGenshinImpact.Model; using System.Linq; +using BetterGenshinImpact.View.Windows.GearTask; +using BetterGenshinImpact.Service.GearTask; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; namespace BetterGenshinImpact.ViewModel.Pages; public partial class GearTriggerPageViewModel : ViewModel { + private readonly ILogger _logger; + private readonly GearTriggerStorageService _storageService; + [ObservableProperty] private ObservableCollection _timedTriggers = new(); @@ -22,29 +30,103 @@ public partial class GearTriggerPageViewModel : ViewModel [ObservableProperty] private GearTaskDefinitionViewModel? _selectedTaskDefinition; - public GearTriggerPageViewModel() + public GearTriggerPageViewModel(ILogger logger, GearTriggerStorageService storageService) { + _logger = logger; + _storageService = storageService; } public override void OnNavigatedTo() { + _ = LoadTriggersAsync(); + } + + /// + /// 异步加载触发器数据 + /// + private async Task LoadTriggersAsync() + { + try + { + var (timedTriggers, hotkeyTriggers) = await _storageService.LoadTriggersAsync(); + + TimedTriggers.Clear(); + HotkeyTriggers.Clear(); + + foreach (var trigger in timedTriggers) + { + TimedTriggers.Add(trigger); + } + + foreach (var trigger in hotkeyTriggers) + { + HotkeyTriggers.Add(trigger); + } + + _logger.LogInformation("已加载 {TimedCount} 个定时触发器和 {HotkeyCount} 个快捷键触发器", + TimedTriggers.Count, HotkeyTriggers.Count); + } + catch (Exception ex) + { + _logger.LogError(ex, "加载触发器数据时发生错误"); + } + } + + /// + /// 保存触发器数据 + /// + private async Task SaveTriggersAsync() + { + try + { + await _storageService.SaveTriggersAsync(TimedTriggers, HotkeyTriggers); + _logger.LogInformation("触发器数据已保存"); + } + catch (Exception ex) + { + _logger.LogError(ex, "保存触发器数据时发生错误"); + } } [RelayCommand] private void AddTimedTrigger() { - var newTrigger = new GearTriggerViewModel($"定时触发器 {TimedTriggers.Count + 1}", TriggerType.Timed); - TimedTriggers.Add(newTrigger); - SelectedTrigger = newTrigger; + var dialog = AddTriggerDialog.ShowAddTriggerDialog(TriggerType.Timed); + if (dialog != null) + { + var newTrigger = new GearTriggerViewModel(dialog.TriggerName, TriggerType.Timed) + { + CronExpression = dialog.CronExpression, + TaskDefinitionName = dialog.SelectedTaskDefinitionName, + IsEnabled = true + }; + TimedTriggers.Add(newTrigger); + SelectedTrigger = newTrigger; + + // 保存数据 + _ = SaveTriggersAsync(); + } } [RelayCommand] private void AddHotkeyTrigger() { - var newTrigger = new GearTriggerViewModel($"快捷键触发器 {HotkeyTriggers.Count + 1}", TriggerType.Hotkey); - HotkeyTriggers.Add(newTrigger); - SelectedTrigger = newTrigger; + var dialog = AddTriggerDialog.ShowAddTriggerDialog(TriggerType.Hotkey); + if (dialog != null) + { + var newTrigger = new GearTriggerViewModel(dialog.TriggerName, TriggerType.Hotkey) + { + Hotkey = dialog.SelectedHotkey, + TaskDefinitionName = dialog.SelectedTaskDefinitionName, + IsEnabled = true + }; + HotkeyTriggers.Add(newTrigger); + SelectedTrigger = newTrigger; + + // 保存数据 + _ = SaveTriggersAsync(); + } } [RelayCommand] @@ -63,5 +145,8 @@ public partial class GearTriggerPageViewModel : ViewModel } SelectedTrigger = null; + + // 保存数据 + _ = SaveTriggersAsync(); } } \ No newline at end of file diff --git a/BetterGenshinImpact/ViewModel/Windows/GearTask/AddTriggerDialogViewModel.cs b/BetterGenshinImpact/ViewModel/Windows/GearTask/AddTriggerDialogViewModel.cs new file mode 100644 index 00000000..a8622cab --- /dev/null +++ b/BetterGenshinImpact/ViewModel/Windows/GearTask/AddTriggerDialogViewModel.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using BetterGenshinImpact.ViewModel.Pages.Component; +using BetterGenshinImpact.Model.Gear.Triggers; +using BetterGenshinImpact.Model; +using BetterGenshinImpact.Service; +using Microsoft.Extensions.Logging; +using Wpf.Ui.Violeta.Controls; + +namespace BetterGenshinImpact.ViewModel.Windows.GearTask; + +/// +/// 新增触发器对话框 ViewModel +/// +public partial class AddTriggerDialogViewModel : ObservableObject +{ + private readonly GearTaskStorageService _storageService; + private readonly ILogger _logger; + + [ObservableProperty] + private string _triggerName = string.Empty; + + [ObservableProperty] + private TriggerType _selectedTriggerType = TriggerType.Timed; + + [ObservableProperty] + private string _cronExpression = "0 0 8 * * ?"; // 默认每天8点 + + [ObservableProperty] + private HotKey? _selectedHotkey; + + [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) + }; + + /// + /// 可用的任务定义列表 + /// + [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) + { + _storageService = storageService; + _logger = logger; + + // 如果指定了预定义类型,则设置并禁用选择 + if (predefinedType.HasValue) + { + SelectedTriggerType = predefinedType.Value; + IsTriggerTypeSelectionEnabled = false; + } + + // 生成默认名称 + GenerateDefaultName(); + + // 加载可用的任务定义 + LoadAvailableTaskDefinitions(); + } + + /// + /// 生成默认触发器名称 + /// + 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) + { + SelectedTaskDefinitionName = AvailableTaskDefinitions[0]; + } + } + catch (Exception ex) + { + _logger.LogDebug(ex, "加载可用任务定义时发生错误"); + + // 发生错误时添加一个提示项 + AvailableTaskDefinitions.Clear(); + AvailableTaskDefinitions.Add("(无可用任务定义)"); + } + } + + /// + /// 触发器类型改变时的处理 + /// + partial void OnSelectedTriggerTypeChanged(TriggerType value) + { + GenerateDefaultName(); + } + + /// + /// 确认创建触发器 + /// + [RelayCommand] + private void Confirm() + { + if (string.IsNullOrWhiteSpace(TriggerName)) + { + Toast.Error("请输入触发器名称"); + return; + } + + if (SelectedTriggerType == TriggerType.Timed && string.IsNullOrWhiteSpace(CronExpression)) + { + Toast.Error("请输入 Cron 表达式"); + return; + } + + if (SelectedTriggerType == TriggerType.Hotkey && SelectedHotkey == null) + { + Toast.Error("请选择热键"); + return; + } + + // 创建触发器 ViewModel + CreatedTrigger = new GearTriggerViewModel(TriggerName, SelectedTriggerType) + { + IsEnabled = IsEnabled, + TaskDefinitionName = SelectedTaskDefinitionName, + CronExpression = SelectedTriggerType == TriggerType.Timed ? CronExpression : null, + Hotkey = SelectedTriggerType == TriggerType.Hotkey ? SelectedHotkey : null + }; + + RequestClose?.Invoke(this, true); + } + + /// + /// 取消创建 + /// + [RelayCommand] + private void Cancel() + { + RequestClose?.Invoke(this, false); + } + + /// + /// 选择热键 + /// + [RelayCommand] + private void SelectHotkey() + { + // TODO: 打开热键选择对话框 + // 这里先创建一个示例热键 + SelectedHotkey = new HotKey(System.Windows.Input.Key.F1, System.Windows.Input.ModifierKeys.Control); + } +} \ No newline at end of file