fix. api 변경 관련 로직 변경

This commit is contained in:
clkim
2025-10-22 11:14:07 +09:00
parent dc369e8065
commit 8e0cdc9478
10 changed files with 80 additions and 98 deletions

View File

@@ -1,7 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { useNuxtApp } from 'nuxt/app' import { useNuxtApp } from 'nuxt/app'
import type { GameDataMetaTag, GameDataValue } from '#layers/types/api/gameData'
import { getResolvedHost } from '#layers/utils/styleUtil' import { getResolvedHost } from '#layers/utils/styleUtil'
import type {
GameDataFavicon,
GameDataMetaTag,
GameDataValue,
} from '#layers/types/api/gameData'
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
@@ -24,9 +28,9 @@ const getGameDataFromServer = (): GameDataValue | null => {
// 통합 메타데이터 설정 // 통합 메타데이터 설정
const setupAllMetaData = (data: GameDataValue) => { const setupAllMetaData = (data: GameDataValue) => {
const meta = data.meta_tag const meta = data.meta_tag_json ?? ({} as GameDataMetaTag)
const faviconPath = data.favicon_path const faviconPath = data.favicon_json ?? ({} as GameDataFavicon)
const theme = data.gnb.theme_type || 'dark' const theme = data.gnb?.theme_type ?? 'dark'
// 파비콘 링크 생성 // 파비콘 링크 생성
const faviconLinks = [ const faviconLinks = [
@@ -62,7 +66,7 @@ const setupAllMetaData = (data: GameDataValue) => {
] ]
// 색상 CSS 변수 생성 // 색상 CSS 변수 생성
const cssVariables = Object.entries(data.key_code_codes) const cssVariables = Object.entries(data.key_color_json ?? {})
.map(([key, value]) => `--${key}: ${value};`) .map(([key, value]) => `--${key}: ${value};`)
.join('\n ') .join('\n ')
@@ -73,7 +77,7 @@ const setupAllMetaData = (data: GameDataValue) => {
` `
useHead({ useHead({
title: meta.page_title, title: meta?.page_title ?? '',
meta: [ meta: [
{ name: 'description', content: meta.page_desc }, { name: 'description', content: meta.page_desc },
{ property: 'og:title', content: meta.og_title }, { property: 'og:title', content: meta.og_title },
@@ -100,7 +104,7 @@ const setupAllMetaData = (data: GameDataValue) => {
// 메타 데이터 설정 // 메타 데이터 설정
const setupMetaData = (data: GameDataValue) => { const setupMetaData = (data: GameDataValue) => {
metaData.value = data.meta_tag metaData.value = data.meta_tag_json
setupAllMetaData(data) setupAllMetaData(data)
} }
@@ -121,10 +125,10 @@ gtag('event', 'screen_view', {
onMounted(() => { onMounted(() => {
useEventListener('scroll', scrollStore.updateScrollValue) useEventListener('scroll', scrollStore.updateScrollValue)
if (gameData.value?.comm_img) { if (gameData.value?.comm_img_json) {
gameData.value?.comm_img.groups.forEach(group => { gameData.value?.comm_img_json.groups.forEach(group => {
const cssVarName = `--${group.img_name}` const cssVarName = `--${group.img_name}`
const imageUrl = `url(${getResolvedHost(group.img_path.comm)})` const imageUrl = `url(${getResolvedHost(group.img_path?.comm ?? '')})`
document.documentElement.style.setProperty(cssVarName, imageUrl) document.documentElement.style.setProperty(cssVarName, imageUrl)
}) })

View File

@@ -10,7 +10,7 @@ const props = withDefaults(defineProps<Props>(), {
</script> </script>
<template> <template>
<video v-if="props.src"> <video v-if="props.src" v-bind="$attrs">
<source :src="props.src" :type="`video/${props.type}`" v-bind="$attrs" /> <source :src="props.src" :type="`video/${props.type}`" />
</video> </video>
</template> </template>

View File

@@ -1,39 +0,0 @@
<script setup lang="ts">
import type { ClassType } from '#layers/types/Common'
interface Props {
to: string
target?: string
class?: ClassType
}
const props = withDefaults(defineProps<Props>(), {
target: '',
class: '',
})
const componentTag = computed(() => {
return props.target === '_blank' ? 'a' : 'AtomsLocaleLink'
})
const componentProps = computed(() => {
if (props.target === '_blank') {
return {
href: props.to,
target: props.target,
class: props.class,
}
}
return {
to: props.to,
class: props.class,
}
})
</script>
<template>
<component :is="componentTag" v-bind="{ ...componentProps }">
<slot />
</component>
</template>

View File

@@ -9,7 +9,7 @@ const { gameData } = useGameDataStore()
const stoveInflowPath = runtimeConfig.public.stoveInflowPath const stoveInflowPath = runtimeConfig.public.stoveInflowPath
const stoveGameNo = runtimeConfig.public.stoveGameNo const stoveGameNo = runtimeConfig.public.stoveGameNo
const gnbData = gameData?.stove_gnb const gnbData = gameData?.stove_gnb_json
const languageCodes = computed(() => { const languageCodes = computed(() => {
if (Array.isArray(availableLocales)) { if (Array.isArray(availableLocales)) {

View File

@@ -201,7 +201,7 @@ onBeforeUnmount(() => {
Object.keys(gnbData?.menus).length - overflowNam, Object.keys(gnbData?.menus).length - overflowNam,
}" }"
> >
<BlocksHybridLink <AtomsLocaleLink
:to="gnbItem.url_path" :to="gnbItem.url_path"
:target="gnbItem.link_target" :target="gnbItem.link_target"
:class="['nav-1depth', { active: isNavItemActive(gnbItem) }]" :class="['nav-1depth', { active: isNavItemActive(gnbItem) }]"
@@ -211,7 +211,7 @@ onBeforeUnmount(() => {
v-if="gnbItem.children" v-if="gnbItem.children"
class="hidden md:block" class="hidden md:block"
/> />
</BlocksHybridLink> </AtomsLocaleLink>
<Transition name="fade"> <Transition name="fade">
<div v-if="gnbItem.children" class="nav-2depth"> <div v-if="gnbItem.children" class="nav-2depth">
<ul> <ul>
@@ -219,7 +219,7 @@ onBeforeUnmount(() => {
v-for="child in gnbItem.children" v-for="child in gnbItem.children"
:key="child.menu_name" :key="child.menu_name"
> >
<BlocksHybridLink <AtomsLocaleLink
:to="child.url_path" :to="child.url_path"
:target="child.link_target" :target="child.link_target"
> >
@@ -227,7 +227,7 @@ onBeforeUnmount(() => {
<AtomsIconsWebLinkLine <AtomsIconsWebLinkLine
v-if="child.link_target === '_blank'" v-if="child.link_target === '_blank'"
/> />
</BlocksHybridLink> </AtomsLocaleLink>
</li> </li>
</ul> </ul>
</div> </div>
@@ -250,20 +250,20 @@ onBeforeUnmount(() => {
Object.keys(gnbData?.menus).length - overflowNam, Object.keys(gnbData?.menus).length - overflowNam,
}" }"
> >
<BlocksHybridLink <AtomsLocaleLink
:to="gnbItem.url_path" :to="gnbItem.url_path"
:target="gnbItem.link_target" :target="gnbItem.link_target"
:class="`${isNavItemActive(gnbItem) ? 'active' : ''}`" :class="`${isNavItemActive(gnbItem) ? 'active' : ''}`"
> >
<span>{{ gnbItem.menu_name }}</span> <span>{{ gnbItem.menu_name }}</span>
</BlocksHybridLink> </AtomsLocaleLink>
<div v-if="gnbItem.children"> <div v-if="gnbItem.children">
<ul> <ul>
<li <li
v-for="child in gnbItem.children" v-for="child in gnbItem.children"
:key="child.menu_name" :key="child.menu_name"
> >
<BlocksHybridLink <AtomsLocaleLink
:to="child.url_path" :to="child.url_path"
:target="child.link_target" :target="child.link_target"
> >
@@ -271,7 +271,7 @@ onBeforeUnmount(() => {
<AtomsIconsWebLinkLine <AtomsIconsWebLinkLine
v-if="child.link_target === '_blank'" v-if="child.link_target === '_blank'"
/> />
</BlocksHybridLink> </AtomsLocaleLink>
</li> </li>
</ul> </ul>
</div> </div>
@@ -279,17 +279,19 @@ onBeforeUnmount(() => {
</div> </div>
</div> </div>
</div> </div>
<div class="event"> <div v-if="gameData?.event_banner" class="event">
<div class="nav-item"> <div class="nav-item">
<BlocksHybridLink <AtomsLocaleLink
:to="'/event'" :to="gameData.event_banner?.page_url"
:target="'_self'" :target="
gameData.event_banner?.link_type === 1 ? '_self' : '_blank'
"
class="nav-1depth text-gradient-pink" class="nav-1depth text-gradient-pink"
> >
<AtomsIconsStarFill /> <AtomsIconsStarFill />
<span>이벤트</span> <span>이벤트</span>
<AtomsIconsStarFill /> <AtomsIconsStarFill />
</BlocksHybridLink> </AtomsLocaleLink>
</div> </div>
</div> </div>
</nav> </nav>

View File

@@ -21,7 +21,8 @@ const shouldShowMetaTag = computed(() => props.pageData.meta_tag_type === 2)
// 템플릿 표시 여부 확인 // 템플릿 표시 여부 확인
const isTemplateVisible = (template: PageDataTemplate): boolean => { const isTemplateVisible = (template: PageDataTemplate): boolean => {
return Boolean( return Boolean(
template?.components && Object.keys(template.components).length > 0 template?.page_ver_tmpl_json &&
Object.keys(template?.page_ver_tmpl_json).length > 0
) )
} }
@@ -33,21 +34,21 @@ const visibleTemplates = computed(() =>
// SEO 메타 태그 설정 // SEO 메타 태그 설정
const setupSeoMeta = (metaTag: PageDataMetaTag) => { const setupSeoMeta = (metaTag: PageDataMetaTag) => {
useSeoMeta({ useSeoMeta({
title: metaTag.page_title ?? '', title: metaTag?.page_title ?? '',
description: metaTag.page_desc ?? '', description: metaTag?.page_desc ?? '',
ogTitle: metaTag.og_title ?? '', ogTitle: metaTag?.og_title ?? '',
ogDescription: metaTag.og_desc ?? '', ogDescription: metaTag?.og_desc ?? '',
ogImage: metaTag.og_image ?? '', ogImage: metaTag?.og_image ?? '',
twitterTitle: metaTag.x_title ?? '', twitterTitle: metaTag?.x_title ?? '',
twitterImage: metaTag.x_image ?? '', twitterImage: metaTag?.x_image ?? '',
twitterDescription: metaTag.x_desc ?? '', twitterDescription: metaTag?.x_desc ?? '',
}) })
} }
// 메타 태그 설정 감시 // 메타 태그 설정 감시
watchEffect(() => { watchEffect(() => {
if (shouldShowMetaTag.value && props.pageData.meta_tag) { if (shouldShowMetaTag.value && props.pageData?.meta_tag_json) {
setupSeoMeta(props.pageData.meta_tag) setupSeoMeta(props.pageData?.meta_tag_json)
} }
}) })
</script> </script>
@@ -60,7 +61,7 @@ watchEffect(() => {
> >
<component <component
:is="getTemplateComponent(template.template_code)" :is="getTemplateComponent(template.template_code)"
:components="template.components" :components="template.page_ver_tmpl_json"
:page-ver-tmpl-seq="template.page_ver_tmpl_seq" :page-ver-tmpl-seq="template.page_ver_tmpl_seq"
/> />
</template> </template>

View File

@@ -68,7 +68,7 @@ const handleButtonClick = (
const marketType = btnInfo?.detail?.market_type const marketType = btnInfo?.detail?.market_type
if (marketType) { if (marketType) {
const url = gameData?.market[marketType]?.url const url = gameData?.market_json[marketType]?.url
window.open(url, '_blank') window.open(url, '_blank')
return return
} }

View File

@@ -6,6 +6,7 @@ import {
getComponentGroup, getComponentGroup,
hasComponentGroup, hasComponentGroup,
} from '#layers/utils/dataUtil' } from '#layers/utils/dataUtil'
import { getResponsiveSrc } from '#layers/utils/styleUtil'
import type { Splide as SplideType } from '@splidejs/splide' import type { Splide as SplideType } from '@splidejs/splide'
import type { import type {
PageDataTemplateComponents, PageDataTemplateComponents,
@@ -88,6 +89,7 @@ const handleSplideMove = (_splide: SplideType, newIndex: number) => {
class="mt-2 text-left md:mt-5" class="mt-2 text-left md:mt-5"
/> />
<AtomsVideo <AtomsVideo
v-if="hasComponentGroup(item, 'video')"
:src="currentVideoSrc(item)" :src="currentVideoSrc(item)"
:autoplay="currentSlideIndex === index" :autoplay="currentSlideIndex === index"
muted muted

View File

@@ -22,9 +22,9 @@ export interface GameDataValue {
ga_code: string ga_code: string
design_theme: number design_theme: number
lang_codes: string[] lang_codes: string[]
key_code_codes: GameDataKeyCodeCodes key_color_json: GameDataKeyColors
use_game_font: boolean use_game_font: boolean
comm_sns_bg_color_code: string comm_sns_bg_color_json: string
comm_multilang_filename: string comm_multilang_filename: string
footer_dev_ci_img_yn: boolean footer_dev_ci_img_yn: boolean
footer_dev_ci_img_path: string footer_dev_ci_img_path: string
@@ -34,19 +34,20 @@ export interface GameDataValue {
gnb: GameDataGnb gnb: GameDataGnb
intro: GameDataIntro intro: GameDataIntro
inspection: Record<string, any> inspection: Record<string, any>
stove_gnb: GameDataStoveGnb stove_gnb_json: GameDataStoveGnb
favicon_path: GameDataFaviconPath favicon_json: GameDataFavicon
meta_tag: GameDataMetaTag meta_tag_json: GameDataMetaTag
sns: GameDataSns sns_json: GameDataSns
footer: string // JSON 문자열로 변경 footer_json: string // JSON 문자열로 변경
comm_img: GameDataCommImg comm_img_json: GameDataCommImg
market: Record<string, { url: string }> market_json: Record<string, { url: string }>
event_banner: GameDataEventBanner
} }
// ===== 세부 데이터 타입들 ===== // ===== 세부 데이터 타입들 =====
// 키 코드 코드 타입 // 키 코드 코드 타입
export interface GameDataKeyCodeCodes { export interface GameDataKeyColors {
primary: string primary: string
'text-primary': string 'text-primary': string
'text-secondary': string 'text-secondary': string
@@ -62,7 +63,7 @@ export interface GameDataGameFont {
} }
// 파비콘 경로 타입 // 파비콘 경로 타입
export interface GameDataFaviconPath { export interface GameDataFavicon {
'16_16': string '16_16': string
'32_32': string '32_32': string
'72_72': string '72_72': string
@@ -116,7 +117,7 @@ export interface GameDataCommImg {
// Global 설정 타입 // Global 설정 타입
export interface GameDataGlobal { export interface GameDataGlobal {
system_font: string // JSON 문자열로 변경 system_font: string // JSON 문자열로 변경
lang: string // JSON 문자열로 변경 lang_json: string // JSON 문자열로 변경
} }
// 트래킹 타입 // 트래킹 타입
@@ -129,7 +130,7 @@ export interface GameDataTracking {
// 버튼 타입 // 버튼 타입
export interface GameDataButton { export interface GameDataButton {
depth_type: number depth_type: number
button: string // JSON 문자열로 변경 button_json: string // JSON 문자열로 변경
} }
export type GameDataMenuChildren = Record<string, GameDataMenu> export type GameDataMenuChildren = Record<string, GameDataMenu>
@@ -144,7 +145,7 @@ export interface GameDataMenu {
url_path: string url_path: string
link_target: string link_target: string
children: GameDataMenuChildren children: GameDataMenuChildren
tracking: string | GameDataTracking // JSON 문자열 또는 객체로 변경 tracking_json: string | GameDataTracking // JSON 문자열 또는 객체로 변경
} }
// GNB 설정 타입 // GNB 설정 타입
@@ -180,6 +181,14 @@ export interface GameDataStoveGnb {
stove_install_button_visible: string stove_install_button_visible: string
} }
// 이벤트 배너 타입
export interface GameDataEventBanner {
link_type: 1 | 2
page_url: string
page_url_type: 1 | 2
promotion_name: string
}
// ===== API 관련 타입들 ===== // ===== API 관련 타입들 =====
// API 에러 응답 타입 // API 에러 응답 타입

View File

@@ -36,7 +36,7 @@ export interface PageDataValue {
lnb_text_color_code_active: string lnb_text_color_code_active: string
lnb_text_color_code_deactive: string lnb_text_color_code_deactive: string
lnb_menus: PageDataLnbMenu[] lnb_menus: PageDataLnbMenu[]
meta_tag: PageDataMetaTag meta_tag_json: PageDataMetaTag
templates: Record<string, PageDataTemplate> templates: Record<string, PageDataTemplate>
} }
@@ -50,7 +50,7 @@ export interface PageDataLnbMenu {
menu_name: string menu_name: string
target_type: number target_type: number
page_ver_tmpl_name_en: string page_ver_tmpl_name_en: string
// tracking: Record<string, PageDataTracking> tracking_json: Record<string, PageDataTracking>
} }
// 메타 태그 타입 // 메타 태그 타입
@@ -121,16 +121,19 @@ export type PageDataTemplateComponentSet = PageDataTemplateComponent & {
// 템플릿 컴포넌트 타입 - 세 가지 패턴 // 템플릿 컴포넌트 타입 - 세 가지 패턴
export type PageDataTemplateComponents = export type PageDataTemplateComponents =
| PageDataTemplateComponent // 단일 컴포넌트 패턴 | PageDataTemplateComponent // 단일 컴포넌트 패턴
| { group_sets: PageDataTemplateComponentSet[], arrow: PageDataArrowComponent } // 그룹 세트 패턴 | {
group_sets: PageDataTemplateComponentSet[]
arrow: PageDataArrowComponent
} // 그룹 세트 패턴
// 템플릿 타입 // 템플릿 타입
export interface PageDataTemplate { export interface PageDataTemplate {
page_ver_tmpl_seq: number page_ver_tmpl_seq: number
tmpl_sort_order: number
page_ver_tmpl_name: string page_ver_tmpl_name: string
page_ver_tmpl_name_en: string page_ver_tmpl_name_en: string
page_ver_tmpl_json: PageDataTemplateComponents
tmpl_sort_order: number
template_code: string template_code: string
components: PageDataTemplateComponents
} }
// ===== API 관련 타입들 ===== // ===== API 관련 타입들 =====