修复证书生成问题
This commit is contained in:
parent
f823dfb7eb
commit
8c298544b4
@ -295,7 +295,15 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
|
|
||||||
// 生成PDF
|
// 生成PDF
|
||||||
var pdfStream = new MemoryStream();
|
var pdfStream = new MemoryStream();
|
||||||
await GeneratePdfWithQuestPDF(pdfStream, documentData);
|
try
|
||||||
|
{
|
||||||
|
await GeneratePdfWithQuestPDF(pdfStream, documentData);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var a = 1;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
pdfStream.Position = 0;
|
pdfStream.Position = 0;
|
||||||
_logger.LogInformation("DOCX转PDF完成,PDF大小: {Size} bytes", pdfStream.Length);
|
_logger.LogInformation("DOCX转PDF完成,PDF大小: {Size} bytes", pdfStream.Length);
|
||||||
@ -793,8 +801,8 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
var outerXml = drawing.OuterXml;
|
var outerXml = drawing.OuterXml;
|
||||||
_logger.LogDebug("Drawing 对象原始 XML (前800字符): {Xml}", outerXml.Substring(0, Math.Min(800, outerXml.Length)));
|
_logger.LogDebug("Drawing 对象原始 XML (前800字符): {Xml}", outerXml.Substring(0, Math.Min(800, outerXml.Length)));
|
||||||
|
|
||||||
// 方法1: 查找 simplePos 属性(通常用于绝对定位)
|
// 方法1: 先查找 simplePos 属性(通常用于绝对定位)
|
||||||
// ExtractSimplePosition(outerXml, paragraphData);
|
ExtractSimplePosition(outerXml, paragraphData);
|
||||||
|
|
||||||
// 方法2: 如果 simplePos 没有值,查找 positionOffset 元素
|
// 方法2: 如果 simplePos 没有值,查找 positionOffset 元素
|
||||||
if (paragraphData.PositionX == null || paragraphData.PositionY == null)
|
if (paragraphData.PositionX == null || paragraphData.PositionY == null)
|
||||||
@ -802,12 +810,6 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
ExtractPositionOffset(outerXml, paragraphData);
|
ExtractPositionOffset(outerXml, paragraphData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注意:不使用 distL, distT 等距离属性
|
|
||||||
// 这些属性不是文本框在页面上的坐标,而是:
|
|
||||||
// - 要么是文本框的内边距(文本到边框的距离)
|
|
||||||
// - 要么是文本框到页面边距的距离(而不是绝对坐标)
|
|
||||||
// 我们目前使用写死定位方式,不需要依赖这些值
|
|
||||||
|
|
||||||
_logger.LogDebug("最终提取的位置 - X: {X}, Y: {Y}", paragraphData.PositionX, paragraphData.PositionY);
|
_logger.LogDebug("最终提取的位置 - X: {X}, Y: {Y}", paragraphData.PositionX, paragraphData.PositionY);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -1063,6 +1065,14 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
var selectedFont = CertificateFontHelper.GetSelectedFont();
|
var selectedFont = CertificateFontHelper.GetSelectedFont();
|
||||||
_logger.LogInformation($"使用字体: {selectedFont ?? "默认字体"}");
|
_logger.LogInformation($"使用字体: {selectedFont ?? "默认字体"}");
|
||||||
|
|
||||||
|
// 记录提取到的位置信息,便于调试
|
||||||
|
_logger.LogInformation($"提取到 {documentData.Paragraphs.Count} 个文本框:");
|
||||||
|
for (int i = 0; i < documentData.Paragraphs.Count; i++)
|
||||||
|
{
|
||||||
|
var p = documentData.Paragraphs[i];
|
||||||
|
_logger.LogInformation($" [{i}] 文本: {p.Text}, X: {p.PositionX}, Y: {p.PositionY}, 字号: {p.FontSize}");
|
||||||
|
}
|
||||||
|
|
||||||
var questDocument = QuestPDF.Fluent.Document.Create(container =>
|
var questDocument = QuestPDF.Fluent.Document.Create(container =>
|
||||||
{
|
{
|
||||||
container.Page(page =>
|
container.Page(page =>
|
||||||
@ -1084,62 +1094,52 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
.Image(documentData.BackgroundImage)
|
.Image(documentData.BackgroundImage)
|
||||||
.FitArea();
|
.FitArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 最简单且工作的方案:使用正常的 Column 布局
|
||||||
|
// 但通过跟踪和补偿累积高度来定位所有文本
|
||||||
|
float cumulativeHeight = 0;
|
||||||
|
|
||||||
// 使用 Column 来放置所有内容
|
|
||||||
page.Content().Column(column =>
|
page.Content().Column(column =>
|
||||||
{
|
{
|
||||||
column.Spacing(0);
|
column.Spacing(0);
|
||||||
|
|
||||||
double? firstParagraphY = null;
|
foreach (var paragraph in documentData.Paragraphs)
|
||||||
double? firstParagraphOriginalY = null;
|
|
||||||
|
|
||||||
// 根据文本框数量确定X轴偏移量
|
|
||||||
float xOffset = documentData.Paragraphs.Count == 1 ? 140 : 100;
|
|
||||||
|
|
||||||
// 根据段落信息进行定位
|
|
||||||
for (int i = 0; i < documentData.Paragraphs.Count; i++)
|
|
||||||
{
|
{
|
||||||
var paragraph = documentData.Paragraphs[i];
|
|
||||||
var fontSize = paragraph.FontSize ?? 14;
|
var fontSize = paragraph.FontSize ?? 14;
|
||||||
var isBold = paragraph.IsBold;
|
var isBold = paragraph.IsBold;
|
||||||
|
|
||||||
// 计算位置
|
// X偏移+80保持不变
|
||||||
float x = (float)(paragraph.PositionX ?? 50) + xOffset;
|
// Y坐标减去之前所有文本占用的高度进行补偿
|
||||||
float y;
|
float x = (float)(paragraph.PositionX ?? 50) + 90;
|
||||||
|
float y = (float)(paragraph.PositionY ?? 50) + 75 - cumulativeHeight;
|
||||||
if (i == 0)
|
|
||||||
{
|
_logger.LogInformation($"放置文本框: 文本={paragraph.Text}, X={x}, Y={y}, cumulativeHeight={cumulativeHeight}");
|
||||||
firstParagraphY = paragraph.PositionY ?? 50;
|
|
||||||
firstParagraphOriginalY = firstParagraphY.Value;
|
// 正常添加文本,不限制高度
|
||||||
y = (float)firstParagraphY + 70;
|
var element = column.Item()
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
y = (float)(firstParagraphOriginalY + 70) + (i * 45);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建文本元素
|
|
||||||
var textElement = column.Item()
|
|
||||||
.TranslateX(x)
|
.TranslateX(x)
|
||||||
.TranslateY(y)
|
.TranslateY(y)
|
||||||
.Text(paragraph.Text)
|
.Text(paragraph.Text)
|
||||||
.FontSize((float)fontSize)
|
.FontSize((float)fontSize)
|
||||||
.FontColor(QuestPDF.Helpers.Colors.Black)
|
.FontColor(Colors.Black)
|
||||||
.AlignLeft();
|
.AlignLeft();
|
||||||
|
|
||||||
// 应用字体
|
|
||||||
if (!string.IsNullOrEmpty(selectedFont))
|
if (!string.IsNullOrEmpty(selectedFont))
|
||||||
{
|
{
|
||||||
textElement = textElement.FontFamily(selectedFont);
|
element = element.FontFamily(selectedFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBold)
|
if (isBold)
|
||||||
{
|
{
|
||||||
textElement = textElement.Bold();
|
element = element.Bold();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 估算当前文本行的高度并累积
|
||||||
|
// 通常一行文本高度大约是 font-size * 1.5
|
||||||
|
cumulativeHeight += (float)(fontSize * 1.5f);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 添加二维码到右下角
|
// 添加二维码到右下角
|
||||||
if (documentData.QRCodeImage != null)
|
if (documentData.QRCodeImage != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -287,7 +287,6 @@ public class PointsRecordService : BaseService<PointsRecord>, ITransient
|
|||||||
Action = e.EventName,
|
Action = e.EventName,
|
||||||
Item = pr.Name,
|
Item = pr.Name,
|
||||||
ProjectId = pr.Id,
|
ProjectId = pr.Id,
|
||||||
ProjectType = pr.ProjectType,
|
|
||||||
Group = er.GroupName,
|
Group = er.GroupName,
|
||||||
Points = p.Points,
|
Points = p.Points,
|
||||||
Remark = p.Remark,
|
Remark = p.Remark,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user