Files
2026-04-07 14:50:23 +09:00

477 lines
25 KiB
Vue

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<Disclosure v-slot="{ open }" as="nav" class="bg-white shadow">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-16 justify-between">
<div class="flex">
<div class="flex flex-shrink-0 items-center">
<a
href="javascript:void(0)"
@click="handleItemClick($event, null)"
>
<img
class="block h-8 w-auto lg:hidden"
:src="siteLogoUrl"
alt="site logo image"
/>
<img
class="hidden h-8 w-auto lg:block"
:src="siteLogoUrl"
alt="site logo image"
/>
</a>
</div>
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
<!-- Current: "border-indigo-500 text-gray-900", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
<template
v-for="item in currentMenu['main']"
:key="item.idx"
>
<a
v-if="item.subs == undefined"
href="javascript:void(0)"
:class="
isCurrentMenu(item)
? 'inline-flex items-center border-b-2 border-indigo-500 px-1 pt-1 text-sm font-medium text-gray-900'
: 'inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700'
"
@click="handleItemClick($event, item)"
>{{ item['title'] }}</a
>
<div
v-else
:class="
isCurrentMenu(item)
? 'inline-flex items-center border-b-2 border-indigo-500 px-1 pt-1 text-sm font-medium text-gray-900'
: 'inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700'
"
>
<!-- dropdown -->
<Menu as="div" class="relative ml-3">
<div>
<MenuButton class="flex">
{{ item['title'] }}
<svg
x-state:on="Item active"
x-state:off="Item inactive"
class="h-5 w-5 group-hover:text-gray-500 text-gray-400"
x-bind:class="{ 'text-gray-600': flyoutMenuOpen, 'text-gray-400': !flyoutMenuOpen }"
x-description="Heroicon name: chevron-down"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</MenuButton>
</div>
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<MenuItems
class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<MenuItem
v-for="subItem in item['subs']"
v-slot="{ active }"
:key="subItem.idx"
>
<a
href="javascript:void(0)"
:class="[
active
? 'bg-gray-100'
: '',
'block px-4 py-2 text-sm text-gray-700',
]"
@click="
handleItemClick(
$event,
subItem
)
"
>{{ subItem.title }}</a
>
</MenuItem>
</MenuItems>
</transition>
</Menu>
</div>
</template>
<template
v-for="item in currentMenu['sub']"
:key="item.idx"
>
<a
v-if="item.subs == undefined"
href="javascript:void(0)"
:class="
isCurrentMenu(item)
? 'inline-flex items-center border-b-2 border-indigo-500 px-1 pt-1 text-sm font-medium text-gray-900'
: 'inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700'
"
@click="handleItemClick($event, item)"
>{{ item['title'] }}</a
>
<div
v-else
:class="
isCurrentMenu(item)
? 'inline-flex items-center border-b-2 border-indigo-500 px-1 pt-1 text-sm font-medium text-gray-900'
: 'inline-flex items-center border-b-2 border-transparent px-1 pt-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700'
"
>
<!-- dropdown -->
<Menu as="div" class="relative ml-3">
<div>
<MenuButton class="flex">
{{ item['title'] }}
<svg
x-state:on="Item active"
x-state:off="Item inactive"
class="h-5 w-5 group-hover:text-gray-500 text-gray-400"
x-bind:class="{ 'text-gray-600': flyoutMenuOpen, 'text-gray-400': !flyoutMenuOpen }"
x-description="Heroicon name: chevron-down"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</MenuButton>
</div>
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<MenuItems
class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<MenuItem
v-for="subItem in item['subs']"
v-slot="{ active }"
:key="subItem.idx"
>
<a
href="javascript:void(0)"
:class="[
active
? 'bg-gray-100'
: '',
'block px-4 py-2 text-sm text-gray-700',
]"
@click="
handleItemClick(
$event,
subItem
)
"
>{{ subItem.title }}</a
>
</MenuItem>
</MenuItems>
</transition>
</Menu>
</div>
</template>
</div>
</div>
<div class="hidden sm:ml-6 sm:flex sm:items-center">
<button
v-if="false"
type="button"
class="rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span class="sr-only">View notifications</span>
<BellIcon class="h-6 w-6" aria-hidden="true" />
</button>
<!-- Profile dropdown -->
<Menu as="div" class="relative ml-3">
<div>
<MenuButton
class="flex rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span class="sr-only">Open user menu</span>
<BaseUserProfileImage :image-size="2" />
</MenuButton>
</div>
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<MenuItems
class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<MenuItem
v-if="isAuthenticated"
v-slot="{ active }"
>
<a
href="javascript:void(0)"
:class="[
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700',
]"
@click="moveToPath('/user/info')"
>설정</a
>
</MenuItem>
<MenuItem v-slot="{ active }">
<a
href="javascript:void(0)"
:class="[
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700',
]"
@click="doSignInAndOut($event)"
>{{
isAuthenticated == true
? '로그아웃'
: '로그인'
}}</a
>
</MenuItem>
</MenuItems>
</transition>
</Menu>
</div>
<div class="-mr-2 flex items-center sm:hidden">
<!-- Mobile menu button -->
<DisclosureButton
class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
>
<span class="sr-only">Open main menu</span>
<Bars3Icon
v-if="!open"
class="block h-6 w-6"
aria-hidden="true"
/>
<XMarkIcon
v-else
class="block h-6 w-6"
aria-hidden="true"
/>
</DisclosureButton>
</div>
</div>
</div>
<DisclosurePanel class="sm:hidden">
<div class="space-y-1 pt-2 pb-3">
<!-- Current: "bg-indigo-50 border-indigo-500 text-indigo-700", Default: "border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700" -->
<template v-for="item in currentMenu['main']" :key="item.idx">
<DisclosureButton
v-if="item.path != undefined"
as="a"
href="javascript:void(0)"
:class="
currentRoutePath == item.path
? 'block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700'
: 'block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-500 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700'
"
@click="handleItemClick($event, item)"
>{{ item['title'] }}</DisclosureButton
>
<a
v-else
href="javascript:void(0)"
:class="
currentRoutePath == item.path
? 'block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700'
: 'block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-500 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700'
"
>{{ item['title'] }}</a
>
<template v-for="subItem in item.subs" :key="subItem.idx">
<DisclosureButton
v-if="subItem.path != undefined"
as="a"
href="javascript:void(0)"
:class="
currentRoutePath == subItem.path
? 'block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700'
: 'block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-500 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700'
"
class="ml-4"
@click="handleItemClick($event, subItem)"
>{{ subItem['title'] }}</DisclosureButton
>
<a
v-else
href="javascript:void(0)"
:class="
currentRoutePath == subItem.path
? 'block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700'
: 'block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-500 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700'
"
>{{ subItem['title'] }}</a
>
</template>
</template>
<template v-for="item in currentMenu['sub']" :key="item.idx">
<DisclosureButton
as="a"
href="javascript:void(0)"
:class="
currentRoutePath == item.path
? 'block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700'
: 'block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-500 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700'
"
@click="handleItemClick($event, item)"
>{{ item['title'] }}</DisclosureButton
>
</template>
</div>
<div class="border-t border-gray-200 pt-4 pb-3">
<div class="flex items-center px-4">
<div class="flex-shrink-0">
<BaseUserProfileImage :image-size="3" />
</div>
<div v-if="false" class="ml-3">
<div class="text-base font-medium text-gray-800">
Tom Cook
</div>
<div class="text-sm font-medium text-gray-500">
tom@example.com
</div>
</div>
<button
v-if="false"
type="button"
class="ml-auto flex-shrink-0 rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span class="sr-only">View notifications</span>
<BellIcon class="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div class="mt-3 space-y-1">
<DisclosureButton
v-if="isAuthenticated"
as="a"
href="javascript:void(0)"
class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800"
@click="moveToPath('/user/info')"
>설정</DisclosureButton
>
<DisclosureButton
as="a"
href="javascript:void(0)"
class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800"
@click="doSignInAndOut($event)"
>{{
isAuthenticated == true ? '로그아웃' : '로그인'
}}</DisclosureButton
>
</div>
</div>
</DisclosurePanel>
</Disclosure>
</template>
<script setup lang="ts">
import {
Disclosure,
DisclosureButton,
DisclosurePanel,
Menu,
MenuButton,
MenuItem,
MenuItems,
} from '@headlessui/vue';
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline';
const route = useRoute();
const currentRoutePath = ref(route.path);
const siteLogoUrl = ref(_siteConfig.siteLogoUrl);
const currentMenu = ref(_crossCtl.menu);
const isAuthenticated = ref(_crossCtl.isAuthenticated);
function isCurrentMenu(menuItem) {
let finalResult = false;
if (menuItem.path == currentRoutePath.value) {
finalResult = true;
} else {
if (menuItem['subs'] != undefined) {
for (let i = 0; i < menuItem['subs'].length; i++) {
if (menuItem['subs'][i].path == currentRoutePath.value) {
finalResult = true;
break;
}
}
}
}
return finalResult;
}
function handleItemClick(e, item) {
if (item == null) {
navigateTo('/');
currentRoutePath.value = '/';
} else {
_crossCtl.moveToMenuItem(item);
currentRoutePath.value = item.path;
}
}
function moveToPath(path) {
navigateTo(path);
currentRoutePath.value = path;
}
async function doSignInAndOut(e) {
e.target.blur();
if (_crossCtl.isAuthenticated.value) {
const response = await _crossCtl.doComm('signout', '', {});
console.log('response=', response);
if (response['responseCode'] == 200) {
_crossCtl.setUserInfo({
isAdmin: false,
isApproved: false,
isAuthenticated: false,
isHighLeveled: false,
isOp: false,
isSuperOp: false,
});
_crossCtl.setUserProfile({});
isAuthenticated.value = false;
window.location.href = '/';
} else {
alert(response['responseMessage']);
}
} else {
navigateTo({
path: '/user/signin',
});
}
}
</script>