212 lines
5.9 KiB
Vue
212 lines
5.9 KiB
Vue
<script setup lang="ts">
|
|
import type {
|
|
PageDataResourceGroup,
|
|
PageDataResourceGroupBtnInfo,
|
|
} from '#layers/types/api/pageData'
|
|
import type { ButtonType } from '#layers/types/components/button'
|
|
|
|
/** 어드민 버튼 타입 */
|
|
const BUTTON_ACTION_TYPE = {
|
|
URL: 'URL',
|
|
RUN: 'RUN',
|
|
POP: 'POP',
|
|
DOWNLOAD: 'DOWNLOAD',
|
|
ANCHOR: 'ANCHOR',
|
|
MOV: 'MOV',
|
|
DEACTIVE: 'DEACTIVE',
|
|
} as const
|
|
|
|
const OS_TYPE = {
|
|
PC: 1,
|
|
} as const
|
|
|
|
interface Props {
|
|
resourcesData: PageDataResourceGroup[]
|
|
buttonSize?: string
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
buttonSize: 'size-extra-small md:size-medium',
|
|
})
|
|
|
|
const { locale, tm } = useI18n()
|
|
const device = useDevice()
|
|
const modalStore = useModalStore()
|
|
const scrollStore = useScrollStore()
|
|
const breakpoints = useResponsiveBreakpoints()
|
|
const { sendLog } = useAnalytics()
|
|
|
|
const buttonList = computed<PageDataResourceGroup[]>(
|
|
() => props.resourcesData ?? []
|
|
)
|
|
|
|
/** 버튼 유형이 '시스템 버튼'인지 확인 */
|
|
const isSystemButton = (button: PageDataResourceGroup): boolean => {
|
|
return button.btn_info?.btn_category === 'system'
|
|
}
|
|
|
|
/** 버튼 타입이 '게임 실행'인지 확인 */
|
|
const isLauncherButton = (button: PageDataResourceGroup): boolean => {
|
|
return button.btn_info?.detail?.btn_type === BUTTON_ACTION_TYPE.RUN
|
|
}
|
|
|
|
/** 버튼 타입이 '비활성화'인지 확인 */
|
|
const isDisabled = (button: PageDataResourceGroup): boolean => {
|
|
return button.btn_info?.detail?.btn_type === BUTTON_ACTION_TYPE.DEACTIVE
|
|
}
|
|
|
|
const usesGameFont = (btnInfo?: PageDataResourceGroupBtnInfo): boolean => {
|
|
return btnInfo?.use_game_font === 1
|
|
}
|
|
|
|
const getButtonType = (btnInfo?: PageDataResourceGroupBtnInfo): ButtonType => {
|
|
const btnType = btnInfo?.detail?.btn_type
|
|
const target = btnInfo?.detail?.action?.link_target
|
|
|
|
if (btnType === BUTTON_ACTION_TYPE.URL && target) {
|
|
return target === '_blank' ? 'external' : 'internal'
|
|
}
|
|
|
|
if (btnType === BUTTON_ACTION_TYPE.DOWNLOAD) return 'download'
|
|
|
|
return 'action'
|
|
}
|
|
|
|
const isRunButtonVisible = (btnInfo: PageDataResourceGroupBtnInfo): boolean => {
|
|
if (breakpoints.value?.isDesktop) return true
|
|
|
|
const marketType = btnInfo?.detail?.market_type
|
|
|
|
switch (marketType) {
|
|
case 'pc':
|
|
return false
|
|
case 'google_play':
|
|
return device.isAndroid
|
|
case 'app_store':
|
|
return device.isApple
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
const openPopupModal = (detail: Record<string, any>) => {
|
|
modalStore.handleOpenContent({
|
|
contentTitle: detail?.title,
|
|
tabInfo: detail?.tab_info,
|
|
})
|
|
}
|
|
|
|
const scrollToAnchor = (detail: Record<string, any>) => {
|
|
scrollStore.scrollToAnchor(detail?.page_ver_tmpl_name_en ?? '')
|
|
}
|
|
|
|
const openYoutubeModal = (detail: Record<string, any>) => {
|
|
modalStore.handleOpenYoutube({ youtubeUrl: detail?.url ?? '' })
|
|
}
|
|
|
|
const downloadFile = async (detail: Record<string, any>) => {
|
|
const url = detail?.file_path ?? ''
|
|
const osType = detail?.os_type ?? 0
|
|
|
|
if (osType === OS_TYPE.PC && breakpoints.value?.isMobile) {
|
|
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_PC') })
|
|
return
|
|
}
|
|
|
|
const fileUrl = formatPathHost(url)
|
|
|
|
try {
|
|
const blob = await $fetch<Blob>(fileUrl, {
|
|
method: 'GET',
|
|
responseType: 'blob',
|
|
timeout: 10000,
|
|
})
|
|
|
|
const blobUrl = URL.createObjectURL(blob)
|
|
const fileName = fileUrl.split('/').pop() ?? 'download'
|
|
|
|
const anchor = document.createElement('a')
|
|
anchor.href = blobUrl
|
|
anchor.download = fileName
|
|
document.body.appendChild(anchor)
|
|
anchor.click()
|
|
anchor.remove()
|
|
|
|
URL.revokeObjectURL(blobUrl)
|
|
|
|
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Success') })
|
|
} catch (err) {
|
|
console.error(err)
|
|
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Error') })
|
|
}
|
|
}
|
|
|
|
const buttonClickHandlers: Record<
|
|
string,
|
|
(detail: Record<string, any>) => void
|
|
> = {
|
|
[BUTTON_ACTION_TYPE.POP]: openPopupModal,
|
|
[BUTTON_ACTION_TYPE.ANCHOR]: scrollToAnchor,
|
|
[BUTTON_ACTION_TYPE.MOV]: openYoutubeModal,
|
|
[BUTTON_ACTION_TYPE.DOWNLOAD]: downloadFile,
|
|
}
|
|
|
|
const handleButtonClick = (button: PageDataResourceGroup) => {
|
|
sendLog(locale.value, button.tracking)
|
|
|
|
const btnDetail = button.btn_info?.detail
|
|
const btnType = btnDetail?.btn_type
|
|
|
|
const handler = buttonClickHandlers[btnType]
|
|
handler?.(btnDetail)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
v-if="buttonList.length"
|
|
v-motion-stagger
|
|
class="flex flex-wrap justify-center items-center gap-3 md:gap-4"
|
|
>
|
|
<template v-for="(button, index) in buttonList" :key="index">
|
|
<!-- 버튼 유형: 시스템 버튼 -->
|
|
<AtomsButton
|
|
v-if="isSystemButton(button)"
|
|
:type="getButtonType(button.btn_info)"
|
|
:size="buttonSize"
|
|
:href="button.btn_info?.detail?.action?.url"
|
|
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
|
|
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
|
|
:disabled="isDisabled(button)"
|
|
:use-gradient="true"
|
|
:use-game-font="usesGameFont(button.btn_info)"
|
|
@click="handleButtonClick(button)"
|
|
>
|
|
{{ button.btn_info?.txt_btn_name }}
|
|
</AtomsButton>
|
|
|
|
<!-- 버튼 유형: 이미지 버튼 + 타입: 게임 실행 -->
|
|
<BlocksButtonLauncher
|
|
v-else-if="
|
|
isLauncherButton(button) && isRunButtonVisible(button.btn_info!)
|
|
"
|
|
type="duplication"
|
|
:platform="button.btn_info?.detail?.market_type"
|
|
@click="handleButtonClick(button)"
|
|
>
|
|
{{ button.btn_info?.txt_btn_name }}
|
|
</BlocksButtonLauncher>
|
|
|
|
<!-- 버튼 유형: 이미지 버튼 + 타입: 기타 -->
|
|
<AtomsButtonImage
|
|
v-else-if="!isLauncherButton(button)"
|
|
:href="button.btn_info?.detail?.action?.url"
|
|
:background-image="formatPathHost(button.btn_info?.res_path)"
|
|
:alt="button.btn_info?.txt_btn_name"
|
|
:disabled="isDisabled(button)"
|
|
@click="handleButtonClick(button)"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</template>
|