map/ui/dasadmin/src/views/backend/equipment/airBlower/realDataChart.vue

475 lines
13 KiB
Vue
Raw Normal View History

<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">
<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 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 = () => {
console.log('-----------------------------------',timer,selectList.value);
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 []
}
let realDataXAxis: any = []
let realDataSeries: 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.find((val: any) => val.id === item)
delete cur.id
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) {
option = {
xAxis: {
data: realDataXAxis,
},
series: realDataSeries,
}
} else {
option = {
grid: {
top: 50,
right: 23,
bottom: 50,
left: 18,
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,
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' })
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 saveSelectPoint = () => {
const data = selectPointRef.value?.getSelectList()
if (data) {
const selectList = data.map((item: any) => {
return {
prop: item.attributeCode,
name: item.attributeName,
unit: item.unit,
}
})
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 = []
pauseState.value = false
}
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>