楼宇能效监测控制系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1009 lines
30 KiB

<template>
<div class="monitor" v-loading="loading">
<div class="monitor-top">
<img
class="title-left"
src="../../../assets/images/title-left.png"
alt=""
/>
<img
class="title-center"
src="../../../assets/images/title-center.png"
alt=""
/>
<img
class="title-right"
src="../../../assets/images/title-right.png"
alt=""
/>
<div class="sys-title">采暖泵监测</div>
<!-- logo -->
<img src="../../../assets/images/logo-3.png" class="sys-logo" alt="" />
<div class="nowTime">{{ formattedDate }}</div>
<div class="monitor-time">已监测时长:{{ dayData }}天</div>
<img
class="icon_warning"
src="../../../assets/images/warning.png"
title="报警记录"
@click="goWarning"
v-if="isShowWarning"
alt=""
/>
<img
class="icon_home"
src="../../../assets/images/icon_home.png"
title="首页"
@click="goSys"
alt=""
/>
<img
class="back-icon"
src="../../../assets/images/back-icon.png"
title="返回"
@click="goBack"
alt=""
/>
</div>
<div class="heatingPump">
<div class="pumpli">
<div class="special-div one">
<div class="special-top">
<div class="special-title">
<div class="title-left">
<div>采暖泵1</div>
</div>
</div>
</div>
<div class="pumpli-monitor">
<div class="pumpli-top">
<img
src="../../../assets/images/heatingPump.png"
class="pump-img"
alt=""
/>
<div class="greenStatus">
<img
src="../../../assets/images/green-out.png"
class="green-out"
alt=""
/>
<img
src="../../../assets/images/whiteFan.png"
class="whiteFan move"
alt=""
/>
</div>
</div>
<div class="pump-data">
<div class="pump-data-li">
<div>运行状态</div>
<div class="pump-data-text">运行</div>
</div>
<div class="pump-data-li">
<div>实际转速(rpm)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>电机功率(kw)</div>
<div class="pump-data-text">100</div>
</div>
<div class="pump-data-li">
<div>电机输入电压(V)</div>
<div class="pump-data-text">220</div>
</div>
<div class="pump-data-li">
<div>点击输入电流(A)</div>
<div class="pump-data-text">5</div>
</div>
<div class="pump-data-li">
<div>总流量(m²/h)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>泵运行总用电量(kwh)</div>
<div class="pump-data-text">10</div>
</div>
<div class="pump-data-li">
<div>泵总运行时间(小时)</div>
<div class="pump-data-text">1000</div>
</div>
</div>
</div>
</div>
</div>
<div class="pumpli">
<div class="special-div one">
<div class="special-top">
<div class="special-title">
<div class="title-left">
<div>采暖泵2</div>
</div>
</div>
</div>
<div class="pumpli-monitor">
<div class="pumpli-top">
<img
src="../../../assets/images/heatingPump.png"
class="pump-img"
alt=""
/>
<div class="greenStatus">
<img
src="../../../assets/images/green-out.png"
class="green-out"
alt=""
/>
<img
src="../../../assets/images/whiteFan.png"
class="whiteFan"
alt=""
/>
</div>
</div>
<div class="pump-data">
<div class="pump-data-li">
<div>运行状态</div>
<div class="pump-data-text">运行</div>
</div>
<div class="pump-data-li">
<div>实际转速(rpm)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>电机功率(kw)</div>
<div class="pump-data-text">100</div>
</div>
<div class="pump-data-li">
<div>电机输入电压(V)</div>
<div class="pump-data-text">220</div>
</div>
<div class="pump-data-li">
<div>点击输入电流(A)</div>
<div class="pump-data-text">5</div>
</div>
<div class="pump-data-li">
<div>总流量(m²/h)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>泵运行总用电量(kwh)</div>
<div class="pump-data-text">10</div>
</div>
<div class="pump-data-li">
<div>泵总运行时间(小时)</div>
<div class="pump-data-text">1000</div>
</div>
</div>
</div>
</div>
</div>
<div class="pumpli">
<div class="special-div one">
<div class="special-top">
<div class="special-title">
<div class="title-left">
<div>采暖泵3</div>
</div>
</div>
</div>
<div class="pumpli-monitor">
<div class="pumpli-top">
<img
src="../../../assets/images/heatingPump.png"
class="pump-img"
alt=""
/>
<div class="greenStatus">
<img
src="../../../assets/images/green-out.png"
class="green-out"
alt=""
/>
<img
src="../../../assets/images/whiteFan.png"
class="whiteFan"
alt=""
/>
</div>
</div>
<div class="pump-data">
<div class="pump-data-li">
<div>运行状态</div>
<div class="pump-data-text">运行</div>
</div>
<div class="pump-data-li">
<div>实际转速(rpm)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>电机功率(kw)</div>
<div class="pump-data-text">100</div>
</div>
<div class="pump-data-li">
<div>电机输入电压(V)</div>
<div class="pump-data-text">220</div>
</div>
<div class="pump-data-li">
<div>点击输入电流(A)</div>
<div class="pump-data-text">5</div>
</div>
<div class="pump-data-li">
<div>总流量(m²/h)</div>
<div class="pump-data-text">1000</div>
</div>
<div class="pump-data-li">
<div>泵运行总用电量(kwh)</div>
<div class="pump-data-text">10</div>
</div>
<div class="pump-data-li">
<div>泵总运行时间(小时)</div>
<div class="pump-data-text">1000</div>
</div>
</div>
</div>
</div>
</div>
<div class="device-message">
<div class="statistics">
<div class="special-div one">
<div class="special-top">
<div class="special-title">
<div class="title-left">
<div>设备统计</div>
</div>
</div>
</div>
<div class="pumpli-monitor">
<div class="charts" ref="chart_ref"></div>
</div>
</div>
</div>
<div class="alarm">
<div class="special-div one">
<div class="special-top">
<div class="special-title">
<div class="title-left">
<div>设备报警信息</div>
</div>
</div>
</div>
<div class="pumpli-monitor" style="min-height: 3.3rem">
<!-- <div class="charts" ref="chart_ref"></div> -->
<el-table :data="alarmList">
<el-table-column
prop="otherName"
label="报警位置"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
prop="curTime"
label="报警时间"
:show-overflow-tooltip="true"
></el-table-column>
</el-table>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { runTime } from "@/api/centerairC/sysMonitor";
import { alarmRecordList } from "@/api/alarm/alarmRecord";
import { getDay } from "@/utils/datetime";
import * as echarts from "echarts";
export default {
name: "boilerMonitorDetails",
data() {
return {
loading: false,
currentDate: new Date(),
nowTimer: null,
isShowWarning: false, //是否有报警
dayData: "", //监测天数
currentWeekday: "",
chartInstance: null,
option: {},
energyMes: {}, //饼图数据
// 报警列表
alarmList: [],
};
},
computed: {
formattedDate() {
const year = this.currentDate.getFullYear();
const month = String(this.currentDate.getMonth() + 1).padStart(2, "0");
const day = String(this.currentDate.getDate()).padStart(2, "0");
const hours = String(this.currentDate.getHours()).padStart(2, "0");
const minutes = String(this.currentDate.getMinutes()).padStart(2, "0");
const seconds = String(this.currentDate.getSeconds()).padStart(2, "0");
const weekDays = [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
];
const weekDay = weekDays[this.currentDate.getDay()];
return `${year}${month}${day}${hours}:${minutes}:${seconds} ${weekDay}`;
},
},
created() {
const weekdays = [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
];
const date = new Date();
const dayIndex = date.getDay();
this.currentWeekday = weekdays[dayIndex];
console.log("今天是星期几", this.currentWeekday);
},
mounted() {
this.getAlarnStatus();
this.getDayData();
this.initChart();
this.$nextTick(() => {
this.echartsData();
});
window.addEventListener("resize", this.screenAdapter);
this.screenAdapter();
},
destroyed() {
//取消监听器
window.removeEventListener("resize", this.screenAdapter);
},
beforeDestroy() {
// 组件销毁前清除定时器
if (this.nowTimer) {
clearInterval(this.nowTimer);
}
},
methods: {
// 进入系统首页
goSys() {
this.$router.push("/");
},
// 返回上一页
goBack() {
window.history.go(-2);
},
// 监测天数
getDayData() {
runTime().then((res) => {
if (res.code == 200) {
this.dayData = res.data.runTime;
}
});
},
// 报警列表
getAlarnStatus() {
let data = {
pageNum: 1,
pageSize: 10,
status: "0",
};
let timeArr = [getDay(0), getDay(0)];
alarmRecordList(this.addDateRange(data, timeArr)).then((res) => {
if (res.code == 200 && res.rows.length > 0) {
this.isShowWarning = true;
} else {
this.isShowWarning = false;
}
});
},
goWarning() {
this.$router.push("/alarm/alarmRecord");
},
echartsData() {
console.log("父组件传过来的值", this.energyMes);
if (this.energyMes) {
const titleFontSize = (this.$refs.chart_ref.offsetWidth / 100) * 2;
const colorList = ["#ffe21e", "#08c8ff", "#0882ff", "#2df499"]; // 提取颜色列表
const adapterOption = {
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
legend: {
itemWidth: titleFontSize,
itemHeight: titleFontSize,
itemGap: titleFontSize * 2,
formatter: function (name) {
var arr = [];
let data = adapterOption.series[0].data;
var index = 0;
var total = 0;
// 计算总和
for (var i = 0; i < data.length; i++) {
total += data[i].value;
if (data[i].name == name) {
index = i;
}
}
// 检查当前项的值是否为 0
var percentage =
data[index].value === 0
? "0.00"
: ((data[index].value / total) * 100).toFixed(2);
arr.push(
"{name|" + name + "}",
"{text|" + " " + ":" + " " + "}",
"{value|" + data[index].value + " " + "}",
"{percentage|" + " " + percentage + "%}"
);
return arr.join("");
},
textStyle: {
color: function (name) {
const dataSeries = adapterOption.series[1].data; // 数据圆的data
const index = dataSeries.findIndex(
(item) => item.name === name
);
const colorList = ["#08c8ff", "#2df499", "#ffe21e", "#0882ff"]; // 数据圆的颜色列表
return colorList[index];
},
rich: {
name: {
align: "left",
fontSize: titleFontSize * 1.6,
},
text: {
align: "left",
fontSize: titleFontSize * 1.6,
},
value: {
align: "left",
fontSize: titleFontSize * 1.6,
// color: function (params) {
// let data = adapterOption.series[1].data;
// return data.itemStyle.color({ dataIndex: params.dataIndex });
// },
},
percentage: {
align: "left",
fontSize: titleFontSize * 1.6,
// color: function (params) {
// let data = adapterOption.series[1].data;
// return data.itemStyle.color({ dataIndex: params.dataIndex });
// },
},
},
},
},
series: [
{
name: "数据详情:",
data: [
{ value: 2, name: "设备1" },
{ value: 3, name: "设备2" },
{ value: 4, name: "设备3" },
{ value: 5, name: "设备4" },
],
itemStyle: {
color: function (params) {
var colorList = ["#08c8ff", "#2df499", "#ffe21e", "#0882ff"];
return colorList[params.dataIndex];
},
// borderWidth: 5,
borderColor: "#002a56",
},
},
{
data: [
{ value: 2, name: "设备1" },
{ value: 3, name: "设备2" },
{ value: 4, name: "设备3" },
{ value: 5, name: "设备4" },
],
},
],
};
this.chartInstance.setOption(adapterOption);
this.chartInstance.resize();
} else {
const titleFontSize = (this.$refs.chart_ref.offsetWidth / 100) * 2;
const adapterOption = {
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
legend: {
itemWidth: titleFontSize,
itemHeight: titleFontSize,
itemGap: titleFontSize * 2,
formatter: function (name) {
var arr = [];
let data = adapterOption.series[0].data;
var index = 0;
var total = 0;
// 计算总和
for (var i = 0; i < data.length; i++) {
total += data[i].value;
if (data[i].name == name) {
index = i;
}
}
// 检查当前项的值是否为 0
var percentage =
data[index].value === 0
? "0.00"
: ((data[index].value / total) * 100).toFixed(2);
arr.push(
"{name|" + name + "}",
"{text|" + " " + ":" + " " + "}",
"{value|" + data[index].value + " " + "}",
"{percentage|" + " " + percentage + "%}"
);
return arr.join("");
},
textStyle: {
color: function (name) {
const dataSeries = adapterOption.series[1].data; // 数据圆的data
const index = dataSeries.findIndex(
(item) => item.name === name
);
const colorList = ["#08c8ff", "#2df499", "#ffe21e", "#0882ff"]; // 数据圆的颜色列表
return colorList[index];
},
rich: {
name: {
align: "left",
fontSize: titleFontSize * 1.6,
},
text: {
align: "left",
fontSize: titleFontSize * 1.6,
},
value: {
align: "left",
fontSize: titleFontSize * 1.6,
// color: function (params) {
// let data = adapterOption.series[1].data;
// return data.itemStyle.color({ dataIndex: params.dataIndex });
// },
},
percentage: {
align: "left",
fontSize: titleFontSize * 1.6,
// color: function (params) {
// let data = adapterOption.series[1].data;
// return data.itemStyle.color({ dataIndex: params.dataIndex });
// },
},
},
},
},
series: [
{
name: "数据详情:",
data: [
{ value: 0, name: "设备1" },
{ value: 0, name: "设备2" },
{ value: 0, name: "设备3" },
{ value: 0, name: "设备4" },
],
itemStyle: {
color: function (params) {
var colorList = ["#08c8ff", "#2df499", "#ffe21e", "#0882ff"];
return colorList[params.dataIndex];
},
// borderWidth: 5,
borderColor: "#002a56",
},
},
{
data: [
{ value: 0, name: "设备1" },
{ value: 0, name: "设备2" },
{ value: 0, name: "设备3" },
{ value: 0, name: "设备4" },
],
},
],
};
this.chartInstance.setOption(adapterOption);
this.chartInstance.resize();
}
},
// 折线图自适应+ 根据按钮切换图例仅限一条且不可点击+ 折线图数据
screenAdapter() {
//自己定义的比较合适的适配大小,2.6 mes_ref是图表盒子
const titleFontSize = this.$refs.chart_ref.offsetWidth / 40;
//因为option可以多次配置的,所以这里的option只需要写 需要配置大小的相关数据
const adapterOption = {
title: {
subtextStyle: {
fontSize: titleFontSize * 1.2,
},
},
};
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关
this.chartInstance.setOption(adapterOption);
//手动的调用图标对象的resize才能产生效果
this.chartInstance.resize();
},
//初始化chartInstance对象
initChart() {
this.chartInstance = echarts.init(this.$refs.chart_ref);
this.option = {
//环形图中间文字
title: {
subtext: "设备数量",
textStyle: {
color: "#ffffff",
},
subtextStyle: {
color: "#ffffff",
},
textAlign: "center",
x: "27%",
y: "36%", //距离上边的距离
},
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
//图例
legend: {
orient: "vertical", // 垂直排列
right: "4%", // 距离右边10%
top: "middle", // 垂直居中
//图例文字颜色
textStyle: {
color: "#ffffff",
// fontSize: 18,
},
},
series: [
// 数据圆
{
name: "数据详情:",
type: "pie",
radius: ["60%", "72%"],
center: ["28%", "44%"],
avoidLabelOverlap: false,
label: {
show: false,
position: "center",
},
labelLine: {
show: false,
},
itemStyle: {
color: function (params) {
var colorList = ["#08c8ff", "#2df499", "#ffe21e", "#0882ff"];
return colorList[params.dataIndex];
},
borderWidth: 5,
borderColor: "#002a56",
},
z: 10, //设置层级更高,否则会被阴影圆遮住
},
// 阴影圆
{
type: "pie",
radius: ["50%", "62%"],
center: ["28%", "44%"],
avoidLabelOverlap: false,
label: {
show: false,
position: "center",
},
silent: true,
labelLine: {
show: false,
},
//颜色
itemStyle: {
color: function (colors) {
var colorList = ["#024e7d", "#09596b", "#385f5c", "#02427f"];
return colorList[colors.dataIndex];
},
},
z: 15,
},
// 内圈边框
{
// 颜色
color: ["#305376"],
type: "pie",
silent: true, //鼠标移入不显示内容,不触发鼠标事件
// hoverAnimation: false, //鼠标移入不放大,此属性已被废弃
// 使用emphasis.scale 是否开启高亮后扇区的放大效果,默认true
// 这里开启silent: true, 就达到效果了
// center与非内圈一致
radius: ["38%", "39%"],
center: ["28%", "44%"],
label: {
show: false,
},
data: [
{
value: 0,
name: "",
itemStyle: {},
},
],
},
// 最里面渐变小圆
{
// 颜色
type: "pie",
silent: true, //鼠标移入不显示内容,不触发鼠标事件
// hoverAnimation: false, //鼠标移入不放大,此属性已被废弃
// 使用emphasis.scale 是否开启高亮后扇区的放大效果,默认true
// 这里开启silent: true, 就达到效果了
// center与非内圈一致
radius: ["0%", "38%"],
center: ["28%", "44%"],
label: {
show: false,
},
data: [
{
value: 0,
name: "",
itemStyle: {},
},
],
itemStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{ offset: 0, color: "#002a55" }, // 0% 处的颜色
{ offset: 1, color: "#0a457a" }, // 100% 处的颜色
],
global: false, // 缺省为 false
},
},
},
],
};
//把配置项给实例对象
this.chartInstance.setOption(this.option, true);
},
},
};
</script>
<style lang="scss" scoped>
.monitor {
width: 100%;
min-height: 100vh;
background-color: black;
color: #fff;
.monitor-top {
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
flex-wrap: nowrap;
padding: 0.1rem 0.2rem;
position: relative;
.title-left {
width: 3.41rem;
height: 0.8rem;
}
.title-center {
width: 9.46rem;
height: 0.69rem;
}
.title-right {
width: 5.04rem;
height: 0.78rem;
}
.sys-title {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 0.28rem;
color: #ffffff;
font-weight: bold;
z-index: 100;
}
.nowTime {
position: absolute;
top: 0.37rem;
right: 0.6rem;
font-size: 0.18rem;
color: #ffffff;
font-weight: bold;
z-index: 100;
}
.sys-logo {
width: 1.8rem;
height: 0.5rem;
position: absolute;
top: 0.26rem;
left: 0.8rem;
z-index: 10;
}
.monitor-time {
position: absolute;
top: 0.44rem;
left: 4.2rem;
z-index: 10;
font-size: 0.18rem;
color: #ffffff;
font-weight: bold;
}
.icon_warning {
position: absolute;
top: 0.39rem;
right: 4.4rem;
z-index: 10;
width: 0.35rem;
height: 0.32rem;
margin: 0 0.25rem 0 0.27rem;
cursor: pointer;
/* 添加闪烁动画 */
animation: blink 1s infinite;
}
@keyframes blink {
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.icon_home {
position: absolute;
top: 0.37rem;
right: 4rem;
z-index: 10;
width: 0.35rem;
height: 0.32rem;
margin: 0 0.2rem 0 0.27rem;
cursor: pointer;
}
.back-icon {
position: absolute;
top: 0.37rem;
right: 3.7rem;
z-index: 10;
width: 0.35rem;
height: 0.32rem;
cursor: pointer;
}
}
.heatingPump {
width: 100%;
padding: 0.2rem;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: stretch;
.special-div {
height: 100%;
}
.pumpli {
width: 22%;
.pumpli-monitor {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0.35rem;
.pumpli-top {
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 0.1rem;
.pump-img {
width: 2rem;
height: 2rem;
}
.greenStatus {
margin-top: 0.1rem;
width: 0.6rem;
height: 0.6rem;
position: relative;
.green-out {
width: 100%;
height: 100%;
position: absolute;
top: 0;
}
.whiteFan {
width: 0.3rem;
height: 0.3rem;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
.move {
animation: continuousRotation 3s linear infinite;
}
@keyframes continuousRotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}
}
.pump-data {
width: 100%;
background: #262f58;
border-radius: 0.1rem;
font-size: 0.16rem;
display: flex;
flex-direction: column;
.pump-data-li {
width: 100%;
padding: 0 0.3rem;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin: 0.2rem 0;
.pump-data-text {
color: #05d120;
font-weight: bold;
}
}
}
}
}
.device-message {
width: 28%;
display: flex;
flex-direction: column;
justify-content: space-between;
.statistics {
margin-bottom: 0.35rem;
.pumpli-monitor {
padding: 0.2rem;
.charts {
width: 5rem;
height: 3rem;
}
}
}
.alarm {
.pumpli-monitor {
margin-top: 0.2rem;
}
}
}
}
}
</style>
<style scoped>
.special-div .special-title {
padding-left: 0.36rem !important;
font-size: 0.2rem !important;
line-height: 0.23rem !important;
background-size: 1.4rem 0.35rem !important;
background-position: 0px -0.03rem !important;
}
.special-div .special-top {
padding: 0.04rem 0.26rem 0.04rem 0px;
min-height: 0.37rem;
}
</style>