feat(app): 初始化自动关机工具首个版本

实现基于 WPF 的 AutoShutdown 主界面,支持关机、重启、睡眠、休眠、唤醒、锁屏和注销等电源任务。

支持指定时间和倒计时计划、执行前提醒、系统关机撤销、Windows 唤醒任务、托盘运行、自定义图标以及 OmniNotify 通知适配。

修复关闭到托盘时的运行提醒,并支持单击托盘图标打开或收起主界面。

补充 README、发布配置和 win-x64 Release 输出要求。

Release: win-x64
This commit is contained in:
2026-05-18 23:54:58 +08:00
commit d2d81a482b
17 changed files with 1611 additions and 0 deletions

282
MainWindow.xaml Normal file
View File

@@ -0,0 +1,282 @@
<Window x:Class="AutoShutdown.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AutoShutdown"
Icon="app.ico"
Width="980"
Height="560"
MinWidth="860"
MinHeight="540"
Background="#F6F8FC"
FontFamily="Microsoft YaHei UI"
FontSize="14"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<SolidColorBrush x:Key="InkBrush" Color="#111827"/>
<SolidColorBrush x:Key="MutedBrush" Color="#64748B"/>
<SolidColorBrush x:Key="CardBrush" Color="#FFFFFF"/>
<SolidColorBrush x:Key="AccentBrush" Color="#2563EB"/>
<SolidColorBrush x:Key="AccentSoftBrush" Color="#E2ECFF"/>
<SolidColorBrush x:Key="BorderBrushSoft" Color="#DEE6F2"/>
<SolidColorBrush x:Key="DangerBrush" Color="#DC2626"/>
<SolidColorBrush x:Key="SlateButtonBrush" Color="#475569"/>
<SolidColorBrush x:Key="SuccessBrush" Color="#008060"/>
<Style x:Key="ModernButton" TargetType="Button">
<Setter Property="Height" Value="40"/>
<Setter Property="MinWidth" Value="112"/>
<Setter Property="Padding" Value="18,0"/>
<Setter Property="Margin" Value="0,0,12,0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Root"
Background="{TemplateBinding Background}"
CornerRadius="6"
SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Root" Property="Opacity" Value="0.88"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Root" Property="Opacity" Value="0.76"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Root" Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ActionChoiceButton" TargetType="Button">
<Setter Property="Height" Value="42"/>
<Setter Property="Margin" Value="0,0,0,8"/>
<Setter Property="Padding" Value="18,0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Background" Value="{StaticResource CardBrush}"/>
<Setter Property="Foreground" Value="{StaticResource InkBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrushSoft}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Root"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="6"
SnapsToDevicePixels="True">
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Root" Property="Background" Value="#F4F8FF"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Root" Property="Background" Value="{StaticResource AccentSoftBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModernTextBox" TargetType="TextBox">
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="64"/>
<Setter Property="Padding" Value="8,3"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{StaticResource InkBrush}"/>
<Setter Property="BorderBrush" Value="#CAD5E4"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border x:Name="Root"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Root" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Root" Property="Opacity" Value="0.55"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Foreground" Value="{StaticResource InkBrush}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<StackPanel Orientation="Horizontal">
<Grid Width="18" Height="18" Margin="0,1,8,0">
<Ellipse Stroke="#6B7280" StrokeThickness="1.4" Fill="White"/>
<Ellipse x:Name="Dot" Width="8" Height="8" Fill="{StaticResource AccentBrush}" Opacity="0"/>
</Grid>
<ContentPresenter VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Dot" Property="Opacity" Value="1"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.55"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Foreground" Value="{StaticResource InkBrush}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Margin" Value="0,0,18,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<StackPanel Orientation="Horizontal">
<Border x:Name="Box" Width="18" Height="18" Margin="0,1,8,0"
BorderBrush="#6B7280" BorderThickness="1.4" CornerRadius="4" Background="White">
<Path x:Name="Tick" Data="M 4 9 L 8 13 L 15 5"
Stroke="White" StrokeThickness="2" StrokeStartLineCap="Round"
StrokeEndLineCap="Round" Opacity="0"/>
</Border>
<ContentPresenter VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Box" Property="Background" Value="{StaticResource AccentBrush}"/>
<Setter TargetName="Box" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
<Setter TargetName="Tick" Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="#F6F8FC">
<Grid Margin="18" Background="#F6F8FC">
<Grid.RowDefinitions>
<RowDefinition Height="480"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Width="920" Height="480" HorizontalAlignment="Center" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="White" CornerRadius="8" Padding="20,18">
<StackPanel>
<TextBlock Text="选择动作"
FontSize="18"
FontWeight="Bold"
Foreground="{StaticResource InkBrush}"
Margin="0,0,0,14"/>
<Button x:Name="ShutdownButton" Content="关机" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="RestartButton" Content="重启" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="SleepButton" Content="睡眠" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="HibernateButton" Content="休眠" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="WakeButton" Content="唤醒" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="LockButton" Content="锁屏" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
<Button x:Name="LogOffButton" Content="注销" Style="{StaticResource ActionChoiceButton}" Click="ActionButton_Click"/>
</StackPanel>
</Border>
<Border Grid.Column="2" Background="White" CornerRadius="8" Padding="28,18">
<StackPanel>
<TextBlock Text="任务计划"
FontSize="18"
FontWeight="Bold"
Foreground="{StaticResource InkBrush}"/>
<TextBlock x:Name="ActionTitleText"
Margin="0,10,0,0"
FontSize="28"
FontWeight="Bold"
Foreground="{StaticResource InkBrush}"/>
<TextBlock x:Name="ActionDescriptionText"
Margin="2,0,0,20"
FontSize="14"
Foreground="{StaticResource MutedBrush}"/>
<RadioButton x:Name="ClockRadio" Content="指定时间" IsChecked="True" Checked="ScheduleModeChanged"/>
<StackPanel Orientation="Horizontal" Margin="20,0,0,18">
<TextBox x:Name="DateInput" Style="{StaticResource ModernTextBox}" Width="120"/>
<TextBox x:Name="TimeInput" Style="{StaticResource ModernTextBox}" Width="74"/>
</StackPanel>
<RadioButton x:Name="CountdownRadio" Content="倒计时" Checked="ScheduleModeChanged"/>
<StackPanel Orientation="Horizontal" Margin="20,0,0,18">
<TextBox x:Name="HoursInput" Style="{StaticResource ModernTextBox}" Text="0"/>
<TextBlock Text="小时" Foreground="{StaticResource MutedBrush}" VerticalAlignment="Center" Margin="0,0,14,0"/>
<TextBox x:Name="MinutesInput" Style="{StaticResource ModernTextBox}" Text="30"/>
<TextBlock Text="分钟" Foreground="{StaticResource MutedBrush}" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,24">
<CheckBox x:Name="ForceCheck" Content="强制关闭"/>
<TextBlock Text="提醒" Foreground="{StaticResource MutedBrush}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBox x:Name="ReminderInput" Style="{StaticResource ModernTextBox}" Text="5"/>
<TextBlock Text="分钟前" Foreground="{StaticResource MutedBrush}" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="StartPlanButton" Content="开始计划" Background="{StaticResource AccentBrush}" Style="{StaticResource ModernButton}" Click="StartButton_Click"/>
<Button x:Name="CancelPlanButton" Content="取消计划" Background="{StaticResource SlateButtonBrush}" Style="{StaticResource ModernButton}" Click="CancelButton_Click"/>
<Button x:Name="AbortShutdownButton" Content="撤销关机" Background="{StaticResource DangerBrush}" Style="{StaticResource ModernButton}" Click="AbortButton_Click"/>
<Button Content="通知设置" Background="{StaticResource SlateButtonBrush}" Style="{StaticResource ModernButton}" Click="SettingsButton_Click"/>
</StackPanel>
<Border Background="#F8FAFC" CornerRadius="6" Padding="12,8" Margin="0,22,0,0">
<Grid>
<TextBlock x:Name="StatusText"
VerticalAlignment="Center"
FontSize="13"
FontWeight="SemiBold"
Foreground="{StaticResource MutedBrush}"/>
<TextBlock x:Name="CountdownText"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="{StaticResource SuccessBrush}"/>
</Grid>
</Border>
</StackPanel>
</Border>
</Grid>
</Grid>
</Grid>
</Window>