将NlogHelper,和NotificationHelper,改为服务的方式注入使用

This commit is contained in:
2025-09-04 17:29:24 +08:00
parent c45287fae0
commit bb650e2682
35 changed files with 307 additions and 474 deletions

View File

@@ -1,4 +1,3 @@
using DMS.Core.Helper;
using DMS.Core.Models;
using DMS.Application.Interfaces;
using DMS.Application.Models;

View File

@@ -2,7 +2,6 @@ using System.Threading.Channels;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Application.Models;
using DMS.Core.Helper;
using DMS.Core.Interfaces;
using DMS.Core.Models;
using Microsoft.Extensions.Hosting;
@@ -22,15 +21,19 @@ public class DataProcessingService : BackgroundService, IDataProcessingService
// 存储数据处理器的链表
private readonly List<IVariableProcessor> _processors;
// 日志记录器
private readonly ILogger<DataProcessingService> _logger;
/// <summary>
/// 构造函数,注入日志记录器。
/// </summary>
/// <param name="logger">日志记录器实例。</param>
public DataProcessingService()
public DataProcessingService(ILogger<DataProcessingService> logger)
{
// 创建一个无边界的 Channel允许生产者快速写入而不会被阻塞。
_queue = Channel.CreateUnbounded<VariableContext>();
_processors = new List<IVariableProcessor>();
_logger = logger;
}
/// <summary>
@@ -66,7 +69,7 @@ public class DataProcessingService : BackgroundService, IDataProcessingService
/// <param name="stoppingToken">用于通知服务停止的取消令牌。</param>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
NlogHelper.Info("数据处理服务已启动。");
_logger.LogInformation("数据处理服务已启动。");
// 当服务未被请求停止时,持续循环
while (!stoppingToken.IsCancellationRequested)
@@ -81,7 +84,7 @@ public class DataProcessingService : BackgroundService, IDataProcessingService
{
if (context.IsHandled)
{
// NlogHelper.Info($"{context.Data.Name}的数据处理已短路,跳过后续处理器。");
// _logger.LogInformation($"{context.Data.Name}的数据处理已短路,跳过后续处理器。");
break; // 短路,跳过后续处理器
}
@@ -94,10 +97,10 @@ public class DataProcessingService : BackgroundService, IDataProcessingService
}
catch (Exception ex)
{
NlogHelper.Error($"处理变量数据时发生错误:{ex.Message}", ex);
_logger.LogError(ex, $"处理变量数据时发生错误:{ex.Message}");
}
}
NlogHelper.Info("数据处理服务已停止。");
_logger.LogInformation("数据处理服务已停止。");
}
}

View File

@@ -1,6 +1,5 @@
using DMS.Application.Interfaces;
using DMS.Application.Models;
using DMS.Core.Helper;
using DMS.Core.Models;
namespace DMS.Application.Services.Processors;

View File

@@ -1,16 +1,18 @@
using System.Threading.Tasks;
using DMS.Application.Interfaces;
using DMS.Application.Models;
using DMS.Core.Helper;
using DMS.Core.Models;
using Microsoft.Extensions.Logging;
namespace DMS.Application.Services.Processors;
public class UpdateDbVariableProcessor : IVariableProcessor
{
private readonly ILogger<UpdateDbVariableProcessor> _logger;
public UpdateDbVariableProcessor()
public UpdateDbVariableProcessor(ILogger<UpdateDbVariableProcessor> logger)
{
_logger = logger;
}
public async Task ProcessAsync(VariableContext context)
@@ -19,18 +21,18 @@ public class UpdateDbVariableProcessor : IVariableProcessor
{
// 假设 DataServices 有一个方法来更新 Variable
// await _dataServices.UpdateVariableAsync(context.Data);
// NlogHelper.Info($"数据库变量 {context.Data.Name} 更新成功,值为: {context.Data.DataValue}");
// _logger.LogInformation($"数据库变量 {context.Data.Name} 更新成功,值为: {context.Data.DataValue}");
// if (!_dataServices.AllVariables.TryGetValue(context.Data.Id, out Variable oldVariable))
// {
// NlogHelper.Warn($"数据库更新完成修改变量值是否改变时在_dataServices.AllVariables中找不到Id:{context.Data.Id},Name:{context.Data.Name}的变量。");
// _logger.LogWarning($"数据库更新完成修改变量值是否改变时在_dataServices.AllVariables中找不到Id:{context.Data.Id},Name:{context.Data.Name}的变量。");
// context.IsHandled = true;
// }
// oldVariable.DataValue = context.Data.DataValue;
}
catch (Exception ex)
{
NlogHelper.Error($"更新数据库变量 {context.Data.Name} 失败: {ex.Message}", ex);
_logger.LogError(ex, $"更新数据库变量 {context.Data.Name} 失败: {ex.Message}");
}
}
}

View File

