初次提交

This commit is contained in:
2025-06-30 10:21:25 +08:00
commit 150b39dfea
396 changed files with 80277 additions and 0 deletions

View File

@ -0,0 +1,660 @@
<template>
<view class="stack-warp">
<view class="all-con-item-box" style="margin-top: 0!important;">
<Section title="排气/回风温度" />
<view class="chart-box">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts :id="'pcsChart'" :options="curve_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section title="运行数据" />
<zero-loading v-if="runLoading" position="absolute"></zero-loading>
<view class="group-box ">
<view class="group-item "
@click="showHistory('空调设定温度', 'airconditionSetTemperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionSetTemperature | isNull}}
</view>
<view class="item-title">空调设定温度()</view>
</view>
</view>
<view class="group-item "
@click="showHistory('空调当前回风温度', 'airconditionAirTemperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionAirTemperature | isNull}}
</view>
<view class="item-title">空调当前回风温度()</view>
</view>
</view>
<view class="group-item "
@click="showHistory('空调当前回风湿度', 'airconditionAirHumidity', 'air_condition','%','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionAirHumidity | isNull}}
</view>
<view class="item-title">空调当前回风湿度(%)</view>
</view>
</view>
<view class="group-item "
@click="showHistory('空调设定湿度', 'airconditionSetHumidity', 'air_condition','%','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionSetHumidity | isNull}}
</view>
<view class="item-title">空调设定湿度(%)</view>
</view>
</view>
<view class="group-item"
@click="showHistory('空调内盘1温度', 'airconditionInner1Temperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionInner1Temperature | isNull}}
</view>
<view class="item-title">空调内盘1温度()</view>
</view>
</view>
<view class="group-item"
@click="showHistory('空调内盘2温度', 'airconditionInner2Temperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionInner2Temperature | isNull}}
</view>
<view class="item-title">空调内盘2温度()</view>
</view>
</view>
<view class="group-item "
@click="showHistory('空调回气温度', 'airconditionInnerGasTemperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionInnerGasTemperature | isNull}}
</view>
<view class="item-title">空调回气温度()</view>
</view>
</view>
<view class="group-item t"
@click="showHistory('空调外盘温度', 'airconditionOuterTemperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionOuterTemperature | isNull}}
</view>
<view class="item-title">空调外盘温度()</view>
</view>
</view>
<view class="group-item "
@click="showHistory('空调排气温度', 'airconditionOuterGasTemperature', 'air_condition','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.airconditionOuterGasTemperature | isNull}}
</view>
<view class="item-title">空调排气温度()</view>
</view>
</view>
</view>
</view>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
import historyModal from '@/components/history-modal/index.vue'
export default {
data() {
return {
curve_option: {},
stationId: null,
panelData: {},
deviceType: 'air_condition',
histroyShow: false,
chartTitle: null,
hisParams: {},
chartLoading:false,
runLoading:false
}
},
components: {
Section,
charts,
historyModal
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
},
},
methods: {
getData(srcId) {
this.loading = true
this.srcId = srcId
const api = [
this.getSocChart(),
this.getTotalData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getTotalData() {
this.runLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: [
'airconditionSetTemperature', 'airconditionAirTemperature',
'airconditionAirHumidity',
'airconditionSetHumidity', 'airconditionInner1Temperature',
'airconditionInner2Temperature',
'airconditionInnerGasTemperature', 'airconditionOuterTemperature',
'airconditionOuterGasTemperature'
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.panelData = {
airconditionSetTemperature: res.data.airconditionSetTemperature?.value,
airconditionAirTemperature: res.data.airconditionAirTemperature?.value,
airconditionAirHumidity: res.data.airconditionAirHumidity?.value,
airconditionSetHumidity: res.data.airconditionSetHumidity?.value,
airconditionInner1Temperature: res.data.airconditionInner1Temperature
?.value,
airconditionInner2Temperature: res.data.airconditionInner2Temperature
?.value,
airconditionInnerGasTemperature: res.data.airconditionInnerGasTemperature
?.value,
airconditionOuterTemperature: res.data.airconditionOuterTemperature?.value,
airconditionOuterGasTemperature: res.data.airconditionOuterGasTemperature
?.value
}
resolve(res);
})
.finally((err) => {
this.runLoading = false
})
});
},
showHistory(name, modelCol, modelType, unit) {
this.hisParams = {
modelCol: modelCol,
modelType: modelType,
unit: unit,
srcId:this.srcId
}
this.chartTitle = name
this.histroyShow = true
},
getSocChart() {
this.chartLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetSocCurve({
colName: ["airconditionOuterGasTemperature", "airconditionAirTemperature"],
stationId: this.stationId,
type: 'day',
srcId: this.srcId
})
.then((res) => {
self.initChargeChart(res.data);
resolve(res);
})
.finally(() => {
this.chartLoading = false
})
});
},
initChargeChart(val) {
const gonglv = []
const soc = []
const xAxis = []
val[0].staticCurveList.forEach(v => {
xAxis.push(v.date)
gonglv.push(v.digital)
})
val[1].staticCurveList.forEach(v => {
soc.push(v.digital)
})
this.curve_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
color: ['#009C77', '#BFE49F'],
grid: {
top: '15%',
left: '10%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [{
type: 'value',
name: '温度(℃)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
}],
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: [{
name: '空调排气温度',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: gonglv
},
{
name: '空调当前回风温度',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: soc
}
]
}
}
}
}
</script>
<style lang="scss" scoped>
.stack-warp {
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
position: relative;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.ring-data-box {
padding: 30rpx;
.ring-data-item {
.ring-title {
font-size: 28rpx;
color: #4c9ee6;
}
}
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
white-space: nowrap;
overflow: hidden; //文本超出隐藏
text-overflow: ellipsis; //文本超出省略号替
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
.chart-box {
width: 650rpx;
height: 500rpx;
margin-top: 20rpx;
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
}
.chart-box {
width: 650rpx;
height: 460rpx;
margin-top: 20rpx;
}
.time-box {
display: flex;
justify-content: space-around;
align-items: center;
font-size: 28rpx;
margin-top: 20rpx;
// border: 1px solid #a3a3a3;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx;
.time {
font-size: 28rpx;
white-space: nowrap;
}
}
.slot-content {
padding: 20rpx;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,899 @@
<template>
<view class="cluster-warp">
<template>
<view class="all-con-item-box" style="margin-top: 0!important;">
<Section :title="$t('homePage.device.clusterTotalVol')">
</Section>
<view class="chart-box" style="position: relative;">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="curve_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.runData')" />
<!-- <u-section title="电站数据" :right="false" line-color="#4C9CE7" color="#2A2A2A"></u-section> -->
<zero-loading v-if="totalLoading" position="absolute"></zero-loading>
<view v-else class="group-box">
<view class="group-item "
@click="showHistory($t('homePage.device.cumCharge'), 'cTotalChargePower', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{totalPanelData.cTotalChargePower | kwhFormat}}
</view>
<view class="item-title">
{{this.$t('homePage.device.cumCharge')}}({{ totalPanelData.cTotalChargePower | kwhUnitFormat }})
</view>
</view>
</view>
<view class="group-item "
@click="showHistory($t('homePage.device.cumDischarge'), 'cTotalDisChargePower', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ totalPanelData.cTotalDisChargePower | kwhFormat}}
</view>
<view class="item-title">
{{this.$t('homePage.device.cumDischarge'),}}({{ totalPanelData.cTotalDisChargePower | kwhUnitFormat }})
</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.avgTem'), 'cageT', 'bms','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{totalPanelData.cageT | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.avgTem')}}()</view>
</view>
</view>
<view class="group-item "
@click="showHistory(this.$t('homePage.device.avgVol'), 'csingleAgeV', 'bms','V','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ totalPanelData.csingleAgeV | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.avgVol')}}(V)</view>
</view>
</view>
<view class="group-item " @click="showHistory('SOC', 'clusterSOC', 'bms','%','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ totalPanelData.clusterSOC | isNull}}
</view>
<view class="item-title">SOC(%)</view>
</view>
</view>
<view class="group-item" @click="showHistory('SOH', 'clusterSOH', 'bms','%','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ totalPanelData.clusterSOH | isNull}}
</view>
<view class="item-title">SOH(%)</view>
</view>
</view>
<view class="group-item "
@click="showHistory($t('homePage.device.maxCellVol'), 'csingleMaxVolData', 'bms','V','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.csingleMaxVolData | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.maxCellVol')}}(V)</view>
</view>
</view>
<view class="group-item"
@click="showHistory($t('homePage.device.minCellVol'), 'csingleMinVolData', 'bms','V','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.csingleMinVolData | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.minCellVol')}}(V)</view>
</view>
</view>
<view class="group-item "
@click="showHistory($t('homePage.device.maxCellTem'), 'csingleMaxTemData', 'bms','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.csingleMaxTemData | isNull}}</view>
<view class="item-title">{{this.$t('homePage.device.maxCellTem')}}()</view>
</view>
</view>
<view class="group-item"
@click="showHistory($t('homePage.device.minCellTem'), 'csingleMinTemData', 'bms','℃','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.csingleMinTemData | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.minCellTem')}}()</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.runData')" />
<zero-loading v-if="runLoading" position="absolute"></zero-loading>
<view v-else class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.maxvolDiff'), 'csinglePressureDifference', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxvolDiff')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{Number(panelData.csingleMaxVolData - panelData.csingleMinVolData).toFixed(3) | isNull}}V
</view>
</view>
<view class="bottom-value">
{{this.$t('homePage.device.avgVol')}}{{totalPanelData.csingleAgeV | isNull}}V
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.avgTem'), 'csingleTDifference', 'bms','%','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxTemDiff')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{Number(panelData.csingleMaxTemData -panelData.csingleMinTemData ).toFixed(3) | isNull}}
</view>
</view>
<view class="bottom-value">
{{this.$t('homePage.device.avgTem')}}{{totalPanelData.cageT | isNull}}
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.maxCellVol'), 'csingleMaxVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxCellVol')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.csingleMaxVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.batteryGroupNum')}}{{panelData.csingleMaxVolBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellPostion')}}{{panelData.csingleMaxVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.minCellVol'), 'csingleMinVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.minCellVol')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.csingleMinVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.batteryGroupNum')}}{{panelData.csingleMinVolBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellPostion')}}{{panelData.csingleMinVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.maxCellTem'), 'csingleMaxTemData', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxCellTem')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.csingleMaxTemData | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
{{ this.$t('homePage.device.batteryGroupNum') }}{{panelData.csingleMaxTemBMUNum | isNull}}
</view>
<view>
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMaxTemBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box padding-top-30 "
@click="showHistory(this.$t('homePage.device.minCellTem'), 'csingleMinTemData', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.minCellTem')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.csingleMinTemData | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
{{ this.$t('homePage.device.batteryGroupNum') }}{{panelData.csingleMinTemBMUNum | isNull}}
</view>
<view>
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMinTemBoxNum | isNull}}
</view>
</view>
</view>
</view>
</view>
</template>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
import historyModal from '@/components/history-modal/index.vue'
export default {
data() {
return {
histroyShow: false,
runLoading: false,
totalLoading: false,
chartTitle: null,
hisParams: {
},
curve_option: {},
srcId: null,
stationId: null,
panelData: {},
totalPanelData: {},
chartLoading: false,
}
},
components: {
Section,
charts,
historyModal
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
},
},
methods: {
// 历史曲线
showHistory(name, modelCol, modelType, unit) {
this.hisParams = {
modelCol: modelCol,
modelType: modelType,
unit: unit
}
this.chartTitle = name
this.histroyShow = true
},
getData(srcId) {
this.srcId = srcId
this.loading = true
const api = [
this.getSocChart(),
this.getTotalData(),
this.getTotalPanelData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getSocChart() {
this.chartLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetSocCurve({
colName: ["clusterVol", "clusterSOC"],
stationId: this.stationId,
type: 'day',
srcId: this.srcId
})
.then((res) => {
self.initChargeChart(res.data);
resolve(res);
})
.finally(() => {
this.chartLoading = false
})
});
},
getTotalPanelData() {
this.totalLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: ["cTotalChargePower", "cTotalDisChargePower",
'cInsulationPositiveResistance', 'cInsulationNegativeResistance',
'clusterSOC', 'clusterSOH', 'csinglePressureDifference', 'csingleAgeV',
'csingleTDifference', 'cageT'
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.totalPanelData = {
cTotalChargePower: res.data.cTotalChargePower?.value ? res.data
.cTotalChargePower?.value : '',
cTotalDisChargePower: res.data.cTotalDisChargePower?.value ? res.data
.cTotalDisChargePower?.value : '0',
cInsulationPositiveResistance: res.data.cInsulationPositiveResistance
?.value ? res.data.cInsulationPositiveResistance
?.value : '',
cInsulationNegativeResistance: res.data.cInsulationNegativeResistance
?.value ? res.data.cInsulationNegativeResistance
?.value : '',
clusterSOC: res.data.clusterSOC?.value ? res.data.clusterSOC?.value : '',
clusterSOH: res.data.clusterSOH?.value ? res.data.clusterSOH?.value : '',
csinglePressureDifference: res.data.csinglePressureDifference?.value ? res
.data.csinglePressureDifference?.value : '',
csingleAgeV: res.data.csingleAgeV?.value ? res.data.csingleAgeV?.value :
'',
csingleTDifference: res.data.csingleTDifference?.value ? res.data
.csingleTDifference?.value : '',
cageT: res.data.cageT?.value ? res.data.cageT?.value : '',
}
resolve(res);
})
.finally(() => {
this.totalLoading = false
})
});
},
getTotalData() {
this.runLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: ['csingleMaxVolData', 'csingleMinVolData',
'csingleMaxTemData', 'csingleMinTemData',
'csingleMaxVolBMUNum', 'csingleMaxVolBoxNum', 'csingleMinVolBMUNum',
'csingleMinVolBoxNum', 'csingleMaxTemBMUNum', 'csingleMaxTemBoxNum',
'csingleMinTemBMUNum', 'csingleMinTemBoxNum'
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.panelData = {
csingleMaxVolData: res.data.csingleMaxVolData?.value,
csingleMinVolData: res.data.csingleMinVolData?.value,
csingleMaxTemData: res.data.csingleMaxTemData?.value,
csingleMinTemData: res.data.csingleMinTemData?.value,
csingleMaxVolBMUNum: res.data.csingleMaxVolBMUNum?.value,
csingleMaxVolBoxNum: res.data.csingleMaxVolBoxNum?.value,
csingleMinVolBMUNum: res.data.csingleMinVolBMUNum?.value,
csingleMinVolBoxNum: res.data.csingleMinVolBoxNum?.value,
csingleMaxTemBMUNum: res.data.csingleMaxTemBMUNum?.value,
csingleMaxTemBoxNum: res.data.csingleMaxTemBoxNum?.value,
csingleMinTemBMUNum: res.data.csingleMinTemBMUNum?.value,
csingleMinTemBoxNum: res.data.csingleMinTemBoxNum?.value,
}
resolve(res);
})
.finally(() => {
this.runLoading = false
})
});
},
initChargeChart(val) {
const gonglv = []
const soc = []
const xAxis = []
val[0].staticCurveList.forEach(v => {
xAxis.push(v.date)
gonglv.push(v.digital)
})
val[1].staticCurveList.forEach(v => {
soc.push(v.digital)
})
this.curve_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
color: ['#009C77', '#BFE49F'],
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [
{
type: 'value',
name: this.$t('homePage.device.vol') + '(V)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
},
{
type: 'value',
name: 'SOC(%)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
}
],
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: [{
name: this.$t('homePage.device.vol'),
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: gonglv
},
{
name: 'SOC',
type: 'line',
smooth: true,
yAxisIndex: 1,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: soc
}
]
}
}
}
}
</script>
<style lang="scss" scoped>
.cluster-warp {
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
position: relative;
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.ring-data-box {
padding: 30rpx;
.ring-data-item {
.ring-title {
font-size: 28rpx;
color: #4c9ee6;
}
}
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
}
.chart-box {
width: 650rpx;
height: 500rpx;
margin-top: 20rpx;
position: relative;
}
.time-box {
display: flex;
justify-content: space-around;
align-items: center;
font-size: 28rpx;
margin-top: 20rpx;
// border: 1px solid #a3a3a3;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx;
.time {
font-size: 28rpx;
white-space: nowrap;
}
}
.slot-content {
padding: 20rpx;
}
}
</style>

