YD_Event.Admin/YD_Event.Core/Certificate/CertificateDocument.cs
2026-03-02 21:09:03 +08:00

121 lines
5.5 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.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();
}
});
}
});
});
}
}
}