初始化

This commit is contained in:
GukSang.Jin
2026-03-10 17:35:25 +08:00
parent bfa418967f
commit 50917b2e38
3 changed files with 196 additions and 149 deletions

View File

@@ -41,85 +41,12 @@
</Border> </Border>
<Grid Grid.Row="2"> <Grid Grid.Row="2">
<Grid.ColumnDefinitions> <Border Style="{StaticResource CardBorderStyle}" Margin="0">
<ColumnDefinition Width="300" />
<ColumnDefinition Width="12" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Auto">
<StackPanel>
<Border Style="{StaticResource CardBorderStyle}" Margin="0,0,0,12">
<StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x68C0;&#x6D4B;&#x603B;&#x89C8;" />
<UniformGrid Columns="1">
<Border Margin="0,0,0,8" Padding="14" Background="#FFE7F5F3" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5408;&#x683C;&#x7387;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding ComplianceDisplay}" />
</StackPanel>
</Border>
<Border Margin="0,0,0,8" Padding="14" Background="#FFF6EFE2" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x538B;&#x5DEE;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding DeltaPressureDisplay}" />
</StackPanel>
</Border>
<Border Margin="0,0,0,8" Padding="14" Background="#FFE9EFF9" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5408;&#x683C;&#x9879;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding QualifiedCount}" />
</StackPanel>
</Border>
<Border Padding="14" Background="#FFFDEBE7" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x9884;&#x8B66;/&#x4E0D;&#x5408;&#x683C;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding WarningCount}" />
</StackPanel>
</Border>
</UniformGrid>
</StackPanel>
</Border>
<Border Style="{StaticResource CardBorderStyle}">
<StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x6D41;&#x91CF;&#x5FEB;&#x7167;" />
<Border Margin="0,0,0,8" Padding="12" Background="#FFEAF6F3" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x4E3B;&#x6CF5;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding PumpFlowDisplay}" />
</StackPanel>
</Border>
<Border Margin="0,0,0,8" Padding="12" Background="#FFEFF1FA" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F15;&#x6D41;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding DrainageFlowDisplay}" />
</StackPanel>
</Border>
<Border Padding="12" Background="#FFFDF0E5" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x56DE;&#x8F93;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding ReturnFlowDisplay}" />
</StackPanel>
</Border>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
<Border Grid.Column="2" Style="{StaticResource CardBorderStyle}" Margin="0">
<TabControl> <TabControl>
<TabItem Header="&#x9879;&#x76EE;&#x68C0;&#x6D4B;"> <TabItem Header="&#x9879;&#x76EE;&#x68C0;&#x6D4B;">
<Grid Margin="0,6,0,0"> <ScrollViewer Margin="0,6,0,0" VerticalScrollBarVisibility="Auto" CanContentScroll="False">
<Grid.RowDefinitions> <StackPanel>
<RowDefinition Height="Auto" /> <Border Style="{StaticResource CardBorderStyle}">
<RowDefinition Height="Auto" />
<RowDefinition Height="280" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Style="{StaticResource CardBorderStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x68C0;&#x7D22;&#x4E0E;&#x91C7;&#x96C6;&#x7B56;&#x7565;" /> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x68C0;&#x7D22;&#x4E0E;&#x91C7;&#x96C6;&#x7B56;&#x7565;" />
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x6839;&#x636E; YY 0948-2025 &#x5C06;&#x9879;&#x76EE;&#x533A;&#x5206;&#x4E3A;&#x201C;&#x5B9E;&#x65F6;&#x76D1;&#x63A7;&#x201D;&#x201C;&#x5B9E;&#x65F6;&#x663E;&#x793A;+&#x624B;&#x52A8;&#x5F55;&#x5165;&#x201D;&#x548C;&#x201C;&#x624B;&#x52A8;&#x5F55;&#x5165;&#x201D;&#x4E09;&#x7C7B;&#x3002;" TextWrapping="Wrap" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x6839;&#x636E; YY 0948-2025 &#x5C06;&#x9879;&#x76EE;&#x533A;&#x5206;&#x4E3A;&#x201C;&#x5B9E;&#x65F6;&#x76D1;&#x63A7;&#x201D;&#x201C;&#x5B9E;&#x65F6;&#x663E;&#x793A;+&#x624B;&#x52A8;&#x5F55;&#x5165;&#x201D;&#x548C;&#x201C;&#x624B;&#x52A8;&#x5F55;&#x5165;&#x201D;&#x4E09;&#x7C7B;&#x3002;" TextWrapping="Wrap" />
@@ -158,7 +85,7 @@
</StackPanel> </StackPanel>
</Border> </Border>
<UniformGrid Grid.Row="1" Columns="3" Margin="0,0,0,12"> <UniformGrid Columns="3" Margin="0,0,0,12">
<Border Margin="0,0,8,8" Padding="14" Background="#FFE7F5F3" CornerRadius="14"> <Border Margin="0,0,8,8" Padding="14" Background="#FFE7F5F3" CornerRadius="14">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5B9E;&#x65F6;&#x76D1;&#x63A7;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5B9E;&#x65F6;&#x76D1;&#x63A7;" />
@@ -182,7 +109,7 @@
</Border> </Border>
</UniformGrid> </UniformGrid>
<Border Grid.Row="2" Style="{StaticResource CardBorderStyle}"> <Border Style="{StaticResource CardBorderStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x6E05;&#x5355;" /> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x6E05;&#x5355;" />
<DataGrid Margin="0,4,0,0" <DataGrid Margin="0,4,0,0"
@@ -194,6 +121,7 @@
CanUserDeleteRows="False" CanUserDeleteRows="False"
SelectionMode="Single" SelectionMode="Single"
SelectionUnit="FullRow" SelectionUnit="FullRow"
Height="280"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
VirtualizingPanel.ScrollUnit="Pixel"> VirtualizingPanel.ScrollUnit="Pixel">
<DataGrid.Columns> <DataGrid.Columns>
@@ -224,7 +152,7 @@
</StackPanel> </StackPanel>
</Border> </Border>
<UniformGrid Grid.Row="3" Columns="4" Margin="0,0,0,12"> <UniformGrid Columns="4" Margin="0,0,0,12">
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"> <Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F53;&#x524D;&#x9879;&#x76EE;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F53;&#x524D;&#x9879;&#x76EE;" />
@@ -252,14 +180,7 @@
</Border> </Border>
</UniformGrid> </UniformGrid>
<Border Grid.Row="4" Style="{StaticResource CardBorderStyle}" Margin="0"> <Border Style="{StaticResource CardBorderStyle}" Margin="0">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Bottom" Margin="0,8,0,0">
<Button Command="{Binding SelectPreviousItemCommand}" Content="&#x4E0A;&#x4E00;&#x9879;" Background="#FF6B8791" />
<Button Command="{Binding SelectNextItemCommand}" Content="&#x4E0B;&#x4E00;&#x9879;" Background="#FF6B8791" />
<Button Command="{Binding ApplyResultCommand}" Content="&#x4FDD;&#x5B58;" />
</WrapPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" CanContentScroll="True">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x8BE6;&#x60C5;&#x4E0E;&#x7ED3;&#x679C;&#x586B;&#x5199;" /> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x9879;&#x76EE;&#x8BE6;&#x60C5;&#x4E0E;&#x7ED3;&#x679C;&#x586B;&#x5199;" />
<Grid> <Grid>
@@ -416,40 +337,75 @@
<TextBox Text="{Binding ResultNote, UpdateSourceTrigger=PropertyChanged}" MinHeight="104" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" IsReadOnly="{Binding SelectedItemUsesRealtimeValue}" /> <TextBox Text="{Binding ResultNote, UpdateSourceTrigger=PropertyChanged}" MinHeight="104" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" IsReadOnly="{Binding SelectedItemUsesRealtimeValue}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<WrapPanel Margin="0,8,0,0">
<Button Command="{Binding SelectPreviousItemCommand}" Content="&#x4E0A;&#x4E00;&#x9879;" Background="#FF6B8791" />
<Button Command="{Binding SelectNextItemCommand}" Content="&#x4E0B;&#x4E00;&#x9879;" Background="#FF6B8791" />
<Button Command="{Binding ApplyResultCommand}" Content="&#x4FDD;&#x5B58;" />
</WrapPanel>
</StackPanel>
</Border>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</DockPanel>
</Border>
</Grid>
</TabItem> </TabItem>
<TabItem Header="&#x5B9E;&#x65F6;&#x6570;&#x636E;"> <TabItem Header="&#x5B9E;&#x65F6;&#x6570;&#x636E;">
<ScrollViewer VerticalScrollBarVisibility="Auto"> <ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="0,6,0,0"> <StackPanel Margin="0,6,0,0">
<UniformGrid Columns="4" Margin="0,0,0,12"> <Border Style="{StaticResource CardBorderStyle}">
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x9636;&#x6BB5;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding CurrentStage}" TextWrapping="Wrap" /></StackPanel></Border> <StackPanel>
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8BBE;&#x5907;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding DeviceStatus}" TextWrapping="Wrap" /></StackPanel></Border> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x5B9E;&#x65F6;&#x603B;&#x89C8;" />
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F85;&#x68C0;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding PendingCount}" /></StackPanel></Border> <WrapPanel Margin="0,0,0,4">
<Border Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x544A;&#x8B66;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding AlarmMessages.Count}" /></StackPanel></Border> <Border Width="150" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
</UniformGrid> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x9636;&#x6BB5;" />
<UniformGrid Columns="2" Margin="0,0,0,12"> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding CurrentStage}" TextWrapping="Wrap" />
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x518D;&#x5FAA;&#x73AF;&#x7387;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding RealtimeRecirculationDisplay}" /></StackPanel></Border> </StackPanel>
<Border Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x4E3B;&#x6CF5;/&#x56DE;&#x8F93;&#x5DEE;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding FlowImbalanceDisplay}" /></StackPanel></Border> </Border>
</UniformGrid> <Border Width="150" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<UniformGrid Columns="4" Margin="0,0,0,12"> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8BBE;&#x5907;" />
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x538B;&#x529B;&#x964D;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding DeltaPressureDisplay}" /></StackPanel></Border> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding DeviceStatus}" TextWrapping="Wrap" />
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8D1F;&#x538B;&#x8F85;&#x52A9;&#x5F15;&#x6D41;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding NegativeAssistPressureDisplay}" /></StackPanel></Border> </StackPanel>
<Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="fHb &#x8D8B;&#x52BF;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding FreeHemoglobinDisplay}" /></StackPanel></Border> </Border>
<Border Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}"><StackPanel><TextBlock Style="{StaticResource CaptionStyle}" Text="&#x767D;&#x7EC6;&#x80DE;&#x51CF;&#x5C11;&#x7387;" /><TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding WhiteCellLossDisplay}" /></StackPanel></Border> <Border Width="150" Margin="0,0,8,8" Padding="14" Background="#FFE7F5F3" CornerRadius="14">
</UniformGrid> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5408;&#x683C;&#x7387;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding ComplianceDisplay}" />
</StackPanel>
</Border>
<Border Width="150" Margin="0,0,8,8" Padding="14" Background="#FFE9EFF9" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5408;&#x683C;&#x9879;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding QualifiedCount}" />
</StackPanel>
</Border>
<Border Width="150" Margin="0,0,8,8" Padding="14" Background="#FFFDEBE7" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x9884;&#x8B66;/&#x4E0D;&#x5408;&#x683C;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="24" Text="{Binding WarningCount}" />
</StackPanel>
</Border>
<Border Width="150" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F85;&#x68C0;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding PendingCount}" />
</StackPanel>
</Border>
<Border Width="150" Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x544A;&#x8B66;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding AlarmMessages.Count}" />
</StackPanel>
</Border>
</WrapPanel>
</StackPanel>
</Border>
<Border Style="{StaticResource CardBorderStyle}"> <Border Style="{StaticResource CardBorderStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x6D41;&#x91CF;&#x4F20;&#x611F;&#x5668;" /> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x6D41;&#x91CF;&#x5FEB;&#x7167;" />
<UniformGrid Columns="3" Margin="0,0,0,8"> <UniformGrid Columns="3" Margin="0,0,0,8">
<Border Margin="0,0,8,0" Style="{StaticResource PanelSectionStyle}"> <Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x4E3B;&#x6CF5;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x4E3B;&#x6CF5;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding PumpFlowDisplay}" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding PumpFlowDisplay}" />
@@ -457,7 +413,7 @@
<ProgressBar Minimum="0" Maximum="1" Value="{Binding PumpFlowNormalizedValue, Mode=OneWay}" Height="10" Foreground="{StaticResource AccentBrush}" Background="#FFDDE7EC" /> <ProgressBar Minimum="0" Maximum="1" Value="{Binding PumpFlowNormalizedValue, Mode=OneWay}" Height="10" Foreground="{StaticResource AccentBrush}" Background="#FFDDE7EC" />
</StackPanel> </StackPanel>
</Border> </Border>
<Border Margin="0,0,8,0" Style="{StaticResource PanelSectionStyle}"> <Border Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F15;&#x6D41;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F15;&#x6D41;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding DrainageFlowDisplay}" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding DrainageFlowDisplay}" />
@@ -465,7 +421,7 @@
<ProgressBar Minimum="0" Maximum="1" Value="{Binding DrainageFlowNormalizedValue, Mode=OneWay}" Height="10" Foreground="{StaticResource AccentBrush}" Background="#FFDDE7EC" /> <ProgressBar Minimum="0" Maximum="1" Value="{Binding DrainageFlowNormalizedValue, Mode=OneWay}" Height="10" Foreground="{StaticResource AccentBrush}" Background="#FFDDE7EC" />
</StackPanel> </StackPanel>
</Border> </Border>
<Border Style="{StaticResource PanelSectionStyle}"> <Border Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x56DE;&#x8F93;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x56DE;&#x8F93;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding ReturnFlowDisplay}" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding ReturnFlowDisplay}" />
@@ -474,33 +430,72 @@
</StackPanel> </StackPanel>
</Border> </Border>
</UniformGrid> </UniformGrid>
<WrapPanel>
<Border Width="180" Margin="0,0,8,8" Padding="14" Background="#FFEAF6F3" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x518D;&#x5FAA;&#x73AF;&#x7387;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding RealtimeRecirculationDisplay}" />
</StackPanel>
</Border>
<Border Width="180" Margin="0,0,8,8" Padding="14" Background="#FFF6EFE2" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x538B;&#x529B;&#x964D;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding DeltaPressureDisplay}" />
</StackPanel>
</Border>
<Border Width="180" Margin="0,0,0,8" Padding="14" Background="#FFEFF1FA" CornerRadius="14">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x4E3B;&#x6CF5;/&#x56DE;&#x8F93;&#x5DEE;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding FlowImbalanceDisplay}" />
</StackPanel>
</Border>
</WrapPanel>
</StackPanel> </StackPanel>
</Border> </Border>
<Border Style="{StaticResource CardBorderStyle}"> <Border Style="{StaticResource CardBorderStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x8F85;&#x52A9;&#x5B9E;&#x65F6;&#x6307;&#x6807;" /> <TextBlock Style="{StaticResource SectionTitleStyle}" Text="&#x538B;&#x529B;&#x4E0E;&#x8F85;&#x52A9;&#x6307;&#x6807;" />
<UniformGrid Columns="3"> <WrapPanel Margin="0,0,0,4">
<Border Margin="0,0,8,0" Style="{StaticResource PanelSectionStyle}"> <Border Width="180" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5165;&#x53E3;/&#x51FA;&#x53E3;&#x538B;&#x529B;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8FD1;&#x7AEF;&#x538B;&#x529B;" />
<TextBlock FontSize="18" FontWeight="Bold" Text="{Binding SelectedItemLiveDisplay}" TextWrapping="Wrap" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding Channels[4].DisplayValue}" />
</StackPanel> </StackPanel>
</Border> </Border>
<Border Margin="0,0,8,0" Style="{StaticResource PanelSectionStyle}"> <Border Width="180" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8FDC;&#x7AEF;&#x538B;&#x529B;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding Channels[3].DisplayValue}" />
</StackPanel>
</Border>
<Border Width="180" Margin="0,0,8,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x8D1F;&#x538B;&#x8F85;&#x52A9;&#x5F15;&#x6D41;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding NegativeAssistPressureDisplay}" />
</StackPanel>
</Border>
<Border Width="180" Margin="0,0,0,8" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x6A21;&#x62DF;&#x8840;&#x6DB2;&#x6E29;&#x5EA6;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="&#x6A21;&#x62DF;&#x8840;&#x6DB2;&#x6E29;&#x5EA6;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding TemperatureDisplay}" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding TemperatureDisplay}" />
</StackPanel> </StackPanel>
</Border> </Border>
<Border Style="{StaticResource PanelSectionStyle}"> </WrapPanel>
<WrapPanel>
<Border Width="220" Margin="0,0,8,0" Style="{StaticResource PanelSectionStyle}">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x5F53;&#x524D;&#x9009;&#x4E2D;&#x6761;&#x6B3E;&#x7B56;&#x7565;" /> <TextBlock Style="{StaticResource CaptionStyle}" Text="fHb &#x8D8B;&#x52BF;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="20" Text="{Binding SelectedItemCaptureModeText}" TextWrapping="Wrap" /> <TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding FreeHemoglobinDisplay}" />
<TextBlock Margin="0,6,0,0" Style="{StaticResource CaptionStyle}" Text="{Binding SelectedItemMeasurementSource}" TextWrapping="Wrap" />
</StackPanel> </StackPanel>
</Border> </Border>
</UniformGrid> <Border Width="220" Margin="0,0,0,0" Style="{StaticResource PanelSectionStyle}">
<StackPanel>
<TextBlock Style="{StaticResource CaptionStyle}" Text="&#x767D;&#x7EC6;&#x80DE;&#x51CF;&#x5C11;&#x7387;" />
<TextBlock Style="{StaticResource MetricValueStyle}" FontSize="22" Text="{Binding WhiteCellLossDisplay}" />
</StackPanel>
</Border>
</WrapPanel>
</StackPanel> </StackPanel>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -1,4 +1,6 @@
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Cardiopulmonarybypasssystems.Models; using Cardiopulmonarybypasssystems.Models;
using NModbus; using NModbus;
@@ -11,6 +13,8 @@ public sealed class MockModbusTelemetryService : IModbusTelemetryService, IDispo
private const byte SlaveId = 1; private const byte SlaveId = 1;
private const ushort ProximalPressureRegister = 1330; private const ushort ProximalPressureRegister = 1330;
private const ushort DistalPressureRegister = 1380; private const ushort DistalPressureRegister = 1380;
private static readonly TimeSpan ConnectionAttemptTimeout = TimeSpan.FromMilliseconds(300);
private static readonly TimeSpan ConnectionRetryInterval = TimeSpan.FromSeconds(5);
private readonly object _syncRoot = new(); private readonly object _syncRoot = new();
private readonly Random _random = new(); private readonly Random _random = new();
@@ -32,16 +36,18 @@ public sealed class MockModbusTelemetryService : IModbusTelemetryService, IDispo
private TcpClient? _tcpClient; private TcpClient? _tcpClient;
private IModbusMaster? _master; private IModbusMaster? _master;
private bool _connectionInitialized; private bool _connectionInitialized;
private Task? _connectionTask;
private DateTime _nextConnectionAttemptUtc = DateTime.MinValue;
public IReadOnlyList<DeviceChannel> GetChannels() public IReadOnlyList<DeviceChannel> GetChannels()
{ {
EnsureConnected(); EnsureConnectionScheduled();
return _channels; return _channels;
} }
public IReadOnlyList<AlarmMessage> UpdateChannels() public IReadOnlyList<AlarmMessage> UpdateChannels()
{ {
EnsureConnected(); EnsureConnectionScheduled();
lock (_syncRoot) lock (_syncRoot)
{ {
@@ -73,15 +79,20 @@ public sealed class MockModbusTelemetryService : IModbusTelemetryService, IDispo
public void Dispose() public void Dispose()
{ {
lock (_syncRoot) lock (_syncRoot)
{
ReleaseConnection();
}
}
private void ReleaseConnection()
{ {
_master?.Dispose(); _master?.Dispose();
_tcpClient?.Dispose(); _tcpClient?.Dispose();
_master = null; _master = null;
_tcpClient = null; _tcpClient = null;
} }
}
private void EnsureConnected() private void EnsureConnectionScheduled()
{ {
lock (_syncRoot) lock (_syncRoot)
{ {
@@ -90,20 +101,50 @@ public sealed class MockModbusTelemetryService : IModbusTelemetryService, IDispo
return; return;
} }
Dispose(); if (_connectionTask is { IsCompleted: false })
{
return;
}
if (DateTime.UtcNow < _nextConnectionAttemptUtc)
{
return;
}
_nextConnectionAttemptUtc = DateTime.UtcNow.Add(ConnectionRetryInterval);
_connectionTask = Task.Run(ConnectWithTimeout);
}
}
private void ConnectWithTimeout()
{
TcpClient? tcpClient = null;
try try
{ {
_tcpClient = new TcpClient(); tcpClient = new TcpClient();
_tcpClient.Connect(IpAddress, Port); using var cancellation = new CancellationTokenSource(ConnectionAttemptTimeout);
_master = _factory.CreateMaster(_tcpClient); tcpClient.ConnectAsync(IpAddress, Port, cancellation.Token).GetAwaiter().GetResult();
tcpClient.ReceiveTimeout = (int)ConnectionAttemptTimeout.TotalMilliseconds;
tcpClient.SendTimeout = (int)ConnectionAttemptTimeout.TotalMilliseconds;
var master = _factory.CreateMaster(tcpClient);
lock (_syncRoot)
{
ReleaseConnection();
_tcpClient = tcpClient;
_master = master;
_connectionInitialized = true; _connectionInitialized = true;
tcpClient = null;
}
} }
catch catch
{ {
_master = null; tcpClient?.Dispose();
_tcpClient?.Dispose();
_tcpClient = null; lock (_syncRoot)
{
ReleaseConnection();
} }
} }
} }
@@ -126,7 +167,12 @@ public sealed class MockModbusTelemetryService : IModbusTelemetryService, IDispo
} }
catch catch
{ {
Dispose(); lock (_syncRoot)
{
ReleaseConnection();
_nextConnectionAttemptUtc = DateTime.MinValue;
}
SimulatePressureChannels(); SimulatePressureChannels();
} }
} }

