validate-health-template.mjs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import fs from "fs";
  2. import PizZip from "pizzip";
  3. import Docxtemplater from "docxtemplater";
  4. import ImageModule from "docxtemplater-image-module-free";
  5. import {
  6. HEALTH_IMAGE_MARKERS,
  7. patchTemplateXml,
  8. } from "../src/server/reportService/docxReportBuilder.js";
  9. const zip = new PizZip(fs.readFileSync("templates/health-report-template.docx"));
  10. let xml = zip.file("word/document.xml").asText();
  11. console.log(
  12. "p open/close",
  13. (xml.match(/<w:p(?:\s|>)/g) || []).length,
  14. (xml.match(/<\/w:p>/g) || []).length,
  15. );
  16. const wt = [];
  17. xml.replace(/<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g, (_, t) => {
  18. wt.push(t);
  19. return _;
  20. });
  21. const bad = wt.filter(
  22. (t) => (t.match(/{/g) || []).length !== (t.match(/}/g) || []).length,
  23. );
  24. console.log("unbalanced w:t", bad.length);
  25. bad.slice(0, 10).forEach((t) => console.log(JSON.stringify(t.slice(0, 120))));
  26. xml = patchTemplateXml(xml, HEALTH_IMAGE_MARKERS);
  27. zip.file("word/document.xml", xml);
  28. const empty = Buffer.from(
  29. "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
  30. "base64",
  31. );
  32. const imageModule = new ImageModule({
  33. centered: true,
  34. getImage: () => empty,
  35. getSize: () => [100, 60],
  36. });
  37. const doc = new Docxtemplater(zip, {
  38. paragraphLoop: true,
  39. linebreaks: true,
  40. modules: [imageModule],
  41. nullGetter: () => "",
  42. });
  43. doc.render({
  44. farm_name: "测试",
  45. Province: "新疆",
  46. Wind_farm: "测试",
  47. Year_now: "2026",
  48. Month_now: "09",
  49. machineTypeCode: "x",
  50. field_id: "F1",
  51. create_time: "t",
  52. source_datetime: "2026-09-01",
  53. eval_start_date: "2026-08-03",
  54. eval_end_date: "2026-09-01",
  55. eval_date_range: "2026-08-03至2026-09-01(滚动30天)",
  56. turbine_count: "1",
  57. valid_turbine_count: "1",
  58. turbine_types: "x",
  59. overall_score: "80",
  60. system_score: "70",
  61. component_score: "70",
  62. "structure_score/未评估": "70",
  63. excellent_count: "1",
  64. good_count: "0",
  65. fair_count: "0",
  66. poor_count: "0",
  67. overall_level_text: "良",
  68. main_level: "良",
  69. level_distribution_text: "x",
  70. overall_summary_text: "x",
  71. focus_engine_list: "A",
  72. chart_fig1: "a",
  73. chart_fig2: "b",
  74. show_chart_fig1: [{}],
  75. show_chart_fig2: [{}],
  76. turbine_rows: [
  77. {
  78. index: 1,
  79. engine_name: "A1",
  80. machine_type: "T",
  81. overall: "80",
  82. level: "良",
  83. system: "70",
  84. component: "70",
  85. structure: "70",
  86. yaw: "1",
  87. pitch: "1",
  88. mcs: "1",
  89. hpu: "1",
  90. generator: "1",
  91. converter: "1",
  92. gearbox: "1",
  93. shaft: "1",
  94. rotor: "1",
  95. tower: "1",
  96. },
  97. ],
  98. focus_rows: [
  99. {
  100. index: 1,
  101. engine_name: "A1",
  102. machine_type: "T",
  103. overall: "80",
  104. level: "中",
  105. system: "70",
  106. component: "70",
  107. structure: "70",
  108. low_item: "系统健康",
  109. },
  110. ],
  111. turbine_trends: [
  112. {
  113. engine_title: "A1 趋势",
  114. charts: [
  115. { chart_title: "综合健康评分趋势图", trend_image: "a" },
  116. { chart_title: "结构健康趋势图", trend_image: "a" },
  117. ],
  118. },
  119. ],
  120. });
  121. console.log("docxtemplater compile+render ok");