
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="content-zone sch-full">
<div class="content">
<div class="setting-box">
<div class="node-zone">
<div class="tree">
<draggable tag="ul" class="tree-node" :list="menuList" :group="{ name: 'menu' }" item-key="id"
handle=".handle" ghost-class="ghost">
<template #item="{ element, index }">
<Hierachy :tasks="element" :icon="iconPath" :selectedNode="selectedMenuId" :isLastNode="element.childList && index === element.childList.length - 1"
@changeSelected="fnViewDetail" />
</template>
</draggable>
</div>
<div class="btn-zone" v-if="pageAuth.mdfcnAuthrt == 'Y'">
<button class="btn top sm secondary" @click="fnTopAdd">
TOP+
</button>
<button class="btn top sm secondary" @click="fnSubAdd">
SUB+
</button>
<button class="btn save sm" @click="fnListUpdate">
메뉴 저장
</button>
</div>
</div>
<div class="setting-zone">
<div class="form-box">
<div class="form-box-title">
<p>메뉴 정보</p>
</div>
<div class="form-content">
<div>
<label class="form-title">상위 메뉴명 </label>
<input type="text" class="form-control sm" v-model="viewMenu.upMenuNm" disabled />
</div>
<div>
<label class="form-title">메뉴명</label>
<input type="text" class="form-control sm" ref="menuNm" v-model="viewMenu.menuNm"
:disabled="!editMode" />
</div>
<div class="grid-column">
<label class="form-title">메뉴 설명</label>
<textarea v-model="viewMenu.menuExpln" :disabled="!editMode" class="form-control lg area"></textarea>
</div>
<div class="grid-column">
<label class="form-title">메뉴 타입</label>
<div class="input-group">
<select class="form-select sm" ref="menuType" v-model="viewMenu.menuType" :disabled="!editMode">
<option value="">선택</option>
<option v-for="(code, index) in codeList" :key="index" :value="code.cd">
{{ code.cdNm }}
</option>
</select>
<template v-if="viewMenu.menuType == 'bbs' ||
viewMenu.menuType == 'conts'
">
<select class="form-select sm" ref="menuTypeCtgry" v-model="viewMenu.menuTypeCtgry"
:disabled="!editMode">
<option value="">선택</option>
<option v-for="(ctgry, index) of ctgryList" :key="index" :value="ctgry.id">
{{ ctgry.name }}
</option>
</select>
</template>
<template v-if="viewMenu.menuType == 'link'">
<input type="text" class="form-control sm" ref="linkUrl" v-model="viewMenu.linkUrl"
:disabled="!editMode" :style="{ width: inputWidth + 'px' }"/>
</template>
</div>
</div>
<div>
<label class="form-title">메뉴 사용자</label>
<div class="check-area">
<div class="form-check">
<input type="radio" name="menuUser" id="menuUserAdm" v-model="viewMenu.menuUser"
value="A" :disabled="!editMode" />
<label for="menuUserAdm">관리자용</label>
</div>
<div class="form-check">
<input type="radio" name="menuUser" id="menuUserUser" v-model="viewMenu.menuUser"
value="U" :disabled="!editMode" />
<label for="menuUserUser">사용자용</label>
</div>
</div>
</div>
<div>
<label class="form-title">링크유형 </label>
<div class="check-area">
<div class="form-check">
<input type="radio" name="linkType" id="linkTypeY" v-model="viewMenu.linkType"
value="0" :disabled="!editMode" />
<label for="linkTypeY">현재창</label>
</div>
<div class="form-check">
<input type="radio" name="linkType" id="linkTypeN" v-model="viewMenu.linkType"
value="1" :disabled="!editMode" />
<label for="linkTypeN">새창</label>
</div>
</div>
</div>
<div class="gd-12 pr0">
<label for="" class="form-title">만족도 조사 사용 여부 </label>
<div class="check-area">
<div class="form-check">
<input type="radio" name="dgstfnExmnUseYn" id="dgstfnExmnUseY"
v-model="viewMenu.dgstfnExmnUseYn" value="Y" :disabled="!editMode" />
<label for="dgstfnExmnUseY">사용</label>
</div>
<div class="form-check">
<input type="radio" name="dgstfnExmnUseYn" id="dgstfnExmnUseN"
v-model="viewMenu.dgstfnExmnUseYn" value="N" :disabled="!editMode" />
<label for="dgstfnExmnUseN">미사용</label>
</div>
</div>
</div>
<div>
<label class="form-title">메뉴 노출 여부</label>
<div class="check-area">
<div class="form-check">
<input type="radio" name="menuExpsrYn" id="menuExpsrY"
v-model="viewMenu.menuExpsrYn" value="Y" :disabled="!editMode" />
<label for="menuExpsrY">사용</label>
</div>
<div class="form-check">
<input type="radio" name="menuExpsrYn" id="menuExpsrN"
v-model="viewMenu.menuExpsrYn" value="N" :disabled="!editMode" />
<label for="menuExpsrN">미사용</label>
</div>
</div>
</div>
<div>
<label class="form-title">등록자</label>
<input type="text" class="form-control sm" v-model="viewMenu.rgtrNm" disabled />
</div>
<div>
<label class="form-title">등록일</label>
<input type="text" class="form-control sm" v-model="viewMenu.regDt" disabled />
</div>
<div>
<label class="form-title">수정자</label>
<input type="text" class="form-control sm" v-model="viewMenu.mdfrNm" disabled />
</div>
<div>
<label class="form-title">수정일</label>
<input type="text" class="form-control sm" v-model="viewMenu.mdfcnDt" disabled />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="btn-wrap">
<button class="btn sm primary" @click="fnInsert" :disabled="!editMode" v-if="
selectedMenuId != null &&
editMode == true &&
pageAuth.mdfcnAuthrt == 'Y'
">
수정
</button>
<button class="btn sm primary" @click="fnInsert" :disabled="!editMode"
v-else-if="editMode == true && pageAuth.regAuthrt == 'Y'">
등록
</button>
<button :class="{
'btn sm red': true,
// 'red-border-btn': editMode,
}" :disabled="isFormDisabled" @click="fnDelete" v-if="pageAuth.delAuthrt == 'Y'">
삭제
</button>
</div>
</template>
<script>
import draggable from "vuedraggable";
import Hierachy from "../../../../component/hierachy/HierachyDraggable.vue";
import { mdiFormatListBulleted } from "@mdi/js";
// Api
import {
menuFindAll,
menuSave,
menuFindByMenu,
menuUpdate,
menuDelete,
updateListProc,
} from "../../../../../resources/api/menu";
import { findAllByExpsr } from "../../../../../resources/api/contsType";
import { findAllByMenuMng } from "../../../../../resources/api/bbsMng";
export default {
data() {
return {
// 페이지 권한 객체
pageAuth: JSON.parse(localStorage.getItem("vuex")).pageAuth,
// 글 작성 모드
// false - 없음 (기본)
// true - 등록/수정
editMode: false,
iconPath: mdiFormatListBulleted,
menuList: [], // 메뉴 목록
newMenu: {}, // 신규 메뉴
viewMenu: {
menuType: "",
menuTypeCtgry: "",
}, // 사용자에게 보여질 메뉴 목록
selectedMenuId: null, // 선택된 메뉴
codeList: [], // 메뉴 타입 목록
ctgryList: [], // 메뉴 타입 항목
bbsList: [], // 메뉴 타입 게시판 목록
contsTypeList: [], // 메뉴 타입 콘텐츠 목록
inputWidth: 0,
};
},
created() {
this.fnViewList();
this.axiosBbsList(); // 메뉴 타입 게시판 목록 조회
this.axiosContsTypeList(); // 메뉴 타입 콘텐츠 목록 조회
// pageId 확인
if (this.pageId != null) {
this.editMode = "true";
}
},
methods: {
// 등록
fnInsert() {
// 유효성검사
if (this.valiadtion() == false) {
return;
}
let data = this.viewMenu;
if (data["menuType"] == "") {
data.menuType = "";
data.menuTypeCtgry = "";
data.linkUrl = "";
} else if (data["menuType"] == "bbs" || data["menuType"] == "conts") {
data["linkUrl"] == null;
} else if (data["menuType"] == "link") {
data["menuTypeCtgry"] == null;
}
if (this.selectedMenuId == null) {
this.axiosInsert(data);
} else {
this.axiosUpdate(data);
}
},
// 조회(목록)
fnViewList() {
this.axiosViewList();
},
// 조회(상세)
fnViewDetail(menuId) {
this.selectedMenuId = menuId;
const data = {
menuId: menuId,
};
this.axiosViewDetail(data);
},
// 삭제
fnDelete() {
if (Object.keys(this.viewMenu).length === 0) {
alert("삭제 대상을 선택해주세요.");
return false;
}
const isDelete = confirm(
"메뉴를 삭제하시겠습니까?\n삭제 시 하위부서 항목도 제거됩니다."
);
if (isDelete) {
const data = { menuId: this.selectedMenuId };
this.axiosDelete(data);
}
},
// 최상위 신규 객체 생성
fnTopAdd() {
this.editMode = true;
this.viewMenu = JSON.parse(JSON.stringify(this.newMenu));
this.selectedMenuId = this.viewMenu.deptId;
},
// 하위 신규 객체 생성
fnSubAdd() {
if (this.viewMenu.menuId == null) {
alert("상위 메뉴를 지정해주세요.");
return;
}
const upMenuId = this.viewMenu.menuId;
const upMenuNm = this.viewMenu.menuNm;
this.viewMenu = JSON.parse(JSON.stringify(this.newMenu));
this.viewMenu.upMenuId = upMenuId;
this.viewMenu.upMenuNm = upMenuNm;
this.selectedMenuId = null;
},
// 메뉴관리 유효성 검사
valiadtion() {
// 메뉴명 입력 여부
if (this.viewMenu["menuNm"] == null || this.viewMenu["menuNm"] == "") {
alert("메뉴명을 입력하세요.");
this.$refs.menuNm.focus();
return false;
}
// 메뉴 타입 입력 여부
if (
this.viewMenu["menuType"] != null &&
this.viewMenu["menuType"] != ""
) {
if (
this.viewMenu["menuType"] == "bbs" ||
this.viewMenu["menuType"] == "conts"
) {
if (
this.viewMenu["menuTypeCtgry"] == null ||
this.viewMenu["menuTypeCtgry"] == ""
) {
alert("메뉴 타입 항목을 선택하세요.");
this.$refs.menuTypeCtgry.focus();
return false;
}
} else if (this.viewMenu["menuType"] == "link") {
if (
this.viewMenu["linkUrl"] == null ||
this.viewMenu["linkUrl"] == ""
) {
alert("링크 주소를 입력하세요.");
this.$refs.linkUrl.focus();
return false;
}
}
}
// 링크 유형
if (
this.viewMenu["linkType"] == null ||
this.viewMenu["linkType"] == ""
) {
alert("링크 유형을 선택하세요.");
return false;
}
// 만족도 조사 사용여부
if (
this.viewMenu["dgstfnExmnUseYn"] == null ||
this.viewMenu["dgstfnExmnUseYn"] == ""
) {
alert("만족도 조사 사용여부를 선택하세요.");
return false;
}
// 메뉴 노출 여부
if (
this.viewMenu["menuExpsrYn"] == null ||
this.viewMenu["menuExpsrYn"] == ""
) {
alert("메뉴 노출 여부를 선택하세요.");
return false;
}
},
// axios: 등록
async axiosInsert(data) {
try {
const res = await menuSave(data);
if (res.status == 200) {
alert(res.data.message);
this.fnViewList(); // 목록 새로고침
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 조회(목록)
async axiosViewList() {
try {
const res = await menuFindAll();
if (res.status == 200) {
this.menuList = res.data.data.hierachyList; // 메뉴 목록
this.codeList = res.data.data.codeList; // 메뉴 타입 목록
this.newMenu = res.data.data.newMenu; // 메뉴 빈 객체
this.newMenu.useYn = "Y";
this.newMenu.linkType = "0"; // 링크 유형
this.newMenu.dgstfnExmnUseYn = "Y"; // 만족도 조사 사용 여부
this.newMenu.menuExpsrYn = "Y"; // 메뉴 노출 여부
this.newMenu.menuType = "";
this.newMenu.menuTypeCtgry = "";
this.newMenu.linkUrl = "";
this.newMenu.menuUser = "A"
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 조회(상세)
async axiosViewDetail(data) {
if (this.selectedMenuId == null) return;
try {
const res = await menuFindByMenu(data);
if (res.status == 200) {
this.editMode = true;
this.viewMenu = res.data.data; // 메뉴 정보
this.selectedMenuId = this.viewMenu.menuId;
if (this.viewMenu.menuType == null) {
this.viewMenu.menuType = "";
}
if (this.viewMenu.menuType == "bbs") {
this.ctgryList = this.bbsList;
} else if (this.viewMenu.menuType == "conts") {
this.ctgryList = this.contsTypeList;
}
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 수정
async axiosUpdate(data) {
try {
const res = await menuUpdate(data);
if (res.status == 200) {
alert(res.data.message);
this.fnViewList(); // 목록 새로고침
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 삭제
async axiosDelete(data) {
try {
const res = await menuDelete(data);
if (res.status == 200) {
this.fnViewList(); // 목록 새로고침
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 조회(목록) - 게시판
async axiosBbsList() {
// 실행
try {
const res = await findAllByMenuMng();
if (res.status == 200) {
let items = [];
for (let item of res.data.data) {
items.push({
id: item["bbsMngId"],
name: item["bbsNm"],
});
}
this.bbsList = items;
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// axios: 조회(목록) - 콘텐츠
async axiosContsTypeList() {
// 데이터 삽입
const data = { sysPvsnYn: "1" };
// 실행
try {
const res = await findAllByExpsr(data);
if (res.status == 200) {
let items = [];
for (let item of res.data.data) {
items.push({
id: item["contsId"],
name: item["contsKornNm"],
});
}
this.contsTypeList = items;
}
} catch (error) {
const errorData = error.response.data;
if (errorData.message != null && errorData.message != "") {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
}
},
// 드래그앤드롭
// axios: 목록 수정
async fnListUpdate() {
try {
const res = await updateListProc(this.menuList);
alert(res.data.message);
if (res.status == 200) {
this.fnViewList(); // 목록 새로고침
}
} catch (error) {
alert(error.res.data.message);
}
},
updateInputWidth() {
this.$nextTick(() => {
const containerEl = this.$el; // 부모 컨테이너 전체 너비
const selectEl = this.$refs.menuType; // select 요소
if (containerEl && selectEl) {
const containerWidth = containerEl.clientWidth; // 부모 요소의 전체 너비 (100%)
const selectWidth = selectEl.offsetWidth; // select 요소의 실제 너비
const gap = 10; // 선택적으로 간격 조정
this.inputWidth = containerWidth - selectWidth - gap; // 전체에서 select 너비를 뺀 값 적용
}
});
},
},
watch: {
"viewMenu.menuType"() {
const menuType = this.viewMenu["menuType"];
// 초기화
this.ctgryList = [];
this.viewMenu["menuTypeCtgry"] == "";
this.viewMenu["linkUrl"] == null;
// 데이터 삽입
if (menuType == "bbs") {
this.ctgryList = this.bbsList;
} else if (menuType == "conts") {
this.ctgryList = this.contsTypeList;
}
},
},
computed: {},
components: {
draggable: draggable,
Hierachy: Hierachy,
},
mounted() {
this.updateInputWidth();
window.addEventListener("resize", this.updateInputWidth);
},
beforeUnmount() {
window.removeEventListener("resize", this.updateInputWidth);
},
};
</script>
<!-- <style scoped>
.tree-node {
height: 100%;
}
.ghost {
height: 15px;
color: transparent;
border: 1px dashed var(--blue);
}
.ghost * {
display: none;
}
</style> -->