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,137 @@
<template>
<div>
<!-- <v-btn :ripple="false" @click="dialog = !dialog">경고창</v-btn> -->
<v-dialog
v-model="dialog"
width="480"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card>
<v-toolbar
:color="isDarkMode ? '#2d3355' : '#3f4d7d'"
class="py-4 pr-3 pl-5"
height="auto"
>
<v-toolbar-title>{{ label }}</v-toolbar-title>
<v-btn
icon
tile
small
:ripple="false"
@click="dialog = !dialog"
:style="{ backgroundColor: isDarkMode ? '#2d3355' : '#3f4d7d' }"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar>
<v-card-text class="text-center py-10">
{{ computedMessage }}
</v-card-text>
<v-card-actions class="justify-center">
<v-btn :ripple="false" @click="clickOk()">확인</v-btn>
<v-btn v-if="confirm" :ripple="false" @click="clickCancle()"
>취소</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
export default {
props: {
message: {
type: String,
default:
'시스템 에러가 발생하였습니다.<br /> 동일문제가 계속 발생할 경우 전산담당자에게 문의하세요.<br /> 불편을 드려 죄송합니다.<br /><br /> [에러내용] java.lang.OutOfMemoryError: GC overhead limit exceeded',
},
parentPrgmId: {
type: String,
require: true,
},
item: {
type: Object,
require: true,
},
label: {
type: String,
require: true,
},
message: {
type: String,
require: true,
},
confirm: {
type: Object,
require: false,
},
},
data() {
return {
dialog: false,
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
computedMessage() {
if (this.item != undefined && this.item != null) {
return this.item.message;
} else {
return this.message;
}
},
},
watch: {
async chkDialog(val) {
if (val) {
//console.log('this.item : ', this.item);
}
},
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
clickOk() {
if (this.parentPrgmId) {
// this.$emit('yesNo',true);
this.setPageData({ AlertPopData: true });
}
this.dialog = !this.dialog;
},
clickCancle() {
this.setPageData({ AlertPopData: false });
this.dialog = !this.dialog;
},
},
};
</script>
<style scoped lang="scss">
::v-deep {
.v-toolbar__content {
justify-content: space-between;
padding: 0;
.v-btn {
margin-right: 0 !important;
}
}
.v-card__actions {
padding-bottom: 30px !important;
}
}
</style>

View File

@ -0,0 +1,412 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
placeholder="배치명을 입력하세요."
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData2.evtObjPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '이벤트항목',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '이벤트항목',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'evtObjPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { evtObjPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '배치 ID', name: 'batchId', align: 'center', width: 150 },
{ header: '배치명', name: 'batchNm', align: 'left' },
],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectBatchMng',
resKey: 'batchMngData',
sendParam: {
useFg: '1',
batchNm: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
if (!this.item) {
this.textFieldData = this.selectedData.batchId;
} else {
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.selectedData.batchNm;
} else {
this.myBindingData.batchNm = this.selectedData.batchNm;
}
const dt = {
columnName: this.item.valueNm,
value: this.selectedData.batchId,
};
this.$emit('gridEditingFinish', dt);
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.selectedData[this.item.valueNm2],
};
this.$emit('gridEditingFinish', dt);
}
if (this.item.bindNm !== undefined) {
const dt = {
columnName: this.item.bindNm,
value: this.selectedData.batchNm,
};
this.$emit('gridEditingFinish', dt);
}
}
},
dialogOpenCloseEvent(val) {
// if(this.item && this.item.disableContent){
// this.dialog = false;
// return;
// }
this.dialog = !val;
},
},
};
var evtObjPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,194 @@
<template>
<div>
<v-dialog
v-model="dialog"
width="400"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">비밀번호 변경</span>
</v-card-title>
<v-divider></v-divider>
<v-card-text>
<v-col>
<label for="" class="search-box-label">
현재 비밀번호를 입력하세요
</label>
<v-text-field
v-model.trim="curPswd"
class="v-input__custom"
type="password"
:readonly="!isFocused"
@focus="isFocused = true"
@blur="isFocused = false"
@keyup.enter="setUpdate()"
></v-text-field>
</v-col>
<v-col>
<label for="" class="search-box-label">
변경할 비밀번호를 입력하세요
</label>
<v-text-field
v-model.trim="firstPswd"
class="v-input__custom"
type="password"
:readonly="!isFocused"
@focus="isFocused = true"
@blur="isFocused = false"
@keyup.enter="setUpdate()"
></v-text-field>
</v-col>
<v-col>
<label for="" class="search-box-label">
변경할 비밀번호를 다시 입력하세요
</label>
<v-text-field
v-model.trim="secondPswd"
class="v-input__custom"
type="password"
:readonly="!isFocused"
@focus="isFocused = true"
@blur="isFocused = false"
@keyup.enter="setUpdate()"
></v-text-field>
</v-col>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = !dialog">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import $cookie from 'vue-cookie';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
item: {
type: Object,
require: true,
},
comId: {
type: String,
require: true,
},
},
components: {},
data() {
return {
dialog: false,
curPswd: null,
firstPswd: null,
secondPswd: null,
isFocused: false,
changeRow: false,
logoutUrl: '/login',
};
},
computed: {
...mapState({}),
chkDialog() {
return this.dialog;
},
},
watch: {
async chkDialog(val) {
//console.log("watch : ", val)
if (val) {
this.openDialog();
this.$nextTick(() => {});
} else {
}
},
},
methods: {
...mapMutations({ setPageData: 'setPageData' }),
...mapActions({
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
}),
async openDialog() {
this.curPswd = null;
this.firstPswd = null;
this.secondPswd = null;
},
async setUpdate() {
if (!this.curPswd || !this.firstPswd || !this.secondPswd) {
alert('비밀번호를 입력해주세요.');
} else if (this.firstPswd !== this.secondPswd) {
alert('입력한 비밀번호가 다릅니다.');
this.firstPswd = null;
this.secondPswd = null;
} else {
var encryptedCurPassword = await sha512(this.curPswd);
let res = await this.postApiReturn({
apiKey: 'selectComparePswd',
resKey: 'roleUserData',
sendParam: {
userPswd: encryptedCurPassword,
},
});
if (res[0].userCompare == 'FALSE') {
alert('현재 비밀번호가 일치하지 않습니다.');
} else {
var encryptedPassword = await sha512(this.firstPswd);
const sendParam = {
datas: {
dsUser: [
{
userPswd: encryptedPassword,
},
],
},
params: {},
};
// console.log(sendParam);
await this.postUpdateApi({
apiKey: 'updatePswd',
sendParam: sendParam,
});
alert(
'비밀번호가 변경되었습니다. 로그아웃 후 새로운 비밀번호로 재 로그인 바랍니다.',
);
this.dialog = false;
$cookie.delete('FEMS_SESSION');
this.$nextTick(() => {
window.location.href = this.logoutUrl + '?' + this.comId;
});
}
}
},
},
};
function sha512(str) {
const crypto = require('crypto');
return crypto
.createHash('sha512')
.update(str)
.digest('hex');
}
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,224 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="item.label" :cols="item.cols == 12 ? 2 : 4">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
<!-- <label for="" class="search-box-label ft-size_14 ft-clr_g-c">
{{ item.label }}
</label> -->
</v-col>
<v-col :cols="item.label ? 7 : ''">
<template v-if="myBindingData && myBindingData.rowStat === 'I'">
<v-text-field
v-model.trim="InputValue"
class="v-input__custom"
type="password"
outlined
@focus="isFocused = true"
@blur="isFocused = false"
@input="modifyValue($event, item.valueNm)"
:hide-details="true"
></v-text-field>
</template>
<template v-else>
<v-btn :ripple="false" @click="dialog = !dialog">
<!-- <v-icon>mdi-content-save</v-icon> -->
<span>비밀번호 {{ isPassword }}</span>
</v-btn>
</template>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">비밀번호 {{ isPassword }}</span>
</v-card-title>
<v-divider></v-divider>
<v-card-text>
<v-col>
<label for="" class="search-box-label">
{{ isPassword }} 비밀번호를 입력하세요
</label>
<v-text-field
v-model.trim="firstPswd"
class="v-input__custom"
type="password"
:readonly="!isFocused"
@focus="isFocused = true"
@blur="isFocused = false"
></v-text-field>
</v-col>
<v-col>
<label for="" class="search-box-label">
{{ isPassword }} 비밀번호를 다시 입력하세요
</label>
<v-text-field
v-model.trim="secondPswd"
class="v-input__custom"
type="password"
:readonly="!isFocused"
@focus="isFocused = true"
@blur="isFocused = false"
></v-text-field>
</v-col>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="close()">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
item: {
type: Object,
require: true,
},
},
data() {
return {
dialog: false,
firstPswd: null,
secondPswd: null,
isFocused: false,
changeRow: false,
};
},
computed: {
...mapState({
myBindingData(state) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
},
myRowGridSelectKey(state) {
return state.pageData[this.parentPrgmId]['rowGridSelectKey'];
},
}),
isPassword() {
return this.myBindingData && this.myBindingData.pwBk ? '변경' : '등록';
},
chkRowGridSelectKey() {
return this.myRowGridSelectKey;
},
InputValue: {
get() {
let value = null;
if (this.myBindingData) {
if (this.myBindingData[this.item.valueNm] !== null)
value = this.myBindingData[this.item.valueNm];
}
if (
this.myBindingData &&
this.myBindingData.rowStat === 'I' &&
this.changeRow
) {
this.changeRow = false;
return this.isFocused || value !== null ? value : '';
} else {
return '';
}
},
set(value) {
return value;
},
},
},
watch: {
chkRowGridSelectKey(val, oldVal) {
// if (val) this.search();
if (oldVal !== '' && val !== oldVal) this.changeRow = true;
else this.changeRow = false;
},
},
methods: {
...mapMutations({ setPageData: 'setPageData' }),
...mapActions({ postUpdateApi: 'modules/list/postUpdateApi' }),
modifyValue(v, n) {
const dt = {
columnName: n,
value: v,
};
this.$emit('gridEditingFinish', dt);
},
async setUpdate() {
if (!this.firstPswd || !this.secondPswd) {
alert('비밀번호를 입력해주세요.');
} else if (this.firstPswd !== this.secondPswd) {
alert('입력한 비밀번호가 다릅니다.');
this.firstPswd = null;
this.secondPswd = null;
} else {
var encryptedPassword = await sha512(this.firstPswd);
const sendParam = {
datas: {
dsUser: [
{
userNo: this.myBindingData.userNo,
userPswd: encryptedPassword,
// userPswd: this.firstPswd,
rowStat: 'U',
},
],
},
params: {},
};
// console.log(sendParam);
await this.postUpdateApi({
apiKey: 'saveUser',
sendParam: sendParam,
});
alert('저장되었습니다.');
this.dialog = false;
this.setPageData({ isFind: true });
this.firstPswd = null;
this.secondPswd = null;
}
},
async close() {
this.dialog = false;
this.firstPswd = null;
this.secondPswd = null;
},
},
};
function sha512(str) {
// return crypto.subtle.digest("SHA-512", new TextEncoder("utf-8").encode(str)).then(buf => {
// return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join('');
// });
const crypto = require('crypto');
return crypto
.createHash('sha512')
.update(str)
.digest('hex');
}
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,444 @@
<template>
<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 }}
</label>
</v-col>
<v-dialog
ref="popModal"
v-model="dialog"
width="700"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ label }}</span>
<v-btn icon tile :ripple="false" @click="dialog = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="searchFilter v-card">
<v-row align="center" no-gutters>
<v-col :cols="6">
<component
:is="'selectSnarEnergy'"
:parentPrgmId="parentPrgmId"
:label="'에너지원'"
:dataKey="'snarEnergyCd'"
:addAll="true"
:labelCols="4"
/>
</v-col>
<v-col :cols="5">
<v-row align="center" no-gutters>
<v-col cols="4">
<label 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
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
</v-row>
<!-- <InputText
:parentPrgmId="parentPrgmId"
label="시나리오명"
valueNm="snarNm"
:searchOption="true"
:labelCols="4"
:textCols="7"
/> -->
</v-col>
</v-row>
<v-row align="center" no-gutters>
<v-col :cols="8">
<DatePicker
:parentPrgmId="parentPrgmId"
:label="'실행일자'"
:labelCols="3"
/>
</v-col>
<v-col :cols="4" class="text-right">
<v-btn :ripple="false" @click="reset()">초기화</v-btn>
<v-btn :ripple="false" @click="search()">검색</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div ref="snargridParent" class="py-3" style="height:400px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid ? 'Grid' : null"
:dataPath="searchParam.modalData.selectSnarPrgm"
:parentPrgmId="parentPrgmId"
:gridName="gridName"
@getRowsData="getRowData"
/>
</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import DatePicker from '~/components/common/Datepicker';
import Buttons from '~/components/common/button/Buttons';
import Utility from '~/plugins/utility';
import SelectSnarEnergy from '@/components/common/select/SelectSnarEnergy';
import InputText from '@/components/common/input/InputText';
import Grid from '~/components/common/Grid';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: true,
},
},
components: {
InputText,
DatePicker,
Buttons,
Utility,
SelectSnarEnergy,
InputText,
Grid,
},
data() {
return {
dialog: false,
myModalKey: 'selectSnarPrgm',
loadGrid: false,
gridName: 'snarGrid',
modalDataKey: 'modalData',
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
selectValue() {
// 선택된 시나리오 값
const temp = [];
const snarData = this.searchParam.isMulti
? this.searchParam.snarInfoList
: this.searchParam.snarInfo;
console.log('this.searchParam.isMulti', this.searchParam.isMulti);
console.log(
'this.searchParam.snarInfoList',
this.searchParam.snarInfoList,
);
console.log('this.searchParam.snarInfo', this.searchParam.snarInfo);
if (Array.isArray(snarData)) {
if (snarData.length > 0) {
for (const item of snarData) {
temp.push(item.simulId);
}
}
} else {
//return snarData.path === undefined ? snarData.simulId : snarData.path;
}
return temp.join();
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
chkSnarEnergy() {
return this.searchParam.snarEnergyCd;
},
chkFromDt() {
// 조회기간 시작일 선택 감지
return this.searchParam.fromDt;
},
chkToDt() {
// 조회기간 종료일 선택 감지
return this.searchParam.toDt;
},
},
watch: {
async chkDialog(val) {
if (val) this.search();
},
async chkSnarEnergy(val) {
if (val) this.search();
},
async chkFromDt(val) {
if (val) this.search();
},
async chkToDt(val) {
if (val) this.search();
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectSnarPrgm },
});
},
created() {
this.init();
if (this.searchParam.isMulti == true) {
this.setPageData({
snarInfoList:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
} else {
this.setPageData({
snarInfo:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
}
// if(this.searchParam.isMulti == true){
// this.setPageData({
// snarInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
search() {
this.getSnarData();
},
init() {
this.activeRowData = {};
this.gridInit();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
const _this = this;
// const myOptionsSnar = {
// snarColumnOptions: {
// name: "simulId",
// useIcon: true
// },
// scrollX: true
// };
if (this.searchParam.isMulti) {
myOptions['rowHeaders'] = [{ type: 'checkbox' }];
myOptions['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
// myOptionsSnar["snarColumnOptions"]["useCascadingCheckbox"] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(350, myOptions),
myOptions,
),
});
const myColumnsSnar = [
{
header: '실행일자',
name: 'calcDt',
align: 'center',
formatter: dateFormatter,
},
{ header: '시나리오명', name: 'snarNm', align: 'center' },
{ header: '완료여부', name: 'exctFg', align: 'center' },
];
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumnsSnar,
});
},
async getSnarData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectSimulSlctList',
resKey: 'selectSimulSlctList',
sendParam: {
snarNm: this.searchWord, // 검색키워드: 시나리오명
ercId: this.searchParam.snarEnergyCd, // 검색키워드: 에너지원
fromDt: this.searchParam.fromDt, // 검색키워드: 시작일자
toDt: this.searchParam.toDt, // 검색키워드: 끝일자
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
//화면 처음 열때 Default 체크 처리
if (localStorage.getItem(this.parentPrgmId + 'CheckedRow') == null) {
let temp = [];
res.filter(item => {
if (item.mntrFg == 1) {
temp.push(item);
}
});
this.searchParam.snarInfoList = temp;
}
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows(res);
}
});
},
setGridCheckedRows(res) {
this.checkedRowDataList =
this.searchParam.snarInfoListSearch.length > 0
? this.searchParam.snarInfoListSearch
: [];
if (this.checkedRowDataList.length > 0) {
if (res.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
//if(res[i].simulId == this.checkedRowDataList[i].simulId){
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs[this.gridName + this.parentPrgmId],
);
//}
}
}
}
},
getRowData(data) {
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
} else {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
this.gridName + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ snarInfoList: this.checkedRowDataList });
this.setPageData({ snarInfoListSearch: this.checkedRowDataList });
} else {
alert('선택 목록이 20개를 초과하였습니다.');
}
} else {
this.dialog = false;
this.setPageData({ snarinfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.simulId),
);
}
},
reset() {
for (
var i = 0;
i < this.$refs[this.gridName + this.parentPrgmId].getData().length;
i++
) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
this.$refs[this.gridName + this.parentPrgmId].getData()[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
},
typeEnterKey() {
this.search();
},
},
};
const selectSnarPrgm = {
snarGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
function dateFormatter({ value }) {
return Utility.setFormatDate(value, 'YYYY-MM-DD');
}
</script>
<style scoped lang="scss">
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,499 @@
<template>
<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 }}
</label>
</v-col>
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ label }}</span>
<v-btn icon tile :ripple="false" @click="btnAction('close')">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<!-- <v-card-actions> -->
<div class="pa-5">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="3">
<label class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
실행 일자
</label>
</v-col>
<v-col :cols="9">
<div class="calcDtpicker-container">
<v-text-field
id="calcDtpicker"
ref="calcDtpicker"
v-model="calcDt"
:class="'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="calcDtpicker-container"
id="calcDtpicker-container"
></div>
</template>
</v-text-field>
</div>
</v-col>
</v-row>
</div>
<!-- </v-card-actions> -->
<span class="pa-4">고급옵션</span>
<div class="px-5 pb-4">
<v-row class="search-box py-2" align="center" no-gutters>
<v-col :cols="3">
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
CBL days
</label>
</v-col>
<v-col :cols="9">
<v-text-field
v-model="cblClacDays"
class="v-input__custom"
outlined
:hide-details="true"
></v-text-field>
</v-col>
</v-row>
<v-row class="search-box py-2" align="center" no-gutters>
<v-col :cols="3">
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
MIN/MAX days
</label>
</v-col>
<v-col :cols="9">
<v-text-field
v-model="minMaxDays"
class="v-input__custom"
outlined
:hide-details="true"
></v-text-field>
</v-col>
</v-row>
<v-row class="search-box py-2" align="center" no-gutters>
<v-col :cols="3">
<label 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">
<div class="exclDtpicker-container">
<v-text-field
id="exclDtpicker"
ref="exclDtpicker"
v-model="exclDt"
:class="'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="exclDtpicker-container"
id="exclDtpicker-container"
></div>
</template>
</v-text-field>
</div>
</v-col>
<v-col :cols="2">
<v-btn :ripple="false" @click="btnAction('add')">추가</v-btn>
</v-col>
</v-row>
<div
id="exclDtListValDiv"
class="px-5 mb-1 h100"
style="overflow-y: auto; max-height:72px"
></div>
</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark :ripple="false" @click="btnAction('save')"
>확인</v-btn
>
<v-btn
color="primary"
dark
:ripple="false"
@click="btnAction('close')"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import InputText from '~/components/common/form/InputText';
import Label from '~/components/common/form/Label';
import TuiDatepicker from 'tui-date-picker';
import Buttons from '~/components/common/button/Buttons';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: true,
},
},
components: {
InputText,
Label,
TuiDatepicker,
Buttons,
Utility,
},
data() {
return {
dialog: false,
snarComId: null,
snarId: null,
simulId: null,
calcDt: this.convertStringToDateFormat(new Date()),
exclDt: this.convertStringToDateFormat(new Date()),
calcDtDatepickerInstance: null,
exclDtDatepickerInstance: null,
cblClacDays: null,
minMaxDays: null,
exclDtListData: null,
exclDtListVal: [],
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
},
watch: {
async chkDialog(val) {
if (val) {
this.openDialog();
} else {
}
},
},
created() {
window.exclDtDel = this.exclDtDel;
},
mounted() {
//this.tuiCalendarInit();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
...mapActions({
postUpdateApi: 'modules/list/postUpdateApi',
}),
tuiCalendarInit() {
const calcDtContainer = document.getElementById('calcDtpicker-container');
const calcDtTarget = document.getElementById('calcDtpicker');
const exclDtContainer = document.getElementById('exclDtpicker-container');
const exclDtTarget = document.getElementById('exclDtpicker');
this.calcDtDatepickerInstance = new TuiDatepicker(calcDtContainer, {
date: new Date(),
language: 'ko',
type: 'date',
input: {
element: calcDtTarget,
format: 'yyyy-MM-dd',
},
timePicker: false,
calendar: {
showToday: false,
},
});
this.exclDtDatepickerInstance = new TuiDatepicker(exclDtContainer, {
date: new Date(),
language: 'ko',
type: 'date',
input: {
element: exclDtTarget,
format: 'yyyy-MM-dd',
},
timePicker: false,
calendar: {
showToday: false,
},
});
// datepicker 초기값 생성
this.calcDtDatepickerInstance.setDate(new Date());
this.exclDtDatepickerInstance.setDate(new Date());
// datepicker 초기값 생성 끝
// datepicker 변경시 이벤트 추가
this.calcDtDatepickerInstance.on('change', () => this.getCalcDt());
this.exclDtDatepickerInstance.on('change', () => this.getExclDt());
// datepicker 이벤트는 mount 될때 추가 해주어야 한다.
},
getCalcDt() {
const dt = this.calcDtDatepickerInstance.getDate();
//this.calcDt = dt.toISOString().substr(0, 10);
this.calcDt = Utility.setFormatDate(dt, 'YYYY-MM-DD');
},
getExclDt() {
const dt = this.exclDtDatepickerInstance.getDate();
this.exclDt = Utility.setFormatDate(dt, 'YYYY-MM-DD');
//this.exclDt = dt.toISOString().substr(0, 10);
},
convertStringToDateFormat(val) {
var result = '';
result = Utility.setFormatDate(val, 'YYYY-MM-DD');
return result;
},
async openDialog() {
this.cblClacDays = null;
this.minMaxDays = null;
this.calcDt = Utility.setFormatDate(new Date(), 'YYYY-MM-DD');
this.exclDt = Utility.setFormatDate(new Date(), 'YYYY-MM-DD');
this.exclDtListVal = [];
this.$nextTick(() => {
this.tuiCalendarInit();
});
},
async btnAction(action) {
switch (action) {
case 'close':
this.dialog = !this.dialog;
document.getElementById('exclDtListValDiv').innerHTML = '';
break;
case 'save':
if (this.cblClacDays == null || this.minMaxDays == null) {
alert('필수값을 입력해주세요.');
} else {
await this.insertDetail();
this.dialog = !this.dialog;
document.getElementById('exclDtListValDiv').innerHTML = '';
}
break;
case 'add':
var chkVal = true;
for (var j = 0; j < this.exclDtListVal.length; j++) {
if (this.exclDtListVal[j] == this.exclDt.substr(0, 10))
chkVal = false;
}
if (!chkVal) {
alert('같은 날짜가 있습니다.');
} else {
this.exclDtListVal.push(this.exclDt.substr(0, 10));
var tmp = '';
for (var i = 0; i < this.exclDtListVal.length; i++) {
tmp +=
"<div class='no-gutters align-center' style='display:inline-block; padding:5px;'>" +
"<span id='exclDt" +
i +
"' class='pr-2' style='font-size:14px'>" +
this.exclDtListVal[i] +
'</span>' +
"<i aria-hidden='true' class='v-icon notranslate mr-1 mdi mdi-close-circle-outline theme--dark' onclick='exclDtDel(" +
i +
")' style='cursor: pointer;'></i>" +
'</div>';
}
document.getElementById('exclDtListValDiv').innerHTML = tmp;
this.exclDtListData = this.exclDtListVal.toString();
}
break;
}
},
exclDtDel(val) {
this.exclDtListVal.splice(val, 1);
var tmp = '';
for (var i = 0; i < this.exclDtListVal.length; i++) {
tmp +=
"<div class='no-gutters align-center' style='display:inline-block; padding:5px;'>" +
"<span id='exclDt" +
i +
"' class='pr-2' style='font-size:14px'>" +
this.exclDtListVal[i] +
'</span>' +
"<i aria-hidden='true' class='v-icon notranslate mr-1 mdi mdi-close-circle-outline theme--dark' onclick='exclDtDel(" +
i +
")' style='cursor: pointer;'></i>" +
'</div>';
}
document.getElementById('exclDtListValDiv').innerHTML = tmp;
this.exclDtListData = this.exclDtListVal.toString();
},
async insertDetail() {
var params = {
comId: this.snarComId,
simulId: this.simulId,
snarId: this.snarId,
calcDt: this.calcDt.substr(0, 10).replace(/-/g, ''),
exclDt: String(this.exclDtListData).replace(/-/g, ''),
cblClacDays: this.cblClacDays,
minMaxDays: this.minMaxDays,
regUserNo: null,
regDttm: null,
procUserNo: null,
procDttm: null,
};
let statusCd = await this.postUpdateApi({
apiKey: 'saveSnarExecPop',
sendParam: {
datas: {
saveSnarExecPop: [params],
},
params: {},
},
});
console.log('statusCd', statusCd);
if (statusCd.data.retnCd == 0) {
const params2 = {
simulationId: statusCd.data.dataset.simulId,
scenarioId: this.snarId,
comId: this.snarComId,
};
const res = await this.$axios.post(
'http://192.168.10.17:3000/fems',
params2,
);
}
this.setPageData({
isFind: true,
});
},
},
};
</script>
<style scoped lang="scss">
.calcDtpicker-container {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#calcDtpicker-container {
width: 100%;
position: absolute;
top: 36px;
left: 0;
}
}
}
}
.exclDtpicker-container {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#exclDtpicker-container {
width: 100%;
position: absolute;
top: -256px;
left: 0;
}
}
}
}
.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;
}
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,576 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card :height="height">
<v-card-title class="d-flex align-center justify-space-between">
<span class="custom-title-4">{{
this.eqpmYn == 1 ? '공정/설비' : '공정'
}}</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col v-if="label" 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="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<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>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn :ripple="false">초기화</v-btn> -->
<v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()"
>초기화</v-btn
>
<v-btn
v-if="!searchParam.isMulti"
:ripple="false"
@click="search()"
>검색</v-btn
>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="{ height: 'calc(100% - 213px)' }">
<div ref="treeGridParent" class="h100 py-3">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectFtnPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate()">확인</v-btn>
<v-btn :ripple="false" @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
default: '공정/설비',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectFtnPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
disabledRowKeyList: [],
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
// 모달 열기/닫기 값
if (this.searchParam.isMulti == false) {
// delete this.$store.state.pageData[this.parentPrgmId]['modalData'][this.myModalKey].treeGrid.option.rowHeaders[0] = {};
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [];
} else {
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [{ type: 'check' }];
}
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
console.log('facData[selectValue] : ', facData);
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.eccNm);
}
}
} else {
return facData.path === undefined ? facData.eccNm : facData.path;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectFtnPlcListTree },
});
},
created() {
this.init();
if (this.searchParam.isMulti == true) {
this.setPageData({
facInfoList:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
} else {
this.setPageData({
facInfo:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
}
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [{ header: '위치정보', name: 'eccNm' }],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcListTree',
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
roiId: this.searchParam.energyList[this.searchParam.energyCd].cd, // "MTT00001" // 전력 코드 고정
eqpmYn: this.eqpmYn,
search: this.searchWord,
},
});
let myOptionsTree = {
treeColumnOptions: {
name: 'eccNm',
useIcon: true,
},
scrollX: false,
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(
this.$refs.treeGridParent.offsetHeight - 60,
),
myOptionsTree,
),
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'ECC_ID',
value: res.map(item => ({
...item,
eccNm: item.eccNm,
})),
});
const setTreeDataKeys = Object.keys(setTreeData);
const resKeys = []; // eccIdList
const lastChildrenResKeys = [];
const lastChildrenResKeysRowKey = []; // lastChildrenResKeys eccId의 rowKey를 담는 리스트
for (var i = 0; i < res.length; i++) {
resKeys.push(res[i]['eccId']);
// resKeys.push(res[i]['eccId']);
}
for (var i = 0; i < res.length; i++) {
if (!setTreeDataKeys.includes(res[i]['eccId'])) {
lastChildrenResKeys.push(res[i]['eccId']);
}
}
// console.log('res : ', res);
// console.log('setTreeData : ', setTreeData);
// console.log('setTreeData.keys : ', setTreeDataKeys);
// console.log('lastChildrenResKeys : ', lastChildrenResKeys);
// for(var i=0; i<setTreeDataKeys.length; i++){
// for(var j=0; j<setTreeData[setTreeDataKeys[i]].length; j++ ){
// console.log('setTreeData[setTreeDataKeys[i]][j] : ', setTreeData[setTreeDataKeys[i]][j]);
// console.log('setTreeData[setTreeDataKeys[i]][j][rowKey] : ', setTreeData[setTreeDataKeys[i]][j]['rowKey']);
// console.log('setTreeData[setTreeDataKeys[i]][j][uniqueKey] : ', setTreeData[setTreeDataKeys[i]][j]['uniqueKey']);
// console.log('setTreeData[setTreeDataKeys[i]][j][sortKey] : ', setTreeData[setTreeDataKeys[i]][j]['sortKey']);
// console.log('setTreeData[setTreeDataKeys[i]][j][flag] : ', setTreeData[setTreeDataKeys[i]][j]['flag']);
// console.log('setTreeData[setTreeDataKeys[i]][j][eccId] : ', setTreeData[setTreeDataKeys[i]][j]['eccId']);
// if( !setTreeDataKeys.includes(setTreeData[setTreeDataKeys[i]][j]['eccId']) ){
// lastChildrenResKeysRowKey.push(setTreeData[setTreeDataKeys[i]][j]['rowKey']);
// }
// }
// }
// console.log('lastChildrenResKeysRowKey : ', lastChildrenResKeysRowKey);
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT || [],
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
for (var i = 0; i < setTreeDataKeys.length; i++) {
for (var j = 0; j < setTreeData[setTreeDataKeys[i]].length; j++) {
// console.log('setTreeData[setTreeDataKeys[i]][j] : ', setTreeData[setTreeDataKeys[i]][j]);
// console.log('setTreeData[setTreeDataKeys[i]][j][rowKey] : ', setTreeData[setTreeDataKeys[i]][j]['rowKey']);
// console.log('setTreeData[setTreeDataKeys[i]][j][flag] : ', setTreeData[setTreeDataKeys[i]][j]['flag']);
// console.log('setTreeData[setTreeDataKeys[i]][j][eccId] : ', setTreeData[setTreeDataKeys[i]][j]['eccId']);
if (
!setTreeDataKeys.includes(
setTreeData[setTreeDataKeys[i]][j]['eccId'],
)
) {
lastChildrenResKeysRowKey.push(
setTreeData[setTreeDataKeys[i]][j]['rowKey'],
);
}
}
}
// console.log('lastChildrenResKeysRowKey : ', lastChildrenResKeysRowKey);
// console.log(this.$refs['treeGrid' + this.parentPrgmId]);
this.disabledRowKeyList = lastChildrenResKeysRowKey;
for (var i = 0; i < lastChildrenResKeysRowKey.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].disabledRow(
lastChildrenResKeysRowKey[i],
);
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.facInfoList.length > 0
? this.searchParam.facInfoList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
console.log('this.activeRowData[setUpdate] : ', this.activeRowData);
if (this.disabledRowKeyList.includes(this.activeRowData['rowKey'])) {
alert('하위목록이 없는 공정은 선택될 수 없습니다.');
return;
}
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ facInfoList: this.checkedRowDataList });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfoList),
);
} else {
alert('비교대상이 20개를 초과하였습니다.');
}
} else {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfo),
);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
reset() {
for (
var i = 0;
i < this.$refs['treeGrid' + this.parentPrgmId].getData().length;
i++
) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
this.$refs['treeGrid' + this.parentPrgmId].getData()[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
},
search() {
this.getTreeData();
},
typeEnterKey() {
this.getTreeData();
},
},
};
const selectFtnPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,594 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
:readonly="item.readonly || false"
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row align="center" no-gutters>
<v-col :cols="12">
<component
:is="'SelectBox'"
ref="SelectBox1"
:labelCols="2"
:textCols="6"
:disabled="option.eqpmGrpDisableFlag"
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비그룹'"
@update:propsValue="selectValue01 = $event"
:readonly="
item.selectBoxReadonly != undefined
? item.selectBoxReadonly
: false
"
/>
</v-col>
</v-row>
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: 429px;'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 w100">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.pyscModalData.egrpPysclQtyPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
<v-btn
v-if="item.closeBtnFg || false"
:ripple="false"
@click="deleteBtnAction($event)"
>삭제</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '물리량',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '물리량선택',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
eqpmGrpDisableFlag:{
type: Boolean,
require: false,
default: false
}
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
SelectBox,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'egrpPysclQtyPop',
modalDataKey: 'pyscModalData',
searchWord: '',
selectedData: {},
textFieldData: '',
selectValue01: null,
selectValueList01: [],
pyscPopVal: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
eqpmGrpDisableFlag:
this.item !== undefined
? this.item.eqpmGrpDisableFlag !== undefined
? this.item.eqpmGrpDisableFlag
: this.eqpmGrpDisableFlag
: this.eqpmGrpDisableFlag
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
pyscPopValChg(state) {
if (this.item.popupSeq != undefined) {
return state.pageData[this.parentPrgmId]['pyscPopValChg'];
}
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
var dt = {
dialog: this.dialog,
selectedData: this.selectedData,
};
this.$emit('dialogOpenCloseEvent', dt);
},
async selectValue01(value) {
await this.search();
},
pyscPopValChg(value) {
this.pyscPopVal = value;
},
},
beforeCreate() {
this.$store.commit('setPageData', {
pyscModalData: { egrpPysclQtyPop },
});
},
async created() {
await this.setSelectValueList01();
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
async setSelectValueList01() {
// form으로 popup 사용할 때 인자로 eqpmKindId, eqpmGrpId 보내줘야한다.
let res = await this.postApiReturn({
apiKey: 'selectEqpmGrpCodeList',
resKey: 'eqpmGrpCodeLists',
sendParam: {
eqpmKindId:
this.item.eqpmKindId != undefined
? this.item.eqpmKindId
: this.searchParam.eqpmKindId,
},
// form을 통해 popup을 사용할 경우 -> this.item.eqpmKindId 사용
// 부모 페이지에서 설비종류인 eqpmKindId 값을 꼭 가져와야한다.
});
if (res.length > 0) {
this.selectValueList01 = await res.map(obj => {
return {
text: obj.eqpmGrpNm,
value: obj.eqpmGrpId,
};
});
// form을 통해 popup을 사용할 경우 -> this.item.eqpmGrpId 사용
// 부모 페이지에서 설비그룹을 선택한 값이 있다면(eqpmGrpId) 그 값으로 바인딩 아닐 경우 조회한 데이터의 첫번째 값으로 선택
// console.log('this.item.eqpmGrpId : ', this.item.eqpmGrpId);
// console.log('this.searchParam.eqpmGrpId : ', this.searchParam.eqpmGrpId);
this.selectValue01 =
this.item.eqpmGrpId != undefined
? this.item.eqpmGrpId
: this.searchParam.eqpmGrpId != undefined
? this.searchParam.eqpmGrpId
: this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '설비종류', name: 'eqpmKindId', hidden: true },
{ header: '설비그룹ID', name: 'eqpmGrpId', hidden: true },
{ header: '물리량ID', name: 'pysclQtyId', width: 100 },
{
header: '물리량코드',
name: 'pysclQtyCd',
align: 'left',
},
{ header: '물리량명', name: 'pysclQtyNm', width: 100 },
{ header: 'pysclQtyTp', name: 'pysclQtyTp', hidden: true },
{ header: '물리량타입', name: 'pysclQtyTpNm', width: 80 },
// { header: 'rowStat', name : 'rowStat'},
],
});
},
async getGridData() {
this.loadGrid = false;
let res = [];
res = await this.postApiReturn({
apiKey: 'selectEgrpPysclQtyPop',
resKey: 'egrpPysclQtyData',
sendParam: {
searchWord: this.searchWord,
eqpmGrpId: this.selectValue01,
openMode: this.item.openMode,
},
});
let newRes = [];
let tempTagList = this.pyscPopVal.split('/*wq2a/');
let tagList = tempTagList.filter(item => item != '');
if (tagList.length > 0) {
newRes = res.filter(item => {
return !tagList.includes(item.pysclQtyId);
});
res = newRes;
}
//이미 선택된 값들 제거(배열)
if (this.item.dataList) {
if (this.item.dataList.length > 0) {
newRes = res.filter(item => {
return !this.item.dataList.includes(item.pysclQtyId);
});
res = newRes;
}
}
// res = [
// {
// 'pysclQtyId' : 'PYSCL00001',
// 'pysclQtyCd' : 'AMP_1A',
// 'pysclQtyNm' : '회로1 전류A',
// 'pysclQtyTpNm' : 'TAG'
// }
// ]
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
let flag = false;
let bindingObj = {};
if (this.item.bindingItemList != undefined) {
bindingObj = this.item.bindingItemList;
}
if (
bindingObj.constructor === Object &&
Object.keys(bindingObj).length === 0
) {
this.textFieldData = this.selectedData.calcProc;
} else {
for (const [parentPageBindingKey, popupBindingKey] of Object.entries(
bindingObj,
)) {
// 여러 물리량 popup을 사용시 같은 물리량 ID 선택을 방지////
if (this.item.popupSeq != undefined) {
flag = this.checkPyscPopVal(this.selectedData[popupBindingKey]);
}
if (flag) {
alert('물리량이 중복 선택되었습니다.');
break;
}
/////////////////////////////////////////////////////////
this.myBindingData[parentPageBindingKey] = this.selectedData[
popupBindingKey
];
const dt = {
columnName: parentPageBindingKey,
value: this.selectedData[popupBindingKey],
};
this.$emit('gridEditingFinish', dt);
this.setPageData({
[parentPageBindingKey]: this.selectedData[popupBindingKey],
});
}
}
this.dialog = flag;
},
async dialogOpenCloseEvent(val) {
await this.setSelectValueList01();
if (!this.myBindingData) {
return alert('그리드를 먼저 선택해주세요.');
}
this.dialog = !val;
},
deleteBtnAction(v) {
this.dialog = false;
let bindingObj = {};
if (this.item.bindingItemList != undefined) {
bindingObj = this.item.bindingItemList;
}
if (
bindingObj.constructor === Object &&
Object.keys(bindingObj).length === 0
) {
this.textFieldData = null;
} else {
for (const [parentPageBindingKey, popupBindingKey] of Object.entries(
bindingObj,
)) {
this.myBindingData[parentPageBindingKey] = null;
const dt = {
columnName: parentPageBindingKey,
value: null,
};
this.$emit('gridEditingFinish', dt);
this.setPageData({ [parentPageBindingKey]: null });
}
}
},
checkPyscPopVal(data) {
//GdIdxMngPage의 setPyscPopValChg 참고
let tempList = [];
let res = false;
tempList = this.pyscPopVal.split('/*wq2a/');
if (tempList.includes(data)) {
if (this.item.popupSeq > tempList.indexOf(data)) {
res = true;
}
}
return res;
},
},
};
var egrpPysclQtyPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,684 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
outlined
:hide-details="true"
:disabled="item.disabled || false"
:required="item.required || false"
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="900"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title
class="v-card__title d-flex align-center justify-space-between"
>
<span class="custom-title-4">{{ item.label }}</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<!-- <v-card-actions> -->
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col :cols="label ? 3 : ''">
<component
:is="'selectCodeList'"
:parentPrgmId="parentPrgmId"
:label="'계약구분'"
dataKey="searchElecContKind"
:sendParam="{ commGrpCd: 'EM_CONT', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="label ? 3 : ''">
<component
:is="'selectCodeList'"
:parentPrgmId="parentPrgmId"
:label="'전압구분'"
dataKey="searchVoltKind"
:sendParam="{ commGrpCd: 'EM_VOLT_KIND', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col :cols="label ? 3 : ''">
<component
:is="'selectCodeList'"
:parentPrgmId="parentPrgmId"
:label="'전압구분'"
dataKey="searchOptKind"
:sendParam="{ commGrpCd: 'EM_VOLT_OPT', useFg: '1' }"
:addAll="true"
/>
</v-col>
<v-col cols="3" class="text-right">
<v-btn
v-if="!searchParam.isMulti"
:ripple="false"
@click="search()"
>검색</v-btn
>
<v-btn
v-if="!searchParam.isMulti"
:ripple="false"
@click="initVal()"
>초기화</v-btn
>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<v-card-text>
<div id="gridParent" ref="gridParent" style="height: 500px">
<component
:ref="'gridName' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData2.selectElecPowChrgPopList"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
},
},
components: {
Grid,
selectCodeList,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectElecPowChrgPopList',
gridName: 'rowElecContGrid',
loadGrid: false,
dialog: false,
modalDataKey: 'modalData2',
activeRowData: {},
checkedRowDataList: [],
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
rowGridSelectData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId].rowGridSelectData;
} else {
return state.pageData[this.parentPrgmId][this.bindingData]
.rowGridSelectData;
}
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
chkElecContKind() {
return this.searchParam.searchElecContKind;
},
chkVoltKind() {
return this.searchParam.searchVoltKind;
},
chkOptKind() {
return this.searchParam.searchOptKind;
},
selectValue: {
get() {
// if(this.searchParam.rowGridSelectData){
// return this.searchParam.rowGridSelectData[this.item.valueNm];
// }
return this.myBindingData ? this.myBindingData[this.item.valueNm] : '';
},
set(value) {
// return value;
// return this.myBindingData({ [this.item.valueNm]: value });
//return this.setPageData({ [this.item.valueNm]: value });
return this.myBindingData({ [this.item.valueNm]: value });
},
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getData();
} else {
this.searchParam.searchElecContKind = '';
this.searchParam.searchVoltKind = '';
this.searchParam.searchOptKind = '';
}
},
chkElecContKind() {
if (this.dialog) {
this.getData();
}
},
chkVoltKind() {
if (this.dialog) {
this.getData();
}
},
chkOptKind() {
if (this.dialog) {
this.getData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { selectElecPowChrgPopList },
});
},
created() {
this.init();
// if(this.searchParam.isMulti == true){
// this.setPageData({
// facInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }else{
// this.setPageData({
// facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const myOptions = {};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(Utility.defaultGridOption(490), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
// 계약 정보 조회
async getData() {
this.loadGrid = false;
let res = [];
res = await this.postApiReturn({
apiKey: 'selectElecPowChrgInfo',
resKey: 'elecPowChrgInfoData',
sendParam: {
elecContKind: this.searchParam.searchElecContKind,
voltKind: this.searchParam.searchVoltKind,
optKind: this.searchParam.searchOptKind,
},
});
// function setRowSpanAttribute(
// res,
// targetAttributeName,
// targetAttributeList,
// ) {
// if (!(res.length && res.length >= 1)) {
// return;
// }
// if (targetAttributeList == undefined) {
// var currentCnt = 1;
// var currentIdx = 0;
// var currentValue = res[0][targetAttributeName];
// for (var i = 1; i < res.length; i++) {
// if (res[i][targetAttributeName] != currentValue) {
// if (res[currentIdx]['_attributes'] == undefined) {
// res[currentIdx]['_attributes'] = { rowSpan: new Object() };
// //추가용
// res[currentIdx]['_attributes']['className'] = {column:new Object()};
// //추가용
// }
// res[currentIdx]['_attributes']['rowSpan'][
// targetAttributeName
// ] = currentCnt;
// //추가용
// res[currentIdx]['_attributes']['className']['column'][targetAttributeName] = ['rowSpan-done'];
// //추가용
// currentValue = res[i][targetAttributeName];
// currentCnt = 1;
// currentIdx = i;
// } else if (
// res[i][targetAttributeName] == currentValue &&
// i == res.length - 1
// ) {
// currentCnt = currentCnt + 1;
// if (res[currentIdx]['_attributes'] == undefined) {
// res[currentIdx]['_attributes'] = { rowSpan: new Object() };
// //추가용
// res[currentIdx]['_attributes']['className'] = {column:new Object()};
// //추가용
// }
// res[currentIdx]['_attributes']['rowSpan'][
// targetAttributeName
// ] = currentCnt;
// //추가용
// res[currentIdx]['_attributes']['className']['column'][targetAttributeName] = ['rowSpan-done'];
// //추가용
// } else {
// currentCnt = currentCnt + 1;
// }
// }
// } else {
// var currentCnt = 1;
// var currentIdx = 0;
// for (var i = 1; i < res.length; i++) {
// if (!compareValue(res, targetAttributeList, currentIdx, i)) {
// if (res[currentIdx]['_attributes'] == undefined) {
// res[currentIdx]['_attributes'] = { rowSpan: new Object() };
// //추가용
// res[currentIdx]['_attributes']['className'] = {column:new Object()};
// //추가용
// }
// if (currentCnt != 1) {
// res[currentIdx]['_attributes']['rowSpan'][
// targetAttributeName
// ] = currentCnt;
// //추가용
// res[currentIdx]['_attributes']['className']['column'][targetAttributeName] = ['rowSpan-done'];
// //추가용
// }
// currentCnt = 1;
// currentIdx = i;
// } else if (
// compareValue(res, targetAttributeList, currentIdx, i) &&
// i == res.length - 1
// ) {
// currentCnt = currentCnt + 1;
// if (res[currentIdx]['_attributes'] == undefined) {
// res[currentIdx]['_attributes'] = { rowSpan: new Object() };
// //추가용
// res[currentIdx]['_attributes']['className'] = {column:new Object()};
// //추가용
// }
// if (currentCnt != 1) {
// res[currentIdx]['_attributes']['rowSpan'][
// targetAttributeName
// ] = currentCnt;
// //추가용
// res[currentIdx]['_attributes']['className']['column'][targetAttributeName] = ['rowSpan-done'];
// //추가용
// }
// } 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;
// }
// }
// setRowSpanAttribute(res, 'elecContKindNm');
// setRowSpanAttribute(res, 'voltKindNm');
// setRowSpanAttribute(res, 'optKindNm');
// setRowSpanAttribute(res, 'baseChrg');
function setRowSpanAttribute(
separateColStandardList,
res,
targetAttributeName,
rowSpanList
) {
if (!(res.length && res.length >= 2)) {
return;
}
var valueList = [];
var rowSpanValueList = [];
var currentIdx = 0;
for (var i = 0; i < res.length; i++) {
valueList.push(res[i][targetAttributeName]);
}
function makeCurrentSeparateVal(idx, separateColStandardList) {
let returnVal = '';
for (var i = 0; i < separateColStandardList.length; i++) {
returnVal += res[idx][separateColStandardList[i]];
}
return returnVal;
}
let beforeSeparateVal = makeCurrentSeparateVal(
0,
separateColStandardList,
);
rowSpanValueList[0] = [valueList[0], 1, currentIdx];
for (var i = 1; i < valueList.length; i++) {
currentIdx += 1;
let currentSeparateVal = makeCurrentSeparateVal(
i,
separateColStandardList,
);
if (
currentSeparateVal == beforeSeparateVal &&
valueList[i] == rowSpanValueList[rowSpanValueList.length - 1][0]
) {
rowSpanValueList[rowSpanValueList.length - 1][1] += 1;
} else {
rowSpanValueList[rowSpanValueList.length] = [
valueList[i],
1,
currentIdx,
];
beforeSeparateVal = currentSeparateVal;
}
}
for (var i = 0; i < rowSpanValueList.length; i++) {
if (rowSpanValueList[i][1] === 1) {
continue;
}
if (res[rowSpanValueList[i][2]]['_attributes'] == undefined) {
res[rowSpanValueList[i][2]]['_attributes'] = {
rowSpan: new Object(),
};
//추가용
res[rowSpanValueList[i][2]]['_attributes']['className'] = {column:new Object()};
for(var j=0; j<rowSpanList.length; j++){
res[rowSpanValueList[i][2]]['_attributes']['className']['column'][rowSpanList[j]] = ['colrowspan'];
}
//추가용
}
res[rowSpanValueList[i][2]]['_attributes']['rowSpan'][
targetAttributeName
] = rowSpanValueList[i][1];
res[rowSpanValueList[i][2]]['_attributes']['className']['column'][targetAttributeName].push(['rowrowspan']);
}
}
// rowSpanList 합쳐지는 row colNm을 넣어야
let rowSpanList = ['elecContKindNm', 'voltKindNm', 'optKindNm', 'baseChrg'];
setRowSpanAttribute(['elecContKindNm'], res, 'elecContKindNm', rowSpanList);
setRowSpanAttribute(['elecContKindNm'], res, 'voltKindNm', rowSpanList);
setRowSpanAttribute(['elecContKindNm'], res, 'optKindNm', rowSpanList);
setRowSpanAttribute(['elecContKindNm'], res, 'baseChrg', rowSpanList);
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
async getRowData(data) {
this.activeRowData = data;
},
setUpdate() {
if (this.searchParam.isMulti) {
// 멀티 처리 필요사 시용...
// this.checkedRowDataList = this
} else {
this.dialog = false;
var nm = this.item.valueNm;
if (nm == 'elecContId') {
this.myBindingData.elecContId = this.activeRowData.eleclContId;
this.myBindingData.elecContNm = this.activeRowData.eleclContNm;
const dt1 = {
columnName: 'elecContId',
value: this.activeRowData.eleclContId,
};
const dt2 = {
columnName: 'elecContNm',
value: this.activeRowData.eleclContNm,
};
this.$emit('gridEditingFinish', dt1);
this.$emit('gridEditingFinish', dt2);
}
}
},
initVal() {
this.dialog = false;
var nm = this.item.valueNm;
if (nm == 'elecContId') {
this.myBindingData.elecContId = '';
this.myBindingData.elecContNm = '';
const dt1 = {
columnName: 'elecContId',
value: '',
};
const dt2 = {
columnName: 'elecContNm',
value: '',
};
this.$emit('gridEditingFinish', dt1);
this.$emit('gridEditingFinish', dt2);
}
},
search() {
this.getData();
},
},
};
document.querySelector("#gridParent > div > div > div.tui-grid-content-area > div.tui-grid-rside-area > div.tui-grid-body-area > div > div.tui-grid-table-container > table > tbody > tr.tui-grid-row-odd.tui-grid-cell-current-row")
const selectElecPowChrgPopList = {
rowElecContGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
const myColumns = [
{ header: '전력계약 ID', name: 'eleclContId', hidden: true},
{ header: '전력계약 명', name: 'eleclContNm', hidden: true},
{ header: '전력계약구분CD', name: 'elecContKind', hidden: true},
{ header: '전력계약구분', name: 'elecContKindNm', align: 'center'},
{ header: '전압구분CD', name: 'voltKind', hidden: true },
{ header: '전압구분', name: 'voltKindNm', align: 'center' },
{ header: '옵션CD', name: 'optKind', hidden: true },
{ header: '옵션', name: 'optKindNm', align: 'center' },
{
header: '기본요금(원/kW)',
name: 'baseChrg',
align: 'right',
formatter({ value }) {
return Utility.setFormatInt(value);
},
},
{ header: '시간대CD', name: 'peakKind', hidden: true },
{ header: '시간대', name: 'peakKindNm', align: 'center' },
{
header: '여름철(6~8월)',
name: 'unitPrcSum',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
{
header: '봄·가을철(3~5,9~10월)',
name: 'unitPrcSprfal',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
{
header: '겨울철(11~2월)',
name: 'unitPrcWin',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
];
// 전력량 요금(원/kWh)
</script>
<style lang="scss">
// @import '@/assets/scss/common.scss';
@import '@/assets/scss/var.scss';
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.tui-grid {
&-row-odd,
&-row-even {
&:hover > .colrowspan{
background-color: map-deep-get(
$config,
#{$theme},
"tui-grid-cell-backgroundColor"
)!important;
.tui-grid-cell-content {
color: map-deep-get($config, #{$theme}, "activate")!important;
}
}
}
&-cell{
&.row-selected.colrowspan{
background-color: map-deep-get(
$config,
#{$theme},
"tui-grid-cell-backgroundColor"
)!important;
.tui-grid-cell-content {
color: map-deep-get($config, #{$theme}, "activate")!important;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,723 @@
<template>
<div>
<v-dialog
v-model="dialog"
width="900"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card>
<v-toolbar
:color="isDarkMode ? '#2d3355' : '#3f4d7d'"
class="py-4 pr-3 pl-5"
height="auto"
>
<v-toolbar-title>{{ label }}</v-toolbar-title>
<!-- <v-btn
icon
tile
small
:ripple="false"
@click="btnAction('close')"
:style="{ backgroundColor: isDarkMode ? '#2d3355' : '#3f4d7d' }"
>
<v-icon>mdi-close</v-icon>
</v-btn> -->
</v-toolbar>
<template>
<div style="padding : 20px">
<v-col :cols="12">
<v-row>
<v-col :cols="6">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
점검자
</label>
</v-col>
<v-col :cols="8">
<v-text-field
v-model="chkMan"
class="v-input__custom"
:disabled="componentDisableFlag"
outlined
:hide-details="true"
></v-text-field>
</v-col>
</v-row>
</v-col>
<v-col :cols="6">
<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="8">
<div class="startpicker-container2">
<v-text-field
id="startpicker2"
ref="startpicker2"
v-model="targetDateTimeValue"
:class="'v-input__custom'"
:hide-details="true"
readonly
outlined
:disabled="componentDisableFlag"
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="startpicker-container2"
id="startpicker-container2"
></div>
</template>
</v-text-field>
</div>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col :cols="6">
<EqpmPop
:parentPrgmId="parentPrgmId"
:bindOption="myBindOption"
ref="eqpmPopInDetailPop"
:disabled="componentDisableFlag"
:textCols="8"
/>
</v-col>
<v-col :cols="6">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
설비용량
</label>
</v-col>
<v-col :cols="8">
<v-text-field
v-model="eqpmCapa"
class="v-input__custom"
:disabled="componentDisableFlag"
outlined
:hide-details="true"
type="number"
></v-text-field>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col :cols="6">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="4">
<label class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
점검결과
</label>
</v-col>
<v-col :cols="8">
<!-- <v-text-field
v-model="chkRslt"
class="v-input__custom"
:disabled="componentDisableFlag"
outlined
:hide-details="true"
></v-text-field> -->
<v-select
v-model="chkRslt"
:items="chkRsltList"
:item-text="chkRsltList.text"
:item-value="chkRsltList.value"
outlined
:hide-details="true"
append-icon="mdi-chevron-down"
class="v-select__custom"
:disabled="componentDisableFlag"
></v-select>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label 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-textarea
v-model="chkExctCntn"
class="v-input__custom"
:disabled="componentDisableFlag"
outlined
:hide-details="true"
:maxlength="1000"
></v-textarea>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label 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-textarea
v-model="elecEqpmSafeMngOpn"
class="v-input__custom"
:disabled="componentDisableFlag"
outlined
:hide-details="true"
:maxlength="1000"
></v-textarea>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row>
<v-col v-show="!componentDisableFlag" :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label 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-file-input
multiple
background-color="#47535c"
show-size
v-model="fileData"
hide-details="true"
>
</v-file-input>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row
v-show="popUpAction === 'read' || popUpAction === 'update'"
>
<v-col :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label 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-row
v-for="fileData in fileList"
:key="fileData.apndFileId"
>
<a @click.prevent="downloadFile(fileData)">
<v-col :cols="12">
<div class="search-box-label">
{{
fileData.apndFileNm + '.' + fileData.apndFileExt
}}
</div>
</v-col>
</a>
<v-icon
v-show="popUpAction === 'update'"
class="pl-5"
@click="addFileToDeleteFileList(fileData)"
>
mdi-close
</v-icon>
</v-row>
</v-col>
</v-row>
</v-col>
</v-row>
</v-col>
</div>
</template>
<v-card-actions class="justify-end">
<v-btn
v-show="!componentDisableFlag"
:ripple="false"
@click="btnAction('save')"
>저장</v-btn
>
<v-btn :ripple="false" @click="btnAction('close')">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import InputText from '~/components/common/form/InputText';
import InputNumber from '~/components/common/form/InputNumber';
import TextArea from '~/components/common/form/TextArea';
import SelectBox from '~/components/common/form/SelectBox';
import SelectBoxes from '~/components/common/form/SelectBoxes';
import CheckBox from '~/components/common/form/CheckBox';
import Label from '~/components/common/form/Label';
import EqpmPop from '~/components/common/modal/EqpmPop';
import TuiDatepicker from 'tui-date-picker';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
default: '',
},
},
components: {
InputText,
InputNumber,
TextArea,
SelectBox,
SelectBoxes,
CheckBox,
Label,
EqpmPop,
TuiDatepicker,
Utility,
},
data() {
return {
dialog: false,
popUpAction: 'read', // 'read', 'insert', 'update'
myBindOption: {
eqpmId: 'modalmodalEqpmId',
eqpmNm: 'modalmodalEqpmNm',
parentModalState: 'close',
},
chkMan: '',
chkDd: '',
eqpmNm: '',
eqpmId: '',
eqpmCapa: '',
chkRslt: '',
chkExctCntn: '',
elecEqpmSafeMngOpn: '',
fileData: null,
fileList: null,
targetDateTimeValue: new Date().toISOString().substr(0, 10),
startDatepickerInstance: null,
deleteFileList: [],
chkRsltList: [
{ text: '적합', value: 'Y' },
{ text: '부적합', value: 'N' },
],
};
},
computed: {
...mapState({
searchParam(state) {
//console.log("#################")
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
componentDisableFlag() {
if (this.popUpAction === 'read') {
return true;
} else {
return false;
}
},
},
watch: {
async chkDialog(val) {
if (val) {
this.openDialog();
this.$nextTick(() => {
if (this.popUpAction === 'insert') {
this.$refs['eqpmPopInDetailPop'].parentModalState = 'openWithInit';
} else {
this.$refs['eqpmPopInDetailPop'].parentModalState = 'open';
}
});
} else {
this.$nextTick(() => {
this.$refs['eqpmPopInDetailPop'].parentModalState = 'close';
});
}
},
},
mounted() {
// this.tuiCalendarInit();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
...mapActions({
postApi: 'modules/list/postApi',
postUpdateApi: 'modules/list/postUpdateApi',
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
chkOpenTabList: 'chkOpenTabList',
getDomain: 'modules/list/getDomain',
}),
tuiCalendarInit() {
const startContainer = document.getElementById('startpicker-container2');
const startTarget = document.getElementById('startpicker2');
this.startDatepickerInstance = new TuiDatepicker(startContainer, {
date: new Date(),
language: 'ko',
type: 'date',
input: {
element: startTarget,
format: 'YYYY-MM-DD',
},
timePicker: false,
});
this.startDatepickerInstance.on('change', () => this.getStartDt());
},
getStartDt() {
const dt = this.startDatepickerInstance.getDate();
this.targetDateTimeValue = String(dt.toISOString()).substr(0, 10);
},
convertStringToDateFormat(val) {
var result = '';
result = Utility.setFormatDate(val, 'YYYY-MM-DD');
return result;
},
convertDateFormatToString(val) {
return val.replaceAll('-', '');
},
async getFileList(apndFileUuid) {
var fileList = [];
if (apndFileUuid === null || apndFileUuid === '') {
return fileList;
}
fileList = await this.postUpdateApi({
apiKey: 'selectApndFile',
sendParam: {
params: {
apndFileUuid: apndFileUuid,
},
datas: {},
},
});
return fileList.data.dataset.apndFile;
},
async openDialog() {
this.targetDateTimeValue = '';
this.fileList = null;
this.fileData = null;
this.deleteFileList = [];
//datepicker setting
this.$nextTick(() => {
this.tuiCalendarInit();
switch (this.popUpAction) {
case 'read':
this.targetDateTimeValue = this.convertStringToDateFormat(
this.searchParam.rowGridSelectData.chkDd,
);
break;
case 'insert':
this.targetDateTimeValue = this.convertStringToDateFormat(
new Date(),
);
break;
case 'update':
this.targetDateTimeValue = this.convertStringToDateFormat(
this.searchParam.rowGridSelectData.chkDd,
);
break;
}
});
switch (this.popUpAction) {
case 'read':
this.chkMan = this.searchParam.rowGridSelectData.chkMan;
this.eqpmNm = this.searchParam.rowGridSelectData.eqpmNm;
this.eqpmId = this.searchParam.rowGridSelectData.eqpmId;
this.eqpmCapa = this.searchParam.rowGridSelectData.eqpmCapa;
this.chkRslt = this.searchParam.rowGridSelectData.chkRslt;
this.chkExctCntn = this.searchParam.rowGridSelectData.chkExctCntn;
this.elecEqpmSafeMngOpn = this.searchParam.rowGridSelectData.elecEqpmSafeMngOpn;
this.fileList = await this.getFileList(
this.searchParam.rowGridSelectData.apndFileUuid,
);
break;
case 'insert':
this.chkMan = '';
this.eqpmNm = '';
this.eqpmId = '';
this.eqpmCapa = '';
this.chkRslt = '';
this.chkExctCntn = '';
this.elecEqpmSafeMngOpn = '';
this.fileData = null;
break;
case 'update':
this.chkMan = this.searchParam.rowGridSelectData.chkMan;
this.eqpmNm = this.searchParam.rowGridSelectData.eqpmNm;
this.eqpmId = this.searchParam.rowGridSelectData.eqpmId;
this.eqpmCapa = this.searchParam.rowGridSelectData.eqpmCapa;
this.chkRslt = this.searchParam.rowGridSelectData.chkRslt;
this.chkExctCntn = this.searchParam.rowGridSelectData.chkExctCntn;
this.elecEqpmSafeMngOpn = this.searchParam.rowGridSelectData.elecEqpmSafeMngOpn;
this.fileList = await this.getFileList(
this.searchParam.rowGridSelectData.apndFileUuid,
);
break;
}
},
async btnAction(action) {
switch (action) {
case 'close':
this.dialog = !this.dialog;
break;
case 'save':
this.dialog = !this.dialog;
if (this.popUpAction === 'insert') {
await this.insertDetail();
} else if (this.popUpAction === 'update') {
await this.updateDetail();
}
break;
}
},
async insertDetail() {
var fileList = this.fileData;
var apndFileUuid = null;
var formData = new FormData();
if (fileList !== null) {
for (var i = 0; i < fileList.length; i++) {
formData.append('file', fileList[i]);
}
formData.append('elecSafeChkNo', '');
apndFileUuid = await this.postUpdateApi({
apiKey: 'saveFileElecSafeChk',
resKey: 'apndFileUuid',
sendParam: formData,
});
}
apndFileUuid =
apndFileUuid === null ? '' : apndFileUuid.data.dataset.apndFileUuid;
var params = {
chkMan: this.chkMan,
chkDd: this.convertDateFormatToString(this.targetDateTimeValue),
eqpmId: this.searchParam[this.myBindOption.eqpmId],
eqpmCapa: this.eqpmCapa,
chkRslt: this.chkRslt,
chkExctCntn: this.chkExctCntn,
elecEqpmSafeMngOpn: this.elecEqpmSafeMngOpn,
apndFileUuid: apndFileUuid,
rowStat: 'I',
};
await this.postUpdateApi({
apiKey: 'saveElecSafeChk',
sendParam: {
datas: {
dsElecSafeChkData: [params],
},
params: {},
},
});
this.setPageData({
isFind: true,
});
},
async updateDetail() {
var fileList = this.fileData;
var apndFileUuid = null;
var formData = new FormData();
if (fileList !== null) {
for (var i = 0; i < fileList.length; i++) {
formData.append('file', fileList[i]);
}
formData.append(
'elecSafeChkNo',
this.searchParam.rowGridSelectData.elecSafeChkNo,
);
apndFileUuid = await this.postUpdateApi({
apiKey: 'saveFileElecSafeChk',
resKey: 'apndFileUuid',
sendParam: formData,
});
}
var deleteFileParam = {
apndFile: this.deleteFileList,
};
if (this.deleteFileList.length > 0) {
await this.postApiReturn({
apiKey: 'deleteApndFile',
sendParam: deleteFileParam,
});
}
apndFileUuid =
apndFileUuid === null ? '' : apndFileUuid.data.dataset.apndFileUuid;
var params = {
elecSafeChkNo: this.searchParam.rowGridSelectData.elecSafeChkNo,
chkMan: this.chkMan,
chkDd: this.convertDateFormatToString(this.targetDateTimeValue),
eqpmId: this.searchParam[this.myBindOption.eqpmId],
eqpmCapa: this.eqpmCapa,
chkRslt: this.chkRslt,
chkExctCntn: this.chkExctCntn,
elecEqpmSafeMngOpn: this.elecEqpmSafeMngOpn,
apndFileUuid: apndFileUuid,
rowStat: 'U',
};
await this.postUpdateApi({
apiKey: 'saveElecSafeChk',
sendParam: {
datas: {
dsElecSafeChkData: [params],
},
params: {},
},
});
this.setPageData({
isFind: true,
});
},
async downloadFile(item) {
var menuId = 'MNU0002';
var urlPrefix = await this.getDomain();
var downLoadUrl =
urlPrefix +
'comm/base/ApndFileCtr/selectDownloadApndFile?$menuId=' +
menuId +
'&apndFileId=' +
item.apndFileId;
await this.$axios
.get(downLoadUrl, { responseType: 'blob' })
.then(response => {
const blob = new Blob([response.data]);
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = item.apndFileNm + '.' + item.apndFileExt;
link.click();
URL.revokeObjectURL(link.href);
})
.catch(console.error);
},
addFileToDeleteFileList(item) {
this.deleteFileList.push({ apndFileId: item.apndFileId });
var index = null;
if (typeof this.fileList === 'object' && this.fileList.length - 1 >= 0) {
for (var i = 0; i < this.fileList.length; i++) {
if (item.apndFileId === this.fileList[i].apndFileId) {
index = i;
break;
}
}
this.fileList.splice(index, 1);
}
},
},
};
</script>
<style scoped lang="scss">
.startpicker-container2 {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#startpicker-container2,
#endpicker-container2 {
width: 100%;
position: absolute;
top: 36px;
left: 0;
}
}
}
}
.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,246 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="item.label" :cols="item.cols == 12 ? 2 : 4">
<label for="" class="search-box-label">
{{ item.label }}
<span v-if="item.essential">*</span>
</label>
</v-col>
<v-col :cols="item.cols == 12 ? 9 : item.label ? 7 : ''">
<v-row>
<v-col cols="5" class="mr-2">
<v-text-field
readonly
v-model="selectValue1"
class="v-input__custom"
disabled
></v-text-field>
</v-col>
<v-col cols="5" class="mr-2">
<v-text-field
readonly
v-model="selectValue2"
class="v-input__custom"
disabled
></v-text-field>
</v-col>
<v-col cols="1">
<v-btn icon class="v-btn-bg__blue" @click="dialog = !dialog">
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-col>
</v-row>
</v-col>
<v-dialog v-model="dialog" width="640px">
<v-card>
<v-card-title class="d-flex justify-space-between">
<span>검침개소위치</span>
<v-btn icon @click="dialog = false"><v-icon>mdi-close</v-icon></v-btn>
</v-card-title>
<v-card-actions class="flex-column">
<v-row class="w100">
<v-col cols="2">
<label for="" class="search-box-label">
검색
</label>
</v-col>
<v-col cols="7">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
</v-row>
<div id="gridParent" class="w100 popup-container my-3">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData.selectReadPlcPopList"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<div class="w100 text-right">
<v-btn class="v-btn__round v-btn-bg__blue" @click="setUpdate()"
>확인</v-btn
>
</div>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
item: {
type: Object,
require: true,
},
},
components: {
Grid,
},
data() {
return {
myModalKey: 'selectReadPlcPopList',
gridName: 'rowGrid',
loadGrid: false,
changeData: {},
dialog: false,
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData() {
return this.searchParam['rowGridSelectData'];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue1() {
// 선택된 값
return this.myBindingData && this.myBindingData[this.item.valueNm.code]
? this.myBindingData[this.item.valueNm.code]
: null;
},
selectValue2() {
// 선택된 값
return this.myBindingData && this.myBindingData[this.item.valueNm.name]
? this.myBindingData[this.item.valueNm.name]
: null;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
const _this = this;
setTimeout(() => {
_this.init();
}, 300);
setTimeout(() => {
_this.getData();
}, 400);
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadPlcPopList },
});
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.gridInit();
},
gridInit() {
//console.log(document.getElementById("gridParent").offsetHeight);
const gridHeight =
document.getElementById('gridParent').offsetHeight - 30;
const myOptions = {};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: myColumns,
});
},
async getData() {
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcInfoList',
resKey: 'ftnPlcInfoData',
sendParam: {
params: {
comId: this.myBindingData.comId,
blocId: this.myBindingData.blocId,
},
isMulti: false,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: res,
});
this.loadGrid = true;
},
// sms 목록 그리드 클릭 이벤트
async getRowData(data) {
this.changeData = data;
//console.log(data);
},
setUpdate() {
this.dialog = false;
// return false;
this.$emit('gridEditingFinish', {
columnName: this.item.valueNm.code,
value: this.changeData[this.item.valueNm.targetCode],
});
this.$emit('gridEditingFinish', {
columnName: this.item.valueNm.name,
value: this.changeData[this.item.valueNm.targetName],
});
},
},
};
const selectReadPlcPopList = {
rowGrid: {
data: [],
column: [],
option: {},
},
// isMulti: false
};
const myColumns = [
{ header: '설비코드', name: 'plcCd', align: 'center' },
{ header: '설비명', name: 'plcNm' },
{ header: '설비명', name: 'plcCdNm', hidden: true },
];
</script>
<style scoped>
/* .v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
} */
</style>

View File

@ -0,0 +1,452 @@
<template>
<v-row class="search-box" align="center" no-gutters >
<!-- <v-col v-if="label" cols="2"> -->
<!-- <v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
</v-col> -->
<!-- <v-col :cols="label ? textCols : ''">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
outlined
:hide-details="true"
:disabled="item.disabled || false"
:required="item.required || false"
></v-text-field>
</v-col> -->
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="1400"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<!-- <v-card-title
class="v-card__title d-flex align-center justify-space-between"
>
<span class="custom-title-4">{{ '' }}</span>
<v-btn icon tile :ripple="false" @click="closePop()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title> -->
<!-- <v-card-actions> -->
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col :cols="4">
<div class="d-flex align-center justify-space-between pb-5">
<v-card-title class="pa-0">가이드 알람이력</v-card-title>
</div>
</v-col>
<v-col :cols="8" class="text-right">
<v-btn icon tile :ripple="false" @click="closePop()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col>
</v-row>
<v-row 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
v-if="dialog"
v-model="InputValue['eqpmId']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
<v-col :cols="3">
<v-text-field
v-if="dialog"
v-model="InputValue['eqpmNm']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
<v-col :cols="6">
</v-col>
<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
v-if="dialog"
v-model="InputValue['gdIdxId']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
<v-col :cols="3">
<v-text-field
v-if="dialog"
v-model="InputValue['gdIdxNm']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4"> 설비 가이드 정보</v-card-title>
</div>
<div class="px-5" style="height:calc(100% - 76px)">
<div ref="modalGridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid? 'Grid' : null"
:dataPath="searchParam.modalData.eqpmDetlPop"
:gridName="gridName"
:parentPrgmId="parentPrgmId"
/>
</div>
</div>
<!-- <div id="gridParent" ref="gridParent" style="height: 500px">
<component
:ref="'gridName' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData2.modifyEnrgUsePlanData"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div> -->
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="closePop()">확인</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '~/components/common/input/InputText';
import dateUtility from '~/plugins/dateUtility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
}
},
components: {
Grid,
selectCodeList,
dateUtility,
InputText
// Tree
},
data() {
return {
labelPrepend: true,
modalDataKey:'modalData',
myModalKey: 'eqpmDetlPop',
gridName: 'eqpmDetlGrid',
loadGrid: false,
setGrid:false,
popCheck:false,
dialog: false,
activeRowData: {},
checkedRowDataList: [],
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
InputValue: {
get() {
return this.myBindingData;
}
},
chkDialog(){
return this.dialog
},
},
watch: {
async chkDialog(val){
if(!val){
this.closePop();
}else{
// await this.getRowGridData();
}
},
async popCheck(val){
if(val){
await this.getRowGridData();
this.dialog= true;
}else{
this.dialog=false;
}
}
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { eqpmDetlPop },
});
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.gridInit();
},
closePop(){
this.popCheck= false;
},
search() {
// this.getData();
},
gridInit(){
// const gridHeight = this.$refs.gridParent.offsetHeight - 30;
const myOptions = {
rowHeaders: ['rowNum'],
columnOptions: {
resizable: true,
minWidth:100
},
setScroll: true,
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
const myColumns= [
{
header : '발생일',
name : 'totDttmDay',
align:'center'
},
{
header : '발생시간대',
name : 'totDttmTime',
align:'center'
},
{
header : '가이드지표명',
minWidth:200,
name : 'gdIdxNm',
},
{
header : '주의',
width:100,
name : 'careStndVal',
align:'center'
},
{
header : '경고',
width:100,
name : 'warnStndVal',
align:'center'
},
{
header : '가이드값',
width:100,
name : 'totVal',
align:'center'
},
{
header : '알람내용',
minWidth:300,
width:'auto',
name : 'alrmMsg',
},
{
header : '알람종류',
name : 'alrmKind',
hidden:true
},
]
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
// this.getRowGridData();
},
async getRowGridData(){
this.loadGrid =false;
var res = await this.postApiReturn({
apiKey: 'selectEqpmDetailPop',
resKey: 'eqpmDetlPopData',
sendParam: {
gdIdxId : this.myBindingData.gdIdxId,
eqpmId : this.myBindingData.eqpmId,
fromDt : this.myBindingData.fromDt,
toDt : this.myBindingData.toDt
},
});
const dayjs = require('dayjs');
var newRes = res.map(item=>
item = {
...item,
totDttmDay : Utility.setFormatDate(item.totDttm, 'YYYY-MM-DD'),
totDttmTime : Utility.setFormatDate(item.totDttm, 'HH') + "~" + dayjs(item.totDttm).add(1,'h').format('HH'),
}
);
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: newRes,
});
this.loadGrid=true;
this.setGrid = true;
}
},
};
var eqpmDetlPop ={
eqpmDetlGrid:{
data:[],
column:[],
option:{}
}
}
// 전력량 요금(원/kWh)
</script>
<style lang="scss">
// @import '@/assets/scss/common/grid.scss';
.tui-grid-scrollbar-left-bottom {
display: none !important;
}
</style>

