Merge branch 'feature/202501107-all' into feature/20251201-gil_qa
This commit is contained in:
@@ -57,7 +57,7 @@ onMounted(async () => {
|
||||
class="btn-control"
|
||||
@click="toggleEventNavigation"
|
||||
>
|
||||
<AtomsIconsArrowRightLine size="24" color="#ffffff" />
|
||||
<AtomsIconsArrowRightLine color="#ffffff" />
|
||||
</AtomsButtonCircle>
|
||||
<ul class="navigation-list">
|
||||
<li v-for="item in eventNavigationList" :key="item.banner_seq">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useThrottleFn } from '@vueuse/core'
|
||||
import { useGameDataStore } from '#layers/stores/useGameDataStore'
|
||||
import type {
|
||||
GameDataMenu,
|
||||
@@ -40,6 +41,13 @@ const officialItemWidths = ref<number[]>([])
|
||||
const overflowNam = ref<number>(0)
|
||||
|
||||
const gnbData = computed(() => gameData.value?.gnb)
|
||||
const hasGnbMenus = computed(() => {
|
||||
const menus = gnbData.value?.menus
|
||||
if (!menus) return false
|
||||
if (typeof menus !== 'object') return false
|
||||
return Object.keys(menus).length > 0
|
||||
})
|
||||
|
||||
const gnb1depthButtonData = computed(
|
||||
() => gnbData.value?.buttons[0]?.button_json as GameDataResourceGroup
|
||||
)
|
||||
@@ -81,6 +89,7 @@ const isNavItemActive = (gnbItem: GameDataMenu): boolean => {
|
||||
|
||||
// navAreaRef의 넓이를 구하는 함수
|
||||
const calculateNavWidth = () => {
|
||||
if (!import.meta.client) return
|
||||
if (!navAreaRef.value || !gnbData.value) return 0
|
||||
|
||||
const navAreaWidth = navAreaRef.value.offsetWidth
|
||||
@@ -89,6 +98,7 @@ const calculateNavWidth = () => {
|
||||
|
||||
// official 자식들의 넓이를 구하는 함수
|
||||
const calculateOfficialItemWidths = () => {
|
||||
if (!import.meta.client) return
|
||||
if (!navAreaRef.value) return
|
||||
|
||||
const officialItems = navAreaRef.value.querySelectorAll('.official .nav-item')
|
||||
@@ -107,6 +117,7 @@ const calculateOfficialItemWidths = () => {
|
||||
|
||||
// 오버플로우 계산 함수
|
||||
const calculateOverflow = () => {
|
||||
if (!import.meta.client) return
|
||||
if (!navAreaRef.value || !startRef.value) return
|
||||
|
||||
if (breakpoints.value.isMobile) {
|
||||
@@ -137,6 +148,11 @@ const calculateOverflow = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 100ms마다 최대 1회 실행
|
||||
const throttledCalculateOverflow = useThrottleFn(() => {
|
||||
calculateOverflow()
|
||||
}, 100)
|
||||
|
||||
const handleMenuOpen = () => {
|
||||
isMenuOpen.value = true
|
||||
scrollStore.controlScrollLock(true)
|
||||
@@ -200,26 +216,26 @@ const handleStartClick = () => {
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
if (!startWidth.value) return // 0, null, undefined면 스킵
|
||||
calculateOverflow()
|
||||
})
|
||||
|
||||
// 화면 크기 변경 시 오버플로우 재계산
|
||||
watch(width, () => {
|
||||
calculateOverflow()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
overflowNam.value = 0
|
||||
isMounted.value = true
|
||||
|
||||
// 초기 계산 시도
|
||||
// 초기 계산
|
||||
nextTick(() => {
|
||||
calculateNavWidth()
|
||||
calculateOfficialItemWidths()
|
||||
calculateOverflow()
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
if (!startWidth.value) return
|
||||
throttledCalculateOverflow()
|
||||
})
|
||||
|
||||
// 화면 크기 변경 시 오버플로우 재계산
|
||||
watch(width, () => {
|
||||
throttledCalculateOverflow()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -256,89 +272,45 @@ onMounted(() => {
|
||||
</AtomsLocaleLink>
|
||||
</div>
|
||||
<nav :class="['nav-list', { 'is-mounted': isMounted }]">
|
||||
<div v-if="gnbData?.menus" class="official custom-theme-scrollbar">
|
||||
<div
|
||||
v-for="(gnbItem, key) in gnbData?.menus"
|
||||
:key="key"
|
||||
class="nav-item"
|
||||
:class="{
|
||||
'is-hidden':
|
||||
overflowNam > 0 &&
|
||||
Number(key) >=
|
||||
Object.keys(gnbData?.menus).length - overflowNam,
|
||||
}"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="isNotClickable(gnbItem) ? '#' : gnbItem.url_path"
|
||||
:target="gnbItem.link_target"
|
||||
:class="[
|
||||
'nav-1depth',
|
||||
{ 'has-link': !isNotClickable(gnbItem) },
|
||||
{ active: isNavItemActive(gnbItem) },
|
||||
]"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<span>{{ gnbItem.menu_name }}</span>
|
||||
<AtomsIconsWebLinkLine
|
||||
v-if="gnbItem.link_target === '_blank'"
|
||||
/>
|
||||
<AtomsIconsArrowDownFill
|
||||
v-if="has2depthButton(gnbItem)"
|
||||
class="hidden md:block"
|
||||
/>
|
||||
<AtomsIconsArrowRightLine
|
||||
v-if="!has2depthButton(gnbItem)"
|
||||
class="ml-auto md:hidden"
|
||||
/>
|
||||
</AtomsLocaleLink>
|
||||
<Transition name="fade">
|
||||
<div v-if="has2depthButton(gnbItem)" class="nav-2depth">
|
||||
<ul>
|
||||
<li
|
||||
v-for="child in gnbItem.children"
|
||||
:key="child.menu_name"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="child.url_path"
|
||||
:target="child.link_target"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<span>{{ child.menu_name }}</span>
|
||||
<AtomsIconsWebLinkLine
|
||||
v-if="child.link_target === '_blank'"
|
||||
/>
|
||||
</AtomsLocaleLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="gnbData?.menus && overflowNam > 0" class="more">
|
||||
<button class="btn-more">
|
||||
<AtomsIconsOptionHorizontalFill class="mx-auto" />
|
||||
<span class="sr-only">more</span>
|
||||
</button>
|
||||
<div class="more-list">
|
||||
<div class="list-inner">
|
||||
<div
|
||||
v-for="(gnbItem, key) in gnbData?.menus"
|
||||
:key="key"
|
||||
:class="{
|
||||
hidden:
|
||||
Number(key) <
|
||||
<template v-if="hasGnbMenus">
|
||||
<div class="official custom-theme-scrollbar">
|
||||
<div
|
||||
v-for="(gnbItem, key) in gnbData?.menus"
|
||||
:key="key"
|
||||
class="nav-item"
|
||||
:class="{
|
||||
'is-hidden':
|
||||
isMounted &&
|
||||
overflowNam > 0 &&
|
||||
Number(key) >=
|
||||
Object.keys(gnbData?.menus).length - overflowNam,
|
||||
}"
|
||||
}"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="isNotClickable(gnbItem) ? '#' : gnbItem.url_path"
|
||||
:target="gnbItem.link_target"
|
||||
:class="[
|
||||
'nav-1depth',
|
||||
{ 'has-link': !isNotClickable(gnbItem) },
|
||||
{ active: isNavItemActive(gnbItem) },
|
||||
]"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="gnbItem.url_path"
|
||||
:target="gnbItem.link_target"
|
||||
:class="`${isNavItemActive(gnbItem) ? 'active' : ''}`"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<span>{{ gnbItem.menu_name }}</span>
|
||||
</AtomsLocaleLink>
|
||||
<div v-if="gnbItem.children">
|
||||
<span>{{ gnbItem.menu_name }}</span>
|
||||
<AtomsIconsWebLinkLine
|
||||
v-if="gnbItem.link_target === '_blank'"
|
||||
/>
|
||||
<AtomsIconsArrowDownFill
|
||||
v-if="has2depthButton(gnbItem)"
|
||||
class="hidden md:block"
|
||||
/>
|
||||
<AtomsIconsArrowRightLine
|
||||
v-if="!has2depthButton(gnbItem)"
|
||||
class="ml-auto md:hidden"
|
||||
/>
|
||||
</AtomsLocaleLink>
|
||||
<Transition name="fade">
|
||||
<div v-if="has2depthButton(gnbItem)" class="nav-2depth">
|
||||
<ul>
|
||||
<li
|
||||
v-for="child in gnbItem.children"
|
||||
@@ -347,6 +319,7 @@ onMounted(() => {
|
||||
<AtomsLocaleLink
|
||||
:to="child.url_path"
|
||||
:target="child.link_target"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<span>{{ child.menu_name }}</span>
|
||||
<AtomsIconsWebLinkLine
|
||||
@@ -356,16 +329,62 @@ onMounted(() => {
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isMounted && overflowNam > 0" class="more">
|
||||
<button class="btn-more">
|
||||
<AtomsIconsOptionHorizontalFill class="mx-auto" />
|
||||
<span class="sr-only">more</span>
|
||||
</button>
|
||||
<div class="more-list">
|
||||
<div class="list-inner">
|
||||
<div
|
||||
v-for="(gnbItem, key) in gnbData?.menus"
|
||||
:key="key"
|
||||
:class="{
|
||||
hidden:
|
||||
Number(key) <
|
||||
Object.keys(gnbData?.menus).length - overflowNam,
|
||||
}"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="gnbItem.url_path"
|
||||
:target="gnbItem.link_target"
|
||||
:class="`${isNavItemActive(gnbItem) ? 'active' : ''}`"
|
||||
@click="handleMenuClose"
|
||||
>
|
||||
<span>{{ gnbItem.menu_name }}</span>
|
||||
</AtomsLocaleLink>
|
||||
<div v-if="gnbItem.children">
|
||||
<ul>
|
||||
<li
|
||||
v-for="child in gnbItem.children"
|
||||
:key="child.menu_name"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="child.url_path"
|
||||
:target="child.link_target"
|
||||
>
|
||||
<span>{{ child.menu_name }}</span>
|
||||
<AtomsIconsWebLinkLine
|
||||
v-if="child.link_target === '_blank'"
|
||||
/>
|
||||
</AtomsLocaleLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="gameData?.event_banner" class="event">
|
||||
<div class="nav-item">
|
||||
<AtomsLocaleLink
|
||||
:to="gameData.event_banner?.page_url"
|
||||
:to="gameData?.event_banner?.page_url"
|
||||
:target="
|
||||
gameData.event_banner?.link_type === 1 ? '_self' : '_blank'
|
||||
gameData?.event_banner?.link_type === 1 ? '_self' : '_blank'
|
||||
"
|
||||
class="nav-1depth text-gradient-pink"
|
||||
@click="handleMenuClose"
|
||||
@@ -560,11 +579,14 @@ onMounted(() => {
|
||||
@apply px-6;
|
||||
}
|
||||
|
||||
.event {
|
||||
@apply relative pr-1 md:ml-[64px] md:pr-0
|
||||
.official ~ .event {
|
||||
@apply md:ml-[64px]
|
||||
before:content-[''] before:block before:h-px before:mb-2 before:mx-3 before:bg-theme-foreground-reversal-8 md:before:hidden
|
||||
after:content-[''] after:absolute md:after:top-[50%] md:after:left-[-32px] md:after:w-[1px] md:after:h-[16px] md:after:bg-theme-foreground-gray-750 md:after:translate-y-[-50%];
|
||||
}
|
||||
.event {
|
||||
@apply relative pr-1 md:pr-0;
|
||||
}
|
||||
|
||||
.is-hidden {
|
||||
@apply hidden;
|
||||
|
||||
Reference in New Issue
Block a user