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
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);
|
|
|
|
}
|
|
}
|
|
}
|