更新202659
This commit is contained in:
@@ -14,6 +14,85 @@
|
|||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<converters:TrendPointCollectionConverter x:Key="TrendPointCollectionConverter" />
|
<converters:TrendPointCollectionConverter x:Key="TrendPointCollectionConverter" />
|
||||||
<converters:TrendLastPointCoordinateConverter x:Key="TrendLastPointCoordinateConverter" />
|
<converters:TrendLastPointCoordinateConverter x:Key="TrendLastPointCoordinateConverter" />
|
||||||
|
<DataTemplate x:Key="ProjectRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||||
|
<Grid Margin="0,0,10,6"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="112" />
|
||||||
|
<ColumnDefinition Width="6" />
|
||||||
|
<ColumnDefinition Width="82" />
|
||||||
|
<ColumnDefinition Width="44" />
|
||||||
|
<ColumnDefinition Width="6" />
|
||||||
|
<ColumnDefinition Width="54" />
|
||||||
|
<ColumnDefinition Width="6" />
|
||||||
|
<ColumnDefinition Width="54" />
|
||||||
|
<ColumnDefinition Width="8" />
|
||||||
|
<ColumnDefinition Width="52" />
|
||||||
|
<ColumnDefinition Width="6" />
|
||||||
|
<ColumnDefinition Width="96" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="{StaticResource HeaderBrush}"
|
||||||
|
Text="{Binding Name}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
ToolTip="{Binding Name}" />
|
||||||
|
<TextBox Grid.Column="2"
|
||||||
|
Height="32"
|
||||||
|
VerticalContentAlignment="Center"
|
||||||
|
FontSize="14"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Cursor="Hand"
|
||||||
|
ToolTip="目标流量 L/min"
|
||||||
|
PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown"
|
||||||
|
GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
||||||
|
<TextBlock Grid.Column="3"
|
||||||
|
Margin="4,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource CaptionStyle}"
|
||||||
|
Text="L/min" />
|
||||||
|
<Button Grid.Column="5"
|
||||||
|
Height="32"
|
||||||
|
MinWidth="0"
|
||||||
|
Padding="6,2"
|
||||||
|
Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||||
|
CommandParameter="{Binding}"
|
||||||
|
Content="启动"
|
||||||
|
IsEnabled="{Binding CanStartRs485Action}"
|
||||||
|
Background="#FF2B8F6A"
|
||||||
|
ToolTipService.ShowOnDisabled="True"
|
||||||
|
ToolTip="{Binding StartActionHint}" />
|
||||||
|
<Button Grid.Column="7"
|
||||||
|
Height="32"
|
||||||
|
MinWidth="0"
|
||||||
|
Padding="6,2"
|
||||||
|
Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||||
|
CommandParameter="{Binding}"
|
||||||
|
Content="停止"
|
||||||
|
IsEnabled="{Binding CanStopRs485Action}"
|
||||||
|
Background="#FFB85C38"
|
||||||
|
ToolTipService.ShowOnDisabled="True"
|
||||||
|
ToolTip="{Binding StopActionHint}" />
|
||||||
|
<CheckBox Grid.Column="9"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Content="稳流"
|
||||||
|
IsChecked="{Binding IsFlowStabilizationEnabled, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
IsEnabled="{Binding CanUseFlowStabilization}"
|
||||||
|
ToolTip="{Binding FlowStabilizationToggleHint}" />
|
||||||
|
<TextBlock Grid.Column="11"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{StaticResource MutedTextBrush}"
|
||||||
|
Text="{Binding FlowStabilizationStateText}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
ToolTip="{Binding FlowStabilizationStateText}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
<Grid Margin="12">
|
<Grid Margin="12">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@@ -202,6 +281,16 @@
|
|||||||
Cursor="Hand"
|
Cursor="Hand"
|
||||||
PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown"
|
PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown"
|
||||||
GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
||||||
|
<CheckBox Margin="0,8,0,0"
|
||||||
|
Content="稳流"
|
||||||
|
IsChecked="{Binding IsFlowStabilizationEnabled, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
IsEnabled="{Binding CanUseFlowStabilization}"
|
||||||
|
ToolTip="{Binding FlowStabilizationToggleHint}" />
|
||||||
|
<TextBlock Margin="0,4,0,0"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{StaticResource MutedTextBrush}"
|
||||||
|
Text="{Binding FlowStabilizationStateText}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
<Border Margin="0,10,0,0"
|
<Border Margin="0,10,0,0"
|
||||||
Padding="10,6"
|
Padding="10,6"
|
||||||
Background="{Binding SetpointStatusBackground}"
|
Background="{Binding SetpointStatusBackground}"
|
||||||
@@ -939,6 +1028,105 @@
|
|||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem x:Name="TightnessTestTab" Header="密合性">
|
||||||
|
<ScrollViewer Margin="0,6,0,0" VerticalScrollBarVisibility="Auto" CanContentScroll="False">
|
||||||
|
<StackPanel>
|
||||||
|
<Border Style="{StaticResource CardBorderStyle}" Padding="14">
|
||||||
|
<ItemsControl ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
||||||
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<WrapPanel />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Style="{StaticResource CardBorderStyle}" Padding="14">
|
||||||
|
<StackPanel IsEnabled="{Binding HasTightnessInspectionItem}">
|
||||||
|
<Grid Margin="0,0,0,8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="12" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource SectionTitleStyle}"
|
||||||
|
Text="{Binding SelectedItemTitle}"
|
||||||
|
TextTrimming="CharacterEllipsis" />
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
MinWidth="112"
|
||||||
|
MinHeight="32"
|
||||||
|
Padding="12,5"
|
||||||
|
Click="OpenProjectInfoDialogButton_OnClick"
|
||||||
|
Background="#FFE3F6EF"
|
||||||
|
Foreground="{StaticResource HeaderBrush}"
|
||||||
|
BorderBrush="#FF9CCBBF"
|
||||||
|
Content="查看项目说明" />
|
||||||
|
</Grid>
|
||||||
|
<TextBlock Style="{StaticResource CaptionStyle}" Text="结果记录" />
|
||||||
|
<TextBox Margin="0,4,0,0"
|
||||||
|
Text="{Binding ResultValue, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
MinHeight="118"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
IsReadOnly="{Binding SelectedItemUsesRealtimeValue}" />
|
||||||
|
|
||||||
|
<Grid Margin="0,10,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="12" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Style="{StaticResource CaptionStyle}" Text="判定" />
|
||||||
|
<ComboBox Grid.Row="1"
|
||||||
|
ItemsSource="{Binding ResultStatusOptions}"
|
||||||
|
SelectedItem="{Binding SelectedResultStatusText, Mode=TwoWay}" />
|
||||||
|
<TextBlock Grid.Column="2" Style="{StaticResource CaptionStyle}" Text="记录人" />
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding ResultOperator, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
<TextBlock Grid.Row="2" Style="{StaticResource CaptionStyle}" Text="复核人" />
|
||||||
|
<TextBox Grid.Row="3" Text="{Binding ReviewerName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="2" Style="{StaticResource CaptionStyle}" Text="批准人" />
|
||||||
|
<TextBox Grid.Row="3" Grid.Column="2" Text="{Binding ApproverName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Margin="0,10,0,0" Style="{StaticResource CaptionStyle}" Text="复核备注" />
|
||||||
|
<TextBox Margin="0,4,0,0"
|
||||||
|
Text="{Binding ResultNote, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
MinHeight="96"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
IsReadOnly="{Binding SelectedItemUsesRealtimeValue}" />
|
||||||
|
|
||||||
|
<DockPanel Margin="0,12,0,0" LastChildFill="True">
|
||||||
|
<Button DockPanel.Dock="Right"
|
||||||
|
MinWidth="112"
|
||||||
|
Height="34"
|
||||||
|
Padding="12,4"
|
||||||
|
Command="{Binding ApplyResultCommand}"
|
||||||
|
Content="保存结果"
|
||||||
|
Background="#FF4D8C72"
|
||||||
|
IsEnabled="{Binding CanModifySession}" />
|
||||||
|
<TextBlock VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource CaptionStyle}"
|
||||||
|
Text="{Binding LatestAction}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</DockPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
<TabItem x:Name="ManualSupplementTab" Header="项目补充">
|
<TabItem x:Name="ManualSupplementTab" Header="项目补充">
|
||||||
<ScrollViewer Margin="0,6,0,0" VerticalScrollBarVisibility="Auto" CanContentScroll="False">
|
<ScrollViewer Margin="0,6,0,0" VerticalScrollBarVisibility="Auto" CanContentScroll="False">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
@@ -1070,34 +1258,8 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Border.Resources>
|
|
||||||
<DataTemplate x:Key="KinkResistanceRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
|
||||||
<Border MinWidth="640"
|
|
||||||
Margin="0,0,10,10"
|
|
||||||
Padding="0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="150" />
|
|
||||||
<ColumnDefinition Width="116" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Text="{Binding Name}" TextWrapping="Wrap" />
|
|
||||||
<TextBox Grid.Column="1" Width="108" Height="32" Margin="8,0,0,0" VerticalContentAlignment="Center" Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Cursor="Hand" PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown" GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
|
||||||
<Button Grid.Column="2" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="启动" IsEnabled="{Binding CanStartRs485Action}" Background="#FF2B8F6A" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StartActionHint}" />
|
|
||||||
<Button Grid.Column="3" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="停止" IsEnabled="{Binding CanStopRs485Action}" Background="#FFB85C38" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StopActionHint}" />
|
|
||||||
<TextBlock Grid.Column="4" Margin="10,0,0,0" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" Foreground="{Binding SetpointStatusForeground}" Text="{Binding Rs485RunStateText}" TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
</Border.Resources>
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,4,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="12" />
|
<ColumnDefinition Width="12" />
|
||||||
@@ -1105,7 +1267,7 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ItemsControl Grid.Column="0"
|
<ItemsControl Grid.Column="0"
|
||||||
ItemsSource="{Binding KinkResistanceRs485FlowPumpControls}"
|
ItemsSource="{Binding KinkResistanceRs485FlowPumpControls}"
|
||||||
ItemTemplate="{StaticResource KinkResistanceRs485PumpCardTemplate}">
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<WrapPanel />
|
<WrapPanel />
|
||||||
@@ -1133,30 +1295,6 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Border.Resources>
|
<Border.Resources>
|
||||||
<DataTemplate x:Key="PressureDropRs485QuickPumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
|
||||||
<Border MinWidth="640"
|
|
||||||
Margin="0,0,10,10"
|
|
||||||
Padding="0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="150" />
|
|
||||||
<ColumnDefinition Width="116" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Text="{Binding Name}" TextWrapping="Wrap" />
|
|
||||||
<TextBox Grid.Column="1" Width="108" Height="32" Margin="8,0,0,0" VerticalContentAlignment="Center" Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Cursor="Hand" PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown" GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
|
||||||
<Button Grid.Column="2" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="启动" IsEnabled="{Binding CanStartRs485Action}" Background="#FF2B8F6A" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StartActionHint}" />
|
|
||||||
<Button Grid.Column="3" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="停止" IsEnabled="{Binding CanStopRs485Action}" Background="#FFB85C38" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StopActionHint}" />
|
|
||||||
<TextBlock Grid.Column="4" Margin="10,0,0,0" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" Foreground="{Binding SetpointStatusForeground}" Text="{Binding Rs485RunStateText}" TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
<DataTemplate x:Key="PressureDropValveControlCardTemplate" DataType="{x:Type models:ValveControlChannel}">
|
<DataTemplate x:Key="PressureDropValveControlCardTemplate" DataType="{x:Type models:ValveControlChannel}">
|
||||||
<Button MinWidth="132"
|
<Button MinWidth="132"
|
||||||
Height="34"
|
Height="34"
|
||||||
@@ -1170,7 +1308,7 @@
|
|||||||
ToolTip="{Binding StateText}" />
|
ToolTip="{Binding StateText}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</Border.Resources>
|
</Border.Resources>
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,4,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="12" />
|
<ColumnDefinition Width="12" />
|
||||||
@@ -1178,7 +1316,7 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ItemsControl Grid.Column="0"
|
<ItemsControl Grid.Column="0"
|
||||||
ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
||||||
ItemTemplate="{StaticResource PressureDropRs485QuickPumpCardTemplate}">
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<WrapPanel />
|
<WrapPanel />
|
||||||
@@ -1224,70 +1362,38 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Border.Resources>
|
<Grid Margin="0,4,0,0">
|
||||||
<DataTemplate x:Key="RecirculationRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
<Grid.ColumnDefinitions>
|
||||||
<Border MinWidth="640"
|
<ColumnDefinition Width="*" />
|
||||||
Margin="0,0,10,10"
|
<ColumnDefinition Width="12" />
|
||||||
Padding="0">
|
<ColumnDefinition Width="Auto" />
|
||||||
<Grid>
|
</Grid.ColumnDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<ItemsControl Grid.Column="0"
|
||||||
<ColumnDefinition Width="150" />
|
ItemsSource="{Binding RecirculationRs485FlowPumpControls}"
|
||||||
<ColumnDefinition Width="116" />
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
<ColumnDefinition Width="Auto" />
|
<ItemsControl.ItemsPanel>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ItemsPanelTemplate>
|
||||||
<ColumnDefinition Width="*" />
|
<WrapPanel />
|
||||||
</Grid.ColumnDefinitions>
|
</ItemsPanelTemplate>
|
||||||
<Grid.RowDefinitions>
|
</ItemsControl.ItemsPanel>
|
||||||
<RowDefinition Height="Auto" />
|
</ItemsControl>
|
||||||
<RowDefinition Height="Auto" />
|
<WrapPanel Grid.Column="2" VerticalAlignment="Top">
|
||||||
</Grid.RowDefinitions>
|
<Button MinWidth="112"
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Text="{Binding Name}" TextWrapping="Wrap" />
|
Height="34"
|
||||||
<TextBox Grid.Column="1" Width="108" Height="32" Margin="8,0,0,0" VerticalContentAlignment="Center" Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Cursor="Hand" PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown" GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
Padding="10,4"
|
||||||
<Button Grid.Column="2" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="启动" IsEnabled="{Binding CanStartRs485Action}" Background="#FF2B8F6A" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StartActionHint}" />
|
Margin="0,0,8,6"
|
||||||
<Button Grid.Column="3" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="停止" IsEnabled="{Binding CanStopRs485Action}" Background="#FFB85C38" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StopActionHint}" />
|
Command="{Binding StartRecirculationRs485PumpsCommand}"
|
||||||
<TextBlock Grid.Column="4" Margin="10,0,0,0" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" Foreground="{Binding SetpointStatusForeground}" Text="{Binding Rs485RunStateText}" TextWrapping="Wrap" />
|
Content="统一启动"
|
||||||
</Grid>
|
Background="#FF2B8F6A" />
|
||||||
</Border>
|
<Button MinWidth="112"
|
||||||
</DataTemplate>
|
Height="34"
|
||||||
</Border.Resources>
|
Padding="10,4"
|
||||||
<StackPanel>
|
Margin="0,0,0,6"
|
||||||
<DockPanel LastChildFill="False">
|
Command="{Binding StopRecirculationRs485PumpsCommand}"
|
||||||
<StackPanel DockPanel.Dock="Left">
|
Content="统一停止"
|
||||||
</StackPanel>
|
Background="#FFB85C38" />
|
||||||
<WrapPanel DockPanel.Dock="Right" Margin="12,0,0,0">
|
</WrapPanel>
|
||||||
<Button MinWidth="120"
|
</Grid>
|
||||||
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,8,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>
|
<Border>
|
||||||
<Border.Style>
|
<Border.Style>
|
||||||
@@ -1312,30 +1418,6 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Border.Resources>
|
<Border.Resources>
|
||||||
<DataTemplate x:Key="AntiCollapseRs485QuickPumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
|
||||||
<Border MinWidth="640"
|
|
||||||
Margin="0,0,10,10"
|
|
||||||
Padding="0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="150" />
|
|
||||||
<ColumnDefinition Width="116" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Text="{Binding Name}" TextWrapping="Wrap" />
|
|
||||||
<TextBox Grid.Column="1" Width="108" Height="32" Margin="8,0,0,0" VerticalContentAlignment="Center" Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Cursor="Hand" PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown" GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
|
||||||
<Button Grid.Column="2" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="启动" IsEnabled="{Binding CanStartRs485Action}" Background="#FF2B8F6A" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StartActionHint}" />
|
|
||||||
<Button Grid.Column="3" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="停止" IsEnabled="{Binding CanStopRs485Action}" Background="#FFB85C38" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StopActionHint}" />
|
|
||||||
<TextBlock Grid.Column="4" Margin="10,0,0,0" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" Foreground="{Binding SetpointStatusForeground}" Text="{Binding Rs485RunStateText}" TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
<DataTemplate x:Key="AntiCollapsePumpControlCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
<DataTemplate x:Key="AntiCollapsePumpControlCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
||||||
<Button MinWidth="132"
|
<Button MinWidth="132"
|
||||||
Height="34"
|
Height="34"
|
||||||
@@ -1362,9 +1444,9 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</Border.Resources>
|
</Border.Resources>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<WrapPanel Margin="0,8,0,0">
|
<WrapPanel Margin="0,4,0,0">
|
||||||
<ItemsControl ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
<ItemsControl ItemsSource="{Binding PressureDropRs485FlowPumpControls}"
|
||||||
ItemTemplate="{StaticResource AntiCollapseRs485QuickPumpCardTemplate}">
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
<ItemsControl.Style>
|
<ItemsControl.Style>
|
||||||
<Style TargetType="ItemsControl">
|
<Style TargetType="ItemsControl">
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
@@ -1377,7 +1459,7 @@
|
|||||||
</ItemsControl.Style>
|
</ItemsControl.Style>
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<StackPanel Orientation="Horizontal" />
|
<WrapPanel />
|
||||||
</ItemsPanelTemplate>
|
</ItemsPanelTemplate>
|
||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
@@ -1437,34 +1519,8 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<Border.Resources>
|
|
||||||
<DataTemplate x:Key="HemolysisRs485PumpCardTemplate" DataType="{x:Type models:PumpControlChannel}">
|
|
||||||
<Border MinWidth="640"
|
|
||||||
Margin="0,0,10,10"
|
|
||||||
Padding="0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="150" />
|
|
||||||
<ColumnDefinition Width="116" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Text="{Binding Name}" TextWrapping="Wrap" />
|
|
||||||
<TextBox Grid.Column="1" Width="108" Height="32" Margin="8,0,0,0" VerticalContentAlignment="Center" Text="{Binding PendingSetpointText, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Cursor="Hand" PreviewMouseLeftButtonDown="PumpSetpointTextBox_OnPreviewMouseLeftButtonDown" GotKeyboardFocus="PumpSetpointTextBox_OnGotKeyboardFocus" />
|
|
||||||
<Button Grid.Column="2" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StartSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="启动" IsEnabled="{Binding CanStartRs485Action}" Background="#FF2B8F6A" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StartActionHint}" />
|
|
||||||
<Button Grid.Column="3" MinWidth="66" Height="32" Margin="8,0,0,0" Padding="8,2" Command="{Binding DataContext.StopSingleRs485PumpCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" Content="停止" IsEnabled="{Binding CanStopRs485Action}" Background="#FFB85C38" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding StopActionHint}" />
|
|
||||||
<TextBlock Grid.Column="4" Margin="10,0,0,0" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" Foreground="{Binding SetpointStatusForeground}" Text="{Binding Rs485RunStateText}" TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
|
||||||
</Border.Resources>
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,4,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="12" />
|
<ColumnDefinition Width="12" />
|
||||||
@@ -1472,7 +1528,7 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ItemsControl Grid.Column="0"
|
<ItemsControl Grid.Column="0"
|
||||||
ItemsSource="{Binding HemolysisRs485FlowPumpControls}"
|
ItemsSource="{Binding HemolysisRs485FlowPumpControls}"
|
||||||
ItemTemplate="{StaticResource HemolysisRs485PumpCardTemplate}">
|
ItemTemplate="{StaticResource ProjectRs485PumpCardTemplate}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<WrapPanel />
|
<WrapPanel />
|
||||||
@@ -1495,18 +1551,27 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Border.Style>
|
</Border.Style>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<DockPanel LastChildFill="False">
|
<Grid Margin="0,0,0,8">
|
||||||
<Button DockPanel.Dock="Right"
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="12" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource SectionTitleStyle}"
|
||||||
|
Text="{Binding SelectedItemTitle}"
|
||||||
|
TextTrimming="CharacterEllipsis" />
|
||||||
|
<Button Grid.Column="2"
|
||||||
MinWidth="112"
|
MinWidth="112"
|
||||||
MinHeight="32"
|
MinHeight="32"
|
||||||
Padding="12,5"
|
Padding="12,5"
|
||||||
Margin="12,0,0,8"
|
|
||||||
Click="OpenProjectInfoDialogButton_OnClick"
|
Click="OpenProjectInfoDialogButton_OnClick"
|
||||||
Background="#FFE3F6EF"
|
Background="#FFE3F6EF"
|
||||||
Foreground="{StaticResource HeaderBrush}"
|
Foreground="{StaticResource HeaderBrush}"
|
||||||
BorderBrush="#FF9CCBBF"
|
BorderBrush="#FF9CCBBF"
|
||||||
Content="查看项目说明" />
|
Content="查看项目说明" />
|
||||||
</DockPanel>
|
</Grid>
|
||||||
<Grid Margin="0,2,0,0">
|
<Grid Margin="0,2,0,0">
|
||||||
<StackPanel Margin="0,0,0,4" IsEnabled="{Binding CanModifySession}">
|
<StackPanel Margin="0,0,0,4" IsEnabled="{Binding CanModifySession}">
|
||||||
<Border Margin="0,0,0,16" Padding="0">
|
<Border Margin="0,0,0,16" Padding="0">
|
||||||
@@ -1983,13 +2048,21 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Margin="0,8,0,0">
|
<Grid Margin="0,4,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="12" />
|
<ColumnDefinition Width="12" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" Style="{StaticResource CaptionStyle}" Text="{Binding LatestAction}" TextWrapping="Wrap" />
|
<TextBlock Grid.Column="0" VerticalAlignment="Center" Style="{StaticResource CaptionStyle}" Text="{Binding LatestAction}" TextWrapping="Wrap" />
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
MinWidth="112"
|
||||||
|
Height="34"
|
||||||
|
Padding="12,4"
|
||||||
|
Command="{Binding ApplyResultCommand}"
|
||||||
|
Content="保存结果"
|
||||||
|
Background="#FF4D8C72"
|
||||||
|
IsEnabled="{Binding CanModifySession}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public partial class MainWindow : Window
|
|||||||
private readonly List<Button> _projectInspectionButtons = [];
|
private readonly List<Button> _projectInspectionButtons = [];
|
||||||
private object? _projectInspectionContent;
|
private object? _projectInspectionContent;
|
||||||
private object? _realtimeContent;
|
private object? _realtimeContent;
|
||||||
|
private object? _tightnessTestContent;
|
||||||
private object? _manualSupplementContent;
|
private object? _manualSupplementContent;
|
||||||
private object? _configurationContent;
|
private object? _configurationContent;
|
||||||
private object? _traceContent;
|
private object? _traceContent;
|
||||||
@@ -85,6 +86,7 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
_realtimeContent = ExtractTabContent(RealtimeDataTab);
|
_realtimeContent = ExtractTabContent(RealtimeDataTab);
|
||||||
_projectInspectionContent = ExtractTabContent(ProjectListTab);
|
_projectInspectionContent = ExtractTabContent(ProjectListTab);
|
||||||
|
_tightnessTestContent = ExtractTabContent(TightnessTestTab);
|
||||||
_manualSupplementContent = ExtractTabContent(ManualSupplementTab);
|
_manualSupplementContent = ExtractTabContent(ManualSupplementTab);
|
||||||
_configurationContent = ExtractTabContent(ConfigurationTab);
|
_configurationContent = ExtractTabContent(ConfigurationTab);
|
||||||
_traceContent = ExtractTabContent(TraceTab);
|
_traceContent = ExtractTabContent(TraceTab);
|
||||||
@@ -126,6 +128,7 @@ public partial class MainWindow : Window
|
|||||||
_projectInspectionButtons.Add(button);
|
_projectInspectionButtons.Add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddNavigationButton("密合性", new NavigationTarget(NavigationPage.TightnessTest, null));
|
||||||
AddNavigationButton("项目补充", new NavigationTarget(NavigationPage.ManualSupplement, null));
|
AddNavigationButton("项目补充", new NavigationTarget(NavigationPage.ManualSupplement, null));
|
||||||
AddNavigationButton("配置", new NavigationTarget(NavigationPage.Configuration, null));
|
AddNavigationButton("配置", new NavigationTarget(NavigationPage.Configuration, null));
|
||||||
AddNavigationButton("追溯", new NavigationTarget(NavigationPage.Trace, null));
|
AddNavigationButton("追溯", new NavigationTarget(NavigationPage.Trace, null));
|
||||||
@@ -188,9 +191,19 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
_currentPage = page;
|
_currentPage = page;
|
||||||
_currentProjectItem = null;
|
_currentProjectItem = null;
|
||||||
|
|
||||||
|
if (page == NavigationPage.TightnessTest
|
||||||
|
&& DataContext is MainViewModel viewModel
|
||||||
|
&& viewModel.TightnessInspectionItem is not null
|
||||||
|
&& !ReferenceEquals(viewModel.SelectedItem, viewModel.TightnessInspectionItem))
|
||||||
|
{
|
||||||
|
viewModel.SelectedItem = viewModel.TightnessInspectionItem;
|
||||||
|
}
|
||||||
|
|
||||||
MainContentHost.Content = page switch
|
MainContentHost.Content = page switch
|
||||||
{
|
{
|
||||||
NavigationPage.RealtimeData => _realtimeContent,
|
NavigationPage.RealtimeData => _realtimeContent,
|
||||||
|
NavigationPage.TightnessTest => _tightnessTestContent,
|
||||||
NavigationPage.ManualSupplement => _manualSupplementContent,
|
NavigationPage.ManualSupplement => _manualSupplementContent,
|
||||||
NavigationPage.Configuration => _configurationContent,
|
NavigationPage.Configuration => _configurationContent,
|
||||||
NavigationPage.Trace => _traceContent,
|
NavigationPage.Trace => _traceContent,
|
||||||
@@ -254,6 +267,7 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
RealtimeData,
|
RealtimeData,
|
||||||
ProjectItem,
|
ProjectItem,
|
||||||
|
TightnessTest,
|
||||||
ManualSupplement,
|
ManualSupplement,
|
||||||
Configuration,
|
Configuration,
|
||||||
Trace
|
Trace
|
||||||
|
|||||||
@@ -109,6 +109,18 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool isBatchSelected;
|
private bool isBatchSelected;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool isFlowStabilizationEnabled;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private DateTime lastFlowStabilizationAdjustmentUtc = DateTime.MinValue;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private int flowStabilizationRawSetpoint;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string flowStabilizationStatusText = "稳流未启用";
|
||||||
|
|
||||||
public string StartAddressDisplay => $"M{StartAddress}";
|
public string StartAddressDisplay => $"M{StartAddress}";
|
||||||
public string FlowAddressDisplay => FlowAddress.HasValue ? $"D{FlowAddress.Value}" : "-";
|
public string FlowAddressDisplay => FlowAddress.HasValue ? $"D{FlowAddress.Value}" : "-";
|
||||||
public bool HasFlowTelemetry => FlowAddress.HasValue;
|
public bool HasFlowTelemetry => FlowAddress.HasValue;
|
||||||
@@ -224,6 +236,15 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
: "未配置流量换算系数";
|
: "未配置流量换算系数";
|
||||||
public string Rs485ReadActionText => IsRs485Busy ? "处理中" : "读取";
|
public string Rs485ReadActionText => IsRs485Busy ? "处理中" : "读取";
|
||||||
public string Rs485WriteActionText => IsRs485Busy ? "处理中" : "写入";
|
public string Rs485WriteActionText => IsRs485Busy ? "处理中" : "写入";
|
||||||
|
public bool CanUseFlowStabilization => SupportsRs485DirectControl && Key != "KinkResistancePump";
|
||||||
|
public string FlowStabilizationToggleHint => CanUseFlowStabilization
|
||||||
|
? "按实际流量小步调节泵速"
|
||||||
|
: "抗扭结采样要求保持固定转速";
|
||||||
|
public string FlowStabilizationStateText => !CanUseFlowStabilization
|
||||||
|
? "固定转速"
|
||||||
|
: IsFlowStabilizationEnabled
|
||||||
|
? FlowStabilizationStatusText
|
||||||
|
: "稳流未启用";
|
||||||
public string SetpointStatusForeground => ResolveSetpointStatusForeground();
|
public string SetpointStatusForeground => ResolveSetpointStatusForeground();
|
||||||
public string SetpointStatusBackground => ResolveSetpointStatusBackground();
|
public string SetpointStatusBackground => ResolveSetpointStatusBackground();
|
||||||
|
|
||||||
@@ -241,6 +262,7 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
OnPropertyChanged(nameof(CanToggleRs485Action));
|
OnPropertyChanged(nameof(CanToggleRs485Action));
|
||||||
OnPropertyChanged(nameof(ToggleActionHint));
|
OnPropertyChanged(nameof(ToggleActionHint));
|
||||||
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnFlowValueChanged(double value)
|
partial void OnFlowValueChanged(double value)
|
||||||
@@ -251,6 +273,7 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
OnPropertyChanged(nameof(StateHint));
|
OnPropertyChanged(nameof(StateHint));
|
||||||
OnPropertyChanged(nameof(IndicatorColor));
|
OnPropertyChanged(nameof(IndicatorColor));
|
||||||
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnStateAvailableChanged(bool value)
|
partial void OnStateAvailableChanged(bool value)
|
||||||
@@ -260,6 +283,7 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
OnPropertyChanged(nameof(IndicatorColor));
|
OnPropertyChanged(nameof(IndicatorColor));
|
||||||
OnPropertyChanged(nameof(ToggleButtonText));
|
OnPropertyChanged(nameof(ToggleButtonText));
|
||||||
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnFlowAvailableChanged(bool value)
|
partial void OnFlowAvailableChanged(bool value)
|
||||||
@@ -270,6 +294,7 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
OnPropertyChanged(nameof(StateHint));
|
OnPropertyChanged(nameof(StateHint));
|
||||||
OnPropertyChanged(nameof(IndicatorColor));
|
OnPropertyChanged(nameof(IndicatorColor));
|
||||||
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
OnPropertyChanged(nameof(CardPrimaryDisplay));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnRs485EnabledChanged(bool value)
|
partial void OnRs485EnabledChanged(bool value)
|
||||||
@@ -280,11 +305,33 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
OnPropertyChanged(nameof(CalibrationStatusText));
|
OnPropertyChanged(nameof(CalibrationStatusText));
|
||||||
OnPropertyChanged(nameof(SetpointReadbackDisplay));
|
OnPropertyChanged(nameof(SetpointReadbackDisplay));
|
||||||
OnPropertyChanged(nameof(RawSetpointDisplay));
|
OnPropertyChanged(nameof(RawSetpointDisplay));
|
||||||
|
OnPropertyChanged(nameof(CanUseFlowStabilization));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationToggleHint));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnRs485SlaveAddressChanged(byte value) => OnPropertyChanged(nameof(Rs485SlaveAddressDisplay));
|
partial void OnRs485SlaveAddressChanged(byte value) => OnPropertyChanged(nameof(Rs485SlaveAddressDisplay));
|
||||||
|
|
||||||
partial void OnRs485MotorControlRegisterChanged(ushort value) => OnPropertyChanged(nameof(SupportsRs485DirectControl));
|
partial void OnRs485MotorControlRegisterChanged(ushort value)
|
||||||
|
{
|
||||||
|
OnPropertyChanged(nameof(SupportsRs485DirectControl));
|
||||||
|
OnPropertyChanged(nameof(CanUseFlowStabilization));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationToggleHint));
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnIsFlowStabilizationEnabledChanged(bool value)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
FlowStabilizationStatusText = "稳流未启用";
|
||||||
|
}
|
||||||
|
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnFlowStabilizationStatusTextChanged(string value) =>
|
||||||
|
OnPropertyChanged(nameof(FlowStabilizationStateText));
|
||||||
|
|
||||||
partial void OnRs485RawPerLitrePerMinuteChanged(double value)
|
partial void OnRs485RawPerLitrePerMinuteChanged(double value)
|
||||||
{
|
{
|
||||||
@@ -327,6 +374,7 @@ public partial class PumpControlChannel : ObservableObject
|
|||||||
ConfirmedSetpointAvailable = false;
|
ConfirmedSetpointAvailable = false;
|
||||||
ConfirmedRawSetpointValue = 0;
|
ConfirmedRawSetpointValue = 0;
|
||||||
ConfirmedSetpointFlowValue = 0;
|
ConfirmedSetpointFlowValue = 0;
|
||||||
|
FlowStabilizationRawSetpoint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnSetpointAvailableChanged(bool value)
|
partial void OnSetpointAvailableChanged(bool value)
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ public sealed class Rs485PumpBindingSettings
|
|||||||
public double RawPerLitrePerMinute { get; set; }
|
public double RawPerLitrePerMinute { get; set; }
|
||||||
public double RawOffset { get; set; }
|
public double RawOffset { get; set; }
|
||||||
public double MinFlowLpm { get; set; }
|
public double MinFlowLpm { get; set; }
|
||||||
public double MaxFlowLpm { get; set; } = 7.0;
|
public double MaxFlowLpm { get; set; } = 20.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public interface IRs485PumpFlowService
|
|||||||
Rs485PumpFlowOperationResult ReadPumpPreset(Rs485PumpFlowRequest request);
|
Rs485PumpFlowOperationResult ReadPumpPreset(Rs485PumpFlowRequest request);
|
||||||
IReadOnlyList<Rs485PumpRuntimeSnapshot> ReadPumpRuntimeStates(IReadOnlyList<Rs485PumpFlowRequest> requests);
|
IReadOnlyList<Rs485PumpRuntimeSnapshot> ReadPumpRuntimeStates(IReadOnlyList<Rs485PumpFlowRequest> requests);
|
||||||
Rs485PumpFlowOperationResult WritePumpPreset(Rs485PumpFlowRequest request, ushort rawForwardSpeed);
|
Rs485PumpFlowOperationResult WritePumpPreset(Rs485PumpFlowRequest request, ushort rawForwardSpeed);
|
||||||
|
Rs485PumpFlowOperationResult WritePumpMotorCommand(Rs485PumpFlowRequest request, short rawMotorSpeed);
|
||||||
Rs485PumpFlowOperationResult StartPump(Rs485PumpFlowRequest request, short rawMotorSpeed);
|
Rs485PumpFlowOperationResult StartPump(Rs485PumpFlowRequest request, short rawMotorSpeed);
|
||||||
Rs485PumpFlowOperationResult StopPump(Rs485PumpFlowRequest request);
|
Rs485PumpFlowOperationResult StopPump(Rs485PumpFlowRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,6 +278,48 @@ public sealed class Rs485PumpFlowService : IRs485PumpFlowService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rs485PumpFlowOperationResult WritePumpMotorCommand(Rs485PumpFlowRequest request, short rawMotorSpeed)
|
||||||
|
{
|
||||||
|
return Execute(request, master =>
|
||||||
|
{
|
||||||
|
var slave = request.PumpSettings.SlaveAddress;
|
||||||
|
if (rawMotorSpeed <= 0)
|
||||||
|
{
|
||||||
|
return Failure("RS485 稳流调节失败:控制值必须大于 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryWriteSignedRegister(master, slave, request.PumpSettings.MotorControlRegister, rawMotorSpeed, out var writeError))
|
||||||
|
{
|
||||||
|
return Failure($"RS485 稳流调节失败:{writeError}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PostCommandVerifyDelayMs > 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(PostCommandVerifyDelayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryReadRegister(master, slave, request.PumpSettings.MotorControlRegister, out var motorCommandReadback, out _)
|
||||||
|
&& motorCommandReadback != unchecked((ushort)rawMotorSpeed))
|
||||||
|
{
|
||||||
|
return Failure($"RS485 稳流调节失败:控制寄存器回读 {motorCommandReadback},目标 {rawMotorSpeed}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort? runStatus = null;
|
||||||
|
if (TryReadRegister(master, slave, request.PumpSettings.RunStatusRegister, out var runStatusValue, out _))
|
||||||
|
{
|
||||||
|
runStatus = runStatusValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Rs485PumpFlowOperationResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
Message = $"RS485 稳流调节成功,控制值 {rawMotorSpeed}",
|
||||||
|
RunStatus = runStatus,
|
||||||
|
RawForwardSpeed = (ushort)rawMotorSpeed
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public Rs485PumpFlowOperationResult StopPump(Rs485PumpFlowRequest request)
|
public Rs485PumpFlowOperationResult StopPump(Rs485PumpFlowRequest request)
|
||||||
{
|
{
|
||||||
return Execute(request, master =>
|
return Execute(request, master =>
|
||||||
|
|||||||
@@ -41,8 +41,12 @@ public partial class MainViewModel
|
|||||||
private const double DefaultRs485RawPerLitrePerMinute = 100d;
|
private const double DefaultRs485RawPerLitrePerMinute = 100d;
|
||||||
private const double DefaultRs485RawOffset = 0d;
|
private const double DefaultRs485RawOffset = 0d;
|
||||||
private const int MaxRs485MotorCommand = short.MaxValue;
|
private const int MaxRs485MotorCommand = short.MaxValue;
|
||||||
|
private const double FlowStabilizationDeadbandLpm = 0.05d;
|
||||||
|
private const int FlowStabilizationMaxRawStep = 5;
|
||||||
|
private const double FlowStabilizationMaxRelativeTrim = 0.20d;
|
||||||
private const string PressureDropRs485PumpKey = "PressureDropPump";
|
private const string PressureDropRs485PumpKey = "PressureDropPump";
|
||||||
private const string KinkResistanceRs485PumpKey = "KinkResistancePump";
|
private const string KinkResistanceRs485PumpKey = "KinkResistancePump";
|
||||||
|
private static readonly TimeSpan FlowStabilizationAdjustmentInterval = TimeSpan.FromSeconds(2);
|
||||||
private static readonly string[] HemolysisRs485PumpKeys =
|
private static readonly string[] HemolysisRs485PumpKeys =
|
||||||
[
|
[
|
||||||
"HemolysisDrainageSinglePump",
|
"HemolysisDrainageSinglePump",
|
||||||
@@ -220,7 +224,7 @@ public partial class MainViewModel
|
|||||||
RawPerLitrePerMinute = DefaultRs485RawPerLitrePerMinute,
|
RawPerLitrePerMinute = DefaultRs485RawPerLitrePerMinute,
|
||||||
RawOffset = DefaultRs485RawOffset,
|
RawOffset = DefaultRs485RawOffset,
|
||||||
MinFlowLpm = 0,
|
MinFlowLpm = 0,
|
||||||
MaxFlowLpm = 7.0
|
MaxFlowLpm = 20.0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +253,7 @@ public partial class MainViewModel
|
|||||||
? binding.RawOffset
|
? binding.RawOffset
|
||||||
: DefaultRs485RawOffset;
|
: DefaultRs485RawOffset;
|
||||||
pump.Rs485MinFlowLpm = binding.MinFlowLpm;
|
pump.Rs485MinFlowLpm = binding.MinFlowLpm;
|
||||||
pump.Rs485MaxFlowLpm = binding.MaxFlowLpm <= 0 ? Math.Max(RatedMaxFlow, 7.0) : binding.MaxFlowLpm;
|
pump.Rs485MaxFlowLpm = binding.MaxFlowLpm <= 0 ? Math.Max(RatedMaxFlow, 20.0) : binding.MaxFlowLpm;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(pump.PendingSetpointText))
|
if (string.IsNullOrWhiteSpace(pump.PendingSetpointText))
|
||||||
{
|
{
|
||||||
@@ -552,6 +556,132 @@ public partial class MainViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task MaintainRs485FlowStabilizationAsync()
|
||||||
|
{
|
||||||
|
var adjustablePumps = ActiveRs485FlowPumpControls
|
||||||
|
.Where(ShouldMaintainFlowStabilization)
|
||||||
|
.OrderBy(item => item.Rs485SlaveAddress)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var pump in adjustablePumps)
|
||||||
|
{
|
||||||
|
await TryAdjustRs485FlowStabilizationAsync(pump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ShouldMaintainFlowStabilization(PumpControlChannel pump)
|
||||||
|
{
|
||||||
|
if (!pump.IsFlowStabilizationEnabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pump.CanUseFlowStabilization)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "当前项目要求固定转速";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pump.IsRs485Busy)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "等待当前 RS485 操作完成";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pump.IsRunning || pump.PendingRs485RunningState == false)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "等待泵运行";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pump.FlowAvailable)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "等待流量反馈";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pump.ConfirmedSetpointAvailable || pump.ConfirmedSetpointFlowValue <= 0)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "等待确认目标流量";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DateTime.UtcNow - pump.LastFlowStabilizationAdjustmentUtc < FlowStabilizationAdjustmentInterval)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TryAdjustRs485FlowStabilizationAsync(PumpControlChannel pump)
|
||||||
|
{
|
||||||
|
var targetFlow = pump.ConfirmedSetpointFlowValue;
|
||||||
|
var flowError = targetFlow - pump.FlowValue;
|
||||||
|
if (Math.Abs(flowError) <= FlowStabilizationDeadbandLpm)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = $"稳流保持:目标 {targetFlow:F2} / 当前 {pump.FlowValue:F2} L/min";
|
||||||
|
pump.LastFlowStabilizationAdjustmentUtc = DateTime.UtcNow;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetRaw = pump.ConfirmedRawSetpointValue > 0
|
||||||
|
? pump.ConfirmedRawSetpointValue
|
||||||
|
: ConvertFlowToRawSpeed(pump, targetFlow);
|
||||||
|
if (targetRaw <= 0)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = "目标流量换算值无效";
|
||||||
|
pump.LastFlowStabilizationAdjustmentUtc = DateTime.UtcNow;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentRaw = pump.FlowStabilizationRawSetpoint > 0
|
||||||
|
? pump.FlowStabilizationRawSetpoint
|
||||||
|
: pump.RawSetpointValue > 0
|
||||||
|
? pump.RawSetpointValue
|
||||||
|
: targetRaw;
|
||||||
|
var maxTrim = Math.Max(FlowStabilizationMaxRawStep, (int)Math.Round(targetRaw * FlowStabilizationMaxRelativeTrim, MidpointRounding.AwayFromZero));
|
||||||
|
var minRaw = Math.Max(1, targetRaw - maxTrim);
|
||||||
|
var maxRaw = Math.Min(MaxRs485MotorCommand, targetRaw + maxTrim);
|
||||||
|
var rawStep = Math.Sign(flowError) * FlowStabilizationMaxRawStep;
|
||||||
|
var nextRaw = Math.Clamp(currentRaw + rawStep, minRaw, maxRaw);
|
||||||
|
|
||||||
|
if (nextRaw == currentRaw)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = $"稳流已到调节限幅:目标 {targetFlow:F2} / 当前 {pump.FlowValue:F2} L/min";
|
||||||
|
pump.LastFlowStabilizationAdjustmentUtc = DateTime.UtcNow;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryBeginRs485PumpOperation(pump, "稳流调节"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = BuildRs485Request(pump);
|
||||||
|
var result = await Task.Run(() => _rs485PumpFlowService.WritePumpMotorCommand(request, (short)nextRaw));
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
pump.FlowStabilizationStatusText = result.Message;
|
||||||
|
Rs485StatusText = result.Message;
|
||||||
|
TraceEvents.Insert(0, NewTrace("RS485 稳流调节失败", $"{pump.Name} / {result.Message}"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pump.FlowStabilizationRawSetpoint = nextRaw;
|
||||||
|
CacheResolvedRs485Setpoint(pump, nextRaw);
|
||||||
|
ApplyPostCommandPumpState(pump, result, expectedRunning: true);
|
||||||
|
pump.FlowStabilizationStatusText = $"稳流调节:目标 {targetFlow:F2} / 当前 {pump.FlowValue:F2} L/min / 控制值 {nextRaw}";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
pump.LastFlowStabilizationAdjustmentUtc = DateTime.UtcNow;
|
||||||
|
EndRs485PumpOperation(pump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RaiseRs485CalibrationSummaryChanges()
|
private void RaiseRs485CalibrationSummaryChanges()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(Rs485EnabledPumpCount));
|
OnPropertyChanged(nameof(Rs485EnabledPumpCount));
|
||||||
@@ -1349,6 +1479,7 @@ public partial class MainViewModel
|
|||||||
pump.ConfirmedSetpointAvailable = true;
|
pump.ConfirmedSetpointAvailable = true;
|
||||||
pump.ConfirmedRawSetpointValue = rawMotorSpeed;
|
pump.ConfirmedRawSetpointValue = rawMotorSpeed;
|
||||||
pump.ConfirmedSetpointFlowValue = flowLpm;
|
pump.ConfirmedSetpointFlowValue = flowLpm;
|
||||||
|
pump.FlowStabilizationRawSetpoint = rawMotorSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryBeginRs485PumpOperation(PumpControlChannel pump, string operationName)
|
private bool TryBeginRs485PumpOperation(PumpControlChannel pump, string operationName)
|
||||||
|
|||||||
@@ -423,6 +423,8 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
public bool HasFilteredItems => !FilteredItemsView.IsEmpty;
|
public bool HasFilteredItems => !FilteredItemsView.IsEmpty;
|
||||||
public bool HasManualSupplementItems => !ManualSupplementItemsView.IsEmpty;
|
public bool HasManualSupplementItems => !ManualSupplementItemsView.IsEmpty;
|
||||||
public bool HasSelectedItem => SelectedItem is not null;
|
public bool HasSelectedItem => SelectedItem is not null;
|
||||||
|
public InspectionItem? TightnessInspectionItem => InspectionItems.FirstOrDefault(IsTightnessInspectionItem);
|
||||||
|
public bool HasTightnessInspectionItem => TightnessInspectionItem is not null;
|
||||||
public IEnumerable<DeviceChannel> FlowSensorChannels => Channels.Where(IsFlowSensorChannel);
|
public IEnumerable<DeviceChannel> FlowSensorChannels => Channels.Where(IsFlowSensorChannel);
|
||||||
public IEnumerable<DeviceChannel> OtherChannels => Channels.Where(channel => !IsFlowSensorChannel(channel));
|
public IEnumerable<DeviceChannel> OtherChannels => Channels.Where(channel => !IsFlowSensorChannel(channel));
|
||||||
public bool IsTelemetryOnline => _isTelemetryOnline;
|
public bool IsTelemetryOnline => _isTelemetryOnline;
|
||||||
@@ -544,7 +546,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
public bool HasItemSearchText => !string.IsNullOrWhiteSpace(ItemSearchText);
|
public bool HasItemSearchText => !string.IsNullOrWhiteSpace(ItemSearchText);
|
||||||
public int RealtimeMonitorCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.RealtimeMonitor);
|
public int RealtimeMonitorCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.RealtimeMonitor);
|
||||||
public int RealtimeAssistCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.RealtimeAssist);
|
public int RealtimeAssistCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.RealtimeAssist);
|
||||||
public int ManualEntryCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.ManualEntry);
|
public int ManualEntryCount => InspectionItems.Count(item => item.CaptureMode == InspectionItemCaptureMode.ManualEntry && !IsTightnessInspectionItem(item));
|
||||||
public string SelectedItemCaptureModeText => SelectedItem?.CaptureModeText ?? "未选择";
|
public string SelectedItemCaptureModeText => SelectedItem?.CaptureModeText ?? "未选择";
|
||||||
public string SelectedItemMeasurementSource => SelectedItem?.MeasurementSource ?? "-";
|
public string SelectedItemMeasurementSource => SelectedItem?.MeasurementSource ?? "-";
|
||||||
public bool SelectedItemUsesRealtimeValue => SelectedItem?.CaptureMode == InspectionItemCaptureMode.RealtimeMonitor;
|
public bool SelectedItemUsesRealtimeValue => SelectedItem?.CaptureMode == InspectionItemCaptureMode.RealtimeMonitor;
|
||||||
@@ -566,6 +568,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
public string KinkResistanceMandrelDiameterDisplay => $"圆角模板直径:{Math.Max(KinkResistanceOuterDiameter, 0d) * 4d:F1} mm(外径 {KinkResistanceOuterDiameter:F1} mm × 4)";
|
public string KinkResistanceMandrelDiameterDisplay => $"圆角模板直径:{Math.Max(KinkResistanceOuterDiameter, 0d) * 4d:F1} mm(外径 {KinkResistanceOuterDiameter:F1} mm × 4)";
|
||||||
public bool IsPressureDropSelected => SelectedItem?.Clause == "4.3.1";
|
public bool IsPressureDropSelected => SelectedItem?.Clause == "4.3.1";
|
||||||
public string PressureDropSamplingSummary => BuildPressureDropSamplingSummary();
|
public string PressureDropSamplingSummary => BuildPressureDropSamplingSummary();
|
||||||
|
public bool IsTightnessSelected => SelectedItem is not null && IsTightnessInspectionItem(SelectedItem);
|
||||||
public bool IsKinkResistanceSelected => SelectedItem?.Clause == "4.2.3";
|
public bool IsKinkResistanceSelected => SelectedItem?.Clause == "4.2.3";
|
||||||
public string KinkResistanceSamplingSummary => BuildKinkResistanceSamplingSummary();
|
public string KinkResistanceSamplingSummary => BuildKinkResistanceSamplingSummary();
|
||||||
public bool IsAntiCollapseSelected => SelectedItem?.Clause == "4.3.2";
|
public bool IsAntiCollapseSelected => SelectedItem?.Clause == "4.3.2";
|
||||||
@@ -692,6 +695,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
OnPropertyChanged(nameof(SelectedItemUsesRealtimeValue));
|
OnPropertyChanged(nameof(SelectedItemUsesRealtimeValue));
|
||||||
OnPropertyChanged(nameof(IsPressureDropSelected));
|
OnPropertyChanged(nameof(IsPressureDropSelected));
|
||||||
OnPropertyChanged(nameof(PressureDropSamplingSummary));
|
OnPropertyChanged(nameof(PressureDropSamplingSummary));
|
||||||
|
OnPropertyChanged(nameof(IsTightnessSelected));
|
||||||
OnPropertyChanged(nameof(IsKinkResistanceSelected));
|
OnPropertyChanged(nameof(IsKinkResistanceSelected));
|
||||||
OnPropertyChanged(nameof(KinkResistanceFlowPointDisplay));
|
OnPropertyChanged(nameof(KinkResistanceFlowPointDisplay));
|
||||||
OnPropertyChanged(nameof(KinkResistanceMandrelDiameterDisplay));
|
OnPropertyChanged(nameof(KinkResistanceMandrelDiameterDisplay));
|
||||||
@@ -1408,6 +1412,7 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
var snapshot = await Task.Run(_telemetryService.UpdateChannels);
|
var snapshot = await Task.Run(_telemetryService.UpdateChannels);
|
||||||
ApplyTelemetrySnapshot(snapshot);
|
ApplyTelemetrySnapshot(snapshot);
|
||||||
await RefreshRs485RuntimeStateSilentlyAsync();
|
await RefreshRs485RuntimeStateSilentlyAsync();
|
||||||
|
await MaintainRs485FlowStabilizationAsync();
|
||||||
_lastTelemetryRefreshFailureMessage = string.Empty;
|
_lastTelemetryRefreshFailureMessage = string.Empty;
|
||||||
RefreshTelemetryPanel();
|
RefreshTelemetryPanel();
|
||||||
RefreshDeviceStatus();
|
RefreshDeviceStatus();
|
||||||
@@ -1635,7 +1640,8 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
var projectCheckItems = FilteredItemsView.Cast<InspectionItem>().ToList();
|
var projectCheckItems = FilteredItemsView.Cast<InspectionItem>().ToList();
|
||||||
var manualSupplementItems = ManualSupplementItemsView.Cast<InspectionItem>().ToList();
|
var manualSupplementItems = ManualSupplementItemsView.Cast<InspectionItem>().ToList();
|
||||||
var selectedItemStillVisible = SelectedItem is not null
|
var selectedItemStillVisible = SelectedItem is not null
|
||||||
&& ((SelectedItem.CaptureMode == InspectionItemCaptureMode.ManualEntry && manualSupplementItems.Contains(SelectedItem))
|
&& ((IsTightnessInspectionItem(SelectedItem))
|
||||||
|
|| (SelectedItem.CaptureMode == InspectionItemCaptureMode.ManualEntry && manualSupplementItems.Contains(SelectedItem))
|
||||||
|| (SelectedItem.CaptureMode != InspectionItemCaptureMode.ManualEntry && projectCheckItems.Contains(SelectedItem)));
|
|| (SelectedItem.CaptureMode != InspectionItemCaptureMode.ManualEntry && projectCheckItems.Contains(SelectedItem)));
|
||||||
|
|
||||||
if (selectedItemStillVisible)
|
if (selectedItemStillVisible)
|
||||||
@@ -2132,8 +2138,13 @@ public partial class MainViewModel : ObservableObject, IDisposable
|
|||||||
private bool MatchesManualSupplementItem(object item) =>
|
private bool MatchesManualSupplementItem(object item) =>
|
||||||
item is InspectionItem inspectionItem
|
item is InspectionItem inspectionItem
|
||||||
&& inspectionItem.CaptureMode == InspectionItemCaptureMode.ManualEntry
|
&& inspectionItem.CaptureMode == InspectionItemCaptureMode.ManualEntry
|
||||||
|
&& !IsTightnessInspectionItem(inspectionItem)
|
||||||
&& MatchesItemSearch(inspectionItem);
|
&& MatchesItemSearch(inspectionItem);
|
||||||
|
|
||||||
|
private static bool IsTightnessInspectionItem(InspectionItem item) =>
|
||||||
|
string.Equals(item.Clause, "4.2.1", StringComparison.Ordinal)
|
||||||
|
&& string.Equals(item.Item, "血液通道密合性", StringComparison.Ordinal);
|
||||||
|
|
||||||
private bool MatchesItemSearch(InspectionItem item)
|
private bool MatchesItemSearch(InspectionItem item)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(ItemSearchText))
|
if (string.IsNullOrWhiteSpace(ItemSearchText))
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "RecirculationMainPump",
|
"PumpKey": "RecirculationMainPump",
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "RecirculationReturnPump",
|
"PumpKey": "RecirculationReturnPump",
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "RecirculationDrainagePump",
|
"PumpKey": "RecirculationDrainagePump",
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "KinkResistancePump",
|
"PumpKey": "KinkResistancePump",
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "HemolysisDrainageSinglePump",
|
"PumpKey": "HemolysisDrainageSinglePump",
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "HemolysisReturnSinglePump",
|
"PumpKey": "HemolysisReturnSinglePump",
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PumpKey": "HemolysisDualLumenPump",
|
"PumpKey": "HemolysisDualLumenPump",
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
"RawPerLitrePerMinute": 100,
|
"RawPerLitrePerMinute": 100,
|
||||||
"RawOffset": 0,
|
"RawOffset": 0,
|
||||||
"MinFlowLpm": 0,
|
"MinFlowLpm": 0,
|
||||||
"MaxFlowLpm": 7
|
"MaxFlowLpm": 20
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user