Files
sk_fems_ui/pages/ems/effc/DataSetMngPage.vue
2025-07-28 16:12:24 +07:00

787 lines
22 KiB
Vue

<template>
<div class="l-layout">
<CommonPageTitle />
<!-- Dataset 페이지 시작 -->
<div v-if="pageActionFlag == 'list'" class="h100">
<v-row ref="searchFilter">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="center" no-gutters>
<v-col :cols="3">
<InputText :parentPrgmId="myPrgmId" label="DataSet 명" valueNm="dataSetNm" :labelCols="12" :textCols="12"
:searchOption="true" customClass="input-large" />
</v-col>
<v-col :cols="3">
<component :is="'selectCodeList'" :parentPrgmId="myPrgmId" :label="'사용여부'" dataKey="useFg"
:sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }"
:addAll="true"
:labelCols="12" customClass="select-large" />
</v-col>
<v-col :cols="3">
<!-- 사업장 -->
<component :is="'SelectBlocMstr'" ref="SelectBlocMstr"
:parentPrgmId="myPrgmId"
:labelCols="12"
:textCols="12"
customClass="select-large" />
</v-col>
<v-col class="text-right d-flex align-end align-self-end justify-end">
<a-button @click="jamoviClickEvent('view')" type="primary" :ripple="false" class="mr-1"
depressed size="large">Jamovi</a-button>
<BtnSearch @click="search" size="large" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents">
<v-col :cols="5" >
<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">Data Set 리스트</v-card-title>
<Buttons :parentPrgmId="myPrgmId" :bindingData="gridName" :detailList="detailList"
:btnActionsFnc="btnActions" />
</div>
<div ref="gridParent" class="px-5" style="min-height: 60vh">
<component :ref="gridName" :is="loadGrid ? 'Grid' : null" :gridName="gridName" :parentPrgmId="myPrgmId"
@getRowsData="getRowData" @sendSelectedRowStatInfo="getSelectedRowStatInfo"
:selectedRowDataWatchFlag="true" />
<!-- <div ref="gridParent" class="w100 h100">
</div> -->
</div>
</v-card>
</v-col>
<v-col :cols="7" >
<v-card class="pb-5">
<v-card-title class="custom-title-4" style="min-height:76px;">Data Set 상세
</v-card-title>
<div class="px-5" style="min-height:calc(100% - 76px)">
<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="min-height: calc(100% - 65px);" class="py-6">
<v-tab-item v-for="(item, idx) in items" :key="item.id">
<component v-if="item.id == 'dataSetInfoTab'" :is="'Form'" :parentPrgmId="myPrgmId"
:detailList="detailList" :bindingData="gridName" @gridEditingFinish="gridEditingFinish" />
<DataSetTagRelTab v-if="item.id == 'dataSetTagRelTab'" :parentPrgmId="myPrgmId"
:innerTabGridInfo="{ tab, idx }" @jamoviClickEvent="jamoviClickEvent" />
</v-tab-item>
</v-tabs-items>
</div>
</v-card>
</v-col>
</v-row>
</div>
<!-- Dataset 페이지 -->
<!-- Jamovi 페이지 시작 -->
<div v-if="pageActionFlag == 'view'" class="h100">
<v-row align="center" no-gutters>
<v-col :cols="12">
<v-card>
<div class="d-flex align-center justify-space-between pa-5">
<v-card-title class="pa-0">모델링 Data Set</v-card-title>
<div class="d-flex align-center">
<v-btn @click="jamoviClickEvent('list')" :ripple="false" class="mr-1" depressed>관리 화면으로</v-btn>
</div>
</div>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<v-card>
<div class="w100 h100">
<iframe name="iframeJamovi" id="iframeJamoviViewComponent" width="100%" height="100%" :src="smgHtmlPath"
frameborder="0" ref="iframeDom" @load="iframeIsLoaded"></iframe>
</div>
</v-card>
</v-col>
</v-row>
</div>
<!-- Jamovi 페이지 -->
</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 InputText from '@/components/common/input/InputText';
import Form from '~/components/common/form/Form';
import DataSetTagRelTab from '@/components/pages/ems/DataSetInfo/DataSetTagRelTab';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import DateUtility from '~/plugins/dateUtility';
let myTitle;
let myPrgmId;
let smgHtmlPath;
let isJamoviInit = false;
let jamoviOpenDocKey = '';
const globalComId = '';
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,
smgHtmlPath: smgHtmlPath,
closable: true,
smgHtmlPath:
'http://jamovi.kfems.co.kr:41337/?access_key=c141f87a126147c593af3825367c4300',
},
components: {
BtnSearch,
Buttons,
SelectBlocMstr,
selectCodeList,
InputText,
Form,
DataSetTagRelTab,
Grid,
},
data() {
return {
myPrgmId: myPrgmId,
pageActionFlag: 'list',
gridName: 'rowGrid',
smgHtmlPath:
'http://jamovi.kfems.co.kr:41337/?access_key=c141f87a126147c593af3825367c4300', // jamoviOpenDocKey,
loadGrid: false,
tab: null,
items: [
{
name: 'Data Set 정보',
id: 'dataSetInfoTab',
disabledFlag: false,
},
{
name: 'Data Set TAG 연결',
id: 'dataSetTagRelTab',
disabledFlag: false,
},
],
detailList: myDetail,
defaultUseFg: 1,
loadGrid: true,
dataPathMock: {
'rowGrid': {
column: [
{ header: '모델링 DataSet ID', name: 'id', headerAlign: 'left' },
{ header: 'DataSet 명', name: 'lable', headerAlign: 'left' },
{ header: '사용 여부', name: 'type', headerAlign: 'left' },
{ header: '비고', name: 'note', headerAlign: 'left' }
],
data: dataPathDataExample,
defaultRow: dataPathDataExample,
option: {}
}
},
};
},
computed: {
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkBlocCd() {
return this.pageData.blocId;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFgList === undefined ? -1 : this.pageData.useFg;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkBlocCd() {
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() {
var data = this.$route.params;
this.routeData = {
fromDt: data.fromDt,
};
// 모델 데이터 유형
this.getCodeList({
dataKey: 'mdlDataTypeCd',
params: { commGrpCd: 'MDL_DATA_TYPE_CD', useFg: '1' },
addAll: false,
});
},
mounted() {
this.init();
},
beforeDestroy() {
this.chkOpenTabList({ key: 'destroy', prgmId: myPrgmId });
},
methods: {
...mapActions({
getCodeList: 'modules/search/getCodeList',
getBlocMstrList: 'modules/search/getBlocMstrList',
getJamoviUrlReturn: 'modules/list/getJamoviUrlReturn',
}),
init() {
this.setFromDt();
this.initData();
this.gridInit();
},
async initData() { },
setFromDt() {
this.pageData.fromDt = Utility.setBeforetDate(
this.pageData,
this.pageData.toDt,
'YYYYMMDD',
);
// this.pageData.toDt = Utility.setAftertDate(this.pageData, this.pageData.fromDt, "YYYYMMDD");
},
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: '모델링 DataSet ID',
name: 'dataSetId',
align: 'center',
width: 180,
},
{
header: 'DataSet 명',
name: 'dataSetNm',
align: 'left',
width: 200,
},
{
header: '사업장',
name: 'blocId',
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.pageData.blocIdList.filter(
item => item.blocId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].blocNm;
}
return retVal;
},
hidden: true,
},
{
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: '비고', name: 'rmrk', align: 'left' },
];
this.setGridColumn({
gridKey: this.gridName,
value: myColumns,
});
this.loadGrid = true;
this.getRowGridData();
},
async search() {
// this.loadTree = false;
this.loadGrid = false;
await this.getRowGridData();
await this.setPageData({
isFind: false,
});
},
async getRowGridData() {
let res = [];
var useFg =
this.pageData.useFgList.length > 0
? this.pageData.useFg
: this.defaultUseFg;
if (this.pageData.blocMstrList.length > 0) {
res = await this.postApiReturn({
apiKey: 'selectDataSetInfo',
resKey: 'dataSetInfoData',
sendParam: {
comId: globalComId,
useFg: useFg,
dataSetNmLike: this.pageData.dataSetNm,
},
});
} else {
this.setPageData({ isFind: false });
}
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
dataSetId: item.dataSetId,
dataSetNm: item.dataSetNm,
useFg: item.useFg === '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:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnName: 'dataSetNm',
setScroll: true,
});
} else {
this.detailDataInit();
}
});
},
async getRowData(data, gridName) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
this.setDataSetTagRelInfo(data);
this.setGridSelectData({
gridKey: gridName,
gridSelect: true,
rowGridSelectKey: data.rowKey,
rowGridSelectData: Object.assign({}, data),
});
this.setGridSelectData({
gridKey: 'rowDataSetTagRelGrid',
gridSelect: true,
rowGridSelectKey: '',
rowGridSelectData: Object.assign({}, {}),
});
},
async setDataSetTagRelInfo(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
// 검침개소 추가 정보 처리
const res = await this.postApiReturn({
apiKey: 'selectMdlDataSetTagRelInfo',
resKey: 'dataSetTagRelData',
sendParam: {
comId: data.comId,
dataSetId: data.dataSetId,
},
});
console.debug('res', res);
const newRes = res.map(item => {
const newObj = {
...item,
comId: item.comId || '',
dataSetId: item.dataSetId || '',
dataSetNm: item.dataSetNm || '',
tagId: item.tagId || '',
tagNm: item.tagNm || '',
rmrk: item.rmrk || '',
useFg: item.useFg === '1' ? true : false,
rowStat: null,
};
return newObj;
});
this.setGridData({
gridKey: 'rowDataSetTagRelGrid',
value: newRes,
});
},
detailDataInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowDetailGrid',
value: [],
});
},
detailDataSetTagRelInit() {
this.setPageData({
rowGridSelectKey: null,
rowGridSelectData: [],
});
this.setGridData({
gridKey: 'rowDataSetTagRelGrid',
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 = {
comId: this.userInfo.comId,
dataSetId: '',
dataSetNm: '',
useFg: '1',
};
this.$refs[this.gridName].addTreeRow(defaultRow);
break;
case 'remove':
this.$refs[this.gridName].removeTreeRow();
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.dataSetNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
} else if (item.rowStat === 'U') {
if (item.dataSetNm == '') {
alert('필수 입력값을 입력해주세요.');
validCheck = false;
}
}
});
if (validCheck) {
const sendParam = {
datas: {
dsMdlDataSetInfo: dataArr.map(item => ({
...item,
comId: globalComId,
useFg: item.useFg ? '1' : '0',
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveMdlDataSetInfo',
sendParam: sendParam,
});
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
gridEditingFinish(data, bindingData) {
switch (bindingData) {
case this.gridName:
this.$refs[bindingData].editingFinish(data);
break;
default:
this.$refs[bindingData][0].editingFinish(data);
break;
}
},
async jamoviClickEvent(action, payload) {
switch (action) {
case 'view':
jamoviOpenDocKey = '';
this.pageActionFlag = 'view';
break; // 리스트 페이지 상세보기 버튼
case 'view1':
console.log('view1', payload);
console.log(
'view1 fromDt : ',
this.pageData.fromDt,
', toDt : ',
this.pageData.toDt,
);
const res = await this.postApiReturn({
apiKey: 'selectJamoviOpen',
resKey: 'jamoviOpenData',
sendParam: {
comId: payload.comId,
dataSetId: payload.dataSetId,
sterm: DateUtility.format(this.pageData.fromDt, 'YYYY-MM-DD'),
eterm: DateUtility.format(this.pageData.toDt, 'YYYY-MM-DD'),
term: this.pageData.mdlDataTerm,
},
});
console.log('jamoviClickEvent : ', res);
if (res.status && res.status == 'OK') {
console.log('jamoviClickEvent Ok : ', stat, url);
let stat = res.status;
let url = res.url;
jamoviOpenDocKey = url;
this.pageActionFlag = 'view';
} else {
alert(
'RTDB로 부터 Data Load중 오류가 발생하였습니다.\n검색기간을 확인하시고 다시 요청 바랍니다.',
);
}
break; // 리스트 페이지 상세보기 버튼
case 'list':
this.pageActionFlag = 'list';
isJamoviInit = false;
break; // 리스트 페이지 상세보기 버튼
}
},
iframeIsLoaded() {
// smgHtmlPath
console.log('iframe loaded');
console.log('iframe iframeJamovi', this.$refs.iframeDom.src);
let url = '';
if (!isJamoviInit) {
console.log('iframe loaded2');
isJamoviInit = true;
this.$refs.iframeDom.src =
'http://jamovi.kfems.co.kr:41337/' +
(jamoviOpenDocKey || '?access_key=c141f87a126147c593af3825367c4300');
console.log('iframe iframeJamovi', this.$refs.iframeDom.src);
}
},
},
};
const defaultData = {
/* 검색옵션 */
comId: globalComId,
dataSetId: '',
dataSetNm: '',
blocId: '',
blocMstrList: [],
blocIdList: [],
useFg: '1',
useFgList: [],
commGrpCd: '',
commGrpCdNm: '',
mdlDataTerm: '',
mdlDataTermList: [],
mdlDataTypeCd: '',
mdlDataTypeCdList: [],
facInfo: {},
isMulti: false,
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
isFind: false, // true 경우 조회, 조회버튼도 이 값으로 연동 예정
cmCycle: 'CYC_DAY', // 주기
defaultRange: {
CYC_DAY: 30,
},
fromDt: '',
toDt: Utility.setFormatDate(new Date(), 'YYYYMMDD'),
smgHtmlPath:
'http://jamovi.kfems.co.kr:41337/?access_key=c141f87a126147c593af3825367c4300',
/* data 세팅 */
// 로컬 gridName 값과 동일한 이름으로 세팅
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: globalComId,
dataSetId: '',
dataSetNm: '',
blocId: null,
useFg: '1',
rowStat: 'I',
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
rowGridSelectKey: 0,
rowGridSelectData: null,
},
rowDataSetTagRelGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
comId: '',
dataSetId: '',
dataSetNm: '',
tagId: '',
tagNm: '',
mdlDataTypeCd: 'SUM',
useFg: '1',
rmrk: null,
rowStat: null,
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
rowGridSelectKey: 0,
rowGridSelectData: null,
},
};
const myDetail = [
{
type: 'InputText',
label: 'Data Set ID',
valueNm: 'dataSetId',
readonly: true,
cols: 6,
class: 'py-2 pr-2',
required: false,
placeholder: '시스템 자동입력',
labelCols: 12,
textCols: 12,
iconShow: true,
},
{
type: 'InputText',
label: 'Data Set 명',
valueNm: 'dataSetNm',
disabled: false,
cols: 6,
class: 'py-2',
required: true,
labelCols: 12,
textCols: 12,
iconShow: true,
},
{
type: 'CheckBox',
label: '사용 여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
class: 'py-2',
value: { '1': true, '0': false },
required: true,
labelCols: 12,
iconShow: true,
},
{
type: 'TextArea',
label: '비고',
valueNm: 'rmrk',
disabled: false,
cols: 12,
textCols: 12,
rows: 2,
class: 'py-2',
required: false,
},
];
import { getPathDataExample } from '@/const/const'
const dataPathDataExample = getPathDataExample({
id: 'INCHEON.HVAC.EQP_HT_CH001.UT_CH101.CHI_AMP_1A_PV',
lable: 'INCHEON 고온 냉동기 101호기 - 호로1',
type: '사용', note: '-'
});
</script>
<style lang="scss" scoped>
::v-deep {
.v-window {
overflow: visible;
}
}
</style>