paiban/NPP.SmartSchedue.Api/Services/Notification/NotificationTemplateService.cs
Asoka.Wang 2b3f9acdce 123
2025-09-22 19:09:47 +08:00

627 lines
22 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 Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using NPP.SmartSchedue.Api.Contracts.Services.Notification;
using NPP.SmartSchedue.Api.Contracts.Services.Notification.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Notification.Output;
namespace NPP.SmartSchedue.Api.Services.Notification;
/// <summary>
/// 通知服务 模板
/// </summary>
[DynamicApi(Area = "app")]
public class NotificationTemplateService : BaseService, INotificationTemplateService, IDynamicApi
{
// 变量匹配正则表达式:匹配 {变量名} 格式
private static readonly Regex VariableRegex = new Regex(@"\{([a-zA-Z_][a-zA-Z0-9_]*)\}", RegexOptions.Compiled);
#region
/// <summary>
/// 渲染通知模板
/// 支持变量替换,如:{变量名}
/// </summary>
/// <param name="input">渲染模板输入参数</param>
/// <returns>渲染结果</returns>
[HttpPost]
public async Task<RenderTemplateOutput> RenderTemplateAsync(RenderTemplateInput input)
{
try
{
var renderedContent = RenderTemplateCore(input.Template, input.Variables);
return await Task.FromResult(new RenderTemplateOutput
{
RenderedContent = renderedContent,
Success = true
});
}
catch (Exception ex)
{
return new RenderTemplateOutput
{
Success = false,
ErrorMessage = $"渲染模板时发生错误:{ex.Message}"
};
}
}
#endregion
#region
/// <summary>
/// 验证模板语法是否正确
/// </summary>
/// <param name="input">验证模板输入参数</param>
/// <returns>验证结果</returns>
[HttpPost]
public async Task<ValidateTemplateOutput> ValidateTemplateAsync(ValidateTemplateInput input)
{
try
{
var validationResult = ValidateTemplateCore(input.Template);
return await Task.FromResult(new ValidateTemplateOutput
{
ValidationResult = validationResult,
Success = true
});
}
catch (Exception ex)
{
return new ValidateTemplateOutput
{
Success = false,
ErrorMessage = $"验证模板时发生错误:{ex.Message}",
ValidationResult = new TemplateValidationResult()
};
}
}
#endregion
#region
/// <summary>
/// 提取模板中的变量列表
/// </summary>
/// <param name="input">提取变量输入参数</param>
/// <returns>变量列表</returns>
[HttpPost]
public async Task<ExtractVariablesOutput> ExtractVariablesAsync(ExtractVariablesInput input)
{
try
{
var variables = ExtractVariablesCore(input.Template);
return await Task.FromResult(new ExtractVariablesOutput
{
Variables = variables,
Success = true
});
}
catch (Exception ex)
{
return new ExtractVariablesOutput
{
Success = false,
ErrorMessage = $"提取变量时发生错误:{ex.Message}"
};
}
}
#endregion
#region
/// <summary>
/// 获取系统内置变量
/// </summary>
/// <returns>系统变量字典</returns>
[HttpPost]
public async Task<GetSystemVariablesOutput> GetSystemVariablesAsync()
{
try
{
var systemVariables = GetSystemVariablesCore();
return await Task.FromResult(new GetSystemVariablesOutput
{
Variables = systemVariables,
Success = true
});
}
catch (Exception ex)
{
return new GetSystemVariablesOutput
{
Success = false,
ErrorMessage = $"获取系统变量时发生错误:{ex.Message}"
};
}
}
/// <summary>
/// 获取业务相关变量
/// </summary>
/// <param name="input">获取业务变量输入参数</param>
/// <returns>业务变量字典</returns>
[HttpPost]
public async Task<GetBusinessVariablesOutput> GetBusinessVariablesAsync(GetBusinessVariablesInput input)
{
try
{
var businessVariables = await GetBusinessVariablesCore(input.BusinessType, input.BusinessId, input.BusinessData);
return new GetBusinessVariablesOutput
{
Variables = businessVariables,
Success = true
};
}
catch (Exception ex)
{
return new GetBusinessVariablesOutput
{
Success = false,
ErrorMessage = $"获取业务变量时发生错误:{ex.Message}"
};
}
}
#endregion
#region
/// <summary>
/// 获取预定义模板列表
/// </summary>
/// <param name="input">获取模板列表输入参数</param>
/// <returns>预定义模板列表</returns>
[HttpPost]
public async Task<GetPredefinedTemplatesOutput> GetPredefinedTemplatesAsync(GetPredefinedTemplatesInput input)
{
try
{
var templates = GetDefaultPredefinedTemplates();
if (!string.IsNullOrWhiteSpace(input.Category))
{
templates = templates.Where(t =>
string.Equals(t.Category, input.Category, StringComparison.OrdinalIgnoreCase)).ToList();
}
return await Task.FromResult(new GetPredefinedTemplatesOutput
{
Templates = templates,
TotalCount = templates.Count,
Success = true
});
}
catch (Exception ex)
{
return new GetPredefinedTemplatesOutput
{
Success = false,
ErrorMessage = $"获取预定义模板列表时发生错误:{ex.Message}"
};
}
}
/// <summary>
/// 获取指定预定义模板
/// </summary>
/// <param name="input">获取指定模板输入参数</param>
/// <returns>预定义模板</returns>
[HttpPost]
public async Task<GetPredefinedTemplateOutput> GetPredefinedTemplateAsync(GetPredefinedTemplateInput input)
{
try
{
var templates = GetDefaultPredefinedTemplates();
var template = templates.FirstOrDefault(t =>
string.Equals(t.TemplateId, input.TemplateId, StringComparison.OrdinalIgnoreCase));
return await Task.FromResult(new GetPredefinedTemplateOutput
{
Template = template,
Success = true
});
}
catch (Exception ex)
{
return new GetPredefinedTemplateOutput
{
Success = false,
ErrorMessage = $"获取指定预定义模板时发生错误:{ex.Message}"
};
}
}
#endregion
#region
/// <summary>
/// 核心模板渲染逻辑
/// </summary>
/// <param name="template">模板内容</param>
/// <param name="variables">变量字典</param>
/// <returns>渲染后的内容</returns>
private string RenderTemplateCore(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;
}
/// <summary>
/// 核心模板验证逻辑
/// </summary>
/// <param name="template">模板内容</param>
/// <returns>验证结果</returns>
private TemplateValidationResult ValidateTemplateCore(string template)
{
var result = new TemplateValidationResult();
if (string.IsNullOrWhiteSpace(template))
{
result.AddError("模板内容不能为空");
return result;
}
try
{
// 提取所有变量
var variables = ExtractVariablesCore(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;
}
/// <summary>
/// 核心变量提取逻辑
/// </summary>
/// <param name="template">模板内容</param>
/// <returns>变量名列表</returns>
private List<string> ExtractVariablesCore(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();
}
/// <summary>
/// 获取系统内置变量核心逻辑
/// </summary>
/// <returns>系统变量字典</returns>
private Dictionary<string, string> GetSystemVariablesCore()
{
var now = DateTime.Now;
return 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"] = "核电站"
};
}
/// <summary>
/// 获取业务相关变量核心逻辑
/// </summary>
/// <param name="businessType">业务类型</param>
/// <param name="businessId">业务ID</param>
/// <param name="businessData">业务数据</param>
/// <returns>业务变量字典</returns>
private async Task<Dictionary<string, string>> GetBusinessVariablesCore(
string businessType,
long? businessId,
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>
/// <param name="variableName">变量名</param>
/// <returns>是否符合规范</returns>
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>
/// <param name="dayOfWeek">星期枚举</param>
/// <returns>中文名称</returns>
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>
/// <param name="variables">变量字典</param>
/// <param name="businessId">业务ID</param>
/// <param name="businessData">业务数据</param>
/// <returns>异步任务</returns>
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>
/// <param name="variables">变量字典</param>
/// <param name="businessId">业务ID</param>
/// <param name="businessData">业务数据</param>
/// <returns>异步任务</returns>
private async Task AddEquipmentVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["EquipmentId"] = businessId?.ToString() ?? "";
// 可以添加更多设备相关变量
await Task.CompletedTask;
}
/// <summary>
/// 添加人员相关变量
/// </summary>
/// <param name="variables">变量字典</param>
/// <param name="businessId">业务ID</param>
/// <param name="businessData">业务数据</param>
/// <returns>异步任务</returns>
private async Task AddPersonnelVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["PersonnelId"] = businessId?.ToString() ?? "";
// 可以添加更多人员相关变量
await Task.CompletedTask;
}
/// <summary>
/// 添加维护相关变量
/// </summary>
/// <param name="variables">变量字典</param>
/// <param name="businessId">业务ID</param>
/// <param name="businessData">业务数据</param>
/// <returns>异步任务</returns>
private async Task AddMaintenanceVariablesAsync(Dictionary<string, string> variables, long? businessId, string businessData)
{
variables["MaintenanceId"] = businessId?.ToString() ?? "";
// 可以添加更多维护相关变量
await Task.CompletedTask;
}
/// <summary>
/// 获取默认预定义模板
/// </summary>
/// <returns>预定义模板列表</returns>
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
}