using System;
using System.Collections.Generic;
using System.Linq;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using YD_Event.Core.Entities;
using System.Text.Json;
namespace YD_Event.Core.Certificate
{
///
/// 动态证书生成文档
///
public class CertificateDocument : IDocument
{
private readonly Entities.Certificate _certificate;
private readonly Dictionary _data;
private readonly byte[] _templateBytes;
public CertificateDocument(Entities.Certificate certificate, Dictionary data, byte[] templateBytes)
{
_certificate = certificate;
_data = data;
_templateBytes = templateBytes;
}
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
// 设置页面大小
page.Size(new PageSize((float)_certificate.Width, (float)_certificate.Height));
page.Margin(0); // 无边距,背景铺满
page.DefaultTextStyle(x => x.FontFamily("Source Han Sans CN")); // 默认字体
// 设置背景
page.Background().Image(_templateBytes);
// 内容层
page.Content().Layers(layers =>
{
// 解析占位符配置
var placeholders = string.IsNullOrEmpty(_certificate.Placeholders)
? new List()
: JsonSerializer.Deserialize>(_certificate.Placeholders);
foreach (var p in placeholders)
{
// 获取数据对象
var dataObj = _data.ContainsKey(p.Key) ? _data[p.Key] : null;
if (dataObj == null) continue;
// 定位层
layers.Layer()
.TranslateX(p.X)
.TranslateY(p.Y)
.Width(p.Width)
.Height(p.Height)
.Element(element =>
{
if (p.Type == "Image")
{
if (dataObj is byte[] imgBytes)
{
element.Image(imgBytes);
}
else if (dataObj is string url && !string.IsNullOrEmpty(url))
{
// 暂不支持直接URL渲染,需预先下载转为byte[]
element.Border(1).BorderColor(Colors.Red.Medium).AlignCenter().AlignMiddle().Text($"Image: {p.Key}");
}
}
else if (p.Type == "QRCode")
{
// 暂无二维码生成库,显示占位符
// 实际项目建议引入 QRCoder 或类似库生成 byte[] 后渲染
element.Border(1).BorderColor(Colors.Black).AlignCenter().AlignMiddle().Text("QR Code");
}
else
{
// 文本处理
string value = dataObj.ToString();
// 处理日期格式化
if (!string.IsNullOrEmpty(p.FormatString))
{
if (dataObj is DateTime dt)
{
value = dt.ToString(p.FormatString);
}
else if (DateTime.TryParse(value, out var dtParsed))
{
value = dtParsed.ToString(p.FormatString);
}
}
var text = element.Text(value);
// 样式设置
var style = TextStyle.Default.FontSize(p.FontSize > 0 ? p.FontSize : 12);
if (!string.IsNullOrEmpty(p.FontFamily)) style = style.FontFamily(p.FontFamily);
if (!string.IsNullOrEmpty(p.Color)) style = style.FontColor(p.Color);
text.Style(style);
// 对齐方式
if (p.TextAlign == "Center") element.AlignCenter();
else if (p.TextAlign == "Right") element.AlignRight();
else element.AlignLeft();
}
});
}
});
});
}
}
}