paiban/NPP.SmartSchedue.Api/Services/Notification/NotificationTemplateService.cs
Developer 058d8edffa 添加通知系统和工作任务分配功能
- 新增通知系统完整架构,包含通知设置、历史记录、任务管理等核心功能
- 实现工作任务分配服务,支持人员和设备的智能分配
- 添加人员分组管理功能,支持灵活的通知目标配置
- 完善相关枚举定义和数据传输对象

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 08:34:01 +08:00

433 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Linq;
using Newtonsoft.Json;
using NPP.SmartSchedue.Api.Contracts.Services.Notification;
namespace NPP.SmartSchedue.Api.Services.Notification;
/// <summary>
/// 通知模板服务实现
/// 决策点7模板通知支持通知内容模板可替换变量
/// 使用简单的变量替换机制:{变量名}
/// </summary>
public class NotificationTemplateService : INotificationTemplateService
{
// 变量匹配正则表达式:匹配 {变量名} 格式
private static readonly Regex VariableRegex = new Regex(@"\{([a-zA-Z_][a-zA-Z0-9_]*)\}", RegexOptions.Compiled);
#region
/// <summary>
/// 渲染通知模板
/// </summary>
public async Task<string> RenderTemplateAsync(string template, Dictionary<string, string> variables)
{
return await Task.FromResult(RenderTemplate(template, variables));
}
/// <summary>
/// 同步渲染通知模板
/// </summary>
public string RenderTemplate(string template, Dictionary<string, string> variables)
{
if (string.IsNullOrWhiteSpace(template))
return string.Empty;
if (variables == null || !variables.Any())
return template;
var result = template;
// 替换所有匹配的变量
result = VariableRegex.Replace(result, match =>
{
var variableName = match.Groups[1].Value;
// 如果变量存在于字典中,则替换
if (variables.TryGetValue(variableName, out var variableValue))
{
return variableValue ?? string.Empty;
}
// 如果变量不存在,保留原始占位符
return match.Value;
});
return result;
}
#endregion
#region
/// <summary>
/// 验证模板语法
/// </summary>
public async Task<TemplateValidationResult> ValidateTemplateAsync(string template)
{
return await Task.FromResult(ValidateTemplate(template));
}
/// <summary>
/// 同步验证模板语法
/// </summary>
public TemplateValidationResult ValidateTemplate(string template)
{
var result = new TemplateValidationResult();
if (string.IsNullOrWhiteSpace(template))
{
result.AddError("模板内容不能为空");
return result;
}
try
{
// 提取所有变量
var variables = ExtractVariables(template);
result.Variables = variables;
// 检查变量命名规范
foreach (var variable in variables)
{
if (!IsValidVariableName(variable))
{
result.AddError($"变量名 '{variable}' 不符合命名规范,变量名只能包含字母、数字和下划线,且不能以数字开头");
}
}
// 检查是否有未闭合的大括号
var openBraceCount = template.Count(c => c == '{');
var closeBraceCount = template.Count(c => c == '}');
if (openBraceCount != closeBraceCount)
{
result.AddError($"大括号不匹配:找到 {openBraceCount} 个左大括号和 {closeBraceCount} 个右大括号");
}
// 检查嵌套大括号
if (template.Contains("{{") || template.Contains("}}"))
{
result.AddWarning("发现嵌套大括号,这可能导致变量替换异常");
}
// 检查空的变量占位符
if (template.Contains("{}"))
{
result.AddError("发现空的变量占位符 {},请指定变量名");
}
}
catch (Exception ex)
{
result.AddError($"模板验证时发生异常:{ex.Message}");
}
return result;
}
#endregion
#region
/// <summary>
/// 提取模板中的变量列表
/// </summary>
public async Task<List<string>> ExtractVariablesAsync(string template)
{
return await Task.FromResult(ExtractVariables(template));
}
/// <summary>
/// 同步提取模板中的变量列表
/// </summary>
public List<string> ExtractVariables(string template)
{
if (string.IsNullOrWhiteSpace(template))
return new List<string>();
var variables = new HashSet<string>();
var matches = VariableRegex.Matches(template);
foreach (Match match in matches)
{
var variableName = match.Groups[1].Value;
variables.Add(variableName);
}
return variables.OrderBy(v => v).ToList();
}
#endregion
#region
/// <summary>
/// 获取系统内置变量
/// </summary>
public async Task<Dictionary<string, string>> GetSystemVariablesAsync()
{
var now = DateTime.Now;
var systemVariables = new Dictionary<string, string>
{
["CurrentDateTime"] = now.ToString("yyyy-MM-dd HH:mm:ss"),
["CurrentDate"] = now.ToString("yyyy-MM-dd"),
["CurrentTime"] = now.ToString("HH:mm:ss"),
["CurrentYear"] = now.Year.ToString(),
["CurrentMonth"] = now.Month.ToString(),
["CurrentDay"] = now.Day.ToString(),
["CurrentWeekday"] = GetWeekdayName(now.DayOfWeek),
["SystemName"] = "NPP智能生产调度系统",
["CompanyName"] = "核电站"
};
return await Task.FromResult(systemVariables);
}
/// <summary>
/// 获取业务相关变量
/// </summary>
public async Task<Dictionary<string, string>> GetBusinessVariablesAsync(
string businessType,
long? businessId = null,
string businessData = "")
{
var businessVariables = new Dictionary<string, string>
{
["BusinessType"] = businessType ?? "",
["BusinessId"] = businessId?.ToString() ?? ""
};
// 根据业务类型添加特定变量
switch (businessType?.ToLower())
{
case "workorder":
case "工作任务":
await AddWorkOrderVariablesAsync(businessVariables, businessId, businessData);
break;
case "equipment":
case "设备":
await AddEquipmentVariablesAsync(businessVariables, businessId, businessData);
break;
case "personnel":
case "人员":
await AddPersonnelVariablesAsync(businessVariables, businessId, businessData);
break;
case "maintenance":
case "维护":
await AddMaintenanceVariablesAsync(businessVariables, businessId, businessData);
break;
}
return businessVariables;
}
#endregion
#region
/// <summary>
/// 获取预定义模板列表
/// </summary>
public async Task<List<PredefinedTemplate>> GetPredefinedTemplatesAsync(string category = "")
{
var templates = GetDefaultPredefinedTemplates();
if (!string.IsNullOrWhiteSpace(category))
{
templates = templates.Where(t =>
string.Equals(t.Category, category, StringComparison.OrdinalIgnoreCase)).ToList();
}
return await Task.FromResult(templates);
}
/// <summary>
/// 获取指定预定义模板
/// </summary>
public async Task<PredefinedTemplate> GetPredefinedTemplateAsync(string templateId)
{
var templates = GetDefaultPredefinedTemplates();
var template = templates.FirstOrDefault(t =>
string.Equals(t.TemplateId, templateId, StringComparison.OrdinalIgnoreCase));
return await Task.FromResult(template);
}
#endregion
#region
/// <summary>
/// 验证变量名是否符合规范
/// </summary>
private static bool IsValidVariableName(string variableName)
{
if (string.IsNullOrWhiteSpace(variableName))
return false;
// 变量名只能包含字母、数字和下划线,且不能以数字开头
return Regex.IsMatch(variableName, @"^[a-zA-Z_][a-zA-Z0-9_]*$");
}
/// <summary>
/// 获取星期几的中文名称
/// </summary>
private static string GetWeekdayName(DayOfWeek dayOfWeek)
{
return dayOfWeek switch
{
DayOfWeek.Monday => "星期一",
DayOfWeek.Tuesday => "星期二",
DayOfWeek.Wednesday => "星期三",
DayOfWeek.Thursday => "星期四",
DayOfWeek.Friday => "星期五",
DayOfWeek.Saturday => "星期六",
DayOfWeek.Sunday => "星期日",
_ => ""
};
}
/// <summary>
/// 添加工作任务相关变量
/// </summary>
private async Task AddWorkOrderVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
// 这里可以根据businessId查询工作任务详情然后添加相关变量
// 为了简化示例,先添加一些基础变量
variables["WorkOrderId"] = businessId?.ToString() ?? "";
if (!string.IsNullOrWhiteSpace(businessData))
{
try
{
var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(businessData);
if (data != null)
{
foreach (var item in data)
{
variables[$"WorkOrder_{item.Key}"] = item.Value?.ToString() ?? "";
}
}
}
catch (JsonException)
{
// 忽略JSON解析错误
}
}
await Task.CompletedTask;
}
/// <summary>
/// 添加设备相关变量
/// </summary>
private async Task AddEquipmentVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["EquipmentId"] = businessId?.ToString() ?? "";
// 可以添加更多设备相关变量
await Task.CompletedTask;
}
/// <summary>
/// 添加人员相关变量
/// </summary>
private async Task AddPersonnelVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["PersonnelId"] = businessId?.ToString() ?? "";
// 可以添加更多人员相关变量
await Task.CompletedTask;
}
/// <summary>
/// 添加维护相关变量
/// </summary>
private async Task AddMaintenanceVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["MaintenanceId"] = businessId?.ToString() ?? "";
// 可以添加更多维护相关变量
await Task.CompletedTask;
}
/// <summary>
/// 获取默认预定义模板
/// </summary>
private static List<PredefinedTemplate> GetDefaultPredefinedTemplates()
{
return new List<PredefinedTemplate>
{
new PredefinedTemplate
{
TemplateId = "work_order_assignment",
TemplateName = "工作任务分配通知",
Category = "工作任务",
Description = "当工作任务被分配给人员时发送的通知",
EmailSubjectTemplate = "工作任务分配通知 - {WorkOrderCode}",
EmailContentTemplate = @"
<div>
<h3>工作任务分配通知</h3>
<p>您好,{PersonnelName}</p>
<p>有新的工作任务分配给您:</p>
<ul>
<li>任务代码:{WorkOrderCode}</li>
<li>项目号:{ProjectNumber}</li>
<li>工序名称:{ProcessName}</li>
<li>计划开始时间:{PlannedStartTime}</li>
<li>计划结束时间:{PlannedEndTime}</li>
</ul>
<p>请及时查看并开始执行任务。</p>
<p>系统时间:{CurrentDateTime}</p>
</div>
",
SystemMessageTitleTemplate = "新任务分配 - {WorkOrderCode}",
SystemMessageContentTemplate = "您有新的工作任务:{WorkOrderCode},请及时处理。",
SupportedVariables = new List<TemplateVariable>
{
new TemplateVariable { Name = "PersonnelName", Description = "人员姓名", IsRequired = true },
new TemplateVariable { Name = "WorkOrderCode", Description = "任务代码", IsRequired = true },
new TemplateVariable { Name = "ProjectNumber", Description = "项目号", IsRequired = true },
new TemplateVariable { Name = "ProcessName", Description = "工序名称", IsRequired = true },
new TemplateVariable { Name = "PlannedStartTime", Description = "计划开始时间", IsRequired = true },
new TemplateVariable { Name = "PlannedEndTime", Description = "计划结束时间", IsRequired = true }
}
},
new PredefinedTemplate
{
TemplateId = "equipment_maintenance_reminder",
TemplateName = "设备维护提醒",
Category = "设备维护",
Description = "设备维护到期提醒通知",
EmailSubjectTemplate = "设备维护提醒 - {EquipmentName}",
EmailContentTemplate = @"
<div>
<h3>设备维护提醒</h3>
<p>您好,{PersonnelName}</p>
<p>以下设备需要进行维护:</p>
<ul>
<li>设备名称:{EquipmentName}</li>
<li>设备编号:{EquipmentCode}</li>
<li>计划维护时间:{PlannedMaintenanceTime}</li>
<li>维护类型:{MaintenanceType}</li>
</ul>
<p>请及时安排维护工作。</p>
<p>系统时间:{CurrentDateTime}</p>
</div>
",
SystemMessageTitleTemplate = "设备维护提醒 - {EquipmentName}",
SystemMessageContentTemplate = "设备 {EquipmentName} 需要维护,计划时间:{PlannedMaintenanceTime}",
SupportedVariables = new List<TemplateVariable>
{
new TemplateVariable { Name = "PersonnelName", Description = "人员姓名", IsRequired = true },
new TemplateVariable { Name = "EquipmentName", Description = "设备名称", IsRequired = true },
new TemplateVariable { Name = "EquipmentCode", Description = "设备编号", IsRequired = true },
new TemplateVariable { Name = "PlannedMaintenanceTime", Description = "计划维护时间", IsRequired = true },
new TemplateVariable { Name = "MaintenanceType", Description = "维护类型", IsRequired = false }
}
}
};
}
#endregion
}