diff --git a/DMS.Application/Services/Triggers/ITriggerEvaluationService.cs b/DMS.Application/Services/Triggers/ITriggerEvaluationService.cs
index 556aeba..447c73d 100644
--- a/DMS.Application/Services/Triggers/ITriggerEvaluationService.cs
+++ b/DMS.Application/Services/Triggers/ITriggerEvaluationService.cs
@@ -14,6 +14,6 @@ namespace DMS.Application.Services.Triggers
/// 变量 ID
/// 变量的当前值
/// 任务
- Task EvaluateTriggersAsync(Guid variableId, object currentValue);
+ Task EvaluateTriggersAsync(int variableId, object currentValue);
}
}
\ No newline at end of file
diff --git a/DMS.Application/Services/Triggers/Impl/TriggerActionExecutor.cs b/DMS.Application/Services/Triggers/Impl/TriggerActionExecutor.cs
index 4231ad2..b105d4d 100644
--- a/DMS.Application/Services/Triggers/Impl/TriggerActionExecutor.cs
+++ b/DMS.Application/Services/Triggers/Impl/TriggerActionExecutor.cs
@@ -4,6 +4,8 @@ using System.Text.Json;
using System.Threading.Tasks;
using DMS.Application.DTOs.Triggers;
using DMS.Application.Services.Triggers;
+using DMS.Core.Interfaces.Services;
+using DMS.Core.Models.Triggers;
using Microsoft.Extensions.Logging; // 使用标准日志接口
namespace DMS.Application.Services.Triggers.Impl
@@ -108,7 +110,7 @@ namespace DMS.Application.Services.Triggers.Impl
.Replace("{UpperBound}", context.Trigger.UpperBound?.ToString() ?? "N/A")
.Replace("{Timestamp}", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
- await _emailService.SendEmailAsync(recipients, subject, body);
+ // await _emailService.SendEmailAsync(recipients, subject, body);
}
/*
diff --git a/DMS.Application/Services/Triggers/Impl/TriggerEvaluationService.cs b/DMS.Application/Services/Triggers/Impl/TriggerEvaluationService.cs
index ece17b6..82eacd3 100644
--- a/DMS.Application/Services/Triggers/Impl/TriggerEvaluationService.cs
+++ b/DMS.Application/Services/Triggers/Impl/TriggerEvaluationService.cs
@@ -8,6 +8,7 @@ using ThreadingTimer = System.Threading.Timer;
using TimersTimer = System.Timers.Timer;
using DMS.Application.DTOs.Triggers;
using DMS.Application.Services.Triggers;
+using DMS.Core.Models.Triggers;
using Microsoft.Extensions.Logging; // 使用 Microsoft.Extensions.Logging.ILogger
namespace DMS.Application.Services.Triggers.Impl
@@ -39,61 +40,61 @@ namespace DMS.Application.Services.Triggers.Impl
///
/// 评估与指定变量关联的所有激活状态的触发器
///
- public async Task EvaluateTriggersAsync(Guid variableId, object currentValue)
+ public async Task EvaluateTriggersAsync(int variableId, object currentValue)
{
- try
- {
- var triggers = await _triggerManagementService.GetTriggersForVariableAsync(variableId);
+ // try
+ // {
+ // var triggers = await _triggerManagementService.GetTriggersForVariableAsync(variableId);
// 注意:这里不再通过 _variableAppService 获取 VariableDto,
// 而是在调用 ExecuteActionAsync 时,由上层(DataEventService)提供。
// 如果需要 VariableDto 信息,可以在 ExecuteActionAsync 的 TriggerContext 中携带。
- _logger.LogDebug($"Evaluating {triggers.Count(t => t.IsActive)} active triggers for variable ID: {variableId}");
-
- foreach (var trigger in triggers.Where(t => t.IsActive))
- {
- if (!IsWithinSuppressionWindow(trigger)) // Check suppression first
- {
- if (EvaluateCondition(trigger, currentValue))
- {
- // 创建一个临时的上下文对象,其中 VariableDto 可以为 null,
- // 因为我们目前没有从 _variableAppService 获取它。
- // 在实际应用中,你可能需要通过某种方式获取 VariableDto。
- var context = new TriggerContext(trigger, currentValue, null);
-
- await _actionExecutor.ExecuteActionAsync(context);
-
- // Update last triggered time and start suppression timer if needed
- trigger.LastTriggeredAt = DateTime.UtcNow;
- // For simplicity, we'll assume it's updated periodically or on next load.
- // In a production scenario, you'd likely want to persist this back to the database.
-
- // Start suppression timer if duration is set (in-memory suppression)
- if (trigger.SuppressionDuration.HasValue)
- {
- // 使用 ThreadingTimer 避免歧义
- var timer = new ThreadingTimer(_ =>
- {
- trigger.LastTriggeredAt = null; // Reset suppression flag after delay
- _logger.LogInformation($"Suppression lifted for trigger {trigger.Id}");
- // Note: Modifying 'trigger' directly affects the object in the list returned by GetTriggersForVariableAsync().
- // This works for in-memory state but won't persist changes. Consider updating DB explicitly if needed.
- }, null, trigger.SuppressionDuration.Value, Timeout.InfiniteTimeSpan); // Single shot timer
-
- // Replace any existing timer for this trigger ID
- _suppressionTimers.AddOrUpdate(trigger.Id, timer, (key, oldTimer) => {
- oldTimer?.Dispose();
- return timer;
- });
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "An error occurred while evaluating triggers for variable ID: {VariableId}", variableId);
- }
+ // _logger.LogDebug($"Evaluating {triggers.Count(t => t.IsActive)} active triggers for variable ID: {variableId}");
+ //
+ // foreach (var trigger in triggers.Where(t => t.IsActive))
+ // {
+ // if (!IsWithinSuppressionWindow(trigger)) // Check suppression first
+ // {
+ // if (EvaluateCondition(trigger, currentValue))
+ // {
+ // // 创建一个临时的上下文对象,其中 VariableDto 可以为 null,
+ // // 因为我们目前没有从 _variableAppService 获取它。
+ // // 在实际应用中,你可能需要通过某种方式获取 VariableDto。
+ // var context = new TriggerContext(trigger, currentValue, null);
+ //
+ // await _actionExecutor.ExecuteActionAsync(context);
+ //
+ // // Update last triggered time and start suppression timer if needed
+ // trigger.LastTriggeredAt = DateTime.UtcNow;
+ // // For simplicity, we'll assume it's updated periodically or on next load.
+ // // In a production scenario, you'd likely want to persist this back to the database.
+ //
+ // // Start suppression timer if duration is set (in-memory suppression)
+ // if (trigger.SuppressionDuration.HasValue)
+ // {
+ // // 使用 ThreadingTimer 避免歧义
+ // var timer = new ThreadingTimer(_ =>
+ // {
+ // trigger.LastTriggeredAt = null; // Reset suppression flag after delay
+ // _logger.LogInformation($"Suppression lifted for trigger {trigger.Id}");
+ // // Note: Modifying 'trigger' directly affects the object in the list returned by GetTriggersForVariableAsync().
+ // // This works for in-memory state but won't persist changes. Consider updating DB explicitly if needed.
+ // }, null, trigger.SuppressionDuration.Value, Timeout.InfiniteTimeSpan); // Single shot timer
+ //
+ // // Replace any existing timer for this trigger ID
+ // _suppressionTimers.AddOrUpdate(trigger.Id, timer, (key, oldTimer) => {
+ // oldTimer?.Dispose();
+ // return timer;
+ // });
+ // }
+ // }
+ // }
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // _logger.LogError(ex, "An error occurred while evaluating triggers for variable ID: {VariableId}", variableId);
+ // }
}
///
diff --git a/DMS.Infrastructure/Profiles/MappingProfile.cs b/DMS.Infrastructure/Profiles/MappingProfile.cs
index 84bbf91..c218956 100644
--- a/DMS.Infrastructure/Profiles/MappingProfile.cs
+++ b/DMS.Infrastructure/Profiles/MappingProfile.cs
@@ -2,6 +2,7 @@ using System;
using AutoMapper;
using DMS.Infrastructure.Entities;
using DMS.Core.Models;
+using DMS.Core.Models.Triggers;
namespace DMS.Infrastructure.Profiles;
@@ -42,5 +43,17 @@ public class MappingProfile : Profile
CreateMap().ReverseMap();
CreateMap().ReverseMap();
CreateMap().ReverseMap();
+
+ // --- 触发器映射 ---
+ CreateMap()
+ .ForMember(dest => dest.SuppressionDuration,
+ opt => opt.MapFrom(src => src.SuppressionDurationTicks.HasValue ?
+ TimeSpan.FromTicks(src.SuppressionDurationTicks.Value) :
+ (TimeSpan?)null))
+ .ReverseMap()
+ .ForMember(dest => dest.SuppressionDurationTicks,
+ opt => opt.MapFrom(src => src.SuppressionDuration.HasValue ?
+ src.SuppressionDuration.Value.Ticks :
+ (long?)null));
}
}
diff --git a/DMS.Infrastructure/Repositories/BaseRepository.cs b/DMS.Infrastructure/Repositories/BaseRepository.cs
index d297c36..16f506f 100644
--- a/DMS.Infrastructure/Repositories/BaseRepository.cs
+++ b/DMS.Infrastructure/Repositories/BaseRepository.cs
@@ -117,6 +117,23 @@ public abstract class BaseRepository
return entity;
}
+ ///
+ /// 异步根据主键 ID (Guid类型) 获取单个实体。
+ ///
+ /// 实体的主键 ID (Guid类型)。
+ /// 返回找到的实体,如果未找到则返回 null。
+ public virtual async Task GetByIdAsync(Guid id)
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ var entity = await Db.Queryable()
+ .In(id)
+ .FirstAsync();
+ stopwatch.Stop();
+ _logger.LogInformation($"GetById {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
+ return entity;
+ }
+
///
/// 异步根据主键 ID 列表批量删除实体。
///
diff --git a/DMS.Infrastructure/Repositories/InitializeRepository.cs b/DMS.Infrastructure/Repositories/InitializeRepository.cs
index a1d5c65..9730bff 100644
--- a/DMS.Infrastructure/Repositories/InitializeRepository.cs
+++ b/DMS.Infrastructure/Repositories/InitializeRepository.cs
@@ -51,6 +51,7 @@ public class InitializeRepository : IInitializeRepository
_db.CodeFirst.InitTables();
_db.CodeFirst.InitTables();
_db.CodeFirst.InitTables();
+ _db.CodeFirst.InitTables();
}
///
@@ -139,26 +140,32 @@ public class InitializeRepository : IInitializeRepository
},
new DbMenu
{
- Id = 5, Header = "日志历史", Icon = "\uE7BA", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "LogHistoryView",
+ Id = 5, Header = "触发器", Icon = "\uE7BA", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "TriggersView",
DisplayOrder = 5
},
new DbMenu
{
- Id = 6, Header = "邮件管理", Icon = "\uE715", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "EmailManagementView",
+ Id = 6, Header = "日志历史", Icon = "\uE7BA", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "LogHistoryView",
DisplayOrder = 6
},
new DbMenu
{
- Id = 7, Header = "设置", Icon = "\uE713", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "SettingView",
+ Id = 7, Header = "邮件管理", Icon = "\uE715", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "EmailManagementView",
DisplayOrder = 7
},
new DbMenu
{
- Id = 8, Header = "关于", Icon = "\uE946", ParentId = 0,
- MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 8
+ Id = 8, Header = "设置", Icon = "\uE713", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "SettingView",
+ DisplayOrder = 8
+ },
+ new DbMenu
+ {
+ Id = 9, Header = "关于", Icon = "\uE946", ParentId = 0,
+ MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 9
} // 假设有一个AboutView
};
diff --git a/DMS.Infrastructure/Repositories/RepositoryManager.cs b/DMS.Infrastructure/Repositories/RepositoryManager.cs
index 79ec674..9f45ff5 100644
--- a/DMS.Infrastructure/Repositories/RepositoryManager.cs
+++ b/DMS.Infrastructure/Repositories/RepositoryManager.cs
@@ -3,7 +3,6 @@ using DMS.Core.Interfaces;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Interfaces.Repositories.Triggers; // 引入新的接口
using DMS.Infrastructure.Data;
-using DMS.Infrastructure.Repositories.Triggers; // 引入实现类所在的命名空间
using SqlSugar;
namespace DMS.Infrastructure.Repositories;
diff --git a/DMS.Infrastructure/Repositories/TriggerRepository.cs b/DMS.Infrastructure/Repositories/TriggerRepository.cs
new file mode 100644
index 0000000..c482a89
--- /dev/null
+++ b/DMS.Infrastructure/Repositories/TriggerRepository.cs
@@ -0,0 +1,97 @@
+using System.Diagnostics;
+using AutoMapper;
+using DMS.Core.Interfaces.Repositories.Triggers;
+using DMS.Core.Models.Triggers;
+using DMS.Infrastructure.Data;
+using DMS.Infrastructure.Entities;
+using Microsoft.Extensions.Logging;
+
+namespace DMS.Infrastructure.Repositories
+{
+ ///
+ /// 触发器仓储实现类,负责触发器数据的持久化操作。
+ /// 继承自 并实现 接口。
+ ///
+ public class TriggerRepository : BaseRepository, ITriggerRepository
+ {
+ private readonly IMapper _mapper;
+
+ ///
+ /// 构造函数,注入 AutoMapper 和 SqlSugarDbContext。
+ ///
+ /// AutoMapper 实例,用于实体模型和数据库模型之间的映射。
+ /// SqlSugar 数据库上下文,用于数据库操作。
+ /// 日志记录器实例。
+ public TriggerRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger)
+ : base(dbContext, logger)
+ {
+ _mapper = mapper;
+ }
+
+ ///
+ /// 获取所有触发器定义
+ ///
+ public async Task> GetAllAsync()
+ {
+ var dbList = await base.GetAllAsync();
+ return _mapper.Map>(dbList);
+ }
+
+ ///
+ /// 根据 ID 获取触发器定义
+ ///
+ public async Task GetByIdAsync(Guid id)
+ {
+ var dbTrigger = await base.GetByIdAsync(id);
+ return _mapper.Map(dbTrigger);
+ }
+
+ ///
+ /// 添加一个新的触发器定义
+ ///
+ public async Task AddAsync(TriggerDefinition trigger)
+ {
+ var dbTrigger = await base.AddAsync(_mapper.Map(trigger));
+ return _mapper.Map(dbTrigger, trigger);
+ }
+
+ ///
+ /// 更新一个已存在的触发器定义
+ ///
+ public async Task UpdateAsync(TriggerDefinition trigger)
+ {
+ var rowsAffected = await base.UpdateAsync(_mapper.Map(trigger));
+ return rowsAffected > 0 ? trigger : null;
+ }
+
+ ///
+ /// 删除一个触发器定义
+ ///
+ public async Task DeleteAsync(Guid id)
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ var rowsAffected = await Db.Deleteable()
+ .In(id)
+ .ExecuteCommandAsync();
+ stopwatch.Stop();
+ _logger.LogInformation($"Delete {typeof(DbTriggerDefinition).Name},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
+ return rowsAffected > 0;
+ }
+
+ ///
+ /// 获取与指定变量关联的所有触发器定义
+ ///
+ public async Task> GetByVariableIdAsync(Guid variableId)
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ var dbList = await Db.Queryable()
+ .Where(t => t.VariableId == variableId)
+ .ToListAsync();
+ stopwatch.Stop();
+ _logger.LogInformation($"GetByVariableId {typeof(DbTriggerDefinition).Name},VariableId={variableId},耗时:{stopwatch.ElapsedMilliseconds}ms");
+ return _mapper.Map>(dbList);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.Infrastructure/Repositories/Triggers/Impl/SqlSugarTriggerRepository.cs b/DMS.Infrastructure/Repositories/Triggers/Impl/SqlSugarTriggerRepository.cs
deleted file mode 100644
index fc30272..0000000
--- a/DMS.Infrastructure/Repositories/Triggers/Impl/SqlSugarTriggerRepository.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using DMS.Core.Models.Triggers;
-using SqlSugar;
-
-namespace DMS.Infrastructure.Repositories.Triggers.Impl
-{
- ///
- /// 基于 SqlSugar 的触发器仓储实现
- ///
- public class SqlSugarTriggerRepository : ITriggerRepository
- {
- private readonly ISqlSugarClient _db;
-
- public SqlSugarTriggerRepository(ISqlSugarClient db)
- {
- _db = db ?? throw new ArgumentNullException(nameof(db));
- }
-
- ///
- /// 获取所有触发器定义
- ///
- public async Task> GetAllAsync()
- {
- return await _db.Queryable().ToListAsync();
- }
-
- ///
- /// 根据 ID 获取触发器定义
- ///
- public async Task GetByIdAsync(Guid id)
- {
- return await _db.Queryable().InSingleAsync(id);
- }
-
- ///
- /// 添加一个新的触发器定义
- ///
- public async Task AddAsync(TriggerDefinition trigger)
- {
- var insertedId = await _db.Insertable(trigger).ExecuteReturnSnowflakeIdAsync();
- trigger.Id = insertedId;
- return trigger;
- }
-
- ///
- /// 更新一个已存在的触发器定义
- ///
- public async Task UpdateAsync(TriggerDefinition trigger)
- {
- var rowsAffected = await _db.Updateable(trigger).ExecuteCommandAsync();
- return rowsAffected > 0 ? trigger : null;
- }
-
- ///
- /// 删除一个触发器定义
- ///
- public async Task DeleteAsync(Guid id)
- {
- var rowsAffected = await _db.Deleteable().In(id).ExecuteCommandAsync();
- return rowsAffected > 0;
- }
-
- ///
- /// 获取与指定变量关联的所有触发器定义
- ///
- public async Task> GetByVariableIdAsync(Guid variableId)
- {
- return await _db.Queryable()
- .Where(t => t.VariableId == variableId)
- .ToListAsync();
- }
- }
-}
\ No newline at end of file
diff --git a/DMS.WPF/App.xaml b/DMS.WPF/App.xaml
index b66dcd1..da96fa7 100644
--- a/DMS.WPF/App.xaml
+++ b/DMS.WPF/App.xaml
@@ -5,7 +5,7 @@
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:triggers="clr-namespace:DMS.Core.Models.Triggers;assembly=DMS.Core"
xmlns:converters="clr-namespace:DMS.WPF.Converters"
- xmlns:localConverters="clr-namespace:DMS.WPF.Converters"
+ xmlns:localConverters="clr-namespace:DMS.WPF.Converters"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern">
diff --git a/DMS.WPF/App.xaml.cs b/DMS.WPF/App.xaml.cs
index cf21434..0dbae03 100644
--- a/DMS.WPF/App.xaml.cs
+++ b/DMS.WPF/App.xaml.cs
@@ -4,8 +4,11 @@ using AutoMapper.Internal;
using DMS.Application.Interfaces;
using DMS.Application.Services;
using DMS.Application.Services.Processors;
+using DMS.Application.Services.Triggers;
+using DMS.Application.Services.Triggers.Impl;
using DMS.Core.Interfaces;
using DMS.Core.Interfaces.Repositories;
+using DMS.Core.Interfaces.Repositories.Triggers;
using DMS.Core.Interfaces.Services;
using DMS.Infrastructure.Configuration;
using DMS.Infrastructure.Configurations;
@@ -14,6 +17,7 @@ using DMS.Infrastructure.Interfaces;
using DMS.Infrastructure.Interfaces.Services;
using DMS.Infrastructure.Repositories;
using DMS.Infrastructure.Services;
+using DMS.WPF.Converters;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;
using DMS.WPF.Logging;
@@ -21,12 +25,14 @@ using DMS.WPF.Services;
using DMS.WPF.ViewModels;
using DMS.WPF.ViewModels.Dialogs;
using DMS.WPF.ViewModels.Items;
+using DMS.WPF.ViewModels.Triggers;
using DMS.WPF.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Web;
+using SqlSugar;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
@@ -204,6 +210,8 @@ public partial class App : System.Windows.Application
return new SqlSugarDbContext(appSettings);
});
+
+
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
@@ -216,7 +224,7 @@ public partial class App : System.Windows.Application
services.AddSingleton();
services.AddSingleton();
services.AddSingleton(); // 添加这行
- services.AddSingleton(); // 注册触发器仓储
+ services.AddSingleton(); // 注册触发器仓储
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
@@ -321,7 +329,7 @@ public partial class App : System.Windows.Application
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient(); // 注册 TriggerEditorViewModel
+ services.AddTransient(); // 注册 TriggerEditorViewModel
// 注册View视图
services.AddSingleton();
@@ -335,6 +343,7 @@ public partial class App : System.Windows.Application
services.AddScoped();
services.AddScoped();
services.AddSingleton();
+ services.AddSingleton(); // 注册 TriggersView
}
diff --git a/DMS.WPF/DMS.WPF.csproj b/DMS.WPF/DMS.WPF.csproj
index 819ab41..8f78734 100644
--- a/DMS.WPF/DMS.WPF.csproj
+++ b/DMS.WPF/DMS.WPF.csproj
@@ -144,6 +144,16 @@
Wpf
Designer
+
+ MSBuild:Compile
+ Wpf
+ Designer
+
+
+ MSBuild:Compile
+ Wpf
+ Designer
+
@@ -166,6 +176,7 @@
+
diff --git a/DMS.WPF/Services/DialogService.cs b/DMS.WPF/Services/DialogService.cs
index f425004..5883643 100644
--- a/DMS.WPF/Services/DialogService.cs
+++ b/DMS.WPF/Services/DialogService.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using DMS.WPF.Interfaces;
+using DMS.WPF.ViewModels.Triggers;
using DMS.WPF.Views;
using iNKORE.UI.WPF.Modern.Controls;
@@ -29,7 +30,8 @@ namespace DMS.WPF.Services
{ typeof(HistorySettingsDialogViewModel), typeof(HistorySettingsDialog) },
{ typeof(AlarmSettingsDialogViewModel), typeof(AlarmSettingsDialog) },
{ typeof(EmailAccountDialogViewModel), typeof(EmailAccountDialog) },
- { typeof(EmailTemplateDialogViewModel), typeof(EmailTemplateDialog) }
+ { typeof(EmailTemplateDialogViewModel), typeof(EmailTemplateDialog) },
+ { typeof(TriggerDialogViewModel), typeof(TriggerDialog) }
// Add other mappings here
// ... other dialogs
};
diff --git a/DMS.WPF/Services/NavigationService.cs b/DMS.WPF/Services/NavigationService.cs
index ef8ea54..52eca4e 100644
--- a/DMS.WPF/Services/NavigationService.cs
+++ b/DMS.WPF/Services/NavigationService.cs
@@ -1,6 +1,7 @@
using DMS.WPF.Interfaces;
using DMS.WPF.ViewModels;
using DMS.WPF.ViewModels.Items;
+using DMS.WPF.ViewModels.Triggers;
using Microsoft.Extensions.DependencyInjection;
namespace DMS.WPF.Services;
@@ -96,6 +97,8 @@ public class NavigationService : INavigationService
return App.Current.Services.GetRequiredService();
case "EmailManagementView":
return App.Current.Services.GetRequiredService();
+ case "TriggersView":
+ return App.Current.Services.GetRequiredService();
default:
return null;
}
diff --git a/DMS.WPF/ViewModels/Triggers/TriggerEditorViewModel.cs b/DMS.WPF/ViewModels/Dialogs/TriggerDialogViewModel.cs
similarity index 81%
rename from DMS.WPF/ViewModels/Triggers/TriggerEditorViewModel.cs
rename to DMS.WPF/ViewModels/Dialogs/TriggerDialogViewModel.cs
index a1b5e73..287ace7 100644
--- a/DMS.WPF/ViewModels/Triggers/TriggerEditorViewModel.cs
+++ b/DMS.WPF/ViewModels/Dialogs/TriggerDialogViewModel.cs
@@ -1,21 +1,19 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
using System.Text.Json;
-using System.Threading.Tasks;
+using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using DMS.Application.DTOs;
using DMS.Application.DTOs.Triggers;
+using DMS.Application.Interfaces;
using DMS.Core.Models.Triggers;
using DMS.WPF.Interfaces;
-using DMS.WPF.Services;
-namespace DMS.WPF.ViewModels.Triggers
+namespace DMS.WPF.ViewModels.Dialogs
{
///
/// 触发器编辑器视图模型
///
- public partial class TriggerEditorViewModel : DialogViewModelBase
+ public partial class TriggerDialogViewModel : DialogViewModelBase
{
private readonly IVariableAppService _variableAppService; // To populate variable selection dropdown
private readonly IDialogService _dialogService;
@@ -29,18 +27,15 @@ namespace DMS.WPF.ViewModels.Triggers
// Properties for easier binding in XAML for SendEmail action config
[ObservableProperty]
- [Required(ErrorMessage = "收件人不能为空")]
private string _emailRecipients = "";
[ObservableProperty]
- [Required(ErrorMessage = "邮件主题模板不能为空")]
private string _emailSubjectTemplate = "";
[ObservableProperty]
- [Required(ErrorMessage = "邮件内容模板不能为空")]
private string _emailBodyTemplate = "";
- public TriggerEditorViewModel(
+ public TriggerDialogViewModel(
IVariableAppService variableAppService,
IDialogService dialogService,
INotificationService notificationService)
@@ -54,7 +49,7 @@ namespace DMS.WPF.ViewModels.Triggers
/// 初始化视图模型(传入待编辑的触发器)
///
/// 待编辑的触发器 DTO
- public override async Task OnInitializedAsync(object? parameter)
+ public async Task OnInitializedAsync(object? parameter)
{
if (parameter is TriggerDefinitionDto triggerDto)
{
@@ -84,7 +79,7 @@ namespace DMS.WPF.ViewModels.Triggers
}
catch (Exception ex)
{
- _notificationService.ShowWarning($"无法解析邮件配置: {ex.Message}");
+ _notificationService.ShowWarn($"无法解析邮件配置: {ex.Message}");
}
}
}
@@ -97,7 +92,7 @@ namespace DMS.WPF.ViewModels.Triggers
{
try
{
- var variables = await _variableAppService.GetAllAsync();
+ var variables = await _variableAppService.GetAllVariablesAsync();
AvailableVariables = variables ?? new List();
}
catch (Exception ex)
@@ -116,13 +111,13 @@ namespace DMS.WPF.ViewModels.Triggers
// Basic validation
if (Trigger.VariableId == Guid.Empty)
{
- _notificationService.ShowWarning("请选择关联的变量");
+ _notificationService.ShowWarn("请选择关联的变量");
return;
}
if (string.IsNullOrWhiteSpace(Trigger.Description))
{
- _notificationService.ShowWarning("请输入触发器描述");
+ _notificationService.ShowWarn("请输入触发器描述");
return;
}
@@ -135,7 +130,7 @@ namespace DMS.WPF.ViewModels.Triggers
case ConditionType.NotEqualTo:
if (!Trigger.Threshold.HasValue)
{
- _notificationService.ShowWarning($"{Trigger.Condition} 条件需要设置阈值");
+ _notificationService.ShowWarn($"{Trigger.Condition} 条件需要设置阈值");
return;
}
break;
@@ -143,12 +138,12 @@ namespace DMS.WPF.ViewModels.Triggers
case ConditionType.OutOfRange:
if (!Trigger.LowerBound.HasValue || !Trigger.UpperBound.HasValue)
{
- _notificationService.ShowWarning($"{Trigger.Condition} 条件需要设置下限和上限");
+ _notificationService.ShowWarn($"{Trigger.Condition} 条件需要设置下限和上限");
return;
}
if (Trigger.LowerBound > Trigger.UpperBound)
{
- _notificationService.ShowWarning("下限必须小于或等于上限");
+ _notificationService.ShowWarn("下限必须小于或等于上限");
return;
}
break;
@@ -159,19 +154,19 @@ namespace DMS.WPF.ViewModels.Triggers
{
if (string.IsNullOrWhiteSpace(EmailRecipients))
{
- _notificationService.ShowWarning("请输入至少一个收件人邮箱地址");
+ _notificationService.ShowWarn("请输入至少一个收件人邮箱地址");
return;
}
if (string.IsNullOrWhiteSpace(EmailSubjectTemplate))
{
- _notificationService.ShowWarning("请输入邮件主题模板");
+ _notificationService.ShowWarn("请输入邮件主题模板");
return;
}
if (string.IsNullOrWhiteSpace(EmailBodyTemplate))
{
- _notificationService.ShowWarning("请输入邮件内容模板");
+ _notificationService.ShowWarn("请输入邮件内容模板");
return;
}
@@ -199,7 +194,7 @@ namespace DMS.WPF.ViewModels.Triggers
}
// Close dialog with the updated trigger DTO
- await CloseDialogAsync(Trigger);
+ await Close(Trigger);
}
///
@@ -208,7 +203,7 @@ namespace DMS.WPF.ViewModels.Triggers
[RelayCommand]
private async Task CancelAsync()
{
- await CloseDialogAsync(null); // Return null to indicate cancellation
+ await Close(null); // Return null to indicate cancellation
}
}
}
\ No newline at end of file
diff --git a/DMS.WPF/ViewModels/Triggers/TriggersViewModel.cs b/DMS.WPF/ViewModels/TriggersViewModel.cs
similarity index 87%
rename from DMS.WPF/ViewModels/Triggers/TriggersViewModel.cs
rename to DMS.WPF/ViewModels/TriggersViewModel.cs
index d48187b..62e1691 100644
--- a/DMS.WPF/ViewModels/Triggers/TriggersViewModel.cs
+++ b/DMS.WPF/ViewModels/TriggersViewModel.cs
@@ -8,6 +8,8 @@ using DMS.Application.DTOs.Triggers;
using DMS.Application.Services.Triggers;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
+using DMS.WPF.ViewModels.Dialogs;
+using Microsoft.Extensions.DependencyInjection;
namespace DMS.WPF.ViewModels.Triggers
{
@@ -70,7 +72,10 @@ namespace DMS.WPF.ViewModels.Triggers
UpdatedAt = DateTime.UtcNow
};
- var result = await _dialogService.ShowDialogAsync("编辑触发器", newTrigger);
+ TriggerDialogViewModel viewModel = App.Current.Services.GetRequiredService();
+ await viewModel.OnInitializedAsync(newTrigger);
+
+ var result = await _dialogService.ShowDialogAsync(viewModel);
if (result != null)
{
try
@@ -95,7 +100,7 @@ namespace DMS.WPF.ViewModels.Triggers
{
if (SelectedTrigger == null)
{
- _notificationService.ShowWarning("请先选择一个触发器");
+ _notificationService.ShowWarn("请先选择一个触发器");
return;
}
@@ -117,8 +122,10 @@ namespace DMS.WPF.ViewModels.Triggers
CreatedAt = SelectedTrigger.CreatedAt,
UpdatedAt = SelectedTrigger.UpdatedAt
};
+ TriggerDialogViewModel viewModel = App.Current.Services.GetRequiredService();
+ await viewModel.OnInitializedAsync(triggerToEdit);
- var result = await _dialogService.ShowDialogAsync("编辑触发器", triggerToEdit);
+ var result = await _dialogService.ShowDialogAsync(viewModel);
if (result != null)
{
try
@@ -154,11 +161,11 @@ namespace DMS.WPF.ViewModels.Triggers
{
if (SelectedTrigger == null)
{
- _notificationService.ShowWarning("请先选择一个触发器");
+ _notificationService.ShowWarn("请先选择一个触发器");
return;
}
- var confirm = await _dialogService.ShowConfirmDialogAsync("确认删除", $"确定要删除触发器 '{SelectedTrigger.Description}' 吗?");
+ var confirm = await _dialogService.ShowDialogAsync(new ConfirmDialogViewModel("确认删除", $"确定要删除触发器 '{SelectedTrigger.Description}' 吗?","删除"));
if (confirm)
{
try
diff --git a/DMS.WPF/Views/Dialogs/TriggerDialog.xaml b/DMS.WPF/Views/Dialogs/TriggerDialog.xaml
new file mode 100644
index 0000000..67d6376
--- /dev/null
+++ b/DMS.WPF/Views/Dialogs/TriggerDialog.xaml
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DMS.WPF/Views/Dialogs/TriggerDialog.xaml.cs b/DMS.WPF/Views/Dialogs/TriggerDialog.xaml.cs
new file mode 100644
index 0000000..ab3ddb8
--- /dev/null
+++ b/DMS.WPF/Views/Dialogs/TriggerDialog.xaml.cs
@@ -0,0 +1,32 @@
+using System.Windows.Controls;
+using DMS.WPF.Helper;
+using iNKORE.UI.WPF.Modern.Controls;
+
+namespace DMS.WPF.Views.Dialogs
+{
+ ///
+ /// TriggerDialog.xaml 的交互逻辑
+ ///
+ public partial class TriggerDialog : ContentDialog
+ {
+ private const int ContentAreaMaxWidth = 1000;
+ private const int ContentAreaMaxHeight = 800;
+
+ public TriggerDialog()
+ {
+ InitializeComponent();
+ this.Opened += OnOpened;
+ }
+
+ private void OnOpened(ContentDialog sender, ContentDialogOpenedEventArgs args)
+ {
+ // 修改对话框内容的最大宽度和最大高度
+ var backgroundElementBorder = VisualTreeFinder.FindVisualChildByName(this, "BackgroundElement");
+ if (backgroundElementBorder != null)
+ {
+ backgroundElementBorder.MaxWidth = ContentAreaMaxWidth;
+ backgroundElementBorder.MaxHeight = ContentAreaMaxHeight;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DMS.WPF/Views/MainView.xaml b/DMS.WPF/Views/MainView.xaml
index 2b3574b..9fd77cb 100644
--- a/DMS.WPF/Views/MainView.xaml
+++ b/DMS.WPF/Views/MainView.xaml
@@ -12,6 +12,7 @@
xmlns:tb="http://hardcodet.net/taskbar"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:vm="clr-namespace:DMS.WPF.ViewModels"
+ xmlns:vmt="clr-namespace:DMS.WPF.ViewModels.Triggers"
Title="设备管理系统"
Width="1080"
Height="800"
@@ -112,6 +113,10 @@
+
+
+
+
diff --git a/DMS.WPF/Views/Triggers/TriggerEditorView.xaml b/DMS.WPF/Views/Triggers/TriggerEditorView.xaml
deleted file mode 100644
index 6f364c7..0000000
--- a/DMS.WPF/Views/Triggers/TriggerEditorView.xaml
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/DMS.WPF/Views/Triggers/TriggerEditorView.xaml.cs b/DMS.WPF/Views/Triggers/TriggerEditorView.xaml.cs
deleted file mode 100644
index c892388..0000000
--- a/DMS.WPF/Views/Triggers/TriggerEditorView.xaml.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Windows.Controls;
-
-namespace DMS.WPF.Views.Triggers
-{
- ///
- /// TriggerEditorView.xaml 的交互逻辑
- ///
- public partial class TriggerEditorView : UserControl
- {
- public TriggerEditorView()
- {
- InitializeComponent();
- }
- }
-}
\ No newline at end of file
diff --git a/DMS.WPF/Views/Triggers/TriggersView.xaml.cs b/DMS.WPF/Views/Triggers/TriggersView.xaml.cs
deleted file mode 100644
index 651b5be..0000000
--- a/DMS.WPF/Views/Triggers/TriggersView.xaml.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Windows.Controls;
-
-namespace DMS.WPF.Views.Triggers
-{
- ///
- /// TriggersView.xaml 的交互逻辑
- ///
- public partial class TriggersView : Page
- {
- public TriggersView()
- {
- InitializeComponent();
- }
- }
-}
\ No newline at end of file
diff --git a/DMS.WPF/Views/Triggers/TriggersView.xaml b/DMS.WPF/Views/TriggersView.xaml
similarity index 60%
rename from DMS.WPF/Views/Triggers/TriggersView.xaml
rename to DMS.WPF/Views/TriggersView.xaml
index 0d8b454..f0286d8 100644
--- a/DMS.WPF/Views/Triggers/TriggersView.xaml
+++ b/DMS.WPF/Views/TriggersView.xaml
@@ -1,16 +1,12 @@
-
-
-
-
+ d:DesignHeight="450" d:DesignWidth="800">
+
@@ -19,12 +15,28 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/DMS.WPF/Views/TriggersView.xaml.cs b/DMS.WPF/Views/TriggersView.xaml.cs
new file mode 100644
index 0000000..c6a6fc3
--- /dev/null
+++ b/DMS.WPF/Views/TriggersView.xaml.cs
@@ -0,0 +1,18 @@
+using System.Windows.Controls;
+using DMS.WPF.ViewModels.Triggers;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DMS.WPF.Views
+{
+ ///
+ /// TriggersView.xaml 的交互逻辑
+ ///
+ public partial class TriggersView : UserControl
+ {
+ public TriggersView()
+ {
+ InitializeComponent();
+ DataContext = App.Current.Services.GetRequiredService();
+ }
+ }
+}
\ No newline at end of file