统计分析

This commit is contained in:
geting 2024-10-31 12:17:53 +08:00
parent 68597dbd8a
commit 5f2ec82b42
4 changed files with 141 additions and 67 deletions

View File

@ -11,7 +11,11 @@
:sortable="item.sortable" :sortable="item.sortable"
> >
<template #default="scope"> <template #default="scope">
<el-radio v-if="item.prop === 'index'" :label="scope.row.id" v-model="selectedIndex" @change="handleRadioChange(scope.row)" <el-radio
v-if="item.prop === 'index'"
:label="scope.row.attributeCode"
v-model="selectedIndex"
@change="handleRadioChange(scope.row)"
>&nbsp;</el-radio >&nbsp;</el-radio
> >
</template> </template>
@ -47,6 +51,10 @@ const props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
irn: {
type: String,
default: '',
},
show: { show: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -91,7 +99,7 @@ const tableColumn = [
const tableData = ref<any[]>([]) const tableData = ref<any[]>([])
const emit = defineEmits(['handleRadioChange']) const emit = defineEmits(['handleRadioChange'])
const handleRadioChange = (row) => { const handleRadioChange = (row) => {
selectedIndex.value = row.id selectedIndex.value = row.attributeCode
emit('handleRadioChange', row) emit('handleRadioChange', row)
} }
const getAttributeList = () => { const getAttributeList = () => {
@ -204,6 +212,7 @@ watch(
(newVal) => { (newVal) => {
if (newVal) { if (newVal) {
getCompleteData() getCompleteData()
selectedIndex.value = props.irn
} }
}, },
{ {

View File

@ -14,7 +14,7 @@ import { useConfig } from '/@/stores/config'
import TrendAnalysis from './trendAnalysis.vue' import TrendAnalysis from './trendAnalysis.vue'
import TrendComparison from './trendComparison.vue' import TrendComparison from './trendComparison.vue'
const config = useConfig() const config = useConfig()
const activeIndex = ref(2) const activeIndex = ref(1)
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')]

View File

@ -6,7 +6,7 @@
<span>{{ t('statAnalysis.deviceId') }}</span> <span>{{ t('statAnalysis.deviceId') }}</span>
<el-select <el-select
v-model="statAnalysisSelect.deviceId" v-model="statAnalysisSelect.deviceId"
@change="selectstatAnalysis('deviceId')" @change="deviceIdChange"
:placeholder="'请选择' + t('statAnalysis.deviceId')" :placeholder="'请选择' + t('statAnalysis.deviceId')"
class="statAnalysisSelect" class="statAnalysisSelect"
> >
@ -18,7 +18,7 @@
<el-input <el-input
class="statAnalysisSelect" class="statAnalysisSelect"
v-model="statAnalysisSelect.attributes" v-model="statAnalysisSelect.attributes"
@click="showMeasure = true" @click="attributesChange"
:placeholder="'请选择' + t('statAnalysis.attributes')" :placeholder="'请选择' + t('statAnalysis.attributes')"
></el-input> ></el-input>
</div> </div>
@ -91,7 +91,7 @@
</div> </div>
</template> </template>
<div class="measureSlot"> <div class="measureSlot">
<MeasurementPage :show="showMeasure" :iotModelId="iotModelId" @handleRadioChange="handleRadioChange"></MeasurementPage> <MeasurementPage :show="showMeasure" :iotModelId="iotModelId" :irn="irn" @handleRadioChange="handleRadioChange"></MeasurementPage>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@ -121,12 +121,13 @@ const statAnalysisSelect = reactive({
const times = reactive([{ time: '' }]) const times = reactive([{ time: '' }])
const addTime = (index) => { const addTime = (index) => {
times.push({ time: '' }) times.push({ time: '' })
customName.push(index + 2) customName.push(String(index + 2))
} }
const switchTime = (index) => { const switchTime = (index) => {
times.splice(index, 1) times.splice(index, 1)
customName.splice(index, 1) customName.splice(index, 1)
calculate.splice(index, 1) calculate.splice(index, 1)
xData.splice(index, 1)
} }
const timechange = (value) => { const timechange = (value) => {
const count = getTimeIntervals(times[0][0], times[0][1]) const count = getTimeIntervals(times[0][0], times[0][1])
@ -142,20 +143,24 @@ const handleClick = () => {
} }
const iotModelId = ref('') const iotModelId = ref('')
watch( const irn = ref('')
() => statAnalysisSelect.deviceId, const attributesChange = () => {
(newVal) => {
if (newVal) {
const row = statAnalysisSelectOptions.deviceId.filter((item) => { const row = statAnalysisSelectOptions.deviceId.filter((item) => {
return item.value == newVal return item.value == statAnalysisSelect.deviceId
}) })
if (row.length) {
iotModelId.value = row[0].iotModelId iotModelId.value = row[0].iotModelId
showMeasure.value = true
irn.value = statAnalysisSelect.attributeCode || ''
} else {
ElMessage.warning('请选择风机!!')
} }
}, }
{
immediate: true, const deviceIdChange = () => {
} statAnalysisSelect.attributes = ''
) statAnalysisSelect.attributeCode = ''
}
const showMeasure = ref(false) const showMeasure = ref(false)
const selectedAttrRow = ref({ const selectedAttrRow = ref({
@ -337,6 +342,7 @@ const getTimeIntervals = (startTimestamp, endTimestamp) => {
} }
const statAnalysisOperate = () => { const statAnalysisOperate = () => {
option.series = [] option.series = []
option.legend.data = []
chart.value.setOption(option, { notMerge: true }) chart.value.setOption(option, { notMerge: true })
times.forEach((time, index) => { times.forEach((time, index) => {
if (time[0] && time[1]) { if (time[0] && time[1]) {
@ -356,6 +362,7 @@ const statAnalysisOperate = () => {
}) })
} }
const calculate = reactive([{ max: '', min: '', average: '' }]) const calculate = reactive([{ max: '', min: '', average: '' }])
const xDatas = reactive([])
const historyDataReq = (data, index) => { const historyDataReq = (data, index) => {
historyReq(data).then((res) => { historyReq(data).then((res) => {
if (res.code == 200) { if (res.code == 200) {
@ -370,11 +377,13 @@ const historyDataReq = (data, index) => {
min: Math.floor(Math.min(...yData)), min: Math.floor(Math.min(...yData)),
average: Math.floor(yData.reduce((a, b) => a + b, 0) / yData.length), average: Math.floor(yData.reduce((a, b) => a + b, 0) / yData.length),
} }
xDatas.push(xData)
option.tooltip = { option.tooltip = {
show: true, show: true,
formatter: function (params) { formatter: function (params) {
const x = timestampToTime(xData[params.dataIndex]) const index = customName.indexOf(params.seriesName)
return `${params.marker} ${params.seriesName} ${x} : ${params.data}` const x = timestampToTime(xDatas[index][params.dataIndex])
return `${params.marker} ${params.seriesName} <br/> ${x} <b>${params.data}</b>`
}, },
} }
option.xAxis.data = Array.from({ length: xData.length }, (_, index) => index) option.xAxis.data = Array.from({ length: xData.length }, (_, index) => index)
@ -383,10 +392,8 @@ const historyDataReq = (data, index) => {
type: 'line', type: 'line',
data: yData, data: yData,
} }
console.log(seriesData)
option.legend.data.push(customName[index]) option.legend.data.push(customName[index])
option.series.push(seriesData) option.series.push(seriesData)
console.log(option)
chart.value.setOption(option) chart.value.setOption(option)
} else { } else {
ElMessage.warning('查询失败1') ElMessage.warning('查询失败1')

View File

@ -30,10 +30,11 @@
<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">
<span>{{ index + 1 }}</span> <el-input v-model="customName[index]" class="customName"></el-input>
<span>{{ t('statAnalysis.deviceId') }}</span> <span>{{ t('statAnalysis.deviceId') }}</span>
<el-select <el-select
v-model="statAnalysisDeviceId[index]" v-model="statAnalysisDeviceId[index]"
@change="deviceIdChange(index)"
:placeholder="'请选择' + t('statAnalysis.deviceId')" :placeholder="'请选择' + t('statAnalysis.deviceId')"
class="statAnalysisSelect" class="statAnalysisSelect"
> >
@ -45,7 +46,7 @@
<el-input <el-input
class="statAnalysisSelect" class="statAnalysisSelect"
v-model="statAnalysisAttributes[index]" v-model="statAnalysisAttributes[index]"
@click="selectAtteibutes(index, statAnalysisAttributes[index])" @click="selectAtteibutes(index)"
:placeholder="'请选择' + t('statAnalysis.attributes')" :placeholder="'请选择' + t('statAnalysis.attributes')"
></el-input> ></el-input>
</div> </div>
@ -64,15 +65,15 @@
<div class="icon"> <div class="icon">
<el-button v-show="index !== 0" type="danger" size="small" :icon="Delete" @click="switchDevice(index)" circle></el-button> <el-button v-show="index !== 0" type="danger" size="small" :icon="Delete" @click="switchDevice(index)" circle></el-button>
</div> </div>
<div class="selectPart" v-if="calculate[index] && calculate[index]['max']"> <div class="selectPart" v-if="calculate[index] && calculate[index]['max'] != ''">
<span>{{ t('statAnalysis.max') }}</span> <span>{{ t('statAnalysis.max') }}</span>
<span class="max">{{ calculate[index]['max'] }}</span> <span class="max">{{ calculate[index]['max'] }}</span>
</div> </div>
<div class="selectPart" v-if="calculate[index] && calculate[index]['min']"> <div class="selectPart" v-if="calculate[index] && calculate[index]['min'] != ''">
<span>{{ t('statAnalysis.min') }}</span> <span>{{ t('statAnalysis.min') }}</span>
<span class="min">{{ calculate[index]['min'] }}</span> <span class="min">{{ calculate[index]['min'] }}</span>
</div> </div>
<div class="selectPart" v-if="calculate[index] && calculate[index]['average']"> <div class="selectPart" v-if="calculate[index] && calculate[index]['average'] != ''">
<span>{{ t('statAnalysis.average') }}</span> <span>{{ t('statAnalysis.average') }}</span>
<span class="average">{{ calculate[index]['average'] }}</span> <span class="average">{{ calculate[index]['average'] }}</span>
</div> </div>
@ -91,7 +92,7 @@
</div> </div>
</template> </template>
<div class="measureSlot"> <div class="measureSlot">
<MeasurementPage :show="showMeasure" :iotModelId="iotModelId" @handleRadioChange="handleRadioChange"></MeasurementPage> <MeasurementPage :show="showMeasure" :iotModelId="iotModelId" :irn="irn" @handleRadioChange="handleRadioChange"></MeasurementPage>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@ -131,13 +132,13 @@ const selectediotModelId = ref('')
const addDevice = (index) => { const addDevice = (index) => {
statAnalysisDeviceId.push('') statAnalysisDeviceId.push('')
statAnalysisAttributes.push('') statAnalysisAttributes.push('')
customName.value.push(index + 2) customName.push(String(index + 2))
} }
const switchDevice = (index) => { const switchDevice = (index) => {
statAnalysisDeviceId.splice(index, 1) statAnalysisDeviceId.splice(index, 1)
statAnalysisAttributes.splice(index, 1) statAnalysisAttributes.splice(index, 1)
statAnalysisAttributeCode.splice(index, 1) statAnalysisAttributeCode.splice(index, 1)
customName.value.splice(index, 1) customName.splice(index, 1)
calculate.splice(index, 1) calculate.splice(index, 1)
} }
@ -147,15 +148,23 @@ const handleClick = () => {
} }
const iotModelId = ref('') const iotModelId = ref('')
const irn = ref('') const irn = ref('')
const selectAtteibutes = (index, data = '') => { const selectAtteibutes = (index) => {
console.log('🚀 ~ selectAtteibutes ~ data:', data)
showMeasure.value = true
openModelIndex.value = index
const row = statAnalysisSelectOptions.deviceId.filter((item) => { const row = statAnalysisSelectOptions.deviceId.filter((item) => {
return item.value == statAnalysisDeviceId[index] return item.value == statAnalysisDeviceId[index]
}) })
if (row.length) {
iotModelId.value = row[0].iotModelId iotModelId.value = row[0].iotModelId
irn.value = data irn.value = statAnalysisAttributeCode[index] || ''
showMeasure.value = true
openModelIndex.value = index
} else {
ElMessage.warning('请选择风机!!')
}
}
const deviceIdChange = (index) => {
statAnalysisAttributeCode[index] = ''
statAnalysisAttributes[index] = ''
} }
const showMeasure = ref(false) const showMeasure = ref(false)
@ -171,7 +180,6 @@ const handleRadioChange = (value) => {
const selectstatAnalysisAttributes = () => { const selectstatAnalysisAttributes = () => {
statAnalysisAttributes[openModelIndex.value] = selectedAttrRow.attributeName statAnalysisAttributes[openModelIndex.value] = selectedAttrRow.attributeName
statAnalysisAttributeCode[openModelIndex.value] = selectedAttrRow.attributeCode statAnalysisAttributeCode[openModelIndex.value] = selectedAttrRow.attributeCode
console.log(statAnalysisAttributeCode)
showMeasure.value = false showMeasure.value = false
} }
@ -200,7 +208,7 @@ const option = {
}, },
} }
const customName = ref(['1']) const customName = reactive(['1'])
const chart = ref(null) const chart = ref(null)
onMounted(() => { onMounted(() => {
if (chartContainer.value) { if (chartContainer.value) {
@ -234,42 +242,71 @@ const selectstatAnalysis = () => {}
const shortcuts = [ const shortcuts = [
{ {
text: '昨日', text: '今天',
value: () => { value: () => {
const start = getFormattedDate(0) + ' 00:00:00'
const end = new Date() const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start, end] return [start, end]
}, },
}, },
{ {
text: '前三天', text: '天',
value: () => { value: () => {
const end = new Date() const start = getFormattedDate(-1) + ' 00:00:00'
const start = new Date() const end = getFormattedDate(-1) + ' 23:59:59'
start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
return [start, end] return [start, end]
}, },
}, },
{ {
text: '前天', text: '前3天',
value: () => { value: () => {
const end = new Date() const start = getFormattedDate(-3) + ' 00:00:00'
const start = new Date() const end = getFormattedDate(-1) + ' 23:59:59'
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start, end] return [start, end]
}, },
}, },
{ {
text: '上个月', text: '本周',
value: () => { value: () => {
const end = new Date() return getDateRange('week')
const start = new Date() },
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) },
return [start, end] {
text: '本月',
value: () => {
return getDateRange('month')
}, },
}, },
] ]
const getFormattedDate = (offset) => {
const date = new Date()
date.setDate(date.getDate() + offset)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
const getDateRange = (type: 'week' | 'month') => {
const today = new Date()
if (type === 'week') {
const dayOfWeek = today.getDay()
const startOfWeek = new Date(today)
startOfWeek.setDate(today.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1))
startOfWeek.setHours(0, 0, 0, 0)
const endOfWeek = new Date(startOfWeek)
endOfWeek.setDate(startOfWeek.getDate() + 6)
endOfWeek.setHours(23, 59, 59, 999)
return [startOfWeek, endOfWeek]
}
if (type === 'month') {
const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1)
startOfMonth.setHours(0, 0, 0, 0)
const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0)
endOfMonth.setHours(23, 59, 59, 999)
return [startOfMonth, endOfMonth]
}
}
const statAnalysisOperate = () => { const statAnalysisOperate = () => {
option.series = [] option.series = []
@ -284,7 +321,6 @@ const statAnalysisOperate = () => {
} }
return deviceId return deviceId
}, []) }, [])
console.log(devices)
const requestData = { const requestData = {
devices: devices, devices: devices,
interval: statAnalysisInterval.value, interval: statAnalysisInterval.value,
@ -297,30 +333,48 @@ const calculate = reactive([{ max: '', min: '', average: '' }])
const historyDataReq = (data, devices) => { const historyDataReq = (data, devices) => {
historyReq(data).then((res) => { historyReq(data).then((res) => {
if (res.code == 200) { if (res.code == 200) {
devices.forEach((item) => { const resData = res.data
const deviceId = item.deviceId const deviceIdKeys = Object.keys(resData)
item.attributes.forEach((attribute) => { const attributeKeys = []
if (res.data && res.data[deviceId] && res.data[deviceId][attribute]) { if (deviceIdKeys.length) {
const resData = res.data[deviceId][attribute] deviceIdKeys.forEach((item) => {
const xData = resData['times'] const indexList1 = findAllOccurrences(statAnalysisDeviceId, item)
const yData = resData['values'] Object.keys(resData[item]).forEach((value) => {
const indexList2 = findAllOccurrences(statAnalysisAttributeCode, value)
const dataIndex = getCommonElements(indexList1, indexList2)[0]
const historyData = resData[item][value]
const xData = historyData['times']
const yData = historyData['values']
const seriesData = { const seriesData = {
name: attribute, name: customName[dataIndex],
type: 'line', type: 'line',
data: yData, data: yData,
} }
calculate[dataIndex] = {
max: Math.floor(Math.max(...yData)),
min: Math.floor(Math.min(...yData)),
average: Math.floor(yData.reduce((a, b) => a + b, 0) / yData.length),
}
option.legend.data.push(customName[dataIndex])
option.xAxis.data = xData.map((item) => timestampToTime(item)) option.xAxis.data = xData.map((item) => timestampToTime(item))
option.series.push(seriesData) option.series.push(seriesData)
chart.value.setOption(option) chart.value.setOption(option)
})
})
} }
})
})
} else { } else {
ElMessage.warning('查询失败') ElMessage.warning('查询失败')
} }
}) })
} }
const findAllOccurrences = (arr, target) => {
return arr.map((value, index) => (value === target ? index : -1)).filter((index) => index !== -1)
}
const getCommonElements = (arr1, arr2) => {
return arr1.filter((item) => arr2.some((x) => x === item))
}
const statAnalysisExport = () => {} const statAnalysisExport = () => {}
const statAnalysiImport = () => {} const statAnalysiImport = () => {}
@ -359,6 +413,10 @@ const timestampToTime = (timestamp) => {
span { span {
margin-right: 10px; margin-right: 10px;
} }
.customName {
width: 80px;
margin-right: 10px;
}
.statAnalysisSelect { .statAnalysisSelect {
width: 200px; width: 200px;
:deep(.el-select__wrapper) { :deep(.el-select__wrapper) {