prepareReportTemplates.mjs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * 将健康/异常报告模板写入 templates/
  3. * 用法:node scripts/prepareReportTemplates.mjs
  4. */
  5. import path from "path";
  6. import fs from "fs";
  7. import { fileURLToPath } from "url";
  8. import PizZip from "pizzip";
  9. import {
  10. HEALTH_IMAGE_MARKERS,
  11. patchAnomalyTemplateXml,
  12. patchTemplateXml,
  13. } from "../src/server/reportService/docxReportBuilder.js";
  14. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  15. const root = path.join(__dirname, "..");
  16. const templatesDir = path.join(root, "templates");
  17. const publicHealthV2 = path.join(
  18. root,
  19. "src",
  20. "public",
  21. "file",
  22. "风电机组健康评估_风场级自动报告模板_V2.0.docx",
  23. );
  24. const publicHealthV1 = path.join(
  25. root,
  26. "..",
  27. "public",
  28. "files",
  29. "风电机组健康评估_风场级自动报告模板_V1.0.docx",
  30. );
  31. const publicHealth = fs.existsSync(publicHealthV2)
  32. ? publicHealthV2
  33. : publicHealthV1;
  34. const publicAnomaly = path.join(
  35. root,
  36. "src",
  37. "public",
  38. "file",
  39. "异常检测数据分析报告模板(大唐版).docx",
  40. );
  41. function writeTemplate(zip, targetName) {
  42. fs.mkdirSync(templatesDir, { recursive: true });
  43. const outPath = path.join(templatesDir, targetName);
  44. if (fs.existsSync(outPath)) {
  45. try {
  46. fs.chmodSync(outPath, 0o644);
  47. } catch (_e) {
  48. // ignore
  49. }
  50. fs.unlinkSync(outPath);
  51. }
  52. fs.writeFileSync(outPath, zip.generate({ type: "nodebuffer" }), {
  53. mode: 0o644,
  54. });
  55. return outPath;
  56. }
  57. function patchAndWrite(sourcePath, targetName, patchFn) {
  58. if (!fs.existsSync(sourcePath)) {
  59. throw new Error(`源模板不存在: ${sourcePath}`);
  60. }
  61. const content = fs.readFileSync(sourcePath, "binary");
  62. const zip = new PizZip(content);
  63. const documentFile = zip.file("word/document.xml");
  64. if (!documentFile) throw new Error("模板缺少 word/document.xml");
  65. zip.file("word/document.xml", patchFn(documentFile.asText()));
  66. return writeTemplate(zip, targetName);
  67. }
  68. fs.mkdirSync(templatesDir, { recursive: true });
  69. if (fs.existsSync(publicHealth)) {
  70. const healthOut = patchAndWrite(
  71. publicHealth,
  72. "health-report-template.docx",
  73. (xml) => patchTemplateXml(xml, HEALTH_IMAGE_MARKERS),
  74. );
  75. console.log("健康模板已写入并插入图片占位:", healthOut);
  76. } else {
  77. console.warn("未找到健康模板,跳过:", publicHealth);
  78. }
  79. if (fs.existsSync(publicAnomaly)) {
  80. const anomalyOut = patchAndWrite(
  81. publicAnomaly,
  82. "anomaly-report-template.docx",
  83. (xml) => patchAnomalyTemplateXml(xml),
  84. );
  85. console.log("异常模板已写入并补齐 image 占位:", anomalyOut);
  86. } else {
  87. console.warn("未找到异常模板,跳过:", publicAnomaly);
  88. }
  89. console.log("完成。重启 downLoadServer 后即可生成报告。");