View File

@ -0,0 +1,463 @@
<template>
<v-row class="search-box" align="center" no-gutters >
<!-- <v-col v-if="label" cols="2"> -->
<!-- <v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
</v-col> -->
<!-- <v-col :cols="label ? textCols : ''">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
outlined
:hide-details="true"
:disabled="item.disabled || false"
:required="item.required || false"
></v-text-field>
</v-col> -->
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="1400"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<!-- <v-card-title
class="v-card__title d-flex align-center justify-space-between"
>
<span class="custom-title-4">{{ '' }}</span>
<v-btn icon tile :ripple="false" @click="closePop()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title> -->
<!-- <v-card-actions> -->
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col :cols="4">
<div class="d-flex align-center justify-space-between pb-5">
<v-card-title class="pa-0">가이드 정보</v-card-title>
</div>
</v-col>
<v-col :cols="8" class="text-right">
<v-btn icon tile :ripple="false" @click="closePop()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col>
</v-row>
<v-row 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="3">
<v-text-field
v-if="dialog"
v-model="InputValue['gdIdxId']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
<v-col :cols="3">
<v-text-field
v-if="dialog"
v-model="InputValue['gdIdxNm']"
class="v-input__custom"
:readonly="true"
outlined
:hide-details="true"
>
</v-text-field>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4">가이드 정보</v-card-title>
</div>
<div class="px-5">
<v-row>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="계산코드"
valueNm="calcProc"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6">
</v-col>
<v-col :cols="12" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="계산설명"
valueNm="calcDesc"
:iconShow="true"
:labelCols="2"
:textCols="9"
:readonly="true"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="물리량1"
valueNm="pysclQtyId1"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="물리량2"
valueNm="pysclQtyId2"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="물리량3"
valueNm="pysclQtyId3"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="물리량4"
valueNm="pysclQtyId4"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="카테고리1"
valueNm="ctgr1"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="카테고리2"
valueNm="ctgr2"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="주의기준값"
valueNm="careStndVal"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="6">
</v-col>
<v-col :cols="6" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="경고기준값"
valueNm="warnStndVal"
:iconShow="true"
:readonly="true"
:labelCols="4"
:textCols="6"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="알람메세지"
valueNm="alrmMsg"
:iconShow="true"
:labelCols="2"
:textCols="9"
:readonly="true"
/>
</v-col>
<v-col :cols="12" class="py-2">
<InputText
id="gdIdx_InputText"
:parentPrgmId="parentPrgmId"
label="가이드방법"
valueNm="gdMeth"
:iconShow="true"
:labelCols="2"
:textCols="9"
:readonly="true"
/>
</v-col>
</v-row>
</div>
<div style="height:20px;"></div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="closePop()">확인</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '~/components/common/input/InputText';
import dateUtility from '~/plugins/dateUtility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
}
},
components: {
Grid,
selectCodeList,
dateUtility,
InputText
// Tree
},
data() {
return {
labelPrepend: true,
modalDataKey:'modalData2',
myModalKey: 'gdIdxDetPop',
gridName: 'gdIdxDetPop',
loadGrid: false,
setGrid:false,
popCheck:false,
dialog: false,
activeRowData: {},
checkedRowDataList: [],
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
InputValue: {
get() {
return this.myBindingData;
}
},
chkDialog(){
return this.dialog
},
},
watch: {
async chkDialog(val){
if(!val){
this.closePop();
}else{
// await this.getRowGridData();
}
},
async popCheck(val){
if(val){
await this.getData();
this.dialog= true;
}else{
this.dialog=false;
}
}
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { gdIdxDetPop },
});
},
created() {
},
mounted(){
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
// this.gridInit();
},
closePop(){
this.popCheck= false;
},
search() {
// this.getData();
},
async getData(){
var res = await this.postApiReturn({
apiKey: 'selectEnrgEffcGdIdxDetPop',
resKey: 'gdIdxDetPopData',
sendParam: {
gdIdxId : this.myBindingData.gdIdxId,
eqpmId : this.myBindingData.eqpmId,
},
});
this.setPageData({
calcProc : res[0].calcProc,
calcDesc : res[0].calcDesc,
pysclQtyId1 : res[0].pysclQtyId1Nm,
pysclQtyId2 : res[0].pysclQtyId2Nm,
pysclQtyId3 : res[0].pysclQtyId3Nm,
pysclQtyId4 : res[0].pysclQtyId4Nm,
ctgr1 : res[0].ctgr1,
ctgr2 : res[0].ctgr2,
warnStndVal : res[0].warnStndVal,
careStndVal : res[0].careStndVal,
alrmMsg : res[0].alrmMsg,
gdMeth : res[0].gdMeth
});
}
},
};
var gdIdxDetPop ={
gdIdxDetGrid:{
data:[],
column:[],
option:{}
}
}
// 전력량 요금(원/kWh)
</script>
<style lang="scss" scoped>
// @import '@/assets/scss/common/grid.scss';
.tui-grid-scrollbar-left-bottom {
display: none !important;
}
#gdIdx_InputText::v-deep .v-input__custom{
margin-left:-60px;
}
.v-input__custom{
margin-left:-60px;
}
</style>

