init source

This commit is contained in:
leejisun9
2025-08-08 13:11:33 +09:00
parent 02660627d2
commit 61d947a644
57 changed files with 1852863 additions and 0 deletions

29
layouts/auth.vue Normal file
View File

@@ -0,0 +1,29 @@
<template>
<div class="auth-layout">
<main class="auth-main">
<slot />
</main>
</div>
</template>
<script setup lang="ts">
// 인증 페이지용 레이아웃 - 헤더와 푸터 없음
</script>
<style scoped>
.auth-layout {
min-height: 100vh;
background: #f8f9fa;
display: flex;
flex-direction: column;
}
.auth-main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 0;
}
</style>

165
layouts/default.vue Normal file
View File

@@ -0,0 +1,165 @@
<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>&copy; 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>