修复重复添加或者导入变量的问题,添加显示导入结果对话框
This commit is contained in:
44
ViewModels/Dialogs/ImportResultDialogViewModel.cs
Normal file
44
ViewModels/Dialogs/ImportResultDialogViewModel.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using PMSWPF.Models;
|
||||||
|
|
||||||
|
namespace PMSWPF.ViewModels.Dialogs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ImportResultDialogViewModel 是用于显示变量导入结果的视图模型。
|
||||||
|
/// 它包含成功导入和已存在变量的列表。
|
||||||
|
/// </summary>
|
||||||
|
public partial class ImportResultDialogViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成功导入的变量名称列表。
|
||||||
|
/// </summary>
|
||||||
|
public ObservableCollection<string> ImportedVariables { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已存在的变量名称列表。
|
||||||
|
/// </summary>
|
||||||
|
public ObservableCollection<string> ExistingVariables { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,初始化导入结果列表。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="importedVariables">成功导入的变量名称列表。</param>
|
||||||
|
/// <param name="existingVariables">已存在的变量名称列表。</param>
|
||||||
|
public ImportResultDialogViewModel(List<string> importedVariables, List<string> existingVariables)
|
||||||
|
{
|
||||||
|
ImportedVariables = new ObservableCollection<string>(importedVariables);
|
||||||
|
ExistingVariables = new ObservableCollection<string>(existingVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭对话框的命令。
|
||||||
|
/// </summary>
|
||||||
|
[RelayCommand]
|
||||||
|
private void Close()
|
||||||
|
{
|
||||||
|
// 在实际应用中,这里可能需要通过IDialogService或其他机制来关闭对话框
|
||||||
|
// 对于ContentDialog,通常不需要显式关闭命令,因为对话框本身有关闭按钮或通过Result返回
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -358,16 +358,13 @@ partial class VariableTableViewModel : ViewModelBase
|
|||||||
foreach (var variableData in importVarDataList)
|
foreach (var variableData in importVarDataList)
|
||||||
{
|
{
|
||||||
// 判断是否存在重复变量
|
// 判断是否存在重复变量
|
||||||
bool isDuplicate = _dataServices.AllVariables.Values.Any(existingVar =>
|
// 判断是否存在重复变量,仅在当前 VariableTable 的 DataVariables 中查找
|
||||||
(existingVar.Name == variableData.Name) ||
|
bool isDuplicate = DataVariables.Any(existingVar =>
|
||||||
(!string.IsNullOrEmpty(
|
(existingVar.Name == variableData.Name) ||
|
||||||
variableData.NodeId) &&
|
(!string.IsNullOrEmpty(variableData.NodeId) &&
|
||||||
existingVar.NodeId ==
|
existingVar.NodeId == variableData.NodeId) ||
|
||||||
variableData.NodeId) ||
|
(!string.IsNullOrEmpty(variableData.S7Address) &&
|
||||||
(!string.IsNullOrEmpty(
|
existingVar.S7Address == variableData.S7Address)
|
||||||
variableData.S7Address) &&
|
|
||||||
existingVar.S7Address ==
|
|
||||||
variableData.S7Address)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isDuplicate)
|
if (isDuplicate)
|
||||||
@@ -438,25 +435,53 @@ partial class VariableTableViewModel : ViewModelBase
|
|||||||
// 显示处理中的对话框
|
// 显示处理中的对话框
|
||||||
processingDialog = _dialogService.ShowProcessingDialog("正在处理...", "正在导入OPC UA变量,请稍等片刻....");
|
processingDialog = _dialogService.ShowProcessingDialog("正在处理...", "正在导入OPC UA变量,请稍等片刻....");
|
||||||
|
|
||||||
// 为导入的每个变量设置创建时间、所属变量表ID和协议类型
|
// 在进行重复检查之前,先刷新 DataVariables 集合,确保其包含所有最新数据
|
||||||
|
await RefreshDataView();
|
||||||
|
|
||||||
|
List<VariableData> newVariables = new List<VariableData>();
|
||||||
|
List<string> importedVariableNames = new List<string>();
|
||||||
|
List<string> existingVariableNames = new List<string>();
|
||||||
|
|
||||||
foreach (var variableData in importedVariables)
|
foreach (var variableData in importedVariables)
|
||||||
{
|
{
|
||||||
variableData.CreateTime = DateTime.Now;
|
// 判断是否存在重复变量,仅在当前 VariableTable 的 DataVariables 中查找
|
||||||
variableData.VariableTableId = VariableTable.Id;
|
bool isDuplicate = DataVariables.Any(existingVar =>
|
||||||
variableData.ProtocolType = ProtocolType.OpcUA; // 确保协议类型正确
|
(existingVar.Name == variableData.Name) ||
|
||||||
variableData.IsModified = false;
|
(!string.IsNullOrEmpty(variableData.NodeId) &&
|
||||||
|
existingVar.NodeId == variableData.NodeId) ||
|
||||||
|
(!string.IsNullOrEmpty(variableData.OpcUaNodeId) &&
|
||||||
|
existingVar.OpcUaNodeId == variableData.OpcUaNodeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isDuplicate)
|
||||||
|
{
|
||||||
|
existingVariableNames.Add(variableData.Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
variableData.CreateTime = DateTime.Now;
|
||||||
|
variableData.VariableTableId = VariableTable.Id;
|
||||||
|
variableData.ProtocolType = ProtocolType.OpcUA; // 确保协议类型正确
|
||||||
|
variableData.IsModified = false;
|
||||||
|
newVariables.Add(variableData);
|
||||||
|
importedVariableNames.Add(variableData.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量插入变量数据到数据库
|
if (newVariables.Any())
|
||||||
var resVarDataCount = await _varDataRepository.AddAsync(importedVariables);
|
{
|
||||||
|
// 批量插入新变量数据到数据库
|
||||||
|
var resVarDataCount = await _varDataRepository.AddAsync(newVariables);
|
||||||
|
NlogHelper.Info($"成功导入OPC UA变量:{resVarDataCount}个。");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再次刷新 DataVariables 集合,以反映新添加的数据
|
||||||
await RefreshDataView();
|
await RefreshDataView();
|
||||||
|
|
||||||
processingDialog?.Hide(); // 隐藏处理中的对话框
|
processingDialog?.Hide(); // 隐藏处理中的对话框
|
||||||
|
|
||||||
// 显示成功通知并记录日志
|
// 显示导入结果对话框
|
||||||
string msgSuccess = $"成功导入OPC UA变量:{resVarDataCount}个。";
|
await _dialogService.ShowImportResultDialog(importedVariableNames, existingVariableNames);
|
||||||
NotificationHelper.ShowSuccess(msgSuccess);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -469,60 +494,55 @@ partial class VariableTableViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// <summary>
|
/// <summary>
|
||||||
// /// 刷新数据列表
|
/// 刷新数据列表,高效地同步UI显示数据与数据库最新数据。
|
||||||
// /// </summary>
|
/// </summary>
|
||||||
private async Task RefreshDataView()
|
private async Task RefreshDataView()
|
||||||
{
|
{
|
||||||
// 更新界面显示的数据:重新从数据库加载所有变量数据
|
// 从数据库加载最新的变量数据
|
||||||
|
var latestVariables = await _varDataRepository.GetByVariableTableIdAsync(VariableTable.Id);
|
||||||
|
|
||||||
var varList = await _varDataRepository.GetByVariableTableIdAsync(VariableTable.Id);
|
// 将最新数据转换为字典,以便快速查找
|
||||||
// 处理删除
|
var latestVariablesDict = latestVariables.ToDictionary(v => v.Id);
|
||||||
if (varList.Count < DataVariables.Count)
|
|
||||||
|
// 用于存储需要从 DataVariables 中移除的项
|
||||||
|
var itemsToRemove = new List<VariableData>();
|
||||||
|
|
||||||
|
// 遍历当前 DataVariables 集合,处理删除和更新
|
||||||
|
for (int i = DataVariables.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
for (int i = DataVariables.Count-1; i >=0; i--)
|
var currentVariable = DataVariables[i];
|
||||||
|
if (latestVariablesDict.TryGetValue(currentVariable.Id, out var newVariable))
|
||||||
{
|
{
|
||||||
bool isExist=false;
|
// 如果存在于最新数据中,检查是否需要更新
|
||||||
foreach (var variableData in varList)
|
if (!currentVariable.Equals(newVariable))
|
||||||
{
|
{
|
||||||
if (variableData.Id==DataVariables[i].Id)
|
// 使用 AutoMapper 更新现有对象的属性,保持对象引用不变
|
||||||
{
|
_mapper.Map(newVariable, currentVariable);
|
||||||
isExist=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isExist)
|
|
||||||
{
|
|
||||||
DataVariables.RemoveAt(i);
|
|
||||||
}
|
}
|
||||||
|
// 从字典中移除已处理的项,剩余的将是新增项
|
||||||
|
latestVariablesDict.Remove(currentVariable.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果不存在于最新数据中,则标记为删除
|
||||||
|
itemsToRemove.Add(currentVariable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理修改和 添加
|
// 移除已标记的项
|
||||||
foreach (var newVariable in varList)
|
foreach (var item in itemsToRemove)
|
||||||
{
|
{
|
||||||
bool isExiset = false;
|
DataVariables.Remove(item);
|
||||||
for (int i = 0; i < DataVariables.Count; i++)
|
|
||||||
{
|
|
||||||
var oldVariable = DataVariables[i];
|
|
||||||
// 判断是否存在
|
|
||||||
if (newVariable.Id == oldVariable.Id)
|
|
||||||
{
|
|
||||||
isExiset = true;
|
|
||||||
//判断是否相等
|
|
||||||
if (!oldVariable.Equals(newVariable))
|
|
||||||
{
|
|
||||||
DataVariables[i] = newVariable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不存在则添加
|
|
||||||
if (!isExiset)
|
|
||||||
{
|
|
||||||
DataVariables.Add(newVariable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加所有剩余在 latestVariablesDict 中的项(这些是新增项)
|
||||||
|
foreach (var newVariable in latestVariablesDict.Values)
|
||||||
|
{
|
||||||
|
DataVariables.Add(newVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新视图以应用所有更改
|
||||||
VariableDataView.Refresh();
|
VariableDataView.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,6 +567,44 @@ partial class VariableTableViewModel : ViewModelBase
|
|||||||
// 设置新变量的所属变量表ID
|
// 设置新变量的所属变量表ID
|
||||||
varData.VariableTableId = variableTable.Id;
|
varData.VariableTableId = variableTable.Id;
|
||||||
|
|
||||||
|
// --- 重复性检查逻辑开始 ---
|
||||||
|
bool isDuplicate = false;
|
||||||
|
string duplicateReason = string.Empty;
|
||||||
|
|
||||||
|
// 检查名称是否重复
|
||||||
|
if (DataVariables.Any(v => v.Name == varData.Name))
|
||||||
|
{
|
||||||
|
isDuplicate = true;
|
||||||
|
duplicateReason = $"名称 '{varData.Name}' 已存在。";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 根据协议类型检查S7地址或NodeId是否重复
|
||||||
|
if (variableTable.ProtocolType == ProtocolType.S7)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(varData.S7Address) && DataVariables.Any(v => v.S7Address == varData.S7Address))
|
||||||
|
{
|
||||||
|
isDuplicate = true;
|
||||||
|
duplicateReason = $"S7地址 '{varData.S7Address}' 已存在。";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (variableTable.ProtocolType == ProtocolType.OpcUA)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(varData.NodeId) && DataVariables.Any(v => v.NodeId == varData.NodeId))
|
||||||
|
{
|
||||||
|
isDuplicate = true;
|
||||||
|
duplicateReason = $"OPC UA NodeId '{varData.NodeId}' 已存在。";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDuplicate)
|
||||||
|
{
|
||||||
|
NotificationHelper.ShowError($"添加变量失败:{duplicateReason}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// --- 重复性检查逻辑结束 ---
|
||||||
|
|
||||||
// 添加变量数据到数据库
|
// 添加变量数据到数据库
|
||||||
var resVarData = await _varDataRepository.AddAsync(varData);
|
var resVarData = await _varDataRepository.AddAsync(varData);
|
||||||
if (resVarData == null)
|
if (resVarData == null)
|
||||||
|
|||||||
55
Views/Dialogs/ImportResultDialog.xaml
Normal file
55
Views/Dialogs/ImportResultDialog.xaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<ui:ContentDialog
|
||||||
|
x:Class="PMSWPF.Views.Dialogs.ImportResultDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||||
|
xmlns:viewmodels="clr-namespace:PMSWPF.ViewModels.Dialogs"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DataContext="{d:DesignInstance Type=viewmodels:ImportResultDialogViewModel}"
|
||||||
|
Title="导入结果"
|
||||||
|
PrimaryButtonText="确定"
|
||||||
|
PrimaryButtonCommand="{Binding CloseCommand}"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Grid Margin="0,10,0,0">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Summary -->
|
||||||
|
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,0,10" HorizontalAlignment="Center" FontSize="14" FontWeight="SemiBold">
|
||||||
|
<Run Text="总计导入: "/>
|
||||||
|
<Run Text="{Binding ImportedVariables.Count, Mode=OneWay}"/>
|
||||||
|
<Run Text="个, 跳过: "/>
|
||||||
|
<Run Text="{Binding ExistingVariables.Count, Mode=OneWay}"/>
|
||||||
|
<Run Text="个"/>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<!-- Imported Variables Section -->
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0" Margin="0,0,10,0">
|
||||||
|
<TextBlock Text="成功导入的变量:" FontWeight="Bold" Margin="0,0,0,5" FontSize="13"/>
|
||||||
|
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderThickness="1" CornerRadius="4" Padding="5">
|
||||||
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
|
<ListBox ItemsSource="{Binding ImportedVariables}" Style="{DynamicResource ListBoxRevealStyle}" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Existing Variables Section -->
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" Margin="10,0,0,0">
|
||||||
|
<TextBlock Text="已存在的变量 (未导入):" FontWeight="Bold" Margin="0,0,0,5" FontSize="13"/>
|
||||||
|
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderThickness="1" CornerRadius="4" Padding="5">
|
||||||
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
|
<ListBox ItemsSource="{Binding ExistingVariables}" Style="{DynamicResource ListBoxRevealStyle}" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</ui:ContentDialog>
|
||||||
20
Views/Dialogs/ImportResultDialog.xaml.cs
Normal file
20
Views/Dialogs/ImportResultDialog.xaml.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using iNKORE.UI.WPF.Modern.Controls;
|
||||||
|
using PMSWPF.ViewModels.Dialogs;
|
||||||
|
|
||||||
|
namespace PMSWPF.Views.Dialogs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ImportResultDialog.xaml 的交互逻辑
|
||||||
|
/// </summary>
|
||||||
|
public partial class ImportResultDialog : ContentDialog
|
||||||
|
{
|
||||||
|
public ImportResultDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportResultDialog(ImportResultDialogViewModel viewModel) : this()
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user