View File

@ -0,0 +1,255 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="item.label" :cols="item.cols == 12 ? 2 : 4">
<label for="" class="search-box-label">
{{ item.label }}
<span v-if="item.essential">*</span>
</label>
</v-col>
<v-col :cols="item.label ? 7 : ''">
<v-row>
<v-col cols="3">
<v-text-field
readonly
v-model="selectValue1"
class="v-input__custom"
style="width:100%"
disabled
></v-text-field>
</v-col>
<v-col cols="3">
<v-text-field
readonly
v-model="selectValue2"
class="v-input__custom"
style="width:100%"
disabled
></v-text-field>
</v-col>
<v-col cols="1">
<v-btn
class="v-btn__round v-btn-bg__blue mr-2"
@click="dialog = !dialog"
>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-col>
<v-spacer></v-spacer>
</v-row>
</v-col>
<v-dialog v-model="dialog" scrollable width="640px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">검침개소위치</span>
</v-card-title>
<v-card-actions>
<v-col cols="2">
<label for="" class="search-box-label">
검색
</label>
</v-col>
<v-col cols="7">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="rowGridParent" style="height: 300px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData.selectReadPlcPopList"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
item: {
type: Object,
require: true,
},
},
components: {
Grid,
},
data() {
return {
myModalKey: 'selectReadPlcPopList',
gridName: 'rowGrid',
loadGrid: false,
changeData: {},
dialog: false,
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData() {
return this.searchParam['rowGridSelectData'];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue1() {
// 선택된 값
return this.myBindingData && this.myBindingData[this.item.valueNm.cede]
? this.myBindingData[this.item.valueNm.cede]
: null;
},
selectValue2() {
// 선택된 값
return this.myBindingData && this.myBindingData[this.item.valueNm.name]
? this.myBindingData[this.item.valueNm.name]
: null;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
await this.getData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadPlcPopList },
});
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.gridInit();
},
gridInit() {
const gridHeight = 490; // this.$refs.rowGridParent.offsetHeight - 30;
const myOptions = {};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: myColumns,
});
},
async getData() {
const res = await this.postApiReturn({
apiKey: 'selectReadPlcPopList',
resKey: 'readPlcData',
sendParam: {
params: { blocId: this.searchParam.blocCodeLists },
isMulti: false,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
value: res,
});
// setTimeout(
// this.$nextTick(() => {
// if (res.length > 0) {
// // console.log(this.$refs[this.gridName + this.parentPrgmId]);
// this.$refs[this.gridName + this.parentPrgmId].focus({
// rowKey: 0,
// setScroll: true
// });
// }
// });
// 2000
// );
this.loadGrid = true;
},
// sms 목록 그리드 클릭 이벤트
async getRowData(data) {
this.changeData = data;
},
setUpdate() {
this.dialog = false;
this.$emit('gridEditingFinish', {
columnName: this.item.valueNm.cede,
value: this.changeData[this.item.valueNm.cede],
});
this.$emit('gridEditingFinish', {
columnName: this.item.valueNm.name,
value: this.changeData[this.item.valueNm.name],
});
},
},
};
const selectReadPlcPopList = {
rowGrid: {
data: [],
column: [],
option: {},
},
// isMulti: false
};
const myColumns = [
{ header: '검침개소코드', name: 'readPlc', align: 'center' },
{ header: '검침개소명', name: 'readPlcNm' },
{ header: '검침개소종류명', name: 'plcKindNm', align: 'center' },
];
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,575 @@
<template>
<v-row class="search-box" align="center" no-gutters >
<v-dialog
ref="popModal"
v-model="dialog"
width="900"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col :cols="4">
<InputText
:parentPrgmId="parentPrgmId"
:label="'설비명'"
:valueNm="'eqpmNm'"
:readonly="true"
/>
</v-col>
<v-col :cols="2">
</v-col>
<v-col :cols="3">
</v-col>
<v-col :cols="3" class="text-right">
<v-btn icon tile :ripple="false" @click="closePop()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<!-- <div id="chartParent" ref="chartParent" style="height: 100px"> -->
<div :style="'height: calc(50vh)'">
<div class="d-flex align-center justify-space-between pa-4" style="height: 10%">
<v-card-title class="pa-0 custom-title-4">사용량 계획</v-card-title>
</div>
<!-- <div id="chartParent" ref="chartParent" :style="'height: 80%'"> -->
<div id="chartParent" ref="chartParent" style="height: 70%">
<component
class="w100 h100"
:is="loadChart ? 'Chart' : null"
:parentPrgmId="parentPrgmId"
:modalId="modalId"
:modalDataKey="modalDataKey"
:chartName="chartName"
:ref="chartName"
/>
</div>
<v-divider></v-divider>
<div style="height: 20%; margin: auto; width: 90%; display: flex; align-items: center;">
<v-row align="center" no-gutters class="pa-5 d-flex align-center justify-center;">
<v-col :cols="5">
<component
:is="'SelectBox'"
ref="SelectBox1"
:labelCols='3'
:textCols='6'
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'대상월'"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
<v-col :cols="5">
<component
:is="'SelectBox'"
ref="SelectBox2"
:labelCols='5'
:textCols='6'
:propsValue="selectValue02"
:itemList="selectValueList02"
:label="'전년대비절감율'"
@update:propsValue="selectValue02 = $event"
/>
</v-col>
<v-col :cols="2" class="text-right">
<v-btn color="primary" dark @click="search()">적용</v-btn>
</v-col>
</v-row>
<!-- <div style="height: 70%; width:10%; float: left; border: 1px solid blue; background-color: #A2A2A2">
설정
</div>
<div style="height: 70%; width:90%; margin-left:10%; border: 1px solid blue;">
<v-row align="center" no-gutters class="pa-5 d-flex align-center justify-center;">
<v-col :cols="4">
</v-col>
<v-col :cols="4">
</v-col>
<v-col :cols="2" class="text-right">
<v-btn color="primary" dark @click="setChart()">적용</v-btn>
</v-col>
</v-row>
</div> -->
<!-- <v-row align="center" no-gutters>
<v-row
:cols="12"
class="d-flex align-center justify-space-between pa-3"
>
<v-col :cols="4">
</v-col>
<v-col :cols="4">
</v-col>
<v-col :cols="2" class="text-right">
<v-btn color="primary" dark @click="setChart()">적용</v-btn>
</v-col>
</v-row> -->
</div>
</div>
<!-- <div id="gridParent" ref="gridParent" style="height: 500px">
<component
:ref="'gridName' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modifyEnrgUsePlanModalDataKey.modifyEnrgUsePlanModalData"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div> -->
<v-divider></v-divider>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn color="primary" dark @click="setUpdate()">확정</v-btn>
<v-btn color="primary" dark @click="closePop()">취소</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '~/components/common/input/InputText';
import Chart from '~/components/common/Chart';
import SelectBox from '@/components/common/select/SelectBox';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
}
},
components: {
Grid,
selectCodeList,
InputText,
Chart,
SelectBox
// Tree
},
data() {
return {
labelPrepend: true,
chartName: 'modifyEnrgUsePlanChart',
modalId: 'modifyEnrgUsePlanModal',
modalDataKey: 'modifyEnrgUsePlanModalDataKey',
// gridName: 'rowElecContGrid',
loadChart: false,
// selectedTargetMonth: 'all',
dialog: false,
selectValue01: null,
selectValueList01: [],
selectValue02: null,
selectValueList02: [],
nowModalChartData: [],
nowSeriesData: [],
activeRowData: {},
checkedRowDataList: [],
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
// searchParam(state) {
// return state.pageData[this.parentPrgmId];
// },
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
rowGrid2SelectData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId].rowGrid2SelectData;
} else {
return state.pageData[this.parentPrgmId][this.bindingData]
.rowGrid2SelectData;
}
},
popupDialogFg(state) {
return state.pageData[this.parentPrgmId].popupDialogFg;
}
}),
chkDialog(){
return this.dialog
},
chkPopupDialogFg() {
// 모달 열기/닫기 값
// return this.dialog
return this.popupDialogFg;
},
// get() {
// // if(this.searchParam.rowGridSelectData){
// // return this.searchParam.rowGridSelectData[this.item.valueNm];
// // }
// return this.myBindingData ? this.myBindingData[this.item.valueNm] : '';
// },
// set(value) {
// // return value;
// // return this.myBindingData({ [this.item.valueNm]: value });
// //return this.setPageData({ [this.item.valueNm]: value });
// return this.myBindingData({ [this.item.valueNm]: value });
// },
// },
},
watch: {
async chkDialog(val){
if (val) {
// await this.getData();
this.nowModalChartData = this.rowGrid2SelectData;
this.setChart();
} else {
this.closePop();
}
},
chkPopupDialogFg(val) {
this.dialog = val;
},
selectValue01(value){
this.setSelectValueList02();
// if(this.selectValue02 == '0'){
// this.search();
// }else{
// this.setSelectValueList02();
// }
},
selectValue02(value){
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modifyEnrgUsePlanModal: {modifyEnrgUsePlanModalDataKey},
});
},
created() {
this.setSelectValueList01();
this.setSelectValueList02();
this.init();
// if(this.searchParam.isMulti == true){
// this.setPageData({
// facInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }else{
// this.setPageData({
// facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setWidgetPageData: 'setWidgetPageData',
setModalChartOption: 'setModalChartOption',
setModalChartSeries: 'setModalChartSeries',
setModalChartTooltip: 'setModalChartTooltip'
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.setChart();
},
setSelectValueList01(){
this.selectValueList01 = [{'text' : '전체', 'value': 'all'}];
for(var i=1; i<=12; i++){
let qty = 'qty' + i.toString().padStart(2, '0');
this.selectValueList01.push(
{
'text' : i+'월',
'value': qty
}
);
}
this.selectValue01 = this.selectValueList01[0].value;
},
setSelectValueList02(){
for(var i=0; i<=100; i+=5){
this.selectValueList02.push(
{
'text' : i + '%',
'value': String(i)
}
);
}
this.selectValue02 = this.selectValueList02[0].value;
},
// 계약 정보 조회
setUpdate() {
this.dialog = false;
let nowSeriesData = this.nowSeriesData;
let nowPlanData = nowSeriesData.filter(item => {
return item.name == '계획';
})[0];
let nowPastData = nowSeriesData.filter(item => {
return item.name == '전년실적';
})[0];
let qtyList = [];
let qtyDict = {};
for(var i=0; i<nowPlanData.data.length; i++){
qtyList.push('qty' + (i+1).toString().padStart(2, '0'));
qtyDict['qty' + (i+1).toString().padStart(2, '0')] = i;
let dt = {
columnName: 'qty' + (i+1).toString().padStart(2, '0'),
value: nowPlanData['data'][i],
// targetRowNum: this.rowGrid2SelectData[1].rowKey,
rowKey: this.rowGrid2SelectData[1].rowKey,
rowEditingFg : true
}
this.$emit('gridEditingFinish', dt);
}
let rowGrid2SelectData = this.rowGrid2SelectData;
let newRowGrid2SelectData = rowGrid2SelectData.map(item => {
qtyList.map(obj => {
if(item.gubun == '2PLAN'){
item[obj] = nowPlanData['data'][qtyDict[obj]];
}else{
item[obj] = nowPastData['data'][qtyDict[obj]];
}
})
return item;
})
this.setPageData({rowGrid2SelectData: newRowGrid2SelectData});
},
closePop(){
this.dialog = false;
this.setPageData({popupDialogFg : false});
this.selectValue01 = this.selectValueList01[0].value;
this.selectValue02 = this.selectValueList02[0].value;
this.nowSeriesData = [];
this.nowModalChartData = [];
},
async setChart(){
this.loadChart = false;
let xAxisData = [];
let seriesData = [];
let data = [];
data = this.nowModalChartData;
let targetMonthList = [];
let _this = this;
let tooltipData = {
trigger:'axis',
confine: true,
axisPointer: {
type: "shadow"
},
// valueFormatter: (value) => '$' +parseFloat(value).toFixed()
formatter: function(params){
var toolTipTitle = params[0].name[0];
let res = "<div style='margin: 0px 0 0;line-height:1;'><div style='font-size:14px;color:#666;font-weight:400;line-height:1;'>"+toolTipTitle+"</div>";
for (var i = 0; i < params.length; i++) {
let tempVal = parseFloat(params[i].value);
if(Number.isFinite(tempVal)){
tempVal = tempVal.toFixed();
}else{
if(!isNaN(tempVal)){
tempVal = 0;
}
}
res += "<div style='margin: 10px 0 0;line-height:1;'><div style='margin: 0px 0 0;line-height:1;'>"
+"<span style='font-size:14px;color:#666;font-weight:400;margin-left:2px'>"+ params[i].marker
+ " "+params[i].seriesName+" "
+"</span>"
+"<span style='float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900'>"
+ _this.numberFormatter(tempVal)
+"</b></span>"
+"</div><div style='clear:both'></div></div>";
}
res += "</div>"
return res;
}
}
for(var i=1; i<=12; i++){
let qty = 'qty' + i.toString().padStart(2, '0');
targetMonthList.push(qty);
xAxisData.push(i);
}
// data = data.map(item => ({
// ...item,
// qty01: Math.floor(Math.random()*100),
// qty02: Math.floor(Math.random()*100),
// qty03: Math.floor(Math.random()*100),
// qty07: Math.floor(Math.random()*100)
// }));
seriesData = data.map(item => ({
name: item.gubun == '2PLAN' ? '계획' : '전년실적',
type: item.gubun == '2PLAN' ? 'line' : 'bar',
data: targetMonthList.map(obj => item[obj] || null)
// data: targetMonthList.map(obj => item[obj] || 0)
}));
this.nowSeriesData = seriesData;
// xAxisData = myKey.map(obj => obj.header);
let option = {
grid: {
top: "3%",
},
xAxis:{
type: 'category',
data: xAxisData
},
yAxis:{
type:'value',
// name: this.unitMapper[this.pageData.energyCd],
nameLocation : 'middle',
nameGap :45
},
legend: {
},
series: seriesData,
tooltip: tooltipData
};
// console.log('option', option);
await this.$nextTick(() => {
});
this.setModalChartOption(
{
prgmId: this.$route.query.prgmId,
chartKey: this.chartName,
modalId: this.modalId,
modalDataKey: this.modalDataKey,
value: option,
}
);
this.loadChart = true;
// this.setModalChartTooltip(
// {
// prgmId: this.$route.query.prgmId,
// chartKey: this.chartName,
// modalId: this.modalId,
// modalDataKey: this.modalDataKey,
// value: tooltipData
// }
// );
},
search() {
// this.setChart();
this.setSeriesData();
},
async setSeriesData(){
this.loadChart = false;
let targetMonth = this.selectValue01;
let targetRatio = (100-this.selectValue02)/100;
let nowSeriesData = this.nowSeriesData;
let seriesData = [];
let sData = [];
let sData2 = [];
sData = nowSeriesData.filter(item => {
return item.name == '전년실적';
})[0]['data'];
sData2 = nowSeriesData.filter(item => {
return item.name == '계획';
})[0]['data'];
// console.log('sData1', sData);
if(targetMonth.includes('qty')){
targetMonth = parseInt(targetMonth.slice(-2));
}
for(var i=0; i<sData.length; i++){
if(targetMonth == 'all' || i+1 == targetMonth){
sData2[i] = sData[i] * targetRatio;
}
}
// console.log('sData2', sData2);
seriesData = nowSeriesData.map(item => ({
...item,
data: item.name == '계획' ? sData2 : item.data
}));
// console.log('seriesData', seriesData);
await this.$nextTick(() => {
});
this.setModalChartSeries(
{
prgmId: this.$route.query.prgmId,
chartKey: this.chartName,
modalId: this.modalId,
modalDataKey: this.modalDataKey,
value: seriesData,
}
);
this.loadChart = true;
this.nowSeriesData = seriesData;
},
numberFormatter(value) {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
},
};
let modifyEnrgUsePlanModalDataKey =
{
modifyEnrgUsePlanChart: Utility.defaultChartOption(true)
};
// 전력량 요금(원/kWh)
</script>

