
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="side-bar">
<div class="logo">
<router-link :to="{path : this.$filters.ctxPath('/adm/main.page')}">ADMINISTRATOR</router-link>
</div>
<nav>
<ul class="main-menu">
<li v-for="(menu, idx) in menuList" :key="idx" class="menu-item"
@click.stop="toggleSubMenu(menu)">
<span :class="{ 'main-active': isActive(menu.menuId), 'open': menu.isOpen,'has-children': menu.childList && menu.childList.length > 0 }">
{{ menu.menuNm }}
</span>
<ul v-if="menu.isOpen" class="sub-menu">
<li v-for="(subMenu, subIdx) in menu.childList" :key="subIdx"
:class="{
'has-third-depth': subMenu.childList && subMenu.childList.length > 0,
'only-second-depth': !(subMenu.childList && subMenu.childList.length > 0),
'sub-active': isActive(subMenu.menuId),
}"
@click.stop="toggleSubMenu(subMenu)">
<span>{{ subMenu.menuNm }}</span>
<ul v-if="subMenu.isOpen && subMenu.childList.length > 0" class="ssub-menu">
<li v-for="(third, thirdIdx) in subMenu.childList" :key="thirdIdx"
:class="{ 'ss-active': isActive(third.menuId) }"
@click.stop="menuClick(third)">
<span>{{ third.menuNm }}</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
</template> -->
<template>
<div class="side-bar">
<div class="logo">
<router-link :to="{ path: $filters.ctxPath('/adm/main.page') }">ADMINISTRATOR</router-link>
</div>
<nav>
<ul class="main-menu">
<MenuItem
v-for="(menu, idx) in menuList"
:key="idx"
:menu="menu"
:is-active="isActive"
:on-click="menuClick"
@toggle="toggleSubMenu"
/>
</ul>
</nav>
</div>
</template>
<script>
import store from "../pages/AppStore";
import queryParams from '../../resources/js/queryParams';
import { defaultSearchParams } from '../../resources/js/defaultSearchParams';
import cntnStatsSave from "../../resources/js/cntnStatsSave";
import { findBySysMenu } from '../../resources/api/menu';
import MenuItem from "../component/menu/MenuItem.vue";
export default {
mixins: [queryParams, cntnStatsSave],
data() {
return {
// checkMenu: null,
currentPath: this.$route.path,
resetSearch: { ...defaultSearchParams },
menuList: [],
activeMenus: [] // 현재 선택된 메뉴 및 부모 메뉴 ID 저장
};
},
components:{
MenuItem
},
created() {
this.findAll();
// this.menuCheck();
},
methods: {
// 새로고침 시 메뉴 체크
menuCheck() {
let menu = store.state.menu;
if (menu) {
// this.checkMenu = menu.menuId;
this.activeMenus = this.getParentMenus(menu);
for (const mu of this.activeMenus) {
if (mu.childList && mu.childList.length > 0) {
mu.isOpen = true; // 하위 메뉴가 있을 시 메뉴 펼치기
}
}
}
},
async findAll() {
try {
const params = {
roles: store.state.roles.map(auth => auth.authority),
menuType: store.state.userType
};
const res = await findBySysMenu(params);
if (res.status === 200) {
this.menuList = this.formatMenuList(res.data.data.menuList);
// // `isOpen` 속성을 추가하여 초기 상태 설정
// this.menuList = res.data.data.menuList.map(menu => ({
// ...menu,
// isOpen: false, // 1뎁스 닫힘
// childList: menu.childList.map(sub => ({
// ...sub,
// isOpen: false, // 2뎁스도 닫힘
// routerUrl: this.$filters.ctxPath(sub.routerUrl)
// }))
// }));
// 전체 메뉴 트리 store에 저장
this.$store.commit('setMenuList', this.menuList);
}
} catch (error) {
alert('에러가 발생했습니다.\n관리자에게 문의하세요.');
}
},
async menuClick(menu) {
this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화
this.$store.commit('setMenu', menu);
await this.cntnStatsSave(menu.menuId);
// 선택된 메뉴 및 부모 메뉴 추적
this.activeMenus = this.getParentMenus(menu);
if (menu.linkType === "0") {
// 현재창
this.$router.push({
path: menu.routerUrl,
});
} else if (menu.linkType === "1") {
// 새창
window.open(menu.routerUrl, "_blank");
}
},
toggleSubMenu(menu) {
console.log("toggleSubMenu",menu)
if (menu.childList && menu.childList.length > 0) {
// 부모 메뉴 클릭 시 펼치기만 함
menu.isOpen = !menu.isOpen;
console.log(menu.isOpen)
} else {
if(menu.routerUrl === "") {
// 하위메뉴가 없는 상위메뉴일 시 알림 출력
alert("하위 메뉴가 존재하지 않습니다.");
return;
}
// 2뎁스 또는 3뎁스 선택 시 menuClick 실행
this.menuClick(menu);
}
},
isActive(menuId) {
// return this.activeMenus.includes(menuId);
return this.activeMenus.some(menu => menu.menuId === menuId);
},
getParentMenus(menu) {
let parents = [];
while (menu) {
// parents.push(menu.menuId);
parents.push(menu);
menu = this.findParent(menu);
}
return parents;
},
findParent(menu) {
for (const parent of this.menuList) {
if (parent.childList?.some(child => child.menuId === menu.menuId)) {
// if (parent.childList && parent.childList.includes(menu)) {
return parent;
}
for (const child of parent.childList || []) {
if (child.childList?.some(grand => grand.menuId === menu.menuId)) {
// if (child.childList && child.childList.includes(menu)) {
return child;
}
}
}
return null;
},
// 메뉴 리스트를 가공
formatMenuList(menuList) {
// `isOpen` 속성을 추가하여 초기 상태 설정
return menuList.map(menu => {
const formatted = {
...menu,
isOpen: false,
routerUrl: menu.routerUrl !== "" ? this.$filters.ctxPath(menu.routerUrl) : menu.routerUrl, // 최상위 메뉴가 아닐 때만 context path 가공
};
// 자식이 있으면 재귀 호출
if (menu.childList && menu.childList.length > 0) {
formatted.childList = this.formatMenuList(menu.childList);
}
return formatted;
});
},
},
watch: {
// 나중에 네비게이션 가드에서 form 받을 수 있으면 form adm/main으로 갈때 sotre.state값0로 바꿔주기
$route(to) {
this.currentPath = to.path;
},
"$store.state.mbrNm"(newVal) {
this.mbrNm = newVal;
},
'$store.state.menuList': {
immediate: true,
handler(val) {
if (val && val.length > 0) {
this.menuCheck();
}
}
}
}
};
</script>