Files
smart_storage_app/pages/tabbar/dashboard.vue
2026-02-27 09:13:55 +08:00

617 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="u-page">
<!-- <zero-loading v-if="loading"></zero-loading> -->
<!-- 顶部电站 -->
<view class="new-nav">
<image type="image" src="../../static/aidex/images/nav-bg.png"
style="width: 100%; height: 100%; z-index: 0" />
<view class="station-box">
<stationDropdow style="width: 100%" ref="dropdow" />
</view>
</view>
<!-- 菜单 -->
<u-notice-bar mode="horizontal" type="primary" :list="list" style="margin-bottom: 20rpx;"
@click="toMsg"></u-notice-bar>
<view class="menu-box">
<view class="box" @click="changeMenu('device-list')">
<view class="icon device" />
<view class="title"> {{ this.$t("homePage.home.device") }} </view>
</view>
<view class="box" @click="changeMenu('earningSelect')">
<view class="icon earning" />
<view class="title"> {{ this.$t("homePage.home.earning") }} </view>
</view>
<view class="box" @click="changeMenu('alarm')">
<view class="icon alarm" />
<view class="title"> {{ this.$t("homePage.home.alarm") }} </view>
</view>
<view class="box" @click="changeMenu('policy-management')">
<view class="icon policy" />
<view class="title"> {{ this.$t("homePage.home.policy") }} </view>
</view>
</view>
<!-- 内容 -->
<view class="content-box">
<view class="box">
<Section :title="$t('homePage.home.stationTopo')" />
<zero-loading v-if="loading"></zero-loading>
<!-- 加载中占位可选 -->
<view v-else class="loading-tip">
<!-- <zero-loading v-if="tuopoloading"></zero-loading> -->
<cixi v-if="topologyType === 0" ref="tuopu" />
<kejiyuan v-else-if="topologyType === 2" ref="tuopu" />
<lingchao v-else-if="topologyType === 3" ref="tuopu" />
<jingke v-else-if="topologyType === 4" ref="tuopu" />
<weishanhu v-else-if="topologyType === 5" ref="tuopu" />
<zhongzihuanbao v-else-if="topologyType === 6" ref="tuopu" />
<sanmenxia v-else-if="topologyType === 7" ref="tuopu" />
<second v-else-if="topologyType === 8" ref="tuopu" />
<fire v-else-if="topologyType === 9" ref="tuopu" />
<runda100 v-else-if="topologyType === 10" ref="tuopu" />
<runda230 v-else-if="topologyType === 11" ref="tuopu" />
<runda215 v-else-if="topologyType === 12" ref="tuopu" />
<third v-else-if="topologyType === 13" ref="tuopu" />
<mdPviese v-else-if="topologyType === 14" ref="tuopu" />
<pv8FourthTopCenter v-else-if="topologyType === 1 && inverterFlag === 1 && pvTopologyType === 5" ref="tuopu" />
<standard v-else ref="tuopu" />
</view>
</view>
<view v-if="topologyType === 9" class="box">
<Section :title="$t('homePage.home.deviceMonitor')" />
<devicemonitoring ref="deviceFire" />
</view>
<view class="box">
<Section :title="$t('homePage.home.runCurve')" />
<runChart ref="runChart" />
</view>
<view class="box">
<Section :title="$t('homePage.home.chargeDisData')">
<view slot="right" style="flex: 1">
<view class="top-right-box">
<view class="top-right-item" :class="{ active: activeTime === 'day' }"
@click="changeTime('day')">{{this.$t('homePage.home.sevenDaycom')}}
</view>
<view class="top-right-item" :class="{ active: activeTime === 'month' }"
@click="changeTime('month')">{{this.$t('homePage.home.monthDay')}}
</view>
<view class="top-right-item" :class="{ active: activeTime === 'year' }"
@click="changeTime('year')">{{this.$t('homePage.home.yearDay')}}
</view>
</view>
</view>
</Section>
<dischargeChart ref="dischargeChart" :activeTime="activeTime" />
</view>
<view class="box">
<Section :title="$t('homePage.home.stationDatacom')" />
<wshStationData v-if="topologyType === 5" />
<zzhbStationData v-else-if="topologyType === 6" />
<commonStationData v-else />
</view>
<view class="box" v-if="inverterFlag === 1">
<Section :title="$t('homePage.home.pvKpi')" />
<view class="">
<my-grid :loading="loading" :col="language !== 'zh_CN'? 2:3" imgHeight="40rpx" imgWidth="40rpx" :list="lightArr"/>
</view>
</view>
<view class="box" v-if="topologyType === 1">
<Section :title="$t('homePage.home.environmentalData')" />
<environmentalControlPosition v-if="rightCenter === 'dispositionRightCenter'" />
<environmentalControl v-else />
</view>
<!-- <view class="box" v-if="inverterFlag === 1">
<Section :title="$t('homePage.home.socialContribution')" />
<view class="">
<my-grid :col="3" imgHeight="72rpx" imgWidth="82rpx" :list="society" />
</view>
</view> -->
</view>
</view>
</template>
<script>
import myGrid from './components/grid/index.vue'
import stationDropdow from '@/components/station-dropdow/index'
import Section from "@/components/section/index";
import charts from "@/components/charts/index";
import cixi from './components/topology/cixi'
import ceshiT from './components/topology/ceshiT.vue'
import ceshiL from './components/topology/ceshiL.vue'
import pv8FourthTopCenter from './components/topology/pv8FourthTopCenter.vue'
import pv2first from './components/topology/pv2first.vue'
import weishanhu from './components/topology/weishanhu.vue'
import sanmenxia from './components/topology/sanmenxia.vue'
import lingchao from './components/topology/lingchao.vue'
import zhongzihuanbao from './components/topology/zhongzihuanbao.vue'
import kejiyuan from './components/topology/kejiyuan.vue'
import standard from './components/topology/standard.vue'
import jingke from './components/topology/jingke.vue'
import second from './components/topology/second.vue'
import third from './components/topology/third.vue'
import fire from './components/topology/fire.vue'
import runda100 from './components/topology/runda100.vue'
import runda215 from './components/topology/runda215.vue'
import runda230 from './components/topology/runda230.vue'
import runChart from './components/runChart/index'
import dischargeChart from './components/dischargeChart/index'
import environmentalControl from './components/environmentalControl/index'
import environmentalControlPosition from './components/environmentalControl/position.vue'
import commonStationData from './components/stationData/common'
import zzhbStationData from './components/stationData/zzhb'
import wshStationData from './components/stationData/wsh'
import devicemonitoring from './components/topology/devicemonitoring.vue'
import mdPviese from './components/topology/mdPvdieseTopCenter.vue'
export default {
components: {
ceshiT,
ceshiL,
pv8FourthTopCenter,
pv2first,
myGrid,
stationDropdow,
Section,
environmentalControlPosition,
charts,
runda100,
runda215,
runda230,
second,
cixi,
fire,
third,
weishanhu,
sanmenxia,
mdPviese,
lingchao,
zhongzihuanbao,
kejiyuan,
standard,
jingke,
runChart,
dischargeChart,
environmentalControl,
commonStationData,
zzhbStationData,
wshStationData,
devicemonitoring
},
data() {
return {
// #ifdef APP
src: '/static/html/demo.html',
// #endif
// #ifdef H5
src: '/static/html/demo.html',
// #endif
loading: false,
curve_option: {},
charge_option: {},
activeTime: 'day',
topologyType: 0,
list: [],
messageList: [],
timer: null,
tuopuTimer: null,
rightCenter: null,
componentsLoaded: false,
tuopoloading:false,
topCenterPvArr:[
{name:'pv1AndStorage_261',value:1},
{name:'pv1AndStorage_sts_261',value:2},
{name:'pv2AndStorage_261',value:3},
{name:'pv2AndStorage_sts_261',value:4},
{name:'pv8FourthTopCenter',value:5}
],
pvTopologyType:0,
society: [{
label: this.$t('homePage.home.saveStandardCoal'),
value: '15.00',
image: require('@/static/aidex/images/ll01.png'),
},
{
label: this.$t('homePage.home.equivalentCo2Reduction'),
value: '20.50',
image: require('@/static/aidex/images/ll02.png'),
},
{
label: this.$t('homePage.home.equivalentTreePlantings'),
value: '1.50',
image: require('@/static/aidex/images/ll03.png'),
},
],
panelData: {
pvCurrentPower: 0, // 对应 lightArr[0].value
dailyReleaseElec: 0, // 对应 lightArr[1].value
totalReleaseElec: 0, // 对应 lightArr[2].value
todayIncone: 0, // 对应 lightArr[3].value
totalIncome: 0, // 对应 lightArr[4].value
pvPower: 0 // 对应 lightArr[5].value
}
};
},
computed: {
currentStation() {
return this.vuex_currentStation;
},
userData() {
return this.vuex_user
},
language() {
return this.vuex_language
},
inverterFlag(){
return this.vuex_inverterFlag;
},
lightArr() {
return [
{
label: this.$t('homePage.home.currentPower') + '(kW)',
value: this.panelData.pvCurrentPower,
image: require('@/static/aidex/images/ll06.png')
},
{
label: this.$t('homePage.home.dailyPowerGeneration') + '(kWh)',
value: this.panelData.dailyReleaseElec,
image: require('@/static/aidex/images/ll07.png')
},
{
label: this.$t('homePage.home.cumulativePowerGeneration') + '(kWh)',
value: this.panelData.totalReleaseElec,
image: require('@/static/aidex/images/ll07.png')
},
{
label: this.$t('homePage.home.todayEarning'),
value: this.panelData.todayIncone,
image: require('@/static/aidex/images/yxts.png')
},
{
label: this.$t('homePage.home.totalRevenue'),
value: this.panelData.totalIncome,
image: require('@/static/aidex/images/yxts.png')
},
{
label: this.$t('homePage.home.ratedPower'),
value: this.panelData.pvPower,
image: require('@/static/aidex/images/ll06.png')
}
];
}
},
onHide() {
if (this.timer) {
clearInterval(this.timer)
}
if (this.tuopuTimer) {
clearInterval(this.tuopuTimer)
}
},
watch: {
currentStation: {
handler(val) {
if (val && val.id) {
this.stationId = val.id
this.userId = this.userData.userId
console.log('topologyType:',val);
this.topologyType = val.topologyType
// 重置加载状态,避免复用旧状态
this.componentsLoaded = false
this.tuopoloading = true
this.getComponents().then(() => {
this.GetPcsTotalData();
this.$nextTick(() => {
if (this.$refs.tuopu) {
this.$refs.tuopu.getData(val.id)
}
if (this.$refs.deviceFire) {
this.$refs.deviceFire.getData(this.stationId)
}
});
});
}
},
deep: true,
immediate: true,
}
},
created() {
uni.setTabBarItem({
index: 0,
text: this.$t('homePage.home.station'),
})
uni.setTabBarItem({
index: 1,
text: this.$t('homePage.home.electricityPrice'),
})
uni.setTabBarItem({
index: 2,
text: this.$t('homePage.home.mine'),
})
uni.showLoading({
title: this.$t('homePage.home.loading')
})
},
onShow() {
// 重置加载状态
this.componentsLoaded = false
this.tuopoloading = true
this.getComponents().then(() => {
this.getMessage()
if (this.$refs.runChart && this.stationId) {
this.$refs.runChart.getData()
}
if (this.$refs.dischargeChart && this.stationId) {
this.$refs.dischargeChart.getData()
}
this.$nextTick(() => {
if (this.$refs.tuopu) {
this.$refs.tuopu.changeEnglish()
this.$refs.tuopu.getData(this.stationId)
}
if (this.$refs.deviceFire) {
this.$refs.deviceFire.getData(this.stationId)
}
})
});
this.timer = setInterval(() => {
this.getMessage()
}, 5000)
this.$nextTick(() => {
this.tuopuTimer = setInterval(() => {
if (this.$refs.tuopu) {
this.$refs.tuopu.getData(this.stationId)
}
if (this.$refs.deviceFire) {
this.$refs.deviceFire.getData(this.stationId)
}
}, 1000 * 10 * 60)
})
},
methods: {
async GetPcsTotalData() {
let self = this;
return new Promise((resolve, reject) => {
self.$u.api.homePageData
.GetPcsTotalData({
stationId: this.stationId,
})
.then((res) => {
this.panelData = Object.assign(this.panelData, res.data);
resolve(res);
})
.catch((err) => {
reject("error");
});
});
},
async getComponents() {
try {
const { data } = await this.$u.api.homePageData.GetHomePageComponents(this.stationId);
if (data && data.length > 0) {
console.log(data)
this.rightCenter = data[0]?.rightCenter;
const matchedItem = this.topCenterPvArr.find(item => item.name === data[0]?.topCenter);
this.pvTopologyType = matchedItem ? matchedItem.value : this.pvTopologyType;
console.log(this.pvTopologyType)
}
// 接口完成标记加载状态为true
this.componentsLoaded = true
this.tuopoloading = false
} catch (e) {
console.error('获取组件配置失败:', e);
// 即使接口失败,也标记完成,避免组件一直不渲染
this.componentsLoaded = true
this.tuopoloading = false
}
},
openTimer() {
},
closeTimer() {
},
toMsg() {
uni.navigateTo({
url: `/pages/sys/user/message`,
});
},
tagVal(val) {
if (+val === 1) {
return `[${this.$t('homePage.home.environmentalData')}]:`
} else if (+val === 2) {
return `[${this.$t('homePage.home.fault')}]:`
} else if (+val === 3) {
return `[${this.$t('homePage.home.alarm')}]:`
}
},
getMessage() {
this.$u.api.GetMessage({
receivingUser: this.userId,
stationId: this.stationId,
createstatus: 3,
readStatus: 0
}).then((res) => {
this.messageList = res.data
this.list = []
this.messageList.forEach((item, index) => {
this.list.push(this.tagVal(item.messageType) + item.messageContent)
})
})
},
changeTime(val) {
if (this.activeTime !== val) {
this.activeTime = val;
}
},
changeMenu(url) {
uni.navigateTo({
url: `/pages/home-page/${url}/index`,
});
}
},
};
</script>
<style>
page {
height: 100%;
}
</style>
<style lang="scss" scoped>
.u-page {
height: 100% !important;
background-color: #f5f5f5;
overflow: hidden;
.new-nav {
width: 100%;
height: 440rpx;
background-size: 100% 100%;
margin-bottom: -15rpx;
display: flex;
align-items: center;
position: relative;
image {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.station-box {
width: 580rpx;
margin-top: -160rpx;
// border: 1px solid #fff;
margin-left: 85rpx;
border-radius: 44rpx;
z-index: 1;
::v-deep .u-input__input {
color: #000 !important;
}
::v-deep .uicon-arrow-down-fill {
color: #000 !important;
}
// backdrop-filter: blur(4rpx);
}
}
.menu-box {
width: 100%;
height: 140rpx;
padding-left: 20rpx;
padding-right: 20rpx;
margin-bottom: 20rpx;
margin-top: 20rpx;
display: flex;
justify-content: space-between;
.box {
width: 140rpx;
height: 140rpx;
border-radius: 8rpx;
box-shadow: 2rpx 4rpx 8rpx 0rpx rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
.icon {
width: 64rpx;
height: 64rpx;
}
.device {
background-image: url(/static/aidex/images/menu-device.png);
background-size: 100% 100%;
}
.earning {
background-image: url(/static/aidex/images/menu-earnings.png);
background-size: 100% 100%;
}
.alarm {
background-image: url(/static/aidex/images/menu-alarm.png);
background-size: 100% 100%;
}
.policy {
background-image: url(/static/aidex/images/menu-policy.png);
background-size: 100% 100%;
}
.title {
margin-top: 16rpx;
font-size: 24rpx;
}
}
}
.content-box {
height: calc(100% - 640rpx);
overflow-y: auto;
.box {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
width: 710rpx;
border: 16rpx;
margin: 20rpx;
margin-top: 30rpx;
box-shadow: 0px 4rpx 16rpx rgba(0, 0, 0, 0.08);
.loading-tip {
width: 650rpx;
// height: 710rpx;
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 #009458;
font-size: 24rpx;
color: #009458;
cursor: pointer;
margin-right: 10rpx;
border-radius: 8rpx;
&.active {
background: #07976E;
color: #ffffff;
}
}
}
}
}
}
</style>