View File

@ -0,0 +1,514 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row align="center" no-gutters>
<v-col :cols="12">
<component
:is="'SelectBox'"
ref="SelectBox1"
:labelCols="2"
:textCols="6"
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비그룹'"
@update:propsValue="selectValue01 = $event"
:readonly="
item.openMode == undefined
? openMode
: item.openMode == 'ALL'
? false
: true
"
/>
</v-col>
</v-row>
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<!-- <div :style="'height: calc(50vh)'"> -->
<div :style="'height: 429px;'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalDataEqpmBaseInfoPop.eqpmBaseInfoPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '설비 선택',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '설비 선택',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
openMode: {
type: Boolean,
require: false,
default: true, // 'ALL'도 있음
},
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
SelectBox,
},
data() {
return {
dialog: false,
loadGrid: false,
gridName: 'gridEqpmBaseInfoPop',
myModalKey: 'eqpmBaseInfoPop',
modalDataKey: 'modalDataEqpmBaseInfoPop',
searchWord: '',
selectedData: {},
textFieldData: '',
selectValue01: null,
selectValueList01: [],
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
bindingGridEqpmIdList: [],
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
nowGridEqpmIdList(state) {
return state.pageData[this.parentPrgmId]['nowGridEqpmIdList'];
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.setSelectValueList01();
await this.getGridData();
}
},
async selectValue01(value) {
await this.search();
},
nowGridEqpmIdList(value) {
this.bindingGridEqpmIdList = value;
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalDataEqpmBaseInfoPop: { eqpmBaseInfoPop },
});
},
async created() {
await this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
async init() {
await this.setSelectValueList01();
this.gridInit();
},
async setSelectValueList01() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmGrpCodeList',
resKey: 'eqpmGrpCodeLists',
sendParam: { eqpmKindId: this.searchParam.eqpmKindId },
// 부모 페이지에서 설비종류인 eqpmKindId 값을 꼭 가져와야한다.
});
if (res.length > 0) {
this.selectValueList01 = await res.map(obj => {
return {
text: obj.eqpmGrpNm,
value: obj.eqpmGrpId,
};
});
// 부모 페이지에서 설비그룹을 선택한 값이 있다면(eqpmGrpId) 그 값으로 바인딩 아닐 경우 조회한 데이터의 첫번째 값으로 선택
this.selectValue01 =
this.searchParam.eqpmGrpId != undefined
? this.searchParam.eqpmGrpId
: this.selectValueList01[0].value;
// this.selectValue01 = this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(390, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: [
{ header: '설비ID', name: 'eqpmId', align: 'left' },
{ header: '설비명', name: 'eqpmNm', align: 'left' },
],
});
},
async getGridData() {
this.loadGrid = false;
let res = await this.postApiReturn({
apiKey: 'selectEqpmBaseInfoPop',
resKey: 'epqmBaseInfoData',
sendParam: {
eqpmGrpId: this.selectValue01,
searchWord: this.searchWord,
// openMode : this.item.openMode == undefined ? this.openMode : this.item.openMode
},
});
// grid와 popup eqpmId 값 중복되는 것 제거하는 로직 - 시작
let newRes = [];
if (this.bindingGridEqpmIdList.length > 0) {
newRes = res.filter(item => {
return !this.bindingGridEqpmIdList.includes(item.eqpmId);
});
res = newRes;
}
// grid와 popup eqpmId 값 중복되는 것 제거하는 로직 - 끝
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
// 그리드와 popup eqpmId값 비교하는 로직 지금은 안씀
// let res = this.checkDuplicateEqpmId();
// if(res.includes(this.selectedData.eqpmId)){
// alert('가이드 지표에 이미 등록된 설비입니다.');
// return;
// };
this.dialog = false;
if (!this.item) {
this.textFieldData = this.selectedData.eqpmId;
} else {
//grid와 popup 겹치는 eqpmId값 수정하는 로직 - 시작
let tempBindingGridEqpmIdList = this.bindingGridEqpmIdList;
let idx = tempBindingGridEqpmIdList.indexOf(this.myBindingData.eqpmId);
if (idx < 0) {
tempBindingGridEqpmIdList.push(this.selectedData.eqpmId);
} else {
tempBindingGridEqpmIdList[idx] = this.selectedData.eqpmId;
}
this.setPageData({ nowGridEqpmIdList: tempBindingGridEqpmIdList });
//grid와 popup 겹치는 eqpmId값 수정하는 로직 - 끝
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.selectedData.eqpmId;
} else {
this.myBindingData.eqpmId = this.selectedData.eqpmId;
}
// this.myBindingData.calcDesc = this.selectedData.calcDesc;
const dt = {
columnName: this.item.valueNm,
value: this.selectedData.eqpmId,
};
this.$emit('gridEditingFinish', dt);
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.selectedData[this.item.valueNm2],
};
this.$emit('gridEditingFinish', dt);
}
if (this.item.bindNm !== undefined) {
const dt = {
columnName: this.item.bindNm,
value: this.selectedData.eqpmId,
};
this.$emit('gridEditingFinish', dt);
}
}
},
checkDuplicateEqpmId() {
let gridData = this.searchParam.rowGrid.data;
let res = gridData.map(item => {
return item.eqpmId;
});
return res;
},
dialogOpenCloseEvent(val) {
// if(this.item && this.item.disableContent){
// this.dialog = false;
// return;
// }
if (this.myBindingData.length <= 0) {
return alert('설비상세 리스트를 먼저 선택해주세요.');
}
this.dialog = !val;
},
},
};
var eqpmBaseInfoPop = {
gridEqpmBaseInfoPop: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,435 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
:readonly="item.readonly || false"
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData2.eqpmCalcPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '이벤트항목',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '이벤트항목',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
openMode:{
type:String,
require:false,
}
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'eqpmCalcPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
selectValue: {
get() {
// return this.searchParam[this.item.valueNm];
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { eqpmCalcPop },
});
},
async created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '계산코드', name: 'calcProc', width: 150},
{ header: '아규먼트갯수', name: 'argCnt', align:'center', width: 100},
// { header: '계산설명', name : 'calcDesc', width: 286},
{ header: '계산설명', name : 'calcDesc', align:'left'},
],
});
},
async getGridData() {
this.loadGrid = false;
let res = await this.postApiReturn({
apiKey: 'selectEqpmCalcPop',
resKey: 'eqpmCalcPopData',
sendParam: {
calcDescLike: this.searchWord,
openMode:this.item.openMode != undefined ? this.item.openMode : this.openMode
},
});
if(this.myBindingData['calcProc']!= '' || this.myBindingData['calcProc']!= null || this.myBindingData['calcProc']!=undefined){
let newRes = [];
newRes = res.filter(item => {
return item.calcProc != this.myBindingData['calcProc']
});
res = newRes;
}
// const res = [
// {
// 'calcProc' : 'AVG_CNT2',
// 'argCnt' : '2',
// 'calcDesc' : '두개 변수에 대한 평균'
// }
// ]
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
if (!this.item) {
this.textFieldData = this.selectedData.calcProc;
} else {
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.selectedData.argCnt;
} else {
this.myBindingData.argCnt = this.selectedData.argCnt;
}
const dt = {
columnName: this.item.valueNm,
value: this.selectedData.calcProc,
};
this.$emit('gridEditingFinish', dt);
this.setPageData({ [this.item.valueNm] : this.selectedData.calcProc});
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.selectedData[this.item.valueNm2],
};
this.$emit('gridEditingFinish', dt);
this.setPageData({[this.item.valueNm2] : this.selectedData.argCnt});
}
if (this.item.bindNm !== undefined) {
const dt = {
columnName: this.item.bindNm,
value: this.selectedData.argCnt,
};
this.$emit('gridEditingFinish', dt);
this.setPageData({ [this.item.bindNm] : this.selectedData.argCnt});
}
}
},
dialogOpenCloseEvent(val) {
// if(this.item && this.item.disableContent){
// this.dialog = false;
// return;
// }
this.dialog = !val;
},
},
};
var eqpmCalcPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,421 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small :color="required ? '#fb8200' : 'primary'" class="mr-1"
>mdi-record-circle</v-icon
>
{{ labelContent }}
</label>
</v-col>
<v-col :cols="textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="required || false"
:disabled="disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="5">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData2.eqpmPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '설비명',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '설비목록',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
required: {
require: false,
default: false,
},
disabled: {
require: false,
default: false,
},
bindOption: {
type: Object,
requrie: false,
default: null,
},
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'eqpmPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
parentModalState: 'close',
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
},
set(value) {
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
parentModalState(val) {
if (this.bindOption !== null) {
if (val === 'open') {
this.textFieldData = this.searchParam.rowGridSelectData.eqpmNm;
this.searchParam[
this.bindOption.eqpmId
] = this.searchParam.rowGridSelectData.eqpmId;
this.searchParam[
this.bindOption.eqpmNm
] = this.searchParam.rowGridSelectData.eqpmNm;
} else if (val === 'openWithInit') {
this.textFieldData = '';
this.searchParam[this.bindOption.eqpmId] = '';
this.searchParam[this.bindOption.eqpmNm] = '';
}
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { eqpmPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
this.textFieldData = '';
this.selectedData.eqpmId = '';
this.selectedData.eqpmNm = '';
if (this.bindOption === null) {
this.setPageData({
modalEqpmId: '',
modalEqpmNm: '',
});
} else {
this.setPageData({
[this.bindOption.eqpmId]: '',
[this.bindOption.eqpmNm]: '',
});
}
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
const _this = this;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '회사 ID', name: 'comId', hidden: true },
{ header: '설비 ID', name: 'eqpmId', width: 100, align: 'center' },
{ header: '설비명', name: 'eqpmNm', width: 150, align: 'center' },
{
header: '설비 유형',
name: 'eqpmKind',
width: 100,
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.searchParam.eqpmKindList.filter(
item => item.commCd == value,
);
if (newValue.length > 0) {
retVal = newValue[0].commCdNm;
}
return retVal;
},
},
{
header: '설비 그룹',
name: 'eqpmGrpId',
width: 100,
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.searchParam.eqpmGrpList.filter(
item => item.eqpmGrpId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].eqpmGrpNm;
}
return retVal;
},
},
{
header: '사업장',
name: 'blocId',
width: 88,
align: 'center',
formatter({ value }) {
let retVal = '';
const newValue = _this.searchParam.blocIdList.filter(
item => item.blocId == value,
);
if (newValue.length > 0) {
retVal = newValue[0].blocNm;
}
return retVal;
},
},
],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectEqpmBaseInfo',
resKey: 'eqpmBaseInfoData',
sendParam: {
eqpmNmLike: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
this.textFieldData = this.selectedData.eqpmNm;
if (this.bindOption === null) {
this.searchParam.modalEqpmId = this.selectedData.eqpmId;
this.searchParam.modalEqpmNm = this.selectedData.eqpmNm;
} else {
this.searchParam[this.bindOption.eqpmId] = this.selectedData.eqpmId;
this.searchParam[this.bindOption.eqpmNm] = this.selectedData.eqpmNm;
}
this.setPageData({ isFind: true });
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
var eqpmPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,563 @@
<template>
<v-row class="search-box" align="center" no-gutters >
<v-col :cols="labelCols">
<label for="" class="search-box-label">
<v-icon v-if="iconShow"
x-small
:color="required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ label }}
</label>
</v-col>
<v-col :cols="textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="required || false"
:disabled="disabled || false"
></v-text-field>
</v-col>
<v-dialog
ref="popModal"
v-model="dialog"
width="1400"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-divider></v-divider>
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0 custom-title-4"> 설비 선택</v-card-title>
</div>
<div class="pa-5">
<v-row align="center" no-gutters>
<v-col :cols="3">
<!-- 설비그룹 -->
<component
:is="'SelectBox'"
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비그룹'"
:disabled="eqpmGrpDisabled"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
<v-col :cols="6" style="padding:0px 10px;">
<!-- FAB -->
<component
:is="'SelectBoxMulti'"
:propsValue="selectValue02"
:itemList="selectValueList02"
:label="'FAB'"
:labelCols="2"
:multiple="true"
:disabled="fabDisabled"
@update:propsValue="selectValue02 = $event"
/>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
<v-row align="center" no-gutters style="margin-top: 14px;">
<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="3">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
</v-row>
</div>
<div class="px-5" style="height:429px;">
<div ref="modalGridParent" class="w100 h100">
<component
:ref="gridName"
:is="loadGrid? 'Grid' : null"
:dataPath="searchParam.eqpmSelectPopData.eqpmSelectPop"
:gridName="gridName"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
/>
</div>
</div>
<v-divider></v-divider>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '~/components/common/input/InputText';
import dateUtility from '~/plugins/dateUtility';
import SelectBox from '@/components/common/select/SelectBox';
import SelectBoxMulti from '@/components/common/select/SelectBoxMulti';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
},
disabled:{
type:Boolean,
require:false,
default:false
},
required:{
type:Boolean,
require:false,
default:false
},
fabDisabled:{
type:Boolean,
require:false,
default:false
},
eqpmGrpDisabled:{
type:Boolean,
require:false,
default:false
},
iconShow:{
type:Boolean,
require:false,
default:true
},
isMulti:{
type:Boolean,
require:false,
default:false
}
},
components: {
Grid,
selectCodeList,
dateUtility,
InputText,
SelectBox,
SelectBoxMulti
// Tree
},
data() {
return {
labelPrepend: true,
modalDataKey:'eqpmSelectPopData',
myModalKey: 'eqpmSelectPop',
gridName: 'eqpmSelectGrid',
loadGrid: false,
setGrid:false,
popCheck:false,
dialog: false,
activeRowData: {},
checkedRowDataList: [],
selectValue01:null,
selectValue02:[],
selectValueList01:[],
selectValueList02:[],
searchWord:'',
activeRowData:{},
textFieldData:'',
selectRow:{}
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
var data = state.pageData[this.parentPrgmId];
if(data.fabId == ''){
data.fabId = null
}else if(typeof(data.fabId)=='string'){
data.fabId = [data.fabId]
}
return {
fabId : data.fabId,
eqpmGrpId : data.eqpmGrpId,
eqpmId:data.eqpmId,
eqpmNm:data.eqpmNm,
eqpmIdList:data.eqpmIdList,
eqpmKindId:data.eqpmKindId,
}
},
}),
selectValue: {
get() {
// return this.searchParam[this.item.valueNm];
return this.myBindingData
? this.myBindingData[this.valueNm]
: this.textFieldData;
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
chkDialog(){
if(this.isMulti){
this.$store.state.pageData[this.parentPrgmId][this.modalDataKey][this.myModalKey][this.gridName].option.rowHeaders = [{type : 'checkbox'}];
}else{
this.$store.state.pageData[this.parentPrgmId][this.modalDataKey][this.myModalKey][this.gridName].option.rowHeaders = [];
}
return this.dialog
},
},
watch: {
async chkDialog(val){
// console.log("val : ", val);
if(val){
this.selectValue01 = this.myBindingData.eqpmGrpId;
this.selectValue02 = this.myBindingData.fabId;
await this.search();
// if(this.isMulti){
// }else{
// // 단일 focus용
// if(this.$refs[this.gridName]){
// this.selectRow = this.$refs[this.gridName].getData().filter(item=>{
// return item.eqpmId == this.myBindingData.eqpmId
// });
// this.$refs[this.gridName].focus({
// rowKey : this.selectRow[0].rowKey,
// setScroll: true
// })
// }
// }
}else{
this.dialog = false;
}
// this.selectValue01 = this.myBindingData.eqpmGrpId;
// this.selectValue02 = this.myBindingData.fabId;
// await this.search();
// this.getChecked();
// }
},
},
beforeCreate() {
this.$store.commit('setPageData', {
eqpmSelectPopData: { eqpmSelectPop },
});
},
async created() {
await this.getFab();
await this.getEqpmGrp();
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
dialogOpenCloseEvent(val){
// this.checkPop = !val;
this.dialog=!val;
},
search() {
this.getRowGridData();
},
async getFab() {
let res = await this.postApiReturn({
apiKey: 'selectFabCodeList',
resKey: 'fabCodeLists',
sendParam: {},
});
if (res.length > 0) {
this.selectValueList02 = await res.map(item => {
return {
text: item.eccNm,
value: item.eccId,
};
});
this.selectValueList02.unshift({
text:"전체",
value:null
});
// if(this.pageData.eccId != null && this.pageData.eccId != ''){
// this.selectValue02 = this.pageData.eccId;
// }else if(this.pageData.eccId == null || this.pageData.eccId == ''){
this.selectValue02.push(this.selectValueList02[0].value);
// }
} else {
this.selectValueList02 = [];
this.selectValue02 = [];
}
},
async getEqpmGrp() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmGrpCodeList',
resKey: 'eqpmGrpCodeLists',
sendParam: { },
});
if (res.length > 0) {
this.selectValueList01 = await res.map(item => {
return {
text: item.eqpmGrpNm,
value: item.eqpmGrpId,
};
});
this.selectValueList01.unshift({
text:"전체",
value:null
});
// if(this.pageData.eqpmGrpId != null && this.pageData.eqpmGrpId != ''){
// this.selectValue02 = this.pageData.eqpmGrpId;
// }else if(this.pageData.eqpmGrpId == null || this.pageData.eqpmGrpId == ''){
this.selectValue01 = this.selectValueList01[0].value;
// }
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
},
gridInit(){
// console.log("modalGridParent : ",this.$refs)
// const gridWidth = this.$refs.modalGridParent.offsetWidth/4;
let myOptions = {
columnOptions: {
resizable: true,
},
// rowHeaders:[{ type: 'checkbox' }],
// rowHeight:'auto'
};
if(this.isMulti){
myOptions['rowHeaders'] = [{type : 'checkbox'}];
myOptions['rowHeight'] = 'auto';
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
const myColumns= [
{
header : 'FAB',
name : 'fabId',
align:'center',
hidden:true
},
{
header : 'FAB',
name : 'fabNm',
align:'center'
},
{
header : '설비ID',
name : 'eqpmId',
align:'center',
// hidden:true
},
{
header : '설비명',
name : 'eqpmNm',
align:'center'
},
{
header : 'eccId',
name : 'eccId',
align:'center',
hidden:true
},
{
header : 'eccNm',
name : 'eccNm',
align:'center',
hidden:true
},
]
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
// this.getRowGridData();
},
async getRowGridData(){
this.loadGrid =false;
var res = await this.postApiReturn({
apiKey: 'selectEqpmPop',
resKey: 'eqpmPopData',
sendParam: {
fabId:this.selectValue02,
eqpmGrpId:this.selectValue01,
searchWord:this.searchWord,
eqpmKindId:this.myBindingData.eqpmKindId,
},
});
// const dayjs = require('dayjs');
// var newRes = res.map(item=>
// item = {
// ...item,
// totDttmDay : Utility.setFormatDate(item.totDttm, 'YYYY-MM-DD'),
// totDttmTime : Utility.setFormatDate(item.totDttm, 'HH') + "~" + dayjs(item.totDttm).add(1,'h').format('HH')
// }
// );
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res
});
this.loadGrid=true;
this.$nextTick(()=>{
if(this.isMulti){
this.getChecked();
}
});
},
setUpdate() {
if(this.isMulti){
var data = this.$refs[this.gridName].getCheckedRowsEvt();
this.dialog = false;
this.setPageData({
checkedRows: data,
eqpmId : data.map(item=>{
return item.eqpmId;
}),
eqpmNm : data.map(item=>{
return item.eqpmNm;
}),
eqpmIdList:data,
isFind2:true
});
}else{
this.dialog = false;
this.setPageData({eqpmInfo : this.activeRowData, eqpmNm : this.activeRowData.eqpmNm})
}
},
getRowData(data){
if(this.isMulti){
if(data._attributes.checked){
this.$refs[this.gridName].uncheckEvt(data, this.$refs[this.gridName]);
}else{
this.$refs[this.gridName].checkEvt(data, this.$refs[this.gridName]);
}
}else{
this.activeRowData = data;
}
},
getChecked(){
if(this.myBindingData.eqpmIdList.length>0){
this.myBindingData.eqpmIdList.map(item=>{
this.$refs[this.gridName].checkEvt(item, this.$refs[this.gridName]);
});
}
}
},
};
var eqpmSelectPop ={
eqpmSelectGrid:{
data:[],
column:[],
option:{}
}
}
</script>

View File

