From 76f16d50be0b173e2c0e6a3089ee9ab2a1c497f3 Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Wed, 16 Jul 2025 18:39:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E9=A1=B5=E9=9D=A2=EF=BC=8C=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E5=9C=A8=E8=AE=BE=E5=A4=87=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E5=AF=B9=E5=BA=94=E7=9A=84=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=B7=B3=E8=BD=AC=E5=88=B0=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.xaml.cs | 2 +- Data/Repositories/DeviceRepository.cs | 4 +- Data/Repositories/MqttRepository.cs | 2 +- Data/Repositories/VarTableRepository.cs | 35 +++--- Models/Device.cs | 3 +- Models/VariableTable.cs | 2 +- PMSWPF.csproj | 1 - Services/DialogService.cs | 15 +++ Services/IDialogService.cs | 1 + Services/OpcUaBackgroundService.cs | 2 +- Services/S7BackgroundService.cs | 2 +- ViewModels/DeviceDetailViewModel.cs | 149 +++++++++++++++++++++++- ViewModels/DevicesViewModel.cs | 10 ++ ViewModels/MainViewModel.cs | 38 +++--- ViewModels/VariableTableViewModel.cs | 20 ++-- Views/DeviceDetailView.xaml | 140 ++++++++++++++++++++-- Views/DevicesView.xaml | 9 +- Views/MainView.xaml | 2 +- 18 files changed, 374 insertions(+), 63 deletions(-) diff --git a/App.xaml.cs b/App.xaml.cs index 780a93d..b80e31d 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -133,7 +133,7 @@ public partial class App : Application services.AddSingleton(); services.AddTransient(); services.AddScoped(); - services.AddScoped(); + services.AddSingleton(); services.AddScoped(); //注册View视图 services.AddSingleton(); diff --git a/Data/Repositories/DeviceRepository.cs b/Data/Repositories/DeviceRepository.cs index 9dac661..7f24031 100644 --- a/Data/Repositories/DeviceRepository.cs +++ b/Data/Repositories/DeviceRepository.cs @@ -150,7 +150,7 @@ public class DeviceRepository var result = await db.Deleteable(new DbDevice { Id = device.Id }) .ExecuteCommandAsync(); // 删除变量表 - await _varTableRepository.Delete(device.VariableTables, db); + await _varTableRepository.DeleteAsync(device.VariableTables, db); // 删除菜单 var menu = DataServicesHelper.FindMenusForDevice(device, menus); @@ -228,7 +228,7 @@ public class DeviceRepository { // 添加默认变量表 var varTable = new VariableTable(); - device.VariableTables = new List(); + device.VariableTables = new (); varTable.IsActive = true; varTable.DeviceId = addDevice.Id; varTable.Name = "默认变量表"; diff --git a/Data/Repositories/MqttRepository.cs b/Data/Repositories/MqttRepository.cs index 28730c8..b3830f8 100644 --- a/Data/Repositories/MqttRepository.cs +++ b/Data/Repositories/MqttRepository.cs @@ -155,7 +155,7 @@ public class MqttRepository var result = await db.Deleteable() .In(mqtt.Id) .ExecuteCommandAsync(); - // Delete menu entry + // DeleteAsync menu entry var menu = await _menuRepository.GetMenuByDataId(mqtt.Id, MenuType.MqttMenu); if (menu!=null ) { diff --git a/Data/Repositories/VarTableRepository.cs b/Data/Repositories/VarTableRepository.cs index cd14225..1202c32 100644 --- a/Data/Repositories/VarTableRepository.cs +++ b/Data/Repositories/VarTableRepository.cs @@ -62,17 +62,15 @@ public class VarTableRepository /// /// /// - public async Task Edit(VariableTable variableTable) + public async Task UpdateAsync(VariableTable variableTable) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); - using (var db = DbContext.GetInstance()) - { - var result = await Edit(variableTable, db); - stopwatch.Stop(); - NlogHelper.Info($"编辑变量表 '{variableTable.Name}' 耗时:{stopwatch.ElapsedMilliseconds}ms"); - return result; - } + using var db = DbContext.GetInstance(); + var result = await UpdateAsync(variableTable, db); + stopwatch.Stop(); + NlogHelper.Info($"编辑变量表 '{variableTable.Name}' 耗时:{stopwatch.ElapsedMilliseconds}ms"); + return result; } /// @@ -80,7 +78,7 @@ public class VarTableRepository /// /// /// - public async Task Edit(VariableTable variableTable, SqlSugarClient db) + public async Task UpdateAsync(VariableTable variableTable, SqlSugarClient db) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); @@ -96,13 +94,13 @@ public class VarTableRepository /// /// /// - public async Task Delete(VariableTable variableTable) + public async Task DeleteAsync(VariableTable variableTable) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); using (var db = DbContext.GetInstance()) { - var result = await Delete(variableTable, db); + var result = await DeleteAsync(variableTable, db); stopwatch.Stop(); NlogHelper.Info($"删除变量表 '{variableTable.Name}' 耗时:{stopwatch.ElapsedMilliseconds}ms"); return result; @@ -114,7 +112,7 @@ public class VarTableRepository /// /// /// - public async Task Delete(VariableTable varTable, SqlSugarClient db) + public async Task DeleteAsync(VariableTable varTable, SqlSugarClient db) { if (varTable == null ) return 0; @@ -133,9 +131,9 @@ public class VarTableRepository /// /// /// - public async Task Delete(List deviceVariableTables, SqlSugarClient db) + public async Task DeleteAsync(IEnumerable deviceVariableTables, SqlSugarClient db) { - if (deviceVariableTables == null || deviceVariableTables.Count == 0) + if (deviceVariableTables == null || deviceVariableTables.Count() == 0) return; // 转换对象 var dbList = deviceVariableTables.Select(v => _mapper.Map(v)) @@ -143,4 +141,13 @@ public class VarTableRepository await db.Deleteable(dbList) .ExecuteCommandAsync(); } + + public async Task AddAsync(VariableTable varTable) + { + using var db = DbContext.GetInstance(); + return await Add(varTable); + } + + + } \ No newline at end of file diff --git a/Models/Device.cs b/Models/Device.cs index e681023..a42cd26 100644 --- a/Models/Device.cs +++ b/Models/Device.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using PMSWPF.Enums; using SqlSugar; @@ -97,5 +98,5 @@ public partial class Device : ObservableObject /// /// 设备关联的变量表列表。 /// - public List? VariableTables { get; set; } + public ObservableCollection? VariableTables { get; set; } } \ No newline at end of file diff --git a/Models/VariableTable.cs b/Models/VariableTable.cs index ffb6e15..8ad57ed 100644 --- a/Models/VariableTable.cs +++ b/Models/VariableTable.cs @@ -30,7 +30,7 @@ public partial class VariableTable : ObservableObject /// 变量表中包含的数据变量列表。 /// [ObservableProperty] - public List dataVariables; + public ObservableCollection dataVariables; // [ObservableProperty] // public ObservableCollection varDataList; // diff --git a/PMSWPF.csproj b/PMSWPF.csproj index 36c8d84..ecafec8 100644 --- a/PMSWPF.csproj +++ b/PMSWPF.csproj @@ -22,7 +22,6 @@ - diff --git a/Services/DialogService.cs b/Services/DialogService.cs index f3fa174..a484722 100644 --- a/Services/DialogService.cs +++ b/Services/DialogService.cs @@ -104,6 +104,21 @@ public class DialogService :IDialogService } return null; } + + public async Task ShowEditVarTableDialog(VariableTable variableTable) + { + VarTableDialogViewModel vm = new(); + vm.Title = "编辑变量表"; + vm.PrimaryButtonText = "编辑变量表"; + vm.VariableTable = variableTable; + var dialog = new VarTableDialog(vm); + var res = await dialog.ShowAsync(); + if (res == ContentDialogResult.Primary) + { + return vm.VariableTable; + } + return null; + } public async Task ShowAddVarDataDialog() { diff --git a/Services/IDialogService.cs b/Services/IDialogService.cs index 7a5a17b..f12e206 100644 --- a/Services/IDialogService.cs +++ b/Services/IDialogService.cs @@ -13,6 +13,7 @@ public interface IDialogService Task ShowConfrimeDialog(string title, string message,string buttonText="确认"); Task ShowAddVarTableDialog(); + Task ShowEditVarTableDialog(VariableTable variableTable); Task ShowAddVarDataDialog(); diff --git a/Services/OpcUaBackgroundService.cs b/Services/OpcUaBackgroundService.cs index 921bf67..623371b 100644 --- a/Services/OpcUaBackgroundService.cs +++ b/Services/OpcUaBackgroundService.cs @@ -417,7 +417,7 @@ namespace PMSWPF.Services variable.DataValue = value.ToString(); variable.DisplayValue = value.ToString(); // 或者根据需要进行格式化 variable.UpdateTime = DateTime.Now; - Console.WriteLine($"OpcUa后台服务轮询变量:{variable.Name},值:{variable.DataValue}"); + // Console.WriteLine($"OpcUa后台服务轮询变量:{variable.Name},值:{variable.DataValue}"); // 将更新后的数据推入处理队列。 await _dataProcessingService.EnqueueAsync(variable); } diff --git a/Services/S7BackgroundService.cs b/Services/S7BackgroundService.cs index caf49ba..c74942b 100644 --- a/Services/S7BackgroundService.cs +++ b/Services/S7BackgroundService.cs @@ -285,7 +285,7 @@ namespace PMSWPF.Services variable.DataValue = dataItem.Value.ToString(); variable.DisplayValue = dataItem.Value.ToString(); variable.UpdateTime = DateTime.Now; - Console.WriteLine($"S7后台服务轮询变量:{variable.Name},值:{variable.DataValue}"); + // Console.WriteLine($"S7后台服务轮询变量:{variable.Name},值:{variable.DataValue}"); // 将更新后的数据推入处理队列。 await _dataProcessingService.EnqueueAsync(variable); } diff --git a/ViewModels/DeviceDetailViewModel.cs b/ViewModels/DeviceDetailViewModel.cs index 3ccc9db..de52fdf 100644 --- a/ViewModels/DeviceDetailViewModel.cs +++ b/ViewModels/DeviceDetailViewModel.cs @@ -1,6 +1,151 @@ -namespace PMSWPF.ViewModels; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using PMSWPF.Data.Repositories; +using PMSWPF.Helper; +using PMSWPF.Models; +using PMSWPF.Services; -public class DeviceDetailViewModel:ViewModelBase +namespace PMSWPF.ViewModels; + +public partial class DeviceDetailViewModel : ViewModelBase { + private readonly IDialogService _dialogService; + private readonly VarTableRepository _varTableRepository; + [ObservableProperty] + private Device _currentDevice; + + [ObservableProperty] + private VariableTable _selectedVariableTable; + + public DeviceDetailViewModel(IDialogService dialogService, VarTableRepository varTableRepository) + { + _dialogService = dialogService; + _varTableRepository = varTableRepository; + } + + public override void OnLoaded() + { + // Ensure VariableTables is an ObservableCollection for UI binding + // if (_curentDevice.VariableTables != null && + // !(_curentDevice.VariableTables is ObservableCollection)) + // { + // _curentDevice.VariableTables = new ObservableCollection(_curentDevice.VariableTables); + // } + // else if (_curentDevice.VariableTables == null) + // { + // _curentDevice.VariableTables = new ObservableCollection(); + // } + } + + [RelayCommand] + private async Task AddVariableTable() + { + try + { + var newVarTable = await _dialogService.ShowAddVarTableDialog(); + if (newVarTable == null) return; + + newVarTable.DeviceId = CurrentDevice.Id; + newVarTable = await _varTableRepository.AddAsync(newVarTable); + if (newVarTable != null) + { + CurrentDevice.VariableTables.Add(newVarTable); + NotificationHelper.ShowSuccess($"变量表 {newVarTable.Name} 添加成功。"); + } + else + { + NotificationHelper.ShowError($"变量表 {newVarTable.Name} 添加失败。"); + } + } + catch (Exception ex) + { + NotificationHelper.ShowError($"添加变量表时发生错误: {ex.Message}", ex); + } + } + + [RelayCommand] + private async Task EditVariableTable() + { + if (SelectedVariableTable == null) + { + NotificationHelper.ShowInfo("请选择要编辑的变量表。"); + return; + } + + try + { + var editedVarTable = await _dialogService.ShowEditVarTableDialog(SelectedVariableTable); + if (editedVarTable == null) return; + + // The dialog already updated the SelectedVariableTable if it returned a non-null value + // So we just need to save it to the database + var result = await _varTableRepository.UpdateAsync(SelectedVariableTable); + if (result > 0) + { + NotificationHelper.ShowSuccess($"变量表 {SelectedVariableTable.Name} 编辑成功。"); + } + else + { + NotificationHelper.ShowError($"变量表 {SelectedVariableTable.Name} 编辑失败。"); + } + } + catch (Exception ex) + { + NotificationHelper.ShowError($"编辑变量表时发生错误: {ex.Message}", ex); + } + } + + [RelayCommand] + private async Task DeleteVariableTable() + { + if (SelectedVariableTable == null) + { + NotificationHelper.ShowInfo("请选择要删除的变量表。"); + return; + } + + var confirm = await _dialogService.ShowConfrimeDialog( + "删除确认", + $"确定要删除变量表 \"{SelectedVariableTable.Name}\" 吗?\n\n此操作将同时删除该变量表下的所有变量数据,且无法恢复!", + "删除"); + + if (!confirm) return; + + try + { + var result = await _varTableRepository.DeleteAsync(SelectedVariableTable); + if (result > 0) + { + CurrentDevice.VariableTables.Remove(SelectedVariableTable); + NotificationHelper.ShowSuccess($"变量表 {SelectedVariableTable.Name} 删除成功。"); + } + else + { + NotificationHelper.ShowError($"变量表 {SelectedVariableTable.Name} 删除失败。"); + } + } + catch (Exception ex) + { + NotificationHelper.ShowError($"删除变量表时发生错误: {ex.Message}", ex); + } + } + + // Placeholder for EditDeviceCommand and DeleteDeviceCommand if they are needed here + [RelayCommand] + private async Task EditDevice() + { + // Implement device editing logic, similar to AddDeviceCommand but for existing device + NotificationHelper.ShowInfo("编辑设备功能待实现。"); + await Task.CompletedTask; + } + + [RelayCommand] + private async Task DeleteDevice() + { + // Implement device deletion logic + NotificationHelper.ShowInfo("删除设备功能待实现。"); + await Task.CompletedTask; + } } \ No newline at end of file diff --git a/ViewModels/DevicesViewModel.cs b/ViewModels/DevicesViewModel.cs index 1d972f1..18eea89 100644 --- a/ViewModels/DevicesViewModel.cs +++ b/ViewModels/DevicesViewModel.cs @@ -1,6 +1,7 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using PMSWPF.Data; using PMSWPF.Data.Repositories; @@ -160,4 +161,13 @@ public partial class DevicesViewModel : ViewModelBase NotificationHelper.ShowError($"编辑设备的过程中发生错误:{e.Message}", e); } } + + [RelayCommand] + public void NavigateToDetail() + { + if (SelectedDevice == null) return; + var deviceDetailVm = App.Current.Services.GetRequiredService(); + deviceDetailVm.CurrentDevice = SelectedDevice; + MessageHelper.SendNavgatorMessage(deviceDetailVm); + } } \ No newline at end of file diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 61f82d5..053926f 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -12,6 +12,7 @@ using PMSWPF.Helper; using PMSWPF.Models; using PMSWPF.Services; using PMSWPF.Views; + // Add this using directive // Add this using directive @@ -49,7 +50,8 @@ public partial class MainViewModel : ViewModelBase /// 对话框服务。 /// 日志记录器。 public MainViewModel(NavgatorServices navgatorServices, DataServices dataServices, IDialogService dialogService, - ILogger logger,VarTableRepository varTableRepository,MenuRepository menuRepository) + ILogger logger, VarTableRepository varTableRepository, + MenuRepository menuRepository) { _navgatorServices = navgatorServices; _dataServices = dataServices; @@ -65,7 +67,7 @@ public partial class MainViewModel : ViewModelBase // 发送消息加载数据 MessageHelper.SendLoadMessage(LoadTypes.All); // 当菜单加载成功后,在前台显示菜单 - dataServices.OnMenuTreeListChanged += ( menus) => { Menus = new ObservableCollection(menus); }; + dataServices.OnMenuTreeListChanged += (menus) => { Menus = new ObservableCollection(menus); }; } /// @@ -124,22 +126,22 @@ public partial class MainViewModel : ViewModelBase // 假设 _varTableRepository.AddAsync 返回一个布尔值表示成功,或者一个表示 ID 的整数 // 这里为了演示,我们假设它返回新添加的ID,如果失败则返回0 await db.BeginTranAsync(); - var addVarTable = await _varTableRepository.Add(varTable,db); + var addVarTable = await _varTableRepository.Add(varTable, db); // 5. 添加变量表菜单 MenuBean newMenu = new MenuBean - { - Icon = SegoeFluentIcons.Tablet.Glyph, - Name = varTable.Name, - DataId = addVarTable.Id, // 使用实际添加的ID - Type = MenuType.VariableTableMenu, - ParentId = menu.Parent.Id - }; + { + Icon = SegoeFluentIcons.Tablet.Glyph, + Name = varTable.Name, + DataId = addVarTable.Id, // 使用实际添加的ID + Type = MenuType.VariableTableMenu, + ParentId = menu.Parent.Id + }; - var addMenuRes = await _menuRepository.Add(newMenu,db); + var addMenuRes = await _menuRepository.Add(newMenu, db); if (addMenuRes > 0) { - await db.CommitTranAsync(); + await db.CommitTranAsync(); // 变量表和菜单都添加成功 MessageHelper.SendLoadMessage(LoadTypes.Menu); MessageHelper.SendLoadMessage(LoadTypes.Devices); @@ -153,7 +155,7 @@ public partial class MainViewModel : ViewModelBase NotificationHelper.ShowError($"变量表:{varTable.Name},添加菜单失败"); _logger.LogError($"变量表:{varTable.Name},添加菜单失败"); // 考虑:如果菜单添加失败,是否需要删除之前添加的变量表? - // 例如:await _varTableRepository.Delete(addVarTableId); + // 例如:await _varTableRepository.DeleteAsync(addVarTableId); } } catch (Exception e) @@ -179,8 +181,11 @@ public partial class MainViewModel : ViewModelBase break; // 导航到设备下面的菜单 case MenuType.DeviceMenu: - menu.ViewModel = App.Current.Services.GetRequiredService(); - menu.Data = _dataServices.Devices.FirstOrDefault(d => d.Id == menu.DataId); + var deviceDetailVm = App.Current.Services.GetRequiredService(); + var currentDevice = _dataServices.Devices.FirstOrDefault(d => d.Id == menu.DataId); + deviceDetailVm.CurrentDevice = currentDevice; + menu.ViewModel = deviceDetailVm; + menu.Data = currentDevice; break; // 导航到变量表菜单 case MenuType.VariableTableMenu: @@ -201,10 +206,9 @@ public partial class MainViewModel : ViewModelBase // 导航到Mqtt服务器 case MenuType.MqttMenu: var mqttVM = App.Current.Services.GetRequiredService(); - mqttVM.CurrentMqtt=_dataServices.Mqtts.FirstOrDefault(d=>d.Id == menu.DataId); + mqttVM.CurrentMqtt = _dataServices.Mqtts.FirstOrDefault(d => d.Id == menu.DataId); menu.ViewModel = mqttVM; break; - } diff --git a/ViewModels/VariableTableViewModel.cs b/ViewModels/VariableTableViewModel.cs index ec162e6..e60f9d9 100644 --- a/ViewModels/VariableTableViewModel.cs +++ b/ViewModels/VariableTableViewModel.cs @@ -442,15 +442,15 @@ partial class VariableTableViewModel : ViewModelBase /// private async Task RefreshDataView() { - // 更新界面显示的数据:重新从数据库加载所有变量数据 - VariableTable.DataVariables = await _varDataRepository.GetByVariableTableId(VariableTable.Id); - DataVariables.Clear(); - foreach (var item in VariableTable.DataVariables) - { - DataVariables.Add(item); - } - - VariableDataView.Refresh(); + // // 更新界面显示的数据:重新从数据库加载所有变量数据 + // VariableTable.DataVariables = await _varDataRepository.GetByVariableTableId(VariableTable.Id); + // DataVariables.Clear(); + // foreach (var item in VariableTable.DataVariables) + // { + // DataVariables.Add(item); + // } + // + // VariableDataView.Refresh(); } /// @@ -723,7 +723,7 @@ partial class VariableTableViewModel : ViewModelBase public async Task OnIsActiveChanged(bool active) { // 更新数据库中变量表的激活状态 - var res = await _varTableRepository.Edit(VariableTable); + var res = await _varTableRepository.UpdateAsync(VariableTable); if (res > 0) { // 根据激活状态显示成功通知 diff --git a/Views/DeviceDetailView.xaml b/Views/DeviceDetailView.xaml index 160a305..b8a5324 100644 --- a/Views/DeviceDetailView.xaml +++ b/Views/DeviceDetailView.xaml @@ -1,15 +1,137 @@ - - - - + d:DesignHeight="600" + d:DesignWidth="800"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Views/DevicesView.xaml b/Views/DevicesView.xaml index 2b0c7d4..59e7db6 100644 --- a/Views/DevicesView.xaml +++ b/Views/DevicesView.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:DevicesViewModel}" mc:Ignorable="d" d:DesignHeight="300" @@ -168,7 +169,13 @@ SelectedItem="{Binding SelectedDevice }" ItemsSource="{Binding Devices}" ItemTemplate="{StaticResource DeviceItemTemplate}" - SelectionMode="Single" /> + SelectionMode="Single"> + + + + + + \ No newline at end of file diff --git a/Views/MainView.xaml b/Views/MainView.xaml index 21fcf00..161a575 100644 --- a/Views/MainView.xaml +++ b/Views/MainView.xaml @@ -100,7 +100,7 @@ - +