diff --git a/aspnet-core/LINGYUN.MicroService.All.slnx b/aspnet-core/LINGYUN.MicroService.All.slnx
index 011923378..a990dac8d 100644
--- a/aspnet-core/LINGYUN.MicroService.All.slnx
+++ b/aspnet-core/LINGYUN.MicroService.All.slnx
@@ -105,6 +105,9 @@
+
+
+
@@ -433,6 +436,7 @@
+
diff --git a/aspnet-core/LINGYUN.MicroService.Aspire.slnx b/aspnet-core/LINGYUN.MicroService.Aspire.slnx
index a19022d70..f44c32ec2 100644
--- a/aspnet-core/LINGYUN.MicroService.Aspire.slnx
+++ b/aspnet-core/LINGYUN.MicroService.Aspire.slnx
@@ -448,6 +448,7 @@
+
diff --git a/aspnet-core/LINGYUN.MicroService.SingleProject.slnx b/aspnet-core/LINGYUN.MicroService.SingleProject.slnx
index 269419841..7f687aba2 100644
--- a/aspnet-core/LINGYUN.MicroService.SingleProject.slnx
+++ b/aspnet-core/LINGYUN.MicroService.SingleProject.slnx
@@ -36,6 +36,9 @@
+
+
+
@@ -96,6 +99,7 @@
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj
index c266d7bb7..d56ea12ac 100644
--- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/LINGYUN.Abp.MicroService.MessageService.csproj
@@ -55,6 +55,7 @@
+
diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs
index 5445db5cd..4bc4d45f3 100644
--- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs
+++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/MessageServiceModule.cs
@@ -23,6 +23,7 @@ using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MessageService;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.Notifications;
+using LINGYUN.Abp.Notifications.Calendar;
using LINGYUN.Abp.Notifications.Common;
using LINGYUN.Abp.Notifications.Emailing;
using LINGYUN.Abp.Notifications.EntityFrameworkCore;
@@ -102,6 +103,7 @@ namespace LINGYUN.Abp.MicroService.MessageService;
typeof(AbpNotificationsWeChatWorkModule),
typeof(AbpNotificationsExceptionHandlingModule),
typeof(AbpNotificationsTemplatingModule),
+ typeof(AbpNotificationsCalendarModule),
typeof(AbpWeChatWorkHandlersModule),
typeof(AbpWeChatOfficialHandlersModule),
typeof(AbpIdentityNotificationsModule),
diff --git a/aspnet-core/framework/calendars/LINGYUN.Abp.Calendar/LINGYUN/Abp/Calendar/WorkdayCalendarService.cs b/aspnet-core/framework/calendars/LINGYUN.Abp.Calendar/LINGYUN/Abp/Calendar/WorkdayCalendarService.cs
index e63ff3150..56f796efc 100644
--- a/aspnet-core/framework/calendars/LINGYUN.Abp.Calendar/LINGYUN/Abp/Calendar/WorkdayCalendarService.cs
+++ b/aspnet-core/framework/calendars/LINGYUN.Abp.Calendar/LINGYUN/Abp/Calendar/WorkdayCalendarService.cs
@@ -87,7 +87,7 @@ public class WorkdayCalendarService : IWorkdayCalendarService, ITransientDepende
return false;
}
if (_options.EnableWorkTimeRestriction &&
- !_options.DefaultWorkTimes.Any(timeRange => timeRange.StartTime >= time.TimeOfDay && timeRange.EndTime <= time.TimeOfDay))
+ !_options.DefaultWorkTimes.Any(timeRange => time.TimeOfDay >= timeRange.StartTime && time.TimeOfDay <= timeRange.EndTime))
{
return false;
}
@@ -109,7 +109,7 @@ public class WorkdayCalendarService : IWorkdayCalendarService, ITransientDepende
if (calendar.EnableWorkTimeRestriction &&
calendar.WorkTimes != null)
{
- return calendar.WorkTimes.Any(x => x.StartTime >= time.TimeOfDay && x.EndTime <= time.TimeOfDay);
+ return calendar.WorkTimes.Any(timeRange => time.TimeOfDay >= timeRange.StartTime && time.TimeOfDay <= timeRange.EndTime);
}
return false;
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/FodyWeavers.xml b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/FodyWeavers.xml
new file mode 100644
index 000000000..1715698cc
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN.Abp.Notifications.Calendar.csproj b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN.Abp.Notifications.Calendar.csproj
new file mode 100644
index 000000000..3715f079e
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN.Abp.Notifications.Calendar.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ net10.0
+ LINGYUN.Abp.Notifications.Calendar
+ LINGYUN.Abp.Notifications.Calendar
+ false
+ false
+ false
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/AbpNotificationsCalendarModule.cs b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/AbpNotificationsCalendarModule.cs
new file mode 100644
index 000000000..781030660
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/AbpNotificationsCalendarModule.cs
@@ -0,0 +1,16 @@
+using LINGYUN.Abp.Calendar;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Notifications.Calendar;
+
+[DependsOn(
+ typeof(AbpNotificationsModule),
+ typeof(AbpCalendarModule))]
+public class AbpNotificationsCalendarModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddTransient();
+ }
+}
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/WorkdayCalendarPublishInterceptor.cs b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/WorkdayCalendarPublishInterceptor.cs
new file mode 100644
index 000000000..f93beff5e
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/LINGYUN/Abp/Notifications/Calendar/WorkdayCalendarPublishInterceptor.cs
@@ -0,0 +1,65 @@
+using LINGYUN.Abp.Calendar;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Timing;
+
+namespace LINGYUN.Abp.Notifications.Calendar;
+
+///
+/// 工作日通知发布拦截器
+///
+public class WorkdayCalendarPublishInterceptor : INotificationPublishInterceptor
+{
+ private readonly IClock _clock;
+ private readonly ICurrentTenant _currentTenant;
+ private readonly IWorkdayCalendarService _workdayCalendarService;
+ public ILogger Logger { protected get; set; }
+
+ public WorkdayCalendarPublishInterceptor(
+ IClock clock,
+ ICurrentTenant currentTenant,
+ IWorkdayCalendarService workdayCalendarService)
+ {
+ _clock = clock;
+ _currentTenant = currentTenant;
+ _workdayCalendarService = workdayCalendarService;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public int Priority => 100;
+
+ public async Task CanPublishAsync(NotificationInfo notification)
+ {
+ try
+ {
+ using (_currentTenant.Change(notification.TenantId))
+ {
+ var isWorktime = await _workdayCalendarService.IsInWorkTimeAsync(_clock.Now);
+
+ if (!isWorktime)
+ {
+ Logger.LogInformation(
+ "Notification {NotificationName} was blocked during the working time check. Type: {NotificationType}, Time: {Time}.",
+ notification.Name,
+ notification.Type,
+ _clock.Now.ToString("yyyy-MM-dd HH:mm:ss"));
+ return false;
+ }
+
+ return true;
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogWarning(ex,
+ "If an abnormality occurs during the working day check, the default setting allows {NotificationName} to be notified to publish.",
+ notification.Name);
+
+ return true;
+ }
+ }
+}
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/README.md b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/README.md
new file mode 100644
index 000000000..8695a85e8
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Calendar/README.md
@@ -0,0 +1,15 @@
+# LINGYUN.Abp.Notifications.Calendar
+
+通知发布提供程序的工作日检查拦截器, 非系统定义工作日时不发布通知.
+
+#### 注意
+
+
+## 功能特性
+
+
+## 配置使用
+
+
+## 更多信息
+
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishInterceptor.cs b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishInterceptor.cs
new file mode 100644
index 000000000..27437a1b5
--- /dev/null
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/INotificationPublishInterceptor.cs
@@ -0,0 +1,20 @@
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Notifications;
+///
+/// 通知发布拦截器, 实现此接口来增加发布前的自定义检查
+///
+public interface INotificationPublishInterceptor
+{
+ ///
+ /// 拦截优先级,数值越小优先级越高
+ ///
+ int Priority { get; }
+
+ ///
+ /// 在通知发布前执行检查
+ ///
+ /// 通知信息
+ /// true-允许发布, false-阻止发布
+ Task CanPublishAsync(NotificationInfo notification);
+}
diff --git a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs
index 8bf1cc899..8e52907a7 100644
--- a/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs
+++ b/aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishProvider.cs
@@ -1,6 +1,8 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
@@ -21,6 +23,11 @@ public abstract class NotificationPublishProvider : INotificationPublishProvider
public ICancellationTokenProvider CancellationTokenProvider => ServiceProvider.LazyGetService(NullCancellationTokenProvider.Instance);
+ private IEnumerable _interceptors;
+ protected IEnumerable Interceptors =>
+ _interceptors ??= ServiceProvider.LazyGetService>()
+ ?? Enumerable.Empty();
+
public async virtual Task CanPublishAsync(NotificationInfo notification)
{
return await CanPublishAsync(notification, GetCancellationToken());
@@ -28,9 +35,23 @@ public abstract class NotificationPublishProvider : INotificationPublishProvider
public async Task PublishAsync(NotificationPublishContext context)
{
- await PublishAsync(context, GetCancellationToken());
+ var cancellationToken = GetCancellationToken();
+
+ // 通知拦截器检查
+ if (!await ExecuteInterceptorsAsync(context, cancellationToken))
+ {
+ return;
+ }
+
+ await PublishAsync(context, cancellationToken);
}
+ ///
+ /// 是否允许发布通知
+ ///
+ ///
+ ///
+ ///
protected virtual Task CanPublishAsync(
NotificationInfo notification,
CancellationToken cancellationToken = default)
@@ -38,6 +59,60 @@ public abstract class NotificationPublishProvider : INotificationPublishProvider
return Task.FromResult(true);
}
+ ///
+ /// 执行通知发布拦截器
+ ///
+ ///
+ ///
+ ///
+ protected virtual async Task ExecuteInterceptorsAsync(
+ NotificationPublishContext context,
+ CancellationToken cancellationToken = default)
+ {
+ if (context.Notification.Type == NotificationType.System ||
+ context.Notification.Type == NotificationType.ServiceCallback)
+ {
+ Logger.LogDebug(
+ "System or service callback notification {NotificationName}, skip all interceptors.",
+ context.Notification.Name);
+ return true;
+ }
+
+ if (!Interceptors.Any())
+ {
+ Logger.LogDebug("No notification publishing interceptors have been registered.");
+ return true;
+ }
+
+ var orderedInterceptors = Interceptors.OrderBy(i => i.Priority);
+
+ foreach (var interceptor in orderedInterceptors)
+ {
+ try
+ {
+ if (!await interceptor.CanPublishAsync(context.Notification))
+ {
+ var reason = string.Format("The interceptor {0} prevented the publication of the notification {1}.",
+ interceptor.GetType().Name,
+ context.Notification.Name);
+
+ context.Cancel(reason);
+
+ Logger.LogWarning(reason);
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogWarning(ex,
+ "An exception occurred while executing the interceptor {InterceptorType}. By default, publication is allowed.",
+ interceptor.GetType().Name);
+ }
+ }
+
+ return true;
+ }
+
protected virtual CancellationToken GetCancellationToken(CancellationToken cancellationToken = default)
{
return CancellationTokenProvider.FallbackToProvider(cancellationToken);
diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
index c2023f0f5..5537e2c55 100644
--- a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
+++ b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
@@ -211,6 +211,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
index e8693c8c6..287123617 100644
--- a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
+++ b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs
@@ -1,4 +1,5 @@
using LINGYUN.Abp.Exporter.MiniSoftware;
+using LINGYUN.Abp.Notifications.Calendar;
namespace LY.MicroService.Applications.Single;
@@ -316,6 +317,8 @@ namespace LY.MicroService.Applications.Single;
typeof(AbpNotificationsWeChatMiniProgramModule),
// 通知模块 企业微信
typeof(AbpNotificationsWeChatWorkModule),
+ // 通知模块 工作日检查拦截器
+ typeof(AbpNotificationsCalendarModule),
// 多租户模块 版本
typeof(AbpMultiTenancyEditionsModule),
diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj
index 0660c8477..f947c5d5a 100644
--- a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj
+++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj
@@ -74,6 +74,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs
index ca465dfb5..e98996175 100644
--- a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs
+++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs
@@ -23,6 +23,7 @@ using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MessageService;
using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.Notifications;
+using LINGYUN.Abp.Notifications.Calendar;
using LINGYUN.Abp.Notifications.Common;
using LINGYUN.Abp.Notifications.Emailing;
using LINGYUN.Abp.Notifications.EntityFrameworkCore;
@@ -107,6 +108,7 @@ namespace LY.MicroService.RealtimeMessage;
typeof(AbpNotificationsWeChatWorkModule),
typeof(AbpNotificationsExceptionHandlingModule),
typeof(AbpNotificationsTemplatingModule),
+ typeof(AbpNotificationsCalendarModule),
typeof(AbpWeChatWorkHandlersModule),
typeof(AbpWeChatOfficialHandlersModule),
typeof(AbpIdentityNotificationsModule),