@@ -1,232 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
using NLog;
namespace DMS.Core.Helper;
/// <summary>
/// NLog 日志帮助类,提供简化的日志记录方法,并自动捕获调用者信息。
/// 新增了日志节流功能,以防止在短时间内产生大量重复的日志(日志风暴)。
/// </summary>
public static class NlogHelper
{
/// <summary>
/// 获取当前类的 NLog 日志实例。
/// </summary>
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// 内部类,用于存储节流日志的状态信息。
/// </summary>
private class ThrottledLogInfo
{
/// <summary>
/// 日志在节流时间窗口内的调用次数。
/// 使用 int 类型,并通过 Interlocked.Increment 进行原子性递增,确保线程安全。
/// </summary>
public int Count;
/// <summary>
/// 用于在节流时间结束后执行操作的计时器。
/// </summary>
public Timer Timer;
/// <summary>
/// 调用日志方法的源文件完整路径。
/// </summary>
public string CallerFilePath;
/// <summary>
/// 调用日志方法的成员或属性名称。
/// </summary>
public string CallerMember;
/// <summary>
/// 调用日志方法的行号。
/// </summary>
public int CallerLineNumber;
/// <summary>
/// 日志级别 (e.g., Info, Error)。
/// </summary>
public LogLevel Level;
/// <summary>
/// 关联的异常对象(如果有)。
/// </summary>
public Exception Exception;
}
/// <summary>
/// 线程安全的字典,用于存储正在被节流的日志。
/// 键 (string) 是根据日志消息和调用位置生成的唯一标识。
/// 值 (ThrottledLogInfo) 是该日志的节流状态信息。
/// </summary>
private static readonly ConcurrentDictionary<string, ThrottledLogInfo> ThrottledLogs = new ConcurrentDictionary<string, ThrottledLogInfo>();
/// <summary>
/// 定义节流的时间窗口(单位:秒)。
/// </summary>
private const int ThrottleTimeSeconds = 30;
/// <summary>
/// 内部核心日志记录方法,包含了节流逻辑。
/// </summary>
/// <param name="msg">日志消息内容。</param>
/// <param name="level">NLog 的日志级别。</param>
/// <param name="exception">可选的异常对象。</param>
/// <param name="throttle">是否启用节流。</param>
/// <param name="callerFilePath">调用此方法的源文件完整路径。</param>
/// <param name="callerMember">调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">调用此方法的行号。</param>
private static void LogInternal(string msg, LogLevel level, Exception exception, bool throttle, string callerFilePath, string callerMember, int callerLineNumber)
{
// 如果不启用节流,则直接记录日志并返回。
if (!throttle)
{
LogWithContext(msg, level, exception, callerFilePath, callerMember, callerLineNumber);
return;
}
// 使用消息内容和调用位置生成唯一键,以区分不同的日志来源。
var key = $"{callerFilePath}:{callerLineNumber}:{msg}";
// 使用 AddOrUpdate 实现原子操作,确保线程安全。
// 它会尝试添加一个新的节流日志条目,如果键已存在,则更新现有条目。
ThrottledLogs.AddOrUpdate(
key,
// --- 添加逻辑 (addValueFactory):当日志第一次被节流时执行 ---
_ =>
{
// 1. 首次出现,立即记录一次原始日志。
LogWithContext(msg, level, exception, callerFilePath, callerMember, callerLineNumber);
// 2. 创建一个新的节流信息对象。
var newThrottledLog = new ThrottledLogInfo
{
Count = 1,
CallerFilePath = callerFilePath,
CallerMember = callerMember,
CallerLineNumber = callerLineNumber,
Level = level,
Exception = exception
};
// 3. 创建并启动一个一次性计时器。
newThrottledLog.Timer = new Timer(s =>
{
// --- 计时器回调在指定时间例如30秒后触发 ---
// 尝试从字典中移除当前日志条目。
if (ThrottledLogs.TryRemove(key, out var finishedLog))
{
// 释放计时器资源。
finishedLog.Timer.Dispose();
// 如果在节流期间有后续调用Count > 1则记录一条摘要日志。
if (finishedLog.Count > 1)
{
var summaryMsg = $"日志 '{msg}' 在过去 {ThrottleTimeSeconds} 秒内被调用 {finishedLog.Count} 次。";
LogWithContext(summaryMsg, finishedLog.Level, finishedLog.Exception, finishedLog.CallerFilePath, finishedLog.CallerMember, finishedLog.CallerLineNumber);
}
}
}, null, ThrottleTimeSeconds * 1000, Timeout.Infinite); // 设置30秒后触发且不重复。
return newThrottledLog;
},
// --- 更新逻辑 (updateValueFactory):当日志在节流窗口内再次被调用时执行 ---
(_, existingLog) =>
{
// 只需将调用次数加一。使用 Interlocked.Increment 保证原子操作,避免多线程下的竞态条件。
Interlocked.Increment(ref existingLog.Count);
return existingLog;
});
}
/// <summary>
/// 将日志信息包装在 NLog 的 MappedDiagnosticsLogicalContext 中进行记录。
/// 这允许在 nlog.config 配置文件中使用 ${mdlc:item=...} 来获取调用者信息。
/// </summary>
private static void LogWithContext(string msg, LogLevel level, Exception exception, string callerFilePath, string callerMember, int callerLineNumber)
{
using (MappedDiagnosticsLogicalContext.SetScoped("CallerFilePath", callerFilePath))
using (MappedDiagnosticsLogicalContext.SetScoped("CallerLineNumber", callerLineNumber))
using (MappedDiagnosticsLogicalContext.SetScoped("CallerMember", callerMember))
{
if (exception != null)
{
Logger.Log(level, exception, msg);
}
else
{
Logger.Log(level, msg);
}
}
}
/// <summary>
/// 记录一个错误级别的日志,支持节流。
/// </summary>
/// <param name="msg">日志消息内容。</param>
/// <param name="exception">可选:要记录的异常对象。</param>
/// <param name="throttle">是否启用日志节流。如果为 true则在30秒内对来自同一位置的相同日志消息进行节流处理。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void Error(string msg, Exception exception = null, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
{
LogInternal(msg, LogLevel.Error, exception, throttle, callerFilePath, callerMember, callerLineNumber);
}
/// <summary>
/// 记录一个信息级别的日志,支持节流。
/// </summary>
/// <param name="msg">日志消息内容。</param>
/// <param name="throttle">是否启用日志节流。如果为 true则在30秒内对来自同一位置的相同日志消息进行节流处理。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void Info(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
{
LogInternal(msg, LogLevel.Info, null, throttle, callerFilePath, callerMember, callerLineNumber);
}
/// <summary>
/// 记录一个警告级别的日志,支持节流。
/// </summary>
/// <param name="msg">日志消息内容。</param>
/// <param name="throttle">是否启用日志节流。如果为 true则在30秒内对来自同一位置的相同日志消息进行节流处理。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void Warn(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
{
LogInternal(msg, LogLevel.Warn, null, throttle, callerFilePath, callerMember, callerLineNumber);
}
/// <summary>
/// 记录一个跟踪级别的日志,支持节流。
/// </summary>
/// <param name="msg">日志消息内容。</param>
/// <param name="throttle">是否启用日志节流。如果为 true则在30秒内对来自同一位置的相同日志消息进行节流处理。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void Trace(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
{
LogInternal(msg, LogLevel.Trace, null, throttle, callerFilePath, callerMember, callerLineNumber);
}
}

View File

@@ -1,8 +1,8 @@
using System.Diagnostics;
using System.Linq.Expressions;
using DMS.Core.Helper;
using DMS.Core.Models;
using DMS.Infrastructure.Data;
using Microsoft.Extensions.Logging;
using SqlSugar;
namespace DMS.Infrastructure.Repositories;
@@ -15,15 +15,17 @@ public abstract class BaseRepository<TEntity>
where TEntity : class, new()
{
private readonly SqlSugarDbContext _dbContext;
protected readonly ILogger<BaseRepository<TEntity>> _logger;
/// <summary>
/// 初始化 BaseRepository 的新实例。
/// </summary>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
protected BaseRepository(SqlSugarDbContext dbContext)
/// <param name="logger">日志记录器实例。</param>
protected BaseRepository(SqlSugarDbContext dbContext, ILogger<BaseRepository<TEntity>> logger)
{
_dbContext = dbContext;
_logger = logger;
}
/// <summary>
@@ -46,7 +48,7 @@ public abstract class BaseRepository<TEntity>
var result = await Db.Insertable(entity)
.ExecuteReturnEntityAsync();
stopwatch.Stop();
NlogHelper.Info($"Add {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Add {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -62,7 +64,7 @@ public abstract class BaseRepository<TEntity>
var result = await Db.Updateable(entity)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Update {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Update {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -78,7 +80,7 @@ public abstract class BaseRepository<TEntity>
var result = await Db.Deleteable(entity)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -94,11 +96,10 @@ public abstract class BaseRepository<TEntity>
var entities = await Db.Queryable<TEntity>()
.ToListAsync();
stopwatch.Stop();
NlogHelper.Info($"GetAll {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"GetAll {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return entities;
}
/// <summary>
/// 异步根据主键 ID 获取单个实体。
/// </summary>
@@ -112,7 +113,7 @@ public abstract class BaseRepository<TEntity>
.In(id)
.FirstAsync();
stopwatch.Stop();
NlogHelper.Info($"GetById {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"GetById {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return entity;
}
@@ -129,7 +130,7 @@ public abstract class BaseRepository<TEntity>
.In(ids)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"DeleteByIds {typeof(TEntity).Name}, Count: {ids.Count}, 耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"DeleteByIds {typeof(TEntity).Name}, Count: {ids.Count}, 耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -145,7 +146,7 @@ public abstract class BaseRepository<TEntity>
var entity = await Db.Queryable<TEntity>()
.FirstAsync(expression);
stopwatch.Stop();
NlogHelper.Info($"GetByCondition {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"GetByCondition {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return entity;
}
@@ -161,7 +162,7 @@ public abstract class BaseRepository<TEntity>
var result = await Db.Queryable<TEntity>()
.AnyAsync(expression);
stopwatch.Stop();
NlogHelper.Info($"Exists {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Exists {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -205,7 +206,7 @@ public abstract class BaseRepository<TEntity>
var entity = await Db.Queryable<TEntity>().Take(number).ToListAsync();
stopwatch.Stop();
NlogHelper.Info($"TakeAsync {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"TakeAsync {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return entity;
}
@@ -215,7 +216,7 @@ public abstract class BaseRepository<TEntity>
stopwatch.Start();
var result = await Db.Insertable(entities).ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"AddBatchAsync {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"AddBatchAsync {typeof(TEntity).Name}耗时:{stopwatch.ElapsedMilliseconds}ms");
return result > 0;
}
}

View File

@@ -1,10 +1,10 @@
using System.Diagnostics;
using AutoMapper;
using DMS.Core.Helper;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Models;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -21,8 +21,9 @@ public class DeviceRepository : BaseRepository<DbDevice>, IDeviceRepository
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public DeviceRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public DeviceRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<DeviceRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -86,7 +87,7 @@ public class DeviceRepository : BaseRepository<DbDevice>, IDeviceRepository
var result = await Db.Deleteable(new DbDevice() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbDevice)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbDevice)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -4,6 +4,7 @@ using DMS.Core.Models;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
using SqlSugar;
namespace DMS.Infrastructure.Repositories;
@@ -16,15 +17,18 @@ public class InitializeRepository : IInitializeRepository
{
private readonly SqlSugarDbContext _dbContext;
private readonly SqlSugarClient _db;
private readonly ILogger<InitializeRepository> _logger;
/// <summary>
/// 构造函数,注入 SqlSugarDbContext。
/// 构造函数,注入 SqlSugarDbContext 和 ILogger
/// </summary>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public InitializeRepository(SqlSugarDbContext dbContext)
/// <param name="logger">日志记录器实例。</param>
public InitializeRepository(SqlSugarDbContext dbContext, ILogger<InitializeRepository> logger)
{
_dbContext = dbContext;
_db = _dbContext.GetInstance();
_logger = logger;
}
/// <summary>

View File

@@ -1,11 +1,11 @@
using System.Diagnostics;
using AutoMapper;
using DMS.Core.Enums;
using DMS.Core.Helper;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Models;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -22,8 +22,9 @@ public class MenuRepository : BaseRepository<DbMenu>, IMenuRepository
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public MenuRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public MenuRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<MenuRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -39,7 +40,7 @@ public class MenuRepository : BaseRepository<DbMenu>, IMenuRepository
var dbMenuTree = await Db.Queryable<DbMenu>()
.ToTreeAsync(dm => dm.Childrens, dm => dm.ParentId, 0);
stopwatch.Stop();
NlogHelper.Info($"获取菜单树耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"获取菜单树耗时:{stopwatch.ElapsedMilliseconds}ms");
return _mapper.Map<List<MenuBean>>(dbMenuTree);
}
@@ -101,7 +102,7 @@ public class MenuRepository : BaseRepository<DbMenu>, IMenuRepository
var result = await Db.Deleteable(new DbMenu { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbMenu)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbMenu)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -123,7 +124,7 @@ public class MenuRepository : BaseRepository<DbMenu>, IMenuRepository
.Where(m => m.Id == id)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbMenu)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbMenu)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return delConut;
}
@@ -147,7 +148,7 @@ public class MenuRepository : BaseRepository<DbMenu>, IMenuRepository
.Where(m => m.Id == menu.Id)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbMenu)},TargetId={targetId},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbMenu)},TargetId={targetId},耗时:{stopwatch.ElapsedMilliseconds}ms");
return delConut;
}

