更新
This commit is contained in:
@@ -118,7 +118,7 @@
|
||||
<TabItem Header="实时数据">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="0,6,0,0">
|
||||
<Border Style="{StaticResource CardBorderStyle}" Padding="14">
|
||||
<Border Style="{StaticResource CardBorderStyle}" Padding="14" Visibility="Collapsed">
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="Rs485QuickPumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border Width="248"
|
||||
@@ -129,14 +129,12 @@
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<DockPanel>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="84" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel DockPanel.Dock="Left">
|
||||
<CheckBox Content="选择"
|
||||
IsChecked="{Binding IsBatchSelected, UpdateSourceTrigger=PropertyChanged}" />
|
||||
@@ -156,24 +154,11 @@
|
||||
Text="{Binding Rs485SlaveAddress, StringFormat=从站 {0}}" />
|
||||
</Border>
|
||||
</DockPanel>
|
||||
<Grid Grid.Row="1" Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
<TextBox Margin="0,10,0,0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Grid.Row="2" Margin="0,10,0,0" Columns="3">
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
@@ -187,8 +172,7 @@
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Grid.Row="3"
|
||||
Margin="0,10,0,0"
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
@@ -204,8 +188,17 @@
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<StackPanel Grid.Row="4" Margin="0,10,0,0">
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Button Height="34"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
<Button Height="34"
|
||||
Margin="0,8,0,0"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
@@ -353,14 +346,47 @@
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<StackPanel Visibility="Collapsed">
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Text="执行机构控制" />
|
||||
<Button DockPanel.Dock="Right"
|
||||
MinWidth="132"
|
||||
Height="34"
|
||||
Padding="10,4"
|
||||
Command="{Binding ToggleRealtimeActuatorControlsCommand}"
|
||||
Content="{Binding RealtimeActuatorControlsToggleText}"
|
||||
Background="#FF6B8791" />
|
||||
</DockPanel>
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="18" FontWeight="Bold" Text="执行机构控制" />
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding RealtimeActuatorControlsVisible}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<Border Margin="0,10,0,12"
|
||||
Padding="12"
|
||||
Background="#FFF3F7F8"
|
||||
CornerRadius="10"
|
||||
BorderBrush="#FFD5E2E6"
|
||||
BorderThickness="1">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasRealtimeRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<StackPanel>
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
@@ -432,7 +458,7 @@
|
||||
Style="{StaticResource CaptionStyle}"
|
||||
Text="{Binding SelectedRs485PumpCount, StringFormat=当前已选中 {0} 台泵}" />
|
||||
<ItemsControl Margin="0,4,0,0"
|
||||
ItemsSource="{Binding ActiveRs485FlowPumpControls}"
|
||||
ItemsSource="{Binding RealtimeRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource Rs485QuickPumpCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
@@ -443,15 +469,7 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<WrapPanel Margin="0,10,0,0">
|
||||
<ItemsControl ItemsSource="{Binding NegativeAssistPumpControls}"
|
||||
ItemTemplate="{StaticResource PumpControlCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding ValveControls}"
|
||||
<ItemsControl ItemsSource="{Binding RealtimeValveControls}"
|
||||
ItemTemplate="{StaticResource ValveControlCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
@@ -461,6 +479,7 @@
|
||||
</ItemsControl>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource CardBorderStyle}" Padding="14">
|
||||
@@ -1268,6 +1287,27 @@
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
</Style>
|
||||
</WrapPanel.Resources>
|
||||
<Button Command="{Binding ToggleValveControlCommand}"
|
||||
CommandParameter="{Binding CirculatingWaterControl}"
|
||||
Content="{Binding CirculatingWaterControl.CirculatingWaterToggleText}"
|
||||
Background="#FFD64545"
|
||||
IsEnabled="{Binding CanModifySession}">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="MinWidth" Value="128" />
|
||||
<Setter Property="MinHeight" Value="34" />
|
||||
<Setter Property="Padding" Value="10,6" />
|
||||
<Setter Property="Margin" Value="0,0,6,6" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasCirculatingWaterControl}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button Click="ReturnToProjectListButton_OnClick"
|
||||
Content="返回项目检查"
|
||||
Background="#FF6B8791" />
|
||||
@@ -1302,6 +1342,724 @@
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelectedItem}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsKinkResistanceSelected}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding HasKinkResistanceRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="KinkResistanceRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border MinWidth="420"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12"
|
||||
Background="#FFF8FBFC"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="96" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="读回" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding SetpointReadbackDisplay}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="实时" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{Binding SetpointStatusForeground}"
|
||||
Text="{Binding Rs485RunStateText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Padding="12,4"
|
||||
Margin="0,44,0,0"
|
||||
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="启动"
|
||||
IsEnabled="{Binding CanStartRs485Action}"
|
||||
Background="#FF2B8F6A"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StartActionHint}" />
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Margin="0,8,0,0"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止"
|
||||
IsEnabled="{Binding CanStopRs485Action}"
|
||||
Background="#FFB85C38"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StopActionHint}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<StackPanel>
|
||||
<Grid Margin="0,8,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ItemsControl Grid.Column="0"
|
||||
ItemsSource="{Binding KinkResistanceRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource KinkResistanceRs485PumpCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelectedItem}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsPressureDropSelected}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding HasPressureDropRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="PressureDropRs485QuickPumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border MinWidth="420"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12"
|
||||
Background="#FFF8FBFC"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="96" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="读回" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding SetpointReadbackDisplay}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="实时" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{Binding SetpointStatusForeground}"
|
||||
Text="{Binding Rs485RunStateText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Padding="12,4"
|
||||
Margin="0,44,0,0"
|
||||
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="启动"
|
||||
IsEnabled="{Binding CanStartRs485Action}"
|
||||
Background="#FF2B8F6A"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StartActionHint}" />
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Margin="0,8,0,0"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止"
|
||||
IsEnabled="{Binding CanStopRs485Action}"
|
||||
Background="#FFB85C38"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StopActionHint}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="PressureDropValveControlCardTemplate" DataType="{x:Type models:ValveControlChannel}">
|
||||
<Button MinWidth="132"
|
||||
Height="34"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.ToggleValveControlCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding ToggleButtonText}"
|
||||
Background="#FF4D8C72"
|
||||
IsEnabled="{Binding DataContext.CanModifySession, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
ToolTip="{Binding StateText}" />
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<Grid Margin="0,8,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ItemsControl Grid.Column="0"
|
||||
ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource PressureDropRs485QuickPumpCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ItemsControl Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
ItemsSource="{Binding PressureDropSecondaryValveControls}"
|
||||
ItemTemplate="{StaticResource PressureDropValveControlCardTemplate}">
|
||||
<ItemsControl.Style>
|
||||
<Style TargetType="ItemsControl">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasPressureDropSecondaryValveControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ItemsControl.Style>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel HorizontalAlignment="Center" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelectedItem}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsRecirculationSelected}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding HasRecirculationRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="RecirculationRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border MinWidth="360"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12"
|
||||
Background="#FFF8FBFC"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="读回" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding SetpointReadbackDisplay}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="实时" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{Binding SetpointStatusForeground}"
|
||||
Text="{Binding Rs485RunStateText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<StackPanel>
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel DockPanel.Dock="Left">
|
||||
</StackPanel>
|
||||
<WrapPanel DockPanel.Dock="Right" Margin="12,0,0,0">
|
||||
<Button MinWidth="120"
|
||||
Height="34"
|
||||
Padding="12,4"
|
||||
Margin="0,0,8,8"
|
||||
Command="{Binding StartRecirculationRs485PumpsCommand}"
|
||||
Content="统一启动三泵"
|
||||
Background="#FF2B8F6A" />
|
||||
<Button MinWidth="120"
|
||||
Height="34"
|
||||
Padding="12,4"
|
||||
Margin="0,0,0,8"
|
||||
Command="{Binding StopRecirculationRs485PumpsCommand}"
|
||||
Content="统一停止三泵"
|
||||
Background="#FFB85C38" />
|
||||
</WrapPanel>
|
||||
</DockPanel>
|
||||
<Grid Margin="0,8,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ItemsControl Grid.Column="0"
|
||||
ItemsSource="{Binding RecirculationRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource RecirculationRs485PumpCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelectedItem}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsAntiCollapseSelected}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding HasPressureDropRs485FlowPumpControls}" Value="False" />
|
||||
<Condition Binding="{Binding HasAntiCollapsePumpControls}" Value="False" />
|
||||
<Condition Binding="{Binding HasAntiCollapseSecondaryValveControls}" Value="False" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</MultiDataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="AntiCollapseRs485QuickPumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border MinWidth="420"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12"
|
||||
Background="#FFF8FBFC"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="96" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="读回" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding SetpointReadbackDisplay}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="实时" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{Binding SetpointStatusForeground}"
|
||||
Text="{Binding Rs485RunStateText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Padding="12,4"
|
||||
Margin="0,44,0,0"
|
||||
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="启动"
|
||||
IsEnabled="{Binding CanStartRs485Action}"
|
||||
Background="#FF2B8F6A"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StartActionHint}" />
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Margin="0,8,0,0"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止"
|
||||
IsEnabled="{Binding CanStopRs485Action}"
|
||||
Background="#FFB85C38"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StopActionHint}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="AntiCollapsePumpControlCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Button MinWidth="132"
|
||||
Height="34"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.TogglePumpControlCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding ToggleButtonText}"
|
||||
Background="#FF4D8C72"
|
||||
IsEnabled="{Binding DataContext.CanModifySession, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
ToolTip="{Binding StateText}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="AntiCollapseValveControlCardTemplate" DataType="{x:Type models:ValveControlChannel}">
|
||||
<Button MinWidth="132"
|
||||
Height="34"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.ToggleValveControlCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding ToggleButtonText}"
|
||||
Background="#FF4D8C72"
|
||||
IsEnabled="{Binding DataContext.CanModifySession, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
ToolTip="{Binding StateText}" />
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<StackPanel>
|
||||
<StackPanel Margin="0,8,0,0" Orientation="Horizontal">
|
||||
<ItemsControl ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource AntiCollapseRs485QuickPumpCardTemplate}">
|
||||
<ItemsControl.Style>
|
||||
<Style TargetType="ItemsControl">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasPressureDropRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ItemsControl.Style>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding NegativeAssistPumpControls}"
|
||||
ItemTemplate="{StaticResource AntiCollapsePumpControlCardTemplate}">
|
||||
<ItemsControl.Style>
|
||||
<Style TargetType="ItemsControl">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasAntiCollapsePumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ItemsControl.Style>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding AntiCollapseSecondaryValveControls}"
|
||||
ItemTemplate="{StaticResource AntiCollapseValveControlCardTemplate}">
|
||||
<ItemsControl.Style>
|
||||
<Style TargetType="ItemsControl">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasAntiCollapseSecondaryValveControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ItemsControl.Style>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasSelectedItem}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsHemolysisPrimaryInputSelected}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding HasHemolysisRs485FlowPumpControls}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="HemolysisRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||
<Border MinWidth="420"
|
||||
Margin="0,0,10,10"
|
||||
Padding="12"
|
||||
Background="#FFF8FBFC"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#FFD8E4E8"
|
||||
BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="96" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock FontSize="14"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Height="34"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1"
|
||||
MinWidth="76"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,2"
|
||||
Command="{Binding DataContext.WritePumpSetpointCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="写入" />
|
||||
</Grid>
|
||||
<UniformGrid Margin="0,10,0,0" Columns="3">
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="目标" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding PendingSetpointText, StringFormat={}{0} L/min}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="读回" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding SetpointReadbackDisplay}" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionStyle}" Text="实时" />
|
||||
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding FlowDisplay}" />
|
||||
</StackPanel>
|
||||
</UniformGrid>
|
||||
<Border Margin="0,10,0,0"
|
||||
Padding="10,6"
|
||||
Background="{Binding SetpointStatusBackground}"
|
||||
CornerRadius="8">
|
||||
<TextBlock FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Foreground="{Binding SetpointStatusForeground}"
|
||||
Text="{Binding Rs485RunStateText}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Stretch">
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Padding="12,4"
|
||||
Margin="0,44,0,0"
|
||||
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="启动"
|
||||
IsEnabled="{Binding CanStartRs485Action}"
|
||||
Background="#FF2B8F6A"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StartActionHint}" />
|
||||
<Button Height="34"
|
||||
MinWidth="84"
|
||||
Margin="0,8,0,0"
|
||||
Padding="12,4"
|
||||
Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="停止"
|
||||
IsEnabled="{Binding CanStopRs485Action}"
|
||||
Background="#FFB85C38"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{Binding StopActionHint}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<StackPanel>
|
||||
<Grid Margin="0,8,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="12" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ItemsControl Grid.Column="0"
|
||||
ItemsSource="{Binding HemolysisRs485FlowPumpControls}"
|
||||
ItemTemplate="{StaticResource HemolysisRs485PumpCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource CardBorderStyle}">
|
||||
|
||||
@@ -198,6 +198,11 @@ public partial class PumpControlChannel : ObservableObject
|
||||
: PendingRs485RunningState == true || IsRunning
|
||||
? "停止"
|
||||
: "启动";
|
||||
public string ToggleButtonText => IsRs485Busy
|
||||
? $"{Name}处理中"
|
||||
: PendingRs485RunningState == true || IsRunning
|
||||
? $"停止{Name}"
|
||||
: $"启动{Name}";
|
||||
public bool CanStartRs485Action => !IsRs485Busy
|
||||
&& PendingRs485RunningState != true
|
||||
&& !IsRunning
|
||||
@@ -228,6 +233,7 @@ public partial class PumpControlChannel : ObservableObject
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
OnPropertyChanged(nameof(IndicatorColor));
|
||||
OnPropertyChanged(nameof(ActionText));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CanStartRs485Action));
|
||||
OnPropertyChanged(nameof(CanStopRs485Action));
|
||||
OnPropertyChanged(nameof(StartActionHint));
|
||||
@@ -252,6 +258,7 @@ public partial class PumpControlChannel : ObservableObject
|
||||
OnPropertyChanged(nameof(StateText));
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
OnPropertyChanged(nameof(IndicatorColor));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
||||
}
|
||||
|
||||
@@ -342,6 +349,7 @@ public partial class PumpControlChannel : ObservableObject
|
||||
OnPropertyChanged(nameof(StateText));
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
OnPropertyChanged(nameof(ActionText));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CanStartRs485Action));
|
||||
OnPropertyChanged(nameof(CanStopRs485Action));
|
||||
OnPropertyChanged(nameof(StartActionHint));
|
||||
@@ -354,6 +362,7 @@ public partial class PumpControlChannel : ObservableObject
|
||||
{
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
OnPropertyChanged(nameof(ActionText));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CanStartRs485Action));
|
||||
OnPropertyChanged(nameof(CanStopRs485Action));
|
||||
OnPropertyChanged(nameof(StartActionHint));
|
||||
|
||||
@@ -16,6 +16,12 @@ public partial class ValveControlChannel : ObservableObject
|
||||
|
||||
public string StateText => !StateAvailable ? "未知" : IsOpen ? "开启" : "关闭";
|
||||
public string ActionText => IsOpen ? "关闭" : "开启";
|
||||
public string ToggleButtonText => Key == "CirculatingWaterTemperature"
|
||||
? (IsOpen ? "停止循环水温" : "启动循环水温")
|
||||
: IsOpen
|
||||
? $"停止{Name}"
|
||||
: $"启动{Name}";
|
||||
public string CirculatingWaterToggleText => IsOpen ? "停止循环水温" : "启动循环水温";
|
||||
public string IndicatorColor => !StateAvailable ? "#FF94A6AE" : IsOpen ? "#FF32B06A" : "#FFC8D4DA";
|
||||
public string StateHint => !StateAvailable ? "未取得 PLC 状态" : $"{Name}已{StateText}";
|
||||
public bool HideRealtimeCardStateDescription => Key is "TestLoopValve1" or "TestLoopValve2" or "CirculatingWaterTemperature";
|
||||
@@ -24,6 +30,8 @@ public partial class ValveControlChannel : ObservableObject
|
||||
{
|
||||
OnPropertyChanged(nameof(StateText));
|
||||
OnPropertyChanged(nameof(ActionText));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CirculatingWaterToggleText));
|
||||
OnPropertyChanged(nameof(IndicatorColor));
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
}
|
||||
@@ -31,6 +39,8 @@ public partial class ValveControlChannel : ObservableObject
|
||||
partial void OnStateAvailableChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(StateText));
|
||||
OnPropertyChanged(nameof(ToggleButtonText));
|
||||
OnPropertyChanged(nameof(CirculatingWaterToggleText));
|
||||
OnPropertyChanged(nameof(IndicatorColor));
|
||||
OnPropertyChanged(nameof(StateHint));
|
||||
}
|
||||
|
||||
@@ -41,6 +41,20 @@ public partial class MainViewModel
|
||||
private const double DefaultRs485RawPerLitrePerMinute = 100d;
|
||||
private const double DefaultRs485RawOffset = 0d;
|
||||
private const int MaxRs485MotorCommand = short.MaxValue;
|
||||
private const string PressureDropRs485PumpKey = "PressureDropPump";
|
||||
private const string KinkResistanceRs485PumpKey = "KinkResistancePump";
|
||||
private static readonly string[] HemolysisRs485PumpKeys =
|
||||
[
|
||||
"HemolysisDrainageSinglePump",
|
||||
"HemolysisReturnSinglePump",
|
||||
"HemolysisDualLumenPump"
|
||||
];
|
||||
private static readonly string[] RecirculationRs485PumpKeys =
|
||||
[
|
||||
"RecirculationMainPump",
|
||||
"RecirculationReturnPump",
|
||||
"RecirculationDrainagePump"
|
||||
];
|
||||
private static readonly TimeSpan Rs485RuntimeRefreshInterval = TimeSpan.FromSeconds(4);
|
||||
private DateTime _lastRs485RuntimeRefreshUtc = DateTime.MinValue;
|
||||
private string _lastRs485RuntimeRefreshFailureMessage = string.Empty;
|
||||
@@ -78,14 +92,28 @@ public partial class MainViewModel
|
||||
[ObservableProperty]
|
||||
private bool rs485AdvancedSettingsVisible;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool realtimeActuatorControlsVisible = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private string rs485StatusText = "RS485 待确认";
|
||||
|
||||
public ObservableCollection<string> Rs485ParityOptions { get; } = new(["Even", "Odd", "None"]);
|
||||
public ObservableCollection<PumpControlChannel> Rs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> ActiveRs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> RealtimeRs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> PressureDropRs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> KinkResistanceRs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> HemolysisRs485FlowPumpControls { get; } = [];
|
||||
public ObservableCollection<PumpControlChannel> RecirculationRs485FlowPumpControls { get; } = [];
|
||||
public bool HasRealtimeRs485FlowPumpControls => RealtimeRs485FlowPumpControls.Count > 0;
|
||||
public bool HasPressureDropRs485FlowPumpControls => PressureDropRs485FlowPumpControls.Count > 0;
|
||||
public bool HasKinkResistanceRs485FlowPumpControls => KinkResistanceRs485FlowPumpControls.Count > 0;
|
||||
public bool HasHemolysisRs485FlowPumpControls => HemolysisRs485FlowPumpControls.Count > 0;
|
||||
public bool HasRecirculationRs485FlowPumpControls => RecirculationRs485FlowPumpControls.Count > 0;
|
||||
public int SelectedRs485PumpCount => ActiveRs485FlowPumpControls.Count(item => item.IsBatchSelected);
|
||||
public string Rs485AdvancedSettingsToggleText => Rs485AdvancedSettingsVisible ? "收起高级维护" : "展开高级维护";
|
||||
public string RealtimeActuatorControlsToggleText => RealtimeActuatorControlsVisible ? "隐藏执行机构控制" : "显示执行机构控制";
|
||||
public string Rs485ConnectionSummary =>
|
||||
$"{Rs485PortName} / {Rs485BaudRate}bps / {Rs485Parity} / {Rs485DataBits}-{Rs485StopBits}";
|
||||
public int Rs485EnabledPumpCount => Rs485FlowPumpControls.Count(item => item.Rs485Enabled);
|
||||
@@ -121,6 +149,13 @@ public partial class MainViewModel
|
||||
partial void OnRs485PersistPresetAfterWriteChanged(bool value) => UpdateAndPersistRs485Settings();
|
||||
partial void OnRs485AutoStartPumpAfterWriteChanged(bool value) => UpdateAndPersistRs485Settings();
|
||||
partial void OnRs485AdvancedSettingsVisibleChanged(bool value) => OnPropertyChanged(nameof(Rs485AdvancedSettingsToggleText));
|
||||
partial void OnRealtimeActuatorControlsVisibleChanged(bool value) => OnPropertyChanged(nameof(RealtimeActuatorControlsToggleText));
|
||||
|
||||
[RelayCommand]
|
||||
private void ToggleRealtimeActuatorControls()
|
||||
{
|
||||
RealtimeActuatorControlsVisible = !RealtimeActuatorControlsVisible;
|
||||
}
|
||||
|
||||
private void InitializeRs485FlowControl()
|
||||
{
|
||||
@@ -290,14 +325,130 @@ public partial class MainViewModel
|
||||
private void RefreshActiveRs485FlowPumpControls()
|
||||
{
|
||||
ActiveRs485FlowPumpControls.Clear();
|
||||
RealtimeRs485FlowPumpControls.Clear();
|
||||
PressureDropRs485FlowPumpControls.Clear();
|
||||
KinkResistanceRs485FlowPumpControls.Clear();
|
||||
HemolysisRs485FlowPumpControls.Clear();
|
||||
RecirculationRs485FlowPumpControls.Clear();
|
||||
foreach (var pump in Rs485FlowPumpControls.Where(item => item.Rs485Enabled))
|
||||
{
|
||||
ActiveRs485FlowPumpControls.Add(pump);
|
||||
if (string.Equals(pump.Key, PressureDropRs485PumpKey, StringComparison.Ordinal))
|
||||
{
|
||||
PressureDropRs485FlowPumpControls.Add(pump);
|
||||
}
|
||||
else if (string.Equals(pump.Key, KinkResistanceRs485PumpKey, StringComparison.Ordinal))
|
||||
{
|
||||
KinkResistanceRs485FlowPumpControls.Add(pump);
|
||||
}
|
||||
else if (HemolysisRs485PumpKeys.Contains(pump.Key, StringComparer.Ordinal))
|
||||
{
|
||||
HemolysisRs485FlowPumpControls.Add(pump);
|
||||
}
|
||||
else if (RecirculationRs485PumpKeys.Contains(pump.Key, StringComparer.Ordinal))
|
||||
{
|
||||
RecirculationRs485FlowPumpControls.Add(pump);
|
||||
}
|
||||
else
|
||||
{
|
||||
RealtimeRs485FlowPumpControls.Add(pump);
|
||||
}
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(HasRealtimeRs485FlowPumpControls));
|
||||
OnPropertyChanged(nameof(HasPressureDropRs485FlowPumpControls));
|
||||
OnPropertyChanged(nameof(HasKinkResistanceRs485FlowPumpControls));
|
||||
OnPropertyChanged(nameof(HasHemolysisRs485FlowPumpControls));
|
||||
OnPropertyChanged(nameof(HasRecirculationRs485FlowPumpControls));
|
||||
RaiseRs485CalibrationSummaryChanges();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task StartRecirculationRs485Pumps()
|
||||
{
|
||||
if (!EnsureSessionEditable("再循环三泵统一启动"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pumps = RecirculationRs485FlowPumpControls.ToList();
|
||||
if (pumps.Count == 0)
|
||||
{
|
||||
Rs485StatusText = "当前未配置再循环 RS485 泵。";
|
||||
LatestAction = Rs485StatusText;
|
||||
return;
|
||||
}
|
||||
|
||||
var issuedCount = 0;
|
||||
var confirmedCount = 0;
|
||||
var skippedCount = 0;
|
||||
var failedCount = 0;
|
||||
foreach (var pump in pumps)
|
||||
{
|
||||
var effectiveRunning = pump.PendingRs485RunningState ?? pump.IsRunning;
|
||||
if (effectiveRunning)
|
||||
{
|
||||
skippedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
var startResult = await TryWriteAndStartPumpCore(pump, "再循环三泵统一启动");
|
||||
if (startResult is Rs485StartExecutionResult.PendingConfirmation or Rs485StartExecutionResult.Confirmed)
|
||||
{
|
||||
issuedCount++;
|
||||
if (startResult == Rs485StartExecutionResult.Confirmed)
|
||||
{
|
||||
confirmedCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
var summary = $"再循环三泵启动完成:已下发 {issuedCount} 台,已确认运行 {confirmedCount} 台,跳过 {skippedCount} 台,失败 {failedCount} 台。";
|
||||
Rs485StatusText = summary;
|
||||
LatestAction = summary;
|
||||
TraceEvents.Insert(0, NewTrace("再循环三泵启动", summary));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task StopRecirculationRs485Pumps()
|
||||
{
|
||||
if (!EnsureSessionEditable("再循环三泵统一停止"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pumps = RecirculationRs485FlowPumpControls.ToList();
|
||||
if (pumps.Count == 0)
|
||||
{
|
||||
Rs485StatusText = "当前未配置再循环 RS485 泵。";
|
||||
LatestAction = Rs485StatusText;
|
||||
return;
|
||||
}
|
||||
|
||||
var stoppedCount = 0;
|
||||
var failedCount = 0;
|
||||
foreach (var pump in pumps)
|
||||
{
|
||||
if (await TryTogglePumpControlViaRs485(pump, nextState: false) == Rs485ToggleExecutionResult.Succeeded)
|
||||
{
|
||||
stoppedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
var summary = $"再循环三泵停止完成:已下发停止 {stoppedCount} 台,失败 {failedCount} 台。";
|
||||
Rs485StatusText = summary;
|
||||
LatestAction = summary;
|
||||
TraceEvents.Insert(0, NewTrace("再循环三泵停止", summary));
|
||||
}
|
||||
|
||||
private async Task RefreshRs485RuntimeStateSilentlyAsync()
|
||||
{
|
||||
if (DateTime.UtcNow - _lastRs485RuntimeRefreshUtc < Rs485RuntimeRefreshInterval)
|
||||
|
||||
@@ -353,6 +353,45 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
public ObservableCollection<DeviceChannel> Channels { get; }
|
||||
public ObservableCollection<PumpControlChannel> PumpControls { get; }
|
||||
public ObservableCollection<ValveControlChannel> ValveControls { get; }
|
||||
public IEnumerable<ValveControlChannel> RealtimeValveControls =>
|
||||
ValveControls.Where(item =>
|
||||
!string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal)
|
||||
&& !string.Equals(item.Key, "TestLoopValve1", StringComparison.Ordinal)
|
||||
&& !string.Equals(item.Key, "TestLoopValve2", StringComparison.Ordinal));
|
||||
public ValveControlChannel? CirculatingWaterControl =>
|
||||
ValveControls.FirstOrDefault(item => string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal));
|
||||
public bool HasCirculatingWaterControl => CirculatingWaterControl is not null;
|
||||
public IEnumerable<ValveControlChannel> PressureDropAuxiliaryValveControls =>
|
||||
ValveControls.Where(item =>
|
||||
string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal)
|
||||
|| string.Equals(item.Key, "TestLoopValve1", StringComparison.Ordinal))
|
||||
.OrderBy(item => string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal) ? 0 : 1);
|
||||
public bool HasPressureDropAuxiliaryValveControls => PressureDropAuxiliaryValveControls.Any();
|
||||
public IEnumerable<ValveControlChannel> PressureDropSecondaryValveControls =>
|
||||
ValveControls.Where(item => string.Equals(item.Key, "TestLoopValve1", StringComparison.Ordinal));
|
||||
public bool HasPressureDropSecondaryValveControls => PressureDropSecondaryValveControls.Any();
|
||||
public ValveControlChannel? RecirculationCirculatingWaterControl =>
|
||||
ValveControls.FirstOrDefault(item => string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal));
|
||||
public bool HasRecirculationCirculatingWaterControl => RecirculationCirculatingWaterControl is not null;
|
||||
public PumpControlChannel? AntiCollapseNegativeAssistPumpControl =>
|
||||
NegativeAssistPumpControls.FirstOrDefault();
|
||||
public bool HasAntiCollapseNegativeAssistPumpControl => AntiCollapseNegativeAssistPumpControl is not null;
|
||||
public ValveControlChannel? AntiCollapseCirculatingWaterControl =>
|
||||
ValveControls.FirstOrDefault(item => string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal));
|
||||
public bool HasAntiCollapseCirculatingWaterControl => AntiCollapseCirculatingWaterControl is not null;
|
||||
public ValveControlChannel? AntiCollapseTestLoopValve2Control =>
|
||||
ValveControls.FirstOrDefault(item => string.Equals(item.Key, "TestLoopValve2", StringComparison.Ordinal));
|
||||
public bool HasAntiCollapseTestLoopValve2Control => AntiCollapseTestLoopValve2Control is not null;
|
||||
public IEnumerable<ValveControlChannel> AntiCollapseAuxiliaryValveControls =>
|
||||
ValveControls.Where(item =>
|
||||
string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal)
|
||||
|| string.Equals(item.Key, "TestLoopValve2", StringComparison.Ordinal))
|
||||
.OrderBy(item => string.Equals(item.Key, "CirculatingWaterTemperature", StringComparison.Ordinal) ? 0 : 1);
|
||||
public bool HasAntiCollapseAuxiliaryValveControls => AntiCollapseAuxiliaryValveControls.Any();
|
||||
public IEnumerable<ValveControlChannel> AntiCollapseSecondaryValveControls =>
|
||||
ValveControls.Where(item => string.Equals(item.Key, "TestLoopValve2", StringComparison.Ordinal));
|
||||
public bool HasAntiCollapseSecondaryValveControls => AntiCollapseSecondaryValveControls.Any();
|
||||
public bool HasAntiCollapsePumpControls => NegativeAssistPumpControls.Any();
|
||||
public IEnumerable<PumpControlChannel> NegativeAssistPumpControls => PumpControlsFor("NegativeAssistPump");
|
||||
public IEnumerable<PumpControlChannel> PressureDropPumpControls => PumpControlsFor("NegativeAssistPump", "PressureDropPump");
|
||||
public IEnumerable<PumpControlChannel> RecirculationPumpControls => PumpControlsFor("RecirculationMainPump", "RecirculationReturnPump", "RecirculationDrainagePump");
|
||||
@@ -559,7 +598,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
public string PressureTrendCurrentSummary => $"近端 {ProximalPressureDisplay} / 远端 {DistalPressureDisplay} / ΔP {DeltaPressureDisplay}";
|
||||
public string FlowTrendCurrentSummary => BuildFlowTrendCurrentSummary();
|
||||
public string HemolysisRecordTemplate =>
|
||||
"3.2 试验血液准备\n" +
|
||||
"1. 试验血液准备\n" +
|
||||
$"- 依据 GB/T 16886.4 进行血液预处理。\n" +
|
||||
$"- 血液来源:{HemolysisTestParameters.BloodSource}\n" +
|
||||
$"- 采血日期:{FormatHemolysisDate(HemolysisTestParameters.CollectionDate)}\n" +
|
||||
@@ -569,13 +608,13 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
$"- 血中葡萄糖:{FormatHemolysisValue(HemolysisTestParameters.Glucose, "F1")} mmol/L\n" +
|
||||
$"- 血红蛋白:{FormatHemolysisValue(HemolysisTestParameters.TotalHemoglobin, "F1")} g/dL\n" +
|
||||
$"- 初始游离血红蛋白 fHb:{FormatHemolysisValue(GetHemolysisInitialFreeHemoglobin(), "F1")} mg/dL\n\n" +
|
||||
"3.3 测试回路说明\n" +
|
||||
"2. 测试回路说明\n" +
|
||||
$"- 回路总充盈量:{FormatHemolysisValue(HemolysisTestParameters.CircuitPrimingVolume, "F0")} mL\n" +
|
||||
$"- 回路初始血液通道试验液容积差:{FormatHemolysisValue(HemolysisTestParameters.CircuitVolumeDifference, "F2")} %(应 ≤ 1%)\n" +
|
||||
$"- 设定流量:{FormatHemolysisValue(HemolysisTestParameters.SetFlow, "F2")} L/min\n" +
|
||||
$"- 设定运行时间:{FormatHemolysisValue(HemolysisTestParameters.RunTimeMinutes, "F0")} min\n" +
|
||||
$"- 温度控制:{FormatHemolysisValue(HemolysisTestParameters.TargetTemperature, "F1")} ℃ ± 2 ℃\n\n" +
|
||||
"4. 试验运行与取样记录";
|
||||
"3. 试验运行与取样记录";
|
||||
public string HemolysisRecordNoteTemplate => BuildHemolysisRecordNoteText();
|
||||
public bool HasAntiCollapseBaseline => _antiCollapseBaselinePressureDrop.HasValue && _antiCollapseBaselineFlow.HasValue;
|
||||
public string AntiCollapseBaselineDisplay => HasAntiCollapseBaseline
|
||||
@@ -778,11 +817,35 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
}
|
||||
|
||||
var nextState = !valve.IsOpen;
|
||||
ValveControlChannel? pairedValve = null;
|
||||
if (nextState)
|
||||
{
|
||||
pairedValve = valve.Key switch
|
||||
{
|
||||
"TestLoopValve1" => ValveControls.FirstOrDefault(item => string.Equals(item.Key, "TestLoopValve2", StringComparison.Ordinal)),
|
||||
"TestLoopValve2" => ValveControls.FirstOrDefault(item => string.Equals(item.Key, "TestLoopValve1", StringComparison.Ordinal)),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (pairedValve?.IsOpen == true)
|
||||
{
|
||||
_telemetryService.SetValveOpen(pairedValve.Key, false);
|
||||
}
|
||||
}
|
||||
|
||||
_telemetryService.SetValveOpen(valve.Key, nextState);
|
||||
var traceDetail = $"{valve.Name} => {(nextState ? "开启" : "关闭")}";
|
||||
if (pairedValve?.IsOpen == true)
|
||||
{
|
||||
traceDetail += $" / {pairedValve.Name} => 关闭";
|
||||
}
|
||||
|
||||
LatestAction = IsTelemetryOnline
|
||||
? $"{valve.Name} 已发送{(nextState ? "开启" : "关闭")}指令。"
|
||||
? pairedValve?.IsOpen == true
|
||||
? $"{valve.Name} 已发送{(nextState ? "开启" : "关闭")}指令,并自动关闭 {pairedValve.Name}。"
|
||||
: $"{valve.Name} 已发送{(nextState ? "开启" : "关闭")}指令。"
|
||||
: $"{valve.Name} 指令未下发,PLC 当前离线。";
|
||||
TraceEvents.Insert(0, NewTrace("阀控", $"{valve.Name} => {(nextState ? "开启" : "关闭")}"));
|
||||
TraceEvents.Insert(0, NewTrace("阀控", traceDetail));
|
||||
_ = RefreshTelemetryAsync();
|
||||
}
|
||||
|
||||
@@ -1349,7 +1412,6 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
RefreshTelemetryPanel();
|
||||
RefreshDeviceStatus();
|
||||
RefreshComputedState();
|
||||
RefreshFilteredItemsView();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -1760,7 +1822,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
||||
var calculationHematocrit = GetHemolysisCalculationHematocrit();
|
||||
|
||||
return
|
||||
"5. 结果计算\n" +
|
||||
"4. 结果计算\n" +
|
||||
$"- 标准取样点完成情况:{BuildHemolysisSamplingCompletionSummary()}\n" +
|
||||
$"- ΔfHb (T360 - T0):{FormatHemolysisDisplay(GetHemolysisDeltaFreeHemoglobin(), "F1", "mg/dL")}\n" +
|
||||
"- NIH = ΔfHb × V(L) × (1-Hct) / (Q×T)\n" +
|
||||
|
||||
Reference in New Issue
Block a user