map/ui/dasadmin/src/views/backend/equipment/airBlower/realDataChart.vue
高云鹏 b533146d3c 物模型:添加敏感字段confidential
实时数据:测点选择修改为搜索框,添加子系统选择框
2024-12-17 10:30:19 +08:00

556 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="realDataChart">
<el-row>
<el-col :span="8" class="leftPart">
<div class="leftHeader">
<el-button type="primary" @click="addPoint">添加测点</el-button>
<span>显示区间</span>
<el-select v-model="showTimeInterval">
<el-option label="5分钟" :value="300"></el-option>
<el-option label="10分钟" :value="600"></el-option>
<el-option label="15分钟" :value="900"></el-option>
</el-select>
</div>
<div class="leftMain">
<el-scrollbar>
<el-checkbox-group v-model="selectList" @change="changeCheck" :max="selectPointNum">
<el-checkbox
v-for="item in realDataList"
:key="item.prop"
:label="item.name"
:value="item.prop"
class="checkboxStyle"
></el-checkbox>
</el-checkbox-group>
</el-scrollbar>
</div>
</el-col>
<el-col :span="16" class="rightPart">
<div class="chartPart">
<div class="chartRef" ref="chartRef"></div>
</div>
</el-col>
</el-row>
</div>
<el-dialog v-model="selectPointVisible" title="选择测点" width="1000">
<SelectPoint ref="selectPointRef" :visible="selectPointVisible" :default-attr="selectPointAttr"></SelectPoint>
<template #footer>
<div class="selectPointDialogFooter">
<el-button type="primary" @click="saveSelectPoint">保存</el-button>
<el-button @click="selectPointVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
import SelectPoint from '/@/views/backend/equipment/airBlower/selectPoint.vue'
import { getRealValueListReq } from '/@/api/backend/deviceModel/request'
import { dayjs, ElMessage } from 'element-plus'
import { getCutDecimalsValue } from './utils'
const emits = defineEmits(['clearChart'])
const props = withDefaults(defineProps<{ id: string; visible: boolean }>(), {
id: '',
visible: false,
})
const showTimeInterval = ref(300)
//#region
const defaultList = [
{
prop: 'iturbineoperationmode',
name: '运行模式',
unit: '',
},
{
prop: 'iwindspeed',
name: '风速',
unit: '(m/s)',
},
{
prop: 'iwinddirection',
name: '风向',
unit: '(°)',
},
{
prop: 'igenspeed',
name: '发电机转速',
unit: '(rpm)',
},
{
prop: 'igenpower',
name: '有功功率',
unit: '(kW)',
},
{
prop: 'iactivepowersetpointvalue',
name: '有功给定',
unit: '(kW)',
},
{
prop: 'ireactivepower',
name: '无功功率',
unit: '(kVar)',
},
{
prop: 'ireactivepowersetpointvalue',
name: '无功给定',
unit: '(kVar)',
},
{
prop: 'ipitchangle1',
name: '桨叶1角度',
unit: '(°)',
},
{
prop: 'ipitchangle2',
name: '桨叶2角度',
unit: '(°)',
},
{
prop: 'ipitchangle3',
name: '桨叶3角度',
unit: '(°)',
},
]
//#endregion
const selectList = ref([])
const changeCheck = () => {
if (!timer && selectList.value[0]) {
createTimer()
}
if (selectList.value.length === 0) {
clearTimer()
chartInstance && chartInstance.clear()
}
}
const realDataList = ref<any[]>(JSON.parse(JSON.stringify(defaultList)))
const chartRef = ref()
let chartInstance: any = null
const getRealData = () => {
const params = selectList.value.map((item: string) => item.toLowerCase())
const time = dayjs().format('YYYY-MM-DD HH:mm:ss')
getRealValueListReq([
{
deviceId: props.id,
attributes: params,
},
]).then((res) => {
if (res.code === 200) {
createChartData(res.data[props.id], time)
}
})
return []
}
const selectPointNum = ref(10)
let realDataXAxis: any = []
let realDataSeries: any = []
let realDataYAxis: any = []
const getRandomDarkColor = () => {
let r = Math.floor(Math.random() * 200) // 限制在0到127之间以生成较深的颜色
let g = Math.floor(Math.random() * 200)
let b = Math.floor(Math.random() * 200)
let color = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
return color
}
const createChartData = (data: { [k: string]: number }, time: string) => {
if (realDataXAxis.length > showTimeInterval.value) {
realDataXAxis.shift()
realDataSeries.forEach((item: any) => {
item.data.shift()
})
}
const attrCode = Object.keys(data)
realDataXAxis.push(time)
const lastSeriesId = realDataSeries.map((item: any) => item.id)
const color = getRandomDarkColor()
let clearState = null
lastSeriesId.forEach((item: any) => {
if (!attrCode.includes(item)) {
const cur = realDataSeries.findIndex((val: any) => val.id === item)
// delete cur.id
realDataSeries.splice(cur, 1)
clearState = true
}
})
if (clearState) {
chartInstance.setOption(
{
series: realDataSeries,
},
{
replaceMerge: ['series'],
}
)
}
const seriesData = attrCode.map((item) => {
const curVal = getCutDecimalsValue(data[item], 2)
if (lastSeriesId.includes(item)) {
const cur = realDataSeries.find((val: any) => val.id === item)
cur.data.push(curVal)
return cur
} else {
const info = realDataList.value.find((val) => val.prop === item)
const list = realDataSeries?.[0]?.data ?? []
const len = list.length
const fillData = new Array(len).fill('')
fillData.push(curVal)
return {
id: item,
name: info.name +' '+ (info?.unit ?? ''),
type: 'line',
barWidth: 20,
itemStyle: {
color: color,
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: fillData,
}
}
})
realDataSeries = seriesData
createChart()
}
const createChart = () => {
const chart = chartInstance ?? echarts.init(chartRef.value)
let option = null
if (chartInstance && realDataXAxis.length > 1) {
const nameMap: any = {}
realDataSeries.forEach((item: any) => {
const yAxisName = item.name.split(' ')[1]
if (nameMap[yAxisName] || nameMap[yAxisName]===0) {
item.yAxisIndex = nameMap[yAxisName]
} else {
const len = Object.keys(nameMap).length
item.yAxisIndex = len
nameMap[yAxisName] = len
}
})
const nameMapKeys = Object.keys(nameMap)
if (realDataSeries.length >= 4 && nameMapKeys.length === 4) {
selectPointNum.value = realDataSeries.length
}
const yAxisData = nameMapKeys.map((item, index) => {
const offset = Math.floor(index / 2) * 50
const position = index % 2 == 0 ? 'left' : 'right'
const yAxisName = item
const cacheYAxis = realDataYAxis.find((item: any) => item.name === yAxisName)
if (cacheYAxis) {
return {
...cacheYAxis,
offset,
position,
}
} else {
return {
type: 'value',
name: item,
nameTextStyle: {
color: '#4E5969',
},
axisLine: {
show: false,
onZero: false,
lineStyle: {
color: '#dadada',
width: 0,
type: 'solid',
},
},
axisLabel: {
//x轴文字的配置
show: true,
color: '#4E5969',
},
axisTick: { show: false },
splitLine: {
interval: 50,
lineStyle: {
type: 'dashed',
color: '#dadada',
},
},
offset,
position,
}
}
})
realDataYAxis = yAxisData
option = {
xAxis: {
data: realDataXAxis,
},
yAxis: realDataYAxis,
series: realDataSeries,
}
} else {
option = {
grid: {
top: 50,
right: 60,
bottom: 50,
left: 60,
containLabel: true,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
xAxis: {
type: 'category',
axisLine: {
show: true,
lineStyle: {
color: '#dadada',
width: 1,
type: 'solid',
},
},
axisLabel: {
//x轴文字的配置
show: true,
color: '#4E5969',
interval: 'auto',
formatter: function (value: any) {
return value.slice(11)
},
//rotate: 45
},
splitLine: {
//分割线配置
show: false,
lineStyle: {
color: '#999999',
},
},
data: realDataXAxis,
},
yAxis: [
{
type: 'value',
name: '',
nameTextStyle: {
color: '#4E5969',
},
axisLine: {
show: false,
onZero: false,
lineStyle: {
color: '#dadada',
width: 0,
type: 'solid',
},
},
axisLabel: {
//x轴文字的配置
show: true,
color: '#4E5969',
},
axisTick: { show: false },
splitLine: {
interval: 50,
lineStyle: {
type: 'dashed',
color: '#dadada',
},
},
},
],
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
legend: {
data: [],
textStyle: {
color: '#73767a',
},
},
series: realDataSeries,
}
}
chart.setOption(option, { replaceMerge: ['series', 'yAxis'] })
chartInstance = chart
}
const selectPointRef = ref()
const selectPointVisible = ref(false)
const selectPointAttr = computed(() => {
return realDataList.value.map((item) => {
return {
attributeName: item.name,
attributeCode: item.prop,
}
})
})
const addPoint = () => {
selectPointVisible.value = true
}
const checkShowChart = (data: any) => {
console.log(realDataSeries)
const curCode = data.map((item: any) => item.prop)
console.log(curCode, 'curCode')
for (let i = selectList.value.length - 1; i >= 0; i--) {
if (!curCode.includes(selectList.value[i])) {
selectList.value.splice(i, 1)
realDataSeries.splice(i, 1)
changeCheck()
}
}
}
const saveSelectPoint = () => {
const data = selectPointRef.value?.getSelectList()
if (data) {
const selectList = data.map((item: any) => {
return {
prop: item.attributeCode,
name: item.attributeName,
unit: item.unit,
}
})
checkShowChart(selectList)
realDataList.value = selectList
selectPointVisible.value = false
ElMessage.success('修改成功')
}
}
let timer: any = null
const createTimer = () => {
timer = setInterval(() => {
getRealData()
}, 1000)
}
const clearTimer = () => {
timer && clearInterval(timer)
timer = null
realDataSeries = []
realDataXAxis = []
realDataYAxis = []
pauseState.value = false
emits('clearChart')
}
const pauseState = ref(false)
const saveChart = () => {
timer && clearInterval(timer)
pauseState.value = true
return {
time: realDataXAxis,
chartData: realDataSeries,
}
}
const continueChart = () => {
pauseState.value = false
const fillVal = new Array(5).fill('')
realDataXAxis.push(...fillVal)
realDataSeries.forEach((item: any) => {
item.data.push(...fillVal)
})
createTimer()
}
defineExpose({
saveChart,
continueChart,
})
onMounted(() => {
if (selectList.value.length > 0) {
createTimer()
}
})
onUnmounted(() => {
clearTimer()
chartInstance && chartInstance.dispose()
selectList.value = []
})
watch(
() => props.visible,
(v) => {
if (!v) {
clearTimer()
chartInstance && chartInstance.clear()
selectList.value = []
}
}
)
</script>
<style scoped lang="scss">
.realDataChart {
width: 100%;
height: 100%;
.leftPart {
width: 100%;
height: 100%;
border-right: 1px solid #edf2fa;
.leftHeader {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
span {
margin-left: auto;
}
.el-select {
width: 100px;
}
:deep(.el-select__wrapper) {
width: 100px;
}
}
.leftMain {
width: 100%;
height: 400px;
.checkboxStyle {
display: flex;
width: 100%;
height: 40px;
}
}
}
.rightPart {
width: 100%;
height: 100%;
min-height: 452px;
.chartPart {
width: 100%;
height: 100%;
min-height: 452px;
.chartRef {
width: 100%;
height: 100%;
min-height: 452px;
}
}
}
}
.selectPointDialogFooter {
text-align: center;
.el-button {
width: 120px;
height: 40px;
}
}
</style>