mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
Add GearTriggerPage and related ViewModel; implement trigger functionality
This commit is contained in:
83
BetterGenshinImpact/Model/Gear/Triggers/HotkeyGearTrigger.cs
Normal file
83
BetterGenshinImpact/Model/Gear/Triggers/HotkeyGearTrigger.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using BetterGenshinImpact.Model.Gear.Tasks;
|
||||
using BetterGenshinImpact.Model;
|
||||
|
||||
namespace BetterGenshinImpact.Model.Gear.Triggers;
|
||||
|
||||
/// <summary>
|
||||
/// 热键触发器
|
||||
/// </summary>
|
||||
public class HotkeyGearTrigger : GearBaseTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// 热键配置
|
||||
/// </summary>
|
||||
public HotKey? Hotkey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 冷却时间(毫秒),防止重复触发
|
||||
/// </summary>
|
||||
public int CooldownMs { get; set; } = 1000;
|
||||
|
||||
private DateTime _lastExecutionTime = DateTime.MinValue;
|
||||
private bool _isExecuting = false;
|
||||
|
||||
public override async Task Run()
|
||||
{
|
||||
// 热键触发器通常不直接调用Run方法
|
||||
// 而是通过热键事件触发ExecuteTasks方法
|
||||
await ExecuteTasks();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 热键触发时执行任务
|
||||
/// </summary>
|
||||
public async Task OnHotkeyPressed()
|
||||
{
|
||||
if (!IsEnabled || _isExecuting)
|
||||
return;
|
||||
|
||||
// 检查冷却时间
|
||||
var now = DateTime.Now;
|
||||
if ((now - _lastExecutionTime).TotalMilliseconds < CooldownMs)
|
||||
return;
|
||||
|
||||
_lastExecutionTime = now;
|
||||
_isExecuting = true;
|
||||
|
||||
try
|
||||
{
|
||||
await ExecuteTasks();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isExecuting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteTasks()
|
||||
{
|
||||
List<BaseGearTask> list = GearTaskRefenceList.Select(gearTask => gearTask.ToGearTask()).ToList();
|
||||
foreach (var gearTask in list)
|
||||
{
|
||||
await gearTask.Run(CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取热键显示文本
|
||||
/// </summary>
|
||||
public string GetHotkeyText()
|
||||
{
|
||||
return Hotkey?.ToString() ?? "未设置";
|
||||
}
|
||||
}
|
||||
90
BetterGenshinImpact/Model/Gear/Triggers/TimedGearTrigger.cs
Normal file
90
BetterGenshinImpact/Model/Gear/Triggers/TimedGearTrigger.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BetterGenshinImpact.Model.Gear.Tasks;
|
||||
|
||||
namespace BetterGenshinImpact.Model.Gear.Triggers;
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发器
|
||||
/// </summary>
|
||||
public class TimedGearTrigger : GearBaseTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发间隔(毫秒)
|
||||
/// </summary>
|
||||
public int IntervalMs { get; set; } = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// 是否重复执行
|
||||
/// </summary>
|
||||
public bool IsRepeating { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 延迟启动时间(毫秒)
|
||||
/// </summary>
|
||||
public int DelayMs { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 最大执行次数(0表示无限制)
|
||||
/// </summary>
|
||||
public int MaxExecutions { get; set; } = 0;
|
||||
|
||||
private int _executionCount = 0;
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
|
||||
public override async Task Run()
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_executionCount = 0;
|
||||
|
||||
// 延迟启动
|
||||
if (DelayMs > 0)
|
||||
{
|
||||
await Task.Delay(DelayMs, _cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
// 执行任务
|
||||
await ExecuteTasks();
|
||||
_executionCount++;
|
||||
|
||||
// 检查是否达到最大执行次数
|
||||
if (MaxExecutions > 0 && _executionCount >= MaxExecutions)
|
||||
break;
|
||||
|
||||
// 如果不重复执行,则退出
|
||||
if (!IsRepeating)
|
||||
break;
|
||||
|
||||
// 等待下次执行
|
||||
await Task.Delay(IntervalMs, _cancellationTokenSource.Token);
|
||||
}
|
||||
while (IsRepeating && !_cancellationTokenSource.Token.IsCancellationRequested);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止触发器
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_cancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
private async Task ExecuteTasks()
|
||||
{
|
||||
List<BaseGearTask> list = GearTaskRefenceList.Select(gearTask => gearTask.ToGearTask()).ToList();
|
||||
foreach (var gearTask in list)
|
||||
{
|
||||
if (_cancellationTokenSource?.Token.IsCancellationRequested == true)
|
||||
break;
|
||||
await gearTask.Run(_cancellationTokenSource?.Token ?? CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BetterGenshinImpact.View.Converters;
|
||||
|
||||
[ValueConversion(typeof(Enum), typeof(Visibility))]
|
||||
public class EnumToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null || parameter == null)
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
var enumValue = value.ToString();
|
||||
var targetValue = parameter.ToString();
|
||||
|
||||
return string.Equals(enumValue, targetValue, StringComparison.OrdinalIgnoreCase)
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BetterGenshinImpact.View.Converters;
|
||||
|
||||
[ValueConversion(typeof(object), typeof(Visibility))]
|
||||
public class NullToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
var isInvert = parameter?.ToString()?.Equals("Invert", StringComparison.OrdinalIgnoreCase) == true;
|
||||
var isNull = value == null;
|
||||
|
||||
if (isInvert)
|
||||
{
|
||||
return isNull ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return isNull ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
404
BetterGenshinImpact/View/Pages/GearTriggerPage.xaml
Normal file
404
BetterGenshinImpact/View/Pages/GearTriggerPage.xaml
Normal file
@@ -0,0 +1,404 @@
|
||||
<UserControl x:Class="BetterGenshinImpact.View.Pages.GearTriggerPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||
xmlns:local="clr-namespace:BetterGenshinImpact.View.Pages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:BetterGenshinImpact.ViewModel.Pages"
|
||||
xmlns:component="clr-namespace:BetterGenshinImpact.ViewModel.Pages.Component"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
d:DataContext="{d:DesignInstance Type=pages:GearTriggerPageViewModel}"
|
||||
d:DesignHeight="850"
|
||||
d:DesignWidth="800"
|
||||
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
|
||||
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
FontFamily="{StaticResource TextThemeFontFamily}"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style x:Key="ConsistentTabControlStyle" TargetType="TabControl"
|
||||
BasedOn="{StaticResource {x:Type TabControl}}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TabControl}">
|
||||
<Grid x:Name="templateRoot"
|
||||
Background="{TemplateBinding Background}"
|
||||
ClipToBounds="True"
|
||||
SnapsToDevicePixels="True">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="ColumnDefinition0" Width="Auto" />
|
||||
<ColumnDefinition x:Name="ColumnDefinition1" Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition x:Name="RowDefinition0" Height="Auto" />
|
||||
<RowDefinition x:Name="RowDefinition1" Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TabPanel x:Name="headerPanel"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Background="Transparent"
|
||||
IsItemsHost="True"
|
||||
Panel.ZIndex="1" />
|
||||
<Border x:Name="contentPanel"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="1"
|
||||
Background="{ui:ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderThickness="0">
|
||||
<ContentPresenter x:Name="PART_SelectedContentHost"
|
||||
ContentTemplate="{TemplateBinding SelectedContentTemplate}"
|
||||
Content="{TemplateBinding SelectedContent}"
|
||||
ContentStringFormat="{TemplateBinding SelectedContentStringFormat}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ConsistentTabItemStyle" TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Width" Value="36" />
|
||||
<Setter Property="Height" Value="26" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TabItem}">
|
||||
<Grid x:Name="templateRoot"
|
||||
Background="Transparent"
|
||||
SnapsToDevicePixels="True">
|
||||
<Border x:Name="mainBorder"
|
||||
Background="{ui:ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
BorderThickness="0"
|
||||
CornerRadius="8,8,0,0"
|
||||
Margin="0,0,1,0">
|
||||
<ContentPresenter x:Name="contentPresenter"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Foreground" Value="{ui:ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<Setter TargetName="mainBorder" Property="Background"
|
||||
Value="{ui:ThemeResource CardBackgroundFillColorDefaultBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Foreground" Value="{ui:ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<Setter TargetName="mainBorder" Property="Background"
|
||||
Value="{ui:ThemeResource CardBackgroundFillColorDefaultBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- 触发器项模板 -->
|
||||
<DataTemplate x:Key="TriggerItemTemplate" DataType="{x:Type component:GearTriggerViewModel}">
|
||||
<ui:Card Margin="0,2,0,2" Padding="10,8,10,8">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Ellipse Grid.Column="0"
|
||||
Width="8"
|
||||
Height="8"
|
||||
Margin="0,0,8,0"
|
||||
Fill="{DynamicResource AccentFillColorDefaultBrush}" />
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
IsHitTestVisible="False"
|
||||
Text="{Binding Name}"
|
||||
FontWeight="Medium" />
|
||||
<TextBlock Text="{Binding Description}"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
IsHitTestVisible="False" />
|
||||
</StackPanel>
|
||||
<ui:ToggleSwitch Grid.Column="2"
|
||||
IsChecked="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</ui:Card>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="8,0,8,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="220" />
|
||||
<ColumnDefinition Width="0" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左侧触发器类型选择区域 -->
|
||||
<Border Grid.Column="0"
|
||||
Margin="0,8,0,8"
|
||||
CornerRadius="8">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TabControl Grid.Row="1" Style="{StaticResource ConsistentTabControlStyle}">
|
||||
<!-- 顺序触发选项卡 -->
|
||||
<TabItem Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<TabItem.Header>
|
||||
<ui:SymbolIcon Symbol="ArrowSort24" />
|
||||
</TabItem.Header>
|
||||
<Grid>
|
||||
<StackPanel Margin="8">
|
||||
<ui:TextBlock Margin="0,0,0,8"
|
||||
Text="顺序触发器"
|
||||
FontWeight="SemiBold"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ui:ListView
|
||||
ItemsSource="{Binding SequentialTriggers}"
|
||||
SelectedItem="{Binding SelectedTrigger, Mode=TwoWay}"
|
||||
SelectionMode="Single"
|
||||
ItemTemplate="{StaticResource TriggerItemTemplate}">
|
||||
<ui:ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<Border x:Name="Bd"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ui:ListView.ItemContainerStyle>
|
||||
</ui:ListView>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<!-- 定时触发选项卡 -->
|
||||
<TabItem Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<TabItem.Header>
|
||||
<ui:SymbolIcon Symbol="Clock24" />
|
||||
</TabItem.Header>
|
||||
<Grid>
|
||||
<StackPanel Margin="8">
|
||||
<ui:TextBlock Margin="0,0,0,8"
|
||||
Text="定时触发器"
|
||||
FontWeight="SemiBold"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ui:ListView
|
||||
ItemsSource="{Binding TimedTriggers}"
|
||||
SelectedItem="{Binding SelectedTrigger, Mode=TwoWay}"
|
||||
SelectionMode="Single"
|
||||
ItemTemplate="{StaticResource TriggerItemTemplate}">
|
||||
<ui:ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<Border x:Name="Bd"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ui:ListView.ItemContainerStyle>
|
||||
</ui:ListView>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<!-- 热键触发选项卡 -->
|
||||
<TabItem Style="{StaticResource ConsistentTabItemStyle}">
|
||||
<TabItem.Header>
|
||||
<ui:SymbolIcon Symbol="Keyboard24" />
|
||||
</TabItem.Header>
|
||||
<Grid>
|
||||
<StackPanel Margin="8">
|
||||
<ui:TextBlock Margin="0,0,0,8"
|
||||
Text="热键触发器"
|
||||
FontWeight="SemiBold"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ui:ListView
|
||||
ItemsSource="{Binding HotkeyTriggers}"
|
||||
SelectedItem="{Binding SelectedTrigger, Mode=TwoWay}"
|
||||
SelectionMode="Single"
|
||||
ItemTemplate="{StaticResource TriggerItemTemplate}">
|
||||
<ui:ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<Border x:Name="Bd"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ui:ListView.ItemContainerStyle>
|
||||
</ui:ListView>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 右侧触发器配置区域 -->
|
||||
<Border Grid.Column="2" Margin="0,14,6,15">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<StackPanel Grid.Row="2"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,0,8">
|
||||
<ui:Button Command="{Binding AddSequentialTriggerCommand}"
|
||||
Content="添加顺序触发器"
|
||||
Icon="{ui:SymbolIcon Add24}"
|
||||
Height="26"
|
||||
Padding="8,2,14,0"
|
||||
Margin="0,0,8,0"/>
|
||||
<ui:Button Command="{Binding AddTimedTriggerCommand}"
|
||||
Content="添加定时触发器"
|
||||
Icon="{ui:SymbolIcon Add24}"
|
||||
Height="26"
|
||||
Padding="8,2,14,0"
|
||||
Margin="0,0,8,0"/>
|
||||
<ui:Button Command="{Binding AddHotkeyTriggerCommand}"
|
||||
Content="添加热键触发器"
|
||||
Icon="{ui:SymbolIcon Add24}"
|
||||
Height="26"
|
||||
Padding="8,2,14,0"
|
||||
Margin="0,0,8,0"/>
|
||||
<ui:Button Command="{Binding DeleteTriggerCommand}"
|
||||
Content="删除触发器"
|
||||
Icon="{ui:SymbolIcon Delete24}"
|
||||
Height="26"
|
||||
Padding="8,2,14,0"
|
||||
IsEnabled="{Binding SelectedTrigger, Converter={StaticResource NotNullConverter}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 触发器配置详情 -->
|
||||
<ui:TreeListView Grid.Row="3"
|
||||
ItemsSource="{Binding TaskReferences}"
|
||||
Visibility="{Binding SelectedTrigger, Converter={StaticResource NotNullConverter}}">
|
||||
<ui:TreeListView.Columns>
|
||||
<GridViewColumnCollection>
|
||||
<ui:GridViewColumn Header="功能" Width="200">
|
||||
<ui:GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ui:GridViewColumn.CellTemplate>
|
||||
</ui:GridViewColumn>
|
||||
<ui:GridViewColumn Header="说明" Width="300">
|
||||
<ui:GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Description}" />
|
||||
</DataTemplate>
|
||||
</ui:GridViewColumn.CellTemplate>
|
||||
</ui:GridViewColumn>
|
||||
<ui:GridViewColumn Header="状态" Width="80">
|
||||
<ui:GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<ui:ToggleSwitch IsChecked="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
</DataTemplate>
|
||||
</ui:GridViewColumn.CellTemplate>
|
||||
</ui:GridViewColumn>
|
||||
</GridViewColumnCollection>
|
||||
</ui:TreeListView.Columns>
|
||||
</ui:TreeListView>
|
||||
|
||||
<!-- 无选中触发器时的提示 -->
|
||||
<StackPanel Grid.Row="3"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{Binding SelectedTrigger, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Invert}">
|
||||
<ui:SymbolIcon Symbol="Settings24" FontSize="48" Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
|
||||
<TextBlock Text="请选择一个触发器进行配置"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,16,0,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
19
BetterGenshinImpact/View/Pages/GearTriggerPage.xaml.cs
Normal file
19
BetterGenshinImpact/View/Pages/GearTriggerPage.xaml.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows.Controls;
|
||||
using BetterGenshinImpact.ViewModel.Pages;
|
||||
|
||||
namespace BetterGenshinImpact.View.Pages;
|
||||
|
||||
/// <summary>
|
||||
/// GearTriggerPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class GearTriggerPage : UserControl
|
||||
{
|
||||
public GearTriggerPageViewModel ViewModel { get; }
|
||||
|
||||
public GearTriggerPage(GearTriggerPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using BetterGenshinImpact.Model.Gear.Triggers;
|
||||
using BetterGenshinImpact.Model.Gear.Tasks;
|
||||
using BetterGenshinImpact.Model;
|
||||
|
||||
namespace BetterGenshinImpact.ViewModel.Pages.Component;
|
||||
|
||||
/// <summary>
|
||||
/// 触发器ViewModel
|
||||
/// </summary>
|
||||
public partial class GearTriggerViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _name = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _description = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isEnabled = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isSelected = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private DateTime _createdTime = DateTime.Now;
|
||||
|
||||
[ObservableProperty]
|
||||
private DateTime _modifiedTime = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 触发器类型
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private TriggerType _triggerType = TriggerType.Sequential;
|
||||
|
||||
/// <summary>
|
||||
/// 任务引用列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTaskRefence> _taskReferences = new();
|
||||
|
||||
// 顺序触发器属性(无额外属性)
|
||||
|
||||
// 定时触发器属性
|
||||
[ObservableProperty]
|
||||
private int _intervalMs = 5000;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isRepeating = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _delayMs = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _maxExecutions = 0;
|
||||
|
||||
// 热键触发器属性
|
||||
[ObservableProperty]
|
||||
private HotKey? _hotkey;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _cooldownMs = 1000;
|
||||
|
||||
public GearTriggerViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public GearTriggerViewModel(string name, TriggerType triggerType)
|
||||
{
|
||||
Name = name;
|
||||
TriggerType = triggerType;
|
||||
Description = GetDefaultDescription(triggerType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取触发器类型的默认描述
|
||||
/// </summary>
|
||||
private string GetDefaultDescription(TriggerType triggerType)
|
||||
{
|
||||
return triggerType switch
|
||||
{
|
||||
TriggerType.Sequential => "按顺序执行任务",
|
||||
TriggerType.Timed => "定时执行任务",
|
||||
TriggerType.Hotkey => "热键触发执行任务",
|
||||
_ => "未知触发器类型"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取触发器类型显示名称
|
||||
/// </summary>
|
||||
public string TriggerTypeDisplayName => TriggerType switch
|
||||
{
|
||||
TriggerType.Sequential => "顺序触发",
|
||||
TriggerType.Timed => "定时触发",
|
||||
TriggerType.Hotkey => "热键触发",
|
||||
_ => "未知类型"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 获取热键显示文本
|
||||
/// </summary>
|
||||
public string HotkeyDisplayText => Hotkey?.ToString() ?? "未设置";
|
||||
|
||||
/// <summary>
|
||||
/// 获取定时器配置显示文本
|
||||
/// </summary>
|
||||
public string TimerDisplayText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TriggerType != TriggerType.Timed) return "";
|
||||
|
||||
var text = $"间隔: {IntervalMs}ms";
|
||||
if (DelayMs > 0) text += $", 延迟: {DelayMs}ms";
|
||||
if (MaxExecutions > 0) text += $", 最大次数: {MaxExecutions}";
|
||||
if (!IsRepeating) text += ", 单次执行";
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为对应的触发器实例
|
||||
/// </summary>
|
||||
public GearBaseTrigger ToTrigger()
|
||||
{
|
||||
GearBaseTrigger trigger = TriggerType switch
|
||||
{
|
||||
TriggerType.Sequential => new SequentialGearTrigger(),
|
||||
TriggerType.Timed => new TimedGearTrigger
|
||||
{
|
||||
IntervalMs = IntervalMs,
|
||||
IsRepeating = IsRepeating,
|
||||
DelayMs = DelayMs,
|
||||
MaxExecutions = MaxExecutions
|
||||
},
|
||||
TriggerType.Hotkey => new HotkeyGearTrigger
|
||||
{
|
||||
Hotkey = Hotkey,
|
||||
CooldownMs = CooldownMs,
|
||||
IsEnabled = IsEnabled
|
||||
},
|
||||
_ => new SequentialGearTrigger()
|
||||
};
|
||||
|
||||
trigger.Name = Name;
|
||||
trigger.GearTaskRefenceList = new ObservableCollection<GearTaskRefence>(TaskReferences);
|
||||
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发器类型枚举
|
||||
/// </summary>
|
||||
public enum TriggerType
|
||||
{
|
||||
/// <summary>
|
||||
/// 顺序触发
|
||||
/// </summary>
|
||||
Sequential,
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发
|
||||
/// </summary>
|
||||
Timed,
|
||||
|
||||
/// <summary>
|
||||
/// 热键触发
|
||||
/// </summary>
|
||||
Hotkey
|
||||
}
|
||||
310
BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs
Normal file
310
BetterGenshinImpact/ViewModel/Pages/GearTriggerPageViewModel.cs
Normal file
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using BetterGenshinImpact.ViewModel.Pages.Component;
|
||||
using BetterGenshinImpact.Model.Gear.Tasks;
|
||||
using BetterGenshinImpact.Model;
|
||||
|
||||
namespace BetterGenshinImpact.ViewModel.Pages;
|
||||
|
||||
/// <summary>
|
||||
/// 任务触发页面ViewModel
|
||||
/// </summary>
|
||||
public partial class GearTriggerPageViewModel : ViewModel
|
||||
{
|
||||
private readonly ILogger<GearTriggerPageViewModel> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// 顺序触发器列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTriggerViewModel> _sequentialTriggers = new();
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发器列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTriggerViewModel> _timedTriggers = new();
|
||||
|
||||
/// <summary>
|
||||
/// 热键触发器列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTriggerViewModel> _hotkeyTriggers = new();
|
||||
|
||||
/// <summary>
|
||||
/// 当前选中的触发器
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private GearTriggerViewModel? _selectedTrigger;
|
||||
|
||||
/// <summary>
|
||||
/// 当前选中的触发器类型Tab
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private int _selectedTriggerTypeIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 触发器配置中的任务定义列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTaskDefinitionViewModel> _availableTaskDefinitions = new();
|
||||
|
||||
/// <summary>
|
||||
/// 当前触发器的任务引用列表
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GearTaskRefence> _currentTaskReferences = new();
|
||||
|
||||
/// <summary>
|
||||
/// 当前选中的任务引用
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private GearTaskRefence? _selectedTaskReference;
|
||||
|
||||
public GearTriggerPageViewModel(ILogger<GearTriggerPageViewModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
InitializeData();
|
||||
}
|
||||
|
||||
private void InitializeData()
|
||||
{
|
||||
// 初始化示例数据
|
||||
var sequentialTrigger = new GearTriggerViewModel("示例顺序触发器", TriggerType.Sequential);
|
||||
SequentialTriggers.Add(sequentialTrigger);
|
||||
|
||||
var timedTrigger = new GearTriggerViewModel("示例定时触发器", TriggerType.Timed)
|
||||
{
|
||||
IntervalMs = 10000,
|
||||
IsRepeating = true
|
||||
};
|
||||
TimedTriggers.Add(timedTrigger);
|
||||
|
||||
var hotkeyTrigger = new GearTriggerViewModel("示例热键触发器", TriggerType.Hotkey)
|
||||
{
|
||||
Hotkey = new HotKey(System.Windows.Input.Key.F1, System.Windows.Input.ModifierKeys.Control)
|
||||
};
|
||||
HotkeyTriggers.Add(hotkeyTrigger);
|
||||
|
||||
// 初始化可用的任务定义(这里应该从实际的任务定义服务获取)
|
||||
LoadAvailableTaskDefinitions();
|
||||
}
|
||||
|
||||
private void LoadAvailableTaskDefinitions()
|
||||
{
|
||||
// 这里应该从实际的任务定义服务获取
|
||||
// 暂时创建示例数据
|
||||
var sampleTask = new GearTaskDefinitionViewModel("示例任务组", "这是一个示例任务组");
|
||||
AvailableTaskDefinitions.Add(sampleTask);
|
||||
}
|
||||
|
||||
partial void OnSelectedTriggerChanged(GearTriggerViewModel? value)
|
||||
{
|
||||
UpdateCurrentTaskReferences();
|
||||
}
|
||||
|
||||
private void UpdateCurrentTaskReferences()
|
||||
{
|
||||
CurrentTaskReferences.Clear();
|
||||
if (SelectedTrigger != null)
|
||||
{
|
||||
foreach (var taskRef in SelectedTrigger.TaskReferences)
|
||||
{
|
||||
CurrentTaskReferences.Add(taskRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加顺序触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void AddSequentialTrigger()
|
||||
{
|
||||
var trigger = new GearTriggerViewModel($"顺序触发器 {SequentialTriggers.Count + 1}", TriggerType.Sequential);
|
||||
SequentialTriggers.Add(trigger);
|
||||
SelectedTrigger = trigger;
|
||||
SelectedTriggerTypeIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加定时触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void AddTimedTrigger()
|
||||
{
|
||||
var trigger = new GearTriggerViewModel($"定时触发器 {TimedTriggers.Count + 1}", TriggerType.Timed);
|
||||
TimedTriggers.Add(trigger);
|
||||
SelectedTrigger = trigger;
|
||||
SelectedTriggerTypeIndex = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加热键触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void AddHotkeyTrigger()
|
||||
{
|
||||
var trigger = new GearTriggerViewModel($"热键触发器 {HotkeyTriggers.Count + 1}", TriggerType.Hotkey);
|
||||
HotkeyTriggers.Add(trigger);
|
||||
SelectedTrigger = trigger;
|
||||
SelectedTriggerTypeIndex = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void DeleteTrigger(GearTriggerViewModel? trigger)
|
||||
{
|
||||
if (trigger == null) return;
|
||||
|
||||
var result = MessageBox.Show($"确定要删除触发器 '{trigger.Name}' 吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
switch (trigger.TriggerType)
|
||||
{
|
||||
case TriggerType.Sequential:
|
||||
SequentialTriggers.Remove(trigger);
|
||||
break;
|
||||
case TriggerType.Timed:
|
||||
TimedTriggers.Remove(trigger);
|
||||
break;
|
||||
case TriggerType.Hotkey:
|
||||
HotkeyTriggers.Remove(trigger);
|
||||
break;
|
||||
}
|
||||
|
||||
if (SelectedTrigger == trigger)
|
||||
{
|
||||
SelectedTrigger = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void EditTrigger(GearTriggerViewModel? trigger)
|
||||
{
|
||||
if (trigger == null) return;
|
||||
SelectedTrigger = trigger;
|
||||
|
||||
// 切换到对应的Tab
|
||||
SelectedTriggerTypeIndex = trigger.TriggerType switch
|
||||
{
|
||||
TriggerType.Sequential => 0,
|
||||
TriggerType.Timed => 1,
|
||||
TriggerType.Hotkey => 2,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加任务定义到当前触发器
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void AddTaskDefinition(GearTaskDefinitionViewModel? taskDefinition)
|
||||
{
|
||||
if (taskDefinition == null || SelectedTrigger == null) return;
|
||||
|
||||
// 创建任务引用
|
||||
var taskRef = new GearTaskRefence
|
||||
{
|
||||
Name = taskDefinition.Name,
|
||||
Enabled = true,
|
||||
GearTaskFilePath = $"tasks/{taskDefinition.Name}.json" // 这里应该是实际的文件路径
|
||||
};
|
||||
|
||||
SelectedTrigger.TaskReferences.Add(taskRef);
|
||||
CurrentTaskReferences.Add(taskRef);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除任务引用
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void RemoveTaskReference(GearTaskRefence? taskRef)
|
||||
{
|
||||
if (taskRef == null || SelectedTrigger == null) return;
|
||||
|
||||
SelectedTrigger.TaskReferences.Remove(taskRef);
|
||||
CurrentTaskReferences.Remove(taskRef);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上移任务引用
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void MoveTaskReferenceUp(GearTaskRefence? taskRef)
|
||||
{
|
||||
if (taskRef == null || SelectedTrigger == null) return;
|
||||
|
||||
var index = CurrentTaskReferences.IndexOf(taskRef);
|
||||
if (index > 0)
|
||||
{
|
||||
CurrentTaskReferences.Move(index, index - 1);
|
||||
SelectedTrigger.TaskReferences.Move(index, index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下移任务引用
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void MoveTaskReferenceDown(GearTaskRefence? taskRef)
|
||||
{
|
||||
if (taskRef == null || SelectedTrigger == null) return;
|
||||
|
||||
var index = CurrentTaskReferences.IndexOf(taskRef);
|
||||
if (index < CurrentTaskReferences.Count - 1)
|
||||
{
|
||||
CurrentTaskReferences.Move(index, index + 1);
|
||||
SelectedTrigger.TaskReferences.Move(index, index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存配置
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void SaveConfiguration()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里应该实现保存到文件的逻辑
|
||||
_logger.LogInformation("触发器配置已保存");
|
||||
MessageBox.Show("配置保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "保存触发器配置时发生错误");
|
||||
MessageBox.Show($"保存失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void LoadConfiguration()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里应该实现从文件加载的逻辑
|
||||
_logger.LogInformation("触发器配置已加载");
|
||||
MessageBox.Show("配置加载成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "加载触发器配置时发生错误");
|
||||
MessageBox.Show($"加载失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user