Merge branch 'develop' into single-develop
This commit is contained in:
BIN
src/assets/images/ems/bigData.png
Normal file
BIN
src/assets/images/ems/bigData.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 MiB |
@ -104,6 +104,10 @@
|
||||
.el-card__header {
|
||||
background-color: #b64040; //#fc6b69;
|
||||
}
|
||||
|
||||
.work-status {
|
||||
color: #b64040 !important;;
|
||||
}
|
||||
}
|
||||
|
||||
//绿色背景颜色标题
|
||||
@ -111,6 +115,10 @@
|
||||
.el-card__header {
|
||||
background-color: #40b6a5; //#05aea3;
|
||||
}
|
||||
|
||||
.work-status {
|
||||
color: #40b6a5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
//灰色背景颜色标题
|
||||
@ -118,6 +126,10 @@
|
||||
.el-card__header {
|
||||
background-color: #666666;
|
||||
}
|
||||
|
||||
.work-status {
|
||||
color: #666666 !important;;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
src/components/BigDataPopup/index.vue
Normal file
49
src/components/BigDataPopup/index.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<el-dialog :fullscreen="true" :append-to-body="true" :visible.sync="show" :show-close="false" top="0"
|
||||
custom-class="big-data-dialog">
|
||||
<img src="@/assets/images/ems/bigData.png" alt="">
|
||||
<div class="close-btn" @click="show=false">
|
||||
<i class="el-icon-close"></i>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
font-size: 23px;
|
||||
line-height: 20px;
|
||||
color: rgba(176, 228, 255, 0.7);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.big-data-dialog {
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,36 +1,68 @@
|
||||
<template>
|
||||
<div class="time-range">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
value-format="yyyy-MM-dd"
|
||||
:clearable="false"
|
||||
:picker-options="pickerOptions"
|
||||
end-placeholder="结束时间">
|
||||
</el-date-picker>
|
||||
<el-button size="mini" style="margin-left: 10px;" :loading="loading" @click="reset">重置</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="search">搜索</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('before')">上一时段</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('next')" :disabled="disabledNextBtn">下一时段</el-button>
|
||||
</div>
|
||||
<div class="time-range">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
:class="miniTimePicker ? 'mini-date-picker' : ''"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
value-format="yyyy-MM-dd"
|
||||
:clearable="false"
|
||||
:picker-options="pickerOptions"
|
||||
end-placeholder="结束时间">
|
||||
</el-date-picker>
|
||||
<template v-if="!showIcon">
|
||||
<el-button size="mini" style="margin-left: 10px;" :loading="loading" @click="reset">重置</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="search">搜索</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('before')">上一时段</el-button>
|
||||
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('next')" :disabled="disabledNextBtn">
|
||||
下一时段
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button class="btn-icon" icon="el-icon-refresh-right" circle size="mini" style="margin-left: 8px;"
|
||||
:loading="loading"
|
||||
@click="reset"></el-button>
|
||||
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-search" circle :loading="loading"
|
||||
@click="search"></el-button>
|
||||
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-d-arrow-left" circle :loading="loading"
|
||||
@click="timeLine('before')"></el-button>
|
||||
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-d-arrow-right" circle :loading="loading"
|
||||
@click="timeLine('next')"
|
||||
:disabled="disabledNextBtn"></el-button>
|
||||
</template>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {formatDate} from '@/filters/ems'
|
||||
|
||||
export default {
|
||||
computed:{
|
||||
disabledNextBtn(){
|
||||
props: {
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
miniTimePicker: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabledNextBtn() {
|
||||
return new Date(this.dateRange[1]) >= new Date(this.defaultDateRange[1])
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading:false,
|
||||
dateRange:[],
|
||||
defaultDateRange:[],
|
||||
pickerOptions:{
|
||||
loading: false,
|
||||
dateRange: [],
|
||||
defaultDateRange: [],
|
||||
pickerOptions: {
|
||||
disabledDate(time) {
|
||||
return time.getTime() > Date.now();
|
||||
},
|
||||
@ -38,64 +70,81 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(today=false){
|
||||
const now = new Date(),formatNow = formatDate(now);
|
||||
const weekAgo = formatDate(today ? new Date(now.getTime()) : new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000))
|
||||
this.dateRange = [weekAgo, formatNow];
|
||||
this.defaultDateRange=[weekAgo, formatNow];
|
||||
this.$emit('updateDate',this.dateRange)
|
||||
init(today = false) {
|
||||
const now = new Date(), formatNow = formatDate(now);
|
||||
const weekAgo = formatDate(today ? new Date(now.getTime()) : new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000))
|
||||
this.dateRange = [weekAgo, formatNow];
|
||||
this.defaultDateRange = [weekAgo, formatNow];
|
||||
this.$emit('updateDate', this.dateRange)
|
||||
},
|
||||
showBtnLoading(status){
|
||||
this.loading = status
|
||||
showBtnLoading(status) {
|
||||
this.loading = status
|
||||
},
|
||||
resetDate(){
|
||||
resetDate() {
|
||||
this.dateRange = this.defaultDateRange
|
||||
},
|
||||
//重置 设置时间范围为初始化时间段
|
||||
reset(){
|
||||
this.resetDate()
|
||||
this.$emit('reset')
|
||||
this.$emit('updateDate',this.dateRange)
|
||||
reset() {
|
||||
this.resetDate()
|
||||
this.$emit('reset')
|
||||
this.$emit('updateDate', this.dateRange)
|
||||
},
|
||||
// 搜索
|
||||
search(){
|
||||
this.$emit('updateDate',this.dateRange)
|
||||
search() {
|
||||
this.$emit('updateDate', this.dateRange)
|
||||
},
|
||||
timeLine(type){
|
||||
if(!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) return
|
||||
const nowStartTimes = new Date(this.dateRange[0]).getTime(),nowEndTimes = new Date(this.dateRange[1]).getTime(),maxTime = new Date(this.defaultDateRange[1]).getTime()
|
||||
timeLine(type) {
|
||||
if (!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) return
|
||||
const nowStartTimes = new Date(this.dateRange[0]).getTime(), nowEndTimes = new Date(this.dateRange[1]).getTime(),
|
||||
maxTime = new Date(this.defaultDateRange[1]).getTime()
|
||||
const nowDis = nowEndTimes - nowStartTimes//用户当前选择时间差 可能=0
|
||||
//baseTime,maxTime 毫秒数
|
||||
const baseDis = 24 * 60 * 60 * 1000
|
||||
const baseDis = 24 * 60 * 60 * 1000
|
||||
const calcDis = nowDis === 0 ? baseDis : nowDis
|
||||
let start = type === 'before' ? nowStartTimes - calcDis : nowStartTimes + calcDis
|
||||
if(start>maxTime) start=maxTime
|
||||
if (start > maxTime) start = maxTime
|
||||
let end = type === 'before' ? nowEndTimes - calcDis : nowEndTimes + calcDis
|
||||
if(end>maxTime) end=maxTime
|
||||
this.dateRange = [formatDate(start),formatDate(end)]
|
||||
this.$emit('updateDate',this.dateRange)
|
||||
if (end > maxTime) end = maxTime
|
||||
this.dateRange = [formatDate(start), formatDate(end)]
|
||||
this.$emit('updateDate', this.dateRange)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.time-range{
|
||||
display: flex;
|
||||
::v-deep {
|
||||
.el-range-editor--medium .el-range__icon, .el-range-editor--medium .el-range__close-icon{
|
||||
line-height: 22px;
|
||||
}
|
||||
.el-range-editor--medium.el-input__inner{
|
||||
height: 30px;
|
||||
}
|
||||
.el-range-editor--medium .el-range-separator{
|
||||
line-height: 24px;
|
||||
}
|
||||
.el-button--mini{
|
||||
padding:3px 10px;
|
||||
}
|
||||
.time-range {
|
||||
display: flex;
|
||||
|
||||
::v-deep {
|
||||
|
||||
.el-range-editor--medium .el-range__icon, .el-range-editor--medium .el-range__close-icon {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.el-range-editor--medium.el-input__inner {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.el-range-editor--medium .el-range-separator {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.el-button--mini {
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
// 展示icon的小组件
|
||||
.btn-icon.el-button--mini {
|
||||
padding: 3px 8px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
//小宽度时间选择框
|
||||
.mini-date-picker {
|
||||
width: 250px !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -32,13 +32,13 @@ export default {
|
||||
attr:'installCapacity'
|
||||
|
||||
},{
|
||||
title:'总充电量(MWh)',
|
||||
title:'总充电量(KWh)',
|
||||
num:'',
|
||||
color:'#A696FF',
|
||||
attr:'totalChargedCap'
|
||||
|
||||
},{
|
||||
title:'总放电量(MWh)',
|
||||
title:'总放电量(KWh)',
|
||||
num:'',
|
||||
color:'#A696FF',
|
||||
attr:'totalDischargedCap'
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container"
|
||||
@toggleClick="toggleSideBar"/>
|
||||
|
||||
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container" />
|
||||
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container" />
|
||||
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container"/>
|
||||
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container"/>
|
||||
|
||||
<div class="right-menu">
|
||||
<template v-if="device!=='mobile'">
|
||||
<search id="header-search" class="right-menu-item" />
|
||||
<div class="big-data-container">
|
||||
<i class="el-icon-s-marketing big-data-icon" @click.stop="showBigDataImg"></i>
|
||||
</div>
|
||||
|
||||
<search id="header-search" class="right-menu-item"/>
|
||||
|
||||
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect"/>
|
||||
|
||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
<size-select id="size-select" class="right-menu-item hover-effect"/>
|
||||
</el-tooltip>
|
||||
|
||||
</template>
|
||||
@ -32,22 +37,23 @@
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<div class="right-menu-item hover-effect setting" @click="setLayout" v-if="setting">
|
||||
<svg-icon icon-class="more-up" />
|
||||
<svg-icon icon-class="more-up"/>
|
||||
</div>
|
||||
</div>
|
||||
<BigDataPopup ref="bigDataPopup"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import {mapGetters} from 'vuex'
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import TopNav from '@/components/TopNav'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
import Screenfull from '@/components/Screenfull'
|
||||
import SizeSelect from '@/components/SizeSelect'
|
||||
import Search from '@/components/HeaderSearch'
|
||||
import BigDataPopup from '@/components/BigDataPopup'
|
||||
|
||||
export default {
|
||||
emits: ['setLayout'],
|
||||
@ -57,7 +63,8 @@ export default {
|
||||
Hamburger,
|
||||
Screenfull,
|
||||
SizeSelect,
|
||||
Search
|
||||
Search,
|
||||
BigDataPopup
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
@ -78,6 +85,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showBigDataImg() {
|
||||
this.$refs.bigDataPopup.show = true
|
||||
},
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
@ -93,7 +103,8 @@ export default {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = '/index'
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,7 +116,7 @@ export default {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
||||
|
||||
.hamburger-container {
|
||||
line-height: 46px;
|
||||
@ -113,7 +124,7 @@ export default {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
transition: background .3s;
|
||||
-webkit-tap-highlight-color:transparent;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, .025)
|
||||
@ -139,6 +150,17 @@ export default {
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
|
||||
.big-data-container {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
font-size: 24px;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
@ -177,7 +199,7 @@ export default {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-nickname{
|
||||
.user-nickname {
|
||||
position: relative;
|
||||
bottom: 10px;
|
||||
font-size: 14px;
|
||||
|
||||
@ -7,6 +7,8 @@ const ems = {
|
||||
zdList: [],
|
||||
zdDeviceCategoryOptions: {},//站点各个站点包含的设备种类 {021_DDS_01:["BATTERY","CLUSTER","STACK", "DH", "AMMETER", "PCS", "XF"],021_DDS_02:[]...}
|
||||
workStatusOptions: {'0': '运行', '1': '停机', '2': '故障'},//工作状态
|
||||
PCSWorkStatusOptions: {'0': '运行', '1': '停机', '2': '故障', '3': '待机', '4': '充电', '5': '放电'},//PCS工作状态
|
||||
STACKWorkStatusOptions: {"0": "净置", "1": "充电", "2": "放电", "3": "浮充", '9': "故障"},//STACK电池簇工作状态
|
||||
deviceStatusOptions: {'0': '离线', '1': '在线'},//设备状态
|
||||
gridStatusOptions: {'0': '并网', '1': '未并网'},//并网状态
|
||||
controlModeOptions: {'0': '远程', '1': '本地'},//控制模式
|
||||
|
||||
@ -1,30 +1,29 @@
|
||||
|
||||
<template>
|
||||
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
|
||||
<div slot="header" class="time-range-header">
|
||||
<span class="card-title">当日功率曲线</span>
|
||||
<date-range-select ref="dateRangeSelect" @updateDate="updateDate"/>
|
||||
</div>
|
||||
<div style="height: 310px" id="activeChart"></div>
|
||||
</el-card>
|
||||
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
|
||||
<div slot="header" class="time-range-header">
|
||||
<span class="card-title">当日功率曲线</span>
|
||||
<date-range-select ref="dateRangeSelect" :showIcon="true" :mini-time-picker="true" @updateDate="updateDate"/>
|
||||
</div>
|
||||
<div style="height: 310px" id="activeChart"></div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
import resize from '@/mixins/ems/resize'
|
||||
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
||||
import { getPointData } from '@/api/ems/dzjk'
|
||||
import {getPointData} from '@/api/ems/dzjk'
|
||||
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
||||
|
||||
export default {
|
||||
mixins: [resize,intervalUpdate],
|
||||
mixins: [resize, intervalUpdate],
|
||||
components: {DateRangeSelect},
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
timeRange:[],
|
||||
siteId:'',
|
||||
isInit:true
|
||||
timeRange: [],
|
||||
siteId: '',
|
||||
isInit: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -41,23 +40,23 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
// 更新时间范围 重置图表
|
||||
updateDate(data){
|
||||
this.timeRange=data
|
||||
updateDate(data) {
|
||||
this.timeRange = data
|
||||
!this.isInit && this.getGVQXData()
|
||||
this.isInit = false
|
||||
},
|
||||
getGVQXData(){
|
||||
getGVQXData() {
|
||||
this.showLoading()
|
||||
const {siteId,timeRange}=this
|
||||
getPointData({siteId,startDate:timeRange[0],endDate:timeRange[1]}).then(response => {
|
||||
const {siteId, timeRange} = this
|
||||
getPointData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => {
|
||||
this.setOption(response?.data || [])
|
||||
}).finally(()=>this.hideLoading())
|
||||
}).finally(() => this.hideLoading())
|
||||
},
|
||||
init(siteId){
|
||||
init(siteId) {
|
||||
//初始化 清空数据
|
||||
this.siteId = siteId
|
||||
this.isInit = true
|
||||
this.timeRange=[]
|
||||
this.timeRange = []
|
||||
this.$refs.dateRangeSelect.init(true)
|
||||
this.getGVQXData()
|
||||
this.updateInterval(this.getGVQXData)
|
||||
@ -65,17 +64,17 @@ export default {
|
||||
initChart() {
|
||||
this.chart = echarts.init(document.querySelector('#activeChart'))
|
||||
},
|
||||
showLoading(){
|
||||
showLoading() {
|
||||
this.chart && this.chart.showLoading()
|
||||
},
|
||||
hideLoading(){
|
||||
hideLoading() {
|
||||
this.chart && this.chart.hideLoading()
|
||||
},
|
||||
setOption(data) {
|
||||
const source = [['日期','电网功率','负载功率','储能功率','光伏功率','soc平均值','soh平均值','电池平均温度平均值']]
|
||||
console.log('source.slice(1)',source[0].slice(1))
|
||||
this.chart && data.forEach((item)=>{
|
||||
source.push([item.statisDate,item.gridPower,item.loadPower,item.storagePower,item.pvPower,item.avgSoc,item.avgSoh,item.avgTemp])
|
||||
const source = [['日期', '电网功率', '负载功率', '储能功率', '光伏功率', 'soc平均值', 'soh平均值', '电池平均温度平均值']]
|
||||
console.log('source.slice(1)', source[0].slice(1))
|
||||
this.chart && data.forEach((item) => {
|
||||
source.push([item.statisDate, item.gridPower, item.loadPower, item.storagePower, item.pvPower, item.avgSoc, item.avgSoh, item.avgTemp])
|
||||
})
|
||||
this.chart.setOption({
|
||||
grid: {
|
||||
@ -91,8 +90,8 @@ export default {
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
textStyle:{
|
||||
color:"#333333",
|
||||
textStyle: {
|
||||
color: "#333333",
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
@ -105,11 +104,17 @@ export default {
|
||||
type: 'value',
|
||||
},
|
||||
],
|
||||
dataset:{source},
|
||||
series: source[0].slice(1).map((item,index)=>{
|
||||
dataset: {source},
|
||||
series: source[0].slice(1).map((item, index) => {
|
||||
return {
|
||||
type: 'line',
|
||||
yAxisIndex:index<=4 ? 0 : 1
|
||||
type: 'line',//index === 5 ? 'bar' : 'line',
|
||||
showSymbol: false,
|
||||
symbolSize: 2,
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
yAxisIndex: index <= 4 ? 0 : 1
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
|
||||
<template>
|
||||
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
|
||||
<div slot="header" class="time-range-header">
|
||||
<span class="card-title">一周充放曲线</span>
|
||||
<date-range-select ref="dateRangeSelect" @updateDate="updateDate"/>
|
||||
</div>
|
||||
<div style="height: 310px" id="weekChart"></div>
|
||||
</el-card>
|
||||
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
|
||||
<div slot="header" class="time-range-header">
|
||||
<span class="card-title">一周充放曲线</span>
|
||||
<date-range-select ref="dateRangeSelect" :showIcon="true" :mini-time-picker="true" @updateDate="updateDate"/>
|
||||
</div>
|
||||
<div style="height: 310px" id="weekChart"></div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -14,14 +13,15 @@ import * as echarts from 'echarts'
|
||||
import resize from '@/mixins/ems/resize'
|
||||
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
||||
import {getSevenChargeData} from '@/api/ems/dzjk'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
components: {DateRangeSelect},
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
timeRange:[],
|
||||
siteId:'',
|
||||
timeRange: [],
|
||||
siteId: '',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -38,41 +38,40 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
// 更新时间范围 重置图表
|
||||
updateDate(data){
|
||||
this.timeRange=data
|
||||
updateDate(data) {
|
||||
this.timeRange = data
|
||||
this.getWeekKData()
|
||||
},
|
||||
getWeekKData(){
|
||||
getWeekKData() {
|
||||
this.showLoading()
|
||||
const {siteId,timeRange}=this
|
||||
this.hideLoading()
|
||||
getSevenChargeData({siteId,startDate:timeRange[0],endDate:timeRange[1]}).then(response => {
|
||||
const {siteId, timeRange} = this
|
||||
getSevenChargeData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => {
|
||||
this.setOption(response?.data || [])
|
||||
}).finally(()=>this.hideLoading())
|
||||
}).finally(() => this.hideLoading())
|
||||
},
|
||||
init(siteId){
|
||||
init(siteId) {
|
||||
//初始化 清空数据
|
||||
this.siteId = siteId
|
||||
this.timeRange=[]
|
||||
this.deviceId=''
|
||||
this.timeRange = []
|
||||
this.deviceId = ''
|
||||
this.$refs.dateRangeSelect.init()
|
||||
},
|
||||
initChart() {
|
||||
this.chart = echarts.init(document.querySelector('#weekChart'))
|
||||
},
|
||||
showLoading(){
|
||||
showLoading() {
|
||||
this.chart && this.chart.showLoading()
|
||||
},
|
||||
hideLoading(){
|
||||
hideLoading() {
|
||||
this.chart && this.chart.hideLoading()
|
||||
},
|
||||
setOption(data,unit) {
|
||||
const source = [['日期','充电量','放电量']]
|
||||
data.forEach(item=>{
|
||||
source.push([item.ammeterDate, item.chargedCap,item.disChargedCap])
|
||||
setOption(data, unit) {
|
||||
const source = [['日期', '充电量', '放电量']]
|
||||
data.forEach(item => {
|
||||
source.push([item.ammeterDate, item.chargedCap, item.disChargedCap])
|
||||
})
|
||||
this.chart && this.chart.setOption({
|
||||
color:['#4472c4','#70ad47'],//所有充放电颜色保持统一
|
||||
color: ['#4472c4', '#70ad47'],//所有充放电颜色保持统一
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
@ -88,29 +87,29 @@ export default {
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
name:unit,
|
||||
nameLocation:'center'
|
||||
name: unit,
|
||||
nameLocation: 'center'
|
||||
},
|
||||
yAxis: [{
|
||||
type: 'value',
|
||||
name:'充电量/放电量kWh',
|
||||
name: '充电量/放电量kWh',
|
||||
axisLine: {
|
||||
lineStyle:{
|
||||
lineStyle: {
|
||||
color: '#333333',
|
||||
},
|
||||
onZero:false
|
||||
onZero: false
|
||||
}
|
||||
}],
|
||||
dataset:{
|
||||
dataset: {
|
||||
source
|
||||
},
|
||||
series: [
|
||||
{
|
||||
yAxisIndex:0,
|
||||
yAxisIndex: 0,
|
||||
type: 'bar',
|
||||
},
|
||||
{
|
||||
yAxisIndex:0,
|
||||
yAxisIndex: 0,
|
||||
type: 'bar',
|
||||
},
|
||||
]
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-row style="background: #fff" class="row-container" :gutter="15">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<el-col :xs="24" :sm="24" :lg="5">
|
||||
<!-- 站点信息-->
|
||||
<el-card
|
||||
shadow="always"
|
||||
class="common-card-container common-card-container-body-no-padding"
|
||||
@ -12,49 +13,82 @@
|
||||
<div slot="header">
|
||||
<span class="card-title">站点信息</span>
|
||||
<div class="alarm-msg" v-if="tableData.length > 0" @click="toAlarm">
|
||||
<i class="el-icon-message-solid"></i>
|
||||
<i class="el-icon-message-solid"></i> 设备告警
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="box-sizing: border-box; height: 250px; padding: 20px 15px"
|
||||
style="box-sizing: border-box; height: 218px; padding: 20px 15px"
|
||||
>
|
||||
<el-descriptions class="home-normal-info" :column="1">
|
||||
<el-descriptions-item
|
||||
size="mini"
|
||||
v-for="(item, index) in singleZdInfo"
|
||||
:key="index + 'singleZdInfo'"
|
||||
:label="item.title"
|
||||
>{{ info[item.attr] | formatNumber }}
|
||||
</el-descriptions-item
|
||||
<!-- 地址、运行时间-->
|
||||
<div class="site-info site-info-address">
|
||||
<div class="title">
|
||||
<i class="el-icon-location"></i>
|
||||
</div>
|
||||
<div class="value">{{ info.siteAddress }}</div>
|
||||
</div>
|
||||
<div class="site-info">
|
||||
<div class="title">
|
||||
<i class="el-icon-date"></i>
|
||||
</div>
|
||||
<div class="value">{{ info.runningTime || '-' }}</div>
|
||||
</div>
|
||||
<!-- 装机功率、容量 -->
|
||||
<el-row :gutter="10" style="margin-top:20px;">
|
||||
<el-col
|
||||
:span="12"
|
||||
class="sjgl-col power-col"
|
||||
>
|
||||
</el-descriptions>
|
||||
<div class="sjgl-wrapper">
|
||||
<div class="sjgl-title">装机功率(MW)</div>
|
||||
<div class="sjgl-value">
|
||||
{{ info.installPower | formatNumber }}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col
|
||||
:span="12"
|
||||
class="sjgl-col power-col"
|
||||
>
|
||||
<div class="sjgl-wrapper">
|
||||
<div class="sjgl-title">装机容量(MW)</div>
|
||||
<div class="sjgl-value">
|
||||
{{ info.installCapacity | formatNumber }}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="16">
|
||||
<cl-info :info="runningInfo.strategyTempInfo"/>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="12">
|
||||
<!-- 总累计运行数据-->
|
||||
<el-col :xs="24" :sm="24" :lg="19">
|
||||
<el-card
|
||||
shadow="always"
|
||||
class="common-card-container common-card-container-body-no-padding"
|
||||
>
|
||||
<div slot="header">
|
||||
<span class="card-title">总累计运行数据</span>
|
||||
<div class="total-count">
|
||||
<span class="title">总收入</span>
|
||||
<span class="value">{{ runningInfo.totalRevenue | formatNumber }}</span>
|
||||
<span class="unit">元</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="box-sizing: border-box; height: 250px; padding: 20px 15px"
|
||||
style="box-sizing: border-box; height: 218px; padding: 20px 15px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-row :gutter="10">
|
||||
<el-col
|
||||
:span="12"
|
||||
:span="6"
|
||||
v-for="(item, index) in sjglData"
|
||||
:key="index + 'sjglData'"
|
||||
class="sjgl-data"
|
||||
class="sjgl-col"
|
||||
>
|
||||
<div class="sjgl-title">{{ item.title }}</div>
|
||||
<div class="sjgl-value">
|
||||
{{ runningInfo[item.attr] | formatNumber }}
|
||||
<div class="sjgl-wrapper">
|
||||
<div class="sjgl-title">{{ item.title }}</div>
|
||||
<div class="sjgl-value" :style="{color:item.color}">
|
||||
{{ runningInfo[item.attr] | formatNumber }}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -62,37 +96,9 @@
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="12">
|
||||
<el-card
|
||||
shadow="always"
|
||||
class="common-card-container common-card-container-body-no-padding"
|
||||
>
|
||||
<div slot="header">
|
||||
<span class="card-title">收入对比数据</span>
|
||||
</div>
|
||||
<div
|
||||
style="box-sizing: border-box; height: 250px; padding: 20px 15px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item, index) in revenueData"
|
||||
:key="index + 'revenueData'"
|
||||
:span="index === 2 ? 24 : 12"
|
||||
class="sjgl-data"
|
||||
:style="{marginTop:index === 2 ? '40px' : 0}"
|
||||
>
|
||||
<div class="sjgl-title">{{ item.title }}</div>
|
||||
<div class="sjgl-value">
|
||||
{{ runningInfo[item.attr] | formatNumber }}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="24">
|
||||
<week-chart ref="weekChart"/>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="24">
|
||||
<el-col :xs="24" :sm="24" :lg="12">
|
||||
<active-chart ref="activeChart"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -116,62 +122,46 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
singleZdInfo: [
|
||||
{
|
||||
title: "电站位置",
|
||||
attr: "siteAddress",
|
||||
},
|
||||
{
|
||||
title: "投运时间",
|
||||
attr: "runningTime",
|
||||
},
|
||||
{
|
||||
title: "装机功率(MW)",
|
||||
attr: "installPower",
|
||||
},
|
||||
{
|
||||
title: "装机容量(MW)",
|
||||
attr: "installCapacity",
|
||||
},
|
||||
],
|
||||
sjglData: [
|
||||
{
|
||||
title: "今日充电量(kWh)",
|
||||
attr: "dayChargedCap",
|
||||
color: '#4472c4'
|
||||
},
|
||||
{
|
||||
title: "今日放电量(kWh)",
|
||||
attr: "dayDisChargedCap",
|
||||
},
|
||||
{
|
||||
title: "昨日充电量(kWh)",
|
||||
attr: "todo",
|
||||
},
|
||||
{
|
||||
title: "昨日放电量(kWh)",
|
||||
attr: "todo",
|
||||
color: '#70ad47'
|
||||
},
|
||||
{
|
||||
title: "总充电量(kWh)",
|
||||
attr: "totalChargedCap",
|
||||
color: '#4472c4'
|
||||
},
|
||||
{
|
||||
title: "今日实时收入(元)",
|
||||
attr: "dayRevenue",
|
||||
color: '#f67438'
|
||||
},
|
||||
{
|
||||
title: "昨日充电量(kWh)",
|
||||
attr: "yesterdayChargedCap",
|
||||
color: '#4472c4'
|
||||
},
|
||||
{
|
||||
title: "昨日放电量(kWh)",
|
||||
attr: "yesterdayDisChargedCap",
|
||||
color: '#70ad47'
|
||||
},
|
||||
{
|
||||
title: "总放电量(kWh)",
|
||||
attr: "totalDischargedCap",
|
||||
},
|
||||
],
|
||||
revenueData: [
|
||||
{
|
||||
title: "当日实时收入(元)",
|
||||
attr: "dayRevenue",
|
||||
color: '#70ad47'
|
||||
},
|
||||
{
|
||||
title: "昨日实时收入(元)",
|
||||
attr: "todo",
|
||||
},
|
||||
{
|
||||
title: "总收入(元)",
|
||||
attr: "totalRevenue",
|
||||
attr: "yesterdayRevenue",
|
||||
color: '#f67438'
|
||||
},
|
||||
],
|
||||
info: {}, //基本信息
|
||||
@ -180,10 +170,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
tableData() {
|
||||
console.log(
|
||||
"this.runningInfo?.siteMonitorHomeAlarmVo ",
|
||||
this.runningInfo?.siteMonitorHomeAlarmVo
|
||||
);
|
||||
return this.runningInfo?.siteMonitorHomeAlarmVo || [];
|
||||
},
|
||||
},
|
||||
@ -220,21 +206,73 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
//设备告警
|
||||
.alarm-msg {
|
||||
background: #ffcec6;
|
||||
width: 32px;
|
||||
border-radius: 17px;
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
line-height: 30px;
|
||||
background: #ff4949;
|
||||
padding: 2px 5px;
|
||||
font-size: 10px;
|
||||
font-weight: bolder;
|
||||
border-radius: 3px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
color: #ff4949;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
//基本信息-地址 运行️时间
|
||||
.site-info {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
|
||||
&.site-info-address {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #1791ff;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #000;
|
||||
font-size: 12px;
|
||||
max-height: 40px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
//总收入
|
||||
.total-count {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 12px;
|
||||
font-weight: bolder;
|
||||
color: #333;
|
||||
line-height: 14px;
|
||||
|
||||
.unit {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22px;
|
||||
font-weight: bolder;
|
||||
color: #ed2f1d;
|
||||
font-style: italic;
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.row-container {
|
||||
& > .el-col {
|
||||
margin-bottom: 20px;
|
||||
@ -242,28 +280,47 @@ export default {
|
||||
}
|
||||
|
||||
//数据概览
|
||||
.sjgl-data {
|
||||
text-align: center;
|
||||
.sjgl-col {
|
||||
.sjgl-wrapper {
|
||||
text-align: left;
|
||||
padding: 15px 20px;
|
||||
background-color: #f2f7fb;
|
||||
}
|
||||
|
||||
&:nth-child(1),
|
||||
&.power-col {
|
||||
.sjgl-wrapper {
|
||||
padding: 10px;
|
||||
|
||||
.sjgl-value {
|
||||
color: #c44444;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(4),
|
||||
&:nth-child(2),
|
||||
&:nth-child(3),
|
||||
&:nth-child(4) {
|
||||
margin-bottom: 25px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sjgl-title {
|
||||
color: #666666;
|
||||
color: #717171;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sjgl-value {
|
||||
color: rgba(51, 51, 51, 1);
|
||||
font-size: 26px;
|
||||
font-size: 22px;
|
||||
line-height: 26px;
|
||||
font-weight: 500;
|
||||
font-weight: bolder;
|
||||
font-style: italic;
|
||||
margin-top: 14px;
|
||||
word-wrap: break-word;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div v-for="(baseInfo,index) in baseInfoList" :key="index+'bmszlContainer'" style="margin-bottom:25px;">
|
||||
<el-card :class="{
|
||||
'timing-card-container':!['0','2'].includes(baseInfo.workStatus),
|
||||
'warning-card-container':baseInfo.workStatus === '2',
|
||||
'running-card-container':baseInfo.workStatus === '0'
|
||||
}" class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
|
||||
shadow="always">
|
||||
<el-card
|
||||
:class="handleCardClass(baseInfo)"
|
||||
class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
|
||||
shadow="always">
|
||||
<div slot="header">
|
||||
<span class="large-title">{{ baseInfo.deviceName }}</span>
|
||||
<div class="info">
|
||||
@ -27,9 +25,9 @@
|
||||
<div class="descriptions-main">
|
||||
<el-descriptions :colon="false" :column="3" direction="vertical">
|
||||
<el-descriptions-item
|
||||
:contentClassName="`descriptions-direction ${baseInfo.workStatus === '0' ? 'save' :'danger'}`" :span="1"
|
||||
contentClassName="descriptions-direction work-status"
|
||||
label="工作状态" labelClassName="descriptions-label">
|
||||
{{ $store.state.ems.workStatusOptions[baseInfo.workStatus] }}
|
||||
{{ STACKWorkStatusOptions[baseInfo.workStatus] }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1" contentClassName="descriptions-direction" label="与PCS通信"
|
||||
labelClassName="descriptions-label">
|
||||
@ -164,11 +162,17 @@ import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
||||
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
||||
import pointChart from "./../PointChart.vue";
|
||||
import PointTable from "@/views/ems/site/sblb/PointTable.vue";
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'DzjkSbjkBmszl',
|
||||
components: {pointChart, PointTable},
|
||||
mixins: [getQuerySiteId, intervalUpdate],
|
||||
computed: {
|
||||
...mapState({
|
||||
STACKWorkStatusOptions: state => state?.ems?.PCSWorkStatusOptions || {},
|
||||
})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@ -187,6 +191,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCardClass(item) {
|
||||
const {workStatus = ''} = item
|
||||
return !Object.keys(this.STACKWorkStatusOptions).find(i => i === workStatus) ? "timing-card-container" : workStatus === '9' ? 'warning-card-container' : 'running-card-container'
|
||||
},
|
||||
|
||||
// 查看设备电位表格
|
||||
pointDetail(row, dataType) {
|
||||
const {siteId, deviceId} = row
|
||||
|
||||
@ -35,7 +35,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<el-row class="device-info-row">
|
||||
<el-col v-for="(tempDataItem,tempDataIndex) in deviceIdTypeMsg[item.deviceId]" :key="tempDataIndex+'dbTempData'"
|
||||
<el-col v-for="(tempDataItem,tempDataIndex) in (deviceIdTypeMsg[item.deviceId] || otherTypeMsg)"
|
||||
:key="tempDataIndex+'dbTempData'"
|
||||
:span="8" class="device-info-col">
|
||||
<span class="pointer" @click="showChart(tempDataItem.pointName,item.deviceId)">
|
||||
<span class="left">{{ tempDataItem.name }}</span> <span class="right">{{ item[tempDataItem.attr] || '-' }}<span
|
||||
@ -70,89 +71,125 @@ export default {
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能'
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能'
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '正向无功电能',
|
||||
attr: 'forwardReactive',
|
||||
pointName: '正向无功电能'
|
||||
pointName: '正向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '反向无功电能',
|
||||
attr: 'reverseReactive',
|
||||
pointName: '反向无功电能'
|
||||
pointName: '反向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率'
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率'
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
],
|
||||
'METE': [
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能'
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能'
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '正向无功电能',
|
||||
attr: 'forwardReactive',
|
||||
pointName: '正向无功电能'
|
||||
pointName: '正向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '反向无功电能',
|
||||
attr: 'reverseReactive',
|
||||
pointName: '反向无功电能'
|
||||
pointName: '反向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率'
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率'
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
],
|
||||
'METEGF': [
|
||||
{
|
||||
name: '有功电能',
|
||||
attr: 'activeEnergy',
|
||||
pointName: '有功电能'
|
||||
pointName: '有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '无功电能',
|
||||
attr: 'reactiveEnergy',
|
||||
pointName: '无功电能'
|
||||
pointName: '无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率'
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率'
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
otherTypeMsg: [
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
@ -8,11 +8,7 @@
|
||||
style="margin-bottom: 25px"
|
||||
>
|
||||
<el-card
|
||||
:class="{
|
||||
'timing-card-container':!['0','2'].includes(pcsItem.workStatus),
|
||||
'warning-card-container':pcsItem.workStatus === '2',
|
||||
'running-card-container':pcsItem.workStatus === '0'
|
||||
}"
|
||||
:class="handleCardClass(pcsItem)"
|
||||
class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
|
||||
shadow="always"
|
||||
>
|
||||
@ -52,14 +48,12 @@
|
||||
<div class="descriptions-main">
|
||||
<el-descriptions :colon="false" :column="4" direction="vertical">
|
||||
<el-descriptions-item
|
||||
:contentClassName="`descriptions-direction ${
|
||||
pcsItem.workStatus === '0' ? 'save' : 'danger'
|
||||
}`"
|
||||
contentClassName="descriptions-direction work-status"
|
||||
:span="1"
|
||||
label="工作状态"
|
||||
labelClassName="descriptions-label"
|
||||
>{{
|
||||
$store.state.ems.workStatusOptions[pcsItem.workStatus]
|
||||
PCSWorkStatusOptions[pcsItem.workStatus]
|
||||
}}
|
||||
</el-descriptions-item
|
||||
>
|
||||
@ -197,11 +191,17 @@ import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
||||
import {getPcsDetailInfo, getRunningHeadInfo} from "@/api/ems/dzjk";
|
||||
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
||||
import PcsSwitch from "@/views/ems/site/sblb/PcsSwitch.vue";
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "DzjkSbjkPcs",
|
||||
components: {RealTimeBaseInfo, pointChart, PointTable, PcsSwitch},
|
||||
mixins: [getQuerySiteId, intervalUpdate],
|
||||
computed: {
|
||||
...mapState({
|
||||
PCSWorkStatusOptions: state => state?.ems?.PCSWorkStatusOptions || {},
|
||||
})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@ -288,6 +288,10 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleCardClass(item) {
|
||||
const {workStatus = ''} = item
|
||||
return workStatus === '1' || !Object.keys(this.PCSWorkStatusOptions).find(i => i === workStatus) ? "timing-card-container" : workStatus === '2' ? 'warning-card-container' : 'running-card-container'
|
||||
},
|
||||
// 查看设备电位表格
|
||||
pointDetail(row, dataType) {
|
||||
const {deviceId} = row
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<el-card
|
||||
shadow="always"
|
||||
class="common-card-container common-card-container-body-no-padding"
|
||||
shadow="always"
|
||||
class="common-card-container common-card-container-body-no-padding"
|
||||
>
|
||||
<div slot="header">
|
||||
<span class="card-title">PCS有功功率/PCS无功功率</span>
|
||||
</div>
|
||||
<div style="height: 360px" id="cnglqxChart" />
|
||||
<div style="height: 360px" id="cnglqxChart"/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<script>
|
||||
import * as echarts from "echarts";
|
||||
import resize from "@/mixins/ems/resize";
|
||||
import { storagePower } from "@/api/ems/dzjk";
|
||||
import {storagePower} from "@/api/ems/dzjk";
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
@ -36,56 +36,56 @@ export default {
|
||||
methods: {
|
||||
init(siteId, timeRange) {
|
||||
this.chart.showLoading();
|
||||
const [startTime='', endTime=''] = timeRange;
|
||||
storagePower(siteId,startTime,endTime)
|
||||
.then((response) => {
|
||||
this.setOption(response?.data?.pcsPowerList || []);
|
||||
})
|
||||
.finally(() => {
|
||||
this.chart.hideLoading();
|
||||
});
|
||||
const [startTime = '', endTime = ''] = timeRange;
|
||||
storagePower(siteId, startTime, endTime)
|
||||
.then((response) => {
|
||||
this.setOption(response?.data?.pcsPowerList || []);
|
||||
})
|
||||
.finally(() => {
|
||||
this.chart.hideLoading();
|
||||
});
|
||||
},
|
||||
setOption(data) {
|
||||
let xdata = [],
|
||||
series = [];
|
||||
series = [];
|
||||
data.forEach((element, index) => {
|
||||
if (index === 0) {
|
||||
xdata = (element.energyStoragePowList || []).map((i) => i.createDate);
|
||||
}
|
||||
series.push(
|
||||
{
|
||||
type: "line",
|
||||
name: `${element.deviceId}有功功率`,
|
||||
areaStyle: {
|
||||
// color:'#FFBD00'
|
||||
{
|
||||
type: "line",
|
||||
name: `${element.deviceId}有功功率`,
|
||||
areaStyle: {
|
||||
// color:'#FFBD00'
|
||||
},
|
||||
data: (element.energyStoragePowList || []).map(
|
||||
(i) => {
|
||||
return {
|
||||
value: i.pcsTotalActPower,
|
||||
year: i.dateDay || ''
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
data: (element.energyStoragePowList || []).map(
|
||||
(i) => {
|
||||
return {
|
||||
value:i.pcsTotalActPower,
|
||||
year:i.dateDay || ''
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
name: `${element.deviceId}无功功率`,
|
||||
areaStyle: {
|
||||
// color:'#FFBD00'
|
||||
},
|
||||
data: (element.energyStoragePowList || []).map(
|
||||
(i) => {
|
||||
return {
|
||||
value: i.pcsTotalReactivePower,
|
||||
year:i.dateDay || ''
|
||||
}
|
||||
}
|
||||
),
|
||||
}
|
||||
{
|
||||
type: "line",
|
||||
name: `${element.deviceId}无功功率`,
|
||||
areaStyle: {
|
||||
// color:'#FFBD00'
|
||||
},
|
||||
data: (element.energyStoragePowList || []).map(
|
||||
(i) => {
|
||||
return {
|
||||
value: i.pcsTotalReactivePower,
|
||||
year: i.dateDay || ''
|
||||
}
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
});
|
||||
this.chart.setOption({
|
||||
this.chart && this.chart.setOption({
|
||||
legend: {
|
||||
left: "center",
|
||||
top: "5",
|
||||
@ -99,29 +99,29 @@ export default {
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
show:true,
|
||||
show: true,
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
// 坐标轴指示器,坐标轴触发有效
|
||||
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
|
||||
},
|
||||
formatter :(params)=>{
|
||||
if(params.length <= 0) return
|
||||
let result = (params[0].data.year || '')+' '+ params[0].name + '<div>'
|
||||
params.forEach(item=>{
|
||||
const {color,seriesName,value} = item
|
||||
result += `<div style="position: relative;padding-left:20px;line-height: 20px;">
|
||||
formatter: (params) => {
|
||||
if (params.length <= 0) return
|
||||
let result = (params[0].data.year || '') + ' ' + params[0].name + '<div>'
|
||||
params.forEach(item => {
|
||||
const {color, seriesName, value} = item
|
||||
result += `<div style="position: relative;padding-left:20px;line-height: 20px;">
|
||||
<div style="position: absolute;top:50%;left:0;width:12px;height:12px;border-radius:100%;background: ${color};transform: translateY(-50%)"></div>
|
||||
<span>${seriesName}</span><span style="margin-left:20px;font-weight: 700">${value}</span></div>`
|
||||
})
|
||||
result+='</div>'
|
||||
result += '</div>'
|
||||
return result
|
||||
}
|
||||
},
|
||||
textStyle: {
|
||||
color: "#333333",
|
||||
},
|
||||
xAxis: { type: "category", data: xdata },
|
||||
xAxis: {type: "category", data: xdata},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
@ -137,7 +137,7 @@ export default {
|
||||
},
|
||||
],
|
||||
series,
|
||||
});
|
||||
}, true);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -54,7 +54,7 @@ export default {
|
||||
year:element.dateDay,
|
||||
});
|
||||
});
|
||||
xdata = this.chart.setOption({
|
||||
this.chart && this.chart.setOption({
|
||||
legend: {
|
||||
left: "center",
|
||||
top: "5",
|
||||
@ -115,7 +115,7 @@ export default {
|
||||
data: ydata,
|
||||
},
|
||||
],
|
||||
});
|
||||
},true);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -57,7 +57,7 @@ export default {
|
||||
}
|
||||
);
|
||||
});
|
||||
xdata = this.chart.setOption({
|
||||
this.chart && this.chart.setOption({
|
||||
legend: {
|
||||
left: "center",
|
||||
top: "5",
|
||||
@ -118,7 +118,7 @@ export default {
|
||||
data: ydata,
|
||||
},
|
||||
],
|
||||
});
|
||||
},true);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -66,7 +66,7 @@ export default {
|
||||
}),
|
||||
});
|
||||
});
|
||||
this.chart.setOption({
|
||||
this.chart && this.chart.setOption({
|
||||
legend: {
|
||||
left: "center",
|
||||
top: "5",
|
||||
@ -118,7 +118,7 @@ export default {
|
||||
},
|
||||
],
|
||||
series,
|
||||
});
|
||||
},true);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -27,15 +27,14 @@
|
||||
class="common-table"
|
||||
:data="tableData"
|
||||
show-summary
|
||||
:summary-method="getSummaries"
|
||||
stripe
|
||||
style="width: 100%;margin-top:25px;">
|
||||
<!-- 汇总列-->
|
||||
<el-table-column label="汇总" min-width="180px" align="center">
|
||||
<el-table-column label="汇总" min-width="100px" align="center">
|
||||
<el-table-column
|
||||
prop="dataTime"
|
||||
label="日期"
|
||||
min-width="180px" align="center">
|
||||
min-width="100px" align="center">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<!--充电量列-->
|
||||
@ -94,6 +93,14 @@
|
||||
label="总">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<!-- 实际收益-->
|
||||
<el-table-column label="" align="center" fixed="right">
|
||||
<el-table-column
|
||||
prop="actualRevenue"
|
||||
label="实际收益"
|
||||
align="center">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-show="tableData.length>0"
|
||||
@ -137,46 +144,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//表格汇总
|
||||
getSummaries(param) {
|
||||
const {columns, data} = param;
|
||||
const sums = [];
|
||||
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
const activeTotal = data.map(item => item.activeTotalPrice).reduce((prev, curr) => {
|
||||
const value = Number(curr);
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr;
|
||||
} else {
|
||||
return prev;
|
||||
}
|
||||
}, 0);
|
||||
const reActiveTotal = data.map(item => item.reActiveTotalPrice).reduce((prev, curr) => {
|
||||
const value = Number(curr);
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr;
|
||||
} else {
|
||||
return prev;
|
||||
}
|
||||
}, 0);
|
||||
sums[index] = '价差收入 : ' + (reActiveTotal - activeTotal);
|
||||
return
|
||||
}
|
||||
const values = data.map(item => Number(item[column.property]));
|
||||
if (!values.every(value => isNaN(value))) {
|
||||
sums[index] = values.reduce((prev, curr) => {
|
||||
const value = Number(curr);
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr;
|
||||
} else {
|
||||
return prev;
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
})
|
||||
return sums
|
||||
},
|
||||
// 搜索
|
||||
onSearch() {
|
||||
this.pageNum = 1//每次搜索从1开始搜索
|
||||
|
||||
@ -1,577 +0,0 @@
|
||||
<template>
|
||||
<div class="ems-dashboard-editor-container" v-loading="loading">
|
||||
<div class="container" v-show="!empty">
|
||||
<!-- 云、电脑 -->
|
||||
<div class="top">
|
||||
<div class="cloud-container">
|
||||
<div class="cloud">
|
||||
<span style="z-index: 2; position: relative">云</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="double-arrows">
|
||||
<div class="top-arrows"></div>
|
||||
<div class="bottom-arrows"></div>
|
||||
</div>
|
||||
<div class="computer">
|
||||
<img src="@/assets/images/ems/computer.png" alt="" />
|
||||
<span style="z-index: 2; position: relative">ems</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="outer-border">
|
||||
<!-- 电表-->
|
||||
<div class="row-lists-container" v-if="showDb">
|
||||
<div class="row-title">电表({{ db.length }})</div>
|
||||
<div class="row-lists">
|
||||
<div v-for="item in db" :key="item.deviceId" class="row-items">
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
item.communicationStatus === '0' ? 'status-running' : ''
|
||||
"
|
||||
>
|
||||
{{ communicationStatusOptions[item.communicationStatus] }}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img
|
||||
class="img-db"
|
||||
:src="require('@/assets/images/ems/db.png')"
|
||||
/>
|
||||
<div class="name">{{ item.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 液冷-->
|
||||
<div class="row-lists-container" v-if="showLq">
|
||||
<div class="row-title">冷却({{ lq.length }})</div>
|
||||
<div class="row-lists">
|
||||
<div v-for="item in lq" :key="item.deviceId" class="row-items">
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
item.communicationStatus === '0' ? 'status-running' : ''
|
||||
"
|
||||
>
|
||||
{{ communicationStatusOptions[item.communicationStatus] }}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img
|
||||
class="img-lq"
|
||||
:src="require('@/assets/images/ems/lq.png')"
|
||||
/>
|
||||
<div class="name">{{ item.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PCS-->
|
||||
<div class="row-lists-container" v-if="showPcs">
|
||||
<div class="row-lists">
|
||||
<div class="row-title">PCS({{ pcs.length }})</div>
|
||||
<div
|
||||
v-for="(item, index) in pcs"
|
||||
:key="item.deviceId"
|
||||
class="row-items row-items-pcs"
|
||||
>
|
||||
<!-- pcs -->
|
||||
<div class="parent-dash">
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
item.communicationStatus === '0' ? 'status-running' : ''
|
||||
"
|
||||
>
|
||||
{{ communicationStatusOptions[item.communicationStatus] }}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img
|
||||
class="img-pcs"
|
||||
:src="require('@/assets/images/ems/pcs.png')"
|
||||
/>
|
||||
<div class="name">{{ item.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 子设备 bms -->
|
||||
<div
|
||||
v-if="item.children && item.children.length > 0"
|
||||
class="children-dash"
|
||||
>
|
||||
<div
|
||||
class="row-children-title"
|
||||
v-if="bmsHasParentLength > 0 && index === 0"
|
||||
>
|
||||
BMS({{ bmsHasParentLength }})
|
||||
</div>
|
||||
<div
|
||||
v-for="(childrenItem, childrenIndex) in item.children"
|
||||
:key="childrenIndex + 'childrenBms'"
|
||||
class="children-dash-items"
|
||||
>
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
childrenItem.communicationStatus === '0'
|
||||
? 'status-running'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
{{
|
||||
communicationStatusOptions[
|
||||
childrenItem.communicationStatus
|
||||
]
|
||||
}}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img
|
||||
class="img-pcs"
|
||||
:src="require('@/assets/images/ems/bms.png')"
|
||||
/>
|
||||
<div class="name">{{ childrenItem.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-lists-container" v-if="showPcs">
|
||||
<div class="row-title">PCS({{ pcs.length }})</div>
|
||||
<div class="row-lists">
|
||||
<div
|
||||
v-for="item in bmsNoParent"
|
||||
:key="item.deviceId"
|
||||
class="row-items row-items-pcs"
|
||||
>
|
||||
<!-- pcs -->
|
||||
<div class="parent-dash">
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
item.communicationStatus === '0' ? 'status-running' : ''
|
||||
"
|
||||
>
|
||||
{{ communicationStatusOptions[item.communicationStatus] }}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img :src="require('@/assets/images/ems/bms.png')" />
|
||||
<div class="name">{{ item.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- bms没有上级设备-->
|
||||
<div class="row-lists-container" v-if="bmsNoParent.length > 0">
|
||||
<div class="row-title">BMS({{ bmsNoParent.length }})</div>
|
||||
<div class="row-lists">
|
||||
<div
|
||||
v-for="item in bmsNoParent"
|
||||
:key="item.deviceId"
|
||||
class="row-items row-items-pcs"
|
||||
>
|
||||
<!-- pcs -->
|
||||
<div class="parent-dash">
|
||||
<div
|
||||
class="status"
|
||||
:class="
|
||||
item.communicationStatus === '0' ? 'status-running' : ''
|
||||
"
|
||||
>
|
||||
{{ communicationStatusOptions[item.communicationStatus] }}
|
||||
</div>
|
||||
<div class="row-items-img">
|
||||
<img :src="require('@/assets/images/ems/bms.png')" />
|
||||
<div class="name">{{ item.deviceName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-show="empty" :image-size="200"></el-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDeviceList } from "@/api/ems/site";
|
||||
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
name: "DzjkZxlt",
|
||||
mixins: [getQuerySiteId],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
pcs: [],
|
||||
bms: [],
|
||||
db: [],
|
||||
lq: [],
|
||||
pcsHasChildren: [],
|
||||
pcsNoChildren: [],
|
||||
bmsNoParent: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
communicationStatusOptions: (state) =>
|
||||
state.ems.communicationStatusOptions,
|
||||
}),
|
||||
|
||||
showPcs() {
|
||||
return this.pcs.length > 0;
|
||||
},
|
||||
showBms() {
|
||||
return this.bms.length > 0;
|
||||
},
|
||||
showDb() {
|
||||
return this.db.length > 0;
|
||||
},
|
||||
showLq() {
|
||||
return this.lq.length > 0;
|
||||
},
|
||||
bmsHasParentLength() {
|
||||
let count = 0;
|
||||
this.pcs.forEach((item) => (count += item.children.length));
|
||||
return count;
|
||||
},
|
||||
empty() {
|
||||
return !this.showBms && !this.showPcs && !this.showDb && !this.showLq;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.pcs = [];
|
||||
this.bms = [];
|
||||
this.lq = [];
|
||||
this.db = [];
|
||||
this.bmsNoParent = [];
|
||||
this.loading = true;
|
||||
getDeviceList(this.siteId)
|
||||
.then((response) => {
|
||||
const data = JSON.parse(JSON.stringify(response?.data || []));
|
||||
let pcs = [],
|
||||
bms = [],
|
||||
db = [],
|
||||
lq = [],
|
||||
bmsNoParent = [];
|
||||
data.forEach((item) => {
|
||||
// 电表
|
||||
if (item.deviceCategory === "AMMETER") {
|
||||
db.push({ ...item, children: [] });
|
||||
} else if (item.deviceCategory === "PCS") {
|
||||
// pcs
|
||||
pcs.push({ ...item, children: [] });
|
||||
} else if (item.deviceCategory === "STACK") {
|
||||
// bms
|
||||
bms.push({ ...item, children: [] });
|
||||
} else if (item.deviceCategory === "COOLING") {
|
||||
// 液冷
|
||||
lq.push({ ...item, children: [] });
|
||||
}
|
||||
});
|
||||
bms.forEach((item, index) => {
|
||||
if (item.parentId) {
|
||||
pcs
|
||||
.find((pcsItem) => pcsItem.deviceId === item.parentId)
|
||||
.children.push(item);
|
||||
} else {
|
||||
bmsNoParent.push(item);
|
||||
}
|
||||
});
|
||||
this.pcs = pcs;
|
||||
this.bms = bms;
|
||||
this.lq = lq;
|
||||
this.db = db;
|
||||
this.pcsHasChildren = pcs.filter((item) => item.children.length > 0);
|
||||
this.pcsNoChildren = pcs.filter((item) => item.children.length === 0);
|
||||
this.bmsNoParent = bmsNoParent;
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$sqDistance: 30px;
|
||||
$borderColor: #174a8e;
|
||||
$lineColor: #86bcc7;
|
||||
|
||||
.ems-dashboard-editor-container {
|
||||
background-color: #ffffff;
|
||||
padding: 0;
|
||||
color: #666666;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
//云 、计算机 、箭头
|
||||
.top {
|
||||
z-index: 2;
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// left: 0;
|
||||
// transform: translateY(-50%);
|
||||
//云 样式
|
||||
.cloud-container {
|
||||
margin: 0 auto;
|
||||
.cloud {
|
||||
width: 60px;
|
||||
height: 26px;
|
||||
background: #cbebfd;
|
||||
border-radius: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.cloud:before,
|
||||
.cloud:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: #cbebfd;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.cloud:before {
|
||||
top: -9px;
|
||||
left: 8px;
|
||||
}
|
||||
.cloud:after {
|
||||
top: -6px;
|
||||
right: 9px;
|
||||
}
|
||||
}
|
||||
//双箭头
|
||||
.double-arrows {
|
||||
height: fit-content;
|
||||
margin: 0 10px;
|
||||
text-align: center;
|
||||
.top-arrows,
|
||||
.bottom-arrows {
|
||||
height: 4px;
|
||||
width: 30px;
|
||||
background-color: #5ea9df;
|
||||
margin: 0 10px;
|
||||
position: relative;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
.top-arrows {
|
||||
vertical-align: super;
|
||||
}
|
||||
.top-arrows::after {
|
||||
top: -4px;
|
||||
border-bottom: 6px solid transparent;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid #5ea9df;
|
||||
border-top: 6px solid transparent;
|
||||
left: -11px;
|
||||
}
|
||||
.bottom-arrows {
|
||||
margin-top: 8px;
|
||||
&::after {
|
||||
top: -4px;
|
||||
border-top: 6px solid transparent;
|
||||
border-left: 6px solid #5ea9df;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid transparent;
|
||||
right: -11px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//电脑
|
||||
.computer {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
img {
|
||||
width: 80px;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.outer-border {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
border: 1.5px solid $borderColor;
|
||||
border-radius: 5px;
|
||||
padding-left: 120px;
|
||||
padding-right: 20px;
|
||||
margin-left: -40px;
|
||||
}
|
||||
|
||||
// 设备列表
|
||||
.row-lists-container {
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
.row-title {
|
||||
position: absolute;
|
||||
left: -$sqDistance - 30px;
|
||||
top: calc(50% + 10px);
|
||||
transform: translateY(-50%);
|
||||
color: #000;
|
||||
font-weight: bolder;
|
||||
}
|
||||
.row-lists {
|
||||
display: flex;
|
||||
position: relative;
|
||||
.row-items {
|
||||
position: relative;
|
||||
padding: 5px 0;
|
||||
&:not(:first-child) {
|
||||
margin-left: $sqDistance; //和外层父元素上下padding一致
|
||||
}
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 3px;
|
||||
width: $sqDistance - 2px;
|
||||
background: $lineColor;
|
||||
position: absolute;
|
||||
left: -$sqDistance;
|
||||
top: calc(50% + 10px);
|
||||
transform: scale(1, 0.4);
|
||||
}
|
||||
// 一列 第一个设备最上面的线
|
||||
&:first-child {
|
||||
&::before {
|
||||
width: $sqDistance + 20px;
|
||||
// top: -$sqDistance - 20px;
|
||||
}
|
||||
}
|
||||
// 一列 最后一个设备最下面的线
|
||||
// &:last-child {
|
||||
// &::after {
|
||||
// content: "";
|
||||
// display: block;
|
||||
// width: 3px;
|
||||
// height: $sqDistance - 2px;
|
||||
// background: $lineColor;
|
||||
// position: absolute;
|
||||
// bottom: -$sqDistance;
|
||||
// left: 50%;
|
||||
// transform: scale(0.4, 1);
|
||||
// }
|
||||
// }
|
||||
// 设备状态
|
||||
.status {
|
||||
margin: 0 auto 4px;
|
||||
width: fit-content;
|
||||
height: 18px;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 8px;
|
||||
line-height: 18px;
|
||||
border: 1px solid #08ffff;
|
||||
border-radius: 2px;
|
||||
background: #aaaaaa;
|
||||
color: #ffffff;
|
||||
&.status-running {
|
||||
background: #00c69c;
|
||||
}
|
||||
}
|
||||
// 图片+设备名称
|
||||
.row-items-img {
|
||||
position: relative;
|
||||
padding-top: 12px;
|
||||
img {
|
||||
width: 80px;
|
||||
height: auto;
|
||||
display: block;
|
||||
&.img-lq {
|
||||
width: 50px;
|
||||
}
|
||||
&.img-pcs {
|
||||
width: 50px;
|
||||
}
|
||||
&.img-db {
|
||||
width: 56px;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//子设备
|
||||
.row-lists-container-children {
|
||||
margin: 10px 0 0 $sqDistance;
|
||||
.parent-dash {
|
||||
position: relative;
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 40px;
|
||||
width: 3px;
|
||||
background: #ec7f8c;
|
||||
position: absolute;
|
||||
left: 20%;
|
||||
top: -40px;
|
||||
transform: scale(0.4, 1) rotate(-40deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.parent-dash {
|
||||
width: fit-content;
|
||||
}
|
||||
.children-dash {
|
||||
margin: $sqDistance 0 0 $sqDistance;
|
||||
position: relative;
|
||||
.row-children-title {
|
||||
position: absolute;
|
||||
left: -$sqDistance - 30px;
|
||||
top: calc(50% + 10px);
|
||||
transform: translateY(-50%);
|
||||
color: #000;
|
||||
font-weight: bolder;
|
||||
}
|
||||
.children-dash-items {
|
||||
position: relative;
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: $sqDistance;
|
||||
width: 3px;
|
||||
background: #ec7f8c;
|
||||
position: absolute;
|
||||
left: 20%;
|
||||
top: -$sqDistance;
|
||||
transform: scale(0.4, 1) rotate(-40deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,614 +0,0 @@
|
||||
<template>
|
||||
<div class="ems-dashboard-editor-container" v-loading="loading" >
|
||||
<div class="container" v-show="!empty">
|
||||
<div class="top">
|
||||
<div class="cloud-container">
|
||||
<div class="cloud">
|
||||
<span style="z-index:2;position: relative;">云</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="double-arrows">
|
||||
<div class="top-arrows"></div>
|
||||
<div class="bottom-arrows"></div>
|
||||
</div>
|
||||
<div class="computer">
|
||||
<img src="@/assets/images/ems/computer.png" alt="">
|
||||
<span style="z-index:2;position: relative;">ems</span>
|
||||
</div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<!-- 四列设备-->
|
||||
<div class="zxlt-row">
|
||||
<!-- bms、pcs 下级和上级在一列 -->
|
||||
<div class="row-lists pcs-row-lists" v-if="showPcsAndBms">
|
||||
<div class="item-square">
|
||||
<div class="row-lists-title" v-if="showPcs">PCS({{pcs.length}})</div>
|
||||
<div class="row-lists-title" v-if="showBms">BMS({{bms.length}})</div>
|
||||
</div>
|
||||
<!-- 上下级块 class区分-->
|
||||
<div class="item-square pcs-has-children-item-square" :class="{'no-bms-list':!showBms}" v-for="(item,index) in pcsHasChildren" :key="index+'pcsHasChildren'">
|
||||
<!-- 左边的上级 上级只有一个-->
|
||||
<div class="item-lists parent-item-lists">
|
||||
<!-- 上级设备-->
|
||||
<div class="items normal-items-arrow">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="item.pictureUrl" :src="item.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/pcs.png')"/>
|
||||
<div class="name">{{item.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右边的下级 下级有多个-->
|
||||
<div class="item-lists children-item-lists">
|
||||
<!-- 下级设备 循环生成-->
|
||||
<div class="items children-items-arrow bms-children-arrow" v-for="children in item.children" :key="children.deviceId">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="children.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[children.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="children.pictureUrl" :src="children.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
|
||||
<div class="name">{{children.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 没有上下级关系的bms、pcs-->
|
||||
<div class="item-square" :class="{'no-bms-list':!showBms}">
|
||||
<!-- 左边没有下级的pcs-->
|
||||
<div class="item-lists">
|
||||
<div class="items normal-items-arrow" v-for="item in pcsNoChildren" :key="item.deviceId">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="item.pictureUrl" :src="item.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/pcs.png')"/>
|
||||
<div class="name">{{item.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右边没有上级的bms-->
|
||||
<div class="item-lists">
|
||||
<!-- 下级设备 循环生成-->
|
||||
<div class="items children-items-arrow" v-for="item in bmsNoParent" :key="item.deviceId">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="item.pictureUrl" :src="item.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
|
||||
<div class="name">{{item.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 电表-->
|
||||
<div class="row-lists" v-if="showDb">
|
||||
<div class="item-square">
|
||||
<div class="row-lists-title" style="width:100%;">电表({{db.length}})</div>
|
||||
</div>
|
||||
<div class="item-square">
|
||||
<!-- 左边的下级 下级有多个-->
|
||||
<div class="item-lists">
|
||||
<!-- 下级设备 循环生成-->
|
||||
<div class="items normal-items-arrow" v-for="item in db" :key="item.deviceId">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="item.pictureUrl" :src="item.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
|
||||
<div class="name">{{item.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--冷却-->
|
||||
<div class="row-lists" v-if="showLq">
|
||||
<div class="item-square">
|
||||
<div class="row-lists-title" style="width:100%;">冷却({{lq.length}})</div>
|
||||
</div>
|
||||
<div class="item-square">
|
||||
<div class="item-lists">
|
||||
<div class="items normal-items-arrow" v-for="item in lq" :key="item.deviceId">
|
||||
<div class="items-inner">
|
||||
<div style="text-align: center;margin-bottom:10px;">
|
||||
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
|
||||
</div>
|
||||
<img v-if="item.pictureUrl" :src="item.pictureUrl">
|
||||
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
|
||||
<div class="name">{{item.deviceName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-show="empty" :image-size="200"></el-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import {getDeviceList} from'@/api/ems/site'
|
||||
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
||||
import {mapState} from "vuex";
|
||||
export default {
|
||||
name: 'DzjkZxlt',
|
||||
mixins: [getQuerySiteId],
|
||||
data() {
|
||||
return {
|
||||
loading:false,
|
||||
pcs :[],
|
||||
bms:[],
|
||||
db:[],
|
||||
lq:[],
|
||||
pcsHasChildren:[],
|
||||
pcsNoChildren:[],
|
||||
bmsNoParent:[]
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapState({
|
||||
communicationStatusOptions:(state)=>state.ems.communicationStatusOptions
|
||||
}),
|
||||
|
||||
showPcs(){
|
||||
return this.pcs.length>0
|
||||
},
|
||||
showBms(){
|
||||
return this.bms.length>0
|
||||
},
|
||||
showDb(){
|
||||
return this.db.length>0
|
||||
},
|
||||
showLq(){
|
||||
return this.lq.length>0
|
||||
},
|
||||
showPcsAndBms(){
|
||||
return this.showPcs || this.showBms
|
||||
},
|
||||
empty(){
|
||||
return !this.showBms && !this.showPcs && !this.showDb && !this.showLq
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
init(){
|
||||
this.pcs = []
|
||||
this.bms = []
|
||||
this.lq=[]
|
||||
this.db=[]
|
||||
this.bmsNoParent=[]
|
||||
this.loading = true
|
||||
getDeviceList(this.siteId).then(response => {
|
||||
const data =JSON.parse(JSON.stringify(response?.data || []))
|
||||
let pcs = [],bms=[],db=[],lq=[],bmsNoParent=[]
|
||||
data.forEach(item=>{
|
||||
// 电表
|
||||
if(item.deviceCategory === 'AMMETER'){
|
||||
db.push({...item,children:[]})
|
||||
}else if(item.deviceCategory === 'PCS'){
|
||||
// pcs
|
||||
pcs.push({...item,children:[]})
|
||||
}else if(item.deviceCategory === 'STACK'){
|
||||
// bms
|
||||
bms.push({...item,children:[]})
|
||||
}else if(item.deviceCategory === 'COOLING'){
|
||||
// 液冷
|
||||
lq.push({...item,children:[]})
|
||||
}
|
||||
})
|
||||
bms.forEach((item,index)=>{
|
||||
if(item.parentId){
|
||||
pcs.find(pcsItem=>pcsItem.deviceId === item.parentId).children.push(item)
|
||||
}else{
|
||||
bmsNoParent.push(item)
|
||||
}
|
||||
})
|
||||
this.pcs = pcs
|
||||
this.bms = bms
|
||||
this.lq=lq
|
||||
this.db=db
|
||||
this.pcsHasChildren = pcs.filter(item=>item.children.length > 0)
|
||||
this.pcsNoChildren = pcs.filter(item=>item.children.length === 0)
|
||||
this.bmsNoParent = bmsNoParent
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$distance:60px;
|
||||
$arrowDistance:80px;//margin:60+quare的padding10
|
||||
$arrowColoe:#5ea9df;
|
||||
$lineColoe:#5ea9df;
|
||||
.ems-dashboard-editor-container {
|
||||
background-color: #ffffff;
|
||||
padding:0;
|
||||
.container{
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
}
|
||||
//云 、计算机 、箭头
|
||||
.top{
|
||||
width: 280px;
|
||||
font-size: 30px;
|
||||
line-height: 40px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
//云 样式
|
||||
.cloud-container{
|
||||
padding-top:40px;
|
||||
margin:0 auto;
|
||||
.cloud {
|
||||
width: 150px;
|
||||
height: 60px;
|
||||
background: #cbebfd;
|
||||
border-radius: 200px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
color:#666666;
|
||||
}
|
||||
.cloud:before, .cloud:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background:#cbebfd;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.cloud:before {
|
||||
top: -28px;
|
||||
left: 20px;
|
||||
}
|
||||
.cloud:after {
|
||||
top: -31px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
//双箭头
|
||||
.double-arrows {
|
||||
height: 50px;
|
||||
margin:20px 0;
|
||||
text-align: center;
|
||||
.top-arrows,.bottom-arrows{
|
||||
height: 100%;
|
||||
width: 6px;
|
||||
background-color: $arrowColoe;
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
position: relative;
|
||||
vertical-align: super;
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left:0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
}
|
||||
}
|
||||
.top-arrows{
|
||||
vertical-align: super;
|
||||
}
|
||||
.top-arrows::after {
|
||||
bottom: -24px;
|
||||
border-bottom: 12px solid transparent;
|
||||
border-left: 12px solid transparent;
|
||||
border-right: 12px solid transparent;
|
||||
border-top: 14px solid $arrowColoe;
|
||||
left: -9px;
|
||||
}
|
||||
.bottom-arrows{
|
||||
margin-top:12px;
|
||||
&::after {
|
||||
top: -24px;
|
||||
border-top: 12px solid transparent;
|
||||
border-left: 12px solid transparent;
|
||||
border-right: 12px solid transparent;
|
||||
border-bottom: 14px solid $arrowColoe;
|
||||
left: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//电脑
|
||||
.computer{
|
||||
margin:20px auto;
|
||||
text-align: center;
|
||||
color:#666666;
|
||||
position: relative;
|
||||
img {
|
||||
width: auto;
|
||||
height: 100px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.arrow{
|
||||
height: 50px;
|
||||
width: 30px;
|
||||
border-radius: 5px;
|
||||
background-color: $arrowColoe;
|
||||
position: relative;
|
||||
margin:0 auto;
|
||||
&::after{
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
left: -9px;
|
||||
border-top: 24px solid $arrowColoe;
|
||||
border-left: 24px solid transparent;
|
||||
border-bottom: 24px solid transparent;
|
||||
border-right: 24px solid transparent;
|
||||
bottom: -44px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.bottom{
|
||||
z-index:1;
|
||||
box-sizing: border-box;
|
||||
margin-top:50px;
|
||||
.zxlt-row{
|
||||
display: flex;
|
||||
padding:20px $distance;
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
&:before{
|
||||
content: '';
|
||||
display: block;
|
||||
width:calc(100% - 100px);
|
||||
height:1px;
|
||||
background-color: $lineColoe;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left: $distance/2;
|
||||
}
|
||||
.row-lists{
|
||||
height: fit-content;
|
||||
position: relative;
|
||||
&:before{
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
left:-($distance/2);
|
||||
top:-20px;
|
||||
background-color: $lineColoe;
|
||||
}
|
||||
//pcs列 bms右侧的边框
|
||||
&.pcs-row-lists{
|
||||
&:after{
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
right:-(($distance/2) + 1);
|
||||
top:-20px;
|
||||
background-color: $lineColoe;
|
||||
}
|
||||
}
|
||||
&:not(:last-child){
|
||||
margin-right: $distance;
|
||||
}
|
||||
.item-square{
|
||||
//左右 两列
|
||||
display: flex;
|
||||
vertical-align: middle;
|
||||
align-items: flex-start;
|
||||
padding:10px;
|
||||
border-radius: 5px;
|
||||
&:not(:last-child){
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.row-lists-title{
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
.item-lists{
|
||||
position: relative;
|
||||
&:not(:last-child){
|
||||
margin-right:$distance;
|
||||
}
|
||||
//每个设备
|
||||
.items{
|
||||
background-color: #cbebfd;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1), 0 0 0 rgba(0, 0, 0, 0.5);
|
||||
//普通设备 箭头方向
|
||||
&.normal-items-arrow{
|
||||
&:before{
|
||||
content: '';
|
||||
display: block;
|
||||
width:($arrowDistance/2) - 15;
|
||||
height: 4px;
|
||||
background-color: $arrowColoe;
|
||||
position: absolute;
|
||||
top:50%;
|
||||
left: -($arrowDistance/2);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
&:after{
|
||||
content: '';
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-left: 10px solid #5ea9df;
|
||||
border-right: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-top: 10px solid transparent;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -15px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
//下级的箭头
|
||||
&.children-items-arrow{
|
||||
&:before{
|
||||
content: '';
|
||||
display: block;
|
||||
width:($arrowDistance/2) - 15;
|
||||
height: 4px;
|
||||
background-color: $arrowColoe;
|
||||
position: absolute;
|
||||
top:50%;
|
||||
right: -($arrowDistance/2);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
&:after{
|
||||
content: '';
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-right: 10px solid #5ea9df;
|
||||
border-left: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-top: 10px solid transparent;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -15px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
&:not(:last-child){
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.items-inner{
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
padding:10px;
|
||||
width:130px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img{
|
||||
width: 80px;
|
||||
height: auto;
|
||||
display: block;
|
||||
z-index:2;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.name{
|
||||
text-align: center;
|
||||
margin-top:10px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
z-index:2;
|
||||
}
|
||||
.status{
|
||||
z-index:2;
|
||||
margin-top:10px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
position: relative;
|
||||
padding-left:20px;
|
||||
display: inline;
|
||||
&.status-normal {
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
background-color: #05AEA3;
|
||||
position: absolute;
|
||||
top:50%;
|
||||
left:0;
|
||||
transform: translate(0,-50%);
|
||||
}
|
||||
}
|
||||
&.status-warn{
|
||||
&:before{
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
background-color: #FC6B69;
|
||||
position: absolute;
|
||||
top:50%;
|
||||
left:0;
|
||||
transform: translate(0,-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.children-item-lists{
|
||||
//todo 手动修改
|
||||
&:before{
|
||||
content: '';
|
||||
display: block;
|
||||
width:40px;
|
||||
height: 4px;
|
||||
background-color: $arrowColoe;
|
||||
position: absolute;
|
||||
top:50%;
|
||||
left: -50px;
|
||||
transform:translateY(-50%);
|
||||
}
|
||||
&:after{
|
||||
content: '';
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-left: 10px solid #5ea9df;
|
||||
border-right: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-top: 10px solid transparent;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -14px;
|
||||
transform:translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.pcs-has-children-item-square{
|
||||
vertical-align: middle;
|
||||
align-items: center;
|
||||
background-color: #ffefad;
|
||||
}
|
||||
.no-bms-list{
|
||||
.item-lists{
|
||||
&:not(:last-child){
|
||||
margin-right:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user