diff --git a/Cardiopulmonarybypasssystems/EngineeringRegistersWindow.xaml b/Cardiopulmonarybypasssystems/EngineeringRegistersWindow.xaml
index 1e67f78..639bc98 100644
--- a/Cardiopulmonarybypasssystems/EngineeringRegistersWindow.xaml
+++ b/Cardiopulmonarybypasssystems/EngineeringRegistersWindow.xaml
@@ -1,7 +1,7 @@
-
+ Text="泵/流量系数" />
diff --git a/Cardiopulmonarybypasssystems/MainWindow.xaml b/Cardiopulmonarybypasssystems/MainWindow.xaml
index ce3bdb6..7cf6922 100644
--- a/Cardiopulmonarybypasssystems/MainWindow.xaml
+++ b/Cardiopulmonarybypasssystems/MainWindow.xaml
@@ -99,6 +99,27 @@
+
@@ -114,8 +135,27 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -154,24 +194,14 @@
Text="{Binding Rs485SlaveAddress, StringFormat=从站 {0}}" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
@@ -484,90 +505,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1644,59 +1226,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Padding="0">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1715,7 +1265,7 @@
@@ -1763,90 +1313,26 @@
-
+ Padding="0">
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -1876,7 +1362,7 @@
-
+
@@ -1931,7 +1417,7 @@
-
+
@@ -1942,7 +1428,7 @@
-
+
@@ -1953,90 +1439,26 @@
-
+ Padding="0">
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -2060,93 +1482,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2243,7 +1573,7 @@
-
+
+
+
+
+
@@ -2289,7 +1623,7 @@
-
+
+
+
+
+
+
+
@@ -2314,7 +1654,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -2357,7 +1707,7 @@
-
+
+
+
+
+
+
+
+
+
-
+
@@ -2389,13 +1747,13 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2444,31 +1802,31 @@
-
+
-
+
-
+
-
+
-
+
@@ -2477,7 +1835,7 @@
-
+
-
-
-
-
-
@@ -2657,7 +1997,7 @@
-
+
@@ -2758,12 +2098,12 @@
@@ -2771,7 +2111,7 @@
-
+
@@ -2815,7 +2155,8 @@
-
+
+
diff --git a/Cardiopulmonarybypasssystems/MainWindow.xaml.cs b/Cardiopulmonarybypasssystems/MainWindow.xaml.cs
index cd23a02..d20319e 100644
--- a/Cardiopulmonarybypasssystems/MainWindow.xaml.cs
+++ b/Cardiopulmonarybypasssystems/MainWindow.xaml.cs
@@ -1,11 +1,15 @@
+using System.Collections.Specialized;
+using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
+using Cardiopulmonarybypasssystems.Models;
using Cardiopulmonarybypasssystems.ViewModels;
namespace Cardiopulmonarybypasssystems;
@@ -13,11 +17,23 @@ namespace Cardiopulmonarybypasssystems;
public partial class MainWindow : Window
{
private EngineeringRegistersWindow? _engineeringRegistersWindow;
+ private readonly List _navigationButtons = [];
+ private readonly List _projectInspectionButtons = [];
+ private object? _projectInspectionContent;
+ private object? _realtimeContent;
+ private object? _manualSupplementContent;
+ private object? _configurationContent;
+ private object? _traceContent;
+ private NavigationPage _currentPage = NavigationPage.RealtimeData;
+ private InspectionItem? _currentProjectItem;
+ private bool _isPumpSetpointKeypadOpen;
public MainWindow(MainViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
+ EmbedProjectDetailContent();
+ ConfigureNavigation(viewModel);
ConfigureTrendBindings();
}
@@ -31,17 +47,525 @@ public partial class MainWindow : Window
Dispatcher.BeginInvoke(() =>
{
- if (sender is DataGrid { SelectedItem: not null })
+ if (sender is DataGrid { SelectedItem: InspectionItem inspectionItem })
{
- ProjectDetailTab.IsSelected = true;
+ NavigateToProjectItem(inspectionItem);
}
}, DispatcherPriority.Background);
}
private void ReturnToProjectListButton_OnClick(object sender, RoutedEventArgs e)
{
- ProjectListTab.IsSelected = true;
- InspectionItemsGrid.Focus();
+ NavigateToFixedPage(NavigationPage.RealtimeData);
+ }
+
+ private void EmbedProjectDetailContent()
+ {
+ if (ProjectDetailContentHost.Content is not null)
+ {
+ return;
+ }
+
+ if (ProjectDetailTab.Content is ScrollViewer detailScrollViewer)
+ {
+ var detailContent = detailScrollViewer.Content;
+ detailScrollViewer.Content = null;
+ ProjectDetailContentHost.Content = detailContent;
+ }
+ else
+ {
+ ProjectDetailContentHost.Content = ProjectDetailTab.Content;
+ }
+
+ ProjectDetailTab.Content = null;
+ RootTabControl.Items.Remove(ProjectDetailTab);
+ }
+
+ private void ConfigureNavigation(MainViewModel viewModel)
+ {
+ _realtimeContent = ExtractTabContent(RealtimeDataTab);
+ _projectInspectionContent = ExtractTabContent(ProjectListTab);
+ _manualSupplementContent = ExtractTabContent(ManualSupplementTab);
+ _configurationContent = ExtractTabContent(ConfigurationTab);
+ _traceContent = ExtractTabContent(TraceTab);
+
+ viewModel.PropertyChanged += ViewModel_OnPropertyChanged;
+
+ if (viewModel.FilteredItemsView is INotifyCollectionChanged filteredItems)
+ {
+ filteredItems.CollectionChanged += (_, _) => RebuildNavigationButtons();
+ }
+
+ RebuildNavigationButtons();
+ NavigateToFixedPage(NavigationPage.RealtimeData);
+ }
+
+ private static object? ExtractTabContent(TabItem tab)
+ {
+ var content = tab.Content;
+ tab.Content = null;
+ return content;
+ }
+
+ private void RebuildNavigationButtons()
+ {
+ if (DataContext is not MainViewModel viewModel)
+ {
+ return;
+ }
+
+ NavigationButtonPanel.Children.Clear();
+ _navigationButtons.Clear();
+ _projectInspectionButtons.Clear();
+
+ AddNavigationButton("实时数据", new NavigationTarget(NavigationPage.RealtimeData, null));
+
+ foreach (var item in viewModel.FilteredItemsView.Cast())
+ {
+ var button = AddNavigationButton(item.Item, new NavigationTarget(NavigationPage.ProjectItem, item));
+ _projectInspectionButtons.Add(button);
+ }
+
+ AddNavigationButton("项目补充", new NavigationTarget(NavigationPage.ManualSupplement, null));
+ AddNavigationButton("配置", new NavigationTarget(NavigationPage.Configuration, null));
+ AddNavigationButton("追溯", new NavigationTarget(NavigationPage.Trace, null));
+
+ if (_currentPage == NavigationPage.ProjectItem
+ && (_currentProjectItem is null || !_projectInspectionButtons.Any(button => ReferenceEquals(((NavigationTarget)button.Tag).ProjectItem, _currentProjectItem))))
+ {
+ NavigateToFixedPage(NavigationPage.RealtimeData);
+ return;
+ }
+
+ RefreshNavigationButtonStates();
+ }
+
+ private Button AddNavigationButton(string text, NavigationTarget target)
+ {
+ var button = new Button
+ {
+ Content = new TextBlock
+ {
+ MaxWidth = 132,
+ Text = text,
+ TextAlignment = TextAlignment.Center,
+ TextWrapping = TextWrapping.Wrap
+ },
+ Tag = target,
+ MinWidth = 92,
+ MinHeight = 38,
+ Padding = new Thickness(10, 6, 10, 6),
+ Margin = new Thickness(0, 0, 6, 6),
+ FontSize = 14
+ };
+
+ button.Click += NavigationButton_OnClick;
+ NavigationButtonPanel.Children.Add(button);
+ _navigationButtons.Add(button);
+ return button;
+ }
+
+ private void NavigationButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is Button { Tag: NavigationTarget target })
+ {
+ Navigate(target);
+ }
+ }
+
+ private void Navigate(NavigationTarget target)
+ {
+ if (target.Page == NavigationPage.ProjectItem)
+ {
+ NavigateToProjectItem(target.ProjectItem);
+ return;
+ }
+
+ NavigateToFixedPage(target.Page);
+ }
+
+ private void NavigateToFixedPage(NavigationPage page)
+ {
+ _currentPage = page;
+ _currentProjectItem = null;
+ MainContentHost.Content = page switch
+ {
+ NavigationPage.RealtimeData => _realtimeContent,
+ NavigationPage.ManualSupplement => _manualSupplementContent,
+ NavigationPage.Configuration => _configurationContent,
+ NavigationPage.Trace => _traceContent,
+ _ => _realtimeContent
+ };
+
+ RefreshNavigationButtonStates();
+ }
+
+ private void NavigateToProjectItem(InspectionItem? item)
+ {
+ if (item is null)
+ {
+ return;
+ }
+
+ if (DataContext is MainViewModel viewModel && !ReferenceEquals(viewModel.SelectedItem, item))
+ {
+ viewModel.SelectedItem = item;
+ }
+
+ _currentPage = NavigationPage.ProjectItem;
+ _currentProjectItem = item;
+ MainContentHost.Content = _projectInspectionContent;
+ RefreshNavigationButtonStates();
+ }
+
+ private void RefreshNavigationButtonStates()
+ {
+ foreach (var button in _navigationButtons)
+ {
+ if (button.Tag is not NavigationTarget target)
+ {
+ continue;
+ }
+
+ var isSelected = target.Page == _currentPage
+ && (_currentPage != NavigationPage.ProjectItem || ReferenceEquals(target.ProjectItem, _currentProjectItem));
+
+ button.Background = isSelected ? BrushFromRgb(0xE3, 0xF6, 0xEF) : BrushFromRgb(0xE1, 0xE9, 0xEC);
+ button.Foreground = isSelected ? BrushFromRgb(0x0E, 0x6C, 0x58) : BrushFromRgb(0x54, 0x65, 0x70);
+ button.BorderBrush = isSelected ? BrushFromRgb(0x6E, 0xB2, 0xA9) : BrushFromRgb(0xC6, 0xD5, 0xDB);
+ button.FontWeight = isSelected ? FontWeights.Bold : FontWeights.SemiBold;
+ }
+ }
+
+ private static SolidColorBrush BrushFromRgb(byte red, byte green, byte blue) => new(Color.FromRgb(red, green, blue));
+
+ private void ViewModel_OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(MainViewModel.SelectedItem) && sender is MainViewModel viewModel)
+ {
+ if (viewModel.SelectedItem is not null && _currentPage == NavigationPage.ProjectItem)
+ {
+ NavigateToProjectItem(viewModel.SelectedItem);
+ }
+ }
+ }
+
+ private enum NavigationPage
+ {
+ RealtimeData,
+ ProjectItem,
+ ManualSupplement,
+ Configuration,
+ Trace
+ }
+
+ private sealed record NavigationTarget(NavigationPage Page, InspectionItem? ProjectItem);
+
+ private void PumpSetpointTextBox_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ e.Handled = true;
+
+ if (sender is TextBox { DataContext: PumpControlChannel pump })
+ {
+ ShowPumpSetpointKeypad(pump);
+ }
+ }
+
+ private void PumpSetpointTextBox_OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
+ {
+ if (sender is TextBox { DataContext: PumpControlChannel pump })
+ {
+ ShowPumpSetpointKeypad(pump);
+ }
+ }
+
+ private void ShowPumpSetpointKeypad(PumpControlChannel pump)
+ {
+ if (_isPumpSetpointKeypadOpen)
+ {
+ return;
+ }
+
+ _isPumpSetpointKeypadOpen = true;
+
+ var valueBox = new TextBox
+ {
+ Text = string.IsNullOrWhiteSpace(pump.PendingSetpointText) ? "0" : pump.PendingSetpointText.Trim(),
+ IsReadOnly = true,
+ Height = 46,
+ FontSize = 22,
+ FontWeight = FontWeights.SemiBold,
+ TextAlignment = TextAlignment.Right,
+ VerticalContentAlignment = VerticalAlignment.Center,
+ Margin = new Thickness(0, 0, 0, 10),
+ Padding = new Thickness(10, 0, 10, 0)
+ };
+
+ var errorText = new TextBlock
+ {
+ Foreground = Brushes.Firebrick,
+ FontSize = 12,
+ MinHeight = 18,
+ Margin = new Thickness(0, 0, 0, 8)
+ };
+
+ var keypad = new UniformGrid
+ {
+ Columns = 3,
+ Rows = 4,
+ Margin = new Thickness(0, 0, 0, 12)
+ };
+
+ foreach (var key in new[] { "7", "8", "9", "4", "5", "6", "1", "2", "3", ".", "0", "退格" })
+ {
+ keypad.Children.Add(CreateKeypadButton(key, (_, _) =>
+ {
+ errorText.Text = string.Empty;
+ ApplyKeypadInput(valueBox, key);
+ }));
+ }
+
+ var actions = new Grid();
+ actions.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ actions.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ actions.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+
+ var clearButton = CreateKeypadButton("清空", (_, _) =>
+ {
+ errorText.Text = string.Empty;
+ valueBox.Text = string.Empty;
+ });
+
+ var cancelButton = CreateKeypadButton("取消", (_, _) =>
+ {
+ if (Window.GetWindow(valueBox) is Window owner)
+ {
+ owner.DialogResult = false;
+ }
+ });
+
+ var okButton = CreateKeypadButton("确定", (_, _) =>
+ {
+ var normalizedValue = NormalizePumpSetpointText(valueBox.Text);
+
+ if (!double.TryParse(
+ normalizedValue,
+ NumberStyles.Float,
+ CultureInfo.InvariantCulture,
+ out var parsedValue)
+ || parsedValue < 0)
+ {
+ errorText.Text = "请输入有效流量";
+ return;
+ }
+
+ pump.PendingSetpointText = parsedValue.ToString("0.##", CultureInfo.InvariantCulture);
+
+ if (DataContext is MainViewModel viewModel
+ && viewModel.WritePumpSetpointCommand.CanExecute(pump))
+ {
+ viewModel.WritePumpSetpointCommand.Execute(pump);
+ }
+
+ if (Window.GetWindow(valueBox) is Window owner)
+ {
+ owner.DialogResult = true;
+ }
+ });
+
+ Grid.SetColumn(clearButton, 0);
+ Grid.SetColumn(cancelButton, 1);
+ Grid.SetColumn(okButton, 2);
+ actions.Children.Add(clearButton);
+ actions.Children.Add(cancelButton);
+ actions.Children.Add(okButton);
+
+ var panel = new StackPanel
+ {
+ Margin = new Thickness(18)
+ };
+ panel.Children.Add(new TextBlock
+ {
+ Text = pump.Name,
+ FontSize = 16,
+ FontWeight = FontWeights.SemiBold,
+ Foreground = BrushFromRgb(0x1F, 0x3B, 0x46),
+ TextWrapping = TextWrapping.Wrap,
+ Margin = new Thickness(0, 0, 0, 10)
+ });
+ panel.Children.Add(valueBox);
+ panel.Children.Add(errorText);
+ panel.Children.Add(keypad);
+ panel.Children.Add(actions);
+
+ var dialog = new Window
+ {
+ Owner = this,
+ Title = "输入目标流量",
+ Width = 450,
+ Height = 500,
+ MinWidth = 280,
+ MinHeight = 390,
+ ResizeMode = ResizeMode.NoResize,
+ WindowStartupLocation = WindowStartupLocation.CenterOwner,
+ Content = panel
+ };
+
+ dialog.Closed += (_, _) => _isPumpSetpointKeypadOpen = false;
+ dialog.ShowDialog();
+ }
+
+ private static Button CreateKeypadButton(string text, RoutedEventHandler handler)
+ {
+ var button = new Button
+ {
+ Content = text,
+ MinHeight = 46,
+ Margin = new Thickness(4),
+ FontSize = 16,
+ FontWeight = FontWeights.SemiBold,
+ Background = BrushFromRgb(0xE3, 0xF6, 0xEF),
+ Foreground = BrushFromRgb(0x1F, 0x3B, 0x46),
+ BorderBrush = BrushFromRgb(0x9C, 0xCB, 0xBF)
+ };
+
+ button.Click += handler;
+ return button;
+ }
+
+ private static void ApplyKeypadInput(TextBox valueBox, string key)
+ {
+ if (key == "退格")
+ {
+ valueBox.Text = valueBox.Text.Length > 0 ? valueBox.Text[..^1] : string.Empty;
+ return;
+ }
+
+ if (key == "." && valueBox.Text.Contains('.', StringComparison.Ordinal))
+ {
+ return;
+ }
+
+ if (valueBox.Text == "0" && key != ".")
+ {
+ valueBox.Text = key;
+ return;
+ }
+
+ valueBox.Text += key;
+ }
+
+ private static string NormalizePumpSetpointText(string value)
+ {
+ var normalizedValue = value.Trim();
+
+ if (normalizedValue.StartsWith(".", StringComparison.Ordinal))
+ {
+ normalizedValue = "0" + normalizedValue;
+ }
+
+ return normalizedValue;
+ }
+
+ private void OpenProjectInfoDialogButton_OnClick(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is not MainViewModel viewModel || viewModel.SelectedItem is null)
+ {
+ return;
+ }
+
+ var item = viewModel.SelectedItem;
+ var panel = new StackPanel
+ {
+ Margin = new Thickness(18)
+ };
+
+ AddDialogSection(panel, "类别", item.Category);
+ AddDialogSection(panel, "判定要求", item.AcceptanceCriteria);
+ AddDialogSection(panel, "检验方法", item.TestMethod);
+ AddDialogSection(panel, "记录要点", item.RecordFocus);
+ AddDialogSection(panel, "数据来源", viewModel.SelectedItemMeasurementSource);
+ AddDialogSection(panel, "填写说明", viewModel.RealtimeMeasurementHint);
+ AddDialogSection(panel, "实时数据预览", viewModel.SelectedItemLiveDisplay);
+ AddDialogSection(panel, "实时数据说明", viewModel.SelectedItemLiveHint);
+
+ var scrollViewer = new ScrollViewer
+ {
+ Content = panel,
+ VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
+ HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled
+ };
+
+ var closeButton = new Button
+ {
+ Content = "关闭",
+ MinWidth = 88,
+ MinHeight = 34,
+ Padding = new Thickness(12, 5, 12, 5),
+ Margin = new Thickness(0, 10, 18, 14),
+ HorizontalAlignment = HorizontalAlignment.Right,
+ Background = BrushFromRgb(0xE3, 0xF6, 0xEF),
+ Foreground = BrushFromRgb(0x1F, 0x3B, 0x46),
+ BorderBrush = BrushFromRgb(0x9C, 0xCB, 0xBF)
+ };
+
+ var content = new Grid();
+ content.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
+ content.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
+ content.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
+
+ var title = new TextBlock
+ {
+ Text = item.Item,
+ Margin = new Thickness(18, 16, 18, 6),
+ FontSize = 18,
+ FontWeight = FontWeights.Bold,
+ Foreground = BrushFromRgb(0x1F, 0x3B, 0x46),
+ TextWrapping = TextWrapping.Wrap
+ };
+
+ Grid.SetRow(title, 0);
+ Grid.SetRow(scrollViewer, 1);
+ Grid.SetRow(closeButton, 2);
+ content.Children.Add(title);
+ content.Children.Add(scrollViewer);
+ content.Children.Add(closeButton);
+
+ var dialog = new Window
+ {
+ Owner = this,
+ Title = "项目说明",
+ Width = Math.Min(760, Math.Max(420, ActualWidth - 120)),
+ Height = Math.Min(620, Math.Max(420, ActualHeight - 140)),
+ MinWidth = 360,
+ MinHeight = 320,
+ WindowStartupLocation = WindowStartupLocation.CenterOwner,
+ Content = content
+ };
+
+ closeButton.Click += (_, _) => dialog.Close();
+ dialog.ShowDialog();
+ }
+
+ private static void AddDialogSection(Panel panel, string title, string? value)
+ {
+ panel.Children.Add(new TextBlock
+ {
+ Text = title,
+ FontSize = 13,
+ FontWeight = FontWeights.SemiBold,
+ Foreground = BrushFromRgb(0x54, 0x65, 0x70),
+ Margin = new Thickness(0, 0, 0, 4)
+ });
+
+ panel.Children.Add(new TextBlock
+ {
+ Text = string.IsNullOrWhiteSpace(value) ? "-" : value.Trim(),
+ FontSize = 14,
+ Foreground = BrushFromRgb(0x1F, 0x3B, 0x46),
+ TextWrapping = TextWrapping.Wrap,
+ Margin = new Thickness(0, 0, 0, 12)
+ });
}
private void OpenEngineeringRegistersButton_OnClick(object sender, RoutedEventArgs e)
diff --git a/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs b/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
index eddc5fd..3f25579 100644
--- a/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
+++ b/Cardiopulmonarybypasssystems/Models/ValveControlChannel.cs
@@ -22,6 +22,7 @@ public partial class ValveControlChannel : ObservableObject
? $"停止{Name}"
: $"启动{Name}";
public string CirculatingWaterToggleText => IsOpen ? "停止循环水温" : "启动循环水温";
+ public string ReservoirToggleText => IsOpen ? "关闭贮液" : "开启贮液";
public string IndicatorColor => !StateAvailable ? "#FF94A6AE" : IsOpen ? "#FF32B06A" : "#FFC8D4DA";
public string StateHint => !StateAvailable ? "未取得 PLC 状态" : $"{Name}已{StateText}";
public bool HideRealtimeCardStateDescription => Key is "TestLoopValve1" or "TestLoopValve2" or "CirculatingWaterTemperature";
@@ -32,6 +33,7 @@ public partial class ValveControlChannel : ObservableObject
OnPropertyChanged(nameof(ActionText));
OnPropertyChanged(nameof(ToggleButtonText));
OnPropertyChanged(nameof(CirculatingWaterToggleText));
+ OnPropertyChanged(nameof(ReservoirToggleText));
OnPropertyChanged(nameof(IndicatorColor));
OnPropertyChanged(nameof(StateHint));
}
@@ -41,6 +43,7 @@ public partial class ValveControlChannel : ObservableObject
OnPropertyChanged(nameof(StateText));
OnPropertyChanged(nameof(ToggleButtonText));
OnPropertyChanged(nameof(CirculatingWaterToggleText));
+ OnPropertyChanged(nameof(ReservoirToggleText));
OnPropertyChanged(nameof(IndicatorColor));
OnPropertyChanged(nameof(StateHint));
}
diff --git a/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs b/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
index 64a6006..987dd68 100644
--- a/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
+++ b/Cardiopulmonarybypasssystems/Services/ModbusTelemetryService.cs
@@ -70,7 +70,7 @@ public sealed class ModbusTelemetryService : IModbusTelemetryService, IDisposabl
private readonly List _pumpControls =
[
new() { Key = "NegativeAssistPump", Name = "负压泵", StartAddress = 0 },
- new() { Key = "PressureDropPump", Name = "压力降/抗塌陷泵", StartAddress = 1, FlowAddress = FlowRegisters["PressureDropPump"] },
+ new() { Key = "PressureDropPump", Name = "压力降泵", StartAddress = 1, FlowAddress = FlowRegisters["PressureDropPump"] },
new() { Key = "RecirculationMainPump", Name = "再循环主泵", StartAddress = 2, FlowAddress = FlowRegisters["RecirculationMainPump"] },
new() { Key = "RecirculationReturnPump", Name = "回流泵", StartAddress = 3, FlowAddress = FlowRegisters["RecirculationReturnPump"] },
new() { Key = "RecirculationDrainagePump", Name = "引流泵", StartAddress = 4, FlowAddress = FlowRegisters["RecirculationDrainagePump"] },