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

1 month ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Net;
  9. using Report.Entity;
  10. using FastReport.Utils;
  11. using System.IO;
  12. using System.Reflection;
  13. using FastReport.Cloud.OAuth;
  14. using Spire.Pdf;
  15. using System.Printing;
  16. using Spire.Pdf.Exporting.XPS.Schema;
  17. using System.Threading;
  18. using System.Drawing.Printing;
  19. namespace ReportLibrary
  20. {
  21. public class ReportHelper
  22. {
  23. private static readonly LocalPrintServer _printServer = new LocalPrintServer();
  24. public ReportHelper()
  25. {
  26. }
  27. public static List<piclog> ToPicTable(Dictionary<string, string> dict, string websiteUrl)
  28. {
  29. List<piclog> picList = new List<piclog>();
  30. piclog pic = new piclog();
  31. string key = "hisLog";
  32. if (dict.ContainsKey(key) == true)
  33. {
  34. var baseUri = new Uri(websiteUrl);
  35. var fullUri = new Uri(baseUri, dict[key]);
  36. pic.photo = fullUri.AbsoluteUri;
  37. }
  38. key = "firstPage";
  39. if (dict.ContainsKey(key) == true)
  40. {
  41. var baseUri = new Uri(websiteUrl);
  42. var fullUri = new Uri(baseUri, dict[key]);
  43. pic.firstPage = fullUri.AbsoluteUri;
  44. }
  45. key = "pageHeader";
  46. if (dict.ContainsKey(key) == true)
  47. {
  48. var baseUri = new Uri(websiteUrl);
  49. var fullUri = new Uri(baseUri, dict[key]);
  50. pic.pageHeader = fullUri.AbsoluteUri;
  51. }
  52. key = "pageFooter";
  53. if (dict.ContainsKey(key) == true)
  54. {
  55. var baseUri = new Uri(websiteUrl);
  56. var fullUri = new Uri(baseUri, dict[key]);
  57. pic.pageFooter = fullUri.AbsoluteUri;
  58. }
  59. key = "resultSign";
  60. if (dict.ContainsKey(key) == true)
  61. {
  62. var baseUri = new Uri(websiteUrl);
  63. var fullUri = new Uri(baseUri, dict[key]);
  64. pic.resultSign = fullUri.AbsoluteUri;
  65. }
  66. key = "orgSign";
  67. if (dict.ContainsKey(key) == true)
  68. {
  69. var baseUri = new Uri(websiteUrl);
  70. var fullUri = new Uri(baseUri, dict[key]);
  71. pic.orgSign = fullUri.AbsoluteUri;
  72. }
  73. key = "picExtOne";
  74. if (dict.ContainsKey(key) == true)
  75. {
  76. var baseUri = new Uri(websiteUrl);
  77. var fullUri = new Uri(baseUri, dict[key]);
  78. pic.picExtOne = fullUri.AbsoluteUri;
  79. }
  80. key = "picExtTwo";
  81. if (dict.ContainsKey(key) == true)
  82. {
  83. var baseUri = new Uri(websiteUrl);
  84. var fullUri = new Uri(baseUri, dict[key]);
  85. pic.picExtTwo = fullUri.AbsoluteUri;
  86. }
  87. key = "picExtThree";
  88. if (dict.ContainsKey(key) == true)
  89. {
  90. var baseUri = new Uri(websiteUrl);
  91. var fullUri = new Uri(baseUri, dict[key]);
  92. pic.picExtThree = fullUri.AbsoluteUri;
  93. }
  94. key = "picExtFour";
  95. if (dict.ContainsKey(key) == true)
  96. {
  97. var baseUri = new Uri(websiteUrl);
  98. var fullUri = new Uri(baseUri, dict[key]);
  99. pic.picExtFour = fullUri.AbsoluteUri;
  100. }
  101. key = "picExtFive";
  102. if (dict.ContainsKey(key) == true)
  103. {
  104. var baseUri = new Uri(websiteUrl);
  105. var fullUri = new Uri(baseUri, dict[key]);
  106. pic.picExtFive = fullUri.AbsoluteUri;
  107. }
  108. key = "picExtSix";
  109. if (dict.ContainsKey(key) == true)
  110. {
  111. var baseUri = new Uri(websiteUrl);
  112. var fullUri = new Uri(baseUri, dict[key]);
  113. pic.picExtSix = fullUri.AbsoluteUri;
  114. }
  115. key = "picExtSeven";
  116. if (dict.ContainsKey(key) == true)
  117. {
  118. var baseUri = new Uri(websiteUrl);
  119. var fullUri = new Uri(baseUri, dict[key]);
  120. pic.picExtSeven = fullUri.AbsoluteUri;
  121. }
  122. key = "picExtEight";
  123. if (dict.ContainsKey(key) == true)
  124. {
  125. var baseUri = new Uri(websiteUrl);
  126. var fullUri = new Uri(baseUri, dict[key]);
  127. pic.picExtEight = fullUri.AbsoluteUri;
  128. }
  129. key = "picExtNine";
  130. if (dict.ContainsKey(key) == true)
  131. {
  132. var baseUri = new Uri(websiteUrl);
  133. var fullUri = new Uri(baseUri, dict[key]);
  134. pic.picExtNine = fullUri.AbsoluteUri;
  135. }
  136. key = "picExtTen";
  137. if (dict.ContainsKey(key) == true)
  138. {
  139. var baseUri = new Uri(websiteUrl);
  140. var fullUri = new Uri(baseUri, dict[key]);
  141. pic.picExtTen = fullUri.AbsoluteUri;
  142. }
  143. picList.Add(pic);
  144. return picList;
  145. }
  146. public async Task<string> ReportExport(RequestExport req, DataSet ds)
  147. {
  148. Task<String> task = Task.Factory.StartNew<string>(() =>
  149. {
  150. using (FastReport.Report report = new FastReport.Report())
  151. {
  152. report.Load(req.TemplatePath);
  153. foreach (var item in req.Parameters)
  154. {
  155. report.SetParameterValue(item.Name, item.Value);
  156. }
  157. report.RegisterData(ds);
  158. report.PrintSettings.ShowDialog = false;
  159. FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
  160. eSet.ReportSettings.ShowProgress = false;
  161. report.Prepare();
  162. if (req.FileFormat.Equals("WORD"))
  163. {
  164. //FastReport.Export.RichText.RTFExport export = new FastReport.Export.RichText.RTFExport();
  165. //export.ShowProgress = true;
  166. //report.Export(export, req.FilePath);
  167. string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  168. string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf");
  169. FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
  170. report.Export(pdfExport, file_path);
  171. PdfDocument pdf = new PdfDocument();
  172. //加载PDF文档
  173. pdf.LoadFromFile(file_path);
  174. //将PDF文档转为Word文档并保存,可选择格式
  175. pdf.SaveToFile(req.FilePath, FileFormat.DOCX);
  176. }
  177. else if (req.FileFormat.Equals("EXCEL"))
  178. {
  179. //FastReport.Export.OoXML.Excel2007Export xlsExport = new FastReport.Export.OoXML.Excel2007Export();
  180. //report.Export(xlsExport, req.FilePath);
  181. string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  182. string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf");
  183. FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
  184. report.Export(pdfExport, file_path);
  185. PdfDocument pdf = new PdfDocument();
  186. //加载PDF文档
  187. pdf.LoadFromFile(file_path);
  188. //将PDF文档转为Word文档并保存,可选择格式
  189. pdf.SaveToFile(req.FilePath, FileFormat.XLSX);
  190. }
  191. else
  192. {
  193. if (File.Exists(req.FilePath))
  194. {
  195. File.Delete(req.FilePath);
  196. }
  197. if (!string.IsNullOrEmpty(req.customerOrgName))
  198. {
  199. string dirPath = System.IO.Path.GetDirectoryName(req.FilePath);
  200. string fileName=System.IO.Path.GetFileName(req.FilePath);
  201. string tempPath = System.IO.Path.Combine(dirPath, req.customerOrgName);
  202. if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); }
  203. if (!string.IsNullOrEmpty(req.departmentName))
  204. {
  205. tempPath = System.IO.Path.Combine(tempPath,req.departmentName);
  206. if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); }
  207. }
  208. req.FilePath=System.IO.Path.Combine(tempPath, fileName);
  209. //MessageBox.Show(req.FilePath);
  210. }
  211. FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
  212. report.Export(pdfExport, req.FilePath);
  213. }
  214. }
  215. return "Success";
  216. });
  217. String taskResult = await task;
  218. return taskResult;
  219. }
  220. public string GetDefaultPrinter()
  221. {
  222. using (PrintDocument pd = new PrintDocument())
  223. {
  224. return pd.PrinterSettings.PrinterName;
  225. }
  226. }
  227. /*
  228. try
  229. {
  230. using (var cts = new CancellationTokenSource())
  231. {
  232. // 关键点1:设置5分钟超时
  233. cts.CancelAfter(TimeSpan.FromMinutes(5));
  234. var result = await Task.Run(async () =>
  235. {
  236. using (var report = new FastReport.Report())
  237. {
  238. // 加载报表模板
  239. report.Load(req.TemplatePath);
  240. report.RegisterData(ds);
  241. // 设置参数
  242. foreach (var param in req.Parameters)
  243. {
  244. report.SetParameterValue(param.Name, param.Value);
  245. }
  246. // 配置打印机
  247. if (!string.IsNullOrEmpty(req.Printer))
  248. {
  249. report.PrintSettings.Printer = req.Printer.Trim();
  250. }
  251. // 执行打印
  252. report.PrintSettings.ShowDialog = req.IsPrintOption == "Y";
  253. report.Print();
  254. // 监控打印状态
  255. string jobName = System.IO.Path.GetFileName(req.TemplatePath);
  256. return await new PrintMonitor().CheckPrintStatusAsync(
  257. GetDefaultPrinter(),
  258. jobName,
  259. cts.Token,
  260. TimeSpan.FromMinutes(3));
  261. }
  262. }, cts.Token);
  263. return result;
  264. }
  265. }
  266. catch (OperationCanceledException ex)
  267. {
  268. // 关键点2:区分超时和手动取消
  269. return ex.CancellationToken.IsCancellationRequested
  270. ? "用户手动取消打印"
  271. : "打印超时(5分钟未完成)";
  272. }
  273. catch (Exception ex) when (ex.Message.Contains("缺纸"))
  274. {
  275. return "打印机缺纸,请装纸后重试";
  276. }
  277. catch (Exception ex)
  278. {
  279. return $"打印失败: {ex.Message}";
  280. }*/
  281. // 创建超时控制源(外层)
  282. public async Task<string> ReportPrint(RequestPrint req, DataSet ds)
  283. {
  284. var combinedCts = new CancellationTokenSource();
  285. combinedCts.CancelAfter(TimeSpan.FromSeconds(30));
  286. try
  287. {
  288. return await Task.Run(async () =>
  289. {
  290. var report = new FastReport.Report();
  291. var monitor = new PrintMonitor();
  292. var printCts = CancellationTokenSource.CreateLinkedTokenSource(combinedCts.Token);
  293. var printerName = GetPrinterName(req);
  294. printCts.CancelAfter(TimeSpan.FromSeconds(30));
  295. try
  296. {
  297. // 加载报表模板
  298. if (!File.Exists(req.TemplatePath))
  299. throw new FileNotFoundException("报表模板文件不存在", req.TemplatePath);
  300. report.Load(req.TemplatePath);
  301. report.RegisterData(ds);
  302. // 配置打印机参数
  303. if (!IsPrinterAvailable(printerName))
  304. throw new InvalidOperationException($"打印机不可用: {printerName}");
  305. ConfigurePrinter(report, req);
  306. // 虚拟打印机特殊处理
  307. if (IsVirtualPrinter(printerName))
  308. {
  309. report.PrintSettings.ShowDialog = false; // 禁用对话框
  310. // report.PrintSettings.ShowProgress = false;
  311. }
  312. report.Print();
  313. var jobName = GenerateJobName(req);
  314. return await monitor.CheckPrintStatusAsync(
  315. printerName,
  316. jobName,
  317. printCts.Token);
  318. }
  319. catch (Exception ex)
  320. {
  321. // 添加虚拟打印机调试信息
  322. if (IsVirtualPrinter(printerName))
  323. throw new Exception($"虚拟打印机处理失败: {ex.Message} [文件:{req.TemplatePath}]", ex);
  324. throw new Exception($"打印操作失败: {ex.Message}", ex);
  325. }
  326. }, combinedCts.Token);
  327. }
  328. catch (OperationCanceledException ex) when (combinedCts.IsCancellationRequested)
  329. {
  330. throw new TimeoutException("操作超时,请检查打印机响应", ex);
  331. }
  332. catch (Exception ex)
  333. {
  334. // 解析异常链
  335. var errorMsg = new StringBuilder("打印流程异常:");
  336. var innerEx = ex;
  337. while (innerEx != null)
  338. {
  339. errorMsg.AppendLine().Append($"→ {innerEx.GetType().Name}: {innerEx.Message}");
  340. innerEx = innerEx.InnerException;
  341. }
  342. // 记录完整堆栈
  343. //Logger.Error(ex, errorMsg.ToString());
  344. // 返回友好提示
  345. if (ex is FileNotFoundException)
  346. return "ERROR: 模板文件路径错误";
  347. if (ex.Message.Contains("虚拟打印机"))
  348. return "ERROR: 虚拟打印机处理失败,请检查输出文件路径";
  349. return $"ERROR: 打印系统异常({ex.GetBaseException().Message})";
  350. }
  351. }
  352. // 打印机检测方法
  353. private bool IsPrinterAvailable(string printerName)
  354. {
  355. return PrinterSettings.InstalledPrinters
  356. .Cast<string>()
  357. .Any(p => p.Equals(printerName, StringComparison.OrdinalIgnoreCase));
  358. }
  359. // 虚拟打印机检测(根据名称特征判断)
  360. private bool IsVirtualPrinter(string printerName)
  361. {
  362. var virtualPrinters = new[] { "Microsoft Print to PDF", "OneNote", "Fax" };
  363. return virtualPrinters.Any(v => printerName.Contains(v));
  364. }
  365. private void ConfigurePrinter(FastReport.Report report, RequestPrint req)
  366. {
  367. if (!string.IsNullOrEmpty(req.Printer))
  368. {
  369. report.PrintSettings.Printer = req.Printer.Trim();
  370. }
  371. }
  372. private string GenerateJobName(RequestPrint req)
  373. {
  374. return System.IO.Path.GetFileNameWithoutExtension(req.TemplatePath);
  375. }
  376. private string GetPrinterName(RequestPrint req)
  377. {
  378. return string.IsNullOrEmpty(req.Printer) ? GetDefaultPrinter() : req.Printer;
  379. }
  380. public async Task<string> ReportPrintPre(RequestPrintPre req, DataSet ds)
  381. {
  382. MemoryStream strm = new MemoryStream();
  383. Task<String> task = Task.Factory.StartNew<string>(() =>
  384. {
  385. using (FastReport.Report report = new FastReport.Report())
  386. {
  387. report.Load(req.TemplatePath);
  388. foreach (var item in req.Parameters)
  389. {
  390. report.SetParameterValue(item.Name, item.Value);
  391. }
  392. report.RegisterData(ds);
  393. report.PrintSettings.ShowDialog = false;
  394. FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
  395. eSet.ReportSettings.ShowProgress = false;
  396. report.Prepare();
  397. FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport();
  398. report.Report.Export(pdfExport, strm);
  399. }
  400. if (req.IsUploadPdf.Equals("Y"))
  401. return CreatePdfFile(strm, req.IsDev, true);
  402. else
  403. return CreatePdfFile(strm, req.IsDev, false);
  404. });
  405. String taskResult = await task;
  406. return taskResult;
  407. }
  408. public static void ReportDesign(RequestDesign req)
  409. {
  410. using (FastReport.Report report = new FastReport.Report())
  411. {
  412. FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings();
  413. eSet.ReportSettings.ShowProgress = false;
  414. string filePath = req.TemplatePath.Replace("//", "\\");
  415. report.Load(filePath);
  416. foreach (var item in req.Parameters)
  417. {
  418. report.SetParameterValue(item.Name, item.Value);
  419. }
  420. //DataSet ds = ClientConfig.DeserializeObject<DataSet>(req.DataSetJson);
  421. DataSet ds = ClientConfig.ConvertJsonToDataSet(req.DataSetJson, req.ImageUrl,req.ApiUrl);
  422. report.RegisterData(ds);
  423. //report.Prepare
  424. report.Design();
  425. report.Save(filePath);
  426. //TemplateDesignForm frm = new TemplateDesignForm(report, filePath);
  427. //frm.ShowDialog();
  428. }
  429. }
  430. private string CreatePdfFile(MemoryStream strm, bool IsDev,bool isUploadPdf)
  431. {
  432. string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  433. DirectoryInfo path_current_info = new DirectoryInfo(path_current);
  434. string path_parent = string.Empty;
  435. string dirPath= string.Empty;
  436. string filePath = string.Empty;
  437. //string file_path = "\\static\\fastReport\\output\\pdf\\print.pdf";
  438. if (!isUploadPdf)
  439. {
  440. string path_parent_path = path_current_info.Parent.FullName;
  441. if (IsDev)
  442. {
  443. path_parent_path = path_parent_path.Replace("extensions", "public");
  444. }
  445. else
  446. {
  447. path_parent_path = path_parent_path.Replace("extensions", "dist");
  448. }
  449. path_parent = path_parent_path + "\\static\\fastReport\\output\\pdf";
  450. if (!Directory.Exists(path_parent))
  451. {
  452. Directory.CreateDirectory(path_parent);
  453. }
  454. dirPath = path_parent;
  455. filePath = path_parent + string.Format("\\{0}.pdf",DateTime.Now.ToString("yyyyMMddHHmmss"));
  456. }else
  457. {
  458. filePath = path_current_info.FullName + "\\upload.pdf";
  459. }
  460. if (!string.IsNullOrEmpty(dirPath))
  461. {
  462. foreach (string file in Directory.GetFiles(dirPath))
  463. {
  464. string fileName = System.IO.Path.GetFileName(file);
  465. if (fileName.Equals("print.pdf")) continue;
  466. File.Delete(file);
  467. }
  468. }
  469. if (File.Exists(filePath))
  470. {
  471. File.Delete(filePath);
  472. }
  473. //MessageBox.Show("CreatePdfFile");
  474. FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
  475. BinaryWriter w = new BinaryWriter(fs);
  476. w.Write(strm.ToArray());
  477. fs.Close();
  478. strm.Close();
  479. return System.IO.Path.GetFileName(filePath);
  480. }
  481. }
  482. }