View File

@ -0,0 +1,849 @@
<template>
<view class="emu-warp">
<scroll-view style="height: 100% ;" scroll-y="true">
<zero-loading v-if="loading"></zero-loading>
<template v-else>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.EMU')" />
<view class="group-box ">
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMURingMainCabinetSwitchClosed ? 'success' : 'warning'">
{{panelData.EMURingMainCabinetSwitchClosed ? this.$t('homePage.device.on') : this.$t('homePage.device.off')}}
</view>
<view class="item-title">{{this.$t('homePage.device.emuSwitchPosition')}}</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMURemoteNetworkCabinet ? 'success' : 'warning'">
{{panelData.EMURemoteNetworkCabinet ? this.$t('homePage.device.distance') : this.$t('homePage.device.local')}}
</view>
<view class="item-title">{{this.$t('homePage.device.emuRemoteOperation')}}</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMUCabinetSwitchClosingPosition ? 'success' : 'warning'">
{{panelData.EMUCabinetSwitchClosingPosition ? this.$t('homePage.device.on') : $t('homePage.device.off')}}
</view>
<view class="item-title">并网柜地刀位置</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMURingMainCabinetSwitchClosed ? 'success' : 'warning'">
{{panelData.EMURingMainCabinetSwitchClosed ? this.$t('homePage.device.online') : this.$t('homePage.device.offline')}}
</view>
<view class="item-title">{{ this.$t('homePage.device.runState') }}</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.temConCabRunData')" />
<view class="group-box">
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUBoxPhaseATemperature | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.aTem')}}()</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUBoxPhaseBTemperature | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.bTem')}}()</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUBoxPhaseCTemperature | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.cTem')}}()</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMUDeviceOnlineStatus ? 'success' : 'warning'">
{{panelData.EMUDeviceOnlineStatus ? this.$t('homePage.device.online') : this.$t('homePage.device.offline')}}
</view>
<view class="item-title">{{ this.$t('homePage.device.runState') }}</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.dehumidifierRunData')" />
<view class="group-box">
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUDehumidifier1Temperature | isNull}}
</view>
<view class="item-title">{{ this.$t('homePage.device.tem') }}()</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUDehumidifier1Humidity | isNull}}
</view>
<view class="item-title">{{ this.$t('homePage.device.hum') }}(%)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUDehumidifier1HumidityStartValue | isNull}}
</view>
<view class="item-title">{{ this.$t('homePage.device.humStartValue') }}(%)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUDehumidifier1HumidityStopValue | isNull}}
</view>
<view class="item-title">{{ this.$t('homePage.device.humStopValue') }}(%)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMUDeviceOnlineStatus ? 'success' : 'warning'">
{{panelData.EMUDeviceOnlineStatus ? this.$t('homePage.device.online') : this.$t('homePage.device.offline')}}
</view>
<view class="item-title">{{ this.$t('homePage.device.runState') }}</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.ammeterRunData')" />
<view class="group-box">
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUPhaseVoltageUA | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.avol')}}(V)</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUIA | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.acur')}}(A)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUPhaseVoltageUB | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.bvol')}}(V)</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUIB | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.bcur')}}(A)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUPhaseVoltageUC | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.cvol')}}(V)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUIC | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.ccur')}}(A)</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMULineVoltageUAB | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.abLineVol')}}(V)</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMULineVoltageUBC | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.bcLineVol')}}(V)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMULineVoltageUAC | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.caLineVol')}}(V)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUFrequency | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.frequency')}}(Hz)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUAbsorbingActiveElectricalEnergy | kwhFormat}}
</view>
<view class="item-title">
{{this.$t('homePage.device.zxygzdl')}}({{panelData.EMUAbsorbingActiveElectricalEnergy | kwhUnitFormat}})</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUReleaseActiveElectricalEnergy | kwhFormat}}
</view>
<view class="item-title">
{{this.$t('homePage.device.fxygzdl')}}({{panelData.EMUReleaseActiveElectricalEnergy | kwhUnitFormat}})</view>
</view>
</view>
<view class="group-item">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUInductiveEnergy | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.perceptualPower')}}(kVarh)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.EMUCapacitiveEnergy | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.CapacitivePower')}}(kVarh)</view>
</view>
</view>
<view class="group-item ">
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num"
:class="panelData.EMUOnlineStatusOfElectricityMeter ? 'success' : 'warning'">
{{panelData.EMUOnlineStatusOfElectricityMeter ? this.$t('homePage.device.online') : this.$t('homePage.device.offline')}}
</view>
<view class="item-title">{{this.$t('homePage.device.runState')}}</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.ammeterRunData')" />
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.totalActivePower')}}
</view>
<view class="value">
{{panelData.EMUPTotal | kWFormat }}{{panelData.EMUPTotal | kwUnitFormat}}
</view>
</view>
<view class="bottom-value">
<view>{{ this.$t('homePage.device.a')}}{{panelData.EMUPA | isNull}}</view>
<view>{{ this.$t('homePage.device.b')}}{{panelData.EMUPB | isNull}}</view>
<view>{{ this.$t('homePage.device.c')}}{{panelData.EMUPC | isNull}}</view>
</view>
</view>
</view>
<view class="group-box padding-top-30 ">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.totalReactivePower')}}
</view>
<view class="value">
{{panelData.EMUQTotal }}kVar
</view>
</view>
<view class="bottom-value">
<view>{{ this.$t('homePage.device.a')}}{{panelData.EMUQA | isNull}}</view>
<view>{{ this.$t('homePage.device.b')}}{{panelData.EMUQB | isNull}}</view>
<view>{{ this.$t('homePage.device.c')}}{{panelData.EMUQC | isNull}}</view>
</view>
</view>
</view>
</view>
</template>
</scroll-view>
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
export default {
data() {
return {
loading: false,
panelData: {},
srcId: null,
stationId: null,
timeArr: [],
datetimerange: ["2021-03-20 20:10:10", "2021-05-10 10:10:10"],
}
},
components: {
Section
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
this.getTime()
},
deep: true,
immediate: true
}
},
methods: {
getTime() {
// 获取当前时间
var now = new Date();
this.maxTime =
new Date(now.toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1;
// 将时间调整到24小时前
now.setHours(now.getHours() - 24);
// 格式化输出开始时间
var year_start = now.getFullYear();
var month_start = now.getMonth() + 1;
month_start = month_start < 10 ? "0" + month_start : month_start;
var day_start = now.getDate();
day_start = day_start < 10 ? "0" + day_start : day_start;
var hours_start = now.getHours();
hours_start = hours_start < 10 ? "0" + hours_start : hours_start;
var minutes_start = now.getMinutes();
minutes_start = minutes_start < 10 ? "0" + minutes_start : minutes_start;
var seconds_start = now.getSeconds();
seconds_start = seconds_start < 10 ? "0" + seconds_start : seconds_start;
var formattedTime_start =
year_start +
"-" +
month_start +
"-" +
day_start +
" " +
hours_start +
":" +
minutes_start +
":" +
seconds_start;
// 获取当前时间
var now_end = new Date();
// 格式化输出结束时间
var year_end = now_end.getFullYear();
var month_end = now_end.getMonth() + 1;
month_end = month_end < 10 ? "0" + month_end : month_end;
var day_end = now_end.getDate();
day_end = day_end < 10 ? "0" + day_end : day_end;
var hours_end = now_end.getHours();
hours_end = hours_end < 10 ? "0" + hours_end : hours_end;
var minutes_end = now_end.getMinutes();
minutes_end = minutes_end < 10 ? "0" + minutes_end : minutes_end;
var seconds_end = now_end.getSeconds();
seconds_end = seconds_end < 10 ? "0" + seconds_end : seconds_end;
var formattedTime_end =
year_end +
"-" +
month_end +
"-" +
day_end +
" " +
hours_end +
":" +
minutes_end +
":" +
seconds_end;
this.datetimerange = [formattedTime_start, formattedTime_end];
this.timeArr = [formattedTime_start, formattedTime_end];
},
getData(srcId) {
this.loading = true
this.srcId = srcId
const api = [
this.getTotalData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getTotalData() {
this.loading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: ["EMURingMainCabinetSwitchClosed", "EMURemoteNetworkCabinet",
'EMUCabinetSwitchClosingPosition', 'EMUDeviceOnlineStatus',
'EMUBoxPhaseATemperature', 'EMUBoxPhaseBTemperature',
'EMUBoxPhaseCTemperature', 'EMUBoxOnlineStatus',
'EMUPhaseVoltageUA', 'EMUIA', 'EMUPhaseVoltageUB', 'EMUIB',
'EMUPhaseVoltageUC', 'EMUIC',
'EMULineVoltageUAB', 'EMULineVoltageUBC', 'EMULineVoltageUAC',
'EMUFrequency', 'EMUAbsorbingActiveElectricalEnergy',
'EMUReleaseActiveElectricalEnergy', 'EMUInductiveEnergy',
'EMUCapacitiveEnergy', 'EMUOnlineStatusOfElectricityMeter',
'EMUPTotal', 'EMUPA', 'EMUPB', 'EMUPC', 'EMUQTotal', 'EMUQA', 'EMUQB',
'EMUQC', 'EMUDehumidifier1Temperature', 'EMUDehumidifier1Humidity',
'EMUDehumidifier1HumidityStartValue', 'EMUDehumidifier1HumidityStopValue',
'EMUDehumidifier1OnlineStatus'
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.panelData = {
EMURingMainCabinetSwitchClosed: res.data.EMURingMainCabinetSwitchClosed
?.value,
EMURemoteNetworkCabinet: res.data.EMURemoteNetworkCabinet?.value,
EMUCabinetSwitchClosingPosition: res.data.EMUCabinetSwitchClosingPosition
?.value,
EMUDeviceOnlineStatus: res.data.EMUDeviceOnlineStatus?.value,
EMUBoxPhaseATemperature: res.data.EMUBoxPhaseATemperature?.value,
EMUBoxPhaseBTemperature: res.data.EMUBoxPhaseBTemperature?.value,
EMUBoxPhaseCTemperature: res.data.EMUBoxPhaseCTemperature?.value,
EMUBoxOnlineStatus: res.data.EMUBoxOnlineStatus?.value,
EMUPhaseVoltageUA: res.data.EMUPhaseVoltageUA?.value,
EMUIA: res.data.EMUIA?.value,
EMUPhaseVoltageUB: res.data.EMUPhaseVoltageUB?.value,
EMUIB: res.data.EMUIB?.value,
EMUPhaseVoltageUC: res.data.EMUPhaseVoltageUC?.value,
EMUIC: res.data.EMUIC?.value,
EMULineVoltageUAB: res.data.EMULineVoltageUAB?.value,
EMULineVoltageUBC: res.data.EMULineVoltageUBC?.value,
EMULineVoltageUAC: res.data.EMULineVoltageUAC?.value,
EMUFrequency: res.data.EMUFrequency?.value,
EMUAbsorbingActiveElectricalEnergy: res.data
.EMUAbsorbingActiveElectricalEnergy?.value,
EMUReleaseActiveElectricalEnergy: res.data.EMUReleaseActiveElectricalEnergy
?.value,
EMUInductiveEnergy: res.data.EMUInductiveEnergy?.value,
EMUCapacitiveEnergy: res.data.EMUCapacitiveEnergy?.value,
EMUOnlineStatusOfElectricityMeter: res.data
.EMUOnlineStatusOfElectricityMeter?.value,
EMUPTotal: res.data.EMUPTotal?.value,
EMUPA: res.data.EMUPA?.value,
EMUPB: res.data.EMUPB?.value,
EMUPC: res.data.EMUPC?.value,
EMUQTotal: res.data.EMUQTotal?.value,
EMUQA: res.data.EMUQA?.value,
EMUQB: res.data.EMUQB?.value,
EMUQC: res.data.EMUQC?.value,
EMUDehumidifier1Temperature: res.data.EMUDehumidifier1Temperature?.value,
EMUDehumidifier1Humidity: res.data.EMUDehumidifier1Humidity?.value,
EMUDehumidifier1HumidityStartValue: res.data
.EMUDehumidifier1HumidityStartValue?.value,
EMUDehumidifier1HumidityStopValue: res.data
.EMUDehumidifier1HumidityStopValue?.value,
EMUDehumidifier1OnlineStatus: res.data.EMUDehumidifier1OnlineStatus?.value,
}
resolve(res);
})
.catch((err) => {
reject("错误");
})
});
}
}
}
</script>
<style lang="scss" scoped>
.emu-warp {
height: 100% !important;
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.ring-data-box {
padding: 30rpx;
.ring-data-item {
.ring-title {
font-size: 28rpx;
color: #4c9ee6;
}
}
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis; //文本超出省略号替
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
}
.slot-content {
padding: 20rpx;
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
.success {
color: green !important;
}
.warning {
color: orange !important;
}
}
</style>

View File

@ -0,0 +1,963 @@
<template>
<view class="pcs-warp">
<view class="box">
<view class="topology-box">
<Section title="PCS拓扑图" />
<topoCanvas cId="canvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData" />
</view>
</view>
<view class="box">
<Section title="总有功/总无功功率">
<view slot="right" style="flex: 1">
<view class="top-right-box">
<span class="time">时间粒度:</span>
<span @click="openTimeAction" class="value">{{sampleTime}}</span>
</view>
</view>
</Section>
<view class="chart-box">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts v-else id="pcsChart" :options="curve_option"></charts>
</view>
</view>
<view class="box" style="margin-bottom: 0;">
<Section title="设备数据" />
<zero-loading v-if="stationLoading" position="absolute"></zero-loading>
<view v-else class="group-box">
<view class="group-item border-right" @click="showHistory('交流有功', 'outputPower', 'pcs', 'kW', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.outputPower | kWFormat }}
</view>
<view class="item-title">交流有功({{panelData.outputPower | kwUnitFormat }})</view>
</view>
</view>
<view class="group-item border-right"
@click="showHistory('交流无功', 'reactivePowerPCS', 'pcs', 'kVar', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.reactivePowerPCS }}
</view>
<view class="item-title">交流无功(kVar)</view>
</view>
</view>
<view class="group-item" @click="showHistory('电网频率', 'grid', 'pcs', 'Hz', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.grid | isNull }}
</view>
<view class="item-title">电网频率(Hz)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('UV电压', 'volA', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volA | isNull }}
</view>
<view class="item-title">UV电压(V)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('VW电压', 'volB', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volB | isNull }}
</view>
<view class="item-title">VW电压(V)</view>
</view>
</view>
<view class="group-item" @click="showHistory('WU电压', 'volC', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volC | isNull }}
</view>
<view class="item-title">WU电压(V)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('U相电流', 'currentA', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentA | isNull }}
</view>
<view class="item-title">U相电流(A)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('V相电流', 'currentB', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentB | isNull }}
</view>
<view class="item-title">V相电流(A)</view>
</view>
</view>
<view class="group-item" @click="showHistory('W相电流', 'currentC', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentC | isNull }}
</view>
<view class="item-title">W相电流(A)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('直流功率', 'dcPower', 'pcs', 'kW', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcPower | kWFormat }}</view>
<view class="item-title">直流功率({{ panelData.dcPower | kwUnitFormat}})</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory('直流电压', 'dcInputVol', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcInputVol | isNull }}
</view>
<view class="item-title">直流电压(V)</view>
</view>
</view>
<view class="group-item" @click="showHistory('直流电流', 'dcCurrent', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcCurrent | isNull }}
</view>
<view class="item-title">直流电流(A)</view>
</view>
</view>
</view>
</view>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
<u-action-sheet :list="actionSheetList" v-model="timeShow" @click="actionSheetCallback" @close="closeTimeAction"
:mask-close-able="false">
</u-action-sheet>
</view>
</template>
<script>
import topoCanvas from '@/components/new-canvas/index.vue'
import historyModal from '@/components/history-modal/index.vue'
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
export default {
components: {
historyModal,
Section,
charts,
topoCanvas
},
data() {
return {
sampleTime: "1分钟",
curve_option: {},
panelData: {},
histroyShow: false,
chartTitle: null,
chartLoading: false,
stationLoading: false,
hisParams: {},
timeShow: false,
time: "1",
stationId: null,
srcId: null,
hnStationId: [417, 398, 416, 415, 405, 485],
actionSheetList: [{
text: "1分钟",
value: 1,
},
{
text: "5分钟",
value: 5,
},
{
text: "10分钟",
value: 10,
},
{
text: "15分钟",
value: 15,
},
{
text: "20分钟",
value: 20,
},
{
text: "30分钟",
value: 30,
},
],
canvasData: [],
textCanvasData: [
//0
{
type: "text",
coord: [
[190, 70]
],
font: [{
text: "交流断路器",
size: 12,
color: "#333333",
}, ],
},
//1
{
type: "text",
coord: [
[190, 200]
],
font: [{
text: "直流断路器",
size: 12,
color: "#333333",
}, ],
},
//2
{
type: "text",
coord: [
[200, 260]
],
font: [{
text: "SOC",
size: 12,
color: "#999",
},
{
text: "20%",
size: 12,
color: "#000",
left: 35
},
],
},
//3
{
type: "text",
coord: [
[35, 80]
],
font: [{
text: "运行状态:",
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000000",
left: 65
},
],
},
//4
{
type: "text",
coord: [
[3, 100]
],
font: [{
text: "远方/就地状态:",
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000000",
left: 98
},
],
},
//5
{
type: "text",
coord: [
[20, 120]
],
font: [{
text: "并离网状态:",
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000",
left: 80
},
],
},
],
imageCanvasData: [{
//AC/DC
type: "image",
url: "/static/topology/DC.png",
coord: [
[140, 110],
[60, 60],
],
},
{
//电池
type: "image",
url: "/static/topology/battary.png",
coord: [
[144, 240],
[50, 50],
],
},
],
lineCanvasData: [{
type: "line",
coord: [
[60, 30],
[280, 30],
],
color: "#19875c",
width: 2,
},
{
type: "line",
coord: [
[170, 30],
[170, 240],
],
color: "#19875c",
width: 2,
},
],
rectCanvasData: [{
type: "rect",
background: "#19875c",
coord: [
[160, 50],
[20, 30],
],
},
{
type: "rect",
background: "#19875c",
coord: [
[160, 180],
[20, 30],
],
},
]
}
},
computed: {
currentStation() {
return this.vuex_currentStation;
},
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true,
},
},
methods: {
getData(srcId) {
this.srcId = srcId
this.getChart()
this.getStatus()
},
getChart() {
const self = this
self.chartLoading = true;
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetPCSCurve({
stationId: this.stationId,
sampleTime: this.time,
srcId: this.srcId,
})
.then((res) => {
self.chartLoading = false;
self.initChargeChart(res.data);
// this.getStatus();
resolve(res);
})
.catch((err) => {
reject("错误");
})
.finally(() => {
self.chartLoading = false;
});
});
},
initChargeChart(val) {
const gonglv = [];
const soc = [];
const xAxis = [];
val.forEach((v) => {
xAxis.push(v.data);
gonglv.push(v.pcsRealTimeCurve);
soc.push(v.inCoreDataCurve);
});
this.curve_option = {
color: ["#009C77", "#BFE49F"],
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
axisPointer: {},
confine: true,
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: "15%",
left: "5%",
right: "3%",
bottom: "10%",
containLabel: true,
},
xAxis: {
type: "category",
data: xAxis,
splitLine: {
show: false,
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = "";
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr =
p === rowNumber - 1 ?
params.substring(start, paramsNameNumber) :
params.substring(start, end) + "\n";
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [{
type: "value",
name: "总有功功率(kW)",
axisLabel: {
color: "#A3A3A3",
},
nameTextStyle: {
color: "#A3A3A3",
},
min: function(value) {
return Math.floor(
(Math.abs(value.min) < value.max ?
-value.max * 1.05 :
value.min * 1.05
).toFixed(2)
);
},
max: function(value) {
return Math.ceil(
(Math.abs(value.min) < value.max ?
value.max * 1.05 :
-value.min * 1.05
).toFixed(2)
);
},
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 30],
},
},
{
type: "value",
name: "总无功功率(kVar)",
axisLabel: {
color: "#A3A3A3",
},
nameTextStyle: {
color: "#A3A3A3",
},
min: function(value) {
return Math.floor(
(Math.abs(value.min) < value.max ?
-value.max * 1.05 :
value.min * 1.05
).toFixed(2)
);
},
max: function(value) {
return Math.ceil(
(Math.abs(value.min) < value.max ?
value.max * 1.05 :
-value.min * 1.05
).toFixed(2)
);
},
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, -40],
},
},
],
dataZoom: {
type: "inside",
},
series: [{
name: "总有功功率",
type: "line",
smooth: true,
symbol: "none",
areaStyle: {
opacity: 0,
},
// lineStyle: {
// color: '#00C8FF'
// },
data: gonglv,
},
{
name: "总无功功率",
type: "line",
smooth: true,
yAxisIndex: 1,
symbol: "none",
areaStyle: {
opacity: 0,
},
// lineStyle: {
// color: '#FBBB11'
// },
data: soc,
},
],
};
},
openTimeAction() {
this.timeShow = true;
},
getStatus() {
this.stationLoading = true
const self = this;
this.$u.api.deviceList
.GetNewValue({
stationId: this.stationId,
srcId: this.srcId,
colList: [
"outputPower", "reactivePowerPCS", "grid", "volA", "volB", "volC", "currentA",
"currentB", "currentC",
"dcPower", "dcInputVol", "dcCurrent", "workStatus", "remoteInPlace", "andOffGrid",
"stateCharging", "stateDischarging",
"deviceStateStand", "deviceStateFault", "deviceStateFull", "deviceStateEmpty",
"acBreaker", "dcBreaker", "eStop", "soc"
],
})
.then((res) => {
const battery = self.updateBattery(res.data.soc?.value ? res.data.soc.value : 0);
self.rectCanvasData.push(battery)
this.panelData = {
outputPower: res.data.outputPower?.value ? res.data.outputPower?.value : 0,
reactivePowerPCS: res.data.reactivePowerPCS?.value ? res.data.reactivePowerPCS?.value : 0,
grid: res.data.grid?.value ? res.data.grid?.value : 0,
volA: res.data.volA?.value ? res.data.volA?.value : 0,
volB: res.data.volB?.value ? res.data.volB?.value : 0,
volC: res.data.volC?.value ? res.data.volC?.value : 0,
currentA: res.data.currentA?.value ? res.data.currentA?.value: 0,
currentB: res.data.currentB?.value ? res.data.currentB?.value : 0,
currentC: res.data.currentC?.value ? res.data.currentC?.value: 0,
dcPower: res.data.dcPower?.value ? res.data.dcPower?.value: 0,
dcInputVol: res.data.dcInputVol?.value ? res.data.dcInputVol?.value:0,
dcCurrent: res.data.dcCurrent?.value ? res.data.dcCurrent?.value:0,
};
this.textCanvasData[2].font[1].text = res.data.soc?.value ? res.data.soc.value + "%" : 0 + "%";
this.textCanvasData[3].font[1].text = this.workStatus(res.data.workStatus?.value);
this.textCanvasData[4].font[1].text = this.GetAndOffGridStatus(res.data.andOffGrid?.value)
if (!res.data.acBreaker?.value) {
self.rectCanvasData[0].background = "rgba(25, 135, 92, 0.6y4)";
}
if (!res.data.dcBreaker?.value) {
self.rectCanvasData[1].background = "rgba(25, 135, 92, 0.6y4)";
}
this.canvasData = [...this.textCanvasData, ...this.imageCanvasData, ...this
.lineCanvasData, ...this.rectCanvasData
]
})
.finally((res) => {
this.stationLoading = false;
});
},
GetAndOffGridStatus(val) {
if (val === 1) {
return '离网'
} else {
return '并网'
}
},
updateBattery(value) {
//电池电量 value 为0~100
const batteryHeight = 0.35 * value;
const battery = {
type: "rect",
background: "#19875c",
coord: [
[156, 285 - batteryHeight],
[25.5, batteryHeight],
],
};
return battery;
},
getRunState(value, value2) {
if (value) {
return "待机";
} else if (value2) {
return "故障";
} else {
return "";
}
},
// 设备工作状态
workStatus(val) {
if (val === 0) {
return '停机'
} else if (val === 1) {
return '待机'
} else if (val === 2) {
return '故障'
} else if (val === 3) {
return '充电'
} else if (val === 4) {
return '放电'
} else if (val === 5) {
return '充电降额'
} else if (val === 6) {
return '放电降额'
}
},
// 充放电状态
getFlowDirection(val, flowDirection) {
if (flowDirection === 2) {
if (+val > +1) {
return '放电'
}
if (+val < -1) {
return '充电'
}
if (val < 1 || +val.abs < 1 || !val) {
return '静置'
}
} else {
if (+val > +1) {
return '充电'
}
if (+val < -1) {
return '放电'
}
if (val < 1 || +val.abs < 1 || !val) {
return '静置'
}
}
},
// 电池信息
updateBattery(value) {
//电池电量 value 为0~100
const batteryHeight = 0.35 * value;
const battery = {
type: "rect",
background: "#19875c",
coord: [
[156, 285 - batteryHeight],
[25.5, batteryHeight],
],
};
return battery;
},
// 历史曲线
showHistory(name, modelCol, modelType, unit) {
this.hisParams = {
modelCol: modelCol,
modelType: modelType,
unit: unit
}
this.chartTitle = name
this.histroyShow = true
},
actionSheetCallback(index) {
this.sampleTime = this.actionSheetList[index].text;
this.time = this.actionSheetList[index].value;
this.getChart()
},
closeTimeAction() {
this.timeShow = false;
},
}
}
</script>
<style lang="scss" scoped>
.pcs-warp {
background-color: #f5f5f5;
.box {
background: #ffffff;
border-radius: 16rpx;
padding: 20rpx;
width: 100%;
border: 16rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
margin-bottom: 20rpx;
position: relative;
.topology-box {
width: 100%;
height: 640rpx;
position: relative;
}
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.time {
padding-right: 10rpx;
display: inline-block;
height: 40rpx;
}
.value {
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx 20rpx 10rpx 20rpx;
height: 40rpx;
}
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.chart-box {
width: 650rpx;
height: 460rpx;
margin-top: 20rpx;
position: relative;
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,856 @@
<template>
<view class="stack-warp">
<view class="all-con-item-box" style="margin-top: 0!important;">
<Section title="堆总压/SOC">
</Section>
<view class="chart-box">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="curve_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section title="运行数据" />
<zero-loading v-if="runLoading" position="absolute"></zero-loading>
<view v-else class="group-box">
<view class="group-item" @click="showHistory('总压', 'bmsTotalVol', 'bms','V','','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.bmsTotalVol | isNull}}
</view>
<view class="item-title">总压(V)</view>
</view>
</view>
<view class="group-item" @click="showHistory('总电流', 'bmsTotalCurrent', 'bms','A','','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.bmsTotalCurrent | isNull}}
</view>
<view class="item-title">总电流(A)</view>
</view>
</view>
<view class="group-item " @click="showHistory('SOC', 'soc', 'bms','%','','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.soc | isNull}}
</view>
<view class="item-title">SOC(%)</view>
</view>
</view>
<view class="group-item" @click="showHistory('SOH', 'soh', 'bms','%','','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.soh | isNull}}
</view>
<view class="item-title">SOH(%)</view>
</view>
</view>
<view class="group-item" @click="showHistory('累计充电量', 'totalDischarge', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{(panelData.totalDischarge / 1000).toFixed(2) | isNull}}
</view>
<view class="item-title">累计充电量(MWh)</view>
</view>
</view>
<view class="group-item" @click="showHistory('累计放电量', 'totalDischarge', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{(panelData.totalDischarge / 1000).toFixed(2) | isNull}}
</view>
<view class="item-title">累计放电量(MWh)</view>
</view>
</view>
<view class="group-item" @click="showHistory('可充电量', 'rechargeCapacity', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.rechargeCapacity | kwhFormat}}
</view>
<view class="item-title">可充电量({{panelData.rechargeCapacity | kwhUnitFormat}})</view>
</view>
</view>
<view class="group-item" @click="showHistory('可放电量', 'dischargeCapacity', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.dischargeCapacity | kwhFormat}}
</view>
<view class="item-title">可放电量({{panelData.dischargeCapacity | kwhUnitFormat}})</view>
</view>
</view>
<view class="group-item " @click="showHistory('电流差异值', 'bmsCurrentDiff', 'bms','A','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.bmsCurrentDiff | isNull}}
</view>
<view class="item-title">电流差异值(A)</view>
</view>
</view>
<view class="group-item" @click="showHistory('总压差异值', 'bmsVolDiff', 'bms','V','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.bmsVolDiff | isNull}}
</view>
<view class="item-title">总压差异值(V)</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section title="运行数据" />
<zero-loading v-if="runLoading" position="absolute"></zero-loading>
<template v-else>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
最大电压差
</view>
<view class="value">
{{(panelData.bmsMaxVol - panelData.bmsMinVol).toFixed(3) | isNull }}V
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory('单体最高电压', 'bmsMaxVol', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
单体最高电压
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.bmsMaxVol | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
电池簇号{{panelData.bmsMaxVolNum | isNull}}
</view>
<view>
电池组号{{panelData.bmsMaxVolBMUNum | isNull}}
</view>
<view>
电芯位置{{panelData.bmsMaxVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory('单体最低电压', 'bmsMinVol', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
单体最低电压
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.bmsMinVol | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
电池簇号{{panelData.bmsMinVolNum | isNull}}
</view>
<view>
电池组号{{panelData.bmsMinVolBMUNum | isNull}}
</view>
<view>
电芯位置{{panelData.bmsMinVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
最大温度差
</view>
<view class="value">
{{ (panelData.bmsMaxTem - panelData.bmsMinTem).toFixed(3) | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory('单体最高温度', 'bmsMaxTem', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
单体最高温度
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{ panelData.bmsMaxTem | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
电池簇号{{ panelData.bmsMaxTemNum | isNull}}
</view>
<view>
电池组号{{ panelData.bmsMaxTemBMUNum | isNull}}
</view>
<view>
电芯位置{{ panelData.bmsMaxTemBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box padding-top-30 " @click="showHistory('单体最低温度', 'bmsMinTem', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
单体最低温度
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{ panelData.bmsMinTem | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
电池簇号{{ panelData.bmsMinTemNum | isNull}}
</view>
<view>
电池组号{{ panelData.bmsMinTemBMUNum | isNull}}
</view>
<view>
电芯位置{{ panelData.bmsMinTemBoxNum | isNull }}
</view>
</view>
</view>
</view>
</template>
</view>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
import historyModal from '@/components/history-modal/index.vue'
export default {
data() {
return {
loading: false,
curve_option: {},
stationId: null,
srcId: null,
chartLoading: false,
panelData: {},
chartTitle: null,
histroyShow: false,
hisParams: {},
curLoading:false,
runLoading:false
}
},
components: {
Section,
charts,
historyModal
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
},
},
methods: {
// 历史曲线
showHistory(name, modelCol, modelType, unit) {
this.hisParams = {
modelCol: modelCol,
modelType: modelType,
unit: unit,
srcId:this.srcId
}
this.chartTitle = name
this.histroyShow = true
},
getTotalData() {
this.runLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: ["bmsTotalVol", "bmsTotalCurrent", "soc", "soh",
"combinerCabinetQFClosingFeedback", "distributionBoxQF1ClosingFeedback",
"totalDischarge", "rechargeCapacity", "dischargeCapacity",
"bmsCurrentDiff", "bmsVolDiff", "totalCharge", "bmsMaxVol", "bmsMaxVolNum",
"bmsMaxVolBMUNum", "bmsMaxVolBoxNum",
"bmsMinVol", "bmsMinVolNum", "bmsMinVolBMUNum", "bmsMinVolBoxNum",
"bmsMaxTem", "bmsMaxTemNum", "bmsMaxTemBMUNum", "bmsMaxTemBoxNum",
"bmsMinTem", "bmsMinTemNum", "bmsMinTemBMUNum", "bmsMinTemBoxNum"
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.panelData = {
bmsTotalVol: res.data.bmsTotalVol?.value,
bmsTotalCurrent: res.data.bmsTotalCurrent?.value,
soc: res.data.soc?.value,
soh: res.data.soh?.value,
combinerCabinetQFClosingFeedback: res.data.combinerCabinetQFClosingFeedback
?.value,
distributionBoxQF1ClosingFeedback: res.data
.distributionBoxQF1ClosingFeedback?.value,
totalDischarge: res.data.totalDischarge?.value,
rechargeCapacity: res.data.rechargeCapacity?.value,
dischargeCapacity: res.data.dischargeCapacity?.value,
bmsCurrentDiff: res.data.bmsCurrentDiff?.value,
bmsVolDiff: res.data.bmsVolDiff?.value,
totalCharge: res.data.totalCharge?.value,
bmsMaxVol: res.data.bmsMaxVol?.value,
bmsMaxVolNum: res.data.bmsMaxVolNum?.value,
bmsMaxVolBMUNum: res.data.bmsMaxVolBMUNum?.value,
bmsMaxVolBoxNum: res.data.bmsMaxVolBoxNum?.value,
bmsMinVol: res.data.bmsMinVol?.value,
bmsMinVolNum: res.data.bmsMinVolNum?.value,
bmsMinVolBMUNum: res.data.bmsMinVolBMUNum?.value,
bmsMinVolBoxNum: res.data.bmsMinVolBoxNum?.value,
bmsMaxTem: res.data.bmsMaxTem?.value,
bmsMaxTemNum: res.data.bmsMaxTemNum?.value,
bmsMaxTemBMUNum: res.data.bmsMaxTemBMUNum?.value,
bmsMaxTemBoxNum: res.data.bmsMaxTemBoxNum?.value,
bmsMinTem: res.data.bmsMinTem?.value,
bmsMinTemBMUNum: res.data.bmsMinTemBMUNum?.value,
bmsMinTemBoxNum: res.data.bmsMinTemBoxNum?.value,
}
resolve(res);
})
.finally((err) => {
this.runLoading = false
})
});
},
getData(srcId) {
this.srcId = srcId
this.loading = true
const api = [
this.getSocChart(),
this.getTotalData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getSocChart() {
this.chartLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetSocCurve({
colName: ["soc", "stackTotalvol"],
stationId: this.stationId,
type: 'day',
srcId: this.srcId
})
.then((res) => {
self.initChargeChart(res.data);
resolve(res);
})
.finally((err) => {
this.chartLoading = false
})
});
},
initChargeChart(val) {
const gonglv = []
const soc = []
const xAxis = []
val[1].staticCurveList.forEach(v => {
xAxis.push(v.date)
gonglv.push(v.digital)
})
val[0].staticCurveList.forEach(v => {
soc.push(v.digital)
})
this.curve_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
color: ['#009C77', '#BFE49F'],
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [
{
type: 'value',
name: '堆总压(V)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
},
{
type: 'value',
name: 'SOC(%)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
}
],
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: [{
name: '堆总压',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: gonglv
},
{
name: 'SOC',
type: 'line',
smooth: true,
yAxisIndex: 1,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: soc
}
]
}
}
}
}
</script>
<style lang="scss" scoped>
.stack-warp {
height: 100% !important;
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
position: relative;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.ring-data-box {
padding: 30rpx;
.ring-data-item {
.ring-title {
font-size: 28rpx;
color: #4c9ee6;
}
}
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
}
.time-box {
display: flex;
justify-content: space-around;
align-items: center;
font-size: 28rpx;
margin-top: 20rpx;
// border: 1px solid #a3a3a3;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx;
.time {
font-size: 28rpx;
white-space: nowrap;
}
}
.chart-box {
width: 650rpx;
height: 500rpx;
margin-top: 20rpx;
position: relative;
}
.slot-content {
padding: 20rpx;
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
}
</style>

View File

@ -0,0 +1,747 @@
<template>
<view class="pack-warp">
<view class="all-con-item-box" style="margin-top: 0!important;">
<Section :title="VolNumber">
</Section>
<view class="chart-box">
<zero-loading v-if="volLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="vol_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section :title="TemNumber">
</Section>
<view class="chart-box">
<zero-loading v-if="temLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="tem_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.volRatio')">
</Section>
<view class="chart-box">
<zero-loading v-if="temLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="val_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.runData')" />
<zero-loading v-if="temLoading" position="absolute"></zero-loading>
<template v-else>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.maxVol') }}
</view>
<view class="value">
{{panelData.csingleMaxVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMaxVolPosition | isNull}}
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.minVol') }}
</view>
<view class="value">
{{panelData.csingleMinVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMinVolPosition | isNull}}
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.maxTem') }}
</view>
<view class="value">
{{panelData.csingleMaxTemData | isNull}}
</view>
</view>
<view class="bottom-value">
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMaxTemPosition | isNull}}
</view>
</view>
</view>
<view class="group-box padding-top-30 ">
<view class="other-value">
<view class="top-value">
<view class="title">
{{ this.$t('homePage.device.minTem') }}
</view>
<view class="value">
{{panelData.csingleMinTemData | isNull}}
</view>
</view>
<view class="bottom-value">
{{ this.$t('homePage.device.cellPostion') }}{{panelData.csingleMinTemPosition | isNull}}
</view>
</view>
</view>
</template>
</view>
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
export default {
data() {
return {
loading: false,
stationId: null,
srcId: null,
vol_option: {},
tem_option: {},
val_option: {},
panelData: {},
volLoading:false,
temLoading:false,
valLoading:false,
runLoading:false,
VolNumber:this.$t('homePage.device.cellVolChart'),
TemNumber:this.$t('homePage.device.cellTemChart')
}
},
components: {
Section,
charts
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
}
},
methods: {
getData(srcId) {
this.srcId = srcId
this.loading = true
const api = [
this.getTemVol(),
this.getTemVolData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getTemVolData() {
this.volLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetTemperatureVoltageData({
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
self.initVolTem(res.data);
resolve(res);
})
.finally(() => {
this.volLoading = false
})
});
},
getTemVol() {
this.temLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetTemVolData({
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
self.panelData = res.data?.packData
self.initVolChart(res.data?.voltageList);
this.VolNumber = res.data.voltageList.length ? this.VolNumber + `(${res.data.voltageList.length})` : '单体电压柱状图'
self.initTemChart(res.data?.temperatureList)
this.TemNumber = res.data.temperatureList.length ? this.TemNumber + `(${res.data.temperatureList.length})` : '单体温度柱状图'
resolve(res);
})
.finally((err) => {
this.temLoading = false
})
});
},
initTemChart(val) {
const yValue = []
const xAxis = []
val.forEach((el) => {
xAxis.push(el.xvalue)
yValue.push(el.yvalue)
})
this.tem_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: {
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
},
type: 'value',
name: '(℃)'
},
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: {
barWidth: 15,
type: 'bar',
itemStyle: {
color: '#009C77',
emphasis: {
color: '#faba11' // hover拐点颜色定义
}
},
data: yValue
},
}
},
initVolChart(val) {
const yValue = []
const xAxis = []
val.forEach((el) => {
xAxis.push(el.xvalue)
yValue.push(el.yvalue)
})
this.vol_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: {
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
},
type: 'value',
name: '(V)'
},
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: {
barWidth: 12,
type: 'bar',
itemStyle: {
color: '#009C77',
emphasis: {
color: '#faba11' // hover拐点颜色定义
}
},
data: yValue
},
}
},
initVolTem(val) {
const categories = []
const categories2 = []
const data = []
const data2 = []
if (val) {
val.voltageList.forEach(i => {
categories2.push(i.xvalue)
data2.push(i.yvalue)
})
val.temperatureList.forEach(i => {
categories.push(i.xvalue)
data.push(i.yvalue)
})
}
this.val_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
axisPointer: {},
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
confine: true,
formatter: function (params) {
var relNameV = ''
var relValV = ''
var relNameT = ''
var relValT = ''
relNameV += params[0].name + 'V'
relValV += params[0].value + this.$t('homePage.device.num')
relNameT += params[1].name + '℃'
relValT += params[1].value + this.$t('homePage.device.num')
return `${params[0].marker}${this.$t('homePage.device.tem')}(${relNameV})` + '\n' + relValV + '\n' + `${ params[1].marker}${this.$t('homePage.device.vol')}(${relNameT})` + '\n' + relValT
},
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: true,
data: categories2,
axisLabel: {
color: '#A3A3A3',
formatter: '{value} V'
}
},
{
type: 'category',
boundaryGap: true,
data: categories,
axisLabel: {
formatter: '{value} ℃',
color: '#A3A3A3',
margin: 2
}
}
],
yAxis: [
{
type: 'value',
name: this.$t('homePage.device.volUnit'),
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3',
padding: [0, 0, 0, 40]
},
min: 0,
},
{
type: 'value',
name: this.$t('homePage.device.temUnit'),
boundaryGap: [0.2, 0.2],
min: 0,
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3',
padding: [0, 80, 0, 0]
},
}
],
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: [{
name: this.$t('homePage.device.vol'),
barWidth: '15',
type: 'bar',
itemStyle: {
color: '#009C77',
emphasis: {
color: '#fbbb11'
}
},
data: data2
},
{
itemStyle: {
color: '#1F78B4',
emphasis: {
color: '#fbbb11'
}
},
name: this.$t('homePage.device.tem'),
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
data: data
}
]
}
}
},
}
</script>
<style lang="scss" scoped>
.pack-warp {
height: 100% !important;
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
position: relative;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.group-box {
display: flex;
flex-direction: row;
align-items: center;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.chart-box {
width: 650rpx;
height: 500rpx;
margin-top: 20rpx;
position: relative;
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
}
}
</style>

View File

@ -0,0 +1,994 @@
<template>
<view class="pcs-warp">
<view class="box">
<view class="topology-box">
<Section :title="$t('homePage.device.pcsTopu')" />
<topoCanvas cId="canvas" :width="'100%'" :height="'100%'" :canvas-data="canvasData" />
</view>
</view>
<view class="box">
<Section :title="$t('homePage.device.totalAcReaPower')">
<view slot="right" style="flex: 1">
<view class="top-right-box">
<span class="time">{{this.$t('homePage.device.timeGranularity')}}:</span>
<span @click="openTimeAction" class="value">{{sampleTime}}</span>
</view>
</view>
</Section>
<view class="chart-box">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts v-else id="pcsChart" :options="curve_option"></charts>
</view>
</view>
<view class="box" style="margin-bottom: 0;">
<Section :title="$t('homePage.device.deviceData')" />
<zero-loading v-if="stationLoading" position="absolute"></zero-loading>
<view v-else class="group-box">
<view class="group-item" @click="showHistory($t('homePage.device.acPower'), 'outputPower', 'pcs', 'kW', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.outputPower | kWFormat }}
</view>
<view class="item-title">{{this.$t('homePage.device.acPower')}}({{panelData.outputPower | kwUnitFormat }})</view>
</view>
</view>
<view class="group-item border-right"
@click="showHistory($t('homePage.device.acRecPower'), 'reactivePowerPCS', 'pcs', 'kVar', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zjrl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.reactivePowerPCS }}
</view>
<view class="item-title">{{this.$t('homePage.device.acRecPower')}}(kVar)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.gridFrequency'), 'grid', 'pcs', 'Hz', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.grid | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.gridFrequency')}}(Hz)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.abLineVol'), 'volA', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volA | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.abLineVol')}}(V)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.bcLineVol'), 'volB', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volB | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.bcLineVol')}}(V)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.caLineVol'), 'volC', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.volC | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.caLineVol')}}(V)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.acur'), 'currentA', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentA | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.acur')}}(A)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.bcur'), 'currentB', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentB | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.bcur')}}(A)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.ccur'), 'currentC', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.currentC | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.ccur')}}(A)</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.DCPower'), 'dcPower', 'pcs', 'kW', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/dqgl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcPower | kWFormat }}</view>
<view class="item-title">{{this.$t('homePage.device.DCPower')}}({{ panelData.dcPower | kwUnitFormat}})</view>
</view>
</view>
<view class="group-item border-right" @click="showHistory($t('homePage.device.DCVol'), 'dcInputVol', 'pcs', 'V', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/zfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcInputVol | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.DCVol')}}(V)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.DCCurrent'), 'dcCurrent', 'pcs', 'A', '')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rfdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{ panelData.dcCurrent | isNull }}
</view>
<view class="item-title">{{this.$t('homePage.device.DCCurrent')}}(A)</view>
</view>
</view>
</view>
</view>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
<u-action-sheet :list="actionSheetList" v-model="timeShow" @click="actionSheetCallback" @close="closeTimeAction"
:mask-close-able="false"></u-action-sheet>
</view>
</template>
<script>
import topoCanvas from '@/components/new-canvas/index.vue'
import historyModal from '@/components/history-modal/index.vue'
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
export default {
components: {
historyModal,
Section,
charts,
topoCanvas
},
data() {
return {
curve_option: {},
panelData: {},
histroyShow: false,
chartTitle: null,
chartLoading: false,
stationLoading: false,
hisParams: {},
timeShow: false,
time: "1",
stationId: null,
srcId: null,
hnStationId: [417, 398, 416, 415, 405, 485],
actionSheetList: this.$t('homePage.device.timesArr'),
sampleTime:this.$t('homePage.device.timesArr')[0].label,
canvasData: [],
textCanvasData: [
//0
{
type: "text",
coord: [
[190, 70]
],
font: [{
text: this.$t('homePage.device.acbreaker'),
size: 12,
color: "#333333",
}, ],
},
//1
{
type: "text",
coord: [
[190, 200]
],
font: [{
text: this.$t('homePage.device.dcbreaker'),
size: 12,
color: "#333333",
}, ],
},
//2
{
type: "text",
coord: [
[200, 260]
],
font: [{
text: "SOC",
size: 12,
color: "#999",
},
{
text: "20%",
size: 12,
color: "#000",
left: 35
},
],
},
//3
{
type: "text",
coord: [
[35, 80]
],
font: [{
text: this.$t('homePage.device.dcbreaker') + ':',
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000000",
left: 65
},
],
},
//4
{
type: "text",
coord: [
[3, 100]
],
font: [{
text: this.$t('homePage.device.rsState') + ':',
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000000",
left: 98
},
],
},
//5
{
type: "text",
coord: [
[3, 120]
],
font: [{
text: this.$t('homePage.device.gridMode') + ':',
size: 14,
color: "#999999",
width: 50,
},
{
text: "",
size: 14,
color: "#000",
left: 80
},
],
},
//6
{
type: "text",
coord: [
[35, 140]
],
font: [{
text: this.$t('homePage.device.deviceState') + ':',
size: 14,
color: "#999",
width: 50,
},
{
text: "",
size: 14,
color: "#000",
left: 65
},
],
},
],
imageCanvasData: [{
//AC/DC
type: "image",
url: "/static/topology/DC.png",
coord: [
[155, 110],
[30, 30],
],
},
{
//电池
type: "image",
url: "/static/topology/battary.png",
coord: [
[144, 240],
[50, 50],
],
},
],
lineCanvasData: [{
type: "line",
coord: [
[60, 30],
[280, 30],
],
color: "#19875c",
width: 2,
},
{
type: "line",
coord: [
[170, 30],
[170, 240],
],
color: "#19875c",
width: 2,
},
],
rectCanvasData: [{
type: "rect",
background: "#19875c",
coord: [
[160, 50],
[20, 30],
],
},
{
type: "rect",
background: "#19875c",
coord: [
[160, 180],
[20, 30],
],
},
]
}
},
computed: {
currentStation() {
return this.vuex_currentStation;
},
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true,
},
},
methods: {
getData(srcId) {
this.srcId = srcId
this.getChart()
this.getStatus()
},
getChart() {
const self = this
self.chartLoading = true;
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetPCSCurve({
stationId: this.stationId,
sampleTime: this.time,
srcId: this.srcId,
})
.then((res) => {
self.chartLoading = false;
self.initChargeChart(res.data);
// this.getStatus();
resolve(res);
})
.catch((err) => {
reject("错误");
})
.finally(() => {
self.chartLoading = false;
});
});
},
initChargeChart(val) {
const gonglv = [];
const soc = [];
const xAxis = [];
val.forEach((v) => {
xAxis.push(v.data);
gonglv.push(v.pcsRealTimeCurve);
soc.push(v.inCoreDataCurve);
});
this.curve_option = {
color: ["#009C77", "#BFE49F"],
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
axisPointer: {},
confine: true,
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
grid: {
top: "15%",
left: "5%",
right: "3%",
bottom: "10%",
containLabel: true,
},
xAxis: {
type: "category",
data: xAxis,
splitLine: {
show: false,
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = "";
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr =
p === rowNumber - 1 ?
params.substring(start, paramsNameNumber) :
params.substring(start, end) + "\n";
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [{
type: "value",
name: this.$t('homePage.device.totalActivePower') + "(kW)",
axisLabel: {
color: "#A3A3A3",
},
nameTextStyle: {
color: "#A3A3A3",
},
min: function(value) {
return Math.floor(
(Math.abs(value.min) < value.max ?
-value.max * 1.05 :
value.min * 1.05
).toFixed(2)
);
},
max: function(value) {
return Math.ceil(
(Math.abs(value.min) < value.max ?
value.max * 1.05 :
-value.min * 1.05
).toFixed(2)
);
},
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, 30],
},
},
{
type: "value",
name: this.$t('homePage.device.totalReactivePower') + "(kVar)",
axisLabel: {
color: "#A3A3A3",
},
nameTextStyle: {
color: "#A3A3A3",
},
min: function(value) {
return Math.floor(
(Math.abs(value.min) < value.max ?
-value.max * 1.05 :
value.min * 1.05
).toFixed(2)
);
},
max: function(value) {
return Math.ceil(
(Math.abs(value.min) < value.max ?
value.max * 1.05 :
-value.min * 1.05
).toFixed(2)
);
},
nameTextStyle: {
fontSize: 12,
padding: [0, 0, 0, -90],
},
},
],
dataZoom: {
type: "inside",
},
series: [{
name: this.$t('homePage.device.totalActivePower'),
type: "line",
smooth: true,
symbol: "none",
areaStyle: {
opacity: 0,
},
// lineStyle: {
// color: '#00C8FF'
// },
data: gonglv,
},
{
name: this.$t('homePage.device.totalReactivePower'),
type: "line",
smooth: true,
yAxisIndex: 1,
symbol: "none",
areaStyle: {
opacity: 0,
},
// lineStyle: {
// color: '#FBBB11'
// },
data: soc,
},
],
};
},
openTimeAction() {
this.timeShow = true;
},
getStatus() {
this.stationLoading = true
const self = this;
this.$u.api.deviceList
.GetNewValue({
stationId: this.stationId,
srcId: this.srcId,
colList: [
"runState",
"remoteInPlace",
"onGrid",
"offGrid",
"stateCharging",
"stateDischarging",
"deviceStateStand",
"deviceStateFault",
"deviceStateFull",
"deviceStateEmpty",
"acBreaker",
"dcBreaker",
"soc",
"outputPower",
"reactivePowerPCS",
"grid",
"volA",
"volB",
"volC",
"currentA",
"currentB",
"currentC",
"dcPower",
"dcInputVol",
"dcCurrent",
],
})
.then((res) => {
const battery = self.updateBattery(res.data.soc?.value ? res.data.soc.value : 0);
self.rectCanvasData.push(battery)
this.panelData = {
outputPower: res.data.outputPower?.value ? res.data.outputPower?.value : 0,
reactivePowerPCS: res.data.reactivePowerPCS?.value ? res.data.reactivePowerPCS?.value :
0,
grid: res.data.grid?.value ? res.data.grid?.value : 0,
volA: res.data.volA?.value ? res.data.volA?.value : 0,
volB: res.data.volB?.value ? res.data.volB?.value : 0,
volC: res.data.volC?.value ? res.data.volC?.value : 0,
currentA: res.data.currentA?.value ? res.data.currentA?.value : 0,
currentB: res.data.currentB?.value ? res.data.currentB?.value : 0,
currentC: res.data.currentC?.value ? res.data.currentC?.value : 0,
dcPower: res.data.dcPower?.value ? res.data.dcPower?.value : 0,
dcInputVol: res.data.dcInputVol?.value ? res.data.dcInputVol?.value : 0,
dcCurrent: res.data.dcCurrent?.value ? res.data.dcCurrent?.value : 0,
};
this.textCanvasData[2].font[1].text = res.data.soc?.value ? res.data.soc.value + "%" : 0 + "%";
this.textCanvasData[3].font[1].text = this.workStatus(res.data.runState?.value);
if (this.stationId === 349 || this.stationId === 362 || this.stationId === 363) {
if (res.data.remoteInPlace?.value === 0) {
this.textCanvasData[4].font[1].text = this.$t('homePage.device.localAutomatic')
}
if (res.data.remoteInPlace?.value === 1) {
this.textCanvasData[4].font[1].text = this.$t('homePage.device.localManual')
}
if (res.data.remoteInPlace?.value === 2) {
this.textCanvasData[4].font[1].text = this.$t('homePage.device.distance')
}
} else {
if (res.data.remoteInPlace?.value === 0) {
this.textCanvasData[4].font[1].text = this.$t('homePage.device.local')
}
if (res.data.remoteInPlace?.value === 1) {
this.textCanvasData[4].font[1].text = this.$t('homePage.device.distance')
}
}
if (!res.data.acBreaker?.value) {
self.rectCanvasData[0].background = "rgba(25, 135, 92, 0.6y4)";
}
if (!res.data.dcBreaker?.value) {
self.rectCanvasData[1].background = "rgba(25, 135, 92, 0.6y4)";
}
this.textCanvasData[5].font[1].text = res.data.onGrid?.value ?
this.$t('homePage.device.grid') :
this.$t('homePage.device.offGrid');
if(res.data.outputPower?.value){
this.textCanvasData[6].font[1].text = this.getFlowDirection(res.data.outputPower?.value, res
.data.flowDirection)
}
this.canvasData = [...this.textCanvasData, ...this.imageCanvasData, ...this
.lineCanvasData, ...this.rectCanvasData
]
})
.finally((res) => {
this.stationLoading = false;
});
},
updateBattery(value) {
//电池电量 value 为0~100
const batteryHeight = 0.35 * value;
const battery = {
type: "rect",
background: "#19875c",
coord: [
[156, 285 - batteryHeight],
[25.5, batteryHeight],
],
};
return battery;
},
getRunState(value, value2) {
if (value) {
return this.$t('homePage.device.standby');
} else if (value2) {
return this.$t('homePage.device.fault');
} else {
return "";
}
},
// 设备工作状态
workStatus(val) {
if (val === 0) {
return this.$t('homePage.device.shutdown')
} else if (val === 1) {
return this.$t('homePage.device.run')
} else if (val === 2) {
return this.$t('homePage.device.standby')
} else {
return ''
}
},
// 充放电状态
getFlowDirection(val, flowDirection) {
if (flowDirection === 2) {
if (+val > +1) {
return this.$t('homePage.device.discharge')
}
if (+val < -1) {
return this.$t('homePage.device.charge')
}
if (val < 1 || +val.abs < 1 || !val) {
return this.$t('homePage.device.standing')
}
} else {
if (+val > +1) {
return this.$t('homePage.device.charge')
}
if (+val < -1) {
return this.$t('homePage.device.discharge')
}
if (val < 1 || +val.abs < 1 || !val) {
return this.$t('homePage.device.standing')
}
}
},
// 电池信息
updateBattery(value) {
//电池电量 value 为0~100
const batteryHeight = 0.35 * value;
const battery = {
type: "rect",
background: "#19875c",
coord: [
[156, 285 - batteryHeight],
[25.5, batteryHeight],
],
};
return battery;
},
// 历史曲线
showHistory(name, modelCol, modelType, unit) {
this.hisParams = {
modelCol: modelCol,
modelType: modelType,
unit: unit
}
this.chartTitle = name
this.histroyShow = true
},
actionSheetCallback(index) {
this.sampleTime = this.actionSheetList[index].text;
this.time = this.actionSheetList[index].value;
this.getChart()
},
closeTimeAction() {
this.timeShow = false;
},
}
}
</script>
<style lang="scss" scoped>
.pcs-warp {
background-color: #f5f5f5;
height: 100%;
.box {
background: #ffffff;
border-radius: 16rpx;
padding: 20rpx;
width: 100%;
border: 16rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
margin-bottom: 20rpx;
position: relative;
.topology-box {
width: 100%;
height: 640rpx;
position: relative;
}
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.time {
padding-right: 10rpx;
display: inline-block;
height: 40rpx;
}
.value {
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx 20rpx 10rpx 20rpx;
height: 40rpx;
}
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.chart-box {
width: 650rpx;
height: 460rpx;
margin-top: 20rpx;
position: relative;
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,962 @@
<template>
<view class="stack-warp">
<view class="all-con-item-box" style="margin-top: 0!important;">
<Section :title="$t('homePage.device.stackTotalVol')">
</Section>
<view class="chart-box">
<zero-loading v-if="chartLoading" position="absolute"></zero-loading>
<charts v-else :id="'pcsChart'" :options="curve_option"></charts>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.runData')" />
<zero-loading v-if="runLoading" position="absolute"></zero-loading>
<view v-else class="group-box ">
<view class="group-item" @click="showHistory($t('homePage.device.leftTemCabin'), 'wet', 'transmitter','℃','','左')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.cabinetTemperatureLeft | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.leftTemCabin')}}()</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.leftHubCabin'), 'temperature', 'transmitter','%','','左')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.cabinetHumidityLeft | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.leftHubCabin')}}(%)</view>
</view>
</view>
<view class="group-item " @click="showHistory($t('homePage.device.rightTemCabin'), 'transmitter', 'stack','℃','','右')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.cabinetTemperatureRight | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.rightTemCabin')}}()</view>
</view>
</view>
<view class="group-item " @click="showHistory($t('homePage.device.rightHubCabin'), 'wet', 'transmitter','%','','右')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.cabinetHumidityRight | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.rightHubCabin')}}(%)</view>
</view>
</view>
<view class="group-item "
@click="showHistory($t('homePage.device.stackCurrent'), 'outputPower', 'bms','A','', '',`${outputPowerType}`,`${outputPowerId}`)">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.outputPower | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.stackCurrent')}}(A)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.stackTotalVol'), 'stackTotalVol', 'bms','V','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.stackTotalVol | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.stackTotalVol')}}(V)</view>
</view>
</view>
<view class="group-item " @click="showHistory($t('homePage.device.stackTotalCurrent'), 'stackTotalCurrent', 'bms','A','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.stackTotalCurrent | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.stackTotalCurrent')}}(A)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.stackSoc'), 'soc', 'bms','%','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.soc | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.stackSoc')}}(%)</view>
</view>
</view>
<view class="group-item " @click="showHistory($t('homePage.device.CumulativeCharge'), 'totalCharge', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{(panelData.totalCharge / 1000).toFixed(2) | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.CumulativeCharge')}}(MWh)</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.CumulativeDischarge'), 'totalDischarge', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{(panelData.totalDischarge / 1000).toFixed(2) | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.CumulativeDischarge')}}(MWh)</view>
</view>
</view>
<view class="group-item"
@click="showHistory($t('homePage.device.zdz'), 'stackInsulationPositiveResistance', 'bms','kΩ','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.stackInsulationPositiveResistance | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.zdz')}}()</view>
</view>
</view>
<view class="group-item "
@click="showHistory($t('homePage.device.fdz'), 'stackInsulationNegativeResistance', 'bms','kΩ','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.stackInsulationNegativeResistance | isNull}}
</view>
<view class="item-title">{{this.$t('homePage.device.fdz')}}()</view>
</view>
</view>
<view class="group-item " @click="showHistory($t('homePage.device.rechargeCapacity'), 'rechargeCapacity', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.rechargeCapacity | kwhFormat}}
</view>
<view class="item-title">{{this.$t('homePage.device.rechargeCapacity')}}({{panelData.rechargeCapacity | kwhUnitFormat}})</view>
</view>
</view>
<view class="group-item" @click="showHistory($t('homePage.device.dischargeCapacity'), 'dischargeCapacity', 'bms','kWh','')">
<view class="history-icon">
<image src="/static/aidex/images/history-icon.png"></image>
</view>
<view class="item-icon">
<image src="/static/aidex/images/rcdl.png"></image>
</view>
<view class="item-con">
<view class="item-num">{{panelData.dischargeCapacity | kwhFormat}}
</view>
<view class="item-title">{{this.$t('homePage.device.dischargeCapacity')}}({{panelData.dischargeCapacity | kwhUnitFormat}})</view>
</view>
</view>
</view>
</view>
<view class="all-con-item-box">
<Section :title="$t('homePage.device.runData')" />
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.totalMaxVolData'), 'totalMaxVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.totalMaxVolData')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.totalMaxVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
{{this.$t('homePage.device.stackCell')}}{{panelData.totalMaxVolNum | isNull}}
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.totalMinVolData'), 'totalMinVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.totalMinVolData')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.totalMinVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
{{this.$t('homePage.device.stackCell')}}{{panelData.totalMinVolNum | isNull}}
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxvolDiff')}}
</view>
<view class="value">
{{(panelData.singleMaxVolData - panelData.singleMinVolData).toFixed(3) | isNull }}V
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.maxCellVol'), 'singleMaxVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxCellVol')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.singleMaxVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.stackNum')}}{{panelData.singleMaxVolNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.groupNum')}}{{panelData.singleMaxVolBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellLocation')}}{{panelData.singleMaxVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.minCellVol'), 'singleMinVolData', 'bms','V','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.minCellVol')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{panelData.singleMinVolData | isNull}}V
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.stackNum')}}{{panelData.singleMinVolNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.groupNum')}}{{panelData.singleMinVolBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellLocation')}}{{panelData.singleMinVolBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxTemDiff')}}
</view>
<view class="value">
{{ panelData.singleMaxTemData - panelData.singleMinTemData | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box border-bottom padding-top-30 padding-bottom-30"
@click="showHistory($t('homePage.device.maxCellTem'), 'singleMaxTemData', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.maxCellTem')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{ panelData.singleMaxTemData | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.stackNum')}}{{ panelData.singleMaxTemNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.groupNum')}}{{ panelData.singleMaxTemBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellLocation')}}{{ panelData.singleMaxTemBoxNum | isNull}}
</view>
</view>
</view>
</view>
<view class="group-box padding-top-30 " @click="showHistory($t('homePage.device.minCellTem'), 'singleMinTemData', 'bms','℃','')">
<view class="other-value">
<view class="top-value">
<view class="title">
{{this.$t('homePage.device.minCellTem')}}
</view>
<view class="zhexian-icon">
<image src="/static/aidex/images/zhexian.png"></image>
</view>
<view class="value">
{{ panelData.singleMinTemData | isNull}}
</view>
</view>
<view class="bottom-value">
<view>
{{this.$t('homePage.device.stackNum')}}{{ panelData.singleMinTemNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.groupNum')}}{{ panelData.singleMinTemBMUNum | isNull}}
</view>
<view>
{{this.$t('homePage.device.cellLocation')}}{{ panelData.singleMinTemBoxNum | isNull }}
</view>
</view>
</view>
</view>
</view>
<historyModal :is-show.sync="histroyShow" :title="chartTitle" :params="hisParams" />
</view>
</template>
<script>
import Section from '@/components/section/index.vue'
import charts from "@/components/charts/index";
import historyModal from '@/components/history-modal/index.vue'
export default {
data() {
return {
loading: false,
histroyShow: false,
chartTitle: null,
curve_option: {},
hisParams: {},
stationId: null,
srcId: null,
chartLoading: false,
panelData: {},
runLoading: false
}
},
components: {
Section,
charts,
historyModal
},
computed: {
currentStation() {
return this.vuex_currentStation
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
},
},
methods: {
showHistory(name, modelCol, modelType, unit, name2, deviceName, outputPowerType, outputPowerId) {
this.hisParams = {
modelCol: modelCol,
modelType: outputPowerType ? outputPowerType : modelType,
unit: unit,
stationId: this.stationId,
srcId: outputPowerId ? outputPowerId : this.srcId,
// deviceType: outputPowerType ? outputPowerType : deviceType,
deviceName: deviceName
}
this.chartTitle = name
this.histroyShow = true
},
getTotalData() {
this.runLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetNewValue({
colList: ["cabinetHumidityLeft", "cabinetHumidityRight",
'cabinetTemperatureLeft', 'cabinetTemperatureRight',
'outputPower', 'stackTotalVol', 'stackTotalCurrent', 'soc',
'singleMaxVolData', 'singleMinVolData', 'totalCharge', 'totalDischarge',
'stackInsulationPositiveResistance', 'stackInsulationNegativeResistance',
'rechargeCapacity', 'dischargeCapacity', 'totalMaxVolData',
'totalMaxVolNum', 'totalMinVolData',
'totalMinVolNum', 'singleMaxVolNum', 'singleMaxVolBMUNum',
'singleMaxVolBoxNum',
'singleMinVolNum', 'singleMinVolBMUNum', 'singleMinVolBoxNum',
'singleMaxTemData', 'singleMaxTemNum', 'singleMaxTemBMUNum',
'singleMaxTemBoxNum',
'singleMinTemData', 'singleMinTemNum', 'singleMinTemBMUNum',
'singleMinTemBoxNum'
],
stationId: this.stationId,
srcId: this.srcId
})
.then((res) => {
this.panelData = {
cabinetHumidityLeft: res.data.cabinetHumidityLeft?.value,
cabinetHumidityRight: res.data.cabinetHumidityRight?.value,
cabinetTemperatureLeft: res.data.cabinetTemperatureLeft?.value,
cabinetTemperatureRight: res.data.cabinetTemperatureRight?.value,
outputPower: res.data.outputPower?.value,
stackTotalVol: res.data.stackTotalVol?.value,
stackTotalCurrent: res.data.stackTotalCurrent?.value,
soc: res.data.soc?.value,
singleMaxVolData: res.data.singleMaxVolData?.value,
singleMinVolData: res.data.singleMinVolData?.value,
totalCharge: res.data.totalCharge?.value,
totalDischarge: res.data.totalDischarge?.value,
stackInsulationPositiveResistance: res.data
.stackInsulationPositiveResistance?.value,
stackInsulationNegativeResistance: res.data
.stackInsulationNegativeResistance?.value,
rechargeCapacity: res.data.rechargeCapacity?.value,
dischargeCapacity: res.data.dischargeCapacity?.value,
totalMaxVolData: res.data.totalMaxVolData?.value,
totalMaxVolNum: res.data.totalMaxVolNum?.value,
totalMinVolData: res.data.totalMinVolData?.value,
totalMinVolNum: res.data.totalMinVolNum?.value,
singleMaxVolNum: res.data.singleMaxVolNum?.value,
singleMaxVolBMUNum: res.data.singleMaxVolBMUNum?.value,
singleMaxVolBoxNum: res.data.singleMaxVolBoxNum?.value,
singleMinVolNum: res.data.singleMinVolNum?.value,
singleMinVolBMUNum: res.data.singleMinVolBMUNum?.value,
singleMinVolBoxNum: res.data.singleMinVolBoxNum?.value,
singleMaxTemData: res.data.singleMaxTemData?.value,
singleMaxTemNum: res.data.singleMaxTemNum?.value,
singleMaxTemBMUNum: res.data.singleMaxTemBMUNum?.value,
singleMaxTemBoxNum: res.data.singleMaxTemBoxNum?.value,
singleMinTemData: res.data.singleMinTemData?.value,
singleMinTemNum: res.data.singleMinTemNum?.value,
singleMinTemBMUNum: res.data.singleMinTemBMUNum?.value,
singleMinTemBoxNum: res.data.singleMinTemBoxNum?.value
}
this.outputPowerType = res.data.outputPower?.deviceType
this.outputPowerId = res.data.outputPower?.srcId
resolve(res);
})
.finally((err) => {
this.runLoading = false
})
});
},
getData(srcId) {
this.srcId = srcId
this.loading = true
const api = [
this.getSocChart(),
this.getTotalData()
]
Promise.all(api).then(result => {
this.err = result
this.loading = false
})
},
getSocChart() {
this.chartLoading = true
const self = this
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetSocCurve({
colName: ["soc", "stackTotalvol"],
stationId: this.stationId,
type: 'day',
srcId: this.srcId
})
.then((res) => {
self.initChargeChart(res.data);
resolve(res);
})
.finally(() => {
this.chartLoading = false
})
});
},
initChargeChart(val) {
const gonglv = []
const soc = []
const xAxis = []
val[1].staticCurveList.forEach(v => {
xAxis.push(v.date)
gonglv.push(v.digital)
})
val[0].staticCurveList.forEach(v => {
soc.push(v.digital)
})
this.curve_option = {
animationDuration: 500,
animationEasing: "cubicInOut",
tooltip: {
trigger: "axis",
textStyle: {
textShadowBlur: 10, // 重点
textShadowColor: 'transparent', // 重点
},
axisPointer: {},
confine: true,
position: function(point, params, dom, rect, size) {
// 鼠标坐标和提示框位置的参考坐标系是以外层div的左上角那一点为原点x轴向右y轴向下
// 提示框位置
var x = 0; // x坐标位置
var y = 0; // y坐标位置
// 当前鼠标位置
var pointX = point[0];
var pointY = point[1];
// 外层div大小
// var viewWidth = size.viewSize[0];
// var viewHeight = size.viewSize[1];
// 提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
// boxWidth > pointX 说明鼠标左边放不下提示框
if (boxWidth > pointX) {
x = 5; // 自己定个x坐标值以防出屏
y -= 15; // 防止点被覆盖住,可根据情况自行调节
} else {
// 左边放的下
x = pointX - boxWidth - 15;
}
// boxHeight > pointY 说明鼠标上边放不下提示框
if (boxHeight + 20 > pointY) {
y = pointY + 15;
} else if (boxHeight > pointY) {
y = 5;
} else {
// 上边放得下
y += pointY - boxHeight;
}
return [x, y];
},
},
color: ['#009C77', '#BFE49F'],
grid: {
top: '15%',
left: '5%',
right: '3%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: xAxis,
splitLine: {
show: false
},
axisLabel: {
show: true,
color: "#A3A3A3",
formatter: function(params) {
let newParamsName = '';
const paramsNameNumber = params.length; // 文字总长度
const provideNumber = 11; //一行显示几个字
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
const start = p * provideNumber;
const end = start + provideNumber;
const tempStr = p === rowNumber - 1 ? params.substring(start,
paramsNameNumber) : params.substring(start, end) + '\n';
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
},
},
yAxis: [
{
type: 'value',
name: this.$t('homePage.device.stackTotalVol') + '(V)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3',
padding: [0,0,0,20]
}
},
{
type: 'value',
name: 'SOC(%)',
axisLabel: {
color: '#A3A3A3'
},
nameTextStyle: {
color: '#A3A3A3'
}
}
],
dataZoom: [{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
height: 20,
bottom: 10,
end: 100
}
],
series: [{
name: this.$t('homePage.device.stackTotalVol'),
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: gonglv
},
{
name: 'SOC',
type: 'line',
smooth: true,
yAxisIndex: 1,
symbol: 'none',
areaStyle: {
opacity: 0
},
data: soc
}
]
}
}
}
}
</script>
<style lang="scss" scoped>
.stack-warp {
background-color: #f5f5f5;
.all-con-item-box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
position: relative;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.top-right-box {
display: flex;
flex-direction: row;
align-items: center;
flex: 1;
justify-content: flex-end;
.top-right-item {
padding: 5rpx 10rpx;
border: 1rpx solid #4c9ee6;
font-size: 24rpx;
color: #4c9ee6;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #4c9ee6;
color: #ffffff;
}
}
}
.ring-data-box {
padding: 30rpx;
.ring-data-item {
.ring-title {
font-size: 28rpx;
color: #4c9ee6;
}
}
}
.group-box {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
.other-value {
display: flex;
flex-direction: column;
width: 100%;
.top-value {
display: flex;
justify-content: space-between;
position: relative;
.title {
font-size: 24rpx;
color: rgba(40, 40, 40, 1);
}
.zhexian-icon {
position: absolute;
right: 70%;
image {
width: 28rpx;
height: 28rpx;
}
}
.value {
font-size: 32rpx;
color: rgba(0, 156, 119, 1);
font-weight: 400;
}
}
.bottom-value {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: rgba(153, 153, 153, 1);
}
}
}
.group-item {
display: flex;
flex-direction: column;
align-items: center;
width: 199rpx;
justify-content: center;
background: #d7e9e548;
border-radius: 10rpx;
margin: 10rpx 10rpx;
position: relative;
padding: 10rpx 0;
.history-icon {
position: absolute;
right: 0rpx;
top: 0rpx;
}
image {
width: 40rpx;
height: 40rpx;
}
.item-con {
display: flex;
flex-direction: column;
align-items: center;
// margin-left: 15rpx;
width: 100%;
.item-title {
width: 100%;
font-size: 24rpx;
color: #2a2a2a;
margin-top: 10rpx;
text-align: center;
}
.item-num {
font-size: 36rpx;
color: #282828;
font-weight: bold;
max-width: 90%;
text-align: center;
}
.item-unit {
color: #cccccc;
font-size: 16rpx;
padding-left: 10rpx;
}
}
}
}
.chart-box {
width: 650rpx;
height: 500rpx;
margin-top: 20rpx;
}
.slot-content {
padding: 20rpx;
}
.border-bottom {
border-bottom: 4rpx dotted #e5e5e5;
}
.border-right {
border-right: 4rpx dotted #e5e5e5;
}
.padding-top-30 {
padding-top: 30rpx;
}
.padding-bottom-30 {
padding-bottom: 30rpx;
}
}
</style>

