# -*- coding: utf-8 -*- """Generate the User Manual Word Document for the Robot Smart Service System.""" import os import sys from docx import Document from docx.shared import Inches, Pt, Cm, RGBColor, Emu from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT from docx.enum.section import WD_ORIENT from docx.oxml.ns import qn from docx.oxml import OxmlElement # ---- config ---- SCREENSHOT_DIR = r"D:\code\机器人智慧服务系统\.workbuddy\screenshots" OUTPUT_PATH = r"D:\code\机器人智慧服务系统\用户手册-机器人智慧服务系统.docx" TITLE = "光伏机器人环境感知服务平台" SUBTITLE = "用户操作手册" VERSION = "V1.0" DATE = "2026年8月" # ---- helpers ---- def set_cell_shading(cell, color): """Set cell background color.""" tc = cell._tc tcPr = tc.get_or_add_tcPr() shading = OxmlElement('w:shd') shading.set(qn('w:fill'), color) shading.set(qn('w:val'), 'clear') tcPr.append(shading) def add_shot(doc, image_path, caption, width=Inches(5.8)): """Add a centered screenshot with caption.""" abs_path = os.path.join(SCREENSHOT_DIR, image_path) if not os.path.exists(abs_path): doc.add_paragraph(f"[截图未找到: {image_path}]") return # center the image p = doc.add_paragraph() p.alignment = WD_ALIGN_PARAGRAPH.CENTER run = p.add_run() run.add_picture(abs_path, width=width) # caption cap = doc.add_paragraph() cap.alignment = WD_ALIGN_PARAGRAPH.CENTER cap_run = cap.add_run(caption) cap_run.font.size = Pt(10) cap_run.font.color.rgb = RGBColor(100, 100, 100) cap_run.italic = True doc.add_paragraph("") # spacer def make_heading(doc, text, level=1): h = doc.add_heading(text, level=level) return h def make_body(doc, text): p = doc.add_paragraph(text) p.paragraph_format.space_after = Pt(6) p.paragraph_format.line_spacing = 1.35 return p def make_bullet(doc, text, bold_prefix=""): p = doc.add_paragraph(style='List Bullet') if bold_prefix: run = p.add_run(bold_prefix) run.bold = True p.add_run(text) else: p.add_run(text) return p def set_narrow_margins(doc): for section in doc.sections: section.top_margin = Cm(2.0) section.bottom_margin = Cm(2.0) section.left_margin = Cm(2.54) section.right_margin = Cm(2.54) def make_cover(doc): # blank lines for vertical centering for _ in range(6): doc.add_paragraph("") # Title p = doc.add_paragraph() p.alignment = WD_ALIGN_PARAGRAPH.CENTER run = p.add_run(TITLE) run.font.size = Pt(28) run.bold = True run.font.color.rgb = RGBColor(22, 119, 255) # Subtitle p2 = doc.add_paragraph() p2.alignment = WD_ALIGN_PARAGRAPH.CENTER run2 = p2.add_run(SUBTITLE) run2.font.size = Pt(20) run2.font.color.rgb = RGBColor(80, 80, 80) doc.add_paragraph("") # version / date p3 = doc.add_paragraph() p3.alignment = WD_ALIGN_PARAGRAPH.CENTER run3 = p3.add_run(f"版本 {VERSION}   {DATE}") run3.font.size = Pt(12) run3.font.color.rgb = RGBColor(120, 120, 120) # copyright line doc.add_paragraph("") p4 = doc.add_paragraph() p4.alignment = WD_ALIGN_PARAGRAPH.CENTER run4 = p4.add_run("机器人智慧服务平台 · 产品文档") run4.font.size = Pt(11) run4.font.color.rgb = RGBColor(150, 150, 150) doc.add_page_break() # ============================================================ def build_doc(): doc = Document() style = doc.styles['Normal'] style.font.name = '微软雅黑' style.font.size = Pt(11) style.element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑') set_narrow_margins(doc) # ---- COVER ---- make_cover(doc) # ==================== 1. 系统概述 ==================== make_heading(doc, "一、系统概述", 1) make_body(doc, "机器人智慧服务平台(正式名称:光伏机器人环境感知服务平台)是一个面向光伏电站场景的综合性智能管理平台。系统将巡检机器人、无人机、视频监控、告警处理与运维工单整合到统一 Web 控制台中,为运维人员提供设备管理、实时监控、视频回传、状态预警、AI 诊断分析、清洗优化、报表中心与视频下载等一站式能力。") make_heading(doc, "1.1 系统架构", 2) make_body(doc, "系统采用前后端分离的 B/S 架构,前端基于 React 19 + TypeScript + Vite 6 构建为单页应用(SPA),通过四条独立通信通道对接后端的 API、MQTT、WebSocket 与 GeoServer 服务:") chans = [ ("HTTP / REST", "Axios 实例,处理用户管理、设备管理、工单、报表等业务接口"), ("MQTT over WebSocket", "设备遥测数据通道,上行推送机器人实时位置、状态、传感器数据"), ("WebSocket", "设备控制通道,下发行走/执行指令、获取控制权、保活"), ("WebRTC", "视频回传通道,无人机/机器人摄像头实时画面推流"), ] for name, desc in chans: make_bullet(doc, desc, f"{name}:") make_heading(doc, "1.2 技术栈", 2) tech = [ ["框架", "React 19 + TypeScript"], ["构建工具", "Vite 6"], ["UI 组件", "Ant Design 5 + TailwindCSS 4"], ["状态管理", "Redux Toolkit(user / station 切片)"], ["路由", "React Router DOM 7(全路由懒加载)"], ["3D / GIS", "Cesium(三维地图、设备轨迹与场站可视化)"], ["图表", "ECharts 6 / Recharts / @ant-design/charts"], ["实时通信", "MQTT / WebSocket / WebRTC / Socket.io"], ] table = doc.add_table(rows=len(tech)+1, cols=2, style='Light Grid Accent 1') table.alignment = WD_TABLE_ALIGNMENT.CENTER hdr = table.rows[0].cells hdr[0].text = "层级" hdr[1].text = "技术选型" for hc in hdr: for p in hc.paragraphs: for r in p.runs: r.bold = True for i, (k, v) in enumerate(tech): table.rows[i+1].cells[0].text = k table.rows[i+1].cells[1].text = v make_heading(doc, "1.3 角色权限", 2) make_body(doc, "系统支持三级角色权限控制(RBAC):") roles = [ ("管理员(admin)", "拥有全部功能权限,可进行系统设置、用户管理、角色管理、菜单配置、组织管理等"), ("操作员(operator)", "可进行设备操作、工单处理、告警确认、AI 诊断、报表查看等业务操作"), ("观察者(viewer)", "只读权限,仅可查看总览、实时监控、视频等页面,不可操作设备或修改数据"), ] for rn, rd in roles: make_bullet(doc, rd, f"{rn}:") doc.add_page_break() # ==================== 2. 登录与导航 ==================== make_heading(doc, "二、登录与系统导航", 1) add_shot(doc, "00_login.png", "图 2-1 系统登录界面(左侧为账号密码表单,右侧为产品形象图)") make_heading(doc, "2.1 登录操作", 2) make_body(doc, "打开系统后进入登录页面,操作步骤如下:") steps = [ "在左侧登录表单输入用户名(账号);", "输入登录密码;", '勾选"我已阅读并同意用户协议和隐私政策"复选框;', '点击蓝色"登录"按钮。', ] for s in steps: make_bullet(doc, s) make_body(doc, "登录成功后,系统自动跳转至首页总览页面。登录态有效期由服务端控制;超时或登录态失效时,系统会自动弹出提示并跳回登录页。") make_heading(doc, "2.2 系统导航", 2) make_body(doc, "登录后进入主界面,左侧为动态侧边栏菜单(根据登录用户角色的权限加载),顶部栏包含当前时间、场站选择下拉框、全屏控制按钮、用户头像与退出操作。主要导航模块说明如下:") nav_items = [ ("总览首页", "聚合展示设备状态、告警、作业统计等概览数据"), ("设备管理", "设备总览、状态监控、航线任务、机器人任务"), ("实时监控", "基于 Cesium 3D 地图的设备轨迹与状态实时渲染"), ("视频监控", "多路无人机/机器人视频回传与在线查看"), ("告警中心", "实时告警、历史告警、告警统计、告警规则与订阅管理"), ("AI 诊断", "基于热成像数据的 AI 分析诊断"), ("清洗优化", "光伏板清洗任务规划与优化"), ("工单任务", "运维工单的全生命周期管理"), ("报表中心", "运行数据统计报表的查看与导出"), ("系统设置", "基础设置、用户与角色、菜单、组织、场站、设备接入、系统维护、日志等"), ] for name, desc in nav_items: make_bullet(doc, desc, f"{name}:") doc.add_page_break() # ==================== 3. 首页总览 ==================== make_heading(doc, "三、首页总览", 1) add_shot(doc, "01_home.png", "图 3-1 首页总览——聚合展示设备状态、告警概览、作业统计") make_body(doc, "首页总览为系统默认登录后展示的仪表盘页面,以卡片和图表形式聚合呈现以下核心信息:") items = [ ("设备状态概览", "在线/离线/告警设备数量统计,支持按场站过滤"), ("告警趋势与分布", "近期告警数量折线图、告警类型分布饼图"), ("作业统计", "当日/本周/本月巡检任务完成率、航线执行统计"), ("快捷入口", "常用功能的一键跳转卡片"), ] for t, d in items: make_bullet(doc, d, f"{t}:") make_body(doc, "顶部的场站选择下拉框支持在不同光伏场站之间快速切换,所有页面数据均基于当前选中场站进行过滤展示。") doc.add_page_break() # ==================== 4. 设备管理 ==================== make_heading(doc, "四、设备管理", 1) make_body(doc, "设备管理是系统的核心模块之一,包含设备总览、设备状态、航线任务、机器人任务四个子页面,覆盖巡检设备及机器人的全生命周期管理。") make_heading(doc, "4.1 设备总览", 2) add_shot(doc, "02_device_overview.png", "图 4-1 设备总览——地图/列表多视图展示设备分布") make_body(doc, "设备总览页面以地图视图和列表视图双模式展示当前场站下所有已接入设备的分布与基本信息。支持按设备类型、状态筛选,点击具体设备可进入详细控制面板。") make_heading(doc, "4.2 设备状态", 2) add_shot(doc, "03_device_status.png", "图 4-2 设备状态——在线状态与实时参数监控") make_body(doc, "设备状态页面以表格形式实时展示每台设备的在线状态、电池电量、信号强度、定位质量、当前任务等关键运行参数。支持批量操作与过滤搜索。") doc.add_page_break() # ==================== 5. 任务管理 ==================== make_heading(doc, "五、任务管理", 1) make_heading(doc, "5.1 航线任务", 2) add_shot(doc, "04_wayline.png", "图 5-1 航线任务——创建与调度巡检航线") make_body(doc, "航线任务页面用于规划和管理无人机/机器人的巡检航线。操作员可以在地图上绘制巡检航点、设置飞行高度与速度、配置拍摄参数(云台角度、拍照间隔等),创建航线并下发至指定设备执行。航线支持一键复用、批量调度和历史航线回放。") make_heading(doc, "5.2 机器人任务", 2) add_shot(doc, "05_robot_task.png", "图 5-2 机器人任务——任务编排与执行监控") make_body(doc, "机器人任务页面提供对地面巡检机器人的任务编排与管理。支持创建定时巡检任务、临时指定目标点位任务、设备自主巡检任务等多种任务类型。页面以时间线形式展示任务执行过程,支持查看任务详情、暂停/继续/取消任务等操作。") doc.add_page_break() # ==================== 6. 视频与实时监控 ==================== make_heading(doc, "六、视频与实时监控", 1) make_heading(doc, "6.1 在线视频", 2) add_shot(doc, "06_video.png", "图 6-1 在线视频——多路 WebRTC 视频流实时查看") make_body(doc, "在线视频页面支持同时查看多路无人机/机器人摄像头的实时画面。系统基于 WebRTC / Agora RTC / 火山引擎 RTC 等多种视频方案,确保低延迟视频回传。用户可以自由调整视频窗口布局(单路、2×2、3×3 等多分屏模式),并通过视频下载页面获取历史录像。") make_heading(doc, "6.2 实时监控(Cesium 3D 地图)", 2) add_shot(doc, "07_realtime.png", "图 6-2 实时监控——Cesium 三维地图上的设备轨迹与状态") make_body(doc, "实时监控页面基于 Cesium 三维 GIS 引擎,在三维地图上实时渲染所有在线设备的位置、运动轨迹和状态信息。设备图标随 MQTT 遥测数据动态更新,支持视角旋转/缩放、点击设备查看详情、轨迹回放等功能。") make_heading(doc, "6.3 视频监控", 2) add_shot(doc, "08_monitor.png", "图 6-3 视频监控——多路视频监控大屏") make_body(doc, "视频监控页面为全屏监控模式,适合投放大屏使用。支持多路视频同时播放、视频墙布局切换、画面截图与录像控制。") doc.add_page_break() # ==================== 7. 告警中心 ==================== make_heading(doc, "七、告警中心", 1) add_shot(doc, "09_alerts.png", "图 7-1 告警中心——多维度告警管理") make_body(doc, "告警中心提供全生命周期的告警管理能力,包含以下子功能模块:") alert_items = [ ("实时告警", "滚动展示当前未处理的活跃告警,支持一键确认/静音/转工单"), ("历史告警", "按时间范围、告警级别、设备等条件查询已处理告警记录"), ("告警统计", "告警趋势折线图、级别分布、设备 TOP 排行等可视化分析"), ("告警规则", "自定义告警触发条件(如电量低于阈值、设备离线超时等)"), ("告警订阅", "订阅指定设备/类型的告警,通过站内信或第三方渠道通知"), ] for t, d in alert_items: make_bullet(doc, d, f"{t}:") doc.add_page_break() # ==================== 8. AI 诊断分析 ==================== make_heading(doc, "八、AI 诊断分析", 1) add_shot(doc, "10_ai.png", "图 8-1 AI 诊断分析——热成像异常检测与分析") make_body(doc, "AI 诊断分析模块利用深度学习算法对无人机/机器人采集的热成像数据进行自动分析,识别光伏板的异常热斑、隐裂、PID 衰减等缺陷。主要功能包括:") ai_items = [ "热成像图片上传与自动标注", "缺陷类型 AI 识别(热斑、隐裂、接线盒异常等)", "缺陷位置在组串中的精确定位", "缺陷严重程度评级与修复建议", "历史诊断报告查询与对比", ] for item in ai_items: make_bullet(doc, item) doc.add_page_break() # ==================== 9. 清洗优化 ==================== make_heading(doc, "九、清洗优化", 1) add_shot(doc, "11_clean.png", "图 9-1 清洗优化——光伏板清洗任务规划") make_body(doc, "清洗优化模块用于光伏板的清洗任务规划与管理。系统根据设备巡检数据和环境因素(积灰程度、降雨预报等),智能推荐清洗优先级和清洗方案。主要功能包括:") clean_items = [ "清洗需求评估——基于巡检图像分析积灰程度,生成清洗建议", "清洗任务排程——按清洗优先级和设备可用窗口自动排期", "清洗记录管理——记录每次清洗的时间、方式、效果评估", "清洗效果对比——清洗前后的发电效率/热成像对比分析", ] for item in clean_items: make_bullet(doc, item) doc.add_page_break() # ==================== 10. 工单任务 ==================== make_heading(doc, "十、工单任务", 1) add_shot(doc, "12_workorder.png", "图 10-1 工单任务——运维工单全流程管理") make_body(doc, "工单任务模块提供运维工单的全生命周期管理,覆盖从创建到关闭的完整流程。支持以下操作:") wo_items = [ ("创建工单", "手工创建运维工单,或从告警一键转工单"), ("派发与接单", "管理员将工单指派给指定操作员,操作员确认接单"), ("执行跟踪", "记录工单处理过程,可关联设备控制命令与处理备注"), ("闭环验收", "操作员提交完工报告,管理员审核验收后关闭工单"), ("工单统计", "按时间、状态、处理人等维度统计工单处理效率"), ] for t, d in wo_items: make_bullet(doc, d, f"{t}:") make_body(doc, "工单支持状态流转:待处理 → 处理中 → 待验收 → 已完成/已关闭,各阶段均有操作日志记录。") doc.add_page_break() # ==================== 11. 报表中心 ==================== make_heading(doc, "十一、报表中心", 1) add_shot(doc, "13_report.png", "图 11-1 报表中心——运营统计报表查看与导出") make_body(doc, "报表中心提供多维度的运营数据统计与报表导出功能:") rpt_items = [ "巡检报表——按日/周/月统计巡检完成率、异常发现率", "设备报表——设备在线率、故障率、任务执行统计", "告警报表——告警数量趋势、级别分布、响应时效分析", "清洗报表——清洗任务执行统计与效果评估汇总", "报表支持导出为 Excel / PDF 格式,并可按场站、时间范围灵活筛选", ] for item in rpt_items: make_bullet(doc, item) doc.add_page_break() # ==================== 12. 系统设置 ==================== make_heading(doc, "十二、系统设置", 1) add_shot(doc, "14_system.png", "图 12-1 系统设置——基础参数配置") make_body(doc, "系统设置为管理员专属模块,提供平台级配置管理功能。左侧以子菜单导航,主要包含以下子模块:") table2 = doc.add_table(rows=10, cols=2, style='Light Grid Accent 1') table2.alignment = WD_TABLE_ALIGNMENT.CENTER t2hdr = table2.rows[0].cells t2hdr[0].text = "子模块" t2hdr[1].text = "说明" for hc in t2hdr: for p in hc.paragraphs: for r in p.runs: r.bold = True sys_set = [ ["基础设置", "系统名称、Logo、时区等基础参数"], ["用户管理", "用户账号的增删改查,启用/停用管理"], ["角色管理", "定义角色与权限分配(admin / operator / viewer)"], ["菜单管理", "自定义侧边栏菜单结构"], ["组织管理", "组织/部门树结构管理"], ["场站管理", "光伏场站信息的增删改查"], ["设备接入", "新设备注册与接入配置"], ["系统维护", "系统缓存清理、数据备份等运维操作"], ["日志管理", "操作日志与登录日志的查看检索"], ] for i, (k, v) in enumerate(sys_set): table2.rows[i+1].cells[0].text = k table2.rows[i+1].cells[1].text = v doc.add_paragraph("") make_heading(doc, "12.1 用户管理", 2) add_shot(doc, "15_users.png", "图 12-2 用户管理——账号与权限管理") make_body(doc, "用户管理页面支持管理员对系统用户的增删改查。每个用户需绑定角色(决定其菜单与操作权限)和组织(决定其数据可见范围)。支持按用户名、角色、状态等条件搜索,以及批量启用/停用用户账号。") make_heading(doc, "12.2 角色管理", 2) make_body(doc, "角色管理页面定义不同的权限角色模板。系统预置 admin、operator、viewer 三个角色,管理员可自定义新增角色,并为每个角色分配菜单访问权限和操作权限组合。") doc.add_page_break() # ==================== 13. 日常运维建议 ==================== make_heading(doc, "十三、日常运维建议", 1) tips = [ ("定期巡检", "建议每日查看首页总览和告警中心,及时处理活跃告警"), ("设备维护", "关注设备状态页面的电池电量与离线设备,及时充电或排查网络问题"), ("数据备份", "定期通过报表中心导出运营数据,系统维护页面可执行数据备份"), ("日志检查", "管理员定期查看操作日志,排查异常登录和误操作"), ("权限管理", "人员变动时及时在用户管理页面更新账号状态和角色分配"), ] for t, d in tips: make_bullet(doc, d, f"{t}:") make_body(doc, "") make_body(doc, "—— 全文完 ——") # ---- Save ---- doc.save(OUTPUT_PATH) print(f"DOCUMENT SAVED: {OUTPUT_PATH}") if __name__ == '__main__': build_doc()