@ -0,0 +1,358 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-btn @click="dialog = !dialog" class="v-input__custom">
단가보기
</v-btn>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="850"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
</v-card-title>
<!-- <div :style="'height: calc(50vh)'"> -->
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="gridParent" style="height: 150px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData.ErcChrgInfoMngPop"
:parentPrgmId="parentPrgmId"
/>
</div>
<!-- </div> -->
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
// default: "공정/설비"
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
popTitle: {
type: String,
require: false,
default: '',
},
},
components: {
Grid,
Utility,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'ErcChrgInfoMngPop',
gridName: 'modalGrid',
loadGrid: false,
dialog: false,
modalDataKey: 'modalData',
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
selectValue() {},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { ErcChrgInfoMngPop },
});
},
created() {
this.init();
},
mounted() {
// console.log("###",this.$refs.gridParent)
// console.log("###",this.$refs.popModal)
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 그리드 세팅
gridInit() {
// const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const myOptions = {
columOptions: {
resizeable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(150, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
// 그리드 데이터 설정
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectElecPowChrgInfo',
resKey: 'elecPowChrgInfoData',
sendParam: {
elecContId: this.searchParam.elecContId,
},
});
function setRowSpanAttribute(
res,
targetAttributeName,
targetAttributeList,
) {
if (!(res.length && res.length >= 1)) {
return;
}
if (targetAttributeList == undefined) {
var currentCnt = 1;
var currentIdx = 0;
var currentValue = res[0][targetAttributeName];
for (var i = 1; i < res.length; 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 - 1
) {
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; 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 - 1
) {
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;
}
}
setRowSpanAttribute(res, 'elecContKindNm');
setRowSpanAttribute(res, 'voltKindNm');
setRowSpanAttribute(res, 'optKindNm');
setRowSpanAttribute(res, 'baseChrg');
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
// row 클릭이벤트
getRowData(data) {},
search() {
this.getGridData();
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
const ErcChrgInfoMngPop = {
modalGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
const myColumns = [
{ header: '전력계약 ID', name: 'eleclContId', hidden: true },
{ header: '전력계약 명', name: 'eleclContNm', hidden: true },
{ header: '전력계약구분CD', name: 'elecContKind', hidden: true },
{ header: '전력계약구분', name: 'elecContKindNm', align: 'center' },
{ header: '전압구분CD', name: 'voltKind', hidden: true },
{ header: '전압구분', name: 'voltKindNm', align: 'center' },
{ header: '옵션CD', name: 'optKind', hidden: true },
{ header: '옵션', name: 'optKindNm', align: 'center' },
{
header: '기본요금(원/kW)',
name: 'baseChrg',
align: 'right',
formatter({ value }) {
return Utility.setFormatInt(value);
},
},
{ header: '시간대CD', name: 'peakKind', hidden: true },
{ header: '시간대', name: 'peakKindNm', align: 'center' },
{
header: '여름철(6~8월)',
name: 'unitPrcSum',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
{
header: '봄·가을철(3~5,9~10월)',
name: 'unitPrcSprfal',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
{
header: '겨울철(11~2월)',
name: 'unitPrcWin',
align: 'right',
formatter({ value }) {
return Utility.setFormatIntDecimal(value, 1);
},
},
];
</script>

View File

@ -0,0 +1,204 @@
<template>
<v-banner>
<div
class="d-flex align-center justify-space-between"
style="cursor:pointer"
@click="dialog = !dialog"
>
<v-card-subtitle class="pa-0">통신이상</v-card-subtitle>
<v-avatar
size="36"
:color="isDarkMode ? '#fb8200' : '#fdab3d'"
min-width="72"
class="font-weight-bold text-color--white-0"
>{{ pointEtc }}</v-avatar
>
</div>
<v-dialog v-model="dialog" scrollable width="600px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">통신이상 개소 조회</span>
</v-card-title>
<v-card-actions>
<v-col>
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="rowGridParent" style="height: 300px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.etcData.selectEtcReadPlc"
:parentPrgmId="parentPrgmId"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark>확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-banner>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid2';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
pointEtc: {
type: Number,
require: true,
},
},
components: {
Grid,
},
data() {
return {
modalDataKey: 'etcData',
myModalKey: 'selectEtcReadPlc',
gridName: 'etcGrid',
loadGrid: false,
searchWord: '',
dialog: false,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
isDarkMode: 'isDarkMode',
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
await this.getData();
} else {
// 닫힐 때
}
},
},
beforeCreate() {
if (this.$store.state.activeMenuInfo.prgmId == '0') {
this.$store.state.activeMenuInfo.prgmId = this.$route.query.prgmId;
}
this.$store.commit('setPageData', {
etcData: { selectEtcReadPlc },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
// setTree: "modules/list/setTree"
}),
init() {
this.gridInit();
},
gridInit() {
const gridHeight = 290; // this.$refs.rowGridParent.offsetHeight - 30;
const myOptions = {
//rowHeaders: ["checkbox"]
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
async getData() {
this.loadGrid = false;
let sendParams = {
readPlcNm: this.searchWord,
};
const res = await this.postApiReturn({
apiKey: 'selectEtcReadPlc',
resKey: 'etcData',
sendParam: sendParams,
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
// 검색
typeEnterKey() {
this.getData();
},
},
};
const selectEtcReadPlc = {
etcGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
const myColumns = [
{ header: '사업장', name: 'blocNm', width: 100, align: 'center' },
{ header: '에너지원', name: 'readObjNm', width: 100, align: 'center' },
/*{ header: "검침개소코드", name: "readPlcId", width:100 , align:"center"},*/
{ header: '검침개소명', name: 'readPlcNm', width: 240 },
{ header: '값', name: 'useVal', width: 100, align: 'right' },
];
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,436 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="1000px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<!-- <div :style="'height: calc(65vh)'"> -->
<div :style="'height: 600px'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData2.evtObjPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate('init')">초기화</v-btn>
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '이벤트항목',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '이벤트항목',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
}
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'evtObjPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
formFlag: this.item.formFg != undefined ? this.item.formFg : true,
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
selectValue: {
get() {
if(this.formFlag){
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
}else{
// grid와 바인딩 안했을 때
return this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { evtObjPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(570, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: 'TAG ID', name: 'tagId' },
{ header: 'TAG 명', name: 'tagNm' },
],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectTagBaseInfo',
resKey: 'tagBaseInfoData',
sendParam: {
tagNmLike: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
// 초기화
if(v == 'init'){
this.selectedData.tagId = null;
this.selectedData.tagNm = null;
}
this.dialog = false;
if (!this.item) {
this.textFieldData = this.selectedData.tagId;
} else {
// let formFg = this.item.formFg != undefined ? this.item.formFg : this.formFg;
if(this.formFlag){
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.selectedData.tagNm;
} else {
this.myBindingData.tagNm = this.selectedData.tagNm;
}
// this.myBindingData.tagNm = this.selectedData.tagNm;
const dt = {
columnName: this.item.valueNm,
value: this.selectedData.tagId,
};
this.$emit('gridEditingFinish', dt);
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.selectedData[this.item.valueNm2],
};
this.$emit('gridEditingFinish', dt);
}
if (this.item.bindNm !== undefined) {
const dt = {
columnName: this.item.bindNm,
value: this.selectedData.tagNm,
};
this.$emit('gridEditingFinish', dt);
}
}else{
// grid와 binding 안되어있는 경우
this.textFieldData = this.selectedData.tagNm;
this.setPageData({
tagId: this.selectedData.tagId,
// [this.item.tagNm]: this.selectedData.tagNm
});
}
}
},
dialogOpenCloseEvent(val) {
// if(this.item && this.item.disableContent){
// this.dialog = false;
// return;
// }
this.dialog = !val;
},
},
};
var evtObjPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,357 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<!-- <v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon> -->
<!-- {{ label }} -->
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<v-btn
readonly
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog2 = !dialog2"
outlined
:hide-details="true"
>{{ label }}</v-btn
>
</v-col>
<v-dialog v-model="dialog2" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">사용자 조회</span>
</v-card-title>
<v-card-actions>
<v-row>
<v-col :cols="7">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-col :cols="5" class="text-right">
<v-btn :ripple="false" @click="getData()">조회</v-btn>
<BtnExcelDownload
:ref="'excelButton01'"
:parentPrgmId="parentPrgmId"
:gridName="gridName"
:parentModalDataName="'modalData2'"
:myModalKey="myModalKey"
/>
<v-btn :ripple="false" @click="saveGridData()">저장</v-btn>
</v-col>
</v-row>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="rowGridParent" style="height: 300px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog2 ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData2.selectFixedValueModiPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<!-- <v-btn color="primary" dark @click="setUpdate()">확인</v-btn> -->
<v-btn color="primary" dark @click="dialog2 = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import BtnExcelDownload from '~/components/common/button/BtnExcelDownload';
import Buttons from '~/components/common/button/Buttons';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
},
components: {
Grid,
BtnExcelDownload,
Buttons,
},
data() {
return {
label: '고정값 수정',
modalDataKey: 'modalData2',
myModalKey: 'selectFixedValueModiPop',
gridName: 'rowGrid',
loadGrid: false,
searchWord: '',
dialog2: false,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog2;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
console.log('dsfafds');
await this.getData();
// console.log("chkDialog: ", val);
// if(this.searchParam.selecUserList.length > 0){
// for(var i=0; i<this.searchParam.selecUserList.length; i++) {
// this.$refs[this.gridName + this.parentPrgmId].checkEvt(this.searchParam.selecUserList[i], this.$refs[this.gridName + this.parentPrgmId]);
// }
// }
// this.$refs[this.gridName + this.parentPrgmId].setCheck(
// this.searchParam.selecUserListRowKeys
// );
} else {
// 닫힐 때
this.setPageData({
myUserList: null,
});
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { selectFixedValueModiPop },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
postUpdateApi: 'modules/list/postUpdateApi',
// setTree: "modules/list/setTree"
}),
init() {
this.gridInit();
},
async saveGridData() {
this.loadGrid = false;
let dataArr = this.$refs[this.gridName + this.parentPrgmId].save();
// this.setPageData({ isFind: true });
for (var i = 0; i < dataArr.length; i++) {
if (
dataArr[i].addInfoDataKind == 'NUM' &&
dataArr[i].addInfoVal == ''
) {
dataArr[i].addInfoVal = null;
}
}
console.log('dataArr', dataArr);
if (dataArr.length > 0) {
const sendParam = {
datas: {
fixedValModiPopDatas: dataArr.map(item => ({
...item,
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'savefixedValModiPopDatas',
sendParam: sendParam,
});
await this.getData();
this.loadGrid = true;
this.setPageData({ isFind: true });
} else {
this.loadGrid = true;
alert('저장할 내용이 없습니다.');
}
},
gridInit() {
const gridHeight = 490; // this.$refs.rowGridParent.offsetHeight - 30;
const myOptions = {
// rowHeaders: ["checkbox"]
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
async getData() {
this.loadGrid = false;
let sendParams = {
search: this.searchWord,
// userNo: '',
// userLoginId: '',
// deptId: ''
};
const res = await this.postApiReturn({
apiKey: 'selectFixedValueModiPop',
resKey: 'tagFixedValData',
sendParam: sendParams,
});
const newRes = res.map(item => {
const newObj = {
...item,
rowStat: null,
useFg: item.useFg === '1' ? true : false, // 화면 개발 편의를 위해 boolean 타입으로 교체, 저장시 "1", "0" 으로 바꿔 보내야 함
};
return newObj;
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: newRes,
});
this.loadGrid = true;
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (data._attributes.checked) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
} else {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
}
},
// setUpdate() {
// // console.log("이게뭐야", this.$refs[this.gridName + this.parentPrgmId])
// console.log("adsfasdfasdfasf", this.$refs[ this.gridName + this.parentPrgmId].getData());
// // let gridInstance = this.$refs[ this.gridName + this.parentPrgmId];
// // const saveTargetRows = gridInstance.invoke("getModifiedRows");
// // console.log('saveTargetRows', saveTargetRows);
// let dataArr = this.$refs[ this.gridName + this.parentPrgmId].save();
// this.dialog2 = false;
// this.setPageData({
// selecUserList: this.$refs[
// this.gridName + this.parentPrgmId
// ].getCheckedRowsEvt()
// });
// // this.setPageData({
// // selecUserListRowKeys: this.$refs[
// // this.gridName + this.parentPrgmId
// // ].getCheckedRowKeys()
// // });
// },
// 검색
typeEnterKey() {
this.getData();
},
},
};
const selectFixedValueModiPop = {
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
defaultRow: {
eccId: '',
readObjId: '',
ucId: '',
tagId: '',
tagNm: '',
dfltVal: '',
userVal: '',
rowStat: null,
},
buttonAuth: {
add: false,
remove: false,
save: true,
excel: true,
},
},
eqpmYn: 1,
xlsFileInfo: {
// 출력하려는 grid 와 같은 이름으로 세팅
rowGrid: {
fileName: null, // 갑이 없으면 해당 페이지 메뉴명
sheetName: null, // 갑이 없으면 'Sheet1'
},
},
};
const myColumns = [
{ header: '공정ID', name: 'eccId', align: 'left', hidden: true },
{ header: '에너지ID', name: 'readObjId', align: 'left', hidden: true },
{ header: '케이스명', name: 'ucId', align: 'left', hidden: true },
{ header: '태그ID', name: 'tagId', align: 'left', hidden: true },
{ header: '태그명(R)', name: 'tagNm', align: 'left' },
{ header: '디폴트값(R)', name: 'dfltVal', align: 'right' },
{
header: '사용자 세팅값(E)',
name: 'userVal',
align: 'right',
editor: 'text',
},
];
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,411 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="700px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="5">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<!-- <div :style="'height: calc(65vh)'"> -->
<div :style="'height: 429px;'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 w100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData3.FtnPlcFormPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '공정',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '공정',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'FtnPlcFormPop',
modalDataKey: 'modalData3',
searchWord: '',
selectedData: {},
textFieldData: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData3: { FtnPlcFormPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
let myOptions = {
treeColumnOptions: {
name: 'eccNm',
useIcon: true,
},
scrollX: false,
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(390, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [{ header: '위치정보', name: 'eccNm' }],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectEccBaseInfo',
resKey: 'eccBaseInfoData',
sendParam: {
blocId: this.myBindingData.blocId,
eqpmYn: '0',
search: this.searchWord,
},
});
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'ECC_ID',
value: res.map(item => ({
...item,
eccNm: item.eccNm,
})),
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
const dt = {
columnName: this.item.valueNm,
value: this.selectedData['eccId'],
};
const dt2 = {
columnName: this.item.valueNm2,
value: this.selectedData['eccNm'],
};
if (!this.item.eccFgYn) {
this.myBindingData.upEccNm = this.selectedData.eccNm;
this.myBindingData.upEccId = this.selectedData.eccId;
this.$emit('gridEditingFinish', dt);
this.$emit('gridEditingFinish', dt2);
} else {
if (this.selectedData.eccFg == '1') {
this.myBindingData.upEccNm = this.selectedData.eccNm;
this.myBindingData.upEccId = this.selectedData.eccId;
this.$emit('gridEditingFinish', dt);
this.$emit('gridEditingFinish', dt2);
} else {
alert('공정(ECC)을 선택해주세요.');
return false;
}
}
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
var FtnPlcFormPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,413 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="searchParam.clickOnOff ? '' : dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="5">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData3.FtnPlcMultiFormPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '공정',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '공정',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'FtnPlcMultiFormPop',
modalDataKey: 'modalData3',
searchWord: '',
selectedData: {},
textFieldData: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
clickOnOff(state) {
return state.pageData[this.parentPrgmId]['clickOnOff'];
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData3: { FtnPlcMultiFormPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
let myOptions = {
treeColumnOptions: {
name: 'eccNm',
useIcon: true,
},
scrollX: false,
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [{ header: '위치정보', name: 'eccNm' }],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcListTree',
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocId: this.searchParam.blocIdList[this.searchParam.blocId].blocId,
eqpmYn: '0',
search: this.searchWord,
roiId: this.searchParam.energyList[this.searchParam.energyCd].cd,
},
});
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'ECC_ID',
value: res.map(item => ({
...item,
eccNm: item.eccNm,
})),
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
const dt = {
columnName: this.item.valueNm,
value: this.selectedData['eccId'],
};
const dt2 = {
columnName: this.item.valueNm2,
value: this.selectedData['eccNm'],
};
if (!this.item.eccFgYn) {
this.myBindingData.upEccNm = this.selectedData.eccNm;
this.myBindingData.upEccId = this.selectedData.eccId;
this.$emit('gridEditingFinish', dt);
this.$emit('gridEditingFinish', dt2);
} else {
if (this.selectedData.eccFg == '1') {
this.myBindingData.upEccNm = this.selectedData.eccNm;
this.myBindingData.upEccId = this.selectedData.eccId;
this.$emit('gridEditingFinish', dt);
this.$emit('gridEditingFinish', dt2);
} else {
alert('공정(ECC)을 선택해주세요.');
return false;
}
}
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
var FtnPlcMultiFormPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,316 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
:hide-details="true"
class="v-input__custom"
@click="dialog = !dialog"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog v-model="dialog" scrollable width="540px">
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">{{
this.eqpmYn ? '공정/설비' : '공정'
}}</span>
</v-card-title>
<v-card-actions>
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
위치정보 선택
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<v-btn color="primary" dark>초기화</v-btn>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectFtnPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
default: '공정/설비',
},
labelCols: {
type: Number,
require: false,
default: 2,
},
textCols: {
type: Number,
require: false,
default: 9,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
},
components: {
Grid,
// Tree
},
data() {
return {
// label: "공정/설비",
labelPrepend: true,
myModalKey: 'selectFtnPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
treeExpandAll: true,
activeRowData: {},
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
return this.searchParam.facInfo.path;
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
// selectValue: {
// get() {
// return this.searchParam[this.parentPrgmId].facInfo;
// },
// set(value) {
// return this.setPageData({ facInfo: value });
// }
// }
},
watch: {
chkDialog(val) {
if (val) this.getTreeData();
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectFtnPlcListTree },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
// this.getTreeData();
// this.lineCOption = chartOption;
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
treeColumnOptions: {
name: 'name',
},
// bodyHeight: treeGridHeight,
// minBodyHeight: treeGridHeight,
// header: {
// height: 28
// },
// rowHeight: 29,
// minRowHeight: 29
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
value: [{ header: '위치정보', name: 'name' }],
});
},
// 공정/설비 조회
async getTreeData() {
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcListTree',
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocId: this.searchParam.blocMstrList[this.searchParam.blocId].blocId, //"BL0001",
eqpmYn: this.eqpmYn,
mttCd: this.searchParam.energyList[this.searchParam.energyCd].cd,
// eqpmYn: this.searchParam.modalData.selectFtnPlcListTree.eqpmYn // "MTT00001" // 전력 코드 고정
},
});
// console.log('res[getTreeData] :', res);
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'PLC_CD',
value: res.map(item => ({
...item,
plcCdNm: item.plcNm,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
this.loadGrid = true;
},
// 공정/설비 트리 row 클릭이벤트
async getRowData(data) {
// console.log("getRowData = ", data);
this.activeRowData = data;
},
setUpdate() {
if (this.activeRowData) {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
},
};
const selectFtnPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
eqpmYn: 1,
};
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,503 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card :height="height">
<v-card-title class="d-flex align-center justify-space-between">
<span class="custom-title-4">{{
this.eqpmYn ? '공정/설비' : '공정'
}}</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col v-if="label" 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="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<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>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn :ripple="false">초기화</v-btn> -->
<v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()"
>초기화</v-btn
>
<v-btn
v-if="!searchParam.isMulti"
:ripple="false"
@click="search()"
>검색</v-btn
>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="{ height: 'calc(100% - 213px)' }">
<div ref="treeGridParent" class="h100 py-3">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectFtnPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate()">확인</v-btn>
<v-btn :ripple="false" @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
default: '공정/설비',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectFtnPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
// 모달 열기/닫기 값
if (this.searchParam.isMulti == false) {
// delete this.$store.state.pageData[this.parentPrgmId]['modalData'][this.myModalKey].treeGrid.option.rowHeaders[0] = {};
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [];
} else {
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [{ type: 'check' }];
}
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.eccNm);
}
}
} else {
return facData.path === undefined ? facData.eccNm : facData.path;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectFtnPlcListTree },
});
},
created() {
this.init();
if (this.searchParam.isMulti == true) {
this.setPageData({
facInfoList:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
} else {
this.setPageData({
facInfo:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
}
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [{ header: '위치정보', name: 'eccNm' }],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcListTree',
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
roiId: this.searchParam.energyList[this.searchParam.energyCd].cd, // "MTT00001" // 전력 코드 고정
eqpmYn: this.eqpmYn,
search: this.searchWord,
},
});
let myOptionsTree = {
treeColumnOptions: {
name: 'eccNm',
useIcon: true,
},
scrollX: false,
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(
this.$refs.treeGridParent.offsetHeight - 60,
),
myOptionsTree,
),
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'ECC_ID',
value: res.map(item => ({
...item,
eccNm: item.eccNm,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT || [],
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.facInfoList.length > 0
? this.searchParam.facInfoList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ facInfoList: this.checkedRowDataList });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfoList),
);
} else {
alert('비교대상이 20개를 초과하였습니다.');
}
} else {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfo),
);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
reset() {
for (
var i = 0;
i < this.$refs['treeGrid' + this.parentPrgmId].getData().length;
i++
) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
this.$refs['treeGrid' + this.parentPrgmId].getData()[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
},
search() {
this.getTreeData();
},
typeEnterKey() {
this.getTreeData();
},
},
};
const selectFtnPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,507 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card :height="height">
<v-card-title class="d-flex align-center justify-space-between">
<span class="custom-title-4">{{
this.eqpmYn ? '공정/설비' : '공정'
}}</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col v-if="label" 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="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<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>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn :ripple="false">초기화</v-btn> -->
<!-- <v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()">초기화</v-btn> -->
<v-btn :ripple="false" @click="search()">검색</v-btn>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="{ height: 'calc(100% - 213px)' }">
<div ref="treeGridParent" class="h100 py-3">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectFtnPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate()">확인</v-btn>
<v-btn :ripple="false" @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
default: '공정/설비',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
apiUrl: {
type: String,
require: false,
default: 'selectFtnPlcListTree',
},
treeFg: {
type: Boolean,
require: false,
default: true,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectFtnPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
// 모달 열기/닫기 값
if (this.searchParam.isMulti == false) {
// delete this.$store.state.pageData[this.parentPrgmId]['modalData'][this.myModalKey].treeGrid.option.rowHeaders[0] = {};
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [];
} else {
this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders = [{ type: 'check' }];
}
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.eccNm);
}
}
} else {
return facData.path === undefined ? facData.eccNm : facData.path;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectFtnPlcListTree },
});
},
created() {
this.init();
// if(this.searchParam.isMulti == true){
// this.setPageData({
// // facInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }else{
// this.setPageData({
// // facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [{ header: '위치정보', name: 'eccNm' }],
});
},
// 공정/설비 조회
async getTreeData() {
let roiIdVal;
if (this.searchParam.energyCd < 0) {
roiIdVal = null;
} else {
console.log(
'this.searchParam.energyList[this.searchParam.energyCd]',
this.searchParam.energyList[this.searchParam.energyCd],
);
roiIdVal = this.searchParam.energyList[this.searchParam.energyCd + 1]
.cd;
}
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: this.apiUrl,
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
roiId: roiIdVal,
eqpmYn: this.eqpmYn,
search: this.searchWord,
},
});
let myOptionsTree = {
treeColumnOptions: {
name: 'eccNm',
useIcon: true,
},
scrollX: false,
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(
this.$refs.treeGridParent.offsetHeight - 60,
),
myOptionsTree,
),
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'ECC_ID',
value: res.map(item => ({
...item,
eccNm: item.eccNm,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: this.treeFg ? setTreeData.ROOT || [] : res,
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.facInfoList.length > 0
? this.searchParam.facInfoList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ facInfoList: this.checkedRowDataList });
// localStorage.setItem(this.parentPrgmId + "CheckedRow", JSON.stringify(this.searchParam.facInfoList));
} else {
alert('비교대상이 20개를 초과하였습니다.');
}
} else {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
// localStorage.setItem(this.parentPrgmId + "CheckedRow", JSON.stringify(this.searchParam.facInfo));
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
reset() {
for (
var i = 0;
i < this.$refs['treeGrid' + this.parentPrgmId].getData().length;
i++
) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
this.$refs['treeGrid' + this.parentPrgmId].getData()[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
},
search() {
this.getTreeData();
},
typeEnterKey() {
this.getTreeData();
},
},
};
const selectFtnPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,505 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="item.disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row align="center" no-gutters>
<v-col :cols="12">
<component
:is="'SelectBox'"
ref="SelectBox1"
:labelCols='2'
:textCols='6'
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비그룹'"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
</v-row>
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: 429px;'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 w100">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.gdIdxModalData.gdIdxPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
<v-btn v-if="item.closeBtnFg || false" :ripple="false" @click="deleteBtnAction($event)">삭제</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import SelectBox from '@/components/common/select/SelectBox';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '가이드',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '가이드지표 선택',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
}
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
SelectBox
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'gdIdxPop',
modalDataKey: 'gdIdxModalData',
searchWord: '',
selectedData: {},
textFieldData: '',
selectValue01:null,
selectValueList01:[],
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
}
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
async selectValue01(value){
await this.search();
}
},
beforeCreate() {
this.$store.commit('setPageData', {
gdIdxModalData: { gdIdxPop },
});
},
async created() {
await this.setSelectValueList01();
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
async setSelectValueList01(){
// form으로 popup 사용할 때 인자로 eqpmKindId, eqpmGrpId 보내줘야한다.
let res = await this.postApiReturn({
apiKey:'selectEqpmGrpCodeList',
resKey: "eqpmGrpCodeLists",
sendParam:{eqpmKindId: this.item.eqpmKindId != undefined ? this.item.eqpmKindId : this.searchParam.eqpmKindId}
// form을 통해 popup을 사용할 경우 -> this.item.eqpmKindId 사용
// 부모 페이지에서 설비종류인 eqpmKindId 값을 꼭 가져와야한다.
});
if(res.length>0){
this.selectValueList01 = await res.map(obj => {
return {
'text':obj.eqpmGrpNm,
'value':obj.eqpmGrpId
};
});
// form을 통해 popup을 사용할 경우 -> this.item.eqpmGrpId 사용
// 부모 페이지에서 설비그룹을 선택한 값이 있다면(eqpmGrpId) 그 값으로 바인딩 아닐 경우 조회한 데이터의 첫번째 값으로 선택
this.selectValue01 = this.item.eqpmGrpId != undefined ? this.item.eqpmGrpId : this.searchParam.eqpmGrpId != undefined ? this.searchParam.eqpmGrpId : this.selectValueList01[0].value;
}else{
this.selectValueList01 = [];
this.selectValue01 = null;
}
// console.log('pyscPop_this.searchParam.eqpmGrpId', this.searchParam.eqpmGrpId);
// console.log('pyscPop_this.selectValueList01[0].value', this.selectValueList01[0].value);
// this.selectValueList01 = [{
// 'text' : 'test_eqpm_grp_03',
// 'value' : 'EQG000003'
// },
// {
// 'text' : 'test_eqpm_grp_01',
// 'value' : 'EQG000001'
// },
// {
// 'text' : 'test_eqpm_grp_02',
// 'value' : 'EQG000002'
// },
// {
// 'text' : 'test_eqpm_grp_04',
// 'value' : 'EQG000004'
// },
// {
// 'text' : 'test_eqpm_grp_05',
// 'value' : 'EQG000005'
// }
// ];
// this.selectValue01 = this.selectValueList01[0].value;
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '설비종류', name: 'eqpmKindId',hidden:true },
{ header: '설비그룹ID', name: 'eqpmGrpId' ,hidden:true},
{ header: '가이드ID', name: 'gdIdxId' },
{ header: '가이드 명', name: 'gdIdxNm', align:'center' },
{ header: '설비그룹ID', name: 'eqpmGrpId' ,hidden:true},
],
});
},
async getGridData() {
this.loadGrid = false;
let res = await this.postApiReturn({
apiKey: 'selectGdIdxPop',
resKey: 'gdIdxData',
sendParam: {
searchWord: this.searchWord,
eqpmGrpId : this.selectValue01,
},
});
//이미 선택된 값들 제거
var newRes = [];
if(res.length>0){
if(this.item.dataList){
newRes = res.filter(item=>{
return !this.item.dataList.includes(item.gdIdxId);
});
}
}
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: newRes,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
let bindingObj = {};
if(this.item.bindingItemList != undefined){
bindingObj = this.item.bindingItemList;
}
if(bindingObj.constructor === Object && Object.keys(bindingObj).length === 0) {
this.textFieldData = this.selectedData.gdIdxNm;
}else{
for (const [parentPageBindingKey, popupBindingKey] of Object.entries(bindingObj)) {
this.myBindingData[parentPageBindingKey] = this.selectedData[popupBindingKey];
const dt = {
columnName: parentPageBindingKey,
value: this.selectedData[popupBindingKey],
};
this.$emit('gridEditingFinish', dt);
this.setPageData({[parentPageBindingKey] : this.selectedData[popupBindingKey]});
}
}
},
async dialogOpenCloseEvent(val) {
await this.setSelectValueList01();
if(!this.myBindingData){
return alert('그리드를 먼저 선택해주세요.');
}
this.dialog = !val;
},
deleteBtnAction(v){
this.dialog = false;
let bindingObj = {};
if(this.item.bindingItemList != undefined){
bindingObj = this.item.bindingItemList;
}
if(bindingObj.constructor === Object && Object.keys(bindingObj).length === 0) {
this.textFieldData = null;
}else{
for (const [parentPageBindingKey, popupBindingKey] of Object.entries(bindingObj)) {
this.myBindingData[parentPageBindingKey] = null;
const dt = {
columnName: parentPageBindingKey,
value: null,
};
this.$emit('gridEditingFinish', dt);
this.setPageData({[parentPageBindingKey] : null});
}
}
}
},
};
var gdIdxPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,176 @@
<template>
<div>
<!-- <v-btn :ripple="false" @click="dialog = !dialog">경고창</v-btn> -->
<v-dialog
v-model="dialog"
width="900"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card>
<v-toolbar
:color="isDarkMode ? '#2d3355' : '#3f4d7d'"
class="py-4 pr-3 pl-5"
height="auto"
>
<v-toolbar-title>{{ label }}</v-toolbar-title>
<v-btn
icon
tile
small
:ripple="false"
@click="dialog = !dialog"
:style="{ backgroundColor: isDarkMode ? '#2d3355' : '#3f4d7d' }"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar>
<!-- <template v-for="(item, index) in detailList"> -->
<template>
<div style="padding : 20px">
<div v-for="n in detailList.length" :key="n">
<v-row v-if="n % 2 == 1" align="center" no-gutters>
<!-- {{detailList[n-1]}} {{detailList[n-1].type}} -->
<v-col
:cols="detailList[n - 1].cols"
:class="detailList[n - 1].class"
>
<component
:is="detailList[n - 1].type"
:item="detailList[n - 1]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
/>
</v-col>
<v-col
v-if="detailList[n] != undefined"
:cols="detailList[n].cols"
:class="detailList[n].class"
>
<component
:is="detailList[n].type"
:item="detailList[n]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
/>
</v-col>
</v-row>
</div>
</div>
</template>
<v-card-actions class="justify-end">
<v-btn :ripple="false" @click="clickOk()">확인</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import InputText from '~/components/common/form/InputText';
import InputNumber from '~/components/common/form/InputNumber';
import TextArea from '~/components/common/form/TextArea';
import SelectBox from '~/components/common/form/SelectBox';
import SelectBoxes from '~/components/common/form/SelectBoxes';
import CheckBox from '~/components/common/form/CheckBox';
import ChangeUserPswdPopPage from '~/components/common/modal/ChangeUserPswdPopPage';
import EnrgReadPlacePop2Page from '~/components/common/modal/EnrgReadPlacePop2Page';
import EnrgCostCenterPop from '~/components/common/modal/EnrgCostCenterPop';
import ReadPlcPop from '~/components/common/modal/ReadPlcPop';
import EvtObjPop from '~/components/common/modal/EvtObjPop';
import FtnPlcFormPop from '~/components/common/modal/FtnPlcMultiPop2';
import Label from '~/components/common/form/Label';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
detailList: {
type: Array,
require: false,
default: () => {
return [];
},
},
label: {
type: String,
require: true,
},
bindingData: {
type: String,
require: false,
},
myGrid: {
require: true,
},
},
components: {
InputText,
InputNumber,
TextArea,
SelectBox,
SelectBoxes,
CheckBox,
ChangeUserPswdPopPage,
EnrgReadPlacePop2Page,
EnrgCostCenterPop,
ReadPlcPop,
EvtObjPop,
Label,
FtnPlcFormPop,
},
data() {
return {
dialog: false,
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
},
watch: {
async chkDialog(val) {
if (val) {
}
},
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
clickOk() {
if (this.parentPrgmId) {
// this.$emit('yesNo',true);
this.setPageData({ rowGridSelectData: null });
}
this.dialog = !this.dialog;
},
},
};
</script>
<style scoped lang="scss">
::v-deep {
.v-toolbar__content {
justify-content: space-between;
padding: 0;
.v-btn {
margin-right: 0 !important;
}
}
.v-card__actions {
padding-bottom: 30px !important;
}
}
</style>

View File