View File

@ -0,0 +1,166 @@
<template>
<view class="warp">
<zero-loading v-if="loading"></zero-loading>
<template v-else>
<Search style="margin-bottom: 20rpx;" @search="search" />
<scroll-view style="height: calc(100% - 130rpx);" scroll-y="true" @scrolltolower="onReachScollBottom"
v-if="total">
<view class="value-box" v-for="(item,index) in table_data" :key="index">
<view class="title" >
{{item.colName}}
</view>
<view class="value">
{{item.value}}
</view>
</view>
<view v-if="total > 10">
<u-loadmore :status="status" icon-type="iconType" :load-text="loadText" v-if="loadmoreshow" />
</view>
<!-- </view> -->
</scroll-view>
<view v-else style="height: 100%;">
<u-empty :text="this.$t('homePage.device.noData')" mode="list"></u-empty>
</view>
</template >
</view>
</template>
<script>
import Search from '@/components/new-search/index.vue'
export default {
components: {
Search
},
data() {
return {
stationId: null,
loading: false,
srcId: null,
table_data: [],
value: '',
name: '',
type: 'text',
border: true,
status: "loadmore",
loadText: this.$t('homePage.device.loadText'),
loadmoreshow: true,
nodata: false,
pageNum: 1,
pageSize: 50,
total: 0
}
},
computed: {
currentStation() {
return this.vuex_currentStation;
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
}
},
onReachBottom() { //与methods 同级
},
created() {
this.loading = true
},
methods: {
onReachScollBottom() {
if (this.table_data.length < this.total) {
// this.pageSize += 5
this.getData()
} else {
this.status = "nomore"
}
},
search(val) {
this.name = val
this.pageNum = 1
this.table_data = []
this.getData()
},
getData(srcId) {
const self = this
if (srcId) {
this.srcId = srcId
}
// this.loading = true
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetPCSPoint({
stationId: this.stationId,
name: self.name,
pageNum: self.pageNum,
pageSize: self.pageSize,
sensType: 2,
srcId: self.srcId
})
.then((res) => {
// self.table_data = res.data.list
self.total = res.data.totalRows
self.table_data = self.table_data.concat(res.data.list)
if (self.total === 0) {
self.table_data = []
};
if (self.total) {
self.nodata = false
} else {
self.nodata = true
self.loadmoreshow = false
}
if (res.data.totalPages > self.pageNum) {
self.pageNum += 1
}
resolve(res);
})
.catch((err) => {
reject("错误");
}).finally(() => {
self.loading = false
})
});
}
}
}
</script>
<style lang="scss" scoped>
.warp {
height: 100% !important;
background-color: #f5f5f5;
padding-bottom: 70rpx;
.value-box {
width: 100%;
height: 80rpx;
// border: 1px solid #000;
display: flex;
justify-content: space-between;
padding: 15rpx 30rpx 15rpx 30rpx;
margin-bottom:20rpx;
border-radius: 8rpx;
background-color: #fff;
align-items: center;
.title {
color: #282828;
font-size: 24rpx;
}
.value {
color: #282828;
font-size: 36rpx;
}
}
}
</style>

