const { Document, Packer, Paragraph, TextRun, HeadingLevel, AlignmentType, Table, TableRow, TableCell, WidthType, BorderStyle, ImageRun, PageBreak, ShadingType, convertInchesToTwip } = require('docx'); const fs = require('fs'); // Read the embedded image from the docx media folder const imageBuffer = fs.readFileSync('content/word/media/image1.png'); // Helper: create a horizontal line paragraph function hline() { return new Paragraph({ border: { bottom: { color: 'CCCCCC', space: 1, style: BorderStyle.SINGLE, size: 6 } }, spacing: { after: 100 }, children: [] }); } // Helper: info box paragraph (bordered) function infoPara(text, color = '4F81BD') { return new Paragraph({ children: [ new TextRun({ text: ' ' + text, font: '微软雅黑', size: 22, color: '333333' }) ], shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, border: { top: { color, style: BorderStyle.SINGLE, size: 4 }, bottom: { color, style: BorderStyle.SINGLE, size: 4 }, left: { color, style: BorderStyle.SINGLE, size: 12 }, right: { color, style: BorderStyle.SINGLE, size: 4 } }, spacing: { before: 80, after: 80, left: 100 }, indent: { left: 100 } }); } // Helper: section title function sectionTitle(text) { return new Paragraph({ children: [ new TextRun({ text: ' ' + text, bold: true, font: '微软雅黑', size: 26, color: 'FFFFFF' }) ], shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, spacing: { before: 120, after: 80 }, indent: { left: 0 } }); } // Helper: normal body text function bodyPara(text, bold = false, color = '333333', size = 22) { return new Paragraph({ children: [new TextRun({ text, bold, font: '微软雅黑', size, color })], spacing: { before: 60, after: 60 }, indent: { firstLine: 480 } }); } // Helper: bullet item function bullet(text, level = 0) { const indent = level * 360; return new Paragraph({ children: [ new TextRun({ text: '• ', font: '微软雅黑', size: 22, color: '2E74B5' }), new TextRun({ text, font: '微软雅黑', size: 22, color: '333333' }) ], spacing: { before: 40, after: 40 }, indent: { left: 480 + indent } }); } // Helper: key-value row in a table function kvRow(label, value, labelColor = '2E74B5') { return new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: label, bold: true, font: '微软雅黑', size: 20, color: labelColor })] })], width: { size: 25, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'E8F0FB' }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: value, font: '微软雅黑', size: 20, color: '333333' })] })], width: { size: 75, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }) ] }); } const doc = new Document({ styles: { default: { document: { run: { font: '微软雅黑', size: 22 } } } }, sections: [{ properties: { page: { margin: { top: 1440, right: 1800, bottom: 1440, left: 1800 } } }, children: [ // ===== 大标题 ===== new Paragraph({ children: [ new TextRun({ text: '报错闭环处理报告', bold: true, font: '微软雅黑', size: 52, color: '1F497D' }) ], alignment: AlignmentType.CENTER, spacing: { after: 200 } }), // ===== 元信息表格 ===== new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, borders: { top: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, bottom: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, left: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, right: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, insideH: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' }, insideV: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' } }, rows: [ kvRow('报告编号', 'REP-20260418-001'), kvRow('处理日期', '2026年4月18日'), kvRow('报告类型', '数据异常报错闭环处理'), kvRow('处理状态', '已完成'), kvRow('报告人', '(请填写)') ] }), new Paragraph({ children: [], spacing: { after: 200 } }), // ===== 一、报错分析 ===== sectionTitle('一、报错分析'), bodyPara('2026年4月18日,系统出现数据异常波动,经排查定位,确认问题原因如下:'), bullet('设备端上传的异常参数参与了后台整体运算流程'), bullet('该参数导致当日统计结果产生剧烈偏差'), new Paragraph({ children: [], spacing: { after: 100 } }), // 图片说明 new Paragraph({ children: [ new TextRun({ text: '【错误截图】', bold: true, font: '微软雅黑', size: 22, color: '2E74B5' }) ], spacing: { before: 80, after: 80 } }), // 嵌入截图 new Paragraph({ children: [ new ImageRun({ data: imageBuffer, transformation: { width: 560, height: 180 } }) ], alignment: AlignmentType.CENTER, spacing: { after: 200 } }), // 原因描述 new Paragraph({ children: [ new TextRun({ text: '问题描述:', bold: true, font: '微软雅黑', size: 22, color: 'C00000' }), new TextRun({ text: '由于设备数据上传到后台后,后台将该参数参与了整体运算过程,导致该天数据产生巨大差异。', font: '微软雅黑', size: 22, color: '333333' }) ], spacing: { before: 80, after: 80 }, indent: { firstLine: 480 } }), hline(), // ===== 二、后台维度处理 ===== sectionTitle('二、后台维度处理措施'), bodyPara('针对本次数据异常,已从以下维度制定并落实处理方案:'), new Paragraph({ children: [new TextRun({ text: '2.1 数据校验增强', bold: true, font: '微软雅黑', size: 24, color: '1F497D' })], spacing: { before: 120, after: 60 } }), bullet('对特定字段数据增加范围校验与合法性校验'), bullet('对边界值与极值进行实时告警拦截'), bullet('引入异常数据默认值兜底机制,防止脏数据扩散'), new Paragraph({ children: [new TextRun({ text: '2.2 后台运算管控', bold: true, font: '微软雅黑', size: 24, color: '1F497D' })], spacing: { before: 120, after: 60 } }), bullet('消除异常操作对数据统计的影响'), bullet('对参与整体运算的字段增加白名单过滤'), bullet('建立敏感参数修改的操作审计日志'), new Paragraph({ children: [new TextRun({ text: '2.3 预警与闭环机制', bold: true, font: '微软雅黑', size: 24, color: '1F497D' })], spacing: { before: 120, after: 60 } }), bullet('设置数据波动阈值告警,超过阈值自动通知'), bullet('完善异常数据处理流程,形成闭环跟踪机制'), bullet('定期回溯验证,确保类似事件不再复发'), new Paragraph({ children: [], spacing: { after: 200 } }), hline(), // ===== 三、处理结论 ===== sectionTitle('三、处理结论'), infoPara('处理结论:对特定字段数据进行管控处理,消除对数据异常进行的异常操作处理,增强校验机制,达到数据处理准确结果,避免类似事件再次发生。'), new Paragraph({ children: [], spacing: { after: 200 } }), hline(), // ===== 四、处理进度 ===== sectionTitle('四、处理进度'), new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, borders: { top: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, bottom: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, left: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, right: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, insideH: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' }, insideV: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' } }, rows: [ new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '序号', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '处理阶段', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 30, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '处理措施', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 35, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '完成时间', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 15, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '状态', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }) ] }), new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '1', font: '微软雅黑', size: 20 })] })], width: { size: 10, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '问题定位', font: '微软雅黑', size: 20 })] })], width: { size: 30, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '确认设备异常参数上传原因', font: '微软雅黑', size: 20 })] })], width: { size: 35, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '2026-04-18', font: '微软雅黑', size: 20 })] })], width: { size: 15, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '已完成', font: '微软雅黑', size: 20, color: '00B050' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }) ] }), new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '2', font: '微软雅黑', size: 20 })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '数据修复', font: '微软雅黑', size: 20 })] })], width: { size: 30, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '清洗当日异常数据,恢复正确统计结果', font: '微软雅黑', size: 20 })] })], width: { size: 35, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '2026-04-18', font: '微软雅黑', size: 20 })] })], width: { size: 15, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '已完成', font: '微软雅黑', size: 20, color: '00B050' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }) ] }), new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '3', font: '微软雅黑', size: 20 })] })], width: { size: 10, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '校验增强', font: '微软雅黑', size: 20 })] })], width: { size: 30, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '增加参数合法性校验与极值告警机制', font: '微软雅黑', size: 20 })] })], width: { size: 35, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '2026-04-18', font: '微软雅黑', size: 20 })] })], width: { size: 15, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '已完成', font: '微软雅黑', size: 20, color: '00B050' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }) ] }), new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '4', font: '微软雅黑', size: 20 })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '持续监控', font: '微软雅黑', size: 20 })] })], width: { size: 30, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '建立数据波动告警与周期性回溯机制', font: '微软雅黑', size: 20 })] })], width: { size: 35, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '2026-04-18', font: '微软雅黑', size: 20 })] })], width: { size: 15, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '已完成', font: '微软雅黑', size: 20, color: '00B050' })] })], width: { size: 10, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: 'F0F7FF' }, margins: { top: 80, bottom: 80, left: 80, right: 80 } }) ] }) ] }), new Paragraph({ children: [], spacing: { after: 300 } }), hline(), // ===== 五、签字确认 ===== sectionTitle('五、签字确认'), new Paragraph({ children: [new TextRun({ text: '本报告由相关责任人确认签字后归档,确保问题处理闭环可追溯。', font: '微软雅黑', size: 22, color: '666666' })], spacing: { before: 80, after: 160 } }), new Table({ width: { size: 100, type: WidthType.PERCENTAGE }, borders: { top: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, bottom: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, left: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, right: { style: BorderStyle.SINGLE, size: 4, color: '2E74B5' }, insideH: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' }, insideV: { style: BorderStyle.SINGLE, size: 2, color: 'BDD7EE' } }, rows: [ new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '角色', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 20, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '姓名', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 25, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '签字', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 35, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: '日期', bold: true, font: '微软雅黑', size: 20, color: 'FFFFFF' })] })], width: { size: 20, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: '2E74B5' }, margins: { top: 80, bottom: 80, left: 120, right: 80 } }) ] }), ...['提出人', '开发负责人', '测试负责人', '审批人'].map((role, i) => new TableRow({ children: [ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: role, font: '微软雅黑', size: 20 })] })], width: { size: 20, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: i % 2 === 0 ? 'FFFFFF' : 'F0F7FF' }, margins: { top: 120, bottom: 120, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [] })], width: { size: 25, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: i % 2 === 0 ? 'FFFFFF' : 'F0F7FF' }, margins: { top: 120, bottom: 120, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [] })], width: { size: 35, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: i % 2 === 0 ? 'FFFFFF' : 'F0F7FF' }, margins: { top: 120, bottom: 120, left: 120, right: 80 } }), new TableCell({ children: [new Paragraph({ children: [] })], width: { size: 20, type: WidthType.PERCENTAGE }, shading: { type: ShadingType.CLEAR, color: 'auto', fill: i % 2 === 0 ? 'FFFFFF' : 'F0F7FF' }, margins: { top: 120, bottom: 120, left: 120, right: 80 } }) ] }) ) ] }) ] }] }); Packer.toBuffer(doc).then(buffer => { fs.writeFileSync('20260418报错闭环处理_美化版.docx', buffer); console.log('Done!'); });