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(); } }); } }); }); } } }