diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xml b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xml
new file mode 100644
index 000000000..5d6962159
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xsd b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xsd
new file mode 100644
index 000000000..3f3946e28
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN.Abp.ElsaNext.Notifications.csproj b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN.Abp.ElsaNext.Notifications.csproj
new file mode 100644
index 000000000..0c1e95496
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN.Abp.ElsaNext.Notifications.csproj
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ net10.0
+ LINGYUN.Abp.ElsaNext.Notifications
+ LINGYUN.Abp.ElsaNext.Notifications
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/AbpElsaNextNotificationsModule.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/AbpElsaNextNotificationsModule.cs
new file mode 100644
index 000000000..afa8b0da0
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/AbpElsaNextNotificationsModule.cs
@@ -0,0 +1,38 @@
+using Elsa.Features.Services;
+using LINGYUN.Abp.ElsaNext.Localization;
+using LINGYUN.Abp.ElsaNext.Notifications.Extensions;
+using LINGYUN.Abp.Notifications;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace LINGYUN.Abp.ElsaNext.Notifications;
+
+[DependsOn(
+ typeof(AbpNotificationsModule),
+ typeof(AbpElsaNextModule))]
+public class AbpElsaNextNotificationsModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(elsa =>
+ {
+ elsa.UseAbpNotifications();
+ });
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Get()
+ .AddVirtualJson("/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources");
+ });
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Activities/SendNotification.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Activities/SendNotification.cs
new file mode 100644
index 000000000..c4d4ea9cb
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Activities/SendNotification.cs
@@ -0,0 +1,136 @@
+using Elsa.Extensions;
+using Elsa.Workflows;
+using Elsa.Workflows.Attributes;
+using Elsa.Workflows.Models;
+using Elsa.Workflows.UIHints;
+using LINGYUN.Abp.ElsaNext.Notifications.UIHints;
+using LINGYUN.Abp.ElsaNext.UIHints;
+using LINGYUN.Abp.Notifications;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Timing;
+using INotificationSender = LINGYUN.Abp.Notifications.INotificationSender;
+
+namespace LINGYUN.Abp.ElsaNext.Notifications.Activities;
+
+[Activity("Elsa", "Notifications", "Send an notification.", Kind = ActivityKind.Task)]
+public class SendNotification : CodeActivity
+{
+ [Input(
+ Description = "The name of the registered notification.",
+ UIHint = NotificationsUIHints.NotificationPicker)]
+ public Input NotificationName { get; set; } = default!;
+
+ [Input(
+ Description = "The notification title.",
+ UIHint = InputUIHints.MultiLine
+ )]
+ public Input Title { get; set; } = default!;
+
+ [Input(
+ Description = "The notification content.",
+ UIHint = InputUIHints.MultiLine
+ )]
+ public Input Content { get; set; } = default!;
+
+ [Input(
+ Description = "The notification description.",
+ UIHint = InputUIHints.MultiLine
+ )]
+ public Input Description { get; set; } = default!;
+
+ [Input(
+ Description = "The notification template name.",
+ UIHint = InputUIHints.MultiLine
+ )]
+ public Input Template { get; set; } = default!;
+
+ [Input(
+ Description = "The notification additional attributes.",
+ UIHint = InputUIHints.Dictionary
+ )]
+ public Input> Propertites { get; set; } = default!;
+
+ [Input(
+ Description = "The tenant id for sending the notification.",
+ UIHint = AbpElsaUIHints.TenantPicker)]
+ public Input TenantId { get; set; } = null!;
+
+ [Input(
+ Description = "The recipients email addresses.",
+ UIHint = AbpElsaUIHints.UserPicker)]
+ public Input> To { get; set; } = null!;
+
+ [Input(
+ Description = "The notifications severity.",
+ Options = new[] { "Success", "Info", "Warn", "Error", "Fatal" },
+ DefaultValue = "Info",
+ UIHint = InputUIHints.DropDown)]
+ public Input Severity { get; set; } = null!;
+
+ [Output(Description = "The notification id.")]
+ public Output NotificationId { get; set; } = null!;
+
+ protected async override ValueTask ExecuteAsync(ActivityExecutionContext context)
+ {
+ var notificationSender = context.GetRequiredService();
+ var currentTenant = context.GetRequiredService();
+ var clock = context.GetRequiredService();
+
+ var tenantId = TenantId.GetOrDefault(context, () => currentTenant.Id);
+ var userIdentifiers = GetUserIdentifiers(context);
+ var severity = GetNotificationSeverity(context);
+ var propertites = Propertites.GetOrDefault(context);
+ var notificationName = NotificationName.Get(context);
+ var template = Template.GetOrDefault(context);
+ if (!string.IsNullOrWhiteSpace(template))
+ {
+ var notificationTemplate = new NotificationTemplate(template, data: propertites);
+ var notificationTemplateId = await notificationSender.SendNofiterAsync(
+ notificationName,
+ notificationTemplate,
+ userIdentifiers,
+ tenantId,
+ severity);
+ NotificationId.Set(context, notificationTemplateId);
+ }
+ else
+ {
+ var title = Title.Get(context);
+ var message = Content.Get(context);
+ var description = Description.GetOrDefault(context) ?? "";
+
+ var notificationData = new NotificationData();
+ notificationData.WriteStandardData(title!, message!, clock.Now, "elsa-workflow", description);
+ var notificationId = await notificationSender.SendNofiterAsync(
+ notificationName,
+ notificationData,
+ userIdentifiers,
+ tenantId,
+ severity);
+ NotificationId.Set(context, notificationId);
+ }
+ }
+
+ private NotificationSeverity GetNotificationSeverity(ActivityExecutionContext context)
+ {
+ var severitySet = Severity.GetOrDefault(context);
+ if (!string.IsNullOrWhiteSpace(severitySet))
+ {
+ if (Enum.TryParse(severitySet, true, out var severity))
+ {
+ return severity;
+ }
+ }
+ return NotificationSeverity.Info;
+ }
+
+ private IEnumerable? GetUserIdentifiers(ActivityExecutionContext context)
+ {
+ var userIdentifiers = To.GetOrDefault(context);
+ return userIdentifiers?.Select(to => new UserIdentifier(to, to.ToString()));
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Extensions/ModuleExtensions.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Extensions/ModuleExtensions.cs
new file mode 100644
index 000000000..2573ab38f
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Extensions/ModuleExtensions.cs
@@ -0,0 +1,14 @@
+using Elsa.Features.Services;
+using LINGYUN.Abp.ElsaNext.Notifications.Features;
+using System;
+
+namespace LINGYUN.Abp.ElsaNext.Notifications.Extensions;
+
+public static class ModuleExtensions
+{
+ public static IModule UseAbpNotifications(this IModule configuration, Action? configure = null)
+ {
+ configuration.Configure(configure);
+ return configuration;
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Features/NotificationsFeature.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Features/NotificationsFeature.cs
new file mode 100644
index 000000000..8d6ef3b04
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Features/NotificationsFeature.cs
@@ -0,0 +1,17 @@
+using Elsa.Extensions;
+using Elsa.Features.Abstractions;
+using Elsa.Features.Services;
+
+namespace LINGYUN.Abp.ElsaNext.Notifications.Features;
+
+public class NotificationsFeature : FeatureBase
+{
+ public NotificationsFeature(IModule module) : base(module)
+ {
+ }
+
+ public override void Configure()
+ {
+ Module.AddActivitiesFrom();
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/en.json b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/en.json
new file mode 100644
index 000000000..477772584
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/en.json
@@ -0,0 +1,18 @@
+{
+ "culture": "en",
+ "texts": {
+ "Notifications": "Notifications",
+ "Send Notification": "Send Notification",
+ "Send an notification.": "Send an notification.",
+ "The name of the registered notification.": "The name of the registered notification.",
+ "The notification title.": "The notification title.",
+ "The notification content.": "The notification content.",
+ "The notification description.": "The notification description.",
+ "The notification template name.": "The notification template name.",
+ "The notification additional attributes.": "The notification additional attributes.",
+ "The tenant id for sending the notification.": "The tenant id for sending the notification.",
+ "The recipients email addresses.": "The recipients email addresses.",
+ "The notifications severity.": "The notifications severity.",
+ "The notification id.": "The notification id."
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/zh-Hans.json b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/zh-Hans.json
new file mode 100644
index 000000000..c6717a413
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/Localization/Resources/zh-Hans.json
@@ -0,0 +1,18 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "Notifications": "消息通知",
+ "Send Notification": "发送通知",
+ "Send an notification.": "发送通知。",
+ "The name of the registered notification.": "已注册的通知名称。",
+ "The notification title.": "通知标题。",
+ "The notification content.": "通知内容。",
+ "The notification description.": "通知描述。",
+ "The notification template name.": "通知模板,使用模板消息时标题、内容、描述内容无效。",
+ "The notification additional attributes.": "通知属性。",
+ "The tenant id for sending the notification.": "将要发送通知的租户Id。",
+ "The recipients email addresses.": "接收通知的用户Id集合。",
+ "The notifications severity.": "通知严重程度。",
+ "The notification id.": "通知Id。"
+ }
+}
diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/UIHints/NotificationsUIHints.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/UIHints/NotificationsUIHints.cs
new file mode 100644
index 000000000..2d5dfa3e4
--- /dev/null
+++ b/aspnet-core/modules/elsa/LINGYUN.Abp.ElsaNext.Notifications/LINGYUN/Abp/ElsaNext/Notifications/UIHints/NotificationsUIHints.cs
@@ -0,0 +1,6 @@
+namespace LINGYUN.Abp.ElsaNext.Notifications.UIHints;
+
+public static class NotificationsUIHints
+{
+ public const string NotificationPicker = "notification-picker";
+}