具备界面基础功能
This commit is contained in:
321
SHH.CameraDashboard/Pages/CameraEdit.xaml
Normal file
321
SHH.CameraDashboard/Pages/CameraEdit.xaml
Normal file
@@ -0,0 +1,321 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraEdit"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DataContext="{d:DesignInstance Type=local:CameraEditViewModel}"
|
||||
d:DesignHeight="700"
|
||||
d:DesignWidth="500"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Margin="15" Background="{DynamicResource Brush.Bg.Window}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Margin="0,0,0,15"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="设备参数配置" />
|
||||
|
||||
<ScrollViewer
|
||||
Grid.Row="1"
|
||||
Padding="0,0,5,0"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
|
||||
<StackPanel.Resources>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Height" Value="26" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Bg.Input}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border}" />
|
||||
</Style>
|
||||
</StackPanel.Resources>
|
||||
|
||||
<GroupBox
|
||||
Margin="0,0,0,15"
|
||||
Padding="10"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Header="基础身份 (Identity)">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<WrapPanel Grid.ColumnSpan="2">
|
||||
<TextBlock Margin="0,5" Text="设备 ID *" />
|
||||
<TextBox
|
||||
Width="80"
|
||||
Margin="30,5"
|
||||
Text="{Binding EditingDto.Id}" />
|
||||
|
||||
<TextBlock Margin="0,5" Text="品牌类型" />
|
||||
<ComboBox
|
||||
Width="180"
|
||||
Margin="5,5,0,5"
|
||||
DisplayMemberPath="Label"
|
||||
ItemsSource="{Binding BrandOptions}"
|
||||
SelectedValue="{Binding EditingDto.Brand}"
|
||||
SelectedValuePath="Value" />
|
||||
</WrapPanel>
|
||||
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="0,5"
|
||||
Text="设备名称" />
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditingDto.Name}" />
|
||||
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Margin="0,5"
|
||||
Text="安装位置" />
|
||||
<TextBox
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditingDto.Location}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox
|
||||
Margin="0,0,0,15"
|
||||
Padding="10"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Header="核心连接 (Connectivity)">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="60" />
|
||||
<ColumnDefinition Width="60" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Margin="0,5" Text="IP 地址 *" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
Margin="0,5,10,5"
|
||||
Text="{Binding EditingDto.IpAddress}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Margin="0,5"
|
||||
HorizontalAlignment="Right"
|
||||
Text="端口 " />
|
||||
<TextBox
|
||||
Grid.Column="3"
|
||||
Margin="5,5,0,5"
|
||||
Text="{Binding EditingDto.Port}" />
|
||||
|
||||
<WrapPanel Grid.Row="1" Grid.ColumnSpan="4">
|
||||
<TextBlock
|
||||
Width="80"
|
||||
Margin="0,5,0,5"
|
||||
Text="用户名" />
|
||||
<TextBox
|
||||
Width="120"
|
||||
Margin="0,5,0,5"
|
||||
Text="{Binding EditingDto.Username}" />
|
||||
|
||||
<TextBlock
|
||||
Width="40"
|
||||
Margin="33,5,10,5"
|
||||
Text="密码" />
|
||||
<TextBox
|
||||
Width="140"
|
||||
Margin="0,5,0,5"
|
||||
Text="{Binding EditingDto.Password}" />
|
||||
</WrapPanel>
|
||||
|
||||
<WrapPanel Grid.Row="2" Grid.ColumnSpan="4">
|
||||
<TextBlock
|
||||
Width="80"
|
||||
Margin="0,5,0,5"
|
||||
Text="句柄" />
|
||||
<TextBox
|
||||
Width="70"
|
||||
Margin="0,5,0,5"
|
||||
Text="{Binding EditingDto.RenderHandle}" />
|
||||
|
||||
<TextBlock
|
||||
Width="40"
|
||||
Margin="23,5,0,5"
|
||||
Text="通道号" />
|
||||
<TextBox
|
||||
Width="40"
|
||||
Margin="10,5,0,5"
|
||||
Text="{Binding EditingDto.ChannelIndex}" />
|
||||
|
||||
<TextBlock
|
||||
Width="50"
|
||||
Margin="20,0,10,0"
|
||||
Text="码流类型" />
|
||||
<ComboBox
|
||||
Width="80"
|
||||
Margin="0,5,0,5"
|
||||
SelectedIndex="{Binding EditingDto.StreamType}">
|
||||
<ComboBoxItem Content="主码流" />
|
||||
<ComboBoxItem Content="子码流" />
|
||||
</ComboBox>
|
||||
</WrapPanel>
|
||||
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox
|
||||
Margin="0,0,0,15"
|
||||
Padding="10"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Header="关联主板 (Metadata)">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="60" />
|
||||
<ColumnDefinition Width="60" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Margin="0,5" Text="主板 IP" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
Margin="0,5,10,5"
|
||||
Text="{Binding EditingDto.MainboardIp}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Margin="0,5"
|
||||
HorizontalAlignment="Right"
|
||||
Text="端口 " />
|
||||
<TextBox
|
||||
Grid.Column="3"
|
||||
Margin="5,5,0,5"
|
||||
Text="{Binding EditingDto.MainboardPort}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox
|
||||
Margin="0,0,0,15"
|
||||
Padding="10"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Header="运行参数 (Runtime)">
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Width="30"
|
||||
Margin="0,5,0,5"
|
||||
Text="RTSP" />
|
||||
<TextBox
|
||||
Width="360"
|
||||
Height="60"
|
||||
Margin="20,5,0,5"
|
||||
VerticalContentAlignment="Top"
|
||||
Text="{Binding EditingDto.RtspPath}" />
|
||||
</WrapPanel>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="0,10,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="100"
|
||||
Height="32"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding SaveCommand}"
|
||||
Content="保存配置"
|
||||
Cursor="Hand">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.State.Success}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="4">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Opacity" Value="0.9" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="100"
|
||||
Height="32"
|
||||
Command="{Binding CancelCommand}"
|
||||
Content="取消"
|
||||
Cursor="Hand">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="4">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Bg.Hover}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
15
SHH.CameraDashboard/Pages/CameraEdit.xaml.cs
Normal file
15
SHH.CameraDashboard/Pages/CameraEdit.xaml.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// CameraEdit.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraEdit : UserControl
|
||||
{
|
||||
public CameraEdit()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
317
SHH.CameraDashboard/Pages/CameraImageSubscription.xaml
Normal file
317
SHH.CameraDashboard/Pages/CameraImageSubscription.xaml
Normal file
@@ -0,0 +1,317 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraImageSubscription"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="900"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
<local:SubscriptionTypeConverter x:Key="TypeConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,15"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
Text="📡" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="订阅管理" />
|
||||
<TextBlock
|
||||
Margin="5,2,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text=" (实时分发控制)" />
|
||||
</StackPanel>
|
||||
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource Radius.Normal}">
|
||||
<DataGrid
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding Subscriptions}"
|
||||
SelectedItem="{Binding SelectedSubscription}"
|
||||
SelectionMode="Single">
|
||||
<DataGrid.Columns>
|
||||
|
||||
<DataGridTextColumn
|
||||
Width="80"
|
||||
Binding="{Binding AppId}"
|
||||
Header="App ID">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTextColumn
|
||||
Width="125"
|
||||
Binding="{Binding Type, Converter={StaticResource TypeConverter}}"
|
||||
Header="类型">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Margin" Value="5,0" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="70" Header="目标帧率">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Border
|
||||
Padding="5,1"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{DynamicResource Brush.Bg.L3}"
|
||||
CornerRadius="3"
|
||||
ToolTip="配置的期望帧率">
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Inverse}"
|
||||
Text="{Binding DisplayFps, StringFormat={}{0} FPS}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="70" Header="实际帧率">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Border
|
||||
Padding="5,1"
|
||||
HorizontalAlignment="Center"
|
||||
CornerRadius="3">
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.State.Success}"
|
||||
Text="{Binding RealFps, StringFormat={}{0:F1} FPS}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn
|
||||
Width="2*"
|
||||
Binding="{Binding Memo}"
|
||||
Header="备注">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
|
||||
<Setter Property="ToolTip" Value="{Binding Memo}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="50" Header="操作">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Button
|
||||
Height="30"
|
||||
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding AppId}"
|
||||
Content="注销"
|
||||
Style="{StaticResource Btn.Ghost.Danger}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Border>
|
||||
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Padding="20"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource Radius.Normal}">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="0,0,0,15"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,5,0"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="➕" />
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="新增 / 编辑订阅" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="App ID:" />
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditAppId}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="3"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="类型:" />
|
||||
<ComboBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="4"
|
||||
Height="{StaticResource Height.Input}"
|
||||
Margin="0,5"
|
||||
VerticalContentAlignment="Center"
|
||||
DisplayMemberPath="Value"
|
||||
ItemsSource="{Binding SubscriptionTypes}"
|
||||
SelectedValue="{Binding EditType}"
|
||||
SelectedValuePath="Key" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="目标帧率:" />
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Slider
|
||||
VerticalAlignment="Center"
|
||||
IsSnapToTickEnabled="True"
|
||||
Maximum="25"
|
||||
Minimum="1"
|
||||
Value="{Binding EditFps}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Brand}"
|
||||
Text="{Binding EditFps, StringFormat={}{0} fps}" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="3"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="备注:" />
|
||||
<TextBox
|
||||
Grid.Row="2"
|
||||
Grid.Column="4"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditMemo}" />
|
||||
|
||||
<Grid
|
||||
Grid.Row="3"
|
||||
Grid.ColumnSpan="5"
|
||||
Visibility="{Binding IsNetworkType, Converter={StaticResource BoolToVis}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="目标 IP:" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditTargetIp}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="目标端口:" />
|
||||
<TextBox
|
||||
Grid.Column="4"
|
||||
Margin="0,5"
|
||||
Text="{Binding EditTargetPort}" />
|
||||
</Grid>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="4"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="0,15,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<Button
|
||||
Width="100"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding ClearFormCommand}"
|
||||
Content="重置表单"
|
||||
Style="{StaticResource Btn.Ghost}" />
|
||||
|
||||
<Button
|
||||
Width="120"
|
||||
Command="{Binding SaveCommand}"
|
||||
Content="提交保存"
|
||||
Style="{StaticResource PrimaryBtnStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
15
SHH.CameraDashboard/Pages/CameraImageSubscription.xaml.cs
Normal file
15
SHH.CameraDashboard/Pages/CameraImageSubscription.xaml.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// CameraImageSubscription.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraImageSubscription : UserControl
|
||||
{
|
||||
public CameraImageSubscription()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
274
SHH.CameraDashboard/Pages/CameraImgProc.xaml
Normal file
274
SHH.CameraDashboard/Pages/CameraImgProc.xaml
Normal file
@@ -0,0 +1,274 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraImgProc"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DataContext="{d:DesignInstance local:CameraImgProcViewModel}"
|
||||
d:DesignHeight="650"
|
||||
d:DesignWidth="500"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<local:BoolToMaxScaleConverter x:Key="BoolToMaxScaleConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="20" Background="{DynamicResource Brush.Bg.Window}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Margin="0,0,0,20" LastChildFill="False">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Title}" />
|
||||
<Button
|
||||
Width="30"
|
||||
Height="30"
|
||||
Command="{Binding CancelCommand}"
|
||||
Content="✕"
|
||||
DockPanel.Dock="Right"
|
||||
Style="{DynamicResource Btn.Ghost}" />
|
||||
</DockPanel>
|
||||
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
Margin="0,0,0,15"
|
||||
Padding="15"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
CornerRadius="6">
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<TextBlock Foreground="{DynamicResource Brush.Text.Secondary}" Text="源画面分辨率:" />
|
||||
<TextBlock
|
||||
Margin="10,0,0,0"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding SourceResolutionText}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<GroupBox
|
||||
Grid.Row="2"
|
||||
Margin="0,0,0,15"
|
||||
Padding="15"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Header="分辨率调整">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource Brush.Text.Primary}" Text="允许缩小 (Allow Shrink)" />
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="可将画面缩小至任意尺寸" />
|
||||
</StackPanel>
|
||||
<CheckBox
|
||||
DockPanel.Dock="Right"
|
||||
IsChecked="{Binding AllowShrink}"
|
||||
Style="{DynamicResource Style.CheckBox.Switch}" />
|
||||
</DockPanel>
|
||||
|
||||
<DockPanel
|
||||
Grid.Column="1"
|
||||
Margin="20,0,0,0"
|
||||
LastChildFill="False">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource Brush.Text.Primary}" Text="允许放大 (Allow Enlarge)" />
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="最大支持 1080P" />
|
||||
</StackPanel>
|
||||
<CheckBox
|
||||
Margin="5,0,0,0"
|
||||
DockPanel.Dock="Right"
|
||||
IsChecked="{Binding AllowEnlarge}"
|
||||
IsEnabled="{Binding CanCheckExpand}"
|
||||
Style="{DynamicResource Style.CheckBox.Switch}" />
|
||||
</DockPanel>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Row="1" Margin="0,20,0,0">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.State.Warning}"
|
||||
Text="请先开启“允许缩小”或“允许放大”以调整分辨率">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSliderEnabled}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<Grid Margin="0,0,0,15" IsEnabled="{Binding IsSliderEnabled}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="50" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="缩放比" />
|
||||
|
||||
<Slider
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
IsSnapToTickEnabled="True"
|
||||
Maximum="{Binding AllowEnlarge, Converter={StaticResource BoolToMaxScaleConverter}}"
|
||||
Minimum="10"
|
||||
TickFrequency="5"
|
||||
Value="{Binding ScalePercent}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Brand}"
|
||||
Text="{Binding ScalePercent, StringFormat={}{0:F0}%}" />
|
||||
</Grid>
|
||||
|
||||
<Grid IsEnabled="{Binding IsSliderEnabled}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,5"
|
||||
FontSize="12"
|
||||
Text="宽度" />
|
||||
<TextBox
|
||||
Height="32"
|
||||
Style="{DynamicResource Style.TextBox.Search}"
|
||||
Text="{Binding TargetWidth, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextAlignment="Center" />
|
||||
</StackPanel>
|
||||
<ToggleButton
|
||||
Grid.Column="1"
|
||||
Margin="15,18,15,0"
|
||||
IsChecked="{Binding IsRatioLocked}"
|
||||
ToolTip="锁定长宽比">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 17,6V8H18M12,4A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,4Z"
|
||||
Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=ToggleButton}}"
|
||||
Stretch="Uniform" />
|
||||
</ToggleButton>
|
||||
<StackPanel Grid.Column="2">
|
||||
<TextBlock
|
||||
Margin="0,0,0,5"
|
||||
FontSize="12"
|
||||
Text="高度" />
|
||||
<TextBox
|
||||
Height="32"
|
||||
Style="{DynamicResource Style.TextBox.Search}"
|
||||
Text="{Binding TargetHeight, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="2" Margin="0,0,0,20">
|
||||
<TextBlock
|
||||
Margin="0,20,0,10"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="常用尺寸预设" />
|
||||
<WrapPanel>
|
||||
<WrapPanel.Resources>
|
||||
<Style BasedOn="{StaticResource Btn.Ghost.Secondary}" TargetType="Button">
|
||||
<Setter Property="Margin" Value="0,0,8,8" />
|
||||
<Setter Property="Width" Value="Auto" />
|
||||
<Setter Property="Padding" Value="6,0" />
|
||||
<Setter Property="Height" Value="16" />
|
||||
<Setter Property="Command" Value="{Binding ApplyPresetCommand}" />
|
||||
</Style>
|
||||
</WrapPanel.Resources>
|
||||
<Button CommandParameter="1920x1080" Content="1080P (1920x1080)" />
|
||||
<Button CommandParameter="1280x720" Content="720P (1280x720)" />
|
||||
<Button CommandParameter="704x576" Content="D1 (704x576)" />
|
||||
<Button CommandParameter="640x480" Content="VGA (640x480)" />
|
||||
<Button CommandParameter="640x640" Content="Square (640x640)" />
|
||||
<Button CommandParameter="352x288" Content="CIF (352x288)" />
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<StackPanel Grid.Row="3">
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="高级处理" />
|
||||
<Border
|
||||
Padding="10"
|
||||
Background="{DynamicResource Brush.Bg.Input}"
|
||||
CornerRadius="4">
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel>
|
||||
<TextBlock Foreground="{DynamicResource Brush.Text.Primary}" Text="图像画质增强 (Image Enhancement)" />
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="自动调节对比度与锐度" />
|
||||
</StackPanel>
|
||||
<CheckBox
|
||||
DockPanel.Dock="Right"
|
||||
IsChecked="{Binding EnhanceImage}"
|
||||
Style="{DynamicResource Style.CheckBox.Switch}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="4"
|
||||
Margin="0,20,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="100"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding CancelCommand}"
|
||||
Content="取消"
|
||||
Style="{DynamicResource Btn.Ghost}" />
|
||||
<Button
|
||||
Width="120"
|
||||
Command="{Binding SaveCommand}"
|
||||
Content="保存应用" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
14
SHH.CameraDashboard/Pages/CameraImgProc.xaml.cs
Normal file
14
SHH.CameraDashboard/Pages/CameraImgProc.xaml.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard;
|
||||
|
||||
/// <summary>
|
||||
/// CameraImgProc.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraImgProc : UserControl
|
||||
{
|
||||
public CameraImgProc()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
364
SHH.CameraDashboard/Pages/CameraItemTop.xaml
Normal file
364
SHH.CameraDashboard/Pages/CameraItemTop.xaml
Normal file
@@ -0,0 +1,364 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraItemTop"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="100"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Border
|
||||
Padding="20,12,20,6"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="0,0,0,1">
|
||||
|
||||
<Grid>
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Grid.Style>
|
||||
<Style TargetType="Grid">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelection}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
<TextBlock
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.5"
|
||||
Text="请在左侧列表中选择一个摄像头以查看详情" />
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Grid.Style>
|
||||
<Style TargetType="Grid">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelection}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120" />
|
||||
<ColumnDefinition Width="210" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<WrapPanel>
|
||||
<!-- 在线、离线小圆点 -->
|
||||
<Border
|
||||
Width="10"
|
||||
Height="10"
|
||||
Margin="0,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="5">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FF5555" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Camera.IsPhysicalOnline}" Value="True">
|
||||
<Setter Property="Background" Value="#55FF55" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
</Border>
|
||||
|
||||
<!-- 播放状态、ID号 -->
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
Margin="6,2,0,0"
|
||||
Padding="6,2"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="4">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#10808080" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Camera.Status}" Value="Playing">
|
||||
<Setter Property="Background" Value="#00CC6A" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Camera.Status}" Value="Faulted">
|
||||
<Setter Property="Background" Value="#FF5555" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="White"
|
||||
Text="{Binding Camera.Status}" />
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="6,8,0,0"
|
||||
FontSize="13"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.6"
|
||||
Text="ID:" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="26,8,0,0"
|
||||
FontSize="13"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="{Binding Camera.Id}" />
|
||||
|
||||
</Grid>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<WrapPanel>
|
||||
<!-- 设备名称 -->
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
FontWeight="Bold">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{Binding Camera.Name}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Camera.Name}" Value="">
|
||||
<Setter Property="Text" Value="未命名" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
<Setter Property="FontStyle" Value="Italic" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Camera.Name}" Value="{x:Null}">
|
||||
<Setter Property="Text" Value="未命名" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
<Setter Property="FontStyle" Value="Italic" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Margin="4,0,0,0"
|
||||
FontSize="13"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.5"
|
||||
Text="{Binding Camera.Brand}" />
|
||||
</WrapPanel>
|
||||
|
||||
<!-- IP 地址 -->
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Left"
|
||||
FontFamily="Consolas"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Camera.IpAddress}" />
|
||||
</Grid>
|
||||
|
||||
<WrapPanel Grid.Column="2" VerticalAlignment="Center">
|
||||
<!-- 分辨率 -->
|
||||
<StackPanel Margin="20,0,20,0">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontSize="10"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.5"
|
||||
Text="RESOLUTION" />
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Camera.Width}" />
|
||||
<TextBlock
|
||||
Margin="2,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text=" x " />
|
||||
<TextBlock
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Camera.Height}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Border BorderBrush="{DynamicResource Brush.Border}" BorderThickness="0,0,1,0" />
|
||||
|
||||
<!-- 实际帧 -->
|
||||
<StackPanel Margin="20,0,20,0">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontSize="10"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.5"
|
||||
Text="REAL FPS" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Camera.RealFps}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="4"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="8,0,8,0"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Danger}"
|
||||
ToolTip="删除此摄像头">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.Trash}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="8,0,8,0"
|
||||
Command="{Binding EditDeviceCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="编辑设备配置">
|
||||
<Path
|
||||
Width="18"
|
||||
Height="18"
|
||||
Data="{StaticResource Icon.Action.Edit}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="5,0,0,0"
|
||||
Command="{Binding ImageProcessCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="图像处理">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.Action.Process}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="5,0,0,0"
|
||||
Command="{Binding ImageSubscribeCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="图像订阅">
|
||||
<Path
|
||||
Width="18"
|
||||
Height="18"
|
||||
Data="{StaticResource Icon.Action.Subscribe}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="0,0,5,0"
|
||||
Command="{Binding PtzCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="云台控制 (PTZ)">
|
||||
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.Ptz}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="8,0,8,0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Command="{Binding TogglePlayCommand}"
|
||||
Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
x:Name="bd"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="8">
|
||||
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Action.Play}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Camera.Status}" Value="Playing">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Action.Pause}" />
|
||||
<Setter Property="Fill" Value="#00CC6A" />
|
||||
</DataTrigger>
|
||||
|
||||
<DataTrigger Binding="{Binding Camera.Status}" Value="Connecting">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Status.Loading}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.State.Warning}" />
|
||||
</DataTrigger>
|
||||
|
||||
<DataTrigger Binding="{Binding Camera.IsPhysicalOnline}" Value="False">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Status.WifiOff}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.State.Danger}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="bd" Property="Background" Value="#1A808080" />
|
||||
</Trigger>
|
||||
<DataTrigger Binding="{Binding Camera.IsPhysicalOnline}" Value="False">
|
||||
<Setter Property="Cursor" Value="Arrow" />
|
||||
</DataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
55
SHH.CameraDashboard/Pages/CameraItemTop.xaml.cs
Normal file
55
SHH.CameraDashboard/Pages/CameraItemTop.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// CameraItemTop.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraItemTop : UserControl
|
||||
{
|
||||
// 持有 ViewModel 的实例
|
||||
private CameraItemTopViewModel _viewModel;
|
||||
|
||||
public CameraItemTop()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 1. 初始化 ViewModel
|
||||
_viewModel = new CameraItemTopViewModel();
|
||||
|
||||
// 2. 设置 DataContext,这样 XAML 里的 {Binding Name} 就能找到 VM 里的属性
|
||||
this.DataContext = _viewModel;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 定义依赖属性 (DependencyProperty) - 这是接收绑定的关键
|
||||
// ============================================================
|
||||
|
||||
// 注册一个名为 "DataSource" 的依赖属性
|
||||
public static readonly DependencyProperty DataSourceProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(DataSource), // 属性名
|
||||
typeof(WebApiCameraModel), // 属性类型
|
||||
typeof(CameraItemTop), // 所属类型
|
||||
new PropertyMetadata(null, OnDataSourceChanged)); // 回调函数
|
||||
|
||||
// 这是一个普通的包装属性,方便代码访问
|
||||
public WebApiCameraModel DataSource
|
||||
{
|
||||
get => (WebApiCameraModel)GetValue(DataSourceProperty);
|
||||
set => SetValue(DataSourceProperty, value);
|
||||
}
|
||||
|
||||
// 当外部绑定的数据发生变化时(比如用户在左侧列表点选了新项)
|
||||
private static void OnDataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as CameraItemTop;
|
||||
if (control != null && control._viewModel != null)
|
||||
{
|
||||
// 【核心逻辑】将外部传进来的数据,转发给 ViewModel
|
||||
control._viewModel.Camera = e.NewValue as WebApiCameraModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
374
SHH.CameraDashboard/Pages/CameraList.xaml
Normal file
374
SHH.CameraDashboard/Pages/CameraList.xaml
Normal file
@@ -0,0 +1,374 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraList"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="300"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="{DynamicResource Brush.Bg.Panel}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ComboBox
|
||||
Grid.Row="0"
|
||||
Height="32"
|
||||
Margin="10,10,10,0"
|
||||
VerticalContentAlignment="Center"
|
||||
ItemsSource="{Binding NodeOptions}"
|
||||
SelectedItem="{Binding SelectedNode}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding ServiceNodeName}" />
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
Foreground="Gray"
|
||||
Text="{Binding ServiceNodeIp, StringFormat=' ({0})'}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ServiceNodeIp}" Value="ALL">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Grid Grid.Row="1" Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border
|
||||
Padding="8,6"
|
||||
Background="{DynamicResource Brush.Bg.Input}"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="🔍" />
|
||||
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
VerticalContentAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CaretBrush="{DynamicResource Brush.Text.Primary}"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<WrapPanel Grid.Column="1" Margin="0,5,0,0">
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="5,0,0,0"
|
||||
Command="{Binding AddCameraCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="添加新设备">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Plus}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="5,0,0,0"
|
||||
Command="{Binding RefreshCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}"
|
||||
ToolTip="重新加载数据">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Refresh}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
<ListBox
|
||||
Grid.Row="2"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ItemsSource="{Binding FilteredCameras}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
SelectedItem="{Binding SelectedCamera}">
|
||||
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Padding" Value="10,8" />
|
||||
<Setter Property="Margin" Value="0,0,0,1" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListBoxItem">
|
||||
<Grid Margin="0,0,0,1">
|
||||
<Border
|
||||
x:Name="bd"
|
||||
Margin="5,0"
|
||||
Background="Transparent"
|
||||
CornerRadius="4"
|
||||
Opacity="0" />
|
||||
<Border Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter />
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="bd" Property="Background" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Setter TargetName="bd" Property="Opacity" Value="0.1" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="bd" Property="Background" Value="{DynamicResource Brush.Brand}" />
|
||||
<Setter TargetName="bd" Property="Opacity" Value="0.2" />
|
||||
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Brand}" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border
|
||||
Width="10"
|
||||
Height="10"
|
||||
Margin="0,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="5">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FF5555" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsPhysicalOnline}" Value="True">
|
||||
<Setter Property="Background" Value="#55FF55" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<WrapPanel>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
FontWeight="Bold">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{Binding Name}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Primary}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Name}" Value="">
|
||||
<Setter Property="Text" Value="未命名" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
<Setter Property="FontStyle" Value="Italic" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Name}" Value="{x:Null}">
|
||||
<Setter Property="Text" Value="未命名" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Text.Secondary}" />
|
||||
<Setter Property="FontStyle" Value="Italic" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Margin="12,0,10,0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="13"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.5"
|
||||
Text="{Binding Id}" />
|
||||
</WrapPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Margin="5,0,0,0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ToolTip="{Binding Status}">
|
||||
|
||||
<Path
|
||||
Width="14"
|
||||
Height="14"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Action.Play}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Brand}" />
|
||||
|
||||
<Style.Triggers>
|
||||
|
||||
<DataTrigger Binding="{Binding IsPhysicalOnline}" Value="False">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Status.WifiOff}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.State.Danger}" />
|
||||
</DataTrigger>
|
||||
|
||||
<DataTrigger Binding="{Binding Status}" Value="Connecting">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Status.Loading}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.State.Warning}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="Authorizing">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Status.Loading}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.State.Warning}" />
|
||||
</DataTrigger>
|
||||
|
||||
<DataTrigger Binding="{Binding Status}" Value="Playing">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Action.Pause}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Status.Warning}" />
|
||||
</DataTrigger>
|
||||
|
||||
<DataTrigger Binding="{Binding Status}" Value="Streaming">
|
||||
<Setter Property="Data" Value="{StaticResource Icon.Action.Pause}" />
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Status.Warning}" />
|
||||
</DataTrigger>
|
||||
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Margin="0,2,0,0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding IpAddress}" />
|
||||
<TextBlock
|
||||
Margin="4,0"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.3"
|
||||
Text="|" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.7"
|
||||
Text="{Binding Brand}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,2,0,0" Orientation="Horizontal">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Status}" Value="Playing">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="Streaming">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.6">
|
||||
<Run Foreground="{DynamicResource Brush.Text.Primary}" Text="{Binding Width}" />
|
||||
<Run Text="x" />
|
||||
<Run Foreground="{DynamicResource Brush.Text.Primary}" Text="{Binding Height}" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Text=" " />
|
||||
|
||||
<TextBlock
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Opacity="0.6">
|
||||
<Run Text="FPS:" />
|
||||
<Run
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding RealFps}" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
Visibility="{Binding IsLoading, Converter={StaticResource BoolToVis}}">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<ProgressBar
|
||||
Width="100"
|
||||
Height="4"
|
||||
Margin="0,0,0,10"
|
||||
IsIndeterminate="True" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="正在同步数据..." />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
17
SHH.CameraDashboard/Pages/CameraList.xaml.cs
Normal file
17
SHH.CameraDashboard/Pages/CameraList.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// CameraList.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraList : UserControl
|
||||
{
|
||||
public CameraList()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = new CameraListViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
413
SHH.CameraDashboard/Pages/CameraPtz.xaml
Normal file
413
SHH.CameraDashboard/Pages/CameraPtz.xaml
Normal file
@@ -0,0 +1,413 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.CameraPtz"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DataContext="{d:DesignInstance local:CameraPtzViewModel}"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="500"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Margin="20" Background="{DynamicResource Brush.Bg.Window}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Margin="0,0,0,20" LastChildFill="False">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="{Binding Title}" />
|
||||
</DockPanel>
|
||||
|
||||
<Grid Grid.Row="1" Margin="0,0,0,30">
|
||||
<Grid
|
||||
Width="220"
|
||||
Height="220"
|
||||
Margin="50,0,0,0"
|
||||
HorizontalAlignment="Left">
|
||||
<Ellipse
|
||||
Fill="{DynamicResource Brush.Bg.Input}"
|
||||
Stroke="{DynamicResource Brush.Border}"
|
||||
StrokeThickness="1" />
|
||||
|
||||
<Button
|
||||
Width="60"
|
||||
Height="60"
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Top"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.Up}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.ChevronUp}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="60"
|
||||
Height="60"
|
||||
Margin="0,0,0,10"
|
||||
VerticalAlignment="Bottom"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.Down}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.ChevronUp}"
|
||||
RenderTransformOrigin="0.5,0.5"
|
||||
Style="{StaticResource Style.IconPath}">
|
||||
<Path.RenderTransform>
|
||||
<RotateTransform Angle="180" />
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="60"
|
||||
Height="60"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.Left}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.ChevronUp}"
|
||||
RenderTransformOrigin="0.5,0.5"
|
||||
Style="{StaticResource Style.IconPath}">
|
||||
<Path.RenderTransform>
|
||||
<RotateTransform Angle="-90" />
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="60"
|
||||
Height="60"
|
||||
Margin="0,0,10,0"
|
||||
HorizontalAlignment="Right"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.Right}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<Path
|
||||
Width="24"
|
||||
Height="24"
|
||||
Data="{StaticResource Icon.ChevronUp}"
|
||||
RenderTransformOrigin="0.5,0.5"
|
||||
Style="{StaticResource Style.IconPath}">
|
||||
<Path.RenderTransform>
|
||||
<RotateTransform Angle="90" />
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="60"
|
||||
Height="60"
|
||||
IsHitTestVisible="False"
|
||||
Opacity="0.8"
|
||||
Style="{StaticResource Btn.Icon.Info}">
|
||||
<Path
|
||||
Width="28"
|
||||
Height="28"
|
||||
Data="{StaticResource Icon.Ptz}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel
|
||||
Margin="300,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<Button
|
||||
Width="150"
|
||||
Height="48"
|
||||
Margin="0,0,5,0"
|
||||
Command="{Binding SyncTimeCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Info}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="32"
|
||||
Height="32"
|
||||
Data="{StaticResource Icon.Action.Time}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Text="一键校时" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Width="150"
|
||||
Height="48"
|
||||
Margin="5,20,0,0"
|
||||
Command="{Binding RebootCommand}"
|
||||
Style="{StaticResource Btn.Ghost.Danger}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="32"
|
||||
Height="32"
|
||||
Data="{StaticResource Icon.Action.Reboot}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Text="远程重启" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
Padding="15"
|
||||
Background="{DynamicResource Brush.Bg.Input}"
|
||||
CornerRadius="8">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,15"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="镜头与辅助" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="50" />
|
||||
<RowDefinition Height="50" />
|
||||
<RowDefinition Height="50" />
|
||||
<RowDefinition Height="15" />
|
||||
<RowDefinition Height="50" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="变倍" />
|
||||
</StackPanel>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.ZoomOut}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Minus}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="缩小" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.ZoomIn}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Plus}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="放大" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="聚焦" />
|
||||
</StackPanel>
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.FocusNear}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Focus.Near}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="拉近" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.FocusFar}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Focus.Far}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="拉远" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="光圈" />
|
||||
</StackPanel>
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.IrisClose}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Iris.Small}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="变小" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Width="120"
|
||||
local:TouchBehavior.Action="{x:Static local:PtzAction.IrisOpen}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Iris.Large}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="变大" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="0,5"
|
||||
VerticalAlignment="Center"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="0,0,0,1" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="4"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="6,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="雨刷" />
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="120"
|
||||
Command="{Binding StopCommand}"
|
||||
CommandParameter="{x:Static local:PtzAction.Wiper}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Action.StopSmall}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="停止" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Width="120"
|
||||
Command="{Binding StartCommand}"
|
||||
CommandParameter="{x:Static local:PtzAction.Wiper}"
|
||||
Style="{StaticResource Btn.Ghost.Secondary}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{StaticResource Icon.Action.PlaySmall}"
|
||||
Style="{StaticResource Style.IconPath}" />
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Text="启动" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
15
SHH.CameraDashboard/Pages/CameraPtz.xaml.cs
Normal file
15
SHH.CameraDashboard/Pages/CameraPtz.xaml.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// CameraPtz.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CameraPtz : UserControl
|
||||
{
|
||||
public CameraPtz()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.ServiceNodesDiagnostic"
|
||||
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:local="clr-namespace:SHH.CameraDashboard"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
|
||||
<local:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
<local:InverseNullToVisibilityConverter x:Key="InverseNullToVisibilityConverter" />
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="{DynamicResource Brush.Bg.Window}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MinWidth="250" />
|
||||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="*" MinWidth="300" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ListView
|
||||
x:Name="LogList"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ItemContainerStyle="{StaticResource Style.ListViewItem.Table}"
|
||||
ItemsSource="{Binding Logs}"
|
||||
SelectedItem="{Binding SelectedLog}">
|
||||
<ListView.View>
|
||||
<GridView ColumnHeaderContainerStyle="{StaticResource Style.GridViewHeader.Flat}">
|
||||
<GridViewColumn
|
||||
Width="150"
|
||||
DisplayMemberBinding="{Binding Time, StringFormat='MM-dd HH:mm:ss fff'}"
|
||||
Header="请求时间" />
|
||||
<GridViewColumn
|
||||
Width="60"
|
||||
DisplayMemberBinding="{Binding StatusCode}"
|
||||
Header="状态" />
|
||||
<GridViewColumn
|
||||
Width="70"
|
||||
DisplayMemberBinding="{Binding ElapsedMilliseconds}"
|
||||
Header="耗时 ms" />
|
||||
<GridViewColumn
|
||||
Width="60"
|
||||
DisplayMemberBinding="{Binding Method}"
|
||||
Header="动作" />
|
||||
<GridViewColumn
|
||||
Width="120"
|
||||
DisplayMemberBinding="{Binding AppModule}"
|
||||
Header="模块" />
|
||||
<GridViewColumn
|
||||
Width="300"
|
||||
DisplayMemberBinding="{Binding Url}"
|
||||
Header="URL" />
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
|
||||
<GridSplitter
|
||||
Grid.Column="1"
|
||||
Width="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource Brush.Bg.Panel}" />
|
||||
|
||||
<Grid Grid.Column="2" Background="{DynamicResource Brush.Bg.Input}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<RadioButton
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="0"
|
||||
Content="Request"
|
||||
GroupName="Logs"
|
||||
IsChecked="True"
|
||||
Style="{StaticResource TabRadioStyle}" />
|
||||
<RadioButton
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="1"
|
||||
Content="Response"
|
||||
GroupName="Logs"
|
||||
Style="{StaticResource TabRadioStyle}" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
IsReadOnly="True"
|
||||
Style="{StaticResource Style.TextBox.CodeEditor}"
|
||||
Text="{Binding DisplayContent}"
|
||||
Visibility="{Binding SelectedLog, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{Binding SelectedLog, Converter={StaticResource InverseNullToVisibilityConverter}}">
|
||||
<TextBlock Foreground="{DynamicResource Brush.Text.Secondary}" Text="请选择一条日志查看详情" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<CheckBox
|
||||
Margin="15,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Content="过滤自动发送"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
IsChecked="{Binding IsFilterAutoLogs}"
|
||||
Style="{DynamicResource Style.CheckBox.Switch}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// ServiceNodesDiagnostic.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ServiceNodesDiagnostic : UserControl
|
||||
{
|
||||
public ServiceNodesDiagnostic()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
SHH.CameraDashboard/Pages/Diagnostics/ServiceNodesViewModel.cs
Normal file
126
SHH.CameraDashboard/Pages/Diagnostics/ServiceNodesViewModel.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace SHH.CameraDashboard;
|
||||
|
||||
public class ServiceNodesViewModel : INotifyPropertyChanged, IOverlayClosable, IDisposable
|
||||
{
|
||||
// 接口要求的关闭事件
|
||||
public event Action? RequestClose;
|
||||
|
||||
// 日志数据集合
|
||||
public ObservableCollection<LogWebApiModel> Logs { get; } = new ObservableCollection<LogWebApiModel>();
|
||||
|
||||
private LogWebApiModel _selectedLog;
|
||||
public LogWebApiModel SelectedLog
|
||||
{
|
||||
get => _selectedLog;
|
||||
set
|
||||
{
|
||||
_selectedLog = value;
|
||||
OnPropertyChanged();
|
||||
UpdateDisplayContent(); // 选中项改变时更新右侧文本
|
||||
}
|
||||
}
|
||||
|
||||
private string _displayContent;
|
||||
public string DisplayContent
|
||||
{
|
||||
get => _displayContent;
|
||||
set { _displayContent = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
private int _currentTabIndex = 0; // 0: Request, 1: Response
|
||||
// =========================================================
|
||||
// [新增] 1. 过滤开关属性 (绑定到界面 CheckBox)
|
||||
// =========================================================
|
||||
private bool _isFilterAutoLogs;
|
||||
public bool IsFilterAutoLogs
|
||||
{
|
||||
get => _isFilterAutoLogs;
|
||||
set
|
||||
{
|
||||
_isFilterAutoLogs = value;
|
||||
OnPropertyChanged();
|
||||
// 可选:切换时是否要清空现有日志?根据需求决定
|
||||
// if (value) Logs.Clear();
|
||||
}
|
||||
}
|
||||
public ICommand ClearCommand { get; }
|
||||
public ICommand CloseCommand { get; }
|
||||
public ICommand SwitchTabCommand { get; }
|
||||
|
||||
public ServiceNodesViewModel()
|
||||
{
|
||||
// 【关键步骤】订阅全局 API 服务的日志事件
|
||||
WebApiService.Instance.OnRequestCompleted += OnNewLogReceived;
|
||||
|
||||
// 初始化指令
|
||||
ClearCommand = new RelayCommand<object>(_ => Logs.Clear());
|
||||
CloseCommand = new RelayCommand<object>(_ => RequestClose?.Invoke());
|
||||
|
||||
SwitchTabCommand = new RelayCommand<string>(index =>
|
||||
{
|
||||
_currentTabIndex = int.Parse(index);
|
||||
UpdateDisplayContent();
|
||||
});
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 WebApiService 产生新日志时的回调
|
||||
/// </summary>
|
||||
private void OnNewLogReceived(LogWebApiModel log)
|
||||
{
|
||||
// 检查程序是否正在退出
|
||||
if (Application.Current == null) return;
|
||||
|
||||
if (IsFilterAutoLogs && CheckIsAutoLog(log))
|
||||
{
|
||||
return; // 如果是自动日志且开启了过滤,直接丢弃,不进入 UI 线程
|
||||
}
|
||||
|
||||
// 【线程安全】必须将操作封送回 UI 线程
|
||||
Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// 1. 将最新日志插入顶部
|
||||
Logs.Insert(0, log);
|
||||
|
||||
// 2. 限制日志数量 (例如只保留最近 500 条),防止内存溢出
|
||||
if (Logs.Count > 500)
|
||||
{
|
||||
Logs.RemoveAt(Logs.Count - 1);
|
||||
}
|
||||
|
||||
// 3. (可选) 如果你想让列表自动滚动,可以在 View 的 CodeBehind 里做,或者在这里处理选中项逻辑
|
||||
}, DispatcherPriority.Background);
|
||||
}
|
||||
private bool CheckIsAutoLog(LogWebApiModel log)
|
||||
{
|
||||
if (log.IsAutoPost) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateDisplayContent()
|
||||
{
|
||||
if (SelectedLog == null)
|
||||
{
|
||||
DisplayContent = string.Empty;
|
||||
return;
|
||||
}
|
||||
// 根据当前选中的 Tab 显示请求或响应内容
|
||||
DisplayContent = _currentTabIndex == 0 ? SelectedLog.RequestData : SelectedLog.ResponseData;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected void OnPropertyChanged([CallerMemberName] string name = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
WebApiService.Instance.OnRequestCompleted -= OnNewLogReceived;
|
||||
}
|
||||
}
|
||||
194
SHH.CameraDashboard/Pages/WizardClientsControl.xaml
Normal file
194
SHH.CameraDashboard/Pages/WizardClientsControl.xaml
Normal file
@@ -0,0 +1,194 @@
|
||||
<UserControl
|
||||
x:Class="SHH.CameraDashboard.WizardClientsControl"
|
||||
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"
|
||||
Width="850"
|
||||
Height="550"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Border
|
||||
Background="{DynamicResource Brush.Bg.Window}"
|
||||
BorderBrush="{DynamicResource Brush.Border.Focus}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{DynamicResource Radius.Normal}">
|
||||
<Grid Margin="25">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Margin="0,0,0,20">
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="{DynamicResource Size.Font.Huge}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.Text.Primary}"
|
||||
Text="📡 服务节点配置" />
|
||||
<Button
|
||||
Width="30"
|
||||
Height="30"
|
||||
Command="{Binding CancelCommand}"
|
||||
Content="✕"
|
||||
DockPanel.Dock="Right"
|
||||
Style="{DynamicResource Btn.Ghost}" />
|
||||
</DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="请添加或修改后端的 IP 地址与端口,配置将用于聚合监控数据。" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border
|
||||
Padding="10"
|
||||
Background="{DynamicResource Brush.Bg.Panel}"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="1,1,1,0">
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="节点清单" />
|
||||
<Button
|
||||
Width="90"
|
||||
Height="26"
|
||||
Padding="15,0"
|
||||
Background="{DynamicResource Brush.Accent}"
|
||||
BorderThickness="0"
|
||||
Command="{Binding AddNodeCommand}"
|
||||
Content="+ 新增一行"
|
||||
DockPanel.Dock="Right"
|
||||
Foreground="White" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<ListView
|
||||
x:Name="NodeList"
|
||||
Grid.Row="1"
|
||||
Background="Transparent"
|
||||
BorderBrush="{DynamicResource Brush.Border}"
|
||||
BorderThickness="1"
|
||||
ItemContainerStyle="{DynamicResource Style.ListViewItem.Table}"
|
||||
ItemsSource="{Binding ServiceNodes}">
|
||||
<ListView.View>
|
||||
<GridView ColumnHeaderContainerStyle="{DynamicResource Style.GridViewHeader.Flat}">
|
||||
<GridViewColumn Width="180" Header="节点名称">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBox Style="{DynamicResource Style.TextBox.InTable}" Text="{Binding ServiceNodeName, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
||||
<GridViewColumn Width="180" Header="IP 地址">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBox Style="{DynamicResource Style.TextBox.InTable}" Text="{Binding ServiceNodeIp, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
||||
<GridViewColumn Width="100" Header="端口">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBox Style="{DynamicResource Style.TextBox.InTable}" Text="{Binding ServiceNodePort, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Width="180" Header="连通性状态">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Border
|
||||
Padding="8,2"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#11000000"
|
||||
CornerRadius="4">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Status}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="Gray" />
|
||||
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Status}" Value="在线">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Status.Success}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="离线">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Status.Danger}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="正在检测...">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Accent}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="警告">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Status.Warning}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
|
||||
<GridViewColumn Width="80" Header="操作">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Button
|
||||
Width="45"
|
||||
Height="24"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.DeleteNodeCommand, RelativeSource={RelativeSource AncestorType=ListView}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="删除"
|
||||
FontSize="11"
|
||||
Style="{DynamicResource Btn.Danger}" />
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
</Grid>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="0,20,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,15,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Brush.Text.Secondary}"
|
||||
Text="修改后请点击检测 →" />
|
||||
<Button
|
||||
Width="110"
|
||||
Height="32"
|
||||
Margin="0,0,10,0"
|
||||
Command="{Binding CheckCommand}"
|
||||
Content="🔍 立即检测"
|
||||
Style="{DynamicResource Btn.Ghost}" />
|
||||
<Button
|
||||
Width="120"
|
||||
Height="32"
|
||||
Background="{DynamicResource Brush.Accent}"
|
||||
BorderThickness="0"
|
||||
Command="{Binding ConfirmCommand}"
|
||||
Content="保存并应用"
|
||||
Foreground="White" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
19
SHH.CameraDashboard/Pages/WizardClientsControl.xaml.cs
Normal file
19
SHH.CameraDashboard/Pages/WizardClientsControl.xaml.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// WizardClientsControl.xaml 的交互逻辑
|
||||
/// <para>客户端配置向导的视图,通过数据绑定与 <see cref="ViewModels.WizardClientsViewModel"/> 交互</para>
|
||||
/// </summary>
|
||||
public partial class WizardClientsControl : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="WizardClientsControl"/> 类的新实例
|
||||
/// </summary>
|
||||
public WizardClientsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user