You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

764 lines
19 KiB

2 years ago
<template>
<view>
<uni-nav-bar left-icon="left" fixed="true" title="逆变器视图" @clickLeft="handlerBack"></uni-nav-bar>
2 years ago
<view class="container">
<view class="search-box">
<uni-section title="选择电站" type="line" >
<uni-data-picker placeholder="请选择电站"
popup-title="请选择分区"
:localdata="stationData"
:clear-icon="false"
v-model="selectStations"
:map="{text:'stationName',value:'id', children: 'children'}"
@change="onchange"
>
</uni-data-picker>
<uni-data-picker placeholder="选择逆变器"
style="margin-top: 10upx;"
:localdata="secondList"
:clear-icon="false"
v-model="secondValueList"
:map="{text:'name',value:'value', children: 'addd'}"
@change="onchange1"
>
</uni-data-picker>
</uni-section>
<uni-section title="设备状态" type="line" >
<template v-slot:right>
<view class="flex">
<u-button @click="handleSetConfig" type="primary" size="mini" text="设置参数"></u-button>
</view>
</template>
<div class="report-status">
<div class="report-status-item">
<div class="flex flex-column flex-col-center">
<div style="margin-bottom: 10px;">
2 years ago
<!-- <div>状态</div -->
<div class="flex">
<div class="item flex flex-center">
<i class="bg s1"></i>
<span class="text">正常</span>
</div>
<div class="item flex flex-center ">
<i class="bg s2"></i>
<span class="text">停机</span>
</div>
<div class="item flex flex-center ">
<i class="bg s3"></i>
<span class="text">异常</span>
</div>
<div class="item flex flex-center ">
<i class="bg s4"></i>
<span class="text">不在线</span>
</div>
</div>
</div>
<div class="flex flex-row-center">
关闭<u-switch v-model="value4" size="20"
inactiveColor="#ff0000"
activeColor="#00a403" style="margin: 0 10px;"></u-switch>
</div>
2 years ago
</div>
</div>
</div>
</uni-section>
</view>
<view class="content">
<view class='timer' @click="show = true">时间{{ timer }}</view>
<echarts ref="echarts" class="uni-ec-canvas" :option="option" canvasId="echarts"></echarts>
<div class="report-item-bottom flex flex-column" v-show="type === 'first'">
<table border="2" :class="itemStateClass(infoData.state).clas">
<tr>
<td>直流电压V</td>
<td class="text-c">{{ infoData.dcVoltage }}</td>
</tr>
<tr>
<td>直流电流A</td>
<td class="text-c">{{ infoData.dcCurrent }}</td>
</tr>
<tr>
<tr>
<td>A相电压V</td>
<td class="text-c">{{ infoData.voltageA }}</td>
</tr>
<tr>
<tr>
<td>A相电流A</td>
<td class="text-c">{{ infoData.currentA }}</td>
</tr>
<tr>
<tr>
<td>B相电压V</td>
<td class="text-c">{{ infoData.voltageB }}</td>
</tr>
<tr>
<tr>
<td>B相电流A</td>
<td class="text-c">{{ infoData.currentB }}</td>
</tr>
<tr>
<tr>
<td>C相电压V</td>
<td class="text-c">{{ infoData.voltageC }}</td>
</tr>
<tr>
<tr>
<td>C相电流A</td>
<td class="text-c">{{ infoData.currentC }}</td>
</tr>
</table>
<table border="2" class="tb2" :class="itemStateClass(infoData.state).clas">
<tr>
<td>日发电量kWh</td>
<td class="text-c">{{ infoData.dayEnergy }}</td>
</tr>
<tr>
<td>总发电量kWh</td>
<td class="text-c">{{ infoData.totalEnergy }}</td>
</tr>
<tr>
<td>逆变器效率</td>
<td class="text-c">{{ infoData.inverterFrequency }}</td>
</tr>
<tr>
<td>并网频率</td>
<td class="text-c">{{ infoData.frequency }}</td>
</tr>
<tr>
<td>功率因数</td>
<td class="text-c">{{ infoData.powerFactor }}</td>
</tr>
<tr>
<td>散热器温度°C</td>
<td class="text-c">{{ infoData.temperature }}</td>
</tr>
<tr>
<td>额定输出功率kW</td>
<td class="text-c">{{ infoData.ratedOutputPower }}</td>
</tr>
<tr>
<td>无功功率kW</td>
<td class="text-c">{{ infoData.noHavePower }}</td>
</tr>
<tr>
<td>AB线电压V</td>
<td class="text-c">{{ infoData.voltageA }}</td>
</tr>
<tr>
<td>A相并网电流A</td>
<td class="text-c">{{ infoData.currentA }}</td>
</tr>
<tr>
<td>BC线电压V</td>
<td class="text-c">{{ infoData.voltageB }}</td>
</tr>
<tr>
<td>B相并网电流A</td>
<td class="text-c">{{ infoData.currentB }}</td>
</tr>
<tr>
<td>CA线电压V</td>
<td class="text-c">{{ infoData.voltageC }}</td>
</tr>
<tr>
<td>C相并网电流A</td>
<td class="text-c">{{ infoData.currentC }}</td>
</tr>
</table>
</div>
<div class="report-item-bottom flex flex-column " v-show="type === 'second'">
<table border="2" :class="itemStateClass(infoData.state).clas">
<tr v-for="(item, index) in infoData._itemList" :key="index">
<td>光伏组串{{index + 1 }}</td>
<td class="text-c">{{ item.value }}</td>
</tr>
</table>
<table border="2" class="tb2" :class="itemStateClass(infoData.state).clas">
<tr>
<td>机内空气温度</td>
<td class="text-c">{{ infoData.temperature }}</td>
</tr>
<tr>
<td>总有功功率</td>
<td class="text-c">{{ infoData.totalHavePower }}</td>
</tr>
<tr>
<td>总无功功率</td>
<td class="text-c">{{ infoData.noHavePower }}</td>
</tr>
<tr>
<td>电网频率</td>
<td class="text-c">{{ infoData.frequency }}</td>
</tr>
<tr>
<td>额定输出功率</td>
<td class="text-c">{{ infoData.ratedOutputPower }}</td>
</tr >
<tr>
<td>效率</td>
<td class="text-c">{{ infoData.inverterFrequency }}</td>
</tr>
<tr>
<td>今日发电</td>
<td class="text-c">{{ infoData.dayEnergy }}</td>
</tr>
<tr>
<td>累计发电</td>
<td class="text-c">{{ infoData.totalEnergy }}</td>
</tr>
<tr>
<td>总运行时长</td>
<td class="text-c">{{ infoData.totalRunTime }}</td>
</tr>
</table>
</div>
</view>
<u-datetime-picker
:show="show"
v-model="timeVal"
mode="date"
@confirm="handleConfirmTime"
@cancel="handleCanceTime"
></u-datetime-picker>
<u-modal :show="showConfig" @confirm="handleConfirmConfig" ref="uModal"
@cancel="handleCloseConfig"
:showCancelButton="true" :asyncClose="true">
<template class="slot-content">
<view style="width:100%">
<uni-section title="限制功率(%)(0-110)">
<template v-slot:right>
<uni-number-box v-model="numVal" :min="0" :step="0.1" :max="110" ></uni-number-box>
</template>
</uni-section>
</view>
</template>
</u-modal>
</view>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
import { scrollSmoothTo } from '@/common/util/index.js'
import echarts from '@/components/echarts-uniapp/echarts-uniapp.vue'
import '@/common/util/day.js'
import {
getBigScreenPowerPinLianSubarrayView,
getBigScreenPowerInverterInfo,
getBigScreenPowerInverterInfo2,
getBigScreenPowerInverterInfoMatrixView,
getBigScreenPowerInverterAGC,
getBigScreenPowerInverterMqttBySn
} from '@/api/modules/station.js'
import _mixin from './mixin.js'
let myChart = null
// 1集中2组串
const FIRST_STATIONS = [
'1052758019', '1052758018', '1052758020', '1052758021', '1052758022'
]
// 不需要显示采集器的电站,分组
const UN_SHOW_STATIONS = [
'23', '22', '2'
]
const END_NUM = 65535
let SECOND_VALUE = ''
let timer = null
export default {
components:{
echarts
},
mixins: [_mixin],
data() {
return {
value4: true,
show: false,
showConfig: false,
timeVal: Number(new Date()),
timer: new Date().format('YYYY-MM-DD'),
option: {},
secondValue: '',
secondSnNo: 0,
selectStations: [],
chartData: {},
type: 'first',
isChange: false,
secondList: [],
secondValueList: [],
infoData:{},
numVal: 0
}
},
mounted() {
this.init()
},
methods: {
handleCloseConfig() {
this.showConfig = false
},
handleConfirmConfig() {
const params = {
sn: this.secondSnNo,
powerLimit: this.numVal
}
if (timer && this.showConfig) return
clearTimeout(timer)
getBigScreenPowerInverterAGC(params).then(res => {
timer = setTimeout(() => {
this.handleSetConfig('second')
clearTimeout(timer)
timer = null
}, 3000)
})
},
handleSetConfig(type = 'init') {
if (!this.secondSnNo) return
const sn = this.secondSnNo
getBigScreenPowerInverterMqttBySn({ sn }).then(res => {
const data = res.data.data
if (!data) {
this.$refs.uToast.show({
message: '未配置系统参数',
type: 'default',
complete() {
}
})
return
}
this.showConfig = true
const mqtt = JSON.parse(data.mqttMessage)
this.numVal = mqtt.p
const that = this
if (type !== 'init') {
that.showConfig = false
this.$refs.uToast.show({
message: '配置成功',
type: 'default',
complete() {
}
})
}
})
},
handlerBack() {
this.$router.replace('/pages/station/item1')
},
onChangeTime(val) {
this.timer = val
this.timeVal = Number(new Date())
this.getChartDataList()
},
onchange(e) {
this.selectStations = e.detail.value.map(v => v.value)
uni.setStorageSync('_pro_selectStation', this.selectStations)
this.isChange = true
SECOND_VALUE = null
this.type = FIRST_STATIONS.includes(this.selectStations[0]) ? 'first' : 'second'
this.getDataListInfo(this.type, 'change')
scrollSmoothTo()
},
onchange1(e) {
this.secondValueList = e.detail.value.map(v => v.value)
this.secondValue = this.secondValueList[0]
this.isChange = true
this.secondSnNo = this.secondList.filter(v => v.value === this.secondValue)[0].snNo
this.getDataInfo(this.secondValue)
this.onChangeTime(new Date().format('YYYY-MM-DD'))
scrollSmoothTo()
},
init() {
const hasLocalData = this.selectStations.length
const stationId = hasLocalData ? this.selectStations[0] : this.$route.query.id
const data = hasLocalData ? this.selectStations : [stationId, this.$route.query.sd]
this.selectStations = data
this.station = this.stationData.filter(v => {
return v.id === data[0]
})[0]
this.type = FIRST_STATIONS.includes(data[0]) ? 'first' : 'second'
uni.setStorageSync('_pro_selectStation', this.selectStations)
this.getDataListInfo(this.type)
},
getDataListInfo(type = 'first', type1 = 'base') {
const data = {
stationId: this.selectStations[0],
powerStationPartitionId: this.selectStations[1]
}
const METHOD = {
'first': getBigScreenPowerInverterInfo,
'second': getBigScreenPowerInverterInfo2
}
METHOD[type](data).then(res => {
this.handleFilterSecondArr(res.data.data, type, type1)
})
},
handleFilterSecondArr(arr, type, type1) {
if (type === 'second') {
const item = arr[0]
const maxNum = this._getMaxNum(item)
this.secondList = Array.from(Array(maxNum)).map((v, inde) => {
const index = inde + 1
return {
name: item[`equipmentName${index}`].split(' ')[1],
value: item[`inverterInfoId${index}`],
snNo: item[`sn${index}`]
}
})
} else {
this.secondList = arr.map(v => {
return {
name: v.equipmentName.split(' ')[1],
value: v.id,
snNo: v.sn
}
})
}
const seList = this.secondList.filter(v => v.value === this.$route.query.ud)
this.secondValue = SECOND_VALUE ? SECOND_VALUE : type1 !== 'base' ?
this.secondList[0].value : seList.length ? seList[0].value : this.secondList[0].value
this.secondSnNo = this.secondList.filter(v => v.value === this.secondValue)[0].snNo
this.secondValueList = [this.secondValue]
this.getDataInfo(this.secondValue)
this.getChartDataList()
},
getDataInfo(inverterInfoId) {
getBigScreenPowerInverterInfoMatrixView(
{
inverterInfoId
}
).then(res => {
const _data = res.data.data
const maxNum = this._getMaxNum(_data, 'electricQuantity')
const _itemList = Array.from(Array(maxNum)).map((v, inde) => {
const index = inde + 1
return {
value: _data[`electricQuantity${index}`],
}
})
_data._name = _data.equipmentName.split(' ')[1]
this.infoData = Object.assign({_itemList }, _data)
})
},
handleConfirmTime(e) {
this.timer = new Date(e.value).format('YYYY-MM-DD')
this.show = false
this.getChartDataList()
},
handleCanceTime() {
this.show = false
},
getChartDataList() {
2 years ago
const data = {
createTime: this.timer,
id: this.secondValue,
stationId: this.selectStations[0]
}
const type1 = '日发电量'
const type2 = '总有功功率'
const type3 = '总直流电流'
const types = [type1, type2, type3]
getBigScreenPowerPinLianSubarrayView(data).then(res => {
if (!res.data.data.length) {
this.setChartData()
return
}
const map = new Map()
res.data.data.forEach(v => {
types.forEach(cv => {
if (v.type.includes(cv)) {
if (map.has(cv)) {
const item = map.get(cv)
item[v.name] = v
map.set(cv, item)
} else {
map.set(cv, {[v.name]: v})
}
}
})
})
function resetList(list) {
if (!list) return []
return list.filter(v => {
const [hour, mint] = v.name.split(':')
const _hour = Number(hour)
const _mint = Number(mint)
if (_hour >= 5 && _mint > 0) {
return v
}
})
}
this.chartData = {
type1: {
name: type1,
list: resetList(Object.values(map.get(type1))) || []
},
type2: {
name: type2,
list: resetList(Object.values(map.get(type2))) || []
},
type3: {
name: type3,
list: resetList(Object.values(map.get(type3))) || []
}
}
this.setChartData(this.chartData)
})
},
setChartData(chartData = {}, type = '') {
console.log(chartData)
if (!Object.keys(chartData).length) {
this.option = option
return
}
2 years ago
const option = this.getChartOption(chartData)
this.option = option
},
_getMaxNum(item, text = 'dayEnergy') {
let maxNum = 1
for (let i = 1; i<= 50; i++) {
if (!item[text + i]) {
maxNum = i-1
break
}
}
return maxNum
},
getChartOption(chartData = {}) {
return {
legend: {
data: Object.values(chartData).map(v => v.name),
textStyle: {
color: '#f2f2f2'
}
},
tooltip: {
trigger: 'axis',
formatter(params) {
let html = ''
params.forEach(v => {
const type = v.seriesName.includes('日发电量') ? 'kWh' : v.seriesName.includes('有功功率') ? 'kW' : 'A'
html += `\n${v.marker} ${v.seriesName} ${v.value} ${type}`
})
return `\t${params[0].name}\t ${html}\t`
}
},
grid: {
top: '20%',
left: '3%',
right: '3%',
bottom: '10%',
// 包含文本
containLabel: true,
// 是否显示网格线
show: false,
// 边框颜色
borderColor: 'rgba(0, 240, 255, 0.3)',
},
xAxis: {
type: 'category',
// show: false,
data: chartData.type1.list.map(v => v.name),
axisLabel: {
color: "#f2f2f2"
}
},
yAxis: [
{
name: 'kW/A',
type: 'value',
nameTextStyle: {
color: "#f2f2f2"
},
axisLabel: {
color: "#f2f2f2"
},
axisLine: {
onZero: false,
show: true,
color: 'red'
},
// max: 10
},
{
name: 'kWh',
type: 'value',
nameTextStyle: {
color: "#f2f2f2"
},
axisLabel: {
color: "#f2f2f2"
},
axisLine: {
onZero: false,
show: true,
color: 'red'
},
}
],
series: [
{
data: chartData.type1.list,
type: 'line',
lineStyle: {
color: "#00ec03"
},
itemStyle: {
opacity: 0
},
color: "#00ec03",
name: chartData.type1.name,
yAxisIndex: 1,
},
{
data: chartData.type2.list,
type: 'line',
lineStyle: {
color: "#e000ec"
},
itemStyle: {
opacity: 0
},
color: "#e000ec",
name: chartData.type2.name,
},
{
data: chartData.type3.list,
type: 'line',
// lineStyle: {
// color: "#e000ec"
// },
itemStyle: {
opacity: 0
},
name: chartData.type3.name
}
]
}
},
}
}
</script>
<style lang="scss">
/deep/ .selected-list{
align-items: center;
}
.uni-ec-canvas{
width:100%;
height:550upx;
display:block;
}
.container {
padding: 20upx 0;
}
.content {
padding: 20upx;
.timer {
margin-bottom: 20upx;
}
background: #000;
color: #f5f5f5;
}
.search-box {
position: sticky;
top: 90upx;
width: 100%;
z-index: 2;
}
.report-status {
color: #555;
transform: scale(0.85);
// margin-left: -110upx;
padding-bottom: 20upx;
.report-status-item {
margin-top: 4upx;
}
.item {
margin-right: 10upx;
.bg {
display: block;
width: 50upx;
height: 30upx;
margin-right: 2px;
border: 1px solid #ccc;
&.s1 {
background: #00a403;
}
&.s2 {
background: #ff0000;
}
&.s3 {
background: #fc6;
}
&.s4 {
background: #808080;
}
}
}
}
.report-item-bottom {
padding: 40upx;
table.tb2 {
margin-top: 20upx;
}
tr td {
width: 50%;
}
table {
&.z1 {
// color: #00d40e;
tr td{
&:nth-child(2) {
color: #00d40e;
}
}
}
&.z2 {
// color: #ff0000;
td{
&:nth-child(2) {
color: #ff0000;
}
}
}
&.z3 {
// color: #fc6;
tr td{
&:nth-child(2) {
color: #fc6;
}
}
}
&.z4 {
// color: #808080;
td{
&:nth-child(2) {
color: #808080;
}
}
}
}
}
</style>