@ -0,0 +1,457 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ popTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()"
>초기화</v-btn
>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="gridParent" class="h100 py-3">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.readObjModalData.OnInDataReadPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
isMulti: {
type: Boolean,
require: true,
default: false,
},
label: {
type: String,
require: true,
// default: "공정/설비"
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
popTitle: {
type: String,
require: false,
default: '',
},
widgetId: {
type: String,
require: false,
default: '',
},
props: {
dialogView: Boolean,
},
},
components: {
Grid,
Utility,
// Tree
},
data() {
return {
labelPrepend: true,
//parentPrgmId: this.parentPrgmId,
myModalKey: 'OnInDataReadPop',
gridName: 'modalGrid',
loadGrid: false,
dialog: false,
modalDataKey: 'readObjModalData',
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
gridSet: true,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
selectValue() {
const temp = [];
const readObjData = this.searchParam.isMulti
? this.searchParam.readObjList
: this.searchParam.readObj;
if (Array.isArray(readObjData)) {
if (readObjData.length > 0) {
for (const item of readObjData) {
temp.push(item.readObjNm);
}
}
} else {
// return readObjData.path === undefined ? readObjData.eccNm : readObjData.path;
}
return temp.join();
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {},
mounted() {},
created() {
this.$store.state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
].readObjModalData = { OnInDataReadPop: OnInDataReadPop };
if (this.searchParam.isMulti) {
this.$store.state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
].readObjList =
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {};
} else {
this.$store.state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
].readObj =
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {};
}
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setWidgetPageData: 'setWidgetPageData',
setWidgetModalGridOption: 'setWidgetModalGridOption',
setWidgetModalGridColumn: 'setWidgetModalGridColumn',
setWidgetModalGridData: 'setWidgetModalGridData',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 그리드 세팅
gridInit() {
// const gridHeight = this.$refs.gridParent.offsetHeight - 36;
if (this.$store.state.activeMenuInfo.prgmId == '0') {
this.$store.state.activeMenuInfo.prgmId = this.$route.query.prgmId;
}
this.setWidgetModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
widgetId: this.widgetId,
modalDataKey: this.modalDataKey,
value: [{ header: '검침 대상 명', name: 'readObjNm' }],
});
},
// 그리드 데이터 설정
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectOnInDataReadPop',
resKey: 'OnInDataReadPopData',
sendParam: {
enrgDiv: this.searchParam.enrgDiv,
search: this.searchWord,
grpCd: this.searchParam.grpCd,
mntrFg: '1',
},
});
let myOptions = {
columOptions: {
resizeable: true,
},
};
if (this.searchParam.isMulti) {
myOptions['rowHeaders'] = [{ type: 'checkbox' }];
myOptions['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
} else {
myOptions['rowHeaders'] = [];
myOptions['rowHeight'] = '';
}
this.setWidgetModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
widgetId: this.widgetId,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setWidgetModalGridData({
modalKey: this.myModalKey,
widgetId: this.widgetId,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
//화면 처음 열때 Default 체크 처리
if (localStorage.getItem(this.parentPrgmId + 'CheckedRow') == null) {
let temp = [];
res.filter(item => {
if (item.mntrFg == 1) {
temp.push(item);
}
});
this.searchParam.readObjList = temp;
}
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.readObjList.length > 0
? this.searchParam.readObjList
: [];
if (this.checkedRowDataList.length > 0) {
if (
this.checkedRowDataList[0].readObjKind != this.searchParam.enrgDiv
) {
this.checkedRowDataList = [];
} else {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
}
}
},
// row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
} else {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
this.gridName + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length > 4) {
alert('검침대상은 최대 4개까지 선택가능합니다.');
return;
}
this.dialog = false;
this.$store.state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
].readObjList = this.checkedRowDataList;
this.$emit('chDialogView' + this.widgetId);
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.readObjList),
);
} else {
this.dialog = false;
this.$store.state.pageData[this.parentPrgmId][this.widgetId][
this.widgetId + 'Data'
].readObjList = [this.activeRowData];
this.$emit('chDialogView' + this.widgetId);
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.readObj),
);
}
},
reset() {
for (
var i = 0;
i < this.$refs[this.gridName + this.parentPrgmId].getData().length;
i++
) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
this.$refs[this.gridName + this.parentPrgmId].getData()[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
},
search() {
this.getGridData();
},
typeEnterKey() {
this.getGridData();
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
const OnInDataReadPop = {
modalGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,420 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small :color="required ? '#fb8200' : 'primary'" class="mr-1"
>mdi-record-circle</v-icon
>
{{ labelContent }}
</label>
</v-col>
<v-col :cols="textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="required || false"
:disabled="disabled || false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="5">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!--
<v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn>
-->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData.onInBaseEccPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '공정명',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '공정목록',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
required: {
require: false,
default: false,
},
disabled: {
require: false,
default: false,
},
bindOption: {
type: Object,
requrie: false,
default: null,
},
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'onInBaseEccPop',
modalDataKey: 'modalData',
searchWord: '',
selectedData: {},
textFieldData: '',
parentModalState: 'close',
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
},
set(value) {
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
parentModalState(val) {
if (this.bindOption !== null) {
if (val === 'open') {
this.textFieldData = this.searchParam.rowGridSelectData.eccNm;
this.searchParam[
this.bindOption.eccId
] = this.searchParam.rowGridSelectData.eccId;
this.searchParam[
this.bindOption.eccNm
] = this.searchParam.rowGridSelectData.eccNm;
} else if (val === 'openWithInit') {
this.textFieldData = '';
this.searchParam[this.bindOption.eccId] = '';
this.searchParam[this.bindOption.eccNm] = '';
}
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { onInBaseEccPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
this.textFieldData = '';
this.selectedData.eccId = '';
this.selectedData.eccNm = '';
if (this.bindOption === null) {
console.log('this.bindOption is null...');
this.setPageData({
modalEccId: '',
modalEccNm: '',
});
} else {
console.log('this.bindOption is not null...');
this.setPageData({
[this.bindOption.eccId]: '',
[this.bindOption.eccNm]: '',
});
}
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
const _this = this;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: '회사 ID', name: 'comId', hidden: true },
{
header: '공정 ID',
name: 'eccId',
width: 100,
align: 'center',
hidden: true,
},
{ header: '공정명', name: 'eccNm', align: 'center' },
],
});
this.setPageData({
modalEccId:
localStorage.getItem(this.parentPrgmId + 'ModalEccId') != null
? localStorage.getItem(this.parentPrgmId + 'ModalEccId')
: '',
modalEccNm:
localStorage.getItem(this.parentPrgmId + 'ModalEccNm') != null
? localStorage.getItem(this.parentPrgmId + 'ModalEccNm')
: '',
});
console.log(
'localStorage.getItem(this.parentPrgmId + "ModalEccNm") : ',
localStorage.getItem(this.parentPrgmId + 'ModalEccNm') != null
? localStorage.getItem(this.parentPrgmId + 'ModalEccNm')
: '',
);
this.textFieldData =
localStorage.getItem(this.parentPrgmId + 'ModalEccNm') != null
? localStorage.getItem(this.parentPrgmId + 'ModalEccNm')
: '';
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectOnlnBaseEcc',
resKey: 'onlnBaseEccData',
sendParam: {
eccNmLike: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
this.textFieldData = this.selectedData.eccNm;
if (this.bindOption === null) {
this.searchParam.modalEccId = this.selectedData.eccId;
this.searchParam.modalEccNm = this.selectedData.eccNm;
localStorage.setItem(
this.parentPrgmId + 'ModalEccId',
this.selectedData.eccId != null ? this.selectedData.eccId : '',
);
localStorage.setItem(
this.parentPrgmId + 'ModalEccNm',
this.selectedData.eccNm != null ? this.selectedData.eccNm : '',
);
} else {
this.searchParam[this.bindOption.eccId] = this.selectedData.eccId;
this.searchParam[this.bindOption.eccNm] = this.selectedData.eccNm;
}
this.setPageData({ isFind: true });
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
localStorage.setItem(
this.parentPrgmId + 'ModalEccId',
this.selectedData.eccId != null ? this.selectedData.eccId : '',
);
localStorage.setItem(
this.parentPrgmId + 'ModalEccNm',
this.selectedData.eccNm != null ? this.selectedData.eccNm : '',
);
},
},
};
var onInBaseEccPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,412 @@
<template>
<v-row v-if="!item.showValue" class="search-box" align="center" no-gutters>
<v-col :cols="option.labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ option.labelContent }}
</label>
</v-col>
<v-col :cols="option.textCols">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
:required="item.required || false"
:disabled="false"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ option.modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="grid_01"
:dataPath="searchParam.modalData2.OnlnBasicUnitAddInfoPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '이벤트항목',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '이벤트항목',
},
modalContent: {
type: String,
require: false,
default: '검색',
},
item: {
type: Object,
require: false,
},
bindingData: {
type: String,
require: false,
},
// bindingFlag:{
// type:Boolean,
// require: false,
// default: false
// }
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
grid_01: 'grid_01',
myModalKey: 'OnlnBasicUnitAddInfoPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
option: {
labelCols:
this.item !== undefined
? this.item.labelCols !== undefined
? this.item.labelCols
: this.labelCols
: this.labelCols,
labelContent:
this.item !== undefined
? this.item.labelContent !== undefined
? this.item.labelContent
: this.labelContent
: this.labelContent,
textCols:
this.item !== undefined
? this.item.textCols !== undefined
? this.item.textCols
: this.textCols
: this.textCols,
modalTitle:
this.item !== undefined
? this.item.modalTitle !== undefined
? this.item.modalTitle
: this.modalTitle
: this.modalTitle,
},
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
}),
selectValue: {
get() {
if (!this.item) {
return this.textFieldData;
}
// else if(this.item.disableContent){
// return "NONE";
// }
else {
return this.myBindingData
? this.myBindingData[this.item.valueNm]
: this.textFieldData;
}
},
set(value) {
// if(this.item && this.item.disableContent){
// return "NONE";
// }
return value;
},
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { OnlnBasicUnitAddInfoPop },
});
},
created() {
this.init();
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.gridInit();
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: [
{ header: 'TAG ID', name: 'tagId' },
{ header: 'TAG 명', name: 'tagNm' },
],
});
},
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectTagBaseInfo',
resKey: 'tagBaseInfoData',
sendParam: {
tagNmLike: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.grid_01,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate(v) {
this.dialog = false;
if (!this.item) {
this.textFieldData = this.selectedData.tagId;
} else {
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.selectedData.tagNm;
} else {
this.myBindingData.tagNm = this.selectedData.tagNm;
}
// this.myBindingData.tagNm = this.selectedData.tagNm;
const dt = {
columnName: this.item.valueNm,
value: this.selectedData.tagId,
};
// console.log("dt1 : ", dt)
this.$emit('gridEditingFinish', dt);
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.selectedData[this.item.valueNm2],
};
// console.log("dt2 : ", dt)
this.$emit('gridEditingFinish', dt);
}
if (this.item.bindNm !== undefined) {
const dt = {
columnName: this.item.bindNm,
value: this.selectedData.tagNm,
};
// console.log("dt3 : ", dt)
this.$emit('gridEditingFinish', dt);
}
}
},
dialogOpenCloseEvent(val) {
// if(this.item && this.item.disableContent){
// this.dialog = false;
// return;
// }
this.dialog = !val;
},
},
};
var OnlnBasicUnitAddInfoPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,383 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog ref="popModal" v-model="dialog" scrollable width="540px">
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title>
<span class="search-box-label">검침개소</span>
</v-card-title>
<v-card-actions>
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
위치정보 선택
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<v-btn color="primary" dark>초기화</v-btn>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectReadPlcTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectReadPlcTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.readPlcNm);
}
}
} else {
return facData.path !== '' ? facData.path : facData.readPlcNm;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
chkDialog(val) {
if (val) {
this.gridInit();
this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadPlcTree },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
if (this.searchParam.isMulti == true) {
this.setPageData({
facInfoList:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
} else {
this.setPageData({
facInfo:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
}
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
//useCascadingCheckbox: false
},
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
} else {
delete this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
modalDataKey: this.modalDataKey,
gridKey: this.gridNameTree,
value: [{ header: '위치정보', name: 'readPlcNm' }],
});
},
// 공정/설비 조회
async getTreeData() {
const res = await this.postApiReturn({
apiKey: 'selectReadPlcTree',
resKey: 'ftnPlcTreeData',
sendParam: {
blocId: this.searchParam.blocMstrList[this.searchParam.blocId].blocId, //"BL0001",
mttCd: this.searchParam.energyList[this.searchParam.energyCd].cd, // "MTT00001" // 전력 코드 고정
},
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC',
value: res.map(item => ({
...item,
readPlcNm: item.readPlcNm,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
async setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.facInfoList.length > 0
? this.searchParam.facInfoList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
async getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ facInfoList: this.checkedRowDataList });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfoList),
);
} else {
alert('비교대상이 20개를 초과하였습니다.');
}
} else {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfo),
);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
},
};
const selectReadPlcTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,467 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card :height="height">
<v-card-title class="d-flex align-center justify-space-between">
<span class="custom-title-4">검침개소</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col v-if="label" 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="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<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>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn :ripple="false">초기화</v-btn> -->
<v-btn
v-if="!searchParam.isMulti"
:ripple="false"
@click="search()"
>검색</v-btn
>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="{ height: 'calc(100% - 213px)' }">
<div ref="treeGridParent" class="h100 py-3">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectReadObjListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setClean()">초기화</v-btn>
<v-btn :ripple="false" @click="setUpdate()">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
default: '공정/설비',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectReadObjListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
const readPlcData = this.searchParam.readPlcId;
return readPlcData.path === undefined
? readPlcData.readPlcNm
: readPlcData.path;
// 선택된 공장/설비 값
// const temp = []
// const facData = this.searchParam.facInfo;
// if(Array.isArray(facData)){
// if(facData.length > 0){
// for(const item of facData) {
// temp.push(item.eccNm);
// }
// }
// } else {
// return facData.path === undefined ? facData.eccNm : facData.path;
// }
// return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadObjListTree },
});
},
created() {
this.init();
this.setPageData({
readPlcId:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: '',
});
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeColumnWidth = this.$refs['treeGridParent'] - 10;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [
{
header: '검침개소명',
name: 'readPlcNm',
width: treeColumnWidth,
align: 'left',
},
],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectReadPlcBaseInfo',
resKey: 'readPlcBaseInfoData',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
// roiId: this.searchParam.energyList[this.searchParam.energyCd].cd, // "MTT00001" // 전력 코드 고정
// eqpmYn: this.eqpmYn,
readObjId: this.searchParam.searchReadObj, // "MTT00001" // 전력 코드 고정,
useFg: '1',
search: this.searchWord,
},
});
let myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(
this.$refs.treeGridParent.offsetHeight - 60,
),
myOptionsTree,
),
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC_ID',
value: res.map(item => ({
...item,
rowStat: null,
readPlcId: item.readPlcId,
readPlcIdNm: item.readPlcId,
upReadPlcId:
item.upReadPlcId == null || item.upReadPlcId == ''
? ''
: item.upReadPlcId,
upReadPlcNm:
item.upReadPlcNm == null || item.upReadPlcNm == ''
? ''
: item.upReadPlcNm,
blocId: item.blocId,
useFg: item.useFg === '1' ? true : false,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
// console.log('this.$refs["treeGrid" + this.parentPrgmId]', this.$refs)
this.loadGrid = true;
// this.$nextTick(() => {
// if (setTreeData.ROOT.length > 0) {
// try {
// this.$refs["treeGrid" + this.parentPrgmId].focus({
// rowKey: 0,
// columnName: "readPlcNm",
// setScroll: true
// });
// } catch (error) {
// }
// }
// });
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
this.activeRowData = data;
},
setUpdate() {
this.dialog = false;
this.setPageData({ readPlcId: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.readPlcId),
);
this.searchWord = '';
},
setClean() {
// this.$refs["treeGrid" + this.parentPrgmId].focus({
// rowKey: 0,
// columnName: "readPlcNm",
// setScroll: true
// });
// this.dialog = false;
// this.setPageData({readPlcId : {'readPlcId' : ''}});
this.activeRowData = {};
localStorage.removeItem(this.parentPrgmId + 'CheckedRow');
this.searchWord = '';
},
dialogOpenCloseEvent(val) {
this.searchWord = '';
this.dialog = !val;
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
search() {
this.getTreeData();
},
typeEnterKey() {
this.getTreeData();
},
},
};
const selectReadObjListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,356 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="label ? textCols : ''">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialogOpenCloseEvent(dialog)"
outlined
:hide-details="true"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ modalTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<!-- <v-btn :ripple="false" @click="initSearch()">
초기화
</v-btn> -->
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="modalGridParent" class="h100 py-3">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData2.selectTagPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
@watchReadPlcPop="watchReadPlcPop"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate()">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
labelContent: {
type: String,
require: false,
default: '태그',
},
textCols: {
type: Number,
require: false,
default: 7,
},
modalTitle: {
type: String,
require: false,
default: '태그명',
},
modalContent: {
type: String,
require: false,
default: '태그명 검색',
},
},
components: {
Grid,
Utility,
},
data() {
return {
dialog: false,
loadGrid: false,
gridName: 'grid_01',
myModalKey: 'selectTagPop',
modalDataKey: 'modalData2',
searchWord: '',
selectedData: {},
textFieldData: '',
searchedData: [],
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
const tagData = this.searchParam.tagData;
return tagData.tagNm;
},
chkReadPlc() {
return this.searchParam.readPlcId;
},
},
watch: {
async dialog(val) {
if (val) {
await this.getGridData();
}
},
chkReadPlc() {
// console.log(this.searchParam.readPlcId);
if (!this.dialog) {
this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { selectTagPop },
});
},
created() {
this.init();
this.setPageData({
tagId:
localStorage.getItem(this.parentPrgmId + 'CheckedRow2') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow2'))
: {},
});
},
mounted() {},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
watchReadPlcPop() {
if (!this.dialog) {
this.getGridData();
}
},
search() {
this.getGridData();
},
initSearch() {
this.searchWord = '';
this.getGridData();
},
gridInit() {
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: [
// { header: "TAG ID", name: "tagId" },
{ header: 'TAG 명', name: 'tagNm' },
],
});
this.getGridData();
},
async getGridData() {
this.loadGrid = false;
let searchparams = {
readPlc: '',
};
searchparams['readPlc'] =
this.searchParam.readPlcId.readPlcId == undefined
? ''
: this.searchParam.readPlcId.readPlcId;
searchparams['searchWord'] = this.searchWord;
const res = await this.postApiReturn({
apiKey: 'selectTagNmList',
resKey: 'tagNmListData',
sendParam: searchparams,
});
this.searchedData = res;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
if (res.length > 0 && !this.dialog) {
this.setPageData({ tagData: res[0] });
} else if (res.length == 0 && !this.dialog) {
this.setPageData({ tagData: { tagId: 'noSearchTagId' } });
}
this.$nextTick(() => {
if (res.length > 0) {
try {
this.$refs['grid_01' + this.parentPrgmId].focus({
rowKey: 0,
columnName: 'tagNm',
setScroll: true,
});
} catch (error) {}
}
});
},
getRowData(data) {
this.selectedData = { ...data };
},
setUpdate() {
this.dialog = false;
this.setPageData({ tagData: this.selectedData });
},
dialogOpenCloseEvent(val) {
this.searchWord = '';
this.dialog = !val;
},
},
};
var selectTagPop = {
grid_01: {
data: [],
column: [],
option: {},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,885 @@
<template>
<div>
<!-- <v-btn :ripple="false" @click="dialog = !dialog">경고창</v-btn> -->
<v-dialog
v-model="dialog"
width="700"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card>
<v-toolbar
:color="isDarkMode ? '#2d3355' : '#3f4d7d'"
class="py-4 pr-3 pl-5"
height="auto"
>
<v-toolbar-title>{{ label }}</v-toolbar-title>
<!-- <v-btn
icon
tile
small
:ripple="false"
@click="dialog = !dialog"
:style="{ backgroundColor: isDarkMode ? '#2d3355' : '#3f4d7d' }"
>
<v-icon>mdi-close</v-icon>
</v-btn> -->
</v-toolbar>
<!-- <v-card-title>
일정 상세 내용
</v-card-title> -->
<!-- <template v-for="(item, index) in detailList"> -->
<template>
<div style="padding : 20px">
<v-col :cols="12">
<v-row>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
일정 시작
</label>
</v-row>
</v-col>
<v-col :cols="4">
<!-- <DatePicker v-model="strtDt" :parentPrgmId="parentPrgmId"/> -->
<div class="startpicker-container2">
<v-text-field
id="startpicker2"
ref="startpicker2"
v-model="strtDt"
:class="'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="startpicker-container2"
id="startpicker-container2"
></div>
</template>
</v-text-field>
</div>
</v-col>
<v-col :cols="2">
<vue-numeric-input
v-model="strtHh"
:min="0"
:max="23"
controls-type="updown"
class="v-input__slot"
width="100%"
align="center"
>
</vue-numeric-input>
</v-col>
<v-col :cols="1" style="text-align: center;">
:
</v-col>
<v-col :cols="2">
<vue-numeric-input
v-model="strtMm"
:min="0"
:max="59"
controls-type="updown"
class="v-input__slot"
width="100%"
align="center"
>
</vue-numeric-input>
</v-col>
</v-row>
<v-row>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
일정 종료
</label>
</v-row>
</v-col>
<v-col :cols="4">
<!-- <DatePicker v-model="endDt" :parentPrgmId="parentPrgmId"/> -->
<div class="startpicker-container3">
<v-text-field
id="startpicker3"
ref="startpicker3"
v-model="endDt"
:class="'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div
ref="startpicker-container3"
id="startpicker-container3"
></div>
</template>
</v-text-field>
</div>
</v-col>
<v-col :cols="2">
<vue-numeric-input
v-model="endHh"
:min="0"
:max="23"
controls-type="updown"
class="v-input__slot"
width="100%"
align="center"
>
</vue-numeric-input>
</v-col>
<v-col :cols="1" style="text-align: center;">
:
</v-col>
<v-col :cols="2">
<vue-numeric-input
v-model="endMm"
:min="0"
:max="59"
controls-type="updown"
class="v-input__slot"
width="100%"
align="center"
>
</vue-numeric-input>
</v-col>
</v-row>
<v-row>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
일정 제목
</label>
</v-row>
</v-col>
<v-col :cols="9">
<v-text-field
v-model="planTitle"
class="v-input__custom"
outlined
:hide-details="true"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<label class="search-box-label">
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
일정 상세 내용
</label>
</v-row>
</v-col>
<v-col :cols="9">
<v-textarea
v-model="planCntn"
class="v-input__custom"
outlined
:hide-details="true"
:maxlength="1000"
></v-textarea>
</v-col>
</v-row>
<v-row>
<v-col :cols="3">
<v-row class="search-box" align="center" no-gutters>
<v-icon x-small color="#fb8200" class="mr-1"
>mdi-record-circle</v-icon
>
표시 색상
</v-row>
</v-col>
<v-col :cols="1">
<div
id="redDiv"
class="colPk redBg"
@click="colorClick('red')"
></div>
</v-col>
<v-col :cols="1">
<div
id="blueDiv"
class="colPk blueBg"
@click="colorClick('blue')"
></div>
</v-col>
<v-col :cols="1">
<div
id="pupleDiv"
class="colPk pupleBg"
@click="colorClick('puple')"
></div>
</v-col>
<v-col :cols="1">
<div
id="greenDiv"
class="colPk greenBg"
@click="colorClick('green')"
></div>
</v-col>
<v-col :cols="1">
<div
id="orangeDiv"
class="colPk orangeBg"
@click="colorClick('orange')"
></div>
</v-col>
<v-col :cols="1">
<div
id="pinkDiv"
class="colPk pinkBg"
@click="colorClick('pink')"
></div>
</v-col>
</v-row>
</v-col>
</div>
</template>
<v-card-actions class="justify-end">
<v-btn :ripple="false" @click="btnAction('save')">저장</v-btn>
<v-btn
v-show="popUpAction === 'update'"
:ripple="false"
@click="btnAction('delete')"
>삭제</v-btn
>
<v-btn :ripple="false" @click="btnAction('close')">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import VueNumericInput from 'vue-numeric-input';
import InputText from '~/components/common/form/InputText';
import InputNumber from '~/components/common/form/InputNumber';
import TextArea from '~/components/common/form/TextArea';
import SelectBox from '~/components/common/form/SelectBox';
import SelectBoxes from '~/components/common/form/SelectBoxes';
import CheckBox from '~/components/common/form/CheckBox';
import Label from '~/components/common/form/Label';
import DatePicker from '~/components/common/Datepicker';
import mixinGlobal from '@/mixin/global.js';
import Utility from '~/plugins/utility';
import TuiDatepicker from 'tui-date-picker';
export default {
mixins: [mixinGlobal],
props: {
parentPrgmId: {
type: String,
require: true,
},
detailList: {
type: Array,
require: false,
default: () => {
return [];
},
},
label: {
type: String,
require: true,
},
bindingData: {
type: String,
require: false,
},
gridName: {
type: String,
require: false,
},
},
components: {
InputText,
InputNumber,
TextArea,
SelectBox,
SelectBoxes,
CheckBox,
Label,
DatePicker,
Utility,
TuiDatepicker,
VueNumericInput,
},
data() {
return {
dialog: false,
popUpAction: '',
param: {},
planCntn: '',
planTitle: '',
strtHh: 0,
strtMm: 0,
endHh: 1,
endMm: 0,
strtDt:null,
endDt:null,
// strtDt: new Date().toISOString().substr(0, 10),
// endDt: new Date().toISOString().substr(0, 10),
planColor: '',
startDatepickerInstance: null,
startDatepickerInstance3: null,
planSeq: '',
blocId: '',
addPlanData:{
}
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
},
watch: {
async chkDialog(val) {
if (val) {
this.openDialog();
this.$nextTick(() => {});
} else {
}
},
strtDt(val){
console.log('strtDt : ', val);
this.checkStrtAndEndDateTime('start');
if(this.startDatepickerInstance3){
this.startDatepickerInstance3.setDate(new Date(this.endDt));
}
},
endDt(val){
console.log('endDt : ', val);
this.checkStrtAndEndDateTime('end');
if(this.startDatepickerInstance){
this.startDatepickerInstance.setDate(new Date(this.strtDt));
}
},
strtHh(val) {
console.log('strtHh : ', val);
this.checkStrtAndEndDateTime('start');
},
endHh(val) {
console.log('endHh : ', val);
this.checkStrtAndEndDateTime('end');
},
strtMm(val) {
this.checkStrtAndEndDateTime('start');
},
endMm(val) {
this.checkStrtAndEndDateTime('end');
},
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
...mapActions({
postUpdateApi: 'modules/list/postUpdateApi',
getDomain: 'modules/list/getDomain',
}),
async checkStrtAndEndDateTime(startEndFlag){
var startDateTime = this.strtDt + ' ' + this.strtHh + ':' + this.strtMm;
var endDateTime = this.endDt + ' ' + this.endHh + ':' + this.endMm;
startDateTime = new Date(startDateTime);
endDateTime = new Date(endDateTime);
if(startDateTime > endDateTime){
if(startEndFlag == 'start'){ // 시작 부분이 변경됨 -> 끝 부분 값을 변경
this.endDt = this.convertDateToString(new Date(new Date().setDate(new Date(this.strtDt).getDate() + 1)));
this.startDatepickerInstance3.setDate(new Date(this.endDt));
}else if(startEndFlag == 'end'){ // 끝 부분이 변경됨 -> 시작 부분 값을 변경
this.strtDt = this.convertDateToString(new Date(new Date().setDate(new Date(this.endDt).getDate() - 1)));
this.startDatepickerInstance.setDate(new Date(this.strtDt));
}
}
},
async tuiCalendarInit() {
const startContainer = document.getElementById('startpicker-container2');
const startTarget = document.getElementById('startpicker2');
const startContainer3 = document.getElementById('startpicker-container3');
const startTarget3 = document.getElementById('startpicker3');
var dt1 = new Date();
var dt2 = new Date();
if(this.strtDt){
dt1 = this.strtDt;
}
if(this.endDt){
dt2 = this.endDt;
}
this.startDatepickerInstance = new TuiDatepicker(startContainer, {
// date: new Date(),
date : dt1,
language: 'ko',
type: 'date',
input: {
element: startTarget,
format: 'YYYY-MM-DD',
},
timePicker: false,
});
this.startDatepickerInstance.on('change', () => this.getStartDt());
this.startDatepickerInstance3 = new TuiDatepicker(startContainer3, {
// date: new Date(),
date : dt2,
language: 'ko',
type: 'date',
input: {
element: startTarget3,
format: 'YYYY-MM-DD',
},
timePicker: false,
});
this.startDatepickerInstance3.on('change', () => this.getEndDt());
},
getStartDt() {
const dt = this.startDatepickerInstance.getDate();
// console.log('dt[getStartDt] : ', dt);
// console.log('dt[getStartDt] : ', dt.toISOString());
// this.strtDt = dt.getFullYear() + '-' + String(dt.getMonth()+1).padStart(2, '0') + '-' + String(dt.getDate()).padStart(2, '0');
// this.strtDt = String(dt.toISOString()).substr(0, 10);
// this.strtDt = this.convertStringToDateFormat(this.strtDt);
this.strtDt = this.convertDateToString(dt);
this.startDatepickerInstance.setDate(new Date(this.strtDt));
},
getEndDt() {
const dt = this.startDatepickerInstance3.getDate();
// console.log('dt[getEndDt] : ', dt);
// console.log('dt[getendDt] : ', dt.toISOString());
// this.endDt = dt.getFullYear() + '-' + String(dt.getMonth()+1).padStart(2, '0') + '-' + String(dt.getDate()).padStart(2, '0');
// this.endDt = String(dt.toISOString()).substr(0, 10);
// this.endDt = this.convertStringToDateFormat(this.endDt);
this.endDt = this.convertDateToString(dt);
this.startDatepickerInstance3.setDate(new Date(this.endDt));
},
convertDateToString(dt){
return dt.getFullYear() + '-' + String(dt.getMonth()+1).padStart(2, '0') + '-' + String(dt.getDate()).padStart(2, '0');
},
convertStringToDateFormat(val) {
var result = '';
result = Utility.setFormatDate(val, 'YYYY-MM-DD');
return result;
},
convertDateFormatToString(val) {
return val.replaceAll('-', '');
},
async openDialog() {
this.$nextTick(() => {
this.tuiCalendarInit();
switch (this.popUpAction) {
case 'read':
this.strtDt = this.convertStringToDateFormat(
this.searchParam.rowGridSelectData.chkDd,
);
this.endDt = this.convertStringToDateFormat(
this.searchParam.rowGridSelectData.chkDd,
);
break;
case 'insert':
this.insertPlanData();
break;
case 'update':
this.getPlanData();
break;
}
});
},
async insertPlanData(){
var year = this.addPlanData.year;
var month = this.addPlanData.month;
var day = this.addPlanData.day;
// this.strtDt = this.convertStringToDateFormat(this.strtDt);
// this.endDt = this.convertStringToDateFormat(this.endDt);
this.strtHh = 0;
this.strtMm = 0;
this.endHh = 1;
this.endMm = 0;
this.planTitle = '';
this.planCntn = '';
this.planColor = '';
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document
.getElementById('orangeDiv')
.classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
// this.strtDt = this.convertStringToDateFormat(this.strtDt);
// this.endDt = this.convertStringToDateFormat(this.endDt);
// console.log('this.strtDt[insertPlanData] : ', this.strtDt);
// console.log('this.endDt[insertPlanData] : ', this.endDt);
// this.startDatepickerInstance.setDate(new Date(this.strtDt));
// this.startDatepickerInstance3.setDate(new Date(this.endDt));
// this.startDatepickerInstance.setDate(new Date(this.strtDt));
// this.startDatepickerInstance3.setDate(new Date(this.endDt));
// this.strtDt = Utility.setFormatDate(this.strtDt, 'YYYY-MM-DD');
// this.endDt = Utility.setFormatDate(this.endDt, 'YYYY-MM-DD');
this.strtDt = year + '-' + String(month).padStart(2, '0') + '-' + String(day).padStart(2, '0');
this.endDt = year + '-' + String(month).padStart(2, '0') + '-' + String(day).padStart(2, '0');
},
async getPlanData() {
let res = await this.postApiReturn({
apiKey: 'selectWorkCaldDetlOne',
resKey: 'workcaldDetlOneData',
sendParam: {
blocId: this.blocId,
planSeq: this.planSeq,
comId: this.comId,
},
});
let returnData = res[0];
this.strtDt = Utility.setFormatDate(returnData.strtDt, 'YYYY-MM-DD');
this.endDt = Utility.setFormatDate(returnData.endDt, 'YYYY-MM-DD');
this.strtHh = returnData.strtHh;
this.strtMm = returnData.strtMm;
this.endHh = returnData.endHh;
this.endMm = returnData.endMm;
this.planTitle = returnData.planTitle;
this.planCntn = returnData.planCntn;
this.planColor = returnData.planColor;
this.colorClick(this.planColor);
},
async btnAction(action) {
switch (action) {
case 'close':
this.dialog = !this.dialog;
break;
case 'save':
if (this.popUpAction === 'insert') {
if (
this.strtDt === '' ||
this.endDt === '' ||
this.strtHh === '' ||
this.strtMm === '' ||
this.endHh === '' ||
this.endMm === '' ||
this.planTitle === '' ||
this.planCntn === '' ||
this.planColor === ''
) {
alert('필수값을 입력해주세요.');
} else {
this.dialog = !this.dialog;
await this.insertDetail();
}
} else if (this.popUpAction === 'update') {
if (
this.strtDt == '' ||
this.endDt == '' ||
this.strtHh == '' ||
this.strtMm == '' ||
this.endHh == '' ||
this.endMm == '' ||
this.planTitle == '' ||
this.planCntn == '' ||
this.planColor == ''
) {
alert('필수값을 입력해주세요.');
} else {
this.dialog = !this.dialog;
await this.updateDetail();
}
}
break;
case 'delete':
this.dialog = !this.dialog;
await this.deleteDetail();
break;
}
//console.log(this);
},
async insertDetail() {
var params = {
strtDt: this.strtDt,
endDt: this.endDt,
strtHh: this.strtHh.toString(),
strtMm: this.strtMm.toString(),
endHh: this.endHh.toString(),
endMm: this.endMm.toString(),
blocId: this.blocId,
planTitle: this.planTitle,
planCntn: this.planCntn,
planColor: this.planColor,
};
await this.postUpdateApi({
apiKey: 'savePlanDetl',
sendParam: {
datas: {
savePlanDetl: [params],
},
params: {},
},
});
this.setPageData({
isFind: true,
});
},
async updateDetail() {
var params = {
strtDt: this.strtDt.substr(0, 10),
endDt: this.endDt.substr(0, 10),
strtHh: this.strtHh.toString(),
strtMm: this.strtMm.toString(),
endHh: this.endHh.toString(),
endMm: this.endMm.toString(),
planTitle: this.planTitle,
planCntn: this.planCntn,
planColor: this.planColor,
blocId: this.blocId,
planSeq: this.planSeq,
};
await this.postUpdateApi({
apiKey: 'updatePlanDetl',
sendParam: {
datas: {
updatePlanDetl: [params],
},
params: {},
},
});
this.setPageData({
isFind: true,
});
},
async deleteDetail() {
var params = {
blocId: this.blocId,
planSeq: this.planSeq,
};
await this.postUpdateApi({
apiKey: 'deletePlanDetl',
sendParam: {
datas: {
deletePlanDetl: [params],
},
params: {},
},
});
this.setPageData({
isFind: true,
});
},
colorClick(t) {
if (t == 'red') {
document.getElementById('redDiv').classList.add('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document.getElementById('orangeDiv').classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
this.planColor = 'red';
} else if (t == 'blue') {
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.add('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document.getElementById('orangeDiv').classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
this.planColor = 'blue';
} else if (t == 'puple') {
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.add('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document.getElementById('orangeDiv').classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
this.planColor = 'puple';
} else if (t == 'green') {
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.add('colPkSelect');
document.getElementById('orangeDiv').classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
this.planColor = 'green';
} else if (t == 'orange') {
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document.getElementById('orangeDiv').classList.add('colPkSelect');
document.getElementById('pinkDiv').classList.remove('colPkSelect');
this.planColor = 'orange';
} else if (t == 'pink') {
document.getElementById('redDiv').classList.remove('colPkSelect');
document.getElementById('blueDiv').classList.remove('colPkSelect');
document.getElementById('pupleDiv').classList.remove('colPkSelect');
document.getElementById('greenDiv').classList.remove('colPkSelect');
document.getElementById('orangeDiv').classList.remove('colPkSelect');
document.getElementById('pinkDiv').classList.add('colPkSelect');
this.planColor = 'pink';
}
},
},
};
</script>
<style scoped lang="scss">
::v-deep {
.v-toolbar__content {
justify-content: space-between;
padding: 0;
.v-btn {
margin-right: 0 !important;
}
}
.v-card__actions {
padding-bottom: 30px !important;
}
.colPk {
width: 25px;
height: 25px;
text-align: center;
border-radius: 5px 5px;
cursor: pointer;
}
.colPkSelect {
border: 2px solid;
}
.redBg {
background-color: rgba(229, 62, 62, var(--bg-opacity));
background-color: #e53e3e;
}
.blueBg {
background-color: rgba(66, 153, 225, var(--bg-opacity));
background-color: #4299e1;
}
.pupleBg {
background-color: rgba(102, 126, 234, var(--bg-opacity));
background-color: #667eea;
}
.greenBg {
background-color: rgba(56, 178, 172, var(--bg-opacity));
background-color: #38b2ac;
}
.orangeBg {
background-color: rgba(237, 137, 54, var(--bg-opacity));
background-color: #ed8936;
}
.pinkBg {
background-color: rgba(237, 100, 166, var(--bg-opacity));
background-color: #ed64a6;
}
}
.startpicker-container2 {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#startpicker-container2,
#endpicker-container2 {
width: 100%;
position: absolute;
top: 36px;
left: 0;
}
}
}
}
.startpicker-container3 {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#startpicker-container3,
#endpicker-container3 {
width: 100%;
position: absolute;
top: 36px;
left: 0;
}
}
}
}
.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,440 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
placeholder="조회항목선택"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-card-title class="pa-5 d-flex align-center justify-space-between">
<span class="custom-title-4">{{ popTitle }}</span>
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="6">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="4" class="text-right">
<v-btn :ripple="false" @click="search()">
조회
</v-btn>
<v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()"
>초기화</v-btn
>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<div :style="'height: calc(50vh)'">
<!-- <div :style="{ height: 'calc(100% - 213px)' }"> -->
<div ref="gridParent" class="h100 py-3">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData.OnInDataReadPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn :ripple="false" @click="setUpdate($event)">확인</v-btn>
<v-btn :ripple="false" @click="dialogOpenCloseEvent(dialog)"
>닫기</v-btn
>
</v-card-actions>
</v-card>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: true,
// default: "공정/설비"
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
height: {
type: Number,
default: 713,
},
eqpmYn: {
type: Number,
require: false,
default: 1,
},
popTitle: {
type: String,
require: false,
default: '',
},
},
components: {
Grid,
Utility,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'OnInDataReadPop',
gridName: 'modalGrid',
loadGrid: false,
dialog: false,
modalDataKey: 'modalData',
activeRowData: {},
checkedRowDataList: [],
searchWord: '',
gridSet: true,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
selectValue() {
const temp = [];
const readObjData = this.searchParam.isMulti
? this.searchParam.readObjList
: this.searchParam.readObj;
if (Array.isArray(readObjData)) {
if (readObjData.length > 0) {
for (const item of readObjData) {
temp.push(item.readObjNm);
}
}
} else {
// return readObjData.path === undefined ? readObjData.eccNm : readObjData.path;
}
return temp.join();
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getGridData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { OnInDataReadPop },
});
},
created() {
this.init();
if (this.searchParam.isMulti == true) {
this.setPageData({
readObjList:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
} else {
this.setPageData({
readObj:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
}
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 그리드 세팅
gridInit() {
// const gridHeight = this.$refs.gridParent.offsetHeight - 36;
const myOptions = {
columOptions: {
resizeable: true,
},
};
if (this.searchParam.isMulti) {
myOptions['rowHeaders'] = [{ type: 'checkbox' }];
myOptions['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
Utility.defaultGridOption(400, myOptions),
myOptions,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: [{ header: '검침 대상 명', name: 'readObjNm' }],
});
},
// 그리드 데이터 설정
async getGridData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectOnInDataReadPop',
resKey: 'OnInDataReadPopData',
sendParam: {
enrgDiv: this.searchParam.enrgDiv,
search: this.searchWord,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
//화면 처음 열때 Default 체크 처리
if (localStorage.getItem(this.parentPrgmId + 'CheckedRow') == null) {
let temp = [];
res.filter(item => {
if (item.mntrFg == 1) {
temp.push(item);
}
});
this.searchParam.readObjList = temp;
}
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows(res);
}
});
},
setGridCheckedRows(res) {
this.checkedRowDataList =
this.searchParam.readObjList.length > 0
? this.searchParam.readObjList
: [];
if (this.checkedRowDataList.length > 0) {
if (res.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
if (res[i].readObjNm == this.checkedRowDataList[i].readObjNm) {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
}
}
}
},
// row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
} else {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
this.gridName + this.parentPrgmId
].getCheckedRowsEvt();
this.dialog = false;
this.setPageData({ readObjList: this.checkedRowDataList });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.readObjList),
);
} else {
this.dialog = false;
this.setPageData({ readObj: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.readObj),
);
}
},
reset() {
for (
var i = 0;
i < this.$refs[this.gridName + this.parentPrgmId].getData().length;
i++
) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
this.$refs[this.gridName + this.parentPrgmId].getData()[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
},
search() {
this.getGridData();
},
typeEnterKey() {
this.getGridData();
},
dialogOpenCloseEvent(val) {
this.dialog = !val;
},
},
};
const OnInDataReadPop = {
modalGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
.tui-grid-tree-icon {
margin-left: -21px !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,379 @@
<template>
<v-row class="search-box">
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title>
<span v-if="label" class="custom-title-4">
검침개소
</span>
</v-card-title>
<v-card-actions>
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
위치정보 선택
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn>
<v-btn color="primary" dark>초기화</v-btn>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.readPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
default: '공장/설비',
},
textCols: {
type: Number,
require: false,
default: 7,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
},
components: {
Grid,
// Tree
},
data() {
return {
// label: "공정/설비",
labelPrepend: true,
myModalKey: 'readPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
treeGridInstance: null,
disabledRowKeyList: [],
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.readPlcNm);
}
}
} else {
return facData.readPlcNm;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { readPlcListTree },
});
},
created() {
this.init();
this.setPageData({
facInfo:
localStorage.getItem(this.parentPrgmId + 'CheckedRow') != null
? JSON.parse(localStorage.getItem(this.parentPrgmId + 'CheckedRow'))
: {},
});
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
// console.log("init 시작...");
this.activeRowData = {};
this.gridInit();
// this.getTreeData();
// this.lineCOption = chartOption;
},
// 공정/설비 트리 그리드 세팅
gridInit() {
// console.log("gridInit 시작...");
const treeGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
//useCascadingCheckbox: false
},
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
} else {
delete this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [
{
header: '측정 개소명',
name: 'readPlcNm',
width: 480,
align: 'left',
},
{
header: 'enableFg',
name: 'enableFg',
width: 480,
align: 'left',
hidden: true,
},
// , { header: "측정 개소", name: "name", align: "center"}
],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectReadPlcDataForEnrgLossAnalysis',
resKey: 'enrgLossAnalysisData',
sendParam: {
blocId: this.searchParam.blocId, //"BL0001",
readObjid: this.searchParam.energyCd,
},
});
console.log('getTreeData : ', res);
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC_ID',
value: res.map(item => ({
...item,
rowStat: null,
readPlcId: item.readPlcId,
readPlcIdNm: item.readPlcNm,
upReadPlcId:
item.upReadPlcId == null || item.upReadPlcId == ''
? ''
: item.upReadPlcId,
})),
});
this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
this.loadGrid = true;
const setTreeDataKeys = Object.keys(setTreeData);
// let nowTreeData = [];
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
for (var i = 0; i < setTreeDataKeys.length; i++) {
for (var j = 0; j < setTreeData[setTreeDataKeys[i]].length; j++) {
if (setTreeData[setTreeDataKeys[i]][j]['enableFg'] == 0) {
this.disabledRowKeyList.push(
setTreeData[setTreeDataKeys[i]][j]['rowKey'],
);
}
}
}
for (var i = 0; i < this.disabledRowKeyList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].disabledRow(
this.disabledRowKeyList[i],
);
}
// console.log('treeGrid' + this.parentPrgmId);
// console.log("확인", this.$refs['treeGrid' + this.parentPrgmId].getData());
// this.treeGridInstance = this.$refs['treeGrid' + this.parentPrgmId];
// nowTreeData = this.treeGridInstance.getData();
// rowDatas.forEach(item => {
// if (item.rowKey == rowKey) {
// this.gridInstance.invoke(
// "addRowClassName",
// item.rowKey,
// "row-selected"
// );
// } else {
// this.gridInstance.invoke(
// "removeRowClassName",
// item.rowKey,
// "row-selected"
// );
// }
// });
});
},
// 공정/설비 트리 row 클릭이벤트
async getRowData(data) {
// console.log("getRowData 시작...");
console.log('data', data);
this.activeRowData = data;
// if(data.enableFg == 1){
// this.activeRowData = data;
// }
},
setUpdate() {
// console.log("setUpdate 시작...");
if (this.disabledRowKeyList.includes(this.activeRowData['rowKey'])) {
alert('활성화된 항목을 선택해주세요');
return;
}
if (this.activeRowData) {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfo),
);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
// console.log("btnTreeExpand 시작...");
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
},
};
const readPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
eqpmYn: 1,
};
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,552 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<!-- <v-col v-if="label" cols="2"> -->
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon
x-small
:color="item.required ? '#fb8200' : 'primary'"
class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- <v-col :cols="label ? 9 : ''"> -->
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
outlined
:hide-details="true"
:disabled="item.disabled || false"
:required="item.required || false"
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title
class="v-card__title d-flex align-center justify-space-between"
>
<span class="custom-title-4">{{ item.label }}</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<!-- <v-card-actions> -->
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
{{ item.label }}
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<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>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn :ripple="false">초기화</v-btn> -->
<!-- <v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()">초기화</v-btn>
<v-btn v-if="!searchParam.isMulti" :ripple="false" @click="search()">검색</v-btn> -->
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-col>
</v-row>
<!-- <v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn> -->
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<!-- <v-btn color="primary" dark>초기화</v-btn> -->
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</div>
<!-- </v-card-actions> -->
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectReadObjListTree"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '검침개소',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '검침대상 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
},
},
components: {
Grid,
// Tree
},
data() {
return {
labelPrepend: true,
myModalKey: 'selectReadObjListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
searchWord: '', // 팝업내 검색
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
rowGridSelectData(state) {
if (!this.bindingData) {
return state.pageData[this.parentPrgmId].rowGridSelectData;
} else {
return state.pageData[this.parentPrgmId][this.bindingData]
.rowGridSelectData;
}
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue: {
get() {
// if(this.searchParam.rowGridSelectData){
// return this.searchParam.rowGridSelectData[this.item.valueNm];
// }
return this.myBindingData ? this.myBindingData[this.item.valueNm] : '';
},
set(value) {
// return value;
// return this.myBindingData({ [this.item.valueNm]: value });
//return this.setPageData({ [this.item.valueNm]: value });
return this.myBindingData({ [this.item.valueNm]: value });
},
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadObjListTree },
});
},
created() {
this.init();
// if(this.searchParam.isMulti == true){
// this.setPageData({
// facInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }else{
// this.setPageData({
// facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490;
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [
{
header: '검침개소명',
name: 'readPlcNm',
width: 370,
align: 'left',
},
{ header: '검침개소', name: 'name', align: 'center' },
],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectReadPlcBaseInfo',
resKey: 'readPlcBaseInfoData',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
// readObjId: this.searchParam.readObj, // "MTT00001" // 전력 코드 고정
readObjId: this.searchParam.searchReadObj, // "MTT00001" // 전력 코드 고정
useFg: '1',
readPlcNmLike: this.searchWord,
},
});
// console.log("treeData", res)
let myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
},
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(Utility.defaultGridOption(490), myOptionsTree),
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC_ID',
value: res.map(item => ({
...item,
rowStat: null,
readPlcId: item.readPlcId,
readPlcIdNm: item.readPlcId,
upReadPlcId:
item.upReadPlcId == null || item.upReadPlcId == ''
? ''
: item.upReadPlcId,
upReadPlcNm:
item.upReadPlcNm == null || item.upReadPlcNm == ''
? ''
: item.upReadPlcNm,
blocId: item.blocId,
useFg: item.useFg === '1' ? true : false,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT || [],
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.plcKindList.length > 0
? this.searchParam.plcKindList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
// 멀티 처리 필요사 시용...
// this.checkedRowDataList = this.$refs['treeGrid' + this.parentPrgmId].getCheckedRowsEvt();
// if(this.checkedRowDataList.length < 20){
// this.dialog = false;
// this.setPageData({facInfoList : this.checkedRowDataList});
// }else{
// alert("비교대상이 20개를 초과하였습니다.");
// }
} else {
this.dialog = false;
const dt = {
columnName: this.item.valueNm,
value: this.activeRowData.name,
};
var nm = this.item.valueNm;
if (this.item.valueNm2 !== undefined) {
const dt = {
columnName: this.item.valueNm2,
value: this.activeRowData[this.item.valueNm2],
};
this.$emit('gridEditingFinish', dt);
}
if (nm == 'objReadPlcId') {
this.myBindingData.objReadPlcId = this.activeRowData.name;
this.myBindingData.objReadPlcNm = this.activeRowData.readPlcNm;
const dt2 = {
columnName: 'objReadPlcNm',
value: this.activeRowData.readPlcNm,
};
this.$emit('gridEditingFinish', dt2);
} else if (nm == 'readPlcId') {
this.myBindingData.readPlcId = this.activeRowData.name;
this.myBindingData.readPlcNm = this.activeRowData.readPlcNm;
} else if (nm == 'upReadPlcId') {
this.myBindingData.upReadPlcId = this.activeRowData.name;
this.myBindingData.upReadPlcNm = this.activeRowData.readPlcNm;
} else {
this.myBindingData.upReadPlcId = this.activeRowData.name;
if (this.item.bindNm) {
this.myBindingData[this.item.bindNm] = this.activeRowData.readPlcNm;
var bindDt = {
columnName: this.item.bindNm,
value: this.activeRowData.readPlcNm,
};
this.$emit('gridEditingFinish', bindDt);
}
}
this.$emit('gridEditingFinish', dt);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll) {
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
} else {
this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
}
},
typeEnterKey() {
this.getTreeData();
},
},
};
const selectReadObjListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,419 @@
<template>
<span>
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon class="mr-1" v-bind="attrs" v-on="on" @click="dialog = true"
>mdi-tooltip-plus
</v-icon>
</template>
<span>검침개소</span>
</v-tooltip>
<v-dialog
ref="popModal"
v-model="dialog"
width="600"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%">
<v-card-title
class="v-card__title d-flex align-center justify-space-between"
>
<span class="custom-title-4">검침개소</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<v-row 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="7">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="3" class="text-right">
<v-btn v-if="searchParam.isMulti" :ripple="false" @click="reset()"
>초기화</v-btn
>
<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>
<v-btn :ripple="false" @click="reset()">초기화</v-btn>
</v-col>
</v-row>
</div>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectReadPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</span>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
widGetKey: {
type: String,
require: true,
},
widgetDataKey: {
type: String,
require: true,
},
isMulti: {
type: Boolean,
require: false,
default: null,
},
mntrFg: {
type: String,
require: false,
default: null,
},
},
components: {
Grid,
// Tree
},
data() {
return {
myModalKey: 'selectReadPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
maxSelectableNum: 12,
searchWord: '', // 팝업내 검색
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId][this.widGetKey][
this.widgetDataKey
];
},
}),
chkDialog() {
return this.dialog;
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {},
created() {
this.$store.state.pageData[this.parentPrgmId][this.widGetKey][
this.widgetDataKey
].modalData = { selectReadPlcListTree };
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
setWidgetModalGridData: 'setWidgetModalGridData',
setWidgetModalGridColumn: 'setWidgetModalGridColumn',
setWidgetModalGridOption: 'setWidgetModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490;
if (this.$store.state.activeMenuInfo.prgmId == '0') {
this.$store.state.activeMenuInfo.prgmId = this.$route.query.prgmId;
}
this.setWidgetModalGridColumn({
widgetId: this.widGetKey,
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [
{
header: '검침개소명',
name: 'readPlcNm',
width: 370,
align: 'left',
},
{ header: '검침개소', name: 'name', align: 'center' },
],
});
},
// 공정/설비 조회
async getTreeData() {
this.loadGrid = false;
const res = await this.postApiReturn({
apiKey: 'selectReadPlcBaseInfo',
resKey: 'readPlcBaseInfoData',
sendParam: {
blocId:
this.searchParam.blocMstrList.length > 0
? this.searchParam.blocMstrList[this.searchParam.blocId].blocId
: this.searchParam.blocId, //"BL0001",
readObjId: this.searchParam.searchReadObj, // "MTT00001" // 전력 코드 고정
mntrFg: this.mntrFg,
useFg: '1',
readPlcNmLike: this.searchWord,
},
});
let myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
},
};
if (this.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setWidgetModalGridOption({
widgetId: this.widGetKey,
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: Object.assign(Utility.defaultGridOption(490), myOptionsTree),
});
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC_ID',
value: res.map(item => ({
...item,
rowStat: null,
readPlcId: item.readPlcId,
readPlcIdNm: item.readPlcId,
upReadPlcId:
item.upReadPlcId == null || item.upReadPlcId == ''
? ''
: item.upReadPlcId,
upReadPlcNm:
item.upReadPlcNm == null || item.upReadPlcNm == ''
? ''
: item.upReadPlcNm,
blocId: item.blocId,
useFg: item.useFg === '1' ? true : false,
})),
});
this.setWidgetModalGridData({
widgetId: this.widGetKey,
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT || [],
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.isMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.plcKindList.length > 0
? this.searchParam.plcKindList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
getRowData(data) {
if (this.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
var checkedRowNumber = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt().length;
if (checkedRowNumber >= this.maxSelectableNum) {
alert(
'최대 ' + this.maxSelectableNum + '개까지 선택할 수 있습니다.',
);
return;
}
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
// this.$store.state.pageData[this.parentPrgmId][this.widGetKey][this.widgetDataKey].selectedReadPlcList = this.checkedRowDataList;
this.$store.state.pageData[this.parentPrgmId][this.widGetKey][
this.widgetDataKey
].plcKindList = this.checkedRowDataList;
} else {
this.$store.state.pageData[this.parentPrgmId][this.widGetKey][
this.widgetDataKey
].plcKindList = this.activeRowData;
}
this.$emit('chDialogView' + this.widGetKey);
this.dialog = false;
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll) {
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
} else {
this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
}
},
typeEnterKey() {
this.getTreeData();
},
reset() {
for (
var i = 0;
i < this.$refs['treeGrid' + this.parentPrgmId].getData().length;
i++
) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
this.$refs['treeGrid' + this.parentPrgmId].getData()[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
this.searchWord = '';
},
},
};
const selectReadPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.v-dialog {
overflow-y: hidden !important;
}
.tui-grid-table-container {
.tui-grid-table {
border-right-style: solid !important;
border-right-color: rgba(255, 255, 255, 0.1) !important;
}
}
.tui-grid-cell.tui-grid-cell-has-tree
.tui-grid-tree-extra-content
+ .tui-grid-cell-content:before {
content: none !important;
}
}
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,359 @@
<template>
<v-row class="search-box">
<v-col v-if="label" :cols="labelCols">
<!-- <label for="" class="search-box-label"> -->
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
:hide-details="true"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog v-model="dialog" scrollable width="540px">
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title>
<!-- <span v-if="!label" class="text-h5">
공정/설비
</span> -->
<span v-if="label" class="custom-title-4">
검침개소
</span>
</v-card-title>
<v-card-actions>
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
위치정보 선택
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<v-btn color="primary" dark>초기화</v-btn>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectFtnPlcListTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
default: '공장/설비',
},
textCols: {
type: Number,
require: false,
default: 7,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
},
components: {
Grid,
// Tree
},
data() {
return {
// label: "공정/설비",
labelPrepend: true,
myModalKey: 'selectFtnPlcListTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData',
treeExpandAll: true,
activeRowData: {},
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.readPlcNm);
}
}
} else {
return facData.readPlcNm;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
async chkDialog(val) {
if (val) {
await this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectFtnPlcListTree },
});
},
created() {
this.init();
// this.setPageData({
// facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
// console.log("init 시작...");
this.activeRowData = {};
this.gridInit();
// this.getTreeData();
// this.lineCOption = chartOption;
},
// 공정/설비 트리 그리드 세팅
gridInit() {
// console.log("gridInit 시작...");
const treeGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
treeColumnOptions: {
name: 'readPlcNm',
//useCascadingCheckbox: false
},
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
} else {
delete this.$store.state.pageData[this.parentPrgmId]['modalData'][
this.myModalKey
].treeGrid.option.rowHeaders;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: [
{
header: '측정 개소명',
name: 'readPlcNm',
width: 370,
align: 'left',
},
{ header: '측정 개소', name: 'name', align: 'center' },
],
});
},
// 공정/설비 조회
async getTreeData() {
// console.log("getTreeData 시작...");
this.loadGrid = false;
// console.log("getTreeData energyList : ", this.searchParam.energyList);
// console.log("getTreeData energyCd : ", this.searchParam.energyCd);
const res = await this.postApiReturn({
apiKey: 'selectReadPlcTree',
resKey: 'ftnPlcTreeData',
sendParam: {
blocId: this.searchParam.blocMstrList[this.searchParam.blocId].blocId, //"BL0001",
// mttCd: this.searchParam.energyList[this.searchParam.energyCd].cd
mttCd: this.searchParam.energyCd,
},
});
// console.log("getTreeData : ", res);
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'READ_PLC_ID',
value: res.map(item => ({
...item,
rowStat: null,
readPlcId: item.readPlcId,
readPlcIdNm: item.readPlcNm,
upReadPlcId:
item.upReadPlcId == null || item.upReadPlcId == ''
? ''
: item.upReadPlcId,
})),
});
this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
modalDataKey: this.modalDataKey,
value: setTreeData.ROOT,
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.isMulti) {
this.setGridCheckedRows();
}
});
},
// 공정/설비 트리 row 클릭이벤트
async getRowData(data) {
// console.log("getRowData 시작...");
this.activeRowData = data;
},
setUpdate() {
// console.log("setUpdate 시작...");
if (this.activeRowData) {
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
localStorage.setItem(
this.parentPrgmId + 'CheckedRow',
JSON.stringify(this.searchParam.facInfo),
);
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
// console.log("btnTreeExpand 시작...");
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
},
};
const selectFtnPlcListTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
eqpmYn: 1,
};
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,557 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-dialog
ref="popModal"
v-model="dialog"
width="1200px"
overlay-color="#000"
overlay-opacity="0.8"
scrollable
>
<v-card style="height: 100%" class="searchFilter">
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-row align="center" no-gutters>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox1"
:propsValue="selectValue01"
:itemList="selectValueList01"
:label="'설비종류'"
:labelCols="4"
:textCols="7"
@update:propsValue="selectValue01 = $event"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox2"
:propsValue="selectValue02"
:itemList="selectValueList02"
:label="'설비그룹'"
:labelCols="4"
:textCols="7"
@update:propsValue="selectValue02 = $event"
/>
</v-col>
<v-col :cols="3">
<component
:is="'SelectBox'"
ref="SelectBox3"
:propsValue="selectValue03"
:itemList="selectValueList03"
:label="'설비'"
:labelCols="4"
:textCols="7"
@update:propsValue="selectValue03 = $event"
/>
</v-col>
<v-col :cols="3">
<v-row align="center">
<v-col :cols="3" style="width: 100%">
<label for="" class="search-box-label">
<v-icon x-small :color="'primary'" class="mr-1"
>mdi-record-circle</v-icon
>
TAG명
</label>
</v-col>
<v-col :cols="8" style="width: 100%">
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
:hide-details="true"
v-model="searchWord"
@keyup.enter="search"
></v-text-field>
</v-col>
<v-col :cols="1" style="width: 100%" class="text-right">
<v-btn
icon
tile
:ripple="false"
@click="dialogOpenCloseEvent(dialog)"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col>
</v-row>
</v-col>
<!-- <v-col :cols="1" class="text-right">
<v-btn icon tile :ripple="false" @click="dialogOpenCloseEvent()">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col> -->
</v-row>
</div>
<v-divider></v-divider>
<!-- <div id="chartParent" ref="chartParent" style="height: 100px"> -->
<div :style="'height: 550px'" ref="modalGridDiv">
<!-- <div :style="'height: 50vh'" ref="modalGridDiv"> -->
<!-- <div :style="'height: calc(50%)'"> -->
<div
class="d-flex align-center justify-space-between pa-4"
style="height: 10%"
>
<v-card-title class="pa-0 custom-title-4">TAG 리스트</v-card-title>
</div>
<!-- <div id="chartParent" ref="chartParent" :style="'height: 80%'"> -->
<div ref="modalGridParent" class="h100 w100">
<component
:is="loadGrid && dialog ? 'Grid' : null"
:ref="gridName + parentPrgmId"
:gridName="gridName"
:dataPath="searchParam.tagTrndPopModalData.tagTrndPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate($event)"
/>
</div>
</div>
<v-divider></v-divider>
<v-card-actions class="pa-5 d-flex align-center justify-center">
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialogOpenCloseEvent(dialog)"
>취소</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
import selectCodeList from '@/components/common/select/selectCodeList';
import InputText from '~/components/common/input/InputText';
import Chart from '~/components/common/Chart';
import SelectBox from '@/components/common/select/SelectBox';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
default: '비교대상 최대(20개)',
},
label: {
type: String,
require: false,
default: '전력 계약 정보',
},
valueNm: {
type: String,
require: false,
default: '',
},
title: {
type: String,
require: false,
default: '전력 계약 목록',
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
item: {
type: Object,
require: true,
},
bindingData: {
type: String,
require: false,
},
},
components: {
Grid,
selectCodeList,
InputText,
Chart,
SelectBox,
// Tree
},
data() {
return {
labelPrepend: true,
gridName: 'grid_01',
myModalKey: 'tagTrndPop',
modalDataKey: 'tagTrndPopModalData',
// gridName: 'rowElecContGrid',
loadChart: false,
// selectedTargetMonth: 'all',
dialog: false,
selectValue01: null,
selectValueList01: [],
selectValue02: null,
selectValueList02: [],
selectValue03: null,
selectValueList03: [],
searchWord: '',
loadGrid: false,
initFlag: false,
selectedData: {},
totalSelectedTags: '',
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
myBindingData(state) {
//return state.pageData[this.parentPrgmId]["rowGridSelectData"];
if (!this.bindingData) {
return state.pageData[this.parentPrgmId]['rowGridSelectData'];
} else {
return state.pageData[this.parentPrgmId][this.bindingData][
'rowGridSelectData'
];
}
},
// chkTotalSelectedTags(state) {
// return state.pageData[this.parentPrgmId]['totalSelectedTags'];
// }
chkTotalSelectedTags(state) {
return this.searchParam['totalSelectedTags'];
},
}),
chkDialog() {
return this.dialog;
},
// get() {
// // if(this.searchParam.rowGridSelectData){
// // return this.searchParam.rowGridSelectData[this.item.valueNm];
// // }
// return this.myBindingData ? this.myBindingData[this.item.valueNm] : '';
// },
// set(value) {
// // return value;
// // return this.myBindingData({ [this.item.valueNm]: value });
// //return this.setPageData({ [this.item.valueNm]: value });
// return this.myBindingData({ [this.item.valueNm]: value });
// },
// },
},
watch: {
async chkDialog(val) {
if (val) {
// await this.setSelectValueList01();
// await this.setSelectValueList02();
// await this.setSelectValueList03();
this.search();
} else {
this.dialogOpenCloseEvent(val);
}
this.$nextTick();
this.dialog = val;
},
async selectValue01(value) {
await this.setSelectValueList02();
// if(this.selectValue02 == '0'){
// this.search();
// }else{
// this.setSelectValueList02();
// }
},
async selectValue02(value) {
await this.setSelectValueList03();
},
async selectValue03(value) {
if (this.initFlag) {
this.search();
}
},
chkTotalSelectedTags(value) {
this.totalSelectedTags = value;
},
},
beforeCreate() {
this.$store.commit('setPageData', {
tagTrndPopModalData: { tagTrndPop },
});
},
async created() {
await this.setSelectValueList01();
await this.setSelectValueList02();
await this.setSelectValueList03();
this.init();
// if(this.searchParam.isMulti == true){
// this.setPageData({
// facInfoList : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }else{
// this.setPageData({
// facInfo : localStorage.getItem(this.parentPrgmId + "CheckedRow") !=null ? JSON.parse(localStorage.getItem(this.parentPrgmId + "CheckedRow")) : {}
// });
// }
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
async init() {
// this.setChart();
this.gridInit();
await this.setGridData();
this.initFlag = true;
},
async setSelectValueList01() {
let res = await this.postApiReturn({
apiKey: 'selectEqpmKindCodeList',
resKey: 'eqpmKindCodeLists',
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.selectValue01 = this.selectValueList01[0].value;
} else {
this.selectValueList01 = [];
this.selectValue01 = null;
}
},
async setSelectValueList02() {
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 setSelectValueList03() {
var res = await this.postApiReturn({
apiKey: 'selectEqpmBaseInfo',
resKey: 'eqpmBaseInfoData',
sendParam: {
eqpmGrpId: this.selectValue02,
},
});
if (res.length > 0) {
this.selectValueList03 = await res.map(item => {
return {
text: item.eqpmNm,
value: item.eqpmId,
data: {
...item,
},
};
});
this.selectValueList03.unshift({
text: '전체',
value: 'all',
});
// 설비 그룹을 변경하여 설비를 다시 조회하였지만 이전에 조회한 값이 '전체'일 경우
// watch에서 값 변화를 인지 못하기 때문에 여기서 조회 시킨다.
if (this.selectValue03 == 'all' && this.initFlag) {
this.search();
}
this.selectValue03 = this.selectValueList03[0].value;
} else {
this.selectValueList03 = [];
this.selectValue03 = null;
}
},
// 계약 정보 조회
setUpdate() {
if (this.selectedData.tagId != undefined) {
let res = this.chkDuplicateTagId(this.selectedData.tagId);
if (res) {
alert('TAG가 중복 됩니다.');
} else {
if (this.selectedData.tagId != undefined) {
}
this.dialog = false;
for (var key in this.searchParam['rowGrid']['defaultRow']) {
let dt = {
columnName: key,
value: this.selectedData[key],
};
this.$emit('gridEditingFinish', dt);
this.setPageData({ rowGridSelectData: this.selectedData });
}
// this.$emit('gridEditingFinish', dt);
// 중복 선택 및
// let tempWord = '';
// tempWord += this.selectedData.tagId + '/*wq2a/';
// let totalSelectedTags = this.totalSelectedTags + tempWord;
// let tempTagList = totalSelectedTags.split('/*wq2a/');
// let tagList = tempTagList.filter(item => item != '');
let tagList = this.searchParam.tagList;
tagList.push(this.selectedData.tagId);
// console.log('temp!!!', temp);
// console.log('tagList!!!', tagList);
// this.setPageData({ totalSelectedTags : totalSelectedTags });
this.setPageData({ tagList: tagList });
}
} else {
alert('TAG를 선택해주세요.');
}
},
dialogOpenCloseEvent(val) {
this.searchWord = '';
if (val) {
this.dialog = !val;
} else {
this.$emit('closePopEvent');
}
},
async search() {
await this.setGridData();
},
gridInit() {
// const gridHeight = this.$refs.modalGridParent.offsetHeight - 60
const myOptions = {
columnOptions: {
resizable: true,
},
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(
// Utility.defaultGridOption(this.$refs.modalGridParent.offsetHeight - 60, myOptions),
Utility.defaultGridOption(460, myOptions),
myOptions,
),
});
const _this = this;
const myColumns = [
// { header: '가이드ID', name: 'gdIdxId', align: 'center', hidden: true},
{ header: '설비그룹', name: 'eqpmGrpNm', align: 'center', width: 130 },
{
header: '설비그룹 ID',
name: 'eqpmGrpId',
align: 'center',
hidden: true,
},
{ header: '설비ID', name: 'eqpmId', align: 'left', width: 130 },
{ header: '설비명', name: 'eqpmNm', align: 'left', width: 130 },
{ header: 'TAG ID', name: 'tagId', align: 'left', width: 470 },
{ header: 'TAG 명', name: 'tagNm', align: 'left' },
{ header: 'rowStat', name: 'rowStat', align: 'center', hidden: true },
];
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
this.loadGrid = true;
},
async setGridData() {
this.loadGrid = false;
let searchParam = {
eqpmGrpId: this.selectValue02,
eqpmId: this.selectValue03,
searchWord: this.searchWord,
};
let res = [];
res = await this.postApiReturn({
apiKey: 'selectTagAndEqpmList',
resKey: 'tagTrndDatas',
sendParam: searchParam,
});
let newRes = [];
if (this.searchParam['tagList'].length > 0) {
newRes = res.filter(item => {
return !this.searchParam['tagList'].includes(item.tagId);
});
res = newRes;
}
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.$nextTick(() => {
if (res.length > 0) {
try {
this.$refs[this.gridName + this.parentPrgmId].focus({
rowKey: 0,
setScroll: true,
});
} catch (error) {
// console.log('error', error);
}
}
// await this.setGridData();
});
this.loadGrid = true;
},
getRowData(data) {
this.selectedData = { ...data };
},
chkDuplicateTagId(data) {
let res = false;
let tempList = [];
// tempList = this.totalSelectedTags.split('/*wq2a/');
tempList = this.searchParam.tagList;
if (tempList.includes(data)) {
res = true;
}
return res;
},
},
};
let tagTrndPop = {
grid_01: {
data: [],
column: {},
option: {},
},
};
// 전력량 요금(원/kWh)
</script>

