Files
sk_fems_ui/pages/ems/base/ElecQualityReadPage.vue
2025-07-22 09:58:38 +07:00

680 lines
17 KiB
Vue

<template>
<div class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="2">
<!-- 사업장 -->
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
:labelCols="3"
/>
</v-col>
<v-col :cols="2">
<!-- 에너지 -->
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'에너지'"
:labelCols="3"
/>
</v-col>
<v-col :cols="4">
<DatePicker
:parentPrgmId="myPrgmId"
:timePicker="true"
:labelCols="2"
label="조회기간"
/>
</v-col>
<v-col cols="4" class="d-flex justify-end align-center">
<BtnSearch @click="search" class="mr-1" />
<BtnExcelDownload :parentPrgmId="myPrgmId" :gridName="gridName" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" lg="3" class="h100">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-5">
<v-card-title class="pa-0 custom-title-4">검침개소</v-card-title>
<v-btn :ripple="false" icon tile @click="btnTreeExpand()">
<!-- {{ treeExpand }} -->
<v-icon
size="30"
v-text="treeExpandAll ? 'mdi-chevron-up' : 'mdi-chevron-down'"
></v-icon>
</v-btn>
</div>
<div class="h100 px-5" :style="{ height: 'calc(100% - 76px)' }">
<div ref="treeGridParent" class="h100 w100">
<!-- 검침개소 트리 -->
<component
:ref="'treeGrid' + myPrgmId"
:is="loadTree ? 'Grid' : null"
:gridName="gridNameTree"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="12" lg="9" class="h100">
<v-card class="pb-5">
<div class="w100 pa-3">
<v-btn
:ripple="false"
icon
tile
@click="btnLegendSelect()"
style="float:right"
>
<v-icon
size="20"
v-text="
legendSelctedAll
? 'mdi-radiobox-marked'
: 'mdi-radiobox-blank'
"
></v-icon
></v-btn>
</div>
<div style="height: 45%" class="pa-5">
<component
ref="VCharts"
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="'rowGridChart'"
/>
</div>
<div ref="gridParent" style="height: 52%" class="px-5">
<component
id="selectOffcTmDataTable"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import { mapActions, mapMutations } from 'vuex';
// import Search from "~/components/common/search";
import Chart from '~/components/common/Chart';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import DatePicker from '~/components/common/Datepicker';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
let myTitle;
// const myPrgmId = "PRG0023";
let myPrgmId;
export default {
mixins: [mixinGlobal],
async asyncData(context) {
const myState = context.store.state;
// context.store.commit("setActiveMenuInfo", myState.menuData[myPrgmId]);
// myTitle = myState.activeMenuInfo.menuNm;
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: {
SelectBlocMstr,
SelectEnergy,
DatePicker,
BtnSearch,
BtnExcelDownload,
// Search,
Chart,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
gridNameTree: 'treeGrid',
loadTree: false,
loadGrid: false,
loadChart: false,
treeExpandAll: true,
legendSelctedAll: true,
legendSeletedList: {},
myRowKey: 0,
};
},
computed: {
chkIsFind() {
return this.pageData.isFind;
},
chkRowdata() {
return this.pageData[this.gridName].data;
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
legendSelcted() {
return this.legendSelctedAll ? '전체선택' : '전체해제';
},
chkBlocCd() {
return this.pageData.blocId;
},
chkEnergyCd() {
return this.pageData.energyCd;
},
initFlag() {
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
chkRowdata(val) {
this.setChartData(val);
},
chkIsFind(val) {
if (val) {
this.search();
}
},
chkBlocCd() {
this.myRowKey = 0;
this.setPageData({ isFind: true });
},
chkEnergyCd() {
this.myRowKey = 0;
this.setPageData({ isFind: true });
},
initFlag(val) {
if (val) {
this.init();
}
},
},
beforeCreate() {
myPrgmId = this.$route.query.prgmId;
this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
// this.$store.commit("setPageData", { searchItems: mySearch() });
},
mounted() {
this.init();
},
methods: {
...mapMutations({
setChartOption: 'setChartOption',
}),
...mapActions({
getHolidayList: 'modules/search/getHolidayList',
}),
init() {
this.gridInit();
this.getTreeData();
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const treeGridHeight = this.$refs.treeGridParent.offsetHeight - 36;
const myOptions = {
columnOptions: {
resizable: true,
minWidth: 100,
//frozenCount: 2
},
scrollX: false,
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
// this.setGridColumn({
// gridKey: this.gridName,
// value: myColumns
// });
const myOptionsTree = {
treeColumnOptions: {
name: 'name',
},
scrollX: true,
};
this.setGridOption({
gridKey: this.gridNameTree,
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setGridColumn({
gridKey: this.gridNameTree,
value: [{ header: '개소', name: 'name' }],
// value: [{ header: "개소", name: "name", width: "auto"}]
});
},
async search() {
// if (this.pageData.blocCodeLists) await this.getTreeData();
await this.getTreeData();
this.setPageData({
isFind: false,
});
},
// 검침개소 조회
async getTreeData() {
let res = [];
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
res = await this.postApiReturn({
apiKey: 'selectElecQualityReadPlcTree',
resKey: 'readPlcData',
sendParam: {
// sh_date: this.pageData.sh_date, // "2021-06-16 00:00:00 - 2021-06-17 00:00:00",
// frDttm: this.pageData.frDttm, // "2021-07-01T15:00:00.000Z",
// endDttm: this.pageData.endDttm, // "2021-07-02T14:59:59.000Z",
// 위 값들은 없어도 같은 결과인듯한데 꼭 필요한건지 확인!!!?
// blocId: this.pageData.blocCodeLists, //"BL0001",
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
// mttCd: this.pageData.mttCd, // "MTT00001" // 전력 코드 고정
// readObjId : "ROI000001"
// readObjId : this.pageData.energyCd
readObjId: this.pageData.energyList[this.pageData.energyCd].cd,
},
});
}
let setTreeData = [];
if (res.length > 0) {
const newRes = res.map(item => {
const arr = {
...item,
plcCdNm: item.plcNm,
};
return arr;
});
setTreeData = await this.setTree({
// gridKey: this.gridNameTree,
treeKey: 'PLC_CD',
value: newRes,
}); // 검침개소 트리구조화
this.treeExpandAll = true;
this.loadTree = true;
await this.setGridData({
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
// 첫번째 row 선택상태
this.$refs['treeGrid' + this.myPrgmId].focus({
rowKey: this.myRowKey,
columnName: 'name',
setScroll: true,
});
} else {
// this.loadTree = false;
this.$store.state.pageData[this.myPrgmId].treeGrid.data = [];
this.loadTree = true;
}
this.setPageData({ isFind: false });
},
async getRowData(data) {
this.loadGrid = false; // grid refresh
this.loadChart = false;
this.$store.state.pageData[this.myPrgmId].rowGridChart.series = [];
this.myRowKey = data.rowKey;
const myChart = this.$refs.VCharts;
if (myChart != null)
this.legendSeletedList = myChart.onGetLegendSelectedList();
const res = await this.postApiReturn({
apiKey: 'selectOffcTmData',
resKey: ['offcTmDataData', 'tagRoiData'],
sendParam: {
frDttm: this.pageData.fromDt, // "2021-06-16 00:00:00",
endDttm: this.pageData.toDt, // "2021-06-17 00:00:00",
readPlc: data.plcCd,
readPlcNm: data.plcNm,
},
});
// 그리드 컬럼 만들어 주기
let myColumns = [
{ header: '검침개소', name: 'readPlcNm', width: 200 },
{ header: '검침일시', name: 'readDt', width: 200, align: 'center' },
];
const columInfo = res['tagRoiData'].length > 0 ? res['tagRoiData'] : [];
for (const infoItem of columInfo) {
myColumns.push({
header: infoItem.readObjNm + '(' + infoItem.unit + ')',
name: String(infoItem.readObjId).toLowerCase(),
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
align: 'right',
width: 100,
excelType: 'number',
// excelFormatter:"2",
});
}
// 그리드 컬럼 설정
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
// 그리드 데이터 설정
const returnList =
res['offcTmDataData'].length > 0 ? res['offcTmDataData'] : [];
this.setGridData({
gridKey: this.gridName,
value: returnList,
});
this.loadGrid = true;
// 컬럼에서 name부분만 추출
let newCol = myColumns.slice(2);
newCol = newCol.map(item => item.name);
this.$nextTick(() => {
this.setChartData(returnList);
});
this.setExlsData(returnList, newCol);
},
setExlsData(list, newCol) {
const rowData = [];
for (const item of list) {
let tempDic = {};
tempDic['readPlcNm'] = item.readPlcNm;
tempDic['readDt'] = item.readDt;
for (var i = 0; i < newCol.length; i++) {
tempDic[newCol[i]] = Utility.setFormatIntDecimal(item[newCol[i]], 2);
}
rowData.push(tempDic);
}
const xlsFileInfo = {
rowGrid: {
rowData,
// rowData: list.map(item => ({
// readPlcNm: item.readPlcNm,
// readDt: item.readDt,
// voltValA: Utility.setFormatDecimal(item.voltValA, 2, true),
// voltValB: Utility.setFormatDecimal(item.voltValB, 2, true),
// voltValC: Utility.setFormatDecimal(item.voltValC, 2, true),
// currValA: Utility.setFormatDecimal(item.currValA, 2, true),
// currValB: Utility.setFormatDecimal(item.currValB, 2, true),
// currValC: Utility.setFormatDecimal(item.currValC, 2, true),
// powFact: Utility.setFormatDecimal(item.powFact, 2, true),
// freq: Utility.setFormatDecimal(item.freq, 2, true),
// instantVal: Utility.setFormatDecimal(item.instantVal, 2, true)
// })),
// 엑셀변환시 데이타 가공이 추가로 필요하게 된다면 여기에 가공된 rowData 를 넣어야 할듯
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
};
this.setPageData({ xlsFileInfo });
},
async setChartData(data) {
this.loadChart = false;
let xAxisData = [];
let seriesData = [];
let chartOption = [];
let legendData = [];
let legendSelectedData = {};
let legendChk = 0;
let tmpList = [];
var myKey = this.pageData[this.gridName].column.filter(v => {
return v.header !== '검침개소';
});
for (var key in this.legendSeletedList) {
if (this.legendSeletedList[key]) legendChk++;
}
//Object.keys(this.legendSeletedList).length
if (legendChk > 0) {
legendSelectedData = this.legendSeletedList;
for (var i = 1; i < myKey.length; i++) {
legendData.push(myKey[i].header);
}
} else {
for (var i = 1; i < myKey.length; i++) {
legendData.push(myKey[i].header);
if (myKey[i].name.toUpperCase() == 'ROI000009') {
legendSelectedData[myKey[i].header] = true;
} else {
legendSelectedData[myKey[i].header] = false;
}
}
}
this.legendData = legendData;
tmpList = myKey.map(item => ({
name: item.header,
type: 'line',
data: data.map(obj => {
var matchKey = Object.keys(obj).filter(v => {
return item.name === v;
});
return obj[matchKey];
}),
}));
xAxisData =
tmpList[0].data.map(item =>
item ? Utility.setFormatDate(item, 'HH:mm') : '',
) || [];
seriesData = tmpList.slice(1, tmpList.length) || [];
chartOption = {
legend: {
type: 'scroll',
pageIconColor: '#18579e',
pageIconInactiveColor: '#ffffff66',
pageTextStyle: { color: '#fff' },
pageIconSize: 18,
pageButtonGap: 10,
left: 10,
right: 10,
data: legendData,
selected: legendSelectedData,
},
};
// console.log("chartOption :: ", chartOption);
this.setChartOption({ chartKey: 'rowGridChart', value: chartOption });
this.setChartXAxisData({ chartKey: 'rowGridChart', value: xAxisData });
this.setChartSeries({ chartKey: 'rowGridChart', value: seriesData });
this.loadChart = true;
},
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.myPrgmId].expandAll();
else this.$refs['treeGrid' + this.myPrgmId].collapseAll();
},
btnLegendSelect() {
this.legendSelctedAll = !this.legendSelctedAll;
const myChart = this.$refs.VCharts;
let legendData = [];
let tmpList = [];
var myKey = this.pageData[this.gridName].column.filter(v => {
return v.header !== '검침개소';
});
for (var i = 1; i < myKey.length; i++) {
legendData.push(myKey[i].header);
}
if (this.legendSelctedAll) {
myChart.onLegendSelect(legendData);
} else {
myChart.onLegendUnSelect(legendData);
}
},
},
};
const defaultData = {
/* 검색옵션 */
// searchItems: {
// options: null,
// buttons: null
// },
// 사업장
blocId: '',
blocMstrList: [],
// blocCodeLists: null, // 사업장
// blocCodeListsList: [],
// 에너지
energyCd: 0,
energyList: [],
// energyData: 'ROI000001',
// energyDataList:[],
mttCd: 'MTT00001', // 고정값, => 에너지원 전력코드
// 주기
cmCycle: 'CYC_HOUR',
cmCycleList: [
{ idx: 0, text: '연', value: 'CYC_YEAR' },
{ idx: 1, text: '월', value: 'CYC_MONTH' },
{ idx: 2, text: '일', value: 'CYC_DAY' },
{ idx: 3, text: '시간', value: 'CYC_HOUR' },
],
defaultRange: {
CYC_YEAR: 10,
CYC_MONTH: 12,
CYC_DAY: 30,
CYC_HOUR: 24,
},
fromDt: '',
toDt: '',
// cmCycle: "CYC_HOUR", // 주기
// defaultRange: {
// CYC_HOUR: 24
// },
// fromDt: "",
// toDt: "",
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [],
option: {},
},
// rowGrid 데이타를 가공해서 보여주는 차트 옵션
rowGridChart: Utility.defaultChartOption(true),
legendData: [],
treeGrid: {
data: [],
column: [],
option: {},
},
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
// tableId: "selectOffcTmDataTable",
rowData: [],
// 엑셀변환시 데이타 가공이 추가로 필요하게 된다면 여기에 가공된 rowData 를 넣어야 할듯
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
// const mySearch = () => {
// return {
// options: {
// cols: 9,
// list: [
// {
// type: "SearchSelect",
// cols: 3,
// class: "py-2",
// label: "사업장",
// labelCols: 4,
// apiKey: "selectBlocMstrCodeList",
// resKey: "blocCodeLists",
// dataCd: "blocId",
// dataNm: "blocNm",
// autoLoad: true
// },
// {
// type: "SearchSelect",
// cols: 3,
// class: "py-2",
// label: "검침대상",
// labelCols: 4,
// apiKey: "selectEnergy",
// resKey: "energyData",
// dataCd: "cd",
// dataNm: "enrgNm",
// autoLoad: true
// },
// {
// type: "DatePicker",
// cols: 6,
// class: "py-2",
// label: "조회기간",
// labelCols: 2,
// timePicker: true,
// autoLoad: true
// }
// ]
// },
// buttons: {
// cols: 2,
// class: "text-right",
// list: [
// {
// type: "BtnSearch"
// },
// {
// type: "BtnExcelDownload",
// bindingData: "rowGrid"
// }
// ]
// }
// };
// };
</script>