View File

@@ -1,10 +1,10 @@
using System.Diagnostics;
using AutoMapper;
using DMS.Core.Helper;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Models;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -21,8 +21,9 @@ public class MqttServerRepository : BaseRepository<DbMqttServer>, IMqttServerRep
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public MqttServerRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public MqttServerRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<MqttServerRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -85,7 +86,7 @@ public class MqttServerRepository : BaseRepository<DbMqttServer>, IMqttServerRep
var result = await Db.Deleteable(new DbMqttServer() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbMqttServer)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbMqttServer)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -12,32 +12,44 @@ namespace DMS.Infrastructure.Repositories;
/// </summary>
public class RepositoryManager : IRepositoryManager
{
private readonly SqlSugarClient _db;
private readonly IMapper _mapper;
private readonly SqlSugarDbContext _dbContext;
private readonly SqlSugarClient _db;
/// <summary>
/// 构造函数,注入 AutoMapper 和 SqlSugarDbContext
/// 在此初始化所有具体的仓储实例。
/// 构造函数,注入所有仓储实例
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public RepositoryManager(IMapper mapper, SqlSugarDbContext dbContext)
/// <param name="initializeRepository">初始化仓储实例。</param>
/// <param name="devices">设备仓储实例。</param>
/// <param name="variableTables">变量表仓储实例。</param>
/// <param name="variables">变量仓储实例。</param>
/// <param name="mqttServers">MQTT服务器仓储实例。</param>
/// <param name="variableMqttAliases">变量MQTT别名仓储实例。</param>
/// <param name="menus">菜单仓储实例。</param>
/// <param name="variableHistories">变量历史仓储实例。</param>
/// <param name="users">用户仓储实例。</param>
public RepositoryManager( SqlSugarDbContext dbContext,
IInitializeRepository initializeRepository,
IDeviceRepository devices,
IVariableTableRepository variableTables,
IVariableRepository variables,
IMqttServerRepository mqttServers,
IVariableMqttAliasRepository variableMqttAliases,
IMenuRepository menus,
IVariableHistoryRepository variableHistories,
IUserRepository users)
{
_mapper = mapper;
_dbContext = dbContext;
_db = dbContext.GetInstance();
InitializeRepository = initializeRepository;
Devices = devices;
VariableTables = variableTables;
Variables = variables;
MqttServers = mqttServers;
VariableMqttAliases = variableMqttAliases;
Menus = menus;
VariableHistories = variableHistories;
Users = users;
// 初始化各个仓储实例
InitializeRepository=new InitializeRepository(dbContext);
Devices = new DeviceRepository(mapper, dbContext);
VariableTables = new VariableTableRepository(mapper, dbContext);
Variables = new VariableRepository(mapper, dbContext);
MqttServers = new MqttServerRepository(mapper, dbContext);
VariableMqttAliases = new VariableMqttAliasRepository(mapper, dbContext);
Menus = new MenuRepository(mapper, dbContext);
VariableHistories = new VariableHistoryRepository(mapper, dbContext);
Users = new UserRepository(mapper, dbContext);
_db = dbContext.GetInstance();
}
/// <summary>
@@ -45,7 +57,7 @@ public class RepositoryManager : IRepositoryManager
/// </summary>
public void Dispose()
{
_db.Close();
_db?.Close();
}
/// <summary>
@@ -89,17 +101,29 @@ public class RepositoryManager : IRepositoryManager
/// 异步开始数据库事务。
/// </summary>
/// <returns>表示异步操作的任务。</returns>
public async Task BeginTranAsync() => await _db.BeginTranAsync();
public async Task BeginTranAsync()
{
if (_db != null)
await _db.BeginTranAsync();
}
/// <summary>
/// 异步提交数据库事务。
/// </summary>
/// <returns>表示异步操作的任务。</returns>
public async Task CommitAsync() => await _db.CommitTranAsync();
public async Task CommitAsync()
{
if (_db != null)
await _db.CommitTranAsync();
}
/// <summary>
/// 异步回滚数据库事务。
/// </summary>
/// <returns>表示异步操作的任务。</returns>
public async Task RollbackAsync() => await _db.RollbackTranAsync();
public async Task RollbackAsync()
{
if (_db != null)
await _db.RollbackTranAsync();
}
}

View File

