修改批量导入变量返回实体,防止Io为0的问题

This commit is contained in:
2025-09-15 13:12:14 +08:00
parent d622d73057
commit 4773e87886
26 changed files with 171 additions and 139 deletions

View File

@@ -79,6 +79,8 @@ public partial class App : System.Windows.Application
dataProcessingService.AddProcessor(Host.Services.GetRequiredService<UpdateDbVariableProcessor>());
// 添加报警处理器
dataProcessingService.AddProcessor(Host.Services.GetRequiredService<DMS.Application.Services.Processors.AlarmProcessor>());
// 添加触发器处理器
dataProcessingService.AddProcessor(Host.Services.GetRequiredService<TriggerProcessor>());
}
catch (Exception exception)
{
@@ -201,6 +203,7 @@ public partial class App : System.Windows.Application
services.AddSingleton<DMS.Application.Interfaces.IAlarmService, DMS.Application.Services.AlarmService>();
services.AddSingleton<DMS.Application.Services.Processors.AlarmProcessor>();
services.AddSingleton<DMS.Application.EventHandlers.AlarmEventHandler>();
services.AddSingleton<TriggerProcessor>(); // 注册触发器处理器
// 注册Core中的仓库
services.AddSingleton<AppSettings>();

View File

@@ -176,7 +176,6 @@
<ItemGroup>
<Folder Include="ViewModels\Items\" />
<Folder Include="ViewModels\Triggers\" />
</ItemGroup>

View File

@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.Messaging;
using DMS.Application.DTOs;
using DMS.Application.DTOs.Events;
using DMS.Application.Interfaces;
using DMS.Application.Services.Triggers; // 添加触发器服务引用
using DMS.Core.Enums;
using DMS.Core.Models;
using DMS.Message;
@@ -23,7 +22,6 @@ public class DataEventService : IDataEventService
private readonly IDataStorageService _dataStorageService;
private readonly IAppDataCenterService _appDataCenterService;
private readonly IWPFDataService _wpfDataService;
private readonly ITriggerEvaluationService _triggerEvaluationService; // 新增依赖
/// <summary>
/// DataEventService类的构造函数。
@@ -31,15 +29,12 @@ public class DataEventService : IDataEventService
public DataEventService(IMapper mapper,
IDataStorageService dataStorageService,
IAppDataCenterService appDataCenterService,
IWPFDataService wpfDataService,
ITriggerEvaluationService triggerEvaluationService // 新增参数
)
IWPFDataService wpfDataService)
{
_mapper = mapper;
_dataStorageService = dataStorageService;
_appDataCenterService = appDataCenterService;
_wpfDataService = wpfDataService;
_triggerEvaluationService = triggerEvaluationService; // 赋值
// 监听变量值变更事件
_appDataCenterService.VariableManagementService.OnVariableValueChanged += OnVariableValueChanged;
@@ -65,7 +60,7 @@ public class DataEventService : IDataEventService
/// <summary>
/// 处理变量值变更事件。
/// </summary>
private async void OnVariableValueChanged(object? sender, VariableValueChangedEventArgs e) // 改为 async void 以便调用 await
private void OnVariableValueChanged(object? sender, VariableValueChangedEventArgs e)
{
// 在UI线程上更新变量值
App.Current.Dispatcher.BeginInvoke(new Action(() =>
@@ -79,27 +74,6 @@ public class DataEventService : IDataEventService
variableToUpdate.UpdatedAt = e.UpdateTime;
}
}));
// 在后台线程上调用触发器评估服务
// 使用 Task.Run 将其放到线程池线程上执行,避免阻塞 UI 线程
// 注意:这里调用的是 Fire-and-forget因为我们不等待结果。
// 如果将来需要处理执行结果或错误,可以考虑使用 async Task 并在适当的地方等待。
_ = Task.Run(async () =>
{
try
{
await _triggerEvaluationService.EvaluateTriggersAsync(e.VariableId, e.NewValue);
}
catch (Exception ex)
{
// Log the exception appropriately.
// Since this is fire-and-forget, we must handle exceptions internally.
// You might have a logging service injected or use a static logger.
// For now, let's assume a static logger or inline comment.
System.Diagnostics.Debug.WriteLine($"Error evaluating triggers for variable {e.VariableId}: {ex}");
// Consider integrating with your logging framework (e.g., NLog) here.
}
});
}

View File

