477 lines
25 KiB
Vue
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>
|