Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db831e82ff | ||
|
|
6bf205f461 | ||
|
|
cf3d19d89d |
@@ -1,327 +0,0 @@
|
|||||||
# 网络设备管理平台用户手册
|
|
||||||
|
|
||||||
## 1. 平台概述与基础操作
|
|
||||||
|
|
||||||
### 1.1 平台简介
|
|
||||||
|
|
||||||
网络设备管理平台(以下简称为“平台”)是专为地铁线路运管中心设计的综合性管理系统。本平台旨在对车站内的各类网络设备进行集中监测、数据查看、运行状态监控及异常告警管理,并提供数据分析与统计功能。
|
|
||||||
|
|
||||||
**支持管理的设备类型包括:**
|
|
||||||
|
|
||||||
- 摄像机
|
|
||||||
- 网络录像机
|
|
||||||
- 交换机
|
|
||||||
- 解码器
|
|
||||||
- 智能安防箱
|
|
||||||
- 媒体服务器
|
|
||||||
- 视频服务器
|
|
||||||
- 网络键盘
|
|
||||||
- 报警主机
|
|
||||||
|
|
||||||
### 1.2 登录与退出
|
|
||||||
|
|
||||||
**登录平台:**
|
|
||||||
|
|
||||||
1. 在浏览器地址栏输入平台访问地址。
|
|
||||||
2. 进入登录页面后,输入您的 **账号** 和 **密码**。
|
|
||||||
3. 点击“登录”按钮。
|
|
||||||
4. 登录成功后,平台将默认跳转至 **车站状态模块 (首页)**。
|
|
||||||
|
|
||||||
**退出登录:**
|
|
||||||
|
|
||||||
1. 在平台任意页面的 **顶部区域** 右侧,找到显示您昵称的用户按钮。
|
|
||||||
2. 将鼠标悬停或点击该按钮,在下拉菜单中选择 **“退出登录”**。
|
|
||||||
3. 平台将安全退出您的账号并返回登录页面。
|
|
||||||
|
|
||||||
### 1.3 界面概览
|
|
||||||
|
|
||||||
登录后,平台主界面主要由以下四个区域组成:
|
|
||||||
|
|
||||||
**1. 顶部区域**
|
|
||||||
|
|
||||||
位于页面最上方,包含:
|
|
||||||
|
|
||||||
- **平台标题**:点击可快速返回首页。
|
|
||||||
- **用户信息**:显示当前登录用户昵称及退出入口。
|
|
||||||
- **设置按钮**:点击可打开设置面板。
|
|
||||||
|
|
||||||
**2. 侧边菜单**
|
|
||||||
|
|
||||||
位于页面左侧,提供各功能模块的导航入口:
|
|
||||||
|
|
||||||
- **车站状态**:全线车站设备运行概览 (首页)。
|
|
||||||
- **设备诊断**:深入查看具体设备的详细运行参数。
|
|
||||||
- **设备告警**:
|
|
||||||
- **设备告警记录**:查询历史告警记录。
|
|
||||||
- **告警忽略管理**:管理忽略设备。
|
|
||||||
- **系统日志**:
|
|
||||||
- **视频平台日志**:审计视频平台操作。
|
|
||||||
- **上级调用日志**:审计上级调用指令。
|
|
||||||
- **权限管理**:用户与权限配置(仅超级管理员可见)。
|
|
||||||
|
|
||||||
**3. 底部状态栏**
|
|
||||||
|
|
||||||
位于页面最下方,主要用于 **未读告警提示**。当有新的设备告警产生时,此处的铃铛图标会显示红色未读数量徽标,点击可快速跳转至告警记录页面。
|
|
||||||
|
|
||||||
**4. 设置面板**
|
|
||||||
|
|
||||||
点击顶部区域的“设置”图标(⚙️)即可打开,包含:
|
|
||||||
|
|
||||||
- **通用设置**:
|
|
||||||
- **主题**:切换深色/浅色模式,适应不同光照环境。
|
|
||||||
- **布局**:折叠/展开左侧菜单;调整 **车站卡片矩阵** 的显示列数(1-10列)。
|
|
||||||
- **业务设置**:
|
|
||||||
- **告警策略**:配置告警截图保留天数等(详见第4章,仅限特定权限人员可见)。
|
|
||||||
|
|
||||||
### 1.4 权限与界面差异说明
|
|
||||||
|
|
||||||
本平台采用严格的权限控制机制,您的账号权限将直接决定您能看到的内容和能执行的操作。
|
|
||||||
|
|
||||||
**1. 查看权限**
|
|
||||||
|
|
||||||
- **影响范围**:决定您能看到哪些车站。
|
|
||||||
- **界面表现**:如果您没有某车站的查看权限,该车站在 **车站卡片矩阵**、设备树以及所有查询筛选器中都将 **完全不可见**。
|
|
||||||
|
|
||||||
**2. 操作权限**
|
|
||||||
|
|
||||||
- **影响范围**:决定您能否对设备进行配置、控制或管理。
|
|
||||||
- **界面表现**:如果您没有某车站的操作权限,相关的 **功能按钮**(如“设备配置”、“同步数据”、“告警确认”等)将 **自动隐藏** 或 **变为不可用状态**。
|
|
||||||
|
|
||||||
> **提示**:如果您发现找不到某个车站或缺少某个功能按钮,请联系管理员确认您是否拥有相应的权限。
|
|
||||||
|
|
||||||
## 2. 车站状态模块 (首页)
|
|
||||||
|
|
||||||
车站状态模块是用户登录后的默认页面,以 **车站卡片矩阵** 的形式展示全线各车站的设备整体运行状态。
|
|
||||||
|
|
||||||
### 2.1 车站卡片解读
|
|
||||||
|
|
||||||
每个卡片代表一个车站,直观展示该站的关键运行指标:
|
|
||||||
|
|
||||||
**1. 基础信息**
|
|
||||||
|
|
||||||
- **车站名称**:显示车站名称。
|
|
||||||
- **在线状态**:右上角的标签显示该车站服务器当前的在线/离线状态。
|
|
||||||
|
|
||||||
**2. 统计数据**
|
|
||||||
|
|
||||||
- **设备概览**:显示“设备总数”,以及通过颜色区分的“在线设备数”(绿色)和“离线设备数”(红色)。
|
|
||||||
- **告警概览**:显示“今日告警总数”,若有告警则以醒目颜色提示。
|
|
||||||
|
|
||||||
**3. 交互操作**
|
|
||||||
|
|
||||||
- **更多菜单**(点击卡片右上角的垂直三点图标):
|
|
||||||
- **视频平台**:跳转至该车站对应的第三方视频管理平台。
|
|
||||||
- **设备配置**:打开参数配置窗口。_(注:仅当拥有该车站“操作权限”且车站在线时显示)_
|
|
||||||
- **查看设备详情**:点击设备概览区域右侧的 **详情按钮**(水平三点图标),弹出 **设备详情窗口**,展示该车站的设备树结构(支持进一步跳转至诊断页面)。
|
|
||||||
- **查看告警详情**:点击告警概览区域右侧的 **详情按钮**(水平三点图标),弹出 **告警详情窗口**,展示该车站当日的告警列表。
|
|
||||||
|
|
||||||
### 2.2 操作栏
|
|
||||||
|
|
||||||
位于页面顶部的工具栏,提供对多个车站的批量管理功能。
|
|
||||||
|
|
||||||
**1. 功能按钮与权限**
|
|
||||||
|
|
||||||
- **导出设备状态 / 导出录像诊断**:_(需查看权限)_ 仅可选择您拥有“查看权限”的车站进行数据导出。
|
|
||||||
- **同步摄像机 / 同步录像机通道**:_(需操作权限)_ 仅可选择您拥有“操作权限”的车站进行数据同步。
|
|
||||||
|
|
||||||
**2. 操作流程**
|
|
||||||
|
|
||||||
1. 点击操作栏中的任一功能按钮(例如“同步摄像机”)。
|
|
||||||
2. 此时进入**多选模式**,所有车站卡片上会出现复选框。_(注:系统会自动根据当前操作所需的权限,禁用无权操作的车站复选框)_
|
|
||||||
3. 勾选您需要操作的车站,或勾选顶部的“全选”框。
|
|
||||||
4. 点击操作栏右侧出现的 **“确定”** 按钮执行操作:
|
|
||||||
- **对于导出类操作**:平台将弹出预览窗口,您可在确认数据无误后点击下载 Excel 文件。
|
|
||||||
- **对于同步类操作**:平台将直接在后台启动同步任务,任务完成后,页面右上角会弹出通知提示成功或失败的数量。
|
|
||||||
|
|
||||||
### 2.3 单站详情与配置
|
|
||||||
|
|
||||||
除了查看概览,您还可以对单个车站进行更细致的管理。
|
|
||||||
|
|
||||||
**1. 设备列表详情**
|
|
||||||
|
|
||||||
在设备详情窗口中,您可以浏览该车站下的所有设备。点击任意设备节点,可直接跳转至 **设备诊断页面** 查看该设备的详细指标。
|
|
||||||
|
|
||||||
**2. 参数配置** _(需操作权限)_
|
|
||||||
|
|
||||||
通过右上角菜单进入“设备配置”,您可以:
|
|
||||||
|
|
||||||
- **阈值配置**:设置交换机、服务器、录像机等设备的运行指标告警阈值(如 CPU 占用率、温度上限等)。
|
|
||||||
- **计划任务**:设置显示器等设备的自动亮屏和息屏计划。
|
|
||||||
|
|
||||||
## 3. 设备诊断模块
|
|
||||||
|
|
||||||
设备诊断模块用于查看和分析具体设备的详细运行状态。您可以通过侧边菜单的 **“设备诊断”** 进入,或从 **车站状态模块** 的设备详情、告警记录页面跳转进入(告警跳转详见第4章)。
|
|
||||||
|
|
||||||
### 3.1 设备树 (侧边栏)
|
|
||||||
|
|
||||||
位于页面左侧,以树形结构展示全线所有车站及其下属设备。
|
|
||||||
|
|
||||||
**1. 搜索与筛选**
|
|
||||||
|
|
||||||
- **搜索框**:输入设备名称、设备 ID 或 IP 地址,可实时过滤设备树节点。
|
|
||||||
- **状态筛选**:点击单选框,可快速筛选 **“全部 / 在线 / 离线”** 设备。
|
|
||||||
|
|
||||||
**2. 设备树交互**
|
|
||||||
|
|
||||||
- **展开与选择**:按 **“车站 -> 设备类型 -> 具体设备”** 的层级展开,点击设备节点即可在右侧查看详情。
|
|
||||||
- **右键菜单管理** _(需操作权限)_:
|
|
||||||
- **在车站节点上右键**:
|
|
||||||
- **导入设备**:批量导入设备数据。
|
|
||||||
- **导出设备**:导出该车站的设备清单。
|
|
||||||
- **在设备节点上右键**:
|
|
||||||
- **删除设备**:将该设备从平台中移除。
|
|
||||||
|
|
||||||
### 3.2 诊断详情页结构
|
|
||||||
|
|
||||||
选中设备后,右侧区域将展示该设备的详细信息。
|
|
||||||
|
|
||||||
**1. 功能标签页**
|
|
||||||
|
|
||||||
- **当前诊断**:展示设备实时的运行数据(默认视图)。头部信息栏和详细诊断指标均包含在此标签页中。
|
|
||||||
- **历史诊断**:以图表形式展示设备的历史健康度或关键指标变化趋势。
|
|
||||||
- **修改设备**:_(需操作权限)_ 编辑设备的基础信息(如名称、安装位置等)。
|
|
||||||
|
|
||||||
**2. 头部信息栏 (位于“当前诊断”标签页顶部)**
|
|
||||||
|
|
||||||
- **基础状态**:展示设备名称、IP 地址、在线/离线状态。
|
|
||||||
- **关联操作**:
|
|
||||||
- **上游设备跳转**:如果设备有上游节点(如摄像机连接的交换机),点击可直接跳转查看上游设备。
|
|
||||||
- **管理入口**:点击 **“管理”** 按钮,可直接打开该设备自身的 Web 管理后台(如摄像机的 Web 配置页面)。
|
|
||||||
|
|
||||||
### 3.3 下游设备配置 (需操作权限)
|
|
||||||
|
|
||||||
对于交换机和智能安防箱,平台支持将其端口或电路与下游设备(如摄像机)进行关联,以便建立网络拓扑关系。
|
|
||||||
|
|
||||||
- **交换机配置**:在“当前诊断”的端口列表中,**右键点击**任意端口,选择 **“关联设备”**,可将该端口与下游设备绑定;若需解绑,右键选择 **“解除关联”** 即可。
|
|
||||||
- **智能安防箱配置**:在电路列表中,**右键点击**电路卡片,选择 **“关联设备”** 或 **“解除关联”** 进行配置。
|
|
||||||
|
|
||||||
### 3.4 设备诊断指标概览
|
|
||||||
|
|
||||||
根据设备类型的不同,“当前诊断”标签页将展示不同的关键指标。以下列举几种典型设备的展示重点:
|
|
||||||
|
|
||||||
- **交换机 / 服务器 / 录像机**:侧重硬件资源监控,展示 CPU、内存、磁盘等使用率仪表盘,以及端口流量或通道录像状态。
|
|
||||||
- **摄像机 / 报警主机**:侧重基础配置展示,如制造商、固件版本、序列号、ONVIF/GB28181 协议配置等。
|
|
||||||
- **解码器 / 智能安防箱**:兼具硬件状态(如温度、风扇转速)与业务配置(如通道状态)的展示。
|
|
||||||
|
|
||||||
## 4. 设备告警模块
|
|
||||||
|
|
||||||
设备告警模块是运维人员处理设备异常的核心区域,包含告警记录查询、确认、忽略以及策略配置等功能。
|
|
||||||
|
|
||||||
### 4.1 设备告警记录
|
|
||||||
|
|
||||||
通过侧边菜单选择 **“设备告警” -> “设备告警记录”** 进入。
|
|
||||||
|
|
||||||
**1. 筛选查询**
|
|
||||||
顶部查询栏提供多维度的组合筛选功能,帮助您快速定位特定告警:
|
|
||||||
|
|
||||||
- **车站**:选择查询范围(仅显示您拥有“查看权限”的车站)。
|
|
||||||
- **设备类型/名称**:按设备属性精确查找。
|
|
||||||
- **告警属性**:按告警类型、级别(严重/紧急/一般等)、恢复状态(已恢复/未恢复)及确认状态进行筛选。
|
|
||||||
- **时间范围**:选择告警发生的起止时间。
|
|
||||||
|
|
||||||
**2. 列表操作**
|
|
||||||
|
|
||||||
- **告警确认** _(需操作权限)_:对于“未确认”的告警,点击操作列的 **“确认”** 按钮进行处理。确认后,系统将记录确认人及时间,且该按钮变为不可点击状态。
|
|
||||||
- **忽略设备** _(需操作权限)_:若某设备频繁误报,点击 **“忽略设备”** 将其加入忽略名单。被忽略的设备将不再产生新告警,直到被手动恢复。
|
|
||||||
- **跳转诊断**:点击列表中的设备名称,可直接跳转至该设备的诊断详情页。
|
|
||||||
|
|
||||||
**3. 数据导出**
|
|
||||||
|
|
||||||
点击页面右上角的 **“导出”** 按钮,可将当前筛选条件下的所有告警记录导出为 Excel 报表,便于线下归档与分析。
|
|
||||||
|
|
||||||
### 4.2 告警忽略管理
|
|
||||||
|
|
||||||
通过侧边菜单选择 **“设备告警” -> “告警忽略管理”** 进入。
|
|
||||||
|
|
||||||
**1. 列表查看**
|
|
||||||
|
|
||||||
展示所有当前处于“忽略状态”的设备列表,包含忽略时间、所属车站及设备信息。
|
|
||||||
|
|
||||||
**2. 取消忽略 (需操作权限)**
|
|
||||||
|
|
||||||
若需恢复对某设备的监控,点击操作列的 **“取消忽略”** 按钮。恢复后,该设备产生的新异常将重新触发告警。
|
|
||||||
|
|
||||||
### 4.3 告警策略配置 (系统设置)
|
|
||||||
|
|
||||||
部分高级告警策略需在全局设置中进行配置。
|
|
||||||
|
|
||||||
**1. 入口与权限**
|
|
||||||
|
|
||||||
- **入口**:点击顶部区域的“设置”图标,在设置面板中找到“告警”板块。
|
|
||||||
- **权限要求**:此板块仅对 **OCC (控制中心) 车站** 的操作员可见。
|
|
||||||
|
|
||||||
**2. 配置项**
|
|
||||||
|
|
||||||
- **告警画面截图保留天数**:设置系统自动抓取的告警截图的存储期限(1-15天)。过期截图将被自动清理以释放存储空间。
|
|
||||||
- **自动获取告警画面截图**:开启/关闭告警触发时的自动截图功能。
|
|
||||||
|
|
||||||
## 5. 系统日志模块
|
|
||||||
|
|
||||||
系统日志模块用于审计和追踪系统内的关键操作记录。
|
|
||||||
|
|
||||||
### 5.1 视频平台日志
|
|
||||||
|
|
||||||
通过侧边菜单选择 **“系统日志” -> “视频平台日志”** 进入。此模块主要记录平台与第三方视频管理系统之间的交互操作。
|
|
||||||
|
|
||||||
**1. 查询功能**
|
|
||||||
|
|
||||||
- **车站筛选**:仅显示您拥有“查看权限”的车站日志。
|
|
||||||
- **操作类型**:筛选具体的交互指令类型(如“获取流地址”、“云台控制”等)。
|
|
||||||
- **时间范围**:按发生时间段进行精确检索。
|
|
||||||
|
|
||||||
**2. 数据导出**
|
|
||||||
|
|
||||||
支持将查询结果导出为 Excel 文件,用于故障排查或安全审计。
|
|
||||||
|
|
||||||
### 5.2 上级调用日志
|
|
||||||
|
|
||||||
通过侧边菜单选择 **“系统日志” -> “上级调用日志”** 进入。此模块记录上级系统(如公安或市级平台)调用本平台资源的请求记录。
|
|
||||||
|
|
||||||
**1. 查询功能**
|
|
||||||
|
|
||||||
- **车站筛选**:选择日志所属的车站范围。
|
|
||||||
- **调用类型**:筛选具体的调用指令(如“视频点播”、“录像回放”等)。
|
|
||||||
- **时间范围**:选择日志记录的时间段。
|
|
||||||
|
|
||||||
**2. 数据导出**
|
|
||||||
|
|
||||||
同样支持将查询结果导出,以便统计上级单位的调用频率和资源使用情况。
|
|
||||||
|
|
||||||
## 6. 权限管理模块
|
|
||||||
|
|
||||||
**(注:本模块仅对“超级管理员”可见,普通用户无法访问)**
|
|
||||||
|
|
||||||
权限管理模块用于配置系统用户及其对各车站的访问和操作权限。
|
|
||||||
|
|
||||||
### 6.1 用户列表管理
|
|
||||||
|
|
||||||
通过侧边菜单选择 **“权限管理”** 进入。
|
|
||||||
|
|
||||||
**1. 用户查找**
|
|
||||||
|
|
||||||
- **搜索**:在顶部搜索框输入 **用户名**,可快速定位目标用户。
|
|
||||||
- **重置**:点击重置按钮清空搜索条件,显示所有用户。
|
|
||||||
|
|
||||||
**2. 列表信息**
|
|
||||||
|
|
||||||
展示系统内所有注册用户的基本信息,包括账号、姓名等。
|
|
||||||
|
|
||||||
### 6.2 权限配置
|
|
||||||
|
|
||||||
点击用户列表右侧的 **“配置权限”** 按钮,进入该用户的权限分配界面。界面以矩阵形式展示,直观易懂。
|
|
||||||
|
|
||||||
**1. 权限矩阵解读**
|
|
||||||
|
|
||||||
- **行(车站)**:每一行代表一条线路上的具体车站。
|
|
||||||
- **列(权限类型)**:
|
|
||||||
- **查看**:决定用户能否看到该车站的数据。
|
|
||||||
- **操作**:决定用户能否对该车站设备进行控制或修改配置。
|
|
||||||
|
|
||||||
**2. 批量操作技巧**
|
|
||||||
|
|
||||||
- **全选/反选**:点击表头的复选框,可一键授予或取消所有车站的某项权限。
|
|
||||||
- **单站全权**:点击某一行车站名称前的复选框(如有),可一键授予该车站的所有权限。
|
|
||||||
|
|
||||||
**3. 特殊规则说明**
|
|
||||||
|
|
||||||
**重要提示**:如果未给某用户勾选任何权限(即所有复选框均为空),平台默认该用户拥有 **超级管理员权限**,可访问所有车站并执行所有操作。请务必谨慎配置。
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
# 《网络设备管理平台用户手册》编写计划
|
|
||||||
|
|
||||||
本计划已根据权限系统的实际逻辑(VIEW/OPERATION)进行了调整,将在各章节中明确体现权限对界面和功能的影响。
|
|
||||||
|
|
||||||
## 阶段一:准备与入门
|
|
||||||
|
|
||||||
1. **平台简介**:平台用途与设备支持范围。
|
|
||||||
2. **登录与注销**:账号登录流程、退出操作。
|
|
||||||
3. **界面概览**:
|
|
||||||
|
|
||||||
* **顶部区域 (Header)**:展示平台标题、当前用户信息及设置入口。
|
|
||||||
|
|
||||||
* **侧边菜单 (Sider)**:功能模块导航。
|
|
||||||
|
|
||||||
* **底部状态栏 (Footer)**:未读告警通知提示。
|
|
||||||
|
|
||||||
* **设置面板**:
|
|
||||||
|
|
||||||
* **通用设置**:主题切换(深色模式)、布局调整(菜单折叠、车站列数)。
|
|
||||||
|
|
||||||
* **业务设置**:告警策略配置(详见阶段四)。
|
|
||||||
4. **权限与界面差异说明(新增)**:
|
|
||||||
|
|
||||||
* 解释“查看权限”如何决定车站列表的显示(无权限则不显示)。
|
|
||||||
|
|
||||||
* 解释“操作权限”如何决定功能按钮的显隐(无权限则隐藏配置入口)。
|
|
||||||
|
|
||||||
## 阶段二:首页 - 车站状态监控
|
|
||||||
|
|
||||||
**涉及模块**:`Station Status` (首页)
|
|
||||||
|
|
||||||
1. **车站卡片解读**
|
|
||||||
|
|
||||||
* **基础信息**:车站名称、在线/离线状态。
|
|
||||||
|
|
||||||
* **统计数据**:设备总数/在线数/离线数、今日告警总数。
|
|
||||||
|
|
||||||
* **交互操作**:
|
|
||||||
|
|
||||||
* **右上角更多菜单**:
|
|
||||||
|
|
||||||
* **视频平台**:跳转至视频管理平台。
|
|
||||||
|
|
||||||
* **设备配置**:打开参数配置窗口 **(注:仅当拥有该车站“操作权限”且车站在线时显示)**。
|
|
||||||
|
|
||||||
* **设备详情入口**:点击“设备总数”区域,弹出设备树模态框(可进一步跳转诊断页)。
|
|
||||||
|
|
||||||
* **告警详情入口**:点击“告警总数”区域,弹出告警列表模态框。
|
|
||||||
2. **操作栏 (Batch Actions)**
|
|
||||||
|
|
||||||
* **功能按钮与权限差异**:
|
|
||||||
|
|
||||||
* **导出设备状态 / 导出录像诊断**:**(需查看权限)** 仅可选择拥有“查看权限”的车站进行导出。
|
|
||||||
|
|
||||||
* **同步摄像机 / 同步录像机通道**:**(需操作权限)** 仅可选择拥有“操作权限”的车站进行同步。
|
|
||||||
|
|
||||||
\*- **操作流程**:
|
|
||||||
|
|
||||||
1. 点击操作栏中的任一功能按钮(如“同步摄像机”)。
|
|
||||||
2. 此时车站卡片上会出现复选框,且仅有权限的车站可选。
|
|
||||||
3. 勾选需要操作的车站(支持“全选”)。
|
|
||||||
4. 点击操作栏右侧出现的“确定”按钮:
|
|
||||||
|
|
||||||
* **导出类操作**:系统将弹出预览窗口,您可在窗口中确认数据并下载 Excel 文件。
|
|
||||||
|
|
||||||
* **同步类操作**:系统将直接在后台启动同步任务,任务完成后右上角会弹出结果通知(成功/失败数量)。
|
|
||||||
3. **单站详情与配置**
|
|
||||||
|
|
||||||
* **设备列表详情**:展示设备树,点击可跳转诊断页。
|
|
||||||
|
|
||||||
* **告警列表详情**。
|
|
||||||
|
|
||||||
* **参数配置**:配置阈值与计划任务 **(需操作权限)**。
|
|
||||||
|
|
||||||
## 阶段三:设备诊断模块
|
|
||||||
|
|
||||||
**涉及模块**:`Device Diagnosis`
|
|
||||||
|
|
||||||
1. **设备树(侧边栏)**
|
|
||||||
|
|
||||||
* **数据范围**:说明仅展示拥有“查看权限”的车站及其下属设备。
|
|
||||||
|
|
||||||
* **搜索与筛选**:按名称/IP搜索,按状态筛选。
|
|
||||||
|
|
||||||
* **树形交互**:
|
|
||||||
|
|
||||||
* **展开与选择**:按“车站 -> 设备类型 -> 具体设备”层级展开与选择。
|
|
||||||
|
|
||||||
* **右键菜单管理**:**(需操作权限)**
|
|
||||||
|
|
||||||
* **车站节点右键**:支持 **导入设备**、**导出设备**。
|
|
||||||
|
|
||||||
* **设备节点右键**:支持 **删除设备**。
|
|
||||||
2. **诊断详情页结构**
|
|
||||||
|
|
||||||
* **头部信息栏**:状态、IP、关联跳转、Web管理入口。
|
|
||||||
|
|
||||||
* **功能标签页**:
|
|
||||||
|
|
||||||
* **当前诊断**:实时数据展示。
|
|
||||||
|
|
||||||
* **历史诊断**:历史趋势查看。
|
|
||||||
|
|
||||||
* **修改设备**:编辑设备信息 **(注:仅对拥有“操作权限”的用户可见)**。
|
|
||||||
3. **特定设备诊断指标**
|
|
||||||
- **分类描述策略**:
|
|
||||||
- **性能类设备**(如交换机、服务器、NVR):侧重硬件监控,展示CPU/内存使用率仪表盘、端口状态、磁盘健康度等。
|
|
||||||
- **(补充) 下游设备关联配置**:
|
|
||||||
- **交换机**:右键点击端口 -> 关联设备(如摄像机)。
|
|
||||||
- **安防箱**:右键点击电路 -> 关联设备。
|
|
||||||
- **操作权限要求**:**(需操作权限)**。
|
|
||||||
- **信息类设备**(如摄像机、报警主机):侧重参数展示,展示制造商、固件版本、协议配置等静态属性。
|
|
||||||
|
|
||||||
## 阶段四:告警管理模块
|
|
||||||
|
|
||||||
**涉及模块**:`Alarm`
|
|
||||||
|
|
||||||
1. **子模块:告警记录 (Alarm Log)**
|
|
||||||
|
|
||||||
* **筛选查询**:
|
|
||||||
|
|
||||||
* 组合筛选:车站(受查看权限限制)、设备类型、设备名称、告警类型、级别、状态、时间。
|
|
||||||
|
|
||||||
* **列表操作**:
|
|
||||||
|
|
||||||
* **告警确认**:点击“确认”按钮处理告警 **(注:需拥有该车站的操作权限,否则按钮禁用/隐藏)**。
|
|
||||||
|
|
||||||
* **忽略设备**:将设备加入忽略列表 **(需操作权限)**。
|
|
||||||
|
|
||||||
* **数据导出**:导出Excel报表。
|
|
||||||
|
|
||||||
2. **子模块:告警忽略 (Alarm Ignore)**
|
|
||||||
|
|
||||||
* **列表查看**:查看被忽略的设备记录。
|
|
||||||
|
|
||||||
* **取消忽略**:点击恢复监控 **(注:需拥有操作权限)**。
|
|
||||||
|
|
||||||
3. **告警策略配置 (系统设置)**
|
|
||||||
|
|
||||||
* **配置入口**:通过顶部导航栏“设置”按钮进入。
|
|
||||||
|
|
||||||
* **配置项**:告警画面截图保留天数、自动获取截图开关。
|
|
||||||
|
|
||||||
* **权限要求**:**(注:仅对 OCC 车站的操作员可见)**。
|
|
||||||
|
|
||||||
## 阶段五:日志管理模块
|
|
||||||
|
|
||||||
**涉及模块**:`Log`
|
|
||||||
|
|
||||||
1. **子模块:上级调用日志 (Call Log)**
|
|
||||||
|
|
||||||
* **查询**:筛选车站(受查看权限限制)、日志类型(如视频点播、云台指令)、时间范围。
|
|
||||||
|
|
||||||
* **导出**:导出查询结果。
|
|
||||||
|
|
||||||
2. **子模块:视频平台日志 (Vimp Log)**
|
|
||||||
|
|
||||||
* **查询**:筛选车站(受查看权限限制)、内部操作类型、时间范围。
|
|
||||||
|
|
||||||
* **导出**:导出查询结果。
|
|
||||||
|
|
||||||
## 阶段六:权限管理模块
|
|
||||||
|
|
||||||
**涉及模块**:`Permission`
|
|
||||||
|
|
||||||
**(注:本模块仅对“超级管理员”可见,普通用户无法访问)**
|
|
||||||
|
|
||||||
1. **用户列表管理**
|
|
||||||
|
|
||||||
* **搜索**:通过真实姓名查找用户。
|
|
||||||
|
|
||||||
* **重置**:清空搜索条件。
|
|
||||||
|
|
||||||
2. **权限配置 (Permission Config)**
|
|
||||||
|
|
||||||
* **矩阵式界面**:
|
|
||||||
|
|
||||||
* **行**:对应各个车站。
|
|
||||||
|
|
||||||
* **列**:对应具体权限类型(如查看、操作)。
|
|
||||||
|
|
||||||
* **批量操作**:支持整行(单站全权)或整列(全站某权)一键勾选。
|
|
||||||
|
|
||||||
* **特殊规则说明**:若未给用户勾选任何权限,平台默认该用户拥有**所有权限**(超级管理员模式)。
|
|
||||||
|
|
||||||
143
README.md
143
README.md
@@ -39,3 +39,146 @@ pnpm build
|
|||||||
```
|
```
|
||||||
|
|
||||||
在执行 `pnpm build` 之前,你可以在 `package.json` 中修改 `version` 字段,将其设置为你期望的版本号,构建完成后,项目的根目录中除了 `dist` 目录外,还会生成三个压缩包,文件名的格式统一为 `ndm-web-platform_v<version>_<datetime>`,文件格式则分别为 `zip`、`tar`、`tar.gz`。
|
在执行 `pnpm build` 之前,你可以在 `package.json` 中修改 `version` 字段,将其设置为你期望的版本号,构建完成后,项目的根目录中除了 `dist` 目录外,还会生成三个压缩包,文件名的格式统一为 `ndm-web-platform_v<version>_<datetime>`,文件格式则分别为 `zip`、`tar`、`tar.gz`。
|
||||||
|
|
||||||
|
## 业务结构
|
||||||
|
|
||||||
|
所有业务相关的页面都在 `src/pages` 目录下,路由配置在 `src/router/index.ts` 文件,除登录页之外,其余页面都作为 `src/layouts/app-layout.vue` 的子路由。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
src/
|
||||||
|
router/
|
||||||
|
index.ts # 路由配置文件
|
||||||
|
layouts/
|
||||||
|
app-layout.vue # 布局
|
||||||
|
pages/
|
||||||
|
login/
|
||||||
|
login-page.vue # 登录页面
|
||||||
|
station/
|
||||||
|
station-page.vue # 车站状态页面(首页)
|
||||||
|
device/
|
||||||
|
device-page.vue # 设备诊断页面
|
||||||
|
alarm/
|
||||||
|
alarm-ignore-page.vue # 告警忽略管理页面
|
||||||
|
alarm-log-page.vue # 设备告警记录页面
|
||||||
|
log/
|
||||||
|
call-log-page.vue # 上级调用日志页面
|
||||||
|
vimp-log-page.vue # 视频平台日志页面
|
||||||
|
permission/
|
||||||
|
permission-page.vue # 权限管理页面
|
||||||
|
error/
|
||||||
|
not-found-page.vue # 404 页面
|
||||||
|
```
|
||||||
|
|
||||||
|
## 数据轮询
|
||||||
|
|
||||||
|
由于后端服务的架构限制,需要前端向所有车站服务依次发送请求来获取数据,需要获取的数据包含车站状态、设备数据以及告警数据,因此需要设计一套数据轮询方案,定期从所有车站服务获取数据。
|
||||||
|
|
||||||
|
在项目中,`src/composables/query/` 目录下是所有数据轮询相关的代码,其中与业务相关的代码主要包括:
|
||||||
|
|
||||||
|
- `use-line-stations-query.ts`: 查询所有车站
|
||||||
|
- `use-line-devices-query.ts`: 查询所有设备
|
||||||
|
- `use-line-alarms-query.ts`: 查询所有告警
|
||||||
|
- `use-user-permission-query.ts`: 查询用户权限
|
||||||
|
|
||||||
|
在描述整个数据轮询流程之前,我们要明确项目中必须存在的几个关键概念:
|
||||||
|
|
||||||
|
- 车站相关:车站query + 车站store
|
||||||
|
- 设备相关:设备query + 设备store
|
||||||
|
- 告警相关:告警query + 告警store
|
||||||
|
- 权限相关:权限query + 权限store
|
||||||
|
|
||||||
|
整个数据轮询流程采用“单点驱动 + 变更监听 + 级联触发”的模式,如下图所示。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. 轮询入口:车站query
|
||||||
|
- 触发条件:以120秒的周期自动轮询车站列表
|
||||||
|
- 数据流向:车站store
|
||||||
|
2. 核心调度:权限query
|
||||||
|
- 触发条件:车站query执行后触发
|
||||||
|
- 数据流向:权限store,并计算当前用户在各车站的权限
|
||||||
|
- 数据监听:监听车站和权限变化,触发设备query和告警query
|
||||||
|
3. 设备query & 告警query
|
||||||
|
- 触发条件:被动触发,由权限query主动调用
|
||||||
|
- 数据流向:设备store & 告警store
|
||||||
|
|
||||||
|
## 调试模式
|
||||||
|
|
||||||
|
在设置面板中有一系列与调试模式有关的设置项,主要用于开发和故障排查。
|
||||||
|
|
||||||
|
### 开启方式
|
||||||
|
|
||||||
|
调试模式默认隐藏,通过以下方式开启:
|
||||||
|
|
||||||
|
1. 使用快捷键 `Ctrl + Alt + D` 唤起验证弹窗
|
||||||
|
2. 输入授权码进行验证(授权码对应环境变量 `.env` 中的 `VITE_DEBUG_CODE`)
|
||||||
|
3. 验证通过后,在“系统设置”面板中会出现 **调试** 分组
|
||||||
|
|
||||||
|
### 设置项说明
|
||||||
|
|
||||||
|
#### 数据设置
|
||||||
|
|
||||||
|
- **显示设备原始数据**
|
||||||
|
- 控制是否在设备详情页显示“原始数据”标签页
|
||||||
|
- 开启后可查看设备接口返回的原始 JSON 数据,便于排查字段缺失或格式错误
|
||||||
|
|
||||||
|
#### 网络设置
|
||||||
|
|
||||||
|
- **轮询车站**
|
||||||
|
- 控制是否定时拉取车站状态,进而触发权限、设备及告警数据的更新
|
||||||
|
- 关闭后将暂停所有业务数据的自动轮询机制
|
||||||
|
- **主动请求**
|
||||||
|
- 控制组件挂载时是否自动发起数据请求
|
||||||
|
- 涵盖设备在线状态检测、用户登录验证等逻辑,关闭后组件在初始化时将不再自动拉取数据
|
||||||
|
- **订阅消息**
|
||||||
|
- 控制是否通过 WebSocket (STOMP) 接收实时告警或状态推送
|
||||||
|
- 关闭后将不再处理后端推送的实时消息
|
||||||
|
- **模拟用户**
|
||||||
|
- 开启后使用内置的超管用户绕过登录
|
||||||
|
- 开启时会自动进入调试模式,便于开发环境快速测试
|
||||||
|
|
||||||
|
#### 数据库设置
|
||||||
|
|
||||||
|
- **直接操作本地数据库**
|
||||||
|
- 控制某些业务逻辑(如交换机端口、安防箱回路)是否直接读写本地 IndexedDB
|
||||||
|
- 用于在无后端环境或特定测试场景下验证本地数据逻辑
|
||||||
|
|
||||||
|
## 离线开发
|
||||||
|
|
||||||
|
项目支持在无后端服务的情况下正常启动,具体操作取决于你的本地环境是否已有历史数据。
|
||||||
|
|
||||||
|
### 场景一:已有本地缓存
|
||||||
|
|
||||||
|
如果你的浏览器曾接入过现场环境,IndexedDB 中已保存了车站、设备等数据,只需在设置中关闭网络请求即可进入离线模式:
|
||||||
|
|
||||||
|
1. 开启调试模式(`Ctrl + Alt + D`)。
|
||||||
|
2. 在“网络设置”中,关闭 **轮询车站**、**主动请求** 和 **订阅消息**。
|
||||||
|
3. 此时平台将停止向后端发起请求,直接展示本地缓存的历史数据。
|
||||||
|
|
||||||
|
### 场景二:全新环境启动(新人推荐)
|
||||||
|
|
||||||
|
如果你是首次拉取项目且无法连接后端,需要按以下步骤操作:
|
||||||
|
|
||||||
|
1. **模拟登录**
|
||||||
|
在登录页按 `F12` 打开控制台,输入以下命令强制进入平台:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
window.$mockUser.value = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
执行后平台将自动完成以下操作:
|
||||||
|
- 注入测试 Token 和管理员身份信息
|
||||||
|
- 关闭所有网络请求(轮询、主动请求、消息订阅)
|
||||||
|
- 开启调试模式
|
||||||
|
- 自动跳转至平台首页
|
||||||
|
|
||||||
|
2. **导入模拟数据**
|
||||||
|
进入平台后,页面默认为空。需导入预设数据以填充内容:
|
||||||
|
- 打开“系统设置”(已自动开启调试模式)。
|
||||||
|
- 在 **调试** -> **数据库设置** 中,勾选 **直接操作本地数据库**。
|
||||||
|
- 点击该选项下方的 **导入数据** 按钮。
|
||||||
|
- 依次导入项目根目录 `docs/data/` 下的三个文件:
|
||||||
|
- `ndm-station-store.json`(车站数据)
|
||||||
|
- `ndm-device-store.json`(设备数据)
|
||||||
|
- `ndm-alarm-store.json`(告警数据)
|
||||||
|
> **注意**:每次导入一个文件后,平台会自动刷新页面以应用数据。请等待刷新完成后,重新打开设置面板导入下一个文件。
|
||||||
|
|||||||
BIN
docs/assets/query-chain.png
Normal file
BIN
docs/assets/query-chain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
527708
docs/data/ndm-alarm-store.json
Normal file
527708
docs/data/ndm-alarm-store.json
Normal file
File diff suppressed because it is too large
Load Diff
195971
docs/data/ndm-device-store.json
Normal file
195971
docs/data/ndm-device-store.json
Normal file
File diff suppressed because one or more lines are too long
203
docs/data/ndm-station-store.json
Normal file
203
docs/data/ndm-station-store.json
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
"stations": [
|
||||||
|
{
|
||||||
|
"code": "1075",
|
||||||
|
"name": "吴中路控制中心",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.128.10",
|
||||||
|
"occ": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1001",
|
||||||
|
"name": "虹桥火车站",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.129.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1002",
|
||||||
|
"name": "虹桥2号航站楼",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.131.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1003",
|
||||||
|
"name": "虹桥一号航站楼",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.133.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1004",
|
||||||
|
"name": "上海动物园",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.135.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1005",
|
||||||
|
"name": "龙溪路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.137.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1006",
|
||||||
|
"name": "水城路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.139.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1007",
|
||||||
|
"name": "伊犁路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.141.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1008",
|
||||||
|
"name": "宋园路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.143.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1009",
|
||||||
|
"name": "虹桥路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.145.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1010",
|
||||||
|
"name": "交通大学",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.147.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1011",
|
||||||
|
"name": "图书馆",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.149.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1012",
|
||||||
|
"name": "陕西南路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.151.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1013",
|
||||||
|
"name": "新天地",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.153.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1014",
|
||||||
|
"name": "老西门",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.155.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1015",
|
||||||
|
"name": "豫园",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.157.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1016",
|
||||||
|
"name": "南京东路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.159.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1017",
|
||||||
|
"name": "天潼路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.161.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1018",
|
||||||
|
"name": "四川北路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.163.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1019",
|
||||||
|
"name": "海伦路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.165.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1020",
|
||||||
|
"name": "邮电新村",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.167.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1021",
|
||||||
|
"name": "四平路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.169.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1022",
|
||||||
|
"name": "同济大学",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.171.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1023",
|
||||||
|
"name": "国权路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.173.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1024",
|
||||||
|
"name": "五角场",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.175.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1025",
|
||||||
|
"name": "江湾体育场",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.177.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1026",
|
||||||
|
"name": "三门路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.179.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1027",
|
||||||
|
"name": "殷高东路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.181.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1028",
|
||||||
|
"name": "新江湾城",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.183.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1029",
|
||||||
|
"name": "航中路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.185.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1030",
|
||||||
|
"name": "紫藤路",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.187.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1031",
|
||||||
|
"name": "龙柏新村",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.189.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "1032",
|
||||||
|
"name": "吴中路基地",
|
||||||
|
"online": true,
|
||||||
|
"ip": "10.18.244.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { batchExportRecordCheckApi, getRecordCheckApi, pageDefParameterApi, type NdmNvrResultVO, type Station } from '@/apis';
|
import { batchExportRecordCheckApi, pageDefParameterApi, type Station } from '@/apis';
|
||||||
import { exportRecordDiagCsv, isNvrCluster, transformRecordChecks } from '@/helpers';
|
|
||||||
import { useDeviceStore } from '@/stores';
|
|
||||||
import { downloadByData, parseErrorFeedback } from '@/utils';
|
import { downloadByData, parseErrorFeedback } from '@/utils';
|
||||||
import { useMutation } from '@tanstack/vue-query';
|
import { useMutation } from '@tanstack/vue-query';
|
||||||
import { isCancel } from 'axios';
|
import { isCancel } from 'axios';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { NButton, NFlex, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui';
|
import { NButton, NFlex, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui';
|
||||||
import { storeToRefs } from 'pinia';
|
import { ref, toRefs } from 'vue';
|
||||||
import { computed, ref, toRefs } from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
stations: Station[];
|
stations: Station[];
|
||||||
@@ -20,93 +17,66 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const show = defineModel<boolean>('show');
|
const show = defineModel<boolean>('show');
|
||||||
|
|
||||||
const deviceStore = useDeviceStore();
|
|
||||||
const { lineDevices } = storeToRefs(deviceStore);
|
|
||||||
|
|
||||||
const { stations } = toRefs(props);
|
const { stations } = toRefs(props);
|
||||||
|
|
||||||
const nvrClusterRecord = computed(() => {
|
|
||||||
const clusterMap: Record<Station['code'], { stationName: Station['name']; clusters: NdmNvrResultVO[] }> = {};
|
|
||||||
stations.value.forEach((station) => {
|
|
||||||
clusterMap[station.code] = {
|
|
||||||
stationName: station.name,
|
|
||||||
clusters: [],
|
|
||||||
};
|
|
||||||
const stationDevices = lineDevices.value[station.code];
|
|
||||||
const nvrs = stationDevices?.['ndmNvr'] ?? [];
|
|
||||||
nvrs.forEach((nvr) => {
|
|
||||||
if (isNvrCluster(nvr)) {
|
|
||||||
clusterMap[station.code]?.clusters?.push(nvr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return clusterMap;
|
|
||||||
});
|
|
||||||
|
|
||||||
const abortController = ref<AbortController>(new AbortController());
|
const abortController = ref<AbortController>(new AbortController());
|
||||||
|
|
||||||
const { mutate: exportRecordDiags, isPending: exporting } = useMutation({
|
|
||||||
mutationFn: async (params: { clusters: NdmNvrResultVO[]; stationCode: Station['code'] }) => {
|
|
||||||
const { clusters, stationCode } = params;
|
|
||||||
if (clusters.length === 0) {
|
|
||||||
const stationName = nvrClusterRecord.value[stationCode]?.stationName ?? '';
|
|
||||||
window.$message.info(`${stationName} 没有录像诊断数据`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cluster = clusters.at(0);
|
|
||||||
if (!cluster) return;
|
|
||||||
abortController.value.abort();
|
|
||||||
abortController.value = new AbortController();
|
|
||||||
const checks = await getRecordCheckApi(cluster, 90, [], { stationCode: stationCode, signal: abortController.value.signal });
|
|
||||||
return checks;
|
|
||||||
},
|
|
||||||
onSuccess: (checks, { stationCode }) => {
|
|
||||||
if (!checks || checks.length === 0) {
|
|
||||||
window.$message.info(`没有录像诊断数据`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const recordDiags = transformRecordChecks(checks);
|
|
||||||
exportRecordDiagCsv(recordDiags, nvrClusterRecord.value[stationCode]?.stationName ?? '');
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
if (isCancel(error)) return;
|
|
||||||
console.error(error);
|
|
||||||
const errorFeedback = parseErrorFeedback(error);
|
|
||||||
window.$message.error(errorFeedback);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutate: batchExportRecordCheck, isPending: batchExporting } = useMutation({
|
const { mutate: batchExportRecordCheck, isPending: batchExporting } = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async (params: { stations: Station[] }) => {
|
||||||
const { records = [] } = await pageDefParameterApi({
|
const timer = setTimeout(() => {
|
||||||
model: {
|
if (!batchExporting.value) return;
|
||||||
key: 'NVR_GAP_SECONDS',
|
window.$message.info('导出耗时较长,请耐心等待...', { duration: 0 });
|
||||||
},
|
}, 3000);
|
||||||
extra: {},
|
|
||||||
current: 1,
|
|
||||||
size: 1,
|
|
||||||
sort: 'id',
|
|
||||||
order: 'descending',
|
|
||||||
});
|
|
||||||
const gapSeconds = parseInt(records.at(0)?.value ?? '5');
|
|
||||||
|
|
||||||
window.$message.info('导出耗时较长,请耐心等待...');
|
try {
|
||||||
|
abortController.value.abort();
|
||||||
|
abortController.value = new AbortController();
|
||||||
|
const { records = [] } = await pageDefParameterApi(
|
||||||
|
{
|
||||||
|
model: {
|
||||||
|
key: 'NVR_GAP_SECONDS',
|
||||||
|
},
|
||||||
|
extra: {},
|
||||||
|
current: 1,
|
||||||
|
size: 1,
|
||||||
|
sort: 'id',
|
||||||
|
order: 'descending',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
signal: abortController.value.signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const gapSeconds = parseInt(records.at(0)?.value ?? '5');
|
||||||
|
|
||||||
const data = await batchExportRecordCheckApi(
|
abortController.value.abort();
|
||||||
{
|
abortController.value = new AbortController();
|
||||||
checkDuration: 90,
|
const data = await batchExportRecordCheckApi(
|
||||||
gapSeconds,
|
{
|
||||||
stationCode: stations.value.map((station) => station.code),
|
checkDuration: 90,
|
||||||
},
|
gapSeconds,
|
||||||
{
|
stationCode: params.stations.map((station) => station.code),
|
||||||
signal: abortController.value.signal,
|
},
|
||||||
},
|
{
|
||||||
);
|
signal: abortController.value.signal,
|
||||||
return data;
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
} finally {
|
||||||
|
window.$message.destroyAll();
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data, { stations }) => {
|
||||||
const time = dayjs().format('YYYY-MM-DD_HH-mm-ss');
|
const time = dayjs().format('YYYY-MM-DD_HH-mm-ss');
|
||||||
downloadByData(data, `录像缺失记录_${time}.xlsx`);
|
let stationName = '';
|
||||||
|
if (stations.length === 1) {
|
||||||
|
const name = stations.at(0)?.name;
|
||||||
|
if (!!name) {
|
||||||
|
stationName = `${name}_`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
downloadByData(data, `${stationName}录像缺失记录_${time}.xlsx`);
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
if (isCancel(error)) return;
|
if (isCancel(error)) return;
|
||||||
@@ -126,11 +96,11 @@ const onAfterLeave = () => {
|
|||||||
<NModal v-model:show="show" preset="card" title="导出录像诊断" @after-leave="onAfterLeave" style="width: 800px">
|
<NModal v-model:show="show" preset="card" title="导出录像诊断" @after-leave="onAfterLeave" style="width: 800px">
|
||||||
<template #default>
|
<template #default>
|
||||||
<NScrollbar style="height: 300px">
|
<NScrollbar style="height: 300px">
|
||||||
<NSpin size="small" :show="exporting">
|
<NSpin size="small" :show="batchExporting">
|
||||||
<NGrid :cols="6">
|
<NGrid :cols="6">
|
||||||
<template v-for="({ stationName, clusters }, code) in nvrClusterRecord" :key="code">
|
<template v-for="station in stations" :key="station.code">
|
||||||
<NGridItem>
|
<NGridItem>
|
||||||
<NButton text type="info" style="height: 30px" @click="() => exportRecordDiags({ clusters, stationCode: code })">{{ stationName }}</NButton>
|
<NButton text type="info" style="height: 30px" @click="() => batchExportRecordCheck({ stations: [station] })">{{ station.name }}</NButton>
|
||||||
</NGridItem>
|
</NGridItem>
|
||||||
</template>
|
</template>
|
||||||
</NGrid>
|
</NGrid>
|
||||||
@@ -139,7 +109,7 @@ const onAfterLeave = () => {
|
|||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<NFlex justify="flex-end" align="center">
|
<NFlex justify="flex-end" align="center">
|
||||||
<NButton secondary :loading="batchExporting" @click="() => batchExportRecordCheck()">导出全部</NButton>
|
<NButton secondary :loading="batchExporting" @click="() => batchExportRecordCheck({ stations })">导出全部</NButton>
|
||||||
</NFlex>
|
</NFlex>
|
||||||
</template>
|
</template>
|
||||||
</NModal>
|
</NModal>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const useSettingStore = defineStore(
|
|||||||
activeRequests.value = true;
|
activeRequests.value = true;
|
||||||
subscribeMessages.value = false;
|
subscribeMessages.value = false;
|
||||||
mockUser.value = false;
|
mockUser.value = false;
|
||||||
|
useLocalDB.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user