map/ui/dasadmin/src/views/backend/energyManage/index.vue
2025-01-22 16:04:54 +08:00

1216 lines
43 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="energyManage">
<el-row :gutter="20">
<el-col :md="24" :lg="{ span: 14, push: 5 }">
<el-tabs v-model="activeName" @tab-change="handleClick">
<el-tab-pane label="风机列表" name="list">
<div class="centerContainer">
<div class="airBlowerList">
<!-- <div class="title">风机列表</div> -->
<el-table class="table" :data="tableData">
<el-table-column
v-for="item in tableColumn"
:key="item.prop"
:prop="item.prop"
:label="item.label"
align="center"
:width="item.width"
>
<template #default="scope">
<div v-if="item.prop === 'processedoperationmode'">
<el-tag v-if="scope.row.locked === 1" color="rgba(254,55,49,0.20)" style="color: #fe3731"
>已锁定</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 20"
color="rgba(0,100,170,0.20)"
style="color: #0064aa"
>并网</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 10"
color="rgba(0,160,150,0.20)"
style="color: #00a096"
>维护</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 8"
color="rgba(255,126,0,0.20)"
style="color: #ff7e00"
>限功率运行</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 0"
color="rgba(153,153,153,0.20)"
style="color: #666666"
>离线</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 16"
color="rgba(6,180,41,0.20)"
style="color: #06b429"
>启动</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 6"
color="rgba(254,55,49,0.20)"
style="color: #fe3731"
>正常停机</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 1"
color="rgba(254,55,49,0.20)"
style="color: #fe3731"
>外部因素导致停机</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 2"
color="rgba(254,55,49,0.20)"
style="color: #fe3731"
>停机</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 11"
color="rgba(255,182,0,0.20)"
style="color: #ffb600"
>待机</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 1110"
color="rgba(153,153,153,0.20)"
style="color: #666666"
>解缆状态</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 1111"
color="rgba(254,55,49,0.20)"
style="color: #fe3731"
>电网故障停机</el-tag
>
<el-tag
v-if="scope.row.processedoperationmode === 33"
color="rgba(153, 153, 153, 0.2)"
style="color: #999999"
>通讯中断</el-tag
>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="风机曲线" name="chart">
<div class="centerContainer">
<div class="chartPart">
<div class="title">
<span> 自动更新 </span>
<el-switch v-model="autoUpdateChartSwitch" @change="changeUpdateChart"></el-switch>
</div>
<div class="lineChart">
<div class="chart" ref="chartRef"></div>
</div>
<div class="info">
<div class="infoItem" v-for="item in infoList" :key="item.label">
<div class="label">{{ item.label }}</div>
<div class="val">{{ item.value }}</div>
</div>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-col>
<el-col :md="12" :lg="{ span: 5, pull: 14 }">
<div class="leftContainer">
<div class="overview">
<div class="title">AGC总览</div>
<div class="content">
<div class="rect">
<div class="left">
<div class="img img1"></div>
<div class="imgName">全场有功</div>
</div>
<div class="right">
<div class="num">{{ realDataList.windfarmactivepower }}</div>
<div class="unit">MW</div>
</div>
</div>
<div class="rect">
<div class="left">
<div class="img img2"></div>
<div class="imgName">AGC目标值</div>
</div>
<div class="right">
<div class="num">{{ realDataListSetValue.AgcTarget }}</div>
<div class="unit">MW</div>
</div>
</div>
<div class="check">
<div class="left">
<div class="name">AGC投入/退出</div>
<div class="status">
<div class="smallDot" :class="realDataList.operationstatusagc ? 'successColor' : 'defaultColor'"></div>
<div class="smallDot" :class="realDataList.operationstatusagc ? 'defaultColor' : 'errorColor'"></div>
</div>
</div>
<div class="right">
<el-switch v-model="agcOnoffSwitch"></el-switch>
</div>
</div>
<div class="checkInput">
<div class="top">
<div class="left">AGC远程/就地</div>
<div class="right">
<el-switch v-model="agcLocalRemoteSwitch"></el-switch>
</div>
</div>
<div class="bottom">
<el-input v-model="agcTargetValue" placeholder="本地目标值设置MW 请输入">
<template #suffix>
<div class="saveBtn"></div>
</template>
</el-input>
</div>
</div>
<div class="check">
<div class="left">AGC增闭锁</div>
<div class="right">
<div class="dot" :class="realDataList.activepowerincdisabled ? 'successColor' : 'errorColor'"></div>
</div>
</div>
<div class="check">
<div class="left">AGC减闭锁</div>
<div class="right">
<div class="dot" :class="realDataList.activepowerdecdisabled ? 'successColor' : 'errorColor'"></div>
</div>
</div>
<div class="check">
<div class="left">AGC可增有功</div>
<div class="right">
<div class="num">{{ realDataList.activepowerinccapacity }}</div>
<div class="unit">MW</div>
</div>
</div>
<div class="check">
<div class="left">AGC可减有功</div>
<div class="right">
<div class="num">{{ realDataList.activepowerdeccapacity }}</div>
<div class="unit">MW</div>
</div>
</div>
</div>
</div>
<div class="record">
<div class="title">AGC记录</div>
<div class="recordList">
<el-scrollbar>
<div class="recordItem" v-for="item in agcRecordList" :key="item">{{ item }}</div>
</el-scrollbar>
</div>
</div>
</div>
</el-col>
<el-col :md="12" :lg="5">
<div class="rightContainer">
<div class="overview">
<div class="title">AVC总览</div>
<div class="content">
<div class="rect">
<div class="left">
<div class="img img1"></div>
<div class="imgName">全场无功</div>
</div>
<div class="right">
<div class="num">{{ realDataList.windfarmreactivepower }}</div>
<div class="unit">MVar</div>
</div>
</div>
<div class="rect">
<div class="left">
<div class="img img2"></div>
<div class="imgName">AVC目标值</div>
</div>
<div class="right">
<div class="num">{{ realDataListSetValue.AvcTarget }}</div>
<div class="unit">MVar</div>
</div>
</div>
<div class="check">
<div class="left">
<div class="name">AVC投入/退出</div>
<div class="status">
<div class="smallDot" :class="realDataList.operationstatusavc ? 'successColor' : 'defaultColor'"></div>
<div class="smallDot" :class="realDataList.operationstatusavc ? 'defaultColor' : 'errorColor'"></div>
</div>
</div>
<div class="right">
<el-switch v-model="avcOnoffSwitch"></el-switch>
</div>
</div>
<div class="checkInput">
<div class="top">
<div class="left">AVC远程/就地</div>
<div class="right">
<el-switch v-model="avcLocalRemoteSwitch"></el-switch>
</div>
</div>
<div class="bottom">
<el-input v-model="avcTargetValue" placeholder="本地目标值设置MW 请输入">
<template #suffix>
<div class="saveBtn"></div>
</template>
</el-input>
</div>
</div>
<div class="check">
<div class="left">AVC增闭锁</div>
<div class="right">
<div class="dot" :class="realDataList.reactivepowerincdisabled ? 'successColor' : 'errorColor'"></div>
</div>
</div>
<div class="check">
<div class="left">AVC减闭锁</div>
<div class="right">
<div class="dot" :class="realDataList.reactivepowerdecdisabled ? 'successColor' : 'errorColor'"></div>
</div>
</div>
<div class="check">
<div class="left">AVC可增无功</div>
<div class="right">
<div class="num">{{ realDataList.reactivepowerinccapacity }}</div>
<div class="unit">MVar</div>
</div>
</div>
<div class="check">
<div class="left">AVC可减无功</div>
<div class="right">
<div class="num">{{ realDataList.reactivepowerdeccapacity }}</div>
<div class="unit">MVar</div>
</div>
</div>
</div>
</div>
<div class="record">
<div class="title">AVC记录</div>
<div class="recordList">
<el-scrollbar>
<div class="recordItem" v-for="item in avcRecordList" :key="item">{{ item }}</div>
</el-scrollbar>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick, reactive } from 'vue'
import { getAirBlowerListReq } from '/@/api/backend/airBlower/request'
import { getRealValueListReq, getRealValueRangeReq } from '/@/api/backend/deviceModel/request'
import { getRealTimeState, getCutDecimalsValue, getEnumToValue } from '/@/views/backend/equipment/airBlower/utils'
import { ElMessage, dayjs } from 'element-plus'
import { debounce } from 'lodash-es'
import * as echarts from 'echarts'
const agcOnoffSwitch = ref(true)
const agcOnOff = ref(true)
const agcLocalRemoteSwitch = ref(false)
const agcTargetValue = ref()
const agcAdd = ref(true)
const agcSub = ref(false)
const agcRecordList = ref([
'2023-12-26 22:07:25一次调频指令变更为156212kW',
'2023-12-25 22:07:25进入一次调频模式',
'2023-12-24 22:07:25进入一次调频模式',
'2023-12-23 22:07:25进入一次调频模式',
'2023-12-22 22:07:25一次调频指令变更为156212kW',
])
const avcOnoffSwitch = ref(true)
const avcOnOff = ref(false)
const avcLocalRemoteSwitch = ref(false)
const avcTargetValue = ref()
const avcAdd = ref(true)
const avcSub = ref(false)
const avcRecordList = ref([
'2023-12-26 22:07:25一次调频指令变更为156212kW',
'2023-12-25 22:07:25进入一次调频模式',
'2023-12-24 22:07:25进入一次调频模式',
'2023-12-23 22:07:25进入一次调频模式',
'2023-12-22 22:07:25一次调频指令变更为156212kW',
])
const tableColumn = [
{
label: '编号',
prop: 'name',
width: '',
},
{
label: '风速m/s',
prop: 'iwindspeed',
width: '',
},
{
label: '转速rmp',
prop: 'igenspeed',
width: '',
},
{
label: '有功kW',
prop: 'igenpower',
width: '',
},
{
label: '有功给定kW',
prop: 'iactivepowersetpointvalue',
width: '',
},
{
label: '无功kVar',
prop: 'ireactivepower',
width: '',
},
{
label: '无功给定kVar',
prop: 'ireactivepowersetpointvalue',
width: '',
},
{
label: '状态',
prop: 'processedoperationmode',
width: '',
},
]
const curDevice = ref('1846101273013739522')
const tableData = ref<any[]>([])
const createTableReqParams = (airblowerList: { irn: string; name: string }[]) => {
const curTableKey = tableColumn.map((item) => item.prop)
const airBlowerIds: any = []
const airBlowerInfo: any = {}
const params = airblowerList.map((item: any) => {
airBlowerInfo[item.irn] = {
name: item.name,
model: item.model,
belongLine: item.belongLine,
modelId: item.modelId,
deviceCode: item.deviceCode,
}
airBlowerIds.push(item.irn)
return {
deviceId: item.irn,
attributes: [...curTableKey, 'processedoperationmode', 'iyplevel', 'gridlostdetected', 'ibplevel'],
}
})
return { params, airBlowerInfo, airBlowerIds }
}
const getAirBlowerList = () => {
let airBlowerInfoObj: any = {}
let airBlowerIdList: any[] = []
getAirBlowerListReq()
.then((res) => {
if (res.success) {
return createTableReqParams(res.data)
} else {
throw '获取风机列表失败'
}
})
.then((data) => {
airBlowerInfoObj = data.airBlowerInfo
airBlowerIdList = data.airBlowerIds
return getRealValueListReq(data!.params)
})
.then((res) => {
if (res.success) {
const data = airBlowerIdList.map((id) => {
const realData: any = {}
Object.keys(res.data[id]).forEach((key) => {
const cutVal = getCutDecimalsValue(res.data[id][key])
realData[key] = getEnumToValue(key, cutVal)
})
const state = getRealTimeState(res.data[id])
return {
irn: id,
name: airBlowerInfoObj[id].name,
model: airBlowerInfoObj[id].model,
iotModelId: airBlowerInfoObj[id].modelId,
belongLine: airBlowerInfoObj[id].belongLine,
deviceCode: airBlowerInfoObj[id].deviceCode,
...realData,
processedoperationmode: state,
}
})
tableData.value = data
} else {
throw '获取风机列表失败'
}
})
.catch((err) => {
ElMessage.error(err)
})
}
let timer: any = null
const autoUpdateAirBlower = () => {
getAirBlowerList()
if (!timer) {
timer = setInterval(() => {
getAirBlowerList()
}, 2000)
}
}
const autoUpdateChartSwitch = ref(false)
const changeUpdateChart = (val: boolean) => {
if (val) {
autoUpdateChart()
} else {
clearInterval(autoUpdateChartTimer)
autoUpdateChartTimer = null
}
}
const chartRef = ref()
let chartInstance: any = null
let realDataXAxis: any[] = [
'2024-12-06 16:53:37',
'2024-12-06 16:53:38',
'2024-12-06 16:53:39',
'2024-12-06 16:53:40',
'2024-12-06 16:53:41',
'2024-12-06 16:53:42',
'2024-12-06 16:53:43',
'2024-12-06 16:53:44',
'2024-12-06 16:53:45',
'2024-12-06 16:53:46',
'2024-12-06 16:53:47',
'2024-12-06 16:53:48',
]
let realDataSeries: any[] = [
{
id: 'iwindspeed',
name: '风速',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#096676',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [24.68, 24.68, 25.3, 24.09, 24.51, 24.51, 24.46, 23.87, 23.97, 23.87, 23.87, 24.61],
},
{
id: 'ireactivepowersetpointvalue',
name: '给定无功功率',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#8236aa',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
},
{
id: 'ireactivepower',
name: '无功功率',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#687068',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6, 50.6],
},
{
id: 'iactivepowersetpointvalue',
name: '给定有功功率',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#164342',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
},
{
id: 'igenpower',
name: '有功功率',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#532457',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [1518.9, 1518.9, 1518.8, 1518.7, 1518.7, 1518.7, 1518.7, 1518.8, 1518.59, 1518.59, 1518.59, 1518.59],
},
{
id: 'igenspeed',
name: '转速',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#945810',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [1808.3, 1808.3, 1808.3, 1808.3, 1808.3, 1808.3, 1808.2, 1808.2, 1808.2, 1808, 1808, 1807.8],
},
{
id: 'iwinddirection',
name: '风向',
type: 'line',
barWidth: 20,
itemStyle: {
color: '#195658',
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [0.8, 0.8, 6.9, -6.1, 0.6, 0.6, -0.5, -6.6, -5.41, -4.21, -4.21, 2.5],
},
]
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 > 300) {
realDataXAxis.shift()
realDataSeries.forEach((item: any) => {
item.data.shift()
})
}
const attrCode = Object.keys(data)
realDataXAxis.push(time)
const seriesData = attrCode.map((item) => {
const curVal = getCutDecimalsValue(data[item], 2)
if (realDataSeries.length) {
const seriesItem = realDataSeries.find((series) => series.id === item)
seriesItem.data.push(curVal)
return seriesItem
} else {
const color = getRandomDarkColor()
return {
id: item,
name: chartProps[item],
type: 'line',
barWidth: 20,
itemStyle: {
color: color,
barBorderRadius: 2,
},
smooth: true,
symbol: 'none',
data: [curVal],
}
}
})
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 {
const legendData = Object.values(chartProps).map((item) => {
return {
name: item,
}
})
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: legendData,
textStyle: {
color: '#73767a',
},
icon: 'roundRect',
},
series: realDataSeries,
}
}
chart.setOption(option, { replaceMerge: 'series' })
chartInstance = chart
}
const chartProps: any = {
iwindspeed: '风速',
iwinddirection: '风向',
igenspeed: '转速',
igenpower: '有功功率',
iactivepowersetpointvalue: '给定有功功率',
ireactivepower: '无功功率',
ireactivepowersetpointvalue: '给定无功功率',
}
const getRangeValueList = () => {
const params = {
startTime: dayjs().startOf('day').valueOf(),
endTime: dayjs().valueOf(),
devices: [
{
deviceId: tableData.value[1].irn,
attributes: Object.keys(chartProps),
},
],
interval: '1m',
}
getRealValueRangeReq(params).then((res) => {
if (res.data) {
}
})
}
const getRealDataForChart = () => {
const params = [
{
deviceId: tableData.value[0].irn,
attributes: Object.keys(chartProps),
},
]
getRealValueListReq(params).then((res) => {
if (res.data) {
const time = dayjs().format('YYYY-MM-DD HH:mm:ss')
createChartData(res.data?.[tableData.value[0].irn], time)
}
})
}
let autoUpdateChartTimer: any = null
const autoUpdateChart = () => {
if (!autoUpdateChartTimer) {
autoUpdateChartTimer = setInterval(() => {
getRealDataForChart()
}, 1000)
}
}
const infoList = ref([
{
label: '风机总功率kW',
value: 157646,
},
{
label: '当前有功指令kW',
value: 156212,
},
{
label: '电网有功指令kW',
value: 120000,
},
{
label: '调频有功指令kW',
value: 156212,
},
{
label: '电网电压kV',
value: 200,
},
{
label: '风机总无功kVar',
value: 1596.4,
},
{
label: '当前无功指令kW',
value: 0.0,
},
{
label: '线路损耗功率kW',
value: 3259,
},
{
label: '电网出口功率kW',
value: 156679,
},
{
label: '电网频率Hz',
value: 0.0,
},
])
const activeName = ref('list')
const handleClick = (tabName: any) => {
if (tabName === 'chart') {
console.log(tabName)
stopAutoUpdate()
nextTick(() => {
createChart()
})
} else if (tabName === 'list') {
autoUpdateAirBlower()
}
}
const containerHeight = ref('900px')
const getContainerHeight = () => {
const container = document.querySelector('.leftContainer')
if (container) {
const { height } = container.getBoundingClientRect()
containerHeight.value = `${height}px`
}
}
const resizeChart = debounce(() => {
chartInstance?.resize()
}, 500)
const resizeFn = () => {
resizeChart()
getContainerHeight()
}
const stopAutoUpdate = () => {
timer && clearInterval(timer)
timer = null
}
const realDataListSetValue = reactive({
AgcTarget: '0',
AvcTarget: '0',
})
const realDataList = reactive({
windfarmactivepower: '',
operationstatusagc: '',
RemoteCtrlStatusAgc: '',
activepowerincdisabled: '',
activepowerdecdisabled: '',
activepowerinccapacity: '',
activepowerdeccapacity: '',
windfarmreactivepower: '',
operationstatusavc: '',
RemoteCtrlStatusAvc: '',
reactivepowerincdisabled: '',
reactivepowerdecdisabled: '',
reactivepowerinccapacity: '',
reactivepowerdeccapacity: '',
})
const getRealDataForList = () => {
const deviceId = '1881630608594132993'
const attrs = Object.keys(realDataList) as (keyof typeof realDataList)[]
const params = [
{
deviceId,
attributes: attrs,
},
]
getRealValueListReq(params).then((res) => {
if (res.data) {
console.log(res.data, 'res.data')
const data = res.data[deviceId]
attrs.forEach((item) => {
realDataList[item] = data?.[item] ?? '-'
})
}
})
}
let listTimer: any = null
const autoUpdateList = () => {
if (!listTimer) {
getRealDataForList()
listTimer = setInterval(() => {
getRealDataForList()
}, 2000)
}
}
const clearListTimer = () => {
listTimer && clearInterval(listTimer)
listTimer = null
}
onMounted(() => {
getContainerHeight()
autoUpdateList()
autoUpdateAirBlower()
window.addEventListener('resize', resizeFn)
})
onUnmounted(() => {
window.removeEventListener('resize', resizeFn)
stopAutoUpdate()
clearListTimer()
})
</script>
<style lang="scss" scoped>
@mixin defaultBoxStyle {
display: flex;
align-self: center;
justify-content: space-between;
padding: 0 10px;
width: 100%;
}
@mixin borderstyle {
border-radius: 10px;
border: 1px solid #e1edf6;
}
@mixin overViewRight {
.right {
display: flex;
align-items: center;
height: 100%;
.num {
font-size: 20px;
line-height: 20px;
color: #333333;
letter-spacing: 0;
font-weight: 700;
}
.unit {
margin-left: 5px;
height: 10%;
font-size: 14px;
color: #4e5969;
letter-spacing: 0;
line-height: 14px;
font-weight: 700;
}
.dot {
height: 45%;
aspect-ratio: 1/1;
border-radius: 50%;
}
}
}
@mixin overview {
.overview {
padding: 20px;
width: 100%;
background-color: #fff;
border-radius: 6px;
.title {
height: 28px;
font-size: 18px;
font-weight: 600;
color: #4e5969;
}
.content {
width: 100%;
height: calc(100% - 20px);
.rect {
@include defaultBoxStyle;
margin: 10px 0;
aspect-ratio: 310/70;
background-color: #f0f6ff;
@include borderstyle;
.left {
display: flex;
align-items: center;
height: 100%;
.img {
height: 51%;
aspect-ratio: 1/1;
background-repeat: no-repeat;
background-size: contain;
}
.imgName {
margin-left: 5px;
font-size: 14px;
color: #4e5969;
letter-spacing: 0;
font-weight: 400;
}
.img1 {
background-image: url('/@/assets/energyManage/power.png');
}
.img2 {
background-image: url('/@/assets/energyManage/AGC.png');
}
}
@include overViewRight;
}
.check {
@include defaultBoxStyle;
margin-bottom: 10px;
aspect-ratio: 310/50;
@include borderstyle;
.left {
display: flex;
align-items: center;
height: 100%;
color: #4e5969;
.status {
display: flex;
align-items: center;
height: 100%;
.smallDot {
margin-left: 5px;
height: 25%;
aspect-ratio: 1/1;
border-radius: 50%;
}
}
}
@include overViewRight;
}
.checkInput {
padding: 0 10px;
margin-bottom: 10px;
width: 100%;
aspect-ratio: 310/88;
color: #4e5969;
@include borderstyle;
.top {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 5px;
margin-bottom: 10px;
height: 30%;
}
.bottom {
.el-input {
background-color: #f0f6ff;
:deep(.el-input__wrapper) {
.el-input__inner {
width: 92%;
flex-grow: 0;
}
}
}
.saveBtn {
margin: 0;
height: 60%;
aspect-ratio: 1/1;
background-image: url('/@/assets/energyManage/defaultSave.png');
background-size: contain;
background-repeat: no-repeat;
cursor: pointer;
}
}
}
}
}
}
@mixin record {
.record {
margin: 20px 0;
padding: 20px;
width: 100%;
aspect-ratio: 350/270;
background-color: #fff;
border-radius: 6px;
color: #4e5969;
.title {
height: 30px;
font-size: 18px;
color: #4e5969;
font-weight: 600;
}
.recordList {
width: 100%;
height: calc(100% - 30px);
.recordItem {
width: 100%;
min-height: 32px;
line-height: 150%;
word-break: break-all;
background-color: #f0f6ff;
&:nth-child(2n) {
background-color: #fff;
}
}
}
}
}
.energyManage {
width: 100%;
// height: 100%;
min-height: 100%;
background-color: #f2f3f5;
.el-row {
width: 100%;
height: 100%;
.el-col {
width: 100%;
height: 100%;
.successColor {
background-color: #06b429;
}
.errorColor {
background-color: #fe3731;
}
.defaultColor {
background-color: #e1e6ed;
}
.leftContainer {
@include overview;
@include record;
}
.centerContainer {
height: v-bind('containerHeight');
color: #4e5969;
.airBlowerList {
padding: 20px;
width: 100%;
height: calc(100% - 10px - 40px);
background-color: #fff;
border-radius: 6px;
// .title {
// height: 38px;
// font-size: 18px;
// font-weight: 600;
// }
.table {
height: 100%;
}
}
.chartPart {
padding: 20px;
width: 100%;
height: calc(100% - 10px - 40px);
background-color: #fff;
border-radius: 6px;
.title {
width: 100%;
height: 32px;
font-size: 14px;
font-weight: 500;
}
.lineChart {
width: 100%;
height: calc(100% - 102px);
.chart {
width: 100%;
height: 100%;
}
}
.info {
display: flex;
flex-wrap: wrap;
padding: 10px;
width: 100%;
height: 70px;
background-color: #f0f6ff;
.infoItem {
display: flex;
align-items: center;
width: 20%;
height: 50%;
font-size: 12px;
color: #333333;
font-weight: 400;
.label {
margin-left: 10%;
}
.val {
margin-left: 10px;
}
}
}
}
}
.rightContainer {
@include overview;
@include record;
}
}
}
}
</style>