根据文本调整显示位置

This commit is contained in:
马梓彭 2026-05-19 14:37:39 +08:00
parent 8c298544b4
commit e4b416d6fa
2 changed files with 90 additions and 18 deletions

View File

@ -810,7 +810,11 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
ExtractPositionOffset(outerXml, paragraphData);
}
_logger.LogDebug("最终提取的位置 - X: {X}, Y: {Y}", paragraphData.PositionX, paragraphData.PositionY);
// 方法3: 提取文本框宽度
ExtractWidthFromDrawing(outerXml, paragraphData);
_logger.LogDebug("最终提取的位置 - X: {X}, Y: {Y}, Width: {Width}",
paragraphData.PositionX, paragraphData.PositionY, paragraphData.Width);
}
catch (Exception ex)
{
@ -818,6 +822,45 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
}
}
/// <summary>
/// 从 Drawing 对象 XML 中提取宽度信息
/// </summary>
private void ExtractWidthFromDrawing(string xml, ParagraphData paragraphData)
{
try
{
// 方法1: 查找 cx 属性,常见格式 ext cx="3000000"
var cxMatch = System.Text.RegularExpressions.Regex.Match(xml, @"<wp:ext[^>]*?cx=[""'](\d+)[""']");
if (cxMatch.Success)
{
if (long.TryParse(cxMatch.Groups[1].Value, out long cx))
{
paragraphData.Width = EmuToPoints(cx);
_logger.LogDebug("提取到宽度 (EMU): {EMU}, (点): {Points}", cx, paragraphData.Width);
return;
}
}
// 方法2: 查找 extents cx 属性
var extentsCxMatch = System.Text.RegularExpressions.Regex.Match(xml, @"extents\s*=\s*[\""'](?:\d+)\s*,\s*(\d+)[""']");
if (extentsCxMatch.Success)
{
if (long.TryParse(extentsCxMatch.Groups[1].Value, out long cx))
{
paragraphData.Width = EmuToPoints(cx);
_logger.LogDebug("提取到 extents 宽度 (EMU): {EMU}, (点): {Points}", cx, paragraphData.Width);
return;
}
}
_logger.LogDebug("未找到宽度信息,使用默认值");
}
catch (Exception ex)
{
_logger.LogError(ex, "提取宽度信息失败");
}
}
/// <summary>
/// 从 XML 中提取 simplePos 属性
/// </summary>
@ -1070,7 +1113,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
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}");
_logger.LogInformation($" [{i}] 文本: {p.Text}, X: {p.PositionX}, Y: {p.PositionY}, Width: {p.Width}, 字号: {p.FontSize}, 对齐: {p.Alignment}");
}
var questDocument = QuestPDF.Fluent.Document.Create(container =>
@ -1095,8 +1138,8 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
.FitArea();
}
// 最简单且工作的方案:使用正常的 Column 布局
// 但通过跟踪和补偿累积高度来定位所有文本
// 解决方案:保持文本框位置不变,在固定宽度容器内对齐
// 这样文本是在文本框内部对齐,而不是移动文本框位置
float cumulativeHeight = 0;
page.Content().Column(column =>
@ -1107,35 +1150,58 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
{
var fontSize = paragraph.FontSize ?? 14;
var isBold = paragraph.IsBold;
var text = paragraph.Text;
// X偏移+80保持不变
// Y坐标减去之前所有文本占用的高度进行补偿
float x = (float)(paragraph.PositionX ?? 50) + 90;
float baseX = (float)(paragraph.PositionX ?? 50) + 90;
float y = (float)(paragraph.PositionY ?? 50) + 75 - cumulativeHeight;
// 使用从 Word 中提取到的文本框宽度,如未提取到则使用默认值 300
float textBoxWidth = (float)(paragraph.Width ?? 300);
_logger.LogInformation($"放置文本框: 文本={text}, baseX={baseX}, Y={y}, width={textBoxWidth}, alignment={paragraph.Alignment}");
_logger.LogInformation($"放置文本框: 文本={paragraph.Text}, X={x}, Y={y}, cumulativeHeight={cumulativeHeight}");
// 正常添加文本,不限制高度
var element = column.Item()
.TranslateX(x)
// 创建元素并根据对齐方式设置
var item = column.Item()
.TranslateX(baseX)
.TranslateY(y)
.Text(paragraph.Text)
.Width(textBoxWidth);
// 创建对齐的文本元素
QuestPDF.Infrastructure.IContainer alignedContainer;
switch (paragraph.Alignment?.ToLower())
{
case "center":
alignedContainer = item.AlignCenter();
break;
case "right":
alignedContainer = item.AlignRight();
break;
case "left":
case "justify":
default:
alignedContainer = item.AlignLeft();
break;
}
// 添加文本并设置样式
var textElement = alignedContainer
.Text(text)
.FontSize((float)fontSize)
.FontColor(Colors.Black)
.AlignLeft();
.FontColor(Colors.Black);
if (!string.IsNullOrEmpty(selectedFont))
{
element = element.FontFamily(selectedFont);
textElement = textElement.FontFamily(selectedFont);
}
if (isBold)
{
element = element.Bold();
textElement = textElement.Bold();
}
// 估算当前文本行的高度并累积
// 通常一行文本高度大约是 font-size * 1.5
cumulativeHeight += (float)(fontSize * 1.5f);
}
});
@ -1418,6 +1484,7 @@ public class ParagraphData
public string Style { get; set; } = "normal"; // normal, heading, subheading
public double? PositionX { get; set; } = null;
public double? PositionY { get; set; } = null;
public double? Width { get; set; } = null; // 文本框宽度
public double? FontSize { get; set; } = null;
public string Alignment { get; set; } = "left"; // left, center, right
public bool IsBold { get; set; } = false;

View File

@ -911,6 +911,11 @@
从 Drawing 对象中提取位置信息
</summary>
</member>
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractWidthFromDrawing(System.String,YD_Event.Application.Certificate.ParagraphData)">
<summary>
从 Drawing 对象 XML 中提取宽度信息
</summary>
</member>
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractSimplePosition(System.String,YD_Event.Application.Certificate.ParagraphData)">
<summary>
从 XML 中提取 simplePos 属性