Files
sk_fems_ui/pages/comm/auth/MenuMngPage.vue
2025-07-31 14:54:02 +09:00

567 lines
12 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="l-layout">
<common-page-title />
<v-row ref="searchFilter" class="mt-2">
<v-col :cols="12">
<v-card class="searchFilter">
<v-row align="end" no-gutters>
<v-col :cols="3">
<component :is="'selectCodeList'" :parentPrgmId="myPrgmId" :label="'시스템구분'"
dataKey="sysDivCd" :sendParam="{ commGrpCd: 'CO_SYSDIV', useFg: '1' }" :addAll="true"
:customClass="'select-large'" />
</v-col>
<v-col :cols="3">
<component :is="'selectCodeList'" :parentPrgmId="myPrgmId" :label="'사용여부'"
:dataKey="'useFg'" :sendParam="{ commGrpCd: 'CO_USEFG', useFg: '1' }" :addAll="true"
:customClass="'select-large'" />
</v-col>
<v-col :cols="6" class="text-right">
<BtnSearch @click="search" size="large" />
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-row ref="contents" class="mt-4">
<v-col :cols="6" class="h100 pr-2">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0">메뉴 리스트</v-card-title>
<div>
<Buttons :parentPrgmId="myPrgmId" :bindingData="gridName" :btnActionsFnc="btnActions" />
</div>
</div>
<div class="h100 px-4" style="height:calc(100% - 70px)">
<div ref="treeGridParent" class="w100 h100">
<component :ref="gridName + myPrgmId" :is="loadTree ? 'Grid' : null" :gridName="gridName"
:parentPrgmId="myPrgmId" @getRowsData="getRowData" />
</div>
</div>
</v-card>
</v-col>
<v-col :cols="6" class="h100 pl-3">
<v-card class="pb-5">
<div class="d-flex align-center justify-space-between pa-4">
<v-card-title class="pa-0">메뉴 상세</v-card-title>
</div>
<div class="px-4 py-2" style="height:calc(100% - 76px)">
<component :is="'Form'" :parentPrgmId="myPrgmId" :detailList="detailList"
@gridEditingFinish="gridEditingFinish" />
</div>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
import mixinGlobal from '@/mixin/global.js';
import Utility from '~/plugins/utility';
import { mapState, mapMutations, mapActions } from 'vuex';
import Grid from '~/components/common/Grid';
import Buttons from '~/components/common/button/Buttons';
import BtnSearch from '~/components/common/button/BtnSearch';
import selectCodeList from '@/components/common/select/selectCodeList';
import Form from '~/components/common/form/Form';
let myTitle;
let myPrgmId;
export default {
mixins: [mixinGlobal],
async asyncData(context) {
const myState = context.store.state;
myPrgmId = context.route.query.prgmId;
await context.store.commit('setActiveMenuInfo', myState.menuData[myPrgmId]);
myTitle = await myState.activeMenuInfo.menuNm;
},
meta: {
title: () => {
return myTitle;
},
prgmId: myPrgmId,
closable: true,
},
components: {
Grid,
Buttons,
selectCodeList,
Form,
BtnSearch
},
data() {
return {
myPrgmId: myPrgmId,
gridName: 'treeGrid',
loadTree: false,
detailList: myDetail,
addRowFg: false,
};
},
computed: {
...mapState({
pageData: state => state.pageData[myPrgmId],
}),
chkIsFind() {
// 조회 플래그
return this.pageData.isFind;
},
chkSysDivCd() {
// 사용여부 선택 감지
return this.pageData.sysDivCd;
},
chkUseFg() {
// 사용여부 선택 감지
return this.pageData.useFg;
},
ChkRowGridSelectData() {
return this.pageData.rowGridSelectData;
},
},
watch: {
chkIsFind(val) {
if (val) this.search();
},
chkSysDivCd() {
this.setPageData({ isFind: true });
},
chkUseFg() {
this.setPageData({ isFind: true });
},
},
async beforeCreate() {
myPrgmId = this.$route.query.prgmId;
await this.$store.dispatch('chkOpenTabList', {
key: 'create',
prgmId: myPrgmId,
defaultData: defaultData,
});
},
mounted() {
this.init();
},
methods: {
init() {
this.gridInit();
},
search() {
this.loadTree = false;
this.addRowFg = false;
this.getTreeData();
},
gridInit() {
const treeGridHeight = this.$refs.treeGridParent.offsetHeight - 30;
const myOptionsTree = {
columnOptions: {
resizable: true,
},
treeColumnOptions: {
name: 'menuNm',
},
scrollX: false,
header: {
height: 37,
},
rowHeight: 37,
};
this.setGridOption({
gridKey: this.gridName,
// value: myOptionsTree
value: Object.assign(
Utility.defaultGridOption(treeGridHeight),
myOptionsTree,
),
});
this.setGridColumn({
gridKey: this.gridName,
value: [
{
header: '',
name: '',
align: 'center',
width: 20,
formatter: (props) => {
return `<label class="custom-radio">
<span class="radio-mark"></span>
</label>`;
}
},
{ header: '메뉴명', name: 'menuNm' },
{ header: 'prgmId ', name: 'prgmId', hidden: true },
{ header: 'sysDivCd ', name: 'sysDivCd', hidden: true },
],
});
this.getTreeData();
},
// 메뉴리스트 조회
async getTreeData() {
let res = await this.postApiReturn({
apiKey: 'selectMenu',
resKey: 'menuData',
sendParam: {
sysDivCd: this.pageData.sysDivCd,
useFg: this.pageData.useFg,
comId: this.comId,
},
});
res = res.map(item => {
const newItem = {
...item,
menuIdNm: item.menuNm,
menuId: item.menuId,
parentId: item.parentId,
useFg: item.useFg === '1' ? true : false,
rowStat: null,
upMenuId:
item.upMenuId && item.upMenuId != '0'
? item.upMenuId
: item.upMenuId == '0'
? '0'
: 'ROOT',
};
return newItem;
});
const setTreeData = await this.setTree({
treeKey: 'MENU_ID',
value: res,
});
this.loadTree = true;
// console.log("setTreeData = ", setTreeData);
await this.setGridData({
gridKey: this.gridName,
value: setTreeData.ROOT || [],
});
// 첫번째 row 선택상태
this.$refs[this.gridName + this.myPrgmId].focus({
//rowKey: 0,
rowKey:
this.pageData.rowGridSelectKey == '' ||
this.pageData.rowGridSelectKey == null
? 0
: this.pageData.rowGridSelectKey ==
this.$refs[this.gridName + this.myPrgmId].getData().length - 1
? this.pageData.rowGridSelectKey
: 0,
columnName: 'menuNm',
setScroll: true,
});
this.setPageData({ isFind: false });
},
async getRowData(data) {
this.setPageData({
rowGridSelectKey: data.rowKey,
rowGridSelectData: data,
});
},
async btnActions(action) {
let dataArr = [];
switch (action) {
case 'add':
if (!this.addRowFg) {
let upMenuId = this.ChkRowGridSelectData.menuId;
if (upMenuId == 'ROOT' || upMenuId == '00') upMenuId = '0';
this.$refs[this.gridName + this.myPrgmId].addTreeRow({
upMenuId: upMenuId,
});
this.addRowFg = true;
} else {
alert('한번에 한가지 메뉴만 추가 가능합니다.');
}
break;
case 'remove':
this.$refs[this.gridName + this.myPrgmId].removeTreeRow();
if (this.addRowFg) this.addRowFg = false;
break;
case 'save':
dataArr = this.$refs[this.gridName + this.myPrgmId].save();
var validCheck = true;
if (dataArr.length > 0) {
dataArr.forEach(item => {
if (
item.upMenuId == '' ||
item.menuNm == '' ||
item.sortSeq == null
) {
validCheck = false;
alert('필수 입력값을 입력해주세요.');
}
});
if (validCheck) {
const sendParam = {
datas: {
dsMenu: dataArr.map(item => ({
...item,
useFg: item.useFg == true ? '1' : '0',
comId: this.comId,
})),
},
params: {},
};
await this.postUpdateApi({
apiKey: 'saveMenu',
sendParam: sendParam,
});
this.loadTree = false;
this.$nextTick(() => {
this.setPageData({ isFind: true });
});
this.loadTree = true;
}
} else {
alert('저장할 내용이 없습니다.');
}
break;
default:
break;
}
},
gridEditingFinish(data) {
this.$refs[this.gridName + this.myPrgmId].editingFinish(data);
},
},
};
const defaultData = {
isFind: false, // true 경우 조회
/* 검색옵션 */
sysDivCd: '',
sysDivCdList: [],
useFg: '',
useFgList: [],
// 선택된 그룹코드 상세 데이터
rowGridSelectKey: 0,
rowGridSelectData: null,
/* data 세팅 */
treeGrid: {
data: [],
column: [],
option: {},
defaultRow: {
upMenuId: '',
menuId: '',
menuNm: '',
prgmId: '',
sysDivCd: '',
useFg: '1',
sortSeq: '',
regUserNo: '',
regDttm: '',
procUserNo: '',
procDttm: '',
rowStat: '',
},
buttonAuth: {
add: true,
remove: true,
save: true,
excel: false,
},
},
};
const sampleData = [
{
"menuNm": "root",
"prgmId": "PRGM001",
"sysDivCd": "SYS01",
"_children": [
{
"menuNm": "서울 본사 - 1층",
"prgmId": "PRGM001-1",
"sysDivCd": "SYS01"
},
{
"menuNm": "서울 본사 - 2층",
"prgmId": "PRGM001-2",
"sysDivCd": "SYS01"
}
]
},
{
"menuNm": "부산 지사",
"prgmId": "PRGM002",
"sysDivCd": "SYS02",
"_children": [
{
"menuNm": "부산 지사 - A동",
"prgmId": "PRGM002-A",
"sysDivCd": "SYS02",
"_children": [
{
"menuNm": "부산 지사 - A동 1층",
"prgmId": "PRGM002-A1",
"sysDivCd": "SYS02"
}
]
}
]
},
{
"menuNm": "대전 창고",
"prgmId": "PRGM003",
"sysDivCd": "SYS03"
}
]
;
const myOptions = {
columnOptions: {
resizable: true,
},
treeColumnOptions: {
name: 'menuNm',       // Showing tree table
useIcon: false,      // Not using icon
indentWidth: 10,
},
}
const myDetail = [
{
type: 'InputText',
label: '메뉴코드',
valueNm: 'menuId',
readonly: true,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
iconShow: true,
required: false,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '상위메뉴코드',
valueNm: 'upMenuId',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pl-4',
iconShow: true,
required: true,
},
{
type: 'InputText',
label: '메뉴명',
valueNm: 'menuNm',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
iconShow: true,
required: true,
},
{
type: 'InputText',
label: '프로그램ID',
valueNm: 'prgmId',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pl-4',
iconShow: true,
},
{
type: 'SelectBox',
label: '시스템구분',
valueNm: 'sysDivCd',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
list: 'sysDivCdList',
itemText: 'commCdNm',
itemValue: 'commCd',
iconShow: true,
},
{
type: 'CheckBox',
label: '사용여부',
valueNm: 'useFg',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pl-4',
iconShow: true,
value: { '1': true, '0': false },
required: true,
},
{
type: 'InputText',
label: '정렬순서',
valueNm: 'sortSeq',
disabled: false,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
iconShow: true,
required: true,
},
{
type: 'InputText',
label: '등록자No',
valueNm: 'regUserNo',
disabled: true,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pl-4',
iconShow: true,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '등록일시',
valueNm: 'regDttm',
disabled: true,
cols: 6,
clabelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
iconShow: true,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정자No',
valueNm: 'procUserNo',
disabled: true,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pl-4',
iconShow: true,
placeholder: '시스템 자동입력',
},
{
type: 'InputText',
label: '수정일시',
valueNm: 'procDttm',
disabled: true,
cols: 6,
labelCols: 12,
textCols: 12,
class: 'py-3 pr-4',
iconShow: true,
placeholder: '시스템 자동입력',
},
];
</script>