@@ -7,7 +7,7 @@ using DMS.Infrastructure.Entities;
using AutoMapper;
using DMS.Core.Helper;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -24,8 +24,9 @@ public class UserRepository : BaseRepository<DbUser>, IUserRepository
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public UserRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public UserRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<UserRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -88,7 +89,7 @@ public class UserRepository : BaseRepository<DbUser>, IUserRepository
var result = await Db.Deleteable(new DbUser() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbUser)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbUser)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -6,7 +6,7 @@ using DMS.Infrastructure.Entities;
using AutoMapper;
using DMS.Core.Helper;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -23,8 +23,9 @@ public class VariableHistoryRepository : BaseRepository<DbVariableHistory>, IVar
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public VariableHistoryRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public VariableHistoryRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<VariableHistoryRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -87,7 +88,7 @@ public class VariableHistoryRepository : BaseRepository<DbVariableHistory>, IVar
var result = await Db.Deleteable(new DbVariableHistory() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbVariableHistory)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbVariableHistory)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -5,7 +5,7 @@ using DMS.Infrastructure.Entities;
using AutoMapper;
using DMS.Core.Helper;
using Microsoft.Extensions.Logging;
using DMS.Core.Models;
namespace DMS.Infrastructure.Repositories;
@@ -23,8 +23,9 @@ public class VariableMqttAliasRepository : BaseRepository<DbVariableMqttAlias>,
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public VariableMqttAliasRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public VariableMqttAliasRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<VariableMqttAliasRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -87,7 +88,7 @@ public class VariableMqttAliasRepository : BaseRepository<DbVariableMqttAlias>,
var result = await Db.Deleteable(new DbVariableMqttAlias() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbVariableMqttAlias)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbVariableMqttAlias)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -1,10 +1,10 @@
using System.Diagnostics;
using AutoMapper;
using DMS.Core.Helper;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Models;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -21,8 +21,9 @@ public class VariableRepository : BaseRepository<DbVariable>, IVariableRepositor
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public VariableRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public VariableRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<VariableRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -98,13 +99,13 @@ public class VariableRepository : BaseRepository<DbVariable>, IVariableRepositor
}
await Db.CommitTranAsync();
//NlogHelper.Info($"成功为 {variableMqttList.Count()} 个变量请求添加/更新了MQTT服务器关联实际影响 {affectedCount} 个。");
//_logger.LogInformation($"成功为 {variableMqttList.Count()} 个变量请求添加/更新了MQTT服务器关联实际影响 {affectedCount} 个。");
return affectedCount;
}
catch (Exception ex)
{
await Db.RollbackTranAsync();
//NlogHelper.Error($"为变量添加MQTT服务器关联时发生错误: {ex.Message}", ex);
//_logger.LogError(ex, $"为变量添加MQTT服务器关联时发生错误: {ex.Message}");
// 根据需要,可以向上层抛出异常
throw;
}
@@ -169,7 +170,7 @@ public class VariableRepository : BaseRepository<DbVariable>, IVariableRepositor
var result = await Db.Deleteable(new DbVariable() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbVariable)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbVariable)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -186,7 +187,7 @@ public class VariableRepository : BaseRepository<DbVariable>, IVariableRepositor
.In(ids)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbVariable)},Count={ids.Count},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbVariable)},Count={ids.Count},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}

View File

@@ -6,7 +6,7 @@ using DMS.Infrastructure.Entities;
using AutoMapper;
using DMS.Core.Helper;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Repositories;
@@ -23,8 +23,9 @@ public class VariableTableRepository : BaseRepository<DbVariableTable>, IVariabl
/// </summary>
/// <param name="mapper">AutoMapper 实例,用于实体模型和数据库模型之间的映射。</param>
/// <param name="dbContext">SqlSugar 数据库上下文,用于数据库操作。</param>
public VariableTableRepository(IMapper mapper, SqlSugarDbContext dbContext)
: base(dbContext)
/// <param name="logger">日志记录器实例。</param>
public VariableTableRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger<VariableTableRepository> logger)
: base(dbContext, logger)
{
_mapper = mapper;
}
@@ -87,7 +88,7 @@ public class VariableTableRepository : BaseRepository<DbVariableTable>, IVariabl
var result = await Db.Deleteable(new DbVariableTable() { Id = id })
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete {typeof(DbVariableTable)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete {typeof(DbVariableTable)},ID={id},耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
@@ -122,7 +123,7 @@ public class VariableTableRepository : BaseRepository<DbVariableTable>, IVariabl
.Where(it => it.DeviceId == deviceId)
.ExecuteCommandAsync();
stopwatch.Stop();
NlogHelper.Info($"Delete VariableTable by DeviceId={deviceId}, 耗时:{stopwatch.ElapsedMilliseconds}ms");
_logger.LogInformation($"Delete VariableTable by DeviceId={deviceId}, 耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
}

View File

@@ -6,7 +6,6 @@ using DMS.Application.Services.Processors;
using DMS.Core.Interfaces;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Interfaces.Services;
using DMS.Helper;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Interfaces.Services;
@@ -76,7 +75,8 @@ public partial class App : System.Windows.Application
}
catch (Exception exception)
{
NotificationHelper.ShowError("加载数据时发生错误,如果是连接字符串不正确,可以在设置界面更改:{exception.Message}", exception);
var notificationService = Host.Services.GetRequiredService<NotificationService>();
notificationService.ShowError($"加载数据时发生错误,如果是连接字符串不正确,可以在设置界面更改:{exception.Message}", exception);
}
var splashWindow = Host.Services.GetRequiredService<SplashWindow>();
@@ -106,10 +106,10 @@ public partial class App : System.Windows.Application
private void ConfigureServices(IServiceCollection services)
{
// 注册NLogLogger作为Microsoft.Extensions.Logging.ILogger的实现
services.AddSingleton<ILogger, NLogLogger>();
services.AddSingleton<ILoggerFactory, NLogLoggerFactory>();
//
services.AddSingleton<GrowlNotificationService>();
services.AddSingleton<NotificationService>();
// services.AddHostedService<S7BackgroundService>();
// services.AddHostedService<OpcUaBackgroundService>();
// services.AddHostedService<DMS.Infrastructure.Services.MqttBackgroundService>();
@@ -148,6 +148,14 @@ public partial class App : System.Windows.Application
});
services.AddSingleton<IInitializeRepository, InitializeRepository>();
services.AddSingleton<IDeviceRepository, DeviceRepository>();
services.AddSingleton<IVariableTableRepository, VariableTableRepository>();
services.AddSingleton<IVariableRepository, VariableRepository>();
services.AddSingleton<IMqttServerRepository, MqttServerRepository>();
services.AddSingleton<IVariableMqttAliasRepository, VariableMqttAliasRepository>();
services.AddSingleton<IMenuRepository, MenuRepository>();
services.AddSingleton<IVariableHistoryRepository, VariableHistoryRepository>();
services.AddSingleton<IUserRepository, UserRepository>();
services.AddSingleton<IRepositoryManager, RepositoryManager>();
services.AddSingleton<IExcelService, ExcelService>();

View File

