报告ReportEngineBase增加页眉页脚,修改因模板变动和分栏、边距等需要修改的函数代码。
This commit is contained in:
@@ -14,7 +14,8 @@ namespace XP.ReportEngine.Interfaces
|
||||
/// </summary>
|
||||
/// <param name="pages">排版后的页面列表 | Laid-out pages</param>
|
||||
/// <param name="options">生成选项 | Generation options</param>
|
||||
/// <param name="template">绑定后的模板(用于页眉页脚配置)| Bound template (for header/footer config)</param>
|
||||
/// <returns>PDF 内存流 | PDF memory stream</returns>
|
||||
MemoryStream Render(List<LayoutPage> pages, ReportGenerationOptions options);
|
||||
MemoryStream Render(List<LayoutPage> pages, ReportGenerationOptions options, ReportTemplate template = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,13 @@ namespace XP.ReportEngine.Models
|
||||
public class LayoutPage
|
||||
{
|
||||
public int PageNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 页面类型(来自模板定义:homepage / metricData / bgaInspection 等)
|
||||
/// Page type from template definition
|
||||
/// </summary>
|
||||
public string PageType { get; set; }
|
||||
|
||||
public List<LayoutElement> Elements { get; set; } = new();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,16 @@ namespace XP.ReportEngine.Models
|
||||
public string PageSize { get; set; } = "A4";
|
||||
public string Orientation { get; set; } = "Portrait";
|
||||
public MarginSettings Margins { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 页眉配置(仅内容页显示,首页不显示)| Header config (content pages only, not homepage)
|
||||
/// </summary>
|
||||
public HeaderFooterSettings Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 页脚配置(仅内容页显示,首页不显示)| Footer config (content pages only, not homepage)
|
||||
/// </summary>
|
||||
public HeaderFooterSettings Footer { get; set; }
|
||||
}
|
||||
|
||||
public class MarginSettings
|
||||
@@ -27,6 +37,52 @@ namespace XP.ReportEngine.Models
|
||||
public float Right { get; set; } = 20f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 页眉/页脚配置 | Header/Footer settings
|
||||
/// </summary>
|
||||
public class HeaderFooterSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用 | Whether enabled
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 左侧文本行(支持 ${} 绑定表达式)| Left-side text lines with binding expressions
|
||||
/// </summary>
|
||||
public List<string> Left { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 右侧文本行(支持 ${} 绑定表达式)| Right-side text lines with binding expressions
|
||||
/// </summary>
|
||||
public List<string> Right { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 右侧图像 dataKey(如 logo)| Right-side image dataKey (e.g. logo)
|
||||
/// </summary>
|
||||
public string RightImageKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左侧图像 dataKey | Left-side image dataKey
|
||||
/// </summary>
|
||||
public string LeftImageKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字体大小 | Font size
|
||||
/// </summary>
|
||||
public float FontSize { get; set; } = 8f;
|
||||
|
||||
/// <summary>
|
||||
/// 字体颜色 | Font color
|
||||
/// </summary>
|
||||
public string Color { get; set; } = "#666666";
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示分隔线 | Whether to show separator line
|
||||
/// </summary>
|
||||
public bool ShowLine { get; set; } = true;
|
||||
}
|
||||
|
||||
public class TemplatePage
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace XP.ReportEngine.Models
|
||||
public class TemplateElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 元素类型:text / image / table / divider / grid
|
||||
/// 元素类型:text / image / table / divider / spacer / row / grid
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
|
||||
@@ -49,6 +49,31 @@ namespace XP.ReportEngine.Models
|
||||
/// </summary>
|
||||
public string Positioning { get; set; } = "absolute";
|
||||
|
||||
/// <summary>
|
||||
/// 子元素列表(用于 row 类型的水平布局容器)
|
||||
/// Child elements (for row type horizontal layout container)
|
||||
/// </summary>
|
||||
public List<TemplateElement> Children { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 水平对齐方式(用于 row 子元素):left / center / right
|
||||
/// Horizontal alignment for row children
|
||||
/// </summary>
|
||||
public string Align { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列宽比例数组(用于 row 类型,如 [7, 3] 表示 7:3 比例)
|
||||
/// Column width ratios for row type (e.g. [7, 3] means 7:3 ratio)
|
||||
/// </summary>
|
||||
public float[] Widths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 条件颜色规则(用于 text 元素,根据内容中包含的关键词匹配颜色)
|
||||
/// Conditional color rules for text elements (match keywords in content to color)
|
||||
/// 格式:{ "Pass": "#008000", "Fail": "#FF0000" }
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ColorRules { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 表格数据行(数据绑定阶段填充,用于排版计算和渲染)
|
||||
/// Table data rows (populated during data binding phase, used for layout calculation and rendering)
|
||||
@@ -69,6 +94,13 @@ namespace XP.ReportEngine.Models
|
||||
public string Field { get; set; }
|
||||
public float Width { get; set; }
|
||||
public string Align { get; set; } = "left";
|
||||
|
||||
/// <summary>
|
||||
/// 条件颜色规则(根据单元格值匹配颜色)
|
||||
/// Conditional color rules (match cell value to color)
|
||||
/// 格式:{ "Pass": "#008000", "Fail": "#FF0000" }
|
||||
/// </summary>
|
||||
public Dictionary<string, string> ColorRules { get; set; }
|
||||
}
|
||||
|
||||
public class StyleDefinition
|
||||
@@ -80,5 +112,26 @@ namespace XP.ReportEngine.Models
|
||||
public string Color { get; set; } = "#000000";
|
||||
public string Align { get; set; } = "left";
|
||||
public string BackgroundColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上边距(mm)| Top margin in mm
|
||||
/// </summary>
|
||||
public float MarginTop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下边距(mm)| Bottom margin in mm
|
||||
/// </summary>
|
||||
public float MarginBottom { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左缩进(mm)| Left indent/padding in mm
|
||||
/// </summary>
|
||||
public float PaddingLeft { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 行高倍数(1.0 = 单倍行距,1.5 = 1.5倍行距,0 表示使用默认)
|
||||
/// Line height multiplier (1.0 = single spacing, 1.5 = 1.5x spacing, 0 = use default)
|
||||
/// </summary>
|
||||
public float LineHeight { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ namespace XP.ReportEngine.Services
|
||||
var currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = templatePage.Type,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
@@ -107,13 +108,28 @@ namespace XP.ReportEngine.Services
|
||||
var elementHeight = CalculateElementHeight(element);
|
||||
var elementWidth = CalculateElementWidth(element, availableWidth);
|
||||
|
||||
// 强制分页元素 | Forced page break element
|
||||
if (string.Equals(element.Type, "pagebreak", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
currentPageNumber++;
|
||||
currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = templatePage.Type,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
currentY = margins.Top;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否需要分页 | Check if pagination is needed
|
||||
if (element.Type == "table" && element.Columns != null)
|
||||
{
|
||||
// 表格跨页拆分逻辑 | Table page-split logic
|
||||
currentY = ProcessTableWithPageSplit(
|
||||
element, template, margins, availableHeight, availableWidth,
|
||||
currentY, pages, ref currentPage, ref currentPageNumber);
|
||||
currentY, pages, ref currentPage, ref currentPageNumber, templatePage.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,6 +141,7 @@ namespace XP.ReportEngine.Services
|
||||
currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = templatePage.Type,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
@@ -240,7 +257,7 @@ namespace XP.ReportEngine.Services
|
||||
TemplateElement element, ReportTemplate template, MarginSettings margins,
|
||||
float availableHeight, float availableWidth,
|
||||
float currentY, List<LayoutPage> pages,
|
||||
ref LayoutPage currentPage, ref int currentPageNumber)
|
||||
ref LayoutPage currentPage, ref int currentPageNumber, string pageType)
|
||||
{
|
||||
var resolvedStyle = _templateEngine.ResolveStyle(template, element.Style);
|
||||
var tableWidth = element.Size != null && element.Size.Length > 0 ? element.Size[0] : availableWidth;
|
||||
@@ -262,6 +279,7 @@ namespace XP.ReportEngine.Services
|
||||
currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = pageType,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
@@ -324,6 +342,7 @@ namespace XP.ReportEngine.Services
|
||||
currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = pageType,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
@@ -359,6 +378,7 @@ namespace XP.ReportEngine.Services
|
||||
currentPage = new LayoutPage
|
||||
{
|
||||
PageNumber = currentPageNumber,
|
||||
PageType = pageType,
|
||||
Elements = new List<LayoutElement>()
|
||||
};
|
||||
pages.Add(currentPage);
|
||||
@@ -423,6 +443,9 @@ namespace XP.ReportEngine.Services
|
||||
{
|
||||
"text" => DefaultTextHeight,
|
||||
"divider" => DefaultDividerHeight,
|
||||
"spacer" => element.Size is { Length: >= 2 } ? element.Size[1] : DefaultTextHeight,
|
||||
"row" => CalculateRowHeight(element),
|
||||
"pagebreak" => 0f,
|
||||
"image" => DefaultTextHeight,
|
||||
"table" => CalculateTableHeight(element),
|
||||
_ => DefaultTextHeight
|
||||
@@ -442,6 +465,36 @@ namespace XP.ReportEngine.Services
|
||||
return DefaultRowHeight + (dataRowCount * DefaultRowHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算 Row 容器高度 | Calculate row container height
|
||||
/// 取子元素中最大高度,如果有 Size 定义则优先使用
|
||||
/// Uses max child height, or Size definition if available
|
||||
/// </summary>
|
||||
private float CalculateRowHeight(TemplateElement element)
|
||||
{
|
||||
// 如果 row 本身有 Size[1] 定义,直接使用 | If row has Size[1], use it directly
|
||||
if (element.Size != null && element.Size.Length > 1 && element.Size[1] > 0)
|
||||
{
|
||||
return element.Size[1];
|
||||
}
|
||||
|
||||
// 否则取子元素中最大高度 | Otherwise use max child height
|
||||
if (element.Children == null || element.Children.Count == 0)
|
||||
return DefaultTextHeight;
|
||||
|
||||
float maxHeight = 0;
|
||||
foreach (var child in element.Children)
|
||||
{
|
||||
float childHeight = DefaultTextHeight;
|
||||
if (child.Size != null && child.Size.Length > 1 && child.Size[1] > 0)
|
||||
{
|
||||
childHeight = child.Size[1];
|
||||
}
|
||||
if (childHeight > maxHeight) maxHeight = childHeight;
|
||||
}
|
||||
return maxHeight > 0 ? maxHeight : DefaultTextHeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算元素宽度 | Calculate element width
|
||||
/// </summary>
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace XP.ReportEngine.Services
|
||||
|
||||
// 阶段 4:PDF 渲染 | Phase 4: PDF rendering
|
||||
_logger.Info("阶段 4:PDF 渲染 | Phase 4: PDF rendering");
|
||||
var stream = _pdfRenderer.Render(pages, options);
|
||||
var stream = _pdfRenderer.Render(pages, options, boundTemplate);
|
||||
_logger.Info("阶段 4 完成:PDF 渲染成功 | Phase 4 completed: PDF rendering successful");
|
||||
|
||||
// 阶段 5:保存文件(可选)| Phase 5: Save file (optional)
|
||||
|
||||
Reference in New Issue
Block a user