Files
web-Iot/generate_monthly_report.cjs

676 lines
42 KiB
JavaScript
Raw Permalink Normal View History

2026-09-22 19:37:13 +08:00
const fs = require('fs');
const path = require('path');
const {
Document, Packer, Paragraph, TextRun, ImageRun,
HeadingLevel, AlignmentType, LevelFormat,
PageBreak, PageNumber, Header, Footer,
Table, TableRow, TableCell, WidthType,
BorderStyle, ShadingType, VerticalAlign,
} = require('docx');
const SCREENSHOT_DIR = path.join(__dirname, '.workbuddy', 'screenshots');
function getPngDimensions(filePath) {
const buf = fs.readFileSync(filePath);
const width = buf.readUInt32BE(16);
const height = buf.readUInt32BE(20);
return { width, height };
}
function createImage(screenshotName, maxWidth = 480) {
const filePath = path.join(SCREENSHOT_DIR, screenshotName);
if (!fs.existsSync(filePath)) return null;
const { width, height } = getPngDimensions(filePath);
const ratio = height / width;
const w = Math.min(maxWidth, width);
const h = Math.round(w * ratio);
return new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 120, after: 80 },
children: [new ImageRun({
type: 'png',
data: fs.readFileSync(filePath),
transformation: { width: w, height: h },
altText: { title: screenshotName, description: screenshotName, name: screenshotName },
})],
});
}
function h1(text) {
return new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun({ text, bold: true })] });
}
function h2(text) {
return new Paragraph({ heading: HeadingLevel.HEADING_2, children: [new TextRun({ text, bold: true })] });
}
function h3(text) {
return new Paragraph({ heading: HeadingLevel.HEADING_3, children: [new TextRun({ text, bold: true })] });
}
function p(text) {
return new Paragraph({ spacing: { after: 120, line: 360 }, children: [new TextRun({ text, size: 22 })] });
}
function bullet(text) {
return new Paragraph({
numbering: { reference: 'bullets', level: 0 },
spacing: { after: 60, line: 360 },
children: [new TextRun({ text, size: 22 })],
});
}
function caption(text) {
return new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 200 },
children: [new TextRun({ text, italics: true, size: 18, color: '888888' })],
});
}
function callout(label, text) {
const border = { style: BorderStyle.SINGLE, size: 1, color: '0969DA' };
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
columnWidths: [9026],
rows: [new TableRow({
cantSplit: true,
children: [new TableCell({
borders: { top: border, bottom: border, left: border, right: border },
width: { size: 9026, type: WidthType.DXA },
shading: { fill: 'EAF2FC', type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [
new Paragraph({ spacing: { after: 40 }, children: [new TextRun({ text: label, bold: true, size: 22, color: '0969DA' })] }),
new Paragraph({ children: [new TextRun({ text, size: 22 })] }),
],
})],
})],
});
}
// 数据统计卡片
function statCard(label, value, color) {
const border = { style: BorderStyle.SINGLE, size: 4, color: color || '0969DA' };
return new TableCell({
borders: { top: border, bottom: border, left: border, right: border },
width: { size: 2256, type: WidthType.DXA },
shading: { fill: 'F5F8FC', type: ShadingType.CLEAR },
margins: { top: 200, bottom: 200, left: 120, right: 120 },
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({ alignment: AlignmentType.CENTER, spacing: { after: 60 }, children: [new TextRun({ text: value, bold: true, size: 40, color: color || '0969DA' })] }),
new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: label, size: 18, color: '6B7785' })] }),
],
});
}
const cjkFont = 'Microsoft YaHei';
const asciiFont = 'Arial';
const fontConfig = { ascii: asciiFont, hAnsi: asciiFont, eastAsia: cjkFont };
const doc = new Document({
styles: {
default: { document: { run: { font: fontConfig, size: 22 } } },
paragraphStyles: [
{ id: 'Heading1', name: 'Heading 1', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 32, bold: true, color: '0969DA', font: fontConfig },
paragraph: { spacing: { before: 360, after: 200 }, outlineLevel: 0 } },
{ id: 'Heading2', name: 'Heading 2', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 28, bold: true, color: '1B232E', font: fontConfig },
paragraph: { spacing: { before: 280, after: 160 }, outlineLevel: 1 } },
{ id: 'Heading3', name: 'Heading 3', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 24, bold: true, color: '3D4D5C', font: fontConfig },
paragraph: { spacing: { before: 200, after: 120 }, outlineLevel: 2 } },
],
},
numbering: {
config: [
{ reference: 'bullets', levels: [{ level: 0, format: LevelFormat.BULLET, text: '\u2022', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: 'bullets2', levels: [{ level: 0, format: LevelFormat.BULLET, text: '\u25E6', alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 1080, hanging: 360 } } } }] },
],
},
sections: [{
properties: {
page: {
size: { width: 11906, height: 16838 },
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 },
},
},
headers: {
default: new Header({
children: [new Paragraph({
alignment: AlignmentType.RIGHT,
children: [new TextRun({ text: '智慧运维系统 · 月度工作总结报告', size: 16, color: '999999', font: fontConfig })],
})],
}),
},
footers: {
default: new Footer({
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: '第 ', size: 16, color: '999999', font: fontConfig }),
new TextRun({ children: [PageNumber.CURRENT], size: 16, color: '999999' }),
new TextRun({ text: ' 页', size: 16, color: '999999', font: fontConfig }),
],
})],
}),
},
children: [
// === 封面 ===
new Paragraph({ spacing: { before: 2400 } }),
new Paragraph({ alignment: AlignmentType.CENTER, spacing: { after: 240 },
children: [new TextRun({ text: '智慧运维系统平台', size: 56, bold: true, color: '0969DA', font: fontConfig })] }),
new Paragraph({ alignment: AlignmentType.CENTER, spacing: { after: 320 },
children: [new TextRun({ text: '月度工作总结报告', size: 44, bold: true, color: '3D4D5C', font: fontConfig })] }),
new Paragraph({ alignment: AlignmentType.CENTER, spacing: { after: 200 },
children: [new TextRun({ text: '( 2026年8月 )', size: 28, color: '6B7785', font: fontConfig })] }),
new Paragraph({ spacing: { before: 1600 } }),
// 信息表
new Table({
width: { size: 60, type: WidthType.PERCENTAGE },
alignment: AlignmentType.CENTER,
columnWidths: [2250, 4050],
rows: [
new TableRow({
children: [
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
shading: { fill: 'F5F8FC', type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '汇 报 人', bold: true, size: 24, color: '3D4D5C', font: fontConfig })] })],
}),
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '葌 昀', size: 24, color: '1B232E', font: fontConfig })] })],
}),
],
}),
new TableRow({
children: [
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
shading: { fill: 'F5F8FC', type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '汇报周期', bold: true, size: 24, color: '3D4D5C', font: fontConfig })] })],
}),
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '2026年8月1日 — 2026年8月31日', size: 24, color: '1B232E', font: fontConfig })] })],
}),
],
}),
new TableRow({
children: [
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
shading: { fill: 'F5F8FC', type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '所属项目', bold: true, size: 24, color: '3D4D5C', font: fontConfig })] })],
}),
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '机器人智慧服务系统', size: 24, color: '1B232E', font: fontConfig })] })],
}),
],
}),
new TableRow({
children: [
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
shading: { fill: 'F5F8FC', type: ShadingType.CLEAR },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '提交日期', bold: true, size: 24, color: '3D4D5C', font: fontConfig })] })],
}),
new TableCell({
borders: { top: { style: BorderStyle.NONE }, bottom: { style: BorderStyle.SINGLE, size: 4, color: 'D6DEE8' }, left: { style: BorderStyle.NONE }, right: { style: BorderStyle.NONE } },
margins: { top: 120, bottom: 120, left: 200, right: 200 },
children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: '2026年9月1日', size: 24, color: '1B232E', font: fontConfig })] })],
}),
],
}),
],
}),
new Paragraph({ spacing: { before: 1600 } }),
new Paragraph({ alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '二〇二六年九月', size: 22, color: '999999', font: fontConfig })] }),
new Paragraph({ children: [new PageBreak()] }),
// === 目录 ===
h1('目 录'),
p('本文档为智慧运维系统平台 2026 年 8 月份工作总结月报,汇总当月在 WebSocket 通信机制优化、控制权限重构、路径规划联调、路由架构升级、设备参数开发、国际化适配、AI 模型升级、APP 端指导测试、软著申报等方面的核心工作成果,并附系统功能截图。'),
new Paragraph({ spacing: { after: 200 } }),
// 目录列表
(() => {
function tocItem(num, title) {
return new Paragraph({
spacing: { after: 120, line: 360 },
indent: { left: 200 },
children: [
new TextRun({ text: num + ' ', bold: true, size: 24, color: '0969DA', font: fontConfig }),
new TextRun({ text: title, size: 24, color: '1B232E', font: fontConfig }),
],
});
}
return [
tocItem('第一章', '本月工作总览'),
tocItem('第二章', '智慧运维平台底层机制优化'),
tocItem('第三章', '苏州算法联调与路径规划'),
tocItem('第四章', '控制权限体系重构与闭环'),
tocItem('第五章', '路由架构升级与组件迭代'),
tocItem('第六章', '设备参数与定时任务功能'),
tocItem('第七章', '视频与日志管理模块'),
tocItem('第八章', '国际化适配与 AI 大模型升级'),
tocItem('第九章', '基础功能模块完善'),
tocItem('第十章', 'APP 端优化指导与测试'),
tocItem('第十一章', '全业务链路闭环测试'),
tocItem('第十二章', '软著申报与文档沉淀'),
tocItem('第十三章', 'Git 提交记录统计'),
tocItem('第十四章', '本月小结与下月计划'),
];
})().reduce((acc, cur) => acc.concat([cur]), []),
new Paragraph({ children: [new PageBreak()] }),
// === 第一章 本月工作总览 ===
h1('第一章 本月工作总览'),
p('2026 年 8 月,围绕智慧运维系统平台稳定性、控制安全性、业务完整性与移动端联调适配四大方向开展系统性工作,持续推进苏州算法团队的路径规划联调,完成 WebSocket 通信机制与控制权限架构的底层重构,落地路由体系升级、设备参数功能、视频日志模块、中英文国际化、AI 模型升级等多项功能迭代,同步指导 APP 端核心功能开发与测试验收,并完成软件著作权申报材料撰写。'),
h2('1.1 核心数据概览'),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
columnWidths: [2256, 2256, 2256, 2258],
rows: [new TableRow({
cantSplit: true,
children: [
statCard('Git 提交次数', '58', '0969DA'),
statCard('功能模块迭代', '10+', '28A745'),
statCard('核心联调里程碑', '3', 'FF8C00'),
statCard('系统界面截图', '18', '8B5CF6'),
],
})],
}),
new Paragraph({ spacing: { after: 200 } }),
h2('1.2 本月工作主线'),
bullet('底层通信机制优化:WebSocket 单页面单连接 + 路由切换自动销毁,彻底解决多页面重复连接、消息错乱、后台心跳堆积'),
bullet('控制权限体系重构:单设备单 Token 唯一占用机制 + 主动释放权限功能,完成 Web/APP 跨端权限交替抢占与释放闭环测试'),
bullet('苏州算法联调:路径规划全流程打通,覆盖设备打点、路径保存、后台规划指令下发、算法回执、地图可视化轨迹绘制'),
bullet('路由架构升级:一级路由整体改造为二级路由体系,完成路由框架适配与跳转逻辑修复'),
bullet('设备参数与定时任务:双端参数修改功能开发与测试、APP 蓝牙模式参数修改、Web 定时任务全流程测试'),
bullet('视频与日志模块:视频批量下载 Node 脚本重构为 Java 接口、日志权限区分展示'),
bullet('国际化与 AI 升级:中英文双语切换覆盖高频业务页面、AI 大模型统一升级为 GPT-5.6'),
bullet('APP 端指导与测试:扫码绑定、蓝牙/非蓝牙模式、参数修改授权管控、视频推拉流、无人机数据展示'),
bullet('软著与文档沉淀:软件著作权申报材料撰写与迭代、iOS 适配技术文档、Web 端路径规划 SOP 文档'),
new Paragraph({ children: [new PageBreak()] }),
// === 第二章 底层机制优化 ===
h1('第二章 智慧运维平台底层机制优化'),
h2('2.1 WebSocket 连接机制优化'),
p('针对系统原有 WebSocket 连接逻辑存在多页面重复连接、消息错乱、后台心跳堆积等问题,本月对 WS 连接逻辑进行深度优化:'),
bullet('实现单页面仅维持一次 WS 连接,避免多页面重复创建连接'),
bullet('页面路由切换时自动销毁当前 WS 连接,杜绝旧连接残留'),
bullet('解决 WS 切换时序差导致的历史数据残留与数据展示异常问题'),
bullet('退出路由时不订阅消息,提升系统整体通信稳定性与性能'),
callout('优化价值', 'WebSocket 机制优化后,系统通信链路更加稳定,消息推送实时性与准确性显著提升,为多端协同、实时监控、告警推送等业务场景提供可靠的底层通信支撑。'),
h2('2.2 实时监控与消息订阅'),
p('结合 WebSocket 机制优化,实时监控页面能够稳定接收设备状态、告警事件、机器位置等实时数据,为运维人员提供准确的一线态势感知。'),
createImage('07_realtime.png'),
caption('图 2-1 实时监控页面 - 实时功率与设备在线率'),
new Paragraph({ children: [new PageBreak()] }),
// === 第三章 苏州算法联调 ===
h1('第三章 苏州算法联调与路径规划'),
h2('3.1 联调背景与目标'),
p('本月持续对接苏州算法团队,开展机器路径规划功能的全流程联调工作。受展会演示设备资源短缺影响,优先完成核心基础联调内容,并支撑苏州现场机器演示调试与保障。'),
h2('3.2 联调里程碑'),
h3('3.2.1 第一步:设备状态界面打点联调成功'),
p('与算法团队完成设备状态界面机器打点功能调试,实现:'),
bullet('机器在线状态正常上报'),
bullet('经纬度数据正常上报与展示'),
bullet('机器实时轨迹打点功能运行正常'),
bullet('设备位置状态精准展示,保障联调基础能力闭环'),
createImage('03_device_status.png'),
caption('图 3-1 设备状态详情页 - 机器经纬度与打点数据'),
h3('3.2.2 第二步:路径规划全链路打通'),
p('完整打通业务链路,实现路径规划功能全流程:'),
bullet('设备打点:在地图上完成机器位置打点与清除打点标志'),
bullet('路径数据保存:将打点数据上传至后台保存'),
bullet('后台规划指令下发:平台向算法端下发路径规划指令'),
bullet('接收算法端回执:接收算法端规划结果回执'),
bullet('地图可视化绘制:在地图上同时绘制规划轨迹与机器实时行走路径'),
p('指令下发成功后,地图上可清晰看到规划路径与机器实时行走轨迹,路径规划功能整体流程跑通、状态正常。'),
h3('3.2.3 第三步:模式适配与显示优化'),
p('根据不同模式显示区域或线段,优化一加载时显示的地图内容,并支持在地图上鼠标悬浮显示机器信息、优化登录用户角色显示等细节体验。'),
createImage('04_wayline.png'),
caption('图 3-2 航线任务页 - 路径规划与可视化'),
callout('联调成果', '路径规划全链路打通,覆盖设备打点、数据保存、指令下发、回执接收、地图可视化绘制五大环节,并支撑苏州现场机器演示顺利落地。'),
new Paragraph({ children: [new PageBreak()] }),
// === 第四章 控制权限体系重构 ===
h1('第四章 控制权限体系重构与闭环'),
h2('4.1 权限架构升级背景'),
p('原有"单用户单设备控制"模式存在多端抢占、权限混乱、权限滞留等问题,无法满足跨端协同控制与设备安全管控需求。本月重构设备抢占控制逻辑,从底层保证设备控制唯一性与安全性。'),
h2('4.2 单设备单 Token 唯一占用机制'),
p('将原有控制模式升级为单设备单 Token 唯一占用机制:'),
bullet('一台设备同一时间仅被一个有效连接控制,彻底解决多端抢占问题'),
bullet('控制权限修改不再需要判断 Web 是否有权限,简化权限判定逻辑'),
bullet('新增主动释放权限功能,支持用户主动让出设备控制权'),
bullet('页面切换/杀死页面时自动释放控制权限,避免权限滞留'),
h2('4.3 跨端闭环测试'),
p('完成权限逻辑的全场景闭环测试,验证权限释放与抢占逻辑准确、稳定、无残留占用:'),
bullet('Web 不同账号切换场景:权限正确释放与抢占'),
bullet('Web 同账号页面切换场景:权限随路由切换自动释放'),
bullet('Web 与 APP 跨端权限交替抢占与释放场景:跨端协同正常'),
p('控制权限重构为后续与苏州团队深度联调、实现跨端权限联动与设备协同控制筑牢了基础。'),
createImage('14_system.png'),
caption('图 4-1 系统设置 - 权限管控与基础配置'),
new Paragraph({ children: [new PageBreak()] }),
// === 第五章 路由架构升级与组件迭代 ===
h1('第五章 路由架构升级与组件迭代'),
h2('5.1 路由架构整体优化升级'),
p('根据团队优化建议,完成系统路由结构重构:'),
bullet('将原有一级路由改造为二级路由体系,页面层级结构更加清晰规范'),
bullet('完成二级菜单初步实现、配置与机器人路由适配'),
bullet('针对性修复更换路由框架带来的适配问题'),
bullet('重点优化设备总览、设备状态详情页面路由跳转逻辑,解决跳转异常、页面定位不准等问题'),
createImage('02_device_overview.png'),
caption('图 5-1 设备总览页 - 二级路由体系下的设备管理'),
h2('5.2 路由组件拆分与性能优化'),
p('完成路由组件拆分优化,精简冗余代码、优化加载逻辑:'),
bullet('路由组件按需拆分,提升页面路由跳转速度'),
bullet('优化整体页面访问流畅度'),
bullet('登录默认选中机制,提升首次访问体验'),
bullet('优化设备管理界面,将 5 个子页面抽离为独立组件,实现组件轻量化'),
bullet('优化设备参数弹窗 loading 效果与两个组件内弹窗的数据影响'),
h2('5.3 设备管理子模块重构'),
p('完成设备管理 tab 重构,针对状态界面视频停止与状态信息解耦进行优化,让数据展示更清晰,业务解耦更彻底。'),
createImage('05_robot_task.png'),
caption('图 5-2 机器人任务页 - 设备任务调度与管理'),
new Paragraph({ children: [new PageBreak()] }),
// === 第六章 设备参数与定时任务 ===
h1('第六章 设备参数与定时任务功能'),
h2('6.1 设备参数编辑功能迭代开发与测试'),
p('完成 Web 端与 APP 端设备参数修改功能开发及测试工作:'),
h3('6.1.1 权限管控机制'),
bullet('双端新增设备参数修改能力,支持通过授权机制管控参数修改权限'),
bullet('Web 端可自定义配置设备参数可修改时长'),
bullet('双端根据授权信息自动判断用户操作权限,精准控制参数编辑功能可用性'),
bullet('根据身份判断能不能选中相关参数项,权限不足时不可编辑'),
h3('6.1.2 交互体验优化'),
bullet('参数滑块联动展示效果,操作更直观'),
bullet('设备参数组件抽离重构,实现组件轻量化,优化页面加载性能'),
bullet('新增 loading 加载状态,完善交互体验'),
bullet('派单流程优化:派单时选择接收人员,根据身份判断能不能选中'),
h3('6.1.3 APP 端蓝牙模式适配'),
bullet('完成 APP 端蓝牙模式修改设备参数功能开发与测试'),
bullet('适配不同设备操作场景,保障无网络/弱网环境下的设备管控能力'),
createImage('06_video.png'),
caption('图 6-1 视频管理页 - 设备视频文件批量下载'),
h2('6.2 定时任务功能测试'),
p('完成 Web 端定时任务功能全流程测试:'),
bullet('任务创建与配置流程校验'),
bullet('任务执行逻辑验证'),
bullet('任务启停控制测试'),
bullet('周期运行逻辑校验'),
bullet('保障定时任务功能稳定可用,满足平台自动化运维需求'),
new Paragraph({ children: [new PageBreak()] }),
// === 第七章 视频与日志管理模块 ===
h1('第七章 视频与日志管理模块'),
h2('7.1 视频管理模块改造升级'),
p('完成视频管理界面功能开发,支持批量下载设备本地存储视频文件。本次改造重点包括:'),
bullet('将原有 Node 脚本实现的下载逻辑重构为 Java 接口,统一后端技术栈'),
bullet('提升服务统一性、稳定性和可维护性'),
bullet('完成视频接入接口对接'),
bullet('设备管理 tab 重构,加上 flv 预览能力(仅供测试,正式建议下载使用)'),
h2('7.2 日志管理模块开发'),
p('完成日志管理界面功能开发,实现权限区分展示:'),
bullet('管理员可查看服务端运行日志'),
bullet('便于后续问题排查与系统运维'),
bullet('目前相关界面已完成开发,待后续对接完整接口'),
createImage('17_profile.png'),
caption('图 7-1 个人中心 - 用户权限与日志查看入口'),
new Paragraph({ children: [new PageBreak()] }),
// === 第八章 国际化与 AI 升级 ===
h1('第八章 国际化适配与 AI 大模型升级'),
h2('8.1 系统中英文国际化适配'),
p('完成平台核心业务界面的中英文双语切换功能开发:'),
bullet('覆盖日常使用高频页面,满足多语言使用场景'),
bullet('登录页右上角支持中英文一键切换'),
bullet('针对静态页面暂未做国际化接入,考虑到后续静态页面结构和内容仍会频繁调整,暂不提前适配,避免重复开发与无效迭代,合理节约开发成本'),
createImage('00_login.png'),
caption('图 8-1 登录页 - 中英文切换入口'),
h2('8.2 AI 大模型版本迭代升级'),
p('根据郭老师工作部署及项目智能化迭代要求,完成项目 AI 大模型版本升级替换:'),
bullet('将原有模型统一更新为 GPT-5.6 版本'),
bullet('新版本模型有效优化推理精度、交互响应效果与业务适配性'),
bullet('进一步提升平台智能化服务能力'),
bullet('为后续各类智能业务场景落地提供可靠的技术支撑'),
createImage('10_ai.png'),
caption('图 8-2 AI 诊断分析页 - 大模型升级后的智能分析能力'),
new Paragraph({ children: [new PageBreak()] }),
// === 第九章 基础功能模块完善 ===
h1('第九章 基础功能模块完善'),
h2('9.1 用户与角色管理优化'),
p('优化用户与角色模块,根据管理员的角色获取名下用户,让权限管理、用户管理体系更清晰规整:'),
bullet('用户角色概览功能开发'),
bullet('角色权限概览功能开发'),
bullet('优化页面展示逻辑与数据渲染效果'),
bullet('修复 admin 可以看到所有用户的问题,按角色严格管控可见范围'),
bullet('地图中鼠标悬浮显示机器信息时,优化显示登录用户的角色'),
createImage('15_users.png'),
caption('图 9-1 用户管理页 - 用户体系与权限概览'),
createImage('16_roles.png'),
caption('图 9-2 角色管理页 - 角色权限概览'),
h2('9.2 电站地址功能接入'),
p('完成电站地址功能接入,适配多场站运维管理场景:'),
bullet('支持自定义修改场站地址'),
bullet('切换不同电站时可精准匹配、展示对应场站位置'),
bullet('修复地图地址显示相关问题'),
bullet('修改名称和电站地址,让场站标识更清晰'),
h2('9.3 控制台报错信息清理'),
p('针对性优化代码消除控制台的报错信息:'),
bullet('修复地图图标大小在初始化时长宽 -1 的警告'),
bullet('优化 mqtt 退出路由时不订阅消息,避免不必要的报错'),
bullet('提升整体代码质量与运行稳定性'),
new Paragraph({ children: [new PageBreak()] }),
// === 第十章 APP 端优化指导 ===
h1('第十章 APP 端优化指导与测试'),
h2('10.1 APP 端功能优化指导'),
p('本月持续跟进机器 APP 端优化迭代与测试工作,全程指导 APP 端完成核心功能适配:'),
bullet('路径规划全套业务流程适配与调试,保证移动端与 Web 端业务逻辑统一、交互闭环'),
bullet('扫码绑定设备功能优化整改'),
bullet('蓝牙/非蓝牙模式适配'),
bullet('授权管控设备参数修改功能开发'),
bullet('视频推拉流控制功能开发与调试,完善设备视频实时操控能力'),
bullet('无人机实时数据展示逻辑优化,提升数据刷新实时性与页面展示效果'),
h2('10.2 APP 端测试验收情况'),
p('对优化后的功能进行全面测试,校验场景适配性、权限逻辑及操作流畅度:'),
bullet('本月针对本月遗留问题进行专项攻坚,绝大部分测试点已完成验证,整体功能基本达标'),
bullet('剩余约 10% 测试内容仍存在轻微问题,后续将持续跟进排查、优化修复,完成全量测试闭环'),
bullet('及时发现问题并反馈、跟进整改落地,保障 APP 端各项核心功能正常运行'),
bullet('进一步提升移动端设备运维操作的便捷性与稳定性'),
callout('移动端价值', 'APP 端作为现场运维人员的随身工具,承担扫码绑定、蓝牙管控、视频操控、数据展示等核心能力,本月完成全部核心功能指导与 90% 测试验证。'),
new Paragraph({ children: [new PageBreak()] }),
// === 第十一章 全业务链路闭环测试 ===
h1('第十一章 全业务链路闭环测试'),
h2('11.1 告警工单全流程链路测试'),
p('完成系统告警、工单、任务全流程链路逻辑测试:'),
bullet('依据系统配置规则,校验告警触发后自动生成工单的准确性'),
bullet('核对告警列表与工单列表的数据一致性'),
bullet('告警闭环逻辑验证:关联告警的工单完成或关闭后,对应告警自动消除、停止持续触发'),
bullet('若设备仍存在异常、处于告警状态,系统可重新触发告警,逻辑符合业务预期'),
createImage('09_alerts.png'),
caption('图 11-1 告警中心 - 告警列表与工单联动'),
h2('11.2 告警钉钉推送测试'),
p('完成告警钉钉推送功能测试:'),
bullet('支持各场站独立配置开启/关闭钉钉推送权限'),
bullet('实现告警消息灵活推送,满足多场站差异化通知需求'),
h2('11.3 工单派发功能迭代优化'),
p('新增平台工单手动派发逻辑:'),
bullet('支持管理员将各类运维工单定向指派给指定用户'),
bullet('用户端可正常展示、接收被派发的工单'),
bullet('完善了平台工单分配管理机制'),
bullet('手动派发功能已调试完成,后续将持续迭代开发工单自动派发功能'),
createImage('12_workorder.png'),
caption('图 11-2 工单任务页 - 工单派发与全生命周期管理'),
h2('11.4 设备参数配置功能测试'),
p('完成平台设备参数配置功能测试:'),
bullet('系统支持自定义配置设备轮胎增益系数、运行速度等核心设备参数'),
bullet('页面配置逻辑、参数保存功能运行正常'),
bullet('受下位机未完成全量测试影响,该模块整体联调工作暂未完成,待下位机测试收尾后继续完善'),
h2('11.5 剩余待测试工作'),
p('当前平台核心链路测试基本完成,后续需结合实际工单场景,完成平台向机器下发任务的全流程测试,补齐业务链路测试闭环。'),
new Paragraph({ children: [new PageBreak()] }),
// === 第十二章 软著申报与文档沉淀 ===
h1('第十二章 软著申报与文档沉淀'),
h2('12.1 软件著作权申报材料撰写'),
p('结合智慧运维平台现有功能、业务架构与技术实现,独立完成软件著作权申报材料的撰写:'),
bullet('梳理系统创新点、功能架构与应用场景'),
bullet('根据审核要求及修改建议持续迭代优化内容'),
bullet('推进软著申报进度,助力后续顺利审核通过'),
callout('知识产权价值', '软件著作权申报是平台技术成果的重要知识产权沉淀,有助于提升项目技术壁垒,保护核心代码资产。'),
h2('12.2 iOS 适配技术文档'),
p('协助指导 APP 苹果端相关功能实现:'),
bullet('梳理 iOS 端调试要点'),
bullet('独立整理并输出 ios.md 技术文档'),
bullet('统一调试规范、记录适配细节'),
bullet('方便后续迭代对接、问题复盘与维护调试'),
bullet('有效降低后续对接成本'),
h2('12.3 Web 端路径规划 SOP 文档'),
p('梳理 Web 端路径规划完整操作流程,编写标准化 SOP 操作文档:'),
bullet('统一操作规范'),
bullet('便于后续迭代维护、人员交接与业务落地'),
h2('12.4 新增 TodoList 页面建设'),
p('完成平台 TodoList 页面的搭建建设工作:'),
bullet('在日常测试与功能迭代过程中,系统梳理汇总各类待优化、待开发、待测试的后续任务点'),
bullet('统一录入 TodoList 页面进行集中管理'),
bullet('通过该页面可清晰沉淀后续迭代需求、未完成工作及长期优化规划'),
bullet('实现任务可视化、条理化管理,为后续工作推进、任务落地、迭代规划提供清晰的参考依据'),
bullet('有效提升工作统筹效率'),
new Paragraph({ children: [new PageBreak()] }),
// === 第十三章 Git 提交记录统计 ===
h1('第十三章 Git 提交记录统计'),
p('本月(2026-08-01 至 2026-08-31)项目代码仓库共提交 58 次,提交者覆盖项目主体开发人员。以下为按时间倒序的关键提交记录摘要,反映本月功能开发与修复节奏。'),
h2('13.1 关键提交节点摘录'),
bullet('2026-08-31:修复地图鼠标悬浮显示机器、admin 用户可见范围、控制台警告信息、地图地址显示等多项问题'),
bullet('2026-08-31:优化 mqtt 退出路由不订阅消息,消除控制台报错信息'),
bullet('2026-08-28:和算法联调显示规划路径并显示实时路径成功;根据模式显示区域还是线;优化一加载显示的地图内容'),
bullet('2026-08-25:地图打点和清除打点标志;测权限控制释放权限,优化 WS 连接'),
bullet('2026-08-21:用户角色概览;基础设置中角色概览;修改名称和电站地址;电站地址接入'),
bullet('2026-08-20:杀死页面和切换页面释放控制权限;控制权限修改,不需要判断 Web 是否有权限'),
bullet('2026-08-20:优化 WS 切换时候的时序差导致遗留上次的消息'),
bullet('2026-08-19:和算法测试成功第一步,状态界面看到经纬度信息和保存可以成功;中英文优化;路由组件拆分;登录默认选中'),
bullet('2026-08-14:中英文切换根据已有功能已经基本完善'),
bullet('2026-08-12:中英文切换初始化;软著文档;设备管理 tab 重构,加上 flv 预览'),
bullet('2026-08-10:视频接入接口;增加视频管理和日志管理;文档增加'),
bullet('2026-08-07:优化设备管理界面将 5 个子页面抽离出组件轻量化,优化设备参数弹窗 loading 效果'),
bullet('2026-08-06:优化用户与角色模块根据管理员角色获取名下用户;优化状态界面视频停止和状态信息解耦;增加推拉流播放和停止;优化派单选择接收人员;两个地方的设备参数组件加上授权功能'),
bullet('2026-08-05:设备参数需要滑块'),
bullet('2026-08-04:所有传 orgId 的地方修改;优化详情跳转'),
bullet('2026-08-03:根据二级路由优化控制状态界面;二级菜单优化完成;二级菜单配置;机器人的路由 OK 了;二级菜单初步实现'),
h2('13.2 提交记录反映的工作主线'),
p('从提交时间线可以看出本月工作呈现以下节奏:'),
bullet('8 月上旬(8/3-8/12):路由架构升级、用户角色模块优化、设备参数滑块与授权、视频日志管理模块、中英文切换、软著文档'),
bullet('8 月中旬(8/14-8/21):中英文完善、路由组件拆分、WS 时序差优化、权限控制重构、电站地址接入、角色概览'),
bullet('8 月下旬(8/25-8/31):权限释放测试与 WS 连接优化、地图打点与算法联调、地图显示与机器悬浮显示优化、控制台报错清理'),
createImage('01_home.png'),
caption('图 13-1 系统总览首页 - 平台整体运行态势'),
new Paragraph({ children: [new PageBreak()] }),
// === 第十四章 本月小结与下月计划 ===
h1('第十四章 本月小结与下月计划'),
h2('14.1 本月工作小结'),
p('本月工作覆盖智慧运维系统平台的底层机制、业务功能、移动端协同、知识产权四大维度,整体呈现"底座加固、业务闭环、移动协同、知识产权沉淀"四大特征。'),
h3('14.1.1 底座加固'),
bullet('WebSocket 单页面单连接 + 路由切换自动销毁,通信稳定性显著提升'),
bullet('控制权限单设备单 Token 唯一占用,跨端协同与权限释放机制完善'),
bullet('路由架构升级为二级路由体系,页面层级更清晰、跳转更顺畅'),
h3('14.1.2 业务闭环'),
bullet('路径规划全链路打通,与苏州算法团队联调成功'),
bullet('设备参数双端开发完成、APP 蓝牙模式适配'),
bullet('视频管理 Java 接口重构、日志权限区分展示'),
bullet('告警工单全流程闭环测试通过、工单手动派发功能上线'),
h3('14.1.3 移动协同'),
bullet('APP 端路径规划、扫码绑定、蓝牙/非蓝牙模式、参数授权、视频推拉流、无人机数据展示等核心功能指导与 90% 测试验证'),
bullet('iOS 适配技术文档沉淀,降低后续对接成本'),
h3('14.1.4 知识产权与智能化'),
bullet('软件著作权申报材料撰写与迭代'),
bullet('AI 大模型统一升级至 GPT-5.6,智能化能力进一步提升'),
bullet('中英文国际化覆盖高频业务页面'),
bullet('Web 端路径规划 SOP 文档与 TodoList 任务管理页面建设'),
h2('14.2 下月工作计划'),
p('基于本月工作成果与遗留事项,下月将重点推进以下方向:'),
bullet('路径规划联调收尾:完成与苏州团队的剩余联调内容,覆盖更多业务场景'),
bullet('设备参数联调:等待下位机完成全量测试后,继续完善设备参数配置模块整体联调'),
bullet('APP 端剩余 10% 测试:完成 APP 端全量测试闭环,保障移动端稳定可用'),
bullet('平台下发任务全流程测试:结合实际工单场景,完成平台向机器下发任务的全流程测试'),
bullet('工单自动派发功能:在手动派发基础上迭代开发自动派发能力,提升运维自动化效率'),
bullet('国际化覆盖扩展:根据静态页面调整情况,逐步推进静态页面国际化适配'),
bullet('软著申报跟进:根据审核反馈持续优化申报材料,推进顺利审核通过'),
callout('结语', '本月围绕"稳定、安全、协同、闭环"四大关键词开展工作,平台底座更加稳固、业务链路更加完整、移动协同更加顺畅、知识产权沉淀更加扎实。后续将持续以业务价值为导向,推进各项功能迭代落地,持续提升智慧运维平台的综合能力。'),
// 附录:更多系统截图
new Paragraph({ children: [new PageBreak()] }),
h1('附录 系统功能截图集'),
p('以下为本月工作过程中涉及的系统功能截图集,作为本月工作产出的可视化补充材料。'),
h2('A.1 总览与监控'),
createImage('08_monitor.png'),
caption('图 A-1 监控中心 - 设备实时监控视图'),
h2('A.2 设备管理'),
createImage('11_clean.png'),
caption('图 A-2 清洗优化页 - 智能清洗策略'),
h2('A.3 报表与系统'),
createImage('13_report.png'),
caption('图 A-3 报表中心 - 多维度报表输出'),
createImage('14_system.png'),
caption('图 A-4 系统设置 - 基础设置入口'),
],
}],
});
Packer.toBuffer(doc).then((buffer) => {
const outPath = path.join(__dirname, '智慧运维系统平台-月度工作总结报告-2026年8月-葌昀.docx');
fs.writeFileSync(outPath, buffer);
console.log('✓ 月度报告已生成:', outPath);
const stats = fs.statSync(outPath);
console.log(' 文件大小:', (stats.size / 1024).toFixed(2), 'KB');
}).catch((err) => {
console.error('✗ 生成失败:', err);
process.exit(1);
});