统计分析
This commit is contained in:
parent
02ad8ef072
commit
eac0aadd87
@ -43,8 +43,12 @@
|
|||||||
<div class="tabsPart">
|
<div class="tabsPart">
|
||||||
<el-table :data="alarmsTableData" class="tablePart" highlight-current-row>
|
<el-table :data="alarmsTableData" class="tablePart" highlight-current-row>
|
||||||
<el-table-column prop="eventTimeFormate" :label="AlarmsFieldsEnums['alarmTime']" align="center"> </el-table-column>
|
<el-table-column prop="eventTimeFormate" :label="AlarmsFieldsEnums['alarmTime']" align="center"> </el-table-column>
|
||||||
<el-table-column prop="deviceCode" :label="AlarmsFieldsEnums['airBlowerNumber']" align="center"> </el-table-column>
|
<el-table-column prop="devicecodeName" :label="AlarmsFieldsEnums['airBlowerNumber']" align="center"> </el-table-column>
|
||||||
<el-table-column prop="eventText" :label="AlarmsFieldsEnums['faultDescription']" align="center"> </el-table-column>
|
<el-table-column prop="eventText" :label="AlarmsFieldsEnums['faultDescription']" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-html="formatText(row.eventText)"></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="eventLevel" :label="AlarmsFieldsEnums['alarmType']" align="center">
|
<el-table-column prop="eventLevel" :label="AlarmsFieldsEnums['alarmType']" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="tip" v-if="scope.row.eventLevel === 0">提示</div>
|
<div class="tip" v-if="scope.row.eventLevel === 0">提示</div>
|
||||||
@ -199,6 +203,7 @@ const getalarmsList = () => {
|
|||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
eventTimeFormate: timestampToTime(item.eventTime),
|
eventTimeFormate: timestampToTime(item.eventTime),
|
||||||
|
devicecodeName: item.deviceName + item.deviceCode,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -209,6 +214,13 @@ const getalarmsList = () => {
|
|||||||
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatText = (text: any) => {
|
||||||
|
text = text.replace(/ 动作/g, '<span style="color:#a03b1d;"> 动作</span>')
|
||||||
|
text = text.replace(/复归/g, '<span style="color:#39baf4;">复归</span>')
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
const timestampToTime = (timestamp: any) => {
|
const timestampToTime = (timestamp: any) => {
|
||||||
timestamp = timestamp ? timestamp : null
|
timestamp = timestamp ? timestamp : null
|
||||||
let date = new Date(timestamp)
|
let date = new Date(timestamp)
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="statAnalysis">
|
<div class="statAnalysis">
|
||||||
<el-menu :default-active="activeIndex" class="headerList" mode="horizontal" @select="handleSelect">
|
<el-menu :default-active="activeIndex" class="headerList" mode="horizontal" @select="handleSelect">
|
||||||
<el-menu-item v-for="(item, index) in headerList" :index="index" :key="index"> {{ item }} </el-menu-item>
|
<el-menu-item index="0" key="0"> {{ headerList[0] }} </el-menu-item>
|
||||||
|
<el-popover placement="top-start" :width="200" popper-class="admin-info-box" trigger="hover" content="同一测点,不同时间段对比">
|
||||||
|
<template #reference>
|
||||||
|
<el-menu-item index="1" key="1"> {{ headerList[1] }} </el-menu-item>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
<el-popover placement="top-start" :width="200" popper-class="admin-info-box" trigger="hover" content="同一时间段,不同测点对比">
|
||||||
|
<template #reference>
|
||||||
|
<el-menu-item index="2" key="2"> {{ headerList[2] }} </el-menu-item>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<PowerCurveAnalysis v-if="activeIndex == 0"></PowerCurveAnalysis>
|
<PowerCurveAnalysis v-if="activeIndex == 0"></PowerCurveAnalysis>
|
||||||
<TrendAnalysis v-if="activeIndex == 1"></TrendAnalysis>
|
<TrendAnalysis v-if="activeIndex == 1"></TrendAnalysis>
|
||||||
@ -19,7 +29,6 @@ const config = useConfig()
|
|||||||
const activeIndex = ref(0)
|
const activeIndex = ref(0)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const headerList = [t('statAnalysis.PowerCurveAnalysis'), t('statAnalysis.trendAnalysis'), t('statAnalysis.trendComparison')]
|
const headerList = [t('statAnalysis.PowerCurveAnalysis'), t('statAnalysis.trendAnalysis'), t('statAnalysis.trendComparison')]
|
||||||
|
|
||||||
const handleSelect = (index: number) => {
|
const handleSelect = (index: number) => {
|
||||||
activeIndex.value = index
|
activeIndex.value = index
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -199,7 +199,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="timeColumns" :class="{ expand: isExpand }">
|
<div class="timeColumns">
|
||||||
<div class="headerPart" v-for="(time, index) in times" :key="index">
|
<div class="headerPart" v-for="(time, index) in times" :key="index">
|
||||||
<div class="topLeft">
|
<div class="topLeft">
|
||||||
<div class="selectPart">
|
<div class="selectPart">
|
||||||
@ -75,10 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="times.length > 2" class="ralIcon" @click="handleClick">
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
<el-icon :size="20" color="#0064AA"><DArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
|
||||||
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="measureSlotHeader">
|
<div class="measureSlotHeader">
|
||||||
@ -131,10 +128,6 @@ const timechange = (value: any) => {
|
|||||||
ElMessage.warning('查询时间点错误,请重新输入')
|
ElMessage.warning('查询时间点错误,请重新输入')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isExpand = ref(false)
|
|
||||||
const handleClick = () => {
|
|
||||||
isExpand.value = !isExpand.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const iotModelId = ref('')
|
const iotModelId = ref('')
|
||||||
const irn = ref('')
|
const irn = ref('')
|
||||||
@ -258,7 +251,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -396,14 +389,27 @@ const historyDataReq = (promises: any) => {
|
|||||||
const deviceId = statAnalysisSelect.deviceId
|
const deviceId = statAnalysisSelect.deviceId
|
||||||
const attributeCode = statAnalysisSelect.attributeCode
|
const attributeCode = statAnalysisSelect.attributeCode
|
||||||
results.forEach((res: any, index: number) => {
|
results.forEach((res: any, index: number) => {
|
||||||
|
console.log(times[index])
|
||||||
const resData = (res && deviceId in res && res[deviceId][attributeCode]) || undefined
|
const resData = (res && deviceId in res && res[deviceId][attributeCode]) || undefined
|
||||||
const xData = resData['times']
|
|
||||||
const yData = resData['values']
|
if (!resData['values'].length) {
|
||||||
if (!yData.length) {
|
|
||||||
ElMessage.info(`${customName[index]}数据为空`)
|
ElMessage.info(`${customName[index]}数据为空`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
calculate.value[index] = calculateStats(yData)
|
const alltimes = getTimestamps(
|
||||||
|
new Date(times[index][0]).getTime(),
|
||||||
|
new Date(times[index][1]).getTime(),
|
||||||
|
statAnalysisSelect.interval || '5m'
|
||||||
|
)
|
||||||
|
console.log(alltimes)
|
||||||
|
console.log('🚀 ~ results.forEach ~ resData:', resData)
|
||||||
|
const fillData = fillMissingData(alltimes, resData)
|
||||||
|
console.log('🚀 ~ results.forEach ~ fillData:', fillData)
|
||||||
|
|
||||||
|
const xData = fillData['times']
|
||||||
|
const yData = fillData['values']
|
||||||
|
console.log(xData)
|
||||||
|
calculate.value[index] = calculateStats(resData['values'])
|
||||||
xDatas.push({
|
xDatas.push({
|
||||||
series: String(customName[index]),
|
series: String(customName[index]),
|
||||||
data: xData,
|
data: xData,
|
||||||
@ -484,6 +490,52 @@ function calculateStats(numbers: any) {
|
|||||||
average: average.toFixed(2),
|
average: average.toFixed(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTimestamps = (start: any, end: any, interval: any) => {
|
||||||
|
let timestamps = []
|
||||||
|
let current = start
|
||||||
|
|
||||||
|
while (current < end) {
|
||||||
|
timestamps.push(current)
|
||||||
|
switch (interval) {
|
||||||
|
case '5m':
|
||||||
|
current += 5 * 60 * 1000
|
||||||
|
break
|
||||||
|
case '1d':
|
||||||
|
current += 24 * 60 * 60 * 1000
|
||||||
|
break
|
||||||
|
case '15m':
|
||||||
|
current += 15 * 60 * 1000
|
||||||
|
break
|
||||||
|
case 'NONE':
|
||||||
|
current += 40 * 1000
|
||||||
|
break
|
||||||
|
case '1h':
|
||||||
|
current += 60 * 60 * 1000
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported interval')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return timestamps
|
||||||
|
}
|
||||||
|
|
||||||
|
const fillMissingData = (intervals: any, data: any) => {
|
||||||
|
const { times, values } = data
|
||||||
|
const filledTimes: any = []
|
||||||
|
const filledValues: any = []
|
||||||
|
intervals.forEach((time: any) => {
|
||||||
|
const index = times.indexOf(time)
|
||||||
|
filledTimes.push(time)
|
||||||
|
if (index !== -1) {
|
||||||
|
filledValues.push(values[index])
|
||||||
|
} else {
|
||||||
|
filledValues.push('')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { times: filledTimes, values: filledValues }
|
||||||
|
}
|
||||||
const timestampToTime = (timestamp: any) => {
|
const timestampToTime = (timestamp: any) => {
|
||||||
timestamp = timestamp ? timestamp : null
|
timestamp = timestamp ? timestamp : null
|
||||||
let date = new Date(timestamp)
|
let date = new Date(timestamp)
|
||||||
@ -498,6 +550,9 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.statAnalysis {
|
.statAnalysis {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.contain {
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
}
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -572,24 +627,11 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timeColumns {
|
.timeColumns {
|
||||||
max-height: 120px;
|
height: calc(100% - 480px);
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 10px 20px;
|
padding: 2px 20px;
|
||||||
}
|
}
|
||||||
&.expand {
|
|
||||||
max-height: max-content;
|
|
||||||
height: auto;
|
|
||||||
overflow: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.timeColumns.expand + div.ralIcon {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
.ralIcon {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
}
|
||||||
#myEChart {
|
#myEChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="timeColumns" :class="{ expand: isExpand }">
|
<div class="timeColumns">
|
||||||
<div class="headerPart" v-for="(deviceId, index) in statAnalysisDeviceId" :key="index">
|
<div class="headerPart" v-for="(deviceId, index) in statAnalysisDeviceId" :key="index">
|
||||||
<div class="topLeft">
|
<div class="topLeft">
|
||||||
<div class="selectPart">
|
<div class="selectPart">
|
||||||
@ -81,10 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="statAnalysisDeviceId.length > 2" class="ralIcon" @click="handleClick">
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
<el-icon :size="20" color="#0064AA"><DArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
|
||||||
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="measureSlotHeader">
|
<div class="measureSlotHeader">
|
||||||
@ -141,10 +138,6 @@ const switchDevice = (index: number) => {
|
|||||||
calculate.value.splice(index, 1)
|
calculate.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExpand = ref(false)
|
|
||||||
const handleClick = () => {
|
|
||||||
isExpand.value = !isExpand.value
|
|
||||||
}
|
|
||||||
const iotModelId = ref('')
|
const iotModelId = ref('')
|
||||||
const irn = ref('')
|
const irn = ref('')
|
||||||
const selectAtteibutes = (index: number) => {
|
const selectAtteibutes = (index: number) => {
|
||||||
@ -260,7 +253,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -457,6 +450,9 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.statAnalysis {
|
.statAnalysis {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.contain {
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
}
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -531,24 +527,11 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timeColumns {
|
.timeColumns {
|
||||||
max-height: 120px;
|
height: calc(100% - 480px);
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 10px 20px;
|
padding: 2px 20px;
|
||||||
}
|
}
|
||||||
&.expand {
|
|
||||||
max-height: max-content;
|
|
||||||
height: auto;
|
|
||||||
overflow: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.timeColumns.expand + div.ralIcon {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
.ralIcon {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
}
|
||||||
#myEChart {
|
#myEChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
Loading…
Reference in New Issue
Block a user