166 lines
6.8 KiB
C#
166 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Newtonsoft.Json;
|
|
using XP.Common.Logging.Interfaces;
|
|
using XP.ReportEngine.Interfaces;
|
|
using XP.ReportEngine.Models;
|
|
|
|
namespace XP.ReportEngine.Services
|
|
{
|
|
/// <summary>
|
|
/// JSON 模板引擎实现 | JSON template engine implementation
|
|
/// 负责加载、反序列化和验证 JSON 格式的报告模板
|
|
/// Responsible for loading, deserializing and validating JSON report templates
|
|
/// </summary>
|
|
public class JsonTemplateEngine : ITemplateEngine
|
|
{
|
|
private readonly ILoggerService _logger;
|
|
|
|
/// <summary>
|
|
/// 默认样式定义(当模板引用未定义的样式名称时使用)
|
|
/// Default style definition (used when template references undefined style name)
|
|
/// </summary>
|
|
public static readonly StyleDefinition DefaultStyle = new()
|
|
{
|
|
Font = null,
|
|
Size = 12f,
|
|
Bold = false,
|
|
Italic = false,
|
|
Color = "#000000",
|
|
Align = "left",
|
|
BackgroundColor = null
|
|
};
|
|
|
|
/// <summary>
|
|
/// 构造函数 | Constructor
|
|
/// </summary>
|
|
/// <param name="logger">日志服务 | Logger service</param>
|
|
public JsonTemplateEngine(ILoggerService logger)
|
|
{
|
|
_logger = logger?.ForModule<JsonTemplateEngine>() ?? throw new ArgumentNullException(nameof(logger));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载并反序列化 JSON 模板文件 | Load and deserialize JSON template file
|
|
/// </summary>
|
|
/// <param name="templatePath">模板文件路径 | Template file path</param>
|
|
/// <returns>解析后的模板对象,文件不存在时返回 null | Parsed template object, null if file not found</returns>
|
|
public ReportTemplate LoadTemplate(string templatePath)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(templatePath))
|
|
{
|
|
_logger.Warn("模板文件路径为空 | Template file path is null or empty");
|
|
return null;
|
|
}
|
|
|
|
if (!File.Exists(templatePath))
|
|
{
|
|
_logger.Warn("模板文件未找到: {Path} | Template file not found: {Path}", templatePath);
|
|
return null;
|
|
}
|
|
|
|
_logger.Info("开始加载模板文件: {Path} | Loading template file: {Path}", templatePath);
|
|
|
|
try
|
|
{
|
|
var json = File.ReadAllText(templatePath);
|
|
var template = JsonConvert.DeserializeObject<ReportTemplate>(json);
|
|
|
|
_logger.Info("模板文件加载成功 | Template file loaded successfully");
|
|
return template;
|
|
}
|
|
catch (JsonReaderException ex)
|
|
{
|
|
// JSON 语法错误,包含错误位置信息 | JSON syntax error with position info
|
|
var message = $"模板 JSON 语法错误,行 {ex.LineNumber},位置 {ex.LinePosition}: {ex.Message} | " +
|
|
$"Template JSON syntax error at line {ex.LineNumber}, position {ex.LinePosition}: {ex.Message}";
|
|
_logger.Error(ex, message);
|
|
throw new InvalidOperationException(message, ex);
|
|
}
|
|
catch (JsonSerializationException ex)
|
|
{
|
|
// JSON 反序列化错误 | JSON deserialization error
|
|
var message = $"模板 JSON 反序列化失败: {ex.Message} | Template JSON deserialization failed: {ex.Message}";
|
|
_logger.Error(ex, message);
|
|
throw new InvalidOperationException(message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 验证模板结构完整性 | Validate template structure integrity
|
|
/// 检查 document、pages、styles 必需字段是否存在
|
|
/// Checks if required fields (document, pages, styles) are present
|
|
/// </summary>
|
|
/// <param name="template">待验证的模板 | Template to validate</param>
|
|
/// <returns>验证结果 | Validation result</returns>
|
|
public TemplateValidationResult Validate(ReportTemplate template)
|
|
{
|
|
if (template == null)
|
|
{
|
|
return TemplateValidationResult.Invalid("模板对象为 null | Template object is null");
|
|
}
|
|
|
|
var missingFields = new List<string>();
|
|
|
|
if (template.Document == null)
|
|
{
|
|
missingFields.Add("document");
|
|
}
|
|
|
|
if (template.Pages == null || template.Pages.Count == 0)
|
|
{
|
|
missingFields.Add("pages");
|
|
}
|
|
|
|
if (template.Styles == null)
|
|
{
|
|
missingFields.Add("styles");
|
|
}
|
|
|
|
if (missingFields.Count > 0)
|
|
{
|
|
var fieldList = string.Join(", ", missingFields);
|
|
var message = $"模板缺少必需字段: {fieldList} | Template missing required fields: {fieldList}";
|
|
_logger.Warn(message);
|
|
return TemplateValidationResult.Invalid(message);
|
|
}
|
|
|
|
_logger.Info("模板验证通过 | Template validation passed");
|
|
return TemplateValidationResult.Valid();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 解析样式名称,未定义时回退为默认样式 | Resolve style name, fallback to default if undefined
|
|
/// </summary>
|
|
/// <param name="template">报告模板 | Report template</param>
|
|
/// <param name="styleName">样式名称 | Style name</param>
|
|
/// <returns>解析后的样式定义 | Resolved style definition</returns>
|
|
public StyleDefinition ResolveStyle(ReportTemplate template, string styleName)
|
|
{
|
|
// 样式名称为空时直接返回默认样式 | Return default style if style name is empty
|
|
if (string.IsNullOrWhiteSpace(styleName))
|
|
{
|
|
return DefaultStyle;
|
|
}
|
|
|
|
// 模板或样式字典为空时返回默认样式 | Return default style if template or styles dictionary is null
|
|
if (template?.Styles == null)
|
|
{
|
|
_logger.Warn("模板样式字典为空,使用默认样式: {StyleName} | Template styles dictionary is null, using default style: {StyleName}", styleName);
|
|
return DefaultStyle;
|
|
}
|
|
|
|
// 查找样式,找到则返回,否则回退为默认样式并记录警告
|
|
// Look up style, return if found, otherwise fallback to default and log warning
|
|
if (template.Styles.TryGetValue(styleName, out var style))
|
|
{
|
|
return style;
|
|
}
|
|
|
|
_logger.Warn("未定义的样式名称 '{StyleName}',使用默认样式 | Undefined style name '{StyleName}', using default style", styleName);
|
|
return DefaultStyle;
|
|
}
|
|
}
|
|
}
|