Files
sk_fems_ui/pages/ems/effc/EnrgMapPage.vue
2025-07-29 13:20:29 +07:00

631 lines
15 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="l-layout">
<CommonPageTitle />
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="end" no-gutters>
<v-col :cols="4">
<!-- 차트목록 -->
<component :is="'SelectBox'" ref="SelectBox" :propsValue="selectValue01" :itemList="selectValueList01"
:label="'차트'" @update:propsValue="selectValue01 = $event" :textCols="12" customClass="select-large" />
</v-col>
<v-col :cols="4">
<!-- 대상일 -->
<component :is="'Datepicker'" :parentPrgmId="myPrgmId" :label="'대상일'" :labelCols="3" />
</v-col>
<v-col :cols="4" class="text-right">
<BtnSearch @click="search" size="large" />
<!-- 조회버튼 -->
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="min-height: 50vh">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-5">
<v-card-title class="pa-0">에너지 현황</v-card-title>
</div>
<v-row align="center" class="mx-2">
<v-col class="d-flex align-center">
<span class="arrowText">
<v-btn class="" outlined fab x-small color="#E6F4FF">
<v-icon>check</v-icon>
</v-btn>
고압반
</span>
<div class="col arrow-right mx-2 pa-0"></div>
<span class="arrowText">
분전반
<v-btn class="" outlined fab x-small color="#E6F4FF">
<v-icon>check</v-icon>
</v-btn>
</span>
</v-col>
</v-row>
<div class="px-5" style="height: 80%">
<div ref="chartParent" class="w100 h100">
<component :ref="chartName" class="w100 h100" :is="loadChart ? 'Chart' : null" :parentPrgmId="myPrgmId"
:chartName="chartName" />
</div>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import { resize } from '@/mixin/resize.js';
import Datepicker from '~/components/common/Datepicker';
import { mapState, mapActions, mapMutations } from 'vuex';
import BtnSearch from '~/components/common/button/BtnSearch';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
import DateUtility from '~/plugins/dateUtility';
import Chart from '~/components/common/Chart';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
async asyncData(context) {
const myState = context.store.state;
myPrgmId = context.route.query.prgmId;
await context.store.commit('setActiveMenuInfo', myState.menuData[myPrgmId]);
myTitle = await myState.activeMenuInfo.menuNm;
},
meta: {
title: () => {
return myTitle;
},
prgmId: myPrgmId,
closable: true,
},
components: {
Datepicker,
BtnSearch,
Utility,
DateUtility,
Chart,
SelectBox,
},
data() {
return {
myPrgmId: myPrgmId,
selectValueList01: [],
selectValue01: null,
loadChart: false,
chartName: 'sankeyChart',
};
},
computed: {
...mapState({
isDarkMode: state => state.isDarkMode,
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkToDt() {
return this.pageData.toDt;
},
chkFromDt() {
return this.pageData.fromDt;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkToDt(val) {
var diff = DateUtility.diff(
Utility.setFormatDate(new Date(), 'YYYY-MM-DD'),
this.pageData.toDt,
'd',
);
if (diff > 0) {
this.setPageData({
toDt: new Date(),
isCheck: true,
});
}
},
chkFromDt(val) {
var diff = DateUtility.diff(
Utility.setFormatDate(new Date(), 'YYYY-MM-DD'),
this.pageData.fromDt,
'd',
);
if (diff > 0) {
this.setPageData({
fromDt: new Date(),
isCheck: true,
});
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
async created() { },
async mounted() {
// this.initTest();
// return;
this.init();
// document.querySelector('.icon_arrow').style.width = document.querySelector('.iconArrowCols').clientWidth-20 + "px";
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setChartOption: 'setChartOption',
setPageData: 'setPageData',
}),
...mapActions({
getCodeList: 'modules/search/getCodeList',
}),
initTest() {
const randomNumber = n => Math.floor(Math.random() * n) + 1;
const makeData = [
{ name: 'A' },
{ name: 'B' },
{ name: 'B2' },
{ name: 'C1' },
{ name: 'C2' },
{ name: 'C3' },
// { name: 'D' }
];
const makeLinks = [
{ source: 'A', target: 'B', value: 100 },
{ source: 'A', target: 'B2', value: 50 },
{ source: 'B', target: 'C1', value: 50 },
{ source: 'B', target: 'C2', value: 50 },
{ source: 'B2', target: 'C3', value: 50 },
];
for (let index = 0; index < 10; index++) {
makeData.push(...[
{ name: 'D' + index },
]);
makeLinks.push(...[
{ source: 'C' + randomNumber(3), target: 'D' + index, value: randomNumber(50) },
]);
}
const chartOption = {
backgroundColor: '#FFFFFF',
series: [
{
layoutIterations: 0,
type: 'sankey',
left: 25.0,
top: 20.0,
right: 120,
bottom: 50.0,
// nodeWidth:10,
nodeGap: 10,
nodeAlign: 'left',
data: makeData,
links: makeLinks,
lineStyle: {
color: 'source',
curveness: 0.5,
},
// triggerEvent: true,
itemStyle: {
//color: '#1f77b4',
//borderColor: '#1f77b4'
},
label: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
fontFamily: 'Arial',
fontSize: 12,
},
},
],
tooltip: {
trigger: 'item',
},
};
this.setChartOption({ chartKey: this.chartName, value: chartOption });
// console.log("----DEBUG chart-options-------", { chartOption });
this.$nextTick(() => {
this.loadChart = true;
});
},
async init() {
await this.getEnrgMapChartList();
this.setFromDt();
},
async search() {
await this.getChartData();
this.setPageData({
isFind: false,
});
},
setFromDt() {
this.pageData.fromDt = Utility.setBeforetDate(
this.pageData,
this.pageData.toDt,
'YYYYMMDD',
);
},
async getEnrgMapChartList() {
let res = await this.postApiReturn({
apiKey: 'selectEnrgMapChartList',
resKey: 'enrgMapChartList',
sendParam: {},
});
if (res.length > 0) {
this.selectValueList01 = await res.map(item => {
return {
text: item.sankeyChartNm,
value: item.sankeyChartSno.toString(),
};
});
this.selectValue01 = this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
this.setPageData({
sankeyChartList: this.selectValueList01,
sankeyChartSno: this.selectValue01,
});
},
async getChartData() {
let res = await this.postApiReturn({
apiKey: 'selectChartNode',
resKey: 'enrgMapChartNodeList',
sendParam: {
sankeyChartSno: this.selectValue01,
},
});
let res2 = await this.postApiReturn({
apiKey: 'selectSankeyTag',
resKey: 'sankeyTagList',
sendParam: {
sankeyChartSno: this.selectValue01,
},
});
var taglist = res2.map(item => {
return item['hmiTagNm'];
});
var tempSObj = {};
var tempEObj = {};
tempSObj['eterm'] = Utility.setFormatDate(
this.pageData.fromDt,
'YYYY-MM-DD 00:29:59',
);
tempSObj['sterm'] = Utility.setFormatDate(
DateUtility.addDate(-1, 'YYYY/MM/DD', this.pageData.fromDt),
'YYYY-MM-DD 23:59:59',
);
tempSObj['interval'] = '1';
tempSObj['vals'] = ['MIN'];
tempSObj['t'] = '2022-06-03 05:22:50';
tempSObj['term'] = 'MIN10';
tempSObj['tags'] = taglist;
tempSObj['url'] = 'http://58.232.11.31:1567/RTDBweapi/aggdata2.do';
var today = Utility.setFormatDate(new Date(), 'YYYYMMDD');
var eterm = Utility.setFormatDate(this.pageData.toDt, 'YYYYMMDD');
tempEObj['eterm'] = Utility.setFormatDate(
this.pageData.toDt,
'YYYY-MM-DD 23:59:59',
);
tempEObj['sterm'] =
today == eterm
? Utility.setFormatDate(this.pageData.toDt, 'YYYY-MM-DD 00:00:00')
: Utility.setFormatDate(this.pageData.toDt, 'YYYY-MM-DD 23:29:59');
tempEObj['interval'] = '1';
tempEObj['vals'] = ['MIN'];
tempEObj['t'] = '2022-06-03 05:22:50';
tempEObj['term'] = 'MIN10';
tempEObj['tags'] = taglist;
tempEObj['url'] = 'http://58.232.11.31:1567/RTDBweapi/aggdata2.do';
var startRes = await this.postApiReturn({
apiKey: 'selectEnrgMapInfo',
resKey: 'enrgMapInfoData',
sendParam: tempSObj,
});
var endRes = await this.postApiReturn({
apiKey: 'selectEnrgMapInfo',
resKey: 'enrgMapInfoData',
sendParam: tempEObj,
});
var resultRes = [];
var tempTags = [];
var allResCheck = false;
for (var i = 0; i < taglist.length; i++) {
if (
startRes.tags[i]['d'].length > 0 &&
endRes.tags[i]['d'].length > 0
) {
resultRes.push(
Utility.setFormatDecimal(
endRes.tags[i]['M'] - startRes.tags[i]['N'],
2,
),
);
} else {
resultRes.push(0);
tempTags.push({ index: i, tag: startRes.tags[i].tag });
}
}
if (tempTags.length > 0) {
allResCheck = true;
console.log('allResCheck... true');
}
if (allResCheck) {
tempSObj['tags'] = tempTags.map(item => {
return item.tag;
});
tempSObj['sterm'] = Utility.setFormatDate(
DateUtility.addDate(-1, 'YYYY/MM/DD', this.pageData.fromDt),
'YYYY-MM-DD 23:59:59',
);
tempSObj['eterm'] = Utility.setFormatDate(
this.pageData.toDt,
'YYYY-MM-DD 23:29:59',
);
var allRes = await this.postApiReturn({
apiKey: 'selectEnrgMapInfo',
resKey: 'enrgMapInfoData',
sendParam: tempSObj,
});
var cnt = 0;
allRes.tags.map(item => {
resultRes[tempTags[cnt++].index] = Utility.setFormatDecimal(
item['M'] - item['N'],
2,
);
});
}
this.setChartData(res, res2, resultRes);
},
async setChartData(nodeList, data, value) {
this.loadChart = false;
let makeData = [];
let makeLinks = [];
this.makeDataAndLink(nodeList, data, value, makeLinks, makeData);
//label에서 보여줄 total 값
var totalVal = 0;
makeLinks.map(item => {
if (item.source == makeData[0].name) {
totalVal += item.value;
}
});
//label , tooltip 셋팅
for (var i = 0; i < makeData.length; i++) {
makeData[i]['label'] = {
show: true,
formatter: function (obj) {
var retVal = makeLinks.filter(n => {
return n.target == obj.name;
});
return (
obj.name +
'\n' +
(obj.name == makeData[0].name
? Utility.setFormatIntDecimal(totalVal, 2)
: Utility.setFormatIntDecimal(retVal[0].value, 2))
);
},
};
makeData[i]['tooltip'] = {
formatter: function (obj) {
var retVal = makeLinks.filter(n => {
return n.target == obj.name;
});
return (
obj.name +
'\n' +
(obj.name == makeData[0].name
? Utility.setFormatIntDecimal(totalVal, 2)
: Utility.setFormatIntDecimal(retVal[0].value, 2)
)
.toString()
.bold()
);
},
};
}
const chartOption = {
backgroundColor: '#FFFFFF',
series: [
{
layoutIterations: 0,
type: 'sankey',
left: 25.0,
top: 20.0,
right: 120,
bottom: 50.0,
// nodeWidth:10,
nodeGap: 10,
nodeAlign: 'left',
data: makeData,
links: makeLinks,
lineStyle: {
color: 'source',
curveness: 0.5,
},
// triggerEvent: true,
itemStyle: {
//color: '#1f77b4',
//borderColor: '#1f77b4'
},
label: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
fontFamily: 'Arial',
fontSize: 12,
},
},
],
tooltip: {
trigger: 'item',
},
};
this.setChartOption({ chartKey: this.chartName, value: chartOption });
this.loadChart = true;
},
makeDataAndLink(nodeList, data, value, makeLinks, makeData) {
var makeTempData = [];
var tempMakeLinks = [];
nodeList.map(item => {
makeTempData.push({
name: item.nodeName,
});
});
var cnt = 0;
data.map(item => {
tempMakeLinks.push({
source: item.sourceName,
target: item.tartgetName,
value: parseFloat(value[cnt++]),
});
});
// var resultArr = parentList.filter((item, index)=>{
// console.log("index :",parentList.indexOf(item))
// console.log("##",parentList.indexOf(item) === index)
// return parentList.indexOf(item) === index;
// });
//1차 정렬
tempMakeLinks.sort(function (a, b) {
if (a.source == b.source) {
return b.value - a.value;
}
});
tempMakeLinks.filter(item => {
if (item.source == makeTempData[0].name) {
makeLinks.push(item);
}
});
//2차 정렬
makeSort(makeLinks, tempMakeLinks);
makeLinks.map(item => {
makeData.push({ name: item.target });
});
makeData.unshift(makeTempData[0]);
//
function makeSort(list, b) {
for (var i = 0; i < list.length; i++) {
b.filter(item => {
if (item.source == list[i].target) {
makeLinks.push(item);
}
});
}
}
},
},
};
const defaultData = {
isFind: false,
cmCycle: 'CYC_DAY', // 주기
defaultRange: {
CYC_DAY: 30,
},
fromDt: '',
toDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'),
sankeyChartList: [],
sankeyChartSno: null,
sankeyChart: {
tooltip: {
trigger: 'axis',
confine: true,
axisPointer: {
type: 'shadow',
},
},
grid: {
left: '0',
right: '0',
top: '0',
},
legend: null,
series: [],
title: {},
backgroundColor: '',
},
};
</script>
<style lang="scss" scoped>
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.arrowText {
.v-btn {
background-color: map-deep-get($config, #{$theme}, "arow-line-btn-bg-color"); // #E6F4FF;
border: none;
.v-icon {
color: map-deep-get($config, #{$theme}, "arow-line-color"); // #1677FF;
}
}
}
.arrow-right {
width: 100%;
height: 1px;
display: flex;
background-color: map-deep-get($config, #{$theme}, "arow-line-color"); //#1677FF;
}
}
}
// .arrow-right:before {
// // content: '';
// background: #594dff;
// width: 100%;
// clip-path: polygon(
// 0 10px,
// calc(100% - 15px) 10px,
// calc(100% - 15px) 0,
// 100% 50%,
// calc(100% - 15px) 100%,
// calc(100% - 15px) calc(100% - 10px),
// 0 calc(100% - 10px)
// );
// }
</style>