|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>tool</title>
|
|
|
|
|
<script type="text/javascript" src="./three/three.min.js"></script>
|
|
|
|
|
<script type="text/javascript" src="./three/OrbitControls.js"></script>
|
|
|
|
|
<script type="text/javascript" src="./three/Lut.js"></script>
|
|
|
|
|
<script src="./js/vue.global.min.js"></script>
|
|
|
|
|
<script src="./js/antd.min.js"></script>
|
|
|
|
|
<link rel="stylesheet" href="./css/antd.min.css">
|
|
|
|
|
<link rel="stylesheet" href="./css/element-plus.css">
|
|
|
|
|
<script src="./js/element-plus.js"></script>
|
|
|
|
|
<!-- 引入 Element Plus 中文语言包 -->
|
|
|
|
|
<script src="./js/zh-cn.min.js"></script>
|
|
|
|
|
<script src="./js/echarts.min.js"></script>
|
|
|
|
|
<script src="./js/echarts-gl.min.js"></script>
|
|
|
|
|
<link rel="stylesheet" href="./css/common.css">
|
|
|
|
|
<script type="text/javascript" src="./js/axios.min.js"></script>
|
|
|
|
|
<style>
|
|
|
|
|
body {
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
<div id="app">
|
|
|
|
|
<div class="content">
|
|
|
|
|
<!-- 树菜单 -->
|
|
|
|
|
<div ref="treeMenu" v-if="treeMenuInfo.menuVisible" class="context-menu"
|
|
|
|
|
:style="{ left: `${treeMenuInfo.menuX}px`, top: `${treeMenuInfo.menuY}px` }">
|
|
|
|
|
<div v-if="treeMenuInfo.data.isRoot" @click="addMonitor(treeMenuInfo.data)">新增监测点</div>
|
|
|
|
|
<div @click="editNodeItem(treeMenuInfo.data)">编辑</div>
|
|
|
|
|
<a-popconfirm title="确定要删除吗?" ok-text="确定" cancel-text="取消"
|
|
|
|
|
@confirm="deleteNodeItem(treeMenuInfo.data)">
|
|
|
|
|
<div>删除</div>
|
|
|
|
|
</a-popconfirm>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tree-content">
|
|
|
|
|
<div class="input-box">
|
|
|
|
|
<a-input placeholder="名称" v-model:value="searchValue" @change="search">
|
|
|
|
|
</a-input>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tree-box">
|
|
|
|
|
<el-tree ref="treeRef" node-key="key" check-strictly :check-on-click-node="false" :data="treeData"
|
|
|
|
|
:props="defaultProps" :load="onLoadData" lazy v-model:checked-keys="checkedKeys1"
|
|
|
|
|
:current-node-key="selectedKey" :show-checkbox="typeOfCheckable.includes(activeKey)"
|
|
|
|
|
:default-expanded-keys="defaultExpendKeys" @check="checkTree" @node-click="handleNodeClick"
|
|
|
|
|
:filter-node-method="filterNode" @node-contextmenu="handleRightClick">
|
|
|
|
|
<template #default="{ node, data }">
|
|
|
|
|
<div :class="[selectedKey===data.key?'hight-light-node':'','node-content']"
|
|
|
|
|
:title="node.label" @click.stop="handleNodeContentClick(data)">
|
|
|
|
|
{{ node.label }}
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</el-tree>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="bottom-btns">
|
|
|
|
|
<a-button type="primary" size="small" @click="isImportMonitorModalShow=true"> 导入监测点 </a-button>
|
|
|
|
|
<a-button style="margin-left: 4px;" type="primary" size="small" @click="addSite"> 新增站点 </a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="right-content">
|
|
|
|
|
<!-- tab切换 -->
|
|
|
|
|
<div class="top-box">
|
|
|
|
|
<a-tabs v-model:active-key="activeKey" @change="(key)=>activeKey=key">
|
|
|
|
|
<a-tab-pane v-for="item in tabsArr" :key="item.key" :tab="item.tab"></a-tab-pane>
|
|
|
|
|
</a-tabs>
|
|
|
|
|
<div class="top-timer" v-if="timeSelectArr.includes(activeKey)">
|
|
|
|
|
<el-date-picker v-model="dateRange" style="width: 260px" class="custom-date-picker"
|
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange" range-separator="至"
|
|
|
|
|
start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="panel-views">
|
|
|
|
|
<div v-if="activeKey === 'alarmConfig'" key="alarmConfig" class="sub-content alarm-config">
|
|
|
|
|
<!-- 告警配置 -->
|
|
|
|
|
<div class="search-bar">
|
|
|
|
|
<div class="search-item">
|
|
|
|
|
<span>放电类型:</span>
|
|
|
|
|
<a-select v-model:value="alarmFilters.pdTypes" :options="pdTypeOps" mode="tags"
|
|
|
|
|
placeholder="请选择" style="width: 300px">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="search-item">
|
|
|
|
|
<span>时间:</span>
|
|
|
|
|
<el-date-picker v-model="alarmFilters.times" style="width: 360px"
|
|
|
|
|
class="custom-date-picker" value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange"
|
|
|
|
|
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="break"></div>
|
|
|
|
|
<div class="search-item">
|
|
|
|
|
<span>是否复归:</span>
|
|
|
|
|
<a-radio-group :options="cancelOps" v-model:value="alarmFilters.isCancel" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="search-item">
|
|
|
|
|
<a-button type="primary" size="small" @click="fetchAlarmGridData">查询</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="search-item">
|
|
|
|
|
<a-button size="small" @click="initAlarmGridData">重置</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="grid-content">
|
|
|
|
|
<a-table :columns="columns" :data-source="dataSource" :pagination="pagination"
|
|
|
|
|
:loading="configLoading" @change="handleTableChange" :scroll="{ y: 460 }"
|
|
|
|
|
:custom-row="alarmRowClick">
|
|
|
|
|
<template #name1="{ text }">
|
|
|
|
|
{{pdTypeOps.find(item=>item.value==text).label}}
|
|
|
|
|
</template>
|
|
|
|
|
<template #name2="{ text }">
|
|
|
|
|
{{ cancelOps.find(item=>item.value==text).label}}
|
|
|
|
|
</template>
|
|
|
|
|
</a-table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="activeKey === 'historyTrend'" key="historyTrend" class="sub-content history-trend">
|
|
|
|
|
<div class="trend-graph-container">
|
|
|
|
|
<history-trend-graph v-for="(item,index) in trendGraphData" :key="item.key"
|
|
|
|
|
:ref="el => { if (el) trendGraphRefs[index] = el }" :data="item"
|
|
|
|
|
@jump-to-prpd="jumpToPRPD" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="activeKey === 'prpdAndPrps'" key="prpdAndPrps" class="sub-content total-prpd-panel">
|
|
|
|
|
<div>
|
|
|
|
|
<history-trend-graph ref="trendRef" :data='trendGraphInfo' used-tab="prpdAndPrps"
|
|
|
|
|
@get-event-list="getEventList" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="prpd-box">
|
|
|
|
|
<!-- 累计PRPD组件 -->
|
|
|
|
|
<div class="totle-prpds">
|
|
|
|
|
<prpd-and-prps-comp class="total-prpd-item" v-for="(item,index) in totalPrpds"
|
|
|
|
|
:key="index" :data="item" :time="prpdAndPrpsTimes"
|
|
|
|
|
:is-count-prpd="isTypeOfCountPrpd" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="time-sider">
|
|
|
|
|
<div class="title">
|
|
|
|
|
<span>
|
|
|
|
|
事件:
|
|
|
|
|
</span>
|
|
|
|
|
<el-popover placement="right" :width="320" trigger="click"
|
|
|
|
|
:visible="everntFilterVisible">
|
|
|
|
|
<template #reference>
|
|
|
|
|
<el-button @click="everntFilterVisible=!everntFilterVisible">筛选</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
<el-form :inline="true" :model="eventFilterForm" label-width="auto"
|
|
|
|
|
label-suffix=":" class="demo-form-inline">
|
|
|
|
|
<el-form-item label="脉冲数">
|
|
|
|
|
<el-input v-model="eventFilterForm.plusCount" placeholder="请输入" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="幅值">
|
|
|
|
|
<el-input v-model="eventFilterForm.maxValue" placeholder="请输入" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="放电类型">
|
|
|
|
|
<el-select v-model="eventFilterForm.pdTypes" multiple collapse-tags
|
|
|
|
|
collapse-tags-tooltip style="width: 240px" placeholder="请选择">
|
|
|
|
|
<el-option v-for="item in allPdTypes" :key="item.value"
|
|
|
|
|
:label="item.label" :value="item.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-button type="primary" @click="onFilterEventList">确定</el-button>
|
|
|
|
|
<el-button @click="onResetEventList">重置</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</el-popover>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="list" v-loading="eventListLoading">
|
|
|
|
|
<div :class="['event-item',activeEventTime==item.time?'active-event-item':'']"
|
|
|
|
|
v-for="(item,index) in eventList" :key="item.time"
|
|
|
|
|
@click="handleEventClick(item)">
|
|
|
|
|
<div class="time">
|
|
|
|
|
<span class="label">时间:</span>
|
|
|
|
|
{{item.time}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="pd-type">
|
|
|
|
|
<span class="label">放电类型:</span>
|
|
|
|
|
{{allPdTypes.find(({value})=>value==item.pdType)?.label}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="num">
|
|
|
|
|
<span style="margin-right: 12px;">
|
|
|
|
|
<span class="label">最大值:</span>
|
|
|
|
|
{{item.maxValue}}</span>
|
|
|
|
|
<span>
|
|
|
|
|
<span class="label">脉冲数:</span>
|
|
|
|
|
{{item.plusCount}}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="activeKey === 'eventCount'" key="eventCount" class="sub-content">
|
|
|
|
|
<!-- 事件统计 -->
|
|
|
|
|
<event-count :time="dateRange" :selected-key="selectedKey" :tree-data="fullTreeData" />
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="activeKey === 'config'" key="config" class="sub-content config-page">
|
|
|
|
|
<!-- 配置页面 -->
|
|
|
|
|
<div class="station-config">
|
|
|
|
|
<div class="title">站点告警配置</div>
|
|
|
|
|
<div class="station">
|
|
|
|
|
<span>站点:</span>
|
|
|
|
|
<a-select v-model:value="stationName1" size="small" style="width: 200px">
|
|
|
|
|
<a-select-option v-for="item in treeData" :key="item.key" :value="item.stationName">
|
|
|
|
|
{{ item.stationName }}
|
|
|
|
|
</a-select-option>
|
|
|
|
|
</a-select>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="delete-bar">
|
|
|
|
|
<span class="delete-time">
|
|
|
|
|
<span class="label">清除告警时间段:</span>
|
|
|
|
|
<el-date-picker v-model="deleteAlarmTimes" style="width: 360px"
|
|
|
|
|
class="custom-date-picker" value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
|
end-placeholder="结束日期" />
|
|
|
|
|
</span>
|
|
|
|
|
<a-popconfirm title="确定删除?" ok-text="是" cancel-text="否" @confirm="deleteAlarmConfirm">
|
|
|
|
|
<a href="#">删除</a>
|
|
|
|
|
</a-popconfirm>
|
|
|
|
|
</div>
|
|
|
|
|
<el-upload action="#" :http-request="alarmCustomUpload" :show-file-list="false" :limit="1"
|
|
|
|
|
accept=".csv,.xlsx,.xls" :before-upload="alarmBeforeUpload">
|
|
|
|
|
<a-button type="primary" size="small">导入告警</el-button>
|
|
|
|
|
</el-upload>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="path-config">
|
|
|
|
|
<div class="title">路径配置</div>
|
|
|
|
|
<div class="path-item" v-for="item in allPathCongfigs" :key="item.key">
|
|
|
|
|
<div class="name">{{item.label}} :</div>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<el-radio-group v-if="item.key==='ALARM_TYPE'" v-model="item.value">
|
|
|
|
|
<el-radio value="3">国网</el-radio>
|
|
|
|
|
<el-radio value="2">南网</el-radio>
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
<el-input v-else v-model="item.value" style="width: 560px" placeholder="请输入路径" />
|
|
|
|
|
</div>
|
|
|
|
|
<a-button size="small" type="primary" style="margin-right: 4px;"
|
|
|
|
|
@click="savePathConfig(item)">保存</a-button>
|
|
|
|
|
<a-button v-if="item.key==='MERGIN_ROOT_PATH'" size="small" type="primary"
|
|
|
|
|
style="margin-right: 4px;" :loading="isCurrentInit"
|
|
|
|
|
@click="initCatalogue">初始化</a-button>
|
|
|
|
|
<a-button size="small" @click="resetPathConfig(item.key)">重置</a-button>
|
|
|
|
|
<p v-if="item.key==='MERGIN_ROOT_PATH'&&isCurrentInit" class="init-warning-tips">
|
|
|
|
|
当前初始化进度:{{initTips}}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 导入监测点弹框 -->
|
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isImportMonitorModalShow" title="导入监测点"
|
|
|
|
|
@ok="onImportMonitor" @cancel="isImportMonitorModalShow=false"
|
|
|
|
|
:confirmLoading="importMonitorModalloading"></a-modal>
|
|
|
|
|
<!-- 站点弹框 -->
|
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isSiteModalShow"
|
|
|
|
|
:title="isAddTypeOfSiteModal?'新增站点':'编辑站点'" @cancel="isSiteModalShow=false">
|
|
|
|
|
<a-form layout=" vertical" ref="siteModalRef" :model="siteModalForm">
|
|
|
|
|
<a-form-item label="站点名称" name="stationName" :rules="[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: '请输入站点名称',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
max: 20,
|
|
|
|
|
message: '最多输入20个字符',
|
|
|
|
|
},
|
|
|
|
|
]">
|
|
|
|
|
<a-input v-model:value="siteModalForm.stationName" placeholder="请输入" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
<a-form-item label="背景图路径" name="img" :rules="[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: '请输入背景图路径',
|
|
|
|
|
},
|
|
|
|
|
]">
|
|
|
|
|
<a-input v-model:value="siteModalForm.img" placeholder="请输入" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-form>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<a-button @click="isSiteModalShow=false">关闭</a-button>
|
|
|
|
|
<a-button type="primary" @click="onSiteModalSubmit" :loading="siteModalloading">确定</a-button>
|
|
|
|
|
</template>
|
|
|
|
|
</a-modal>
|
|
|
|
|
<!-- 监测点弹框 -->
|
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isMonitorModalShow"
|
|
|
|
|
:title="isAddTypeOfMonitorModal?'新增监测点':'编辑监测点'" @cancel="isMonitorModalShow=false">
|
|
|
|
|
<a-form layout=" vertical" ref="monitorModalRef" :model="monitorModalForm">
|
|
|
|
|
<a-form-item label="站点名称" name="stationName" :rules="[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: '请输入监测点名称',
|
|
|
|
|
},
|
|
|
|
|
]" disabled>
|
|
|
|
|
<a-input v-model:value="monitorModalForm.stationName" disabled />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
<a-form-item label="监测点Key" name="monitorKey" :rules="[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: '请输入监测点Key',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
max: 20,
|
|
|
|
|
message: '最多输入20个字符',
|
|
|
|
|
},
|
|
|
|
|
]">
|
|
|
|
|
<a-input v-model:value="monitorModalForm.monitorKey" placeholder="请输入"
|
|
|
|
|
:disabled="!isAddTypeOfMonitorModal" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
<a-form-item label="监测点名称" name="name" :rules="[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: '请输入监测点名称',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
max: 20,
|
|
|
|
|
message: '最多输入20个字符',
|
|
|
|
|
},
|
|
|
|
|
]">
|
|
|
|
|
<a-input v-model:value="monitorModalForm.name" placeholder="请输入" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-form>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<a-button @click="isMonitorModalShow=false">关闭</a-button>
|
|
|
|
|
<a-button type="primary" @click="onMonitorModalSubmit" :loading="monitorModalLoading">确定</a-button>
|
|
|
|
|
</template>
|
|
|
|
|
</a-modal>
|
|
|
|
|
</div>
|
|
|
|
|
<script>
|
|
|
|
|
const { createApp, ref, onMounted, unref, watch, reactive, computed, nextTick, onUnmounted, components, provide, inject } = Vue;
|
|
|
|
|
const { message } = antd;
|
|
|
|
|
axios.defaults.baseURL = 'http://192.168.1.198:9501'; // 临时服务地址
|
|
|
|
|
axios.defaults.timeout = 10000;
|
|
|
|
|
const HISTORY_TREND_LEGEND = [
|
|
|
|
|
{ id: 'avg', name: '平均值' },
|
|
|
|
|
{ id: 'maxValue', name: '最大值' },
|
|
|
|
|
{ id: 'plusAvg', name: '脉冲平均值' },
|
|
|
|
|
{ id: 'plusCount', name: '脉冲次数' },
|
|
|
|
|
]
|
|
|
|
|
const findParentByKey = (tree, targetKey) => {
|
|
|
|
|
for (const parent of tree) {
|
|
|
|
|
// 检查子节点
|
|
|
|
|
if (parent?.children?.length) {
|
|
|
|
|
for (const child of parent.children) {
|
|
|
|
|
if (child.key === targetKey) {
|
|
|
|
|
return parent.stationName; // 返回父节点
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
const formatTreeData = (node) => {
|
|
|
|
|
return {
|
|
|
|
|
...node.data,
|
|
|
|
|
children: node.childNodes?.map(child => formatTreeData(child)) || []
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
// 生成正弦波形
|
|
|
|
|
const generateSineWaveData = () => {
|
|
|
|
|
const dataPoints = [];
|
|
|
|
|
// 遍历0到360度,每1度取一个点
|
|
|
|
|
for (let angle = 0; angle <= 360; angle++) {
|
|
|
|
|
// 将角度转换为弧度
|
|
|
|
|
const radian = angle * Math.PI / 180;
|
|
|
|
|
// 计算增益值
|
|
|
|
|
const gain = 40 * Math.sin(radian) - 40;
|
|
|
|
|
// 将 [相位, 增益] 对添加到数组中
|
|
|
|
|
// 使用 toFixed(2) 来保留两位小数,避免浮点数精度问题,并将其转换为数字类型
|
|
|
|
|
dataPoints.push([angle, parseFloat(gain.toFixed(2))]);
|
|
|
|
|
}
|
|
|
|
|
return dataPoints;
|
|
|
|
|
}
|
|
|
|
|
// 处理数据,生成 ECharts 所需的三维坐标格式
|
|
|
|
|
const deal = (arr, dbm) => {
|
|
|
|
|
for (let i = 0; i < 6400; i++) {
|
|
|
|
|
let j = parseInt(i / 128) + 1;
|
|
|
|
|
arr[i] = [j, parseInt((i - (j - 1) * 128 + 1) * 2.8125), parseInt(dbm[i]) + 80];
|
|
|
|
|
}
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
const findMonitorNameByKey = (arr, key) => {
|
|
|
|
|
let result = [];
|
|
|
|
|
arr.forEach(item => {
|
|
|
|
|
if (item?.children?.length) {
|
|
|
|
|
result = [...result, ...item.children]
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return result.find(item => item.key === key)?.name
|
|
|
|
|
}
|
|
|
|
|
// 获取24h前时间
|
|
|
|
|
const getPrevious24HourMark = (timeStr) => {
|
|
|
|
|
const date = new Date(timeStr);
|
|
|
|
|
date.setHours(date.getHours() - 24);
|
|
|
|
|
// 注意:分钟、秒、毫秒会保留原始值
|
|
|
|
|
const year = date.getFullYear();
|
|
|
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
|
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
|
|
}
|
|
|
|
|
// 历史趋势图组件
|
|
|
|
|
const trendGraphRefs = ref([]);
|
|
|
|
|
watch(trendGraphRefs, (arr) => {
|
|
|
|
|
// 此处定时器解决异步
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
arr.forEach((el) => {
|
|
|
|
|
el.getChart().group = 'trend-group';
|
|
|
|
|
});
|
|
|
|
|
}, 300);
|
|
|
|
|
}, {
|
|
|
|
|
immediate: true,
|
|
|
|
|
deep: true,
|
|
|
|
|
},);
|
|
|
|
|
// 历史趋势图谱
|
|
|
|
|
const historyTrendGraph = {
|
|
|
|
|
template: `<div class='graph-container'>
|
|
|
|
|
<div class="title">
|
|
|
|
|
监测点:{{ data?.label||'' }}
|
|
|
|
|
</div>
|
|
|
|
|
<div ref='graphRef' class="line-graph" @dblclick='onDblclickGraph'></div>
|
|
|
|
|
</div>`,
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
resizeObserver: null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
props: {
|
|
|
|
|
data: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => { }
|
|
|
|
|
},
|
|
|
|
|
// 使用的场景
|
|
|
|
|
usedTab: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: 'historyTrend'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 定义常量,不定义在data(减少性能开销)
|
|
|
|
|
created() {
|
|
|
|
|
this.chart = null
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
data: {
|
|
|
|
|
async handler(val, oldVal) {
|
|
|
|
|
if (
|
|
|
|
|
val.key === oldVal?.key &&
|
|
|
|
|
val.label === oldVal?.label &&
|
|
|
|
|
val.startTime === oldVal?.startTime &&
|
|
|
|
|
val.endTime === oldVal?.endTime
|
|
|
|
|
) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const { startTime, endTime, key } = val
|
|
|
|
|
if (!key || !startTime) return
|
|
|
|
|
this.chart?.showLoading()
|
|
|
|
|
const params = {
|
|
|
|
|
current: 1,
|
|
|
|
|
startTime,
|
|
|
|
|
endTime,
|
|
|
|
|
monitorKey: key,
|
|
|
|
|
pageSize: 99999
|
|
|
|
|
}
|
|
|
|
|
const { data: { result: { result: { result } } } } = await axios.get(`/ldpdtools/trendData/listByParam`, {
|
|
|
|
|
params,
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
this.chart?.hideLoading()
|
|
|
|
|
})
|
|
|
|
|
this.initTrendGraph(result || [])
|
|
|
|
|
},
|
|
|
|
|
deep: true,
|
|
|
|
|
immediate: true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async mounted() {
|
|
|
|
|
this.resizeObserver = new ResizeObserver(() => {
|
|
|
|
|
this.chart?.resize();
|
|
|
|
|
});
|
|
|
|
|
this.resizeObserver.observe(this.$refs.graphRef);
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
initTrendGraph(data) {
|
|
|
|
|
// 图数据
|
|
|
|
|
const series = HISTORY_TREND_LEGEND.map((item, index) => ({
|
|
|
|
|
name: item.name,
|
|
|
|
|
type: 'line',
|
|
|
|
|
yAxisIndex: index,
|
|
|
|
|
data: data.map(el => el[item.id]),
|
|
|
|
|
smooth: true,
|
|
|
|
|
showSymbol: false,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
width: 2,
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
const legend = {
|
|
|
|
|
data: HISTORY_TREND_LEGEND.map(s => s.name), // 图例数据
|
|
|
|
|
top: 0,
|
|
|
|
|
};
|
|
|
|
|
const xAxis = {
|
|
|
|
|
type: 'category',
|
|
|
|
|
data: data.map(el => el.time.replace(' ', '\n')),
|
|
|
|
|
axisLine: {
|
|
|
|
|
onZero: false, // 禁止轴线对齐到0刻度,强制固定在底部
|
|
|
|
|
},
|
|
|
|
|
name: '时间',
|
|
|
|
|
axisLabel: {
|
|
|
|
|
fontSize: 10,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const yAxis = HISTORY_TREND_LEGEND.map((item, index) => {
|
|
|
|
|
return {
|
|
|
|
|
type: 'value',
|
|
|
|
|
name: item.name,
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
color: '#666',
|
|
|
|
|
fontSize: 10,
|
|
|
|
|
padding: [0, 0, 0, 30], // 上、右、下、左(左间距30px)
|
|
|
|
|
},
|
|
|
|
|
triggerEvent: true, // 关键配置
|
|
|
|
|
axisLabel: {
|
|
|
|
|
formatter: '{value}',
|
|
|
|
|
fontSize: 10,
|
|
|
|
|
},
|
|
|
|
|
position: 'right',
|
|
|
|
|
offset: (index + 1) * 48, // 控制 Y 轴横向间距
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: false, // 仅第一个 Y 轴显示网格线
|
|
|
|
|
},
|
|
|
|
|
splitNumber: 3, // Y轴仅显示3个刻度线
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
this.chart = echarts.init(this.$refs.graphRef);
|
|
|
|
|
const option = {
|
|
|
|
|
// 设置响应式
|
|
|
|
|
grid: {
|
|
|
|
|
top: 30,
|
|
|
|
|
right: 230,
|
|
|
|
|
bottom: 30,
|
|
|
|
|
left: 30
|
|
|
|
|
},
|
|
|
|
|
tooltip: {
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
axisPointer: {
|
|
|
|
|
type: 'cross'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
legend,
|
|
|
|
|
xAxis,
|
|
|
|
|
yAxis,
|
|
|
|
|
series,
|
|
|
|
|
dataZoom: [
|
|
|
|
|
{
|
|
|
|
|
type: 'slider', // 滑动条型数据区域缩放
|
|
|
|
|
xAxisIndex: [0],
|
|
|
|
|
start: 0,
|
|
|
|
|
end: 100,
|
|
|
|
|
top: 20, // 距离底部的距离
|
|
|
|
|
height: 10, // 滑动条高度
|
|
|
|
|
throttle: 500,
|
|
|
|
|
showDetail: false // 不显示详细的起止数值,根据需求设置
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
// 3. 设置配置项并渲染图表
|
|
|
|
|
this.chart.setOption(option);
|
|
|
|
|
this.addEchartsEvents();
|
|
|
|
|
if (this.usedTab === 'prpdAndPrps') {
|
|
|
|
|
this.handleDataZoom({ start: 0, end: 100 })
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
addEchartsEvents() {
|
|
|
|
|
if (!this.chart || this.usedTab !== 'prpdAndPrps') return;
|
|
|
|
|
this.chart.on('datazoom', (params) => {
|
|
|
|
|
this.handleDataZoom(params)
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
// 外界触发筛选逻辑
|
|
|
|
|
emitFilterEvent() {
|
|
|
|
|
const { start, end } = this.chart.getOption()?.dataZoom?.[0] || {}
|
|
|
|
|
this.handleDataZoom({ start, end })
|
|
|
|
|
},
|
|
|
|
|
// 获取时间段
|
|
|
|
|
handleDataZoom(params) {
|
|
|
|
|
const startPercent = params.start;
|
|
|
|
|
const endPercent = params.end;
|
|
|
|
|
if (startPercent === undefined || endPercent === undefined) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 获取当前的 ECharts option,特别是 xAxis 的 data
|
|
|
|
|
const currentOption = this.chart.getOption();
|
|
|
|
|
const xAxisData = currentOption.xAxis[0].data; // 假设你的X轴是第一个 (index 0)
|
|
|
|
|
if (!xAxisData || xAxisData.length === 0) {
|
|
|
|
|
this.$emit('getEventList', { startTime: null, endTime: null })
|
|
|
|
|
return message.warning(`当前监测点历史趋势为空,请重新选择监测点!`);
|
|
|
|
|
}
|
|
|
|
|
const dataLength = xAxisData.length;
|
|
|
|
|
const startIndex = Math.floor(dataLength * (startPercent / 100));
|
|
|
|
|
const endIndex = Math.min(Math.ceil(dataLength * (endPercent / 100)) - 1, dataLength - 1); // -1 是因为索引从0开始
|
|
|
|
|
const startCategory = xAxisData[startIndex];
|
|
|
|
|
const endCategory = xAxisData[endIndex];
|
|
|
|
|
const startTime = startCategory ? String(startCategory).replace(/\n/g, ' ') : '';
|
|
|
|
|
const endTime = endCategory ? String(endCategory).replace(/\n/g, ' ') : '';
|
|
|
|
|
if (!startTime || !endTime) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.$emit('getEventList', { startTime, endTime })
|
|
|
|
|
},
|
|
|
|
|
// 双击跳转
|
|
|
|
|
onDblclickGraph() {
|
|
|
|
|
if (this.usedTab !== 'historyTrend') return
|
|
|
|
|
// 是否空数据
|
|
|
|
|
const isEmptyData = this.chart.getOption().series?.[0]?.data?.length === 0
|
|
|
|
|
if (isEmptyData) {
|
|
|
|
|
return message.error(`当前数据为空!`);
|
|
|
|
|
}
|
|
|
|
|
this.$emit('jumpToPrpd', this.data.key)
|
|
|
|
|
},
|
|
|
|
|
getChart() {
|
|
|
|
|
return this.chart;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// prpd/prps组件
|
|
|
|
|
const prpdAndPrpsComp = {
|
|
|
|
|
template: `<div>
|
|
|
|
|
<div class="total-prpd-title" :style="{color:!!data.monitorName?'red':''}">
|
|
|
|
|
{{title}}</div>
|
|
|
|
|
<div v-show='currentKey==="PRPD"' ref="prpdBoxRef" class="prpd"></div>
|
|
|
|
|
<div v-show='currentKey==="PRPS"' ref="prpsBoxRef" class="prps"></div>
|
|
|
|
|
<div v-if='!isCountPrpd' class='switcher'>
|
|
|
|
|
<span v-for='item in switchBox' :key='item' @click='currentKey=item'
|
|
|
|
|
:class='[currentKey===item?"active-span":""]'>
|
|
|
|
|
<span v-if='item==="PRPS"'>/</span>
|
|
|
|
|
{{item}}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`,
|
|
|
|
|
props: ['data', 'time', 'isCountPrpd'],
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
currentKey: 'PRPD',
|
|
|
|
|
switchBox: ['PRPD', 'PRPS',],
|
|
|
|
|
timer: 0,
|
|
|
|
|
len: 0,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
// prpd所需参数
|
|
|
|
|
mixPRPDParams() {
|
|
|
|
|
return {
|
|
|
|
|
...this.data,
|
|
|
|
|
isCountPrpd: this.isCountPrpd,
|
|
|
|
|
time: this.time
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
title() {
|
|
|
|
|
return this.data.monitorName ? this.data.monitorName + (this.isCountPrpd ? '(累计PRPD)' : '') : '暂无监测点'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
mixPRPDParams: {
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
if (newVal.monitorKey && newVal.time[0]) {
|
|
|
|
|
// 新增操作
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
if (newVal.isCountPrpd) {
|
|
|
|
|
// 加载累计prpd
|
|
|
|
|
this.currentKey = 'PRPD'
|
|
|
|
|
this.fetchPRPDData(newVal)
|
|
|
|
|
} else {
|
|
|
|
|
// 加载prpd / prps
|
|
|
|
|
this.fetchPRPDAndPrpsData(newVal)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if (!newVal.monitorKey || !newVal.time[0]) {
|
|
|
|
|
// 删除操作
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
series: [{
|
|
|
|
|
name: 'PRPD数据',
|
|
|
|
|
data: []
|
|
|
|
|
}]
|
|
|
|
|
}, { notMerge: false });
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
deep: true
|
|
|
|
|
},
|
|
|
|
|
isCountPrpd: {
|
|
|
|
|
handler(bool) {
|
|
|
|
|
if (bool) {
|
|
|
|
|
this.currentKey = 'PRPD'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
immediate: true,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
created() {
|
|
|
|
|
this.myChart = null
|
|
|
|
|
this.resizeObserver = null
|
|
|
|
|
this.myPRPSChart = null // prps容器
|
|
|
|
|
this.myPRPSOps = null
|
|
|
|
|
this.resize3dObserver = null
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
this.initPrpd()
|
|
|
|
|
this.initPrps()
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
initPrpd() {
|
|
|
|
|
const chartDom = this.$refs.prpdBoxRef;
|
|
|
|
|
this.myChart = echarts.init(chartDom);
|
|
|
|
|
const option = {
|
|
|
|
|
backgroundColor: '#ffffff', // 设置背景色为深色,与图片相似
|
|
|
|
|
tooltip: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
grid: {
|
|
|
|
|
left: '8%',
|
|
|
|
|
right: '10%',
|
|
|
|
|
top: '8%',
|
|
|
|
|
bottom: '10%',
|
|
|
|
|
containLabel: true
|
|
|
|
|
},
|
|
|
|
|
xAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
name: '相位',
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
color: '#000000' // <-- 将轴名称“相位”的颜色设置为黑色
|
|
|
|
|
},
|
|
|
|
|
nameLocation: 'middle',
|
|
|
|
|
nameGap: 30, // 调整名称与轴线的距离
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 360,
|
|
|
|
|
interval: 90, // 固定刻度为0, 90, 180, 270, 360
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#000' // X轴刻度文字颜色
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ccc' // X轴线颜色
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: true,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ccc', // X轴网格线颜色
|
|
|
|
|
type: 'solid'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
yAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
name: '幅值',
|
|
|
|
|
nameLocation: 'middle',
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
color: '#000000' // <-- 将轴名称“相位”的颜色设置为黑色
|
|
|
|
|
},
|
|
|
|
|
nameRotate: 90, // Y轴名称旋转
|
|
|
|
|
nameGap: 30, // 调整名称与轴线的距离
|
|
|
|
|
min: -80,
|
|
|
|
|
max: 0,
|
|
|
|
|
interval: 20, // 固定刻度为 -80, -60, -40, -20, 0
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#000', // Y轴刻度文字颜色
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ccc' // Y轴线颜色
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: true,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ccc', // Y轴网格线颜色
|
|
|
|
|
type: 'solid'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 颜色区分
|
|
|
|
|
visualMap: {
|
|
|
|
|
dimension: 2,
|
|
|
|
|
show: false,
|
|
|
|
|
inRange: {
|
|
|
|
|
color: ['#007ACC', '#FF4500'] // 例如:从浅蓝色到深蓝色
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
name: '正弦波形', // 系列名称
|
|
|
|
|
type: 'line', // 图表类型为折线图
|
|
|
|
|
smooth: true, // 开启平滑曲线
|
|
|
|
|
showSymbol: false, // 不显示数据点符号
|
|
|
|
|
lineStyle: {
|
|
|
|
|
width: 2 // 调整线条宽度
|
|
|
|
|
},
|
|
|
|
|
data: generateSineWaveData() // 调用函数生成数据
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'PRPD数据',
|
|
|
|
|
type: 'scatter', // 使用折线图来模拟曲线
|
|
|
|
|
symbolSize: 1,
|
|
|
|
|
data: [],
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
this.myChart.setOption(option);
|
|
|
|
|
this.resizeObserver = new ResizeObserver(() => {
|
|
|
|
|
this.myChart?.resize();
|
|
|
|
|
});
|
|
|
|
|
this.resizeObserver.observe(chartDom);
|
|
|
|
|
},
|
|
|
|
|
// 请求PRPD数据
|
|
|
|
|
async fetchPRPDData(data) {
|
|
|
|
|
this.myChart.showLoading()
|
|
|
|
|
const params = {
|
|
|
|
|
startTime: data.time[0],
|
|
|
|
|
endTime: data.time[1],
|
|
|
|
|
monitorKey: data.monitorKey,
|
|
|
|
|
}
|
|
|
|
|
const { data: { result: res } } = await axios.get(`/ldpdtools/eventData/getPrpdByParam`, {
|
|
|
|
|
params,
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
series: [{
|
|
|
|
|
name: 'PRPD数据',
|
|
|
|
|
data: [],
|
|
|
|
|
symbolSize: 1,
|
|
|
|
|
}],
|
|
|
|
|
}, { notMerge: false });
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
this.myChart.hideLoading()
|
|
|
|
|
})
|
|
|
|
|
const result = res || []
|
|
|
|
|
const countArr = result.map(item => item[2])
|
|
|
|
|
const minCount = Math.min(...countArr)
|
|
|
|
|
const maxCount = Math.max(...countArr)
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
series: [{
|
|
|
|
|
name: 'PRPD数据',
|
|
|
|
|
data: result,
|
|
|
|
|
symbolSize: 1,
|
|
|
|
|
}],
|
|
|
|
|
visualMap: {
|
|
|
|
|
min: minCount,
|
|
|
|
|
max: maxCount
|
|
|
|
|
}
|
|
|
|
|
}, { notMerge: false });
|
|
|
|
|
},
|
|
|
|
|
// 请求prpd/prps的float数据
|
|
|
|
|
async fetchPRPDAndPrpsData({ monitorKey, time }) {
|
|
|
|
|
this.myChart.showLoading()
|
|
|
|
|
const params = {
|
|
|
|
|
monitorKey,
|
|
|
|
|
timeStr: time[0],
|
|
|
|
|
}
|
|
|
|
|
const { data: { result: res } } = await axios.get(`/ldpdtools/eventData/getInfoByTime`, {
|
|
|
|
|
params,
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
this.myChart.hideLoading()
|
|
|
|
|
})
|
|
|
|
|
this.draw2dChart(res)
|
|
|
|
|
this.draw3dChart(res)
|
|
|
|
|
},
|
|
|
|
|
// prpd数据处理
|
|
|
|
|
draw2dChart(params) {
|
|
|
|
|
const res = params || []
|
|
|
|
|
let dbm = res.slice(6400, 12800);
|
|
|
|
|
if (dbm.length == 0) {
|
|
|
|
|
dbm = res.slice(0, 6400)
|
|
|
|
|
} else if (dbm.length < 6400) {
|
|
|
|
|
dbm = res.slice(6400, 6400 + dbm.length).concat(res.slice(0, 6400 - dbm.length))
|
|
|
|
|
}
|
|
|
|
|
let arr = [];
|
|
|
|
|
deal(arr, dbm)
|
|
|
|
|
const data = this.datting(arr)
|
|
|
|
|
const result = data.map(item => [item[1], item[2] - 80, item[0]])
|
|
|
|
|
const countArr = result.map(item => item[2])
|
|
|
|
|
const minCount = Math.min(...countArr)
|
|
|
|
|
const maxCount = Math.max(...countArr)
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
series: [{
|
|
|
|
|
name: 'PRPD数据',
|
|
|
|
|
data: result,
|
|
|
|
|
symbolSize: 2.5,
|
|
|
|
|
}],
|
|
|
|
|
visualMap: {
|
|
|
|
|
min: minCount,
|
|
|
|
|
max: maxCount
|
|
|
|
|
}
|
|
|
|
|
}, { notMerge: false });
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
datting(arr) {
|
|
|
|
|
let dataArr = [];
|
|
|
|
|
let newArr = [];
|
|
|
|
|
for (let i = 1; i <= 128; i++) {
|
|
|
|
|
let obj = []
|
|
|
|
|
for (let j = 0; j < 50; j++) {
|
|
|
|
|
obj.push(arr[i + j * 128 - 1])
|
|
|
|
|
}
|
|
|
|
|
newArr.push(obj);
|
|
|
|
|
};
|
|
|
|
|
let lay1 = []
|
|
|
|
|
for (let i = 0; i < newArr.length; i++) {
|
|
|
|
|
let lay2 = [];
|
|
|
|
|
for (let k = 0; k < 80; k++) {
|
|
|
|
|
let lay3 = [];
|
|
|
|
|
for (let j = 0; j < newArr[i].length; j++) {
|
|
|
|
|
if (newArr[i][j][2] == k) {
|
|
|
|
|
lay3.push(newArr[i][j])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (lay3 != '') {
|
|
|
|
|
lay2.push(lay3)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lay1.push(lay2)
|
|
|
|
|
// console.log(lay1)
|
|
|
|
|
}
|
|
|
|
|
for (let i = 0; i < lay1.length; i++) {
|
|
|
|
|
for (let j = 0; j < lay1[i].length; j++) {
|
|
|
|
|
for (let k = 0; k < lay1[i][j].length; k++) {
|
|
|
|
|
for (let m = 0; m < lay1[i][j][k].length; m++) {
|
|
|
|
|
lay1[i][j][k][0] = lay1[i][j].length;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dataArr.push(lay1[i][j][0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// console.log(dataArr)
|
|
|
|
|
return dataArr;
|
|
|
|
|
},
|
|
|
|
|
// 初始化prps
|
|
|
|
|
initPrps() {
|
|
|
|
|
const dom3d = this.$refs.prpsBoxRef
|
|
|
|
|
this.myPRPSChart = echarts.init(dom3d);
|
|
|
|
|
// 初始化一次不变的 ECharts 配置
|
|
|
|
|
this.myPRPSOps = {
|
|
|
|
|
title: {
|
|
|
|
|
text: 'PRPS',
|
|
|
|
|
left: 'center',
|
|
|
|
|
top: 10,
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
color: '#111'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
animation: false,
|
|
|
|
|
tooltip: {
|
|
|
|
|
show: false,
|
|
|
|
|
},
|
|
|
|
|
toolbox: {
|
|
|
|
|
show: false,
|
|
|
|
|
},
|
|
|
|
|
visualMap: {
|
|
|
|
|
min: -20,
|
|
|
|
|
max: 80,
|
|
|
|
|
show: false,
|
|
|
|
|
itemWidth: 5,
|
|
|
|
|
orient: "vertical",
|
|
|
|
|
inRange: {
|
|
|
|
|
color: ['transparent', '#00ee00', '#eeee00', '#ee0000', '#4e0211']
|
|
|
|
|
},
|
|
|
|
|
formatter: (value) => {
|
|
|
|
|
return parseInt(value - 80);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
xAxis3D: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 50,
|
|
|
|
|
splitNumber: 5,
|
|
|
|
|
name: '周期',
|
|
|
|
|
nameGap: 24,
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#000'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#000',
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
formatter: (value, index) => {
|
|
|
|
|
value = 50 - value
|
|
|
|
|
if (value >= 0) {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
yAxis3D: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 360,
|
|
|
|
|
splitNumber: 4,
|
|
|
|
|
interval: 90,
|
|
|
|
|
name: '相位',
|
|
|
|
|
nameGap: 24,
|
|
|
|
|
splitArea: {
|
|
|
|
|
interval: 4,
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#000'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#000',
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
zAxis3D: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 80,
|
|
|
|
|
scale: true,
|
|
|
|
|
splitNumber: 4,
|
|
|
|
|
name: '幅值',
|
|
|
|
|
nameGap: 24,
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#000'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#000',
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
formatter: (value, index) => {
|
|
|
|
|
if (value >= 0) {
|
|
|
|
|
return value - 80;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
grid3D: {
|
|
|
|
|
boxHeight: 100,
|
|
|
|
|
boxWidth: 120,
|
|
|
|
|
boxDepth: 100,
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#fff',
|
|
|
|
|
opacity: 0.1
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisPointer: {
|
|
|
|
|
show: false,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#fff'
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
viewControl: {
|
|
|
|
|
distance: 260,
|
|
|
|
|
minDistance: 40,
|
|
|
|
|
maxDistance: 400,
|
|
|
|
|
rotateSensitivity: [1, 1],
|
|
|
|
|
zoomSensitivity: 0,
|
|
|
|
|
panSensitivity: 0,
|
|
|
|
|
panMouseButton: "middle",
|
|
|
|
|
rotateMouseButton: "left",
|
|
|
|
|
orthographicSize: 150,
|
|
|
|
|
maxOrthographicSize: 400,
|
|
|
|
|
minOrthographicSize: 20,
|
|
|
|
|
center: [0, -10, 0],
|
|
|
|
|
minBeta: 30,
|
|
|
|
|
maxBeta: 180,
|
|
|
|
|
minAlpha: -90,
|
|
|
|
|
maxAlpha: 90,
|
|
|
|
|
projection: "perspective",
|
|
|
|
|
autoRotateDirection: "cw",
|
|
|
|
|
autoRotateAfterStill: 3,
|
|
|
|
|
damping: 0.8
|
|
|
|
|
},
|
|
|
|
|
light: {
|
|
|
|
|
main: { intensity: 1.2 },
|
|
|
|
|
ambient: { intensity: 0.3 }
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
roam: false,
|
|
|
|
|
series: [{
|
|
|
|
|
type: 'bar3D',
|
|
|
|
|
data: [],
|
|
|
|
|
shading: 'color',
|
|
|
|
|
label: {
|
|
|
|
|
show: false,
|
|
|
|
|
},
|
|
|
|
|
itemStyle: {
|
|
|
|
|
opacity: 0.8,
|
|
|
|
|
},
|
|
|
|
|
silent: true,
|
|
|
|
|
emphasis: {
|
|
|
|
|
label: { show: false },
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
};
|
|
|
|
|
this.myPRPSChart.setOption(this.myPRPSOps);
|
|
|
|
|
this.resize3dObserver = new ResizeObserver(() => {
|
|
|
|
|
this.myPRPSChart?.resize();
|
|
|
|
|
});
|
|
|
|
|
this.resize3dObserver.observe(dom3d);
|
|
|
|
|
},
|
|
|
|
|
// prps数据处理
|
|
|
|
|
draw3dChart(data) {
|
|
|
|
|
let databox = []
|
|
|
|
|
for (let i = 0; i < 6400; i++) {
|
|
|
|
|
databox[i] = -128;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
const fullData = databox.concat(data); // 直接使用导入的 JSON 数
|
|
|
|
|
this.dispose([...fullData]); // 启动动画
|
|
|
|
|
},
|
|
|
|
|
// 动画循环逻辑
|
|
|
|
|
dispose(data) {
|
|
|
|
|
clearTimeout(this.timer); // 清除上一个定时器
|
|
|
|
|
this.drawEcharts3d(data); // 绘制图表
|
|
|
|
|
let em = [];
|
|
|
|
|
em = data.splice(0, 1280); // 移除前1000个元素
|
|
|
|
|
this.len++; // 计数器加一
|
|
|
|
|
|
|
|
|
|
if (this.len > 5) { // 如果超过5次循环,将移除的元素重新加回末尾
|
|
|
|
|
data = data.concat(em);
|
|
|
|
|
}
|
|
|
|
|
// 设置下一个定时器
|
|
|
|
|
this.timer = setTimeout(() => {
|
|
|
|
|
this.dispose(data); // 递归调用自身
|
|
|
|
|
}, 200);
|
|
|
|
|
},
|
|
|
|
|
drawEcharts3d(obj) {
|
|
|
|
|
if (!this.myPRPSChart) return; // 确保图表实例已存在
|
|
|
|
|
let arr = [];
|
|
|
|
|
deal(arr, obj); // 处理数据
|
|
|
|
|
// 只更新 series 的 data 部分
|
|
|
|
|
this.myPRPSChart.setOption({
|
|
|
|
|
series: [{
|
|
|
|
|
data: arr.map(function (item) {
|
|
|
|
|
return {
|
|
|
|
|
value: [item[0], item[1], item[2]]
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
// 事件统计组件
|
|
|
|
|
const eventCount = {
|
|
|
|
|
components: {
|
|
|
|
|
historyTrendGraph,
|
|
|
|
|
},
|
|
|
|
|
template: `<div class='event-count-box'>
|
|
|
|
|
<history-trend-graph :data='graphInfo' used-tab="eventCount"/>
|
|
|
|
|
<div class="pd-type-grid">
|
|
|
|
|
<el-table :data="pdTypeData" border>
|
|
|
|
|
<el-table-column prop="typeCn" label="局放类型"/>
|
|
|
|
|
<el-table-column prop="max" label="最大值" />
|
|
|
|
|
<el-table-column prop="avg" label="平均值" />
|
|
|
|
|
<el-table-column prop="count" label="事件数" />
|
|
|
|
|
<el-table-column prop="plusCount" label="脉冲数" />
|
|
|
|
|
</el-table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>`,
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
pdTypeData: []
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
props: ['time', 'selectedKey', 'treeData'],
|
|
|
|
|
inject: ['provideAllPdTypes'],
|
|
|
|
|
computed: {
|
|
|
|
|
graphInfo() {
|
|
|
|
|
return {
|
|
|
|
|
key: this.selectedKey,
|
|
|
|
|
label: findMonitorNameByKey(this.treeData, this.selectedKey),
|
|
|
|
|
startTime: this.time[0],
|
|
|
|
|
endTime: this.time[1],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
graphInfo: {
|
|
|
|
|
handler(value) {
|
|
|
|
|
const { startTime, endTime, key } = value
|
|
|
|
|
if (!key || !startTime) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.feachGrid()
|
|
|
|
|
},
|
|
|
|
|
deep: true,
|
|
|
|
|
immediate: true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 获取表格数据
|
|
|
|
|
async feachGrid() {
|
|
|
|
|
this.loading = true
|
|
|
|
|
const params = {
|
|
|
|
|
startTime: this.time[0],
|
|
|
|
|
endTime: this.time[1],
|
|
|
|
|
monitorKey: this.selectedKey,
|
|
|
|
|
}
|
|
|
|
|
const { data: { result } } = await axios.get(`/ldpdtools/eventData/getEventStatistics`, {
|
|
|
|
|
params,
|
|
|
|
|
})
|
|
|
|
|
const res = result || {}
|
|
|
|
|
const data = [] // 展示的数据
|
|
|
|
|
Object.keys(res).forEach(key => {
|
|
|
|
|
const type = unref(this.provideAllPdTypes).find(el => el.value == key)
|
|
|
|
|
data.push({
|
|
|
|
|
typeCn: type.label,
|
|
|
|
|
typeEn: type.value,
|
|
|
|
|
...res[key]
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
this.pdTypeData = data || []
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
createApp({
|
|
|
|
|
setup() {
|
|
|
|
|
const typeOfCheckable = ['historyTrend', 'prpdAndPrps']
|
|
|
|
|
const timeSelectArr = ['historyTrend', 'prpdAndPrps', 'eventCount'] // 含有时间选择的组件
|
|
|
|
|
const treeData = ref([])
|
|
|
|
|
const fullTreeData = ref([]) // 懒加载后的完整菜单数据
|
|
|
|
|
const checkedKeys1 = ref([]); // 勾选
|
|
|
|
|
const selectedKey = ref('') // 选中
|
|
|
|
|
const defaultExpendKeys = ref([]); // 默认展开的节点
|
|
|
|
|
const treeMenuInfo = reactive({
|
|
|
|
|
menuVisible: false,
|
|
|
|
|
data: null,
|
|
|
|
|
menuX: 0,
|
|
|
|
|
menuY: 0
|
|
|
|
|
})
|
|
|
|
|
const treeMenu = ref()
|
|
|
|
|
const handleClickOutside = (e) => {
|
|
|
|
|
if (treeMenuInfo.menuVisible && !treeMenu.value?.contains(e.target)) {
|
|
|
|
|
treeMenuInfo.menuVisible = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const searchValue = ref('');
|
|
|
|
|
const treeRef = ref()
|
|
|
|
|
const activeKey = ref('alarmConfig')
|
|
|
|
|
const tabsArr = [
|
|
|
|
|
{ key: 'alarmConfig', tab: '告警列表' },
|
|
|
|
|
{ key: 'historyTrend', tab: '历史趋势' },
|
|
|
|
|
{ key: 'prpdAndPrps', tab: 'PRPD/PRPS' },
|
|
|
|
|
{ key: 'eventCount', tab: '事件统计' },
|
|
|
|
|
{ key: 'config', tab: '配置' }
|
|
|
|
|
|
|
|
|
|
]
|
|
|
|
|
const isImportMonitorModalShow = ref(false)
|
|
|
|
|
const importMonitorModalloading = ref(false)
|
|
|
|
|
const siteModalloading = ref(false)
|
|
|
|
|
const isSiteModalShow = ref(false)
|
|
|
|
|
const siteModalRef = ref()
|
|
|
|
|
const siteHistoryData = ref() // 站点历史数据
|
|
|
|
|
// 站点信息
|
|
|
|
|
const siteModalForm = reactive({
|
|
|
|
|
stationName: '',
|
|
|
|
|
img: ''
|
|
|
|
|
})
|
|
|
|
|
const isAddTypeOfSiteModal = ref(true) // true:新增站点 false:修改站点
|
|
|
|
|
const isMonitorModalShow = ref(false) // 监测点弹框
|
|
|
|
|
const isAddTypeOfMonitorModal = ref(true) // true:新增监测点 false:修改监测点
|
|
|
|
|
const monitorModalLoading = ref(false)
|
|
|
|
|
const monitorModalRef = ref()
|
|
|
|
|
const monitorModalForm = reactive({
|
|
|
|
|
stationName: '', // 站点名称
|
|
|
|
|
name: '',// 监测点名称
|
|
|
|
|
monitorKey: '' // 监测点key
|
|
|
|
|
})
|
|
|
|
|
// 查询树
|
|
|
|
|
const search = () => {
|
|
|
|
|
treeRef.value.filter(unref(searchValue)); // 触发过滤
|
|
|
|
|
};
|
|
|
|
|
const filterNode = (value, data) => {
|
|
|
|
|
if (!value) return true;
|
|
|
|
|
return data.name.includes(value); // 根据label匹配
|
|
|
|
|
};
|
|
|
|
|
const handleRightClick = (event, data) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
treeMenuInfo.menuVisible = true
|
|
|
|
|
treeMenuInfo.menuX = event.clientX - 8
|
|
|
|
|
treeMenuInfo.menuY = event.clientY - 12
|
|
|
|
|
treeMenuInfo.data = data
|
|
|
|
|
}
|
|
|
|
|
const checkTree = (checkedNode, { checkedKeys: currentKeys }) => {
|
|
|
|
|
if (currentKeys.length > 6) {
|
|
|
|
|
message.warning('最多只能勾选6个节点!');
|
|
|
|
|
// 阻止勾选:回退到前一次的状态
|
|
|
|
|
checkedKeys1.value = checkedKeys1.value.slice(0, 6);
|
|
|
|
|
treeRef.value.setCheckedKeys(checkedKeys1.value);
|
|
|
|
|
} else {
|
|
|
|
|
if (unref(activeKey) === 'prpdAndPrps') {
|
|
|
|
|
// 处理累计prpd逻辑
|
|
|
|
|
handleCountPRPDSelect(checkedNode)
|
|
|
|
|
}
|
|
|
|
|
checkedKeys1.value = currentKeys
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
const handleNodeContentClick = (node) => {
|
|
|
|
|
if (node.isRoot) {
|
|
|
|
|
// 单击父节点
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
selectedKey.value = node.key
|
|
|
|
|
}
|
|
|
|
|
const defaultProps = {
|
|
|
|
|
children: 'children',
|
|
|
|
|
label: 'name',
|
|
|
|
|
isLeaf: 'leaf',
|
|
|
|
|
class: (node) => node.isRoot ? 'is-root' : ''
|
|
|
|
|
}
|
|
|
|
|
const onLoadData = (node, resolve) => {
|
|
|
|
|
if (node.level !== 1) {
|
|
|
|
|
resolve([]);
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const stationName = node?.label ?? ''
|
|
|
|
|
axios.get(`/ldpdtools/monitor/monitorList?stationName=${stationName}`).then(({ data: { code, result } }) => {
|
|
|
|
|
const data = (result || []).map(item => {
|
|
|
|
|
return {
|
|
|
|
|
title: item.name,
|
|
|
|
|
key: item.monitorKey,
|
|
|
|
|
isRoot: false,
|
|
|
|
|
disabled: false,
|
|
|
|
|
leaf: true,
|
|
|
|
|
...item
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
resolve(data)
|
|
|
|
|
fullTreeData.value = treeRef.value?.store?.root.childNodes.map(node => formatTreeData(node));
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// 初始化树
|
|
|
|
|
const initTreeData = async () => {
|
|
|
|
|
const { data: { code, result } } = await axios.get('/ldpdtools/monitor/getStations');
|
|
|
|
|
if (code !== 200) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
treeData.value = result.map((item, index) => {
|
|
|
|
|
return {
|
|
|
|
|
key: index,
|
|
|
|
|
title: item.stationName,
|
|
|
|
|
isRoot: true,
|
|
|
|
|
disabled: true,
|
|
|
|
|
leaf: false,
|
|
|
|
|
...item
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
// 初始化默认展开第一个父节点
|
|
|
|
|
if (unref(treeData)?.length) {
|
|
|
|
|
const firstParentNodeData = unref(treeData)[0].key;
|
|
|
|
|
defaultExpendKeys.value = [firstParentNodeData]
|
|
|
|
|
}
|
|
|
|
|
fullTreeData.value = treeRef.value?.store?.root.childNodes.map(node => formatTreeData(node));
|
|
|
|
|
}
|
|
|
|
|
// 编辑节点
|
|
|
|
|
const editNodeItem = (data) => {
|
|
|
|
|
const { isRoot, stationName, img, monitorKey, name } = data
|
|
|
|
|
if (isRoot) {
|
|
|
|
|
// 编辑站点
|
|
|
|
|
isSiteModalShow.value = true
|
|
|
|
|
isAddTypeOfSiteModal.value = false
|
|
|
|
|
siteModalForm.stationName = stationName
|
|
|
|
|
siteModalForm.img = img
|
|
|
|
|
siteHistoryData.value = JSON.parse(JSON.stringify({ stationName, img }))
|
|
|
|
|
} else {
|
|
|
|
|
// 编辑监测点
|
|
|
|
|
isMonitorModalShow.value = true
|
|
|
|
|
isAddTypeOfMonitorModal.value = false
|
|
|
|
|
monitorModalForm.stationName = stationName
|
|
|
|
|
monitorModalForm.name = name
|
|
|
|
|
monitorModalForm.monitorKey = monitorKey
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 删除节点
|
|
|
|
|
const deleteNodeItem = async (data) => {
|
|
|
|
|
const { isRoot, stationName, monitorKey } = data
|
|
|
|
|
let resultCode = 200
|
|
|
|
|
if (isRoot) {
|
|
|
|
|
// 删除站点
|
|
|
|
|
const { data: { code } } = await axios.delete(`/ldpdtools/monitor/deleteStation?stationName=${stationName}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
} else {
|
|
|
|
|
// 删除检测点
|
|
|
|
|
const { data: { code } } = await axios.delete(`/ldpdtools/monitor/deleteMonitor?stationName=${stationName}&monitorKey=${monitorKey}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
}
|
|
|
|
|
if (resultCode === 200) {
|
|
|
|
|
message.success(`删除${isRoot ? '站点' : '监测点'}成功`);
|
|
|
|
|
initTreeData()
|
|
|
|
|
} else {
|
|
|
|
|
message.error(`删除${isRoot ? '站点' : '监测点'}失败`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 新增监测点
|
|
|
|
|
const addMonitor = (data) => {
|
|
|
|
|
const { stationName } = data
|
|
|
|
|
monitorModalForm.stationName = stationName
|
|
|
|
|
isMonitorModalShow.value = true
|
|
|
|
|
}
|
|
|
|
|
// 导入监测点
|
|
|
|
|
const onImportMonitor = () => {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
const addSite = () => {
|
|
|
|
|
isSiteModalShow.value = true
|
|
|
|
|
}
|
|
|
|
|
// 新增、编辑站点
|
|
|
|
|
const onSiteModalSubmit = async () => {
|
|
|
|
|
await siteModalRef.value.validate()
|
|
|
|
|
siteModalloading.value = true
|
|
|
|
|
const { img, stationName } = unref(siteModalForm)
|
|
|
|
|
let resultCode = 200
|
|
|
|
|
if (unref(isAddTypeOfSiteModal)) {
|
|
|
|
|
// 新增
|
|
|
|
|
const { data: { code } } = await axios.put(`/ldpdtools/monitor/saveStateion?img=${img}&stationName=${stationName}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
} else {
|
|
|
|
|
// 编辑
|
|
|
|
|
const { data: { code } } = await axios.put(`/ldpdtools/monitor/editStateion?img=${img}&newStationName=${stationName}&stationName=${unref(siteHistoryData).stationName}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
}
|
|
|
|
|
siteModalloading.value = false
|
|
|
|
|
if (resultCode === 200) {
|
|
|
|
|
message.success(`${unref(isAddTypeOfSiteModal) ? '新增' : '编辑'}站点成功`);
|
|
|
|
|
isSiteModalShow.value = false
|
|
|
|
|
initTreeData()
|
|
|
|
|
} else {
|
|
|
|
|
message.error(`${unref(isAddTypeOfSiteModal) ? '新增' : '编辑'}站点失败`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 新增、编辑监测点
|
|
|
|
|
const onMonitorModalSubmit = async () => {
|
|
|
|
|
await monitorModalRef.value.validate()
|
|
|
|
|
monitorModalLoading.value = true
|
|
|
|
|
const { stationName, name, monitorKey } = unref(monitorModalForm)
|
|
|
|
|
let resultCode = 200
|
|
|
|
|
let resultMsg = ''
|
|
|
|
|
if (unref(isAddTypeOfMonitorModal)) {
|
|
|
|
|
// 新增
|
|
|
|
|
const { data: { code, message } } = await axios.put(`/ldpdtools/monitor/saveMonitor?stationName=${stationName}&name=${name}&monitorKey=${monitorKey}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
resultMsg = message
|
|
|
|
|
} else {
|
|
|
|
|
// 编辑
|
|
|
|
|
const { data: { code, message } } = await axios.put(`/ldpdtools/monitor/editMonitor?stationName=${stationName}&name=${name}&monitorKey=${monitorKey}`);
|
|
|
|
|
resultCode = code
|
|
|
|
|
resultMsg = message
|
|
|
|
|
}
|
|
|
|
|
monitorModalLoading.value = false
|
|
|
|
|
if (resultCode === 200) {
|
|
|
|
|
message.success(`${unref(isAddTypeOfMonitorModal) ? '新增' : '编辑'}监测点成功`);
|
|
|
|
|
isMonitorModalShow.value = false
|
|
|
|
|
initTreeData()
|
|
|
|
|
} else {
|
|
|
|
|
message.error(resultMsg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 监测站点弹框关闭
|
|
|
|
|
watch(isSiteModalShow, (bool) => {
|
|
|
|
|
if (bool) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
siteModalRef.value.resetFields()
|
|
|
|
|
isAddTypeOfSiteModal.value = true
|
|
|
|
|
siteModalForm.stationName = ''
|
|
|
|
|
siteModalForm.img = ''
|
|
|
|
|
siteHistoryData.value = {}
|
|
|
|
|
})
|
|
|
|
|
// 监测监测点弹框关闭
|
|
|
|
|
watch(isMonitorModalShow, (bool) => {
|
|
|
|
|
if (bool) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
monitorModalRef.value.resetFields()
|
|
|
|
|
isAddTypeOfMonitorModal.value = true
|
|
|
|
|
monitorModalForm.stationName = ''
|
|
|
|
|
monitorModalForm.name = ''
|
|
|
|
|
monitorModalForm.monitorKey = ''
|
|
|
|
|
})
|
|
|
|
|
// 历史趋势部分逻辑
|
|
|
|
|
const trendGraphData = ref([])
|
|
|
|
|
const dateRange = ref([]);
|
|
|
|
|
// tab在历史趋势监听勾选节点
|
|
|
|
|
watch([checkedKeys1, dateRange], async ([keys, time]) => {
|
|
|
|
|
const [startTime, endTime] = time || [];
|
|
|
|
|
if (unref(activeKey) !== 'historyTrend' || !startTime || !endTime) return;
|
|
|
|
|
echarts.connect('trend-group'); // 通过分组连接
|
|
|
|
|
trendGraphData.value = keys.map((key) => {
|
|
|
|
|
return {
|
|
|
|
|
key,
|
|
|
|
|
label: findMonitorNameByKey(unref(fullTreeData), key),
|
|
|
|
|
startTime,
|
|
|
|
|
endTime,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
// 跳转到prpd/prps
|
|
|
|
|
const jumpToPRPD = (key) => {
|
|
|
|
|
activeKey.value = 'prpdAndPrps'
|
|
|
|
|
selectedKey.value = key
|
|
|
|
|
const isExist = unref(totalPrpds).some(item => item.monitorKey === key)
|
|
|
|
|
if (isExist) return
|
|
|
|
|
const addItem = unref(totalPrpds).find(item => !item.monitorKey)
|
|
|
|
|
addItem.monitorKey = key
|
|
|
|
|
addItem.monitorName = findMonitorNameByKey(unref(fullTreeData), key)
|
|
|
|
|
}
|
|
|
|
|
// 告警信息
|
|
|
|
|
const configLoading = ref(false)
|
|
|
|
|
const columns = [
|
|
|
|
|
{
|
|
|
|
|
title: '监测点',
|
|
|
|
|
dataIndex: 'name',
|
|
|
|
|
align: 'center',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '告警信息',
|
|
|
|
|
dataIndex: 'detailsInfo',
|
|
|
|
|
align: 'center',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '放电类型',
|
|
|
|
|
dataIndex: 'pdType',
|
|
|
|
|
align: 'center',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
slots: { customRender: 'name1' },
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '是否复归',
|
|
|
|
|
dataIndex: 'isCancel',
|
|
|
|
|
align: 'center',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
slots: { customRender: 'name2' },
|
|
|
|
|
width: 120
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '告警时间',
|
|
|
|
|
dataIndex: 'time',
|
|
|
|
|
align: 'center',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
width: 180
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
const dataSource = ref([])
|
|
|
|
|
const pagination = reactive({
|
|
|
|
|
current: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
total: 0,
|
|
|
|
|
showSizeChanger: true,
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
pageSizeOptions: ['5', '10', '20'],
|
|
|
|
|
showTotal: (total) => `共 ${total} 条数据`,
|
|
|
|
|
});
|
|
|
|
|
const cancelOps = [
|
|
|
|
|
{ label: '是', value: '0' },
|
|
|
|
|
{ label: '否', value: '1' },
|
|
|
|
|
]
|
|
|
|
|
const pdTypeOps = [
|
|
|
|
|
{
|
|
|
|
|
value: '1',
|
|
|
|
|
label: '尖刺放电',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: '2',
|
|
|
|
|
label: '悬浮放电',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: '3',
|
|
|
|
|
label: '沿面放电',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: '4',
|
|
|
|
|
label: '内部放电',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: '5',
|
|
|
|
|
label: '颗粒放电',
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
const alarmFilters = reactive({
|
|
|
|
|
times: [],
|
|
|
|
|
isCancel: '',
|
|
|
|
|
pdTypes: []
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 请求告警信息表格数据
|
|
|
|
|
const fetchAlarmGridData = async () => {
|
|
|
|
|
if (!unref(selectedKey)) {
|
|
|
|
|
message.warning(`请先选择左侧监测点`);
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
configLoading.value = true;
|
|
|
|
|
const params = {
|
|
|
|
|
current: pagination.current,
|
|
|
|
|
pageSize: pagination.pageSize,
|
|
|
|
|
startTime: alarmFilters.times?.[0] || '',
|
|
|
|
|
endTime: alarmFilters.times?.[1] || '',
|
|
|
|
|
isCancel: alarmFilters.isCancel,
|
|
|
|
|
pdType: alarmFilters.pdTypes,
|
|
|
|
|
monitorKey: unref(selectedKey),
|
|
|
|
|
stationName: findParentByKey(unref(fullTreeData), unref(selectedKey))
|
|
|
|
|
}
|
|
|
|
|
const { data: { result } } = await axios.post(`/ldpdtools/alarm/queryAlarmList`, params)
|
|
|
|
|
configLoading.value = false
|
|
|
|
|
dataSource.value = result?.result || []
|
|
|
|
|
pagination.total = result?.total || 0
|
|
|
|
|
}
|
|
|
|
|
// 重置表格
|
|
|
|
|
const initAlarmGridData = () => {
|
|
|
|
|
Object.assign(alarmFilters, {
|
|
|
|
|
times: [],
|
|
|
|
|
isCancel: '',
|
|
|
|
|
pdTypes: []
|
|
|
|
|
});
|
|
|
|
|
fetchAlarmGridData();
|
|
|
|
|
}
|
|
|
|
|
const handleTableChange = (pag) => {
|
|
|
|
|
Object.assign(pagination, pag);
|
|
|
|
|
fetchAlarmGridData();
|
|
|
|
|
};
|
|
|
|
|
// 单点击行
|
|
|
|
|
const alarmRowClick = (record, index) => {
|
|
|
|
|
return {
|
|
|
|
|
onDblclick: () => {
|
|
|
|
|
// 跳转到历史趋势
|
|
|
|
|
const pre24hTime = getPrevious24HourMark(record.time)
|
|
|
|
|
activeKey.value = 'historyTrend'
|
|
|
|
|
checkedKeys1.value = [record.monitorKey]
|
|
|
|
|
treeRef.value.setCheckedKeys(checkedKeys1.value);
|
|
|
|
|
dateRange.value = [pre24hTime, record.time]
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// 告警管理监听
|
|
|
|
|
watch(selectedKey, (key) => {
|
|
|
|
|
if (!key || unref(activeKey) !== 'alarmConfig') return
|
|
|
|
|
// 初始化筛选数据
|
|
|
|
|
Object.assign(alarmFilters, {
|
|
|
|
|
times: [],
|
|
|
|
|
isCancel: '',
|
|
|
|
|
pdTypes: []
|
|
|
|
|
});
|
|
|
|
|
// 请求数据
|
|
|
|
|
fetchAlarmGridData();
|
|
|
|
|
});
|
|
|
|
|
// prpd/prps
|
|
|
|
|
const totalPrpds = ref([
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '', // 监控点key
|
|
|
|
|
monitorName: '' // 监控点名称
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '',
|
|
|
|
|
monitorName: ''
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '',
|
|
|
|
|
monitorName: ''
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '',
|
|
|
|
|
monitorName: ''
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '',
|
|
|
|
|
monitorName: ''
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
monitorKey: '',
|
|
|
|
|
monitorName: ''
|
|
|
|
|
},
|
|
|
|
|
])
|
|
|
|
|
const prpdAndPrpsTimes = ref([]) // prpd/prps筛选时间
|
|
|
|
|
const eventListLoading = ref(false)
|
|
|
|
|
const eventList = ref([]) //事件列表
|
|
|
|
|
const isTypeOfCountPrpd = ref(false) //是否是累计prpd
|
|
|
|
|
const activeEventTime = ref('') // 当前选中的事件时间
|
|
|
|
|
const everntFilterVisible = ref(false)
|
|
|
|
|
const trendRef = ref()
|
|
|
|
|
// 事件筛选
|
|
|
|
|
const eventFilterForm = ref({
|
|
|
|
|
plusCount: '',
|
|
|
|
|
maxValue: '',
|
|
|
|
|
pdTypes: []
|
|
|
|
|
})
|
|
|
|
|
// 历史趋势所需数据
|
|
|
|
|
const trendGraphInfo = computed(() => {
|
|
|
|
|
return {
|
|
|
|
|
key: unref(selectedKey),
|
|
|
|
|
label: findMonitorNameByKey(unref(fullTreeData), unref(selectedKey)),
|
|
|
|
|
startTime: unref(dateRange)[0],
|
|
|
|
|
endTime: unref(dateRange)[1],
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
// 获取事件列表
|
|
|
|
|
const getEventList = async ({ startTime, endTime }) => {
|
|
|
|
|
if (startTime === null && endTime === null) {
|
|
|
|
|
// 历史趋势没数据
|
|
|
|
|
isTypeOfCountPrpd.value = true
|
|
|
|
|
eventList.value = []
|
|
|
|
|
activeEventTime.value = ''
|
|
|
|
|
prpdAndPrpsTimes.value = [] // 子组件判断空清除
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
isTypeOfCountPrpd.value = true
|
|
|
|
|
prpdAndPrpsTimes.value = [startTime, endTime]
|
|
|
|
|
eventListLoading.value = true
|
|
|
|
|
const params = {
|
|
|
|
|
current: 1,
|
|
|
|
|
pageSize: 999999999,
|
|
|
|
|
startTime,
|
|
|
|
|
endTime,
|
|
|
|
|
monitorKey: unref(selectedKey),
|
|
|
|
|
...unref(eventFilterForm),
|
|
|
|
|
pdTypes: unref(eventFilterForm).pdTypes.join(','),
|
|
|
|
|
};
|
|
|
|
|
const { data: { code, result: { result: res } } } = await axios.get('/ldpdtools/eventData/listByParam', { params }).finally(() => {
|
|
|
|
|
eventListLoading.value = false
|
|
|
|
|
})
|
|
|
|
|
if (code !== 200) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
activeEventTime.value = ''
|
|
|
|
|
eventList.value = res?.map(item => {
|
|
|
|
|
return {
|
|
|
|
|
pdType: item.pdType,
|
|
|
|
|
time: item.time,
|
|
|
|
|
maxValue: item.maxFloat,
|
|
|
|
|
plusCount: item.plusCount,
|
|
|
|
|
}
|
|
|
|
|
}) || []
|
|
|
|
|
}
|
|
|
|
|
// 筛选
|
|
|
|
|
const onFilterEventList = () => {
|
|
|
|
|
trendRef.value.emitFilterEvent()
|
|
|
|
|
everntFilterVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
// 重置筛选框
|
|
|
|
|
const onResetEventList = () => {
|
|
|
|
|
eventFilterForm.value = {
|
|
|
|
|
plusCount: '',
|
|
|
|
|
maxValue: '',
|
|
|
|
|
pdTypes: []
|
|
|
|
|
}
|
|
|
|
|
onFilterEventList()
|
|
|
|
|
}
|
|
|
|
|
// 点击事件
|
|
|
|
|
const handleEventClick = (data) => {
|
|
|
|
|
activeEventTime.value = data.time
|
|
|
|
|
isTypeOfCountPrpd.value = false
|
|
|
|
|
prpdAndPrpsTimes.value = [data.time, '']
|
|
|
|
|
}
|
|
|
|
|
const handleCountPRPDSelect = ({ key: currentKey }) => {
|
|
|
|
|
const index = unref(checkedKeys1).indexOf(currentKey);
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
// 取消选中
|
|
|
|
|
const deleteItem = unref(totalPrpds).find(item => item.monitorKey === currentKey)
|
|
|
|
|
deleteItem.monitorKey = ''
|
|
|
|
|
deleteItem.monitorName = ''
|
|
|
|
|
} else {
|
|
|
|
|
// 选中
|
|
|
|
|
const addItem = unref(totalPrpds).find(item => !item.monitorKey)
|
|
|
|
|
addItem.monitorKey = currentKey
|
|
|
|
|
addItem.monitorName = findMonitorNameByKey(unref(fullTreeData), currentKey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 配置页面
|
|
|
|
|
const stationName1 = ref('')
|
|
|
|
|
const deleteAlarmTimes = ref([]) // 删除告警时间段
|
|
|
|
|
const deleteAlarmConfirm = async () => {
|
|
|
|
|
if (!unref(stationName1)) {
|
|
|
|
|
return message.warning(`请选择站点!`);
|
|
|
|
|
}
|
|
|
|
|
if (!unref(deleteAlarmTimes).length) {
|
|
|
|
|
return message.warning(`请选择需要清除告警时间段!`);
|
|
|
|
|
}
|
|
|
|
|
const res = await axios.get(`/ldpdtools/alarm/deleteAlarmByTime`, {
|
|
|
|
|
params: {
|
|
|
|
|
startTime: unref(deleteAlarmTimes)?.[0] || '',
|
|
|
|
|
endTime: unref(deleteAlarmTimes)?.[1] || '',
|
|
|
|
|
stationName: unref(stationName1)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// 上传前校验
|
|
|
|
|
const alarmBeforeUpload = (file) => {
|
|
|
|
|
if (!unref(stationName1)) {
|
|
|
|
|
message.warning(`请选择站点!`);
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
const allowedTypes = ['text/csv', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
|
|
|
|
|
const isAllowedType = allowedTypes.includes(file.type) ||
|
|
|
|
|
['.csv', '.xlsx', '.xls'].some(ext => file.name.toLowerCase().endsWith(ext))
|
|
|
|
|
if (!isAllowedType) {
|
|
|
|
|
message.error('只能上传 CSV 或 Excel 文件!')
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
const isLt10M = file.size / 1024 / 1024 < 10
|
|
|
|
|
if (!isLt10M) {
|
|
|
|
|
message.error('文件大小不能超过 10MB!')
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 自定义上传方法
|
|
|
|
|
const alarmCustomUpload = async (options) => {
|
|
|
|
|
const { file } = options
|
|
|
|
|
try {
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
formData.append('file', file)
|
|
|
|
|
const { data: { code, message: message1 } } = await axios.post(`/ldpdtools/alarm/importAlarm`, formData, {
|
|
|
|
|
params: {
|
|
|
|
|
stationName: unref(stationName1)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
message.success(message1)
|
|
|
|
|
} else {
|
|
|
|
|
message.error('导入失败')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('上传错误:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const allPathCongfigs = ref([]) // 所有路径配置
|
|
|
|
|
const isCurrentInit = ref(false) // 是否正在初始化
|
|
|
|
|
const initTips = ref('')
|
|
|
|
|
const allPdTypes = ref([])
|
|
|
|
|
provide('provideAllPdTypes', allPdTypes)
|
|
|
|
|
// 获取放电类型
|
|
|
|
|
const getPdTypes = async () => {
|
|
|
|
|
const types = []
|
|
|
|
|
const { data: { result } } = await axios.get('/ldpdtools/config/getPdTypes');
|
|
|
|
|
Object.keys(result).forEach(key => {
|
|
|
|
|
types.push({
|
|
|
|
|
value: key,
|
|
|
|
|
label: result[key]
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
allPdTypes.value = types
|
|
|
|
|
}
|
|
|
|
|
// 获取所有配置项
|
|
|
|
|
const getAllConfigs = async () => {
|
|
|
|
|
getPdTypes()
|
|
|
|
|
allPathCongfigs.value = []
|
|
|
|
|
const { data: { result } } = await axios.post('/ldpdtools/config/getConfigKey')
|
|
|
|
|
Object.keys(result).forEach(key => {
|
|
|
|
|
allPathCongfigs.value = [...unref(allPathCongfigs), {
|
|
|
|
|
key,
|
|
|
|
|
label: result[key],
|
|
|
|
|
value: ''
|
|
|
|
|
}]
|
|
|
|
|
})
|
|
|
|
|
const { data: { result: paths } } = await axios.get('/ldpdtools/config/getConfig')
|
|
|
|
|
// 初始化路径赋值
|
|
|
|
|
allPathCongfigs.value.forEach(item => {
|
|
|
|
|
item.value = paths[item.key] || ''
|
|
|
|
|
})
|
|
|
|
|
// 排序
|
|
|
|
|
const itemIdToMoves = ["ALARM_TYPE", "MERGIN_ROOT_PATH"];
|
|
|
|
|
const startOfItemToMove = unref(allPathCongfigs).find(item => item.key === itemIdToMoves[0]);
|
|
|
|
|
const endOfItemToMove = unref(allPathCongfigs).find(item => item.key === itemIdToMoves[1]);
|
|
|
|
|
const remainingItems = unref(allPathCongfigs).filter(item => !itemIdToMoves.includes(item.key));
|
|
|
|
|
if (startOfItemToMove && endOfItemToMove) {
|
|
|
|
|
allPathCongfigs.value = [startOfItemToMove, ...remainingItems, endOfItemToMove];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 保存路径
|
|
|
|
|
const savePathConfig = async (data) => {
|
|
|
|
|
if (!data.value) {
|
|
|
|
|
return message.error(`请输入${data.label}!`);
|
|
|
|
|
}
|
|
|
|
|
const { label, ...params } = data
|
|
|
|
|
const { data: { code } } = await axios.get('/ldpdtools/config/editConfig', { params })
|
|
|
|
|
if (code !== 200) return message.error(`保存${data.label}失败`)
|
|
|
|
|
message.success('保存成功!')
|
|
|
|
|
getAllConfigs()
|
|
|
|
|
}
|
|
|
|
|
// 重置路径
|
|
|
|
|
const resetPathConfig = async (key) => {
|
|
|
|
|
const { data: { code } } = await axios.get('/ldpdtools/config/resetConfig', { params: { key } })
|
|
|
|
|
if (code !== 200) return message.error(`重置${data.label}失败`)
|
|
|
|
|
message.success('重置成功!')
|
|
|
|
|
getAllConfigs()
|
|
|
|
|
}
|
|
|
|
|
// 获取初始化进度
|
|
|
|
|
const getInitPrgress = async () => {
|
|
|
|
|
const { data: { message } } = await axios.get('/ldpdtools/config/getInitProgress')
|
|
|
|
|
isCurrentInit.value = message.includes('/')
|
|
|
|
|
initTips.value = message
|
|
|
|
|
}
|
|
|
|
|
// 初始化目录
|
|
|
|
|
const initCatalogue = async () => {
|
|
|
|
|
const { data: { code } } = await axios.get('/ldpdtools/config/initConfig')
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
getInitPrgress()
|
|
|
|
|
}, 1000) // 后台有一定延迟
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
initTreeData()
|
|
|
|
|
getAllConfigs()
|
|
|
|
|
getInitPrgress()
|
|
|
|
|
document.addEventListener('click', handleClickOutside);
|
|
|
|
|
})
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
document.removeEventListener('click', handleClickOutside);
|
|
|
|
|
});
|
|
|
|
|
return {
|
|
|
|
|
treeRef,
|
|
|
|
|
treeData,
|
|
|
|
|
fullTreeData,
|
|
|
|
|
treeMenuInfo,
|
|
|
|
|
treeMenu,
|
|
|
|
|
filterNode,
|
|
|
|
|
handleRightClick,
|
|
|
|
|
checkedKeys1,
|
|
|
|
|
searchValue,
|
|
|
|
|
search,
|
|
|
|
|
activeKey,
|
|
|
|
|
tabsArr,
|
|
|
|
|
onLoadData,
|
|
|
|
|
editNodeItem,
|
|
|
|
|
deleteNodeItem,
|
|
|
|
|
isImportMonitorModalShow,
|
|
|
|
|
onImportMonitor,
|
|
|
|
|
importMonitorModalloading,
|
|
|
|
|
siteModalloading,
|
|
|
|
|
addSite,
|
|
|
|
|
isSiteModalShow,
|
|
|
|
|
siteModalRef,
|
|
|
|
|
siteModalForm,
|
|
|
|
|
onSiteModalSubmit,
|
|
|
|
|
isAddTypeOfSiteModal,
|
|
|
|
|
isMonitorModalShow,
|
|
|
|
|
isAddTypeOfMonitorModal,
|
|
|
|
|
monitorModalLoading,
|
|
|
|
|
addMonitor,
|
|
|
|
|
monitorModalRef,
|
|
|
|
|
monitorModalForm,
|
|
|
|
|
onMonitorModalSubmit,
|
|
|
|
|
dateRange,
|
|
|
|
|
checkTree,
|
|
|
|
|
trendGraphData,
|
|
|
|
|
typeOfCheckable,
|
|
|
|
|
timeSelectArr,
|
|
|
|
|
columns,
|
|
|
|
|
dataSource,
|
|
|
|
|
pagination,
|
|
|
|
|
configLoading,
|
|
|
|
|
handleTableChange,
|
|
|
|
|
selectedKey,
|
|
|
|
|
cancelOps,
|
|
|
|
|
alarmFilters,
|
|
|
|
|
pdTypeOps,
|
|
|
|
|
deleteAlarmTimes,
|
|
|
|
|
deleteAlarmConfirm,
|
|
|
|
|
fetchAlarmGridData,
|
|
|
|
|
initAlarmGridData,
|
|
|
|
|
stationName1,
|
|
|
|
|
alarmCustomUpload,
|
|
|
|
|
alarmBeforeUpload,
|
|
|
|
|
defaultProps,
|
|
|
|
|
totalPrpds,
|
|
|
|
|
allPathCongfigs,
|
|
|
|
|
savePathConfig,
|
|
|
|
|
resetPathConfig,
|
|
|
|
|
initCatalogue,
|
|
|
|
|
isCurrentInit,
|
|
|
|
|
initTips,
|
|
|
|
|
trendGraphRefs,
|
|
|
|
|
allPdTypes,
|
|
|
|
|
trendGraphInfo,
|
|
|
|
|
prpdAndPrpsTimes,
|
|
|
|
|
eventListLoading,
|
|
|
|
|
getEventList,
|
|
|
|
|
eventList,
|
|
|
|
|
isTypeOfCountPrpd,
|
|
|
|
|
handleEventClick,
|
|
|
|
|
activeEventTime,
|
|
|
|
|
alarmRowClick,
|
|
|
|
|
defaultExpendKeys,
|
|
|
|
|
jumpToPRPD,
|
|
|
|
|
everntFilterVisible,
|
|
|
|
|
eventFilterForm,
|
|
|
|
|
onFilterEventList,
|
|
|
|
|
onResetEventList,
|
|
|
|
|
trendRef,
|
|
|
|
|
handleNodeContentClick
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
components: {
|
|
|
|
|
prpdAndPrpsComp,
|
|
|
|
|
eventCount,
|
|
|
|
|
historyTrendGraph
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.use(antd)
|
|
|
|
|
.use(ElementPlus, {
|
|
|
|
|
locale: ElementPlusLocaleZhCn // 使用中文语言包
|
|
|
|
|
})
|
|
|
|
|
.mount('#app');
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
</html>
|