sk_fems_ui commit

This commit is contained in:
unknown
2025-07-12 15:13:46 +09:00
commit ffdf5ccb66
380 changed files with 137913 additions and 0 deletions

View File

@ -0,0 +1,599 @@
<template>
<div ref="mainDiv" class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'SelectAddGrp'"
:parentPrgmId="myPrgmId"
:label="'추가 정보 그룹'"
dataKey="searchAddGrp"
:sendParam="{ useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
label="추가 정보명"
valueNm="addInfoNm"
:searchOption="true"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'사용여부'"
dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" class="h100">
<v-card class="pb-5">
<v-card-title class="d-flex justify-space-between align-end">
<span class="tit ft-size_20 ft-weight_600">추가 정보</span>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</v-card-title>
<div class="px-5" style="height:calc(100% - 76px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<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>
<div class="px-5" style="height:calc(100% - 76px)">
<component
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
</div>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import SelectAddGrp from '@/components/common/select/SelectAddGrp';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectUseFg from '@/components/common/select/SelectUseFg';
import selectCodeList from '@/components/common/select/selectCodeList';
let myTitle;
// const myPrgmId = "PRG0059";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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]);
console.log('myState.menuData : ', myState.menuData);
myTitle = await myState.activeMenuInfo.menuNm;
},
meta: {
title: () => {
return myTitle;
},
prgmId: myPrgmId,
closable: true,
},
components: {
BtnSearch,
Buttons,
SelectAddGrp,
InputText,
Form,
Grid,
SelectUseFg,
selectCodeList,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
detailList: myDetail,
initedFlag: false,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkAddGrp() {
return this.pageData.searchAddGrp;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
initFlag() {
if (
!this.initedFlag &&
this.pageData.addInfoDataKindList &&
this.pageData.blocMstrList &&
this.pageData.useFgList &&
this.pageData.addInfoDataKindList.length > 0 &&
this.pageData.blocMstrList.length > 0 &&
this.pageData.useFgList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkUseFg() {
this.setPageData({ isFind: true });
},
chkAddGrp() {
this.setPageData({ isFind: true });
},
initFlag(val) {
if (val) {
this.init();
this.initedFlag = true;
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
/////////// 추가 정보 Tab 에서 사용
// 데이터 유형 목록 조회
this.getCodeList({
dataKey: 'addInfoDataKind',
params: { commGrpCd: 'CO_DATA_TYPE', useFg: '1' },
addAll: false,
});
// 추가 정보 목록 조회
this.getAddGrpInfoList({
dataKey: 'addGrp',
params: { useFg: '1' },
addAll: false,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.initedFlag = false;
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({
getCodeList: 'modules/search/getCodeList',
getAddGrpInfoList: 'modules/search/getAddGrpInfoList',
}),
async init() {
await this.gridInit();
},
async gridInit() {
// await this.getCodeList({
// dataKey: "addInfoDataKind",
// params: { commGrpCd: 'CO_DATA_TYPE', useFg: '1'},
// addAll: false
// });
// // 추가 정보 목록 조회
// await this.getAddGrpInfoList({
// dataKey: "addGrp",
// params: { useFg: '1'},
// addAll: false
// });
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{
header: '추가 정보 그룹',
name: 'addGrpId',
minWidth: 125,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.addGrpList.filter(
item => item.addGrpId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].addGrpNm;
}
return retVal;
},
},
{
header: '추가 정보 ID',
name: 'addInfoId',
minWidth: 170,
align: 'left',
},
{
header: '추가 정보 명',
name: 'addInfoNm',
minWidth: 170,
align: 'left',
},
{
header: 'Data 형식',
name: 'addInfoDataKind',
minWidth: 85,
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.addInfoDataKindList.filter(
item => item.commCd == value,
);
console.log('newValue[데이터 형식] : ', newValue);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '사용여부',
name: 'useFg',
minWidth: 85,
align: 'center',
formatter({ value }) {
let retVal = '';
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
console.log('newValue[사용여부] : ', newValue);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{ header: '등록자NO', name: 'regUserNo', hidden: true },
{ header: '등록일시', name: 'regDttm', hidden: true },
{ header: '수정자NO', name: 'procUserNo', hidden: true },
{ header: '수정일시', name: 'procDttm', hidden: true },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.search();
},
async search() {
this.loadGrid = false;
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
const res = await this.postApiReturn({
apiKey: 'selectAddInfo',
resKey: 'addInfoData',
sendParam: {
useFg: this.pageData.useFg,
addGrpId: this.pageData.searchAddGrp,
addInfoNmLike: this.pageData.addInfoNm,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.loadGrid = true;
this.$nextTick(() => {
if (newRes.length > 0) {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
setScroll: true,
});
}
});
},
async getRowData(data) {
if (data.rowStat === 'I') {
this.detailList[0].disabled = false;
this.detailList[1].disabled = false;
} else {
this.detailList[0].disabled = true;
this.detailList[1].disabled = true;
}
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
this.$refs[this.gridName].addRow();
this.detailList[0].disabled = false;
this.detailList[1].disabled = false;
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
var validCheck = true;
if (dataArr.length > 0) {
dataArr.filter(item => {
if (item.rowStat === 'I') {
if (
item.addGrpId == '' ||
item.addInfoId == '' ||
item.addInfoNm == '' ||
item.addInfoDataKind == ''
) {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
} else if (item.rowStat === 'U') {
if (item.addInfoNm == '') {
alert('추가 정보 명을 입력해주세요');
validCheck = false;
}
}
});
if (validCheck) {
const sendParam = {
datas: {
dsAddInfo: dataArr.map(item => ({
...item,
addGrpId: item.addGrpId,
useFg: item.useFg ? '1' : '0',
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveAddInfo',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
},
};
const defaultData = {
/* 검색옵션 */
addInfoNm: '',
useFg: '1',
useFgList: [],
searchAddGrp: '',
searchAddGrpList: [],
addInfoDataKind: '',
addInfoDataKindList: [],
addGrp: '',
addGrpList: [],
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
addGrpId: '',
addInfoId: '',
addInfoNm: '',
addInfoDataKind: 'NUM',
useFg: '1',
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
};
const myDetail = [
{
type: 'SelectBox',
label: '추가 정보 그룹',
valueNm: 'addGrpId',
disabled: true,
cols: 6,
class: 'py-2',
list: 'addGrpList',
itemText: 'addGrpNm',
itemValue: 'addGrpId',
required: true,
},
{
type: 'InputText',
label: '추가정보 ID',
valueNm: 'addInfoId',
disabled: true,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'InputText',
label: '추가 정보 명',
valueNm: 'addInfoNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'SelectBox',
label: 'Data 형식',
valueNm: 'addInfoDataKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'addInfoDataKindList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
},
{
type: 'InputText',
label: '등록자NO',
valueNm: 'regUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '등록일시',
valueNm: 'regDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정자NO',
valueNm: 'procUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정일시',
valueNm: 'procDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,719 @@
<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="3">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
사업장
</label>
</v-col>
<v-col :cols="7">
<v-select
v-model="blocId"
:items="blocMstrList"
item-text="blocNm"
item-value="blocId"
solo
outlined
:hide-details="true"
append-icon="mdi-chevron-down"
class="v-select__custom"
></v-select>
</v-col>
</v-row>
</v-col>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
검침대상유형
</label>
</v-col>
<v-col :cols="7">
<v-select
v-model="roiGrpCode"
:items="roiGrpCodeList"
item-text="commCdNm"
item-value="commCd"
solo
outlined
:hide-details="true"
append-icon="mdi-chevron-down"
class="v-select__custom"
></v-select>
</v-col>
</v-row>
</v-col>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
검침대상
</label>
</v-col>
<v-col :cols="7">
<v-select
v-model="mttCd"
:items="mttCdList"
item-text="mttNm"
item-value="mttCd"
solo
outlined
:hide-details="true"
append-icon="mdi-chevron-down"
class="v-select__custom"
></v-select>
</v-col>
</v-row>
</v-col>
<v-col :cols="3" class="text-right">
<v-btn :ripple="false" class="mr-1" @click="searchGrid2()"
>조회</v-btn
>
<BtnExcelDownload
class="mr-1"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
ref="fromPicker"
:is="'Datepicker'"
:parentPrgmId="myPrgmId"
:label="'조회기간'"
/>
</v-col>
<v-col :cols="4">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="3">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>정시만조회</label
>
</v-col>
<v-col :cols="1">
<v-checkbox
v-model="timeChkValue"
:color="isDarkMode ? '#fff' : '#4777d9'"
></v-checkbox>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="3">
<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
>
<div>
<v-btn :ripple="false" icon tile @click="btnTreeExpand()">
<v-icon
size="30"
v-text="treeExpandAll ? 'mdi-chevron-up' : 'mdi-chevron-down'"
></v-icon>
</v-btn>
</div>
</div>
<div style="height:calc(100% - 76px)" class="px-5">
<div ref="treeGridParent" class="w100 h100">
<component
:ref="gridNameTree + myPrgmId"
:is="loadTree ? 'Grid' : null"
:gridName="gridNameTree"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="9">
<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
>
<div class="d-flex align-center">
<v-select
v-model="tagId"
:items="tagIdList"
item-text="tagNm"
item-value="tagId"
solo
append-icon="mdi-chevron-down"
class="v-select__custom"
outlined
hide-details
></v-select>
<v-col :cols="1"> </v-col>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</div>
</div>
<div style="height:calc(100% - 76px)" class="px-5">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
:editorGrid="true"
@updateDataInfo="evtUpdateDataInfo"
/>
</div>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global.js';
import Utility from '~/plugins/utility';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import Datepicker from '~/components/common/Datepicker';
import Grid from '~/components/common/Grid';
import Buttons from '~/components/common/button/Buttons';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
let myTitle;
//const myPrgmId = "PRG0017";
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,
Datepicker,
Grid,
Buttons,
BtnExcelDownload,
},
data() {
return {
myPrgmId: myPrgmId,
createdFlag: false,
roiGrpCode: '',
roiGrpCodeList: [],
mttCd: '',
mttCdList: [],
blocId: '',
blocMstrList: [],
selectedRoiId: null,
tagId: '',
tagIdList: [],
timeChkValue: false,
treeExpandAll: true,
loadTree: false,
gridNameTree: 'treeGrid',
loadGrid: false,
gridName: 'rowGrid',
searchFlag: false,
selectedData: null,
};
},
computed: {
...mapState({
isDarkMode: state => state.isDarkMode,
pageData: state => state.pageData[myPrgmId],
}),
chkFromDt() {
// console.log("this", this.pageData)
return this.pageData.fromDt;
},
},
watch: {
async createdFlag(val) {
if (val === true) {
await this.init();
}
},
async searchFlag(val) {
if (val === true) {
await this.search();
}
},
async chkFromDt() {
await this.searchGrid2();
},
blocId() {
if (this.createdFlag === true) {
this.searchFlag = true;
}
},
mttCd(val) {
if (this.createdFlag === true) {
this.searchFlag = true;
}
},
tagId(val) {
if (this.createdFlag === true) {
for (var i = 0; i < this.tagIdList.length; i++) {
if (this.tagIdList[i]['tagId'] == this.tagId) {
this.selectedRoiId = this.tagIdList[i]['readObjId'];
}
}
this.setRowGridData();
}
},
async roiGrpCode(val) {
var idx = 0;
for (var i = 0; i < this.roiGrpCodeList.length; i++) {
if (this.roiGrpCodeList[i]['commCd'] == this.roiGrpCode) {
idx = i;
break;
}
}
this.mttCdList = await this.postApiReturn({
apiKey: 'selectMtt',
resKey: 'mttData',
sendParam: {
mttTp: this.roiGrpCodeList[idx]['commCd'],
mttGrp: this.roiGrpCodeList[idx]['userDefVal1'],
},
});
if (this.mttCdList.length > 0) {
this.mttCd = this.mttCdList[0]['mttCd'];
}
},
async timeChkValue(val) {
await this.searchGrid2();
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
async created() {
this.blocMstrList = await this.postApiReturn({
apiKey: 'selectBlocMstrCodeList',
resKey: 'blocCodeLists',
sendParam: {},
});
this.blocId = this.blocMstrList[0]['blocId'];
this.roiGrpCodeList = await this.postApiReturn({
apiKey: 'selectCodeList',
resKey: 'codeLists',
sendParam: {
commGrpCd: 'CM_MTTTP',
useFg: '1',
},
});
this.roiGrpCode = this.roiGrpCodeList[0]['commCd'];
this.mttCdList = await this.postApiReturn({
apiKey: 'selectMtt',
resKey: 'mttData',
sendParam: {
mttTp: this.roiGrpCodeList[0]['commCd'],
mttGrp: this.roiGrpCodeList[0]['userDefVal1'],
},
});
this.mttCd = this.mttCdList[0]['mttCd'];
this.createdFlag = true;
},
async mounted() {
// await this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
getCodeList: 'modules/search/getCodeList',
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
async init() {
this.gridInit();
await this.getTreeData();
},
async search() {
await this.getTreeData();
this.searchFlag = false;
},
async searchGrid2() {
await this.setRowGridData();
},
gridInit() {
const treeGridHeight = this.$refs.treeGridParent.offsetHeight - 35;
const gridHeight = this.$refs.gridParent.offsetHeight - 45;
const myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
},
scrollX: false,
};
const myOptions = {};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setGridOption({
gridKey: this.gridNameTree,
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
var columnList = [
{
header: 'TAG 명',
name: 'tagNm',
aling: 'center',
width: 450,
},
{
header: '검침일자',
name: 'readDt',
align: 'center',
formatter({ value }) {
return Utility.setFormatDate(value, 'YYYY-MM-DD');
},
},
{
header: '검침시간',
name: 'readTm',
align: 'center',
},
{
header: '검침값',
name: 'readVal',
align: 'right',
editor: 'text',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '배율(%)',
name: 'mgnf',
align: 'center',
},
{
header: '값(검침값*배율)',
name: 'readValMgnf',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '단위',
name: 'unit',
align: 'center',
},
];
this.setGridColumn({
gridKey: this.gridName,
value: columnList,
});
},
async getTreeData() {
this.loadTree = false;
if (this.blocMstrList.length > 0) {
const res = await this.postApiReturn({
apiKey: 'selectReadPlc',
resKey: 'readPlacereg',
sendParam: {
blocId: this.blocId,
fromObjDt: Utility.setFormatDate(
this.pageData.fromDt,
'YYYY-MM-DD',
),
readObjKind: this.roiGrpCode,
readObjId: this.mttCd,
},
});
if (res.length === 0) {
this.tagId = '';
this.tagIdList = [];
this.selectedRoiId = null;
}
this.setGridColumn({
gridKey: this.gridNameTree,
value: [
{
header: '개소',
name: 'readPlcNm',
},
],
});
const setTreeData = await this.setTree({
treeKey: 'READ_PLC_ID',
value: res,
});
await this.setGridData({
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
this.loadTree = true;
// gridData 초기화하는 부분
if (
this.$store.state.pageData[this.myPrgmId].treeGrid.data === undefined
) {
this.setGridData({
gridKey: this.gridName,
value: [],
});
}
this.$nextTick(() => {
this.$refs[this.gridNameTree + this.myPrgmId].focus({
rowKey: 0,
columnName: 'readPlcNm',
setScroll: true,
});
});
if (this.$refs[this.gridNameTree + this.myPrgmId] != undefined) {
this.$refs[this.gridNameTree + this.myPrgmId].expandAll();
}
}
},
async setTagIdList(readPlcId) {
this.tagIdList = await this.postApiReturn({
apiKey: 'selectTagNmList',
resKey: 'tagNmListData',
// apiKey : 'selectReadPlcTagRel',
// resKey : 'readPlcTagRelData',
sendParam: {
readPlc: readPlcId,
// 'readPlcId':readPlcId,
useFg: '1',
},
});
if (this.tagIdList.length === 0) {
this.tagId = '';
this.selectedRoiId = null;
this.tagIdList.push({
tagId: '',
tagNm: '',
readPlcId: null,
readObjId: null,
reprTagFg: null,
});
} else if (this.selectedRoiId == null) {
for (var i = 0; i < this.tagIdList.length; i++) {
if (this.tagIdList[i]['reprTagFg'] == 1) {
this.tagId = this.tagIdList[i]['tagId'];
this.selectedRoiId = this.tagIdList[i]['readObjId'];
}
}
if (this.tagId === '') {
this.tagId = this.tagIdList[0]['tagId'];
this.selectedRoiId = this.tagIdList[0]['readObjId'];
}
} else {
for (var i = 0; i < this.tagIdList.length; i++) {
if (this.tagIdList[i]['readObjId'] == this.selectedRoiId) {
this.tagId = this.tagIdList[i]['tagId'];
}
}
if (this.tagId === '') {
this.tagId = this.tagIdList[0]['tagId'];
this.selectedRoiId = this.tagIdList[0]['readObjId'];
}
}
},
async setRowGridData() {
this.loadGrid = false;
var res = [];
res = await this.postApiReturn({
apiKey: 'selectAutoRsltMng',
resKey: 'autoReadRsltData',
sendParam: {
blocId: this.blocId,
fromObjDt: Utility.setFormatDate(this.pageData.fromDt, 'YYYY-MM-DD'),
readObjId: this.mttCd,
mttTp: this.roiGrpCode,
readDt: Utility.setFormatDate(this.pageData.fromDt, 'YYYYMMDD'),
readPlc: this.selectedData.readPlcId,
readPlcNm: this.selectedData.readPlcNm,
tmFg: this.timeChkValue === false ? 0 : 1,
tagId: this.tagId,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.loadGrid = true;
},
async getRowData(data) {
this.selectedData = data;
await this.setTagIdList(this.selectedData.readPlcId);
await this.setRowGridData();
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
this.$refs[this.gridName].addRow();
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
this.loadGrid = false;
dataArr = this.$refs[this.gridName].save();
if (dataArr.length > 0) {
const sendParam = {
datas: { dsAutoRsltMng: dataArr },
params: {},
};
await this.postUpdateApi({
apiKey: 'saveAutoRsltMng',
sendParam: sendParam,
});
this.setGridData({
gridKey: this.gridName,
value: [],
});
this.loadGrid = true;
this.searchFlag = true;
} else {
alert('저장할 내용이 없습니다.');
this.loadGrid = true;
}
break;
default:
break;
}
},
evtUpdateDataInfo(data) {
var gridInstance = this.$refs.rowGrid.$el.__vue__.$el.__vue__
.gridInstance;
gridInstance.invoke(
'setValue',
data.rowIdxKey,
'readValMgnf',
(data.value * data.rowData.mgnf) / 100.0,
);
},
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.myPrgmId].expandAll();
else this.$refs['treeGrid' + this.myPrgmId].collapseAll();
},
},
};
const defaultData = {
/* 검색옵션 */
cmCycle: 'CYC_HOUR',
fromDt: Utility.setFormatDate(new Date(), 'YYYY/MM/DD'),
treeGrid: {
data: [],
column: [],
option: {},
},
rowGrid: {
data: [],
column: [],
option: {},
defaultRow: {
readDt: null,
readVal: 0,
regDttm: null,
readTm: null,
rowStat: '',
},
buttonAuth: {
save: true,
},
},
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
function numberFormatter({ value }) {
return Utility.setFormatIntDecimal(Number(value), 2);
}
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,516 @@
<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="4">
<component :is="'SelectSysDiv'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="4">
<component :is="'SelectUseFg'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="4" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="4">
<InputText
:parentPrgmId="myPrgmId"
label="그룹코드"
valueNm="commGrpCd"
/>
</v-col>
<v-col :cols="4">
<InputText
:parentPrgmId="myPrgmId"
label="그룹코드명"
valueNm="commGrpCdNm"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" class="h100">
<v-card class="py-5 h100">
<v-card-title class="d-flex justify-between">
<span class="tit ft-size_20 ft-weight_600">공통그룹코드</span>
<div>
<v-btn
class="v-btn-radius__20 v-btn-bg__white-blue mr-1"
@click="addRow"
>
<v-icon>mdi-plus</v-icon>
<span>추가</span>
</v-btn>
<v-btn
class="v-btn-radius__20 v-btn-bg__white-blue mr-1"
@click="removeRow"
>
<v-icon>mdi-delete-outline</v-icon>
<span>삭제</span>
</v-btn>
<v-btn class="v-btn-radius__20 v-btn-bg__blue" @click="save">
<v-icon>mdi-content-save</v-icon>
<span>저장</span>
</v-btn>
</div>
</v-card-title>
<v-card-actions>
<div ref="gridParent" class="h100 w100">
<component
ref="myGrid"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</v-card-actions>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<v-card class="py-5">
<v-card-title>
<span class="tit ft-size_20 ft-weight_600">설비그룹 상세</span>
</v-card-title>
<v-card-actions class="flex-column">
<v-tabs v-model="tab">
<v-tab v-for="item in items" :key="item.id">
{{ item.name }}
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab" style="height: calc(100% - 65px);">
<v-tab-item v-for="item in items" :key="item.id">
<GrpinfoTab
v-if="item.id == 'grpInfoTab'"
:parentPrgmId="myPrgmId"
/>
<CommCdTab
v-if="item.id == 'commCdTab'"
:parentPrgmId="myPrgmId"
/>
</v-tab-item>
</v-tabs-items>
</v-card-actions>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import SelectSysDiv from '@/components/common/select/SelectSysDiv';
import SelectUseFg from '@/components/common/select/SelectUseFg';
import InputText from '@/components/common/input/InputText';
import GrpinfoTab from '@/components/pages/comm/GrpCdInfoTab';
import CommCdTab from '@/components/pages/comm/CommCdTab';
import Grid from '~/components/common/Grid';
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: {
BtnSearch,
SelectSysDiv,
SelectUseFg,
InputText,
GrpinfoTab,
CommCdTab,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
items: [
{ name: '그룹코드정보', id: 'grpInfoTab' },
{ name: '공통코드', id: 'commCdTab' },
],
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkSysDivCd() {
// 시스템구분 선택 감지
return this.pageData.sysDivCd;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
selectedCommCdData() {
return this.pageData.selectedCommCdData;
},
modifySysDivCd() {
return this.pageData.modifySysDivCd;
},
modifyUseFg() {
return this.pageData.modifyUseFg;
},
modifyCommGrpCd() {
return this.pageData.modifyCommGrpCd;
},
modifyCommGrpCdNm() {
return this.pageData.modifyCommGrpCdNm;
},
modifyRmrk() {
return this.pageData.rmrk;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkSysDivCd() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
modifyCommGrpCd(val) {
const isSameData = this.compareData('commGrpCd', val);
if (!isSameData) {
const dt = {
name: 'commGrpCd',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyCommGrpCdNm(val) {
const isSameData = this.compareData('commGrpNm', val);
if (!isSameData) {
const dt = {
name: 'commGrpNm',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifySysDivCd(val) {
const isSameData = this.compareData('sysDiv', val);
if (!isSameData) {
const dt = {
name: 'sysDiv',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyUseFg(val) {
const isSameData = this.compareData('useFg', val);
if (!isSameData) {
const dt = {
name: 'useFg',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyRmrk(val) {
const isSameData = this.compareData('rmrk', val);
if (!isSameData) {
const dt = {
name: 'rmrk',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
bodyHeight: gridHeight,
minBodyHeight: gridHeight,
header: {
height: 28,
},
rowHeight: 29,
minRowHeight: 29,
};
this.setGridOption({
gridKey: this.gridName,
value: myOptions,
});
const _this = this;
const myColumns = [
{
header: '시스템구분',
name: 'sysDiv',
align: 'center',
formatter({ value }) {
const newValue = _this.pageData.sysDivCdList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{ header: '그룹코드', name: 'commGrpCd', align: 'center' },
{ header: '그룹코드명', name: 'commGrpNm' },
{
header: '사용여부',
name: 'useFg',
align: 'center',
formatter({ value }) {
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{ header: '비고', name: 'rmrk', hidden: true },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.getRowGridData();
this.loadGrid = true;
},
async search() {
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
const res = await this.postApiReturn({
apiKey: 'selectCommGrpCd',
resKey: 'commGrpCdData',
sendParm: {
commGrpCd: this.pageData.commGrpCd,
commGrpNm: this.pageData.commGrpCdNm,
sysDivCd: this.pageData.sysDivCd,
useFg: this.pageData.useFg,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.$nextTick(() => {
if (newRes.length > 0) {
this.$refs['myGrid'].focus({
rowKey: 0,
columnName: 'sysDiv',
setScroll: true,
});
} else {
this.detailDataInit();
}
});
},
async getRowData(data) {
this.setPageData({
selectedRowKey: data.rowKey,
modifySysDivCd: data.sysDiv,
modifyUseFg: data.useFg,
modifyCommGrpCdNm: data.commGrpNm,
modifyCommGrpCd: data.commGrpCd,
rmrk: data.rmrk,
selectedCommCdData: data,
});
const res = await this.postApiReturn({
apiKey: 'selectCommCd',
resKey: 'commCdData',
sendParm: {
commGrpCd: data.commGrpCd,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: newRes,
});
},
detailDataInit() {
this.setPageData({
selectedCommCdData: null,
selectedRowKey: null,
modifySysDivCd: 'COMM',
modifyUseFg: '1',
modifyCommGrpCdNm: '',
modifyCommGrpCd: '',
rmrk: '',
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: [],
});
},
compareData(type, newDt) {
if (this.selectedCommCdData[type] == newDt) {
return true;
} else {
return false;
}
},
addRow() {
this.$refs.myGrid.addRow();
},
removeRow() {
this.$refs.myGrid.removeRow();
},
async save() {
const dataArr = this.$refs.myGrid.save();
const sendParam = {
datas: { dsGrpCd: dataArr },
params: {},
};
await this.postUpdateApi({
apiKey: 'saveCommGrpCd',
sendParm: sendParam,
});
await this.search();
},
},
};
const defaultData = {
/* 검색옵션 */
sysDivCd: 'COMM',
sysDivCdList: [],
useFg: '1',
useFgList: [],
commGrpCd: '',
commGrpCdNm: '',
/* 그룹코드정보 탭 옵션 */
// 그롭코드정보 탭에서 사용될 사용여부 model 값 셋팅
modifySysDivCd: 'COMM',
modifyUseFg: '1',
modifyCommGrpCdNm: '',
modifyCommGrpCd: '',
rmrk: '',
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
sysDiv: 'COMM',
commGrpCd: '',
commGrpNm: '',
useFg: '1',
rmrk: '',
rowStat: null,
},
},
rowDetailGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
commCd: '',
commCdNm: '',
commCdAbbrnm: '',
sortSeq: '',
useFg: '1',
userDefVal1: '',
userDefVal2: '',
userDefVal3: '',
rowStat: null,
},
},
// 선택된 그룹코드 상세 데이터
selectedRowKey: null,
selectedCommCdData: null,
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,682 @@
<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>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,992 @@
<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="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'위치 종류'"
dataKey="searchLocKind"
:sendParam="{ commGrpCd: 'EM_LOC_KIND', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'공정 종류'"
dataKey="searchEccKind"
:sendParam="{ commGrpCd: 'EM_ECC_KIND', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<!-- 사업장 -->
<div style="visibility:hidden">
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
/>
</div>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'사용여부'"
dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="6">
<InputText
:parentPrgmId="myPrgmId"
label="공정명"
valueNm="eccNm"
:labelCols="2"
:textCols="9"
:searchOption="true"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" 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>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:detailList="detailList"
:btnActionsFnc="btnActions"
/>
</div>
<div class="px-5" style="height:calc(100% - 76px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
@sendSelectedRowStatInfo="getSelectedRowStatInfo"
:selectedRowDataWatchFlag="true"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<v-card class="pb-5">
<v-card-title class="custom-title-4" style="min-height:76px;"
>공정 상세
</v-card-title>
<div class="px-5" style="height:calc(100% - 76px)">
<v-tabs v-model="tab">
<v-tab
v-for="item in items"
:key="item.id"
:disabled="item.disabledFlag"
>
{{ item.name }}
</v-tab>
</v-tabs>
<v-tabs-items
v-model="tab"
style="height: calc(100% - 65px);"
class="py-6"
>
<v-tab-item v-for="(item, idx) in items" :key="item.id">
<component
v-if="item.id == 'eccBaseInfoTab'"
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
<EccAddInfoTab
v-if="item.id == 'eccAddInfoTab'"
:parentPrgmId="myPrgmId"
:innerTabGridInfo="{ tab, idx }"
/>
<EccIaoTab
v-if="item.id == 'eccIaoTab'"
:parentPrgmId="myPrgmId"
:innerTabGridInfo="{ tab, idx }"
/>
</v-tab-item>
</v-tabs-items>
</div>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import selectCodeList from '@/components/common/select/selectCodeList';
import SelectReadObj from '@/components/common/select/SelectReadObj';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import EccAddInfoTab from '@/components/pages/ems/EccInfo/EccAddInfoTab';
import EccIaoTab from '@/components/pages/ems/EccInfo/EccIaoTab';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
let myTitle;
// const myPrgmId = "PRG0012";
let myPrgmId;
const globalComId = '';
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Buttons,
SelectBlocMstr,
selectCodeList,
SelectReadObj,
InputText,
Form,
EccAddInfoTab,
EccIaoTab,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
items: [
{ name: '공정 정보', id: 'eccBaseInfoTab', disabledFlag: false },
{ name: '공정 추가 정보', id: 'eccAddInfoTab', disabledFlag: false },
{ name: '공정 연결 정보', id: 'eccIaoTab', disabledFlag: false },
],
detailList: myDetail,
loadGrid: false,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocId() {
return this.pageData.blocId;
},
chkLocKind() {
// 시스템구분 선택 감지
return this.pageData.searchLocKind;
},
chkEccKind() {
// 시스템구분 선택 감지
return this.pageData.searchEccKind;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocId() {
this.setPageData({ isFind: true });
},
chkLocKind() {
this.setPageData({ isFind: true });
},
chkEccKind() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
async created() {
//
this.getBlocMstrList({
dataKey: 'blocId',
params: { useFg: '1' },
addAll: false,
});
// 공정 위치 유형 목록 조회
this.getCodeList({
dataKey: 'locKind',
params: { commGrpCd: 'EM_LOC_KIND', useFg: '1' },
addAll: false,
});
// 공정 유형 목록 조회
this.getCodeList({
dataKey: 'eccKind',
params: { commGrpCd: 'EM_ECC_KIND', useFg: '1' },
addAll: false,
});
/////////// 추가 정보 Tab 에서 사용
// 데이터 유형 목록 조회
this.getCodeList({
dataKey: 'addInfoDataKind',
params: { commGrpCd: 'CO_DATA_TYPE', useFg: '1' },
addAll: false,
});
// 추가 정보 목록 조회
this.getAddInfoList({
dataKey: 'addInfo',
params: { addGrpId: 'ECC_INFO', useFg: '1' },
addAll: false,
});
this.getCodeList({
dataKey: 'emMapDiv',
params: { commGrpCd: 'EM_MAP_DIV', useFg: 1 },
addAll: false,
});
this.getCodeList({
dataKey: 'cmInout',
params: { commGrpCd: 'CM_INOUT', useFg: 1 },
addAll: false,
});
let ercList = [];
const res = await this.postApiReturn({
apiKey: 'selectErcInfo',
resKey: 'ercInfoData',
sendParam: {
blocId: this.userInfo.blocId,
},
});
res.forEach(item => {
const it = { text: item.ercNm, value: item.ercId };
ercList.push(it);
});
this.setPageData({ ercNmList: ercList });
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
...mapActions({
getCodeList: 'modules/search/getCodeList',
getBlocMstrList: 'modules/search/getBlocMstrList',
getAddInfoList: 'modules/search/getAddInfoList',
}),
init() {
this.gridInit();
this.setPageData({
blocId: this.userInfo.blocId,
});
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const gridWidth = this.$refs.gridParent.offsetWidth;
const myOptions = {
columnOptions: {
resizable: true,
},
treeColumnOptions: {
name: 'eccNm',
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{ header: '회사 ID', name: 'comId', hidden: true },
{
header: '공정 명',
name: 'eccNm',
width: gridWidth * 0.44,
align: 'left',
},
{
header: '공정 ID',
name: 'eccId',
width: 150,
align: 'center',
hidden: true,
},
{
header: '상위 공정 ID',
name: 'upEccId',
width: 150,
align: 'center',
hidden: true,
},
{
header: '상위 공정 명',
name: 'upEccNm',
width: 150,
align: 'center',
hidden: true,
},
{
header: '위치 유형',
name: 'locKind',
width: gridWidth * 0.18,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.locKindList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '공정 유형',
name: 'eccKind',
width: gridWidth * 0.18,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.eccKindList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '사업장',
name: 'blocId',
width: 100,
align: 'center',
hidden: true,
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.blocIdList.filter(
item => item.blocCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].blocNm;
}
return retVal;
},
},
{
header: '정렬 순서',
name: 'sortSeq',
width: 80,
align: 'center',
hidden: true,
},
{
header: '공정 여부',
name: 'eccFg',
width: 80,
align: 'center',
hidden: true,
formatter({ value }) {
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{
header: '사용 여부',
name: 'useFg',
width: gridWidth * 0.18,
align: 'center',
formatter({ value }) {
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.getRowGridData();
},
async search() {
this.loadGrid = false;
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
let res = [];
if (this.pageData.blocMstrList.length > 0) {
res = await this.postApiReturn({
apiKey: 'selectEccBaseInfo',
resKey: 'eccBaseInfoData',
sendParam: {
comId: globalComId,
blocId: this.pageData.blocId,
locKind: this.pageData.searchLocKind,
eccKind: this.pageData.searchEccKind,
useFg: this.pageData.useFg,
eccNmLike: this.pageData.eccNm,
},
});
} else {
this.setPageData({ isFind: false });
}
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
eccIdNm: item.eccId,
upEccId:
item.upEccId == null || item.upEccId == '' ? 'ROOT' : item.upEccId,
blocId: item.blocId,
eccFg: item.eccFg === '1' ? true : false,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
const setTreeData = await this.setTree({
treeKey: 'ECC_ID',
value: newRes,
});
this.loadGrid = true;
this.setGridData({
gridKey: this.gridName,
value: setTreeData.ROOT || [],
// value: newRes
});
this.$nextTick(() => {
if (res.length > 0) {
this.$refs[this.gridName].focus({
// rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnName: 'eccNm',
setScroll: true,
});
} else {
this.detailDataInit();
}
});
},
async getRowData(data) {
this.setEccAddInfo(data);
this.setEccIao(data);
this.setGridSelectData({
gridKey: 'rowEccIaoGrid',
gridSelect: true,
rowGridSelectKey: '',
rowGridSelectData: Object.assign({}, {}),
});
this.setGridSelectData({
gridKey: this.gridName,
gridSelect: true,
rowGridSelectKey: data.rowKey,
rowGridSelectData: Object.assign({}, data),
});
},
async setEccAddInfo(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
// 검침개소 추가 정보 처리
const res = await this.postApiReturn({
apiKey: 'selectEccAddInfoList',
resKey: 'eccAddInfoData',
sendParam: {
comId: data.comId,
blocId: data.blocId,
eccId: data.eccId,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
comId: item.comId || '',
eccId: item.eccId || '',
addInfoId: item.addInfoId || '',
addInfoDataKind: item.addInfoDataKind || '',
addInfoNumVal: item.addInfoNumVal || '',
addInfoTxtVal: item.addInfoTxtVal || '',
addInfoVal: item.addInfoVal || '',
useFg: item.useFg || '1',
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: newRes,
});
},
async setEccIao(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
// 검침개소 추가 정보 처리
const res = await this.postApiReturn({
apiKey: 'selectEccIao',
resKey: 'eccIaoData',
sendParam: {
comId: data.comId,
eccId: data.eccId,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
comId: item.comId || '',
eccId: item.eccId || '',
objId: item.objId || '',
ercId: item.ercId || '',
objKind: item.objKind || '',
inProdKind: item.inProdKind || '',
// calcFg: item.calcFg || "",
calcFg: item.calcFg === '1' ? true : false,
distRt: item.distRt || '',
blocId: item.blocId || '',
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowEccIaoGrid',
value: newRes,
});
},
detailDataInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: [],
});
},
detailEccIaoInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowEccIaoGrid',
value: [],
});
},
getSelectedRowStatInfo(data) {
if (data) {
var rowStat = data.rowStat;
if (rowStat === 'I') {
this.tab = 0;
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = true;
}
} else if (rowStat === 'U') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === 'D') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === null) {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
}
}
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
this.$refs[this.gridName].addTreeRow();
break;
case 'remove':
this.$refs[this.gridName].removeTreeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
if (dataArr.length > 0) {
var validCheck = true;
dataArr.forEach(item => {
if (item.upEccId == '') item.upEccId = 'ROOT';
if (
item.eccNm == '' ||
item.upEccId == '' ||
item.locKind == ''
) {
validCheck = false;
alert('필수 입력값을 입력해주세요.');
}
});
if (validCheck) {
const sendParam = {
datas: {
dsEccBaseInfo: dataArr.map(item => ({
...item,
blocId: item.blocId,
useFg: item.useFg ? '1' : '0',
eccFg: item.eccFg ? '1' : '0',
sortSeq: parseInt(item.sortSeq),
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveEccBaseInfo',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
},
};
const defaultData = {
/* 검색옵션 */
eccNm: '',
blocId: '',
blocMstrList: [],
blocIdList: [],
searchLocKind: '',
searchLocKindList: [],
searchEccKind: '',
searchEccKindList: [],
locKind: '',
locKindList: [],
eccKind: '',
eccKindList: [],
useFg: '1',
useFgList: [],
ercNm: '',
ercNmList: [],
addInfoDataKind: '',
addInfoDataKindList: [],
addInfo: '',
addInfoList: [],
facInfo: {},
isMulti: false,
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
eccId: '',
eccNm: '',
upEccId: '',
upEccNm: '',
locKind: '',
eccKind: '',
blocId: null,
eccFg: '0',
sortSeq: '0',
useFg: '1',
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
rowGridSelectKey: 0,
rowGridSelectData: null,
},
rowDetailGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
eccId: '',
addInfoId: null,
addInfoDataKind: null,
addInfoNumVal: null,
addInfoTxtVal: null,
addInfoVal: null,
useFg: '1',
rowStat: 'I',
},
buttonAuth: {
remove: false,
save: true,
excel: false,
},
rowGridSelectKey: 0,
rowGridSelectData: null,
},
rowEccIaoGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: globalComId,
eccId: '',
objId: '',
ercId: null,
objKind: null,
inProdKind: null,
calcFg: null,
distRt: null,
blocId: null,
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
rowGridSelectKey: 0,
rowGridSelectData: null,
},
};
const myDetail = [
{
type: 'InputText',
label: '공정 ID',
valueNm: 'eccId',
readonly: true,
cols: 6,
class: 'py-2',
required: false,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '공정 명',
valueNm: 'eccNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
// {
// type: "ReadPlcPop",
// label: "상위 검침개소",
// valueNm: "upEccId",
// disabled: false,
// cols: 6,
// class: "py-2",
// required: true
// },
// {
// type: "InputText",
// valueNm: "upEccNm",
// label: "상위 검침개소명",
// readonly: true,
// cols: 6,
// class: "py-2"
// },
// {
// type: "InputText",
// label: "상위 공정 코드",
// valueNm: "upEccId",
// disabled: false,
// cols: 6,
// class: "py-2",
// required: true
// },
{
type: 'FtnPlcFormPop',
valueNm: 'upEccId',
valueNm2: 'upEccNm',
labelContent: '상위 공정',
disabled: false,
required: true,
cols: 6,
class: 'py-2',
labelCols: 4,
textCols: 7,
disableContent: true,
},
{
type: 'InputText',
valueNm: 'upEccNm',
readonly: true,
cols: 5,
class: 'py-2',
},
{
type: 'SelectBox',
label: '위치 유형',
valueNm: 'locKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'locKindList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'SelectBox',
label: '공정 유형',
valueNm: 'eccKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'eccKindList',
itemText: 'commCdNm',
itemValue: 'commCd',
addNull: true,
},
{
type: 'InputText',
label: '정렬',
valueNm: 'sortSeq',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
// onkeydown : "if(this.value > 100) this.value = 100;if(this.value < 0) this.value = 0;if(this.value == '') this.value = 0;"
},
{
type: 'SelectBox',
label: '사업장',
valueNm: 'blocId',
disabled: false,
cols: 6,
class: 'py-2',
list: 'blocIdList',
itemText: 'blocNm',
itemValue: 'blocId',
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
},
{
type: 'CheckBox',
label: 'ECC 공정 여부',
valueNm: 'eccFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,881 @@
<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="3">
<component :is="'SelectBlocMstr'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3">
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'검침대상'"
/>
</v-col>
<v-col :cols="3"> </v-col>
<v-col :cols="3" class="text-right">
<v-btn :ripple="false" @click="searchInit">초기화</v-btn>
<v-btn :ripple="false" @click="search">조회</v-btn>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="enrgUseViewFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="3">
<v-row align="center" no-gutters>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>전력</strong
>
</div>
</div>
</v-col>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>{{ cumulUsage_elec
}}<span class="body-2"> Kwh</span></strong
>
</div>
</div>
</v-col>
</v-row>
</v-col>
<v-col :cols="3">
<v-row align="center" no-gutters>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>가스</strong
>
</div>
</div>
</v-col>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>{{ cumulUsage_gas
}}<span class="body-2"> Kg</span></strong
>
</div>
</div>
</v-col>
</v-row>
</v-col>
<v-col :cols="3">
<v-row align="center" no-gutters>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>스팀</strong
>
</div>
</div>
</v-col>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>{{ cumulUsage_stem
}}<span class="body-2"> </span></strong
>
</div>
</div>
</v-col>
</v-row>
</v-col>
<v-col :cols="3">
<v-row align="center" no-gutters>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>에어</strong
>
</div>
</div>
</v-col>
<v-col :cols="6">
<div class="v-box " style="width:95%; min-width: 100px">
<div class="text-center" style="width:100%">
<strong class="custom-title-8" style="text-align: center;"
>{{ cumulUsage_air
}}<span class="body-2"> Ton</span></strong
>
</div>
</div>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" :eager="true">
<v-col style="height:100%;" :cols="12">
<v-card class="px-5 py-5">
<div ref="chartParent" id="test2" style="height: 100%;">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="chartName"
ref="chartName"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import { mapState, mapMutations, mapActions } from 'vuex';
import Search from '~/components/common/search';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import SelectEnergy from '@/components/common/select/SelectEnergy';
import Chart from '~/components/common/Chart';
import Utility from '~/plugins/utility';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal],
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: {
SelectBlocMstr,
SelectEnergy,
Chart,
Search,
},
data() {
return {
myPrgmId: myPrgmId,
loadChart: false,
chartName: 'treemapChart',
// 바인딩 (사용량 표시용)
cumulUsage_elec: 0,
cumulUsage_gas: 0,
cumulUsage_stem: 0,
cumulUsage_air: 0,
cumulAmt_elec: 0,
cumulAmt_gas: 0,
cumulAmt_stem: 0,
cumulAmt_air: 0,
currUsage_elec: 0,
currUsage_gas: 0,
currUsage_stem: 0,
currUsage_air: 0,
};
},
computed: {
...mapState({
isDarkMode: state => state.isDarkMode,
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocCd() {
// 사업장 코드
return this.pageData.blocId;
},
chkEnergyCd() {
// 에너지 선택 여부 감지
return this.pageData.energyCd;
},
chkDarkMode() {
return this.isDarkMode;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
this.setPageData({ isFind: true });
},
chkEnergyCd() {
this.setPageData({ isFind: true });
},
chkDarkMode() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
//this.timer= setInterval(this.searchTimer, 10000); //5분 주기마다 갱신
},
mounted() {
this.init();
},
beforeDestroy() {
this.cancelAutoUpdate();
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setChartOption: 'setChartOption',
setChartTitle: 'setChartTitle',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
cancelAutoUpdate() {
clearInterval(this.timer);
},
init() {
this.layoutInit();
this.getChartData();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
const enrgUseViewFilterHeight = this.$refs.enrgUseViewFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px - ${enrgUseViewFilterHeight}px`;
},
// 에너지 계통 실시간 조회
async getChartData() {
// console.log("getChartData 시작");
this.loadChart = false;
let res = [];
// console.log("this.pageData.blocMstrList.length : ", this.pageData.blocMstrList.length);
// console.log("this.pageData.energyList.length : ", this.pageData.energyList.length);
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
res = await this.postApiReturn({
apiKey: 'selectEnrgPlantStatusMonitoringInfo',
//resKey:"enrgUseMonitoringInfoData",
resKey: 'enrgPlantStatusMonitoringInfoTreeData',
// sendParm : sendParams
sendParam: {
readObjId: this.pageData.energyList[this.pageData.energyCd].cd,
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
},
});
}
this.setPageData({ isFind: false });
this.setChartData(res);
this.loadChart = true;
this.loadGrid = true;
},
async setChartData(data) {
let makeData = [];
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st = 0;
let datetime = '';
for (var idx in data) {
datetime = '검침 시간 : ' + data[idx].datetime;
if (data[idx].upEccId == 'ROOT') {
for (var idxSub in data[idx]['childeVo']) {
makeData.push(
this.makeData(null, data[idx]['childeVo'][idxSub]).data,
);
}
} else {
makeData.push(this.makeData(null, data[idx]).data);
}
}
const option = {
// color: ['#5470c6',
// '#91cc75',
// '#fac858',
// '#ee6666',
// '#73c0de',
// '#3ba272',
// '#fc8452',
// '#9a60b4',
// '#ea7ccc'],
tooltip: {
// formatter: function (info) {
// var value = info.value;
// var treePathInfo = info.treePathInfo;
// var treePath = [];
// for (var i = 1; i < treePathInfo.length; i++) {
// treePath.push(treePathInfo[i].name);
// }
// return [
// '<div class="tooltip-title">' +
// echarts.format.encodeHTML(treePath.join('/')) +
// '</div>',
// 'Disk Usage: ' + echarts.format.addCommas(value) + ' KB'
// ].join('');
// }
},
series: [
{
name: '전력',
type: 'treemap',
visibleMin: 300,
label: {
show: true,
formatter: '{b}',
},
upperLabel: {
show: true,
height: 30,
},
itemStyle: {
borderColor: '#fff',
},
levels: [
{
itemStyle: {
borderColor: '#777',
borderWidth: 0,
gapWidth: 1,
},
upperLabel: {
show: false,
},
},
{
itemStyle: {
borderColor: '#555',
borderWidth: 5,
gapWidth: 1,
},
emphasis: {
itemStyle: {
borderColor: '#ddd',
},
},
},
{
colorSaturation: [0.35, 0.5],
itemStyle: {
borderWidth: 5,
gapWidth: 1,
borderColorSaturation: 0.6,
},
},
],
data: makeData,
},
],
};
this.setChartOption({ chartKey: this.chartName, value: option });
this.loadChart = true;
},
async setChartSeriesData(data) {
let makeData = [];
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st = 0;
let datetime = '';
for (var idx in data) {
datetime = '검침 시간 : ' + data[idx].datetime;
if (data[idx].upEccId == 'ROOT') {
for (var idxSub in data[idx]['childeVo']) {
makeData.push(
this.makeData(null, data[idx]['childeVo'][idxSub]).data,
);
}
} else {
makeData.push(this.makeData(null, data[idx]).data);
}
}
const seriesData = {
type: 'sunburst',
data: makeData,
radius: [0, '95%'],
sort: undefined,
emphasis: {
focus: 'ancestor',
},
levels: [
{},
{
r0: '15%',
r: '35%',
itemStyle: {
borderWidth: 2,
},
label: {
rotate: 'tangential',
},
},
{
r0: '35%',
r: '70%',
label: {
align: 'right',
},
},
{
r0: '70%',
r: '73%',
label: {
position: 'outside',
padding: 3,
silent: false,
},
itemStyle: {
borderWidth: 3,
},
},
{
r0: '73%',
r: '75%',
label: {
position: 'outside',
padding: 3,
silent: false,
},
itemStyle: {
borderWidth: 3,
},
},
],
};
this.setChartSeries({ chartKey: this.chartName, value: seriesData });
},
search() {
let urlPath = this.$router.currentRoute.fullPath;
let index = urlPath.indexOf('/ems/base/EnrgPlantStatusMonitoringMngPage');
if (index >= 0) {
this.getChartData();
}
},
searchInit() {
this.pageData.upEccId = 'ROOT';
},
async searchTimer() {
let urlPath = this.$router.currentRoute.fullPath;
let index = urlPath.indexOf('/ems/base/EnrgPlantStatusMonitoringMngPage');
if (index >= 0) {
let res = [];
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
res = await this.postApiReturn({
apiKey: 'selectEnrgUseMonitoringInfo',
//resKey:"enrgUseMonitoringInfoData",
resKey: 'enrgUseMonitoringInfoTreeData',
// sendParm : sendParams
sendParam: {
upReadPlcId: this.pageData.upReadPlcId,
energyCd: this.pageData.energyList[this.pageData.energyCd].cd,
// sh_blocCd:"BL0001"
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
},
});
}
this.setPageData({ isFind: false });
this.setChartSeriesData(res);
this.loadChart = true;
this.loadGrid = true;
}
},
setView(value) {
this.isFind = true;
},
makeData(parentsVo, chlVo) {
let retVal = {};
//console.log("chlVo.has('childeVo') : ", chlVo["childeVo"]);
if (chlVo['childeVo'] != null || chlVo['childeVo'] != undefined) {
// 하위 자료가 있으면
let subSum = 0;
let chartChildren = [];
for (var idx in chlVo['childeVo']) {
let subRet = this.makeData(chlVo, chlVo['childeVo'][idx]);
subSum += subRet.value;
chartChildren.push(subRet.data);
}
if (chlVo.instantVal > subSum) {
//chartChildren.push(this.makeDataOverVal(parentsVo, chlVo, chlVo.instantVal - subSum));
}
// const chartColor = this.getColor();
const chdData = {
value:
chlVo.instantVal == null ||
chlVo.instantVal == 0 ||
chlVo.instantVal < subSum
? subSum
: chlVo.instantVal,
name: chlVo.eccNm,
path: chlVo.eccPath,
children: chartChildren,
};
retVal = {
data: chdData,
value:
chlVo.instantVal == null ||
chlVo.instantVal == 0 ||
chlVo.instantVal < subSum
? subSum
: chlVo.instantVal,
};
} else {
// 하위 자료가 없으면.
// const chartColor = this.getColor();
const chdData = {
value: chlVo.instantVal == null ? 0 : chlVo.instantVal,
name: chlVo.eccNm,
path: chlVo.eccPath,
};
retVal = {
data: chdData,
value: chlVo.instantVal == null ? 0 : chlVo.instantVal,
};
}
return retVal;
},
makeDataOverVal(parentsVo, chlVo, otherVal) {
const chdData = {
name: chlVo.eccNm + '_미검침 사용량',
eccId: chlVo.eccId + '_OTHER',
upEccId: chlVo.upEccId,
value: 1,
itemStyle: {
color: '#FF0000',
curveness: 0.5,
},
tooltip: {
formatter:
chlVo.eccNm +
'_미검침 사용량<br />순시 :' +
Utility.setFormatIntDecimal(otherVal, 2),
},
};
return chdData;
},
getColor() {
let retColor = '';
if (this.pageData.colorInx1st > 4) {
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st += 1;
}
if (this.pageData.colorInx2st > 9) {
this.pageData.colorInx2st = 0;
this.pageData.colorInx1st += 1;
}
if (this.isDarkMode) {
retColor = this.pageData.darkColorSet[this.pageData.colorInx1st][
this.pageData.colorInx2st
];
} else {
retColor = this.pageData.lightColorSet[this.pageData.colorInx1st][
this.pageData.colorInx2st
];
}
this.pageData.colorInx1st += 1;
return retColor;
},
labelGen(value, splitLangth) {
let retVal = '';
let subStrInx = 0;
if (value.length <= splitLangth) {
retVal = value;
} else {
subStrInx = this.sliceByByte(value, splitLangth);
retVal +=
value.substring(0, subStrInx) +
'\n' +
this.labelGen(value.substring(subStrInx + 1), splitLangth);
}
return retVal;
},
labelGen2(value, splitLangth, maxLineLength) {
let retVal = '';
let sumLength = 0;
let subStrInx = 0;
let splitVal = value.split(' ');
for (let idx in splitVal) {
if (splitVal[idx].length >= splitLangth) {
} else {
}
}
return retVal;
},
sliceByByte(str, maxByte) {
let b = 0;
let i = 0;
let c = '';
for (b = i = 0; (c = str.charCodeAt(i)); ) {
b += c >> 7 ? 2 : 1;
if (b > maxByte) {
break;
}
i++;
}
return i;
},
chartDblClick(event) {
//console.log("chartClick : ", event);
if (event.componentType == 'series' && event.data.downPlcCnt > 0) {
this.pageData.upReadPlcId = event.data.readPlcId;
this.pageData.parentsReadPlcId = event.data.upReadPlcId;
}
},
chartClick(evnet) {
//console.log("chartClick : ", evnet);
//console.log(evnet.componentType, evnet.componentIndex, this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
if (evnet.componentType == 'title' && evnet.componentIndex == 1) {
//console.log("여기 오남 : ", this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
this.pageData.upReadPlcId = this.pageData.parentsReadPlcId;
//console.log("여기 오남 2 : ", this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
}
},
},
};
const defaultData = {
/* 검색옵션 */
upReadPlcId: 'ROOT',
parentsReadPlcId: 'ROOT',
energyCd: 'ROI000001',
energyList: [],
blocId: '',
blocMstrList: [],
viewCheck: 'viewAll',
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
colorInx1st: 0,
colorInx2st: 0,
/*chartdata 세팅 */
treemapChart: {
tooltip: {},
series: [
{
name: '전력',
type: 'treemap',
visibleMin: 300,
label: {
show: true,
formatter: '{b}',
},
upperLabel: {
show: true,
height: 30,
},
itemStyle: {
borderColor: '#fff',
},
levels: [
{
itemStyle: {
borderColor: '#777',
borderWidth: 0,
gapWidth: 1,
},
upperLabel: {
show: false,
},
},
{
itemStyle: {
borderColor: '#555',
borderWidth: 5,
gapWidth: 1,
},
emphasis: {
itemStyle: {
borderColor: '#ddd',
},
},
},
{
colorSaturation: [0.35, 0.5],
itemStyle: {
borderWidth: 5,
gapWidth: 1,
borderColorSaturation: 0.6,
},
},
],
data: [],
},
],
},
darkColorSet: [
[
'#01AE6A',
'#04A166',
'#089362',
'#0B865D',
'#0F7959',
'#126C55',
'#165E51',
'#19514D',
'#1D4448',
'#1F3D46',
],
[
'#FFB046',
'#EAA345',
'#D39545',
'#BE8844',
'#A77A44',
'#926D43',
'#7C5F42',
'#665242',
'#4C4141',
'#453D41',
],
[
'#F6637B',
'#E15D75',
'#CC576F',
'#B75269',
'#A24C63',
'#8D465E',
'#784058',
'#633B52',
'#4E354C',
'#433249',
],
[
'#944FE9',
'#894BD8',
'#7E47C7',
'#7344B7',
'#6740A5',
'#5C3C95',
'#513884',
'#463473',
'#3A3162',
'#352F59',
],
[
'#4385E3',
'#407CD3',
'#3D73C2',
'#3A6AB2',
'#3760A2',
'#345792',
'#304E81',
'#2D4571',
'#2A3B61',
'#293758',
],
],
lightColorSet: [
[
'#3CC380',
'#4BC88A',
'#5BCD94',
'#6BD19E',
'#7BD6A9',
'#8ADBB3',
'#99E0BD',
'#A9E5C7',
'#B9E9D1',
'#C9EEDC',
],
[
'#FFB13B',
'#FFB74A',
'#FFBE5B',
'#FFC46A',
'#FFCA7A',
'#FFD089',
'#FFD699',
'#FFDDA9',
'#FFE3B8',
'#FFE9C8',
],
[
'#F98694',
'#F98F9C',
'#FA99A5',
'#FAA3AE',
'#FBADB6',
'#FBB6BF',
'#FCC0C7',
'#FCCAD0',
'#FDD3D8',
'#FDDDE1',
],
[
'#CF74E5',
'#D37FE7',
'#D78AE9',
'#DA95EB',
'#DEA1ED',
'#E2ACEF',
'#E6B7F1',
'#EAC2F4',
'#EECDF6',
'#F2D8F8',
],
[
'#6A9BF4',
'#76A3F5',
'#82ABF6',
'#8EB3F7',
'#9ABBF8',
'#A6C3F8',
'#B1CBF9',
'#BED3FA',
'#C9DBFB',
'#D6E3FC',
],
],
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,949 @@
<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="3">
<!-- 사업장 -->
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'에너지원 유형'"
dataKey="searchErcKind"
:sendParam="{ commGrpCd: 'EM_ERCKIND', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectReadObj'"
:parentPrgmId="myPrgmId"
:label="'검침대상'"
dataKey="searchReadObj"
:sendParam="{ useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'고지 유형'"
dataKey="searchChrgKind"
:sendParam="{ commGrpCd: 'EM_ENGCHAGKIND', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'사용여부'"
dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
label="에너지원명"
valueNm="ercNm"
:textCols="7"
:labelCols="4"
:searchOption="true"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" style="height: calc(100vh - 400px)">
<v-col :cols="5" class="h100">
<v-card class="pb-5">
<v-card-title class="d-flex justify-space-between align-end">
<span class="tit ft-size_20 ft-weight_600">에너지원 정보</span>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:detailList="detailList"
:btnActionsFnc="btnActions"
/>
</v-card-title>
<div class="px-5" style="height:calc(100% - 106px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
@sendSelectedRowStatInfo="getSelectedRowStatInfo"
:selectedRowDataWatchFlag="true"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<v-card class="pb-5">
<v-card-title>에너지원 상세</v-card-title>
<div class="px-5" style="height:calc(100% - 70px)">
<v-tabs v-model="tab">
<v-tab
v-for="item in items"
:key="item.id"
:disabled="item.disabledFlag"
>
{{ item.name }}
</v-tab>
</v-tabs>
<v-tabs-items
v-model="tab"
style="height: calc(100% - 65px);"
class="py-6"
>
<v-tab-item v-for="(item, idx) in items" :key="item.id">
<component
v-if="item.id == 'ercInfoTab'"
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
<ErcChrgInfoTab
v-if="item.id == 'ercChrgInfoTab'"
:parentPrgmId="myPrgmId"
:innerTabGridInfo="{ tab, idx }"
/>
</v-tab-item>
</v-tabs-items>
</div>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import selectCodeList from '@/components/common/select/selectCodeList';
import SelectReadObj from '@/components/common/select/SelectReadObj';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import ErcChrgInfoTab from '@/components/pages/ems/ErcChrgInfo/ErcChrgInfoTab';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import DateUtility from '~/plugins/dateUtility';
let myTitle;
// const myPrgmId = "PRG0010";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Buttons,
SelectBlocMstr,
selectCodeList,
SelectReadObj,
InputText,
Form,
ErcChrgInfoTab,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
items: [
{ name: '에너지원 정보', id: 'ercInfoTab', disabledFlag: false },
{ name: '에너지 요금 정보', id: 'ercChrgInfoTab', disabledFlag: false },
],
detailList: myDetail,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocId() {
return this.pageData.blocId;
},
chkErcKind() {
// 시스템구분 선택 감지
return this.pageData.searchErcKind;
},
chkReadObj() {
return this.pageData.searchReadObj;
},
chkChrgKind() {
return this.pageData.searchChrgKind;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocId() {
this.setPageData({ isFind: true });
},
chkErcKind() {
this.setPageData({ isFind: true });
},
chkReadObj() {
this.setPageData({ isFind: true });
},
chkChrgKind() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
// 측정 Data 구분 목록 조회
this.getCodeList({
dataKey: 'ercKind',
params: { commGrpCd: 'EM_ERCKIND', useFg: '1' },
addAll: false,
});
// 측정 대상 목록 조회
this.getReadObjInfoList({
dataKey: 'readObj',
params: { useFg: '1' },
addAll: false,
});
// 단위 코드 목록 조회
this.getCodeList({
dataKey: 'chrgKind',
params: { commGrpCd: 'EM_ENGCHAGKIND', useFg: '1' },
addAll: false,
});
/////////// 추가 정보 Tab 에서 사용
// 데이터 유형 목록 조회
this.getCodeList({
dataKey: 'addInfoDataKind',
params: { commGrpCd: 'CO_DATA_TYPE', useFg: '1' },
addAll: false,
});
// 추가 정보 목록 조회
this.getAddInfoList({
dataKey: 'addInfo',
params: { addGrpId: 'TAG_INFO', useFg: '1' },
addAll: false,
});
this.search();
},
mounted() {
this.userComId = this.userInfo.comId;
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({
getCodeList: 'modules/search/getCodeList',
getBlocMstrList: 'modules/search/getBlocMstrList',
getReadObjInfoList: 'modules/search/getReadObjInfoList',
getAddInfoList: 'modules/search/getAddInfoList',
}),
init() {
this.gridInit();
var date = new Date();
this.pageData.toDt =
String(date.getFullYear()) +
String(date.getMonth() + 1).padStart(2, '0');
this.pageData.fromDt = DateUtility.addMonth(-11, 'YYYYMM', date);
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{ header: '회사 ID', name: 'comId', hidden: true },
{ header: '에너지원ID', name: 'ercId', width: 120, align: 'center' },
{ header: '에너지원명', name: 'ercNm', align: 'left' },
{
header: '에너지원 유형',
name: 'ercKind',
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.ercKindList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '검침대상',
name: 'readObjId',
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.readObjList.filter(
item => item.readObjId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].readObjNm;
}
return retVal;
},
},
{
header: '검침 개소 ID',
name: 'readPlcId',
width: 80,
align: 'center',
hidden: true,
},
{
header: '고지 유형',
name: 'chrgKind',
width: 80,
align: 'center',
hidden: true,
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.chrgKindList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '기본단가',
name: 'unitPrce',
width: 100,
align: 'right',
hidden: true,
},
{
header: '단가 사용여부',
name: 'prceFg',
width: 100,
align: 'center',
hidden: true,
formatter({ value }) {
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{
header: '피크 전력',
name: 'peakPow',
width: 100,
align: 'right',
hidden: true,
},
{
header: '전력 계약',
name: 'elecContId',
width: 100,
align: 'center',
hidden: true,
},
{
header: '전력 계약',
name: 'elecContNm',
width: 100,
align: 'center',
hidden: true,
},
{
header: '사업장',
name: 'blocId',
width: 100,
align: 'center',
hidden: true,
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.blocMstrList.filter(
item => item.blocId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].blocNm;
}
return retVal;
},
},
{
header: '사용 여부',
name: 'useFg',
width: 95,
align: 'center',
formatter({ value }) {
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.getRowGridData();
},
async search() {
this.loadGrid = false;
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
this.loadGrid = true;
},
async getRowGridData() {
let res = [];
if (this.pageData.blocMstrList.length > 0) {
res = await this.postApiReturn({
apiKey: 'selectErcInfo',
resKey: 'ercInfoData',
sendParam: {
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
ercKind: this.pageData.searchErcKind,
readObjId: this.pageData.searchReadObj,
chrgKind: this.pageData.searchChrgKind,
useFg: this.pageData.useFg,
ercNmLike: this.pageData.ercNm,
},
});
} else {
this.setPageData({ isFind: false });
}
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
blocId: item.blocId,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
prceFg: item.prceFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
this.loadGrid = true;
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.$nextTick(() => {
if (newRes.length > 0) {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnName: 'ercId',
setScroll: true,
});
} else {
this.detailDataInit();
}
});
},
async getRowData(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
const res = await this.postApiReturn({
apiKey: 'selectEnrgChrgPrcInfo',
resKey: 'enrgChrgInfoData',
sendParam: {
comId: data.comId,
blocId: data.blocId,
ercId: data.ercId,
startDt: this.pageData.fromDt,
endDt: this.pageData.toDt,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
comId: item.comId || '',
blocId: item.blocId || '',
ercId: item.ercId || '',
objMm: item.objMm || '',
objYm: item.objYm || '',
strtDt: item.strtDt || '',
endDt: item.endDt || '',
notiChrg: item.notiChrg || '',
baseChrg: item.baseChrg || '',
rmrk: item.rmrk || '',
useQty: item.useQty || '',
unitPrce: item.unitPrce || '',
corrCoff: item.corrCoff || '',
heatCoff: item.heatCoff || '',
peakPow: item.peakPow || '',
elecContId: item.elecContId || '',
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: newRes,
});
},
detailDataInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: [],
});
},
getSelectedRowStatInfo(data) {
if (data) {
var rowStat = data.rowStat;
if (rowStat === 'I') {
this.tab = 0;
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = true;
}
} else if (rowStat === 'U') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === 'D') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === null) {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
}
}
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
const defaultRow = {
ercId: '',
ercNm: '',
ercKind: this.pageData.ercKind,
readObjId: this.pageData.readObj,
chrgKind: this.pageData.chrgKind,
unitPrce: 0,
peakPow: '',
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
elecContId: '',
elecContNm: '',
readPlcId: '',
readPlcNm: '',
prceFg: '1',
useFg: '1',
};
this.$refs[this.gridName].addRow(defaultRow);
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
var validCheck = true;
if (dataArr.length > 0) {
dataArr.filter(item => {
if (item.rowStat === 'I') {
if (item.ercNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
} else if (item.rowStat === 'U') {
if (item.ercNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
}
});
if (validCheck) {
const sendParam = {
datas: {
dsErcInfo: dataArr.map(item => ({
...item,
blocId: item.blocId,
useFg: item.useFg ? '1' : '0',
prceFg: item.prceFg ? '1' : '0',
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveErcInfo',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
},
};
const defaultData = {
/* 검색옵션 */
ercNm: '',
blocId: '',
blocMstrList: [],
searchErcKind: '',
searchErcKindList: [],
searchReadObj: '',
searchReadObjList: [],
searchChrgKind: '',
searchChrgKindList: [],
ercKind: '',
ercKindList: [],
readObj: '',
readObjList: [],
chrgKind: '',
chrgKindList: [],
useFg: '1',
useFgList: [],
addInfoDataKind: '',
addInfoDataKindList: [],
addInfo: '',
addInfoList: [],
searchElecContKind: '',
searchElecContKindList: [],
searchVoltKind: '',
searchVoltKindList: [],
searchOptKind: '',
searchOptKindList: [],
cmCycle: 'CYC_MONTH',
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: 1,
CYC_MONTH: 12,
CYC_DAY: 30,
CYC_HOUR: 0,
},
fromDt: '',
toDt: '',
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
ercId: '',
ercNm: null,
ercKind: '',
readObjId: '',
readPlcId: '',
readPlcNm: '',
chrgKind: '',
unitPrce: null,
prceFg: null,
peakPow: null,
elecContId: '',
elecContNm: '',
blocId: null,
useFg: '1',
rowStat: 'I',
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
rowDetailGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
ercId: '',
objMm: '',
blocId: '',
startDt: null,
endDt: null,
notiChrg: null,
baseChrg: null,
rmrk: null,
useQty: null,
unitPrce: null,
corrCoff: null,
heatCoff: null,
peakPow: null,
elecContId: '',
rowStat: null,
},
buttonAuth: {
remove: true,
save: true,
},
},
rowGridChart: Utility.defaultChartOption({
data: ['기본요금', '고지요금'],
selectedMode: true,
selected: {
기본요금: true,
고지요금: true,
},
}),
};
const myDetail = [
{
type: 'InputText',
label: '에너지원 ID',
valueNm: 'ercId',
readonly: true,
cols: 6,
class: 'py-2',
required: false,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '에너지원 명',
valueNm: 'ercNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'SelectBox',
label: '에너지원 유형',
valueNm: 'ercKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'ercKindList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'SelectBox',
label: '검침대상',
valueNm: 'readObjId',
disabled: false,
cols: 6,
class: 'py-2',
list: 'readObjList',
itemText: 'readObjNm',
itemValue: 'readObjId',
required: true,
},
{
type: 'SelectBox',
label: '고지 유형',
valueNm: 'chrgKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'chrgKindList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'InputText',
label: '기본단가',
valueNm: 'unitPrce',
disabled: false,
cols: 6,
class: 'py-2',
},
{
type: 'InputText',
label: '피크 전력',
valueNm: 'peakPow',
disabled: false,
cols: 6,
class: 'py-2',
},
{
type: 'SelectBox',
label: '사업장',
valueNm: 'blocId',
disabled: false,
cols: 6,
class: 'py-2',
list: 'blocMstrList',
itemText: 'blocNm',
itemValue: 'blocId',
required: true,
},
{
type: 'ElecPowChrgPop',
label: '전력 계약',
valueNm: 'elecContId',
disabled: false,
cols: 6,
class: 'py-2',
},
{
type: 'InputText',
valueNm: 'elecContNm',
readonly: true,
cols: 5,
class: 'py-2',
},
{
type: 'ReadPlcPop',
label: '검침개소',
valueNm: 'readPlcId',
disabled: false,
cols: 6,
class: 'py-2',
},
{
type: 'InputText',
valueNm: 'readPlcNm',
readonly: true,
cols: 5,
class: 'py-2',
},
{
type: 'CheckBox',
label: '단가사용 여부',
valueNm: 'prceFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,834 @@
<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="3">
<component :is="'SelectBlocMstr'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3">
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'검침대상'"
/>
</v-col>
<v-col :cols="3"> </v-col>
<v-col :cols="3" class="text-right">
<v-btn :ripple="false" @click="searchInit">처음으로</v-btn>
<v-btn :ripple="false" @click="search">조회</v-btn>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" :eager="true">
<v-col style="height:100%;">
<v-card class="px-5 py-5">
<div ref="chartParent" id="test2" style="height: 100%;">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="chartName"
ref="treeGridChart"
@dblclick="chartDblClick"
@click="chartClick"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import { mapState, mapMutations, mapActions } from 'vuex';
import Search from '~/components/common/search';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import SelectEnergy from '@/components/common/select/SelectEnergy';
import Chart from '~/components/common/Chart';
import Utility from '~/plugins/utility';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal],
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: {
SelectBlocMstr,
SelectEnergy,
Chart,
Search,
},
data() {
return {
myPrgmId: myPrgmId,
loadChart: false,
chartName: 'sankyChart',
};
},
computed: {
...mapState({
isDarkMode: state => state.isDarkMode,
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocCd() {
// 사업장 코드
return this.pageData.blocId;
},
chkEnergyCd() {
// 에너지 선택 여부 감지
return this.pageData.energyCd;
},
chkUpReadPlcId() {
return this.pageData.upReadPlcId;
},
chkDarkMode() {
return this.isDarkMode;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
this.setPageData({ isFind: true });
},
chkEnergyCd() {
this.setPageData({ isFind: true });
},
chkUpReadPlcId() {
this.setPageData({ isFind: true });
},
chkDarkMode() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
this.timer = setInterval(this.searchTimer, 10000); // 10초 주기마다 갱신
},
mounted() {
this.init();
},
beforeDestroy() {
this.cancelAutoUpdate();
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setChartOption: 'setChartOption',
setChartTitle: 'setChartTitle',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
cancelAutoUpdate() {
clearInterval(this.timer);
},
init() {
this.layoutInit();
this.getChartData();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
// 에너지 계통 실시간 조회
async getChartData() {
this.loadChart = false;
let res = [];
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
res = await this.postApiReturn({
apiKey: 'selectEnrgSystemMonitoringInfo',
//resKey:"enrgSystemMonitoringInfoData",
resKey: 'enrgSystemMonitoringInfoTreeData',
// sendParm : sendParams
sendParam: {
upReadPlcId: this.pageData.upReadPlcId,
energyCd: this.pageData.energyList[this.pageData.energyCd].cd,
// sh_blocCd:"BL0001"
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
},
});
}
this.setPageData({ isFind: false });
this.setChartData(res);
this.loadChart = true;
this.loadGrid = true;
},
async setChartData(data) {
let makeData = [];
let makeLinks = [];
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st = 0;
let datetime = '';
for (var idx in data) {
datetime = '검침 시간 : ' + data[0].datetime;
if (data[idx].mapUpReadPlcId == 'ROOT') {
for (var idxSub in data[idx]['childeVo']) {
this.makeDataAndLinks(
null,
data[idx]['childeVo'][idxSub],
makeData,
makeLinks,
);
}
} else {
this.makeDataAndLinks(null, data[idx], makeData, makeLinks);
}
}
const title = [
{
text: datetime,
left: '3%',
bottom: '10',
textStyle: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
},
},
{
text: ' < ',
left: '10',
top: 'center',
textStyle: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
},
triggerEvent: true,
},
];
const option = {
title: title,
backgroundColor: '#FFFFFF',
series: [
{
type: 'sankey',
left: 50.0,
top: 20.0,
right: 50.0,
bottom: 25.0,
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: option });
this.loadChart = true;
},
async setChartSeriesData(data) {
let makeData = [];
let makeLinks = [];
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st = 0;
let datetime = '';
for (var idx in data) {
datetime = '검침 시간 : ' + data[0].datetime;
if (data[idx].upReadPlcId == 'ROOT') {
for (var idxSub in data[idx]['childeVo']) {
this.makeDataAndLinks(
null,
data[idx]['childeVo'][idxSub],
makeData,
makeLinks,
);
}
} else {
this.makeDataAndLinks(null, data[idx], makeData, makeLinks);
}
}
const title = [
{
text: datetime,
left: '3%',
bottom: '10',
textStyle: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
},
},
{
text: ' < ',
left: '10',
top: 'center',
textStyle: {
color: this.isDarkMode
? 'rgba(250,250,250,0.7)'
: 'rgba(0,0,0,0.7)',
},
triggerEvent: true,
},
];
const seriesData = [
{
type: 'sankey',
left: 50.0,
top: 20.0,
right: 50.0,
bottom: 25.0,
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,
},
},
];
this.setChartSeries({ chartKey: this.chartName, value: seriesData });
this.setChartTitle({ chartKey: this.chartName, value: title });
},
search() {
let urlPath = this.$router.currentRoute.fullPath;
let index = urlPath.indexOf('/ems/base/EnrgSystemMonitoringMngPage');
if (index >= 0) {
this.getChartData();
}
},
searchInit() {
this.pageData.upReadPlcId = 'ROOT';
},
async searchTimer() {
let urlPath = this.$router.currentRoute.fullPath;
let index = urlPath.indexOf('/ems/base/EnrgSystemMonitoringMngPage');
if (index >= 0) {
let res = [];
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
res = await this.postApiReturn({
apiKey: 'selectEnrgSystemMonitoringInfo',
//resKey:"enrgSystemMonitoringInfoData",
resKey: 'enrgSystemMonitoringInfoTreeData',
// sendParm : sendParams
sendParam: {
upReadPlcId: this.pageData.upReadPlcId,
energyCd: this.pageData.energyList[this.pageData.energyCd].cd,
// sh_blocCd:"BL0001"
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
},
});
}
this.setPageData({ isFind: false });
this.setChartSeriesData(res);
this.loadChart = true;
this.loadGrid = true;
}
},
setView(value) {
this.isFind = true;
},
makeDataAndLinks(parentsVo, chlVo, data, link) {
let retVal = 0;
//console.log("chlVo.has('childeVo') : ", chlVo["childeVo"]);
if (chlVo['childeVo'] != null || chlVo['childeVo'] != undefined) {
// 하위 자료가 있으면
let subSum = 0;
for (var idx in chlVo['childeVo']) {
let subRet = this.makeDataAndLinks(
chlVo,
chlVo['childeVo'][idx],
data,
link,
);
subSum += subRet;
}
if (chlVo.instantVal > subSum) {
//this.makeDataAndLinksOverVal(parentsVo, chlVo, data, link, chlVo.instantVal - subSum);
}
if (chlVo.instantVal != null && chlVo.instantVal > 0) {
retVal = chlVo.instantVal;
}
const chartColor = this.getColor();
data.push({
name: chlVo.readPlcNm + '(' + chlVo.readPlcId + ')',
readPlcId: chlVo.readPlcId,
upReadPlcId: chlVo.upReadPlcId,
downPlcCnt: chlVo.downPlcCnt,
itemStyle: {
color: chartColor,
borderColor: chartColor,
},
label: {
show: true,
formatter:
chlVo.readPlcNm +
'\n순시 :' +
Utility.setFormatIntDecimal(chlVo.instantVal, 2) +
'\n적산 :' +
Utility.setFormatIntDecimal(chlVo.addupVal, 2),
rich: this.pageData.richData,
},
tooltip: {
formatter:
chlVo.readPlcNm +
'<br />순시 :' +
Utility.setFormatIntDecimal(chlVo.instantVal, 2) +
'<br />적산 :' +
Utility.setFormatIntDecimal(chlVo.addupVal, 2),
// formatter: [
// '{title|{b}}{titlebg|}',
// ' {typeHead|순시 : }{value|' + Utility.setFormatIntDecimal(chlVo.instantVal,2) + '}',
// ' {typeHead|적산 : }{value|' + Utility.setFormatIntDecimal(chlVo.addupVal,2) + '}',
// ].join('\n'),
// backgroundColor: '#eee',
// borderColor: '#777',
// borderWidth: 1,
// borderRadius: 4,
// rich: this.pageData.richData
},
});
if (parentsVo != null) {
console.debug('parentsVo : ', parentsVo);
console.debug('parentsVo.readPlcNm : ', parentsVo.readPlcNm);
link.push({
source: parentsVo.readPlcNm + '(' + parentsVo.readPlcId + ')',
target: chlVo.readPlcNm + '(' + chlVo.readPlcId + ')',
value: chlVo.instantVal,
});
}
} else {
// 하위 자료가 없으면.
let labelFormatter = '';
let labelPosition = 'left';
if (chlVo.maxLvl < 3 || chlVo.maxLvl > chlVo.lvl) {
labelFormatter =
chlVo.readPlcNm +
'\n순시 :' +
Utility.setFormatIntDecimal(chlVo.instantVal, 2) +
'\n적산 :' +
Utility.setFormatIntDecimal(chlVo.addupVal, 2);
} else {
labelFormatter = chlVo.readPlcNm;
}
if (chlVo.maxLvl > chlVo.lvl) {
labelPosition = 'right';
}
const chartColor = this.getColor();
data.push({
name: chlVo.readPlcNm + '(' + chlVo.readPlcId + ')',
readPlcId: chlVo.readPlcId,
upReadPlcId: chlVo.upReadPlcId,
downPlcCnt: chlVo.downPlcCnt,
itemStyle: {
color: chartColor,
borderColor: chartColor,
},
label: {
show: true,
formatter: labelFormatter,
position: labelPosition,
},
tooltip: {
formatter:
chlVo.readPlcNm +
'<br />순시 :' +
Utility.setFormatIntDecimal(chlVo.instantVal, 2) +
'<br />적산 :' +
Utility.setFormatIntDecimal(chlVo.addupVal, 2),
// formatter: [
// '{title|{b}}{titlebg|}',
// ' {typeHead|순시 : }{value|' + Utility.setFormatIntDecimal(chlVo.instantVal,2) + '}',
// ' {typeHead|적산 : }{value|' + Utility.setFormatIntDecimal(chlVo.addupVal,2) + '}',
// ].join('\n'),
// backgroundColor: '#eee',
// borderColor: '#777',
// borderWidth: 1,
// borderRadius: 4,
// rich: this.pageData.richData
},
});
if (parentsVo != null) {
console.debug('parentsVo : ', parentsVo);
console.debug('parentsVo.readPlcNm : ', parentsVo.readPlcNm);
link.push({
source: parentsVo.readPlcNm + '(' + parentsVo.readPlcId + ')',
target: chlVo.readPlcNm + '(' + chlVo.readPlcId + ')',
value: chlVo.instantVal == null ? 0 : chlVo.instantVal,
});
}
retVal = chlVo.instantVal == null ? 0 : chlVo.instantVal;
if (retVal < 0) {
retVal = 0;
}
}
// if(parentsVo == null){
// }else{
// }
return retVal;
},
makeDataAndLinksOverVal(parentsVo, chlVo, data, link, otherVal) {
//console.log("makeDataAndLinksOverVal : ", chlVo, data, link, otherVal);
let labelFormatter = '';
let labelPosition = 'left';
if (chlVo.maxLvl < 3 || chlVo.maxLvl > chlVo.lvl + 1) {
labelFormatter =
chlVo.readPlcNm +
'_미검침 사용량\n순시 :' +
Utility.setFormatIntDecimal(otherVal, 2);
} else {
labelFormatter = chlVo.readPlcNm + '_미검침 사용량';
}
if (chlVo.maxLvl > chlVo.lvl + 1) {
labelPosition = 'right';
}
// const chartColor = this.getColor();
data.push({
name: chlVo.readPlcNm + '_미검침 사용량(' + chlVo.readPlcId + '_OTHER)',
readPlcId: chlVo.readPlcId + '_OTHER',
upReadPlcId: chlVo.upReadPlcId,
downPlcCnt: 0,
itemStyle: {
color: '#FF0000',
borderColor: '#FF0000',
},
label: {
show: true,
formatter: labelFormatter,
position: labelPosition,
},
tooltip: {
formatter:
chlVo.readPlcNm +
'_미검침 사용량<br />순시 :' +
Utility.setFormatIntDecimal(otherVal, 2),
},
});
link.push({
source: chlVo.readPlcNm + '(' + chlVo.readPlcId + ')',
target:
chlVo.readPlcNm + '_미검침 사용량(' + chlVo.readPlcId + '_OTHER)',
value: otherVal,
lineStyle: {
color: '#FF0000',
},
});
},
getColor() {
let retColor = '';
if (this.pageData.colorInx1st > 4) {
this.pageData.colorInx1st = 0;
this.pageData.colorInx2st += 1;
}
if (this.pageData.colorInx2st > 9) {
this.pageData.colorInx2st = 0;
this.pageData.colorInx1st += 1;
}
if (this.isDarkMode) {
retColor = this.pageData.darkColorSet[this.pageData.colorInx1st][
this.pageData.colorInx2st
];
} else {
retColor = this.pageData.lightColorSet[this.pageData.colorInx1st][
this.pageData.colorInx2st
];
}
this.pageData.colorInx1st += 1;
return retColor;
},
chartDblClick(event) {
// console.log("chartDblClick : ", event);
if (event.componentType == 'series' && event.data.downPlcCnt > 0) {
this.pageData.upReadPlcId = event.data.readPlcId;
this.pageData.parentsReadPlcId = event.data.upReadPlcId;
}
},
chartClick(evnet) {
// console.log("chartClick : ", evnet);
//console.log(evnet.componentType, evnet.componentIndex, this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
if (evnet.componentType == 'title' && evnet.componentIndex == 1) {
// console.log("여기 오남 : ", this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
this.pageData.upReadPlcId = this.pageData.parentsReadPlcId;
// console.log("여기 오남 2 : ", this.pageData.upReadPlcId, this.pageData.parentsReadPlcId);
}
},
},
};
const defaultData = {
/* 검색옵션 */
upReadPlcId: 'ROOT',
parentsReadPlcId: 'RPC000001',
energyCd: 'ROI000001',
energyList: [],
blocId: '',
blocMstrList: [],
viewCheck: 'viewAll',
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
colorInx1st: 0,
colorInx2st: 0,
/*chartdata 세팅 */
sankyChart: {
tooltip: {
trigger: 'axis',
confine: true,
axisPointer: {
type: 'shadow',
},
},
grid: {
left: '0',
right: '0',
top: '0',
},
legend: null,
series: [],
title: {},
backgroundColor: '',
},
richData: {
title: {
color: '#eee',
align: 'center',
},
titleBg: {
backgroundColor: '#999',
width: '100%',
align: 'right',
height: 25,
borderRadius: [4, 4, 0, 0],
},
typeHead: {
color: '#333',
height: 24,
width: 40,
align: 'left',
},
value: {
color: '#333',
width: 70,
padding: [0, 10, 0, 10],
align: 'right',
},
},
darkColorSet: [
[
'#01AE6A',
'#04A166',
'#089362',
'#0B865D',
'#0F7959',
'#126C55',
'#165E51',
'#19514D',
'#1D4448',
'#1F3D46',
],
[
'#FFB046',
'#EAA345',
'#D39545',
'#BE8844',
'#A77A44',
'#926D43',
'#7C5F42',
'#665242',
'#4C4141',
'#453D41',
],
[
'#F6637B',
'#E15D75',
'#CC576F',
'#B75269',
'#A24C63',
'#8D465E',
'#784058',
'#633B52',
'#4E354C',
'#433249',
],
[
'#944FE9',
'#894BD8',
'#7E47C7',
'#7344B7',
'#6740A5',
'#5C3C95',
'#513884',
'#463473',
'#3A3162',
'#352F59',
],
[
'#4385E3',
'#407CD3',
'#3D73C2',
'#3A6AB2',
'#3760A2',
'#345792',
'#304E81',
'#2D4571',
'#2A3B61',
'#293758',
],
],
lightColorSet: [
[
'#3CC380',
'#4BC88A',
'#5BCD94',
'#6BD19E',
'#7BD6A9',
'#8ADBB3',
'#99E0BD',
'#A9E5C7',
'#B9E9D1',
'#C9EEDC',
],
[
'#FFB13B',
'#FFB74A',
'#FFBE5B',
'#FFC46A',
'#FFCA7A',
'#FFD089',
'#FFD699',
'#FFDDA9',
'#FFE3B8',
'#FFE9C8',
],
[
'#F98694',
'#F98F9C',
'#FA99A5',
'#FAA3AE',
'#FBADB6',
'#FBB6BF',
'#FCC0C7',
'#FCCAD0',
'#FDD3D8',
'#FDDDE1',
],
[
'#CF74E5',
'#D37FE7',
'#D78AE9',
'#DA95EB',
'#DEA1ED',
'#E2ACEF',
'#E6B7F1',
'#EAC2F4',
'#EECDF6',
'#F2D8F8',
],
[
'#6A9BF4',
'#76A3F5',
'#82ABF6',
'#8EB3F7',
'#9ABBF8',
'#A6C3F8',
'#B1CBF9',
'#BED3FA',
'#C9DBFB',
'#D6E3FC',
],
],
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,819 @@
<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"
/>
</v-col>
<v-col :cols="2">
<!-- 에너지 -->
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'에너지'"
/>
</v-col>
<v-col cols="2">
<!-- 주기 -->
<component :is="'SelectCmCycle'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col cols="4">
<!-- 조회기간 -->
<!-- <component :is="swichDatePicker" :parentPrgmId="myPrgmId" /> -->
<DatePicker
:parentPrgmId="myPrgmId"
label="조회기간"
:labelCols="3"
:textCols="9"
/>
</v-col>
<v-col cols="2" class="d-flex justify-end align-center">
<BtnSearch @click="search" class="mr-1" />
<BtnExcelDownload :parentPrgmId="myPrgmId" :gridName="gridName" />
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="4">
<!-- 공정/설비 -->
<component
:is="'FtnPlcMultiPop'"
:parentPrgmId="myPrgmId"
:labelCols="2"
:textCols="10"
/>
</v-col>
<v-col :cols="2">
<v-radio-group v-model="radioButtonData" row hide-details dense>
<v-col :cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
구분
</label>
</v-col>
<v-radio
label="사용량"
value="0"
on-icon="mdi-record-circle"
:color="isDarkMode ? '#1b74d7' : '#4777d9'"
:ripple="false"
></v-radio>
<v-radio
label="비용"
value="1"
on-icon="mdi-record-circle"
:color="isDarkMode ? '#1b74d7' : '#4777d9'"
:ripple="false"
></v-radio>
</v-radio-group>
</v-col>
<v-col :cols="2">
<v-row class="search-box">
<v-col :cols="6">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
합계
</label>
</v-col>
<v-col :cols="6">
<v-checkbox
v-model="sumChkValue"
:color="isDarkMode ? '#fff' : '#4777d9'"
></v-checkbox>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" style="height: calc(100vh - 230px)">
<v-col>
<v-card>
<div ref="chartParent" style="height: 50%">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="'rowGridChart'"
/>
</div>
<!-- <p class="custom-text-2 font-weight-bold text-right text-color--non-activate" v-if="unit"> 단위 : {{unit}}</p> -->
<v-card-title>
<!-- 차트와 그리드 사이 공백을 위한 공간 -->
</v-card-title>
<div ref="gridParent" class="px-5" style="height: 43%">
<component
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
ref="rowGrid"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import SelectCmCycle from '@/components/common/select/SelectCmCycle';
import SelectDate from '~/components/common/select/SelectDate';
import SelectDateVc from '~/components/common/select/SelectDateVc';
import FtnPlcMultiPop from '~/components/common/modal/FtnPlcMultiPop2';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Utility from '~/plugins/utility';
import Grid from '~/components/common/Grid';
import Chart from '~/components/common/Chart';
import DatePicker from '~/components/common/Datepicker';
import mixinGlobal from '@/mixin/global.js';
let myTitle;
//const myPrgmId = "PRG0022";
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,
SelectCmCycle,
SelectDate,
SelectDateVc,
FtnPlcMultiPop,
BtnSearch,
BtnExcelDownload,
Utility,
Grid,
Chart,
DatePicker,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
loadChart: false,
radioButtonData: '0', // 0: 사용량, 1: 비용
unit: '', // 그리드 우상단 라벨
apiKey: 'selectEnergyUseReadYear',
locKind: 'LOC_COM', // defaultValue
upEccId: 'PLC00001', // defaultValue
qtyLength: [],
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
isDarkMode: state => state.isDarkMode,
}),
swichDatePicker() {
let picker = 'SelectDateVc';
if (
this.pageData.cmCycle == 'CYC_MONTH' ||
this.pageData.cmCycle == 'CYC_YEAR'
) {
picker = 'SelectDate';
}
return picker;
},
sumChkValue: {
get() {
return this.pageData.chkSum;
},
set(value) {
return this.setPageData({ chkSum: value });
},
},
chkIsFind() {
return this.pageData.isFind;
},
myCmCycle() {
return this.pageData.cmCycle;
},
chkBlocCd() {
return this.pageData.blocId;
},
chkEnergyCd() {
return this.pageData.energyCd;
},
chkFacInfo() {
return this.pageData.facInfo;
},
initFlag() {
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
sumChkValue(val) {
this.setPageData({ isFind: true });
},
chkIsFind(val) {
if (val) this.search();
},
myCmCycle: function(val) {},
chkBlocCd() {},
chkEnergyCd() {
this.setUnitLabel();
},
chkFacInfo() {
this.setPageData({ isFind: true });
},
radioButtonData() {
this.setPageData({ isFind: true });
},
initFlag(val) {
if (val) {
this.init();
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartXAxisData: 'setChartXAxisData',
setChartSeries: 'setChartSeries',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
async search() {
this.setLocalStorage();
await this.getFacList();
},
setLocalStorage() {
if (this.pageData.energyCd !== '' && this.pageData.energyCd != null) {
localStorage.setItem(
myPrgmId + 'SelectedEnergyCd',
this.pageData.energyCd,
);
}
if (this.pageData.blocId !== '' && this.pageData.blocId != null) {
localStorage.setItem(myPrgmId + 'SelectedBlocCd', this.pageData.blocId);
}
},
setUnitLabel() {
this.unit = this.pageData.energyList[this.pageData.energyCd].unit
? this.pageData.energyList[this.pageData.energyCd].unit
: 'kwh';
if (this.apiKey.search('Cost') > 0) {
this.unit = '원';
}
},
setApiKey() {
var apiKeyMapper = {
/*
cycValue + radioButtonData
사용량 API : ~0
비용 API : ~1
*/
CYC_YEAR0: 'selectEnergyUseReadYear',
CYC_MONTH0: 'selectEnergyUseReadMonth',
CYC_DAY0: 'selectEnergyUseReadDay',
CYC_HOUR0: 'selectEnergyUseReadHour',
CYC_YEAR1: 'selectEnergyUseReadYearCost',
CYC_MONTH1: 'selectEnergyUseReadMonthCost',
CYC_DAY1: 'selectEnergyUseReadDayCost',
CYC_HOUR1: 'selectEnergyUseReadHourCost',
};
this.apiKey = apiKeyMapper[this.pageData.cmCycle + this.radioButtonData];
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 46;
const myOptions = {
// scrollX: false,
setScroll: true,
columnOptions: {
//frozenCount:2,
minWidth: 100,
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.getFacList();
},
async getFacList() {
this.loadChart = false;
this.pageData.rowGrid.data = [];
var facList = null;
this.setApiKey();
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
this.setUnitLabel();
var apiParameters = {
blocId: this.pageData.blocMstrList[this.chkBlocCd].blocId, //"BL0001",
readObjId: this.pageData.energyList[this.chkEnergyCd].cd,
locKind: this.pageData.facInfo.locKind
? this.pageData.facInfo.locKind
: this.locKind,
upEccId: this.pageData.facInfo.eccId
? this.pageData.facInfo.eccId
: this.eccId,
};
facList = await this.postApiReturn({
apiKey: 'selectEnergyUseReadDnPlc',
resKey: 'energyUseReadDnPlc',
sendParam: apiParameters,
});
const isRange =
this.pageData.defaultRange[this.pageData.cmCycle] === 0
? false
: true;
apiParameters['toObjDt'] = isRange
? this.pageData.toDt
: this.pageData.fromDt;
apiParameters['fromObjDt'] = this.pageData.fromDt;
apiParameters['eccId'] = facList.map(item => item.eccId);
apiParameters['eccNm'] = facList.map(item => item.eccNm);
this.setQtyParameters(apiParameters);
await this.getGridData(apiParameters);
} else {
this.setPageData({ isFind: false });
}
this.setPageData({ isFind: false });
},
setQtyParameters(params) {
switch (this.pageData.cmCycle) {
case 'CYC_YEAR':
var qtyNumber;
var year = parseInt(params['fromObjDt']);
for (var i = 0; i < 10; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
params['qty' + qtyNumber] = (year++).toString();
}
break;
case 'CYC_MONTH':
var qtyNumber;
var date = new Date(
params['fromObjDt'].substr(0, 4),
params['fromObjDt'].substr(4, 2),
);
date.setMonth(date.getMonth() - 1);
for (var i = 0; i < 12; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
params['qtyY' + qtyNumber] = String(date.getFullYear());
params['qtyM' + qtyNumber] = String(date.getMonth() + 1).padStart(
2,
'0',
);
date.setMonth(date.getMonth() + 1);
}
break;
case 'CYC_DAY':
var qtyNumber;
var date = new Date(
params['fromObjDt'].substr(0, 4),
params['fromObjDt'].substr(4, 2),
params['fromObjDt'].substr(6, 2),
);
date.setMonth(date.getMonth() - 1);
for (var i = 0; i < 31; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
params['qty' + qtyNumber] =
String(date.getFullYear()) +
String(date.getMonth() + 1).padStart(2, '0') +
String(date.getDate()).padStart(2, '0');
date.setDate(date.getDate() + 1);
}
break;
case 'CYC_HOUR':
break;
}
},
makeColumnList(params) {
var colNameList = [
{ header: '에너지', name: 'readObjNm', align: 'center', width: '200' },
{ header: '구분', name: 'eccNm', align: 'left', width: '200' },
];
switch (this.pageData.cmCycle) {
case 'CYC_YEAR':
var qtyNumber, qtyStr;
for (var i = 0; i < 10; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
qtyStr = 'qty' + qtyNumber;
if (
parseInt(params[qtyStr]) >= parseInt(params['fromObjDt']) &&
parseInt(params[qtyStr]) <= parseInt(params['toObjDt'])
) {
colNameList.push({
header: params[qtyStr],
name: qtyStr,
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
});
}
}
break;
case 'CYC_MONTH':
var qtyNumber;
var qtyY;
var qtyM;
for (var i = 0; i < 12; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
qtyStr = 'qty' + qtyNumber;
qtyY = 'qtyY' + qtyNumber;
qtyM = 'qtyM' + qtyNumber;
if (
parseInt(params[qtyY] + params[qtyM]) >=
parseInt(params['fromObjDt']) &&
parseInt(params[qtyY] + params[qtyM]) <=
parseInt(params['toObjDt'])
) {
colNameList.push({
header: params[qtyY] + '/' + params[qtyM],
name: qtyStr,
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
});
}
}
break;
case 'CYC_DAY':
var qtyNumber, qtyStr;
for (var i = 0; i < 31; i++) {
qtyNumber = (i + 1).toString().padStart(2, '0');
qtyStr = 'qty' + qtyNumber;
if (
parseInt(params[qtyStr]) >= parseInt(params['fromObjDt']) &&
parseInt(params[qtyStr]) <= parseInt(params['toObjDt'])
) {
colNameList.push({
header:
params[qtyStr].substr(4, 2) +
'/' +
params[qtyStr].substr(6, 2),
name: qtyStr,
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
});
}
}
break;
case 'CYC_HOUR':
var qtyNumber, qtyStr;
for (var i = 0; i < 24; i++) {
qtyNumber = i.toString().padStart(2, '0');
qtyStr = 'qty' + qtyNumber;
colNameList.push({
header: i.toString().padStart(1, '0') + '시',
name: qtyStr,
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
});
}
break;
}
return colNameList;
},
addChkSumRowData(res) {
var chkSumRowData = {};
var columnListMap = {
CYC_YEAR: [
'qty01',
'qty02',
'qty03',
'qty04',
'qty05',
'qty06',
'qty07',
'qty08',
'qty09',
'qty10',
],
CYC_MONTH: [
'qty01',
'qty02',
'qty03',
'qty04',
'qty05',
'qty06',
'qty07',
'qty08',
'qty09',
'qty10',
'qty11',
'qty12',
],
CYC_DAY: [
'qty01',
'qty02',
'qty03',
'qty04',
'qty05',
'qty06',
'qty07',
'qty08',
'qty09',
'qty10',
'qty11',
'qty12',
'qty13',
'qty14',
'qty15',
'qty16',
'qty17',
'qty18',
'qty19',
'qty20',
'qty21',
'qty22',
'qty23',
'qty24',
'qty25',
'qty26',
'qty27',
'qty28',
'qty29',
'qty30',
'qty31',
],
CYC_HOUR: [
'qty00',
'qty01',
'qty02',
'qty03',
'qty04',
'qty05',
'qty06',
'qty07',
'qty08',
'qty09',
'qty10',
'qty11',
'qty12',
'qty13',
'qty14',
'qty15',
'qty16',
'qty17',
'qty18',
'qty19',
'qty20',
'qty21',
'qty22',
'qty23',
],
};
var columnList = columnListMap[this.myCmCycle];
if (this.sumChkValue && res.length && res.length > 0) {
chkSumRowData['eccNm'] = this.pageData.facInfo.eccNm;
chkSumRowData['eccId'] = this.pageData.facInfo.eccId;
chkSumRowData['readObjNm'] = res[0]['readObjNm'];
chkSumRowData['readObjId'] = res[0]['readObjId'];
chkSumRowData['comId'] = res[0]['comId'];
for (var i = 0; i < columnList.length; i++) {
chkSumRowData[columnList[i]] = 0;
}
for (var i = 0; i < res.length; i++) {
for (var j = 0; j < columnList.length; j++) {
var oldValue =
chkSumRowData[columnList[j]] != undefined
? chkSumRowData[columnList[j]]
: 0;
var newValue =
res[i][columnList[j]] != undefined ? res[i][columnList[j]] : 0;
chkSumRowData[columnList[j]] =
Math.round((oldValue + newValue) * 100) / 100;
}
}
// res.unshift(chkSumRowData);
res.push(chkSumRowData);
}
},
async getGridData(params) {
var res = null;
this.loadGrid = false;
let colNameList = await this.makeColumnList(params);
try {
res = await this.postApiReturn({
apiKey: this.apiKey,
resKey: 'energyUseRead',
sendParam: params,
});
} catch (error) {
res = [];
}
// res = await this.postApiReturn({
// apiKey: this.apiKey,
// resKey: "energyUseRead",
// sendParam: params
// });
// if(res.length < 1){
// for(var i=0;i<params.eccNm.length;i++){
// res.push({
// readObjNm : this.pageData.energyList[this.pageData.energyCd].enrgNm,
// eccNm:params.eccNm[i]
// })
// }
// }
this.addChkSumRowData(res);
if (res.length && res.length > 0) {
Object.assign(res[0], {
_attributes: { rowSpan: { readObjNm: res.length } },
});
}
this.setGridColumn({
gridKey: this.gridName,
value: colNameList,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
this.loadGrid = true;
this.setPageData({ isFind: false });
this.setChartData(res);
},
setChartData(data) {
this.$store.state.pageData[this.myPrgmId].rowGridChart.series = [];
// if(!data.length){
// return;
// }
let exceptionColumList = ['에너지', '구분'];
let xAxisData = [];
let seriesData = [];
var keyList = this.pageData[this.gridName].column.filter(el => {
return !exceptionColumList.includes(el.header);
});
xAxisData = keyList.map(el => el.header);
seriesData = data.map(item => ({
name: item.eccNm,
type: 'line',
data: keyList.map(obj => item[obj.name] || 0),
}));
var _this = this;
var chartOption = {
grid: {
top: '3%',
// right: '8%',
},
yAxis: {
type: 'value',
nameLocation: 'middle',
nameGap: 45,
name: _this.unit,
},
xAxis: {
data: xAxisData,
},
series: seriesData,
};
this.setChartOption({ chartKey: 'rowGridChart', value: chartOption });
this.loadChart = true;
},
},
};
const defaultData = {
isFind: false,
blocId: '',
blocMstrList: [],
energyCd: '',
energyList: [],
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: 0,
},
fromDt: '',
toDt: '',
facInfo: {},
chkSum: false,
rowGrid: {
data: [],
option: {},
column: [],
},
modalData: {},
isMulti: false,
rowGridChart: Utility.defaultChartOption(true),
xlsFileInfo: {
rowGrid: {
fileName: null,
sheetName: null,
},
},
};
function numberFormatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
}
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,444 @@
<template>
<div ref="mainDiv" class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="5">
<InputText
:parentPrgmId="myPrgmId"
label="설비종류명"
valueNm="eqpmKindNm"
:searchOption="true"
:textCols="9"
:labelCols="3"
/>
</v-col>
<v-col :cols="7" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" class="h100">
<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>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</div>
<div class="h100 px-5" style="height:calc(100% - 70px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
:preventFocusChangeEventFlag="false"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<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>
<div class="px-5" style="height:calc(100% - 76px)">
<component
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import { resize } from '@/mixin/resize.js';
import mixinGlobal from '@/mixin/global.js';
import BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
let myTitle;
// const myPrgmId = "PRG0013";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Buttons,
selectCodeList,
InputText,
Form,
Grid,
Utility,
SelectBox,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'eqpmKindGrid',
loadGrid: false,
tab: null,
detailList: myDetail,
selectValueList01: [],
selectValue01: null,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkUseFg() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {},
mounted() {
this.gridInit();
// this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({}),
init() {
// this.gridInit();
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const gridWidth = this.$refs.gridParent.offsetWidth;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{
header: '설비종류ID',
name: 'eqpmKindId',
width: gridWidth * 0.5,
align: 'center',
},
{
header: '설비종류명',
name: 'eqpmKindNm',
width: gridWidth * 0.5,
align: 'left',
},
{ header: '등록자NO', name: 'regUserNo', hidden: true },
{ header: '등록일시', name: 'regDttm', hidden: true },
{ header: '수정자NO', name: 'procUserNo', hidden: true },
{ header: '수정일시', name: 'procDttm', hidden: true },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.getRowGridData();
},
async search() {
this.loadGrid = false;
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
const res = await this.postApiReturn({
apiKey: 'selectEqpmKind',
resKey: 'eqpmKindData',
sendParam: {
eqpmKindNm: this.pageData.eqpmKindNm,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.loadGrid = true;
this.$nextTick(() => {
if (newRes.length > 0) {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
setScroll: true,
});
}
});
},
async getRowData(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
var defaultRow = {
eqpmKindId: '',
eqpmKindNm: '',
rowStat: null,
};
this.$refs[this.gridName].addRow(defaultRow);
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
if (dataArr.length > 0) {
var validCheck = true;
dataArr.filter(item => {
if (item.rowStat != 'D') {
// if (confirm('삭제하시겠습니까?')) {
// validCheck = true;
// } else {
// validCheck = false;
// }
// } else {
dataArr.forEach(item => {
if (
// if(item.eqpmGrpId == null || item.eqpmGrpId == ""||
item.eqpmKindNm == '' ||
item.eqpmKindNm == null
) {
validCheck = false;
alert('필수 입력값을 입력해주세요');
} else {
validCheck = true;
}
});
}
});
if (validCheck) {
const sendParam = {
datas: {
dsEqpmKind: dataArr.map(item => ({
...item,
})),
},
params: {},
};
var result = await this.postUpdateApi({
apiKey: 'saveEqpmKind',
sendParam: sendParam,
});
if (result.data.dataset.deleteYn != '') {
alert(result.data.dataset.deleteYn);
} else {
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
},
};
const defaultData = {
/* 검색옵션 */
eqpmKindId: '',
eqpmKindNm: '',
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
eqpmKindGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
eqpmKindId: '',
eqpmKindNm: null,
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
};
const myDetail = [
{
type: 'InputText',
label: '설비종류 ID',
valueNm: 'eqpmKindId',
cols: 6,
class: 'py-2',
required: false,
readonly: true,
placeholder: '시스템 자동입력',
},
{
cols: 6,
},
{
type: 'InputText',
label: '설비종류명',
valueNm: 'eqpmKindNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
{
cols: 6,
},
{
type: 'InputText',
label: '등록자NO',
valueNm: 'regUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
cols: 6,
},
{
type: 'InputText',
label: '등록일시',
valueNm: 'regDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
cols: 6,
},
{
type: 'InputText',
label: '수정자NO',
valueNm: 'procUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
cols: 6,
},
{
type: 'InputText',
label: '수정일시',
valueNm: 'procDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,560 @@
<template>
<div ref="mainDiv" class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'사용여부'"
dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox1"
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비종류'"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
label="설비 그룹 명"
valueNm="eqpmGrpNm"
:searchOption="true"
:textCols="8"
:labelCols="4"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" class="h100">
<v-card class="pb-5">
<v-card-title class="d-flex justify-space-between align-end">
<span class="tit ft-size_20 ft-weight_600">설비 그룹</span>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</v-card-title>
<div class="h100 px-5" style="height:calc(100% - 70px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<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>
<div class="px-5" style="height:calc(100% - 76px)">
<component
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
</div>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
let myTitle;
// const myPrgmId = "PRG0013";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Buttons,
selectCodeList,
InputText,
Form,
Grid,
Utility,
SelectBox,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
detailList: myDetail,
selectValueList01: [],
selectValue01: null,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
loadFlag() {
var init1 = this.pageData.useFgList.length > 0 ? true : false;
return init1;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkUseFg() {
this.setPageData({ isFind: true });
},
loadFlag(val) {
if (val) {
this.gridInit();
}
// await this.gridInit();
},
selectValue01(val) {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {},
mounted() {
this.setSelectValueList01();
// if (this.loadFlag) {
// this.gridInit();
// }
// this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({}),
init() {
// this.gridInit();
},
async setSelectValueList01() {
var res = await this.postApiReturn({
apiKey: 'selectEmsEqpmKindList',
resKey: 'eqpmGrpPysclQtyMngData',
sendParam: {},
});
this.setPageData({
eqpmKindIdList: res,
eqpmKindId: res[0].eqpmKindId,
});
if (res.length > 0) {
this.selectValueList01 = await res.map(item => {
return {
text: item.eqpmKindNm,
value: item.eqpmKindId,
data: {
...item,
},
};
});
this.selectValueList01.unshift({
text: '전체',
value: '',
});
this.selectValue01 = this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 70;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{ header: '회사 ID', name: 'comId', hidden: true },
{
header: '설비 그룹 ID',
name: 'eqpmGrpId',
width: 150,
align: 'left',
},
{
header: '설비 그룹 명',
name: 'eqpmGrpNm',
minwidth: 210,
align: 'left',
},
{
header: '설비종류',
name: 'eqpmKindId',
minWidth: 175,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.eqpmKindIdList.filter(
item => item.eqpmKindId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].eqpmKindNm;
}
return retVal;
},
},
{
header: '사용여부',
name: 'useFg',
width: 100,
align: 'center',
formatter({ value }) {
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{ header: '등록자NO', name: 'regUserNo', hidden: true },
{ header: '등록일시', name: 'regDttm', hidden: true },
{ header: '수정자NO', name: 'procUserNo', hidden: true },
{ header: '수정일시', name: 'procDttm', hidden: true },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.getRowGridData();
},
async search() {
this.loadGrid = false;
// if (this.loadFlag == false) {
// return;
// }
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
const res = await this.postApiReturn({
apiKey: 'selectEqpmGrp',
resKey: 'eqpmGrpData',
sendParam: {
comId: this.userInfo.comCd,
useFg: this.pageData.useFg,
eqpmGrpNmLike: this.pageData.eqpmGrpNm,
eqpmKindId: this.selectValue01,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.loadGrid = true;
this.$nextTick(() => {
if (newRes.length > 0) {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
setScroll: true,
});
}
});
},
async getRowData(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
var defaultRow = {
comId: '',
eqpmGrpId: '',
eqpmGrpNm: null,
eqpmKindId: this.pageData.eqpmKindIdList[0].eqpmKindId,
useFg: '1',
rowStat: null,
};
this.$refs[this.gridName].addRow(defaultRow);
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
if (dataArr.length > 0) {
var validCheck = true;
dataArr.map(item => {
if (item.rowStat != 'D')
for (var i = 0; i < dataArr.length; i++) {
if (
dataArr[i].eqpmGrpNm == null ||
dataArr[i].eqpmGrpNm == ''
) {
validCheck = false;
alert('필수 입력값을 입력해주세요');
break;
} else {
validCheck = true;
break;
}
}
});
if (validCheck) {
const sendParam = {
datas: {
dsEqpmGrp: dataArr.map(item => ({
...item,
useFg: item.useFg == true ? '1' : '0',
})),
},
params: {},
};
var result = await this.postUpdateApi({
apiKey: 'saveEqpmGrp',
sendParam: sendParam,
});
if (result.data.dataset && result.data.dataset.deleteYn != '') {
alert(result.data.dataset.deleteYn);
} else {
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
},
};
const defaultData = {
/* 검색옵션 */
eqpmGrpNm: '',
useFg: '1',
useFgList: [],
eqpmKindIdList: [],
eqpmKindId: '',
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
eqpmGrpId: '',
eqpmGrpNm: null,
eqpmKindId: '',
useFg: '1',
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
};
const myDetail = [
{
type: 'InputText',
label: '설비 그룹 ID',
valueNm: 'eqpmGrpId',
disabled: true,
cols: 6,
class: 'py-2',
required: false,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '설비 그룹 명',
valueNm: 'eqpmGrpNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
},
{
type: 'SelectBox',
label: '설비종류',
valueNm: 'eqpmKindId',
disabled: false,
cols: 6,
class: 'py-2',
list: 'eqpmKindIdList',
itemText: 'eqpmKindNm',
itemValue: 'eqpmKindId',
required: true,
},
{
type: 'InputText',
label: '등록자NO',
valueNm: 'regUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '등록일시',
valueNm: 'regDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정자NO',
valueNm: 'procUserNo',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정일시',
valueNm: 'procDttm',
disabled: true,
cols: 6,
class: 'py-2',
placeholder: '시스템 자동입력',
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,883 @@
<template>
<div ref="mainDiv" class="l-layout">
<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="'설비종류'"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox2"
:propsValue="selectValue02"
:itemList="selectValueList02"
:label="'설비그룹'"
@update:propsValue="selectValue02 = $event"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox3"
:propsValue="selectValue03"
:itemList="selectValueList03"
:label="'가이드지표'"
@update:propsValue="selectValue03 = $event"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="height: 100%">
<!-- <v-card class="py-5"> -->
<v-row style="height: 50%">
<v-col :cols="12" style="height: 100%">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4"
>가이드 정보</v-card-title
>
</div>
<v-row
:cols="12"
class="d-flex align-center justify-space-between pa-3"
>
<!-- 가이드 설비그룹 라인 시작 -->
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'가이드 ID'"
:valueNm="'gdIdxId'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="0"
:textCols="4"
:valueNm="'gdIdxNm'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'설비그룹'"
:valueNm="'eqpmGrpNm'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3"> </v-col>
<!-- 가이드 설비그룹 라인 -->
<!-- 물리량 라인 시작 -->
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'물리량1'"
:valueNm="'pysclQtyCdNm1'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'물리량2'"
:valueNm="'pysclQtyCdNm2'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'물리량3'"
:valueNm="'pysclQtyCdNm3'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'물리량4'"
:valueNm="'pysclQtyCdNm4'"
:readonly="readonlyFg"
/>
</v-col>
<!-- 물리량 라인 -->
<!-- 카테고리 라인 시작 -->
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'카테고리1'"
:valueNm="'ctgr1'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'카테고리2'"
:valueNm="'ctgr2'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'주의기준값'"
:valueNm="'careStndVal'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'경고기준값'"
:valueNm="'warnStndVal'"
:readonly="readonlyFg"
/>
</v-col>
<!-- 카테고리 기준값 라인 -->
<!-- 알람메세지 라인 시작 -->
<v-col :cols="12">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="1"
:textCols="11"
:label="'알람메세지'"
:valueNm="'alrmMsg'"
:readonly="readonlyFg"
/>
</v-col>
<!-- 알람메세지 라인 -->
<!-- 계산코드 라인 시작 -->
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="8"
:label="'계산코드'"
:valueNm="'calcProc'"
:readonly="readonlyFg"
/>
</v-col>
<v-col :cols="3"> </v-col>
<v-col :cols="3"> </v-col>
<v-col :cols="3"> </v-col>
<!-- 계산코드 라인 -->
<!-- 계산설명 라인 시작 -->
<v-col :cols="12">
<InputText
:parentPrgmId="myPrgmId"
:labelCols="1"
:textCols="11"
:label="'계산설명'"
:valueNm="'calcDesc'"
:readonly="readonlyFg"
/>
</v-col>
<!-- 계산설명 라인 -->
</v-row>
</v-card>
</v-col>
</v-row>
<v-row style="height: 50%">
<v-col :cols="6" style="height: 100%">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4 "
>설비상세 리스트</v-card-title
>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</div>
<div class="h100 px-5" style="height:calc(100% - 70px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="6" style="height: 100%">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4"
>설비가이드 기준 정보</v-card-title
>
</div>
<v-row
:cols="12"
class="d-flex align-center justify-space-between pa-3"
>
<!-- 가이드 설비그룹 라인 시작 -->
<v-col :cols="12">
<component
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<!-- </v-card> -->
</v-col>
</v-row>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global.js';
import { resize } from '@/mixin/resize.js';
import BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import SelectBox from '@/components/common/select/SelectBox';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
let myTitle;
// const myPrgmId = "PRG0009";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
async asyncData(context) {
const myState = context.store.state;
// console.log('asyncData',context.store)
// console.log(context.store.$router.currentRoute.fullPath);
myPrgmId = context.route.query.prgmId;
// context.store.commit('pageInit', { prgmId: myPrgmId, value: payload.defaultData });
await context.store.commit('setActiveMenuInfo', myState.menuData[myPrgmId]);
myTitle = await myState.activeMenuInfo.menuNm;
},
meta: {
title: () => {
return myTitle;
},
prgmId: myPrgmId,
closable: true,
},
components: {
BtnSearch,
Buttons,
InputText,
Form,
Grid,
SelectBox,
},
data() {
return {
myPrgmId: myPrgmId,
readonlyFg: true,
initedFlag: false,
gridName: 'rowGrid',
loadGrid: false,
detailList: myDetail,
selectValue01: null,
selectValueList01: [],
selectValue02: null,
selectValueList02: [],
selectValue03: null,
selectValueList03: [],
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
async selectValue01(val) {
this.setPageData({ eqpmKindId: val });
if (this.initedFlag) await this.getEqpmGrp();
// this.setPageData({ isFind: true });
},
async selectValue02(val) {
this.setPageData({ eqpmGrpId: val });
if (this.initedFlag) await this.getEqpmGdIdx();
// this.setPageData({ isFind: true });
},
async selectValue03(val) {
this.setPageData({ eqpmGdIdx: val });
if (this.initedFlag) this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
// 검침 Data 구분 목록 조회
},
async mounted() {
await this.init();
this.initedFlag = true;
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({
getCodeList: 'modules/search/getCodeList',
getBlocMstrList: 'modules/search/getBlocMstrList',
getAddInfoList: 'modules/search/getAddInfoList',
}),
async init() {
await this.getEqpmKind();
await this.getEqpmGrp();
await this.getEqpmGdIdx();
this.gridInit();
},
search() {
this.getGdIdxData();
this.getGridData();
this.setPageData({
isFind: false,
});
},
async getEqpmKind() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmKindCodeList',
resKey: 'eqpmKindCodeLists',
sendParam: {},
});
if (res.length > 0) {
this.selectValueList01 = await res.map(item => {
return {
text: item.eqpmKindNm,
value: item.eqpmKindId,
};
});
this.selectValue01 = this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
this.setPageData({
eqpmKindList: this.selectValueList01,
eqpmKindId: this.selectValue01,
});
},
async getEqpmGrp() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmGrpCodeList',
resKey: 'eqpmGrpCodeLists',
sendParam: { eqpmKindId: this.selectValue01 },
});
if (res.length > 0) {
this.selectValueList02 = await res.map(item => {
return {
text: item.eqpmGrpNm,
value: item.eqpmGrpId,
};
});
this.selectValue02 = this.selectValueList02[0].value;
} else {
this.selectValueList02 = [];
this.selectValue02 = null;
}
this.setPageData({
eqpmGrpList: this.selectValueList02,
eqpmGrpId: this.selectValue02,
});
},
async getEqpmGdIdx() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmGdIdxCodeList',
resKey: 'eqpmGdIdxCodeLists',
sendParam: { eqpmGrpId: this.selectValue02 },
});
if (res.length > 0) {
this.selectValueList03 = await res.map(item => {
return {
text: item.gdIdxId + ': ' + item.gdIdxNm,
value: item.gdIdxId,
};
});
this.selectValue03 = this.selectValueList03[0].value;
} else {
this.selectValueList03 = [];
this.selectValue03 = null;
}
this.setPageData({
eqpmGdIdxList: this.selectValueList03,
eqpmGdIdx: this.selectValue03,
});
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
// { header: '가이드ID', name: 'gdIdxId', align: 'center', hidden: true},
{ header: '설비', name: 'eqpmId', align: 'left' },
{
header: 'origin설비',
name: 'originEqpmId',
align: 'center',
hidden: true,
},
{ header: '설비명', name: 'eqpmNm', align: 'left' },
{ header: '주의기준', name: 'careStndVal', align: 'right' },
{ header: '심각기준', name: 'warnStndVal', align: 'right' },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.search();
},
async getGdIdxData() {
let res = [];
if (this.selectValue01 && this.selectValue02 && this.selectValue03) {
res = await this.postApiReturn({
apiKey: 'selectEqpmGdIdxData',
resKey: 'eqpmGdIdxData',
sendParam: {
eqpmGrpId: this.selectValue02,
gdIdxId: this.selectValue03,
},
});
} else {
if (this.initedFlag) {
alert('조회 조건을 확인해 주세요.');
}
}
this.setGuideInfo(res);
},
setGuideInfo(res) {
if (res.length == 0) {
this.setPageData({
gdIdxId: '',
gdIdxNm: '',
eqpmGrpNm: '',
upTotMeth: '',
unit: '',
pysclQtyCdNm1: '',
pysclQtyCdNm2: '',
pysclQtyCdNm3: '',
pysclQtyCdNm4: '',
pysclQtyId1: '',
pysclQtyId2: '',
pysclQtyId3: '',
pysclQtyId4: '',
ctgr1: '',
ctgr2: '',
careStndVal: '',
warnStndVal: '',
gdMeth: '',
alrmMsg: '',
calcProc: '',
calcDesc: '',
});
} else {
this.setPageData({
gdIdxId: res[0].gdIdxId,
gdIdxNm: res[0].gdIdxNm,
eqpmGrpNm: res[0].eqpmGrpNm,
upTotMeth: res[0].upTotMeth,
unit: res[0].unit,
pysclQtyCdNm1: res[0].pysclQtyCdNm1,
pysclQtyCdNm2: res[0].pysclQtyCdNm2,
pysclQtyCdNm3: res[0].pysclQtyCdNm3,
pysclQtyCdNm4: res[0].pysclQtyCdNm4,
pysclQtyId1: res[0].pysclQtyId1,
pysclQtyId2: res[0].pysclQtyId2,
pysclQtyId3: res[0].pysclQtyId3,
pysclQtyId4: res[0].pysclQtyId4,
ctgr1: res[0].ctgr1,
ctgr2: res[0].ctgr2,
careStndVal: res[0].careStndVal,
warnStndVal: res[0].warnStndVal,
gdMeth: res[0].geMeth,
alrmMsg: res[0].alrmMsg,
calcProc: res[0].calcProc,
calcDesc: res[0].calcDesc,
});
}
},
async getGridData() {
this.loadGrid = false;
let res = [];
if (this.selectValue01 && this.selectValue02 && this.selectValue03) {
res = await this.postApiReturn({
apiKey: 'selectEqpmGdDetl',
resKey: 'eqpmGdDetlData',
sendParam: {
gdIdxId: this.selectValue03,
},
});
}
// grid에서 eqpmId를 기억해서 popup에서 중복되는 값을 제거하는데 사용하기위해 저장 - 시작
let eqpmIdList = res.map(item => {
return item.eqpmId;
});
this.setPageData({ nowGridEqpmIdList: eqpmIdList });
// grid에서 eqpmId를 기억해서 popup에서 중복되는 값을 제거하는데 사용하기위해 저장 - 끝
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.loadGrid = true;
this.$nextTick(() => {
if (newRes.length > 0) {
try {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnNmae: 'eqpmId',
setScroll: true,
});
} catch (error) {}
} else {
this.detailDataInit();
}
});
},
async getRowData(data) {
// this.setReadObjAddInfo(data);
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
detailDataInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowGrid',
value: [],
});
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
if (this.pageData.eqpmGdIdx == null) {
alert(
'조회된 가이드 정보가 없습니다.\n설비그룹의 가이드 지표를 먼저 추가해 주세요',
);
break;
}
// console.log("this.pageData : ", this.pageData.readObjGrp);
const defaultRow = {
gdIdxId: this.pageData.eqpmGdIdx,
eqpmId: '',
eqpmNm: '',
careStndVal: null,
warnStndVal: null,
rowStat: 'I',
};
this.$refs[this.gridName].addRow(defaultRow);
break;
case 'remove':
//if (confirm('삭제 하시겠습니까?')) {
this.$refs[this.gridName].removeRow();
this.setPageData({ rowGridSelectData: null });
//}
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
var validCheck = true;
let chkEqpmIdList = [];
if (dataArr.length > 0) {
dataArr.filter(item => {
// 미입력시 0으로 입력 되는 거 방지
if (item.careStndVal == '') {
item.careStndVal = null;
}
if (item.warnStndVal == '') {
item.warnStndVal = null;
}
if (item.eqpmId == '') {
item.eqpmId = null;
}
if (item.rowStat === 'I') {
if (
item.eqpmId == null ||
item.eqpmId == '' ||
((item.careStndVal == null || item.careStndVal == '') &&
(item.warnStndVal == null || item.warnStndVal == ''))
) {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
if (chkEqpmIdList.includes(item.eqpmId)) {
alert('특정 가이드지표에 대한 설비는 중복될 수 없습니다.');
validCheck = false;
} else {
chkEqpmIdList.push(item.eqpmId);
}
} else if (item.rowStat === 'U') {
if (
item.eqpmId == null ||
item.eqpmId == '' ||
((item.careStndVal == null || item.careStndVal == '') &&
(item.warnStndVal == null || item.warnStndVal == ''))
) {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
}
});
if (validCheck) {
const sendParam = {
datas: {
dsEqpmGdDetlInfo: dataArr.map(item => ({
...item,
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveEqpmGdDetl',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
// click2(val){
// console.log('wpfkqfdfafasd', val);
// }
},
};
const defaultData = {
/* 검색옵션 */
eqpmKindList: [],
eqpmKindId: '',
eqpmGrpList: [],
eqpmGrpId: '',
eqpmGdIdxList: [],
eqpmGdIdx: '',
// 가이드 정보
gdIdxId: '',
gdIdxNm: '',
eqpmGrpNm: '',
upTotMeth: '',
unit: '',
pysclQtyCdNm1: '',
pysclQtyCdNm2: '',
pysclQtyCdNm3: '',
pysclQtyCdNm4: '',
pysclQtyId1: '',
pysclQtyId2: '',
pysclQtyId3: '',
pysclQtyId4: '',
ctgr1: '',
ctgr2: '',
careStndVal: '',
warnStndVal: '',
gdMeth: '',
alrmMsg: '',
calcProc: '',
calcDesc: '',
// Popup과 설비가이드 기준 정보(grid) databinding에 사용 될 변수
eqpmId: '',
eqpmNm: '',
nowGridEqpmIdList: [],
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
gdIdxId: '',
eqpmId: '',
eqpmNm: '',
careStndVal: null,
warnStndVal: null,
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
};
const myDetail = [
{
type: 'EqpmBaseInfoPop',
label: '설비',
valueNm: 'eqpmId',
valueNm2: 'eqpmNm',
cols: 6,
class: 'py-2',
required: true,
openMode: 'GRP',
},
{
type: 'InputText',
// label: '검침 대상 명',
valueNm: 'eqpmNm',
readonly: true,
// disabled: true,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'InputText',
label: '주의기준값',
valueNm: 'careStndVal',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
required: true,
},
{
// 공백 처리
type: 'Label',
cols: 6,
class: 'py-2',
disabled: false,
},
{
type: 'InputText',
label: '경고기준값',
valueNm: 'warnStndVal',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
required: true,
},
{
// 공백 처리
type: 'Label',
cols: 6,
class: 'py-2',
disabled: false,
},
{
// 공백 처리
type: 'Label',
cols: 12,
class: 'py-2',
label: "* '주의기준값' 또는 '경고기준값' 중 하나는 필수로 입력해 주세요.",
disabled: false,
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,545 @@
<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="4">
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="7"
/>
</v-col>
<v-col :cols="4">
<DatePicker
:parentPrgmId="myPrgmId"
label="조회기간"
:labelCols="4"
:textCols="7"
/>
</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-row align="center" no-gutters>
<v-col :cols="4">
<component
:is="'FtnPlcMultiPop'"
:parentPrgmId="myPrgmId"
:labelCols="4"
:textCols="7"
/>
</v-col>
<v-col :cols="4" hidden>
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'에너지'"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col style="height: 100%">
<v-card class="pa-5">
<div ref="chartParent" style="height: 40vh">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="'rowGridChart'"
ref="rowGridChart"
/>
</div>
<div style="height: 30px"></div>
<div ref="gridParent" class="pd-2" style="height: 20vh">
<component
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
ref="rowGrid"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global.js';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import DatePicker from '~/components/common/Datepicker';
import FtnPlcMultiPop from '~/components/common/modal/FtnPlcMultiPop2';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Utility from '~/plugins/utility';
import Grid from '~/components/common/Grid';
import Chart from '~/components/common/Chart';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal],
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: {
SelectBlocMstr,
SelectEnergy,
DatePicker,
FtnPlcMultiPop,
BtnSearch,
BtnExcelDownload,
Utility,
Grid,
Chart,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
loadChart: false,
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
return this.pageData.isFind;
},
chkFacInfo() {
return this.pageData.facInfo;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkFacInfo() {
this.setPageData({ isFind: true });
},
},
beforeCreate() {
myPrgmId = this.$route.query.prgmId;
this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartXAxisData: 'setChartXAxisData',
setChartYAxisData: 'setChartYAxisData',
setChartSeries: 'setChartSeries',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
async init() {
await this.makeGrid();
},
async search() {
await this.makeGrid();
},
async makeGrid() {
this.loadGrid = false;
const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const myOptions = {
scrollX: false,
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
var res = await this.makeResponse();
var columnList = [
{ header: '회사번호', name: 'comId', align: 'center', hidden: true },
{ header: 'no', name: 'no', align: 'center' },
{ header: '일자', name: 'totDttm', align: 'center' },
{
header: '경부하',
name: 'minQty',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '경부하-비율(%)',
name: 'minRto',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '중부하',
name: 'midQty',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '중부하-비율(%)',
name: 'midRto',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '최대부하',
name: 'maxQty',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '최대부하-비율(%)',
name: 'maxRto',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '총사용량',
name: 'totQty',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
{
header: '비용',
name: 'cost',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter: numberFormatter,
},
];
this.setGridColumn({
gridKey: this.gridName,
value: columnList,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
await this.makeChart(res);
this.loadGrid = true;
this.setPageData({ isFind: false });
},
async makeChart(data) {
this.$store.state.pageData[this.myPrgmId].rowGridChart.series = [];
this.loadChart = false;
// if(!data.length){
// return;
// }
var xAxisData = [];
var seriesData = [];
var xAxisData = data.map(el => el.totDttm.substring(5, 10));
seriesData.push({
name: '경부하',
type: 'bar',
stack: 'stack1',
data: data.map(el => el.minQty),
yAxisIndex: 0,
});
seriesData.push({
name: '중부하',
type: 'bar',
stack: 'stack1',
data: data.map(el => el.midQty),
yAxisIndex: 0,
});
seriesData.push({
name: '최대부하',
type: 'bar',
stack: 'stack1',
data: data.map(el => el.maxQty),
yAxisIndex: 0,
});
seriesData.push({
name: '비용',
type: 'line',
data: data.map(el => el.cost),
yAxisIndex: 1,
});
var chartOption = {
grid: {
top: '3%',
},
yAxis: [
{
type: 'value',
name: 'kwh',
position: 'left',
axisLine: {
show: true,
},
},
{
type: 'value',
name: '원',
position: 'right',
axisLine: {
show: true,
},
},
],
xAxis: {
type: 'category',
data: xAxisData,
},
series: seriesData,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
};
this.setChartOption({ chartKey: 'rowGridChart', value: chartOption });
this.setChartYAxisData({
chartKey: 'rowGridChart',
value: [
{
type: 'value',
name: 'kwh',
position: 'left',
axisLine: {
show: false,
},
nameLocation: 'middle',
nameGap: 50,
splitLine: {
show: true,
},
},
{
type: 'value',
name: '원',
position: 'right',
axisLine: {
show: false,
},
nameLocation: 'middle',
nameGap: 70,
splitLine: {
show: true,
},
},
],
});
this.loadChart = true;
},
makeSendParam() {
var param = {
fromDt:
this.pageData.fromDt.substring(0, 4) +
'-' +
this.pageData.fromDt.substring(4, 6) +
'-' +
this.pageData.fromDt.substring(6, 8),
toDt:
this.pageData.toDt.substring(0, 4) +
'-' +
this.pageData.toDt.substring(4, 6) +
'-' +
this.pageData.toDt.substring(6, 8),
eccId: this.pageData.facInfo.eccId,
};
return param;
},
async makeResponse() {
var resultColumnList = [
'comId',
'cost',
'maxQty',
'maxRto',
'midQty',
'midRto',
'minQty',
'minRto',
'totDttm',
'totQty',
];
var res = await this.postApiReturn({
apiKey: 'selectLoadElecPowCmpr',
resKey: 'loadElecPowCmpr',
sendParam: this.makeSendParam(),
});
if (!res.length || res.length < 1) {
return res;
}
for (var i = 0; i < res.length; i++) {
res[i]['totDttm'] = res[i]['totDttm'].replaceAll('-', '/');
}
var fromDt = new Date(
this.pageData.fromDt.substring(0, 4),
this.pageData.fromDt.substring(4, 6),
this.pageData.fromDt.substring(6, 8),
);
var toDt = new Date(
this.pageData.toDt.substring(0, 4),
this.pageData.toDt.substring(4, 6),
this.pageData.toDt.substring(6, 8),
);
var diffDay = (toDt.getTime() - fromDt.getTime()) / (1000 * 60 * 60 * 24);
for (var i = 0; i < diffDay + 1; i++) {
var tempDt = new Date(
this.pageData.fromDt.substring(0, 4),
this.pageData.fromDt.substring(4, 6) - 1,
this.pageData.fromDt.substring(6, 8),
);
tempDt.setDate(tempDt.getDate() + i);
tempDt =
tempDt.getFullYear() +
'/' +
(tempDt.getMonth() + 1).toString().padStart(2, '0') +
'/' +
tempDt
.getDate()
.toString()
.padStart(2, '0');
if (res[i] == undefined || res[i]['totDttm'] != tempDt) {
res.splice(i, 0, {
totDttm: tempDt,
comId: '',
cost: 0,
totQty: 0,
maxQty: 0,
maxRto: 0,
midQty: 0,
midRto: 0,
minQty: 0,
minRto: 0,
});
}
}
for (var i = 0; i < res.length; i++) {
for (var j = 0; j < resultColumnList.length; j++) {
res[i]['no'] = i + 1;
if (res[i][resultColumnList[j]] === undefined) {
res[i][resultColumnList[j]] = 0;
}
}
}
return res;
},
},
};
var dt1 = new Date();
var dt2 = new Date(dt1.setMonth(dt1.getMonth() - 1));
const defaultData = {
isFind: false,
blocId: '',
blocMstrList: [],
energyCd: '',
energyList: [],
cmCycle: 'CYC_DAY',
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: 0,
},
fromDt: Utility.setFormatDate(dt2, 'YYYYMMDD'),
toDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'),
isMulti: false,
modalData: {},
facInfo: {},
rowGrid: {
data: [],
option: {},
column: [],
},
rowGridChart: Utility.defaultChartOption(true),
xlsFileInfo: {
rowGrid: {
fileName: null,
sheetName: null,
},
},
};
function numberFormatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
}
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,591 @@
<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="4">
<component :is="'SelectSysDiv'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="4">
<component :is="'SelectUseFg'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="4" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" :eager="true">
<v-col :cols="5" class="h100">
<v-card class="pb-5 h100">
<v-card-title>메뉴 리스트</v-card-title>
<div class="px-5 h100">
<div ref="treeGridParent" class="w100 h100">
<component
ref="myGrid"
:is="loadTree ? 'Grid' : null"
:gridName="gridNameTree"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<v-card class="py-5 h100">
<v-card-title class="d-flex justify-between">
<span class="tit ft-size_20 ft-weight_600">메뉴 상세</span>
<div>
<v-btn
class="v-btn-radius__20 v-btn-bg__white-blue mr-1"
@click="addRow"
>
<v-icon>mdi-plus</v-icon>
<span>추가</span>
</v-btn>
<v-btn
class="v-btn-radius__20 v-btn-bg__white-blue mr-1"
@click="removeRow"
>
<v-icon>mdi-delete-outline</v-icon>
<span>삭제</span>
</v-btn>
<v-btn class="v-btn-radius__20 v-btn-bg__blue mr-1" @click="save">
<v-icon>mdi-content-save</v-icon>
<span>저장</span>
</v-btn>
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="gridNameTree"
/>
</div>
</v-card-title>
<v-card-actions>
<v-row>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="상위메뉴코드"
valueNm="modifyupMenuId"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="메뉴코드"
valueNm="menuId"
:disabled="true"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="메뉴명"
valueNm="modifyMenuNm"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="프로그램ID"
valueNm="modifyprgmId"
/>
</v-col>
<v-col :cols="12" class="py-2">
<component
:is="'SelectSysDiv'"
diffModel="modifySysDivCd"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="12" class="py-2">
<component
:is="'SelectUseFg'"
diffModel="modifyUseFg"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="정렬순서"
valueNm="modifysortSeq"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="등록지NO"
valueNm="regUserNo"
:disabled="true"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="등록일시"
valueNm="regDttm"
:disabled="true"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="수정지NO"
valueNm="procUserNo"
:disabled="true"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
:parentPrgmId="myPrgmId"
label="수정일시"
valueNm="procDttm"
:disabled="true"
/>
</v-col>
</v-row>
</v-card-actions>
</v-card>
</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 BtnSearch from '~/components/common/button/BtnSearch';
import SelectSysDiv from '@/components/common/select/SelectSysDiv';
import SelectUseFg from '@/components/common/select/SelectUseFg';
import InputText from '@/components/common/input/InputText';
import Grid from '~/components/common/Grid';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Utility from '~/plugins/utility';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
asyncData(context) {
const myState = context.store.state;
context.store.commit('setActiveMenuInfo', myState.menuData[myPrgmId]);
myTitle = myState.activeMenuInfo.menuNm;
},
meta: {
title: () => {
return myTitle;
},
prgmId: myPrgmId,
closable: true,
},
components: {
BtnSearch,
SelectSysDiv,
SelectUseFg,
InputText,
Grid,
BtnExcelDownload,
},
data() {
return {
myPrgmId: myPrgmId,
gridNameTree: 'treeGrid',
loadTree: false,
myRowKey: 0,
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkSysDivCd() {
// 시스템구분 선택 감지
return this.pageData.sysDivCd;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
selectedCommCdData() {
return this.pageData.selectedCommCdData;
},
modifyupMenuId() {
return this.pageData.modifyupMenuId;
},
modifyMenuNm() {
return this.pageData.modifyMenuNm;
},
modifyprgmId() {
return this.pageData.modifyprgmId;
},
modifysortSeq() {
return this.pageData.modifysortSeq;
},
modifySysDivCd() {
return this.pageData.modifySysDivCd;
},
modifyUseFg() {
return this.pageData.modifyUseFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkSysDivCd() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
modifyupMenuId(val) {
const isSameData = this.compareData('upMenuId', val);
if (!isSameData) {
const dt = {
name: 'upMenuId',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyMenuNm(val) {
const isSameData = this.compareData('MenuNm', val);
if (!isSameData) {
const dt = {
name: 'MenuNm',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyprgmId(val) {
const isSameData = this.compareData('prgmId', val);
if (!isSameData) {
const dt = {
name: 'prgmId',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifysortSeq(val) {
const isSameData = this.compareData('sortSeq', val);
if (!isSameData) {
const dt = {
name: 'sortSeq',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifySysDivCd(val) {
const isSameData = this.compareData('sysDivCd', val);
if (!isSameData) {
const dt = {
name: 'sysDivCd',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
modifyUseFg(val) {
const isSameData = this.compareData('useFg', val);
if (!isSameData) {
const dt = {
name: 'useFg',
value: val,
};
this.$refs.myGrid.externalDataEdit(dt);
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
gridInit() {
const treeGridHeight = this.$refs.treeGridParent.offsetHeight - 36;
const myOptionsTree = {
rowHeaders: ['checkbox'],
treeColumnOptions: {
name: 'menuNm',
},
scrollX: false,
};
this.setGridOption({
gridKey: this.gridNameTree,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setGridColumn({
gridKey: this.gridNameTree,
value: [
{
header: '메뉴명',
name: 'menuNm',
align: 'center',
},
{
header: '메뉴ID',
name: 'menuId',
hidden: true,
},
{
header: '상위메뉴ID',
name: 'upMenuId',
hidden: true,
},
{
header: '정렬순서',
name: 'sortSeq',
hidden: true,
},
{
header: '사용여부',
name: 'useFg',
hidden: true,
},
{
header: '회사코드',
name: 'comId',
hidden: true,
},
{
header: '시스템구분',
name: 'sysDivCd',
hidden: true,
},
{
header: '등록자NO',
name: 'regUserNo',
hidden: true,
},
{
header: '등록일시',
name: 'regDttm',
hidden: true,
},
{
header: '수정자NO',
name: 'procUserNo',
hidden: true,
},
{
header: '수정일시',
name: 'procDttm',
hidden: true,
},
],
});
this.getTreeData();
},
//메뉴 리스트
async getTreeData() {
const res = await this.postApiReturn({
apiKey: 'selectMenu',
resKey: 'menuData',
sendParm: {
comId: this.pageData.comId,
sysDivCd: this.pageData.sysDivCd,
useFg: this.pageData.useFg,
},
});
res[0].upMenuId = 'ROOT';
// res[0].parentId= 'ROOT';
const setTreeData = await this.setTree({
treeKey: 'MENU_ID',
value: res,
});
this.loadTree = true;
await this.setGridData({
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
// this.$refs.myGrid.focus({
// rowKey:this.myRowKey,
// columnName: "menuNm",
// setScroll: true
// });
this.$nextTick(() => {
if (setTreeData.length > 0) {
this.$refs['myGrid'].focus({
rowKey: this.myRowKey,
columnName: 'menuNm',
setScroll: true,
});
}
});
this.setPageData({ isFind: false });
},
async getRowData(data) {
this.myRowKey = data.rowKey;
this.setPageData({
selectedCommCdData: data,
modifyupMenuId: data.menuId,
modifyMenuNm: data.menuNm,
modifyprgmId: data.prgmId,
modifysortSeq: data.sortSeq,
modifySysDivCd: data.sysDivCd,
modifyUseFg: data.useFg,
procDttm: data.procDttm,
procUserNo: data.procUserNo,
regUserNo: data.regUserNo,
regDttm: data.regDttm,
menuId: data.menuId,
});
},
async search() {
await this.getTreeData();
await this.setPageData({
isFind: false,
});
},
compareData(type, newDt) {
if (this.selectedCommCdData[type] == newDt) {
return true;
} else {
return false;
}
},
addRow() {
this.$refs.myGrid.gridInstance.invoke(
'appendRow',
{
menuId: '',
menuNm: '',
prgmId: '',
sortSeq: '',
sysDivCd: '',
useFg: '',
procDttm: '',
procUserNo: '',
regUserNo: '',
regDttm: '',
},
{ focus: true },
);
// this.$refs.myGrid.addRow();
// var rowData = {menuId: "", menuNm : "", prgmId:"", sortSeq:"", sysDivCd:"", useFg:"",procDttm:"",procUserNo:"",regUserNo:"",regDttm:""}
// this.$refs.myGrid.appendRow(rowData, {
// at:1,
// extendPrevRowSpan:true,
// focus:true
// });
},
removeRow() {
this.$refs.myGrid.removeRow();
},
async save() {
const dataArr = this.$refs.myGrid.save();
const sendParam = {
datas: { dsMenu: dataArr },
params: {},
};
await this.postUpdateApi({
apiKey: 'saveMenu',
sendParm: sendParam,
});
await this.search();
},
},
};
const defaultData = {
/* 검색옵션 */
comId: this.comId,
sysDivCd: '',
sysDivCdList: [],
useFg: '',
useFgList: [],
menuId: '',
modifySysDivCd: 'COMM',
modifyUseFg: '1',
regUserNo: '',
regDttm: '',
procUserNo: '',
procDttm: '',
modifyupMenuId: '',
modifyMenuNm: '',
modifyprgmId: '',
modifysortSeq: '',
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
treeGrid: {
data: [],
column: [],
option: {},
defaultRow: {
menuId: '',
menuNm: '',
upMenuId: '',
prgmId: '',
sortSeq: '',
useFg: '',
comId: '',
sysDivCd: '',
regUserNo: '',
regDttm: '',
procUserNo: '',
procDttm: '',
rowStat: null,
},
},
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,817 @@
<template>
<div class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="1">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
기간
</label>
</v-col>
<v-col :cols="2">
<v-text-field
id="startpicker"
ref="startpicker"
v-model="targetDateTimeObject.value"
:class="'v-input__custom'"
readonly
outlined
:hide-details="true"
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="startpicker-container"
id="startpicker-container"
></div>
</template>
</v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col :cols="2" class="d-flex justify-end align-center">
<BtnSearch @click="search" class="mr-1" />
<div id="btnExeclDownload">
<v-btn :ripple="false" @click="downloadExcelFile">액셀</v-btn>
</div>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="height: 100%">
<v-card class="pb-5">
<v-row class="pa-5">
<v-col :cols="12">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
<span class="custom-title-4">권역 종합</span>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<div
ref="gridParent01"
class="px-5"
:style="{ height: 'calc(25vh - 90px)' }"
>
<component
:is="loadGrid01 ? 'Grid' : null"
:gridName="gridName01"
:parentPrgmId="myPrgmId"
ref="rowGrid01"
/>
</div>
</v-col>
</v-row>
<v-row class="pa-5">
<v-col :cols="12">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
<span class="custom-title-4">에너지원별 종합</span>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<div
ref="gridParent02"
class="px-5"
:style="{ height: 'calc(25vh - 90px)' }"
>
<component
:is="loadGrid02 ? 'Grid' : null"
:gridName="gridName02"
:parentPrgmId="myPrgmId"
ref="rowGrid02"
/>
</div>
</v-col>
</v-row>
<v-row class="pa-5">
<v-col :cols="12">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
<span class="custom-title-4">조직별 종합</span>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<div
ref="gridParent03"
class="px-5"
:style="{ height: 'calc(25vh - 90px)' }"
>
<component
:is="loadGrid03 ? 'Grid' : null"
:gridName="gridName03"
:parentPrgmId="myPrgmId"
ref="rowGrid03"
/>
</div>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global.js';
import SelectDate from '~/components/common/select/SelectDate';
import SelectDateVc from '~/components/common/select/SelectDateVc';
import FtnPlcMultiPop from '~/components/common/modal/FtnPlcMultiPop';
import TuiDatepicker from 'tui-date-picker';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Utility from '~/plugins/utility';
import Grid from '~/components/common/Grid';
import XLSX from 'xlsx';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal],
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: {
SelectDate,
SelectDateVc,
FtnPlcMultiPop,
BtnSearch,
BtnExcelDownload,
Utility,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
targetDateTimeObject: {
value: new Date().toISOString().substr(0, 7),
},
startDatepickerInstance: null,
loadGrid01: false,
loadGrid02: false,
loadGrid03: false,
gridName01: 'rowGrid01',
gridName02: 'rowGrid02',
gridName03: 'rowGrid03',
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
return this.pageData.isFind;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
'targetDateTimeObject.value': function() {
this.setPageData({ isFind: true });
},
},
beforeCreate() {
myPrgmId = this.$route.query.prgmId;
this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
async init() {
await this.gridInit();
this.tuiCalendarInit();
},
tuiCalendarInit() {
const startContainer = document.getElementById('startpicker-container');
const startTarget = document.getElementById('startpicker');
this.startDatepickerInstance = new TuiDatepicker(startContainer, {
date: new Date(),
language: 'ko',
type: 'month',
input: {
element: startTarget,
format: 'YYYY-MM', //"YYYY-MM-DD" //this.format
},
timePicker: false,
});
this.startDatepickerInstance.on('change', () => this.getStartDt());
},
getStartDt() {
const dt = this.startDatepickerInstance.getDate();
this.targetDateTimeObject.value = String(dt.toISOString()).substr(0, 7);
},
async gridInit() {
const gridHeight01 = this.$refs.gridParent01.offsetHeight - 36;
const gridHeight02 = this.$refs.gridParent02.offsetHeight - 36;
const gridHeight03 = this.$refs.gridParent03.offsetHeight - 36;
const myOptions = {
scrollX: false,
};
this.setGridOption({
gridKey: this.gridName01,
value: Object.assign(
Utility.defaultGridOption(gridHeight01),
myOptions,
),
});
this.setGridOption({
gridKey: this.gridName02,
value: Object.assign(
Utility.defaultGridOption(gridHeight02),
myOptions,
),
});
this.setGridOption({
gridKey: this.gridName03,
value: Object.assign(
Utility.defaultGridOption(gridHeight03),
myOptions,
),
});
var params = this.makeParams();
await this.getGridData01(params);
await this.getGridData02(params);
await this.getGridData03(params);
},
makeParams() {
var params = {};
params['year'] = this.targetDateTimeObject.value.substr(0, 4);
params['month'] = this.targetDateTimeObject.value.substr(5, 2);
params['lang'] = 'ko_KR';
params['blocId'] = this.userInfo.blocId;
params['blocPlcCd'] = 'PLC00002';
return params;
},
async getGridData01(params) {
var res = null;
var columnList = [
{ header: '에너지', name: 'mttNm', align: 'left' },
{
header: '계획 사용량',
name: 'planQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '실적 사용량',
name: 'useQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 증감률',
name: 'preYyQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 증감률',
name: 'preMmQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '비용(원)',
name: 'useCost',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 비용 증감률',
name: 'preYyCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 비용 증감률',
name: 'preMmCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: 'TOE',
name: 'toe',
align: 'right',
formatter: numberFormatter,
},
{
header: 'tCO2',
name: 'tco2',
align: 'right',
formatter: numberFormatter,
},
];
this.loadGrid01 = false;
res = await this.postApiReturn({
apiKey: 'selectMonthReportFactory',
resKey: 'monthReportFactory',
sendParam: params,
});
this.setGridColumn({
gridKey: this.gridName01,
value: columnList,
});
this.setGridData({
gridKey: this.gridName01,
value: res,
});
this.loadGrid01 = true;
this.setPageData({ isFind: false });
},
async getGridData02(params) {
var res = null;
var columnList = [
{ header: '에너지', name: 'mttNm', align: 'left' },
{ header: '상위공정', name: 'eccNm', align: 'left' },
{
header: '계획 사용량',
name: 'planQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '실적 사용량',
name: 'useQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 증감률',
name: 'preYyQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 증감률',
name: 'preMmQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '비용(원)',
name: 'useCost',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 비용 증감률',
name: 'preYyCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 비용 증감률',
name: 'preMmCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: 'TOE',
name: 'toe',
align: 'right',
formatter: numberFormatter,
},
{
header: 'tCO2',
name: 'tco2',
align: 'right',
formatter: numberFormatter,
},
];
this.loadGrid02 = false;
res = await this.postApiReturn({
apiKey: 'selectMonthReportEnergy',
resKey: 'monthReportEnergy',
sendParam: params,
});
setRowSpanAttribute(res, 'mttNm');
this.setGridColumn({
gridKey: this.gridName02,
value: columnList,
});
this.setGridData({
gridKey: this.gridName02,
value: res,
});
this.loadGrid02 = true;
this.setPageData({ isFind: false });
},
async getGridData03(params) {
var res = null;
var columnList = [
{ header: '상위공정', name: 'upPlcNm', align: 'left' },
{ header: '공정', name: 'eccNm', align: 'left' },
{ header: '에너지', name: 'mttNm', align: 'left' },
{
header: '계획 사용량',
name: 'planQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '실적 사용량',
name: 'useQty',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 증감률',
name: 'preYyQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 증감률',
name: 'preMmQtyRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '비용(원)',
name: 'useCost',
align: 'right',
formatter: numberFormatter,
},
{
header: '전년동월대비 비용 증감률',
name: 'preYyCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: '전월대비 비용 증감률',
name: 'preMmCostRate',
align: 'right',
formatter: numberFormatter,
},
{
header: 'TOE',
name: 'toe',
align: 'right',
formatter: numberFormatter,
},
{
header: 'tCO2',
name: 'tco2',
align: 'right',
formatter: numberFormatter,
},
];
this.loadGrid03 = false;
res = await this.postApiReturn({
apiKey: 'selectMonthReportDept',
resKey: 'monthReportDept',
sendParam: params,
});
setRowSpanAttribute(res, 'upPlcNm');
// setRowSpanAttribute(res, 'mttNm', ['upPlcNm', 'mttNm']);
this.setGridColumn({
gridKey: this.gridName03,
value: columnList,
});
this.setGridData({
gridKey: this.gridName03,
value: res,
});
this.loadGrid03 = true;
this.setPageData({ isFind: false });
},
async search() {
var params = this.makeParams();
await this.getGridData01(params);
await this.getGridData02(params);
await this.getGridData03(params);
},
downloadExcelFile() {
this.makeExcelFile('rowGrid01', '권역 종합.xlsx');
this.makeExcelFile('rowGrid02', '에너지원별 종합.xlsx');
this.makeExcelFile('rowGrid03', '조직별 종합.xlsx');
},
makeExcelFile(gridName, fileName) {
var xlsData = this.makeExcelData(gridName);
var workBook = XLSX.utils.book_new();
var excelData = XLSX.utils.json_to_sheet(xlsData);
var sheetName = fileName;
XLSX.utils.book_append_sheet(workBook, excelData, sheetName);
XLSX.writeFile(workBook, fileName);
},
makeExcelData(gridName) {
var xlsData = null;
var xlsHeader = this.pageData[gridName].column;
var xlsRowData = this.pageData[gridName].data;
var tmpData = [];
var tmpMap = {};
xlsRowData.map(item => {
xlsHeader.map(v => {
// return Object.assign(tmpMap, { [v.header]: item[v.name] || 0 });
var value = item[v.name];
if (value == undefined) {
value = 0;
}
if (typeof value === 'number') {
value = parseFloat(
Utility.setFormatIntDecimal(value, 2).replace(',', ''),
);
}
return Object.assign(tmpMap, { [v.header]: value || 0.0 });
});
tmpData = tmpData.concat(tmpMap);
tmpMap = {};
});
xlsData = tmpData;
return xlsData;
},
},
};
const defaultData = {
isFind: false,
rowGrid01: {
data: [],
option: {},
column: [],
},
rowGrid02: {
data: [],
option: {},
column: [],
},
rowGrid03: {
data: [],
option: {},
column: [],
},
};
function setRowSpanAttribute(res, targetAttributeName, targetAttributeList) {
if (!(res.length && res.length >= 2)) {
return;
}
if (targetAttributeList == undefined) {
var valueList = [];
var rowSpanValueList = [];
var currentIdx = 0;
for (var i = 0; i < res.length; i++) {
valueList.push(res[i][targetAttributeName]);
}
rowSpanValueList[0] = [valueList[0], 1, currentIdx];
for (var i = 1; i < valueList.length; i++) {
currentIdx += 1;
if (valueList[i] === rowSpanValueList[rowSpanValueList.length - 1][0]) {
rowSpanValueList[rowSpanValueList.length - 1][1] += 1;
} else {
rowSpanValueList[rowSpanValueList.length] = [
valueList[i],
1,
currentIdx,
];
}
}
for (var i = 0; i < rowSpanValueList.length; i++) {
if (rowSpanValueList[i][1] === 1) {
continue;
}
res[rowSpanValueList[i][2]]['_attributes'] = { rowSpan: new Object() };
res[rowSpanValueList[i][2]]['_attributes']['rowSpan'][
targetAttributeName
] = rowSpanValueList[i][1];
}
} else {
// targetAttributeList 전달 ...
var valueList = [];
var rowSpanValueList = [];
var currentIdx = 0;
for (var i = 0; i < res.length; i++) {
var tempList = [];
for (var j = 0; j < targetAttributeList.length; j++) {
tempList.push(res[i][targetAttributeList[j]]);
}
valueList.push(tempList);
}
rowSpanValueList[0] = [valueList[0], 1, currentIdx];
for (var i = 1; i < valueList.length; i++) {
currentIdx += 1;
if (
comepareValueWithTargetAttributeList(
valueList[i],
rowSpanValueList[rowSpanValueList.length - 1][0],
)
) {
rowSpanValueList[rowSpanValueList.length - 1][1] += 1;
} else {
rowSpanValueList[rowSpanValueList.length] = [
valueList[i],
1,
currentIdx,
];
}
}
for (var i = 0; i < rowSpanValueList.length; i++) {
if (rowSpanValueList[i][1] === 1) {
continue;
}
res[rowSpanValueList[i][2]]['_attributes'] = { rowSpan: new Object() };
res[rowSpanValueList[i][2]]['_attributes']['rowSpan'][
targetAttributeName
] = rowSpanValueList[i][1];
}
}
function comepareValueWithTargetAttributeList(valueList_01, valueList_02) {
for (var i = 0; i < valueList_01.length; i++) {
if (valueList_01[i] != valueList_02[i]) {
return false;
}
}
return true;
}
}
function setRowSpanAttribute_old(
res,
targetAttributeName,
targetAttributeList,
) {
if (!(res.length && res.length >= 2)) {
return;
}
if (targetAttributeList == undefined) {
var currentCnt = 1;
var currentIdx = 0;
var currentValue = res[0][targetAttributeName];
for (var i = 1; i < res.length - 1; i++) {
if (res[i][targetAttributeName] != currentValue) {
if (res[currentIdx]['_attributes'] == undefined) {
res[currentIdx]['_attributes'] = { rowSpan: new Object() };
}
res[currentIdx]['_attributes']['rowSpan'][
targetAttributeName
] = currentCnt;
currentValue = res[i][targetAttributeName];
currentCnt = 1;
currentIdx = i;
} else if (
res[i][targetAttributeName] == currentValue &&
i == res.length - 2
) {
currentCnt = currentCnt + 1;
if (res[currentIdx]['_attributes'] == undefined) {
res[currentIdx]['_attributes'] = { rowSpan: new Object() };
}
res[currentIdx]['_attributes']['rowSpan'][
targetAttributeName
] = currentCnt;
} else {
currentCnt = currentCnt + 1;
}
}
} else {
var currentCnt = 1;
var currentIdx = 0;
for (var i = 1; i < res.length - 1; i++) {
if (!compareValue(res, targetAttributeList, currentIdx, i)) {
if (res[currentIdx]['_attributes'] == undefined) {
res[currentIdx]['_attributes'] = { rowSpan: new Object() };
}
if (currentCnt != 1) {
res[currentIdx]['_attributes']['rowSpan'][
targetAttributeName
] = currentCnt;
}
currentCnt = 1;
currentIdx = i;
} else if (
compareValue(res, targetAttributeList, currentIdx, i) &&
i == res.length - 2
) {
currentCnt = currentCnt + 1;
if (res[currentIdx]['_attributes'] == undefined) {
res[currentIdx]['_attributes'] = { rowSpan: new Object() };
}
if (currentCnt != 1) {
res[currentIdx]['_attributes']['rowSpan'][
targetAttributeName
] = currentCnt;
}
} else {
currentCnt = currentCnt + 1;
}
}
}
function compareValue(res, targetAttributeList, currentIdx, targetIdx) {
for (var i = 0; i < targetAttributeList.length; i++) {
if (
res[currentIdx][targetAttributeList[i]] !=
res[targetIdx][targetAttributeList[i]]
) {
return false;
}
}
return true;
}
}
function numberFormatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
}
</script>
<style lang="scss" scoped>
#startpicker-container,
#endpicker-container {
position: relative;
z-index: 20;
}
.v-input__custom {
flex: 0 0 auto;
&.half {
width: calc(50% - 20px);
}
}
::v-deep {
.tui-timepicker-row {
display: flex;
justify-content: space-around;
background-color: #edf4fc;
.tui-timepicker-column.tui-timepicker-colon {
color: #000 !important;
}
}
}
</style>

View File

@ -0,0 +1,517 @@
<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"
/>
</v-col>
<!-- <v-col :cols="2">
<component
label="검침개소"
:is="'PastRsltDataReadPop'"
:parentPrgmId="myPrgmId"
/>
</v-col> -->
<!-- <v-col :cols="2">
<component
:is="'SelectTagNmList'"
ref="SelectTagNmList"
:parentPrgmId="myPrgmId"
/>
</v-col> -->
<v-col :cols="3">
<!-- <component
:is="'PastRsltDataReadTagPop'"
:parentPrgmId="myPrgmId"
:label="'TAG'"
/> -->
<component
:is="'EvtObjPop'"
:parentPrgmId="myPrgmId"
:item="evtObjPopItem"
/>
</v-col>
<v-col :cols="4">
<component
:is="'Datepicker'"
:parentPrgmId="myPrgmId"
:label="'조회기간'"
:labelCols="2"
/>
</v-col>
<v-col :cols="3" class="text-right">
<!-- 조회버튼 -->
<BtnSearch @click="search" />
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="height: 100%" class="h100">
<v-card class="px-5 py-5 h100">
<div ref="gridParent" class="h100 px-5" style="height: 100%">
<component
ref="myGrid"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import BtnSearch from '~/components/common/button/BtnSearch';
import Grid from '~/components/common/Grid';
import mixinGlobal from '@/mixin/global.js';
import { resize } from '@/mixin/resize.js';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import Utility from '~/plugins/utility';
import Datepicker from '~/components/common/PastRsltDatePicker';
import PastRsltDataReadPop from '~/components/common/modal/PastRsltDataReadPop';
import PastRsltDataReadTagPop from '~/components/common/modal/PastRsltDataReadTagPop';
import SelectTagNmList from '~/components/common/select/SelectTagNmList';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
// import TotUseQtyCmprPageVue from './TotUseQtyCmprPage.vue';
import DateUtility from '~/plugins/dateUtility';
// import Search from "~/components/common/search";
import EvtObjPop from '~/components/common/modal/EvtObjPop';
let myTitle;
// const myPrgmId = "PRG0052";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Datepicker,
SelectBlocMstr,
SelectTagNmList,
BtnExcelDownload,
Grid,
PastRsltDataReadPop,
PastRsltDataReadTagPop,
EvtObjPop,
},
data() {
return {
myPrgmId: myPrgmId,
loadGrid: false,
gridName: 'rowGrid',
myRowKey: 0,
initFlag: false,
evtObjPopItem: {
labelContent: 'TAG',
modalTitle: 'TAG 리스트',
valueNm: 'tagId',
valueNm2: 'tagNm',
disabled: false,
labelCols: 2,
textCols: 9,
class: 'py-2',
required: false,
formFg: false,
},
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
return this.pageData.isFind;
},
chkTagId() {
return this.pageData.tagList === undefined ? null : this.pageData.tagId;
},
// chkTagList() {
// return this.pageData.tagList;
// },
chkTagNm() {
return this.pageData.tagData.tagNm;
},
chkReadPlcId() {
return this.pageData.readPlcId;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkTagId(val) {
if (this.initFlag && val != null) {
this.search();
}
},
// chkTagList() {
// if(this.initFlag){
// this.search();
// }
// },
chkTagNm() {
if (this.initFlag) {
this.search();
}
},
chkReadPlcId() {
this.setPageData({
sendTagParam: { readPlc: this.pageData.readPlcId.readPlcId },
});
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {},
async mounted() {
await this.setFromDt();
await this.init();
this.initFlag = true;
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
async search() {
// this.gridInit();
if (this.initFlag) {
if (this.pageData.tagId == '' || this.pageData.tagId == null) {
alert('TAG를 선택해 주세요');
} else {
this.getRowGridData();
}
}
this.setPageData({
isFind: false,
});
},
async init() {
//this.layoutInit();
this.gridInit();
this.pageData.blocId = this.userInfo.blocId;
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
async setFromDt() {
this.pageData.fromDt = Utility.setBeforetDate(
this.pageData,
this.pageData.toDt,
'YYYYMMDD',
);
// this.pageData.toDt = Utility.setAftertDate(this.pageData, this.pageData.fromDt, "YYYYMMDD");
},
gridInit() {
this.loadGrid = false;
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
let myColumns = [
{
header: 'TAG ID',
name: 'tagId',
align: 'left',
minWidth: 500,
},
{
header: 'TAG명',
name: 'tagNm',
align: 'left',
},
{
header: '대상일시',
name: 'readDttm',
align: 'center',
width: 200,
},
{
header: '값',
name: 'readVal',
align: 'right',
width: 100,
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
},
{
header: '취득일시',
name: 'regDttm',
align: 'center',
width: 200,
},
{
header: '적재일시',
name: 'procDttm',
align: 'center',
width: 200,
},
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
},
async getRowGridData() {
this.loadGrid = false;
let res = [];
let yearQuarterData = [];
yearQuarterData = this.yearQuarterMaker([
this.pageData.fromDt,
this.pageData.toDt,
]);
// if(this.pageData.tagList.length > 0){
// const sendParams= {
// fromDt: this.pageData.fromDt,
// toDt: this.pageData.toDt,
// yearQuarterList: yearQuarter,
// }
// if(this.pageData.tagList[this.pageData.tagId].tagId == '' || this.pageData.tagList[this.pageData.tagId].tagId == null){
// sendParams['readPlcId']= this.pageData.readPlcId.readPlcId
// }else{
// sendParams['tagId']= this.pageData.tagList[this.pageData.tagId].tagId
// }
// res = await this.postApiReturn({
// apiKey: "selectTagRawDataByQuarter",
// resKey: "pastRsltReadData",
// sendParam: sendParams
// });
// this.setGridData({
// gridKey: this.gridName,
// value: res
// })
// }
// 기존 소스
if (this.pageData.tagData.tagNm != '') {
const sendParams = {
fromDt: this.pageData.fromDt,
toDt: this.pageData.toDt,
yearQuarterList: yearQuarterData['yearQuarterList'],
};
sendParams['tagId'] = this.pageData.tagData.tagId;
//
if (yearQuarterData['newToDt'] != undefined) {
sendParams['toDt'] = yearQuarterData['newToDt'];
sendParams['newFromDt'] = yearQuarterData['newFromDt'];
sendParams['rawTableToDt'] = yearQuarterData['rawTableToDt'];
} else if (yearQuarterData['rawTableToDt'] != undefined) {
sendParams['newFromDt'] = yearQuarterData['newFromDt'];
sendParams['rawTableToDt'] = yearQuarterData['rawTableToDt'];
}
res = await this.postApiReturn({
apiKey: 'selectTagRawDataByQuarter',
resKey: 'pastRsltReadData',
sendParam: sendParams,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
} else {
// 바뀐 popup에 맞춘 소스
const sendParams = {
fromDt: this.pageData.fromDt,
toDt: this.pageData.toDt,
yearQuarterList: yearQuarterData['yearQuarterList'],
};
sendParams['tagId'] = this.pageData.tagId;
//
if (yearQuarterData['newToDt'] != undefined) {
sendParams['toDt'] = yearQuarterData['newToDt'];
sendParams['newFromDt'] = yearQuarterData['newFromDt'];
sendParams['rawTableToDt'] = yearQuarterData['rawTableToDt'];
} else if (yearQuarterData['rawTableToDt'] != undefined) {
sendParams['newFromDt'] = yearQuarterData['newFromDt'];
sendParams['rawTableToDt'] = yearQuarterData['rawTableToDt'];
}
res = await this.postApiReturn({
apiKey: 'selectTagRawDataByQuarter',
resKey: 'pastRsltReadData',
sendParam: sendParams,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
}
this.loadGrid = true;
},
yearQuarterMaker(dateList) {
//1번 조건: 오늘 날짜 기준 최근 4개월까지는 raw_data 테이블 조회
//2번 조건: 그 이후의 경우는 raw_data2022Y2Q 같은 backup 테이블 조회
//3번 조건: 1+2번 조건
let finalResult = {};
let newFromDt = '';
let newToDt = '';
let today = Utility.setFormatDate(new Date(), 'YYYYMMDDHHmmss');
let checkPoint = 0;
let diffTime = DateUtility.diff(dateList[0], today, 'd');
if (diffTime >= 120) {
newFromDt = DateUtility.addDate(-119, 'YYYYMMDD', dateList[1]);
newToDt = DateUtility.addDate(-120, 'YYYYMMDD', today);
checkPoint = DateUtility.diff(newToDt, dateList[1], 'd');
// 오늘날짜로부터 4개월 보다 많은 경우(raw_data + raw_data_backup 테이블)
if (checkPoint > 0) {
finalResult['newToDt'] = newToDt;
finalResult['newFromDt'] = newFromDt;
finalResult['rawTableToDt'] = dateList[1];
}
// console.log('newFromDt', dateList[0], newToDt, newFromDt, dateList[1]);
//1번 조건: 최근 4개월이내의 경우(raw_data만 조회)
} else {
finalResult['newFromDt'] = dateList[0];
finalResult['rawTableToDt'] = dateList[1];
finalResult['yearQuarterList'] = [];
return finalResult;
}
//2번 조건: 최근 4개월을 벗어나는 경우(raw_data_backup 테이블 조회)
let result = [];
let quarterNum;
//2022Y3Q 같은 형태로 만들기
for (let date of [dateList[0], newToDt]) {
quarterNum = 'Y1Q';
let year = date.substring(0, 4);
let qNum = parseInt(date.substring(4, 6).replace(/(^0+)/, ''));
if (qNum > 3) quarterNum = 'Y2Q';
if (qNum > 6) quarterNum = 'Y3Q';
if (qNum > 9) quarterNum = 'Y4Q';
result.push(year + quarterNum);
}
if (result.length > 1) {
let fromYear = parseInt(result[0].substring(0, 4));
let fromQuarter = parseInt(result[0].substring(5, 6));
let toYear = parseInt(result[1].substring(0, 4));
let toQuarter = parseInt(result[1].substring(5, 6));
let endPoint = toYear + 'Y' + toQuarter + 'Q';
let diffYear = toYear - fromYear;
for (var i = 0; i <= diffYear; i++) {
if (fromQuarter + 1 >= 4) {
fromYear = fromYear + 1;
fromQuarter = 0;
}
let newYearQuarter = fromYear + 'Y' + (fromQuarter + i + 1) + 'Q';
if (endPoint == newYearQuarter) {
break;
} else {
result.splice(i + 1, 0, newYearQuarter);
}
}
}
finalResult['yearQuarterList'] = result;
return finalResult;
},
},
};
const defaultData = {
sendTagParam: { readPlc: '' },
tagData: { tagNm: '' },
/* 검색옵션 */
blocId: '',
blocMstrList: [],
tagId: '',
tagNm: '',
tagList: [],
isFind: false,
modalData: {},
cmCycle: 'CYC_DAY', // 주기
readPlcId: '',
defaultRange: {
CYC_DAY: 30,
},
fromDt: '', // 조회 시작일
toDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'), // 조회 종료일,
rowGrid: {
data: [],
column: [],
option: {},
defaultRow: {},
},
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,815 @@
<template>
<div ref="mainDiv" class="l-layout">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'검침대상 유형'"
dataKey="readObjKind"
:addAll="true"
:sendParam="{ commGrpCd: 'CM_MTTTP', useFg: '1' }"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'사용여부'"
dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="3">
<InputText
:parentPrgmId="myPrgmId"
label="검침대상명"
valueNm="readObjNm"
:searchOption="true"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" 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
>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:detailList="detailList"
:btnActionsFnc="btnActions"
/>
</div>
<div class="h100 px-5" style="height:calc(100% - 70px)">
<div ref="gridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
@sendSelectedRowStatInfo="getSelectedRowStatInfo"
:selectedRowDataWatchFlag="true"
/>
</div>
</div>
</v-card>
</v-col>
<v-col :cols="7" class="h100">
<v-card class="pb-5">
<v-card-title class="custom-title-4" style="min-height:76px;"
>검침대상 상세
</v-card-title>
<div class="px-5" style="height:calc(100% - 76px)">
<v-tabs v-model="tab">
<v-tab
v-for="item in items"
:key="item.id"
:disabled="item.disabledFlag"
>
{{ item.name }}
</v-tab>
</v-tabs>
<v-tabs-items
v-model="tab"
style="height: calc(100% - 65px);"
class="py-6"
>
<v-tab-item v-for="(item, idx) in items" :key="item.id">
<component
v-if="item.id == 'readObjBaseInfoTab'"
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
<readObjAddInfoTab
v-if="item.id == 'readObjAddInfoTab'"
:parentPrgmId="myPrgmId"
:innerTabGridInfo="{ tab, idx }"
/>
</v-tab-item>
</v-tabs-items>
</div>
</v-card>
</v-col>
<!--
<v-col :cols="7" class="h100">
<v-card class="py-5">
<div class="d-flex align-center justify-space-between pa-5">
<v-card-title class="pa-0">검침 대상 정보 상세</v-card-title>
<div>
<Buttons
:parentPrgmId="myPrgmId"
:bindingData="gridName"
:btnActionsFnc="btnActions"
/>
</div>
</div>
<div class="px-5" style="height:calc(100% - 76px)">
<component
:is="'Form'"
:parentPrgmId="myPrgmId"
:detailList="detailList"
@gridEditingFinish="gridEditingFinish"
/>
</div>
</v-card>
</v-col>
-->
</v-row>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global.js';
import { resize } from '@/mixin/resize.js';
import BtnSearch from '~/components/common/button/BtnSearch';
import Buttons from '~/components/common/button/Buttons';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import ReadObjAddInfoTab from '@/components/pages/ems/ReadObjInfo/ReadObjAddInfoTab';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
let myTitle;
// const myPrgmId = "PRG0009";
let myPrgmId;
export default {
mixins: [mixinGlobal, resize],
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: {
BtnSearch,
Buttons,
SelectBlocMstr,
selectCodeList,
InputText,
Form,
ReadObjAddInfoTab,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
tab: null,
items: [
{
name: '검침 대상 정보',
id: 'readObjBaseInfoTab',
disabledFlag: false,
},
{
name: '검침 대상 추가 정보',
id: 'readObjAddInfoTab',
disabledFlag: false,
},
],
detailList: myDetail,
};
},
computed: {
// ...mapState({
// pageData: state => state.pageData[myPrgmId]
// }),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkReadObjKind() {
// 시스템구분 선택 감지
return this.pageData.readObjKind;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkReadObjKind() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
// 검침 Data 구분 목록 조회
this.getCodeList({
dataKey: 'readObjGrp',
params: { commGrpCd: 'EM_READ_OBJ_GRP', useFg: '1' },
addAll: false,
});
// 검침 Data 구분 목록 조회
this.getCodeList({
dataKey: 'readObjKindDetail',
params: { commGrpCd: 'CM_MTTTP', useFg: '1' },
addAll: false,
});
// 단위 코드 목록 조회
this.getCodeList({
dataKey: 'unitCd',
params: { commGrpCd: 'CM_UNIT', useFg: '1' },
addAll: false,
});
/////////// 추가 정보 Tab 에서 사용
// 데이터 유형 목록 조회
this.getCodeList({
dataKey: 'addInfoDataKind',
params: { commGrpCd: 'CO_DATA_TYPE', useFg: '1' },
addAll: false,
});
// 추가 정보 목록 조회
this.getAddInfoList({
dataKey: 'addInfo',
params: { addGrpId: 'READ_OBJ_INFO', useFg: '1' },
addAll: false,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({
getCodeList: 'modules/search/getCodeList',
getBlocMstrList: 'modules/search/getBlocMstrList',
getAddInfoList: 'modules/search/getAddInfoList',
}),
init() {
this.gridInit();
},
search() {
this.getRowGridData();
this.setPageData({
isFind: false,
});
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
const _this = this;
const myColumns = [
{ header: '회사 ID', name: 'comId', hidden: true },
{
header: '검침 대상 ID',
name: 'readObjId',
width: 130,
align: 'center',
},
{
header: '검침 대상 명',
name: 'readObjNm',
align: 'left',
},
{
header: '검침 값 유형',
name: 'readObjKind',
width: 110,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.readObjKindDetailList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '그룹',
name: 'grpCd',
width: 110,
align: 'left',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.readObjGrpList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: 'TJ 환산계수',
name: 'tjCvrtCoef',
width: 80,
align: 'center',
hidden: true,
},
{
header: 'TOE 환산계수',
name: 'toeCvrtCoef',
width: 80,
align: 'center',
hidden: true,
},
{
header: 'CO2 환산계수',
name: 'co2CvrtCoef',
width: 100,
align: 'right',
hidden: true,
},
{
header: '단위 코드',
name: 'unitCd',
width: 80,
align: 'center',
hidden: true,
},
{
header: '사용여부',
name: 'useFg',
align: 'center',
width: 100,
formatter({ value }) {
value = value === true ? '1' : '0';
const newValue = _this.pageData.useFgList.filter(
item => item.commCd == value,
);
return newValue[0].commCdNm;
},
},
{ header: '등록자NO', name: 'regUserNo', hidden: true },
{ header: '등록일시', name: 'regDttm', hidden: true },
{ header: '수정자NO', name: 'procUserNo', hidden: true },
{ header: '수정일시', name: 'procDttm', hidden: true },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.search();
},
async getRowGridData() {
let res = [];
res = await this.postApiReturn({
apiKey: 'selectReadObjBaseInfo',
resKey: 'readObjBaseInfoData',
sendParam: {
readObjKind: this.pageData.readObjKind,
useFg: this.pageData.useFg,
readObjNmLike: this.pageData.readObjNm,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
this.setGridData({
gridKey: this.gridName,
value: newRes,
});
this.$nextTick(() => {
if (newRes.length > 0) {
try {
this.$refs[this.gridName].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnNmae: 'readObjId',
setScroll: true,
});
} catch (error) {}
} else {
this.detailDataInit();
}
});
},
async getRowData(data) {
this.setReadObjAddInfo(data);
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
async setReadObjAddInfo(data) {
// 검침 대상 추가 정보 처리
const res = await this.postApiReturn({
apiKey: 'selectReadObjAddInfoList',
resKey: 'readObjAddInfoData',
sendParam: {
comId: data.comId,
blocId: data.blocId,
readObjId: data.readObjId,
},
});
const newRes = res.map(item => {
const newObj = {
...item,
comId: item.comId || '',
readObjId: item.readObjId || '',
addInfoId: item.addInfoId || '',
addInfoDataKind: item.addInfoDataKind || '',
addInfoNumVal: item.addInfoNumVal || '',
addInfoTxtVal: item.addInfoTxtVal || '',
addInfoVal: item.addInfoVal || '',
useFg: item.useFg || '1',
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: newRes,
});
},
gridEditingFinish(data) {
this.$refs[this.gridName].editingFinish(data);
},
detailDataInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: [],
});
},
getSelectedRowStatInfo(data) {
if (data) {
var rowStat = data.rowStat;
if (rowStat === 'I') {
this.tab = 0;
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = true;
}
} else if (rowStat === 'U') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === 'D') {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
} else if (rowStat === null) {
for (var i = 1; i < this.items.length; i++) {
this.items[i].disabledFlag = false;
}
}
}
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
// console.log("this.pageData : ", this.pageData.readObjGrp);
const defaultRow = {
readObjId: '',
readObjNm: '',
readObjKind: this.pageData.readObjKindDetail,
grpCd: this.pageData.readObjGrp,
tjCvrtCoef: '',
toeCvrtCoef: '',
co2CvrtCoef: '',
unitCd: this.pageData.unitCd,
useFg: '1',
};
this.$refs[this.gridName].addRow(defaultRow);
break;
case 'remove':
this.$refs[this.gridName].removeRow();
break;
case 'save':
dataArr = this.$refs[this.gridName].save();
var validCheck = true;
var gridInstance = this.$refs[this.gridName].gridInstance;
var gridData = gridInstance.invoke('getData');
var duplicationCheckList = [
{
cd: 'readObjNm',
nm: '검침 대상 명',
},
];
if (dataArr.length > 0) {
dataArr.filter(item => {
if (item.rowStat === 'I') {
if (item.readObjNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
} else if (item.rowStat === 'U') {
if (item.readObjNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
}
console.log('gridData : ', gridData);
if (!this.duplicationCheck(gridData, duplicationCheckList)) {
validCheck = false;
}
});
if (validCheck) {
const sendParam = {
datas: {
dsReadObjBaseInfo: dataArr.map(item => ({
...item,
useFg: item.useFg ? '1' : '0',
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveReadObjBaseInfo',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
duplicationCheck(data, keyList) {
var result = true;
outer: for (var i = 0; i < keyList.length; i++) {
var checkSet = new Set();
for (var j = 0; j < data.length; j++) {
if (checkSet.has(data[j][keyList[i]['cd']])) {
result = false;
alert(keyList[i]['nm'] + '값이 중복되었습니다.');
break outer;
} else {
checkSet.add(data[j][keyList[i]['cd']]);
}
}
}
return result;
},
},
};
const defaultData = {
/* 검색옵션 */
readObjNm: '',
readObjKind: '',
readObjKindList: [],
readObjKindDetail: '',
readObjKindDetailList: [],
readObjGrp: '',
readObjGrpList: [],
unitCdList: [],
useFg: '1',
useFgList: [],
commGrpCd: '',
commGrpCdNm: '',
addInfoDataKind: '',
addInfoDataKindList: [],
addInfo: '',
addInfoList: [],
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
readObjId: '',
blocId: null,
readObjNm: null,
readObjKind: '',
grpCd: '',
tjCvrtCoef: null,
toeCvrtCoef: null,
co2CvrtCoef: null,
unitCd: '',
useFg: '1',
// rowStat: null
rowStat: 'I',
regDttm: '',
regUserNo: '',
procDttm: '',
procUserNo: '',
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
rowDetailGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
readObjId: '',
addInfoId: null,
addInfoDataKind: null,
addInfoNumVal: null,
addInfoTxtVal: null,
addInfoVal: null,
useFg: '1',
rowStat: null,
},
buttonAuth: {
remove: false,
save: true,
excel: false,
},
},
};
const myDetail = [
{
type: 'InputText',
label: '검침 대상 ID',
valueNm: 'readObjId',
readonly: true,
cols: 6,
class: 'py-2',
required: false,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '검침 대상 명',
valueNm: 'readObjNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
},
{
type: 'SelectBox',
label: '검침 대상 유형',
valueNm: 'readObjKind',
disabled: false,
cols: 6,
class: 'py-2',
list: 'readObjKindDetailList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'SelectBox',
label: '그룹',
valueNm: 'grpCd',
disabled: false,
cols: 6,
class: 'py-2',
list: 'readObjGrpList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'InputText',
label: 'TJ 환산계수',
valueNm: 'tjCvrtCoef',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
},
{
type: 'InputText',
label: 'TOE 환산계수',
valueNm: 'toeCvrtCoef',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
},
{
type: 'InputText',
label: 'CO2 환산계수',
valueNm: 'co2CvrtCoef',
disabled: false,
cols: 6,
class: 'py-2',
inputType: 'number',
},
{
type: 'SelectBox',
label: '단위',
valueNm: 'unitCd',
disabled: false,
cols: 6,
class: 'py-2',
list: 'unitCdList',
itemText: 'commCdNm',
itemValue: 'commCd',
required: true,
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,399 @@
<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="3">
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'검침대상유형'"
dataKey="commCd"
:sendParam="{ commGrpCd: 'CM_MTTTP', useFg: '1' }"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectMttList'"
ref="SelectMttList"
:parentPrgmId="myPrgmId"
:label="'검침대상'"
dataKey="readObjId"
/>
</v-col>
<v-col :cols="3" class="text-right">
<v-btn :ripple="false" @click="search">조회</v-btn>
<BtnExcelDownload
class="mr-1"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
ref="fromPicker"
:is="'Datepicker'"
:parentPrgmId="myPrgmId"
:label="'조회기간'"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<!-- 일일검침정보 목록-->
<v-col :cols="12" class="h100">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-5">
<v-card-title class="custom-title-4 pa-0"
>일일검침정보</v-card-title
>
<div class="d-flex align-center">
<v-btn
:ripple="false"
@click="saveReadResultCloseMngMM()"
class="mr-1"
>월마감</v-btn
>
<v-btn :ripple="false" @click="saveReadResultCloseMng('N')"
>일마감</v-btn
>
</div>
</div>
<div class="px-5" style="height:calc(100% - 76px)">
<div ref="gridParent" class="h100 w100">
<component
:is="loadGrid ? 'Grid' : null"
:ref="gridName"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</div>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import { resize } from '@/mixin/resize.js';
import { mapState, mapMutations, mapActions } from 'vuex';
import Search from '~/components/common/search';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import selectCodeList from '@/components/common/select/selectCodeList';
import SelectMttList from '@/components/common/select/SelectMttList';
import Datepicker from '~/components/common/Datepicker';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
let myTitle;
// const myPrgmId = "PRG0018";
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: {
SelectBlocMstr,
selectCodeList,
SelectMttList,
BtnExcelDownload,
Datepicker,
Search,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
};
},
computed: {
...mapState({
isDarkMode: state => state.isDarkMode,
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocId() {
// 사업장 코드
return this.pageData.blocId;
},
chkCommCd() {
this.setPageData({ sendMttParam: { mttTp: this.pageData.commCd } });
return this.pageData.commCd;
},
chkReadObjId() {
return this.pageData.readObjId;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocId() {
this.setPageData({ isFind: true });
},
chkPlcKind() {
this.setPageData({ isFind: true });
},
chkCommCd() {},
async chkReadObjId(val) {
// console.log("sendMttParam",this.pageData.sendMttParam.mttTp);
// if(this.pageData.sendMttParam.mttTp){
// await this.getRowGridData();
// }
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
created() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.gridInit();
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
},
async search() {
await this.getRowGridData();
},
async getRowGridData() {
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.commCdList.length > 0 &&
this.pageData.readObjIdList.length > 0
) {
const res = await this.postApiReturn({
apiKey: 'selectReadResultCloseMng',
resKey: 'cdKindData',
sendParam: {
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId, // 사업장
mttCd: this.pageData.commCd, // 검침대상유형
mttTp: this.pageData.readObjId, // 검침대상
readDt: this.pageData.fromDt, // 조회기간
},
});
this.setGridData({
gridKey: this.gridName,
value: res.map(item => ({
...item,
mgnf: item.mgnf || 0,
})),
});
}
this.setPageData({ isFind: false });
},
//전월 or 일 마감--------------------------------------------------------------------------------------------
async saveReadResultCloseMng(mnthYn) {
const result = confirm('마감시 기존자료는 삭제됩니다. \n계속하겠습니까?');
if (await result) {
const sendParam = {
datas: {},
params: {
mnthYn: mnthYn,
procIp: '0.0.0.0',
readDt: this.pageData.fromDt,
},
};
await this.postUpdateApi({
apiKey: 'saveReadResultCloseMngSP',
sendParam: sendParam,
});
this.setPageData({ isFind: true });
}
},
async saveReadResultCloseMngMM() {
const result = confirm('마감시 기존자료는 삭제됩니다. \n계속하겠습니까?');
if (await result) {
const sendParam = {
datas: {},
params: {
procIp: '0.0.0.0',
readDt: this.pageData.fromDt,
},
};
await this.postUpdateApi({
apiKey: 'saveReadResultCloseMngSPMM',
sendParam: sendParam,
});
this.setPageData({ isFind: true });
}
},
},
};
const defaultData = {
/* 검색옵션 */
mttTp: '',
mttTpList: [],
sendMttParam: {},
readPlc: '',
readObjId: '',
readObjIdList: [],
commCd: '',
commCdList: [],
cmCycle: 'CYC_HOUR',
blocId: '',
blocMstrList: [],
fromDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'),
isFind: false,
/* data 세팅 - sms 목록 */
rowGrid: {
data: [],
column: [],
option: {},
},
defaultRange: {
CYC_HOUR: 0,
},
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
// 엑셀변환시 데이타 가공이 추가로 필요하게 된다면 여기에 가공된 rowData 를 넣어야 할듯
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
const myColumns = [
{
header: '태그',
name: 'readPlcNm',
width: 300,
},
{
header: '배율',
name: 'distRt',
align: 'right',
formatter({ value }) {
if (value === null) {
return '';
} else {
return value;
}
},
},
{
header: '설비비',
name: 'eccNm',
formatter({ value }) {
if (value === null) {
return '';
} else {
return value;
}
},
},
{
header: '설비배분비율',
name: 'eccDistRt',
align: 'right',
formatter({ value }) {
if (value === null) {
return '';
} else {
return value;
}
},
},
{
header: '금일데이터',
name: 'totVal',
align: 'right',
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
},
{
header: '최종마감시각',
name: 'procDttm',
align: 'center',
formatter({ value }) {
if (value === null) {
return '';
} else {
return value;
}
},
},
];
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,617 @@
<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="3">
<component :is="'SelectBlocMstr'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3">
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'검침대상'"
/>
</v-col>
<v-col :cols="3">
<component :is="'RadioView'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="gridNameTree"
/>
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'DatePicker'"
:label="'기간'"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="4">
<component
:is="'RadioCmCycle'"
:label="'주기'"
:parentPrgmId="myPrgmId"
:labelCols="3"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" :eager="true">
<v-col style="height:100%;">
<v-card class="px-5 py-5">
<div ref="chartParent" id="test2" style="height: 56%;">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="chartName"
ref="treeGridChart"
/>
</div>
<div ref="treeGridParent" id="test" style="height: 44%;">
<component
:ref="gridNameTree"
:is="loadTree ? 'Grid' : null"
:gridName="gridNameTree"
:parentPrgmId="myPrgmId"
@getRowsData="getRowData"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import BtnSearch from '~/components/common/button/BtnSearch';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import SelectEnergy from '@/components/common/select/SelectEnergy';
import DatePicker from '@/components/common/Datepicker';
import RadioCmCycle from '@/components/common/RadioCmCycle';
import RadioView from '@/components/common/RadioView';
import InputText from '@/components/common/input/InputText';
import Grid from '~/components/common/Grid';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Chart from '~/components/common/Chart';
import Utility from '~/plugins/utility';
import dateUtility from '~/plugins/dateUtility';
let myTitle;
//const myPrgmId = "PRG0024";
let myPrgmId;
export default {
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: {
BtnSearch,
SelectBlocMstr,
SelectEnergy,
DatePicker,
RadioCmCycle,
RadioView,
InputText,
Grid,
Chart,
BtnExcelDownload,
},
data() {
return {
myPrgmId: myPrgmId,
loadTree: false,
loadChart: false,
gridNameTree: 'treeGrid',
chartName: 'treeGridChart',
defaultRowKey: 1,
selRowKey: null,
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkViewCheck() {
return this.pageData.viewCheck;
},
chkBlocCd() {
// 사업장 코드
return this.pageData.blocId;
},
chkCmCycle() {
return this.pageData.cmCycle;
},
chkEnergyCd() {
// 에너지 선택 여부 감지
return this.pageData.energyCd;
},
selectedCommCdData() {
return this.pageData.selectedCommCdData;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
this.setPageData({ isFind: true });
},
chkViewCheck() {
this.setView(this.pageData.viewCheck);
},
chkEnergyCd() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
gridInit() {
const treeGridHeight = this.$refs.treeGridParent.offsetHeight - 36;
const myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
},
columnOptions: {
//frozenCount : 1,
minWidth: 100,
resizable: true,
},
scrollX: true,
};
this.setGridOption({
gridKey: this.gridNameTree,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.getTreeData();
},
//메뉴 리스트
async getTreeData() {
this.loadTree = false;
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
const res = await this.postApiReturn({
apiKey: 'selectReadResultRet',
resKey: 'readPlcData',
// sendParm : sendParams
sendParam: {
sh_readObjId: this.pageData.energyList[this.chkEnergyCd].cd,
// sh_mttTp: "MTT00001",
sh_searchType:
this.pageData.cmCycle == 'CYC_YEAR'
? 'month'
: this.pageData.cmCycle == 'CYC_MONTH'
? 'day'
: 'time',
sh_date:
this.pageData.cmCycle == 'CYC_YEAR'
? this.pageData.fromDt
: this.pageData.cmCycle == 'CYC_MONTH'
? Utility.setFormatDate(this.pageData.fromDt, 'YYYY/MM')
: Utility.setFormatDate(this.pageData.fromDt, 'YYYY/MM/DD'),
// sh_blocCd:"BL0001"
sh_blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
},
});
let columnList = [
{
header: '개소',
name: 'readPlcNm',
width: 300,
},
{
header: 'readPlc',
name: 'readPlc',
hidden: true,
},
{
header: 'upReadPlc',
name: 'upReadPlc',
hidden: true,
},
];
switch (this.pageData.cmCycle) {
case 'CYC_YEAR':
for (var i = 1; i < 13; i++) {
var tempObj = {
header:
Utility.setFormatDate(this.pageData.fromDt, 'YYYY') +
'/' +
String(i).padStart(2, '0'),
name: 'qty' + String(i - 1).padStart(2, '0'),
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
align: 'right',
excelType: 'number',
excelFormatter: '2',
};
columnList.push(tempObj);
}
break;
case 'CYC_MONTH':
for (
var i = 1;
i <= dateUtility.getLastDay('D', this.pageData.fromDt);
i++
) {
var tempObj = {
header:
Utility.setFormatDate(this.pageData.fromDt, 'MM') +
'/' +
String(i).padStart(2, '0'),
name: 'qty' + String(i - 1).padStart(2, '0'),
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
align: 'right',
excelType: 'number',
excelFormatter: '2',
};
columnList.push(tempObj);
}
break;
case 'CYC_DAY':
for (var i = 0; i < 24; i++) {
var tempObj = {
header: String(i).padStart(1, '0') + '시',
name: 'qty' + String(i).padStart(2, '0'),
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
align: 'right',
excelType: 'number',
excelFormatter: '2',
};
columnList.push(tempObj);
}
break;
}
this.setGridColumn({
gridKey: this.gridNameTree,
value: columnList,
});
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC',
isId: true,
value: res.map(item => ({
...item,
readPlc: item.readPlcId,
})),
});
this.xlsDataBind(res);
await this.setGridData({
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
// setTreeData["ROOT"][0]['_attributes'] = {expanded : true};
// this.$refs["treeGrid"].expandAll();
this.loadTree = true;
this.$nextTick(() => {
if (setTreeData != null) {
this.$refs[this.gridNameTree].focus({
// rowKey: this.chkRowGridSelectKey || 0,
rowKey:
this.selRowKey != null ? this.selRowKey : this.defaultRowKey,
setScroll: true,
});
}
});
this.setChartData([]);
this.loadChart = true;
}
},
async setChartData(data) {
let xAxisData = [];
let seriesData = [];
let tmpList = [];
let series = {};
let exceptionColumList = ['개소', 'readPlc', 'upReadPlc'];
const myKey = this.pageData[this.gridNameTree].column.filter(v => {
return !exceptionColumList.includes(v.header);
});
tmpList = Object.values(data);
tmpList.shift();
series.name = tmpList.shift();
series.type = 'bar';
series.data = tmpList;
xAxisData = myKey.map(obj => obj.header);
seriesData.push(series);
var option = {
xAxis: {
data: xAxisData,
},
yAxis: {
type: 'value',
name: this.pageData.energyList[this.pageData.energyCd].unit,
nameLocation: 'middle',
nameGap: 40,
},
legend: {
xtStyle: {
color: '#95A0A9',
fontSize: 10,
},
},
series: seriesData,
};
this.setChartOption({ chartKey: this.chartName, value: option });
},
async getRowData(data) {
this.loadChart = false;
this.selRowKey = data.rowKey;
let length =
this.pageData.cmCycle == 'CYC_YEAR'
? 12
: this.pageData.cmCycle == 'CYC_MONTH'
? 31
: 24;
var pageDataObj = {
readPlc: data.readPlc,
readPlcNm: data.readPlcNm,
};
for (var i = 0; i < length; i++) {
if (data['qty' + String(i).padStart(2, '0')] == null) {
data['qty' + String(i).padStart(2, '0')] = 0;
}
pageDataObj['qty' + String(i).padStart(2, '0')] =
data['qty' + String(i).padStart(2, '0')];
}
this.setChartData(pageDataObj);
this.loadChart = true;
},
async setView(value) {
switch (value) {
case 'viewAll':
this.loadTree = false;
this.loadChart = false;
this.$refs.treeGridParent.style.height = '44%';
this.$refs.chartParent.style.height = '56%';
this.gridInit();
this.loadChart = true;
break;
case 'viewGrid':
this.loadChart = false;
this.$refs.chartParent.style.height = '0%';
this.$refs.treeGridParent.style.height = '100%';
this.gridInit();
break;
case 'viewChart':
this.loadTree = false;
this.loadChart = true;
this.$refs.chartParent.style.height = '100%';
this.$refs.treeGridParent.style.height = '0%';
break;
}
this.isFind = true;
},
async search() {
await this.getTreeData();
await this.setPageData({
isFind: false,
});
},
xlsDataBind(res) {
const xlsRowData = res.map(item => {
const obj = {
...item,
useFg: item.useFg == '1' ? '사용' : '사용안함',
prgmTpCd: item.prgmTpCd == '1' ? '프로그램' : '팝업',
};
return obj;
});
this.setPageData({
xlsFileInfo: {
[this.gridNameTree]: {
rowData: xlsRowData,
},
},
});
},
},
};
const defaultData = {
/* 검색옵션 */
readPlc: '',
energyCd: 'MTT00001',
energyList: [],
blocId: null,
blocMstrList: [],
defaultRange: {
CYC_YEAR: 0,
CYC_MONTH: 0,
CYC_DAY: 0,
},
cmCycle: 'CYC_DAY',
viewCheck: 'viewAll',
fromDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'), // 조회 시작일
// cmCycleList:[],
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
/* data 세팅 */
treeGrid: {
data: [],
column: [],
option: {},
},
/*chartdata 세팅 */
treeGridChart: Utility.defaultChartOption(true),
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
treeGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>
//
<style scoped lang="scss">
// ::v-deep {
// .tui-grid {
// &-row-odd,
// &-row-even {
// .tui-grid-cell {
// .tui-grid-tree-depth i {
// width: 10px !important;
// height: 6px !important;
// background: url("@/assets/images/ico_grid_open.png")
// no-repeat
// center /
// 100%
// auto !important;
// }
// &.tui-grid-cell-has-tree {
// .tui-grid-tree-extra-content + .tui-grid-cell-content {
// position: relative;
// &:before {
// content: "";
// width: 10px !important;
// height: 8px !important;
// display: inline-block;
// margin-right: 6px;
// background: url("@/assets/images/ico_grid_list.png")
// no-repeat
// center /
// 100%
// auto !important;
// vertical-align: middle;
// }
// }
// [class*="tui-grid-tree-button-"] + .tui-grid-cell-content {
// &:before {
// content: none;
// }
// }
// }
// }
// &:hover {
// .tui-grid-cell {
// background-color: #1a4e87;
// .tui-grid-tree-depth i {
// background-image: url("@/assets/images/ico_grid_open_active.png") !important;
// }
// .tui-grid-cell-content {
// color: map-deep-get($config, "dark", "activate");
// &:before {
// background-image: url("@/assets/images/ico_grid_list_active.png") !important;
// }
// }
// }
// }
// }
// &-cell-current-row {
// .tui-grid-cell {
// .tui-grid-tree-depth i {
// background-image: url("@/assets/images/ico_grid_open_active.png") !important;
// }
// .tui-grid-cell-content {
// color: map-deep-get($config, "dark", "activate");
// &:before {
// background-image: url("@/assets/images/ico_grid_list_active.png") !important;
// }
// }
// }
// }
// }
// }
//
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,895 @@
<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="3">
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'에너지'"
/>
</v-col>
<v-col :cols="3">
<component :is="'SelectCmCycle2'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col cols="3" class="d-flex justify-end align-center">
<BtnSearch @click="search" class="mr-1" />
<BtnExcelDownload :parentPrgmId="myPrgmId" :gridName="gridName" />
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col cols="3">
<v-row class="search-box" align="center" no-gutters>
<v-col cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
기준일
</label>
</v-col>
<v-col cols="7">
<v-text-field
id="startpicker"
ref="startpicker"
v-model="fromDtValue"
:class="'v-input__custom'"
readonly
outlined
:hide-details="true"
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="startpicker-container"
id="startpicker-container"
></div>
</template>
</v-text-field>
</v-col>
</v-row>
</v-col>
<v-col cols="3">
<v-row class="search-box">
<v-col cols="4">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
비교일
</label>
</v-col>
<v-col cols="7">
<v-text-field
id="endpicker"
ref="endpicker"
v-model="toDtValue"
:class="'v-input__custom'"
readonly
outlined
:hide-details="true"
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="endpicker-container"
id="endpicker-container"
></div>
</template>
</v-text-field>
</v-col>
</v-row>
</v-col>
<v-col cols="6">
<component
:is="'SelectReadPlcPop'"
:parentPrgmId="myPrgmId"
:label="'비교대상'"
:textFieldLength="6"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="height: 60%;">
<v-card class="pa-5">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="'rowGridChart'"
ref="rowGridChart"
/>
</v-card>
</v-col>
<v-col :cols="12" style="height: 40%;">
<v-card class="pb-5">
<v-card-title class="justify-end caption text-color--non-activate"
>단위 : {{ unit }}</v-card-title
>
<div ref="gridParent" class="px-5" style="height: calc(100% - 70px)">
<component
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
ref="rowGrid"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
// import SelectBlocMstr from "@/components/common/select/SelectBlocMstr";
// import SelectEnergy from "@/components/common/select/SelectEnergy";
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import SelectCmCycle from '@/components/common/select/SelectCmCycle';
import SelectCmCycle2 from '@/components/common/select/SelectCmCycle2';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Utility from '~/plugins/utility';
import TuiDatepicker from 'tui-date-picker';
import SelectReadPlcPop from '~/components/common/modal/OutSideWeatherPlcMultiPop';
import Chart from '~/components/common/Chart';
let myTitle;
let myPrgmId;
export default {
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: {
Grid,
SelectBlocMstr,
SelectEnergy,
SelectCmCycle,
SelectCmCycle2,
BtnSearch,
BtnExcelDownload,
Utility,
TuiDatepicker,
SelectReadPlcPop,
Chart,
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'rowGrid',
loadGrid: false,
loadChart: false,
unit: '',
apiKey: 'selectSameReadPlcMonth',
startDatepickerInstance: null,
endDatepickerInstance: null,
startDtValue: null,
endDtValue: null,
timePicker: false,
datePickerSearchFlag: 3,
};
},
created() {
const today = Utility.setFormatDate('today', 'YYYY-MM-DD');
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
// chkCmCycle(){
myCmCycle() {
return this.pageData.cmCycle;
},
chkBlocCd() {
// 사업장 선택 감지
return this.pageData.blocId;
},
chkEnergyCd() {
// 에너지 선택 감지
return this.pageData.energyCd;
},
chkFacInfo() {
// 공정/설비 변경 감지
return this.pageData.facInfo;
},
// datepicker_computed[시작]
myOptions() {
let returnObj = {};
switch (this.myCmCycle) {
case 'CYC_MONTH':
returnObj = {
type: 'year',
viewFormat: 'YYYY',
pickerFormat: 'YYYY',
sendFormat: 'YYYY',
};
break;
case 'CYC_WEEK':
returnObj = {
type: 'date',
viewFormat: 'YYYY-MM-DD',
pickerFormat: 'YYYY-MM-dd',
sendFormat: 'YYYYMMDD',
};
break;
case 'CYC_DAY':
returnObj = {
type: 'month',
viewFormat: 'YYYY-MM',
pickerFormat: 'yyyy-MM',
sendFormat: 'YYYYMM',
};
break;
case 'CYC_HOUR':
returnObj = {
type: 'date',
viewFormat: 'YYYY-MM-DD' + (this.timePicker ? ' HH:mm:ss' : ''),
pickerFormat: 'yyyy-MM-dd' + (this.timePicker ? ' HH:mm A' : ''),
sendFormat: this.timePicker ? 'YYYY-MM-DD HH:mm:ss' : 'YYYYMMDD',
};
// returnObj = { type: "day", format: "YYYY-MM-DD HH:mm:ss" };
break;
default:
break;
}
return returnObj;
},
fromDtValue() {
return this.startDtValue;
},
toDtValue() {
return this.endDtValue;
},
// datepicker_computed[끝]
initFlag() {
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
myCmCycle: function() {
this.datePickerSearchFlag = 2;
var day1 = new Date();
var day2 = new Date();
if (this.myCmCycle == 'CYC_MONTH') {
day2.setFullYear(day1.getFullYear() - 1);
} else if (this.myCmCycle == 'CYC_WEEK') {
day2.setDate(day1.getDate() - 7);
} else if (this.myCmCycle == 'CYC_DAY') {
day2.setMonth(day1.getMonth() - 1);
} else if (this.myCmCycle == 'CYC_HOUR') {
day2.setDate(day1.getDate() - 1);
}
this.startDtValue = setDateWithFormat(day1, this.myOptions.type);
this.endDtValue = setDateWithFormat(day2, this.myOptions.type);
this.startDatepickerInstance.setDate(this.startDtValue);
this.endDatepickerInstance.setDate(this.endDtValue);
this.startDatepickerInstance.setDate(new Date(this.fromDtValue));
this.endDatepickerInstance.setDate(new Date(this.toDtValue));
this.startDatepickerInstance.setType(this.myOptions.type);
this.endDatepickerInstance.setType(this.myOptions.type);
// this.setPageData({ isFind: true });
},
chkBlocCd() {
// this.setPageData({ isFind: true });
},
chkEnergyCd() {
// this.setPageData({ isFind: true });
this.initUnit();
},
chkFacInfo() {
if (this.initFlag == true) {
this.setPageData({ isFind: true });
}
// this.setPageData({ isFind: true });
},
// datepicker_watch[시작]
fromDtValue(newVal, oldVal) {
this.datePickerSearchFlag--;
if (this.datePickerSearchFlag == 0) {
this.datePickerSearchFlag = 1;
this.setPageData({ isFind: true });
}
},
toDtValue(newVal, oldVal) {
this.datePickerSearchFlag--;
if (this.datePickerSearchFlag == 0) {
this.datePickerSearchFlag = 1;
this.setPageData({ isFind: true });
}
},
// datepicker_watch[끝]
initFlag(val) {
if (val) {
this.init();
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {},
mounted() {
this.tuiCalendarInit();
// this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartXAxisData: 'setChartXAxisData',
setChartSeries: 'setChartSeries',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
setLocalStorage() {
if (this.pageData.energyCd !== '' && this.pageData.energyCd != null) {
localStorage.setItem(
myPrgmId + 'SelectedEnergyCd',
this.pageData.energyCd,
);
}
if (this.pageData.blocId !== '' && this.pageData.blocId != null) {
localStorage.setItem(myPrgmId + 'SelectedBlocCd', this.pageData.blocId);
}
},
tuiCalendarInit() {
const startContainer = document.getElementById('startpicker-container');
const startTarget = document.getElementById('startpicker');
const endContainer = document.getElementById('endpicker-container');
const endTarget = document.getElementById('endpicker');
// datepicker 초기값 생성
var day1 = new Date();
var day2 = new Date();
day2.setFullYear(day1.getFullYear() - 1);
this.startDtValue = setDateWithFormat(day1, 'year');
this.endDtValue = setDateWithFormat(day2, 'year');
this.pageData.cmCycle = 'CYC_MONTH';
// datepicker 초기값 생성 끝
// datepicker 생성
this.startDatepickerInstance = new TuiDatepicker(startContainer, {
date: day1,
language: 'ko',
type: this.myOptions.type,
input: {
element: startTarget,
format: this.myOptions.pickerFormat,
},
timePicker: this.timePicker,
});
// datepicker 생성
this.endDatepickerInstance = new TuiDatepicker(endContainer, {
date: day2,
language: 'ko',
type: this.myOptions.type,
input: {
element: endTarget,
format: this.myOptions.pickerFormat,
},
timePicker: this.timePicker,
});
// datepicker 생성 끝
// datepicker 변경시 이벤트 추가
this.startDatepickerInstance.on('change', () => this.getStartDt());
this.endDatepickerInstance.on('change', () => this.getEndDt());
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
async search() {
this.setLocalStorage();
await this.getGridDatas();
},
async initUnit() {
this.unit = this.pageData.energyList[this.pageData.energyCd].unit;
},
async gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const myOptions = {};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
await this.getGridDatas();
this.initUnit();
},
async getGridDatas() {
this.loadChart = false;
this.pageData.rowGrid.data = [];
var res = [];
var apiKeymapper = {
CYC_MONTH: 'selectSameReadPlcMonth',
CYC_WEEK: 'selectSameReadPlcWeek',
CYC_DAY: 'selectSameReadPlcDay',
CYC_HOUR: 'selectSameReadPlcTime',
};
this.apiKey = apiKeymapper[this.pageData.cmCycle];
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
const selectFacInfo = this.pageData.facInfo;
const sendParams = {
blocId: this.pageData.blocMstrList[this.chkBlocCd].blocId, //"BL0001",
readPlc: selectFacInfo.readPlc,
readPlcNm: selectFacInfo.readPlcNm,
sh_baseDt: this.fromDtValue.replaceAll('-', ''),
sh_compareDt: this.toDtValue.replaceAll('-', ''),
};
this.loadGrid = false;
res = await this.postApiReturn({
apiKey: this.apiKey,
resKey: 'sameReadPlcData',
sendParam: sendParams,
});
} else {
this.setPageData({ isFind: false });
}
let myColumns = [{ header: '구분', name: 'readPlcNm', align: 'center' }];
let timeList = [
{
header: '연도',
name: 'date',
align: 'center',
formatter({ value }) {
if (String(value).length == 4) {
return value + '년';
} else {
return value;
}
},
},
{
header: '주차',
name: 'week',
align: 'center',
formatter({ value }) {
return value;
},
},
{
header: '월',
name: 'date',
align: 'center',
formatter({ value }) {
if (String(value).length == 6) {
return value.substr(0, 4) + '/' + value.substr(4, 2);
} else {
return value;
}
},
},
{
header: '일',
name: 'date',
align: 'center',
formatter({ value }) {
if (String(value).length == 8) {
return (
value.substr(0, 4) +
'/' +
value.substr(4, 2) +
'/' +
value.substr(6, 2)
);
} else {
return value;
}
},
},
];
switch (this.pageData.cmCycle) {
case 'CYC_MONTH':
myColumns.push(timeList[0]);
for (var i = 1; i < 13; i++) {
var tempObject = {
header: i + '월',
name: 'corrVal' + String(i).padStart(2, '0'),
// width : 150,
align: 'right',
formatter: numberFormatter,
};
myColumns.push(tempObject);
}
break;
case 'CYC_WEEK':
myColumns.push(timeList[1]);
var headerList = [
'일요일',
'월요일',
'화요일',
'수요일',
'목요일',
'금요일',
'토요일',
];
for (var i = 1; i < 8; i++) {
var tempObject = {
header: headerList[i - 1],
name: 'corrVal' + String(i).padStart(2, '0'),
// width : 150,
align: 'right',
formatter: numberFormatter,
};
myColumns.push(tempObject);
}
break;
case 'CYC_DAY':
myColumns.push(timeList[2]);
for (var i = 1; i < 32; i++) {
var tempObject = {
header: i + '일',
name: 'corrVal' + String(i).padStart(2, '0'),
// width : 150,
align: 'right',
formatter: numberFormatter,
};
myColumns.push(tempObject);
}
break;
case 'CYC_HOUR':
myColumns.push(timeList[3]);
for (var i = 0; i < 24; i++) {
var tempObject = {
header: i + '시',
name: 'corrVal' + String(i).padStart(2, '0'),
// width : 70,
align: 'right',
formatter: numberFormatter,
};
myColumns.push(tempObject);
}
break;
}
myColumns.push({
header: '합계',
name: 'corrVal',
width: 50,
align: 'right',
});
if (res.length >= 1) {
// 기준일 <-> 비교일 순서 보정[시작]
var tempRes = [...res];
var tempIdx;
res = [];
for (var i = 0; i < tempRes.length ? tempRes.length : 0; i++) {
if (tempRes[i].date == this.toDtValue.replaceAll('-', '')) {
res.push({ ...tempRes[i] });
} else {
tempIdx = i;
}
}
if (typeof tempIdx == 'number') {
res.push({ ...tempRes[tempIdx] });
}
// 기준일 <-> 비교일 순서 보정[끝]
var sumData = {
readPlcNm: res[0].readPlcNm,
};
var columnList = Object.keys(res[0]);
columnList = columnList.filter(item => item.startsWith('corrVal'));
switch (this.pageData.cmCycle) {
case 'CYC_MONTH':
sumData[timeList[0].name] = '차이(기준-비교)';
break;
case 'CYC_WEEK':
sumData[timeList[1].name] = '차이(기준-비교)';
break;
case 'CYC_DAY':
sumData[timeList[2].name] = '차이(기준-비교)';
break;
case 'CYC_HOUR':
sumData[timeList[3].name] = '차이(기준-비교)';
break;
}
if (res.length >= 2) {
for (var i = 0; i < columnList.length; i++) {
sumData[columnList[i]] = res[0][columnList[i]];
}
for (var i = 0; i < columnList.length; i++) {
sumData[columnList[i]] =
Math.round(
(sumData[columnList[i]] - res[1][columnList[i]]) * 100,
) / 100;
}
} else {
for (var i = 0; i < columnList.length; i++) {
sumData[columnList[i]] = res[0][columnList[i]];
}
}
res.push(sumData);
Object.assign(res[0], {
_attributes: { rowSpan: { readPlcNm: res.length } },
});
}
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
this.loadGrid = true;
this.setPageData({ isFind: false });
this.setChartData(res);
},
async setChartData(data) {
let copiedData = [...data];
let xAxisData = [];
let seriesData = [];
this.$store.state.pageData[this.myPrgmId].rowGridChart.series = [];
if (!data.length) {
return;
}
let tmpLsit = [];
let exceptionColumList = [
'구분',
'연도',
'월',
'주차',
'월',
'일',
'합계',
];
const myKey = this.pageData[this.gridName].column.filter(v => {
return !exceptionColumList.includes(v.header);
});
copiedData.pop();
tmpLsit = copiedData.map(item => ({
// name: item.plcNm,
name: item.date,
type: 'line',
data: myKey.map(obj => item[obj.name] || 0),
}));
xAxisData = myKey.map(obj => obj.header);
seriesData = tmpLsit;
// this.setChartXAxisData({ chartKey: "rowGridChart", value: xAxisData });
// this.setChartSeries({ chartKey: "rowGridChart", value: seriesData });
var chartOption = {
legend: {
top: 'center',
left: 'right',
orient: 'vertical',
textStyle: {
color: '#95A0A9',
fontSize: 10,
},
},
grid: {
top: '3%',
right: '8%',
},
yAxis: {
type: 'value',
nameLocation: 'middle',
nameGap: 40,
name: this.unit,
},
xAxis: {
data: xAxisData,
},
series: seriesData,
};
this.setChartOption({ chartKey: 'rowGridChart', value: chartOption });
this.loadChart = true;
},
getStartDt() {
const dt = this.startDatepickerInstance.getDate();
this.startDtValue = setDateWithFormat(dt, this.myOptions.type);
},
getEndDt() {
const dt = this.endDatepickerInstance.getDate();
this.endDtValue = setDateWithFormat(dt, this.myOptions.type);
},
},
};
const defaultData = {
/* 검색옵션 */
isMulti: false,
isFind: false,
blocId: null,
blocMstrList: [],
energyCd: null,
energyList: [],
cmCycle: 'CYC_MONTH', // 주기
cmCycleList: [
{ idx: 0, text: '월', value: 'CYC_MONTH' },
{ idx: 1, text: '주', value: 'CYC_WEEK' },
{ idx: 2, text: '일', value: 'CYC_DAY' },
{ idx: 3, text: '시간', value: 'CYC_HOUR' },
],
defaultRange: {
CYC_MONTH: 12,
CYC_WEEK: 7,
CYC_DAY: 31,
CYC_HOUR: 0,
},
fromDt: '',
toDt: '',
dateFormat: {
CYC_MONTH: 'YYYY',
CYC_WEEK: 'YYYY-MM-DD',
CYC_DAY: 'YYYY-MM',
CYC_HOUR: 'YYYY-MM-DD',
},
tableId: null,
gridId: null,
facInfo: {},
modalData: {},
rowGrid: {
data: [],
option: {}, // myOptions
column: [], // myColumns,
},
rowGridChart: Utility.defaultChartOption(true),
xlsFileInfo: {
rowGrid: {
fileName: null,
sheetName: null,
},
},
};
function setDateWithFormat(date, format) {
var formattedDate = null;
if (typeof date == 'string') {
formattedDate = date;
} else if (typeof date == 'object') {
formattedDate = String(date.toISOString());
}
if (format == 'year') {
formattedDate = formattedDate.substr(0, 4);
} else if (format == 'month') {
formattedDate = formattedDate.substr(0, 7);
} else if (format == 'date') {
formattedDate = formattedDate.substr(0, 10);
}
return formattedDate;
}
function numberFormatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
}
function myLogger(msg, caller) {
if (caller) {
}
if (msg.title) {
}
if (msg.content) {
}
if (typeof msg === 'string') {
}
}
</script>
<style lang="scss" scoped>
#startpicker-container,
#endpicker-container {
position: relative;
z-index: 20;
}
.v-input__custom {
flex: 0 0 auto;
&.half {
width: calc(50% - 20px);
}
}
::v-deep {
.tui-timepicker-row {
display: flex;
justify-content: space-around;
background-color: #edf4fc;
.tui-timepicker-column.tui-timepicker-colon {
color: #000 !important;
}
}
}
</style>

View File

@ -0,0 +1,694 @@
<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="3">
<component
:is="'SelectBlocMstr'"
ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="3">
<component
label="에너지"
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
/>
</v-col>
<v-col :cols="3">
<!-- 구분(사용량, 비용) -->
<component :is="'RadioUseCost'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<component :is="'SelectCmCycle'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3">
<!-- 조회기간 -->
<DatePicker :parentPrgmId="myPrgmId" :label="'조회기간'" />
</v-col>
<v-col :cols="4">
<!-- 공정/설비 -->
<component
label="비교대상"
:is="'FtnPlcMultiPop'"
:parentPrgmId="myPrgmId"
:labelCols="3"
:textCols="9"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" style="height: calc(100vh - 230px)">
<v-col>
<v-card>
<div ref="chartParent" style="height: 65%">
<component
class="w100 h100"
ref="chart1"
:is="loadChart1 ? 'Chart' : null"
:chartName="chartName"
:parentPrgmId="myPrgmId"
/>
</div>
<v-card-title>
<!-- 차트와 그리드 사이 공백을 위한 공간 -->
</v-card-title>
<div ref="gridParent" class="px-5" style="height: 28%">
<component
class="w100 h100"
ref="grid1"
:is="loadGrid1 ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import SelectCmCycle from '@/components/common/select/SelectCmCycle';
import SelectDate from '~/components/common/select/SelectDate';
import SelectDateVc from '~/components/common/select/SelectDateVc';
import DatePicker from '~/components/common/Datepicker';
import FtnPlcMultiPop from '~/components/common/modal/FtnPlcMultiPop2';
import InputText from '@/components/common/input/InputText';
import RadioUseCost from '~/components/common/RadioUseCost';
import Utility from '~/plugins/utility';
import dateUtility from '~/plugins/dateUtility';
import Grid from '~/components/common/Grid';
import Chart from '~/components/common/Chart';
let myTitle;
let myPrgmId;
export default {
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: {
BtnSearch,
BtnExcelDownload,
SelectBlocMstr,
SelectEnergy,
SelectCmCycle,
SelectDate,
SelectDateVc,
RadioUseCost,
DatePicker,
FtnPlcMultiPop,
InputText,
Utility,
dateUtility,
Grid,
Chart,
},
data() {
return {
myPrgmId: myPrgmId,
myGrid: null,
gridName: 'grid1',
chartName: 'chart1',
loadGrid1: false,
loadChart1: false,
apiKey: 'selectSameTermReadHour',
unit: '',
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
rdbUseCost: {
get() {
return this.pageData[this.parentPrgmId].rdbUseCost;
},
set(value) {
return this.setPageData({ rdbUseCost: value });
},
},
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocCd() {
// 사업장 선택 감지
return this.pageData.blocId;
},
chkEnergyCd() {
// 에너지 선택 감지
return this.pageData.energyCd;
},
chkFacInfo() {
// 공정/설비 변경 감지
return this.pageData.facInfoList;
},
chkCmCycle() {
// 주기 변경 감지
return this.pageData.cmCycle;
},
chkRadio() {
// 구분: 사용량, 비용 선택 감지
return this.pageData.rdbUseCost;
},
initFlag() {
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
//지우지말자
},
chkEnergyCd() {
this.initUnit();
},
chkFacInfo() {
this.setPageData({ isFind: true });
},
chkRadio() {
this.initUnit();
this.setPageData({ isFind: true });
},
initFlag(val) {
if (val) {
this.init();
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartXAxisData: 'setChartXAxisData',
setChartSeries: 'setChartSeries',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
init() {
this.layoutInit();
this.gridInit();
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
async search() {
await this.getRowGridData();
if (this.pageData.energyCd !== '' && this.pageData.energyCd != null) {
localStorage.setItem(
myPrgmId + 'SelectedEnergyCd',
this.pageData.energyCd,
);
}
if (this.pageData.blocId !== '' && this.pageData.blocId != null) {
localStorage.setItem(myPrgmId + 'SelectedBlocCd', this.pageData.blocId);
}
},
initUnit() {
this.unit =
this.pageData.energyList.length > 0 && this.pageData.rdbUseCost == 'use'
? this.pageData.energyList[this.pageData.energyCd].unit
: '원';
},
gridInit() {
setTimeout(() => {
const gridHeight = this.$refs.gridParent.offsetHeight - 46;
const myOptions = {
setScroll: true,
columnOptions: {
//frozenCount: 3,
minWidth: 100,
resizable: true,
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(
Utility.defaultGridOption(gridHeight),
myOptions,
),
});
this.getRowGridData();
this.initUnit();
});
},
async getRowGridData() {
this.loadGrid1 = false;
this.loadChart1 = false;
this.pageData.grid1.data = [];
var url = {};
if (this.pageData.cmCycle == 'CYC_YEAR') {
url =
this.pageData.rdbUseCost == 'use'
? 'selectSameTermReadYear'
: 'selectSameTermReadYearCost';
} else if (this.pageData.cmCycle == 'CYC_MONTH') {
url =
this.pageData.rdbUseCost == 'use'
? 'selectSameTermReadMonth'
: 'selectSameTermReadMonthCost';
} else if (this.pageData.cmCycle == 'CYC_DAY') {
url =
this.pageData.rdbUseCost == 'use'
? 'selectSameTermReadDay'
: 'selectSameTermReadDayCost';
} else {
url =
this.pageData.rdbUseCost == 'use'
? 'selectSameTermReadHour'
: 'selectSameTermReadHourCost';
}
this.apiKey = url;
var temp = [],
temp2 = [],
res = [];
const facInfoList = this.pageData.facInfoList;
if (facInfoList.length > 0) {
for (var i = 0; i < facInfoList.length; i++) {
temp.push(facInfoList[i].eccId);
temp2.push(facInfoList[i].eccNm);
}
}
let myColumns = [
{ header: '번호', name: 'rowNum', align: 'center', width: 50 },
{ header: '에너지', name: 'readObjNm', align: 'center', width: 100 },
{ header: '구분', name: 'eccNm', align: 'left', width: 150 },
];
switch (this.pageData.cmCycle) {
case 'CYC_YEAR':
var dateDiff =
dateUtility.diff(this.pageData.fromDt, this.pageData.toDt, 'y') + 1;
for (var i = 0; i < 10; i++) {
if (i < dateDiff) {
var tempObject = {
header: dateUtility.addYear(i, 'YYYY', this.pageData.fromDt),
name: 'qty' + String(i).padStart(2, '0'),
align: 'right',
width: 100,
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
};
myColumns.push(tempObject);
}
}
break;
case 'CYC_MONTH':
var dateDiff =
dateUtility.diff(this.pageData.fromDt, this.pageData.toDt, 'm') + 2;
for (var i = 1; i < 13; i++) {
if (i < dateDiff) {
var tempObject = {
header: dateUtility.addMonth(
i - 1,
'YYYY/MM',
this.pageData.fromDt,
),
name: 'qty' + String(i).padStart(2, '0'),
align: 'right',
width: 100,
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
};
myColumns.push(tempObject);
}
}
break;
case 'CYC_DAY':
var dateDiff =
dateUtility.diff(this.pageData.fromDt, this.pageData.toDt) + 2;
for (var i = 1; i < 32; i++) {
if (i < dateDiff) {
var tempObject = {
header: dateUtility.addDate(
i - 1,
'MM/DD',
this.pageData.fromDt,
),
name: 'qty' + String(i).padStart(2, '0'),
align: 'right',
width: 100,
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
};
myColumns.push(tempObject);
}
}
break;
case 'CYC_HOUR':
for (var i = 0; i < 24; i++) {
var tempObject = {
header: i + '시',
name: 'qty' + String(i).padStart(2, '0'),
align: 'right',
width: 100,
excelType: 'number',
excelFormatter: '2',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
};
myColumns.push(tempObject);
}
break;
}
var qtyList = [];
for (i = 0; i < myColumns.length - 3; i++) {
if (this.pageData.cmCycle == 'CYC_YEAR') {
var val = parseInt(this.pageData.fromDt) + i;
var val2 = 'QTY' + String(i).padStart(2, '0');
qtyList.push({ qty: val, as: val2 });
} else if (this.pageData.cmCycle == 'CYC_MONTH') {
var val =
this.pageData.fromDt.substr(0, 4) +
'-' +
this.pageData.fromDt.substr(4, 2);
var val1 = new Date(val);
val1.setMonth(val1.getMonth() + i);
var val2 = val1
.toISOString()
.replaceAll('-', '')
.substr(0, 4);
var val3 = val1
.toISOString()
.replaceAll('-', '')
.substr(4, 2);
var val4 = 'QTY' + String(i + 1).padStart(2, '0');
qtyList.push({ qtyY: val2, qtyM: val3, as: val4 });
} else if (this.pageData.cmCycle == 'CYC_DAY') {
var val =
this.pageData.fromDt.substr(0, 4) +
'-' +
this.pageData.fromDt.substr(4, 2) +
'-' +
this.pageData.fromDt.substr(6, 2);
var val1 = new Date(val);
val1.setDate(val1.getDate() + i);
var val2 =
val1
.toISOString()
.replaceAll('-', '')
.substr(0, 4) +
val1
.toISOString()
.replaceAll('-', '')
.substr(4, 2) +
val1
.toISOString()
.replaceAll('-', '')
.substr(6, 2);
var val3 = 'QTY' + String(i + 1).padStart(2, '0');
qtyList.push({ qty: val2, as: val3 });
} else {
qtyList = [];
}
}
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
const sendParams = {
blocId: this.pageData.blocMstrList[this.chkBlocCd].blocId,
sh_blocCd:
this.pageData.cmCycle == 'CYC_DAY'
? this.pageData.blocMstrList[this.chkBlocCd].blocId
: null,
cbEnrgCd: this.pageData.energyList[this.chkEnergyCd].cd,
readObjId: this.pageData.energyList[this.chkEnergyCd].cd,
cmCycle:
this.pageData.cmCycle == 'CYC_YEAR'
? 'year'
: this.pageData.cmCycle == 'CYC_MONTH'
? 'month'
: this.pageData.cmCycle == 'CYC_DAY'
? 'day'
: 'hour',
eqpmId: temp,
eqpmNm: temp2,
menuList: temp.join(),
qtyList: qtyList,
fromObjDt:
this.pageData.cmCycle == 'CYC_HOUR'
? this.pageData.fromDt.substr(0, 4) +
'-' +
this.pageData.fromDt.substr(4, 2) +
'-' +
this.pageData.fromDt.substr(6, 2)
: this.pageData.fromDt,
sh_startDt:
this.pageData.cmCycle == 'CYC_DAY'
? this.pageData.fromDt.substr(0, 4) +
'-' +
this.pageData.fromDt.substr(4, 2) +
'-' +
this.pageData.fromDt.substr(6, 2)
: null,
toObjDt:
this.pageData.cmCycle == 'CYC_HOUR'
? this.pageData.fromDt
: this.pageData.toDt,
sh_endDt:
this.pageData.cmCycle == 'CYC_DAY'
? this.pageData.toDt.substr(0, 4) +
'-' +
this.pageData.toDt.substr(4, 2) +
'-' +
this.pageData.toDt.substr(6, 2)
: null,
};
if (this.pageData.facInfoList.length > 0) {
res = await this.postApiReturn({
apiKey: this.apiKey,
resKey: 'sameTermReadDataList',
sendParam: sendParams,
});
}
} else {
this.setPageData({ isFind: false });
}
for (i = 0; i < res.length; i++) {
Object.assign(res[i], {
_attributes: { rowSpan: { readObjNm: res.length } },
});
}
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
this.loadGrid1 = true;
this.setPageData({ isFind: false });
this.$nextTick(() => {
if (this.loadGrid1) {
this.setChartData(res);
}
});
},
async setChartData(data) {
let xAxisData = [];
let seriesData = [];
let seriesDataList = [];
const myKey = this.pageData[this.gridName].column.filter(v => {
return (
v.header !== '번호' && v.header !== '에너지' && v.header !== '구분'
);
});
seriesDataList = data.map(item => ({
name: item.eccNm,
type: 'line',
data: myKey.map(obj => item[obj.name] || 0),
}));
xAxisData = myKey.map(obj => obj.header);
seriesData = seriesDataList;
function setChartOption(chartName, unitVal) {
var option = {
grid: {},
xAxis: {
type: 'category',
data: xAxisData,
},
yAxis: {
type: 'value',
nameLocation: 'middle',
nameGap: 50,
name: unitVal,
axisLabel: {
textStyle: {
fontSize: 10,
},
},
},
legend: {},
series: seriesData,
};
return option;
}
this.setChartOption({
chartKey: 'chart1',
value: setChartOption('chart1', this.unit),
});
this.loadChart1 = true;
},
},
};
const defaultData = {
/* 검색옵션 */
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
blocId: null, // 사업장
blocMstrList: [],
energyCd: '',
energyList: [],
rdbUseCost: 'use',
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: 0,
},
// popup 설정
isMulti: true, //checkBox
facInfo: {},
facInfoList: [], // 선택된 공정/설비 데이타 리스트
modalData: {}, // 모달 관련 데이타 저장소
fromDt: '',
toDt: '',
/* Grid data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
grid1: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {},
},
// chart 설정
chart1: Utility.defaultChartOption(true),
// 선택된 그룹코드 상세 데이터
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
grid1: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,666 @@
<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="3">
<!-- 사업장 -->
<component
:is="'SelectBlocMstr'"
:parentPrgmId="myPrgmId"
valueNm="blocNm"
/>
</v-col>
<v-col :cols="3">
<!-- 에너지 -->
<component
:is="'SelectEnergy'"
:parentPrgmId="myPrgmId"
:label="'에너지'"
/>
</v-col>
<v-col :cols="3">
<!-- 주기 -->
<component :is="'SelectCmCycle'" :parentPrgmId="myPrgmId" />
</v-col>
<v-col :cols="3" class="text-right">
<!-- 조회버튼 -->
<BtnSearch @click="search" />
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="grid_01"
/>
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="3">
<!-- 조회기간 -->
<!-- <component :is="swichDatePicker" :parentPrgmId="myPrgmId" /> -->
<component
:is="'Datepicker'"
:parentPrgmId="myPrgmId"
:label="'조회기간'"
/>
</v-col>
<v-col :cols="7">
<!-- 공정/설비 -->
<component
:is="'OutSideWeatherPlcPop'"
:parentPrgmId="myPrgmId"
/>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12" style="height: 65%">
<v-card class="pa-5">
<component
class="w100 h100"
:is="loadChart_01 ? 'Chart' : null"
:parentPrgmId="myPrgmId"
:chartName="chart_01"
ref="chart_01"
/>
</v-card>
</v-col>
<v-col :cols="12" style="height: 35%">
<v-card class="pb-5">
<v-card-title class="justify-end caption text-color--non-activate"
>단위 : {{ unit }}
</v-card-title>
<div ref="gridParent" class="px-5" style="height: calc(100% - 70px)">
<component
ref="grid_01"
:is="loadGrid_01 ? 'Grid' : null"
:gridName="grid_01"
:parentPrgmId="myPrgmId"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import mixinGlobal from '@/mixin/global';
import SelectCmCycle from '@/components/common/select/SelectCmCycle';
import SelectEnergy from '@/components/common/select/SelectEnergyForPop';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstrForPop';
import OutSideWeatherPlcPop from '~/components/common/modal/OutSideWeatherPlcMultiPop';
import BtnSearch from '~/components/common/button/BtnSearch';
import Grid from '~/components/common/Grid';
import Datepicker from '~/components/common/Datepicker';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Chart from '~/components/common/Chart';
import SelectMttGrp from '@/components/common/select/SelectMttGrp';
import SelectUseFg from '@/components/common/select/SelectUseFg';
import SelectUnit from '@/components/common/select/SelectUnit';
import SelectEqpmGrpKind from '@/components/common/select/SelectEqpmGrpKind';
import InputText from '@/components/common/input/InputText';
import InputTextPassword from '@/components/common/input/InputTextPassword';
import InputRmrk from '@/components/common/input/InputRmrk';
import Utility from '~/plugins/utility';
import DateUtility from '~/plugins/dateUtility';
// import ChangePassword from "~/components/common/modal/ChangePassword";
let myTitle;
let myPrgmId;
export default {
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,
},
mixins: [mixinGlobal],
components: {
Grid,
SelectEnergy,
SelectCmCycle,
SelectBlocMstr,
BtnSearch,
OutSideWeatherPlcPop,
BtnExcelDownload,
Chart,
Datepicker,
SelectMttGrp,
SelectUseFg,
SelectUnit,
SelectEqpmGrpKind,
InputText,
InputTextPassword,
InputRmrk,
// ChangePassword
},
data() {
return {
myPrgmId: myPrgmId,
grid_01: 'readPlcGrid', // defaultData랑 맞춰야 됨
chart_01: 'readPlcChart',
loadGrid_01: false,
loadChart_01: false,
apiKey: 'selectSameTermReadPlcHour',
unit: '',
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
swichDatePicker() {
let picker = 'SelectDateVc';
if (
this.pageData.cmCycle == 'CYC_MONTH' ||
this.pageData.cmCycle == 'CYC_YEAR'
) {
picker = 'SelectDate';
}
return picker;
},
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocCd: function() {
// 사업장 선택 감지
//this.selectBoxEvt();
return this.pageData.blocId;
},
chkEnergyCd() {
// 에너지 선택 감지
//this.selectBoxEvt();
return this.pageData.energyCd;
},
chkFacInfo() {
// 공정/설비 변경 감지
return this.pageData.facInfoList;
},
initFlag() {
if (
this.pageData.energyList.length > 0 &&
this.pageData.blocMstrList.length > 0
) {
return true;
} else {
return false;
}
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
//this.setPageData({ isFind: true });
},
chkEnergyCd() {
this.initUnit();
//this.setPageData({ isFind: true });
},
chkFacInfo() {
this.setPageData({ isFind: true });
},
initFlag(val) {
if (val) {
this.init();
}
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
// this.pageData.facInfoList = localStorage.getItem(myPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(myPrgmId + "CheckedRow")) : [] // 선택된 공정/설비 데이타 리스트
},
mounted() {
//this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
}),
async init() {
// await this.layoutInit();
await this.gridInit();
},
async initUnit() {
this.unit = this.pageData.energyList[this.pageData.energyCd].unit;
},
async gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const isRange =
this.pageData.defaultRange[this.pageData.cmCycle] === 0 ? false : true;
// const gridHeight = this.$refs.contents.offsetHeight - 30;
const myOptions = {
scrollX: false,
};
this.setGridOption({
gridKey: this.grid_01,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
await this.getRowGridData();
},
async search() {
await this.setPageData({
isFind: false,
});
await this.getRowGridData();
if (this.pageData.energyCd !== '' && this.pageData.energyCd != null) {
localStorage.setItem(
myPrgmId + 'SelectedEnergyCd',
this.pageData.energyCd,
);
}
if (this.pageData.blocId !== '' && this.pageData.blocId != null) {
localStorage.setItem(myPrgmId + 'SelectedBlocCd', this.pageData.blocId);
}
// await this.getRowGridData2(); // tab2
},
async getRowGridData() {
this.loadGrid_01 = false;
this.loadChart_01 = false;
let diffTime;
var apiKeymapper = {
CYC_YEAR: 'selectSameTermReadPlcYear',
CYC_MONTH: 'selectSameTermReadPlcMonth',
CYC_DAY: 'selectSameTermReadPlcDay',
CYC_HOUR: 'selectSameTermReadPlcHour',
};
this.apiKey = apiKeymapper[this.pageData.cmCycle];
// readPlcList setting
const readPlcCdList = [];
const facInfoList = this.pageData.facInfoList;
if (facInfoList.length > 0) {
for (const item of facInfoList) {
readPlcCdList.push(item.readPlc);
}
}
var sendParams = {};
if (
this.pageData.blocMstrList.length > 0 &&
this.pageData.energyList.length > 0
) {
sendParams = {
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
endDt: this.pageData.toDt,
frDt: this.pageData.fromDt,
readPlcList: readPlcCdList,
};
}
let myColumns = [
{ header: '번호', name: 'rowNum', align: 'center' },
{ header: '구분', name: 'readPlcNm', align: 'left' },
{ header: '검침개소', name: 'readPlc', align: 'left', hidden: true },
{ header: '에너지', name: 'mttCd', align: 'left', hidden: true },
{ header: '공통코드', name: 'comId', align: 'left', hidden: true },
];
// 주기별 qty 파라미터 및 gridHeader 세팅
switch (this.pageData.cmCycle) {
case 'CYC_YEAR':
// diffTime = this.calDiffTime();
diffTime =
DateUtility.diff(this.pageData.fromDt, this.pageData.toDt, 'y') + 1;
for (var i = 0; i < 10; i++) {
let qtyKey;
qtyKey = 'qty' + String(i + 1).padStart(2, '0');
sendParams[qtyKey] = parseInt(parseInt(this.pageData.fromDt) + i);
if (i < diffTime) {
myColumns.push({
header: parseInt(parseInt(this.pageData.fromDt) + i),
name: qtyKey,
align: 'center',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
});
}
}
break;
case 'CYC_MONTH':
diffTime =
DateUtility.diff(this.pageData.fromDt, this.pageData.toDt, 'm') + 1;
for (var i = 0; i < 12; i++) {
let qtyKey;
let tDate;
let tDateVal;
qtyKey = 'qty' + String(i + 1).padStart(2, '0');
tDate = DateUtility.addMonth(i, 'YYYYMM', this.pageData.fromDt);
tDateVal = DateUtility.getDate(tDate);
sendParams[qtyKey] = parseInt(tDate);
if (i < diffTime) {
myColumns.push({
header:
String(tDateVal['$y']) +
'/' +
String(tDateVal['$M'] + 1).padStart(2, '0'),
name: qtyKey,
align: 'center',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
});
}
}
break;
case 'CYC_DAY':
diffTime =
DateUtility.diff(this.pageData.fromDt, this.pageData.toDt, 'd') + 1;
for (var i = 0; i < 31; i++) {
let qtyKey;
let tDate;
let tDateVal;
qtyKey = 'qty' + String(i + 1).padStart(2, '0');
tDate = DateUtility.addDate(i, 'YYYYMMDD', this.pageData.fromDt);
tDateVal = DateUtility.getDate(tDate);
sendParams[qtyKey] = parseInt(tDate);
if (i < diffTime) {
myColumns.push({
header:
String(tDateVal['$M'] + 1).padStart(2, '0') +
'/' +
String(tDateVal['$D']).padStart(2, '0'),
name: qtyKey,
align: 'center',
width: 100,
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
});
}
}
break;
case 'CYC_HOUR':
for (var i = 0; i < 24; i++) {
let qtyKey;
qtyKey = 'qty' + String(i + 1).padStart(2, '0');
sendParams['endDt'] = sendParams['frDt'];
myColumns.push({
header: i + '시',
name: qtyKey,
align: 'center',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 2);
},
});
}
break;
}
let res = [];
if (sendParams.endDt != undefined && sendParams.readPlcList.length > 0) {
res = await this.postApiReturn({
apiKey: this.apiKey,
resKey: 'ddlyReadRsltData',
sendParam: sendParams,
});
} else {
this.setPageData({ isFind: false });
//alert("검침개소 정보가 없습니다.");
}
// const newRes = res.map(item => {
// const newObj = {
// ...item,
// rowStat: null
// };
// return newObj;
// });
this.setGridColumn({
gridKey: this.grid_01,
value: myColumns,
});
this.setGridData({
gridKey: this.grid_01,
value: res,
});
this.loadGrid_01 = true;
this.setPageData({ isFind: false });
this.$nextTick(() => {
if (this.loadGrid_01) {
this.setChartData(res);
}
});
},
async setChartData(data) {
let xAxisData = [];
let seriesData = [];
let seriesDataList = [];
const myKey = this.pageData[this.grid_01].column.filter(v => {
return (
v.header !== '구분' &&
v.header !== '번호' &&
v.header !== '에너지' &&
v.header !== '공통코드' &&
v.header !== '검침개소'
);
});
seriesDataList = data.map(item => ({
name: item.readPlcNm,
type: 'line',
data: myKey.map(obj => item[obj.name] || 0),
}));
xAxisData = myKey.map(obj => obj.header);
seriesData = seriesDataList;
let option = {
grid: {
right: '10%',
},
xAxis: {
type: 'category',
data: xAxisData,
},
legend: {
top: 'center',
left: 'right',
orient: 'vertical',
},
series: seriesData,
};
this.setChartOption({ chartKey: 'readPlcChart', value: option });
this.loadChart_01 = true;
},
// compareData(type, newData) {
// if (this.selectedUserData[type] == newData) {
// return true;
// } else {
// return false;
// }
// },
calDiffTime() {
var toDate;
var fromDate;
if (this.pageData.cmCycle == 'CYC_YEAR') {
return (
parseInt(this.pageData.toDt) - parseInt(this.pageData.fromDt) + 1
);
} else if (this.pageData.cmCycle == 'CYC_MONTH') {
var toDate = new Date(
this.pageData.toDt.substr(0, 4),
this.pageData.toDt.substr(4, 2),
);
var fromDate = new Date(
this.pageData.fromDt.substr(0, 4),
this.pageData.fromDt.substr(4, 2),
);
} else if (this.pageData.cmCycle == 'CYC_DAY') {
var toDate = new Date(
this.pageData.toDt.substr(0, 4),
this.pageData.toDt.substr(4, 2),
this.pageData.toDt.substr(6, 2),
);
var fromDate = new Date(
this.pageData.fromDt.substr(0, 4),
this.pageData.fromDt.substr(4, 2),
this.pageData.fromDt.substr(6, 2),
);
}
toDate.setMonth(toDate.getMonth() - 1);
fromDate.setMonth(fromDate.getMonth() - 1);
var diff = toDate - fromDate;
var cDay = 24 * 60 * 60 * 1000;
var cMonth = cDay * 30;
//var cYear = cMonth * 12;
var typeMapper = {
CYC_MONTH: cMonth,
CYC_DAY: cDay,
};
return parseInt(diff / typeMapper[this.pageData.cmCycle]) + 1;
},
// // 확인하기1
// selectBoxEvt() {
// localStorage.removeItem("SameTermReadPlcCheckedRow");
// this.pageData.facInfoList = [];
// }
},
};
const defaultData = {
/* 검색옵션 */
isFind: false,
blocId: '', // 사업장
//blocId: "BL0001", // 사업장
blocMstrList: [],
energyCd: null, // 에너지
//energyCd: "MTT00001", // 에너지
energyList: [],
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' },
],
// 각 주기에 따른 기간 max
defaultRange: {
CYC_YEAR: 10,
CYC_MONTH: 12,
CYC_DAY: 30,
CYC_HOUR: 0,
},
// fromDt: "", // 조회 시작일
fromDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'), // 조회 시작일
toDt: '', // 조회 종료일,
// popup 설정
isMulti: true, //checkBox
facInfo: {}, // 선택된 공정/설비 데이타
facInfoList: [], // 선택된 공정/설비 데이타 리스트
modalData: {}, // 모달 관련 데이타 저장소
//
//localStorageKey: "SameTermReadPlcCheckedRow",
/* data 세팅 */
readPlcGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {},
},
// chart 설정
readPlcChart: Utility.defaultChartOption(true),
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
readPlcGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
// selectedRowKey:null,
// selectedUserData: null,
};
function numberFormatter({ value }) {
if (value == null) {
return 0;
} else {
return value;
}
}
function makeDateVal(date, cmCycle) {
let result = '';
var newDate = DateUtility.getDate(date);
result = newDate['$y'];
if (cmCycle == 'CYC_YEAR') return result;
result = result + '-' + String(newDate['$M'] + 1).padStart(2, '0');
if (cmCycle == 'CYC_MONTH') return result;
result = result + '-' + String(newDate['$D']).padStart(2, '0');
return result;
}
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

View File

@ -0,0 +1,477 @@
<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"
/>
</v-col>
<v-col :cols="3">
<component
:is="'selectCodeList'"
:parentPrgmId="myPrgmId"
:label="'검침대상 유형'"
dataKey="readObjKind"
:addAll="true"
:sendParam="{ commGrpCd: 'CM_MTTTP', useFg: '1' }"
/>
</v-col>
<v-col :cols="4">
<component
:is="'RadioStandard'"
:parentPrgmId="myPrgmId"
label="기준"
:labelCols="2"
:textCols="10"
/>
</v-col>
<v-col :cols="3" class="text-right">
<BtnSearch @click="search" />
<BtnExcelDownload
style="vertical-align: middle;"
class="d-inline-flex"
:parentPrgmId="myPrgmId"
:gridName="gridName"
/>
</v-col>
</v-row>
<v-row aling="center" no-gutters>
<v-col :cols="4">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
검색어
</label>
</v-col>
<v-col :cols="10">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:placeholder="placeholderValue"
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
</v-row>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="12">
<v-card class="px-5 py-5">
<div ref="gridParent" id="test2" style="height:100%;">
<component
class="w100 h100"
ref="myGrid"
:is="loadGrid ? 'Grid' : null"
:gridName="gridName"
:parentPrgmId="myPrgmId"
/>
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import BtnSearch from '~/components/common/button/BtnSearch';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Grid from '~/components/common/Grid';
import mixinGlobal from '@/mixin/global.js';
import SelectBlocMstr from '@/components/common/select/SelectBlocMstr';
import Utility from '~/plugins/utility';
import RadioStandard from '~/components/common/RadioStandard';
import selectCodeList from '@/components/common/select/selectCodeList';
let myTitle;
// const myPrgmId = "PRG0054";
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: {
BtnSearch,
SelectBlocMstr,
RadioStandard,
selectCodeList,
Grid,
BtnExcelDownload,
},
data() {
return {
myPrgmId: myPrgmId,
loadGrid: false,
gridName: 'rowGrid',
myRowKey: 0,
searchWord: '',
apiKey: '',
placeholderValue: '',
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
return this.pageData.isFind;
},
chkBloc() {
return this.pageData.blocId;
},
chkStandard() {
return this.pageData.rdbStandard;
},
chkReadObjKind() {
return this.pageData.readObjKind;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBloc() {
this.setPageData({ isFind: true });
},
chkStandard() {
this.searchWord = '';
this.setPageData({ isFind: true });
},
chkReadObjKind() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
created() {
//공정 유형 조회
this.getCodeList({
dataKey: 'eccKind',
params: { commGrpCd: 'EM_ECC_KIND', useFg: '1' },
addAll: false,
});
//개소 종류 조회
this.getCodeList({
dataKey: 'plcKind',
params: { commGrpCd: 'CM_CHKKIND', useFg: '1' },
addAll: false,
});
//READ_DATA_TYPE 조회
this.getCodeList({
dataKey: 'readDataTypeCd',
params: { commGrpCd: 'EM_READ_DATA_TYPE', useFg: '1' },
addAll: false,
});
//사용여부 조회
this.getCodeList({
dataKey: 'eccFg',
params: { commGrpCd: 'CO_USEFG', useFg: '1' },
addAll: false,
});
},
mounted() {},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
}),
...mapActions({
getCodeList: 'modules/search/getCodeList',
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
async search() {
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
typeEnterKey() {
this.getRowGridData();
},
init() {
this.layoutInit();
this.gridInit();
this.pageData.blocId = this.userInfo.blocId;
},
layoutInit() {
const searchFilterHeight = this.$refs.searchFilter.offsetHeight;
this.$refs.contents.style.height = `calc(100% - ${searchFilterHeight}px)`;
},
gridInit() {
const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
columnOptions: {
resizable: true,
},
header: {
height: 60,
complexColumns: [
{
header: '태그',
name: 'tagColumns',
childNames: [
'tagNm',
'readDataTypeCd',
'readObjNm',
'mgnf',
'distRt',
],
},
{
header: '검침개소',
name: 'readPlcColumns',
childNames: ['readPlcNm', 'plcKind', 'distRt2'],
},
{
header: '공정',
name: 'eccColumns',
childNames: ['eccNm', 'eccKind', 'eccFg'],
},
{
header: '설비',
name: 'eqpmColumns',
childNames: ['1', '2', '3'],
},
],
},
};
this.setGridOption({
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.getRowGridData();
},
async getRowGridData() {
this.loadGrid = false;
const _this = this;
let myColumns = [
{
header: '태그명',
name: 'tagNm',
align: 'left',
width: 'auto',
},
{
header: '타입',
name: 'readDataTypeCd',
align: 'center',
formatter({ value }) {
let retVal = '';
const newVal = _this.pageData.readDataTypeCdList.filter(
item => item.commCd == value,
);
if (newVal.length > 0) {
retVal = newVal[0].commCdNm;
}
return retVal;
},
},
{
header: '검침대상',
name: 'readObjNm',
align: 'center',
},
{
header: '배부율',
name: 'mgnf',
align: 'center',
},
{
header: '매핑배율',
name: 'distRt',
align: 'center',
},
{
header: '개소명',
name: 'readPlcNm',
align: 'left',
width: 'auto',
},
{
header: '개소유형',
name: 'plcKind',
align: 'center',
formatter({ value }) {
let retVal = '';
const newVal = _this.pageData.plcKindList.filter(
item => item.commCd == value,
);
if (newVal.length > 0) {
retVal = newVal[0].commCdNm;
}
return retVal;
},
},
{
header: '매핑배율',
name: 'distRt2',
align: 'center',
},
{
header: '공정명',
name: 'eccNm',
align: 'left',
width: 'auto',
},
{
header: '공정타입',
name: 'eccKind',
align: 'center',
formatter({ value }) {
let retVal = '';
const newVal = _this.pageData.eccKindList.filter(
item => item.commCd == value,
);
if (newVal.length > 0) {
retVal = newVal[0].commCdNm;
}
return retVal;
},
},
{
header: 'ECC여부',
name: 'eccFg',
align: 'center',
formatter({ value }) {
let retVal = '';
const newVal = _this.pageData.eccFgList.filter(
item => item.commCd == value,
);
if (newVal.length > 0) {
retVal = newVal[0].commCdNm;
}
return retVal;
},
},
];
var apiKeyMapper = {
tag: 'selectStndInfoReadTag',
readPlc: 'selectStndInfoReadReadPlc',
ecc: 'selectStndInfoReadEcc',
eqpm: 'selectStndInfoReadEqpm',
};
this.apiKey = apiKeyMapper[this.pageData.rdbStandard];
let res = [];
res = await this.postApiReturn({
apiKey: this.apiKey,
resKey: 'stndInfoReadData',
sendParam: {
search: this.searchWord,
// blocId: this.pageData.blocId,
blocId: this.pageData.blocMstrList[this.pageData.blocId].blocId,
readObjKind: this.pageData.readObjKind,
},
});
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.setGridData({
gridKey: this.gridName,
value: res,
});
let placeObj = {
tag: '태그명 검색',
readPlc: '검침개소명 검색',
ecc: '공정명 검색',
eqpm: '설비명 검색',
};
this.$nextTick(() => {
this.placeholderValue = placeObj[this.pageData.rdbStandard];
});
this.loadGrid = true;
this.setPageData({ isFind: false });
},
},
};
const defaultData = {
/* 검색옵션 */
isFind: false,
blocId: '',
blocMstrList: [],
rdbStandard: 'tag',
plcKind: '',
plcKindList: [],
eccKind: '',
readObjKind: '',
readObjKindList: [],
eccFg: '',
eccFgList: [],
eccKindList: [],
readDataTypeCd: '',
readDataTypeCdList: [],
rowGrid: {
data: [],
column: [],
option: {},
defaultRow: {},
},
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
</script>
<style lang="scss">
@import '@/assets/scss/common.scss';
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
<template>
<div class="w100 h100">
<iframe
src="/webHmi/home"
name="hmi"
width="100%"
height="100%"
frameborder="0"
></iframe>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Utility from '~/plugins/utility';
let myTitle;
// const myPrgmId = "PRG4107";
let myPrgmId;
export default {
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: {
Utility,
},
data() {
return {
myPrgmId: myPrgmId,
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
},
watch: {},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
async created() {},
async mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setGridData: 'setGridData',
setGridColumn: 'setGridColumn',
setGridOption: 'setGridOption',
setChartOption: 'setChartOption',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
chkOpenTabList: 'chkOpenTabList',
}),
},
};
const defaultData = {
isFind: false,
};
const myDetail = [];
</script>
<style lang="scss">
.swiper-wrapper {
box-sizing: inherit !important;
}
.swiper-pagination-horizontal {
bottom: 10px;
left: 0;
width: 100%;
}
.swiper-pagination-bullet {
width: 15px;
height: 15px;
margin: 0 var(--swiper-pagination-bullet-horizontal-gap, 5px);
background: #fff;
}
.swiper-pagination-bullet-active {
opacity: 1;
background: #196dcb;
}
// .swiper-position{
// position: fixed;
// }
</style>