prepareReportTemplates.mjs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 publicHealth = path.join(
  18. root,
  19. "..",
  20. "public",
  21. "files",
  22. "风电机组健康评估_风场级自动报告模板_V1.0.docx",
  23. );
  24. const publicAnomaly = path.join(
  25. root,
  26. "src",
  27. "public",
  28. "file",
  29. "异常检测数据分析报告模板(大唐版).docx",
  30. );
  31. function writeTemplate(zip, targetName) {
  32. fs.mkdirSync(templatesDir, { recursive: true });
  33. const outPath = path.join(templatesDir, targetName);
  34. if (fs.existsSync(outPath)) {
  35. try {
  36. fs.chmodSync(outPath, 0o644);
  37. } catch (_e) {
  38. // ignore
  39. }
  40. fs.unlinkSync(outPath);
  41. }
  42. fs.writeFileSync(outPath, zip.generate({ type: "nodebuffer" }), {
  43. mode: 0o644,
  44. });
  45. return outPath;
  46. }
  47. function patchAndWrite(sourcePath, targetName, patchFn) {
  48. if (!fs.existsSync(sourcePath)) {
  49. throw new Error(`源模板不存在: ${sourcePath}`);
  50. }
  51. const content = fs.readFileSync(sourcePath, "binary");
  52. const zip = new PizZip(content);
  53. const documentFile = zip.file("word/document.xml");
  54. if (!documentFile) throw new Error("模板缺少 word/document.xml");
  55. zip.file("word/document.xml", patchFn(documentFile.asText()));
  56. return writeTemplate(zip, targetName);
  57. }
  58. fs.mkdirSync(templatesDir, { recursive: true });
  59. if (fs.existsSync(publicHealth)) {
  60. const healthOut = patchAndWrite(
  61. publicHealth,
  62. "health-report-template.docx",
  63. (xml) => patchTemplateXml(xml, HEALTH_IMAGE_MARKERS),
  64. );
  65. console.log("健康模板已写入并插入图片占位:", healthOut);
  66. } else {
  67. console.warn("未找到健康模板,跳过:", publicHealth);
  68. }
  69. if (fs.existsSync(publicAnomaly)) {
  70. const anomalyOut = patchAndWrite(
  71. publicAnomaly,
  72. "anomaly-report-template.docx",
  73. (xml) => patchAnomalyTemplateXml(xml),
  74. );
  75. console.log("异常模板已写入并补齐 image 占位:", anomalyOut);
  76. } else {
  77. console.warn("未找到异常模板,跳过:", publicAnomaly);
  78. }
  79. console.log("完成。重启 downLoadServer 后即可生成报告。");