|
@@ -0,0 +1,587 @@
|
|
|
+<template>
|
|
|
+ <div class="body">
|
|
|
+ <div
|
|
|
+ :class="index < 3 ? 'showContents' : 'showContents'"
|
|
|
+ v-for="(item, index) in station"
|
|
|
+ :key="index"
|
|
|
+ >
|
|
|
+ <div class="stationName">
|
|
|
+ <div class="titleName">{{ item.name }}</div>
|
|
|
+ <div class="titleNames" v-if="item.schedulingName">
|
|
|
+ ({{ item.schedulingName }})
|
|
|
+ </div>
|
|
|
+ <img
|
|
|
+ v-if="
|
|
|
+ !allDate[item.id]?.Status?.value ||
|
|
|
+ allDate[item.id]?.Status?.value === 0
|
|
|
+ "
|
|
|
+ class="statusIcons"
|
|
|
+ src="../../assets/img/controlcenter/daraTrue.png"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else
|
|
|
+ class="statusIcons"
|
|
|
+ src="../../assets/img/controlcenter/dataFalse.png"
|
|
|
+ />
|
|
|
+ <div
|
|
|
+ class="titleNames"
|
|
|
+ v-if="
|
|
|
+ allDate[item.id]?.Status?.value &&
|
|
|
+ allDate[item.id]?.Status?.value !== 0
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ (
|
|
|
+ (1 -
|
|
|
+ this.allDate[item.id]?.PowerSet?.value /
|
|
|
+ this.allDate[item.id]?.InstalledCapacity?.value) *
|
|
|
+ 100
|
|
|
+ ).toFixed(2)
|
|
|
+ }}%
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="dataList">
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.PowerSet, '有功设定限值')"
|
|
|
+ >
|
|
|
+ <div class="name">有功设定限值:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.PowerSet?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.ActualPower, '实发有功')"
|
|
|
+ >
|
|
|
+ <div class="name">实发有功:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.ActualPower?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.AgcUp, 'AGC可调上限')"
|
|
|
+ >
|
|
|
+ <div class="name">AGC可调上限:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.AgcUp?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.TheoryPower, '理论功率')"
|
|
|
+ >
|
|
|
+ <div class="name">理论功率:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.TheoryPower?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.AgcLower, 'AGC可调下限')"
|
|
|
+ >
|
|
|
+ <div class="name">AGC可调下限:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.AgcLower?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="data"
|
|
|
+ @dblclick="dbClicks(allDate[item.id]?.ForecastPower, '预测功率')"
|
|
|
+ >
|
|
|
+ <div class="name">预测功率:</div>
|
|
|
+ <div :class="index < 3 ? 'nums' : 'nums'">
|
|
|
+ {{ allDate[item.id]?.ForecastPower?.value ?? 0 }}
|
|
|
+ </div>
|
|
|
+ <div class="unit">MW</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="condition">
|
|
|
+ <div class="status">
|
|
|
+ <div class="name">{{ allDate[item.id]?.AgcIn?.name }}:</div>
|
|
|
+ <img
|
|
|
+ v-if="allDate[item.id]?.AgcIn?.value === 0"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/daraTrue.png"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else-if="allDate[item.id]?.AgcIn?.value === 1"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/dataFalse.png"
|
|
|
+ />
|
|
|
+ <div v-else-if="allDate[item.id]?.AgcIn?.value === ''">暂无数据</div>
|
|
|
+ </div>
|
|
|
+ <div class="status">
|
|
|
+ <div class="name">{{ allDate[item.id]?.AgcFar?.name }}:</div>
|
|
|
+ <img
|
|
|
+ v-if="allDate[item.id]?.AgcFar?.value === 0"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/daraTrue.png"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else-if="allDate[item.id]?.AgcFar?.value === 1"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/dataFalse.png"
|
|
|
+ />
|
|
|
+ <div v-else-if="allDate[item.id]?.AgcFar?.value === ''">暂无数据</div>
|
|
|
+ </div>
|
|
|
+ <div class="status">
|
|
|
+ <div class="name">{{ allDate[item.id]?.SumLock?.name }}:</div>
|
|
|
+ <img
|
|
|
+ v-if="allDate[item.id]?.SumLock?.value === 0"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/daraTrue.png"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else-if="allDate[item.id]?.SumLock?.value === 1"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/dataFalse.png"
|
|
|
+ />
|
|
|
+ <div v-else-if="allDate[item.id]?.SumLock?.value === ''">
|
|
|
+ 暂无数据
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="status">
|
|
|
+ <div class="name">{{ allDate[item.id]?.SubLock?.name }}:</div>
|
|
|
+ <img
|
|
|
+ v-if="allDate[item.id]?.SubLock?.value === 0"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/daraTrue.png"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else-if="allDate[item.id]?.SubLock?.value === 1"
|
|
|
+ class="statusIcon"
|
|
|
+ src="../../assets/img/controlcenter/dataFalse.png"
|
|
|
+ />
|
|
|
+ <div v-else-if="allDate[item.id]?.SubLock?.value === ''">
|
|
|
+ 暂无数据
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div :id="item.id" class="echarts" @dblclick="handleClick(item.id)"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Details
|
|
|
+ @closed="closed()"
|
|
|
+ v-model="display"
|
|
|
+ :partsName="partsName"
|
|
|
+ echartsId="modelEcharts"
|
|
|
+ :datas="modelDetails"
|
|
|
+ :calc="this.modelData.calc"
|
|
|
+ @search-data="search"
|
|
|
+ @original-data="originalData"
|
|
|
+ ></Details>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import * as echarts from "echarts";
|
|
|
+import Details from "../basicDataDetails.vue";
|
|
|
+import api from "api/index";
|
|
|
+import dayjs from "dayjs";
|
|
|
+export default {
|
|
|
+ components: {
|
|
|
+ Details,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ display: false,
|
|
|
+ modelData: {},
|
|
|
+ partsName: "",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ allDate: {
|
|
|
+ type: String,
|
|
|
+ default: "",
|
|
|
+ },
|
|
|
+ allChartDate: {
|
|
|
+ type: Array,
|
|
|
+ default: () => {
|
|
|
+ return [];
|
|
|
+ },
|
|
|
+ },
|
|
|
+ station: {
|
|
|
+ type: Array,
|
|
|
+ default: () => {
|
|
|
+ return [];
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ updated() {
|
|
|
+ // this.totleErtcher()
|
|
|
+ },
|
|
|
+ mounted() {},
|
|
|
+ methods: {
|
|
|
+ dbClicks(data, partsName, timeValues) {
|
|
|
+ this.partsName = partsName;
|
|
|
+ this.display = true;
|
|
|
+ let modelDetails = [];
|
|
|
+ for (let i = 0; i < 20; i++) {
|
|
|
+ const value = this.BASE.randomNum(50, 80);
|
|
|
+ const item = {
|
|
|
+ ts: "2025-05-26 10:27:57",
|
|
|
+ doubleValue: value,
|
|
|
+ longValue: value,
|
|
|
+ };
|
|
|
+ modelDetails.push(item);
|
|
|
+ }
|
|
|
+ this.modelDetails = modelDetails;
|
|
|
+ return;
|
|
|
+ this.modelData = data;
|
|
|
+ let date = new Date();
|
|
|
+ let endTs = timeValues
|
|
|
+ ? timeValues[1] > date.getTime()
|
|
|
+ ? date.getTime()
|
|
|
+ : timeValues[1]
|
|
|
+ : date.getTime();
|
|
|
+ let startTs = timeValues ? timeValues[0] : endTs - 28800000;
|
|
|
+ data.tag &&
|
|
|
+ api
|
|
|
+ .getPower({
|
|
|
+ tagName: data.tag,
|
|
|
+ startTs: startTs,
|
|
|
+ endTs: endTs,
|
|
|
+ interval: 60,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ if (res.data.length > 0) {
|
|
|
+ this.partsName = partsName;
|
|
|
+ this.display = true;
|
|
|
+ this.modelDetails = res.data;
|
|
|
+ } else {
|
|
|
+ this.modelDetails = [];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ original(data, partsName, timeValues) {
|
|
|
+ this.modelData = data;
|
|
|
+ let date = new Date();
|
|
|
+ let endTs = timeValues
|
|
|
+ ? timeValues[1] > date.getTime()
|
|
|
+ ? date.getTime()
|
|
|
+ : timeValues[1]
|
|
|
+ : date.getTime();
|
|
|
+ let startTs = timeValues ? timeValues[0] : endTs - 28800000;
|
|
|
+ api
|
|
|
+ .getOriginalPower({
|
|
|
+ tagName: data.tag,
|
|
|
+ startTs: startTs,
|
|
|
+ endTs: endTs,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ if (res.data.length > 0) {
|
|
|
+ this.partsName = partsName;
|
|
|
+ this.display = true;
|
|
|
+ this.modelDetails = res.data;
|
|
|
+ } else {
|
|
|
+ this.modelDetails = [];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ search(values, interval) {
|
|
|
+ this.interval = interval;
|
|
|
+ this.dbClicks(this.modelData, this.partsName, values);
|
|
|
+ },
|
|
|
+ originalData(values) {
|
|
|
+ this.original(this.modelData, this.partsName, values);
|
|
|
+ },
|
|
|
+ totleErtcher() {
|
|
|
+ this.allChartDate.forEach((item) => {
|
|
|
+ let chartDom = document.getElementById(item.id);
|
|
|
+ let myChart = echarts.init(chartDom, "#ffffff");
|
|
|
+ let option;
|
|
|
+ option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: "axis",
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ show: true,
|
|
|
+ data: item.value.map((t) => {
|
|
|
+ return t.title;
|
|
|
+ }),
|
|
|
+ right: 30,
|
|
|
+ icon: "circle",
|
|
|
+ itemWidth: 6,
|
|
|
+ inactiveColor: "#606769",
|
|
|
+ textStyle: {
|
|
|
+ color: "#B3BDC0",
|
|
|
+ fontSize: 12,
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ grid: {
|
|
|
+ top: 40,
|
|
|
+ left: 30,
|
|
|
+ right: 30,
|
|
|
+ bottom: 40,
|
|
|
+ },
|
|
|
+
|
|
|
+ xAxis: [
|
|
|
+ {
|
|
|
+ type: "category",
|
|
|
+ boundaryGap: false,
|
|
|
+ axisLabel: {
|
|
|
+ // interval: 60,
|
|
|
+ showMinLabel: true,
|
|
|
+ showMaxLabel: true,
|
|
|
+ formatter: "{value}",
|
|
|
+ fontSize: 14,
|
|
|
+ textStyle: {
|
|
|
+ color: "#606769",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ data: item.value[0].value.map((items) => {
|
|
|
+ return items.text;
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ yAxis: {
|
|
|
+ type: "value",
|
|
|
+ axisLabel: {
|
|
|
+ formatter: "{value}",
|
|
|
+ fontSize: 14,
|
|
|
+ },
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ color: "#606769",
|
|
|
+ type: "dashed",
|
|
|
+ opacity: 0.5,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ dataZoom: [
|
|
|
+ {
|
|
|
+ show: false,
|
|
|
+ type: "inside",
|
|
|
+ start: 0,
|
|
|
+ end: 100,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: item.value[0].title,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false,
|
|
|
+ data: item.value[0].value.map((items) => {
|
|
|
+ return items.value;
|
|
|
+ }),
|
|
|
+ type: "line",
|
|
|
+ lineStyle: {
|
|
|
+ normal: {
|
|
|
+ color: "rgba(75, 85, 174, 1)",
|
|
|
+ width: 1,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: item.value[1].title,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false,
|
|
|
+ data: item.value[1].value.map((items) => {
|
|
|
+ return items.value;
|
|
|
+ }),
|
|
|
+ type: "line",
|
|
|
+ lineStyle: {
|
|
|
+ normal: {
|
|
|
+ color: "rgba(05, 187, 76, 1)",
|
|
|
+ width: 1,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ option && myChart.setOption(option);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleClick(id) {
|
|
|
+ this.$emit("handleClick", id);
|
|
|
+ },
|
|
|
+ opened() {},
|
|
|
+ closed() {
|
|
|
+ this.detailsDisplay = false;
|
|
|
+ this.display = false;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ allChartDate: {
|
|
|
+ handler: function (json) {
|
|
|
+ if (json) {
|
|
|
+ this.totleErtcher();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.showTitles {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-top: -10px;
|
|
|
+ font-size: 18px;
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.showContent {
|
|
|
+ width: 32%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ border: 1px solid rgba(77, 77, 77, 1);
|
|
|
+ /* background-color: rgba(77, 77, 77, 1); */
|
|
|
+ margin-right: 10px;
|
|
|
+ margin-left: 10px;
|
|
|
+ height: 44vh;
|
|
|
+ margin-top: 20px;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.showContents {
|
|
|
+ width: 40%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ border: 1px solid rgba(77, 77, 77, 1);
|
|
|
+ /* background-color: rgba(77, 77, 77, 1); */
|
|
|
+ margin-right: 10px;
|
|
|
+ margin-left: 10px;
|
|
|
+ height: 43vh;
|
|
|
+ margin-top: 20px;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.stationName {
|
|
|
+ font-size: 20px;
|
|
|
+ width: 400px;
|
|
|
+ height: 45px;
|
|
|
+ border: 1px solid rgba(77, 77, 77, 1);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: baseline;
|
|
|
+ justify-content: center;
|
|
|
+ color: #ffffff;
|
|
|
+ background-color: #000000;
|
|
|
+ margin-top: -15px;
|
|
|
+}
|
|
|
+
|
|
|
+.titleName {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.titleNames {
|
|
|
+ font-size: 12px;
|
|
|
+ margin-left: 10px;
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.body {
|
|
|
+ background-color: black;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: center;
|
|
|
+ height: 90vh;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.body::-webkit-scrollbar {
|
|
|
+ /*隐藏滚轮*/
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+.echarts {
|
|
|
+ width: 100%;
|
|
|
+ height: 500px;
|
|
|
+ margin-left: 10px;
|
|
|
+ padding-top: -20px;
|
|
|
+}
|
|
|
+
|
|
|
+.dataList {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ align-items: center;
|
|
|
+ padding-top: 27px;
|
|
|
+}
|
|
|
+
|
|
|
+.data {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.name {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row-reverse;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.num {
|
|
|
+ margin-left: 59px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #05bb4c;
|
|
|
+ min-width: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.nums {
|
|
|
+ margin-left: 29px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #05bb4c;
|
|
|
+ min-width: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.unit {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #ffffff;
|
|
|
+ margin-left: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.condition {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ border-bottom: 1px solid #3d3d3d;
|
|
|
+ padding-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.status {
|
|
|
+ width: 25%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.statusIcon {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ margin-left: 8px;
|
|
|
+}
|
|
|
+.statusIcons {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
+</style>
|