@@ -59,10 +59,10 @@ public partial class DataServices : ObservableObject
/// <summary>
/// DataServices类的构造函数。
/// 注入ILogger<DataServices>,并初始化各个数据仓库。
/// 初始化各个数据仓库。
/// </summary>
/// <param name="mapper">AutoMapper 实例。</param>
/// <param name="varDataRepository"></param>
/// <param name="dataCenterService">数据服务中心实例。</param>
public DataServices(IMapper mapper, IDataCenterService dataCenterService)
{
_mapper = mapper;

View File

@@ -1,6 +1,5 @@
// 文件: DMS.WPF/Services/NavigationService.cs
using DMS.Helper;
using DMS.ViewModels;
using DMS.WPF.ViewModels;
using DMS.WPF.ViewModels.Items;
@@ -11,6 +10,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
namespace DMS.WPF.Services;
@@ -43,8 +43,8 @@ public class NavigationService : INavigationService
var viewModel = GetViewModelByKey(menu.TargetViewKey);
if (viewModel == null)
{
NotificationHelper.ShowError($"切换界面失败,没有找到界面:{menu.TargetViewKey}");
var notificationService = App.Current.Services.GetRequiredService<NotificationService>();
notificationService.ShowError($"切换界面失败,没有找到界面:{menu.TargetViewKey}");
return;
}

View File

@@ -1,21 +1,22 @@
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
using CommunityToolkit.Mvvm.Messaging;
using DMS.Core.Enums;
using DMS.Core.Helper;
using DMS.Message;
using Microsoft.Extensions.Logging;
namespace DMS.Helper;
namespace DMS.WPF.Services;
/// <summary>
/// 通知帮助类,用于显示各种类型的通知消息,并集成日志记录功能。
/// 通知服务类,用于显示各种类型的通知消息,并集成日志记录功能。
/// 新增了通知节流功能,以防止在短时间内向用户发送大量重复的通知。
/// </summary>
public static class NotificationHelper
public class NotificationService
{
private readonly ILogger<NotificationService> _logger;
/// <summary>
/// 内部类,用于存储节流通知的状态信息。
/// </summary>
@@ -26,22 +27,38 @@ public static class NotificationHelper
public NotificationType NotificationType;
}
private static readonly ConcurrentDictionary<string, ThrottledNotificationInfo> ThrottledNotifications = new ConcurrentDictionary<string, ThrottledNotificationInfo>();
private readonly ConcurrentDictionary<string, ThrottledNotificationInfo> _throttledNotifications = new ConcurrentDictionary<string, ThrottledNotificationInfo>();
private const int ThrottleTimeSeconds = 30;
public NotificationService(ILogger<NotificationService> logger)
{
_logger = logger;
}
/// <summary>
/// 内部核心通知发送方法,包含了节流逻辑。
/// </summary>
private static void SendNotificationInternal(string msg, NotificationType notificationType, bool throttle, Exception exception, string callerFilePath, string callerMember, int callerLineNumber)
private void SendNotificationInternal(string msg, NotificationType notificationType, bool throttle, Exception exception, string callerFilePath, string callerMember, int callerLineNumber)
{
// 根据通知类型决定日志级别,并使用 NlogHelper 记录日志(利用其自身的节流逻辑)
// 根据通知类型决定日志级别,并使用 ILogger 记录日志
if (notificationType == NotificationType.Error)
{
NlogHelper.Error(msg, exception, throttle, callerFilePath, callerMember, callerLineNumber);
_logger.LogError(exception, $"[{callerFilePath}:{callerMember}:{callerLineNumber}] {msg}");
}
else
{
NlogHelper.Info(msg, throttle, callerFilePath, callerMember, callerLineNumber);
switch (notificationType)
{
case NotificationType.Info:
_logger.LogInformation($"[{callerFilePath}:{callerMember}:{callerLineNumber}] {msg}");
break;
case NotificationType.Success:
_logger.LogInformation($"[{callerFilePath}:{callerMember}:{callerLineNumber}] {msg}");
break;
case NotificationType.Warning:
_logger.LogWarning($"[{callerFilePath}:{callerMember}:{callerLineNumber}] {msg}");
break;
}
}
// 如果不启用通知节流,则直接发送通知并返回。
@@ -53,7 +70,7 @@ public static class NotificationHelper
var key = $"{callerFilePath}:{callerLineNumber}:{msg}";
ThrottledNotifications.AddOrUpdate(
_throttledNotifications.AddOrUpdate(
key,
// --- 添加逻辑:当通知第一次被节流时执行 ---
_ =>
@@ -71,7 +88,7 @@ public static class NotificationHelper
// 3. 创建并启动计时器。
newThrottledNotification.Timer = new Timer(s =>
{
if (ThrottledNotifications.TryRemove(key, out var finishedNotification))
if (_throttledNotifications.TryRemove(key, out var finishedNotification))
{
finishedNotification.Timer.Dispose();
if (finishedNotification.Count > 1)
@@ -100,7 +117,7 @@ public static class NotificationHelper
/// <param name="throttle">是否启用通知节流。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void ShowMessage(string msg, NotificationType notificationType = NotificationType.Info, bool throttle = true,
public void ShowMessage(string msg, NotificationType notificationType = NotificationType.Info, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerLineNumber] int callerLineNumber = 0)
{
@@ -116,7 +133,7 @@ public static class NotificationHelper
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void ShowError(string msg, Exception exception = null, bool throttle = true,
public void ShowError(string msg, Exception exception = null, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
@@ -132,7 +149,7 @@ public static class NotificationHelper
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void ShowSuccess(string msg, bool throttle = true,
public void ShowSuccess(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
@@ -148,22 +165,23 @@ public static class NotificationHelper
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void ShowInfo(string msg, bool throttle = true,
public void ShowInfo(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)
{
SendNotificationInternal(msg, NotificationType.Info, throttle, null, callerFilePath, callerMember, callerLineNumber);
}
/// <summary>
/// 显示一个信息通知消息,并记录信息日志。支持节流。
/// 显示一个警告通知消息,并记录警告日志。支持节流。
/// </summary>
/// <param name="msg">信息消息内容。</param>
/// <param name="msg">警告消息内容。</param>
/// <param name="throttle">是否启用通知和日志节流。</param>
/// <param name="callerFilePath">自动捕获:调用此方法的源文件完整路径。</param>
/// <param name="callerMember">自动捕获:调用此方法的成员或属性名称。</param>
/// <param name="callerLineNumber">自动捕获:调用此方法的行号。</param>
public static void ShowWarn(string msg, bool throttle = true,
public void ShowWarn(string msg, bool throttle = true,
[CallerFilePath] string callerFilePath = "",
[CallerMemberName] string callerMember = "",
[CallerLineNumber] int callerLineNumber = 0)

View File

@@ -5,7 +5,6 @@ using Dm;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Helper;
using DMS.WPF.Services;
using DMS.Services;
using DMS.WPF.Interfaces;
@@ -28,12 +27,15 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
[ObservableProperty]
private VariableTableItemViewModel _selectedVariableTable;
private readonly NotificationService _notificationService;
public DeviceDetailViewModel(IMapper mapper, IDialogService dialogService, INavigationService navigationService,
DataServices dataServices)
DataServices dataServices, NotificationService notificationService)
{
_mapper = mapper;
_dialogService = dialogService;
_navigationService = navigationService;
_notificationService = notificationService;
DataServices = dataServices;
}
@@ -65,17 +67,17 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
if (await DataServices.AddVariableTable(_mapper.Map<VariableTableDto>(variableTableItemViewModel),
tableMenu, true))
{
NotificationHelper.ShowSuccess($"添加变量表成功:{variableTableItemViewModel.Name}");
_notificationService.ShowSuccess($"添加变量表成功:{variableTableItemViewModel.Name}");
}
else
{
NotificationHelper.ShowError($"添加变量表失败:{variableTableItemViewModel.Name}");
_notificationService.ShowError($"添加变量表失败:{variableTableItemViewModel.Name}");
}
}
catch (Exception ex)
{
NotificationHelper.ShowError($"添加变量表时发生错误: {ex.Message}", ex);
_notificationService.ShowError($"添加变量表时发生错误: {ex.Message}", ex);
}
}
@@ -86,7 +88,7 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
{
if (SelectedVariableTable == null)
{
NotificationHelper.ShowError("你没有选择任何变量表,请选择变量表后再点击编辑变量表");
_notificationService.ShowError("你没有选择任何变量表,请选择变量表后再点击编辑变量表");
return;
}
@@ -104,16 +106,16 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
if (await DataServices.UpdateVariableTable(variableTable))
{
NotificationHelper.ShowSuccess($"编辑变量表成功:{variableTable.Name}");
_notificationService.ShowSuccess($"编辑变量表成功:{variableTable.Name}");
}
else
{
NotificationHelper.ShowError($"编辑变量表失败:{variableTable.Name}");
_notificationService.ShowError($"编辑变量表失败:{variableTable.Name}");
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"编辑变量表的过程中发生错误:{e.Message}", e);
_notificationService.ShowError($"编辑变量表的过程中发生错误:{e.Message}", e);
}
}
@@ -124,7 +126,7 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
{
if (SelectedVariableTable == null)
{
NotificationHelper.ShowError("你没有选择任何变量表,请选择变量表后再点击删除变量表");
_notificationService.ShowError("你没有选择任何变量表,请选择变量表后再点击删除变量表");
return;
}
@@ -135,17 +137,17 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
var tableName = SelectedVariableTable.Name;
if (await DataServices.DeleteVariableTable(SelectedVariableTable,true))
{
NotificationHelper.ShowSuccess($"变量表:{tableName},删除成功。");
_notificationService.ShowSuccess($"变量表:{tableName},删除成功。");
}
else
{
NotificationHelper.ShowError($"变量表:{tableName},删除失败!!!");
_notificationService.ShowError($"变量表:{tableName},删除失败!!!");
}
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"删除变量表的过程中发生错误:{e.Message}", e);
_notificationService.ShowError($"删除变量表的过程中发生错误:{e.Message}", e);
}
}

View File

@@ -5,14 +5,7 @@ using CommunityToolkit.Mvvm.Input;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Core.Helper;
using DMS.Core.Models;
using DMS.Helper;
using DMS.Services;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Dialogs;
using DMS.WPF.ViewModels.Items;
@@ -45,6 +38,8 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
[ObservableProperty]
private DeviceItemViewModel _selectedDevice;
private readonly NotificationService _notificationService;
/// <summary>
/// 初始化 <see cref="DevicesViewModel"/> 类的新实例。
/// </summary>
@@ -53,13 +48,15 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
/// <param name="dataServices">数据服务。</param>
public DevicesViewModel(IMapper mapper,
IDialogService dialogService, INavigationService navigationService,
DataServices dataServices, IDeviceAppService deviceAppService)
DataServices dataServices, IDeviceAppService deviceAppService,
NotificationService notificationService)
{
_mapper = mapper;
_dialogService = dialogService;
_navigationService = navigationService;
DataServices = dataServices;
_deviceAppService = deviceAppService;
_notificationService = notificationService;
Devices = new ObservableCollection<DeviceItemViewModel>();
DataServices.OnDeviceListChanged += (devices) => { };
}
@@ -116,12 +113,12 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
// 添加设备
var addDto = await DataServices.AddDevice(dto);
NotificationHelper.ShowSuccess($"设备添加成功:{addDto.Device.Name}");
_notificationService.ShowSuccess($"设备添加成功:{addDto.Device.Name}");
}
catch (Exception e)
{
Console.WriteLine(e);
NotificationHelper.ShowError($"添加设备的过程中发生错误:{e.Message}", e);
_notificationService.ShowError($"添加设备的过程中发生错误:{e.Message}", e);
}
}
@@ -135,7 +132,7 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
{
if (SelectedDevice == null)
{
NotificationHelper.ShowError("你没有选择任何设备,请选择设备后再点击删除设备");
_notificationService.ShowError("你没有选择任何设备,请选择设备后再点击删除设备");
return;
}
@@ -145,13 +142,13 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
var deviceName = SelectedDevice.Name;
if (await DataServices.DeleteDevice(SelectedDevice))
{
NotificationHelper.ShowSuccess($"删除设备成功,设备名:{deviceName}");
_notificationService.ShowSuccess($"删除设备成功,设备名:{deviceName}");
}
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"删除设备的过程中发生错误:{e.Message}", e);
_notificationService.ShowError($"删除设备的过程中发生错误:{e.Message}", e);
}
}
@@ -165,7 +162,7 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
{
if (SelectedDevice == null)
{
NotificationHelper.ShowError("你没有选择任何设备,请选择设备后再点击编辑设备");
_notificationService.ShowError("你没有选择任何设备,请选择设备后再点击编辑设备");
return;
}
@@ -183,12 +180,12 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
if (await DataServices.UpdateDevice(device))
{
NotificationHelper.ShowSuccess($"编辑设备成功:{device.Name}");
_notificationService.ShowSuccess($"编辑设备成功:{device.Name}");
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"编辑设备的过程中发生错误:{e.Message}", e);
_notificationService.ShowError($"编辑设备的过程中发生错误:{e.Message}", e);
}
}

View File

@@ -6,7 +6,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Core.Interfaces.Services;
using DMS.Core.Models;
using DMS.Helper;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Items;
namespace DMS.WPF.ViewModels.Dialogs;
@@ -15,6 +15,7 @@ public partial class ImportExcelDialogViewModel : DialogViewModelBase<List<Varia
{
private readonly IMapper _mapper;
private readonly IExcelService _excelService;
private readonly NotificationService _notificationService;
[ObservableProperty]
private string? _filePath;
@@ -28,10 +29,11 @@ public partial class ImportExcelDialogViewModel : DialogViewModelBase<List<Varia
[ObservableProperty]
private IList _selectedVariables = new ArrayList();
public ImportExcelDialogViewModel(IMapper mapper,IExcelService excelService)
public ImportExcelDialogViewModel(IMapper mapper,IExcelService excelService, NotificationService notificationService)
{
_mapper = mapper;
_excelService = excelService;
_notificationService = notificationService;
VariableItemViewModels = new();
}
@@ -49,7 +51,7 @@ public partial class ImportExcelDialogViewModel : DialogViewModelBase<List<Varia
}
catch (System.Exception ex)
{
NotificationHelper.ShowError($"从Excel文件中读取变量时发生了错误:{ex.Message}",ex);
_notificationService.ShowError($"从Excel文件中读取变量时发生了错误:{ex.Message}",ex);
}
}