@@ -39,26 +39,26 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
/// 建议的变量列表
/// </summary>
[ObservableProperty]
private ObservableCollection<VariableHistoryDto> _suggestedVariables;
private ObservableCollection<string> _suggestedVariables;
/// <summary>
/// 历史记录条数限制
/// </summary>
[ObservableProperty]
private int? _historyLimit;
/// <summary>
/// 历史记录开始时间
/// </summary>
[ObservableProperty]
private DateTime? _startTime;
/// <summary>
/// 历史记录结束时间
/// </summary>
[ObservableProperty]
private DateTime? _endTime;
/// <summary>
/// 选中的变量历史记录
/// </summary>
@@ -79,7 +79,8 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
private List<VariableHistoryDto> _allVariableHistories;
public VariableHistoryViewModel(IMapper mapper, IDialogService dialogService, IHistoryAppService historyAppService,
IWPFDataService wpfDataService, IDataStorageService dataStorageService, INotificationService notificationService)
IWPFDataService wpfDataService, IDataStorageService dataStorageService,
INotificationService notificationService)
{
_mapper = mapper;
_dialogService = dialogService;
@@ -92,8 +93,8 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
_variableHistorySynchronizedView = _variableHistoryList.CreateView(v => v);
VariableHistories = _variableHistorySynchronizedView.ToNotifyCollectionChanged();
_allVariableHistories = new List<VariableHistoryDto>();
_suggestedVariables = new ObservableCollection<VariableHistoryDto>();
_suggestedVariables = new ObservableCollection<string>();
// 初始化默认值
_historyLimit = 1000; // 默认限制1000条记录
_startTime = null;
@@ -115,7 +116,7 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
var allHistories = await _historyAppService.GetAllVariableHistoriesAsync(limit, startTime, endTime);
_allVariableHistories = allHistories.ToList();
_variableHistoryList.AddRange(_allVariableHistories);
// 更新建议列表
UpdateSuggestedVariables();
}
@@ -127,52 +128,38 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
}
/// <summary>
/// 更新建议的变量列表
/// </summary>
private void UpdateSuggestedVariables()
{
// 清空现有建议列表
_suggestedVariables.Clear();
if (string.IsNullOrWhiteSpace(SearchText))
/// 更新建议的变量列表
/// </summary>
private void UpdateSuggestedVariables()
{
// 如果搜索文本为空,显示所有唯一的变量名
var uniqueVariables = _allVariableHistories
.GroupBy(h => h.VariableName)
.Select(g => g.First())
.Take(10)
.ToList();
// 清空现有建议列表
_suggestedVariables.Clear();
foreach (var variable in uniqueVariables)
if (!string.IsNullOrWhiteSpace(SearchText))
{
_suggestedVariables.Add(variable);
// 根据搜索文本过滤建议列表
var filteredVariables = _dataStorageService.Variables
.Where(v =>
v.Name?.Contains(
SearchText, StringComparison.OrdinalIgnoreCase) ==
true)
.Select(v => v.Name)
.Take(10)
.ToList();
foreach (var variable in filteredVariables)
{
_suggestedVariables.Add(variable);
}
}
}
else
{
// 根据搜索文本过滤建议列表
var filteredVariables = _allVariableHistories
.Where(h =>
h.VariableName?.Contains(SearchText, StringComparison.OrdinalIgnoreCase) ==
true)
.GroupBy(h => h.VariableName)
.Select(g => g.First())
.Take(10)
.ToList();
foreach (var variable in filteredVariables)
{
_suggestedVariables.Add(variable);
}
}
}
public async Task OnNavigatedToAsync(MenuItemViewModel menu)
{
// 加载所有变量的历史记录
LoadAllVariableHistories(HistoryLimit, StartTime, EndTime);
}
/// <summary>
/// 重新加载历史记录命令
/// </summary>
@@ -181,7 +168,7 @@ private void UpdateSuggestedVariables()
{
LoadAllVariableHistories(HistoryLimit, StartTime, EndTime);
}
/// <summary>
/// 更新建议列表命令
/// </summary>
@@ -190,16 +177,19 @@ private void UpdateSuggestedVariables()
{
UpdateSuggestedVariables();
}
/// <summary>
/// 当搜索文本改变时触发
/// </summary>
/// <param name="value"></param>
partial void OnSearchTextChanged(string value)
{
// 添加调试信息
System.Diagnostics.Debug.WriteLine($"OnSearchTextChanged called with value: '{value}'");
// 更新建议列表
UpdateSuggestedVariables();
if (string.IsNullOrWhiteSpace(value))
{
// 如果搜索文本为空,显示所有历史记录
@@ -219,7 +209,7 @@ private void UpdateSuggestedVariables()
_variableHistoryList.AddRange(filteredHistories);
}
}
/// <summary>
/// 根据搜索文本过滤历史记录
/// </summary>
@@ -245,7 +235,7 @@ private void UpdateSuggestedVariables()
_variableHistoryList.AddRange(filteredHistories);
}
}
/// <summary>
/// 重新加载历史记录,使用当前设置的限制和时间范围
/// </summary>
@@ -253,7 +243,7 @@ private void UpdateSuggestedVariables()
{
LoadAllVariableHistories(HistoryLimit, StartTime, EndTime);
}
/// <summary>
/// 根据变量ID加载历史记录
/// </summary>
@@ -261,14 +251,15 @@ private void UpdateSuggestedVariables()
/// <param name="limit">返回记录的最大数量null表示无限制</param>
/// <param name="startTime">开始时间null表示无限制</param>
/// <param name="endTime">结束时间null表示无限制</param>
public async Task LoadVariableHistoriesAsync(int variableId, int? limit = null, DateTime? startTime = null, DateTime? endTime = null)
public async Task LoadVariableHistoriesAsync(int variableId, int? limit = null, DateTime? startTime = null,
DateTime? endTime = null)
{
try
{
_variableHistoryList.Clear();
var histories = await _historyAppService.GetVariableHistoriesAsync(variableId, limit, startTime, endTime);
_variableHistoryList.AddRange(histories);
// 更新建议列表
UpdateSuggestedVariables();
}

View File

@@ -261,10 +261,10 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (improtVariableDtos.Count != 0)
{
var isSuccess = await _variableAppService.BatchImportVariablesAsync(improtVariableDtos);
if (isSuccess)
var addVariableDtos = await _variableAppService.BatchImportVariablesAsync(improtVariableDtos);
if (addVariableDtos is { Count: > 0 })
{
_variableItemList.AddRange(_mapper.Map<List<VariableItemViewModel>>(improtVariableDtos));
_variableItemList.AddRange(_mapper.Map<List<VariableItemViewModel>>(addVariableDtos));
_notificationService.ShowSuccess($"从Excel导入变量成功共导入变量{improtVariableDtos.Count}个");
}
}
@@ -338,12 +338,9 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 如果还有变量需要导入,则执行导入操作
if (importedVariableDtos.Count != 0)
{
var isSuccess = await _variableAppService.BatchImportVariablesAsync(importedVariableDtos);
if (isSuccess)
var addVariableDtos = await _variableAppService.BatchImportVariablesAsync(importedVariableDtos);
if (addVariableDtos is { Count: > 0 })
{
var addVariableDtos = await _variableAppService.GetVariableByOpcUaNodeIdsAsync(
importedVariableDtos.Select(v => v.OpcUaNodeId)
.ToList());
_variableItemList.AddRange(_mapper.Map<List<VariableItemViewModel>>(addVariableDtos));
_notificationService.ShowSuccess($"从OPC UA服务器导入变量成功共导入变量{importedVariableDtos.Count}个");
}

View File

@@ -98,7 +98,7 @@
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Top">
<Border Background="{Binding IsConnected,
<Border Background="{Binding IsRunning,
Converter={StaticResource BoolToColorConverter},
ConverterParameter='Green;Red'}"
CornerRadius="8"
@@ -106,7 +106,7 @@
Height="16"
Margin="0,0,10,0">
<Border.ToolTip>
<TextBlock Text="{Binding IsConnected,
<TextBlock Text="{Binding IsRunning,
Converter={StaticResource BoolToStringConverter},
ConverterParameter='已连接;未连接'}"/>
</Border.ToolTip>
@@ -267,6 +267,7 @@
</Button>
<Button Content="&#xE76C;"
Command="{Binding EditDeviceCommand}"
FontFamily="Segoe MDL2 Assets"
FontSize="16"
Width="36"
@@ -287,6 +288,7 @@
ToolTip="监控设备"/>
<Button Content="&#xE74D;"
Command="{Binding DeleteDeviceCommand}"
FontFamily="Segoe MDL2 Assets"
FontSize="16"
Width="36"