135 lines
3.7 KiB
Vue
135 lines
3.7 KiB
Vue
<script setup lang="ts">
|
|
import { useTemplateRegistry } from '#layers/composables/useTemplateRegistry'
|
|
import { useGameDataStore } from '#layers/stores/useGameDataStore'
|
|
import type {
|
|
PageDataMetaTag,
|
|
PageDataTemplate,
|
|
} from '#layers/types/api/pageData'
|
|
|
|
const { tm, locale } = useI18n()
|
|
const { getTemplateComponent } = useTemplateRegistry()
|
|
const loadingStore = useLoadingStore()
|
|
const pageDataStore = usePageDataStore()
|
|
const gameDataStore = useGameDataStore()
|
|
const modalStore = useModalStore()
|
|
|
|
const { isPAssApiLoading, hasApiCallStarted } = storeToRefs(loadingStore)
|
|
const { gameMetaTag } = storeToRefs(gameDataStore)
|
|
const {
|
|
pageTemplates,
|
|
pageMetaTag,
|
|
isUseMetaTag,
|
|
isUseTopBtn,
|
|
isUseSnsBtn,
|
|
isUseLnb,
|
|
isLoginRequired,
|
|
} = storeToRefs(pageDataStore)
|
|
|
|
const getTemplateKey = (template: PageDataTemplate, index: number) => {
|
|
return `${template.page_ver_tmpl_name_en}-${Number.isFinite(Number(template.tmpl_sort_order)) ? Number(template.tmpl_sort_order) : index}`
|
|
}
|
|
|
|
// SEO 메타 태그 설정
|
|
const buildSeoMetaPayload = (metaTag: PageDataMetaTag) => ({
|
|
title: metaTag?.page_title ?? '',
|
|
description: metaTag?.page_desc ?? '',
|
|
ogTitle: metaTag?.og_title ?? '',
|
|
ogDescription: metaTag?.og_desc ?? '',
|
|
ogImage: formatPathHost(metaTag?.og_image) ?? '',
|
|
twitterTitle: metaTag?.x_title ?? '',
|
|
twitterImage: formatPathHost(metaTag?.x_image) ?? '',
|
|
twitterDescription: metaTag?.x_desc ?? '',
|
|
})
|
|
|
|
// SEO 메타 태그 설정
|
|
const setupSeoMeta = (metaTag: PageDataMetaTag) => {
|
|
useSeoMeta(buildSeoMetaPayload(metaTag))
|
|
}
|
|
|
|
// 메타 태그 설정 감시
|
|
let lastSeoMetaFingerprint = ''
|
|
watch(
|
|
[gameMetaTag, isUseMetaTag, pageMetaTag],
|
|
([gameMeta, usePageMeta, pageMeta]) => {
|
|
// 개별 메타 사용 페이지면 pageMeta로, 아니면 게임 메타로 fallback
|
|
const metaToUse = usePageMeta && pageMeta ? pageMeta : gameMeta
|
|
if (!metaToUse) return
|
|
|
|
const fingerprint = JSON.stringify(buildSeoMetaPayload(metaToUse))
|
|
if (fingerprint === lastSeoMetaFingerprint) return
|
|
lastSeoMetaFingerprint = fingerprint
|
|
setupSeoMeta(metaToUse)
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
watch(isPAssApiLoading, newVal => {
|
|
if (newVal) {
|
|
loadingStore.stopFullLoading()
|
|
}
|
|
})
|
|
|
|
onMounted(() => {
|
|
const { sendLog } = useAnalytics()
|
|
sendLog(locale.value, 'view')
|
|
|
|
if (!hasApiCallStarted.value) {
|
|
loadingStore.stopFullLoading()
|
|
}
|
|
|
|
// 페이지 접근 권한 설정(로그인 유무)
|
|
if (isLoginRequired.value && !csrGetAccessToken()) {
|
|
modalStore.handleOpenConfirm({
|
|
contentText: tm('Alert_StoveLogin'),
|
|
confirmButtonText: tm('Text_StoveLogin'),
|
|
confirmButtonEvent: () => {
|
|
csrGoStoveLogin()
|
|
},
|
|
})
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="content-wrap">
|
|
<template
|
|
v-for="(template, index) in pageTemplates"
|
|
:key="getTemplateKey(template, index)"
|
|
>
|
|
<component
|
|
:is="getTemplateComponent(template.template_code)"
|
|
:id="template.page_ver_tmpl_name_en"
|
|
:components="template.page_ver_tmpl_json"
|
|
:page-ver-tmpl-seq="template.page_ver_tmpl_seq"
|
|
:page-ver-tmpl-name-en="template.page_ver_tmpl_name_en"
|
|
/>
|
|
</template>
|
|
</div>
|
|
<ClientOnly>
|
|
<BlocksLnb v-if="isUseLnb" />
|
|
<div v-if="isUseTopBtn" class="utile-wrap">
|
|
<BlocksButtonScrollTop v-if="isUseTopBtn" />
|
|
</div>
|
|
</ClientOnly>
|
|
<BlocksSns v-if="isUseSnsBtn" />
|
|
</template>
|
|
|
|
<style scoped>
|
|
.empty-game + main .content-wrap {
|
|
@apply pt-0;
|
|
}
|
|
.content-wrap {
|
|
@apply relative pt-[48px] md:pt-[64px];
|
|
}
|
|
.utile-wrap {
|
|
@apply fixed flex flex-col items-end z-[100]
|
|
bottom-[12px] right-[12px] gap-2 md:bottom-[40px] md:right-[40px] md:gap-3;
|
|
}
|
|
|
|
[data-theme='light'] {
|
|
.content-wrap {
|
|
@apply bg-theme-foreground;
|
|
}
|
|
}
|
|
</style>
|