mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-27 10:15:50 +08:00
新增触发器与持久化
This commit is contained in:
@@ -12,6 +12,7 @@ using BetterGenshinImpact.Helpers.Extensions;
|
|||||||
using BetterGenshinImpact.Helpers.Win32;
|
using BetterGenshinImpact.Helpers.Win32;
|
||||||
using BetterGenshinImpact.Hutao;
|
using BetterGenshinImpact.Hutao;
|
||||||
using BetterGenshinImpact.Service;
|
using BetterGenshinImpact.Service;
|
||||||
|
using BetterGenshinImpact.Service.GearTask;
|
||||||
using BetterGenshinImpact.Service.Interface;
|
using BetterGenshinImpact.Service.Interface;
|
||||||
using BetterGenshinImpact.Service.Notification;
|
using BetterGenshinImpact.Service.Notification;
|
||||||
using BetterGenshinImpact.Service.Notifier;
|
using BetterGenshinImpact.Service.Notifier;
|
||||||
@@ -159,6 +160,7 @@ public partial class App : Application
|
|||||||
services.AddSingleton<BgiOnnxFactory>();
|
services.AddSingleton<BgiOnnxFactory>();
|
||||||
services.AddSingleton<OcrFactory>();
|
services.AddSingleton<OcrFactory>();
|
||||||
services.AddSingleton<GearTaskStorageService>();
|
services.AddSingleton<GearTaskStorageService>();
|
||||||
|
services.AddSingleton<GearTriggerStorageService>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 齿轮触发器存储服务,负责触发器数据的 JSON 持久化
|
||||||
|
/// </summary>
|
||||||
|
public class GearTriggerStorageService
|
||||||
|
{
|
||||||
|
private readonly ILogger<GearTriggerStorageService> _logger;
|
||||||
|
private readonly string _triggerStoragePath;
|
||||||
|
private readonly string _triggerFilePath;
|
||||||
|
private readonly JsonSerializerSettings _jsonSettings;
|
||||||
|
|
||||||
|
public GearTriggerStorageService(ILogger<GearTriggerStorageService> 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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存所有触发器到 JSON 文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timedTriggers">定时触发器列表</param>
|
||||||
|
/// <param name="hotkeyTriggers">快捷键触发器列表</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task SaveTriggersAsync(IEnumerable<GearTriggerViewModel> timedTriggers, IEnumerable<GearTriggerViewModel> hotkeyTriggers)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var triggerData = new GearTriggerCollectionData
|
||||||
|
{
|
||||||
|
TimedTriggers = new List<GearTriggerData>(),
|
||||||
|
HotkeyTriggers = new List<GearTriggerData>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 转换定时触发器
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从 JSON 文件加载所有触发器
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<(List<GearTriggerViewModel> TimedTriggers, List<GearTriggerViewModel> HotkeyTriggers)> LoadTriggersAsync()
|
||||||
|
{
|
||||||
|
var timedTriggers = new List<GearTriggerViewModel>();
|
||||||
|
var hotkeyTriggers = new List<GearTriggerViewModel>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!File.Exists(_triggerFilePath))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("触发器数据文件不存在,返回空列表: {FilePath}", _triggerFilePath);
|
||||||
|
return (timedTriggers, hotkeyTriggers);
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = await File.ReadAllTextAsync(_triggerFilePath);
|
||||||
|
var triggerData = JsonConvert.DeserializeObject<GearTriggerCollectionData>(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将 ViewModel 转换为数据模型
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将数据模型转换为 ViewModel
|
||||||
|
/// </summary>
|
||||||
|
private GearTriggerViewModel? ConvertToViewModel(GearTriggerData data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse<TriggerType>(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器集合数据模型,用于 JSON 序列化
|
||||||
|
/// </summary>
|
||||||
|
public class GearTriggerCollectionData
|
||||||
|
{
|
||||||
|
[JsonProperty("timed_triggers")]
|
||||||
|
public List<GearTriggerData> TimedTriggers { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonProperty("hotkey_triggers")]
|
||||||
|
public List<GearTriggerData> HotkeyTriggers { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器数据模型,用于 JSON 序列化
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -276,16 +276,36 @@
|
|||||||
<TabItem Header="定时触发" Style="{StaticResource ConsistentTabItemStyle}">
|
<TabItem Header="定时触发" Style="{StaticResource ConsistentTabItemStyle}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- 工具栏 -->
|
||||||
|
<Border Grid.Row="0"
|
||||||
|
Background="{DynamicResource CardBackgroundFillColorSecondaryBrush}"
|
||||||
|
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="0,0,0,1"
|
||||||
|
Padding="12,8">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<ui:Button Content="新增定时触发器"
|
||||||
|
Command="{Binding AddTimedTriggerCommand}"
|
||||||
|
Icon="{ui:SymbolIcon Add24}"
|
||||||
|
Appearance="Primary"
|
||||||
|
Margin="0,0,8,0" />
|
||||||
|
<ui:Button Content="删除选中项"
|
||||||
|
Command="{Binding DeleteTriggerCommand}"
|
||||||
|
Icon="{ui:SymbolIcon Delete24}"
|
||||||
|
Appearance="Secondary" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<!-- 固定表格头部 -->
|
<!-- 固定表格头部 -->
|
||||||
<ContentPresenter Grid.Row="0"
|
<ContentPresenter Grid.Row="1"
|
||||||
ContentTemplate="{StaticResource TimedTableHeaderTemplate}" />
|
ContentTemplate="{StaticResource TimedTableHeaderTemplate}" />
|
||||||
|
|
||||||
<!-- 可滚动的列表内容 -->
|
<!-- 可滚动的列表内容 -->
|
||||||
<ScrollViewer Grid.Row="1"
|
<ScrollViewer Grid.Row="2"
|
||||||
VerticalScrollBarVisibility="Auto"
|
VerticalScrollBarVisibility="Auto"
|
||||||
HorizontalScrollBarVisibility="Disabled">
|
HorizontalScrollBarVisibility="Disabled">
|
||||||
<ui:ListView ItemsSource="{Binding TimedTriggers}"
|
<ui:ListView ItemsSource="{Binding TimedTriggers}"
|
||||||
@@ -300,16 +320,36 @@
|
|||||||
<TabItem Header="快捷键触发" Style="{StaticResource ConsistentTabItemStyle}">
|
<TabItem Header="快捷键触发" Style="{StaticResource ConsistentTabItemStyle}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- 工具栏 -->
|
||||||
|
<Border Grid.Row="0"
|
||||||
|
Background="{DynamicResource CardBackgroundFillColorSecondaryBrush}"
|
||||||
|
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="0,0,0,1"
|
||||||
|
Padding="12,8">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<ui:Button Content="新增快捷键触发器"
|
||||||
|
Command="{Binding AddHotkeyTriggerCommand}"
|
||||||
|
Icon="{ui:SymbolIcon Add24}"
|
||||||
|
Appearance="Primary"
|
||||||
|
Margin="0,0,8,0" />
|
||||||
|
<ui:Button Content="删除选中项"
|
||||||
|
Command="{Binding DeleteTriggerCommand}"
|
||||||
|
Icon="{ui:SymbolIcon Delete24}"
|
||||||
|
Appearance="Secondary" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<!-- 固定表格头部 -->
|
<!-- 固定表格头部 -->
|
||||||
<ContentPresenter Grid.Row="0"
|
<ContentPresenter Grid.Row="1"
|
||||||
ContentTemplate="{StaticResource TableHeaderTemplate}" />
|
ContentTemplate="{StaticResource TableHeaderTemplate}" />
|
||||||
|
|
||||||
<!-- 可滚动的列表内容 -->
|
<!-- 可滚动的列表内容 -->
|
||||||
<ScrollViewer Grid.Row="1"
|
<ScrollViewer Grid.Row="2"
|
||||||
VerticalScrollBarVisibility="Auto"
|
VerticalScrollBarVisibility="Auto"
|
||||||
HorizontalScrollBarVisibility="Disabled">
|
HorizontalScrollBarVisibility="Disabled">
|
||||||
<ui:ListView ItemsSource="{Binding HotkeyTriggers}"
|
<ui:ListView ItemsSource="{Binding HotkeyTriggers}"
|
||||||
|
|||||||
127
BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml
Normal file
127
BetterGenshinImpact/View/Windows/GearTask/AddTriggerDialog.xaml
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
<ui:FluentWindow x:Class="BetterGenshinImpact.View.Windows.GearTask.AddTriggerDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||||
|
xmlns:gearTask="clr-namespace:BetterGenshinImpact.ViewModel.Windows.GearTask"
|
||||||
|
xmlns:converters="clr-namespace:BetterGenshinImpact.View.Converters"
|
||||||
|
d:DataContext="{d:DesignInstance Type=gearTask:AddTriggerDialogViewModel}"
|
||||||
|
Width="500"
|
||||||
|
Height="450"
|
||||||
|
MinWidth="450"
|
||||||
|
MinHeight="400"
|
||||||
|
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
|
||||||
|
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||||
|
ExtendsContentIntoTitleBar="True"
|
||||||
|
FontFamily="{DynamicResource TextThemeFontFamily}"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
WindowStyle="SingleBorderWindow"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<ui:FluentWindow.Resources>
|
||||||
|
<converters:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />
|
||||||
|
</ui:FluentWindow.Resources>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- 标题栏 -->
|
||||||
|
<ui:TitleBar Grid.Row="0" Title="新增触发器">
|
||||||
|
<ui:TitleBar.Icon>
|
||||||
|
<ui:ImageIcon Source="pack://application:,,,/Resources/Images/logo.png" />
|
||||||
|
</ui:TitleBar.Icon>
|
||||||
|
</ui:TitleBar>
|
||||||
|
|
||||||
|
<!-- 主要内容 -->
|
||||||
|
<ScrollViewer Grid.Row="1" Margin="20" VerticalScrollBarVisibility="Auto">
|
||||||
|
<StackPanel>
|
||||||
|
|
||||||
|
<!-- 触发器名称 -->
|
||||||
|
<StackPanel>
|
||||||
|
<ui:TextBlock Text="触发器名称" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
<ui:TextBox x:Name="TriggerNameTextBox"
|
||||||
|
Text="{Binding TriggerName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
PlaceholderText="请输入触发器名称" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 触发器类型 -->
|
||||||
|
<StackPanel Margin="0,16,0,0">
|
||||||
|
<ui:TextBlock Text="触发器类型" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
<ComboBox ItemsSource="{Binding TriggerTypes}"
|
||||||
|
SelectedValue="{Binding SelectedTriggerType, Mode=TwoWay}"
|
||||||
|
SelectedValuePath="Value"
|
||||||
|
DisplayMemberPath="DisplayName"
|
||||||
|
IsEnabled="{Binding IsTriggerTypeSelectionEnabled}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 定时触发设置 -->
|
||||||
|
<StackPanel Margin="0,16,0,0"
|
||||||
|
Visibility="{Binding SelectedTriggerType, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=Timed}">
|
||||||
|
<ui:TextBlock Text="Cron 表达式" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
<ui:TextBox Text="{Binding CronExpression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
PlaceholderText="例如: 0 0 8 * * ? (每天8点)"
|
||||||
|
FontFamily="Consolas" />
|
||||||
|
<ui:TextBlock Text="格式: 秒 分 时 日 月 星期 [年]"
|
||||||
|
FontSize="12"
|
||||||
|
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||||
|
Margin="0,4,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 热键触发设置 -->
|
||||||
|
<StackPanel Margin="0,16,0,0"
|
||||||
|
Visibility="{Binding SelectedTriggerType, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=Hotkey}">
|
||||||
|
<ui:TextBlock Text="快捷键" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<ui:TextBox Grid.Column="0"
|
||||||
|
Text="{Binding SelectedHotkey, Mode=OneWay}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
PlaceholderText="点击右侧按钮设置快捷键" />
|
||||||
|
|
||||||
|
<ui:Button Grid.Column="1"
|
||||||
|
Content="设置"
|
||||||
|
Command="{Binding SelectHotkeyCommand}"
|
||||||
|
Margin="8,0,0,0" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 关联任务 -->
|
||||||
|
<StackPanel Margin="0,16,0,0">
|
||||||
|
<ui:TextBlock Text="关联任务定义" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
<ComboBox ItemsSource="{Binding AvailableTaskDefinitions}"
|
||||||
|
SelectedItem="{Binding SelectedTaskDefinitionName, Mode=TwoWay}"
|
||||||
|
IsEditable="True" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<!-- 按钮栏 -->
|
||||||
|
<Border Grid.Row="2"
|
||||||
|
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="0,1,0,0"
|
||||||
|
Padding="20,16">
|
||||||
|
<StackPanel Orientation="Horizontal"
|
||||||
|
HorizontalAlignment="Right">
|
||||||
|
<ui:Button Content="取消"
|
||||||
|
Command="{Binding CancelCommand}"
|
||||||
|
Appearance="Secondary"
|
||||||
|
MinWidth="80" />
|
||||||
|
<ui:Button Content="确定"
|
||||||
|
Command="{Binding ConfirmCommand}"
|
||||||
|
Appearance="Primary"
|
||||||
|
MinWidth="80" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ui:FluentWindow>
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示新增触发器对话框
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>如果用户点击确定返回创建的触发器ViewModel,否则返回null</returns>
|
||||||
|
public static AddTriggerDialogViewModel? ShowAddTriggerDialog()
|
||||||
|
{
|
||||||
|
// 使用依赖注入获取 ViewModel
|
||||||
|
var storageService = App.GetRequiredService<GearTaskStorageService>();
|
||||||
|
var logger = App.GetRequiredService<ILogger<AddTriggerDialogViewModel>>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示新增触发器对话框,指定触发器类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predefinedType">预定义的触发器类型</param>
|
||||||
|
/// <returns>如果用户点击确定返回创建的触发器ViewModel,否则返回null</returns>
|
||||||
|
public static AddTriggerDialogViewModel? ShowAddTriggerDialog(TriggerType predefinedType)
|
||||||
|
{
|
||||||
|
// 使用依赖注入获取 ViewModel
|
||||||
|
var storageService = App.GetRequiredService<GearTaskStorageService>();
|
||||||
|
var logger = App.GetRequiredService<ILogger<AddTriggerDialogViewModel>>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
using BetterGenshinImpact.Model.Gear.Triggers;
|
using BetterGenshinImpact.Model.Gear.Triggers;
|
||||||
using BetterGenshinImpact.Model.Gear.Tasks;
|
|
||||||
using BetterGenshinImpact.Model;
|
using BetterGenshinImpact.Model;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace BetterGenshinImpact.ViewModel.Pages.Component;
|
namespace BetterGenshinImpact.ViewModel.Pages.Component;
|
||||||
|
|
||||||
@@ -107,10 +108,12 @@ public enum TriggerType
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定时触发
|
/// 定时触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Description("定时触发")]
|
||||||
Timed,
|
Timed,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 热键触发
|
/// 热键触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Description("热键触发")]
|
||||||
Hotkey
|
Hotkey
|
||||||
}
|
}
|
||||||
@@ -5,11 +5,19 @@ using BetterGenshinImpact.ViewModel.Pages.Component;
|
|||||||
using BetterGenshinImpact.Model.Gear.Triggers;
|
using BetterGenshinImpact.Model.Gear.Triggers;
|
||||||
using BetterGenshinImpact.Model;
|
using BetterGenshinImpact.Model;
|
||||||
using System.Linq;
|
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;
|
namespace BetterGenshinImpact.ViewModel.Pages;
|
||||||
|
|
||||||
public partial class GearTriggerPageViewModel : ViewModel
|
public partial class GearTriggerPageViewModel : ViewModel
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<GearTriggerPageViewModel> _logger;
|
||||||
|
private readonly GearTriggerStorageService _storageService;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private ObservableCollection<GearTriggerViewModel> _timedTriggers = new();
|
private ObservableCollection<GearTriggerViewModel> _timedTriggers = new();
|
||||||
|
|
||||||
@@ -22,29 +30,103 @@ public partial class GearTriggerPageViewModel : ViewModel
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private GearTaskDefinitionViewModel? _selectedTaskDefinition;
|
private GearTaskDefinitionViewModel? _selectedTaskDefinition;
|
||||||
|
|
||||||
public GearTriggerPageViewModel()
|
public GearTriggerPageViewModel(ILogger<GearTriggerPageViewModel> logger, GearTriggerStorageService storageService)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_storageService = storageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnNavigatedTo()
|
public override void OnNavigatedTo()
|
||||||
{
|
{
|
||||||
|
_ = LoadTriggersAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步加载触发器数据
|
||||||
|
/// </summary>
|
||||||
|
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, "加载触发器数据时发生错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存触发器数据
|
||||||
|
/// </summary>
|
||||||
|
private async Task SaveTriggersAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _storageService.SaveTriggersAsync(TimedTriggers, HotkeyTriggers);
|
||||||
|
_logger.LogInformation("触发器数据已保存");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "保存触发器数据时发生错误");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void AddTimedTrigger()
|
private void AddTimedTrigger()
|
||||||
{
|
{
|
||||||
var newTrigger = new GearTriggerViewModel($"定时触发器 {TimedTriggers.Count + 1}", TriggerType.Timed);
|
var dialog = AddTriggerDialog.ShowAddTriggerDialog(TriggerType.Timed);
|
||||||
TimedTriggers.Add(newTrigger);
|
if (dialog != null)
|
||||||
SelectedTrigger = newTrigger;
|
{
|
||||||
|
var newTrigger = new GearTriggerViewModel(dialog.TriggerName, TriggerType.Timed)
|
||||||
|
{
|
||||||
|
CronExpression = dialog.CronExpression,
|
||||||
|
TaskDefinitionName = dialog.SelectedTaskDefinitionName,
|
||||||
|
IsEnabled = true
|
||||||
|
};
|
||||||
|
TimedTriggers.Add(newTrigger);
|
||||||
|
SelectedTrigger = newTrigger;
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
_ = SaveTriggersAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void AddHotkeyTrigger()
|
private void AddHotkeyTrigger()
|
||||||
{
|
{
|
||||||
var newTrigger = new GearTriggerViewModel($"快捷键触发器 {HotkeyTriggers.Count + 1}", TriggerType.Hotkey);
|
var dialog = AddTriggerDialog.ShowAddTriggerDialog(TriggerType.Hotkey);
|
||||||
HotkeyTriggers.Add(newTrigger);
|
if (dialog != null)
|
||||||
SelectedTrigger = newTrigger;
|
{
|
||||||
|
var newTrigger = new GearTriggerViewModel(dialog.TriggerName, TriggerType.Hotkey)
|
||||||
|
{
|
||||||
|
Hotkey = dialog.SelectedHotkey,
|
||||||
|
TaskDefinitionName = dialog.SelectedTaskDefinitionName,
|
||||||
|
IsEnabled = true
|
||||||
|
};
|
||||||
|
HotkeyTriggers.Add(newTrigger);
|
||||||
|
SelectedTrigger = newTrigger;
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
_ = SaveTriggersAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -63,5 +145,8 @@ public partial class GearTriggerPageViewModel : ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectedTrigger = null;
|
SelectedTrigger = null;
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
_ = SaveTriggersAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增触发器对话框 ViewModel
|
||||||
|
/// </summary>
|
||||||
|
public partial class AddTriggerDialogViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly GearTaskStorageService _storageService;
|
||||||
|
private readonly ILogger<AddTriggerDialogViewModel> _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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器类型选择是否可用
|
||||||
|
/// </summary>
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isTriggerTypeSelectionEnabled = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可用的触发器类型
|
||||||
|
/// </summary>
|
||||||
|
public ObservableCollection<EnumItem<TriggerType>> TriggerTypes { get; } = new()
|
||||||
|
{
|
||||||
|
EnumItem<TriggerType>.Create(TriggerType.Timed),
|
||||||
|
EnumItem<TriggerType>.Create(TriggerType.Hotkey)
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可用的任务定义列表
|
||||||
|
/// </summary>
|
||||||
|
[ObservableProperty]
|
||||||
|
private ObservableCollection<string> _availableTaskDefinitions = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求关闭事件
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<bool>? RequestClose;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建的触发器
|
||||||
|
/// </summary>
|
||||||
|
public GearTriggerViewModel? CreatedTrigger { get; private set; }
|
||||||
|
|
||||||
|
public AddTriggerDialogViewModel(GearTaskStorageService storageService, ILogger<AddTriggerDialogViewModel> logger)
|
||||||
|
{
|
||||||
|
_storageService = storageService;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
// 生成默认名称
|
||||||
|
GenerateDefaultName();
|
||||||
|
|
||||||
|
// 加载可用的任务定义
|
||||||
|
LoadAvailableTaskDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,用于指定触发器类型
|
||||||
|
/// </summary>
|
||||||
|
public AddTriggerDialogViewModel(GearTaskStorageService storageService, ILogger<AddTriggerDialogViewModel> logger, TriggerType? predefinedType = null)
|
||||||
|
{
|
||||||
|
_storageService = storageService;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
// 如果指定了预定义类型,则设置并禁用选择
|
||||||
|
if (predefinedType.HasValue)
|
||||||
|
{
|
||||||
|
SelectedTriggerType = predefinedType.Value;
|
||||||
|
IsTriggerTypeSelectionEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成默认名称
|
||||||
|
GenerateDefaultName();
|
||||||
|
|
||||||
|
// 加载可用的任务定义
|
||||||
|
LoadAvailableTaskDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成默认触发器名称
|
||||||
|
/// </summary>
|
||||||
|
private void GenerateDefaultName()
|
||||||
|
{
|
||||||
|
var typeName = SelectedTriggerType == TriggerType.Timed ? "定时触发器" : "热键触发器";
|
||||||
|
TriggerName = $"{typeName} {DateTime.Now:MMdd_HHmm}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载可用的任务定义
|
||||||
|
/// </summary>
|
||||||
|
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("(无可用任务定义)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器类型改变时的处理
|
||||||
|
/// </summary>
|
||||||
|
partial void OnSelectedTriggerTypeChanged(TriggerType value)
|
||||||
|
{
|
||||||
|
GenerateDefaultName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 确认创建触发器
|
||||||
|
/// </summary>
|
||||||
|
[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消创建
|
||||||
|
/// </summary>
|
||||||
|
[RelayCommand]
|
||||||
|
private void Cancel()
|
||||||
|
{
|
||||||
|
RequestClose?.Invoke(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 选择热键
|
||||||
|
/// </summary>
|
||||||
|
[RelayCommand]
|
||||||
|
private void SelectHotkey()
|
||||||
|
{
|
||||||
|
// TODO: 打开热键选择对话框
|
||||||
|
// 这里先创建一个示例热键
|
||||||
|
SelectedHotkey = new HotKey(System.Windows.Input.Key.F1, System.Windows.Input.ModifierKeys.Control);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user