View File

@@ -1,16 +1,15 @@
using System.Collections;
using System.Collections.ObjectModel;
using AutoMapper;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Core.Enums;
using DMS.Core.Helper;
using DMS.Helper;
using DMS.Infrastructure.Interfaces.Services;
using DMS.Infrastructure.Models;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Items;
using Opc.Ua;
using Opc.Ua.Client;
using System.Collections;
using System.Collections.ObjectModel;
namespace DMS.WPF.ViewModels.Dialogs;
@@ -90,16 +89,23 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
/// </summary>
private readonly CancellationTokenSource _cancellationTokenSource;
/// <summary>
/// 通知服务实例
/// </summary>
private readonly NotificationService _notificationService;
/// <summary>
/// 构造函数
/// 初始化ImportOpcUaDialogViewModel实例
/// </summary>
/// <param name="opcUaService">OPC UA服务接口实例</param>
/// <param name="mapper">对象映射器实例</param>
public ImportOpcUaDialogViewModel(IOpcUaService opcUaService, IMapper mapper)
/// <param name="notificationService">通知服务实例</param>
public ImportOpcUaDialogViewModel(IOpcUaService opcUaService, IMapper mapper, NotificationService notificationService)
{
_opcUaService = opcUaService;
_mapper = mapper;
_notificationService = notificationService;
// 初始化根节点
RootOpcUaNode = new OpcUaNodeItemViewModel() { DisplayName = "根节点", NodeId = Objects.ObjectsFolder, IsExpanded = true };
// 初始化取消令牌源
@@ -143,15 +149,15 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
// 处理特定异常类型提供更友好的用户提示
catch (UnauthorizedAccessException ex)
{
NotificationHelper.ShowError($"连接被拒绝,请检查用户名和密码: {ex.Message}");
_notificationService.ShowError($"连接被拒绝,请检查用户名和密码: {ex.Message}");
}
catch (TimeoutException ex)
{
NotificationHelper.ShowError($"连接超时,请检查服务器地址和网络连接: {ex.Message}");
_notificationService.ShowError($"连接超时,请检查服务器地址和网络连接: {ex.Message}");
}
catch (Exception ex)
{
NotificationHelper.ShowError($"连接 OPC UA 服务器失败: {EndpointUrl} - {ex.Message}", ex);
_notificationService.ShowError($"连接 OPC UA 服务器失败: {EndpointUrl} - {ex.Message}", ex);
}
finally
{
@@ -181,7 +187,7 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
}
catch (Exception ex)
{
NotificationHelper.ShowError($"断开连接时发生错误: {ex.Message}", ex);
_notificationService.ShowError($"断开连接时发生错误: {ex.Message}", ex);
}
}
@@ -201,7 +207,7 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
}
catch (Exception ex)
{
NotificationHelper.ShowError($"断开连接时发生错误: {ex.Message}", ex);
_notificationService.ShowError($"断开连接时发生错误: {ex.Message}", ex);
}
}
@@ -219,7 +225,7 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
}
catch (Exception ex)
{
NotificationHelper.ShowError($"断开连接时发生错误: {ex.Message}", ex);
_notificationService.ShowError($"断开连接时发生错误: {ex.Message}", ex);
}
}
@@ -235,7 +241,7 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
// 检查是否有选中的节点
if (SelectedNode == null)
{
NotificationHelper.ShowError("请先选择左边的节点,然后再查找变量。");
_notificationService.ShowError("请先选择左边的节点,然后再查找变量。");
return;
}
@@ -252,12 +258,12 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
catch (OperationCanceledException)
{
// 处理用户取消操作的情况
NotificationHelper.ShowInfo("操作已被取消");
_notificationService.ShowInfo("操作已被取消");
}
catch (Exception ex)
{
// 处理其他异常情况
NotificationHelper.ShowError($"加载 OPC UA 节点变量失败: {SelectedNode?.NodeId} - {ex.Message}", ex);
_notificationService.ShowError($"加载 OPC UA 节点变量失败: {SelectedNode?.NodeId} - {ex.Message}", ex);
}
}
@@ -285,12 +291,12 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
catch (OperationCanceledException)
{
// 处理用户取消操作的情况
NotificationHelper.ShowInfo("操作已被取消");
_notificationService.ShowInfo("操作已被取消");
}
catch (Exception ex)
{
// 处理其他异常情况
NotificationHelper.ShowError($"加载 OPC UA 节点变量失败: {node?.NodeId} - {ex.Message}", ex);
_notificationService.ShowError($"加载 OPC UA 节点变量失败: {node?.NodeId} - {ex.Message}", ex);
}
}
@@ -355,13 +361,13 @@ public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<Varia
catch (OperationCanceledException)
{
// 处理取消操作
NlogHelper.Info("节点浏览操作已被取消");
_notificationService.ShowInfo("节点浏览操作已被取消");
throw; // 重新抛出异常以保持调用链
}
catch (Exception ex)
{
// 记录浏览节点失败的日志
NlogHelper.Error($"浏览节点失败: {node.NodeId} - {ex.Message}", ex);
_notificationService.ShowError($"浏览节点失败: {node.NodeId} - {ex.Message}", ex);
throw; // 重新抛出异常以保持调用链
}
}

