fix. 게임 스타트 버튼 platform, os 분기 로직 위치 이동

This commit is contained in:
clkim
2025-12-09 19:02:37 +09:00
parent 23621184c7
commit e6382f9f69
3 changed files with 82 additions and 90 deletions

View File

@@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { CSSProperties } from 'vue' import type { CSSProperties } from 'vue'
import type { PlatformTransformType } from '#layers/types/api/gameData'
import type { import type {
DownloadButtonType, DownloadButtonType,
ButtonVariant, ButtonVariant,
@@ -21,8 +22,17 @@ const props = withDefaults(defineProps<Props>(), {
disabled: false, disabled: false,
}) })
const PLATFORM_LABEL_KEY: Record<PlatformTransformType, string> = {
pc: 'PC',
google_play: 'Google Play',
app_store: 'App Store',
} as const
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
const { tm } = useI18n()
const device = useDevice()
const gameDataStore = useGameDataStore() const gameDataStore = useGameDataStore()
const modalStore = useModalStore()
const { isProcessing, validateLauncher } = useCheckGameStart() const { isProcessing, validateLauncher } = useCheckGameStart()
const { gameData } = storeToRefs(gameDataStore) const { gameData } = storeToRefs(gameDataStore)
@@ -42,15 +52,20 @@ const DUP_IMAGE_MAP: Record<Platform, string> = {
} as const } as const
const componentTag = computed(() => { const componentTag = computed(() => {
if (props.type !== 'duplication' && props.platform === 'stove') { if (props.platform === 'stove' && props.type !== 'duplication') {
return 'a' return 'a'
} }
return 'button' return 'button'
}) })
const isDuplication = computed(() => props.type === 'duplication')
const isSingle = computed(() => props.type === 'single') const isSingle = computed(() => props.type === 'single')
const supportedPlatforms = computed(
() =>
getSupportedPlatforms(
gameData.value?.platform_type,
gameData.value?.os_type
) as PlatformTransformType[]
)
const platformIcon = computed(() => PLATFORM_ICON_MAP[props.platform]) const platformIcon = computed(() => PLATFORM_ICON_MAP[props.platform])
const inlineStyle = computed<CSSProperties>(() => { const inlineStyle = computed<CSSProperties>(() => {
const style: CSSProperties = {} const style: CSSProperties = {}
@@ -66,18 +81,61 @@ const inlineStyle = computed<CSSProperties>(() => {
return style return style
}) })
const handleClick = () => { const highlight = (text: string) => `<span class="highlight">${text}</span>`
if (props.platform === 'pc') {
validateLauncher() const tmWithGameName = (key: string): string => {
return const raw = tm(key)
if (typeof raw !== 'string') return ''
const withName = raw.replace(
/%게임명%/g,
highlight(gameData.value?.game_name || '')
)
const platformLines = supportedPlatforms.value
.map(platform => highlight(PLATFORM_LABEL_KEY[platform] as string))
.filter(Boolean)
return platformLines.length
? `${withName}<br><br>${platformLines.join('<br>')}`
: withName
} }
if (props.platform === 'stove' && !isDuplication.value) {
const handleClick = () => {
if (props.platform === 'stove') {
if (props.type === 'duplication') return
const stoveClientDownloadUrl = runtimeConfig.public.stoveClientDownloadUrl const stoveClientDownloadUrl = runtimeConfig.public.stoveClientDownloadUrl
location.href = stoveClientDownloadUrl location.href = stoveClientDownloadUrl
return return
} }
const url = gameData.value?.market_json[props.platform]?.url if (props.platform === 'pc') {
if (device.isDesktop && gameData.value?.platform_type !== '2') {
validateLauncher()
return
} else {
const target = device.isAndroid
? 'google_play'
: device.isApple
? 'app_store'
: null
if (!target || !supportedPlatforms.value.includes(target)) {
modalStore.handleOpenAlert({
contentText: tmWithGameName('Alert_Not_SupportedOS'),
})
return
}
const url = gameData.value?.market_json?.[target]?.url || ''
window.open(url, '_blank')
return
}
}
const url = gameData.value?.market_json[props.platform]?.url || ''
if (url) window.open(url, '_blank') if (url) window.open(url, '_blank')
} }
</script> </script>
@@ -100,14 +158,14 @@ const handleClick = () => {
<span class="btn-content"> <span class="btn-content">
<component <component
:is="platformIcon" :is="platformIcon"
v-if="!isDuplication" v-if="props.type !== 'duplication'"
class="icon-platform" class="icon-platform"
/> />
<span class="text"> <span class="text">
<slot /> <slot />
</span> </span>
<span <span
v-if="type === 'default' && platform === 'pc'" v-if="props.platform === 'pc' && props.type === 'default'"
class="icon-download" class="icon-download"
> >
<AtomsIconsDownloadLine /> <AtomsIconsDownloadLine />

View File

@@ -6,26 +6,18 @@ import type {
GameDataMenuChildren, GameDataMenuChildren,
GameDataResourceGroup, GameDataResourceGroup,
GameDataResourceGroupSet, GameDataResourceGroupSet,
PlatformTransformType,
} from '#layers/types/api/gameData' } from '#layers/types/api/gameData'
const MORE_WIDTH = 72 const MORE_WIDTH = 72
const START_WIDTH_MARGIN = 40 const START_WIDTH_MARGIN = 40
const PLATFORM_LABEL_KEY: Record<PlatformTransformType, string> = {
pc: 'PC',
google_play: 'Google Play',
app_store: 'App Store',
} as const
const route = useRoute() const route = useRoute()
const { tm } = useI18n() const { tm } = useI18n()
const { width } = useWindowSize() const { width } = useWindowSize()
const device = useDevice()
const gameDataStore = useGameDataStore() const gameDataStore = useGameDataStore()
const pageDataStore = usePageDataStore() const pageDataStore = usePageDataStore()
const scrollStore = useScrollStore() const scrollStore = useScrollStore()
const breakpoints = useResponsiveBreakpoints() const breakpoints = useResponsiveBreakpoints()
const modalStore = useModalStore()
const { gameData } = storeToRefs(gameDataStore) const { gameData } = storeToRefs(gameDataStore)
const { pageLayoutType } = storeToRefs(pageDataStore) const { pageLayoutType } = storeToRefs(pageDataStore)
@@ -55,16 +47,8 @@ const start1depthData = computed(
const start2depthData = computed( const start2depthData = computed(
() => gnbData.value?.buttons[1]?.button_json as GameDataResourceGroupSet () => gnbData.value?.buttons[1]?.button_json as GameDataResourceGroupSet
) )
const supportedPlatforms = computed(
() => console.log('start2depthData', start2depthData.value)
getSupportedPlatforms(
gameData.value?.platform_type,
gameData.value?.os_type
) as PlatformTransformType[]
)
const isStartPCVisible = computed(() => {
return device.isDesktop && gameData.value?.platform_type !== '2'
})
// 자식 중 활성 링크 존재 여부 확인 // 자식 중 활성 링크 존재 여부 확인
const hasActiveChild = (children?: GameDataMenuChildren) => { const hasActiveChild = (children?: GameDataMenuChildren) => {
@@ -158,52 +142,6 @@ const has2depthButton = (gnbItem: GameDataMenu) => {
return gnbItem.children && Object.keys(gnbItem.children).length > 0 return gnbItem.children && Object.keys(gnbItem.children).length > 0
} }
const highlight = (text: string) => `<span class="highlight">${text}</span>`
const tmWithGameName = (key: string): string => {
const raw = tm(key)
if (typeof raw !== 'string') return ''
const withName = raw.replace(
/%게임명%/g,
highlight(gameData.value?.game_name || '')
)
const platformLines = supportedPlatforms.value
.map(platform => highlight(PLATFORM_LABEL_KEY[platform] as string))
.filter(Boolean)
return platformLines.length
? `${withName}<br><br>${platformLines.join('<br>')}`
: withName
}
const showNotSupportedOSAlert = () => {
return modalStore.handleOpenAlert({
contentText: tmWithGameName('Alert_Not_SupportedOS'),
})
}
const handleStartClick = () => {
if (isStartPCVisible.value) return
const target = device.isAndroid
? 'google_play'
: device.isApple
? 'app_store'
: null
if (!target || !supportedPlatforms.value.includes(target)) {
showNotSupportedOSAlert()
return
}
const url = gameData.value?.market_json?.[target]?.url || ''
if (!url) return showNotSupportedOSAlert()
window.open(url, '_blank')
}
onMounted(() => { onMounted(() => {
overflowCount.value = 0 overflowCount.value = 0
isMounted.value = true isMounted.value = true
@@ -263,14 +201,14 @@ onMounted(() => {
<template v-if="hasGnbMenus"> <template v-if="hasGnbMenus">
<div class="official custom-theme-scrollbar"> <div class="official custom-theme-scrollbar">
<div <div
v-for="(gnbItem, index) in gnbData?.menus" v-for="(gnbItem, key) in gnbData?.menus"
:key="index" :key="key"
class="nav-item group" class="nav-item group"
:class="{ :class="{
'is-hidden': 'is-hidden':
breakpoints.isDesktop && breakpoints.isDesktop &&
overflowCount > 0 && overflowCount > 0 &&
Number(index) >= Number(key) >=
Object.keys(gnbData?.menus).length - overflowCount, Object.keys(gnbData?.menus).length - overflowCount,
}" }"
> >
@@ -334,13 +272,13 @@ onMounted(() => {
<div class="more-list"> <div class="more-list">
<div class="list-inner"> <div class="list-inner">
<div <div
v-for="(gnbItem, index) in gnbData?.menus" v-for="(gnbItem, key) in gnbData?.menus"
:key="index" :key="key"
:class="{ :class="{
'is-hidden': 'is-hidden':
breakpoints.isDesktop && breakpoints.isDesktop &&
overflowCount > 0 && overflowCount > 0 &&
Number(index) >= Number(key) >=
Object.keys(gnbData?.menus).length - overflowCount, Object.keys(gnbData?.menus).length - overflowCount,
}" }"
> >
@@ -424,10 +362,7 @@ onMounted(() => {
<ClientOnly> <ClientOnly>
<div ref="startRef" class="btn-start"> <div ref="startRef" class="btn-start">
<template v-if="start1depthData"> <template v-if="start1depthData">
<component <BlocksButtonLauncher
:is="
isStartPCVisible ? 'BlocksButtonLauncher' : 'AtomsButton'
"
type="custom" type="custom"
platform="pc" platform="pc"
:background-color=" :background-color="
@@ -436,17 +371,16 @@ onMounted(() => {
:text-color=" :text-color="
getColorCodeFromData(start1depthData?.btn_info, 'txt') getColorCodeFromData(start1depthData?.btn_info, 'txt')
" "
@click="handleStartClick"
> >
{{ start1depthData?.btn_info?.txt_btn_name }} {{ start1depthData?.btn_info?.txt_btn_name }}
</component> </BlocksButtonLauncher>
<div <div
v-if="breakpoints.isDesktop && start2depthData" v-if="breakpoints.isDesktop && start2depthData"
class="nav-2depth" class="nav-2depth"
> >
<ul> <ul>
<li v-for="(item, index) in start2depthData" :key="index"> <li v-for="(item, key) in start2depthData" :key="key">
<BlocksButtonLauncher type="custom" :platform="index"> <BlocksButtonLauncher type="custom" :platform="key">
{{ item.btn_info?.txt_btn_name }} {{ item.btn_info?.txt_btn_name }}
</BlocksButtonLauncher> </BlocksButtonLauncher>
</li> </li>

View File

@@ -191,8 +191,8 @@ const handleMoveFocus = (target: 'pc' | 'mobile') => {
:key="dIndex" :key="dIndex"
> >
<p <p
class="relative flex items-center justify-start w-full text-left text-[#999999] text-[14px] font-[400] leading-[24px] tracking-[-0.42px] md:text-[15px] md:tracking-[-0.45px]"
v-dompurify-html="tm(description as string)" v-dompurify-html="tm(description as string)"
class="relative flex items-center justify-start w-full text-left text-[#999999] text-[14px] font-[400] leading-[24px] tracking-[-0.42px] md:text-[15px] md:tracking-[-0.45px]"
></p> ></p>
</template> </template>