From 824c3e4df6385049dd908ce22461d7a9800cfadd Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Sun, 27 Jul 2025 21:58:50 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84CpuType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DMS.Application/DTOs/DeviceDto.cs | 2 +- DMS.Core/Enums/CpuType.cs | 15 +++ DMS.Core/Models/Device.cs | 2 +- DMS.Infrastructure.UnitTests/FakerHelper.cs | 2 +- DMS.Infrastructure/Entities/DbDevice.cs | 4 +- .../Services/S7BackgroundService.cs | 11 ++- DMS.WPF/Services/DataServices.cs | 92 +++++++++++++++++++ DMS.WPF/ViewModels/DevicesViewModel.cs | 36 ++++---- .../ViewModels/Items/DeviceItemViewModel.cs | 8 +- .../ViewModels/Items/VariableItemViewModel.cs | 2 +- DMS.WPF/ViewModels/SplashViewModel.cs | 4 + DMS.WPF/Views/Dialogs/DeviceDialog.xaml | 4 +- 12 files changed, 149 insertions(+), 33 deletions(-) create mode 100644 DMS.Core/Enums/CpuType.cs diff --git a/DMS.Application/DTOs/DeviceDto.cs b/DMS.Application/DTOs/DeviceDto.cs index e513e61..49a8d2a 100644 --- a/DMS.Application/DTOs/DeviceDto.cs +++ b/DMS.Application/DTOs/DeviceDto.cs @@ -15,7 +15,7 @@ public class DeviceDto public int Port { get; set; } public int Rack { get; set; } public int Slot { get; set; } - public string CpuType { get; set; } + public CpuType CpuType { get; set; } public DeviceType DeviceType { get; set; } public string OpcUaServerUrl { get; set; } public bool IsActive { get; set; } diff --git a/DMS.Core/Enums/CpuType.cs b/DMS.Core/Enums/CpuType.cs new file mode 100644 index 0000000..165b4dd --- /dev/null +++ b/DMS.Core/Enums/CpuType.cs @@ -0,0 +1,15 @@ +using System.ComponentModel; + +namespace DMS.Core.Enums; + +public enum CpuType +{ + [Description("S7-1200")] + S71200, + [Description("S7-1500")] + S71500, + [Description("S7-300")] + S7300, + [Description("S7-400")] + S7400 +} diff --git a/DMS.Core/Models/Device.cs b/DMS.Core/Models/Device.cs index 6b53ec2..63bd807 100644 --- a/DMS.Core/Models/Device.cs +++ b/DMS.Core/Models/Device.cs @@ -63,7 +63,7 @@ public class Device /// public List VariableTables { get; set; } = new(); - public string CpuType { get; set; } + public CpuType CpuType { get; set; } public DeviceType DeviceType { get; set; } public bool IsRunning { get; set; } } \ No newline at end of file diff --git a/DMS.Infrastructure.UnitTests/FakerHelper.cs b/DMS.Infrastructure.UnitTests/FakerHelper.cs index f0532eb..a45469c 100644 --- a/DMS.Infrastructure.UnitTests/FakerHelper.cs +++ b/DMS.Infrastructure.UnitTests/FakerHelper.cs @@ -25,7 +25,7 @@ namespace DMS.Infrastructure.UnitTests dbDevice.Protocol = ProtocolType.S7; dbDevice.Slot = 1; dbDevice.Rack = 0; - dbDevice.CpuType = "S7-1200"; + dbDevice.CpuType = CpuType.S71200; dbDevice.DeviceType = Core.Enums.DeviceType.SiemensPLC; return dbDevice; diff --git a/DMS.Infrastructure/Entities/DbDevice.cs b/DMS.Infrastructure/Entities/DbDevice.cs index 093b746..8427276 100644 --- a/DMS.Infrastructure/Entities/DbDevice.cs +++ b/DMS.Infrastructure/Entities/DbDevice.cs @@ -56,8 +56,8 @@ public class DbDevice /// /// /// - [SugarColumn(IsNullable = true)] - public string CpuType { get; set; } + [SugarColumn(ColumnDataType="varchar(20)",SqlParameterDbType=typeof(EnumToStringConvert))] + public CpuType CpuType { get; set; } /// /// 设备槽号 (针对PLC等设备)。 /// diff --git a/DMS.Infrastructure/Services/S7BackgroundService.cs b/DMS.Infrastructure/Services/S7BackgroundService.cs index 2624ace..ffe54c2 100644 --- a/DMS.Infrastructure/Services/S7BackgroundService.cs +++ b/DMS.Infrastructure/Services/S7BackgroundService.cs @@ -8,6 +8,7 @@ using DateTime = System.DateTime; using Microsoft.Extensions.Logging; using DMS.Application.Interfaces; using DMS.Core.Interfaces; +using CpuType = DMS.Core.Enums.CpuType; namespace DMS.Infrastructure.Services; @@ -378,12 +379,12 @@ public class S7BackgroundService : BackgroundService /// CPU类型的字符串表示。 /// 对应的S7.Net.CpuType枚举值。 /// 如果无法解析CPU类型字符串。 - private S7.Net.CpuType ConvertCpuType(string cpuTypeString) + private S7.Net.CpuType ConvertCpuType(CpuType cpuTypeString) { - if (Enum.TryParse(cpuTypeString, true, out S7.Net.CpuType cpuType)) - { - return cpuType; - } + // if (Enum.TryParse(cpuTypeString, true, out S7.Net.CpuType cpuType)) + // { + // return cpuType; + // } throw new ArgumentException($"无法解析CPU类型: {cpuTypeString}"); } diff --git a/DMS.WPF/Services/DataServices.cs b/DMS.WPF/Services/DataServices.cs index 7211299..13a0b46 100644 --- a/DMS.WPF/Services/DataServices.cs +++ b/DMS.WPF/Services/DataServices.cs @@ -447,4 +447,96 @@ public partial class DataServices : ObservableRecipient, IRecipient } } } + + /// + /// 将变量表关联到对应的设备上。 + /// + public void AssociateVariableTablesToDevices() + { + // 1. 创建一个字典,按 DeviceId 分组所有变量表,以便高效查找 + var variableTablesGroupedByDevice = _variableTables + .GroupBy(vt => vt.DeviceId) + .ToDictionary(g => g.Key, g => g.ToList()); + + foreach (var device in _devices) + { + // 获取当前设备应该关联的所有变量表 + List associatedVariableTables = new List(); + if (variableTablesGroupedByDevice.TryGetValue(device.Id, out var foundTables)) + { + associatedVariableTables = foundTables; + } + + // 创建一个HashSet,用于快速查找当前设备应有的变量表ID + var shouldHaveVariableTableIds = new HashSet(associatedVariableTables.Select(vt => vt.Id)); + + // 2. 移除不再关联的变量表 + // 从后往前遍历,避免在循环中修改集合导致索引问题 + for (int i = device.VariableTables.Count - 1; i >= 0; i--) + { + var existingVariableTable = device.VariableTables[i]; + if (!shouldHaveVariableTableIds.Contains(existingVariableTable.Id)) + { + device.VariableTables.RemoveAt(i); + } + } + + // 3. 添加新关联的变量表 + var currentlyHasVariableTableIds = new HashSet(device.VariableTables.Select(vt => vt.Id)); + foreach (var newVariableTable in associatedVariableTables) + { + if (!currentlyHasVariableTableIds.Contains(newVariableTable.Id)) + { + device.VariableTables.Add(newVariableTable); + } + // 如果已经存在,则不需要额外操作,因为 LoadVariableTables 已经更新了 _variableTables 中的实例 + } + } + } + + /// + /// 将变量关联到对应的变量表上。 + /// + public void AssociateVariablesToVariableTables() + { + // 1. 创建一个字典,按 VariableTableId 分组所有变量,以便高效查找 + var variablesGroupedByVariableTable = _variables + .GroupBy(v => v.VariableTableId) + .ToDictionary(g => g.Key, g => g.ToList()); + + foreach (var variableTable in _variableTables) + { + // 获取当前变量表应该关联的所有变量 + List associatedVariables = new List(); + if (variablesGroupedByVariableTable.TryGetValue(variableTable.Id, out var foundVariables)) + { + associatedVariables = foundVariables; + } + + // 创建一个HashSet,用于快速查找当前变量表应有的变量ID + var shouldHaveVariableIds = new HashSet(associatedVariables.Select(v => v.Id)); + + // 2. 移除不再关联的变量 + // 从后往前遍历,避免在循环中修改集合导致索引问题 + for (int i = variableTable.Variables.Count - 1; i >= 0; i--) + { + var existingVariable = variableTable.Variables[i]; + if (!shouldHaveVariableIds.Contains(existingVariable.Id)) + { + variableTable.Variables.RemoveAt(i); + } + } + + // 3. 添加新关联的变量 + var currentlyHasVariableIds = new HashSet(variableTable.Variables.Select(v => v.Id)); + foreach (var newVariable in associatedVariables) + { + if (!currentlyHasVariableIds.Contains(newVariable.Id)) + { + variableTable.Variables.Add(newVariable); + } + // 如果已经存在,则不需要额外操作,因为 LoadVariables 已经更新了 _variables 中的实例 + } + } + } } \ No newline at end of file diff --git a/DMS.WPF/ViewModels/DevicesViewModel.cs b/DMS.WPF/ViewModels/DevicesViewModel.cs index 88cfeaa..8772690 100644 --- a/DMS.WPF/ViewModels/DevicesViewModel.cs +++ b/DMS.WPF/ViewModels/DevicesViewModel.cs @@ -113,25 +113,25 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable PrimaryButContent = "添加设备" }; // 1. 显示添加设备对话框 - // DeviceItemViewModel device = await _dialogService.ShowDialogAsync(deviceDialogViewModel); - // // 如果用户取消或对话框未返回设备,则直接返回 - // if (device == null) - // { - // return; - // } + DeviceItemViewModel device = await _dialogService.ShowDialogAsync(deviceDialogViewModel); + // 如果用户取消或对话框未返回设备,则直接返回 + if (device == null) + { + return; + } - DeviceItemViewModel device = new DeviceItemViewModel() - { - Name = "Test", - Description = "Test Device", - IpAddress = "127.0.0.1", - Port = 8080, - Protocol = ProtocolType.S7, - CpuType = "S7-1200", - DeviceType = DeviceType.SiemensPLC, - IsActive = true, - - }; + // DeviceItemViewModel device = new DeviceItemViewModel() + // { + // Name = "Test", + // Description = "Test Device", + // IpAddress = "127.0.0.1", + // Port = 8080, + // Protocol = ProtocolType.S7, + // CpuType = "S7-1200", + // DeviceType = DeviceType.SiemensPLC, + // IsActive = true, + // + // }; CreateDeviceWithDetailsDto dto = new CreateDeviceWithDetailsDto(); diff --git a/DMS.WPF/ViewModels/Items/DeviceItemViewModel.cs b/DMS.WPF/ViewModels/Items/DeviceItemViewModel.cs index 5f27587..6078198 100644 --- a/DMS.WPF/ViewModels/Items/DeviceItemViewModel.cs +++ b/DMS.WPF/ViewModels/Items/DeviceItemViewModel.cs @@ -1,4 +1,6 @@ // 文件: DMS.WPF/ViewModels/Items/DeviceItemViewModel.cs + +using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using DMS.Application.DTOs; using DMS.Core.Enums; @@ -35,7 +37,7 @@ public partial class DeviceItemViewModel : ObservableObject private int _slot; [ObservableProperty] - private string _cpuType; + private CpuType _cpuType; [ObservableProperty] private DeviceType _deviceType; @@ -51,8 +53,8 @@ public partial class DeviceItemViewModel : ObservableObject [ObservableProperty] private string _status; - - public List VariableTables { get; set; } + + public ObservableCollection VariableTables { get; set; } = new(); public DeviceItemViewModel(DeviceDto dto) { diff --git a/DMS.WPF/ViewModels/Items/VariableItemViewModel.cs b/DMS.WPF/ViewModels/Items/VariableItemViewModel.cs index c88084e..704dfcc 100644 --- a/DMS.WPF/ViewModels/Items/VariableItemViewModel.cs +++ b/DMS.WPF/ViewModels/Items/VariableItemViewModel.cs @@ -29,7 +29,7 @@ public partial class VariableItemViewModel : ObservableObject private List? _mqttAliases; [ObservableProperty] - private SignalType _signalType; + private SignalType _signalType ; [ObservableProperty] private PollLevelType _pollLevel; diff --git a/DMS.WPF/ViewModels/SplashViewModel.cs b/DMS.WPF/ViewModels/SplashViewModel.cs index b9a2a9e..8ba5137 100644 --- a/DMS.WPF/ViewModels/SplashViewModel.cs +++ b/DMS.WPF/ViewModels/SplashViewModel.cs @@ -46,6 +46,10 @@ public partial class SplashViewModel : ObservableObject await _dataServices.LoadVariableTables(); await _dataServices.LoadVariables(); await _dataServices.LoadMenus(); + + _dataServices.AssociateVariableTablesToDevices(); + _dataServices.AssociateVariablesToVariableTables(); + // 可以在这里添加加载配置的逻辑 await Task.Delay(500); // 模拟耗时 diff --git a/DMS.WPF/Views/Dialogs/DeviceDialog.xaml b/DMS.WPF/Views/Dialogs/DeviceDialog.xaml index 0bfd0ba..fb46847 100644 --- a/DMS.WPF/Views/Dialogs/DeviceDialog.xaml +++ b/DMS.WPF/Views/Dialogs/DeviceDialog.xaml @@ -31,6 +31,8 @@ EnumType="{x:Type enums:DeviceType}" /> + @@ -125,7 +127,7 @@ HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" /> + ItemsSource="{Binding Source={StaticResource cpuType}}" />