1735 lines
59 KiB
Vue
1735 lines
59 KiB
Vue
<template>
|
||
<el-dialog v-model="visible" :title="subSystemName" width="1020" :before-close="handleClose" :show-close="false">
|
||
<div class="radioItem">
|
||
<el-radio-group v-model="dialogradioactiveName">
|
||
<el-radio :value="138">模拟量</el-radio>
|
||
<el-radio :value="140">状态量</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
<div class="dialogContent">
|
||
<div class="PitchPart">
|
||
<el-row :gutter="20">
|
||
<div class="Pitchitem" v-for="item in subSystemDataList" :key="item.name">
|
||
<span class="PitchitemLeft">{{ item.name }}</span>
|
||
<span class="PitchitemRight">{{ item.value }}</span>
|
||
</div>
|
||
</el-row>
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button type="primary">导出</el-button>
|
||
<el-button @click="visible = false">取消</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<div class="windBlower" ref="windBlower">
|
||
<el-row :gutter="10">
|
||
<el-col :md="24" :lg="6" :span="6">
|
||
<div class="cardContentLeft">
|
||
<!--实时预览-->
|
||
<div class="overview">
|
||
<div class="cardLabel">实时预览</div>
|
||
<div class="overviewDataSection" ref="listContainer">
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">网侧A相电压:</span>
|
||
<span class="reafRight">{{ overviewData.iul1_690v }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">网侧B相电压:</span>
|
||
<span class="reafRight">{{ overviewData.iul2_690v }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">网侧C相电压:</span>
|
||
<span class="reafRight">{{ overviewData.iul3_690v }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">有功功率:</span>
|
||
<span class="reafRight">{{ overviewData.igenpower }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">无功功率:</span>
|
||
<span class="reafRight">{{ overviewData.ireactivepower }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">功率因素:</span>
|
||
<span class="reafRight">{{ overviewData.icosphi }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">主轴承温度A:</span>
|
||
<span class="reafRight">{{ overviewData.itemprotorbeara_1sec }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">主轴承温度B:</span>
|
||
<span class="reafRight">{{ overviewData.itemprotorbeara_1sec }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">总扭缆角度:</span>
|
||
<span class="reafRight">{{ overviewData.icabletwisttotal }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">发动机驱动侧轴承温度:</span>
|
||
<span class="reafRight">{{ overviewData.itempgenbearde_1sec }}</span>
|
||
</div>
|
||
<div class="overviewDataSectionItem">
|
||
<span class="realLeft">发动机非驱动侧轴承温度:</span>
|
||
<span class="reafRight">{{ overviewData.itempgenbearnde_1sec }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="overviewDataBtn">
|
||
<el-icon color="#0064AA" @click="() => (overviewSlotData.visible = true)"><DArrowRight /></el-icon>
|
||
</div>
|
||
</div>
|
||
|
||
<!--功率趋势-->
|
||
<div class="power">
|
||
<div class="cardLabel">功率趋势</div>
|
||
<div class="chartBox">
|
||
<div class="power-chart" ref="powerChartRef"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
|
||
<el-col :md="24" :lg="12" :span="12">
|
||
<div class="cardContentCenter">
|
||
<!--风机控制-->
|
||
<div class="controlBackgroundImg">
|
||
<div class="control-type">
|
||
<el-tag v-if="realTimeData.locked === 1" class="control-tag control-tag-left" type="primary">已锁定</el-tag>
|
||
<el-tag class="control-tag" type="primary">{{ realTimeDataState }}</el-tag>
|
||
</div>
|
||
<div class="btnLeft">
|
||
<el-button
|
||
@click="sendCommand('setTurbineFastStart')"
|
||
v-if="realTimeData.iturbineoperationmode !== 16"
|
||
class="control-btn"
|
||
type="primary"
|
||
>启动</el-button
|
||
>
|
||
<el-button @click="sendCommand('setTurbineStop')" v-else class="control-btn" type="primary">停机</el-button>
|
||
<el-button @click="sendCommand('setTurbineResetStatusCode')" class="control-btn" type="primary">复位</el-button>
|
||
<el-button @click="sendManualCommand(1)" v-if="realTimeData.locked !== 1" class="control-btn" type="primary"
|
||
>锁定</el-button
|
||
>
|
||
<el-button @click="sendManualCommand(0)" v-else class="control-btn" type="primary">解锁</el-button>
|
||
</div>
|
||
<el-tooltip content="变桨/轮毂系统">
|
||
<div @click="openSubSystem(1)" class="dot index-1"></div>
|
||
</el-tooltip>
|
||
<el-tooltip content="轴承/传动链/齿轮箱系统">
|
||
<div @click="openSubSystem(2)" class="dot index-2"></div>
|
||
</el-tooltip>
|
||
<el-tooltip content="发电机系统">
|
||
<div @click="openSubSystem(3)" class="dot index-3"></div>
|
||
</el-tooltip>
|
||
<el-tooltip content="机舱系统">
|
||
<div @click="openSubSystem(4)" class="dot index-4"></div>
|
||
</el-tooltip>
|
||
<el-tooltip content="控制系统">
|
||
<div @click="openSubSystem(5)" class="dot index-5"></div>
|
||
</el-tooltip>
|
||
<el-tooltip content="环境/气象系统">
|
||
<div @click="openSubSystem(6)" class="dot index-6"></div>
|
||
</el-tooltip>
|
||
</div>
|
||
<div class="Parameters">
|
||
<div class="Parameters-item">
|
||
<img src="~assets/WindBlower/power.png" />
|
||
<p class="Parameters-font">{{ realTimeDataForSingle.igenpower }}</p>
|
||
<p>有功功率(MW)</p>
|
||
</div>
|
||
<div class="Parameters-item">
|
||
<img src="~assets/WindBlower/generator.png" />
|
||
<p class="Parameters-font">{{ realTimeDataForSingle.igenspeed }}</p>
|
||
<p>发电机转速(RPM)</p>
|
||
</div>
|
||
<div class="Parameters-item">
|
||
<img src="~assets/WindBlower/pitch.png" />
|
||
<p class="Parameters-font">{{ realTimeDataForSingle.ipitchangle }}</p>
|
||
<p>变桨角度(°)</p>
|
||
</div>
|
||
<div class="Parameters-item">
|
||
<img src="~assets/WindBlower/speed.png" />
|
||
<p class="Parameters-font">{{ realTimeDataForSingle.iwindspeed }}</p>
|
||
<p>风速(m/s)</p>
|
||
</div>
|
||
<div class="Parameters-item">
|
||
<img src="~assets/WindBlower/direction.png" />
|
||
<p class="Parameters-font">{{ realTimeDataForSingle.iwinddirection }}</p>
|
||
<p>风向(°)</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="chartPart">
|
||
<div class="chartPart-item">
|
||
<div class="chartParm" ref="temperatureChartRef1"></div>
|
||
</div>
|
||
<div class="chartPart-item">
|
||
<div class="chartParm" ref="temperatureChartRef2"></div>
|
||
</div>
|
||
<div class="chartPart-item">
|
||
<div class="chartParm" ref="temperatureChartRef3"></div>
|
||
</div>
|
||
<div class="chartPart-item item_bar">
|
||
<div class="frequencyChart" ref="frequencyChartRef"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :md="24" :lg="6" :span="6" style="background: #f5f5f5">
|
||
<div class="cardContentRight">
|
||
<!--发电量概况-->
|
||
<div class="summarize">
|
||
<div class="cardLabel">发电量概况</div>
|
||
<div class="summarize-panel-list">
|
||
<div class="summarize-panel">
|
||
<div class="summarize-panel-pic">
|
||
<img src="~assets/dashboard/fdl1.png" alt="" />
|
||
</div>
|
||
<div class="summarize-panel-base">
|
||
<div>
|
||
<span class="content-number">{{ realTimeDataForSingle.ikwhthisday }}</span>
|
||
</div>
|
||
<div>kWh</div>
|
||
<div>日发电量</div>
|
||
</div>
|
||
</div>
|
||
<div class="summarize-panel">
|
||
<div class="summarize-panel-pic">
|
||
<img src="~assets/dashboard/fdl2.png" alt="" />
|
||
</div>
|
||
<div class="summarize-panel-base">
|
||
<div>
|
||
<span class="content-number">{{ realTimeDataForSingle.monthprodenergy }}</span>
|
||
</div>
|
||
<div>万kWh</div>
|
||
<div>月发电量</div>
|
||
</div>
|
||
</div>
|
||
<div class="summarize-panel">
|
||
<div class="summarize-panel-pic">
|
||
<img src="~assets/dashboard/fdl3.png" alt="" />
|
||
</div>
|
||
<div class="summarize-panel-base">
|
||
<div>
|
||
<span class="content-number">{{ realTimeDataForSingle.yearprodenergy }}</span>
|
||
</div>
|
||
<div>万kWh</div>
|
||
<div>年发电量</div>
|
||
</div>
|
||
</div>
|
||
<div class="summarize-panel">
|
||
<div class="summarize-panel-pic">
|
||
<img src="~assets/dashboard/fdl4.png" alt="" />
|
||
</div>
|
||
<div class="summarize-panel-base">
|
||
<div>
|
||
<span class="content-number">{{ realTimeDataForSingle.ikwhoverall }}</span>
|
||
</div>
|
||
<div>万kWh</div>
|
||
<div>总发电量</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!--发电量趋势-->
|
||
<div class="trend">
|
||
<div class="cardLabel">发电量趋势</div>
|
||
<el-radio-group class="trendTabs" v-model="trendChartType" @change="tabhandleClick">
|
||
<el-radio-button label="日" value="day" />
|
||
<el-radio-button label="月" value="month" />
|
||
</el-radio-group>
|
||
<div class="trend-chart" ref="trendChartRef"></div>
|
||
</div>
|
||
|
||
<!--实时告警-->
|
||
<div class="alarm" style="margin-bottom: 0">
|
||
<div class="cardLabel">实时告警</div>
|
||
<el-table
|
||
:data="tableData"
|
||
class="tablePart"
|
||
height="calc(100% - 38px)"
|
||
ref="myTable"
|
||
@mouseover.native="clearScroll"
|
||
@mouseleave.native="createScroll"
|
||
>
|
||
<el-table-column fixed prop="time" label="时间" />
|
||
<el-table-column prop="alertcontent" label="告警信息" />
|
||
</el-table>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
<el-dialog v-model="overviewSlotData.visible" title="实时预览">
|
||
<template #header>
|
||
<div class="overviewSlot">
|
||
<span style="font-size: 20px">实时预览</span>
|
||
<div class="radioForOverviewType">
|
||
<el-radio-group v-model="overviewSlotData.type">
|
||
<el-radio value="138">模拟量</el-radio>
|
||
<el-radio value="140">状态量</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<Overview v-bind="overviewSlotData"></Overview>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { nextTick, onActivated, onMounted, reactive, ref, computed, onBeforeMount, onUnmounted, VNode, VNodeRef } from 'vue'
|
||
import * as echarts from 'echarts'
|
||
import { useEventListener } from '@vueuse/core'
|
||
import { useI18n } from 'vue-i18n'
|
||
import { DArrowRight } from '@element-plus/icons-vue'
|
||
import { getRealValueListReq, getRealValueRangeReq } from '/@/api/backend/deviceModel/request'
|
||
import { getModelAttributeListReq } from '/@/api/backend/deviceModel/request'
|
||
import { useRoute } from 'vue-router'
|
||
import Overview from './overview.vue'
|
||
import { TableInstance } from 'element-plus'
|
||
import { dayjs, ElMessage, ElMessageBox } from 'element-plus'
|
||
import { getRealTimeState, getCutDecimalsValue } from '/@/views/backend/equipment/airBlower/utils'
|
||
import { sendCommandReq, sendManualCommandReq } from '/@/api/backend/control/request'
|
||
import { getAlarmListReq } from '/@/api/backend/alarms/request'
|
||
import { useEnumStore } from '/@/stores/enums'
|
||
const enumStore = useEnumStore()
|
||
|
||
const route = useRoute()
|
||
|
||
const { t } = useI18n()
|
||
|
||
const windBlower = ref()
|
||
const computedHeight = reactive({
|
||
powerHeight: '305px',
|
||
centerHeight: '1100px',
|
||
alarmHeight: '360px',
|
||
})
|
||
const sizeChange = () => {
|
||
const rect = windBlower.value?.getBoundingClientRect()
|
||
if (!rect) return
|
||
computedHeight.powerHeight = rect.height - 626 + 'px'
|
||
computedHeight.alarmHeight = rect.height - 570 + 'px'
|
||
computedHeight.centerHeight = rect.height - 20 + 'px'
|
||
}
|
||
|
||
let timer: any = null
|
||
let myTable = ref<TableInstance>()
|
||
|
||
const overviewData = reactive({
|
||
iul1_690v: '-',
|
||
iul2_690v: '-',
|
||
iul3_690v: '-',
|
||
igenpower: '-',
|
||
ireactivepower: '-',
|
||
icosphi: '-',
|
||
itemprotorbeara_1sec: '-',
|
||
itemprotorbearb_1sec: '-',
|
||
icabletwisttotal: '-',
|
||
itempgenbearde_1sec: '-',
|
||
itempgenbearnde_1sec: '-',
|
||
})
|
||
|
||
const realTimeDataForSingle = ref<any>({
|
||
ikwhthisday: '-',
|
||
ikwhoverall: '-',
|
||
igenpower: '-',
|
||
igenspeed: '-',
|
||
ipitchangle: '',
|
||
iwindspeed: '-',
|
||
iwinddirection: '-',
|
||
monthprodenergy: '-',
|
||
yearprodenergy: '-',
|
||
})
|
||
|
||
const state: {
|
||
charts: { powerChart: any; temperatureChart1: any; temperatureChart2: any; temperatureChart3: any; frequencyChart: any; trendChart: any }
|
||
remark: string
|
||
workingTimeFormat: string
|
||
pauseWork: boolean
|
||
} = reactive({
|
||
charts: { powerChart: null, temperatureChart1: null, temperatureChart2: null, temperatureChart3: null, frequencyChart: null, trendChart: null },
|
||
remark: 'dashboard.Loading',
|
||
workingTimeFormat: '',
|
||
pauseWork: false,
|
||
})
|
||
|
||
const powerChartRef = ref<VNodeRef>()
|
||
const powerChartData: { time: any; values: any } = {
|
||
time: {},
|
||
values: {},
|
||
}
|
||
const initpowerChart = () => {
|
||
const powerChart = state.charts.powerChart ?? echarts.init(powerChartRef.value as unknown as HTMLElement)
|
||
|
||
const option = {
|
||
grid: {
|
||
top: 50,
|
||
right: 23,
|
||
bottom: 10,
|
||
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',
|
||
//rotate: 45
|
||
},
|
||
splitLine: {
|
||
//分割线配置
|
||
show: false,
|
||
lineStyle: {
|
||
color: '#999999',
|
||
},
|
||
},
|
||
data: powerChartData.time.iTheoreticalPower,
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: 'value',
|
||
name: '功率MW',
|
||
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',
|
||
},
|
||
},
|
||
},
|
||
{
|
||
type: 'value',
|
||
name: '风速m/s',
|
||
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',
|
||
},
|
||
},
|
||
},
|
||
],
|
||
legend: {
|
||
data: ['有功功率', '理论有功功率', '风速'],
|
||
textStyle: {
|
||
color: '#73767a',
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: '有功功率',
|
||
type: 'line',
|
||
barWidth: 20,
|
||
itemStyle: {
|
||
color: '#00A7EB',
|
||
barBorderRadius: 2,
|
||
},
|
||
smooth: 0.6,
|
||
symbol: 'none',
|
||
data: powerChartData.values?.iGenPower ?? [],
|
||
},
|
||
{
|
||
name: '理论有功功率',
|
||
type: 'line',
|
||
barWidth: 20,
|
||
itemStyle: {
|
||
color: '#62bd25',
|
||
barBorderRadius: 2,
|
||
},
|
||
smooth: 0.6,
|
||
symbol: 'none',
|
||
data: powerChartData.values?.iTheoreticalPower ?? [],
|
||
},
|
||
{
|
||
name: '风速',
|
||
type: 'line',
|
||
yAxisIndex: 1,
|
||
itemStyle: {
|
||
color: '#FF7E00',
|
||
barBorderRadius: 2,
|
||
},
|
||
smooth: 0.6,
|
||
symbol: 'none',
|
||
/*areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{
|
||
offset: 0,
|
||
color: 'rgba(255,126,0,0.8)'
|
||
}
|
||
])
|
||
},*/
|
||
data: powerChartData.values?.iWindSpeed ?? [],
|
||
},
|
||
],
|
||
}
|
||
powerChart.setOption(option)
|
||
state.charts.powerChart = powerChart
|
||
}
|
||
|
||
const TrendDataForDay: {
|
||
currentPeriod: {
|
||
time: string[]
|
||
value: number[]
|
||
}
|
||
samePeriod: {
|
||
time: string[]
|
||
value: number[]
|
||
}
|
||
} = {
|
||
currentPeriod: {
|
||
time: [],
|
||
value: [],
|
||
},
|
||
samePeriod: {
|
||
time: [],
|
||
value: [],
|
||
},
|
||
}
|
||
|
||
const TrendDataForMonth = [
|
||
{
|
||
currentPeriod: 26.3,
|
||
samePeriod: 53.5,
|
||
generationTime: '2024-10-01',
|
||
},
|
||
{
|
||
currentPeriod: 36.3,
|
||
samePeriod: 53.5,
|
||
generationTime: '2024-10-02',
|
||
},
|
||
{
|
||
currentPeriod: 46.3,
|
||
samePeriod: 53.5,
|
||
generationTime: '2024-10-03',
|
||
},
|
||
]
|
||
const trendChartRef = ref<VNodeRef>()
|
||
|
||
const trendChartType = ref<'day' | 'month'>('day')
|
||
const tabhandleClick = () => {
|
||
state.charts.trendChart.clear()
|
||
nextTick(() => {
|
||
initTrendChart(trendChartType.value)
|
||
})
|
||
}
|
||
|
||
const initTrendChart = (type: 'day' | 'month') => {
|
||
const currentPeriod: number[] = type === 'day' ? TrendDataForDay.currentPeriod.value : TrendDataForMonth.map((item) => item.currentPeriod)
|
||
const samePeriod: number[] = type === 'day' ? TrendDataForDay.samePeriod.value : TrendDataForMonth.map((item) => item.samePeriod)
|
||
const xAxisdata: string[] = type === 'day' ? TrendDataForDay.currentPeriod.time : TrendDataForMonth.map((item) => item.generationTime)
|
||
const trendChart = state.charts?.trendChart ?? echarts.init(trendChartRef.value as unknown as HTMLElement)
|
||
|
||
const option = {
|
||
grid: {
|
||
top: 30,
|
||
right: 10,
|
||
bottom: 20,
|
||
left: 25,
|
||
borderColor: '#dadada',
|
||
},
|
||
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',
|
||
},
|
||
splitLine: {
|
||
//分割线配置
|
||
show: false,
|
||
lineStyle: {
|
||
color: '#999999',
|
||
},
|
||
},
|
||
data: xAxisdata,
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: 'value',
|
||
name: 'kWh',
|
||
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',
|
||
},
|
||
},
|
||
},
|
||
],
|
||
legend: {
|
||
data: ['本期', '同期'],
|
||
textStyle: {
|
||
color: '#73767a',
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
name: '本期',
|
||
data: currentPeriod,
|
||
type: 'bar',
|
||
smooth: true,
|
||
itemStyle: {
|
||
color: '#0277B3',
|
||
},
|
||
},
|
||
{
|
||
name: '同期',
|
||
data: samePeriod,
|
||
type: 'bar',
|
||
smooth: true,
|
||
itemStyle: {
|
||
color: '#00A096',
|
||
},
|
||
},
|
||
],
|
||
}
|
||
trendChart.setOption(option)
|
||
state.charts.trendChart = trendChart
|
||
}
|
||
const temperatureChartsData: { name: string; value: string | number }[] = [
|
||
{
|
||
name: '环境温度(°C)',
|
||
value: 56,
|
||
},
|
||
{
|
||
name: '舱内温度(°C)',
|
||
value: 56,
|
||
},
|
||
{
|
||
name: '环境温度(°C)',
|
||
value: 56,
|
||
},
|
||
]
|
||
const temperatureChartRef1 = ref<VNodeRef>()
|
||
const temperatureChartRef2 = ref<VNodeRef>()
|
||
const temperatureChartRef3 = ref<VNodeRef>()
|
||
const initTemperatureChart = () => {
|
||
const temperatureChart1 = state.charts.temperatureChart1 ?? echarts.init(temperatureChartRef1.value as unknown as HTMLElement)
|
||
const temperatureChart2 = state.charts.temperatureChart2 ?? echarts.init(temperatureChartRef2.value as unknown as HTMLElement)
|
||
const temperatureChart3 = state.charts.temperatureChart3 ?? echarts.init(temperatureChartRef3.value as unknown as HTMLElement)
|
||
const options = []
|
||
for (let i = 0; i < temperatureChartsData.length; i++) {
|
||
const option = {
|
||
grid: {
|
||
top: 30,
|
||
//right: 100,
|
||
bottom: 0,
|
||
left: -100,
|
||
containLabel: true,
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
show: false,
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
show: false,
|
||
},
|
||
series: [
|
||
{
|
||
name: temperatureChartsData[i].name,
|
||
data: [temperatureChartsData[i].value],
|
||
type: 'bar',
|
||
label: {
|
||
show: true,
|
||
align: 'center',
|
||
formatter: `{a|{c}}\n{b|{a}}`,
|
||
rich: {
|
||
a: {
|
||
color: '#333333',
|
||
fontSize: 22,
|
||
},
|
||
b: {
|
||
color: '#4E5969',
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
position: 'insideBottom',
|
||
offset: [62, 0],
|
||
},
|
||
itemStyle: {
|
||
color: '#048bd2',
|
||
borderRadius: [0, 0, 4, 4],
|
||
},
|
||
barWidth: 20,
|
||
},
|
||
{
|
||
show: true,
|
||
type: 'bar',
|
||
barGap: '-100%',
|
||
barWidth: 20, // 统计条宽度
|
||
itemStyle: {
|
||
normal: {
|
||
color: '#048bd2',
|
||
opacity: 0.2,
|
||
borderRadius: 4,
|
||
},
|
||
},
|
||
z: 1,
|
||
data: [100],
|
||
},
|
||
],
|
||
aria: {
|
||
enabled: true,
|
||
decal: {
|
||
show: true,
|
||
decals: {
|
||
symbol: 'rect',
|
||
symbolSize: 3,
|
||
dashArrayX: 3,
|
||
rotation: 45,
|
||
color: 'rgba(0, 0, 0, 0.1)',
|
||
},
|
||
},
|
||
},
|
||
}
|
||
options.push(option)
|
||
}
|
||
temperatureChart1.setOption(options[0])
|
||
state.charts.temperatureChart1 = temperatureChart1
|
||
temperatureChart2.setOption(options[1])
|
||
state.charts.temperatureChart2 = temperatureChart2
|
||
temperatureChart3.setOption(options[2])
|
||
state.charts.temperatureChart3 = temperatureChart3
|
||
}
|
||
|
||
var frequencyData: {
|
||
name: string[]
|
||
value: number[]
|
||
} = {
|
||
name: [
|
||
'0~22.5',
|
||
'22.5~45',
|
||
'45~67.5',
|
||
'67.5~90',
|
||
'90~112.5',
|
||
'112.5~135',
|
||
'135~157.5',
|
||
'157.5~180',
|
||
'180~202.5',
|
||
'202.5~225',
|
||
'225~247.5',
|
||
'247.5~270',
|
||
'270~292.5',
|
||
'292.5~315',
|
||
'315~337.5',
|
||
'337.5~360',
|
||
],
|
||
value: [],
|
||
}
|
||
|
||
const frequencyChartRef = ref()
|
||
const initFrequencyChart = () => {
|
||
const frequencyChart = state.charts.frequencyChart ?? echarts.init(frequencyChartRef.value as unknown as HTMLElement)
|
||
// const seriesdata: any = frequencyData.map((item) => item.value)
|
||
|
||
const option = {
|
||
title: [
|
||
{
|
||
text: '风频图',
|
||
textStyle: {
|
||
color: '#4E5969',
|
||
fontSize: 14,
|
||
fontFamily: 'PingFangSC-Semibold',
|
||
},
|
||
padding: 15,
|
||
},
|
||
],
|
||
polar: {
|
||
radius: [0, '70%'],
|
||
},
|
||
radiusAxis: {
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#dadada',
|
||
},
|
||
},
|
||
axisLabel: {
|
||
show: true,
|
||
color: 'rgba(0,0,0,0.45)',
|
||
fontSize: 10,
|
||
},
|
||
axisTick: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#dadada',
|
||
},
|
||
},
|
||
max: 100,
|
||
},
|
||
angleAxis: {
|
||
min: 0,
|
||
interval: 22.5,
|
||
startAngle: 90,
|
||
type: 'category',
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#dadada',
|
||
},
|
||
},
|
||
axisLabel: {
|
||
show: true,
|
||
color: 'rgba(0,0,0,0.45)',
|
||
fontSize: 10,
|
||
boundaryGap: false,
|
||
formatter: function (value: string) {
|
||
const reg = /.*(?=\~)/
|
||
return value.match(reg)![0]
|
||
},
|
||
},
|
||
axisTick: {
|
||
show: false,
|
||
lineStyle: {
|
||
color: '#dadada',
|
||
},
|
||
},
|
||
data: frequencyData.name,
|
||
//startAngle: 75
|
||
},
|
||
tooltip: {},
|
||
series: {
|
||
type: 'bar',
|
||
data: frequencyData.value,
|
||
coordinateSystem: 'polar',
|
||
itemStyle: {
|
||
color: '#0277B3',
|
||
},
|
||
// label: {
|
||
// show: true,
|
||
// position: 'middle',
|
||
// formatter: '{b}: {c}',
|
||
// },
|
||
},
|
||
animation: false,
|
||
}
|
||
frequencyChart.setOption(option)
|
||
state.charts.frequencyChart = frequencyChart
|
||
}
|
||
|
||
const echartsResize = () => {
|
||
nextTick(() => {
|
||
const chartKeys = Object.keys(state.charts) as Array<keyof typeof state.charts>
|
||
chartKeys.forEach((key) => {
|
||
state.charts[key].resize()
|
||
})
|
||
})
|
||
}
|
||
onActivated(() => {
|
||
echartsResize()
|
||
})
|
||
|
||
const tableData = ref<{ time: string; alertcontent: string }[]>([])
|
||
|
||
const clearScroll = () => {
|
||
clearInterval(timer)
|
||
timer = null
|
||
}
|
||
const createScroll = () => {
|
||
clearScroll()
|
||
const table = myTable.value!.layout.table.refs
|
||
const tableWrapper = table.bodyWrapper.firstElementChild!.firstElementChild
|
||
|
||
timer = setInterval(() => {
|
||
tableWrapper!.scrollTop += 1
|
||
if (tableWrapper!.clientHeight + tableWrapper!.scrollTop == tableWrapper!.scrollHeight) {
|
||
tableWrapper!.scrollTop = 0
|
||
}
|
||
}, 30)
|
||
}
|
||
|
||
const realTimeData = ref<any>({
|
||
iturbineoperationmode: 1111,
|
||
locked: 0,
|
||
})
|
||
|
||
const realTimeDataState = computed(() => {
|
||
switch (realTimeData.value.iturbineoperationmode) {
|
||
case 20:
|
||
return '并网'
|
||
case 10:
|
||
return '维护'
|
||
case 8:
|
||
return '限功率运行'
|
||
case 0:
|
||
return '离线'
|
||
case 16:
|
||
return '启动'
|
||
case 6:
|
||
return '正常停机'
|
||
case 1:
|
||
return '紧急停机'
|
||
case 2:
|
||
return '停机'
|
||
case 11:
|
||
return '待机'
|
||
case 1110:
|
||
return '解缆状态'
|
||
case 1111:
|
||
return '电网故障停机'
|
||
case 1112:
|
||
return '安全链停机'
|
||
}
|
||
})
|
||
|
||
const getModelList = () => {
|
||
return new Promise((resolve) => {
|
||
getModelAttributeListReq({ iotModelId: route.query.iotModelId as string }).then((res) => {
|
||
resolve(res.rows)
|
||
})
|
||
})
|
||
}
|
||
|
||
const getRealTimeData = () => {
|
||
return new Promise((resolve) => {
|
||
getRealValueListReq([{ deviceId: route.query.irn as string }]).then((res) => {
|
||
resolve(res.data?.[route.query.irn as string])
|
||
})
|
||
})
|
||
}
|
||
const createRealTimeData = async () => {
|
||
try {
|
||
const modelList: any = await getModelList()
|
||
const realData: any = await getRealTimeData()
|
||
realTimeData.value.iturbineoperationmode = getRealTimeState(realData)
|
||
realTimeData.value.locked = realData.locked
|
||
|
||
temperatureChartsData[0].value = getCutDecimalsValue(realData.itempoutdoor_1sec)
|
||
temperatureChartsData[1].value = getCutDecimalsValue(realData.itempnacelle_1sec)
|
||
temperatureChartsData[2].value = getCutDecimalsValue(realData.itempoutdoor_1sec)
|
||
|
||
const ipitchangle = Math.min(realData.ipitchangle1, realData.ipitchangle2, realData.ipitchangle3)
|
||
realTimeDataForSingle.value.ipitchangle = ipitchangle / 1 === 0 ? ipitchangle : Math.floor(ipitchangle * 1000) / 1000
|
||
|
||
const overviewDatakeys: any = Object.keys(overviewData)
|
||
const sigleDataKeys: any = Object.keys(realTimeDataForSingle.value)
|
||
|
||
const dataFor138And139: { name: string; value: string }[] = []
|
||
const dataFor140: { name: string; value: string }[] = []
|
||
const realDataForSub: any = [
|
||
{ type138: [], type140: [] },
|
||
{ type138: [], type140: [] },
|
||
{ type138: [], type140: [] },
|
||
{ type138: [], type140: [] },
|
||
{ type138: [], type140: [] },
|
||
{ type138: [], type140: [] },
|
||
]
|
||
modelList.forEach((item: any) => {
|
||
const realVal = realData[item.attributeCode.toLowerCase()]
|
||
let val = getCutDecimalsValue(realVal)
|
||
if (enumStore.keys.includes(item.attributeCode)) {
|
||
val = enumStore.data[item.attributeCode][val]
|
||
}
|
||
if (sigleDataKeys.includes(item.attributeCode.toLowerCase())) {
|
||
realTimeDataForSingle.value[item.attributeCode.toLowerCase()] = val === '-' ? val : val
|
||
}
|
||
if (overviewDatakeys.includes(item.attributeCode.toLowerCase())) {
|
||
overviewData[item.attributeCode.toLowerCase() as keyof typeof overviewData] = val === '-' ? val : val + item.unit
|
||
}
|
||
const showData = {
|
||
name: item.attributeName,
|
||
value: val === '-' ? val : val + item.unit,
|
||
}
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
dataFor138And139.push({
|
||
name: item.attributeName,
|
||
value: val === '-' ? val : val + item.unit,
|
||
})
|
||
} else if (item.attributeType === 140) {
|
||
dataFor140.push(showData)
|
||
}
|
||
if (item.subSystem === '变桨系统' || item.subSystem === '轮毂') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[0].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[0].type140.push(showData)
|
||
}
|
||
} else if (item.subSystem === '轴承' || item.subSystem === '传动链' || item.subSystem === '齿轮箱') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[1].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[1].type140.push(showData)
|
||
}
|
||
} else if (item.subSystem === '发电机') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[2].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[2].type140.push(showData)
|
||
}
|
||
} else if (item.subSystem === '机舱') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[3].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[3].type140.push(showData)
|
||
}
|
||
} else if (item.subSystem === '控制系统') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[4].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[4].type140.push(showData)
|
||
}
|
||
} else if (item.subSystem === '环境' || item.subSystem === '气象') {
|
||
if (item.attributeType === 138 || item.attributeType === 139) {
|
||
realDataForSub[5].type138.push(showData)
|
||
} else if (item.attributeType === 140) {
|
||
realDataForSub[5].type140.push(showData)
|
||
}
|
||
}
|
||
})
|
||
overviewSlotData.type138 = dataFor138And139
|
||
overviewSlotData.type140 = dataFor140
|
||
|
||
realTimeForSubSystem.type1 = realDataForSub[0]
|
||
realTimeForSubSystem.type2 = realDataForSub[1]
|
||
realTimeForSubSystem.type3 = realDataForSub[2]
|
||
realTimeForSubSystem.type4 = realDataForSub[3]
|
||
realTimeForSubSystem.type5 = realDataForSub[4]
|
||
realTimeForSubSystem.type6 = realDataForSub[5]
|
||
} catch (err) {
|
||
console.log(err)
|
||
}
|
||
}
|
||
|
||
const subSystemName = ref('')
|
||
|
||
const visible = ref(false)
|
||
const handleClose = (done: () => void) => {
|
||
visible.value = false
|
||
}
|
||
const dialogradioactiveName = ref(138)
|
||
|
||
const realTimeForSubSystem = reactive<any>({
|
||
type1: null,
|
||
type2: null,
|
||
type3: null,
|
||
type4: null,
|
||
type5: null,
|
||
type6: null,
|
||
})
|
||
const curSubSystem = ref('type1')
|
||
const subSystemDataList = computed(() => {
|
||
const type = dialogradioactiveName.value === 138 ? 'type138' : 'type140'
|
||
return realTimeForSubSystem[curSubSystem.value][type]
|
||
})
|
||
|
||
const openSubSystem = (type: number) => {
|
||
switch (type) {
|
||
case 1:
|
||
subSystemName.value = '变桨/轮毂系统'
|
||
curSubSystem.value = 'type1'
|
||
break
|
||
case 2:
|
||
subSystemName.value = '轴承/传动链/齿轮箱系统'
|
||
curSubSystem.value = 'type2'
|
||
break
|
||
case 3:
|
||
subSystemName.value = '发电机系统'
|
||
curSubSystem.value = 'type3'
|
||
break
|
||
case 4:
|
||
subSystemName.value = '机舱系统'
|
||
curSubSystem.value = 'type4'
|
||
break
|
||
case 5:
|
||
subSystemName.value = '控制系统'
|
||
curSubSystem.value = 'type5'
|
||
break
|
||
case 6:
|
||
subSystemName.value = '环境/气象系统'
|
||
curSubSystem.value = 'type6'
|
||
break
|
||
}
|
||
visible.value = true
|
||
}
|
||
|
||
const overviewSlotData = reactive<{ visible: boolean; type: '138' | '140'; type138: any[]; type140: any[] }>({
|
||
visible: false,
|
||
type: '138',
|
||
type138: [],
|
||
type140: [],
|
||
})
|
||
|
||
let autoUpdateForSecondTimer: any = null
|
||
let autoUpdateTimerForMinuteTimer: any = null
|
||
let autoUpdateTimerForHourTimer: any = null
|
||
const autoUpdate = () => {
|
||
createRealTimeData()
|
||
initTemperatureChart()
|
||
if (!autoUpdateForSecondTimer) {
|
||
autoUpdateForSecondTimer = setInterval(() => {
|
||
createRealTimeData()
|
||
initTemperatureChart()
|
||
}, 2000)
|
||
}
|
||
if (!autoUpdateTimerForMinuteTimer) {
|
||
autoUpdateTimerForMinuteTimer = setInterval(() => {
|
||
getAllChartData(['power', 'frequency'])
|
||
}, 60000)
|
||
}
|
||
if (!autoUpdateTimerForHourTimer) {
|
||
autoUpdateTimerForHourTimer = setInterval(() => {
|
||
getAllChartData(['trend'])
|
||
}, 60000 * 30)
|
||
}
|
||
}
|
||
|
||
const getChartData = <T extends string = any>(params: {
|
||
startTime: number
|
||
endTime: number
|
||
attr: T[]
|
||
interval: string
|
||
}): Promise<{ times: { [K in T]: string[] }; val: { [K in T]: number[] } }> => {
|
||
return new Promise((resolve) => {
|
||
const data = {
|
||
startTime: params.startTime,
|
||
endTime: params.endTime,
|
||
devices: [
|
||
{
|
||
deviceId: route.query.irn as string,
|
||
attributes: params.attr,
|
||
},
|
||
],
|
||
interval: params.interval,
|
||
}
|
||
getRealValueRangeReq(data).then((res) => {
|
||
if (res.success) {
|
||
const data = res.data[route.query.irn as string]
|
||
const rangeKeys = Object.keys(data)
|
||
const times: any = {}
|
||
const val: any = {}
|
||
rangeKeys.forEach((key) => {
|
||
times[key] = []
|
||
val[key] = []
|
||
data[key].times.forEach((item: number) => {
|
||
times[key].push(dayjs(item).format('HH:mm'))
|
||
})
|
||
data[key].values.forEach((item: number) => {
|
||
val[key].push(item)
|
||
})
|
||
})
|
||
resolve({ times, val })
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
const getThisDayChartData = () => {
|
||
return new Promise((resolve) => {
|
||
getChartData<'iGenPower' | 'iTheoreticalPower' | 'iWindSpeed'>({
|
||
startTime: new Date(new Date().toLocaleDateString()).getTime(),
|
||
endTime: Date.now(),
|
||
attr: ['iGenPower', 'iTheoreticalPower', 'iWindSpeed'],
|
||
interval: '5m',
|
||
}).then(({ times, val }) => {
|
||
powerChartData.time = { iGenPower: times.iGenPower, iTheoreticalPower: times.iTheoreticalPower, iWindSpeed: times.iWindSpeed }
|
||
powerChartData.values = { iGenPower: val.iGenPower, iTheoreticalPower: val.iTheoreticalPower, iWindSpeed: val.iWindSpeed }
|
||
resolve(true)
|
||
})
|
||
})
|
||
}
|
||
|
||
const getLastYearTodayTimestamp = () => {
|
||
const now = new Date()
|
||
const lastYear = now.getFullYear() - 1
|
||
const lastYearToday = new Date(lastYear, now.getMonth(), now.getDate())
|
||
return lastYearToday.getTime()
|
||
}
|
||
|
||
const getLastYearChartData = () => {
|
||
return new Promise((resolve) => {
|
||
const start = getLastYearTodayTimestamp()
|
||
const end = new Date()
|
||
end.setFullYear(end.getFullYear() - 1)
|
||
|
||
getChartData<'iKWhThisDay'>({
|
||
startTime: start,
|
||
endTime: end.getTime(),
|
||
attr: ['iKWhThisDay'],
|
||
interval: '1h',
|
||
}).then(({ times, val }) => {
|
||
TrendDataForDay.samePeriod.time = times.iKWhThisDay
|
||
TrendDataForDay.samePeriod.value = val.iKWhThisDay
|
||
resolve(true)
|
||
})
|
||
})
|
||
}
|
||
|
||
const getThisDayChartForHourData = () => {
|
||
return new Promise((resolve) => {
|
||
getChartData<'iKWhThisDay'>({
|
||
startTime: new Date(new Date().toLocaleDateString()).getTime(),
|
||
endTime: Date.now(),
|
||
attr: ['iKWhThisDay'],
|
||
interval: '1h',
|
||
}).then(({ times, val }) => {
|
||
TrendDataForDay.currentPeriod.time = times.iKWhThisDay
|
||
TrendDataForDay.currentPeriod.value = val.iKWhThisDay
|
||
resolve(true)
|
||
})
|
||
})
|
||
}
|
||
|
||
const getThisDayChartDataForMinute = () => {
|
||
return new Promise((resolve) => {
|
||
getChartData<'iWindDirection'>({
|
||
startTime: new Date(new Date().toLocaleDateString()).getTime(),
|
||
endTime: Date.now(),
|
||
attr: ['iWindDirection'],
|
||
interval: '1m',
|
||
}).then(({ val }) => {
|
||
const len = val.iWindDirection.length
|
||
const result: number[] = new Array(16).fill(0)
|
||
val.iWindDirection.forEach((item: number) => {
|
||
item = item < 0 ? 360 + item : item > 360 ? 360 : item
|
||
const divisor = Math.ceil(item / 22.5) - 1
|
||
result[divisor] += 1
|
||
})
|
||
const percent = result.map((item) => Math.floor((item / len) * 100000) / 1000)
|
||
frequencyData.value = percent
|
||
resolve(true)
|
||
})
|
||
})
|
||
}
|
||
|
||
const getAllChartData = (type: ('power' | 'trend' | 'frequency')[] = ['power', 'trend', 'frequency']) => {
|
||
if (type.includes('power')) {
|
||
getThisDayChartData().then(() => {
|
||
initpowerChart()
|
||
initTemperatureChart()
|
||
})
|
||
}
|
||
if (type.includes('trend')) {
|
||
const trendDataForLastYear = getLastYearChartData()
|
||
const trendDataForThisDay = getThisDayChartForHourData()
|
||
Promise.all([trendDataForLastYear, trendDataForThisDay]).then(() => {
|
||
initTrendChart(trendChartType.value)
|
||
})
|
||
}
|
||
if (type.includes('frequency')) {
|
||
getThisDayChartDataForMinute().then((res) => {
|
||
initFrequencyChart()
|
||
})
|
||
}
|
||
}
|
||
|
||
const sendCommand = (type: 'setTurbineFastStart' | 'setTurbineStop' | 'setTurbineResetStatusCode') => {
|
||
const sendTypeEnum = {
|
||
setTurbineFastStart: '风机快速启动指令',
|
||
setTurbineStop: '风机停机指令',
|
||
setTurbineResetStatusCode: '风机复位故障代码指令',
|
||
}
|
||
ElMessageBox.confirm('确认发送' + sendTypeEnum[type] + '吗?', '', {
|
||
confirmButtonText: '确认',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}).then(() => {
|
||
const serviceName = sendTypeEnum[type]
|
||
const optDesc = serviceName + ',设定值为:1'
|
||
sendCommandReq({
|
||
deviceId: route.query.irn as string,
|
||
serviceCode: type,
|
||
serviceName,
|
||
optDesc,
|
||
opValue: 1,
|
||
}).then((res) => {
|
||
if (res.code == 200) {
|
||
ElMessage.success('指令发送成功')
|
||
} else {
|
||
ElMessage.error('指令发送失败')
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
const sendManualCommand = (type: 1 | 0) => {
|
||
const serviceName = type === 0 ? '风机解锁' : '风机锁定'
|
||
ElMessageBox.confirm('确认' + serviceName + '吗?', '', {
|
||
confirmButtonText: '确认',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}).then(() => {
|
||
sendManualCommandReq({
|
||
deviceId: route.query.irn as string,
|
||
serviceCode: 'Locked',
|
||
serviceName,
|
||
optDesc: serviceName + ',设定值为:' + type,
|
||
opValue: type,
|
||
}).then((res) => {
|
||
if (res.code == 200) {
|
||
ElMessage.success('指令发送成功')
|
||
} else {
|
||
ElMessage.error('指令发送失败')
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
const getAlarmList = () => {
|
||
const start = dayjs().subtract(3, 'day').startOf('day').toDate().getTime()
|
||
const end = dayjs().endOf('day').toDate().getTime()
|
||
console.log(route.query.name)
|
||
|
||
getAlarmListReq({
|
||
startTime: start,
|
||
endTime: end,
|
||
deviceCode: [route.query.name],
|
||
}).then((res) => {
|
||
if (res.rows) {
|
||
tableData.value = res.rows.map((item: any) => {
|
||
return {
|
||
time: dayjs(item.eventTime).format('YYYY-MM-DD HH:mm:ss'),
|
||
alertcontent: item.eventText,
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
getAlarmList()
|
||
onMounted(() => {
|
||
window.addEventListener('resize', sizeChange)
|
||
sizeChange()
|
||
getAllChartData()
|
||
createScroll()
|
||
useEventListener(window, 'resize', echartsResize)
|
||
autoUpdate()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
window.removeEventListener('resize', sizeChange)
|
||
autoUpdateForSecondTimer && clearInterval(autoUpdateForSecondTimer)
|
||
autoUpdateTimerForHourTimer && clearInterval(autoUpdateTimerForHourTimer)
|
||
autoUpdateTimerForMinuteTimer && clearInterval(autoUpdateTimerForMinuteTimer)
|
||
const chartKeys = Object.keys(state.charts) as Array<keyof typeof state.charts>
|
||
chartKeys.forEach((key) => {
|
||
state.charts[key] && state.charts[key].dispose()
|
||
})
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
$marginNum: 10px;
|
||
$labelHeight: 38px;
|
||
@mixin cardDefaultStyle {
|
||
margin-top: $marginNum;
|
||
margin-bottom: $marginNum;
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
background-color: #fff;
|
||
}
|
||
@mixin cardlabel {
|
||
.cardLabel {
|
||
width: 100%;
|
||
height: $labelHeight;
|
||
font-size: 18px;
|
||
line-height: 18px;
|
||
font-weight: 600;
|
||
color: #4e5969;
|
||
}
|
||
}
|
||
.radioItem {
|
||
margin-top: -43px;
|
||
float: right;
|
||
}
|
||
.dialogContent {
|
||
max-height: 500px;
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
.PitchPart {
|
||
.Pitchitem {
|
||
border: 1px solid #e1edf6;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-left: 15px;
|
||
width: 480px;
|
||
.PitchitemLeft {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 325px;
|
||
min-height: 50px;
|
||
background: #f7f9fc;
|
||
padding-left: 20px;
|
||
font-size: 14px;
|
||
color: #4e5969;
|
||
letter-spacing: 0;
|
||
font-weight: 500;
|
||
word-break: break-all;
|
||
}
|
||
.PitchitemRight {
|
||
/*width: 180px;*/
|
||
height: 25px;
|
||
line-height: 50px;
|
||
padding-right: 20px;
|
||
font-size: 14px;
|
||
color: #4e5969;
|
||
letter-spacing: 0;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.dialog-footer {
|
||
text-align: center;
|
||
.el-button {
|
||
width: 120px;
|
||
height: 40px;
|
||
}
|
||
}
|
||
.overviewSlot {
|
||
display: flex;
|
||
.radioForOverviewType {
|
||
margin-left: auto;
|
||
}
|
||
}
|
||
|
||
.windBlower {
|
||
width: 100%;
|
||
height: 100%;
|
||
min-height: 920px;
|
||
background-color: #f2f3f5;
|
||
// overflow: hidden;
|
||
.el-row{
|
||
width: calc(100% - 10px);
|
||
}
|
||
.cardContentLeft {
|
||
width: 100%;
|
||
.overview {
|
||
width: 100%;
|
||
@include cardDefaultStyle;
|
||
@include cardlabel;
|
||
.overviewDataSection {
|
||
width: 100%;
|
||
min-height: 495px;
|
||
.overviewDataSectionItem {
|
||
font-size: 14px;
|
||
color: #333333;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
background: #f0f6ff;
|
||
border-radius: 4px;
|
||
width: 100%;
|
||
min-height: 40px;
|
||
line-height: 40px;
|
||
margin-bottom: 5px;
|
||
padding: 0 10px;
|
||
}
|
||
}
|
||
.overviewDataBtn {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: end;
|
||
width: 100%;
|
||
height: 40px;
|
||
font-size: 22px;
|
||
.el-icon {
|
||
transform: rotate(90deg);
|
||
}
|
||
:hover {
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
}
|
||
.power {
|
||
@include cardDefaultStyle;
|
||
@include cardlabel;
|
||
width: 100%;
|
||
min-height: 285px;
|
||
height: v-bind('computedHeight.powerHeight');
|
||
.chartBox {
|
||
width: 100%;
|
||
height: calc(100% - $labelHeight);
|
||
.power-chart {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.cardContentCenter {
|
||
@include cardDefaultStyle;
|
||
display: flex;
|
||
padding-bottom: 20px;
|
||
flex-direction: column;
|
||
justify-content: space-around;
|
||
width: 100%;
|
||
min-height: 900px;
|
||
height: v-bind('computedHeight.centerHeight');
|
||
.controlBackgroundImg {
|
||
position: relative;
|
||
width: 100%;
|
||
// height: 450px;
|
||
aspect-ratio: 43 / 24;
|
||
background: url('/@/assets/WindBlower/bg.png') no-repeat;
|
||
background-size: contain;
|
||
.control-type {
|
||
width: 100%;
|
||
display: flex;
|
||
.control-tag {
|
||
background: #0064aa;
|
||
border-radius: 0 8px 0 0;
|
||
min-width: 80px;
|
||
height: 40px;
|
||
color: #ffffff;
|
||
font-size: 20px;
|
||
border: none;
|
||
margin-left: auto;
|
||
}
|
||
.control-tag-left {
|
||
margin-left: 0;
|
||
border-radius: 8px 0 0 0;
|
||
background-color: #ff4949;
|
||
}
|
||
}
|
||
.btnLeft {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
position: absolute;
|
||
bottom: 0;
|
||
.el-button {
|
||
width: 80px;
|
||
height: 40px;
|
||
// background: rgb(0,100,170);
|
||
border-radius: 6px;
|
||
color: #ffffff;
|
||
border: none;
|
||
margin-bottom: 10px;
|
||
}
|
||
}
|
||
.dot {
|
||
position: absolute;
|
||
width: 15px;
|
||
height: 15px;
|
||
border-radius: 10px;
|
||
background-color: #ff7e00;
|
||
&:hover {
|
||
cursor: pointer;
|
||
}
|
||
&:nth-of-type(1) {
|
||
top: 25%;
|
||
left: 50%;
|
||
}
|
||
}
|
||
.index-1 {
|
||
left: 25%;
|
||
top: 60%;
|
||
}
|
||
.index-2 {
|
||
left: 52%;
|
||
top: 53%;
|
||
}
|
||
.index-3 {
|
||
left: 65%;
|
||
top: 60%;
|
||
}
|
||
.index-4 {
|
||
left: 83%;
|
||
top: 54%;
|
||
}
|
||
.index-5 {
|
||
left: 75%;
|
||
top: 28%;
|
||
}
|
||
.index-6 {
|
||
left: 73%;
|
||
top: 4%;
|
||
}
|
||
}
|
||
.Parameters {
|
||
margin-top: 10px;
|
||
width: 100%;
|
||
display: flex;
|
||
.Parameters-item {
|
||
margin: 5px;
|
||
width: 20%;
|
||
height: 160px;
|
||
background: #f0f6ff;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
color: #4e5969;
|
||
.Parameters-font {
|
||
font-size: 20px;
|
||
color: #333333;
|
||
}
|
||
}
|
||
}
|
||
.chartPart {
|
||
margin-top: auto;
|
||
width: 100%;
|
||
min-height: 220px;
|
||
flex-shrink: 1;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.chartPart-item {
|
||
margin: 5px;
|
||
width: 23%;
|
||
height: 100%;
|
||
background: #f0f6ff;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
color: #4e5969;
|
||
.chartParm {
|
||
width: 100%;
|
||
height: 100%;
|
||
min-height: 220px;
|
||
}
|
||
.frequencyChart {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
.item_bar {
|
||
width: 31%;
|
||
}
|
||
}
|
||
}
|
||
.cardContentRight {
|
||
width: 100%;
|
||
height: 100%;
|
||
// min-height: 920px;
|
||
.summarize {
|
||
width: 100%;
|
||
@include cardDefaultStyle;
|
||
@include cardlabel;
|
||
.summarize-panel-list {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
.summarize-panel {
|
||
margin: 5px;
|
||
width: 25%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
background-color: #f0f6ff;
|
||
border-radius: 10px;
|
||
.summarize-panel-base {
|
||
width: 100%;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
div {
|
||
display: flex;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
color: rgb(78, 89, 105);
|
||
.content-number {
|
||
color: #333333;
|
||
font-size: 20px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.trend {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 360px;
|
||
@include cardDefaultStyle;
|
||
@include cardlabel;
|
||
.trendTabs {
|
||
position: absolute;
|
||
right: 10px;
|
||
top: 5px;
|
||
}
|
||
.trend-chart {
|
||
width: 100%;
|
||
height: calc(100% - $labelHeight);
|
||
}
|
||
}
|
||
.alarm {
|
||
width: 100%;
|
||
min-height: 350px;
|
||
height: v-bind('computedHeight.alarmHeight');
|
||
@include cardDefaultStyle;
|
||
@include cardlabel;
|
||
}
|
||
}
|
||
}
|
||
</style>
|