|
|
@ -5,9 +5,6 @@
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<title>tool</title>
|
|
|
|
<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/vue.global.min.js"></script>
|
|
|
|
<script src="./js/antd.min.js"></script>
|
|
|
|
<script src="./js/antd.min.js"></script>
|
|
|
|
<link rel="stylesheet" href="./css/antd.min.css">
|
|
|
|
<link rel="stylesheet" href="./css/antd.min.css">
|
|
|
@ -36,8 +33,7 @@
|
|
|
|
:style="{ left: `${treeMenuInfo.menuX}px`, top: `${treeMenuInfo.menuY}px` }">
|
|
|
|
:style="{ left: `${treeMenuInfo.menuX}px`, top: `${treeMenuInfo.menuY}px` }">
|
|
|
|
<div v-if="treeMenuInfo.data.isRoot" @click="addMonitor(treeMenuInfo.data)">新增监测点</div>
|
|
|
|
<div v-if="treeMenuInfo.data.isRoot" @click="addMonitor(treeMenuInfo.data)">新增监测点</div>
|
|
|
|
<div @click="editNodeItem(treeMenuInfo.data)">编辑</div>
|
|
|
|
<div @click="editNodeItem(treeMenuInfo.data)">编辑</div>
|
|
|
|
<a-popconfirm title="确定要删除吗?" ok-text="确定" cancel-text="取消"
|
|
|
|
<a-popconfirm title="确定要删除吗?" ok-text="确定" cancel-text="取消" @confirm="deleteNodeItem(treeMenuInfo.data)">
|
|
|
|
@confirm="deleteNodeItem(treeMenuInfo.data)">
|
|
|
|
|
|
|
|
<div>删除</div>
|
|
|
|
<div>删除</div>
|
|
|
|
</a-popconfirm>
|
|
|
|
</a-popconfirm>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -53,8 +49,8 @@
|
|
|
|
:default-expanded-keys="defaultExpendKeys" @check="checkTree" @node-click="handleNodeClick"
|
|
|
|
:default-expanded-keys="defaultExpendKeys" @check="checkTree" @node-click="handleNodeClick"
|
|
|
|
:filter-node-method="filterNode" @node-contextmenu="handleRightClick">
|
|
|
|
:filter-node-method="filterNode" @node-contextmenu="handleRightClick">
|
|
|
|
<template #default="{ node, data }">
|
|
|
|
<template #default="{ node, data }">
|
|
|
|
<div :class="[selectedKey===data.key?'hight-light-node':'','node-content']"
|
|
|
|
<div :class="[selectedKey===data.key?'hight-light-node':'','node-content']" :title="node.label"
|
|
|
|
:title="node.label" @click.stop="handleNodeContentClick(data)">
|
|
|
|
@click.stop="handleNodeContentClick(data)">
|
|
|
|
{{ node.label }}
|
|
|
|
{{ node.label }}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
@ -73,8 +69,8 @@
|
|
|
|
</a-tabs>
|
|
|
|
</a-tabs>
|
|
|
|
<div class="top-timer" v-if="timeSelectArr.includes(activeKey)">
|
|
|
|
<div class="top-timer" v-if="timeSelectArr.includes(activeKey)">
|
|
|
|
<el-date-picker v-model="dateRange" style="width: 260px" class="custom-date-picker"
|
|
|
|
<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="至"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
|
end-placeholder="结束日期" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="panel-views">
|
|
|
|
<div class="panel-views">
|
|
|
@ -83,14 +79,14 @@
|
|
|
|
<div class="search-bar">
|
|
|
|
<div class="search-bar">
|
|
|
|
<div class="search-item">
|
|
|
|
<div class="search-item">
|
|
|
|
<span>放电类型:</span>
|
|
|
|
<span>放电类型:</span>
|
|
|
|
<a-select v-model:value="alarmFilters.pdTypes" :options="pdTypeOps" mode="tags"
|
|
|
|
<a-select v-model:value="alarmFilters.pdTypes" :options="pdTypeOps" mode="tags" placeholder="请选择"
|
|
|
|
placeholder="请选择" style="width: 300px">
|
|
|
|
style="width: 300px">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="search-item">
|
|
|
|
<div class="search-item">
|
|
|
|
<span>时间:</span>
|
|
|
|
<span>时间:</span>
|
|
|
|
<el-date-picker v-model="alarmFilters.times" style="width: 360px"
|
|
|
|
<el-date-picker v-model="alarmFilters.times" style="width: 360px" class="custom-date-picker"
|
|
|
|
class="custom-date-picker" value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
|
end-placeholder="结束日期" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="break"></div>
|
|
|
|
<div class="break"></div>
|
|
|
|
<div class="search-item">
|
|
|
|
<div class="search-item">
|
|
|
@ -105,9 +101,8 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="grid-content">
|
|
|
|
<div class="grid-content">
|
|
|
|
<a-table :columns="columns" :data-source="dataSource" :pagination="pagination"
|
|
|
|
<a-table :columns="columns" :data-source="dataSource" :pagination="pagination" :loading="configLoading"
|
|
|
|
:loading="configLoading" @change="handleTableChange" :scroll="{ y: 460 }"
|
|
|
|
@change="handleTableChange" :scroll="{ y: 460 }" :custom-row="alarmRowClick">
|
|
|
|
:custom-row="alarmRowClick">
|
|
|
|
|
|
|
|
<template #name1="{ text }">
|
|
|
|
<template #name1="{ text }">
|
|
|
|
{{pdTypeOps.find(item=>item.value==text).label}}
|
|
|
|
{{pdTypeOps.find(item=>item.value==text).label}}
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
@ -120,8 +115,7 @@
|
|
|
|
<div v-if="activeKey === 'historyTrend'" key="historyTrend" class="sub-content history-trend">
|
|
|
|
<div v-if="activeKey === 'historyTrend'" key="historyTrend" class="sub-content history-trend">
|
|
|
|
<div class="trend-graph-container">
|
|
|
|
<div class="trend-graph-container">
|
|
|
|
<history-trend-graph v-for="(item,index) in trendGraphData" :key="item.key"
|
|
|
|
<history-trend-graph v-for="(item,index) in trendGraphData" :key="item.key"
|
|
|
|
:ref="el => { if (el) trendGraphRefs[index] = el }" :data="item"
|
|
|
|
:ref="el => { if (el) trendGraphRefs[index] = el }" :data="item" @jump-to-prpd="jumpToPRPD" />
|
|
|
|
@jump-to-prpd="jumpToPRPD" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="activeKey === 'prpdAndPrps'" key="prpdAndPrps" class="sub-content total-prpd-panel">
|
|
|
|
<div v-if="activeKey === 'prpdAndPrps'" key="prpdAndPrps" class="sub-content total-prpd-panel">
|
|
|
@ -132,33 +126,32 @@
|
|
|
|
<div class="prpd-box">
|
|
|
|
<div class="prpd-box">
|
|
|
|
<!-- 累计PRPD组件 -->
|
|
|
|
<!-- 累计PRPD组件 -->
|
|
|
|
<div class="totle-prpds">
|
|
|
|
<div class="totle-prpds">
|
|
|
|
<prpd-and-prps-comp class="total-prpd-item" v-for="(item,index) in totalPrpds"
|
|
|
|
<prpd-and-prps-comp class="total-prpd-item" v-for="(item,index) in totalPrpds" :key="index" :data="item"
|
|
|
|
:key="index" :data="item" :time="prpdAndPrpsTimes"
|
|
|
|
:time="prpdAndPrpsTimes" :is-count-prpd="isTypeOfCountPrpd" :fiter-data="eventFilterForm" />
|
|
|
|
:is-count-prpd="isTypeOfCountPrpd" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="time-sider">
|
|
|
|
<div class="time-sider">
|
|
|
|
<div class="title">
|
|
|
|
<div class="title">
|
|
|
|
<span>
|
|
|
|
<span>
|
|
|
|
事件:
|
|
|
|
事件:
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
<el-popover placement="right" :width="320" trigger="click"
|
|
|
|
<el-popover placement="right" :width="320" trigger="click" :visible="everntFilterVisible">
|
|
|
|
:visible="everntFilterVisible">
|
|
|
|
|
|
|
|
<template #reference>
|
|
|
|
<template #reference>
|
|
|
|
<el-button @click="everntFilterVisible=!everntFilterVisible">筛选</el-button>
|
|
|
|
<el-button @click="everntFilterVisible=!everntFilterVisible">筛选</el-button>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
<el-form :inline="true" :model="eventFilterForm" label-width="auto"
|
|
|
|
<el-form :inline="true" :model="eventFilterForm" label-width="auto" label-suffix=":"
|
|
|
|
label-suffix=":" class="demo-form-inline">
|
|
|
|
class="demo-form-inline">
|
|
|
|
<el-form-item label="脉冲数">
|
|
|
|
<el-form-item label="脉冲数">
|
|
|
|
<el-input v-model="eventFilterForm.plusCount" placeholder="请输入" />
|
|
|
|
<el-input v-model="eventFilterForm.plusCount" placeholder="请输入" type="number" min="0"
|
|
|
|
|
|
|
|
@input="validatePlusCount" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="幅值">
|
|
|
|
<el-form-item label="幅值">
|
|
|
|
<el-input v-model="eventFilterForm.maxValue" placeholder="请输入" />
|
|
|
|
<el-input v-model="eventFilterForm.maxValue" placeholder="请输入" type="number" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="放电类型">
|
|
|
|
<el-form-item label="放电类型">
|
|
|
|
<el-select v-model="eventFilterForm.pdTypes" multiple collapse-tags
|
|
|
|
<el-select v-model="eventFilterForm.pdTypes" multiple collapse-tags collapse-tags-tooltip
|
|
|
|
collapse-tags-tooltip style="width: 240px" placeholder="请选择">
|
|
|
|
style="width: 240px" placeholder="请选择">
|
|
|
|
<el-option v-for="item in allPdTypes" :key="item.value"
|
|
|
|
<el-option v-for="item in allPdTypes" :key="item.value" :label="item.label"
|
|
|
|
:label="item.label" :value="item.value" />
|
|
|
|
:value="item.value" />
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
@ -170,8 +163,7 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="list" v-loading="eventListLoading">
|
|
|
|
<div class="list" v-loading="eventListLoading">
|
|
|
|
<div :class="['event-item',activeEventTime==item.time?'active-event-item':'']"
|
|
|
|
<div :class="['event-item',activeEventTime==item.time?'active-event-item':'']"
|
|
|
|
v-for="(item,index) in eventList" :key="item.time"
|
|
|
|
v-for="(item,index) in eventList" :key="item.time" @click="handleEventClick(item)">
|
|
|
|
@click="handleEventClick(item)">
|
|
|
|
|
|
|
|
<div class="time">
|
|
|
|
<div class="time">
|
|
|
|
<span class="label">时间:</span>
|
|
|
|
<span class="label">时间:</span>
|
|
|
|
{{item.time}}
|
|
|
|
{{item.time}}
|
|
|
@ -213,9 +205,8 @@
|
|
|
|
<div class="delete-bar">
|
|
|
|
<div class="delete-bar">
|
|
|
|
<span class="delete-time">
|
|
|
|
<span class="delete-time">
|
|
|
|
<span class="label">清除告警时间段:</span>
|
|
|
|
<span class="label">清除告警时间段:</span>
|
|
|
|
<el-date-picker v-model="deleteAlarmTimes" style="width: 360px"
|
|
|
|
<el-date-picker v-model="deleteAlarmTimes" style="width: 360px" class="custom-date-picker"
|
|
|
|
class="custom-date-picker" value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
|
|
|
|
end-placeholder="结束日期" />
|
|
|
|
end-placeholder="结束日期" />
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
<a-popconfirm title="确定删除?" ok-text="是" cancel-text="否" @confirm="deleteAlarmConfirm">
|
|
|
|
<a-popconfirm title="确定删除?" ok-text="是" cancel-text="否" @confirm="deleteAlarmConfirm">
|
|
|
@ -240,9 +231,8 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<a-button size="small" type="primary" style="margin-right: 4px;"
|
|
|
|
<a-button size="small" type="primary" style="margin-right: 4px;"
|
|
|
|
@click="savePathConfig(item)">保存</a-button>
|
|
|
|
@click="savePathConfig(item)">保存</a-button>
|
|
|
|
<a-button v-if="item.key==='MERGIN_ROOT_PATH'" size="small" type="primary"
|
|
|
|
<a-button v-if="item.key==='MERGIN_ROOT_PATH'" size="small" type="primary" style="margin-right: 4px;"
|
|
|
|
style="margin-right: 4px;" :loading="isCurrentInit"
|
|
|
|
:loading="isCurrentInit" @click="initCatalogue">初始化</a-button>
|
|
|
|
@click="initCatalogue">初始化</a-button>
|
|
|
|
|
|
|
|
<a-button size="small" @click="resetPathConfig(item.key)">重置</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">
|
|
|
|
<p v-if="item.key==='MERGIN_ROOT_PATH'&&isCurrentInit" class="init-warning-tips">
|
|
|
|
当前初始化进度:{{initTips}}
|
|
|
|
当前初始化进度:{{initTips}}
|
|
|
@ -254,8 +244,31 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- 导入监测点弹框 -->
|
|
|
|
<!-- 导入监测点弹框 -->
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isImportMonitorModalShow" title="导入监测点"
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isImportMonitorModalShow" title="导入监测点"
|
|
|
|
@ok="onImportMonitor" @cancel="isImportMonitorModalShow=false"
|
|
|
|
@ok="onImportMonitor" @cancel="isImportMonitorModalShow=false" :confirmLoading="importMonitorModalloading"
|
|
|
|
:confirmLoading="importMonitorModalloading"></a-modal>
|
|
|
|
ok-text="确定" cancel-text="取消">
|
|
|
|
|
|
|
|
<el-form :inline="true" ref="importMonitorFormRef" :model="importMonitorForm" label-width="auto"
|
|
|
|
|
|
|
|
label-suffix=":" class="demo-form-inline" :rules="importMonitorRules">
|
|
|
|
|
|
|
|
<el-form-item label="站点" prop="stationName">
|
|
|
|
|
|
|
|
<el-select v-model="importMonitorForm.stationName" style="width: 320px" placeholder="请选择">
|
|
|
|
|
|
|
|
<el-option v-for="item in fullTreeData" :key="item.title" :label="item.title" :value="item.title" />
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="选择文件" prop="file">
|
|
|
|
|
|
|
|
<el-upload ref="monitorImportRef" action="#" :on-change="handleFileChange"
|
|
|
|
|
|
|
|
:before-upload="beforImportMonitor" :show-file-list="true" :limit="1" accept=".csv,.xlsx,.xls"
|
|
|
|
|
|
|
|
:auto-upload="false" @remove="handleImportMonitorFileRemove">
|
|
|
|
|
|
|
|
<template #trigger>
|
|
|
|
|
|
|
|
<el-button size="small" type="primary">选择文件</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<template #tip>
|
|
|
|
|
|
|
|
<div class="el-upload__tip">
|
|
|
|
|
|
|
|
支持 CSV, XLSX, XLS 格式文件,单次仅导入一个文件。
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-upload>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</a-modal>
|
|
|
|
<!-- 站点弹框 -->
|
|
|
|
<!-- 站点弹框 -->
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isSiteModalShow"
|
|
|
|
<a-modal width="550px" :destroyOnClose="true" :visible="isSiteModalShow"
|
|
|
|
:title="isAddTypeOfSiteModal?'新增站点':'编辑站点'" @cancel="isSiteModalShow=false">
|
|
|
|
:title="isAddTypeOfSiteModal?'新增站点':'编辑站点'" @cancel="isSiteModalShow=false">
|
|
|
@ -405,6 +418,28 @@
|
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取15分钟前的时间索引
|
|
|
|
|
|
|
|
const getLastIndexWithinMaxTime = (times, maxTimeRange) => {
|
|
|
|
|
|
|
|
if (!times || times.length === 0) {
|
|
|
|
|
|
|
|
return -1; // 如果数组为空,返回 -1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const firstTimestamp = new Date(times[0]).getTime();
|
|
|
|
|
|
|
|
const timeLimit = firstTimestamp + maxTimeRange;
|
|
|
|
|
|
|
|
// --- 特殊逻辑检查:索引 1 是否就超过了 15 分钟 ---
|
|
|
|
|
|
|
|
if (times.length > 1) { // 确保有索引 1 存在
|
|
|
|
|
|
|
|
const secondTimestamp = new Date(times[1]).getTime();
|
|
|
|
|
|
|
|
if (secondTimestamp > timeLimit) {
|
|
|
|
|
|
|
|
return 1; // 如果索引 1 就超出了 15 分钟,直接返回 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 1; i < times.length; i++) {
|
|
|
|
|
|
|
|
const currentTimestamp = new Date(times[i]).getTime();
|
|
|
|
|
|
|
|
if (currentTimestamp > timeLimit) {
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return times.length - 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
// 历史趋势图组件
|
|
|
|
// 历史趋势图组件
|
|
|
|
const trendGraphRefs = ref([]);
|
|
|
|
const trendGraphRefs = ref([]);
|
|
|
|
watch(trendGraphRefs, (arr) => {
|
|
|
|
watch(trendGraphRefs, (arr) => {
|
|
|
@ -422,13 +457,30 @@
|
|
|
|
const historyTrendGraph = {
|
|
|
|
const historyTrendGraph = {
|
|
|
|
template: `<div class='graph-container'>
|
|
|
|
template: `<div class='graph-container'>
|
|
|
|
<div class="title">
|
|
|
|
<div class="title">
|
|
|
|
监测点:{{ data?.label||'' }}
|
|
|
|
<span> 监测点:{{ data?.label||'' }}</span>
|
|
|
|
|
|
|
|
<div v-if="usedTab==='prpdAndPrps'" class="time-range">
|
|
|
|
|
|
|
|
<span> 最大框选时间范围:</span>
|
|
|
|
|
|
|
|
<a-select v-model:value="maxInMs" size="small" style="width: 200px;margin-left: 10px;">
|
|
|
|
|
|
|
|
<a-select-option v-for="item in timeOps" :key="item.value" :value="item.value">
|
|
|
|
|
|
|
|
{{ item.label }}
|
|
|
|
|
|
|
|
</a-select-option>
|
|
|
|
|
|
|
|
</a-select>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div ref='graphRef' class="line-graph" @dblclick='onDblclickGraph'></div>
|
|
|
|
<div ref='graphRef' class="line-graph" @dblclick='onDblclickGraph'></div>
|
|
|
|
</div>`,
|
|
|
|
</div>`,
|
|
|
|
data() {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
resizeObserver: null
|
|
|
|
resizeObserver: null,
|
|
|
|
|
|
|
|
lastBrushSelected: null, // 用于存储上次成功的框选范围,防止重复触发
|
|
|
|
|
|
|
|
timeOps: [
|
|
|
|
|
|
|
|
{ label: '15分钟', value: 15 * 60 * 1000 },
|
|
|
|
|
|
|
|
{ label: '30分钟', value: 30 * 60 * 1000 },
|
|
|
|
|
|
|
|
{ label: '1小时', value: 60 * 60 * 1000 },
|
|
|
|
|
|
|
|
{ label: '6小时', value: 6 * 60 * 60 * 1000 },
|
|
|
|
|
|
|
|
{ label: '24小时', value: 24 * 60 * 60 * 1000 },
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
maxInMs: 15 * 60 * 1000 // 最大框选时间
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
props: {
|
|
|
@ -556,60 +608,62 @@
|
|
|
|
series,
|
|
|
|
series,
|
|
|
|
dataZoom: [
|
|
|
|
dataZoom: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
type: 'slider', // 滑动条型数据区域缩放
|
|
|
|
type: 'inside', // 内置型数据区域缩放
|
|
|
|
xAxisIndex: [0],
|
|
|
|
xAxisIndex: [0], // 作用于第一个(或所有)X轴
|
|
|
|
start: 0,
|
|
|
|
start: 0, // 数据窗口范围的起始百分比,0%
|
|
|
|
end: 100,
|
|
|
|
end: 100, // 数据窗口范围的结束百分比,100%
|
|
|
|
top: 20, // 距离底部的距离
|
|
|
|
// 以下是 type: 'inside' 独有的配置项,控制交互
|
|
|
|
height: 10, // 滑动条高度
|
|
|
|
zoomOnMouseWheel: true, // 鼠标滚轮缩放
|
|
|
|
throttle: 500,
|
|
|
|
moveOnMouseMove: true, // 鼠标移动(拖拽)平移
|
|
|
|
showDetail: false // 不显示详细的起止数值,根据需求设置
|
|
|
|
moveOnMouseWheel: false, // 鼠标滚轮不平移,只缩放
|
|
|
|
|
|
|
|
filterMode: 'filter' // 数据过滤模式,'filter' 会过滤掉超出范围的数据
|
|
|
|
|
|
|
|
}]
|
|
|
|
|
|
|
|
,
|
|
|
|
|
|
|
|
brush: {
|
|
|
|
|
|
|
|
brushLink: 'all', // 刷选联动所有系列
|
|
|
|
|
|
|
|
xAxisIndex: 'all', // 允许在所有 X 轴上进行刷选 (这里只有一个 X 轴)
|
|
|
|
|
|
|
|
yAxisIndex: 'all', // 允许在所有 Y 轴上进行刷选
|
|
|
|
|
|
|
|
brushMode: 'rect', // **只允许矩形框选**
|
|
|
|
|
|
|
|
throttleType: 'debounce', // 内部刷选状态更新的节流模式
|
|
|
|
|
|
|
|
throttleDelay: 300, // 节流延迟
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
toolbox: {
|
|
|
|
|
|
|
|
show: this.usedTab === 'prpdAndPrps', // 只有prpd/prps展示
|
|
|
|
|
|
|
|
feature: {
|
|
|
|
|
|
|
|
// brush 工具箱,包含矩形框选和清除按钮
|
|
|
|
|
|
|
|
brush: {
|
|
|
|
|
|
|
|
type: ['lineX',] // 只显示矩形框选工具和清除刷选工具
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
left: 30, // 工具箱位置
|
|
|
|
|
|
|
|
top: '0'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 3. 设置配置项并渲染图表
|
|
|
|
// 3. 设置配置项并渲染图表
|
|
|
|
this.chart.setOption(option);
|
|
|
|
this.chart.setOption(option);
|
|
|
|
this.addEchartsEvents();
|
|
|
|
// 监听 'brushEnd' 事件,在用户松开鼠标完成框选时触发,用于获取最终结果
|
|
|
|
|
|
|
|
this.chart.on('brushEnd', this.handleBrushEnd);
|
|
|
|
if (this.usedTab === 'prpdAndPrps') {
|
|
|
|
if (this.usedTab === 'prpdAndPrps') {
|
|
|
|
this.handleDataZoom({ start: 0, end: 100 })
|
|
|
|
this.loadInitTimeData()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
addEchartsEvents() {
|
|
|
|
// 加载初始化时间数据
|
|
|
|
if (!this.chart || this.usedTab !== 'prpdAndPrps') return;
|
|
|
|
loadInitTimeData() {
|
|
|
|
this.chart.on('datazoom', (params) => {
|
|
|
|
const xAxisData = this.chart.getOption().xAxis[0].data?.map(item => item.replace(/\n/g, ' ')) || [];
|
|
|
|
this.handleDataZoom(params)
|
|
|
|
const index = getLastIndexWithinMaxTime(xAxisData, this.maxInMs)
|
|
|
|
});
|
|
|
|
if (index < 0) {
|
|
|
|
},
|
|
|
|
return message.error(`当前数据为空!`);
|
|
|
|
// 外界触发筛选逻辑
|
|
|
|
|
|
|
|
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 })
|
|
|
|
this.chart.dispatchAction({
|
|
|
|
|
|
|
|
type: 'brush', // 这是一个与 brush 组件相关的 action
|
|
|
|
|
|
|
|
command: 'brush', // 命令是 'brush',表示设置刷选区域
|
|
|
|
|
|
|
|
areas: [{ // areas 是一个数组,可以定义多个刷选区域
|
|
|
|
|
|
|
|
brushType: 'lineX', // 刷选类型,与你在 option.brush 中设置的一致
|
|
|
|
|
|
|
|
xAxisIndex: 0, // 对应你的第一个 X 轴(索引为 0)
|
|
|
|
|
|
|
|
coordRange: [0, index] // 设置刷选区域的坐标范围(类目轴是索引)
|
|
|
|
|
|
|
|
}]
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
this.$emit('getEventList', { startTime: xAxisData[0], endTime: xAxisData[index] })
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// 双击跳转
|
|
|
|
// 双击跳转
|
|
|
|
onDblclickGraph() {
|
|
|
|
onDblclickGraph() {
|
|
|
@ -621,6 +675,69 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.$emit('jumpToPrpd', this.data.key)
|
|
|
|
this.$emit('jumpToPrpd', this.data.key)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
handleBrushEnd(params) {
|
|
|
|
|
|
|
|
const brushAreas = params.areas;
|
|
|
|
|
|
|
|
// 如果没有框选区域(例如用户只是点击了一下,或者点击了工具箱的清除按钮)
|
|
|
|
|
|
|
|
if (!brushAreas || brushAreas.length === 0) {
|
|
|
|
|
|
|
|
this.lastBrushSelected = null; // 清除上次的选中状态
|
|
|
|
|
|
|
|
this.loadInitTimeData()
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取第一个(也是唯一一个)刷选区域的信息
|
|
|
|
|
|
|
|
// 由于你在 brushstart 中清除了旧框,这里通常只会有一个 areas 元素。
|
|
|
|
|
|
|
|
const brushArea = brushAreas[0];
|
|
|
|
|
|
|
|
let minXValue = null;
|
|
|
|
|
|
|
|
let maxXValue = null;
|
|
|
|
|
|
|
|
// `coordRanges` 针对 'category' 类型的 X 轴,会直接给出数据索引的范围
|
|
|
|
|
|
|
|
if (brushArea.coordRanges && brushArea.coordRanges.length > 0) {
|
|
|
|
|
|
|
|
const xAxisCoordRange = brushArea.coordRanges[0];
|
|
|
|
|
|
|
|
if (xAxisCoordRange && xAxisCoordRange.length > 0) {
|
|
|
|
|
|
|
|
const rawMinXIndex = xAxisCoordRange[0]; // 获取X轴的最小索引 (例如: 0)
|
|
|
|
|
|
|
|
const rawMaxXIndex = xAxisCoordRange[1]; // 获取X轴的最大索引 (例如: 6)
|
|
|
|
|
|
|
|
// 获取 ECharts 配置中 X 轴的所有数据(时间字符串数组)
|
|
|
|
|
|
|
|
const xAxisData = this.chart.getOption().xAxis[0].data;
|
|
|
|
|
|
|
|
// 根据索引从 xAxisData 中取出对应的实际时间值
|
|
|
|
|
|
|
|
if (xAxisData[rawMinXIndex] !== undefined && xAxisData[rawMaxXIndex] !== undefined) {
|
|
|
|
|
|
|
|
// 假设你的时间字符串可能包含换行符 '\n',这里将其替换为空格以统一格式
|
|
|
|
|
|
|
|
minXValue = String(xAxisData[rawMinXIndex]).replace(/\n/g, ' ');
|
|
|
|
|
|
|
|
maxXValue = String(xAxisData[rawMaxXIndex]).replace(/\n</g, ' ');
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.$emit('getEventList', { startTime: null, endTime: null })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 如果未能从 `coordRanges` 中解析出有效的 X 轴时间范围
|
|
|
|
|
|
|
|
if (!minXValue || !maxXValue) {
|
|
|
|
|
|
|
|
message.warning(`未能从 brush 选中区域中解析出有效的 X 轴时间范围!`);
|
|
|
|
|
|
|
|
this.$emit('getEventList', { startTime: null, endTime: null })
|
|
|
|
|
|
|
|
this.lastBrushSelected = null;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 这在 brushEnd 事件中依然有用,例如用户连续两次选择完全相同的范围
|
|
|
|
|
|
|
|
if (this.lastBrushSelected &&
|
|
|
|
|
|
|
|
this.lastBrushSelected.minX === minXValue &&
|
|
|
|
|
|
|
|
this.lastBrushSelected.maxX === maxXValue) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const startTime = minXValue ? String(minXValue).replace(/\n/g, ' ') : '';
|
|
|
|
|
|
|
|
const endTime = maxXValue ? String(maxXValue).replace(/\n/g, ' ') : '';
|
|
|
|
|
|
|
|
const xAxisData = this.chart.getOption().xAxis[0].data;
|
|
|
|
|
|
|
|
const isOver15Min = new Date(endTime).getTime() - new Date(startTime).getTime() > this.maxInMs;
|
|
|
|
|
|
|
|
if (isOver15Min) {
|
|
|
|
|
|
|
|
this.chart.dispatchAction({
|
|
|
|
|
|
|
|
type: 'brush',
|
|
|
|
|
|
|
|
command: 'clear', // 'clear' 命令用于清除所有刷选区域
|
|
|
|
|
|
|
|
areas: [] // 空数组表示清除所有
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
this.$emit('getEventList', { startTime: null, endTime: null })
|
|
|
|
|
|
|
|
const warningLable = this.timeOps.find(item => item.value === this.maxInMs)?.label || ''
|
|
|
|
|
|
|
|
return message.error(`数据加载过多,请框选时间区域不超过${warningLable}!`);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 更新上次的选中状态
|
|
|
|
|
|
|
|
this.lastBrushSelected = { minX: startTime, maxX: endTime };
|
|
|
|
|
|
|
|
// 通过事件将框选的 X 轴范围传递给父组件
|
|
|
|
|
|
|
|
this.$emit('getEventList', { startTime, endTime })
|
|
|
|
|
|
|
|
},
|
|
|
|
getChart() {
|
|
|
|
getChart() {
|
|
|
|
return this.chart;
|
|
|
|
return this.chart;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -641,7 +758,7 @@
|
|
|
|
{{item}}</span>
|
|
|
|
{{item}}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>`,
|
|
|
|
</div>`,
|
|
|
|
props: ['data', 'time', 'isCountPrpd'],
|
|
|
|
props: ['data', 'time', 'isCountPrpd', 'fiterData'],
|
|
|
|
data() {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
currentKey: 'PRPD',
|
|
|
|
currentKey: 'PRPD',
|
|
|
@ -822,6 +939,8 @@
|
|
|
|
startTime: data.time[0],
|
|
|
|
startTime: data.time[0],
|
|
|
|
endTime: data.time[1],
|
|
|
|
endTime: data.time[1],
|
|
|
|
monitorKey: data.monitorKey,
|
|
|
|
monitorKey: data.monitorKey,
|
|
|
|
|
|
|
|
...this.fiterData,
|
|
|
|
|
|
|
|
pdTypes: this.fiterData.pdTypes.join(','),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const { data: { result: res } } = await axios.get(`/ldpdtools/eventData/getPrpdByParam`, {
|
|
|
|
const { data: { result: res } } = await axios.get(`/ldpdtools/eventData/getPrpdByParam`, {
|
|
|
|
params,
|
|
|
|
params,
|
|
|
@ -921,7 +1040,6 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lay1.push(lay2)
|
|
|
|
lay1.push(lay2)
|
|
|
|
// console.log(lay1)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let i = 0; i < lay1.length; i++) {
|
|
|
|
for (let i = 0; i < lay1.length; i++) {
|
|
|
|
for (let j = 0; j < lay1[i].length; j++) {
|
|
|
|
for (let j = 0; j < lay1[i].length; j++) {
|
|
|
@ -933,7 +1051,6 @@
|
|
|
|
dataArr.push(lay1[i][j][0]);
|
|
|
|
dataArr.push(lay1[i][j][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// console.log(dataArr)
|
|
|
|
|
|
|
|
return dataArr;
|
|
|
|
return dataArr;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// 初始化prps
|
|
|
|
// 初始化prps
|
|
|
@ -1254,6 +1371,79 @@
|
|
|
|
]
|
|
|
|
]
|
|
|
|
const isImportMonitorModalShow = ref(false)
|
|
|
|
const isImportMonitorModalShow = ref(false)
|
|
|
|
const importMonitorModalloading = ref(false)
|
|
|
|
const importMonitorModalloading = ref(false)
|
|
|
|
|
|
|
|
const importMonitorFormRef = ref()
|
|
|
|
|
|
|
|
const monitorImportRef = ref()
|
|
|
|
|
|
|
|
const importMonitorRules = {
|
|
|
|
|
|
|
|
stationName: [
|
|
|
|
|
|
|
|
{ required: true, message: '请选择站点', trigger: 'change' } // 'change' 适合 select
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
file: [
|
|
|
|
|
|
|
|
{ required: true, message: '请选择文件', trigger: 'change' } // 'change' 适合 upload
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 上传校验
|
|
|
|
|
|
|
|
const beforImportMonitor = (file) => {
|
|
|
|
|
|
|
|
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 handleFileChange = (file, fileList) => {
|
|
|
|
|
|
|
|
importMonitorForm.value.file = fileList.length > 0 ? fileList[0].raw : null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const importMonitorForm = ref({
|
|
|
|
|
|
|
|
stationName: '',
|
|
|
|
|
|
|
|
file: null
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
watch(isImportMonitorModalShow, (bool) => {
|
|
|
|
|
|
|
|
if (bool) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
importMonitorForm.value.stationName = ''
|
|
|
|
|
|
|
|
importMonitorForm.value.file = null
|
|
|
|
|
|
|
|
monitorImportRef.value.clearFiles()
|
|
|
|
|
|
|
|
},)
|
|
|
|
|
|
|
|
// 清除文件
|
|
|
|
|
|
|
|
const handleImportMonitorFileRemove = () => {
|
|
|
|
|
|
|
|
importMonitorForm.value.file = null
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 导入监测点
|
|
|
|
|
|
|
|
const onImportMonitor = async () => {
|
|
|
|
|
|
|
|
importMonitorFormRef.value.validate(async (valid) => {
|
|
|
|
|
|
|
|
if (!valid) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
|
|
|
formData.append('file', unref(importMonitorForm).file);
|
|
|
|
|
|
|
|
const { data: { code, message: message1 } } = await axios.post(`/ldpdtools/monitor/importMonitor`, formData, {
|
|
|
|
|
|
|
|
params: {
|
|
|
|
|
|
|
|
stationName: unref(importMonitorForm).stationName
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
|
|
|
initTreeData()
|
|
|
|
|
|
|
|
isImportMonitorModalShow.value = false
|
|
|
|
|
|
|
|
message.success(message1)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
message.error('导入失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('上传错误:', error)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// const uploadMonitor = (options) => { }
|
|
|
|
const siteModalloading = ref(false)
|
|
|
|
const siteModalloading = ref(false)
|
|
|
|
const isSiteModalShow = ref(false)
|
|
|
|
const isSiteModalShow = ref(false)
|
|
|
|
const siteModalRef = ref()
|
|
|
|
const siteModalRef = ref()
|
|
|
@ -1404,10 +1594,6 @@
|
|
|
|
const { stationName } = data
|
|
|
|
const { stationName } = data
|
|
|
|
monitorModalForm.stationName = stationName
|
|
|
|
monitorModalForm.stationName = stationName
|
|
|
|
isMonitorModalShow.value = true
|
|
|
|
isMonitorModalShow.value = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// 导入监测点
|
|
|
|
|
|
|
|
const onImportMonitor = () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const addSite = () => {
|
|
|
|
const addSite = () => {
|
|
|
|
isSiteModalShow.value = true
|
|
|
|
isSiteModalShow.value = true
|
|
|
@ -1703,6 +1889,18 @@
|
|
|
|
endTime: unref(dateRange)[1],
|
|
|
|
endTime: unref(dateRange)[1],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
// 输入脉冲数校验函数
|
|
|
|
|
|
|
|
const validatePlusCount = (value) => {
|
|
|
|
|
|
|
|
let numValue = Number(value);
|
|
|
|
|
|
|
|
if (isNaN(numValue)) {
|
|
|
|
|
|
|
|
numValue = 0; // 如果不是有效数字,设置为0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numValue < 0) {
|
|
|
|
|
|
|
|
numValue = 0; // 如果小于0,设置为0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
numValue = Math.floor(numValue);
|
|
|
|
|
|
|
|
eventFilterForm.value.plusCount = numValue;
|
|
|
|
|
|
|
|
};
|
|
|
|
// 获取事件列表
|
|
|
|
// 获取事件列表
|
|
|
|
const getEventList = async ({ startTime, endTime }) => {
|
|
|
|
const getEventList = async ({ startTime, endTime }) => {
|
|
|
|
if (startTime === null && endTime === null) {
|
|
|
|
if (startTime === null && endTime === null) {
|
|
|
@ -1743,7 +1941,7 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 筛选
|
|
|
|
// 筛选
|
|
|
|
const onFilterEventList = () => {
|
|
|
|
const onFilterEventList = () => {
|
|
|
|
trendRef.value.emitFilterEvent()
|
|
|
|
trendRef.value.loadInitTimeData()
|
|
|
|
everntFilterVisible.value = false
|
|
|
|
everntFilterVisible.value = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 重置筛选框
|
|
|
|
// 重置筛选框
|
|
|
@ -1895,30 +2093,61 @@
|
|
|
|
message.success('重置成功!')
|
|
|
|
message.success('重置成功!')
|
|
|
|
getAllConfigs()
|
|
|
|
getAllConfigs()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const progressTimer = ref(null)
|
|
|
|
// 获取初始化进度
|
|
|
|
// 获取初始化进度
|
|
|
|
const getInitPrgress = async () => {
|
|
|
|
const getInitPrgress = async () => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { data: { message } } = await axios.get('/ldpdtools/config/getInitProgress')
|
|
|
|
const { data: { message } } = await axios.get('/ldpdtools/config/getInitProgress')
|
|
|
|
isCurrentInit.value = message.includes('/')
|
|
|
|
isCurrentInit.value = message.includes('/')
|
|
|
|
initTips.value = message
|
|
|
|
initTips.value = message
|
|
|
|
|
|
|
|
if (!isCurrentInit.value) {
|
|
|
|
|
|
|
|
clearInterval(progressTimer.value); // 停止定时器
|
|
|
|
|
|
|
|
progressTimer.value = null; // 将定时器ID置空,以防误操作
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
clearInterval(progressTimer.value);
|
|
|
|
|
|
|
|
progressTimer.value = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 初始化目录
|
|
|
|
|
|
|
|
const initCatalogue = async () => {
|
|
|
|
const initCatalogue = async () => {
|
|
|
|
const { data: { code } } = await axios.get('/ldpdtools/config/initConfig')
|
|
|
|
// 在启动新的初始化前,确保清除任何正在运行的定时器
|
|
|
|
if (code === 200) {
|
|
|
|
if (unref(progressTimer)) {
|
|
|
|
setTimeout(() => {
|
|
|
|
clearInterval(progressTimer.value);
|
|
|
|
getInitPrgress()
|
|
|
|
progressTimer.value = null;
|
|
|
|
}, 1000) // 后台有一定延迟
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { data: { code } } = await axios.get('/ldpdtools/config/initConfig');
|
|
|
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
|
|
|
// 立即执行一次进度获取,获取最新状态
|
|
|
|
|
|
|
|
await getInitPrgress();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果初始化尚未完成 (isCurrentInit.value 仍为 true),则启动轮询
|
|
|
|
|
|
|
|
if (isCurrentInit.value) {
|
|
|
|
|
|
|
|
progressTimer.value = setInterval(getInitPrgress, 2000);
|
|
|
|
|
|
|
|
console.log('初始化配置成功,进度定时器已启动。');
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
console.log('初始化已完成,无需启动进度轮询。');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
console.error('初始化配置请求失败,code:', code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('初始化目录时发生网络或服务器错误:', error);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
onMounted(() => {
|
|
|
|
onMounted(() => {
|
|
|
|
initTreeData()
|
|
|
|
initTreeData()
|
|
|
|
getAllConfigs()
|
|
|
|
getAllConfigs()
|
|
|
|
getInitPrgress()
|
|
|
|
progressTimer.value = setInterval(getInitPrgress, 2000);
|
|
|
|
document.addEventListener('click', handleClickOutside);
|
|
|
|
document.addEventListener('click', handleClickOutside);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
|
|
onUnmounted(() => {
|
|
|
|
document.removeEventListener('click', handleClickOutside);
|
|
|
|
document.removeEventListener('click', handleClickOutside);
|
|
|
|
|
|
|
|
if (unref(progressTimer)) {
|
|
|
|
|
|
|
|
clearInterval(progressTimer.value);
|
|
|
|
|
|
|
|
progressTimer.value = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
treeRef,
|
|
|
|
treeRef,
|
|
|
@ -2000,7 +2229,15 @@
|
|
|
|
onFilterEventList,
|
|
|
|
onFilterEventList,
|
|
|
|
onResetEventList,
|
|
|
|
onResetEventList,
|
|
|
|
trendRef,
|
|
|
|
trendRef,
|
|
|
|
handleNodeContentClick
|
|
|
|
handleNodeContentClick,
|
|
|
|
|
|
|
|
importMonitorForm,
|
|
|
|
|
|
|
|
handleFileChange,
|
|
|
|
|
|
|
|
beforImportMonitor,
|
|
|
|
|
|
|
|
importMonitorRules,
|
|
|
|
|
|
|
|
importMonitorFormRef,
|
|
|
|
|
|
|
|
handleImportMonitorFileRemove,
|
|
|
|
|
|
|
|
monitorImportRef,
|
|
|
|
|
|
|
|
validatePlusCount
|
|
|
|
};
|
|
|
|
};
|
|
|
|
},
|
|
|
|
},
|
|
|
|
components: {
|
|
|
|
components: {
|
|
|
|