监控配置保存
This commit is contained in:
@@ -13,51 +13,7 @@
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- 普通操作按钮 -->
|
||||
<Style x:Key="CmdBtn" TargetType="Button" BasedOn="{StaticResource MaterialDesignRaisedButton}">
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Padding" Value="12,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
</Style>
|
||||
|
||||
<!-- 危险/警告操作按钮(橙色/红色) -->
|
||||
<Style x:Key="WarnBtn" TargetType="Button" BasedOn="{StaticResource MaterialDesignRaisedButton}">
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Padding" Value="12,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
<Setter Property="Background" Value="#EF6C00"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
|
||||
<!-- 数字输入框 -->
|
||||
<Style x:Key="NumInput" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignOutlinedTextBox}">
|
||||
<Setter Property="Width" Value="100"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
</Style>
|
||||
|
||||
<!-- 测量值只读显示 -->
|
||||
<Style x:Key="MeasureBox" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignOutlinedTextBox}">
|
||||
<Setter Property="Width" Value="110"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="IsReadOnly" Value="True"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
<Setter Property="Background" Value="#F5F5F5"/>
|
||||
</Style>
|
||||
|
||||
<!-- 标签 -->
|
||||
<Style x:Key="ParamLabel" TargetType="TextBlock">
|
||||
<Setter Property="Width" Value="80"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="0,0,4,0"/>
|
||||
</Style>
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
|
||||
@@ -12,47 +12,6 @@
|
||||
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<Style x:Key="CmdBtn" TargetType="Button" BasedOn="{StaticResource MaterialDesignRaisedButton}">
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Padding" Value="12,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="WarnBtn" TargetType="Button" BasedOn="{StaticResource MaterialDesignRaisedButton}">
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Padding" Value="12,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
<Setter Property="Background" Value="#EF6C00"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="NumInput" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignOutlinedTextBox}">
|
||||
<Setter Property="Width" Value="100"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MeasureBox" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignOutlinedTextBox}">
|
||||
<Setter Property="Width" Value="110"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="IsReadOnly" Value="True"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="4,0"/>
|
||||
<Setter Property="Background" Value="#F5F5F5"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ParamLabel" TargetType="TextBlock">
|
||||
<Setter Property="Width" Value="80"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="0,0,4,0"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Common.Attributes;
|
||||
using Model.Entity;
|
||||
using Model.Models;
|
||||
using NLog;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
@@ -19,6 +20,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using UIShare.GlobalVariable;
|
||||
using UIShare.PubEvent;
|
||||
using UIShare.UIViewModel;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
|
||||
@@ -42,13 +44,25 @@ namespace MonitorModule.ViewModels
|
||||
public PlotModel Plot { get; }
|
||||
|
||||
/// <summary>已添加的监测通道列表</summary>
|
||||
public ObservableCollection<MonitorChannel> Channels { get; } = new();
|
||||
public ObservableCollection<MonitorChannelVM> Channels
|
||||
{
|
||||
get => _systemConfig?.Channels ?? new ObservableCollection<MonitorChannelVM>();
|
||||
set
|
||||
{
|
||||
if (_systemConfig != null && _systemConfig.Channels != value)
|
||||
{
|
||||
_systemConfig.Channels = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>可添加的设备方法列表(供用户选择)</summary>
|
||||
public ObservableCollection<AvailableMethodItem> AvailableMethods { get; } = new();
|
||||
|
||||
private MonitorChannel? _selectedChannel;
|
||||
public MonitorChannel? SelectedChannel
|
||||
private MonitorChannelVM? _selectedChannel;
|
||||
public MonitorChannelVM? SelectedChannel
|
||||
{
|
||||
get => _selectedChannel;
|
||||
set => SetProperty(ref _selectedChannel, value);
|
||||
@@ -75,12 +89,14 @@ namespace MonitorModule.ViewModels
|
||||
public ICommand ResetViewCommand { get; }
|
||||
public ICommand RefreshDataCommand { get; }
|
||||
public ICommand RefreshCommand { get; }
|
||||
public ICommand SaveCommand { get; }
|
||||
#endregion
|
||||
|
||||
#region 私有字段
|
||||
private bool IsInitiated = false;
|
||||
private IScopedProvider? _scope;
|
||||
private DeviceManager? _deviceManager;
|
||||
private SystemConfig? _systemConfig;
|
||||
private CancellationTokenSource? _monitorCTS = new();
|
||||
|
||||
// 颜色调色盘
|
||||
@@ -125,6 +141,7 @@ namespace MonitorModule.ViewModels
|
||||
ResetViewCommand = new DelegateCommand(OnResetView);
|
||||
RefreshDataCommand = new DelegateCommand(OnRefreshData);
|
||||
RefreshCommand = new DelegateCommand(OnExpand);
|
||||
SaveCommand = new DelegateCommand(OnSave);
|
||||
|
||||
// OxyPlot 刷新定时器(1000ms,只负责视觉更新)
|
||||
_plotRefreshTimer = new DispatcherTimer(DispatcherPriority.Background)
|
||||
@@ -134,6 +151,8 @@ namespace MonitorModule.ViewModels
|
||||
_plotRefreshTimer.Tick += OnPlotRefreshTick;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_monitorCTS?.Cancel();
|
||||
@@ -159,7 +178,21 @@ namespace MonitorModule.ViewModels
|
||||
Channels.Clear();
|
||||
AvailableMethods.Clear();
|
||||
}
|
||||
|
||||
private void OnSave()
|
||||
{
|
||||
// 将当前 Channels 序列化为 MonitorChannelConfig 列表保存到 MonitorChannels
|
||||
if (_systemConfig != null)
|
||||
{
|
||||
_systemConfig.MonitorChannels = new ObservableCollection<MonitorChannelConfig>(Channels
|
||||
.Select(c => new MonitorChannelConfig
|
||||
{
|
||||
Fingerprint = c.Fingerprint,
|
||||
MethodName = c.MethodName,
|
||||
IsDisplayed = c.IsDisplayed
|
||||
}));
|
||||
}
|
||||
ConfigService.Save(_systemConfig);
|
||||
}
|
||||
#region 事件驱动:接收广播数据
|
||||
/// <summary>
|
||||
/// 由 HardwareDataBroadcaster 通过 EventAggregator 广播触发。
|
||||
@@ -275,6 +308,8 @@ namespace MonitorModule.ViewModels
|
||||
_scope = _globalInfo.ScopeDic[TestStatus];
|
||||
_scopedContext = _scope.Resolve<ScopedContext>();
|
||||
_deviceManager = _scope.Resolve<DeviceManager>();
|
||||
_systemConfig = _scope.Resolve<SystemConfig>();
|
||||
RaisePropertyChanged(nameof(Channels));
|
||||
_broadcaster = _scope.Resolve<HardwareDataBroadcaster>();
|
||||
IsInitiated = true;
|
||||
|
||||
@@ -286,15 +321,18 @@ namespace MonitorModule.ViewModels
|
||||
// 2. 扫描可监测方法(供 UI 选择)
|
||||
DiscoverAvailableMethods();
|
||||
|
||||
// 3. 启动广播器(Discover + Start)
|
||||
// 3. 从配置自动恢复已保存的监测通道
|
||||
RestoreChannelsFromConfig();
|
||||
|
||||
// 4. 启动广播器(Discover + Start)
|
||||
_broadcaster.Discover();
|
||||
_broadcaster.Start();
|
||||
|
||||
// 4. 订阅 HardwareDataReportedEvent(UI 线程回调)
|
||||
// 5. 订阅 HardwareDataReportedEvent(UI 线程回调)
|
||||
_subscriptionToken = _eventAggregator.GetEvent<HardwareDataReportedEvent>()
|
||||
.Subscribe(OnHardwareDataReceived, ThreadOption.UIThread);
|
||||
|
||||
// 5. 启动 OxyPlot 视觉刷新定时器
|
||||
// 6. 启动 OxyPlot 视觉刷新定时器
|
||||
_stopwatch.Start();
|
||||
_plotRefreshTimer.Start();
|
||||
}
|
||||
@@ -404,6 +442,72 @@ namespace MonitorModule.ViewModels
|
||||
? $"发现 {AvailableMethods.Count} 个可监测项"
|
||||
: "未发现可监测的设备方法";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 SystemConfig.MonitorChannels 持久化列表自动还原监测通道。
|
||||
/// </summary>
|
||||
private void RestoreChannelsFromConfig()
|
||||
{
|
||||
if (_systemConfig?.MonitorChannels == null || _systemConfig.MonitorChannels.Count == 0) return;
|
||||
if (AvailableMethods.Count == 0) return;
|
||||
|
||||
int restored = 0;
|
||||
foreach (var config in _systemConfig.MonitorChannels)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(config.Fingerprint) ||
|
||||
string.IsNullOrWhiteSpace(config.MethodName)) continue;
|
||||
|
||||
// 已在 Channels 中存在则跳过
|
||||
if (Channels.Any(c => c.Fingerprint == config.Fingerprint && c.MethodName == config.MethodName))
|
||||
continue;
|
||||
|
||||
// 在 AvailableMethods 中查找匹配项
|
||||
var method = AvailableMethods.FirstOrDefault(m =>
|
||||
m.Fingerprint == config.Fingerprint && m.MethodName == config.MethodName);
|
||||
if (method == null) continue;
|
||||
|
||||
var color = _palette[_colorIndex % _palette.Length];
|
||||
_colorIndex++;
|
||||
|
||||
var channel = new MonitorChannelVM
|
||||
{
|
||||
DeviceName = method.DeviceName,
|
||||
Fingerprint = method.Fingerprint,
|
||||
MethodName = method.MethodName,
|
||||
DisplayName = method.DisplayName,
|
||||
Color = color,
|
||||
IsMonitored = true,
|
||||
IsDisplayed = config.IsDisplayed
|
||||
};
|
||||
|
||||
// 仅当 IsDisplayed=true 时才创建 LineSeries
|
||||
if (channel.IsDisplayed)
|
||||
{
|
||||
channel.Series = new LineSeries
|
||||
{
|
||||
Title = channel.DisplayName,
|
||||
Color = color,
|
||||
StrokeThickness = 1.5
|
||||
};
|
||||
Plot.Series.Add(channel.Series);
|
||||
}
|
||||
|
||||
channel.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(MonitorChannelVM.IsDisplayed))
|
||||
OnChannelDisplayChanged(channel);
|
||||
};
|
||||
|
||||
Channels.Add(channel);
|
||||
restored++;
|
||||
}
|
||||
|
||||
if (restored > 0)
|
||||
{
|
||||
Plot.InvalidatePlot(true);
|
||||
StatusMessage = $"已从配置自动恢复 {restored} 个监测通道";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 命令处理
|
||||
@@ -426,7 +530,7 @@ namespace MonitorModule.ViewModels
|
||||
var color = _palette[_colorIndex % _palette.Length];
|
||||
_colorIndex++;
|
||||
|
||||
var channel = new MonitorChannel
|
||||
var channel = new MonitorChannelVM
|
||||
{
|
||||
DeviceName = method.DeviceName,
|
||||
Fingerprint = method.Fingerprint,
|
||||
@@ -447,7 +551,7 @@ namespace MonitorModule.ViewModels
|
||||
|
||||
channel.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(MonitorChannel.IsDisplayed))
|
||||
if (e.PropertyName == nameof(MonitorChannelVM.IsDisplayed))
|
||||
OnChannelDisplayChanged(channel);
|
||||
};
|
||||
|
||||
@@ -497,7 +601,7 @@ namespace MonitorModule.ViewModels
|
||||
#endregion
|
||||
|
||||
#region 显示/隐藏切换与数学变换
|
||||
public void OnChannelDisplayChanged(MonitorChannel channel)
|
||||
public void OnChannelDisplayChanged(MonitorChannelVM channel)
|
||||
{
|
||||
if (channel.IsDisplayed)
|
||||
{
|
||||
@@ -530,7 +634,7 @@ namespace MonitorModule.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public void OnChannelMathChanged(MonitorChannel channel)
|
||||
public void OnChannelMathChanged(MonitorChannelVM channel)
|
||||
{
|
||||
if (channel.Series == null) return;
|
||||
var points = channel.DataPoints.ToArray();
|
||||
|
||||
@@ -89,6 +89,10 @@
|
||||
Command="{Binding RefreshDataCommand}"
|
||||
Padding="12,4" Margin="6,0,0,0"
|
||||
ToolTip="重新绘制图表"/>
|
||||
<Button Content=" 保存"
|
||||
Command="{Binding SaveCommand}"
|
||||
Padding="12,4" Margin="6,0,0,0"
|
||||
ToolTip="保存到配置文件"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@@ -33,6 +33,12 @@ namespace UIShare.GlobalVariable
|
||||
public ObservableCollection<CANSignalConfig> ConfigurationList = new();
|
||||
public ObservableCollection<AutoDBCLoadItem> dbcAutoLoadList = new();
|
||||
public ObservableCollection<ValueLimitVM> ValueLimitList = new();
|
||||
[JsonIgnore]
|
||||
public ObservableCollection<MonitorChannelVM> Channels = new();
|
||||
/// <summary>
|
||||
/// 监测通道持久化配置列表(包含 Fingerprint、MethodName、IsDisplayed)
|
||||
/// </summary>
|
||||
public ObservableCollection<MonitorChannelConfig> MonitorChannels = new();
|
||||
public ZLGCANFD CANFD = new();
|
||||
[JsonIgnore]
|
||||
public ObservableCollection<ParameterVM> ParameterList = new()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<PackageReference Include="MaterialDesignThemes" Version="5.3.0" />
|
||||
<PackageReference Include="MaterialDesignThemes.MahApps" Version="5.3.0" />
|
||||
<PackageReference Include="Notifications.Wpf.Core" Version="2.0.1" />
|
||||
<PackageReference Include="OxyPlot.Wpf" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Concurrent;
|
||||
using Prism.Mvvm;
|
||||
using NCalc;
|
||||
|
||||
namespace MonitorModule.ViewModels
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 监测通道:一个设备方法对应一个通道。
|
||||
@@ -12,7 +12,7 @@ namespace MonitorModule.ViewModels
|
||||
/// - IsMonitored=true 时始终记录 DataPoints
|
||||
/// - IsDisplayed=true 时才创建 LineSeries 并绘制
|
||||
/// </summary>
|
||||
public class MonitorChannel : BindableBase
|
||||
public class MonitorChannelVM : BindableBase
|
||||
{
|
||||
// ===== 标识 =====
|
||||
public string DeviceName { get; init; } = string.Empty;
|
||||
17
UIShare/UIViewModel/MonitorChannelConfig.cs
Normal file
17
UIShare/UIViewModel/MonitorChannelConfig.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace UIShare.UIViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 监测通道持久化配置(用于 JSON 保存/恢复)。
|
||||
/// </summary>
|
||||
public class MonitorChannelConfig
|
||||
{
|
||||
/// <summary>硬件指纹(物理设备唯一标识)</summary>
|
||||
public string Fingerprint { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>监测方法名</summary>
|
||||
public string MethodName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>是否在图表上显示该通道的线图</summary>
|
||||
public bool IsDisplayed { get; set; } = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user