fix. [SWV-866] 액션버튼 기능 개선 (이미지 타입 추가)
Made-with: Cursor
@@ -69,10 +69,9 @@
|
|||||||
type="single"
|
type="single"
|
||||||
platform="pc"
|
platform="pc"
|
||||||
class="inspection-launcher"
|
class="inspection-launcher"
|
||||||
:icon-component="AtomsIconsPlayRoundFill"
|
|
||||||
:icon-props="{ size: 16, color: '#332C2A' }"
|
|
||||||
>
|
>
|
||||||
{{ tm('Txt_Game_Start') }}
|
{{ tm('Txt_Game_Start') }}
|
||||||
|
<AtomsIconsPlayRoundFill :size="16" color="#332C2A" />
|
||||||
</BlocksButtonLauncher>
|
</BlocksButtonLauncher>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -358,6 +357,9 @@ definePageMeta({
|
|||||||
.button-group:deep(.inspection-launcher.btn-base) {
|
.button-group:deep(.inspection-launcher.btn-base) {
|
||||||
@apply flex-1 bg-[var(--primary)] px-0 rounded md:rounded-lg;
|
@apply flex-1 bg-[var(--primary)] px-0 rounded md:rounded-lg;
|
||||||
}
|
}
|
||||||
|
.button-group:deep(.inspection-launcher) .text {
|
||||||
|
@apply flex items-center justify-center gap-[2px] mr-0 md:gap-[4px];
|
||||||
|
}
|
||||||
.button-group:deep(.inspection-launcher.btn-base .icon-platform) {
|
.button-group:deep(.inspection-launcher.btn-base .icon-platform) {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
13
app/pages/teaser.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
layout: false, // 동적 레이아웃을 위해 기본 레이아웃 비활성화
|
||||||
|
middleware: ['inspection'],
|
||||||
|
})
|
||||||
|
|
||||||
|
// 진입 시 /home으로 리다이렉트
|
||||||
|
await navigateTo('/home', { replace: true })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div />
|
||||||
|
</template>
|
||||||
@@ -1,32 +1,45 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface props {
|
interface props {
|
||||||
|
<<<<<<< HEAD
|
||||||
type?: 'button' | 'link'
|
type?: 'button' | 'link'
|
||||||
to?: string
|
to?: string
|
||||||
target?: '_self' | '_blank'
|
target?: '_self' | '_blank'
|
||||||
|
=======
|
||||||
|
type?: 'internal' | 'external' | 'action'
|
||||||
|
href?: string
|
||||||
|
>>>>>>> feature/20250228_SWV-866
|
||||||
backgroundColor?: string
|
backgroundColor?: string
|
||||||
srOnly?: string
|
srOnly?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<props>(), {
|
const props = withDefaults(defineProps<props>(), {
|
||||||
|
<<<<<<< HEAD
|
||||||
type: 'button',
|
type: 'button',
|
||||||
to: '',
|
to: '',
|
||||||
target: '_self',
|
target: '_self',
|
||||||
|
=======
|
||||||
|
type: 'action',
|
||||||
|
>>>>>>> feature/20250228_SWV-866
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
srOnly: '',
|
srOnly: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const componentTag = computed((): string => {
|
const componentTag = computed((): string => {
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'link':
|
case 'internal':
|
||||||
return 'AtomsLocaleLink'
|
return 'AtomsLocaleLink'
|
||||||
|
case 'external':
|
||||||
|
return 'a'
|
||||||
default:
|
default:
|
||||||
return 'button'
|
return 'button'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const componentProps = computed(() => {
|
const componentProps = computed(() => {
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'link':
|
case 'internal':
|
||||||
return { to: props.to, target: props.target }
|
return { to: props.href, target: '_self' }
|
||||||
|
case 'external':
|
||||||
|
return { href: props.href, target: '_blank' }
|
||||||
default:
|
default:
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|||||||
87
layers/components/atoms/Button/Image.vue
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ImageButtonType } from '#layers/types/components/button'
|
||||||
|
|
||||||
|
interface props {
|
||||||
|
type?: ImageButtonType
|
||||||
|
href?: string
|
||||||
|
backgroundImage: string
|
||||||
|
alt: string
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<props>(), {
|
||||||
|
type: 'action',
|
||||||
|
disabled: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const componentTag = computed((): string => {
|
||||||
|
switch (props.type) {
|
||||||
|
case 'external':
|
||||||
|
return 'a'
|
||||||
|
case 'internal':
|
||||||
|
return 'AtomsLocaleLink'
|
||||||
|
default:
|
||||||
|
return 'button'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const componentProps = computed(() => {
|
||||||
|
if (props.type === 'external') {
|
||||||
|
return {
|
||||||
|
href: props.href,
|
||||||
|
target: '_blank',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.type === 'internal') {
|
||||||
|
if (props.href) {
|
||||||
|
return {
|
||||||
|
to: props.href,
|
||||||
|
target: '_self',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}
|
||||||
|
})
|
||||||
|
const buttonStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
backgroundImage: props.backgroundImage,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component
|
||||||
|
:is="componentTag"
|
||||||
|
v-bind="{ ...componentProps }"
|
||||||
|
:class="['btn-base', { disabled: props.disabled }]"
|
||||||
|
:style="buttonStyle"
|
||||||
|
:disabled="props.disabled"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="props.backgroundImage"
|
||||||
|
:src="props.backgroundImage"
|
||||||
|
:alt="props.alt"
|
||||||
|
class="btn-bg"
|
||||||
|
/>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.btn-base {
|
||||||
|
@apply overflow-hidden relative h-[48px] md:h-[64px] rounded-[8px] md:rounded-[10px] cursor-pointer
|
||||||
|
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:transition-opacity after:duration-300 after:ease-in-out after:opacity-0
|
||||||
|
hover:after:opacity-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-base.disabled {
|
||||||
|
@apply cursor-default pointer-events-none
|
||||||
|
after:opacity-20 after:z-[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-bg {
|
||||||
|
@apply w-full h-full object-contain;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,23 +2,23 @@
|
|||||||
import type { TrackingObject } from '#layers/types/api/common'
|
import type { TrackingObject } from '#layers/types/api/common'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
category?: 'system' | 'image'
|
variant?: 'videoPlay' | 'videoPlayImg'
|
||||||
backgroundColor?: string
|
backgroundColor?: string
|
||||||
tracking: TrackingObject
|
tracking: TrackingObject
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), { category: 'system' })
|
const props = withDefaults(defineProps<Props>(), { variant: 'videoPlay' })
|
||||||
|
|
||||||
const { locale } = useI18n()
|
const { locale } = useI18n()
|
||||||
const { sendLog } = useAnalytics()
|
const { sendLog } = useAnalytics()
|
||||||
|
|
||||||
const buttonClasses = computed(() => [
|
const buttonClasses = computed(() => [
|
||||||
'btn-play',
|
'btn-play',
|
||||||
props.category === 'system' ? 'play-icon' : 'play-image',
|
props.variant === 'videoPlay' ? 'play-icon' : 'play-image',
|
||||||
])
|
])
|
||||||
|
|
||||||
const buttonStyle = computed(() =>
|
const buttonStyle = computed(() =>
|
||||||
props.category === 'system' && props.backgroundColor
|
props.variant === 'videoPlay' && props.backgroundColor
|
||||||
? { backgroundColor: props.backgroundColor }
|
? { backgroundColor: props.backgroundColor }
|
||||||
: {}
|
: {}
|
||||||
)
|
)
|
||||||
@@ -28,7 +28,7 @@ const onClick = () => sendLog(locale.value, props.tracking)
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button :class="buttonClasses" :style="buttonStyle" @click="onClick">
|
<button :class="buttonClasses" :style="buttonStyle" @click="onClick">
|
||||||
<span v-if="props.category === 'system'" class="icon">
|
<span v-if="props.variant === 'videoPlay'" class="icon">
|
||||||
<AtomsIconsArrowRightFill />
|
<AtomsIconsArrowRightFill />
|
||||||
</span>
|
</span>
|
||||||
<span class="sr-only">Play</span>
|
<span class="sr-only">Play</span>
|
||||||
@@ -37,12 +37,11 @@ const onClick = () => sendLog(locale.value, props.tracking)
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.btn-play {
|
.btn-play {
|
||||||
@apply relative flex items-center justify-center;
|
@apply relative flex items-center justify-center rounded-full w-[60px] h-[60px] md:w-[80px] md:h-[80px];
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-icon {
|
.play-icon {
|
||||||
@apply w-[60px] h-[60px] md:w-[80px] md:h-[80px] rounded-full
|
@apply before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.5)] before:rounded-full
|
||||||
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.5)] before:rounded-full
|
|
||||||
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-[50%] after:opacity-0 after:transition-opacity after:duration-300 after:ease-in-out
|
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-[50%] after:opacity-0 after:transition-opacity after:duration-300 after:ease-in-out
|
||||||
hover:after:opacity-10;
|
hover:after:opacity-10;
|
||||||
}
|
}
|
||||||
@@ -54,16 +53,13 @@ const onClick = () => sendLog(locale.value, props.tracking)
|
|||||||
}
|
}
|
||||||
|
|
||||||
.play-image {
|
.play-image {
|
||||||
@apply w-[69px] h-[69px] md:w-[110px] md:h-[110px];
|
@apply overflow-hidden;
|
||||||
}
|
}
|
||||||
.play-image::before {
|
.play-image::before {
|
||||||
@apply content-[''] absolute inset-0 z-0 bg-no-repeat bg-center bg-cover bg-[url(/images/common/btn_play/btn_default.png)] transition-opacity duration-300 ease-out;
|
@apply content-[''] absolute inset-0 z-0 rounded-full bg-no-repeat bg-center bg-cover bg-[url(/images/common/btn_play/btn_default_m.png)] md:bg-[url(/images/common/btn_play/btn_default.png)];
|
||||||
}
|
}
|
||||||
.play-image::after {
|
.play-image::after {
|
||||||
@apply content-[''] absolute inset-0 z-0 bg-no-repeat bg-center bg-cover bg-[url(/images/common/btn_play/btn_hover.png)] opacity-0 transition-opacity duration-300 ease-out;
|
@apply content-[''] absolute inset-0 z-0 rounded-full bg-no-repeat bg-center bg-cover bg-[url(/images/common/btn_play/btn_hover_m.png)] md:bg-[url(/images/common/btn_play/btn_hover.png)] opacity-0 transition-opacity duration-300 ease-out;
|
||||||
}
|
|
||||||
.play-image:hover::before {
|
|
||||||
@apply opacity-0;
|
|
||||||
}
|
}
|
||||||
.play-image:hover::after {
|
.play-image:hover::after {
|
||||||
@apply opacity-100;
|
@apply opacity-100;
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ interface props {
|
|||||||
type?: ButtonType
|
type?: ButtonType
|
||||||
size?: string
|
size?: string
|
||||||
variant?: ButtonVariant
|
variant?: ButtonVariant
|
||||||
target?: '_self' | '_blank'
|
|
||||||
href?: string
|
href?: string
|
||||||
backgroundColor?: string
|
backgroundColor?: string
|
||||||
textColor?: string
|
textColor?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
gradient?: boolean
|
useGradient?: boolean
|
||||||
useGameFont?: boolean
|
useGameFont?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ const props = withDefaults(defineProps<props>(), {
|
|||||||
target: '_self',
|
target: '_self',
|
||||||
textColor: 'var(--alternative-02)',
|
textColor: 'var(--alternative-02)',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
gradient: false,
|
useGradient: false,
|
||||||
useGameFont: false,
|
useGameFont: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -31,21 +30,20 @@ const { fontFamily } = storeToRefs(gameDataStore)
|
|||||||
const componentTag = computed((): string => {
|
const componentTag = computed((): string => {
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'external':
|
case 'external':
|
||||||
case 'link':
|
|
||||||
return 'a'
|
return 'a'
|
||||||
case 'download':
|
case 'download':
|
||||||
return props.href ? 'a' : 'button'
|
return props.href ? 'a' : 'button'
|
||||||
case 'internal':
|
case 'internal':
|
||||||
return props.href ? 'AtomsLocaleLink' : 'button'
|
return 'AtomsLocaleLink'
|
||||||
default:
|
default:
|
||||||
return 'button'
|
return 'button'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const componentProps = computed(() => {
|
const componentProps = computed(() => {
|
||||||
if (props.type === 'external' || props.type === 'link') {
|
if (props.type === 'external') {
|
||||||
return {
|
return {
|
||||||
href: props.href,
|
href: props.href,
|
||||||
target: props.target,
|
target: '_blank',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +51,7 @@ const componentProps = computed(() => {
|
|||||||
if (props.href) {
|
if (props.href) {
|
||||||
return {
|
return {
|
||||||
to: props.href,
|
to: props.href,
|
||||||
|
target: '_self',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
@@ -106,7 +105,8 @@ const textStyle = computed(() => {
|
|||||||
:style="buttonStyle"
|
:style="buttonStyle"
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
>
|
>
|
||||||
<i v-if="props.gradient" class="btn-gradient"></i>
|
<!-- 그라데이션 -->
|
||||||
|
<i v-if="props.useGradient" class="btn-gradient"></i>
|
||||||
<span class="btn-content" :style="textStyle">
|
<span class="btn-content" :style="textStyle">
|
||||||
<slot />
|
<slot />
|
||||||
<AtomsIconsLongArrowRightLine
|
<AtomsIconsLongArrowRightLine
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const analytics = {
|
|||||||
<template>
|
<template>
|
||||||
<AtomsButtonCircle
|
<AtomsButtonCircle
|
||||||
sr-only="home"
|
sr-only="home"
|
||||||
type="link"
|
type="internal"
|
||||||
to="/home"
|
href="/home"
|
||||||
class="btn-home"
|
class="btn-home"
|
||||||
background-color="rgb(0 0 0 / 0.2)"
|
background-color="rgb(0 0 0 / 0.2)"
|
||||||
@click="sendLog(locale, analytics)"
|
@click="sendLog(locale, analytics)"
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { CSSProperties, Component } from 'vue'
|
import type { CSSProperties } from 'vue'
|
||||||
import type { PlatformTransformType } from '#layers/types/api/gameData'
|
import type { PlatformTransformType } from '#layers/types/api/gameData'
|
||||||
import type {
|
import type {
|
||||||
DownloadButtonType,
|
LauncherButtonType,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
Platform,
|
Platform,
|
||||||
} from '#layers/types/components/button'
|
} from '#layers/types/components/button'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type?: DownloadButtonType
|
type?: LauncherButtonType
|
||||||
platform: Platform
|
platform: Platform
|
||||||
variant?: ButtonVariant
|
variant?: ButtonVariant
|
||||||
backgroundColor?: string
|
backgroundColor?: string
|
||||||
textColor?: string
|
textColor?: string
|
||||||
iconComponent?: Component
|
|
||||||
iconProps?: Record<string, any>
|
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
useGameFont?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
type: 'default',
|
type: 'default',
|
||||||
variant: 'filled',
|
variant: 'filled',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
useGameFont: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig()
|
const runtimeConfig = useRuntimeConfig()
|
||||||
@@ -33,7 +29,7 @@ const gameDataStore = useGameDataStore()
|
|||||||
const modalStore = useModalStore()
|
const modalStore = useModalStore()
|
||||||
const { isProcessing, validateLauncher } = useCheckGameStart()
|
const { isProcessing, validateLauncher } = useCheckGameStart()
|
||||||
|
|
||||||
const { gameName, platformType, osType, marketJson, fontFamily } =
|
const { gameName, platformType, osType, marketJson } =
|
||||||
storeToRefs(gameDataStore)
|
storeToRefs(gameDataStore)
|
||||||
|
|
||||||
const PLATFORM_ICON_MAP: Record<Platform, string> = {
|
const PLATFORM_ICON_MAP: Record<Platform, string> = {
|
||||||
@@ -55,11 +51,6 @@ const componentTag = computed(() => {
|
|||||||
}
|
}
|
||||||
return 'button'
|
return 'button'
|
||||||
})
|
})
|
||||||
const shouldShowPlatformIcon = computed(
|
|
||||||
() =>
|
|
||||||
(props.type === 'default' && props.variant !== 'custom') ||
|
|
||||||
props.type === 'single'
|
|
||||||
)
|
|
||||||
const shouldShowDownloadIcon = computed(
|
const shouldShowDownloadIcon = computed(
|
||||||
() =>
|
() =>
|
||||||
props.platform === 'pc' &&
|
props.platform === 'pc' &&
|
||||||
@@ -91,9 +82,6 @@ const textStyle = computed<CSSProperties>(() => {
|
|||||||
if (props.textColor) {
|
if (props.textColor) {
|
||||||
style.color = props.textColor
|
style.color = props.textColor
|
||||||
}
|
}
|
||||||
if (props.useGameFont && fontFamily.value) {
|
|
||||||
style.fontFamily = fontFamily.value
|
|
||||||
}
|
|
||||||
|
|
||||||
return style
|
return style
|
||||||
})
|
})
|
||||||
@@ -158,24 +146,19 @@ const handleClick = () => {
|
|||||||
:is="componentTag"
|
:is="componentTag"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:class="['btn-base', props.type, { 'no-text': !$slots.default }]"
|
:class="['btn-base', props.type, { 'no-text': !$slots.default }]"
|
||||||
:data-variant="props.variant"
|
|
||||||
:data-platform="props.platform"
|
:data-platform="props.platform"
|
||||||
|
:data-variant="props.variant"
|
||||||
:style="buttonStyle"
|
:style="buttonStyle"
|
||||||
:disabled="disabled || isProcessing"
|
:disabled="disabled || isProcessing"
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
>
|
>
|
||||||
<span class="btn-content">
|
<span class="btn-content">
|
||||||
<span v-if="shouldShowPlatformIcon" class="icon-platform">
|
<span v-if="props.type !== 'duplication'" class="icon-platform">
|
||||||
<component :is="platformIcon" />
|
<component :is="platformIcon" />
|
||||||
</span>
|
</span>
|
||||||
<span class="text" :style="textStyle">
|
<span class="text" :style="textStyle">
|
||||||
<slot />
|
<slot />
|
||||||
</span>
|
</span>
|
||||||
<component
|
|
||||||
:is="props.iconComponent"
|
|
||||||
v-if="props.iconComponent"
|
|
||||||
v-bind="props.iconProps"
|
|
||||||
/>
|
|
||||||
<span v-if="shouldShowDownloadIcon" class="icon-download">
|
<span v-if="shouldShowDownloadIcon" class="icon-download">
|
||||||
<AtomsIconsDownloadLine />
|
<AtomsIconsDownloadLine />
|
||||||
</span>
|
</span>
|
||||||
@@ -193,9 +176,6 @@ const handleClick = () => {
|
|||||||
.icon-platform {
|
.icon-platform {
|
||||||
@apply w-5 h-5 mr-2 flex-shrink-0;
|
@apply w-5 h-5 mr-2 flex-shrink-0;
|
||||||
}
|
}
|
||||||
.icon-download {
|
|
||||||
@apply ml-auto pl-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-base[data-variant='filled'] {
|
.btn-base[data-variant='filled'] {
|
||||||
@apply bg-[#383838] text-[#ffffff]
|
@apply bg-[#383838] text-[#ffffff]
|
||||||
@@ -208,6 +188,9 @@ const handleClick = () => {
|
|||||||
@apply bg-white text-[#1F1F1F]
|
@apply bg-white text-[#1F1F1F]
|
||||||
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-black/10 before:rounded-lg;
|
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-black/10 before:rounded-lg;
|
||||||
}
|
}
|
||||||
|
.btn-base[data-variant='outlined']:hover {
|
||||||
|
@apply before:border-[#999];
|
||||||
|
}
|
||||||
.btn-base[data-variant='outlined'][data-platform='app_store'] svg,
|
.btn-base[data-variant='outlined'][data-platform='app_store'] svg,
|
||||||
.btn-base[data-variant='outlined'][data-platform='pc'] svg,
|
.btn-base[data-variant='outlined'][data-platform='pc'] svg,
|
||||||
.btn-base[data-variant='outlined'][data-platform='stove'] svg {
|
.btn-base[data-variant='outlined'][data-platform='stove'] svg {
|
||||||
@@ -226,13 +209,15 @@ const handleClick = () => {
|
|||||||
@apply line-clamp-2 text-[14px]
|
@apply line-clamp-2 text-[14px]
|
||||||
md:text-[16px];
|
md:text-[16px];
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-base.default[data-variant='outlined'] .icon-download {
|
.btn-base.default[data-variant='outlined'] .icon-download {
|
||||||
@apply border-black/10;
|
@apply border-black/10;
|
||||||
}
|
}
|
||||||
.btn-base.default[data-variant='outlined'] .icon-download svg {
|
.btn-base.default[data-variant='outlined'] .icon-download svg {
|
||||||
@apply fill-[#1F1F1F];
|
@apply fill-[#1F1F1F];
|
||||||
}
|
}
|
||||||
|
.icon-download {
|
||||||
|
@apply ml-auto pl-4;
|
||||||
|
}
|
||||||
|
|
||||||
/* duplication */
|
/* duplication */
|
||||||
.btn-base.duplication {
|
.btn-base.duplication {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import type { ColorObject, TrackingObject } from '#layers/types/api/common'
|
import type { ColorObject, TrackingObject } from '#layers/types/api/common'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
color: ColorObject
|
backgroundColor: ColorObject
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
@@ -19,7 +19,7 @@ const analytics = {
|
|||||||
|
|
||||||
const showBtn = computed(() => windowY.value > 0)
|
const showBtn = computed(() => windowY.value > 0)
|
||||||
const backgroundColor = computed(
|
const backgroundColor = computed(
|
||||||
() => getColorCodeFromData(props.color, 'none') ?? 'var(--primary)'
|
() => getColorCodeFromData(props.backgroundColor, 'none') ?? 'var(--primary)'
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleScrollToTop = () => {
|
const handleScrollToTop = () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const props = defineProps<Props>()
|
|||||||
const { locale } = useI18n()
|
const { locale } = useI18n()
|
||||||
const { sendLog } = useAnalytics()
|
const { sendLog } = useAnalytics()
|
||||||
|
|
||||||
const getArrowBgColor = (direction: 'prev' | 'next') => {
|
const getArrowBackgroundColor = (direction: 'prev' | 'next') => {
|
||||||
return (
|
return (
|
||||||
getColorCodeFromData(
|
getColorCodeFromData(
|
||||||
props.arrowsData?.[direction === 'prev' ? 0 : 1]?.display,
|
props.arrowsData?.[direction === 'prev' ? 0 : 1]?.display,
|
||||||
@@ -32,7 +32,7 @@ const handleArrowClick = (direction: 'prev' | 'next') => {
|
|||||||
<AtomsButtonCircle
|
<AtomsButtonCircle
|
||||||
sr-only="Previous"
|
sr-only="Previous"
|
||||||
class="splide-arrow splide__arrow--prev"
|
class="splide-arrow splide__arrow--prev"
|
||||||
:background-color="getArrowBgColor('prev')"
|
:background-color="getArrowBackgroundColor('prev')"
|
||||||
@click="handleArrowClick('prev')"
|
@click="handleArrowClick('prev')"
|
||||||
>
|
>
|
||||||
<AtomsIconsArrowRightLine color="#ffffff" />
|
<AtomsIconsArrowRightLine color="#ffffff" />
|
||||||
@@ -40,7 +40,7 @@ const handleArrowClick = (direction: 'prev' | 'next') => {
|
|||||||
<AtomsButtonCircle
|
<AtomsButtonCircle
|
||||||
sr-only="Next"
|
sr-only="Next"
|
||||||
class="splide-arrow splide__arrow--next"
|
class="splide-arrow splide__arrow--next"
|
||||||
:background-color="getArrowBgColor('next')"
|
:background-color="getArrowBackgroundColor('next')"
|
||||||
@click="handleArrowClick('next')"
|
@click="handleArrowClick('next')"
|
||||||
>
|
>
|
||||||
<AtomsIconsArrowRightLine color="#ffffff" />
|
<AtomsIconsArrowRightLine color="#ffffff" />
|
||||||
|
|||||||
@@ -59,9 +59,8 @@ const handleCopy = async () => {
|
|||||||
<template v-for="(item, key) in snsJson" :key="key">
|
<template v-for="(item, key) in snsJson" :key="key">
|
||||||
<AtomsButtonCircle
|
<AtomsButtonCircle
|
||||||
v-if="item.use_yn === 1 && item.url"
|
v-if="item.use_yn === 1 && item.url"
|
||||||
type="link"
|
type="external"
|
||||||
:to="item.url"
|
:href="item.url"
|
||||||
target="_blank"
|
|
||||||
:class="['btn-sns', key]"
|
:class="['btn-sns', key]"
|
||||||
:sr-only="key"
|
:sr-only="key"
|
||||||
@click="sendLog(locale, { ...analytics, click_item: key })"
|
@click="sendLog(locale, { ...analytics, click_item: key })"
|
||||||
@@ -79,6 +78,7 @@ const handleCopy = async () => {
|
|||||||
</AtomsButtonCircle>
|
</AtomsButtonCircle>
|
||||||
</template>
|
</template>
|
||||||
<AtomsButtonCircle
|
<AtomsButtonCircle
|
||||||
|
type="action"
|
||||||
class="btn-sns link"
|
class="btn-sns link"
|
||||||
sr-only="copy"
|
sr-only="copy"
|
||||||
@click="handleCopy"
|
@click="handleCopy"
|
||||||
|
|||||||
@@ -586,6 +586,9 @@ onMounted(() => {
|
|||||||
.btn-start:deep(.btn-base.default[data-variant='custom']) {
|
.btn-start:deep(.btn-base.default[data-variant='custom']) {
|
||||||
@apply w-full h-[48px] px-10 font-[700] text-[16px];
|
@apply w-full h-[48px] px-10 font-[700] text-[16px];
|
||||||
}
|
}
|
||||||
|
.btn-start:deep(.btn-base.default[data-variant='custom']) .icon-platform {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-start .nav-2depth {
|
.btn-start .nav-2depth {
|
||||||
@apply left-[unset] right-[-40px];
|
@apply left-[unset] right-[-40px];
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ onMounted(() => {
|
|||||||
<div v-if="isShowTopBtn" class="utile-wrap">
|
<div v-if="isShowTopBtn" class="utile-wrap">
|
||||||
<BlocksButtonScrollTop
|
<BlocksButtonScrollTop
|
||||||
v-if="isShowTopBtn"
|
v-if="isShowTopBtn"
|
||||||
:color="pageData?.top_btn_color_json"
|
:background-color="pageData?.top_btn_color_json"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|||||||
@@ -5,6 +5,37 @@ import type {
|
|||||||
} from '#layers/types/api/pageData'
|
} from '#layers/types/api/pageData'
|
||||||
import type { ButtonType } from '#layers/types/components/button'
|
import type { ButtonType } from '#layers/types/components/button'
|
||||||
|
|
||||||
|
/** 어드민 버튼 유형 (시스템 버튼 / 이미지 버튼) */
|
||||||
|
const BUTTON_CATEGORY = {
|
||||||
|
SYSTEM: 'SYSTEM', // 시스템 버튼
|
||||||
|
IMAGE: 'IMAGE', // 이미지 버튼
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/** 어드민 버튼 타입 */
|
||||||
|
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
|
||||||
|
|
||||||
|
const MARKET_TYPE = {
|
||||||
|
PC: 'pc',
|
||||||
|
GOOGLE_PLAY: 'google_play',
|
||||||
|
APP_STORE: 'app_store',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const LINK_TARGET = {
|
||||||
|
BLANK: '_blank',
|
||||||
|
} as const
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
resourcesData: PageDataResourceGroup[]
|
resourcesData: PageDataResourceGroup[]
|
||||||
buttonSize?: string
|
buttonSize?: string
|
||||||
@@ -25,15 +56,35 @@ const buttonList = computed<PageDataResourceGroup[]>(
|
|||||||
() => props.resourcesData ?? []
|
() => props.resourcesData ?? []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** 버튼 유형이 '시스템 버튼'인지 확인 */
|
||||||
|
const isSystemButton = (button: PageDataResourceGroup): boolean => {
|
||||||
|
// [TODO] 어디민 개발 후 수정 필요
|
||||||
|
return button.btn_info?.btn_category === BUTTON_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 getButtonType = (btnInfo?: PageDataResourceGroupBtnInfo): ButtonType => {
|
||||||
const btnType = btnInfo?.detail?.btn_type
|
const btnType = btnInfo?.detail?.btn_type
|
||||||
const target = btnInfo?.detail?.action?.link_target
|
const target = btnInfo?.detail?.action?.link_target
|
||||||
|
|
||||||
if (btnType === 'URL' && target) {
|
if (btnType === BUTTON_ACTION_TYPE.URL && target) {
|
||||||
return target === '_blank' ? 'external' : 'internal'
|
return target === LINK_TARGET.BLANK ? 'external' : 'internal'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btnType === 'DOWNLOAD') return 'download'
|
if (btnType === BUTTON_ACTION_TYPE.DOWNLOAD) return 'download'
|
||||||
|
|
||||||
return 'action'
|
return 'action'
|
||||||
}
|
}
|
||||||
@@ -44,19 +95,37 @@ const isRunButtonVisible = (btnInfo: PageDataResourceGroupBtnInfo): boolean => {
|
|||||||
const marketType = btnInfo?.detail?.market_type
|
const marketType = btnInfo?.detail?.market_type
|
||||||
|
|
||||||
switch (marketType) {
|
switch (marketType) {
|
||||||
case 'pc':
|
case MARKET_TYPE.PC:
|
||||||
return false
|
return false
|
||||||
case 'google_play':
|
case MARKET_TYPE.GOOGLE_PLAY:
|
||||||
return device.isAndroid
|
return device.isAndroid
|
||||||
case 'app_store':
|
case MARKET_TYPE.APP_STORE:
|
||||||
return device.isApple
|
return device.isApple
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadFile = async (url: string = '', osType: number = 0) => {
|
const openPopupModal = (detail: Record<string, any>) => {
|
||||||
if (osType === 1 && breakpoints.value?.isMobile) {
|
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') })
|
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_PC') })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -64,25 +133,22 @@ const downloadFile = async (url: string = '', osType: number = 0) => {
|
|||||||
const fileUrl = formatPathHost(url)
|
const fileUrl = formatPathHost(url)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await $fetch<Blob>(fileUrl, {
|
const blob = await $fetch<Blob>(fileUrl, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
})
|
})
|
||||||
|
|
||||||
const blob = res
|
|
||||||
const blobUrl = URL.createObjectURL(blob)
|
const blobUrl = URL.createObjectURL(blob)
|
||||||
|
const fileName = fileUrl.split('/').pop() ?? 'download'
|
||||||
|
|
||||||
const pathPart = fileUrl.split('/').pop() ?? 'download'
|
const anchor = document.createElement('a')
|
||||||
const a = document.createElement('a')
|
anchor.href = blobUrl
|
||||||
|
anchor.download = fileName
|
||||||
|
document.body.appendChild(anchor)
|
||||||
|
anchor.click()
|
||||||
|
anchor.remove()
|
||||||
|
|
||||||
a.href = blobUrl
|
|
||||||
a.download = pathPart
|
|
||||||
document.body.appendChild(a)
|
|
||||||
a.click()
|
|
||||||
a.remove()
|
|
||||||
|
|
||||||
// 메모리 정리
|
|
||||||
URL.revokeObjectURL(blobUrl)
|
URL.revokeObjectURL(blobUrl)
|
||||||
|
|
||||||
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Success') })
|
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Success') })
|
||||||
@@ -92,30 +158,24 @@ const downloadFile = async (url: string = '', osType: number = 0) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) => {
|
const handleButtonClick = (button: PageDataResourceGroup) => {
|
||||||
sendLog(locale.value, button.tracking)
|
sendLog(locale.value, button.tracking)
|
||||||
|
|
||||||
const btnDetail = button.btn_info?.detail
|
const btnDetail = button.btn_info?.detail
|
||||||
|
const btnType = btnDetail?.btn_type
|
||||||
|
|
||||||
switch (btnDetail?.btn_type) {
|
const handler = buttonClickHandlers[btnType]
|
||||||
case 'POP':
|
handler?.(btnDetail)
|
||||||
modalStore.handleOpenContent({
|
|
||||||
contentTitle: btnDetail?.title,
|
|
||||||
tabInfo: btnDetail?.tab_info,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
case 'ANCHOR':
|
|
||||||
scrollStore.scrollToAnchor(btnDetail?.page_ver_tmpl_name_en ?? '')
|
|
||||||
return
|
|
||||||
case 'MOV':
|
|
||||||
modalStore.handleOpenYoutube({ youtubeUrl: btnDetail.url ?? '' })
|
|
||||||
return
|
|
||||||
case 'DOWNLOAD':
|
|
||||||
downloadFile(btnDetail?.file_path, btnDetail?.os_type)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -126,35 +186,46 @@ const handleButtonClick = (button: PageDataResourceGroup) => {
|
|||||||
class="flex flex-wrap justify-center items-center gap-3 md:gap-4"
|
class="flex flex-wrap justify-center items-center gap-3 md:gap-4"
|
||||||
>
|
>
|
||||||
<template v-for="(button, index) in buttonList" :key="index">
|
<template v-for="(button, index) in buttonList" :key="index">
|
||||||
<template v-if="button.btn_info?.detail?.btn_type === 'RUN'">
|
<!-- 버튼 유형: 시스템 버튼 -->
|
||||||
<BlocksButtonLauncher
|
|
||||||
v-if="isRunButtonVisible(button.btn_info)"
|
|
||||||
type="duplication"
|
|
||||||
:platform="button.btn_info?.detail?.market_type"
|
|
||||||
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
|
|
||||||
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
|
|
||||||
:use-game-font="button.btn_info?.use_game_font === 1"
|
|
||||||
@click="handleButtonClick(button)"
|
|
||||||
>
|
|
||||||
{{ button.btn_info?.txt_btn_name }}
|
|
||||||
</BlocksButtonLauncher>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<AtomsButton
|
<AtomsButton
|
||||||
v-else
|
v-if="isSystemButton(button)"
|
||||||
:type="getButtonType(button.btn_info)"
|
:type="getButtonType(button.btn_info)"
|
||||||
:size="buttonSize"
|
:size="buttonSize"
|
||||||
:href="button.btn_info?.detail?.action?.url"
|
:href="button.btn_info?.detail?.action?.url"
|
||||||
:target="button.btn_info?.detail?.action?.link_target"
|
|
||||||
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
|
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
|
||||||
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
|
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
|
||||||
:disabled="button.btn_info?.detail?.btn_type === 'DEACTIVE'"
|
:disabled="isDisabled(button)"
|
||||||
:gradient="true"
|
:use-gradient="true"
|
||||||
:use-game-font="button.btn_info?.use_game_font === 1"
|
:use-game-font="usesGameFont(button.btn_info)"
|
||||||
@click="handleButtonClick(button)"
|
@click="handleButtonClick(button)"
|
||||||
>
|
>
|
||||||
{{ button.btn_info?.txt_btn_name }}
|
{{ button.btn_info?.txt_btn_name }}
|
||||||
</AtomsButton>
|
</AtomsButton>
|
||||||
|
|
||||||
|
<!-- 버튼 유형: 이미지 버튼 + 타입: 게임 실행 -->
|
||||||
|
<BlocksButtonLauncher
|
||||||
|
v-else-if="
|
||||||
|
isLauncherButton(button) && isRunButtonVisible(button.btn_info!)
|
||||||
|
"
|
||||||
|
type="duplication"
|
||||||
|
:platform="button.btn_info?.detail?.market_type"
|
||||||
|
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
|
||||||
|
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
|
||||||
|
@click="handleButtonClick(button)"
|
||||||
|
>
|
||||||
|
{{ button.btn_info?.txt_btn_name }}
|
||||||
|
</BlocksButtonLauncher>
|
||||||
|
|
||||||
|
<!-- 버튼 유형: 이미지 버튼 + 타입: 기타 -->
|
||||||
|
<!-- [TODO] api 개발 후 수정 필요 (background-image, alt 에 연결 필요) -->
|
||||||
|
<AtomsButtonImage
|
||||||
|
v-else-if="!isSystemButton(button) && !isLauncherButton(button)"
|
||||||
|
:href="button.btn_info?.detail?.action?.url"
|
||||||
|
:background-image="'/images/test.png'"
|
||||||
|
alt="test"
|
||||||
|
:disabled="isDisabled(button)"
|
||||||
|
@click="handleButtonClick(button)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
category?: 'system' | 'image'
|
variant?: 'videoPlay' | 'videoPlayImg'
|
||||||
resourcesData: PageDataResourceGroup
|
resourcesData: PageDataResourceGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ const handleVideoPlayClick = () => {
|
|||||||
<template>
|
<template>
|
||||||
<AtomsButtonPlay
|
<AtomsButtonPlay
|
||||||
v-motion-stagger
|
v-motion-stagger
|
||||||
:category="props.category"
|
:variant="props.variant"
|
||||||
:background-color="backgroundColor"
|
:background-color="backgroundColor"
|
||||||
:tracking="props.resourcesData.tracking"
|
:tracking="props.resourcesData.tracking"
|
||||||
@click="handleVideoPlayClick"
|
@click="handleVideoPlayClick"
|
||||||
|
|||||||
@@ -444,12 +444,11 @@ const handleMoveFocus = (target: 'pc' | 'mobile') => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<AtomsButton
|
<AtomsButton
|
||||||
type="link"
|
type="external"
|
||||||
size="size-small"
|
size="size-small"
|
||||||
background-color="#383838"
|
background-color="#383838"
|
||||||
text-color="#FFFFFF"
|
text-color="#FFFFFF"
|
||||||
class="w-full px-0"
|
class="btn-download"
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
:href="tm(`Download_Driver_${driver.driverCode}_Url`)"
|
:href="tm(`Download_Driver_${driver.driverCode}_Url`)"
|
||||||
@click="handleSendLog(`다운로드_${driver.driverText}`)"
|
@click="handleSendLog(`다운로드_${driver.driverText}`)"
|
||||||
@@ -527,12 +526,10 @@ table td {
|
|||||||
md:h-[80px] md:py-[14px] md:px-[20px] md:text-[16px] md:leading-[26px] md:tracking-[-0.48px];
|
md:h-[80px] md:py-[14px] md:px-[20px] md:text-[16px] md:leading-[26px] md:tracking-[-0.48px];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 플랫폼별 다운로드 Mobile Overflow Visible 처리 */
|
.btn-download {
|
||||||
.splide :deep(.splide__track) {
|
@apply w-full px-0;
|
||||||
overflow: visible !important;
|
|
||||||
}
|
}
|
||||||
|
.btn-download:deep(.icon-external) {
|
||||||
::v-deep([data-platform='stove']) .icon-platform {
|
@apply hidden;
|
||||||
display: none !important;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const descriptionData = computed(() =>
|
|||||||
getComponentGroup(props.components, 'description')
|
getComponentGroup(props.components, 'description')
|
||||||
)
|
)
|
||||||
const videoPlayData = computed(() =>
|
const videoPlayData = computed(() =>
|
||||||
getComponentGroup(props.components, 'videoPlay')
|
getComponentGroup(props.components, 'videoPlayImg')
|
||||||
)
|
)
|
||||||
// [TODO] api 수정 후 사용
|
// [TODO] api 수정 후 사용
|
||||||
// const videoPlayData = computed(() =>
|
// const videoPlayData = computed(() =>
|
||||||
@@ -51,7 +51,7 @@ const buttonListData = computed(() =>
|
|||||||
/>
|
/>
|
||||||
<WidgetsVideoPlay
|
<WidgetsVideoPlay
|
||||||
v-if="videoPlayData"
|
v-if="videoPlayData"
|
||||||
category="image"
|
variant="videoPlayImg"
|
||||||
:resources-data="videoPlayData"
|
:resources-data="videoPlayData"
|
||||||
/>
|
/>
|
||||||
<WidgetsButtonList
|
<WidgetsButtonList
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ const slideItemSize = {
|
|||||||
/>
|
/>
|
||||||
<WidgetsVideoPlay
|
<WidgetsVideoPlay
|
||||||
v-if="videoPlayData"
|
v-if="videoPlayData"
|
||||||
category="image"
|
variant="videoPlayImg"
|
||||||
:resources-data="videoPlayData"
|
:resources-data="videoPlayData"
|
||||||
/>
|
/>
|
||||||
<WidgetsSlideCenterHighlight
|
<WidgetsSlideCenterHighlight
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export interface PageDataResourceGroupResPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface PageDataResourceGroupBtnInfo extends ColorObject {
|
export interface PageDataResourceGroupBtnInfo extends ColorObject {
|
||||||
|
btn_category: string
|
||||||
txt_btn_name: string
|
txt_btn_name: string
|
||||||
detail: Record<string, any>
|
detail: Record<string, any>
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
export type ButtonType =
|
export type ButtonType = 'internal' | 'external' | 'download' | 'action'
|
||||||
| 'internal'
|
|
||||||
| 'external'
|
|
||||||
| 'download'
|
|
||||||
| 'action'
|
|
||||||
| 'link'
|
|
||||||
|
|
||||||
export type DownloadButtonType = 'default' | 'single' | 'duplication'
|
export type ImageButtonType = 'internal' | 'external' | 'action'
|
||||||
|
|
||||||
|
export type LauncherButtonType = 'default' | 'duplication' | 'single'
|
||||||
|
|
||||||
export type ButtonSize = 'large' | 'medium' | 'small' | 'extra-small'
|
export type ButtonSize = 'large' | 'medium' | 'small' | 'extra-small'
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 582 KiB After Width: | Height: | Size: 7.4 KiB |
BIN
public/images/common/btn_play/btn_default_m.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 23 KiB |
BIN
public/images/common/btn_play/btn_hover_m.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/images/test.png
Normal file
|
After Width: | Height: | Size: 15 KiB |