diff --git a/Data/Entities/DbDevice.cs b/Data/Entities/DbDevice.cs index ceb9b3f..e9d217f 100644 --- a/Data/Entities/DbDevice.cs +++ b/Data/Entities/DbDevice.cs @@ -2,7 +2,7 @@ using PMSWPF.Enums; using SqlSugar; using SqlSugar.DbConvert; using ProtocolType = PMSWPF.Enums.ProtocolType; -using S7.Net; // Add this using directive +using S7.Net; // AddAsync this using directive namespace PMSWPF.Data.Entities; diff --git a/Helper/ThemeHelper.cs b/Helper/ThemeHelper.cs index 70c5047..f5dccc3 100644 --- a/Helper/ThemeHelper.cs +++ b/Helper/ThemeHelper.cs @@ -66,7 +66,7 @@ public static class ThemeHelper ? "pack://application:,,,/HandyControl;component/Themes/SkinDark.xaml" : "pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"; - // Add the new skin dictionary + // AddAsync the new skin dictionary dictionaries.Add(new ResourceDictionary { Source = new Uri(skinUri, UriKind.Absolute) }); // To force refresh of dynamic resources, remove and re-add the main theme dictionary diff --git a/Models/Device.cs b/Models/Device.cs index a42cd26..ed7d4ba 100644 --- a/Models/Device.cs +++ b/Models/Device.cs @@ -3,7 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using PMSWPF.Enums; using SqlSugar; using SqlSugar.DbConvert; -using S7.Net; // Add this using directive +using S7.Net; // AddAsync this using directive namespace PMSWPF.Models; @@ -42,6 +42,12 @@ public partial class Device : ObservableObject [ObservableProperty] private bool isActive = true; + public event Action OnDeviceIsActiveChanged ; + + partial void OnIsActiveChanged(bool isActive){ + OnDeviceIsActiveChanged?.Invoke(this,isActive); + } + /// /// 表示是否添加默认变量表。 /// diff --git a/Services/DataServices.cs b/Services/DataServices.cs index c736036..884c610 100644 --- a/Services/DataServices.cs +++ b/Services/DataServices.cs @@ -150,7 +150,7 @@ public partial class DataServices : ObservableRecipient, IRecipient } } - Devices = await _deviceRepository.GetAll(); + Devices = await _deviceRepository.GetAllAsync(); // 订阅新设备的属性变更事件 if (Devices != null) @@ -189,7 +189,7 @@ public partial class DataServices : ObservableRecipient, IRecipient /// 表示异步操作的任务。 private async Task LoadMenus() { - MenuTrees = await _menuRepository.GetMenuTrees(); + MenuTrees = await _menuRepository.GetMenuTreesAsync(); foreach (MenuBean menu in MenuTrees) { MenuHelper.MenuAddParent(menu); // 为菜单添加父级引用 @@ -205,7 +205,7 @@ public partial class DataServices : ObservableRecipient, IRecipient /// 包含所有MQTT配置的列表。 public async Task> GetMqttsAsync() { - var mqtts = await _mqttRepository.GetAll(); + var mqtts = await _mqttRepository.GetAllAsync(); OnMqttListChanged?.Invoke(mqtts); return mqtts; } @@ -216,7 +216,7 @@ public partial class DataServices : ObservableRecipient, IRecipient /// 表示异步操作的任务。 private async Task LoadMqtts() { - Mqtts = await _mqttRepository.GetAll(); + Mqtts = await _mqttRepository.GetAllAsync(); } @@ -227,7 +227,7 @@ public partial class DataServices : ObservableRecipient, IRecipient /// 设备对象,如果不存在则为null。 public async Task GetDeviceByIdAsync(int id) { - return await _deviceRepository.GetById(id); + return await _deviceRepository.GetByIdAsync(id); } /// diff --git a/Services/MqttBackgroundService.cs b/Services/MqttBackgroundService.cs index c143430..e919ec1 100644 --- a/Services/MqttBackgroundService.cs +++ b/Services/MqttBackgroundService.cs @@ -4,6 +4,7 @@ using MQTTnet.Client; using MQTTnet.Client.Connecting; using MQTTnet.Client.Disconnecting; using MQTTnet.Client.Options; +using PMSWPF.Data.Repositories; using PMSWPF.Helper; using PMSWPF.Models; @@ -16,6 +17,7 @@ namespace PMSWPF.Services { // 数据服务实例,用于访问和操作应用程序数据,如MQTT配置和变量数据。 private readonly DataServices _dataServices; + private readonly MqttRepository _mqttRepository; // 存储MQTT客户端实例的字典,键为MQTT配置ID,值为IMqttClient对象。 private readonly Dictionary _mqttClients; @@ -38,9 +40,10 @@ namespace PMSWPF.Services /// 构造函数,注入DataServices。 /// /// 数据服务实例。 - public MqttBackgroundService(DataServices dataServices) + public MqttBackgroundService(DataServices dataServices, MqttRepository mqttRepository) { _dataServices = dataServices; + _mqttRepository = mqttRepository; _mqttClients = new Dictionary(); _mqttConfigDic = new Dictionary(); _reconnectAttempts = new Dictionary(); @@ -132,7 +135,7 @@ namespace PMSWPF.Services } catch (Exception e) { - NlogHelper.Error($"MqttID:{mqttId},断开连接的过程中发生了错误:{e.Message}",e); + NlogHelper.Error($"MqttID:{mqttId},断开连接的过程中发生了错误:{e.Message}", e); } } } @@ -195,6 +198,9 @@ namespace PMSWPF.Services _mqttClients.Remove(mqtt.Id); NlogHelper.Info($"{mqtt.Name}的客户端,与服务器断开连接."); } + + await _mqttRepository.UpdateAsync(mqtt); + NotificationHelper.ShowSuccess($"Mqtt客户端:{mqtt.Name},激活状态修改成功。"); } catch (Exception e) { diff --git a/ValueConverts/EnumDescriptionConverter.cs b/ValueConverts/EnumDescriptionConverter.cs index 33bbfb4..e09b9ed 100644 --- a/ValueConverts/EnumDescriptionConverter.cs +++ b/ValueConverts/EnumDescriptionConverter.cs @@ -22,7 +22,7 @@ public class EnumDescriptionConverter : IValueConverter private string GetEnumDescription(object enumObj) { - if (enumObj == null) return null; // Add null check here + if (enumObj == null) return null; // AddAsync null check here var fi = enumObj.GetType().GetField(enumObj.ToString()); diff --git a/ViewModels/DeviceDetailViewModel.cs b/ViewModels/DeviceDetailViewModel.cs index de52fdf..cf0db0c 100644 --- a/ViewModels/DeviceDetailViewModel.cs +++ b/ViewModels/DeviceDetailViewModel.cs @@ -1,7 +1,10 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.DependencyInjection; +using PMSWPF.Data; using PMSWPF.Data.Repositories; +using PMSWPF.Enums; using PMSWPF.Helper; using PMSWPF.Models; using PMSWPF.Services; @@ -12,6 +15,8 @@ public partial class DeviceDetailViewModel : ViewModelBase { private readonly IDialogService _dialogService; private readonly VarTableRepository _varTableRepository; + private readonly MenuRepository _menuRepository; + private readonly DataServices _dataServices; [ObservableProperty] private Device _currentDevice; @@ -19,10 +24,12 @@ public partial class DeviceDetailViewModel : ViewModelBase [ObservableProperty] private VariableTable _selectedVariableTable; - public DeviceDetailViewModel(IDialogService dialogService, VarTableRepository varTableRepository) + public DeviceDetailViewModel(IDialogService dialogService, VarTableRepository varTableRepository, MenuRepository menuRepository, DataServices dataServices) { _dialogService = dialogService; _varTableRepository = varTableRepository; + _menuRepository = menuRepository; + _dataServices = dataServices; } public override void OnLoaded() @@ -42,25 +49,55 @@ public partial class DeviceDetailViewModel : ViewModelBase [RelayCommand] private async Task AddVariableTable() { + + using var db = DbContext.GetInstance(); try { + // 1. Show dialog to get new variable table details var newVarTable = await _dialogService.ShowAddVarTableDialog(); - if (newVarTable == null) return; + if (newVarTable == null) return; // User cancelled + // 2. Set properties for the new variable table newVarTable.DeviceId = CurrentDevice.Id; - newVarTable = await _varTableRepository.AddAsync(newVarTable); - if (newVarTable != null) + newVarTable.ProtocolType = CurrentDevice.ProtocolType; + newVarTable.IsActive = true; + + // 3. Find the parent menu for the current device + var parentMenu = DataServicesHelper.FindMenusForDevice(CurrentDevice, _dataServices.MenuTrees); + if (parentMenu == null) { - CurrentDevice.VariableTables.Add(newVarTable); - NotificationHelper.ShowSuccess($"变量表 {newVarTable.Name} 添加成功。"); + NotificationHelper.ShowError("无法找到当前设备的父级菜单,无法添加变量表菜单。"); + return; } - else + + // 4. Start database transaction + await db.BeginTranAsync(); + + // 5. AddAsync variable table to the database + var addedVarTable = await _varTableRepository.AddAsync(newVarTable, db); + + // 6. Create and add the corresponding menu item + var newMenu = new MenuBean { - NotificationHelper.ShowError($"变量表 {newVarTable.Name} 添加失败。"); - } + Name = addedVarTable.Name, + DataId = addedVarTable.Id, + Type = MenuType.VariableTableMenu, + ParentId = parentMenu.Id, + Icon = iNKORE.UI.WPF.Modern.Common.IconKeys.SegoeFluentIcons.Tablet.Glyph + }; + await _menuRepository.AddAsync(newMenu, db); + + // 7. Commit transaction + await db.CommitTranAsync(); + + // 8. Update UI + CurrentDevice.VariableTables.Add(addedVarTable); + MessageHelper.SendLoadMessage(Enums.LoadTypes.Menu); // Refresh the main navigation menu + NotificationHelper.ShowSuccess($"变量表 {addedVarTable.Name} 添加成功。"); } catch (Exception ex) { + await db.RollbackTranAsync(); NotificationHelper.ShowError($"添加变量表时发生错误: {ex.Message}", ex); } } @@ -148,4 +185,14 @@ public partial class DeviceDetailViewModel : ViewModelBase NotificationHelper.ShowInfo("删除设备功能待实现。"); await Task.CompletedTask; } + + [RelayCommand] + private void NavigateToVariableTable() + { + if (SelectedVariableTable == null) return; + + var variableTableVm = App.Current.Services.GetRequiredService(); + variableTableVm.VariableTable = SelectedVariableTable; + MessageHelper.SendNavgatorMessage(variableTableVm); + } } \ No newline at end of file diff --git a/ViewModels/DevicesViewModel.cs b/ViewModels/DevicesViewModel.cs index 18eea89..1e9cb67 100644 --- a/ViewModels/DevicesViewModel.cs +++ b/ViewModels/DevicesViewModel.cs @@ -30,6 +30,7 @@ public partial class DevicesViewModel : ViewModelBase [ObservableProperty] private ObservableCollection _devices; + /// /// 当前选中的设备。 /// @@ -64,6 +65,37 @@ public partial class DevicesViewModel : ViewModelBase if (_dataServices.Devices!=null && _dataServices.Devices.Count>0) { Devices=new ObservableCollection(_dataServices.Devices); + foreach (var device in Devices) + { + device.OnDeviceIsActiveChanged += HandleDeviceIsActiveChanged; + + } + } + } + + public override Task OnExitAsync() + { + if (_dataServices.Devices!=null && _dataServices.Devices.Count>0) + { + foreach (var device in Devices) + { + device.OnDeviceIsActiveChanged -= HandleDeviceIsActiveChanged; + } + } + + return Task.FromResult(true); + } + + private async void HandleDeviceIsActiveChanged(Device device, bool isActive) + { + try + { + await _deviceRepository.UpdateAsync(device); + NotificationHelper.ShowSuccess($"设备 {device.Name} 的激活状态已更新。"); + } + catch (Exception ex) + { + NotificationHelper.ShowError($"更新设备 {device.Name} 激活状态失败: {ex.Message}", ex); } } @@ -87,7 +119,7 @@ public partial class DevicesViewModel : ViewModelBase if (device.ProtocolType == ProtocolType.OpcUA) device.OpcUaEndpointUrl = $"opc.tcp://{device.Ip}:{device.Prot}"; - await _deviceRepository.Add(device); + await _deviceRepository.AddAsync(device); } catch (Exception e) { @@ -116,7 +148,7 @@ public partial class DevicesViewModel : ViewModelBase { // 删除设备 - await _deviceRepository.Delete(SelectedDevice ,_dataServices.MenuTrees); + await _deviceRepository.DeleteAsync(SelectedDevice ,_dataServices.MenuTrees); MessageHelper.SendLoadMessage(LoadTypes.Menu); MessageHelper.SendLoadMessage(LoadTypes.Devices); @@ -147,10 +179,10 @@ public partial class DevicesViewModel : ViewModelBase if (editDievce != null) { // 更新菜单 - var res = await _deviceRepository.Edit(editDievce); + var res = await _deviceRepository.UpdateAsync(editDievce); var menu = DataServicesHelper.FindMenusForDevice(editDievce, _dataServices.MenuTrees); if (menu != null) - await _menuRepository.Edit(menu); + await _menuRepository.UpdateAsync(menu); MessageHelper.SendLoadMessage(LoadTypes.Menu); MessageHelper.SendLoadMessage(LoadTypes.Devices); diff --git a/ViewModels/Dialogs/DeviceDialogViewModel.cs b/ViewModels/Dialogs/DeviceDialogViewModel.cs index e7c6958..3bf45c2 100644 --- a/ViewModels/Dialogs/DeviceDialogViewModel.cs +++ b/ViewModels/Dialogs/DeviceDialogViewModel.cs @@ -1,7 +1,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using PMSWPF.Models; -using S7.Net; // Add this using directive +using S7.Net; // AddAsync this using directive namespace PMSWPF.ViewModels.Dialogs; @@ -25,7 +25,7 @@ public partial class DeviceDialogViewModel : ObservableObject _device = device; } - // Add a property to expose CpuType enum values for ComboBox + // AddAsync a property to expose CpuType enum values for ComboBox public Array CpuTypes => Enum.GetValues(typeof(CpuType)); diff --git a/ViewModels/Dialogs/MqttSelectionDialogViewModel.cs b/ViewModels/Dialogs/MqttSelectionDialogViewModel.cs index 97a32a0..469455b 100644 --- a/ViewModels/Dialogs/MqttSelectionDialogViewModel.cs +++ b/ViewModels/Dialogs/MqttSelectionDialogViewModel.cs @@ -26,7 +26,7 @@ public partial class MqttSelectionDialogViewModel : ObservableObject { try { - var allMqtts = await _mqttRepository.GetAll(); + var allMqtts = await _mqttRepository.GetAllAsync(); Mqtts = new ObservableCollection(allMqtts); } catch (Exception ex) diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 053926f..77f835c 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -13,8 +13,8 @@ using PMSWPF.Models; using PMSWPF.Services; using PMSWPF.Views; -// Add this using directive -// Add this using directive +// AddAsync this using directive +// AddAsync this using directive namespace PMSWPF.ViewModels; @@ -126,7 +126,7 @@ public partial class MainViewModel : ViewModelBase // 假设 _varTableRepository.AddAsync 返回一个布尔值表示成功,或者一个表示 ID 的整数 // 这里为了演示,我们假设它返回新添加的ID,如果失败则返回0 await db.BeginTranAsync(); - var addVarTable = await _varTableRepository.Add(varTable, db); + var addVarTable = await _varTableRepository.AddAsync(varTable, db); // 5. 添加变量表菜单 MenuBean newMenu = new MenuBean @@ -138,7 +138,7 @@ public partial class MainViewModel : ViewModelBase ParentId = menu.Parent.Id }; - var addMenuRes = await _menuRepository.Add(newMenu, db); + var addMenuRes = await _menuRepository.AddAsync(newMenu, db); if (addMenuRes > 0) { await db.CommitTranAsync(); diff --git a/ViewModels/MqttServerDetailViewModel.cs b/ViewModels/MqttServerDetailViewModel.cs index 28acc3d..8504bab 100644 --- a/ViewModels/MqttServerDetailViewModel.cs +++ b/ViewModels/MqttServerDetailViewModel.cs @@ -132,7 +132,7 @@ namespace PMSWPF.ViewModels // 例如:var selectedVariables = await _dialogService.ShowVariableSelectionDialogAsync(); // 这里只是一个占位符,实际需要一个UI来选择变量 NotificationHelper.ShowInfo("添加变量功能待实现,需要一个变量选择对话框。"); - _logger.LogInformation("Add variables to MQTT server initiated."); + _logger.LogInformation("AddAsync variables to MQTT server initiated."); // 假设我们已经通过对话框获取到了一些要添加的变量 // List newVariables = ...; @@ -141,9 +141,9 @@ namespace PMSWPF.ViewModels // if (variable.Mqtts == null) variable.Mqtts = new List(); // if (!variable.Mqtts.Any(m => m.Id == CurrentMqtt.Id)) // { - // variable.Mqtts.Add(CurrentMqtt); + // variable.Mqtts.AddAsync(CurrentMqtt); // variable.IsModified = true; // 标记为已修改 - // AssociatedVariables.Add(variable); + // AssociatedVariables.AddAsync(variable); // } // } // NotificationHelper.ShowMessage("变量添加成功,请记得保存更改。", NotificationType.Success); diff --git a/ViewModels/MqttsViewModel.cs b/ViewModels/MqttsViewModel.cs index 0a020bd..35519b3 100644 --- a/ViewModels/MqttsViewModel.cs +++ b/ViewModels/MqttsViewModel.cs @@ -84,7 +84,7 @@ public partial class MqttsViewModel : ViewModelBase { try { - await _mqttRepository.Edit(mqtt); + await _mqttRepository.UpdateAsync(mqtt); NotificationHelper.ShowSuccess($"MQTT: {mqtt.Name} 的启用状态已更新。"); MessageHelper.SendLoadMessage(LoadTypes.Mqtts); } @@ -108,7 +108,7 @@ public partial class MqttsViewModel : ViewModelBase return; } - await _mqttRepository.Add(mqtt); + await _mqttRepository.AddAsync(mqtt); MessageHelper.SendLoadMessage(LoadTypes.Mqtts); MessageHelper.SendLoadMessage(LoadTypes.Menu); } @@ -133,7 +133,7 @@ public partial class MqttsViewModel : ViewModelBase var isDel = await _dialogService.ShowConfrimeDialog("删除MQTT", msg, "删除MQTT"); if (isDel) { - await _mqttRepository.Delete(SelectedMqtt); + await _mqttRepository.DeleteAsync(SelectedMqtt); MessageHelper.SendLoadMessage(LoadTypes.Mqtts); MessageHelper.SendLoadMessage(LoadTypes.Menu); NotificationHelper.ShowSuccess($"删除MQTT成功,MQTT名:{SelectedMqtt.Name}"); @@ -159,7 +159,7 @@ public partial class MqttsViewModel : ViewModelBase var editMqtt = await _dialogService.ShowEditMqttDialog(SelectedMqtt); if (editMqtt != null) { - var res = await _mqttRepository.Edit(editMqtt); + var res = await _mqttRepository.UpdateAsync(editMqtt); MessageHelper.SendLoadMessage(LoadTypes.Mqtts); } } diff --git a/ViewModels/SettingViewModel.cs b/ViewModels/SettingViewModel.cs index 09aa293..326405b 100644 --- a/ViewModels/SettingViewModel.cs +++ b/ViewModels/SettingViewModel.cs @@ -14,17 +14,11 @@ namespace PMSWPF.ViewModels; public partial class SettingViewModel : ViewModelBase { private ConnectionSettings _connectionSettings; - private readonly S7BackgroundService _s7BackgroundService; - private readonly MqttBackgroundService _mqttBackgroundService; - private readonly OpcUaBackgroundService _opcUaBackgroundService; - public SettingViewModel(S7BackgroundService s7BackgroundService, MqttBackgroundService mqttBackgroundService, OpcUaBackgroundService opcUaBackgroundService) + public SettingViewModel() { _connectionSettings = ConnectionSettings.Load(); AvailableDbTypes = Enum.GetNames(typeof(SqlSugar.DbType)).ToList(); - _s7BackgroundService = s7BackgroundService; - _mqttBackgroundService = mqttBackgroundService; - _opcUaBackgroundService = opcUaBackgroundService; Themes = new List { "浅色", "深色", "跟随系统" }; } @@ -131,72 +125,6 @@ public partial class SettingViewModel : ViewModelBase } } - public bool EnableS7Service - { - get => _connectionSettings.EnableS7Service; - set - { - if (_connectionSettings.EnableS7Service != value) - { - _connectionSettings.EnableS7Service = value; - OnPropertyChanged(); - _connectionSettings.Save(); - if (value) - { - // _s7BackgroundService.StartService(); - } - else - { - // _s7BackgroundService.StopService(); - } - } - } - } - - public bool EnableMqttService - { - get => _connectionSettings.EnableMqttService; - set - { - if (_connectionSettings.EnableMqttService != value) - { - _connectionSettings.EnableMqttService = value; - OnPropertyChanged(); - _connectionSettings.Save(); - if (value) - { - _mqttBackgroundService.StartService(); - } - else - { - _mqttBackgroundService.StopService(); - } - } - } - } - - public bool EnableOpcUaService - { - get => _connectionSettings.EnableOpcUaService; - set - { - if (_connectionSettings.EnableOpcUaService != value) - { - _connectionSettings.EnableOpcUaService = value; - OnPropertyChanged(); - _connectionSettings.Save(); - // if (value) - // { - // _opcUaBackgroundService.StartService(); - // } - // else - // { - // _opcUaBackgroundService.StopService(); - // } - } - } - } - public bool MinimizeToTrayOnClose { get => _connectionSettings.MinimizeToTrayOnClose; diff --git a/ViewModels/VariableTableViewModel.cs b/ViewModels/VariableTableViewModel.cs index e60f9d9..240e52e 100644 --- a/ViewModels/VariableTableViewModel.cs +++ b/ViewModels/VariableTableViewModel.cs @@ -443,11 +443,11 @@ partial class VariableTableViewModel : ViewModelBase private async Task RefreshDataView() { // // 更新界面显示的数据:重新从数据库加载所有变量数据 - // VariableTable.DataVariables = await _varDataRepository.GetByVariableTableId(VariableTable.Id); + // VariableTable.DataVariables = await _varDataRepository.GetByVariableTableIdAsync(VariableTable.Id); // DataVariables.Clear(); // foreach (var item in VariableTable.DataVariables) // { - // DataVariables.Add(item); + // DataVariables.AddAsync(item); // } // // VariableDataView.Refresh(); diff --git a/Views/DeviceDetailView.xaml b/Views/DeviceDetailView.xaml index b8a5324..3351f25 100644 --- a/Views/DeviceDetailView.xaml +++ b/Views/DeviceDetailView.xaml @@ -6,6 +6,7 @@ xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf" xmlns:vm="clr-namespace:PMSWPF.ViewModels" + xmlns:hc="https://handyorg.github.io/handycontrol" d:DataContext="{d:DesignInstance vm:DeviceDetailViewModel}" mc:Ignorable="d" d:DesignHeight="600" @@ -132,6 +133,12 @@ SelectedItem="{Binding SelectedVariableTable}" ItemsSource="{Binding CurrentDevice.VariableTables}" ItemTemplate="{StaticResource VariableTableItemTemplate}" - SelectionMode="Single" /> + SelectionMode="Single"> + + + + + + \ No newline at end of file diff --git a/Views/SettingView.xaml b/Views/SettingView.xaml index fcb9e65..43d2a06 100644 --- a/Views/SettingView.xaml +++ b/Views/SettingView.xaml @@ -127,30 +127,6 @@ - - - - - - - - - - - - - - - - -