View File

@ -0,0 +1,202 @@
<template>
<v-banner>
<div
class="d-flex align-center justify-space-between"
style="cursor:pointer"
@click="dialog = !dialog"
>
<v-card-subtitle class="pa-0">미사용개소</v-card-subtitle>
<v-avatar
size="36"
:color="isDarkMode ? '#fb5a8b' : '#ff7b8b'"
min-width="72"
class="font-weight-bold text-color--white-0"
>{{ pointNoUse }}</v-avatar
>
</div>
<v-dialog v-model="dialog" scrollable width="600px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">미사용 개소 조회</span>
</v-card-title>
<v-card-actions>
<v-col>
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="rowGridParent" style="height: 300px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.unUsedData.selectUnusedReadPlc"
:parentPrgmId="parentPrgmId"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark>확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-banner>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid2';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
pointNoUse: {
type: Number,
require: true,
},
},
components: {
Grid,
},
data() {
return {
modalDataKey: 'unUsedData',
myModalKey: 'selectUnusedReadPlc',
gridName: 'unUsedGrid',
loadGrid: false,
searchWord: '',
dialog: false,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
isDarkMode: 'isDarkMode',
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
await this.getData();
} else {
// 닫힐 때
}
},
},
beforeCreate() {
if (this.$store.state.activeMenuInfo.prgmId == '0') {
this.$store.state.activeMenuInfo.prgmId = this.$route.query.prgmId;
}
this.$store.commit('setPageData', {
unUsedData: { selectUnusedReadPlc },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
// setTree: "modules/list/setTree"
}),
init() {
this.gridInit();
},
gridInit() {
const gridHeight = 290;
//const gridHeight = this.$refs.rowGridParent.offsetHeight - 30;
const myOptions = {};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
async getData() {
this.loadGrid = false;
let sendParams = {
readPlcNm: this.searchWord,
};
const res = await this.postApiReturn({
apiKey: 'selectUnusedReadPlc',
resKey: 'unusedData',
sendParam: sendParams,
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
// 검색
typeEnterKey() {
this.getData();
},
},
};
const selectUnusedReadPlc = {
unUsedGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
const myColumns = [
{ header: '사업장', name: 'blocNm', width: 100, align: 'center' },
{ header: '에너지원', name: 'readObjNm', width: 100, align: 'center' },
{ header: '검침개소명', name: 'readPlcNm', width: 240 },
{ header: '값', name: 'useVal', width: 100, align: 'right' },
];
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,269 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small color="primary" class="mr-1">mdi-record-circle</v-icon>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
outlined
:hide-details="true"
></v-text-field>
</v-col>
<v-dialog v-model="dialog" scrollable width="540px">
<v-card style="height: 100%">
<v-card-title>
<span class="custom-title-4">사용자 조회</span>
</v-card-title>
<v-card-actions>
<v-col>
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
v-model="searchWord"
@keyup.enter="typeEnterKey"
></v-text-field>
</v-col>
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="rowGridParent" style="height: 300px">
<component
:ref="gridName + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData.selectUserPop"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 7,
},
},
components: {
Grid,
},
data() {
return {
label: '사용자',
modalDataKey: 'modalData',
myModalKey: 'selectUserPop',
gridName: 'rowGrid',
loadGrid: false,
searchWord: '',
dialog: false,
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
return this.searchParam.selecUserList.length > 0
? this.searchParam.selecUserList.map(item => item.userNm)
: null;
},
},
watch: {
async chkDialog(val) {
if (val) {
// 열릴 때
await this.getData();
// console.log("chkDialog: ", val);
if (this.searchParam.selecUserList.length > 0) {
for (var i = 0; i < this.searchParam.selecUserList.length; i++) {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
this.searchParam.selecUserList[i],
this.$refs[this.gridName + this.parentPrgmId],
);
}
}
// this.$refs[this.gridName + this.parentPrgmId].setCheck(
// this.searchParam.selecUserListRowKeys
// );
} else {
// 닫힐 때
this.setPageData({
myUserList:
this.searchParam.selecUserList.length > 0
? this.searchParam.selecUserList.map(item => item.userNo)
: '',
});
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectUserPop },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
// setTree: "modules/list/setTree"
}),
init() {
this.gridInit();
},
gridInit() {
const gridHeight = 490; // this.$refs.rowGridParent.offsetHeight - 30;
const myOptions = {
rowHeaders: ['checkbox'],
};
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: Object.assign(Utility.defaultGridOption(gridHeight), myOptions),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: myColumns,
});
},
async getData() {
this.loadGrid = false;
let sendParams = {
userNm: this.searchWord,
userNo: '',
userLoginId: '',
deptId: '',
};
const res = await this.postApiReturn({
apiKey: 'selectUserPop',
resKey: 'userData',
sendParam: sendParams,
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
},
// 공정/설비 트리 row 클릭이벤트
getRowData(data) {
//this.activeRowData = data;
if (data._attributes.checked) {
this.$refs[this.gridName + this.parentPrgmId].uncheckEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
} else {
this.$refs[this.gridName + this.parentPrgmId].checkEvt(
data,
this.$refs[this.gridName + this.parentPrgmId],
);
}
},
setUpdate() {
// console.log("이게뭐야", this.$refs[this.gridName + this.parentPrgmId])
this.dialog = false;
this.setPageData({
selecUserList: this.$refs[
this.gridName + this.parentPrgmId
].getCheckedRowsEvt(),
});
// this.setPageData({
// selecUserListRowKeys: this.$refs[
// this.gridName + this.parentPrgmId
// ].getCheckedRowKeys()
// });
},
// 검색
typeEnterKey() {
this.getData();
},
},
};
const selectUserPop = {
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
eqpmYn: 1,
};
const myColumns = [
{ header: '사용자NO', name: 'userNo', align: 'center' },
{ header: '사용자ID', name: 'userLoginId' },
{ header: '사용자명', name: 'userNm' },
{ header: '부서명', name: 'deptNm' },
];
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>