View File

@@ -191,6 +191,8 @@ public partial class MainViewModel : ObservableObject
public string PumpFlowDisplay => $"{PumpFlow:F2} L/min"; public string PumpFlowDisplay => $"{PumpFlow:F2} L/min";
public string DrainageFlowDisplay => $"{DrainageFlow:F2} L/min"; public string DrainageFlowDisplay => $"{DrainageFlow:F2} L/min";
public string ReturnFlowDisplay => $"{ReturnFlow:F2} L/min"; public string ReturnFlowDisplay => $"{ReturnFlow:F2} L/min";
public string ProximalPressureDisplay => $"{ChannelValue("è¿ç«¯åŽåŠ"):F1} mmHg";
public string DistalPressureDisplay => $"{ChannelValue("远端åŽåŠ"):F1} mmHg";
public string FlowImbalanceDisplay => $"{Math.Abs(PumpFlow - ReturnFlow):F2} L/min"; public string FlowImbalanceDisplay => $"{Math.Abs(PumpFlow - ReturnFlow):F2} L/min";
public string PumpFlowLoadDisplay => $"{ChannelNormalizedValue(""):P0} 量程"; public string PumpFlowLoadDisplay => $"{ChannelNormalizedValue(""):P0} 量程";
public string DrainageFlowLoadDisplay => $"{ChannelNormalizedValue(""):P0} 量程"; public string DrainageFlowLoadDisplay => $"{ChannelNormalizedValue(""):P0} 量程";
@@ -569,9 +571,11 @@ public partial class MainViewModel : ObservableObject
private void RefreshTelemetry() private void RefreshTelemetry()
{ {
var alarms = _telemetryService.UpdateChannels(); var alarms = _telemetryService.UpdateChannels();
AlarmMessages.Clear();
foreach (var alarm in alarms.OrderByDescending(a => a.Timestamp)) foreach (var alarm in alarms.OrderByDescending(a => a.Timestamp))
{ {
AlarmMessages.Insert(0, alarm); AlarmMessages.Add(alarm);
} }
RefreshTelemetryPanel(); RefreshTelemetryPanel();
@@ -591,6 +595,8 @@ public partial class MainViewModel : ObservableObject
OnPropertyChanged(nameof(PumpFlowDisplay)); OnPropertyChanged(nameof(PumpFlowDisplay));
OnPropertyChanged(nameof(DrainageFlowDisplay)); OnPropertyChanged(nameof(DrainageFlowDisplay));
OnPropertyChanged(nameof(ReturnFlowDisplay)); OnPropertyChanged(nameof(ReturnFlowDisplay));
OnPropertyChanged(nameof(ProximalPressureDisplay));
OnPropertyChanged(nameof(DistalPressureDisplay));
OnPropertyChanged(nameof(RealtimeRecirculationDisplay)); OnPropertyChanged(nameof(RealtimeRecirculationDisplay));
OnPropertyChanged(nameof(FlowImbalanceDisplay)); OnPropertyChanged(nameof(FlowImbalanceDisplay));
OnPropertyChanged(nameof(NegativeAssistPressureDisplay)); OnPropertyChanged(nameof(NegativeAssistPressureDisplay));