View File

@ -0,0 +1,165 @@
<template>
<view class="warp" >
<zero-loading v-if="loading"></zero-loading>
<template v-else>
<Search style="margin-bottom: 20rpx;" @search="search" />
<scroll-view style="height: calc(100% - 130rpx);" scroll-y="true" @scrolltolower="onReachScollBottom" v-if="total">
<view class="value-box" v-for="(item,index) in table_data" :key="index">
<view class="title" >
{{item.colName}}
</view>
<view class="value">
{{item.value}}
</view>
</view>
<view v-if="total > 10">
<u-loadmore :status="status" icon-type="iconType" :load-text="loadText" v-if="loadmoreshow" />
</view>
</scroll-view>
<view v-else style="height: 100%;">
<u-empty :text="this.$t('homePage.device.noData')" mode="list"></u-empty>
</view>
</template >
</view>
</template>
<script>
import Search from '@/components/new-search/index.vue'
export default {
components: {
Search
},
data() {
return {
stationId: null,
loading: false,
srcId: null,
table_data: [],
value: '',
name:'',
type: 'text',
border: true,
status: "loadmore",
loadText: this.$t('homePage.device.loadText'),
loadmoreshow: true,
nodata:false,
pageNum:1,
pageSize:50,
total:0
}
},
computed: {
currentStation() {
return this.vuex_currentStation;
}
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id;
},
deep: true,
immediate: true
}
},
onReachBottom() { //与methods 同级
},
created(){
this.loading = true
},
methods: {
onReachScollBottom(){
if (this.table_data.length < this.total) {
// this.pageSize += 5
this.getData()
} else {
this.status = "nomore"
}
},
search(val) {
this.name = val
this.pageNum = 1
this.table_data = []
this.getData()
},
getData(srcId) {
const self = this
if (srcId) {
this.srcId = srcId
}
// this.loading = true
return new Promise((resolve, reject) => {
self.$u.api.deviceList
.GetPCSPoint({
stationId: this.stationId,
name:self.name,
pageNum: self.pageNum,
pageSize: self.pageSize,
sensType: 1,
srcId: self.srcId
})
.then((res) => {
// self.table_data = res.data.list
self.total = res.data.totalRows
self.table_data = self.table_data.concat(res.data.list)
if (self.total === 0) {
self.table_data = []
};
if (self.total) {
self.nodata = false
} else {
self.nodata = true
self.loadmoreshow = false
}
if(res.data.totalPages > self.pageNum){
self.pageNum += 1
}
resolve(res);
})
.catch((err) => {
reject("错误");
}).finally(() => {
self.loading = false
})
});
}
}
}
</script>
<style lang="scss" scoped>
.warp {
height: 100% !important;
background-color: #f5f5f5;
padding-bottom: 70rpx;
.value-box {
width: 100%;
height: 80rpx;
// border: 1px solid #000;
display: flex;
justify-content: space-between;
padding: 15rpx 30rpx 15rpx 30rpx;
margin-bottom:20rpx;
border-radius: 8rpx;
background-color: #fff;
align-items: center;
.title {
color: #282828;
font-size: 24rpx;
}
.value {
color: #282828;
font-size: 36rpx;
}
}
}
</style>

