|
|
@ -31,15 +31,7 @@
|
|
|
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
|
|
|
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
|
|
|
|
label-width="100px"
|
|
|
|
label-width="100px"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<!-- <el-form-item label="计量设备编号" prop="monitorCode">-->
|
|
|
|
<el-form-item label="记录时间">
|
|
|
|
<!-- <el-input-->
|
|
|
|
|
|
|
|
<!-- v-model="queryParams.monitorCode"-->
|
|
|
|
|
|
|
|
<!-- placeholder="请输入计量设备编号"-->
|
|
|
|
|
|
|
|
<!-- clearable-->
|
|
|
|
|
|
|
|
<!-- @keyup.enter.native="handleQuery"-->
|
|
|
|
|
|
|
|
<!-- />-->
|
|
|
|
|
|
|
|
<!-- </el-form-item>-->
|
|
|
|
|
|
|
|
<el-form-item label="采集时间">
|
|
|
|
|
|
|
|
<date-picker
|
|
|
|
<date-picker
|
|
|
|
v-model="daterangeRecordTime"
|
|
|
|
v-model="daterangeRecordTime"
|
|
|
|
range
|
|
|
|
range
|
|
|
@ -52,37 +44,43 @@
|
|
|
|
></date-picker>
|
|
|
|
></date-picker>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- <el-form-item label="采集日期范围">
|
|
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
|
|
v-model="daterangeCollectTime"
|
|
|
|
|
|
|
|
style="width: 340px"
|
|
|
|
|
|
|
|
value-format="yyyy-MM-dd"
|
|
|
|
|
|
|
|
type="daterange"
|
|
|
|
|
|
|
|
range-separator="-"
|
|
|
|
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
|
|
|
|
></el-date-picker>
|
|
|
|
|
|
|
|
</el-form-item>-->
|
|
|
|
|
|
|
|
<!-- <el-form-item label="记录时间范围">
|
|
|
|
|
|
|
|
<el-time-picker
|
|
|
|
|
|
|
|
v-model="timerangeRecordTime"
|
|
|
|
|
|
|
|
style="width: 340px"
|
|
|
|
|
|
|
|
value-format="HH:mm:ss"
|
|
|
|
|
|
|
|
is-range
|
|
|
|
|
|
|
|
range-separator="-"
|
|
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
|
|
|
|
></el-time-picker>
|
|
|
|
|
|
|
|
</el-form-item>-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
|
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
|
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图表联动提示 -->
|
|
|
|
|
|
|
|
<el-alert
|
|
|
|
|
|
|
|
v-if="powerOutageSummary.count > 0"
|
|
|
|
|
|
|
|
title="图表已联动,缩放任一图表将同步其它图表"
|
|
|
|
|
|
|
|
type="info"
|
|
|
|
|
|
|
|
:closable="false"
|
|
|
|
|
|
|
|
show-icon
|
|
|
|
|
|
|
|
style="margin-bottom: 10px"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 停电统计信息 -->
|
|
|
|
|
|
|
|
<el-card v-if="powerOutageSummary.count > 0" class="power-outage-summary" shadow="hover">
|
|
|
|
|
|
|
|
<div slot="header">
|
|
|
|
|
|
|
|
<span><i class="el-icon-lightning" style="color: red;"></i> 停电统计</span>
|
|
|
|
|
|
|
|
<el-button style="float: right; padding: 3px 0" type="text" @click="exportPowerOutageData">
|
|
|
|
|
|
|
|
导出停电记录
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="power-outage-info">
|
|
|
|
|
|
|
|
<p><strong>停电次数:</strong> {{ powerOutageSummary.count }} 次</p>
|
|
|
|
|
|
|
|
<p><strong>最长停电:</strong> {{ powerOutageSummary.longestDuration }} 小时</p>
|
|
|
|
|
|
|
|
<p><strong>总停电时长:</strong> {{ powerOutageSummary.totalDuration }} 小时</p>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图表区域 -->
|
|
|
|
|
|
|
|
<div class="charts-container">
|
|
|
|
<Chart ref="Chart1" class="chart1"/>
|
|
|
|
<Chart ref="Chart1" class="chart1"/>
|
|
|
|
<Chart ref="Chart2" class="chart2"/>
|
|
|
|
<Chart ref="Chart2" class="chart2"/>
|
|
|
|
<Chart ref="Chart3" class="chart3"/>
|
|
|
|
<Chart ref="Chart3" class="chart3"/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</el-col>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -194,11 +192,22 @@ export default {
|
|
|
|
firstDayOfWeek: 1
|
|
|
|
firstDayOfWeek: 1
|
|
|
|
},
|
|
|
|
},
|
|
|
|
monthBeforeYear: false
|
|
|
|
monthBeforeYear: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// 停电统计信息
|
|
|
|
|
|
|
|
powerOutageSummary: {
|
|
|
|
|
|
|
|
count: 0,
|
|
|
|
|
|
|
|
totalDuration: 0,
|
|
|
|
|
|
|
|
longestDuration: 0
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// 停电详情列表
|
|
|
|
|
|
|
|
powerOutageList: [],
|
|
|
|
|
|
|
|
// 数据抽样阈值
|
|
|
|
|
|
|
|
samplingThreshold: 1000,
|
|
|
|
|
|
|
|
// 图表基础配置
|
|
|
|
|
|
|
|
baseChartOptions: {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
created() {
|
|
|
|
created() {
|
|
|
|
|
|
|
|
|
|
|
|
const nowDate = new Date();
|
|
|
|
const nowDate = new Date();
|
|
|
|
const today = parseTime(new Date(), '{y}-{m}-{d}')
|
|
|
|
const today = parseTime(new Date(), '{y}-{m}-{d}')
|
|
|
|
const lastDate = new Date();
|
|
|
|
const lastDate = new Date();
|
|
|
@ -209,13 +218,8 @@ export default {
|
|
|
|
this.daterangeRecordTime[0] = yesterday+ ' 08:00:00'
|
|
|
|
this.daterangeRecordTime[0] = yesterday+ ' 08:00:00'
|
|
|
|
this.daterangeRecordTime[1] = today + ' 08:00:00'
|
|
|
|
this.daterangeRecordTime[1] = today + ' 08:00:00'
|
|
|
|
|
|
|
|
|
|
|
|
/* this.daterangeCollectTime[0] = parseTime(yesterday, '{y}-{m}-{d}') ;
|
|
|
|
// 初始化图表基础配置
|
|
|
|
this.daterangeCollectTime[1] = parseTime(today, '{y}-{m}-{d}') ;
|
|
|
|
this.initBaseChartOptions()
|
|
|
|
//时间默认为8点
|
|
|
|
|
|
|
|
this.timerangeRecordTime[0] = '08:00:00';
|
|
|
|
|
|
|
|
this.timerangeRecordTime[1] = '08:00:00';*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.getTreeselect()
|
|
|
|
this.getTreeselect()
|
|
|
|
this.getTreeMonitorInfo()
|
|
|
|
this.getTreeMonitorInfo()
|
|
|
|
this.getList()
|
|
|
|
this.getList()
|
|
|
@ -227,6 +231,72 @@ export default {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
methods: {
|
|
|
|
|
|
|
|
/** 初始化图表基础配置 */
|
|
|
|
|
|
|
|
initBaseChartOptions() {
|
|
|
|
|
|
|
|
this.baseChartOptions = {
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
top: '15%',
|
|
|
|
|
|
|
|
bottom: '10%',
|
|
|
|
|
|
|
|
left: '10%',
|
|
|
|
|
|
|
|
right: '3%'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
|
|
axisPointer: {
|
|
|
|
|
|
|
|
type: 'shadow',
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
dataZoom: [{
|
|
|
|
|
|
|
|
type: 'slider'
|
|
|
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
right: 0,
|
|
|
|
|
|
|
|
data: ['数据', '停电']
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: {
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
|
|
show: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/** 转换计量设备信息数据结构 */
|
|
|
|
/** 转换计量设备信息数据结构 */
|
|
|
|
normalizer(node) {
|
|
|
|
normalizer(node) {
|
|
|
|
if (node.children && !node.children.length) {
|
|
|
|
if (node.children && !node.children.length) {
|
|
|
@ -238,19 +308,15 @@ export default {
|
|
|
|
children: node.children
|
|
|
|
children: node.children
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/** 查询电实时数据列表 */
|
|
|
|
/** 查询电实时数据列表 */
|
|
|
|
getList() {
|
|
|
|
getList() {
|
|
|
|
this.loading = true
|
|
|
|
this.loading = true
|
|
|
|
this.queryParams.params = {}
|
|
|
|
this.queryParams.params = {}
|
|
|
|
/* if (null != this.daterangeCollectTime && '' != this.daterangeCollectTime) {
|
|
|
|
|
|
|
|
this.queryParams.params['beginCollectTime'] =this.daterangeCollectTime[0] + ' ' + this.timerangeRecordTime[0];
|
|
|
|
|
|
|
|
this.queryParams.params['endCollectTime'] =this.daterangeCollectTime[1] + ' ' + this.timerangeRecordTime[1];
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
if (null != this.daterangeRecordTime && '' != this.daterangeRecordTime) {
|
|
|
|
if (null != this.daterangeRecordTime && '' != this.daterangeRecordTime) {
|
|
|
|
this.queryParams.params['beginRecordTime'] =this.daterangeRecordTime[0];
|
|
|
|
this.queryParams.params['beginRecordTime'] = this.daterangeRecordTime[0];
|
|
|
|
this.queryParams.params['endRecordTime'] =this.daterangeRecordTime[1];
|
|
|
|
this.queryParams.params['endRecordTime'] = this.daterangeRecordTime[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.getChart()
|
|
|
|
this.getChart()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
@ -298,6 +364,50 @@ export default {
|
|
|
|
}, `recordSteamInstant_${new Date().getTime()}.xlsx`)
|
|
|
|
}, `recordSteamInstant_${new Date().getTime()}.xlsx`)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 导出停电数据 */
|
|
|
|
|
|
|
|
exportPowerOutageData() {
|
|
|
|
|
|
|
|
if (this.powerOutageList.length === 0) {
|
|
|
|
|
|
|
|
this.$message.warning('没有停电数据可导出');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 准备导出数据
|
|
|
|
|
|
|
|
const columns = [
|
|
|
|
|
|
|
|
{label: '序号', prop: 'index'},
|
|
|
|
|
|
|
|
{label: '开始时间', prop: 'startTime'},
|
|
|
|
|
|
|
|
{label: '结束时间', prop: 'endTime'},
|
|
|
|
|
|
|
|
{label: '持续时间(小时)', prop: 'duration'}
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let table = '<table border="1" cellspacing="0" cellpadding="5">';
|
|
|
|
|
|
|
|
// 添加表头
|
|
|
|
|
|
|
|
table += '<tr>';
|
|
|
|
|
|
|
|
columns.forEach(col => {
|
|
|
|
|
|
|
|
table += `<th>${col.label}</th>`;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
table += '</tr>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加数据行
|
|
|
|
|
|
|
|
this.powerOutageList.forEach(item => {
|
|
|
|
|
|
|
|
table += '<tr>';
|
|
|
|
|
|
|
|
columns.forEach(col => {
|
|
|
|
|
|
|
|
table += `<td>${item[col.prop]}</td>`;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
table += '</tr>';
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
table += '</table>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建临时HTML文件下载
|
|
|
|
|
|
|
|
const deviceName = this.selectMonitorName || '设备';
|
|
|
|
|
|
|
|
const fileName = `${deviceName}停电记录_${new Date().getTime()}.xls`;
|
|
|
|
|
|
|
|
const blob = new Blob([table], {type: 'application/vnd.ms-excel'});
|
|
|
|
|
|
|
|
const link = document.createElement('a');
|
|
|
|
|
|
|
|
link.href = URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
link.download = fileName;
|
|
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
|
|
URL.revokeObjectURL(link.href);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/** 查询计量设备信息下拉树结构 */
|
|
|
|
/** 查询计量设备信息下拉树结构 */
|
|
|
|
getTreeselect() {
|
|
|
|
getTreeselect() {
|
|
|
|
getMonitorInfoTree({ monitorType: 4 }).then(response => {
|
|
|
|
getMonitorInfoTree({ monitorType: 4 }).then(response => {
|
|
|
@ -318,284 +428,346 @@ export default {
|
|
|
|
this.handleQuery()
|
|
|
|
this.handleQuery()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 数据抽样处理,当数据量大时进行抽样
|
|
|
|
|
|
|
|
* @param {Array} dataArray 原始数据数组
|
|
|
|
|
|
|
|
* @returns {Array} 抽样后的数据
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
sampleData(dataArray) {
|
|
|
|
|
|
|
|
if (!dataArray || dataArray.length <= this.samplingThreshold) {
|
|
|
|
|
|
|
|
return dataArray;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算抽样间隔
|
|
|
|
|
|
|
|
const interval = Math.ceil(dataArray.length / this.samplingThreshold);
|
|
|
|
|
|
|
|
const sampledData = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 抽样处理,保留首尾数据
|
|
|
|
|
|
|
|
for (let i = 0; i < dataArray.length; i += interval) {
|
|
|
|
|
|
|
|
sampledData.push(dataArray[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 确保最后一个数据点被包含
|
|
|
|
|
|
|
|
if (sampledData[sampledData.length - 1] !== dataArray[dataArray.length - 1]) {
|
|
|
|
|
|
|
|
sampledData.push(dataArray[dataArray.length - 1]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return sampledData;
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 处理时间间隔大于1小时的数据,插入标红的0值点
|
|
|
|
|
|
|
|
* @param {Array} originalData 原始数据数组
|
|
|
|
|
|
|
|
* @param {string} valueField 数值字段名
|
|
|
|
|
|
|
|
* @returns {Object} 处理后的数据和标记点
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
processDataBreaks(originalData, valueField) {
|
|
|
|
|
|
|
|
// 先进行数据抽样处理
|
|
|
|
|
|
|
|
const sampledData = this.sampleData(originalData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!sampledData || sampledData.length < 2) {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
processedData: sampledData || [],
|
|
|
|
|
|
|
|
timeData: sampledData ? sampledData.map(e => e.recordTime) : [],
|
|
|
|
|
|
|
|
valueData: sampledData ? sampledData.map(e => e[valueField]) : [],
|
|
|
|
|
|
|
|
markPoints: [],
|
|
|
|
|
|
|
|
markAreas: []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 按时间排序(确保数据按时间顺序)
|
|
|
|
|
|
|
|
const sortedData = [...sampledData].sort((a, b) => {
|
|
|
|
|
|
|
|
return new Date(a.recordTime) - new Date(b.recordTime)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const processedData = []
|
|
|
|
|
|
|
|
const markPoints = []
|
|
|
|
|
|
|
|
const markAreas = []
|
|
|
|
|
|
|
|
const powerOutages = []
|
|
|
|
|
|
|
|
const oneHourMs = 60 * 60 * 1000 // 1小时的毫秒数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历并处理数据
|
|
|
|
|
|
|
|
for (let i = 0; i < sortedData.length; i++) {
|
|
|
|
|
|
|
|
// 添加当前数据点
|
|
|
|
|
|
|
|
processedData.push(sortedData[i])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有数据中断
|
|
|
|
|
|
|
|
if (i < sortedData.length - 1) {
|
|
|
|
|
|
|
|
const currentTime = new Date(sortedData[i].recordTime).getTime()
|
|
|
|
|
|
|
|
const nextTime = new Date(sortedData[i + 1].recordTime).getTime()
|
|
|
|
|
|
|
|
const timeDiff = nextTime - currentTime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果时间间隔大于1小时,插入断点
|
|
|
|
|
|
|
|
if (timeDiff > oneHourMs) {
|
|
|
|
|
|
|
|
// 创建断点 - 使用null值强制图表线断开
|
|
|
|
|
|
|
|
// 当前点之后的断点
|
|
|
|
|
|
|
|
const breakTime1 = new Date(currentTime + 60000)
|
|
|
|
|
|
|
|
const breakTime1Str = parseTime(breakTime1, '{y}-{m}-{d} {h}:{i}:{s}')
|
|
|
|
|
|
|
|
const nullPoint1 = {
|
|
|
|
|
|
|
|
recordTime: breakTime1Str,
|
|
|
|
|
|
|
|
[valueField]: null, // 使用null而不是0
|
|
|
|
|
|
|
|
isBreakPoint: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
processedData.push(nullPoint1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 下一个点之前的断点
|
|
|
|
|
|
|
|
const breakTime2 = new Date(nextTime - 60000)
|
|
|
|
|
|
|
|
const breakTime2Str = parseTime(breakTime2, '{y}-{m}-{d} {h}:{i}:{s}')
|
|
|
|
|
|
|
|
const nullPoint2 = {
|
|
|
|
|
|
|
|
recordTime: breakTime2Str,
|
|
|
|
|
|
|
|
[valueField]: null, // 使用null而不是0
|
|
|
|
|
|
|
|
isBreakPoint: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
processedData.push(nullPoint2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const endBreakTime = new Date(nextTime - 60000)
|
|
|
|
|
|
|
|
const endBreakTimeStr = parseTime(endBreakTime, '{y}-{m}-{d} {h}:{i}:{s}')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加标记点信息
|
|
|
|
|
|
|
|
markPoints.push({
|
|
|
|
|
|
|
|
value: '停电',
|
|
|
|
|
|
|
|
xAxis: breakTime1Str,
|
|
|
|
|
|
|
|
yAxis: 0,
|
|
|
|
|
|
|
|
symbol: 'path://M11.184 6.6C10.744 5.04 9.252 4 7.5 4s-3.244 1.04-3.684 2.6l-3.755 9.96A.5.5 0 0 0 .5 17h3.882a.5.5 0 0 0 .474-.65l-.333-1h6.954l-.333 1A.5.5 0 0 0 11.618 17H15.5a.5.5 0 0 0 .46-.69l-3.776-9.71zm1.372 8.15l-1.087-2.792A.5.5 0 0 0 11 11.5H4a.5.5 0 0 0-.47.342l-1.087 2.917h-1.3l3.446-9.13C5.819 4.673 6.64 4 7.5 4s1.68.673 1.908 1.63l3.446 9.13h-1.298z',
|
|
|
|
|
|
|
|
symbolSize: 30,
|
|
|
|
|
|
|
|
symbolOffset: [0, '-50%'],
|
|
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
|
|
color: 'red'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 标记区域
|
|
|
|
|
|
|
|
markAreas.push([
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xAxis: breakTime1Str,
|
|
|
|
|
|
|
|
itemStyle: { color: 'rgba(255, 0, 0, 0.1)' }
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xAxis: endBreakTimeStr,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 记录停电信息
|
|
|
|
|
|
|
|
const durationHours = (timeDiff / (1000 * 60 * 60)).toFixed(2);
|
|
|
|
|
|
|
|
powerOutages.push({
|
|
|
|
|
|
|
|
startTime: parseTime(new Date(currentTime), '{y}-{m}-{d} {h}:{i}:{s}'),
|
|
|
|
|
|
|
|
endTime: parseTime(new Date(nextTime), '{y}-{m}-{d} {h}:{i}:{s}'),
|
|
|
|
|
|
|
|
duration: durationHours
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新停电统计信息
|
|
|
|
|
|
|
|
this.updatePowerOutageSummary(powerOutages);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提取时间和数值数据
|
|
|
|
|
|
|
|
const timeData = processedData.map(e => e.recordTime)
|
|
|
|
|
|
|
|
const valueData = processedData.map(e => e[valueField])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算平均值时排除中断点
|
|
|
|
|
|
|
|
const validData = processedData.filter(item => !item.isBreakPoint)
|
|
|
|
|
|
|
|
const validValues = validData.map(e => parseFloat(e[valueField]))
|
|
|
|
|
|
|
|
const average = validValues.length > 0 ?
|
|
|
|
|
|
|
|
(validValues.reduce((a, b) => a + b, 0) / validValues.length).toFixed(2) : 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
processedData,
|
|
|
|
|
|
|
|
timeData,
|
|
|
|
|
|
|
|
valueData,
|
|
|
|
|
|
|
|
markPoints,
|
|
|
|
|
|
|
|
markAreas,
|
|
|
|
|
|
|
|
average
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 更新停电统计信息
|
|
|
|
|
|
|
|
* @param {Array} powerOutages 停电记录数组
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
updatePowerOutageSummary(powerOutages) {
|
|
|
|
|
|
|
|
if (!powerOutages || powerOutages.length === 0) {
|
|
|
|
|
|
|
|
this.powerOutageSummary = {
|
|
|
|
|
|
|
|
count: 0,
|
|
|
|
|
|
|
|
totalDuration: 0,
|
|
|
|
|
|
|
|
longestDuration: 0
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
this.powerOutageList = [];
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算总停电时长和最长停电时长
|
|
|
|
|
|
|
|
let totalDuration = 0;
|
|
|
|
|
|
|
|
let longestDuration = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
powerOutages.forEach((outage, index) => {
|
|
|
|
|
|
|
|
const duration = parseFloat(outage.duration);
|
|
|
|
|
|
|
|
totalDuration += duration;
|
|
|
|
|
|
|
|
longestDuration = Math.max(longestDuration, duration);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新停电统计信息
|
|
|
|
|
|
|
|
this.powerOutageSummary = {
|
|
|
|
|
|
|
|
count: powerOutages.length,
|
|
|
|
|
|
|
|
totalDuration: totalDuration.toFixed(2),
|
|
|
|
|
|
|
|
longestDuration: longestDuration.toFixed(2)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新停电详情列表
|
|
|
|
|
|
|
|
this.powerOutageList = powerOutages.map((outage, index) => ({
|
|
|
|
|
|
|
|
index: index + 1,
|
|
|
|
|
|
|
|
startTime: outage.startTime,
|
|
|
|
|
|
|
|
endTime: outage.endTime,
|
|
|
|
|
|
|
|
duration: outage.duration
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 创建图表配置
|
|
|
|
|
|
|
|
* @param {String} title 图表标题
|
|
|
|
|
|
|
|
* @param {Object} dataResult 处理后的数据结果
|
|
|
|
|
|
|
|
* @param {String} name 数据名称
|
|
|
|
|
|
|
|
* @param {String} yAxisName Y轴名称
|
|
|
|
|
|
|
|
* @param {String} color 图表颜色
|
|
|
|
|
|
|
|
* @param {Function} tooltipFormatter 提示格式化函数
|
|
|
|
|
|
|
|
* @returns {Object} 图表配置
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
createChartOption(title, dataResult, name, yAxisName, color, tooltipFormatter) {
|
|
|
|
|
|
|
|
const option = JSON.parse(JSON.stringify(this.baseChartOptions));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置标题
|
|
|
|
|
|
|
|
option.title = {
|
|
|
|
|
|
|
|
text: this.selectMonitorName + ' ' + title + ' (平均值:' + dataResult.average + ")",
|
|
|
|
|
|
|
|
x: 'center',
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
fontSize: 15
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置X轴数据
|
|
|
|
|
|
|
|
option.xAxis.data = dataResult.timeData;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置Y轴名称
|
|
|
|
|
|
|
|
option.yAxis.name = yAxisName;
|
|
|
|
|
|
|
|
option.yAxis.nameTextStyle = {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置提示格式化
|
|
|
|
|
|
|
|
option.tooltip.formatter = tooltipFormatter || function(params) {
|
|
|
|
|
|
|
|
const dataIndex = params[0].dataIndex;
|
|
|
|
|
|
|
|
const isBreakPoint = dataResult.processedData[dataIndex] && dataResult.processedData[dataIndex].isBreakPoint;
|
|
|
|
|
|
|
|
if (isBreakPoint) {
|
|
|
|
|
|
|
|
return '停电<br/>时间: ' + params[0].axisValue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return params[0].seriesName + ': ' + params[0].value + '<br/>时间: ' + params[0].axisValue;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置数据系列
|
|
|
|
|
|
|
|
option.series = [{
|
|
|
|
|
|
|
|
name: name,
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: false,
|
|
|
|
|
|
|
|
showAllSymbol: true,
|
|
|
|
|
|
|
|
symbol: 'circle',
|
|
|
|
|
|
|
|
symbolSize: 4,
|
|
|
|
|
|
|
|
step: 'end',
|
|
|
|
|
|
|
|
connectNulls: false,
|
|
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
|
|
normal: {
|
|
|
|
|
|
|
|
color: function(params) {
|
|
|
|
|
|
|
|
return dataResult.processedData[params.dataIndex] && dataResult.processedData[params.dataIndex].isBreakPoint ? 'red' : color;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
data: dataResult.valueData,
|
|
|
|
|
|
|
|
markPoint: {
|
|
|
|
|
|
|
|
data: dataResult.markPoints,
|
|
|
|
|
|
|
|
symbolSize: 60,
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
|
|
|
color: '#000000',
|
|
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
|
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
|
|
|
|
|
|
borderColor: '#ff0000',
|
|
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
|
|
borderRadius: 4,
|
|
|
|
|
|
|
|
padding: [4, 8]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
markArea: {
|
|
|
|
|
|
|
|
data: dataResult.markAreas,
|
|
|
|
|
|
|
|
silent: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
markLine: {
|
|
|
|
|
|
|
|
silent: true,
|
|
|
|
|
|
|
|
symbol: 'none',
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#ff0000',
|
|
|
|
|
|
|
|
width: 2,
|
|
|
|
|
|
|
|
type: 'dashed'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
|
|
|
show: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
data: dataResult.markPoints.map(point => ({
|
|
|
|
|
|
|
|
xAxis: point.xAxis
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 确保y轴包含0点
|
|
|
|
|
|
|
|
if (!option.yAxis.min) {
|
|
|
|
|
|
|
|
option.yAxis.min = function(value) {
|
|
|
|
|
|
|
|
// 数据中有停电断点,确保图表显示到0
|
|
|
|
|
|
|
|
if (dataResult.processedData.some(item => item.isBreakPoint)) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return value.min;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return option;
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/** 曲线 */
|
|
|
|
/** 曲线 */
|
|
|
|
async getChart() {
|
|
|
|
async getChart() {
|
|
|
|
|
|
|
|
this.loading = true;
|
|
|
|
let query = JSON.parse(JSON.stringify(this.queryParams))
|
|
|
|
let query = JSON.parse(JSON.stringify(this.queryParams))
|
|
|
|
|
|
|
|
try {
|
|
|
|
const {data} = await steamInstantList(query)
|
|
|
|
const {data} = await steamInstantList(query)
|
|
|
|
|
|
|
|
|
|
|
|
let option1 = {
|
|
|
|
// 处理瞬时流量数据
|
|
|
|
title: {
|
|
|
|
const fluxFlowResult = this.processDataBreaks(data, 'fluxFlow')
|
|
|
|
text: this.selectMonitorName + ' 瞬时流量' + ' (平均值:'+
|
|
|
|
// 处理温度数据
|
|
|
|
((data.map(e=>parseFloat(e.fluxFlow)).reduce((a,b)=>a+b,0))/data.length).toFixed(2)+")",
|
|
|
|
const temperatureResult = this.processDataBreaks(data, 'temperature')
|
|
|
|
x: 'center',
|
|
|
|
// 处理压力数据
|
|
|
|
textStyle: {
|
|
|
|
const pressResult = this.processDataBreaks(data, 'press')
|
|
|
|
fontSize: 15 // 设置字体大小
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
top: '15%',
|
|
|
|
|
|
|
|
bottom: '10%',
|
|
|
|
|
|
|
|
left: '10%',
|
|
|
|
|
|
|
|
right: '3%'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
|
|
axisPointer: {
|
|
|
|
|
|
|
|
type: 'shadow',
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
dataZoom: [{
|
|
|
|
|
|
|
|
type: 'slider'
|
|
|
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
right: 0
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
data: data.map(e => e.recordTime),
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true, //隐藏X轴轴线
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true //隐藏X轴刻度
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000' //X轴文字颜色
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
name: '瞬时流量y',
|
|
|
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
|
|
show: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
series: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '瞬时流量',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true, //平滑曲线显示
|
|
|
|
|
|
|
|
showAllSymbol: true, //显示所有图形。
|
|
|
|
|
|
|
|
symbol: 'circle', //标记的图形为实心圆
|
|
|
|
|
|
|
|
symbolSize: 0, //标记的大小
|
|
|
|
|
|
|
|
data: data.map(e => e.fluxFlow)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let option2 = {
|
|
|
|
|
|
|
|
/* 过滤无效数据:使用 filter 方法过滤掉 temperature 为 undefined 或 null 的数据
|
|
|
|
|
|
|
|
title: {
|
|
|
|
|
|
|
|
text: this.selectMonitorName + ' 温度' + ' (平均值:' +
|
|
|
|
|
|
|
|
((data.filter(e => e.temperature !== undefined && e.temperature !== null)
|
|
|
|
|
|
|
|
.map(e => parseFloat(e.temperature))
|
|
|
|
|
|
|
|
.reduce((a, b) => a + b, 0)) /
|
|
|
|
|
|
|
|
data.filter(e => e.temperature !== undefined && e.temperature !== null).length).toFixed(2) + ")",
|
|
|
|
|
|
|
|
x: 'center'
|
|
|
|
|
|
|
|
},*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建图表配置
|
|
|
|
|
|
|
|
const option1 = this.createChartOption(
|
|
|
|
|
|
|
|
'瞬时流量',
|
|
|
|
|
|
|
|
fluxFlowResult,
|
|
|
|
|
|
|
|
'瞬时流量',
|
|
|
|
|
|
|
|
'瞬时流量y',
|
|
|
|
|
|
|
|
'#5470c6'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
title: {
|
|
|
|
const option2 = this.createChartOption(
|
|
|
|
text: this.selectMonitorName + ' 温度' + ' (平均值:'+
|
|
|
|
'温度',
|
|
|
|
((data.map(e=>parseFloat(e.temperature)).reduce((a,b)=>a+b,0))/data.length).toFixed(2)+")",
|
|
|
|
temperatureResult,
|
|
|
|
x: 'center',
|
|
|
|
'温度',
|
|
|
|
textStyle: {
|
|
|
|
'温度y',
|
|
|
|
fontSize: 15 // 设置字体大小
|
|
|
|
'#91cc75'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
top: '15%',
|
|
|
|
|
|
|
|
bottom: '10%',
|
|
|
|
|
|
|
|
left: '10%',
|
|
|
|
|
|
|
|
right: '3%'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dataZoom: [{
|
|
|
|
const option3 = this.createChartOption(
|
|
|
|
type: 'slider'
|
|
|
|
'压力',
|
|
|
|
}],
|
|
|
|
pressResult,
|
|
|
|
tooltip: {
|
|
|
|
'压力',
|
|
|
|
trigger: 'axis',
|
|
|
|
'压力y',
|
|
|
|
axisPointer: {
|
|
|
|
'#fac858'
|
|
|
|
type: 'shadow',
|
|
|
|
);
|
|
|
|
label: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
right: 0
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
data: data.map(e => e.recordTime),
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true, //隐藏X轴轴线
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true //隐藏X轴刻度
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000' //X轴文字颜色
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
name: '温度y',
|
|
|
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
|
|
show: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
series: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '温度',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true, //平滑曲线显示
|
|
|
|
|
|
|
|
showAllSymbol: true, //显示所有图形。
|
|
|
|
|
|
|
|
symbol: 'circle', //标记的图形为实心圆
|
|
|
|
|
|
|
|
symbolSize: 0, //标记的大小
|
|
|
|
|
|
|
|
data: data.map(e => e.temperature)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let option3 = {
|
|
|
|
|
|
|
|
title: {
|
|
|
|
|
|
|
|
text: this.selectMonitorName + ' 压力' + ' (平均值:'+
|
|
|
|
|
|
|
|
((data.map(e=>parseFloat(e.press)).reduce((a,b)=>a+b,0))/data.length).toFixed(2)+")",
|
|
|
|
|
|
|
|
x: 'center',
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
fontSize: 15 // 设置字体大小
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
top: '15%',
|
|
|
|
|
|
|
|
bottom: '10%',
|
|
|
|
|
|
|
|
left: '10%',
|
|
|
|
|
|
|
|
right: '3%'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
|
|
axisPointer: {
|
|
|
|
|
|
|
|
type: 'shadow',
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
dataZoom: [{
|
|
|
|
|
|
|
|
type: 'slider'
|
|
|
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
right: 0
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
data: data.map(e => e.recordTime),
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true, //隐藏X轴轴线
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true //隐藏X轴刻度
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000' //X轴文字颜色
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
name: '压力y',
|
|
|
|
|
|
|
|
nameTextStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
|
|
show: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
|
|
show: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
color: '#000000'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
series: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '压力',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true, //平滑曲线显示
|
|
|
|
|
|
|
|
showAllSymbol: true, //显示所有图形。
|
|
|
|
|
|
|
|
symbol: 'circle', //标记的图形为实心圆
|
|
|
|
|
|
|
|
symbolSize: 0, //标记的大小
|
|
|
|
|
|
|
|
data: data.map(e => e.press)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.$refs.Chart1.setData(option1)
|
|
|
|
this.$refs.Chart1.setData(option1)
|
|
|
|
this.$refs.Chart2.setData(option2)
|
|
|
|
this.$refs.Chart2.setData(option2)
|
|
|
@ -603,12 +775,7 @@ export default {
|
|
|
|
|
|
|
|
|
|
|
|
echarts.connect(this.$refs.Chart1.chart, this.$refs.Chart2.chart, this.$refs.Chart3.chart)
|
|
|
|
echarts.connect(this.$refs.Chart1.chart, this.$refs.Chart2.chart, this.$refs.Chart3.chart)
|
|
|
|
|
|
|
|
|
|
|
|
/* this.$refs.Chart1.chart.on('datazoom', (e) => {
|
|
|
|
// 同步缩放
|
|
|
|
option.dataZoom[0].start = e.start;
|
|
|
|
|
|
|
|
option.dataZoom[0].end = e.end;
|
|
|
|
|
|
|
|
this.$refs.Chart1.setData(option);
|
|
|
|
|
|
|
|
});*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.$refs.Chart1.chart.on('datazoom', (e) => {
|
|
|
|
this.$refs.Chart1.chart.on('datazoom', (e) => {
|
|
|
|
option2.dataZoom[0].start = e.start
|
|
|
|
option2.dataZoom[0].start = e.start
|
|
|
|
option2.dataZoom[0].end = e.end
|
|
|
|
option2.dataZoom[0].end = e.end
|
|
|
@ -616,8 +783,8 @@ export default {
|
|
|
|
option3.dataZoom[0].start = e.start
|
|
|
|
option3.dataZoom[0].start = e.start
|
|
|
|
option3.dataZoom[0].end = e.end
|
|
|
|
option3.dataZoom[0].end = e.end
|
|
|
|
this.$refs.Chart3.setData(option3)
|
|
|
|
this.$refs.Chart3.setData(option3)
|
|
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
this.$refs.Chart2.chart.on('datazoom', (e) => {
|
|
|
|
this.$refs.Chart2.chart.on('datazoom', (e) => {
|
|
|
|
option1.dataZoom[0].start = e.start
|
|
|
|
option1.dataZoom[0].start = e.start
|
|
|
|
option1.dataZoom[0].end = e.end
|
|
|
|
option1.dataZoom[0].end = e.end
|
|
|
@ -626,6 +793,7 @@ export default {
|
|
|
|
option3.dataZoom[0].end = e.end
|
|
|
|
option3.dataZoom[0].end = e.end
|
|
|
|
this.$refs.Chart3.setData(option3)
|
|
|
|
this.$refs.Chart3.setData(option3)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
this.$refs.Chart3.chart.on('datazoom', (e) => {
|
|
|
|
this.$refs.Chart3.chart.on('datazoom', (e) => {
|
|
|
|
option2.dataZoom[0].start = e.start
|
|
|
|
option2.dataZoom[0].start = e.start
|
|
|
|
option2.dataZoom[0].end = e.end
|
|
|
|
option2.dataZoom[0].end = e.end
|
|
|
@ -634,12 +802,31 @@ export default {
|
|
|
|
option1.dataZoom[0].end = e.end
|
|
|
|
option1.dataZoom[0].end = e.end
|
|
|
|
this.$refs.Chart1.setData(option1)
|
|
|
|
this.$refs.Chart1.setData(option1)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('获取图表数据失败:', error)
|
|
|
|
|
|
|
|
this.$message.error('获取图表数据失败')
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 查询树形结构 */
|
|
|
|
|
|
|
|
getTreeMonitorInfo() {
|
|
|
|
|
|
|
|
getMonitorInfoTree({ monitorType: 4 }).then(response => {
|
|
|
|
|
|
|
|
this.baseMonitorInfoOptions = this.handleTree(response.data, "id", "parentId")
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
<style scoped >
|
|
|
|
<style scoped >
|
|
|
|
|
|
|
|
.app-container {
|
|
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.charts-container {
|
|
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart1 {
|
|
|
|
.chart1 {
|
|
|
|
width: 50%;
|
|
|
|
width: 50%;
|
|
|
@ -652,24 +839,43 @@ export default {
|
|
|
|
height: 40vh;
|
|
|
|
height: 40vh;
|
|
|
|
display: inline-block;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart3 {
|
|
|
|
.chart3 {
|
|
|
|
width: 50%;
|
|
|
|
width: 50%;
|
|
|
|
height: 40vh;
|
|
|
|
height: 40vh;
|
|
|
|
display: inline-block;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 选中节点的样式 */
|
|
|
|
.power-outage-summary {
|
|
|
|
/deep/ .el-tree .el-tree-node.is-current > .el-tree-node__content {
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.power-outage-info {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.power-outage-info p {
|
|
|
|
|
|
|
|
margin: 5px 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 选中节点的样式 */
|
|
|
|
|
|
|
|
::v-deep .el-tree .el-tree-node.is-current > .el-tree-node__content {
|
|
|
|
background-color: #67C23A !important; /* 选中节点的背景色 */
|
|
|
|
background-color: #67C23A !important; /* 选中节点的背景色 */
|
|
|
|
color: #303133 !important; /* 选中节点的文字颜色 */
|
|
|
|
color: #303133 !important; /* 选中节点的文字颜色 */
|
|
|
|
padding: 0; /* 清除内边距 */
|
|
|
|
padding: 0; /* 清除内边距 */
|
|
|
|
margin: 0; /* 清除外边距 */
|
|
|
|
margin: 0; /* 清除外边距 */
|
|
|
|
z-index: 1; /* 确保在其他元素之上 */
|
|
|
|
z-index: 1; /* 确保在其他元素之上 */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 鼠标悬停时的样式 */
|
|
|
|
/* 鼠标悬停时的样式 */
|
|
|
|
.el-tree .el-tree-node__content:hover {
|
|
|
|
.el-tree .el-tree-node__content:hover {
|
|
|
|
background-color: #e6f7ff; /* 鼠标悬停时的背景色 */
|
|
|
|
background-color: #e6f7ff; /* 鼠标悬停时的背景色 */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 闪电图标 */
|
|
|
|
|
|
|
|
.el-icon-lightning:before {
|
|
|
|
|
|
|
|
content: "\e6a8"; /* 使用现有的element-ui图标字体 */
|
|
|
|
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|