You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
21 KiB
352 lines
21 KiB
|
1 month ago
|
<reactive:ReactiveUserControl 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.Pages"
|
||
|
|
xmlns:converters="using:AuroraDesk.Presentation.Converters"
|
||
|
|
xmlns:reactive="using:ReactiveUI.Avalonia"
|
||
|
|
xmlns:heroicons="clr-namespace:HeroIconsAvalonia.Controls;assembly=HeroIconsAvalonia"
|
||
|
|
mc:Ignorable="d"
|
||
|
|
x:Class="AuroraDesk.Presentation.Views.Pages.PlinkPageView"
|
||
|
|
x:DataType="vm:PlinkPageViewModel"
|
||
|
|
d:DesignWidth="1200"
|
||
|
|
d:DesignHeight="800">
|
||
|
|
|
||
|
|
<reactive:ReactiveUserControl.Resources>
|
||
|
|
<converters:NullToBoolConverter x:Key="NullToBoolConverter"/>
|
||
|
|
<converters:NullToInverseBoolConverter x:Key="NullToInverseBoolConverter"/>
|
||
|
|
<converters:PlinkMessageBackgroundConverter x:Key="PlinkMessageBackgroundConverter"/>
|
||
|
|
</reactive:ReactiveUserControl.Resources>
|
||
|
|
|
||
|
|
<Grid Margin="16" RowDefinitions="Auto,16,2*">
|
||
|
|
<!-- 顶部:新建 Plink 会话 -->
|
||
|
|
<Border Grid.Row="0"
|
||
|
|
Background="White"
|
||
|
|
BorderBrush="#E5E7EB"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="10"
|
||
|
|
Padding="12"
|
||
|
|
MaxHeight="300">
|
||
|
|
<Expander IsExpanded="True"
|
||
|
|
HorizontalAlignment="Stretch"
|
||
|
|
HorizontalContentAlignment="Stretch">
|
||
|
|
<Expander.HeaderTemplate>
|
||
|
|
<DataTemplate>
|
||
|
|
<Grid HorizontalAlignment="Stretch">
|
||
|
|
<StackPanel Orientation="Horizontal"
|
||
|
|
Spacing="6"
|
||
|
|
Margin="12,10">
|
||
|
|
<heroicons:HeroIcon Type="PlusCircle"
|
||
|
|
Width="18"
|
||
|
|
Height="18"
|
||
|
|
Foreground="#1F2937"
|
||
|
|
VerticalAlignment="Center"/>
|
||
|
|
<TextBlock Text="新建 Plink 会话"
|
||
|
|
FontSize="15"
|
||
|
|
FontWeight="SemiBold"
|
||
|
|
Foreground="#1F2937"
|
||
|
|
VerticalAlignment="Center"/>
|
||
|
|
</StackPanel>
|
||
|
|
</Grid>
|
||
|
|
</DataTemplate>
|
||
|
|
</Expander.HeaderTemplate>
|
||
|
|
|
||
|
|
<Grid Margin="0,8,0,0"
|
||
|
|
RowDefinitions="Auto,Auto,Auto,Auto"
|
||
|
|
RowSpacing="12"
|
||
|
|
ColumnDefinitions="Auto,*,24,Auto,*,24,Auto,*,24,Auto,*"
|
||
|
|
ColumnSpacing="8">
|
||
|
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="主机" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Host}" Watermark="例如: 192.168.1.10" FontSize="12" Padding="6,4" CornerRadius="6"/>
|
||
|
|
<TextBlock Grid.Row="0" Grid.Column="3" Text="端口" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<NumericUpDown Grid.Row="0" Grid.Column="4" Value="{Binding Port}" Minimum="1" Maximum="65535" FontSize="12" Padding="6,4" CornerRadius="6" Width="110"/>
|
||
|
|
<TextBlock Grid.Row="0" Grid.Column="6" Text="用户名" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="0" Grid.Column="7" Text="{Binding UserName}" Watermark="root" FontSize="12" Padding="6,4" CornerRadius="6"/>
|
||
|
|
<TextBlock Grid.Row="0" Grid.Column="9" Text="显示名称" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="0" Grid.Column="10" Text="{Binding DisplayName}" Watermark="可选,默认为 user@host" FontSize="12" Padding="6,4" CornerRadius="6"/>
|
||
|
|
|
||
|
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="认证方式" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<StackPanel Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Orientation="Horizontal" Spacing="16">
|
||
|
|
<RadioButton Content="密码登录"
|
||
|
|
GroupName="PlinkAuthModes"
|
||
|
|
IsChecked="{Binding IsPasswordMode, Mode=OneWay}"
|
||
|
|
Command="{Binding SelectPasswordAuthCommand}"/>
|
||
|
|
<RadioButton Content="私钥登录"
|
||
|
|
GroupName="PlinkAuthModes"
|
||
|
|
IsChecked="{Binding IsPrivateKeyMode, Mode=OneWay}"
|
||
|
|
Command="{Binding SelectPrivateKeyAuthCommand}"/>
|
||
|
|
</StackPanel>
|
||
|
|
<TextBlock Grid.Row="1" Grid.Column="6" Text="密码" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="1" Grid.Column="7" Text="{Binding Password}" Watermark="用于密码认证,可留空" FontSize="12" Padding="6,4" CornerRadius="6" PasswordChar="●" IsEnabled="{Binding IsPasswordMode}"/>
|
||
|
|
<TextBlock Grid.Row="1" Grid.Column="9" Text="附加参数" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="1" Grid.Column="10" Text="{Binding AdditionalArguments}" Watermark="-N -T 等" FontSize="12" Padding="6,4" CornerRadius="6"/>
|
||
|
|
|
||
|
|
<TextBlock Grid.Row="2" Grid.Column="0" Text="私钥路径" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="5" Text="{Binding PrivateKeyPath}" Watermark="例如: C:\keys\id_rsa.ppk" FontSize="12" Padding="6,4" CornerRadius="6" IsEnabled="{Binding IsPrivateKeyMode}"/>
|
||
|
|
<TextBlock Grid.Row="2" Grid.Column="6" Text="Plink 路径" FontSize="12" Foreground="#6B7280" VerticalAlignment="Center"/>
|
||
|
|
<TextBox Grid.Row="2" Grid.Column="7" Grid.ColumnSpan="4" Text="{Binding PlinkExecutablePath}" Watermark="默认使用 PATH 中的 plink" FontSize="12" Padding="6,4" CornerRadius="6"/>
|
||
|
|
|
||
|
|
<CheckBox Grid.Row="3"
|
||
|
|
Grid.Column="0"
|
||
|
|
Grid.ColumnSpan="6"
|
||
|
|
Content="允许自动接受未知主机密钥(批量模式)"
|
||
|
|
IsChecked="{Binding AllowAnyHostKey}"
|
||
|
|
FontSize="12"
|
||
|
|
Foreground="#1F2937"
|
||
|
|
VerticalAlignment="Center"/>
|
||
|
|
<Button Grid.Row="3"
|
||
|
|
Grid.Column="7"
|
||
|
|
Command="{Binding AddSessionCommand}"
|
||
|
|
Background="#2563EB"
|
||
|
|
Foreground="White"
|
||
|
|
BorderThickness="0"
|
||
|
|
CornerRadius="8"
|
||
|
|
Padding="10,6"
|
||
|
|
FontSize="13"
|
||
|
|
FontWeight="SemiBold"
|
||
|
|
HorizontalAlignment="Left">
|
||
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="6">
|
||
|
|
<heroicons:HeroIcon Type="PlusCircle" Width="16" Height="16" Foreground="White"/>
|
||
|
|
<TextBlock Text="创建并连接会话" FontSize="13" FontWeight="SemiBold"/>
|
||
|
|
</StackPanel>
|
||
|
|
<Button.Styles>
|
||
|
|
<Style Selector="Button:pointerover">
|
||
|
|
<Setter Property="Background" Value="#1D4ED8"/>
|
||
|
|
</Style>
|
||
|
|
<Style Selector="Button:disabled">
|
||
|
|
<Setter Property="Background" Value="#D1D5DB"/>
|
||
|
|
<Setter Property="Foreground" Value="#6B7280"/>
|
||
|
|
</Style>
|
||
|
|
</Button.Styles>
|
||
|
|
</Button>
|
||
|
|
<Border Grid.Row="3"
|
||
|
|
Grid.Column="9"
|
||
|
|
Grid.ColumnSpan="2"
|
||
|
|
Background="#F9FAFB"
|
||
|
|
BorderBrush="#E5E7EB"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="8"
|
||
|
|
Padding="6">
|
||
|
|
<TextBlock Text="{Binding StatusMessage}" FontSize="12" Foreground="#4B5563" TextWrapping="Wrap"/>
|
||
|
|
</Border>
|
||
|
|
</Grid>
|
||
|
|
</Expander>
|
||
|
|
</Border>
|
||
|
|
|
||
|
|
<!-- 底部:会话列表与详情 -->
|
||
|
|
<Grid Grid.Row="2" ColumnDefinitions="320,16,*">
|
||
|
|
<!-- 左侧:当前会话列表 -->
|
||
|
|
<Border Grid.Column="0"
|
||
|
|
Background="White"
|
||
|
|
BorderBrush="#E5E7EB"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="10"
|
||
|
|
Padding="0">
|
||
|
|
<Grid>
|
||
|
|
<Grid.RowDefinitions>
|
||
|
|
<RowDefinition Height="Auto"/>
|
||
|
|
<RowDefinition Height="*"/>
|
||
|
|
<RowDefinition Height="Auto"/>
|
||
|
|
</Grid.RowDefinitions>
|
||
|
|
|
||
|
|
<Border Grid.Row="0"
|
||
|
|
Background="#F9FAFB"
|
||
|
|
BorderBrush="#E5E7EB"
|
||
|
|
BorderThickness="0,0,0,1"
|
||
|
|
Padding="14,12"
|
||
|
|
CornerRadius="10,10,0,0">
|
||
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||
|
|
<heroicons:HeroIcon Type="ComputerDesktop" Width="16" Height="16" Foreground="#1F2937"/>
|
||
|
|
<TextBlock Text="当前会话" FontSize="14" FontWeight="SemiBold" Foreground="#1F2937"/>
|
||
|
|
<Border Background="#E0E7FF" CornerRadius="8" Padding="4,2">
|
||
|
|
<TextBlock Text="{Binding Sessions.Count}" FontSize="10" FontWeight="Bold" Foreground="#3730A3"/>
|
||
|
|
</Border>
|
||
|
|
</StackPanel>
|
||
|
|
</Border>
|
||
|
|
|
||
|
|
<ListBox Grid.Row="1"
|
||
|
|
ItemsSource="{Binding Sessions}"
|
||
|
|
SelectedItem="{Binding SelectedSession, Mode=TwoWay}"
|
||
|
|
BorderThickness="0"
|
||
|
|
Background="Transparent"
|
||
|
|
Padding="10,6">
|
||
|
|
<ListBox.ItemTemplate>
|
||
|
|
<DataTemplate x:DataType="vm:PlinkSessionItemViewModel">
|
||
|
|
<Border Background="#F8FAFC"
|
||
|
|
BorderBrush="#E2E8F0"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="8"
|
||
|
|
Padding="10"
|
||
|
|
Margin="0,0,0,8">
|
||
|
|
<StackPanel Spacing="6">
|
||
|
|
<TextBlock Text="{Binding DisplayName}" FontSize="13" FontWeight="SemiBold" Foreground="#0F172A"/>
|
||
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||
|
|
<Border Background="#E2E8F0"
|
||
|
|
CornerRadius="6"
|
||
|
|
Padding="6,3">
|
||
|
|
<TextBlock Text="{Binding SessionId}" FontSize="10" Foreground="#475569" TextTrimming="CharacterEllipsis"/>
|
||
|
|
</Border>
|
||
|
|
<Border Background="#DCFCE7"
|
||
|
|
CornerRadius="6"
|
||
|
|
Padding="6,3"
|
||
|
|
IsVisible="{Binding IsConnected}">
|
||
|
|
<TextBlock Text="已连接" FontSize="11" FontWeight="SemiBold" Foreground="#047857"/>
|
||
|
|
</Border>
|
||
|
|
</StackPanel>
|
||
|
|
<TextBlock Text="{Binding Status}" FontSize="11" Foreground="#475569"/>
|
||
|
|
</StackPanel>
|
||
|
|
</Border>
|
||
|
|
</DataTemplate>
|
||
|
|
</ListBox.ItemTemplate>
|
||
|
|
</ListBox>
|
||
|
|
|
||
|
|
<Border Grid.Row="2"
|
||
|
|
Padding="12">
|
||
|
|
<StackPanel Orientation="Horizontal"
|
||
|
|
HorizontalAlignment="Stretch"
|
||
|
|
Spacing="8">
|
||
|
|
<Button Content="刷新"
|
||
|
|
Command="{Binding RefreshSnapshotCommand}"
|
||
|
|
Background="#E0E7FF"
|
||
|
|
Foreground="#1E3A8A"
|
||
|
|
BorderThickness="0"
|
||
|
|
CornerRadius="6"
|
||
|
|
Padding="14,8"
|
||
|
|
FontSize="12"/>
|
||
|
|
<Button Content="移除"
|
||
|
|
Command="{Binding RemoveSessionCommand}"
|
||
|
|
CommandParameter="{Binding SelectedSession}"
|
||
|
|
Background="#F87171"
|
||
|
|
Foreground="White"
|
||
|
|
BorderThickness="0"
|
||
|
|
CornerRadius="6"
|
||
|
|
Padding="14,8"
|
||
|
|
FontSize="12"
|
||
|
|
IsEnabled="{Binding SelectedSession, Converter={StaticResource NullToBoolConverter}}"/>
|
||
|
|
</StackPanel>
|
||
|
|
</Border>
|
||
|
|
</Grid>
|
||
|
|
</Border>
|
||
|
|
|
||
|
|
<!-- 右侧:会话详情 -->
|
||
|
|
<Border Grid.Column="2"
|
||
|
|
Background="White"
|
||
|
|
BorderBrush="#E5E7EB"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="12"
|
||
|
|
Padding="18">
|
||
|
|
<Grid>
|
||
|
|
<Grid.RowDefinitions>
|
||
|
|
<RowDefinition Height="Auto"/>
|
||
|
|
<RowDefinition Height="*"/>
|
||
|
|
<RowDefinition Height="Auto"/>
|
||
|
|
</Grid.RowDefinitions>
|
||
|
|
|
||
|
|
<Border Grid.Row="0"
|
||
|
|
Background="#EEF2FF"
|
||
|
|
CornerRadius="10"
|
||
|
|
Padding="14"
|
||
|
|
Margin="0,0,0,12">
|
||
|
|
<Grid ColumnDefinitions="*,Auto,Auto" ColumnSpacing="12">
|
||
|
|
<StackPanel Orientation="Vertical" Spacing="4">
|
||
|
|
<TextBlock Text="{Binding SelectedSession.DisplayName}" FontSize="16" FontWeight="SemiBold" Foreground="#312E81"/>
|
||
|
|
<TextBlock Text="{Binding SelectedSession.SessionId}" FontSize="11" Foreground="#4338CA" TextTrimming="CharacterEllipsis"/>
|
||
|
|
</StackPanel>
|
||
|
|
<Border Grid.Column="1"
|
||
|
|
Background="#C7D2FE"
|
||
|
|
CornerRadius="8"
|
||
|
|
Padding="8,4">
|
||
|
|
<TextBlock Text="{Binding SelectedSession.Status}" FontSize="12" FontWeight="SemiBold" Foreground="#1E1B4B"/>
|
||
|
|
</Border>
|
||
|
|
<Button Grid.Column="2"
|
||
|
|
Content="断开"
|
||
|
|
Command="{Binding SelectedSession.DisconnectCommand}"
|
||
|
|
Background="#F87171"
|
||
|
|
Foreground="White"
|
||
|
|
BorderThickness="0"
|
||
|
|
CornerRadius="8"
|
||
|
|
Padding="16,8"
|
||
|
|
FontSize="12"
|
||
|
|
IsEnabled="{Binding SelectedSession.IsConnected}"/>
|
||
|
|
</Grid>
|
||
|
|
</Border>
|
||
|
|
|
||
|
|
<Border Grid.Row="1"
|
||
|
|
Background="#F8FAFC"
|
||
|
|
BorderBrush="#E2E8F0"
|
||
|
|
BorderThickness="1"
|
||
|
|
CornerRadius="10"
|
||
|
|
Padding="12"
|
||
|
|
IsVisible="{Binding SelectedSession, Converter={StaticResource NullToBoolConverter}}">
|
||
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||
|
|
<ItemsControl ItemsSource="{Binding SelectedSession.Messages}">
|
||
|
|
<ItemsControl.ItemTemplate>
|
||
|
|
<DataTemplate x:DataType="vm:PlinkMessageEntry">
|
||
|
|
<Border CornerRadius="8"
|
||
|
|
Padding="10"
|
||
|
|
Margin="0,0,0,8"
|
||
|
|
Background="{Binding ., Converter={StaticResource PlinkMessageBackgroundConverter}}">
|
||
|
|
<StackPanel Spacing="4">
|
||
|
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||
|
|
<TextBlock Text="{Binding Timestamp}" FontSize="11" Foreground="#6B7280"/>
|
||
|
|
<TextBlock Text="{Binding Direction}" FontSize="11" Foreground="#6B7280"/>
|
||
|
|
<Border Background="#FEE2E2"
|
||
|
|
CornerRadius="6"
|
||
|
|
Padding="6,2"
|
||
|
|
IsVisible="{Binding IsError}">
|
||
|
|
<TextBlock Text="错误" FontSize="11" FontWeight="SemiBold" Foreground="#B91C1C"/>
|
||
|
|
</Border>
|
||
|
|
</StackPanel>
|
||
|
|
<TextBlock Text="{Binding Content}" TextWrapping="Wrap" FontSize="13" Foreground="#0F172A"/>
|
||
|
|
</StackPanel>
|
||
|
|
</Border>
|
||
|
|
</DataTemplate>
|
||
|
|
</ItemsControl.ItemTemplate>
|
||
|
|
</ItemsControl>
|
||
|
|
</ScrollViewer>
|
||
|
|
</Border>
|
||
|
|
|
||
|
|
<Grid Grid.Row="2"
|
||
|
|
ColumnDefinitions="*,Auto"
|
||
|
|
ColumnSpacing="10"
|
||
|
|
Margin="0,12,0,0">
|
||
|
|
<TextBox Grid.Column="0"
|
||
|
|
Text="{Binding SelectedSession.OutgoingText}"
|
||
|
|
Watermark="输入要发送的命令或文本"
|
||
|
|
AcceptsReturn="True"
|
||
|
|
TextWrapping="Wrap"
|
||
|
|
MinHeight="60"
|
||
|
|
FontSize="13"
|
||
|
|
Padding="12,10"
|
||
|
|
CornerRadius="8"/>
|
||
|
|
<Button Grid.Column="1"
|
||
|
|
Command="{Binding SelectedSession.SendCommand}"
|
||
|
|
Background="#10B981"
|
||
|
|
Foreground="White"
|
||
|
|
BorderThickness="0"
|
||
|
|
CornerRadius="10"
|
||
|
|
Padding="22,14"
|
||
|
|
FontSize="13"
|
||
|
|
FontWeight="SemiBold"
|
||
|
|
IsEnabled="{Binding SelectedSession.IsConnected}">
|
||
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="6">
|
||
|
|
<heroicons:HeroIcon Type="PaperAirplane" Width="16" Height="16" Foreground="White"/>
|
||
|
|
<TextBlock Text="发送" FontSize="13" FontWeight="SemiBold"/>
|
||
|
|
</StackPanel>
|
||
|
|
</Button>
|
||
|
|
</Grid>
|
||
|
|
|
||
|
|
<TextBlock Grid.Row="1"
|
||
|
|
Text="请选择左侧会话以查看实时内容。"
|
||
|
|
FontSize="14"
|
||
|
|
Foreground="#6B7280"
|
||
|
|
HorizontalAlignment="Center"
|
||
|
|
VerticalAlignment="Center"
|
||
|
|
IsVisible="{Binding SelectedSession, Converter={StaticResource NullToInverseBoolConverter}}"/>
|
||
|
|
</Grid>
|
||
|
|
</Border>
|
||
|
|
</Grid>
|
||
|
|
</Grid>
|
||
|
|
</reactive:ReactiveUserControl>
|
||
|
|
|