报告XP.ReportEngine:新增 IReportService接口封装完整报告生成流程,支持外部类库直接调用;新增 ReportRequest、ReportServiceResult 请求/响应模型;新增引擎预热机制;PDF 生成改为 Task.Run 后台线程执行,解决进度窗口和主窗口卡死问题;完善文档。

This commit is contained in:
QI Mingxuan
2026-05-14 19:29:11 +08:00
parent 11c69d03fb
commit 29bc8576af
13 changed files with 1485 additions and 318 deletions
+18 -2
View File
@@ -85,6 +85,12 @@ namespace XP.ReportEngine.Services
_logger.Info("开始 PDF 渲染,共 {PageCount} 页 | Starting PDF rendering, {PageCount} pages", pages?.Count ?? 0);
_currentTemplate = template;
// 每次渲染重置字体,避免跨 PdfDocument 复用导致 "belongs to other PDF document" 错误
// Reset fonts on each render to avoid cross-PdfDocument reuse error
_fontsInitialized = false;
_cjkFont = null;
_westernFont = null;
var memoryStream = new MemoryStream();
try
@@ -130,6 +136,8 @@ namespace XP.ReportEngine.Services
{
for (int i = 0; i < pages.Count; i++)
{
var pageStopwatch = System.Diagnostics.Stopwatch.StartNew();
if (i > 0)
{
// 添加新页面 | Add new page
@@ -148,6 +156,10 @@ namespace XP.ReportEngine.Services
}
RenderPage(document, pages[i]);
pageStopwatch.Stop();
_logger.Info("第 {PageIndex}/{TotalPages} 页渲染完成,类型: {PageType},元素数: {ElementCount},耗时: {ElapsedMs}ms | Page {PageIndex}/{TotalPages} rendered, type: {PageType}, elements: {ElementCount}, elapsed: {ElapsedMs}ms",
i + 1, pages.Count, pages[i].PageType ?? "unknown", pages[i].Elements?.Count ?? 0, pageStopwatch.ElapsedMilliseconds);
}
}
@@ -157,9 +169,13 @@ namespace XP.ReportEngine.Services
headerFooterHandler.WriteTotal(pdfDocument);
}
// 关闭 Document(它会级联关闭 PdfDocument 和 PdfWriter
// Only close Document (it cascades to PdfDocument and PdfWriter)
// 关闭文档(触发字体子集化嵌入 + PDF 交叉引用表写入 + 流压缩
// Close document (triggers font subsetting + PDF cross-reference table writing + stream compression)
_logger.Info("开始关闭文档(字体嵌入 + 压缩)| Starting document close (font embedding + compression)");
var closeStopwatch = System.Diagnostics.Stopwatch.StartNew();
document.Close();
closeStopwatch.Stop();
_logger.Info("文档关闭完成,耗时: {ElapsedMs}ms | Document close completed, elapsed: {ElapsedMs}ms", closeStopwatch.ElapsedMilliseconds);
// 重置流位置以便后续读取 | Reset stream position for subsequent reading
memoryStream.Position = 0;