View File

@@ -4,7 +4,6 @@ using CommunityToolkit.Mvvm.Input;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Helper;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Items;

View File

@@ -1,20 +1,13 @@
using System.Collections.ObjectModel;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Core.Enums;
using DMS.WPF.Services;
using DMS.WPF.Views;
using DMS.Core.Helper;
using DMS.Core.Models;
using DMS.Helper;
using DMS.Services;
using DMS.ViewModels;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Items;
using iNKORE.UI.WPF.Modern.Common.IconKeys;
using Microsoft.Extensions.DependencyInjection;
using DMS.WPF.Views;
using Microsoft.Extensions.Logging;
// AddAsync this using directive

View File

@@ -3,7 +3,6 @@ using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using DMS.Core.Models;
using DMS.Helper;
using DMS.Services;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
@@ -21,6 +20,7 @@ namespace DMS.ViewModels
private readonly ILogger<MqttServerDetailViewModel> _logger;
private readonly DataServices _dataServices;
private readonly IDialogService _dialogService;
private readonly NotificationService _notificationService;
/// <summary>
/// 当前正在编辑的MQTT服务器对象。
@@ -41,12 +41,14 @@ namespace DMS.ViewModels
/// <param name="logger">日志服务。</param>
/// <param name="dataServices">数据服务。</param>
/// <param name="dialogService">对话框服务。</param>
/// <param name="notificationService">通知服务。</param>
public MqttServerDetailViewModel(ILogger<MqttServerDetailViewModel> logger, DataServices dataServices,
IDialogService dialogService)
IDialogService dialogService, NotificationService notificationService)
{
_logger = logger;
_dataServices = dataServices;
_dialogService = dialogService;
_notificationService = notificationService;
}
public override void OnLoaded()
@@ -81,7 +83,7 @@ namespace DMS.ViewModels
// await _dataServices.UpdateVariableAsync(variable);
// }
NotificationHelper.ShowInfo("MQTT服务器详情保存功能待实现。");
_notificationService.ShowInfo("MQTT服务器详情保存功能待实现。");
_logger.LogInformation("Save changes for MQTT server detail initiated.");
}
@@ -131,7 +133,7 @@ namespace DMS.ViewModels
// TODO: 实现选择变量的对话框,让用户选择要添加的变量
// 例如var selectedVariables = await _dialogService.ShowVariableSelectionDialogAsync();
// 这里只是一个占位符实际需要一个UI来选择变量
NotificationHelper.ShowInfo("添加变量功能待实现,需要一个变量选择对话框。");
_notificationService.ShowInfo("添加变量功能待实现,需要一个变量选择对话框。");
_logger.LogInformation("AddAsync variables to MQTT server initiated.");
// 假设我们已经通过对话框获取到了一些要添加的变量

View File

@@ -2,7 +2,6 @@ using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Core.Enums;
using DMS.Helper;
using DMS.Services;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;

View File

@@ -1,6 +1,5 @@
using CommunityToolkit.Mvvm.Input;
using DMS.WPF.Helper;
using DMS.Helper;
namespace DMS.WPF.ViewModels;

View File

