166 lines
4.0 KiB
Vue
166 lines
4.0 KiB
Vue
<template>
|
|
<div class="layout">
|
|
<AppHeader v-model="activeMenu" @update:model-value="onMenuClick" />
|
|
<nav
|
|
v-if="subMenus && subMenus.length && showSubmenuBar"
|
|
class="submenu-bar"
|
|
@click.stop
|
|
>
|
|
<NuxtLink
|
|
v-for="sub in subMenus"
|
|
:key="sub.key"
|
|
:to="sub.to"
|
|
class="submenu-btn"
|
|
:class="{ active: $route.path === sub.to }"
|
|
>
|
|
{{ sub.label }}
|
|
</NuxtLink>
|
|
</nav>
|
|
<main class="main">
|
|
<slot />
|
|
</main>
|
|
<footer class="footer">
|
|
<p>© 2024 Nuxt.js App</p>
|
|
</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import AppHeader from "../components/AppHeader.vue";
|
|
import { ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
|
|
import { useRouter, useRoute } from "vue-router";
|
|
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const activeMenu = ref("home");
|
|
const showSubmenuBar = ref(false);
|
|
|
|
// HOME 메뉴가 선택되었을 때 최상단 경로로 이동
|
|
watch(activeMenu, newValue => {
|
|
if (newValue === "home") {
|
|
router.push("/");
|
|
}
|
|
});
|
|
|
|
watch(route, () => {
|
|
showSubmenuBar.value = false;
|
|
});
|
|
|
|
const subMenus = computed(() => {
|
|
if (activeMenu.value === "test") {
|
|
return [
|
|
{ key: "test", label: "테스트", to: "/test/test01" },
|
|
{ key: "igv", label: "ivg", to: "/test/test02" },
|
|
{ key: "igv2", label: "ivg2", to: "/test/igv2" },
|
|
{ key: "pathway", label: "pathway", to: "/test/pathway" },
|
|
{ key: "pathway2", label: "pathway2", to: "/test/pathway2" },
|
|
{ key: "pathway3", label: "pathway3", to: "/test/pathway3" },
|
|
{ key: "pathway4", label: "pathway4", to: "/cultureGraph/pathway4" },
|
|
{ key: "pathwayjson", label: "pathwayjson", to: "/test/pathwayjson" },
|
|
{ key: "cultureGraph", label: "배양그래프", to: "/test/culture-graph" },
|
|
{
|
|
key: "cultureGraphMulti",
|
|
label: "배양그래프 멀티",
|
|
to: "/test/culture-graph-multi",
|
|
},
|
|
{
|
|
key: "cultureGraphTab",
|
|
label: "배양그래프 탭",
|
|
to: "/test/culture-graph-tab",
|
|
},
|
|
];
|
|
} else if (activeMenu.value === "admin") {
|
|
return [
|
|
{ key: "logs", label: "접속기록", to: "/admin/logs" },
|
|
{ key: "codes", label: "공통코드", to: "/admin/codes" },
|
|
{ key: "programs", label: "프로그램", to: "/admin/programs" },
|
|
];
|
|
}
|
|
// HOME 메뉴일 때는 서브메뉴 없음
|
|
return [];
|
|
});
|
|
|
|
function onMenuClick(menu: string) {
|
|
activeMenu.value = menu;
|
|
showSubmenuBar.value = true;
|
|
}
|
|
|
|
function handleClickOutsideSubmenuBar(event: MouseEvent) {
|
|
const submenu = document.querySelector(".submenu-bar");
|
|
// menu-btn(대메뉴) 클릭 시에는 닫히지 않도록 예외 처리
|
|
if (
|
|
submenu &&
|
|
!submenu.contains(event.target as Node) &&
|
|
!(event.target as HTMLElement).classList.contains("menu-btn")
|
|
) {
|
|
showSubmenuBar.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
window.addEventListener("click", handleClickOutsideSubmenuBar);
|
|
});
|
|
onBeforeUnmount(() => {
|
|
window.removeEventListener("click", handleClickOutsideSubmenuBar);
|
|
});
|
|
/*
|
|
useHead({
|
|
title: "Integrated Bio Foundry Platform",
|
|
meta: [{ name: "description", content: "Integrated Bio Foundry Platform" }],
|
|
});
|
|
*/
|
|
</script>
|
|
|
|
<style scoped>
|
|
.layout {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
}
|
|
.main {
|
|
flex: 1;
|
|
padding: 2rem;
|
|
padding-top: 0.5rem;
|
|
}
|
|
.footer {
|
|
background: #f8f9fa;
|
|
padding: 1rem;
|
|
text-align: center;
|
|
border-top: 1px solid #e9ecef;
|
|
}
|
|
.submenu-bar {
|
|
background: #f4f6fa;
|
|
border-bottom: 1px solid #e0e7ef;
|
|
padding: 0.5rem 2rem;
|
|
display: flex;
|
|
gap: 1rem;
|
|
position: absolute;
|
|
top: 80px;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 10;
|
|
}
|
|
.submenu-btn {
|
|
font-size: 1.05rem;
|
|
font-weight: 500;
|
|
color: #222;
|
|
background: none;
|
|
border: none;
|
|
padding: 0.5rem 1.2rem;
|
|
border-radius: 6px;
|
|
transition:
|
|
background 0.15s,
|
|
color 0.15s;
|
|
cursor: pointer;
|
|
}
|
|
.submenu-btn.active {
|
|
background: none;
|
|
color: #1976d2;
|
|
}
|
|
.submenu-btn:hover {
|
|
background: #e6f0fa;
|
|
color: #1976d2;
|
|
}
|
|
</style>
|