Files
web-Iot/scripts/fill_collect.py

241 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""填充《采集表》中「软件的主要功能」「软件的主要特点」两栏。
源文件:C:/Users/15563/Desktop/软著/软著-机器人智慧服务系统/采集表.doc
内容依据:《用户操作手册-机器人智慧服务系统-完整版.docx》
"""
import zipfile, os, shutil, copy, re, time
from xml.etree import ElementTree as ET
W = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
def w(t): return '{%s}%s' % (W, t)
ET.register_namespace('w', W)
for pfx, uri in (
('w14', 'http://schemas.microsoft.com/office/word/2010/wordml'),
('mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'),
('v', 'urn:schemas-microsoft-com:vml'),
('wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'),
('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
('m', 'http://schemas.openxmlformats.org/officeDocument/2006/math'),
('wps', 'http://schemas.microsoft.com/office/word/2010/wordprocessingShape'),
('wpg', 'http://schemas.microsoft.com/office/word/2010/wordprocessingGroup'),
('wp14', 'http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing'),
('w10', 'urn:schemas-microsoft-com:office:word'),
('w15', 'http://schemas.microsoft.com/office/word/2012/wordml'),
):
try: ET.register_namespace(pfx, uri)
except Exception: pass
SRC = r'C:/Users/15563/Desktop/软著/软著-机器人智慧服务系统/采集表.doc'
TMP = r'D:/code/机器人智慧服务系统/.tmp/采集表_new.doc'
os.makedirs(os.path.dirname(TMP), exist_ok=True)
# ---------------- 内容 ----------------
FUNC_INTRO = ("本系统是面向光伏电站场景的机器人智能运维平台,采用前后端分离的 B/S 架构,"
"以三维电子地图为统一空间底座,把巡检机器人、除草机器人、无人机机场、清洗无人机等"
"智能装备的接入、调度、控制、作业与告警处置集中到统一的 Web 控制台,"
"实现“一张图指挥、一套流程闭环”。主要功能包括:")
FUNC = [
("(1)系统登录与权限管理:",
"支持账号密码登录与用户协议确认,未登录访问任意业务页面自动重定向至登录页,"
"登录态超时后提示并跳回登录页,重新登录可回到原页面。系统采用 RBAC 三级角色权限"
"(管理员、操作员、观察者),权限差异同时体现在菜单是否可见与按钮是否可操作两个层面;"
"并支持按组织与场站限定数据可见范围,跨场站数据不在列表中呈现。顶部栏提供场站切换、"
"全屏控制、中英文切换、用户头像与退出登录入口。"),
("(2)装备总览:",
"以五张状态统计卡(无人机机场状态、巡检机器人、除草机器人、清洗无人机、今日任务执行)"
"按场站汇总装备数量、在线台数与任务完成率;提供基于 Cesium 三维地图与场站正射影像的"
"装备协同态势图,叠加设备位置、作业路径、分区、障碍物、返航点等图层,支持图层开关与"
"“定位到机器人”一键聚焦;装备调度列表展示装备名称、类型、当前状态、电量、位置与通讯状态,"
"支持刷新、编辑设备 SN(可一键复制)、设备类型与设备别名,并可打开设备参数设置弹窗;"
"设备控制面板展示在线状态、电量、产品类型、SN、激活时间、固件版本,提供控制、回充、返航、"
"生成任务等快捷操作,无人机展示风速/温度/降雨等飞行条件,地面机器人展示累计作业里程、"
"面积与时长;另提供 AI 分析与操作建议、控制日志与告警记录、任务执行时间线,便于回溯与研判。"),
("(3)机器人任务:",
"顶部六张任务统计卡展示当日作业指标并给出较昨日的变化趋势;机器人路径规划与监控地图"
"实时显示机器人位置、规划路线与历史轨迹,支持控制模式(本地/自动任务/远程)显示与切换、"
"定位图层与视频开关、寻车与返航快捷按钮,以及清空实时轨迹、清空规划区域等视图清理操作;"
"任务下发支持按路线下发(单选,点击路线地图自动飞至该路线)与按区域下发(可多选,"
"多条路径可拖拽调节执行顺序)两种方式,任务类型分为立即执行与定时任务,定时任务可按天、"
"按周、按月重复并设置执行日期、执行时间与周期范围,提交前自动校验路径、执行机器人与"
"定时时间;任务列表分任务池、任务执行计划、历史任务三个页签,支持按状态、机器人与日期"
"范围筛选,行内提供暂停、恢复、取消(普通取消/强制取消)、删除与继续作业操作,"
"任务状态覆盖待执行、执行中、已暂停、已完成、执行失败、已取消六种。"),
("(4)机器人控制:",
"设备状态面板以列表形式实时刷新电机温度、电流、电压、电量、速度、航向与姿态等十四项"
"运行参数,每项标注单位与含义;实时视频监控通过 WebRTC 拉取机载摄像头画面,支持前视角、"
"左视角、右视角、后视角与全景五个视角切换、播放与停止控制,后视角自动叠加倒车辅助线;"
"设备态势地图实时显示航向角、横滚角与俯仰角,支持清空轨迹与定位到机器人;手柄控制支持"
"游戏手柄按键映射、控制器连接状态显示以及请求控制、释放控制与权限状态标签;方向盘控制"
"提供前进、后退、左转、右转与中键停止的屏幕虚拟方向盘,行驶速度可在 0–100% 之间调节,"
"控制指令以 100 毫秒为周期下发,并集成点火/熄火、底盘升起/下降、割刀加速/减速等执行机构"
"按钮;功能控制区提供五项辅助开关与红色急停按钮,急停触发后立即下发停车指令并自动补发"
"复位帧。"),
("(5)地图编辑:",
"提供返航点、分区、障碍物点、路径生成四种绘制模式,以及点选工具、机器人选择、撤销与清空"
"操作,地图区实时显示操作提示与已选点位数量;返航点支持在地图上标注多点、核对坐标后保存,"
"并可在已配置列表中编辑与删除;分区需不少于三个点位闭合边界,保存时可填写分区名称、"
"分区编码、默认线路与绑定线路(可多选),用于按区域编排任务;障碍物点用于标记支架基础、"
"水塘、电杆等固定障碍,标记后路径规划与自动作业自动绕开;路径生成可配置路径名称、"
"规划类型与作业模式,保存后进入预设路线列表,供任务下发页面直接引用。"),
("(6)告警中心:",
"顶部四张统计卡展示今日总告警、今日严重告警、今日待处理与今日已关闭数量并附昨日对比与"
"升降趋势,下方以折线图、饼图与柱状图分别展示告警趋势、告警类型比例与告警状态统计;"
"筛选栏支持按告警级别、处理状态、设备 ID 与时间范围组合查询,并提供重置、查询与结果导出;"
"告警列表展示告警编号、标题、级别、类型、来源设备、发生时间、处理状态等字段;"
"点击查看可从右侧展开告警详情抽屉,展示告警完整描述并提供联系处理人与一键生成工单入口,"
"填写处理状态、处理结果、根原因与处理备注后确认处理,告警由待处理流转为已关闭;"
"告警分提示、一般、重要、严重四级,支持修改告警标题、级别与类型并保留操作记录。"),
("(7)实时监控与数据统计:",
"基于 Cesium 三维地图与 MQTT 遥测通道,对设备位置、状态与运动轨迹进行实时渲染与回放,"
"支持电子围栏与场站可视化监控;历史任务、控制日志与告警记录长期留存并支持多维查询与"
"趋势分析,运营数据可导出为报表,为作业计划编排、绩效考核与管理决策提供数据支撑。"),
("(8)工单联动处置:",
"对需要现场处置的告警可一键转为运维工单,系统自动带出告警编号、设备与告警描述,"
"补充处理人与期望完成时间后提交;工单按待处理、处理中、待验收、已完成状态流转,"
"验收关闭后对应告警同步标记为已关闭,形成“发现—派单—处置—验收”的完整闭环。"),
]
FEAT_INTRO = "本系统在架构设计与人机交互上具备以下特点:"
FEAT = [
("(1)一张图指挥:",
"以 Cesium 三维地图与场站正射影像为统一空间底座,将所有可动作装备、航线、分区、障碍物与"
"实时位置叠加在同一张态势图上,图层可独立开关、目标可一键定位,运维人员无需在多系统间"
"切换即可掌握全场站态势。"),
("(2)四通道实时通信:",
"HTTP/REST 承载业务接口,MQTT over WebSocket 上行设备遥测,WebSocket 下行控制指令,"
"WebRTC 回传机载视频,四条通道职责清晰、互不阻塞,兼顾业务可靠性与遥控低延迟。"),
("(3)任务全流程闭环:",
"从地图要素配置、路线与区域编排、立即或定时下发,到执行监控、异常处置与统计回溯,"
"作业全链路可追溯;失败或取消的任务可基于原编排“继续作业”,无需重新规划路径。"),
("(4)双模遥控与低延迟指令:",
"同时支持游戏手柄与屏幕虚拟方向盘两种操控方式,控制指令以 100 毫秒为周期打包下发,"
"结合速度分级调节,既满足精细作业的稳定操控,也支持突发情况下的快速接管。"),
("(5)多重安全保护机制:",
"提供急停(自动补发复位帧)、控制权独占、管理员强制抢占、会话保活、避障开关、倾斜保护、"
"低电量自动返航等多重保护,控制权申请与释放过程全程可见,避免多操作员指令冲突与设备"
"被长期占用在远程模式。"),
("(6)告警与工单联动闭环:",
"告警处理结果与工单状态双向同步,告警可一键转工单,工单验收后告警自动关闭,"
"使异常处置从“被动发现”转为“流程闭环、责任到人”。"),
("(7)精细化权限与数据隔离:",
"三级 RBAC 角色权限同时约束菜单可见性与按钮可用性,并按组织与场站隔离数据可见范围,"
"满足多场站、多班组协同运维的管理要求。"),
("(8)跨平台免安装部署:",
"前后端分离的 B/S 架构,前端基于 React 19 + TypeScript + Vite 6 构建单页应用,"
"服务端可在 Windows/Linux 环境部署,客户端仅需现代浏览器即可访问,无需安装任何插件;"
"界面支持中英文双语切换。"),
]
# ---------------- 写入 ----------------
zin = zipfile.ZipFile(SRC)
doc = ET.fromstring(zin.read('word/document.xml'))
def cell_text(tc):
return ''.join(t.text or '' for t in tc.iter(w('t')))
def fill_cell(tc, intro, items):
"""用 intro + 分条内容重写单元格,沿用原单元格字体与段落格式。"""
paras = tc.findall(w('p'))
tpl_p = paras[0]
pPr = tpl_p.find(w('pPr'))
# 取第一个带文字 run 的 rPr 作为字体模板
rPr = None
for r in tpl_p.findall(w('r')):
rp = r.find(w('rPr'))
if rp is not None:
rPr = rp
break
if rPr is None:
for r in tpl_p.iter(w('r')):
rp = r.find(w('rPr'))
if rp is not None:
rPr = rp
break
# 清空原有段落
for p in paras:
tc.remove(p)
def add(text, bold=False):
p = ET.SubElement(tc, w('p'))
if pPr is not None:
newpPr = copy.deepcopy(pPr)
# 去重:段落级段落标记 rPr 保留
p.append(newpPr)
r = ET.SubElement(p, w('r'))
if rPr is not None:
newrPr = copy.deepcopy(rPr)
if bold:
b = ET.SubElement(newrPr, w('b'))
r.append(newrPr)
t = ET.SubElement(r, w('t'))
t.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
t.text = text
return p
add(intro)
for head, body in items:
# 每条一段:小标题加粗 + 正文
p = ET.SubElement(tc, w('p'))
if pPr is not None:
p.append(copy.deepcopy(pPr))
r1 = ET.SubElement(p, w('r'))
if rPr is not None:
rp = copy.deepcopy(rPr)
ET.SubElement(rp, w('b'))
r1.append(rp)
t1 = ET.SubElement(r1, w('t'))
t1.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
t1.text = head
r2 = ET.SubElement(p, w('r'))
if rPr is not None:
r2.append(copy.deepcopy(rPr))
t2 = ET.SubElement(r2, w('t'))
t2.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
t2.text = body
done = []
for tbl in doc.iter(w('tbl')):
for tr in tbl.findall(w('tr')):
tcs = tr.findall(w('tc'))
if len(tcs) < 2:
continue
label = cell_text(tcs[0]).strip().replace(' ', '')
if label == '软件的主要功能':
fill_cell(tcs[1], FUNC_INTRO, FUNC)
done.append('功能')
elif label == '软件的主要特点':
fill_cell(tcs[1], FEAT_INTRO, FEAT)
done.append('特点')
print('已填充:', done)
assert len(done) == 2, '未找到目标单元格'
new_doc = ET.tostring(doc, encoding='UTF-8', xml_declaration=True)
zout = zipfile.ZipFile(TMP, 'w', zipfile.ZIP_DEFLATED)
for item in zin.namelist():
if item == 'word/document.xml':
continue
zout.writestr(item, zin.read(item))
zout.writestr('word/document.xml', new_doc)
zout.close()
zin.close()
print('生成:', TMP, os.path.getsize(TMP))
# 尝试覆盖源文件
ok = False
for i in range(3):
try:
shutil.copyfile(TMP, SRC)
ok = True
break
except Exception as e:
print('写入失败', i, e)
time.sleep(1.5)
print('覆盖源文件:', '成功' if ok else '源文件被占用,已保留新文件')
print('OUT=' + (SRC if ok else TMP))