12 changed files with 1902 additions and 4578 deletions
@ -1,372 +0,0 @@ |
|||
<reactive:ReactiveWindow xmlns="https://github.com/avaloniaui" |
|||
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:vm="using:AuroraDesk.Presentation.ViewModels" |
|||
xmlns:converters="using:AuroraDesk.Presentation.Converters" |
|||
xmlns:tooltip="using:Avalonia.Controls" |
|||
xmlns:heroicons="clr-namespace:HeroIconsAvalonia.Controls;assembly=HeroIconsAvalonia" |
|||
xmlns:reactive="clr-namespace:Avalonia.ReactiveUI;assembly=Avalonia.ReactiveUI" |
|||
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" |
|||
x:Class="AuroraDesk.MainWindow" |
|||
x:TypeArguments="vm:MainWindowViewModel" |
|||
x:DataType="vm:MainWindowViewModel" |
|||
Title="{Binding Title}" |
|||
MinWidth="1000" MinHeight="600" |
|||
ExtendClientAreaToDecorationsHint="True" |
|||
ExtendClientAreaChromeHints="NoChrome" |
|||
SystemDecorations="None"> |
|||
|
|||
<Design.DataContext> |
|||
<vm:MainWindowViewModel /> |
|||
</Design.DataContext> |
|||
|
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="250" MinWidth="200"/> |
|||
<ColumnDefinition Width="*"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<!-- 左侧导航栏 --> |
|||
<Border Grid.Column="0" |
|||
Background="{StaticResource PrimaryDark}" |
|||
BorderBrush="{StaticResource PrimaryDarkHover}" |
|||
BorderThickness="0,0,1,0"> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="*"/> |
|||
<RowDefinition Height="Auto"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<!-- 导航栏标题 --> |
|||
<StackPanel Grid.Row="0" Margin="20,20,20,30"> |
|||
<TextBlock Text="{StaticResource AppTitle}" |
|||
FontSize="20" |
|||
FontWeight="Bold" |
|||
Foreground="White" |
|||
HorizontalAlignment="Center"/> |
|||
<TextBlock Text="{StaticResource AppSubtitle}" |
|||
FontSize="12" |
|||
Foreground="{StaticResource SecondaryGray}" |
|||
HorizontalAlignment="Center" |
|||
Margin="0,5,0,0"/> |
|||
</StackPanel> |
|||
|
|||
<!-- 导航菜单 --> |
|||
<ScrollViewer Grid.Row="1" |
|||
VerticalScrollBarVisibility="Auto" |
|||
HorizontalScrollBarVisibility="Disabled" |
|||
Margin="10,0,10,0"> |
|||
<ItemsControl ItemsSource="{Binding NavigationItems}"> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate> |
|||
<StackPanel> |
|||
<!-- 主导航项 --> |
|||
<Button Command="{Binding $parent[Window].DataContext.NavigateCommand}" |
|||
CommandParameter="{Binding}" |
|||
HorizontalAlignment="Stretch" |
|||
HorizontalContentAlignment="Left" |
|||
Margin="0,2" |
|||
Padding="15,12" |
|||
FontSize="14" |
|||
Background="Transparent" |
|||
Foreground="White" |
|||
BorderThickness="0" |
|||
CornerRadius="8"> |
|||
<Button.Styles> |
|||
<Style Selector="Button"> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
<Setter Property="Foreground" Value="White"/> |
|||
</Style> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource PrimaryDarkHover}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
<Style Selector="Button:selected"> |
|||
<Setter Property="Background" Value="{StaticResource PrimaryBlue}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<Button.Content> |
|||
<StackPanel Orientation="Horizontal" Spacing="10"> |
|||
<heroicons:HeroIcon Type="{Binding IconType}" |
|||
Width="16" Height="16" |
|||
Foreground="{StaticResource TextWhite}"/> |
|||
<TextBlock Text="{Binding Title}" |
|||
VerticalAlignment="Center"/> |
|||
</StackPanel> |
|||
</Button.Content> |
|||
</Button> |
|||
|
|||
<!-- 子导航项 --> |
|||
<ItemsControl ItemsSource="{Binding Children}" |
|||
IsVisible="{Binding IsExpanded}" |
|||
Margin="20,0,0,0"> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate> |
|||
<Button Command="{Binding $parent[Window].DataContext.NavigateCommand}" |
|||
CommandParameter="{Binding}" |
|||
HorizontalAlignment="Stretch" |
|||
HorizontalContentAlignment="Left" |
|||
Margin="0,1" |
|||
Padding="15,10" |
|||
FontSize="13" |
|||
Background="Transparent" |
|||
Foreground="{StaticResource SecondaryGray}" |
|||
BorderThickness="0" |
|||
CornerRadius="6"> |
|||
<Button.Styles> |
|||
<Style Selector="Button"> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
<Setter Property="Foreground" Value="{StaticResource SecondaryGray}"/> |
|||
</Style> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource PrimaryDarkHover}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
<Style Selector="Button:selected"> |
|||
<Setter Property="Background" Value="{StaticResource PrimaryBlue}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<Button.Content> |
|||
<StackPanel Orientation="Horizontal" Spacing="8"> |
|||
<heroicons:HeroIcon Type="{Binding IconType}" |
|||
Width="14" Height="14" |
|||
Foreground="{Binding $parent[Button].Foreground}"/> |
|||
<TextBlock Text="{Binding Title}" |
|||
VerticalAlignment="Center"/> |
|||
</StackPanel> |
|||
</Button.Content> |
|||
</Button> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</StackPanel> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</ScrollViewer> |
|||
|
|||
<!-- 底部信息 --> |
|||
<StackPanel Grid.Row="2" Margin="20,0,20,20"> |
|||
<Border Background="{StaticResource PrimaryDarkHover}" CornerRadius="8" Padding="15"> |
|||
<StackPanel> |
|||
<TextBlock Text="{StaticResource VersionInfo}" |
|||
FontSize="12" |
|||
Foreground="{StaticResource SecondaryGray}" |
|||
HorizontalAlignment="Center"/> |
|||
<TextBlock Text="{StaticResource VersionNumber}" |
|||
FontSize="14" |
|||
FontWeight="Bold" |
|||
Foreground="White" |
|||
HorizontalAlignment="Center" |
|||
Margin="0,5,0,0"/> |
|||
</StackPanel> |
|||
</Border> |
|||
</StackPanel> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- 右侧主内容区域 --> |
|||
<Grid Grid.Column="1"> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="*"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<!-- 头部区域 --> |
|||
<Border Grid.Row="0" |
|||
Background="{StaticResource BackgroundWhite}" |
|||
BorderBrush="{StaticResource BorderLight}" |
|||
BorderThickness="0,0,0,1" |
|||
Padding="0,0,0,0"> |
|||
<Grid Height="50" Name="TitleBarGrid"> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*"/> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<!-- 左侧标题区域 --> |
|||
<StackPanel Grid.Column="0" |
|||
VerticalAlignment="Center" |
|||
Margin="20,0,0,0"> |
|||
<TextBlock Text="{Binding HeaderTitle}" |
|||
FontSize="18" |
|||
FontWeight="SemiBold" |
|||
Foreground="{StaticResource TextPrimary}"/> |
|||
<TextBlock Text="{Binding HeaderSubtitle}" |
|||
FontSize="12" |
|||
Foreground="{StaticResource SecondaryGrayDark}" |
|||
Margin="0,2,0,0"/> |
|||
</StackPanel> |
|||
|
|||
<!-- 右侧按钮区域 --> |
|||
<StackPanel Grid.Column="1" |
|||
Orientation="Horizontal" |
|||
VerticalAlignment="Center" |
|||
Margin="0,0,0,0"> |
|||
|
|||
|
|||
<!-- 窗口控制按钮组 --> |
|||
<StackPanel Orientation="Horizontal" Spacing="0"> |
|||
<!-- 最小化按钮 --> |
|||
<Button Name="MinimizeButton" |
|||
Width="46" Height="30" |
|||
Background="Transparent" |
|||
BorderThickness="0" |
|||
tooltip:ToolTip.Tip="{StaticResource BtnMinimize}"> |
|||
<Button.Styles> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource BackgroundLight}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<heroicons:HeroIcon Type="Minus" |
|||
Width="16" Height="16" |
|||
Foreground="{StaticResource SecondaryGrayStroke}"/> |
|||
</Button> |
|||
|
|||
<!-- 最大化/还原按钮 --> |
|||
<Button Name="MaximizeButton" |
|||
Width="46" Height="30" |
|||
Background="Transparent" |
|||
BorderThickness="0" |
|||
tooltip:ToolTip.Tip="{StaticResource BtnMaximize}"> |
|||
<Button.Styles> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource BackgroundLight}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<heroicons:HeroIcon Type="ArrowsPointingOut" |
|||
Width="16" Height="16" |
|||
Foreground="{StaticResource SecondaryGrayStroke}"/> |
|||
</Button> |
|||
|
|||
<!-- 关闭按钮 --> |
|||
<Button Name="CloseButton" |
|||
Width="46" Height="30" |
|||
Background="Transparent" |
|||
BorderThickness="0" |
|||
tooltip:ToolTip.Tip="{StaticResource BtnClose}"> |
|||
<Button.Styles> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource ButtonClose}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<heroicons:HeroIcon Type="XMark" |
|||
Width="16" Height="16" |
|||
Foreground="{StaticResource SecondaryGrayStroke}"/> |
|||
</Button> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- 标签页区域 --> |
|||
<Border Grid.Row="1" |
|||
Background="{StaticResource BackgroundLight}" |
|||
BorderBrush="{StaticResource BorderLight}" |
|||
BorderThickness="0,0,0,1" |
|||
Padding="0,0,0,0"> |
|||
<ScrollViewer HorizontalScrollBarVisibility="Auto" |
|||
VerticalScrollBarVisibility="Disabled"> |
|||
<ItemsControl ItemsSource="{Binding Tabs}" |
|||
Margin="8,4,8,0"> |
|||
<ItemsControl.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<StackPanel Orientation="Horizontal" Spacing="0"/> |
|||
</ItemsPanelTemplate> |
|||
</ItemsControl.ItemsPanel> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate> |
|||
<Button Background="{Binding IsSelected, Converter={x:Static converters:TabStyleConverter.Instance}, ConverterParameter=Background}" |
|||
BorderBrush="{Binding IsSelected, Converter={x:Static converters:TabStyleConverter.Instance}, ConverterParameter=BorderBrush}" |
|||
BorderThickness="1,1,1,0" |
|||
CornerRadius="4,4,0,0" |
|||
Margin="0,0,1,0" |
|||
Padding="12,8,8,8" |
|||
MinWidth="120" |
|||
Cursor="Hand" |
|||
Command="{Binding $parent[Window].DataContext.SelectTabCommand}" |
|||
CommandParameter="{Binding}"> |
|||
<Button.Styles> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource BackgroundLight}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*"/> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
<StackPanel Grid.Column="0" |
|||
Orientation="Horizontal" |
|||
Spacing="6" |
|||
VerticalAlignment="Center"> |
|||
<heroicons:HeroIcon Type="{Binding IconType}" |
|||
Width="14" Height="14" |
|||
VerticalAlignment="Center"/> |
|||
<TextBlock Text="{Binding Title}" |
|||
FontSize="13" |
|||
FontWeight="Normal" |
|||
Foreground="{Binding IsSelected, Converter={x:Static converters:TabStyleConverter.Instance}, ConverterParameter=Foreground}" |
|||
VerticalAlignment="Center"/> |
|||
</StackPanel> |
|||
<Button Grid.Column="1" |
|||
Command="{Binding $parent[Window].DataContext.CloseTabCommand}" |
|||
CommandParameter="{Binding $parent[Button].DataContext}" |
|||
Width="18" Height="18" |
|||
Background="Transparent" |
|||
Foreground="{StaticResource SecondaryGrayLight}" |
|||
BorderThickness="0" |
|||
FontSize="12" |
|||
IsVisible="{Binding CanClose}" |
|||
Margin="6,0,0,0" |
|||
CornerRadius="9" |
|||
tooltip:ToolTip.Tip="{StaticResource BtnCloseTab}"> |
|||
<heroicons:HeroIcon Type="XMark" |
|||
Width="6" Height="6" |
|||
Foreground="{Binding $parent[Button].Foreground}" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"/> |
|||
<Button.Styles> |
|||
<Style Selector="Button:pointerover"> |
|||
<Setter Property="Background" Value="{StaticResource ButtonCloseHover}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
<Style Selector="Button:pressed"> |
|||
<Setter Property="Background" Value="{StaticResource ButtonCloseActive}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextWhite}"/> |
|||
</Style> |
|||
</Button.Styles> |
|||
</Button> |
|||
</Grid> |
|||
</Button> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</ScrollViewer> |
|||
</Border> |
|||
|
|||
<!-- 内容区域 --> |
|||
<Border Grid.Row="2" |
|||
Background="{StaticResource BackgroundWhite}" |
|||
CornerRadius="8" |
|||
Margin="10" |
|||
Padding="5" |
|||
BorderBrush="{StaticResource BorderLight}" |
|||
BorderThickness="1"> |
|||
<Border.Effect> |
|||
<DropShadowEffect Color="{StaticResource ShadowBlack}" |
|||
Opacity="0.08" |
|||
BlurRadius="12" |
|||
OffsetX="0" |
|||
OffsetY="2"/> |
|||
</Border.Effect> |
|||
<reactive:RoutedViewHost Router="{Binding Router}"/> |
|||
</Border> |
|||
</Grid> |
|||
</Grid> |
|||
</reactive:ReactiveWindow> |
|||
@ -1,114 +0,0 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Input; |
|||
using Avalonia.Markup.Xaml; |
|||
using Avalonia.ReactiveUI; |
|||
using Microsoft.Extensions.Logging; |
|||
using AuroraDesk.Presentation.ViewModels; |
|||
using ReactiveUI; |
|||
using System.Reactive.Disposables; |
|||
|
|||
namespace AuroraDesk; |
|||
|
|||
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>, IActivatableView |
|||
{ |
|||
private readonly ILogger<MainWindow>? _logger; |
|||
|
|||
/// <summary>
|
|||
/// 无参构造函数,用于 XAML 设计器
|
|||
/// </summary>
|
|||
public MainWindow() |
|||
{ |
|||
InitializeComponent(); |
|||
SetupWindowControls(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 构造函数,接受依赖注入的 ViewModel
|
|||
/// </summary>
|
|||
/// <param name="viewModel">主窗口的 ViewModel</param>
|
|||
/// <param name="logger">日志记录器</param>
|
|||
public MainWindow(MainWindowViewModel viewModel, ILogger<MainWindow>? logger = null) |
|||
{ |
|||
ArgumentNullException.ThrowIfNull(viewModel); |
|||
|
|||
_logger = logger; |
|||
InitializeComponent(); |
|||
ViewModel = viewModel; |
|||
SetupWindowControls(); |
|||
|
|||
_logger?.LogInformation("MainWindow 已创建,ViewModel 已设置"); |
|||
|
|||
// 使用 WhenActivated 管理订阅
|
|||
this.WhenActivated(disposables => |
|||
{ |
|||
// 可以在这里添加窗口级别的订阅,如果需要的话
|
|||
// 例如:this.WhenAnyValue(x => x.ViewModel.Title)
|
|||
// .Subscribe(title => ...)
|
|||
// .DisposeWith(disposables);
|
|||
}); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置窗口控制按钮事件
|
|||
/// </summary>
|
|||
private void SetupWindowControls() |
|||
{ |
|||
// 设置标题栏拖动功能
|
|||
var titleBarGrid = this.FindControl<Grid>("TitleBarGrid"); |
|||
if (titleBarGrid != null) |
|||
{ |
|||
titleBarGrid.PointerPressed += OnTitleBarPointerPressed; |
|||
} |
|||
|
|||
// 最小化按钮
|
|||
var minimizeButton = this.FindControl<Button>("MinimizeButton"); |
|||
if (minimizeButton != null) |
|||
{ |
|||
minimizeButton.Click += (sender, e) => WindowState = WindowState.Minimized; |
|||
} |
|||
|
|||
// 最大化/还原按钮
|
|||
var maximizeButton = this.FindControl<Button>("MaximizeButton"); |
|||
if (maximizeButton != null) |
|||
{ |
|||
maximizeButton.Click += (sender, e) => |
|||
{ |
|||
if (WindowState == WindowState.Maximized) |
|||
{ |
|||
WindowState = WindowState.Normal; |
|||
ToolTip.SetTip(maximizeButton, "最大化"); |
|||
} |
|||
else |
|||
{ |
|||
WindowState = WindowState.Maximized; |
|||
ToolTip.SetTip(maximizeButton, "还原"); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
// 关闭按钮
|
|||
var closeButton = this.FindControl<Button>("CloseButton"); |
|||
if (closeButton != null) |
|||
{ |
|||
closeButton.Click += (sender, e) => Close(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理标题栏鼠标按下事件,实现窗口拖动
|
|||
/// </summary>
|
|||
private void OnTitleBarPointerPressed(object? sender, PointerPressedEventArgs e) |
|||
{ |
|||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) |
|||
{ |
|||
BeginMoveDrag(e); |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
02d000a9cd9f4212cd5f985e8dde572b7faf973dcff59560607da4f46a53442e |
|||
5ca4ed031f11e2a7ccc654d616879421a1337553d516bd89fe174081ee58b17a |
|||
|
|||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Loading…
Reference in new issue