121 lines
5.5 KiB
C#
121 lines
5.5 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 动态证书生成文档
|
||
/// </summary>
|
||
public class CertificateDocument : IDocument
|
||
{
|
||
private readonly Entities.Certificate _certificate;
|
||
private readonly Dictionary<string, object> _data;
|
||
private readonly byte[] _templateBytes;
|
||
|
||
public CertificateDocument(Entities.Certificate certificate, Dictionary<string, object> 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<CertificatePlaceholder>()
|
||
: JsonSerializer.Deserialize<List<CertificatePlaceholder>>(_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();
|
||
}
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
}
|
||
}
|