From 1d8d4a7f5eff0a482e14ee51f80e4ee0adf28478 Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Sun, 24 Aug 2025 17:48:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=88=A0=E9=99=A4=E5=8F=98?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interfaces/IVariableAppService.cs | 5 + .../Services/VariableAppService.cs | 37 +++ .../Repositories/IBaseRepository.cs | 6 + .../Repositories/BaseRepository.cs | 17 ++ .../Repositories/VariableRepository.cs | 17 ++ DMS.WPF/Services/DataServices.cs | 25 +- DMS.WPF/ViewModels/VariableTableViewModel.cs | 236 +++++------------- DMS.WPF/Views/VariableTableView.xaml | 22 +- DMS.WPF/Views/VariableTableView.xaml.cs | 72 +----- 9 files changed, 171 insertions(+), 266 deletions(-) diff --git a/DMS.Application/Interfaces/IVariableAppService.cs b/DMS.Application/Interfaces/IVariableAppService.cs index b33f131..efd3bf8 100644 --- a/DMS.Application/Interfaces/IVariableAppService.cs +++ b/DMS.Application/Interfaces/IVariableAppService.cs @@ -32,6 +32,11 @@ public interface IVariableAppService /// Task DeleteVariableAsync(int id); + /// + /// 异步批量删除变量。 + /// + Task DeleteVariablesAsync(List ids); + /// /// 异步批量导入变量。 /// diff --git a/DMS.Application/Services/VariableAppService.cs b/DMS.Application/Services/VariableAppService.cs index 72ed38c..c0c5a6c 100644 --- a/DMS.Application/Services/VariableAppService.cs +++ b/DMS.Application/Services/VariableAppService.cs @@ -127,6 +127,43 @@ public class VariableAppService : IVariableAppService } } + /// + /// 异步批量删除变量(事务性操作)。 + /// + /// 要删除的变量ID列表。 + /// 如果删除成功则为 true,否则为 false。 + /// 如果ID列表为空或null。 + /// 如果删除变量时发生错误。 + public async Task DeleteVariablesAsync(List ids) + { + if (ids == null || !ids.Any()) + { + throw new ArgumentException("变量ID列表不能为空", nameof(ids)); + } + + try + { + await _repoManager.BeginTranAsync(); + + // 批量删除变量 + var deletedCount = await _repoManager.Variables.DeleteByIdsAsync(ids); + + // 检查是否所有变量都被成功删除 + if (deletedCount != ids.Count) + { + throw new InvalidOperationException($"删除变量失败:请求删除 {ids.Count} 个变量,实际删除 {deletedCount} 个变量"); + } + + await _repoManager.CommitAsync(); + return true; + } + catch (Exception ex) + { + await _repoManager.RollbackAsync(); + throw new ApplicationException($"批量删除变量时发生错误,操作已回滚,错误信息:{ex.Message}", ex); + } + } + public async Task BatchImportVariablesAsync(List variables) { try diff --git a/DMS.Core/Interfaces/Repositories/IBaseRepository.cs b/DMS.Core/Interfaces/Repositories/IBaseRepository.cs index 8dd6c1b..8e7c00e 100644 --- a/DMS.Core/Interfaces/Repositories/IBaseRepository.cs +++ b/DMS.Core/Interfaces/Repositories/IBaseRepository.cs @@ -43,6 +43,12 @@ public interface IBaseRepository where T : class /// 要删除的实体的主键ID。 Task DeleteByIdAsync(int id); + /// + /// 异步根据ID列表批量删除实体。 + /// + /// 要删除的实体的主键ID列表。 + Task DeleteByIdsAsync(List ids); + /// /// 从数据库获取数据。 /// diff --git a/DMS.Infrastructure/Repositories/BaseRepository.cs b/DMS.Infrastructure/Repositories/BaseRepository.cs index dd45459..c0bb8d6 100644 --- a/DMS.Infrastructure/Repositories/BaseRepository.cs +++ b/DMS.Infrastructure/Repositories/BaseRepository.cs @@ -116,6 +116,23 @@ public abstract class BaseRepository return entity; } + /// + /// 异步根据主键 ID 列表批量删除实体。 + /// + /// 要删除的实体主键 ID 列表。 + /// 返回受影响的行数。 + public virtual async Task DeleteByIdsAsync(List ids) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var result = await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + stopwatch.Stop(); + NlogHelper.Info($"DeleteByIds {typeof(TEntity).Name}, Count: {ids.Count}, 耗时:{stopwatch.ElapsedMilliseconds}ms"); + return result; + } + /// /// 异步根据指定条件获取单个实体。 /// diff --git a/DMS.Infrastructure/Repositories/VariableRepository.cs b/DMS.Infrastructure/Repositories/VariableRepository.cs index 694934a..73d492a 100644 --- a/DMS.Infrastructure/Repositories/VariableRepository.cs +++ b/DMS.Infrastructure/Repositories/VariableRepository.cs @@ -173,6 +173,23 @@ public class VariableRepository : BaseRepository, IVariableRepositor return result; } + /// + /// 异步根据ID列表批量删除变量。 + /// + /// 要删除变量的唯一标识符列表。 + /// 受影响的行数。 + public async Task DeleteByIdsAsync(List ids) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var result = await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + stopwatch.Stop(); + NlogHelper.Info($"Delete {typeof(DbVariable)},Count={ids.Count},耗时:{stopwatch.ElapsedMilliseconds}ms"); + return result; + } + /// /// 异步获取指定数量的变量。 /// diff --git a/DMS.WPF/Services/DataServices.cs b/DMS.WPF/Services/DataServices.cs index 603a74e..066fd9d 100644 --- a/DMS.WPF/Services/DataServices.cs +++ b/DMS.WPF/Services/DataServices.cs @@ -368,10 +368,10 @@ public partial class DataServices : ObservableRecipient, IRecipient { // 这是一个新变量表,添加到集合中 var newItem = _mapper.Map(dto); - var device=Devices.FirstOrDefault(d=>d.Id==dto.DeviceId); - if (device!=null) + var device = Devices.FirstOrDefault(d => d.Id == dto.DeviceId); + if (device != null) { - newItem.Device=device; + newItem.Device = device; } VariableTables.Add(newItem); } @@ -500,7 +500,7 @@ public partial class DataServices : ObservableRecipient, IRecipient public void AddVariable(VariableItemViewModel variableItem) { - if (variableItem==null) + if (variableItem == null) { return; } @@ -612,4 +612,21 @@ public partial class DataServices : ObservableRecipient, IRecipient } } } + + public void DeleteVariableById(int id) + { + var variableItem = Variables.FirstOrDefault(v => v.Id == id); + if (variableItem == null) + { + return; + } + + var variableTable = VariableTables.FirstOrDefault(vt => vt.Id == variableItem.VariableTableId); + + variableTable.Variables.Remove(variableItem); + + Variables.Remove(variableItem); + + + } } \ No newline at end of file diff --git a/DMS.WPF/ViewModels/VariableTableViewModel.cs b/DMS.WPF/ViewModels/VariableTableViewModel.cs index e8f4b86..03579f5 100644 --- a/DMS.WPF/ViewModels/VariableTableViewModel.cs +++ b/DMS.WPF/ViewModels/VariableTableViewModel.cs @@ -1,26 +1,27 @@ using AutoMapper; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using DMS.Core.Enums; -using DMS.Core.Interfaces; -using DMS.Core.Models; -using DMS.WPF.Services; -using DMS.WPF.ViewModels.Dialogs; -using DMS.WPF.ViewModels.Items; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Windows; -using System.Windows.Data; using DMS.Application.DTOs; using DMS.Application.Interfaces; using DMS.Application.Services; +using DMS.Core.Enums; +using DMS.Core.Interfaces; +using DMS.Core.Models; using DMS.Helper; +using DMS.WPF.Services; +using DMS.WPF.ViewModels.Dialogs; +using DMS.WPF.ViewModels.Items; using DMS.WPF.Views; using HandyControl.Controls; using HandyControl.Data; using HandyControl.Tools.Extension; using Microsoft.Extensions.DependencyInjection; using ObservableCollections; +using System.Collections; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Windows; +using System.Windows.Data; namespace DMS.WPF.ViewModels; @@ -56,6 +57,10 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable [ObservableProperty] private VariableItemViewModel _selectedVariable; + + [ObservableProperty] + private IList _selectedVariables = new ArrayList(); + /// /// 用于过滤变量数据的搜索文本。 /// 通过 ObservableProperty 自动生成 SearchText 属性和 OnSearchTextChanged 方法。 @@ -168,83 +173,9 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable public override void OnLoaded() { _variableItemList.AddRange(CurrentVariableTable.Variables); - // - // // 创建原始数据的深拷贝备份,用于在取消保存时还原 - // var settings = new JsonSerializerSettings - // { - // ReferenceLoopHandling = ReferenceLoopHandling.Ignore - // }; - // var serialized = JsonConvert.SerializeObject(Variables, settings); - // _originalVariables = JsonConvert.DeserializeObject>(serialized); - // - // // 在数据加载完成后,将所有变量的 IsModified 状态重置为 false - // foreach (var variable in Variables) - // { - // variable.IsModified = false; - // } - - // 标记加载完成 - IsLoadCompletion = true; } - /// - /// 当用户尝试退出当前视图时异步调用。 - /// 检查是否有未保存的修改,并提示用户是否保存或放弃更改。 - /// - /// 如果可以安全退出则为 true,否则为 false。 - public override async Task OnExitAsync() - { - // 查找所有已修改的变量数据 - var modifiedDatas = Variables.Where(d => d.IsModified == true) - .ToList(); - // 如果没有修改,则直接允许退出 - if (modifiedDatas.Count == 0) - return true; - // 提示用户有未保存的数据,询问是否离开 - // var isExit = await _dialogService.ShowConfrimeDialog( - // "数据未保存", $"你有{modifiedDatas.Count}个修改的变量没有保存,离开后这些数据就可能丢失了确认要离开吗?", "离开"); - - // // 如果用户选择不离开(即不保存),则还原数据 - // if (!isExit) - // { - // // 遍历所有已修改的数据,从原始备份中还原 - // foreach (var modifiedData in modifiedDatas) - // { - // var oldData = _originalVariables.First(od => od.Id == modifiedData.Id); - // // 将原始数据复制回当前数据 - // _mapper.Map(oldData, modifiedData); - // modifiedData.IsModified = false; // 重置修改状态 - // } - // - // return false; // 不允许退出 - // } - - return true; // 允许退出 - } - - /// - /// 保存所有已修改的变量数据到数据库。 - /// 此命令通常绑定到UI中的“保存”按钮。 - /// - [RelayCommand] - private async void SaveModifiedVarData() - { - // // 查找所有已标记为修改的变量数据 - // var modifiedDatas = Variables.Where(d => d.IsModified == true) - // .ToList(); - // // 更新数据库中的这些数据 - // await _varDataRepository.UpdateAsync(modifiedDatas); - // - // // 还原所有已保存数据的修改状态 - // foreach (var modifiedData in modifiedDatas) - // { - // modifiedData.IsModified = false; - // } - // - // // 显示成功通知 - // NotificationHelper.ShowSuccess($"修改的{modifiedDatas.Count}变量保存成功."); - } /// /// 编辑选定的变量数据。 @@ -447,58 +378,6 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable // } } - /// - /// 刷新数据列表,高效地同步UI显示数据与数据库最新数据。 - /// - private async Task RefreshDataView() - { - // // 从数据库加载最新的变量数据 - // var latestVariables = await _varDataRepository.GetByVariableTableIdAsync(VariableTable.Id); - // - // // 将最新数据转换为字典,以便快速查找 - // var latestVariablesDict = latestVariables.ToDictionary(v => v.Id); - // - // // 用于存储需要从 Variables 中移除的项 - // var itemsToRemove = new List(); - // - // // 遍历当前 Variables 集合,处理删除和更新 - // for (int i = Variables.Count - 1; i >= 0; i--) - // { - // var currentVariable = Variables[i]; - // if (latestVariablesDict.TryGetValue(currentVariable.Id, out var newVariable)) - // { - // // 如果存在于最新数据中,检查是否需要更新 - // if (!currentVariable.Equals(newVariable)) - // { - // // 使用 AutoMapper 更新现有对象的属性,保持对象引用不变 - // _mapper.Map(newVariable, currentVariable); - // } - // - // // 从字典中移除已处理的项,剩余的将是新增项 - // latestVariablesDict.Remove(currentVariable.Id); - // } - // else - // { - // // 如果不存在于最新数据中,则标记为删除 - // itemsToRemove.Add(currentVariable); - // } - // } - // - // // 移除已标记的项 - // foreach (var item in itemsToRemove) - // { - // Variables.Remove(item); - // } - // - // // 添加所有剩余在 latestVariablesDict 中的项(这些是新增项) - // foreach (var newVariable in latestVariablesDict.Values) - // { - // Variables.Add(newVariable); - // } - // - // // 刷新视图以应用所有更改 - // VariableView.Refresh(); - } // /// @@ -554,48 +433,51 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable /// /// 要删除的变量数据列表。 [RelayCommand] - public async Task DeleteVarData(List variablesToDelete) + public async Task DeleteVariable() { - // // 检查是否有变量被选中 - // if (variablesToDelete == null || !variablesToDelete.Any()) - // { - // NotificationHelper.ShowInfo("请选择要删除的变量"); - // return; - // } - // - // // 拼接要删除的变量名称,用于确认提示 - // var names = string.Join("、", variablesToDelete.Select(v => v.Name)); - // - // // 显示确认删除对话框 - // var confirm = await _dialogService.ShowConfrimeDialog( - // "删除确认", - // $"确定要删除选中的 {variablesToDelete.Count} 个变量吗?\n\n{names}", - // "删除"); - // - // if (!confirm) - // return; // 如果用户取消删除,则返回 - // - // try - // { - // // 从数据库中删除变量数据 - // var result = await _varDataRepository.DeleteAsync(variablesToDelete); - // if (result > 0) - // { - // await RefreshDataView(); - // // 显示成功通知 - // NotificationHelper.ShowSuccess($"成功删除 {result} 个变量"); - // } - // else - // { - // // 显示删除失败通知 - // NotificationHelper.ShowError("删除变量失败"); - // } - // } - // catch (Exception e) - // { - // // 捕获并显示错误通知 - // NotificationHelper.ShowError($"删除变量的过程中发生了不可预期的错误:{e.Message}", e); - // } + try + { + List variablesToDelete = SelectedVariables.Cast().ToList(); + // 检查是否有变量被选中 + if (variablesToDelete == null || !variablesToDelete.Any()) + { + NotificationHelper.ShowInfo("请选择要删除的变量"); + return; + } + + // 拼接要删除的变量名称,用于确认提示 + var names = string.Join("、", variablesToDelete.Select(v => v.Name)); + + // 显示确认删除对话框 + ConfirmDialogViewModel confirmDialogViewModel = new ConfirmDialogViewModel("删除变量", $"确认要删除变量:{names},删除后不可恢复,确认要删除吗?", "删除变量"); + var isDel = await _dialogService.ShowDialogAsync(confirmDialogViewModel); + + if (!isDel) + return; // 如果用户取消删除,则返回 + + // 从数据库中删除变量数据 + var result = await _variableAppService.DeleteVariablesAsync(variablesToDelete.Select(v => v.Id).ToList()); + if (result) + { + foreach (var variable in variablesToDelete) + { + _variableItemList.Remove(variable); + _dataServices.DeleteVariableById(variable.Id); + } + // 显示成功通知 + NotificationHelper.ShowSuccess($"成功删除 {variablesToDelete.Count} 个变量"); + } + else + { + // 显示删除失败通知 + NotificationHelper.ShowError("删除变量失败"); + } + } + catch (Exception e) + { + // 捕获并显示错误通知 + NotificationHelper.ShowError($"删除变量的过程中发生了不可预期的错误:{e.Message}", e); + } } /// diff --git a/DMS.WPF/Views/VariableTableView.xaml b/DMS.WPF/Views/VariableTableView.xaml index 987ec9c..929d6fc 100644 --- a/DMS.WPF/Views/VariableTableView.xaml +++ b/DMS.WPF/Views/VariableTableView.xaml @@ -6,6 +6,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:enums="clr-namespace:DMS.Core.Enums;assembly=DMS.Core" xmlns:ex="clr-namespace:DMS.Extensions" + xmlns:helper="clr-namespace:DMS.WPF.Helper" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" @@ -61,19 +63,12 @@ - + - - - - - - - + + + + - + - - - - - ().ToList(); - // if (selectedVariables.Any()) - // { - // await _viewModel.DeleteVarData(selectedVariables); - // } - // else - // { - // NotificationHelper.ShowInfo("请选择要删除的变量"); - // } - } + } \ No newline at end of file