You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

543 lines
21 KiB

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using Report.Entity;
using FastReport.Utils;
using System.IO;
using System.Reflection;
using FastReport.Cloud.OAuth;
using Spire.Pdf;
using System.Printing;
using Spire.Pdf.Exporting.XPS.Schema;
using System.Threading;
using System.Drawing.Printing;
namespace ReportLibrary
{
public class ReportHelper
{
private static readonly LocalPrintServer _printServer = new LocalPrintServer();
public ReportHelper()
{
}
public static List<piclog> ToPicTable(Dictionary<string, string> dict, string websiteUrl)
{
List<piclog> picList = new List<piclog>();
piclog pic = new piclog();
string key = "hisLog";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.photo = fullUri.AbsoluteUri;
}
key = "firstPage";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.firstPage = fullUri.AbsoluteUri;
}
key = "pageHeader";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.pageHeader = fullUri.AbsoluteUri;
}
key = "pageFooter";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.pageFooter = fullUri.AbsoluteUri;
}
key = "resultSign";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.resultSign = fullUri.AbsoluteUri;
}
key = "orgSign";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.orgSign = fullUri.AbsoluteUri;
}
key = "picExtOne";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtOne = fullUri.AbsoluteUri;
}
key = "picExtTwo";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtTwo = fullUri.AbsoluteUri;
}
key = "picExtThree";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtThree = fullUri.AbsoluteUri;
}
key = "picExtFour";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtFour = fullUri.AbsoluteUri;
}
key = "picExtFive";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtFive = fullUri.AbsoluteUri;
}
key = "picExtSix";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtSix = fullUri.AbsoluteUri;
}
key = "picExtSeven";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtSeven = fullUri.AbsoluteUri;
}
key = "picExtEight";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtEight = fullUri.AbsoluteUri;
}
key = "picExtNine";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtNine = fullUri.AbsoluteUri;
}
key = "picExtTen";
if (dict.ContainsKey(key) == true)
{
var baseUri = new Uri(websiteUrl);
var fullUri = new Uri(baseUri, dict[key]);
pic.picExtTen = fullUri.AbsoluteUri;
}
picList.Add(pic);
return picList;
}
public async Task<string> ReportExport(RequestExport req, DataSet ds)
{
Task<String> task = Task.Factory.StartNew<string>(() =>
{
using (FastReport.Report report = new FastReport.Report())
{
report.Load(req.TemplatePath);
foreach (var item in req.Parameters)
{
report.SetParameterValue(item.Name, item.Value);
}
report.RegisterData(ds);
report.PrintSettings.ShowDialog = false;
FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
eSet.ReportSettings.ShowProgress = false;
report.Prepare();
if (req.FileFormat.Equals("WORD"))
{
//FastReport.Export.RichText.RTFExport export = new FastReport.Export.RichText.RTFExport();
//export.ShowProgress = true;
//report.Export(export, req.FilePath);
string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf");
FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
report.Export(pdfExport, file_path);
PdfDocument pdf = new PdfDocument();
//加载PDF文档
pdf.LoadFromFile(file_path);
//将PDF文档转为Word文档并保存,可选择格式
pdf.SaveToFile(req.FilePath, FileFormat.DOCX);
}
else if (req.FileFormat.Equals("EXCEL"))
{
//FastReport.Export.OoXML.Excel2007Export xlsExport = new FastReport.Export.OoXML.Excel2007Export();
//report.Export(xlsExport, req.FilePath);
string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf");
FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
report.Export(pdfExport, file_path);
PdfDocument pdf = new PdfDocument();
//加载PDF文档
pdf.LoadFromFile(file_path);
//将PDF文档转为Word文档并保存,可选择格式
pdf.SaveToFile(req.FilePath, FileFormat.XLSX);
}
else
{
if (File.Exists(req.FilePath))
{
File.Delete(req.FilePath);
}
if (!string.IsNullOrEmpty(req.customerOrgName))
{
string dirPath = System.IO.Path.GetDirectoryName(req.FilePath);
string fileName=System.IO.Path.GetFileName(req.FilePath);
string tempPath = System.IO.Path.Combine(dirPath, req.customerOrgName);
if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); }
if (!string.IsNullOrEmpty(req.departmentName))
{
tempPath = System.IO.Path.Combine(tempPath,req.departmentName);
if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); }
}
req.FilePath=System.IO.Path.Combine(tempPath, fileName);
//MessageBox.Show(req.FilePath);
}
FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
report.Export(pdfExport, req.FilePath);
}
}
return "Success";
});
String taskResult = await task;
return taskResult;
}
public string GetDefaultPrinter()
{
using (PrintDocument pd = new PrintDocument())
{
return pd.PrinterSettings.PrinterName;
}
}
/*
try
{
using (var cts = new CancellationTokenSource())
{
// 关键点1:设置5分钟超时
cts.CancelAfter(TimeSpan.FromMinutes(5));
var result = await Task.Run(async () =>
{
using (var report = new FastReport.Report())
{
// 加载报表模板
report.Load(req.TemplatePath);
report.RegisterData(ds);
// 设置参数
foreach (var param in req.Parameters)
{
report.SetParameterValue(param.Name, param.Value);
}
// 配置打印机
if (!string.IsNullOrEmpty(req.Printer))
{
report.PrintSettings.Printer = req.Printer.Trim();
}
// 执行打印
report.PrintSettings.ShowDialog = req.IsPrintOption == "Y";
report.Print();
// 监控打印状态
string jobName = System.IO.Path.GetFileName(req.TemplatePath);
return await new PrintMonitor().CheckPrintStatusAsync(
GetDefaultPrinter(),
jobName,
cts.Token,
TimeSpan.FromMinutes(3));
}
}, cts.Token);
return result;
}
}
catch (OperationCanceledException ex)
{
// 关键点2:区分超时和手动取消
return ex.CancellationToken.IsCancellationRequested
? "用户手动取消打印"
: "打印超时(5分钟未完成)";
}
catch (Exception ex) when (ex.Message.Contains("缺纸"))
{
return "打印机缺纸,请装纸后重试";
}
catch (Exception ex)
{
return $"打印失败: {ex.Message}";
}*/
// 创建超时控制源(外层)
public async Task<string> ReportPrint(RequestPrint req, DataSet ds)
{
var combinedCts = new CancellationTokenSource();
combinedCts.CancelAfter(TimeSpan.FromSeconds(30));
try
{
return await Task.Run(async () =>
{
var report = new FastReport.Report();
var monitor = new PrintMonitor();
var printCts = CancellationTokenSource.CreateLinkedTokenSource(combinedCts.Token);
var printerName = GetPrinterName(req);
printCts.CancelAfter(TimeSpan.FromSeconds(30));
try
{
// 加载报表模板
if (!File.Exists(req.TemplatePath))
throw new FileNotFoundException("报表模板文件不存在", req.TemplatePath);
report.Load(req.TemplatePath);
report.RegisterData(ds);
// 配置打印机参数
if (!IsPrinterAvailable(printerName))
throw new InvalidOperationException($"打印机不可用: {printerName}");
ConfigurePrinter(report, req);
// 虚拟打印机特殊处理
if (IsVirtualPrinter(printerName))
{
report.PrintSettings.ShowDialog = false; // 禁用对话框
// report.PrintSettings.ShowProgress = false;
}
report.Print();
var jobName = GenerateJobName(req);
return await monitor.CheckPrintStatusAsync(
printerName,
jobName,
printCts.Token);
}
catch (Exception ex)
{
// 添加虚拟打印机调试信息
if (IsVirtualPrinter(printerName))
throw new Exception($"虚拟打印机处理失败: {ex.Message} [文件:{req.TemplatePath}]", ex);
throw new Exception($"打印操作失败: {ex.Message}", ex);
}
}, combinedCts.Token);
}
catch (OperationCanceledException ex) when (combinedCts.IsCancellationRequested)
{
throw new TimeoutException("操作超时,请检查打印机响应", ex);
}
catch (Exception ex)
{
// 解析异常链
var errorMsg = new StringBuilder("打印流程异常:");
var innerEx = ex;
while (innerEx != null)
{
errorMsg.AppendLine().Append($"→ {innerEx.GetType().Name}: {innerEx.Message}");
innerEx = innerEx.InnerException;
}
// 记录完整堆栈
//Logger.Error(ex, errorMsg.ToString());
// 返回友好提示
if (ex is FileNotFoundException)
return "ERROR: 模板文件路径错误";
if (ex.Message.Contains("虚拟打印机"))
return "ERROR: 虚拟打印机处理失败,请检查输出文件路径";
return $"ERROR: 打印系统异常({ex.GetBaseException().Message})";
}
}
// 打印机检测方法
private bool IsPrinterAvailable(string printerName)
{
return PrinterSettings.InstalledPrinters
.Cast<string>()
.Any(p => p.Equals(printerName, StringComparison.OrdinalIgnoreCase));
}
// 虚拟打印机检测(根据名称特征判断)
private bool IsVirtualPrinter(string printerName)
{
var virtualPrinters = new[] { "Microsoft Print to PDF", "OneNote", "Fax" };
return virtualPrinters.Any(v => printerName.Contains(v));
}
private void ConfigurePrinter(FastReport.Report report, RequestPrint req)
{
if (!string.IsNullOrEmpty(req.Printer))
{
report.PrintSettings.Printer = req.Printer.Trim();
}
}
private string GenerateJobName(RequestPrint req)
{
return System.IO.Path.GetFileNameWithoutExtension(req.TemplatePath);
}
private string GetPrinterName(RequestPrint req)
{
return string.IsNullOrEmpty(req.Printer) ? GetDefaultPrinter() : req.Printer;
}
public async Task<string> ReportPrintPre(RequestPrintPre req, DataSet ds)
{
MemoryStream strm = new MemoryStream();
Task<String> task = Task.Factory.StartNew<string>(() =>
{
using (FastReport.Report report = new FastReport.Report())
{
report.Load(req.TemplatePath);
foreach (var item in req.Parameters)
{
report.SetParameterValue(item.Name, item.Value);
}
report.RegisterData(ds);
report.PrintSettings.ShowDialog = false;
FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
eSet.ReportSettings.ShowProgress = false;
report.Prepare();
FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
report.Report.Export(pdfExport, strm);
}
if (req.IsUploadPdf.Equals("Y"))
return CreatePdfFile(strm, req.IsDev, true);
else
return CreatePdfFile(strm, req.IsDev, false);
});
String taskResult = await task;
return taskResult;
}
public static void ReportDesign(RequestDesign req)
{
using (FastReport.Report report = new FastReport.Report())
{
FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
eSet.ReportSettings.ShowProgress = false;
string filePath = req.TemplatePath.Replace("//", "\\");
report.Load(filePath);
foreach (var item in req.Parameters)
{
report.SetParameterValue(item.Name, item.Value);
}
//DataSet ds = ClientConfig.DeserializeObject<DataSet>(req.DataSetJson);
DataSet ds = ClientConfig.ConvertJsonToDataSet(req.DataSetJson, req.ImageUrl,req.ApiUrl);
report.RegisterData(ds);
//report.Prepare
report.Design();
report.Save(filePath);
//TemplateDesignForm frm = new TemplateDesignForm(report, filePath);
//frm.ShowDialog();
}
}
private string CreatePdfFile(MemoryStream strm, bool IsDev,bool isUploadPdf)
{
string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
DirectoryInfo path_current_info = new DirectoryInfo(path_current);
string path_parent = string.Empty;
string dirPath= string.Empty;
string filePath = string.Empty;
//string file_path = "\\static\\fastReport\\output\\pdf\\print.pdf";
if (!isUploadPdf)
{
string path_parent_path = path_current_info.Parent.FullName;
if (IsDev)
{
path_parent_path = path_parent_path.Replace("extensions", "public");
}
else
{
path_parent_path = path_parent_path.Replace("extensions", "dist");
}
path_parent = path_parent_path + "\\static\\fastReport\\output\\pdf";
if (!Directory.Exists(path_parent))
{
Directory.CreateDirectory(path_parent);
}
dirPath = path_parent;
filePath = path_parent + string.Format("\\{0}.pdf",DateTime.Now.ToString("yyyyMMddHHmmss"));
}else
{
filePath = path_current_info.FullName + "\\upload.pdf";
}
if (!string.IsNullOrEmpty(dirPath))
{
foreach (string file in Directory.GetFiles(dirPath))
{
string fileName = System.IO.Path.GetFileName(file);
if (fileName.Equals("print.pdf")) continue;
File.Delete(file);
}
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
//MessageBox.Show("CreatePdfFile");
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
BinaryWriter w = new BinaryWriter(fs);
w.Write(strm.ToArray());
fs.Close();
strm.Close();
return System.IO.Path.GetFileName(filePath);
}
}
}