From 26a25c1410be077b32145a9ac0191a32763de881 Mon Sep 17 00:00:00 2001 From: gaofei1985 <181547018@qq.com> Date: Wed, 24 Jun 2026 15:54:24 +0800 Subject: [PATCH] 1 --- .gitignore | 1 + HJGL_DS/BLL/Common/FastReportService.cs | 210 ++++++++++++++---- HJGL_DS/FineUIPro.Web/Global.asax.cs | 1 + .../WeldMat/UsingSentMat/UsingMatCheck.aspx | 55 ++++- .../UsingSentMat/UsingMatCheck.aspx.cs | 7 +- 5 files changed, 220 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index 63094fa..5aa11bb 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ bin-release/ /CreateModel2017.bat *.xls /HJGL_DS/FineUIPro.Web/File/PDF/Pipe +/HJGL_DS/FineUIPro.Web/File/Fastreport/Temp diff --git a/HJGL_DS/BLL/Common/FastReportService.cs b/HJGL_DS/BLL/Common/FastReportService.cs index 8256bba..8bd5b05 100644 --- a/HJGL_DS/BLL/Common/FastReportService.cs +++ b/HJGL_DS/BLL/Common/FastReportService.cs @@ -8,78 +8,195 @@ using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Security; +using System.Timers; +using System; +using FastReport.Export.Pdf; +using System.IO; namespace BLL.Common { public static class FastReportService { + private static Timer tempReportCleanupTimer; // 缓存过期时间:30分钟 private static readonly int CacheExpirationMinutes = 5; /// - /// 重置数据 - 清理缓存和Session + /// 重置数据 /// public static void ResetData() { - if (HttpContext.Current?.Session == null) + HttpContext.Current.Session["ReportDataTables"] = null; + HttpContext.Current.Session["ReportParameterValues"] = null; + } + public static void AddFastreportTable(DataTable dataTable) + { + List dataTables = (List)HttpContext.Current.Session["ReportDataTables"]; + if (dataTables == null) { - return; + dataTables = new List(); + } + dataTables.Add(dataTable); + + HttpContext.Current.Session["ReportDataTables"] = dataTables; + } + public static void AddFastreportParameter(Dictionary Dicparames) + { + HttpContext.Current.Session["ReportParameterValues"] = Dicparames; + + } + + /// + /// 启动临时报表清理定时器,定期删除超过 1 小时的 PDF。 + /// + public static void StartTempReportCleanupMonitor() + { + if (tempReportCleanupTimer != null) + { + tempReportCleanupTimer.Stop(); + tempReportCleanupTimer.Dispose(); + tempReportCleanupTimer = null; } - // 清理Session中的缓存键引用 - var cacheKeys = HttpContext.Current.Session["ReportDataCacheKeys"] as List; - if (cacheKeys != null) + CleanExpiredTempReports(); + tempReportCleanupTimer = new Timer { - foreach (var key in cacheKeys) + AutoReset = true, + Interval = 1000 * 60 * 30 + }; + tempReportCleanupTimer.Elapsed += TempReportCleanupTimer_Elapsed; + tempReportCleanupTimer.Start(); + } + + private static void TempReportCleanupTimer_Elapsed(object sender, ElapsedEventArgs e) + { + CleanExpiredTempReports(); + } + + /// + /// 删除 File/Fastreport/Temp 下创建时间超过 1 小时的 PDF 临时文件。 + /// + public static void CleanExpiredTempReports() + { + try + { + string tempDirectory = Path.Combine(Funs.RootPath, @"File\Fastreport\Temp\"); + if (!Directory.Exists(tempDirectory)) { - try + return; + } + + DateTime expiredTime = DateTime.Now.AddHours(-1); + foreach (string file in Directory.GetFiles(tempDirectory, "*.pdf", SearchOption.TopDirectoryOnly)) + { + FileInfo fileInfo = new FileInfo(file); + if (fileInfo.CreationTime < expiredTime) { - CacheHelper.Remove(key); - } - catch - { - // 忽略缓存删除异常 + fileInfo.Attributes = FileAttributes.Normal; + fileInfo.Delete(); } } } - HttpContext.Current.Session["ReportDataCacheKeys"] = null; - HttpContext.Current.Session["ReportParameterCacheKey"] = null; - } - - /// - /// 添加报表数据表到缓存 - /// - public static void AddFastreportTable(DataTable dataTable) - { - - // 生成唯一缓存键 - string cacheKey = $"ReportData_{Guid.NewGuid()}_{DateTime.Now.Ticks}"; - - // 将数据表存储到缓存中,设置5分钟过期 - CacheHelper.Add(cacheKey, dataTable, DateTimeOffset.Now.AddMinutes(CacheExpirationMinutes)); - - List cacheKeys = HttpContext.Current.Session["ReportDataCacheKeys"] as List; - if (cacheKeys==null) + catch (Exception ex) { - cacheKeys = new List(); + ErrLogInfo.WriteLog(ex, "FastReport临时报表清理", "FastReportService.CleanExpiredTempReports"); } - cacheKeys.Add(cacheKey); - HttpContext.Current.Session["ReportDataCacheKeys"] = cacheKeys; } /// - /// 添加报表参数到缓存 + /// 导出报表 PDF 到临时目录,并返回可访问的相对 URL。 /// - public static void AddFastreportParameter(Dictionary Dicparames) - { - // 生成唯一缓存键 - string cacheKey = $"ReportParam_{Guid.NewGuid()}_{DateTime.Now.Ticks}"; + /// 报表模板路径,支持绝对路径或相对 Funs.RootPath 的路径。 + public static string ExportReport(string reportPath) + { + List dataTables = (List)HttpContext.Current.Session["ReportDataTables"]; + Dictionary parameterValues = (Dictionary)HttpContext.Current.Session["ReportParameterValues"]; + return ExportReport(reportPath, dataTables, parameterValues); + } - // 将参数存储到缓存中,设置5分钟过期 - CacheHelper.Add(cacheKey, Dicparames, DateTimeOffset.Now.AddMinutes(CacheExpirationMinutes)); + /// + /// 导出报表 PDF 到临时目录,并返回可访问的相对 URL。 + /// + /// 报表模板路径,支持绝对路径或相对 Funs.RootPath 的路径。 + /// 报表数据源集合。 + /// 报表参数集合。 + public static string ExportReport(string reportPath, List dataTables, Dictionary parameterValues) + { + string fullReportPath = GetReportFullPath(reportPath); + if (string.IsNullOrEmpty(fullReportPath) || !File.Exists(fullReportPath)) + { + throw new FileNotFoundException("打印模板不存在!", reportPath); + } - // Session只存储缓存键的引用(轻量级) - HttpContext.Current.Session["ReportParameterCacheKey"] = cacheKey; + string relativeDirectory = @"File\Fastreport\Temp\"; + string tempDirectory = Path.Combine(Funs.RootPath, relativeDirectory); + if (!Directory.Exists(tempDirectory)) + { + Directory.CreateDirectory(tempDirectory); + } + + string fileName = "report_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N") + ".pdf"; + string filePath = Path.Combine(tempDirectory, fileName); + using (Report report = BuildPreparedReport(fullReportPath, dataTables, parameterValues)) + using (PDFExport pdfExport = new PDFExport()) + { + // Web 打印先导出 PDF,前端用 iframe 装载后调用浏览器打印。 + pdfExport.PrintScaling = false; + pdfExport.ShowPrintDialog = true; + report.Export(pdfExport, filePath); + } + + return "~/" + relativeDirectory.Replace("\\", "/") + fileName; + } + + private static Report BuildPreparedReport(string reportPath, List dataTables, Dictionary parameterValues) + { + FastReport.Utils.Config.WebMode = true; + Report report = new Report(); + report.Load(reportPath); + if (report.Dictionary.Connections.Count > 0) + { + var reportConnection = report.Dictionary.Connections[0]; + if (reportConnection.ConnectionString != Funs.ConnString) + { + // 打印时只替换本次报表连接,避免把运行环境连接串写回模板文件。 + reportConnection.ConnectionString = Funs.ConnString; + } + } + + if (dataTables != null && dataTables.Count > 0) + { + for (int i = 0; i < dataTables.Count; i++) + { + report.RegisterData(dataTables[i], dataTables[i].TableName); + } + } + + if (parameterValues != null && parameterValues.Count > 0) + { + foreach (KeyValuePair kvp in parameterValues) + { + report.SetParameterValue(kvp.Key, kvp.Value); + } + } + + report.Prepare(); + return report; + } + + private static string GetReportFullPath(string reportPath) + { + if (string.IsNullOrEmpty(reportPath)) + { + return reportPath; + } + + if (Path.IsPathRooted(reportPath)) + { + return reportPath; + } + + return Path.Combine(Funs.RootPath, reportPath.TrimStart('\\', '/')); } /// @@ -105,26 +222,21 @@ namespace BLL.Common { report.RegisterData(dataTables[j], dataTables[j].TableName);//绑定数据源 } - } if (ParameterValues.Count > 0) { foreach (KeyValuePair kvp in ParameterValues) { - report.SetParameterValue(kvp.Key, kvp.Value);//绑定参数 - + report.SetParameterValue(kvp.Key, kvp.Value);//绑定参数 } - } if (i == 0) { report.Prepare(); - } else { report.Prepare(true); - } } if (printType == "1") diff --git a/HJGL_DS/FineUIPro.Web/Global.asax.cs b/HJGL_DS/FineUIPro.Web/Global.asax.cs index bc83077..edd3b97 100644 --- a/HJGL_DS/FineUIPro.Web/Global.asax.cs +++ b/HJGL_DS/FineUIPro.Web/Global.asax.cs @@ -37,6 +37,7 @@ Funs.APPUrl = ConfigurationManager.AppSettings["APPUrl"]; Funs.SystemCode = ConfigurationManager.AppSettings["SystemCode"]; Funs.HJGLUrl = ConfigurationManager.AppSettings["HJGLUrl"]; + BLL.Common.FastReportService.StartTempReportCleanupMonitor(); } catch (Exception ex) { diff --git a/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx b/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx index 002c995..45873cd 100644 --- a/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx +++ b/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx @@ -80,15 +80,64 @@ var result = window.showModalDialog("LC700.aspx?keyId=" + keyId + "&flag=" + flag + "&grid=" + grid, "", "status=no;dialogWidth=600px;dialogHeight=280px;menu=no;resizeable=no;scroll=yes;center=yes;edge=raise;location=no"); } - function ReportPrint(reportId, replaceParameter, varValue) { - var result = window.showModalDialog("../../Common/ReportPrint/ExReportPrint.aspx?ispop=1&projectId=0&reportId=" + reportId + "&replaceParameter=" + replaceParameter + "&varValue=" + varValue, "", "status=no;dialogWidth=610px;dialogHeight=460px;menu=no;resizeable=no;scroll=no;center=yes;edge=raise;location=no"); - } + //function ReportPrint(reportId, replaceParameter, varValue) { + // var result = window.showModalDialog("../../Common/ReportPrint/ExReportPrint.aspx?ispop=1&projectId=0&reportId=" + reportId + "&replaceParameter=" + replaceParameter + "&varValue=" + varValue, "", "status=no;dialogWidth=610px;dialogHeight=460px;menu=no;resizeable=no;scroll=no;center=yes;edge=raise;location=no"); + //} function backData(data) { //debugger //alert(data); alert("焊工已确认领料!"); } + + function printByHiddenFrame(url) { + var frameId = 'fastreport-print-frame-' + new Date().getTime(); + var frame = document.createElement('iframe'); + frame.id = frameId; + frame.name = frameId; + frame.style.position = 'fixed'; + frame.style.left = '-10000px'; + frame.style.top = '-10000px'; + frame.style.width = '1px'; + frame.style.height = '1px'; + frame.style.border = '0'; + frame.style.opacity = '0'; + frame.onload = function () { + setTimeout(function () { + try { + frame.contentWindow.onafterprint = cleanupPrintFrame; + frame.contentWindow.focus(); + frame.contentWindow.print(); + } catch (e) { + window.print(); + } + }, 500); + }; + frame.src = url; + document.body.appendChild(frame); + var cleaned = false; + function cleanupPrintFrame() { + if (cleaned) { + return; + } + cleaned = true; + if (frame && frame.parentNode) { + frame.parentNode.removeChild(frame); + } + window.removeEventListener('afterprint', cleanupPrintFrame); + } + window.addEventListener('afterprint', cleanupPrintFrame); + setTimeout(cleanupPrintFrame, 300000); + } + window.addEventListener('message', function (event) { + if (!event.data || event.data.type !== 'fastreport-print-finished') { + return; + } + var frame = document.getElementById(event.data.frameId); + if (frame && frame.parentNode) { + frame.parentNode.removeChild(frame); + } + }); diff --git a/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx.cs b/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx.cs index aa66c47..fb6889b 100644 --- a/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx.cs +++ b/HJGL_DS/FineUIPro.Web/WeldMat/UsingSentMat/UsingMatCheck.aspx.cs @@ -316,8 +316,11 @@ namespace FineUIPro.Web.WeldMat.UsingSentMat if (File.Exists(rootPath + initTemplatePath)) { - PageContext.RegisterStartupScript(Window2.GetShowReference(String.Format("../../common/ReportPrint/Fastreport.aspx?ReportPath={0}", rootPath + initTemplatePath))); - + //PageContext.RegisterStartupScript(Window2.GetShowReference(String.Format("../../common/ReportPrint/Fastreport.aspx?ReportPath={0}", rootPath + initTemplatePath))); + string printUrl = ResolveUrl(BLL.Common.FastReportService.ExportReport(rootPath + initTemplatePath)); + PageContext.RegisterStartupScript(String.Format("printByHiddenFrame('{0}');", printUrl)); + Window2.Hidden = true; + Window2.IFrameUrl = ""; } } }