View File

@ -0,0 +1,580 @@
<template>
<div>
<!-- <v-btn :ripple="false" @click="dialog = !dialog">경고창</v-btn> -->
<v-dialog
v-model="dialog"
width="900"
overlay-color="#000"
overlay-opacity="0.8"
>
<v-card>
<v-toolbar
:color="isDarkMode ? '#2d3355' : '#3f4d7d'"
class="py-4 pr-3 pl-5"
height="auto"
>
<v-toolbar-title>{{ label }}</v-toolbar-title>
<v-btn
icon
tile
small
:ripple="false"
@click="dialog = !dialog"
:style="{ backgroundColor: isDarkMode ? '#2d3355' : '#3f4d7d' }"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar>
<v-card-title>
VOC 내용
</v-card-title>
<!-- <template v-for="(item, index) in detailList"> -->
<template>
<div style="padding : 10px 40px">
<div v-for="n in detailList.length" :key="n">
<v-row v-if="n % 2 == 1" align="center" no-gutters>
<!-- {{detailList[n-1]}} {{detailList[n-1].type}} -->
<!-- v-model="detailList[n-1].valueNm" -->
<v-col
:cols="detailList[n - 1].cols"
:class="detailList[n - 1].class"
>
<component
:ref="detailList[n - 1].valueNm"
:is="detailList[n - 1].type"
:item="detailList[n - 1]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getValue="getValue"
/>
</v-col>
<v-col
v-if="detailList[n] != undefined"
:cols="detailList[n].cols"
:class="detailList[n].class"
>
<component
:ref="detailList[n].valueNm"
:is="detailList[n].type"
:item="detailList[n]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
@getValue="getValue"
/>
</v-col>
</v-row>
</div>
<div>
<v-row v-show="!componentDisableFlag" align="center" no-gutters>
<v-col :cols="2">
<label
for=""
class="search-box-label"
style="padding-left:10px"
>
<v-icon x-small :color="'primary'" class="mr-1"
>mdi-record-circle</v-icon
>
첨부파일
</label>
</v-col>
<v-col :cols="8">
<v-file-input
multiple
background-color="#47535c"
show-size
v-model="fileData"
hide-details="true"
>
</v-file-input>
</v-col>
</v-row>
<v-row v-show="state === 'update' || state === 'read'">
<v-col :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label class="search-box-label" style="padding-left:10px">
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
파일 목록
</label>
</v-col>
<v-col :cols="10">
<v-row
v-for="fileData in fileList"
:key="fileData.apndFileId"
>
<a @click.prevent="downloadFile(fileData)">
<v-col :cols="12">
<div class="search-box-label">
{{
fileData.apndFileNm + '.' + fileData.apndFileExt
}}
</div>
</v-col>
</a>
<v-icon
v-show="state === 'update'"
class="pl-5"
@click="addFileToDeleteFileList(fileData)"
>
mdi-close
</v-icon>
</v-row>
</v-col>
</v-row>
</v-col>
</v-row>
</div>
</div>
<div v-if="answerDialog == true">
<v-card-title style="padding : 16px 24px 10px ">
답변 내용
</v-card-title>
<div style="padding : 10px 40px">
<div v-for="n in answerList.length" :key="n">
<v-row v-if="n % 2 == 1" align="center" no-gutters>
<v-col
:cols="answerList[n - 1].cols"
:class="answerList[n - 1].class"
>
<component
:is="answerList[n - 1].type"
:item="answerList[n - 1]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
/>
</v-col>
<v-col
v-if="answerList[n] != undefined"
:cols="answerList[n].cols"
:class="answerList[n].class"
>
<component
:is="answerList[n].type"
:item="answerList[n]"
:parentPrgmId="parentPrgmId"
:bindingData="bindingData"
/>
</v-col>
</v-row>
</div>
<div>
<!-- <v-row v-show="!componentDisableFlag" 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="8">
<v-file-input
multiple
background-color="#47535c"
show-size
v-model="fileData"
hide-details="true"
>
</v-file-input>
</v-col>
</v-row> -->
<v-row>
<v-col :cols="12">
<v-row class="search-box" align="center" no-gutters>
<v-col :cols="2">
<label
class="search-box-label"
style="padding-left:10px"
>
<v-icon x-small color="primary" class="mr-1"
>mdi-record-circle</v-icon
>
파일 목록
</label>
</v-col>
<v-col :cols="10">
<v-row
v-for="replyFileData in replyFileList"
:key="replyFileData.apndFileId"
>
<a @click.prevent="downloadFile(replyFileData)">
<v-col :cols="12">
<div class="search-box-label">
{{
replyFileData.apndFileNm +
'.' +
replyFileData.apndFileExt
}}
</div>
</v-col>
</a>
<!-- <v-icon v-show="state === 'update'" class="pl-5" @click="addFileToDeleteFileList(replyFileData)">
mdi-close
</v-icon> -->
</v-row>
</v-col>
</v-row>
</v-col>
</v-row>
</div>
</div>
</div>
</template>
<v-card-actions class="justify-end">
<v-btn :ripple="false" @click="clickOk()">등록</v-btn>
<v-btn :ripple="false" @click="clickCancle()">취소</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import InputText from '~/components/common/form/InputText';
import InputNumber from '~/components/common/form/InputNumber';
import TextArea from '~/components/common/form/TextArea';
import SelectBox from '~/components/common/form/SelectBox';
import SelectBoxes from '~/components/common/form/SelectBoxes';
import CheckBox from '~/components/common/form/CheckBox';
import ChangeUserPswdPopPage from '~/components/common/modal/ChangeUserPswdPopPage';
import EnrgReadPlacePop2Page from '~/components/common/modal/EnrgReadPlacePop2Page';
import EnrgCostCenterPop from '~/components/common/modal/EnrgCostCenterPop';
import ReadPlcPop from '~/components/common/modal/ReadPlcPop';
import EvtObjPop from '~/components/common/modal/EvtObjPop';
import FtnPlcFormPop from '~/components/common/modal/FtnPlcMultiPop2';
import Label from '~/components/common/form/Label';
import mixinGlobal from '@/mixin/global.js';
export default {
mixins: [mixinGlobal],
props: {
parentPrgmId: {
type: String,
require: true,
},
detailList: {
type: Array,
require: false,
default: () => {
return [];
},
},
answerList: {
type: Array,
require: false,
default: () => {
return [];
},
},
label: {
type: String,
require: true,
},
bindingData: {
type: String,
require: false,
},
gridName: {
type: String,
require: false,
},
},
components: {
InputText,
InputNumber,
TextArea,
SelectBox,
SelectBoxes,
CheckBox,
ChangeUserPswdPopPage,
EnrgReadPlacePop2Page,
EnrgCostCenterPop,
ReadPlcPop,
EvtObjPop,
Label,
FtnPlcFormPop,
},
data() {
return {
fileList: null,
fileData: null,
dialog: false,
answerDialog: true,
param: {},
state: '',
deleteFileList: [],
replyFileList: null,
replyFileData: null,
chkcomNm: '',
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
isDarkMode: 'isDarkMode',
}),
chkDialog() {
return this.dialog;
},
chkAnswerDialog() {
return this.answerDialog;
},
componentDisableFlag() {
if (this.state === 'read') {
return true;
} else {
return false;
}
},
},
watch: {
async chkDialog(val) {
if (val) {
this.openDialog();
}
},
},
methods: {
...mapMutations({
setPageData: 'setPageData',
}),
...mapActions({
postUpdateApi: 'modules/list/postUpdateApi',
getDomain: 'modules/list/getDomain',
}),
async clickOk() {
this.dialog = !this.dialog;
switch (this.state) {
case 'insert':
await this.insertDetail();
break;
case 'update':
await this.updateDetail();
break;
}
// apndFileUuid = this.postUpdateApi({
// apiKey: "saveFile",
// resKey: "apndFileUuid",
// sendParam: formData
// })
},
async getFileList(apndFileUuid) {
var fileList = [];
if (apndFileUuid === null || apndFileUuid === '') {
return fileList;
}
fileList = await this.postUpdateApi({
apiKey: 'selectApndFile',
sendParam: {
params: {
apndFileUuid: apndFileUuid,
},
datas: {},
},
});
return fileList.data.dataset.apndFile;
},
async openDialog() {
this.fildList = null;
this.fileData = null;
this.deleteFileList = [];
this.replyFileData = null;
this.replyFileList = null;
switch (this.state) {
case 'insert':
break;
case 'update':
this.fileList = await this.getFileList(
this.searchParam[this.gridName]['rowGridSelectData'].apndFileUuid,
);
this.replyFileList = await this.getFileList(
this.searchParam[this.gridName]['rowGridSelectData']
.answApndFileUuid,
);
break;
case 'read':
this.fileList = await this.getFileList(
this.searchParam[this.gridName]['rowGridSelectData'].apndFileUuid,
);
this.replyFileList = await this.getFileList(
this.searchParam[this.gridName]['rowGridSelectData']
.answApndFileUuid,
);
break;
}
},
async insertDetail() {
var fileList = this.fileData;
var apndFileUuid = null;
var formData = new FormData();
if (fileList !== null) {
for (var i = 0; i < fileList.length; i++) {
formData.append('file', fileList[i]);
}
formData.append('rcptNo', '');
apndFileUuid = await this.postUpdateApi({
apiKey: 'saveFileVocRqst',
resKey: 'apndFileUuid',
sendParam: formData,
});
}
apndFileUuid =
apndFileUuid === null ? '' : apndFileUuid.data.dataset.apndFileUuid;
this.param = {
comId: this.userInfo.comId,
userNm: this.$refs['userNm'][0].InputValue,
comNm: this.$refs['comNm'][0].InputValue,
rowStat: 'I',
apndFileUuid: apndFileUuid,
...this.param,
};
await this.postUpdateApi({
apiKey: 'saveVocRqst',
sendParam: {
datas: {
vocRqstData: [this.param],
},
params: {},
},
});
this.param = {};
this.setPageData({
isFind: true,
});
},
async updateDetail() {
var fileList = this.fileData;
var apndFileUuid = null;
var formData = new FormData();
if (fileList !== null) {
for (var i = 0; i < fileList.length; i++) {
formData.append('file', fileList[i]);
}
formData.append(
'rcptNo',
this.searchParam[this.gridName].rowGridSelectData.rcptNo,
);
apndFileUuid = await this.postUpdateApi({
apiKey: 'saveFileVocRqst',
resKey: 'apndFileUuid',
sendParam: formData,
});
}
var deleteFileParam = {
apndFile: this.deleteFileList,
};
if (this.deleteFileList.length > 0) {
await this.postApiReturn({
apiKey: 'deleteApndFile',
sendParam: deleteFileParam,
});
}
apndFileUuid =
apndFileUuid === null ? '' : apndFileUuid.data.dataset.apndFileUuid;
this.param = {
...this.param,
comId: this.userInfo.comId,
userNm: this.$refs['userNm'][0].InputValue,
comNm: this.$refs['comNm'][0].InputValue,
rowStat: 'U',
apndFileUuid: apndFileUuid,
rcptNo: this.searchParam[this.gridName].rowGridSelectData.rcptNo,
};
await this.postUpdateApi({
apiKey: 'saveVocRqst',
sendParam: {
datas: {
vocRqstData: [this.param],
},
params: {},
},
});
this.param = {};
this.setPageData({
isFind: true,
});
},
clickCancle() {
this.dialog = !this.dialog;
},
getValue(data) {
this.param[data.key] = data.value;
},
async downloadFile(item) {
var menuId = 'MNU1102';
var urlPrefix = await this.getDomain();
// console.log("getDomain", this.getDomain());
var downLoadUrl =
urlPrefix +
'comm/base/ApndFileCtr/selectDownloadApndFile?$menuId=' +
menuId +
'&apndFileId=' +
item.apndFileId;
await this.$axios
.get(downLoadUrl, { responseType: 'blob' })
.then(response => {
const blob = new Blob([response.data]);
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = item.apndFileNm + '.' + item.apndFileExt;
link.click();
URL.revokeObjectURL(link.href);
})
.catch(console.error);
},
addFileToDeleteFileList(item) {
this.deleteFileList.push({ apndFileId: item.apndFileId });
var index = null;
if (typeof this.fileList === 'object' && this.fileList.length - 1 >= 0) {
for (var i = 0; i < this.fileList.length; i++) {
if (item.apndFileId === this.fileList[i].apndFileId) {
index = i;
break;
}
}
this.fileList.splice(index, 1);
}
},
},
};
</script>
<style scoped lang="scss">
::v-deep {
.v-toolbar__content {
justify-content: space-between;
padding: 0;
.v-btn {
margin-right: 0 !important;
}
}
.v-card__actions {
padding-bottom: 30px !important;
}
}
</style>

View File

@ -0,0 +1,346 @@
<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="label" :cols="labelCols">
<!-- <label for="" class="search-box-label"> -->
<label for="" class="search-box-label">
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
:hide-details="true"
@click="dialog = !dialog"
outlined
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog v-model="dialog" scrollable width="540px">
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card>
<v-card-title class="d-flex align-center justify-space-between">
<span class="custom-title-4" v-if="label">검침개소</span>
<v-btn icon tile :ripple="false" @click="dialog = !dialog">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<div class="pa-5">
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
outlined
hide-details
></v-text-field>
</div>
<v-divider></v-divider>
<div>
<div ref="gridParent" style="height: calc(100% - 139px)">
<component
:ref="'rowGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridName"
:dataPath="searchParam.modalData2.selectOutsideWeather"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
@dblClick="setUpdate()"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</div>
<v-divider></v-divider>
<v-card-actions class="justify-center">
<v-btn @click="setUpdate()">확인</v-btn>
<v-btn @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
default: '공장/설비',
},
textCols: {
type: Number,
require: false,
default: 7,
},
labelCols: {
type: Number,
require: false,
default: 2,
},
},
components: {
Grid,
// Tree
},
data() {
return {
// label: "공정/설비",
labelPrepend: true,
myModalKey: 'selectOutsideWeather',
gridName: 'rowGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
modalDataKey: 'modalData2',
treeExpandAll: true,
activeRowData: {},
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
var temp = [];
if (this.searchParam.readPlcList.length > 0) {
for (const item of this.searchParam.readPlcList) {
temp.push(item.readPlcNm);
}
}
return temp.join();
},
},
watch: {
chkDialog(val) {
if (val) this.getModalGridData();
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData2: { selectOutsideWeather },
});
},
created() {
this.init();
this.setPageData({
readPlcList:
localStorage.getItem(this.parentPrgmId + 'WeatherCheckedRow') != null
? JSON.parse(
localStorage.getItem(this.parentPrgmId + 'WeatherCheckedRow'),
)
: {},
});
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
}),
init() {
this.activeRowData = {};
this.gridInit();
// this.getTreeData();
// this.lineCOption = chartOption;
},
// 공정/설비 트리 그리드 세팅
gridInit() {
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: [
{
header: '검침개소',
name: 'readPlc',
align: 'center',
},
{
header: '검침개소명',
name: 'readPlcNm',
align: 'center',
},
{
header: '단위',
name: 'unit',
hidden: true,
},
],
});
},
async getModalGridData() {
this.loadGrid = false;
const myOptions = {
rowHeaders: ['checkbox'],
rowHeight: 'auto',
};
const rowGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(rowGridHeight),
myOptions,
),
});
const res = await this.postApiReturn({
apiKey: 'selectOutsideWeather',
resKey: 'outsideWeatherData',
sendParam: {
blocId: this.userInfo.blocId,
},
});
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridName,
modalDataKey: this.modalDataKey,
value: res,
});
this.loadGrid = true;
this.$nextTick(() => {
if (this.searchParam.weatherIsMulti) {
this.setGridCheckedRows();
}
});
},
setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.readPlcList.length > 0
? this.searchParam.readPlcList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['rowGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['rowGrid' + this.parentPrgmId],
);
}
}
},
getRowData(data) {
if (this.searchParam.weatherIsMulti) {
if (data._attributes.checked) {
this.$refs['rowGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['rowGrid' + this.parentPrgmId],
);
} else {
this.$refs['rowGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['rowGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.weatherIsMulti) {
this.checkedRowDataList = this.$refs[
'rowGrid' + this.parentPrgmId
].getCheckedRowsEvt();
this.dialog = false;
this.setPageData({ readPlcList: this.checkedRowDataList });
localStorage.setItem(
this.parentPrgmId + 'WeatherCheckedRow',
JSON.stringify(this.searchParam.readPlcList),
);
}
},
},
};
const selectOutsideWeather = {
rowGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
eqpmYn: 1,
};
</script>
<style scoped lang="scss">
@each $theme in dark, light {
.v-application.#{$theme}-mode {
.v-dialog {
.v-card {
&__title {
color: map-deep-get($color, 'white', '0');
@if $theme == dark {
background-color: #2d3355;
.v-btn {
background-color: #2d3355;
}
} @else {
background-color: #3f4d7d;
.v-btn {
background-color: #3f4d7d;
}
}
}
&__actions {
padding: 30px 0;
}
}
}
}
}
</style>

View File

@ -0,0 +1,333 @@
<template>
<v-row class="search-box">
<v-col v-if="label" cols="2">
<label for="" class="search-box-label">
{{ label }}
</label>
</v-col>
<v-col :cols="label ? 9 : ''">
<!-- :value="textfield" -->
<v-text-field
readonly
v-model="selectValue"
append-icon="mdi-magnify"
class="v-input__custom"
@click="dialog = !dialog"
></v-text-field>
</v-col>
<!-- <v-row justify="center"> -->
<v-dialog ref="popModal" v-model="dialog" scrollable width="540px">
<!-- <template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">공정/설비</v-btn>
</template> -->
<v-card style="height: 100%">
<v-card-title>
<span class="search-box-label">공정/설비</span>
</v-card-title>
<v-card-actions>
<!-- <v-text-field label="위치정보 선택"></v-text-field> -->
<v-col v-if="label" cols="3">
<label for="" class="search-box-label">
위치정보 선택
</label>
</v-col>
<v-col :cols="label ? 6 : ''">
<!-- :value="textfield" -->
<v-text-field
append-icon="mdi-magnify"
class="v-input__custom"
></v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="btnTreeExpand()">{{
treeExpand
}}</v-btn>
<!-- <v-btn color="primary" dark>펼치기</v-btn> -->
<!-- <v-btn color="primary" dark>접기</v-btn> -->
<v-btn color="primary" dark>초기화</v-btn>
<!-- as-is 봐도 초기화가 하는 기능을 모르겠음.. -->
</v-card-actions>
<v-divider></v-divider>
<v-card-text>
<div ref="treeGridParent" style="height: 500px">
<component
:ref="'treeGrid' + parentPrgmId"
:is="loadGrid && dialog ? 'Grid' : null"
:gridName="gridNameTree"
:dataPath="searchParam.modalData.selectReadPlcTree"
:parentPrgmId="parentPrgmId"
@getRowsData="getRowData"
/>
</div>
<!-- <component
:is="ftnPlcListTreeData.length > 0 ? 'Tree' : null"
:tree-data="ftnPlcListTreeData"
/> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" dark @click="setUpdate()">확인</v-btn>
<v-btn color="primary" dark @click="dialog = false">닫기</v-btn>
<!-- <v-btn
color="green darken-1"
text
@click="dialog = false"
>
Disagree
</v-btn>
<v-btn
color="green darken-1"
text
@click="dialog = false"
>
Agree
</v-btn> -->
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Utility from '~/plugins/utility';
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
},
components: {
Grid,
// Tree
},
data() {
return {
label: '비교대상 최대(20개)',
labelPrepend: true,
myModalKey: 'selectReadPlcTree',
gridNameTree: 'treeGrid',
loadGrid: false,
dialog: false,
treeData: [], // 리턴받은 원본 트리 데이터
treeExpandAll: true,
activeRowData: {},
checkedRowDataList: [],
// isUpdate: false
// ftnPlcListTreeData: []
};
},
computed: {
...mapState({
// searchParam: state => state.pageData,
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
chkDialog() {
// 모달 열기/닫기 값
return this.dialog;
},
selectValue() {
// 선택된 공장/설비 값
const temp = [];
const facData = this.searchParam.isMulti
? this.searchParam.facInfoList
: this.searchParam.facInfo;
if (Array.isArray(facData)) {
if (facData.length > 0) {
for (const item of facData) {
temp.push(item.readPlcNm);
}
}
} else {
return facData.path;
}
return temp.join();
},
treeExpand() {
return this.treeExpandAll ? '접기' : '펼치기';
},
},
watch: {
chkDialog(val) {
if (val) {
this.getTreeData();
}
},
},
beforeCreate() {
this.$store.commit('setPageData', {
modalData: { selectReadPlcTree },
});
// console.log("2.vue::beforeCreate");
},
created() {
this.init();
},
methods: {
...mapMutations({
setPageData: 'setPageData',
setModalGridData: 'setModalGridData',
setModalGridColumn: 'setModalGridColumn',
setModalGridOption: 'setModalGridOption',
}),
...mapActions({
postApiReturn: 'modules/list/postApiReturn',
setTree: 'modules/list/setTree',
}),
init() {
this.activeRowData = {};
this.gridInit();
},
// 공정/설비 트리 그리드 세팅
gridInit() {
const treeGridHeight = 490; // this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
treeColumnOptions: {
name: 'name',
},
};
if (this.searchParam.isMulti) {
myOptionsTree['rowHeaders'] = [{ type: 'checkbox' }];
myOptionsTree['rowHeight'] = 'auto'; // checkbox와 그리드 높이 같게
myOptionsTree['treeColumnOptions']['useCascadingCheckbox'] = false;
}
this.setModalGridOption({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setModalGridColumn({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
value: [{ header: '위치정보', name: 'name' }],
});
},
// 공정/설비 조회
async getTreeData() {
const res = await this.postApiReturn({
apiKey: 'selectFtnPlcListTree',
resKey: 'ftnPlcTreeDatas',
sendParam: {
blocCd: this.searchParam.blocCd, //"BL0001",
mttCd: this.searchParam.energyList[this.searchParam.energyCd].cd, // "MTT00001" // 전력 코드 고정
},
});
// this.treeData = res;
// const ROOT = res[0].plcCd;
const setTreeData = await this.setTree({
gridKey: this.gridNameTree,
treeKey: 'PLC_CD',
value: res.map(item => ({
...item,
plcCdNm: item.plcNm,
})),
});
// this.treeData = setTreeData;
this.setModalGridData({
modalKey: this.myModalKey,
gridKey: this.gridNameTree,
value: setTreeData.ROOT,
});
this.loadGrid = true;
this.$nextTick(() => {
this.setGridCheckedRows();
});
},
async setGridCheckedRows() {
this.checkedRowDataList =
this.searchParam.facInfoList.length > 0
? this.searchParam.facInfoList
: [];
if (this.checkedRowDataList.length > 0) {
for (var i = 0; i < this.checkedRowDataList.length; i++) {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
this.checkedRowDataList[i],
this.$refs['treeGrid' + this.parentPrgmId],
);
}
}
},
// 공정/설비 트리 row 클릭이벤트
async getRowData(data) {
//this.activeRowData = data;
if (this.searchParam.isMulti) {
if (data._attributes.checked) {
this.$refs['treeGrid' + this.parentPrgmId].uncheckEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
} else {
this.$refs['treeGrid' + this.parentPrgmId].checkEvt(
data,
this.$refs['treeGrid' + this.parentPrgmId],
);
}
} else {
this.activeRowData = data;
}
},
setUpdate() {
if (this.searchParam.isMulti) {
this.checkedRowDataList = this.$refs[
'treeGrid' + this.parentPrgmId
].getCheckedRowsEvt();
if (this.checkedRowDataList.length < 20) {
this.dialog = false;
this.setPageData({ facInfoList: this.checkedRowDataList });
} else {
alert('비교대상이 20개를 초과하였습니다.');
}
} else {
// console.log(this.activeRowData);
this.dialog = false;
this.setPageData({ facInfo: this.activeRowData });
}
},
// 공정/설비 트리 접기/펼치기
btnTreeExpand() {
this.treeExpandAll = !this.treeExpandAll;
if (this.treeExpandAll)
this.$refs['treeGrid' + this.parentPrgmId].expandAll();
else this.$refs['treeGrid' + this.parentPrgmId].collapseAll();
},
},
};
const selectReadPlcTree = {
treeGrid: {
data: [],
column: [], // myColumns,
option: {}, // myOptions
},
};
</script>
<style scoped>
.v-input {
font-size: 12px;
}
.v-label {
font-size: 10px;
}
</style>