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; /// /// 通知模板服务实现 /// 决策点7:模板通知,支持通知内容模板,可替换变量 /// 使用简单的变量替换机制:{变量名} /// public class NotificationTemplateService : INotificationTemplateService { // 变量匹配正则表达式:匹配 {变量名} 格式 private static readonly Regex VariableRegex = new Regex(@"\{([a-zA-Z_][a-zA-Z0-9_]*)\}", RegexOptions.Compiled); #region 模板渲染 /// /// 渲染通知模板 /// public async Task RenderTemplateAsync(string template, Dictionary variables) { return await Task.FromResult(RenderTemplate(template, variables)); } /// /// 同步渲染通知模板 /// public string RenderTemplate(string template, Dictionary 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 模板验证 /// /// 验证模板语法 /// public async Task ValidateTemplateAsync(string template) { return await Task.FromResult(ValidateTemplate(template)); } /// /// 同步验证模板语法 /// 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 变量解析 /// /// 提取模板中的变量列表 /// public async Task> ExtractVariablesAsync(string template) { return await Task.FromResult(ExtractVariables(template)); } /// /// 同步提取模板中的变量列表 /// public List ExtractVariables(string template) { if (string.IsNullOrWhiteSpace(template)) return new List(); var variables = new HashSet(); 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 内置变量 /// /// 获取系统内置变量 /// public async Task> GetSystemVariablesAsync() { var now = DateTime.Now; var systemVariables = new Dictionary { ["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); } /// /// 获取业务相关变量 /// public async Task> GetBusinessVariablesAsync( string businessType, long? businessId = null, string businessData = "") { var businessVariables = new Dictionary { ["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 模板预定义 /// /// 获取预定义模板列表 /// public async Task> 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); } /// /// 获取指定预定义模板 /// public async Task 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 私有辅助方法 /// /// 验证变量名是否符合规范 /// private static bool IsValidVariableName(string variableName) { if (string.IsNullOrWhiteSpace(variableName)) return false; // 变量名只能包含字母、数字和下划线,且不能以数字开头 return Regex.IsMatch(variableName, @"^[a-zA-Z_][a-zA-Z0-9_]*$"); } /// /// 获取星期几的中文名称 /// private static string GetWeekdayName(DayOfWeek dayOfWeek) { return dayOfWeek switch { DayOfWeek.Monday => "星期一", DayOfWeek.Tuesday => "星期二", DayOfWeek.Wednesday => "星期三", DayOfWeek.Thursday => "星期四", DayOfWeek.Friday => "星期五", DayOfWeek.Saturday => "星期六", DayOfWeek.Sunday => "星期日", _ => "" }; } /// /// 添加工作任务相关变量 /// private async Task AddWorkOrderVariablesAsync(Dictionary variables, long? businessId, string businessData) { // 这里可以根据businessId查询工作任务详情,然后添加相关变量 // 为了简化示例,先添加一些基础变量 variables["WorkOrderId"] = businessId?.ToString() ?? ""; if (!string.IsNullOrWhiteSpace(businessData)) { try { var data = JsonConvert.DeserializeObject>(businessData); if (data != null) { foreach (var item in data) { variables[$"WorkOrder_{item.Key}"] = item.Value?.ToString() ?? ""; } } } catch (JsonException) { // 忽略JSON解析错误 } } await Task.CompletedTask; } /// /// 添加设备相关变量 /// private async Task AddEquipmentVariablesAsync(Dictionary variables, long? businessId, string businessData) { variables["EquipmentId"] = businessId?.ToString() ?? ""; // 可以添加更多设备相关变量 await Task.CompletedTask; } /// /// 添加人员相关变量 /// private async Task AddPersonnelVariablesAsync(Dictionary variables, long? businessId, string businessData) { variables["PersonnelId"] = businessId?.ToString() ?? ""; // 可以添加更多人员相关变量 await Task.CompletedTask; } /// /// 添加维护相关变量 /// private async Task AddMaintenanceVariablesAsync(Dictionary variables, long? businessId, string businessData) { variables["MaintenanceId"] = businessId?.ToString() ?? ""; // 可以添加更多维护相关变量 await Task.CompletedTask; } /// /// 获取默认预定义模板 /// private static List GetDefaultPredefinedTemplates() { return new List { new PredefinedTemplate { TemplateId = "work_order_assignment", TemplateName = "工作任务分配通知", Category = "工作任务", Description = "当工作任务被分配给人员时发送的通知", EmailSubjectTemplate = "工作任务分配通知 - {WorkOrderCode}", EmailContentTemplate = @"

工作任务分配通知

您好,{PersonnelName}!

有新的工作任务分配给您:

  • 任务代码:{WorkOrderCode}
  • 项目号:{ProjectNumber}
  • 工序名称:{ProcessName}
  • 计划开始时间:{PlannedStartTime}
  • 计划结束时间:{PlannedEndTime}

请及时查看并开始执行任务。

系统时间:{CurrentDateTime}

", SystemMessageTitleTemplate = "新任务分配 - {WorkOrderCode}", SystemMessageContentTemplate = "您有新的工作任务:{WorkOrderCode},请及时处理。", SupportedVariables = new List { 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 = @"

设备维护提醒

您好,{PersonnelName}!

以下设备需要进行维护:

  • 设备名称:{EquipmentName}
  • 设备编号:{EquipmentCode}
  • 计划维护时间:{PlannedMaintenanceTime}
  • 维护类型:{MaintenanceType}

请及时安排维护工作。

系统时间:{CurrentDateTime}

", SystemMessageTitleTemplate = "设备维护提醒 - {EquipmentName}", SystemMessageContentTemplate = "设备 {EquipmentName} 需要维护,计划时间:{PlannedMaintenanceTime}", SupportedVariables = new List { 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 }