You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1878 lines
93 KiB
HTML

2 months ago
<!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)"
@check="checkTree" @node-click="selectTree" highlight-current :filter-node-method="filterNode"
@node-contextmenu="handleRightClick" />
</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切换 -->
2 months ago
<div class="top-box">
<a-tabs v-model:activeKey="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>
2 months ago
<div class="panel-views">
<div v-if="activeKey === 'historyTrend'" key="historyTrend" class="sub-content history-trend">
<div class="trend-graph-container">
2 months ago
<history-trend-graph v-for="(item,index) in trendGraphData" :key="item.key"
:ref="el => { if (el) trendGraphRefs[index] = el }" :data="item" />
2 months ago
</div>
</div>
2 months ago
<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 }">
<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 === 'countPRPD'" key="countPRPD" class="sub-content total-prpd-panel">
2 months ago
<!-- 累计PRPD -->
<div>
<history-trend-graph :data='trendGraphInfo' used-tab="countPRPD"
@get-time-list="getTimeList" />
</div>
2 months ago
<div class="prpd-box">
<!-- 累计PRPD组件 -->
<div class="totle-prpds">
<total-prpd class="total-prpd-item" v-for="(item,index) in totalPrpds" :key="index"
:data="item" :time="prpdTimeArr" />
</div>
<div class="time-sider">
<div class="title">时间:</div>
<div class="list">
<div v-for="item in timeList" :key="item"
:class="['time-item',activeTime==item?'time-active-item':'']"
@click="selectTime(item)">
{{item}}
</div>
</div>
</div>
2 months ago
</div>
</div>
<div v-if="activeKey === 'prpdAndPrps'" key="prpdAndPrps" class="sub-content prpd-and-prps">
<!-- PRPD/PRPS -->
<div class="trend-box"></div>
<div class="prpd-and-prps-box">
<prpd-and-prps class="prpd-and-prps-item"
:ref="el => { if (el) prpdAndPrpsRefs[index] = el }" v-for="(item,index) in totalPrpds"
:key="index" :sort="index" />
</div>
</div>
<div v-if="activeKey === 'eventCount'" key="eventCount" class="sub-content">
<!-- 事件统计 -->
2 months ago
<event-count :time="dateRange" :selected-key="selectedKey" :tree-data="fullTreeData" />
2 months ago
</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="请输入路径" />
2 months ago
</div>
<a-button size="small" type="primary" style="margin-right: 4px;"
@click="savePathConfig(item)">保存</a-button>
2 months ago
<a-button v-if="item.key==='MERGIN_ROOT_PATH'" size="small" type="primary"
style="margin-right: 4px;" :loading="isCurrentInit"
@click="initCatalogue">初始化</a-button>
2 months ago
<a-button size="small" @click="resetPathConfig(item.key)">重置</a-button>
2 months ago
<p v-if="item.key==='MERGIN_ROOT_PATH'&&isCurrentInit" class="init-warning-tips">
当前初始化进度:{{initTips}}
</p>
2 months ago
</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="[
{
2 months ago
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;
2 months ago
const { message } = antd;
axios.defaults.baseURL = 'http://192.168.1.198:9501'; // 临时服务地址
2 months ago
axios.defaults.timeout = 10000;
2 months ago
const HISTORY_TREND_LEGEND = [
{ id: 'avg', name: '平均值' },
{ id: 'maxValue', name: '最大值' },
{ id: 'plusAvg', name: '脉冲平均值' },
{ id: 'plusCount', name: '脉冲次数' },
]
2 months ago
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 < 5000; i++) {
let j = parseInt(i / 100) + 1;
arr[i] = [j, parseInt((i - (j - 1) * 100 + 1) * 3.6), parseInt(dbm[i]) + 80];
}
return arr;
}
2 months ago
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
}
// 生成21个时间点
const generateTimePoints = (centralTimeString) => {
const timePoints = [];
const centralDate = new Date(centralTimeString);
if (isNaN(centralDate.getTime())) {
return [];
}
const firstPointTime = centralDate.getTime() - (10 * 15 * 60 * 1000);
for (let i = 0; i < 21; i++) {
const currentTime = new Date(firstPointTime + (i * 15 * 60 * 1000));
// 4. 格式化时间点为 'YYYY-MM-DD HH:mm:ss' 格式
const year = currentTime.getFullYear();
const month = (currentTime.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始
const day = currentTime.getDate().toString().padStart(2, '0');
const hours = currentTime.getHours().toString().padStart(2, '0');
const minutes = currentTime.getMinutes().toString().padStart(2, '0');
const seconds = currentTime.getSeconds().toString().padStart(2, '0');
const formattedTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
timePoints.push(formattedTime);
}
return timePoints;
}
// 获取前十五分钟数据
const getFifteenMinutesBefore = (timeString) => {
const originalDate = new Date(timeString);
if (isNaN(originalDate.getTime())) {
return null; // 返回 null 或抛出错误,表示输入无效
}
const originalTimeInMs = originalDate.getTime();
const fifteenMinutesInMs = 15 * 60 * 1000;
const newTimeInMs = originalTimeInMs - fifteenMinutesInMs;
const newDate = new Date(newTimeInMs);
const year = newDate.getFullYear();
const month = (newDate.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始需要加1
const day = newDate.getDate().toString().padStart(2, '0');
const hours = newDate.getHours().toString().padStart(2, '0');
const minutes = newDate.getMinutes().toString().padStart(2, '0');
const seconds = newDate.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
2 months ago
// 历史趋势图组件
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"></div>
</div>`,
data() {
return {
resizeObserver: null
}
},
props: {
data: {
type: Object,
default: () => { }
},
// 使用的场景
usedTab: {
type: String,
default: 'historyTrend'
2 months ago
}
},
// 定义常量不定义在data减少性能开销
created() {
this.chart = null
},
watch: {
data: {
async handler(val) {
const { startTime, endTime, key } = val
if (!key || !startTime) return
const params = {
current: 1,
startTime,
endTime,
monitorKey: key,
pageSize: 99999
}
const { data: { result: { result: { result } } } } = await axios.get(`/ldpdtools/trendData/listByParam`, {
params,
})
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,
},
markLine: {
data: [], // 初始为空,点击时再添加
symbol: 'none', // 不显示标记线两端的箭头
lineStyle: {
color: '#ff0000', // 标记线的颜色,例如红色
type: 'solid',
width: 1.5
},
label: {
show: false // 标记线上不显示标签
},
// 可以在这里设置 z 值让标记线在最上层
// z: 99
}
2 months ago
}));
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,
}
// 3. 设置配置项并渲染图表
this.chart.setOption(option);
// 图数据的点击事件(获取时间段数据)
this.chart.on('click', (params) => {
if (this.usedTab === 'countPRPD' && params.componentType === 'series' && params.dataIndex !== undefined) {
// 或者直接获取 X 轴的值
const clickedXValue = params.name;
const updatedSeries = this.chart.getOption().series.map((s, idx) => {
// 克隆 series防止直接修改option导致问题
const newSeries = JSON.parse(JSON.stringify(s));
// 更新 markLine 数据
newSeries.markLine = {
symbol: 'none',
lineStyle: {
color: '#ff0000',
type: 'solid',
width: 1.5
},
data: [{ xAxis: clickedXValue }]
};
return newSeries;
});
this.chart.setOption({
series: updatedSeries
});
this.$emit('getTimeList', clickedXValue);
}
});
2 months ago
},
getChart() {
return this.chart;
}
},
}
2 months ago
// 累计prpd组件
const totalPrpd = {
template: `<div>
<div class="total-prpd-title" :style="{color:!!data.monitorName?'red':''}">{{data.monitorName ||'暂无监测点'}}</div>
<div ref="prpdBoxRef" class="prpd"></div>
</div>`,
props: ['data', 'time'], // 接收父组件传递的数据
2 months ago
data() {
return {
}
},
computed: {
// prpd所需参数
mixPRPDParams() {
return {
...this.data,
time: this.time
}
}
},
watch: {
mixPRPDParams: {
handler(newVal) {
if (newVal.monitorKey && newVal.time[0]) {
// 新增操作
this.$nextTick(() => {
this.fetchPRPDData(newVal)
})
}
if (!newVal.monitorKey) {
// 删除操作
this.myChart.setOption({
series: [{
name: 'PRPD数据',
data: []
}]
}, { notMerge: false });
}
},
deep: true
}
},
created() {
this.myChart = null
this.resizeObserver = null
},
mounted() {
this.initPrpd()
},
2 months ago
methods: {
initPrpd() {
const chartDom = this.$refs.prpdBoxRef;
this.myChart = echarts.init(chartDom);
const option = {
backgroundColor: '#ffffff', // 设置背景色为深色,与图片相似
tooltip: {
show: false
},
// axisPointer: {
// show: true,
// snap: true,
// lineStyle: {
// type: 'dashed',
// },
// label: {
// show: true,
// margin: 6,
// backgroundColor: '#556',
// textStyle: {
// color: '#fff'
// }
// },
// link: [{
// xAxisId: ['xAxisLeft-yAxisTop', 'xAxisLeft-yAxisBottom']
// }, {
// xAxisId: ['xAxisRight-yAxisTop', 'xAxisRight-yAxisBottom']
// }, {
// yAxisId: ['xAxisLeft-yAxisTop', 'xAxisRight-yAxisTop']
// }, {
// yAxisId: ['xAxisLeft-yAxisBottom', 'xAxisRight-yAxisBottom']
// }]
// },
2 months ago
grid: {
left: '8%',
2 months ago
right: '10%',
top: '8%',
bottom: '10%',
2 months ago
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,
2 months ago
data: [],
},
]
};
this.myChart.setOption(option);
this.resizeObserver = new ResizeObserver(() => {
this.myChart?.resize();
});
this.resizeObserver.observe(chartDom);
},
// 请求PRPD数据
async fetchPRPDData(data) {
const params = {
// startTime: data.time[0],
// endTime: data.time[1],
// monitorKey: data.monitorKey,
// mock数据
startTime: '2025-07-16 22:50:54',
endTime: '2025-07-16 23:05:54',
monitorKey: '50100542_1'
2 months ago
}
const { data: { code, result } } = await axios.get(`/ldpdtools/eventData/getPrpdByParam`, {
params,
})
if (code === 200) {
console.log(result, 'res');
2 months ago
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
}],
visualMap: {
min: minCount,
max: maxCount
}
}, { notMerge: false });
}
}
2 months ago
},
}
// 放在vue中的data会卡顿
const prpsData = [
{
prpsChart: null,
prpsChartOps: null
},
{
prpsChart: null,
prpsChartOps: null
},
{
prpsChart: null,
prpsChartOps: null
},
{
prpsChart: null,
prpsChartOps: null
},
{
prpsChart: null,
prpsChartOps: null
},
{
prpsChart: null,
prpsChartOps: null
}
]
const prpdAndPrpsRefs = ref([]);
const prpdAndPrps = {
components: {
totalPrpd,
},
template: `<div class='prps-and-prpd-container'>
<div v-show='currentKey==="PRPS"' ref='prpsRef' style="width: 100%; height: 100%;"></div>
<total-prpd v-show='currentKey==="PRPD"' class="total-prpd-item" />
<div class='switcher'>
<span v-for='item in switchBox' :key='item' @click='currentKey=item'
:class='{"active-span":currentKey===item}'>
<span v-if='item==="PRPD"'>/</span>
{{item}}</span>
</div>
</div>`,
data() {
return {
len: 0,
timer: 0,
switchBox: ['PRPS', 'PRPD'],
currentKey: 'PRPS'
};
},
props: {
sort: {
type: Number,
default: 0
}
},
async mounted() {
this.initChart(); // 初始化 ECharts 实例和基础配置
await fetch('./three/prps copy.json')  // JSON文件路径
.then(response => response.json())  // 解析为JSON对象
.then(data => {
let databox = []
for (let i = 0; i < 5000; i++) {
databox[i] = -100;
}
const fullData = databox.concat(data); // 直接使用导入的 JSON 数
this.dispose([...fullData]); // 启动动画
})
.catch(error => console.error('加载JSON失败:', error));
},
beforeDestroy() {
// 在组件销毁前,清除定时器并销毁 ECharts 实例
if (this.timer) {
this.closeTimer()
}
},
methods: {
closeTimer() {
clearTimeout(this.timer);
},
initChart() {
if (this.$refs.prpsRef) {
prpsData[this.sort].prpsChart = echarts.init(this.$refs.prpsRef);
// 初始化一次不变的 ECharts 配置
prpsData[this.sort].prpsChartOps = {
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: function (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: function (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: function (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 },
}
}]
};
prpsData[this.sort].prpsChart.setOption(prpsData[this.sort].prpsChartOps);
}
},
// 绘制/更新 ECharts 3D 图表
drawEcharts3d(obj) {
if (!prpsData[this.sort].prpsChart) return; // 确保图表实例已存在
let arr = [];
deal(arr, obj); // 处理数据
// 只更新 series 的 data 部分
prpsData[this.sort].prpsChart.setOption({
series: [{
data: arr.map(function (item) {
return {
value: [item[0], item[1], item[2]]
}
})
}]
});
},
// 动画循环逻辑
dispose(data) {
clearTimeout(this.timer); // 清除上一个定时器
this.drawEcharts3d(data); // 绘制图表
let em = [];
em = data.splice(0, 1000); // 移除前1000个元素
this.len++; // 计数器加一
if (this.len > 5) { // 如果超过5次循环将移除的元素重新加回末尾
data = data.concat(em);
}
// 设置下一个定时器
this.timer = setTimeout(() => {
this.dispose(data); // 递归调用自身
}, 200);
}
}
}
2 months ago
// 事件统计组件
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>
2 months ago
</div>`,
data() {
return {
pdTypeData: []
2 months ago
}
},
props: ['time', 'selectedKey', 'treeData'],
inject: ['provideAllPdTypes'],
2 months ago
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
}
},
2 months ago
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 || []
},
2 months ago
}
}
2 months ago
createApp({
setup() {
const typeOfCheckable = ['historyTrend', 'countPRPD', 'prpdAndPrps']
2 months ago
const timeSelectArr = ['historyTrend', 'countPRPD', 'prpdAndPrps', 'eventCount'] // 含有时间选择的组件
2 months ago
const treeData = ref([])
const fullTreeData = ref([]) // 懒加载后的完整菜单数据
const checkedKeys1 = ref([]); // 勾选
const selectedKey = 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('countPRPD')
2 months ago
const tabsArr = [
{ key: 'historyTrend', tab: '历史趋势' },
{ key: 'alarmConfig', tab: '告警管理' },
{ key: 'countPRPD', tab: '累计PRPD' },
{ 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 }) => {
2 months ago
if (currentKeys.length > 6) {
message.warning('最多只能勾选6个节点');
// 阻止勾选:回退到前一次的状态
checkedKeys1.value = checkedKeys1.value.slice(0, 6);
treeRef.value.setCheckedKeys(checkedKeys1.value);
} else {
if (unref(activeKey) === 'countPRPD') {
// 处理累计prpd逻辑
handleCountPRPDSelect(checkedNode)
}
2 months ago
checkedKeys1.value = currentKeys
}
}
const selectTree = (node) => {
if (node.isRoot) {
selectedKey.value = ''
} else {
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,
...item
}
})
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]) => {
2 months ago
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,
};
2 months ago
});
});
// 告警信息
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();
};
// 告警管理监听
watch(selectedKey, (key) => {
if (!key || unref(activeKey) !== 'alarmConfig') return
// 初始化筛选数据
Object.assign(alarmFilters, {
times: [],
isCancel: '',
pdTypes: []
});
// 请求数据
fetchAlarmGridData();
});
// 累计prpd
const totalPrpds = ref([
{
monitorKey: '', // 监控点key
monitorName: '' // 监控点名称
2 months ago
},
{
monitorKey: '',
monitorName: ''
2 months ago
},
{
monitorKey: '',
monitorName: ''
2 months ago
},
{
monitorKey: '',
monitorName: ''
2 months ago
},
{
monitorKey: '',
monitorName: ''
2 months ago
},
{
monitorKey: '',
monitorName: ''
2 months ago
},
])
const timeList = ref([]) // 事件列表
const activeTime = ref('')
const prpdTimeArr = ref([]) // prpd筛选时间
// 历史趋势所需数据
const trendGraphInfo = computed(() => {
return {
key: unref(selectedKey),
label: findMonitorNameByKey(unref(fullTreeData), unref(selectedKey)),
startTime: unref(dateRange)[0],
endTime: unref(dateRange)[1],
}
})
const getTimeList = (time) => {
timeList.value = generateTimePoints(time)
}
const selectTime = async (time) => {
activeTime.value = time
const before15Min = getFifteenMinutesBefore(time)
prpdTimeArr.value = [before15Min, time]
console.log(prpdTimeArr.value, ' prpdTimeArr.value ');
}
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)
}
console.log(unref(totalPrpds), ' unref(totalPrpds)');
}
2 months ago
// 配置页面
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([]) // 所有路径配置
2 months ago
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
}
2 months ago
// 获取所有配置项
const getAllConfigs = async () => {
getPdTypes()
2 months ago
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] || ''
})
2 months ago
// 排序
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];
2 months ago
}
2 months ago
}
// 保存路径
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()
}
2 months ago
// 获取初始化进度
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) // 后台有一定延迟
}
}
2 months ago
// 监听tab切换
watch(activeKey, (tabKey, oldKey) => {
2 months ago
// 先注释切换tab不清空树选中状态
// checkedKeys1.value = []
// treeRef.value.setCheckedKeys([]);
// selectedKey.value = ''
// treeRef.value.setCurrentKey(null);
2 months ago
if (oldKey === 'historyTrend') {
// 销毁历史趋势数据
2 months ago
// trendGraphData.value = []
// dateRange.value = []
2 months ago
}
if (oldKey === 'alarmConfig') {
// 销毁告警管理
Object.assign(alarmFilters, {
times: [],
isCancel: '',
pdTypes: []
});
dataSource.value = []
}
if (oldKey === 'prpdAndPrps') {
// 销毁prpd/Prps
unref(prpdAndPrpsRefs).forEach(item => {
item.closeTimer()
})
prpsData.forEach(item => {
item.prpsChart?.dispose()
})
}
});
onMounted(() => {
initTreeData()
getAllConfigs()
2 months ago
getInitPrgress()
2 months ago
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,
2 months ago
timeSelectArr,
2 months ago
columns,
dataSource,
pagination,
configLoading,
handleTableChange,
selectedKey,
selectTree,
cancelOps,
alarmFilters,
pdTypeOps,
deleteAlarmTimes,
deleteAlarmConfirm,
fetchAlarmGridData,
initAlarmGridData,
stationName1,
alarmCustomUpload,
alarmBeforeUpload,
defaultProps,
totalPrpds,
allPathCongfigs,
savePathConfig,
resetPathConfig,
2 months ago
prpdAndPrpsRefs,
initCatalogue,
isCurrentInit,
initTips,
trendGraphRefs,
allPdTypes,
trendGraphInfo,
getTimeList,
timeList,
selectTime,
activeTime,
prpdTimeArr
2 months ago
};
},
components: {
totalPrpd,
2 months ago
prpdAndPrps,
eventCount,
historyTrendGraph
2 months ago
}
})
.use(antd)
.use(ElementPlus, {
locale: ElementPlusLocaleZhCn // 使用中文语言包
})
.mount('#app');
</script>
</body>
</html>