View File

@ -0,0 +1,344 @@
<template>
<view class="device-warp">
<u-navbar :is-back="true" :background="background" :border-bottom="false">
<view class="slot-wrap">
{{stationName}}
</view>
</u-navbar>
<view class="site-footer">
<u-tabs style="width: 100%;" :list="list" :is-scroll="false" :offset="[10,0]" active-color="#009C77"
:current="type" @change="changeTab"></u-tabs>
<view class="navigation">
<text v-for="(item,index) in deviceNavArr" :key="index">
<text class="null-text">{{item.name}}</text>
<text class="img"></text>
</text>
<text class="text" style="color: #009C77;">{{deviceName ? deviceName : ''}}</text>
</view>
</view>
<view class="components-box" :style="{height:`calc(100% - ${safeHeight}rpx)`}">
<JKPCS ref="PCS" v-if="type === 0 && Devicetype === 'pcs' && stationId === 484" />
<PCS ref="PCS" v-if="type === 0 && Devicetype === 'pcs' && stationId !== 484" />
<Cluster ref="Cluster" v-if="type === 0 && Devicetype === 'cluster'" />
<Pack ref="Pack" v-if="type === 0 && Devicetype === 'pack'" />
<Stack ref="Stack" v-if="type === 0 && Devicetype === 'stack' && stationId !== 484 " />
<JKStack ref="JKStack" v-if="type === 0 && Devicetype === 'stack' && stationId === 484" />
<Air ref="Air" v-if="type === 0 && Devicetype === 'air'" />
<Ammeter ref="Ammeter" v-if="type === 0 && Devicetype === 'ammeter'" />
<Emu ref="Emu" v-if="type === 0 && Devicetype === 'emu'" />
<DeviceYX ref="YX" v-if=" list.length === 3 && type === 1 " />
<DeviceYC ref="YC" v-if=" list.length === 3 &&type === 2 " />
<DeviceYX ref="YX" v-if=" list.length === 2 && type === 0" />
<DeviceYC ref="YC" v-if=" list.length === 2 && type === 1" />
</view>
</view>
</template>
<script>
import JKPCS from './components/jingke-pcs.vue'
import JKStack from './components/jingke-stack.vue'
import PCS from './components/pcs.vue'
import Cluster from './components/cluster.vue'
import Stack from './components/stack.vue'
import Pack from './components/pack.vue'
import DeviceYC from './components/yc.vue'
import DeviceYX from './components/yx.vue'
import Air from './components/air.vue'
import Ammeter from './components/ammeter.vue'
import Emu from './components/emu.vue'
export default {
created() {
const self = this
uni.getStorage({
key: 'deviceNavArr', //本地缓存中的指定的 key
success(res) { //接口调用的回调函数res = {data: key对应的内容}
self.deviceNavArr = res.data
}
})
uni.getStorage({
key: 'deviceName', //本地缓存中的指定的 key
success(res) { //接口调用的回调函数res = {data: key对应的内容}
self.deviceName = res.data
}
})
},
watch: {
currentStation: {
handler(val) {
this.stationId = val.id
this.stationName = val.name
},
deep: true,
immediate: true,
},
},
computed: {
currentStation() {
return this.vuex_currentStation;
}
},
onLoad(options) {
this.Devicetype = options.type
if (this.Devicetype === 'storage' || this.Devicetype === 'anything') {
this.list = [{
name: this.$t('homePage.device.yx')
}, {
name: this.$t('homePage.device.yc'),
}],
this.type = 0
}
this.srcId = options.srcId
},
mounted() {
this.$nextTick(() => {
if (this.$refs.JKPCS) {
this.$refs.JKPCS.getData(this.srcId)
}
if (this.$refs.JKStack) {
this.$refs.JKStack.getData(this.srcId)
}
if (this.$refs.PCS) {
this.$refs.PCS.getData(this.srcId)
}
if (this.$refs.Stack) {
this.$refs.Stack.getData(this.srcId)
}
if (this.$refs.YC) {
this.$refs.YC.getData(this.srcId)
}
if (this.$refs.YX) {
this.$refs.YX.getData(this.srcId)
}
if (this.$refs.Cluster) {
this.$refs.Cluster.getData(this.srcId)
}
if (this.$refs.Pack) {
this.$refs.Pack.getData(this.srcId)
}
if (this.$refs.Air) {
this.$refs.Air.getData(this.srcId)
}
if (this.$refs.Ammeter) {
this.$refs.Ammeter.getData(this.srcId)
}
if (this.$refs.Emu) {
this.$refs.Emu.getData(this.srcId)
}
})
},
components: {
JKPCS,
PCS,
DeviceYC,
DeviceYX,
Cluster,
Stack,
Pack,
Air,
Ammeter,
Emu,
JKStack
},
data() {
return {
type: 0,
srcId: null,
Devicetype: null,
deviceNavArr: [],
deviceName: null,
list: [{
name: this.$t('homePage.device.data')
}, {
name: this.$t('homePage.device.yx')
}, {
name: this.$t('homePage.device.yc'),
}],
background: {
backgroundColor: "#0EA17E",
},
stationId: null,
stationName: null,
safeHeight: 225
};
},
onShow() {
uni.getSystemInfo({
success: res => {
this.safeHeight = this.safeHeight + (res.screenHeight - res.safeArea.bottom) + 60;
},
fail(err) {
console.log(err);
}
})
},
onReachBottom() {
},
methods: {
device(val) {
this.Devicetype = val
},
changeTab(type) {
this.type = type
this.$nextTick(() => {
if (this.$refs.JKPCS) {
this.$refs.JKPCS.getData(this.srcId)
}
if (this.$refs.JKStack) {
this.$refs.JKStack.getData(this.srcId)
}
if (this.$refs.PCS) {
this.$refs.PCS.getData(this.srcId)
}
if (this.$refs.Stack) {
this.$refs.Stack.getData(this.srcId)
}
if (this.$refs.YC) {
this.$refs.YC.getData(this.srcId)
}
if (this.$refs.YX) {
this.$refs.YX.getData(this.srcId)
}
if (this.$refs.Cluster) {
this.$refs.Cluster.getData(this.srcId)
}
if (this.$refs.Pack) {
this.$refs.Pack.getData(this.srcId)
}
if (this.$refs.Air) {
this.$refs.Air.getData(this.srcId)
}
if (this.$refs.Ammeter) {
this.$refs.Ammeter.getData(this.srcId)
}
if (this.$refs.Emu) {
this.$refs.Emu.getData(this.srcId)
}
})
}
},
};
</script>
<style lang="scss" >
page{
height: 100%!important;
}
</style>
<style lang="scss" scoped>
.device-warp {
height: 100%;
background-color: #f5f5f5;
padding-top: 0;
}
::v-deep .u-tabs {
width: 100%;
height: 100%;
}
.components-box {
padding: 20rpx;
// height: calc(100% - 225rpx);
// overflow: auto;
margin-top: 20rpx;
}
.slot-wrap {
display: flex;
align-items: center;
justify-content: center;
color: #fff;
/* 如果您想让slot内容占满整个导航栏的宽度 */
flex: 1;
/* 如果您想让slot内容与导航栏左右有空隙 */
/* padding: 0 30rpx; */
}
.site-footer {
width: 100%;
height: 120rpx;
margin-bottom: 10rpx;
display: flex;
flex-direction: column;
// flex-direction: row;
align-items: center;
justify-content: space-around;
background-color: #fff;
z-index: 98;
.navigation {
width: 100%;
padding-top: 20rpx;
padding-left: 20rpx;
background-color: #f5f5f5;
.img {
display: inline-block;
width: 24rpx;
height: 24rpx;
margin-left: 10rpx;
margin-right: 10rpx;
background-image: url(/static/aidex/images/arrow-right.png);
background-size: 100% 120%;
}
.null-text {
height: 24rpx;
border-radius: 8rpx;
padding: 5rpx 10rpx 5rpx 10rpx;
color: #666666;
font-size: 20rpx;
background-color: rgba(217, 217, 217, 0.2);
padding-left: 5rpx;
}
.text {
height: 22rpx;
border: 1rpx solid rgba(0, 156, 119, 1);
border-radius: 8rpx;
padding: 5rpx 10rpx 5rpx 10rpx;
color: #666666;
font-size: 20rpx;
background-color: rgba(0, 156, 119, 0.1);
padding-left: 5rpx;
}
}
.footer-item {
display: flex;
flex-direction: column;
align-items: center;
color: #979797;
.footer-icon {
font-size: 48rpx;
}
.footer-title {
font-size: 28rpx;
margin-top: 10rpx;
}
&.active {
color: #24d1a9;
}
}
}
</style>