734 lines
20 KiB
Vue
734 lines
20 KiB
Vue
<template>
|
||
<div ref="mainDiv" class="l-layout">
|
||
<CommonPageTitle />
|
||
<v-row ref="searchFilter">
|
||
<v-col :cols="12">
|
||
<v-card class="searchFilter">
|
||
<v-row align="center" no-gutters>
|
||
<v-col :cols="3">
|
||
<component
|
||
:is="'SelectBox'"
|
||
ref="SelectBox1"
|
||
:propsValue="selectValue01"
|
||
:itemList="selectValueList01"
|
||
:label="'설비종류'"
|
||
:labelCols="12"
|
||
:textCols="12"
|
||
:iconShow="true"
|
||
:customClass="'select-large'"
|
||
@update:propsValue="selectValue01 = $event"
|
||
/>
|
||
</v-col>
|
||
<v-col :cols="3">
|
||
<component
|
||
:is="'DatePicker'"
|
||
:label="'대상연월'"
|
||
:parentPrgmId="myPrgmId"
|
||
:customClass="'datepicker-large'"
|
||
/>
|
||
</v-col>
|
||
<v-col :cols="3"> </v-col>
|
||
<v-col :cols="3" class="text-right">
|
||
<!-- <v-btn v-show="false" :ripple="false" @click="test()">TEST</v-btn> -->
|
||
<!-- <v-btn :ripple="false" @click="search()">조회</v-btn> -->
|
||
<a-button
|
||
style="margin-top: 25px; height: 40px"
|
||
icon="search"
|
||
class="search-button"
|
||
type="primary"
|
||
@click="search"
|
||
>조회</a-button
|
||
>
|
||
</v-col>
|
||
</v-row>
|
||
</v-card>
|
||
</v-col>
|
||
</v-row>
|
||
<v-row ref="contents" style="overflow: auto">
|
||
<v-col>
|
||
<div v-for="(value, key, index) in contentData" :key="'key1_' + index">
|
||
<v-card-title class="d-flex align-center justify-space-between pa-3">
|
||
<span class="tit ft-size_20 ft-weight_600">{{ value.eqpmGrpNm }}</span>
|
||
</v-card-title>
|
||
<v-row>
|
||
<v-col :cols="3" v-for="(item, i) in value.chartData" :key="'key2_' + i">
|
||
<div
|
||
class="v-box"
|
||
style="height: 330px; position: relative"
|
||
:ref="item.eqpmGrpId + '_' + item.fabId"
|
||
@click="chartClickEvent(item, $event)"
|
||
>
|
||
<!-- Card border at the top of the title -->
|
||
<div
|
||
style="
|
||
position: absolute;
|
||
left: 0;
|
||
top: 10px;
|
||
width: 4px;
|
||
height: 50px;
|
||
background-color: #91caff;
|
||
border-radius: 2px;
|
||
"
|
||
></div>
|
||
<!-- Information area -->
|
||
<v-col :cols="5" style="height: 100%">
|
||
<div style="height: 10%">
|
||
<strong style="font-size: 20px; font-weight: 600">{{
|
||
item.fabNm
|
||
}}</strong>
|
||
</div>
|
||
<div style="height: 25%"></div>
|
||
<div style="height: 50%; text-align: center">
|
||
<v-row>
|
||
<!-- <v-col :cols="1"> </v-col> -->
|
||
일에너지:
|
||
</v-row>
|
||
<v-row>
|
||
<v-col :cols="12" style="text-align: left">
|
||
<span class="textInfo">
|
||
{{ item.dayVal }}
|
||
</span>
|
||
<span class="textDetail">MWh</span>
|
||
</v-col>
|
||
<!-- <v-col :cols="4" style="text-align: left"> MWh </v-col> -->
|
||
<!-- <v-col :cols="1"> </v-col> -->
|
||
</v-row>
|
||
<v-row style="margin-top: 20px">
|
||
<!-- <v-col :cols="1"> </v-col> -->
|
||
월에너지:
|
||
</v-row>
|
||
<v-row>
|
||
<v-col :cols="12" style="text-align: left">
|
||
<span class="textInfo">{{ item.mnthVal }}</span>
|
||
<span class="textDetail">MWh</span>
|
||
</v-col>
|
||
<!-- <v-col :cols="4" style="text-align: left"> MWh </v-col> -->
|
||
<!-- <v-col :cols="1"> </v-col> -->
|
||
</v-row>
|
||
</div>
|
||
<div style="height: 5%"></div>
|
||
</v-col>
|
||
<!-- Chart area -->
|
||
<v-col :cols="7" style="height: 100%">
|
||
<div style="height: 20%"></div>
|
||
<div style="text-align: center">에너지사용효율</div>
|
||
<div style="height: 70%">
|
||
<component
|
||
class="w100 h100"
|
||
:is="loadChart ? 'Chart' : null"
|
||
:parentPrgmId="myPrgmId"
|
||
:chartName="'chart_' + item.eqpmGrpId + '_' + item.fabId"
|
||
:ref="'chart_' + item.eqpmGrpId + '_' + item.fabId"
|
||
/>
|
||
</div>
|
||
</v-col>
|
||
</div>
|
||
</v-col>
|
||
</v-row>
|
||
</div>
|
||
</v-col>
|
||
</v-row>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapState, mapMutations, mapActions } from "vuex";
|
||
import mixinGlobal from "@/mixin/global.js";
|
||
import { resize } from "@/mixin/resize.js";
|
||
import Utility from "~/plugins/utility";
|
||
import SelectBox from "@/components/common/select/SelectBox";
|
||
import BtnSearch from "~/components/common/button/BtnSearch";
|
||
import DatePicker from "@/components/common/Datepicker";
|
||
import Chart from "~/components/common/Chart";
|
||
import PageTitle from "~/components/common/PageTitle";
|
||
import getGaugeChartOption from "~/components/common/chartoptions/GaugeChart";
|
||
|
||
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: {
|
||
Utility,
|
||
SelectBox,
|
||
BtnSearch,
|
||
DatePicker,
|
||
Chart,
|
||
PageTitle,
|
||
},
|
||
data() {
|
||
return {
|
||
myPrgmId: myPrgmId,
|
||
|
||
initedFlag: false,
|
||
|
||
selectValueList01: [], // 설비종류 리스트
|
||
selectValue01: null,
|
||
|
||
contentData: {},
|
||
loadChart: false,
|
||
|
||
testFlag: false,
|
||
};
|
||
},
|
||
computed: {
|
||
...mapState({
|
||
pageData: (state) => state.pageData[myPrgmId],
|
||
isDarkMode: "isDarkMode",
|
||
}),
|
||
fromDt() {
|
||
return this.pageData.fromDt;
|
||
},
|
||
},
|
||
watch: {
|
||
async selectValue01(value) {
|
||
if (this.initedFlag) {
|
||
await this.search();
|
||
}
|
||
},
|
||
async fromDt(value) {
|
||
if (this.initedFlag) {
|
||
await this.search();
|
||
}
|
||
},
|
||
isDarkMode(newVal) {
|
||
this.setChartData(this.contentData);
|
||
},
|
||
},
|
||
async beforeCreate() {
|
||
myPrgmId = this.$route.query.prgmId;
|
||
await this.$store.dispatch("chkOpenTabList", {
|
||
key: "create",
|
||
prgmId: myPrgmId,
|
||
defaultData: defaultData,
|
||
});
|
||
},
|
||
created() {},
|
||
mounted() {
|
||
this.init();
|
||
},
|
||
beforeDestroy() {
|
||
this.initedFlag = false;
|
||
this.chkOpenTabList({ key: "destroy", prgmId: myPrgmId });
|
||
},
|
||
methods: {
|
||
...mapMutations({
|
||
setChartOption: "setChartOption",
|
||
}),
|
||
async test() {
|
||
this.testFlag = !this.testFlag;
|
||
|
||
await this.search();
|
||
},
|
||
async init() {
|
||
await this.getSelectValueList01();
|
||
|
||
await this.search();
|
||
this.initedFlag = true;
|
||
},
|
||
async search() {
|
||
var enrgUseTotSummData = await this.getEnrgUseTotSummData();
|
||
var data = this.replaceUndefined(enrgUseTotSummData);
|
||
var dataGroupByEqpmGrpId = this.groupByEqpmGrpId(data);
|
||
|
||
this.contentData = dataGroupByEqpmGrpId;
|
||
this.setContent(this.contentData);
|
||
},
|
||
async getSelectValueList01() {
|
||
var res = await this.postApiReturn({
|
||
apiKey: "selectEmsEqpmKindList",
|
||
resKey: "eqpmGrpPysclQtyMngData",
|
||
sendParam: {},
|
||
});
|
||
|
||
if (res.length > 0) {
|
||
this.selectValueList01 = await res.map((item) => {
|
||
return {
|
||
text: item.eqpmKindNm,
|
||
value: item.eqpmKindId,
|
||
data: {
|
||
...item,
|
||
},
|
||
};
|
||
});
|
||
this.selectValue01 = this.selectValueList01[0].value;
|
||
} else {
|
||
this.selectValueList01 = [];
|
||
this.selectValue01 = null;
|
||
}
|
||
},
|
||
async getEnrgUseTotSummData() {
|
||
var res = await this.postApiReturn({
|
||
apiKey: "selectEnrgUseTotSumm",
|
||
resKey: "data",
|
||
sendParam: {
|
||
fromDt: this.pageData.fromDt,
|
||
eqpmKind: this.selectValue01,
|
||
},
|
||
});
|
||
|
||
if (this.testFlag == true) {
|
||
res = [
|
||
{
|
||
eqpmGrpNm: "냉동기저온",
|
||
fabId: "ECC000003",
|
||
eqpmGrpId: "EQG000001",
|
||
fabNm: "삼천1공장",
|
||
dayVal: 252.55,
|
||
mnthVal: 4800.12,
|
||
planVal: 4400,
|
||
effcRt: 87.5,
|
||
},
|
||
{
|
||
eqpmGrpNm: "냉동기저온",
|
||
fabId: "ECC000008",
|
||
eqpmGrpId: "EQG000001",
|
||
fabNm: "삼천2공장",
|
||
dayVal: 353.46,
|
||
mnthVal: 2000.12,
|
||
planVal: 1800,
|
||
effcRt: 86,
|
||
},
|
||
{
|
||
eqpmGrpNm: "냉동기저온",
|
||
fabId: "ECC000009",
|
||
eqpmGrpId: "EQG000001",
|
||
fabNm: "삼천3공장",
|
||
dayVal: 353.46,
|
||
mnthVal: 2000.12,
|
||
planVal: 1800,
|
||
effcRt: 86,
|
||
},
|
||
{
|
||
eqpmGrpNm: "냉동기저온",
|
||
fabId: "ECC000010",
|
||
eqpmGrpId: "EQG000001",
|
||
fabNm: "삼천4공장",
|
||
dayVal: 553.46,
|
||
mnthVal: 3000.12,
|
||
planVal: 2800,
|
||
effcRt: 90,
|
||
},
|
||
{
|
||
eqpmGrpNm: "냉동기저온",
|
||
fabId: "ECC000011",
|
||
eqpmGrpId: "EQG000001",
|
||
fabNm: "삼천5공장",
|
||
dayVal: 453.46,
|
||
mnthVal: 3000.12,
|
||
planVal: 2800,
|
||
effcRt: 86,
|
||
},
|
||
{
|
||
eqpmGrpNm: "냉동기고온",
|
||
fabId: "ECC000008",
|
||
eqpmGrpId: "EQG000002",
|
||
fabNm: "삼천2공장",
|
||
dayVal: 444,
|
||
mnthVal: 8888.888,
|
||
planVal: 6000,
|
||
effcRt: 72.44,
|
||
},
|
||
{
|
||
eqpmGrpNm: "test1",
|
||
fabId: "ECC000008",
|
||
eqpmGrpId: "EQG000007",
|
||
fabNm: "삼천2공장",
|
||
dayVal: 455,
|
||
mnthVal: 9999.999,
|
||
planVal: 5000,
|
||
effcRt: 50.555,
|
||
},
|
||
];
|
||
}
|
||
|
||
return res;
|
||
},
|
||
groupByEqpmGrpId(data) {
|
||
var result = {};
|
||
|
||
for (var i = 0; i < data.length; i++) {
|
||
if (!result.hasOwnProperty(data[i]["eqpmGrpId"])) {
|
||
var tempObject = {};
|
||
tempObject.eqpmGrpId = data[i]["eqpmGrpId"];
|
||
tempObject.eqpmGrpNm = data[i]["eqpmGrpNm"];
|
||
tempObject.chartData = [];
|
||
|
||
tempObject.chartData.push({
|
||
...data[i],
|
||
});
|
||
result[data[i]["eqpmGrpId"]] = tempObject;
|
||
} else {
|
||
result[data[i]["eqpmGrpId"]].chartData.push({
|
||
...data[i],
|
||
});
|
||
}
|
||
}
|
||
|
||
return result;
|
||
},
|
||
replaceUndefined(data) {
|
||
var dataKeyList = ["dayVal", "mnthVal", "planVal", "effcRt"];
|
||
var replaceValList = [0, 0, 0, 0];
|
||
// var replaceValList = [666666.66, 252.35, '', 50];
|
||
|
||
for (var i = 0; i < data.length; i++) {
|
||
for (var j = 0; j < dataKeyList.length; j++) {
|
||
if (data[i][dataKeyList[j]] == undefined) {
|
||
data[i][dataKeyList[j]] = replaceValList[j];
|
||
}
|
||
}
|
||
}
|
||
|
||
return data;
|
||
},
|
||
async setContent(data) {
|
||
this.initChart(data);
|
||
this.loadChart = false;
|
||
await this.$nextTick();
|
||
this.setChartData(data);
|
||
this.loadChart = true;
|
||
},
|
||
initChart(data) {
|
||
var dataKeyList = Object.keys(data);
|
||
var currentChartData = null;
|
||
var chartKey = null;
|
||
|
||
for (var i = 0; i < dataKeyList.length; i++) {
|
||
for (var j = 0; j < data[dataKeyList[i]].chartData.length; j++) {
|
||
currentChartData = data[dataKeyList[i]].chartData[j];
|
||
chartKey =
|
||
"chart_" + currentChartData["eqpmGrpId"] + "_" + currentChartData["fabId"];
|
||
|
||
this.setPageData({
|
||
[chartKey]: getGaugeChartOption({
|
||
title: chartKey,
|
||
value: 75,
|
||
isDarkMode: this.isDarkMode,
|
||
backgroundRadius: 89,
|
||
}),
|
||
});
|
||
}
|
||
}
|
||
},
|
||
async setChartData(data) {
|
||
var dataKeyList = Object.keys(data);
|
||
var currentChartData = null;
|
||
var chartKey = null;
|
||
var chartOption = null;
|
||
|
||
for (var i = 0; i < dataKeyList.length; i++) {
|
||
for (var j = 0; j < data[dataKeyList[i]].chartData.length; j++) {
|
||
currentChartData = data[dataKeyList[i]].chartData[j];
|
||
chartKey =
|
||
"chart_" + currentChartData["eqpmGrpId"] + "_" + currentChartData["fabId"];
|
||
|
||
chartOption = getGaugeChartOption({
|
||
title: chartKey,
|
||
value: 75,
|
||
isDarkMode: this.isDarkMode,
|
||
backgroundRadius: 89,
|
||
});
|
||
chartOption["series"][0]["data"][0].value = currentChartData["effcRt"];
|
||
this.$store.state.pageData[myPrgmId][chartKey] = chartOption;
|
||
}
|
||
}
|
||
|
||
//Mock chart
|
||
// chartKey = 'chart_test_01'
|
||
// chartOption["series"][0]["data"][0].value = 56;
|
||
// this.$store.state.pageData[myPrgmId][chartKey] = chartOption;
|
||
},
|
||
getGuageChartOption() {
|
||
// const gaugeColors = [
|
||
// [0.125, '#009245'],
|
||
// [0.25, '#39b54a'],
|
||
// [0.375, '#d9e021'],
|
||
// [0.5, '#fcee21'],
|
||
// [0.625, '#fbb03b'],
|
||
// [0.75, '#f7931e'],
|
||
// [0.875, '#f15a24'],
|
||
// [1.0, '#ed1c24']
|
||
// ];
|
||
const gaugeColors = [
|
||
[0, "#ed1c24"],
|
||
[0.6, "#ed1c24"],
|
||
[0.8, "#f7931e"],
|
||
[1.0, "#009245"],
|
||
];
|
||
var guageChartOption = {
|
||
grid: {
|
||
top: "30%",
|
||
bottom: 0,
|
||
},
|
||
series: [
|
||
{
|
||
type: "gauge",
|
||
center: ["50%", "80%"],
|
||
radius: "100%",
|
||
startAngle: 180,
|
||
endAngle: 0,
|
||
min: 0,
|
||
max: 100,
|
||
splitNumber: 10,
|
||
itemStyle: {
|
||
// color: '#FFAB91'
|
||
color: "auto",
|
||
// color:gaugeColors
|
||
},
|
||
progress: {
|
||
// show: true,
|
||
show: false,
|
||
width: 20,
|
||
},
|
||
pointer: {
|
||
// show: false
|
||
show: true,
|
||
itemStyle: {
|
||
// color: '#FFAB91',
|
||
color: "auto",
|
||
},
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
width: 20,
|
||
color: gaugeColors,
|
||
},
|
||
},
|
||
axisTick: {
|
||
distance: -35,
|
||
splitNumber: 5,
|
||
lineStyle: {
|
||
width: 2,
|
||
color: "#999",
|
||
},
|
||
},
|
||
splitLine: {
|
||
distance: -42,
|
||
length: 14,
|
||
lineStyle: {
|
||
width: 3,
|
||
color: "#999",
|
||
},
|
||
},
|
||
axisLabel: {
|
||
distance: -10,
|
||
color: "#999",
|
||
fontSize: 10,
|
||
},
|
||
anchor: {
|
||
show: false,
|
||
},
|
||
title: {
|
||
show: false,
|
||
},
|
||
detail: {
|
||
valueAnimation: true,
|
||
width: "60%",
|
||
lineHeight: 25,
|
||
borderRadius: 8,
|
||
// offsetCenter: [0, '-15%'],
|
||
offsetCenter: [0, "33%"],
|
||
fontSize: 17,
|
||
fontWeight: "bolder",
|
||
formatter: "{value} %",
|
||
color: "auto",
|
||
},
|
||
data: [
|
||
{
|
||
value: NaN,
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|
||
|
||
return guageChartOption;
|
||
},
|
||
getGuageChartOption2(chartName) {
|
||
const gaugeColors = [
|
||
[0, "#ed1c24"],
|
||
[0.6, "#ed1c24"],
|
||
[0.8, "#f7931e"],
|
||
[1.0, "#009245"],
|
||
];
|
||
const gaugeColors2 = [
|
||
[0, "#009245"],
|
||
[0.6, "#009245"],
|
||
[0.8, "#f7931e"],
|
||
[1.0, "#ed1c24"],
|
||
];
|
||
var guageChartOption = {
|
||
grid: {
|
||
// top: '-10%',
|
||
bottom: 0,
|
||
},
|
||
title: {},
|
||
graphic: [
|
||
{
|
||
type: "circle",
|
||
left: "center",
|
||
top: "center",
|
||
shape: {
|
||
r: 97, // radius of the background circle
|
||
},
|
||
style: {
|
||
fill: this.isDarkMode ? "#141415" : "#F5F5F5", // Light grey color
|
||
opacity: 0.3, // Semi-transparent
|
||
},
|
||
z: 0, // make sure it's behind the gauge
|
||
},
|
||
],
|
||
|
||
series: [
|
||
{
|
||
type: "gauge",
|
||
radius: "100%",
|
||
startAngle: 225,
|
||
endAngle: -45,
|
||
min: 0,
|
||
max: 160,
|
||
// progress: {
|
||
// show: true,
|
||
// width: 15,
|
||
// },
|
||
axisLine: {
|
||
lineStyle: {
|
||
width: 12,
|
||
color: [
|
||
[0.375, "#3CB371"], // Green (0–60)
|
||
[0.5, "#FFD700"], // Yellow (60–80)
|
||
[0.625, "#FFA500"], // Orange (80–100)
|
||
[1, "#FF4500"], // Red (100–160)
|
||
],
|
||
},
|
||
},
|
||
axisTick: {
|
||
distance: -5,
|
||
length: 5,
|
||
lineStyle: {
|
||
color: "#000000",
|
||
width: 1,
|
||
},
|
||
},
|
||
splitLine: {
|
||
distance: -15,
|
||
length: 8,
|
||
lineStyle: {
|
||
color: "#000000",
|
||
width: 2,
|
||
},
|
||
},
|
||
axisLabel: {
|
||
color: this.isDarkMode ? "#fff" : "#333333",
|
||
distance: 23,
|
||
fontSize: 12,
|
||
},
|
||
pointer: {
|
||
show: true,
|
||
length: "70%",
|
||
width: 6,
|
||
itemStyle: {
|
||
color: "#FA8C16", // Set your desired pointer color here
|
||
},
|
||
},
|
||
title: {
|
||
show: false,
|
||
offsetCenter: [0, "40%"],
|
||
fontSize: 18,
|
||
},
|
||
detail: {
|
||
valueAnimation: true,
|
||
fontWeight: 500, // or "normal", "lighter", "bolder", or a number like 600
|
||
fontFamily: "Oxanium, sans-serif", // or any custom font
|
||
fontSize: 30,
|
||
lineHeight: 25,
|
||
offsetCenter: [0, "60%"],
|
||
color: this.isDarkMode ? "#fff" : "#333333",
|
||
formatter: function (value) {
|
||
return `{valueStyle|${value}}\n{percentStyle|%}`;
|
||
},
|
||
rich: {
|
||
// valueStyle: {
|
||
// fontSize: 25,
|
||
// fontWeight: "bold",
|
||
// },
|
||
percentStyle: {
|
||
fontSize: 10,
|
||
color: this.isDarkMode ? "#fff" : "#333333",
|
||
// fontWeight: "normal",
|
||
},
|
||
},
|
||
},
|
||
data: [
|
||
{
|
||
value: 16,
|
||
name: "에너지사용효율", // "Energy Usage Efficiency"
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|
||
|
||
return guageChartOption;
|
||
},
|
||
chartClickEvent(argData, $event) {
|
||
var data = {
|
||
...argData,
|
||
fromDt: this.pageData.fromDt,
|
||
};
|
||
|
||
var key = "tick_" + Math.random();
|
||
this.$router.push({
|
||
name: "ems-effc-EqpmIndMntrPage",
|
||
query: {
|
||
prgmId: "PRG0081",
|
||
// tick:key
|
||
},
|
||
params: {
|
||
...data,
|
||
key: key,
|
||
},
|
||
});
|
||
},
|
||
},
|
||
};
|
||
|
||
const defaultData = {
|
||
cmCycle: "CYC_MONTH",
|
||
fromDt: Utility.setFormatDate(new Date(), "YYYYMM"), // 조회 시작일
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.textInfo {
|
||
font-family: "Oxanium", sans-serif;
|
||
font-weight: 500;
|
||
font-size: 24px;
|
||
line-height: 24px;
|
||
letter-spacing: 0;
|
||
color: #1677ff;
|
||
}
|
||
|
||
.textDetail {
|
||
// color: #000000;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 22px;
|
||
letter-spacing: 0;
|
||
}
|
||
</style>
|