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.

770 lines
20 KiB

2 years ago
<template>
<view>
<uni-nav-bar left-icon="left" fixed="true" title="" @clickLeft="handleClickLeft"></uni-nav-bar>
<view class="station-box">
<view class="station-search-box">
<uni-section title="选择电站" type="line" padding="10px" >
<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-section>
<uni-section title="设备状态" type="line" padding="" >
<div class="report-status">
<div class="report-status-item">
<div class="flex flex-row-center ">
<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>
<div class="report-status-item" v-show="showSecond">
<div class="flex flex-column-start">
<div>组串</div>
<div>
<div class="flex">
<div class="item flex flex-center">
<i class="bg z1"></i>
<span class="text">正常</span>
</div>
<div class="item flex flex-center">
<i class="bg z2"></i>
<span class="text">有警告</span>
</div>
<div class="item flex flex-center">
<i class="bg z3"></i>
<span class="text">未接入</span>
</div>
</div>
<div class="flex">
<div class="item flex flex-center">
<i class="bg z4"></i>
<span class="text">未关联或电流为0或关联错误</span>
</div>
</div>
</div>
</div>
</div>
</div>
</uni-section>
</view>
<view class="station-content">
<uni-section title="采集器" type="line">
<template v-slot:right >
<view class="second-status" :class="allOffLineState ? 'z4' : 'z1'" v-show="showSecond" @click="handleGetStatus">
{{ secondData.collectorName }}
</view>
</template>
<block v-if="type==='second'">
<u-collapse :value="['1']" class="second-class">
<u-collapse-item title="数据" name="1">
<view class="content-box">
<div class="report-item1 c3">
<div class="item flex" :class="itemStateClass(item.state).clas" v-for="item in secondList" :key="item.id">
<div class="item-img">
<div class="img-list flex flex-wrap base-item">
<div :class="['img-it'
, itemClass(it.electricQuantity)
]" v-for="(it,ind) in item.list" :key="ind">
{{ it.electricQuantity | itemNum }}
</div>
</div>
<div class="img-text">
{{ item.equipmentName }}
</div>
</div>
<div class="item-info flex" @click="handleGetDetail(item)">
<div class="info-img">
<img :src="`/static/station/${item.state === '1' ? 'zc1' : 'zc2'}.png`" alt="">
</div>
<div :class="['info-text text-state', itemStateClass(item.state).clas]">
<div>
{{ item.totalHavePower }}
</div>
<div>{{ item.dayEnergy }}</div>
</div>
</div>
</div>
</div>
</view>
</u-collapse-item>
</u-collapse>
</block>
<block v-if="type==='first'">
<u-collapse accordion :value="0" class="first-class">
<u-collapse-item
:name="index"
:title="item.key"
v-for="(item, index) in firstList"
:key="item.key"
>
<view class="content-box">
<div class="info-box-list flex flex-center" v-for="it in item.arr" :key="it.id">
<div class="info-img flex flex-column flex-center" @click="handleGetDetail(it)">
<img :src="`/static/station/${it.state === '1' ? 'b2' : 'b1'}.png`" alt="">
<div class="info-text">{{ it._sName }}</div>
<td :class="['text text-state flex flex-center jc-center', itemStateClass(it.state).clas]">
<div>{{ itemStateClass(it.state).text }}</div>
</td>
</div>
<table border="2" class="info-detail">
<tr class="row flex">
<td class="name flex">
<div>直流电压/</div>
</td>
<td :class="['text text-state flex flex-center jc-center', itemStateClass(it.state).clas]">
<div>{{ it.dcVoltage || '#' }} / {{ it.dcCurrent || '#'}}</div>
</td>
</tr>
<tr class="row flex">
<td class="name flex "><div>总有功功率</div></td>
<td :class="['text text-state flex flex-center jc-center', itemStateClass(it.state).clas]">
<!-- <div>#V</div>-->
<!-- <div class="text2">#A</div>-->
<div>{{ it.totalHavePower || '#' }}</div>
</td>
</tr>
<tr class="row flex">
<td class="name flex">
<div>日发电量</div>
</td>
<td :class="['text text-state flex flex-center jc-center', itemStateClass(it.state).clas]">
<div>{{ it.dayEnergy || '#'}}</div>
</td>
</tr>
<tr class="row flex">
<td class="name flex">
<div>总发电量</div>
</td>
<td :class="['text text-state flex flex-center jc-center', itemStateClass(it.state).clas]">
<div>{{ it.totalEnergy || '#'}}</div>
</td>
</tr>
</table>
</div>
</view>
</u-collapse-item>
</u-collapse>
</block>
</uni-section>
</view>
</view>
<u-action-sheet
:show="show4"
@close="show4 = false"
title="标题位置"
:round="10"
>
<view>
<div class="report-pos-info item2-total-info" :class="allOffLineState ? 'z4' : 'z1'">
<div class="item2 flex flex-center flex-column">
<img src="/static/station/B0.jpg" alt="">
<div class="text">{{ secondData.collectorName }} 采集器</div>
</div>
<div class="item3 flex flex-center" v-show="showItemDetail">
<table border="3">
<tr>
<td>接入设备总数</td>
<td >{{ secondData.equipmentQuantity }}</td>
</tr>
<tr>
<td>故障设备总数</td>
<td>{{ secondData.faultEquipmentQuantity }}</td>
</tr>
<tr>
<td>温度</td>
<td>{{ secondData.temperature }}</td>
</tr>
<tr>
<td>湿度</td>
<td>{{ secondData.humidity }}</td>
</tr>
<tr>
<td>总有功功率</td>
<td>{{ secondData.totalActivePower }}</td>
</tr>
<tr>
<td>今日发电</td>
<td>{{ secondData.dayEnergy }}</td>
</tr>
<tr>
<td>累计发电</td>
<td>{{ secondData.totalEnergy }}</td>
</tr>
</table>
</div>
</div>
</view>
<u-status-bar></u-status-bar>
</u-action-sheet>
<u-status-bar></u-status-bar>
</view>
</template>
<script>
import { scrollSmoothTo } from '@/common/util/index.js'
import _mixin from './mixin.js'
import { getBigScreenPowerInverterInfo, getBigScreenPowerInverterInfo2 } from '@/api/modules/station.js'
// 1集中2组串
const FIRST_STATIONS = [
'1052758019', '1052758018', '1052758020', '1052758021', '1052758022'
]
// 不需要显示采集器的电站,分组
const UN_SHOW_STATIONS = [
'23', '22', '2'
]
const END_NUM = 65535
export default {
data() {
return {
modalName: null,
index: 0,
selectStations: uni.getStorageSync('_pro_selectStation') || [],
accordionVal:'1',
station: {},
type: 'first',
firstList: [],
secondList: [],
secondData: {},
show4: false,
allOffLineState: false
}
},
mixins: [_mixin],
created() {
this.initData()
},
filters: {
itemNum(data) {
if (!data) return ''
return data <= 0 || data === END_NUM ? '' : data
},
itemName(data) {
if (!data) return ''
return data.split(' ')[1]
},
},
computed: {
showItemDetail() {
return this.selectStations.length ? !UN_SHOW_STATIONS.includes(this.selectStations[1]) : false
},
showSecond(){
return this.type === 'second'
},
},
methods: {
handleGetDetail(item) {
uni.removeStorageSync('_pro_selectStation')
this.$router.push({
name: 'stationListItem2',
query: {
id: this.selectStations[0],
sd: this.selectStations[1],
ud: item.id
}
})
},
handleClickLeft() {
uni.removeStorageSync('_pro_selectStation')
this.$router.replace('/pages/station/list')
},
initData() {
const hasLocalData = this.selectStations.length
const stationId = hasLocalData ? this.selectStations[0] : this.$route.query.id
const station = this.stationData.filter(v => {
return v.id === stationId
})
const data = hasLocalData ? this.selectStations :
station.length ?
[station[0].id, station[0].children[0].id]
:[this.stationData[0].id, this.stationData[0].children[0].id]
this.selectStations = data
this.station = this.stationData.filter(v => {
return v.id === data[0]
})[0]
this.type = FIRST_STATIONS.includes(data[0]) ? 'first' : 'second'
this.getDataInfo(this.type)
},
getDataInfo(type = 'first') {
const data = {
stationId: this.selectStations[0],
powerStationPartitionId: this.selectStations[1]
}
const METHOD = {
'first': getBigScreenPowerInverterInfo,
'second': getBigScreenPowerInverterInfo2
}
METHOD[type](data).then(res => {
if (type === 'first') {
const _data = res.data.data.map(v => {
v._tip = v.equipmentName.split(' ')[1].split('-')[0]
return v
})
this.firstList = this.handleFilterArray(_data)
} else {
this.secondData = this.handleFilterSecondArr(res.data.data)
}
})
},
handleFilterSecondArr(arr) {
const item = arr[0]
let maxNum = 1
for (let i = 1; i<= 50; i++) {
if (!item['dayEnergy' + i]) {
maxNum = i-1
break
}
}
// width: 183px;
const eightNumArr = ['1052758023'] // 塞纳8个组串
this.itemNum = eightNumArr.includes(this.selectStations[0]) ? 8 : 12
this.secondList = Array.from(Array(maxNum)).map((v, inde) => {
const index = inde + 1
const cList = Array.from(Array(this.itemNum)).map((cv, cIndex) => {
const _cIndex = cIndex + 1
const num = item[`electricQuantity${index}_${_cIndex}`].split('A')[0]
const reg = /^65/g
const is65535 = reg.test(num)
const _num = is65535 ? num.split('.').join('') : num
return {
id: '',
electricQuantity: parseFloat(_num),
}
})
return {
list: cList,
dayEnergy: item[`dayEnergy${index}`],
equipmentName: item[`equipmentName${index}`].split(' ')[1],
id: item[`inverterInfoId${index}`],
state: item[`state${index}`],
totalHavePower: item[`totalHavePower${index}`],
offLineState: cList.every(v => v.electricQuantity <= 0 || v.electricQuantity === END_NUM )
}
}).sort((a, b) => a.equipmentName.localeCompare(b.equipmentName, 'zh-CN'))
this.allOffLineState = this.secondList.every(v => v.offLineState)
return item
},
handleFilterArray(arr) {
const data = arr.reduce((c, v) => {
c[v._tip] = c[v._tip] || []
c[v._tip].push(v)
return c
}, {})
const data1 = Object.keys(data).map(v => {
const mat = v.match(/(\d)+/g)
const arr = data[v].map(v => {
v._sName = v.equipmentName.split(' ')[1]
return v
}).sort((a, b) => a._sName.localeCompare(b._sName, 'zh-CN'))
const num = mat.length ? mat[0] : 0
return {
key: v,
num,
arr
}
}).sort((a, b) => a.num- b.num)
this.firstListMaxLength = data1.reduce((c, v) => {
c = c >= v.arr.length ? c : v.arr.length
return c
}, 1)
return data1
},
handleGetStatus() {
this.show4 = true
},
itemClass(_data) {
const offLineArr = ['1052758027'] // 健堂口 数值为0和未接入的都是黑色
const id = this.selectStations[0]
let str = ''
if (offLineArr.includes(id)) {
str = _data <= 0 || _data === END_NUM ? 'z3' : 'z1'
} else {
str = _data <= 0 ? 'z4' : _data === END_NUM ? 'z3' : 'z1'
}
return str
},
onnodeclick(e) {
console.log(e);
},
onchange(e) {
this.selectStations = e.detail.value.map(v => v.value)
uni.setStorageSync('_pro_selectStation', this.selectStations)
this.initData()
scrollSmoothTo(0);
},
handlerChangeStation(e) {
// this.station = this.stationData[this.index]
},
change(e) {
console.log(e);
}
}
}
</script>
<style lang="scss">
:root {
--c-green: #00d40e;
//--c-z1: #1d49a8;
--c-z1: #0c4ad1;
--c-z2: #ff0000;
--c-z3: #000;
--c-z4: #808080;
--c-z5: #fc6;
}
/deep/ .selected-list{
align-items: center;
}
/deep/ .u-collapse-item__content__text {
background-color: rgba(0,0,0, .8);
}
/deep/ .second-class .u-collapse-item__content {
height: auto !important;
}
/deep/ .u-action-sheet {
background: #000;
}
/deep/ .u-action-sheet__header__title {
color: #000;
}
html, body {
scroll-behavior:smooth;
}
.second-status {
&.z1 {
color:#00d40e;
}
&.z4 {
color: #808080;
}
}
.report-status {
// position: absolute;
// left: 68%;
// top: 2px;
color: #555;
transform: scale(0.85);
margin-left: -50upx;
.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;
}
&.z1 {
background: #0c4ad1;
}
&.z2 {
background: #ff0000;
}
&.z3 {
background: #000;
}
&.z4 {
background: #808080;
}
}
}
}
.report-pos-info {
z-index: 1;
padding-bottom: 20upx;
color: #f5f5f5;
background-color: #000;
&.item2-total-info {
&.z1 {
table {
td:nth-child(2) {
color: #00d40e;
}
}
.text {
color:#00d40e;
}
}
&.z4 {
td:nth-child(2) {
color: #808080;
}
.text {
color: #808080;
}
}
}
.item1,.item2,.item3 {
margin-top: 10upx;
img {
width: 240upx;
}
.text {
margin-top:5upx;
}
table {
font-size: 18upx;
td {
padding: 4upx 10upx;
//padding-left: 20px;
//width: 180px;
}
}
}
.item2 {
img {
width: 100upx;
}
}
}
.station-box {
// padding: 0 10px 10px 10px;
padding-top: 10px;
padding-bottom: 10px;
font-size: 24upx;
.station-content {
margin-top: 5px;
padding: 5px 0;
.content-box {
margin: 5px auto;
padding: 0 10px;
}
.report-item1 {
color: #f6f6f6;
display: grid;
// height:100%;
grid-row-gap: 5upx;
grid-column-gap: 20upx;
grid-template-columns: 100%;
grid-template-rows:repeat(auto-fill,150upx);
place-items: center center;
.item {
//width: 100%;
//height: 100%;
&.z1 {
color: #00d40e;
}
&.z2 {
color: #ff0000;
}
&.z3 {
color: #fc6;
}
&.z4 {
color: #808080;
}
.item-img {
//width: 60%;
.img-list {
width: 450upx;
border: 1px solid #f5f5f5;
padding: 2upx;
justify-content: space-around;
&.eight-item {
width: 184upx;
}
.img-it {
width: 70upx;
height: 40upx;
border: 1px solid #fff;
transform: scale(0.85);
background-size: 4upx 4upx;
text-align: center;
line-height: 40upx;
font-size: 24upx;
color: #fff;
&.z1 {
background-color: #0c4ad1;
}
&.z2 {
background-color: #ff0000;
}
&.z3 {
background-color: #000;
}
&.z4 {
background-color: #808080;
}
}
}
.img-text {
text-align: right;
margin-right: -20upx;
margin-top: 4upx;
font-size: 14upx;
}
}
.item-info {
margin-left: 10upx;
&.z1 {
.info-text {
color: #00d40e;
}
}
&.z2 {
.info-text {
color: #ff0000;
}
}
&.z3 {
.info-text {
color: #fc6;
}
}
.info-img {
width: 80upx;
image, img {
width: 100%;
}
}
.info-text {
font-size: 26upx;
line-height: 1.6;
}
}
}
}
}
.station-search-box {
position: sticky;
top: 90upx;
width: 100%;
z-index: 2;
}
.info-box-list {
// margin-left: 5upx;
//width: 25%;
//flex-shrink: 0;
color: #fff;
padding: 10upx 0;
// background-color: rgba(0,0,0, 0.6);
&:not(:first-child) {
margin-top: 6upx;
}
&.base {
.text {
color: #fff;
}
}
&.nor {
.text-c, .info-text1 {
color: #00d40e;
}
}
.text-state {
font-size: 18upx;
&.z1 {
color: #00d40e;
}
&.z2 {
color: #ff0000;
}
&.z3 {
color: #fc6;
}
&.z4 {
color: #808080;
}
}
.info-detail {
font-size: 14upx;
margin-left: 10upx;
.row {
td {
padding: 8upx;
}
.name {
width: 140upx;
}
.text {
width: 180upx;
.text2 {
margin-left: 20upx;
}
}
}
}
.info-img {
width: 220upx;
font-size: 28upx;
transform: scale(0.86);
img {
width: 100%;
}
.info-text1 {
margin-top: 10upx;
font-size: 24upx;
}
}
}
}
</style>