Files
bio_frontend/layouts/default.vue

270 lines
5.3 KiB
Vue
Raw Normal View History

2025-08-08 13:11:33 +09:00
<script setup lang="ts">
2025-08-22 14:01:30 +09:00
import AppHeader from "../components/layout/AppHeader.vue";
import { ref, computed, watch } from "vue";
2025-08-22 14:01:30 +09:00
import { useRouter } from "vue-router";
2025-08-14 11:00:48 +09:00
import { useTabsStore } from "../stores/tab";
2025-08-08 13:11:33 +09:00
const router = useRouter();
const activeMenu = ref("home");
const showSubmenuBar = ref(false);
2025-08-14 11:00:48 +09:00
const tabsStore = useTabsStore();
2025-08-22 14:01:30 +09:00
// 메뉴 클릭 시 홈 이동
watch(activeMenu, newValue => {
2025-08-22 14:01:30 +09:00
if (newValue === "home") router.push("/");
2025-08-08 13:11:33 +09:00
});
2025-08-14 11:00:48 +09:00
// 서브메뉴 정의
2025-08-08 13:11:33 +09:00
const subMenus = computed(() => {
if (activeMenu.value === "test") {
return [
{
2025-08-22 14:01:30 +09:00
key: "test",
label: "테스트",
to: "/test/test01",
},
{
2025-08-22 14:01:30 +09:00
key: "igv",
label: "ivg",
to: "/test/test02",
},
{
2025-08-22 14:01:30 +09:00
key: "igv2",
label: "ivg2",
to: "/test/igv2",
},
{
2025-08-22 14:01:30 +09:00
key: "pathway",
label: "pathway",
to: "/test/pathway",
},
{
2025-08-22 14:01:30 +09:00
key: "pathway2",
label: "pathway2",
to: "/test/pathway2",
},
{
2025-08-22 14:01:30 +09:00
key: "pathway3",
label: "pathway3",
to: "/test/pathway3",
},
{
2025-08-22 14:01:30 +09:00
key: "pathway4",
label: "pathway4",
to: "/cultureGraph/pathway4",
},
{
2025-08-22 14:01:30 +09:00
key: "pathwayjson",
label: "pathwayjson",
to: "/test/pathwayjson",
},
{
2025-08-22 14:01:30 +09:00
key: "cultureGraph",
label: "배양그래프",
to: "/test/culture-graph",
},
{
2025-08-22 14:01:30 +09:00
key: "cultureGraphMulti",
label: "배양그래프 멀티",
to: "/test/culture-graph-multi",
},
{
2025-08-22 14:01:30 +09:00
key: "cultureGraphTab",
label: "배양그래프 탭",
to: "/test/culture-graph-tab",
},
{
2025-08-22 14:01:30 +09:00
key: "tui-grid",
label: "tui-grid",
to: "/tui",
},
{
2025-08-22 14:01:30 +09:00
key: "리소스",
label: "리소스",
to: "/admin/resource",
},
{
2025-08-22 14:01:30 +09:00
key: "sample",
label: "sample",
to: "/sampleList",
},
{
key: "common-test",
label: "공용 기능 테스트",
to: "/common-test",
},
];
} else if (activeMenu.value === "ADMIN") {
return [
{
2025-08-22 14:01:30 +09:00
key: "logs",
label: "접속기록",
to: "/admin/logs",
},
{
2025-08-22 14:01:30 +09:00
key: "codes",
label: "공통코드",
to: "/admin/codes",
},
{
2025-08-22 14:01:30 +09:00
key: "programs",
label: "프로그램",
to: "/admin/programs",
},
];
}
2025-08-08 13:11:33 +09:00
return [];
});
function onMenuClick(menu: string) {
activeMenu.value = menu;
showSubmenuBar.value = true;
}
2025-08-22 14:01:30 +09:00
// ✅ 서브메뉴 클릭 → 현재 활성 탭 내용만 변경
function onSubMenuClick(sub: {
key: string;
label: string;
to: string;
componentName: string;
}) {
2025-08-22 14:01:30 +09:00
tabsStore.updateActiveTab(sub);
// const activeKey = tabsStore.activeTab;
// router.push(`/${activeKey}${sub.to}`);
2025-08-14 11:00:48 +09:00
}
2025-08-22 14:01:30 +09:00
// ✅ 새 탭 추가 버튼
function addNewTab() {
tabsStore.addTab();
// router.push(`/${key}/`);
2025-08-08 13:11:33 +09:00
}
</script>
2025-08-14 11:00:48 +09:00
<template>
<div class="layout">
<AppHeader v-model="activeMenu" @update:model-value="onMenuClick" />
<!-- 서브메뉴 -->
<nav
v-if="subMenus && subMenus.length && showSubmenuBar"
class="submenu-bar"
@click.stop
>
2025-08-14 11:00:48 +09:00
<button
v-for="sub in subMenus"
:key="sub.key"
class="submenu-btn"
2025-08-22 14:01:30 +09:00
@click="onSubMenuClick({ ...sub, componentName: sub.key })"
2025-08-14 11:00:48 +09:00
>
{{ sub.label }}
</button>
</nav>
<br /><br />
2025-08-22 14:01:30 +09:00
<!-- -->
<div class="tab-bar">
2025-08-14 11:00:48 +09:00
<div
v-for="tab in tabsStore.tabs"
:key="tab.key"
class="tab-item"
:class="{ active: tabsStore.activeTab === tab.key }"
@click="tabsStore.setActiveTab(tab.key)"
2025-08-14 11:00:48 +09:00
>
{{ tab.label }}
<span
v-show="tabsStore.activeTab !== tab.key"
class="close-btn"
@click.stop="tabsStore.removeTab(tab.key)"
>
×
</span>
2025-08-14 11:00:48 +09:00
</div>
2025-08-22 14:01:30 +09:00
<!-- 추가 버튼 -->
<button class="add-tab-btn" @click="addNewTab"></button>
2025-08-14 11:00:48 +09:00
</div>
<main class="main">
<slot />
</main>
</div>
</template>
2025-08-08 13:11:33 +09:00
<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;
}
2025-08-14 11:00:48 +09:00
/* 탭바 스타일 */
.tab-bar {
display: flex;
gap: 6px;
padding: 0.4rem 0.8rem;
background: #fff;
border-bottom: 1px solid #ddd;
}
.tab-item {
padding: 0.3rem 0.8rem;
background: #f2f2f2;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
}
.tab-item.active {
background: #1976d2;
color: white;
}
.close-btn {
margin-left: 6px;
cursor: pointer;
}
2025-08-08 13:11:33 +09:00
</style>