@@ -19,7 +19,7 @@ namespace DMS.WPF.ViewModels;
/// </summary>
public partial class SplashViewModel : ObservableObject
{
private readonly ILogger _logger;
private readonly ILogger<SplashViewModel> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly IInitializeService _initializeService;
private readonly IDataCenterService _dataCenterService;
@@ -28,7 +28,7 @@ public partial class SplashViewModel : ObservableObject
[ObservableProperty]
private string _loadingMessage = "正在加载...";
public SplashViewModel( ILogger logger,IServiceProvider serviceProvider, IInitializeService initializeService,
public SplashViewModel(ILogger<SplashViewModel> logger,IServiceProvider serviceProvider, IInitializeService initializeService,
IDataCenterService dataCenterService, DataServices dataServices)
{
_logger = logger;

View File

@@ -5,7 +5,6 @@ using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Core.Models;
using DMS.Helper;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Dialogs;
using DMS.WPF.ViewModels.Items;
@@ -87,13 +86,16 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
private readonly ISynchronizedView<VariableItemViewModel, VariableItemViewModel> _synchronizedView;
public NotifyCollectionChangedSynchronizedViewList<VariableItemViewModel> VariableItemListView { get; }
private readonly NotificationService _notificationService;
public VariableTableViewModel(IMapper mapper, IDialogService dialogService, IVariableAppService variableAppService,
DataServices dataServices)
DataServices dataServices, NotificationService notificationService)
{
_mapper = mapper;
_dialogService = dialogService;
_variableAppService = variableAppService;
_dataServices = dataServices;
_notificationService = notificationService;
IsLoadCompletion = false; // 初始设置为 false表示未完成加载
@@ -170,7 +172,7 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 检查是否有变量被选中
if (SelectedVariable == null)
{
NotificationHelper.ShowInfo("请选择要编辑的变量");
_notificationService.ShowInfo("请选择要编辑的变量");
return;
}
@@ -201,17 +203,17 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 更新当前页面显示的数据:找到原数据在集合中的索引并替换
_mapper.Map(editedVariable, SelectedVariable); // 更新选中项的属性
// 显示成功通知
NotificationHelper.ShowSuccess($"编辑变量成功:{editedVariable.Name}");
_notificationService.ShowSuccess($"编辑变量成功:{editedVariable.Name}");
}
else
{
NotificationHelper.ShowError("编辑变量失败");
_notificationService.ShowError("编辑变量失败");
}
}
catch (Exception e)
{
// 捕获并显示错误通知
NotificationHelper.ShowError($"编辑变量的过程中发生了不可预期的错误:{e.Message}", e);
_notificationService.ShowError($"编辑变量的过程中发生了不可预期的错误:{e.Message}", e);
}
}
@@ -257,17 +259,17 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (isSuccess)
{
_variableItemList.AddRange(_mapper.Map<List<VariableItemViewModel>>(improtVariableDtos));
NotificationHelper.ShowSuccess($"从Excel导入变量成功共导入变量{improtVariableDtos.Count}个");
_notificationService.ShowSuccess($"从Excel导入变量成功共导入变量{improtVariableDtos.Count}个");
}
}
else
{
NotificationHelper.ShowSuccess($"列表中没有要添加的变量了。 ");
_notificationService.ShowSuccess($"列表中没有要添加的变量了。 ");
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"从TIA导入变量的过程中发生了不可预期的错误{e.Message}", e);
_notificationService.ShowError($"从TIA导入变量的过程中发生了不可预期的错误{e.Message}", e);
}
}
@@ -282,14 +284,14 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
{
if (CurrentVariableTable.Device == null)
{
NotificationHelper.ShowError("当前变量表的Device对象为空请检查。");
_notificationService.ShowError("当前变量表的Device对象为空请检查。");
return;
}
// 检查OPC UA Endpoint URL是否已设置
string opcUaEndpointUrl = CurrentVariableTable.Device.OpcUaServerUrl;
if (string.IsNullOrEmpty(opcUaEndpointUrl))
{
NotificationHelper.ShowError("OPC UA Endpoint URL 未设置。请在设备详情中配置。");
_notificationService.ShowError("OPC UA Endpoint URL 未设置。请在设备详情中配置。");
return;
}
@@ -331,21 +333,21 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (isSuccess)
{
_variableItemList.AddRange(_mapper.Map<List<VariableItemViewModel>>(importedVariableDtos));
NotificationHelper.ShowSuccess($"从OPC UA服务器导入变量成功共导入变量{importedVariableDtos.Count}个");
_notificationService.ShowSuccess($"从OPC UA服务器导入变量成功共导入变量{importedVariableDtos.Count}个");
}
else
{
NotificationHelper.ShowError("从OPC UA服务器导入变量失败");
_notificationService.ShowError("从OPC UA服务器导入变量失败");
}
}
else
{
NotificationHelper.ShowSuccess("列表中没有要添加的变量了。");
_notificationService.ShowSuccess("列表中没有要添加的变量了。");
}
}
catch (Exception e)
{
NotificationHelper.ShowError($"从OPC UA服务器导入变量的过程中发生了不可预期的错误{e.Message}", e);
_notificationService.ShowError($"从OPC UA服务器导入变量的过程中发生了不可预期的错误{e.Message}", e);
}
}
@@ -389,12 +391,12 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
_dataServices.AddVariable(variableItemViewModel);
//
// // 显示成功通知
NotificationHelper.ShowSuccess($"添加变量成功:{variableItemViewModel.Name}");
_notificationService.ShowSuccess($"添加变量成功:{variableItemViewModel.Name}");
}
catch (Exception e)
{
// 捕获并显示错误通知
NotificationHelper.ShowError($"添加变量的过程中发生了不可预期的错误:{e.Message}", e);
_notificationService.ShowError($"添加变量的过程中发生了不可预期的错误:{e.Message}", e);
}
}
@@ -412,7 +414,7 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 检查是否有变量被选中
if (variablesToDelete == null || !variablesToDelete.Any())
{
NotificationHelper.ShowInfo("请选择要删除的变量");
_notificationService.ShowInfo("请选择要删除的变量");
return;
}
@@ -436,18 +438,18 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
_dataServices.DeleteVariable(variable.Id);
}
// 显示成功通知
NotificationHelper.ShowSuccess($"成功删除 {variablesToDelete.Count} 个变量");
_notificationService.ShowSuccess($"成功删除 {variablesToDelete.Count} 个变量");
}
else
{
// 显示删除失败通知
NotificationHelper.ShowError("删除变量失败");
_notificationService.ShowError("删除变量失败");
}
}
catch (Exception e)
{
// 捕获并显示错误通知
NotificationHelper.ShowError($"删除变量的过程中发生了不可预期的错误:{e.Message}", e);
_notificationService.ShowError($"删除变量的过程中发生了不可预期的错误:{e.Message}", e);
}
}
@@ -462,7 +464,7 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 检查是否有变量被选中
if (SelectedVariables.Count == 0)
{
NotificationHelper.ShowInfo("请选择要修改轮询频率的变量");
_notificationService.ShowInfo("请选择要修改轮询频率的变量");
return;
}
@@ -488,11 +490,11 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (result > 0)
{
// 显示成功通知
NotificationHelper.ShowSuccess($"已成功更新 {validVariables.Count} 个变量的轮询频率");
_notificationService.ShowSuccess($"已成功更新 {validVariables.Count} 个变量的轮询频率");
}
else
{
NotificationHelper.ShowError("更新轮询频率失败");
_notificationService.ShowError("更新轮询频率失败");
}
}
}
@@ -646,7 +648,7 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// 检查是否有变量被选中
if (SelectedVariables.Count == 0)
{
NotificationHelper.ShowInfo("请选择要修改启用状态的变量");
_notificationService.ShowInfo("请选择要修改启用状态的变量");
return;
}
@@ -672,11 +674,11 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (result > 0)
{
// 显示成功通知
NotificationHelper.ShowSuccess($"已成功更新 {validVariables.Count} 个变量的启用状态");
_notificationService.ShowSuccess($"已成功更新 {validVariables.Count} 个变量的启用状态");
}
else
{
NotificationHelper.ShowError("更新启用状态失败");
_notificationService.ShowError("更新启用状态失败");
}
}
}

View File

@@ -1,9 +1,5 @@
using System.Windows;
using System.Windows.Controls;
using DMS.Core.Helper;
using DMS.WPF.Helper;
using DMS.WPF.ViewModels.Dialogs;
using iNKORE.UI.WPF.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
namespace DMS.WPF.Views.Dialogs;
@@ -23,7 +19,7 @@ public partial class DeviceDialog : ContentDialog
private void OnOpened(ContentDialog sender, ContentDialogOpenedEventArgs args)
{
//<2F>޸ĶԻ<C4B6><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
//<2F>޸ĶԻ<C4B6><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
var backgroundElementBorder = VisualTreeFinder.FindVisualChildByName<Border>(this, "BackgroundElement");
backgroundElementBorder.MaxWidth = ContentAreaMaxWidth;
backgroundElementBorder.MaxWidth = ContentAreaMaxHeight;

View File

@@ -1,6 +1,6 @@
using DMS.Helper;
using DMS.Services;
using DMS.WPF.Helper;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Dialogs;
using DMS.WPF.ViewModels.Items;
using iNKORE.UI.WPF.Modern.Controls;
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Microsoft.Extensions.DependencyInjection;
namespace DMS.WPF.Views.Dialogs;
@@ -22,6 +23,8 @@ public partial class ImportOpcUaDialog : ContentDialog
public ImportOpcUaDialog()
{
InitializeComponent();
@@ -49,7 +52,8 @@ public partial class ImportOpcUaDialog : ContentDialog
}
catch (Exception ex)
{
NotificationHelper.ShowError($"选择节点时发生了错误:{ex.Message}");
var notificationService = App.Current.Services.GetRequiredService<NotificationService>();
notificationService.ShowError($"选择节点时发生了错误:{ex.Message}");
}

View File

@@ -1,5 +1,4 @@
using System.Windows;
using DMS.Core.Helper;
using DMS.WPF.Services;
using DMS.WPF.ViewModels;
using iNKORE.UI.WPF.Modern.Controls;
@@ -23,7 +22,6 @@ public partial class MainView : Window
InitializeComponent();
_viewModel = App.Current.Services.GetRequiredService<MainViewModel>();
DataContext = _viewModel;
NlogHelper.Info("主界面加载成功");
// Set the NotifyIcon's DataContext to the ViewModel
MyNotifyIcon.DataContext = _viewModel;

View File

@@ -2,8 +2,8 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using DMS.Helper;
using DMS.WPF.ViewModels;
using DMS.WPF.Services;
using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -39,7 +39,8 @@ public partial class VariableTableView : UserControl
}
catch (Exception exception)
{
NotificationHelper.ShowError($"修改变量表启用,停用时发生了错误:{exception.Message}", exception);
var notificationService = App.Current.Services.GetRequiredService<NotificationService>();
notificationService.ShowError($"修改变量表启用,停用时发生了错误:{exception.Message}", exception);
}
}
@@ -48,5 +49,4 @@ public partial class VariableTableView : UserControl
IsLoadCompletion = true;
}
}