feat. 공통 로그 변경, 고정 템플릿 로그 추가

This commit is contained in:
clkim
2025-12-15 15:25:32 +09:00
parent 966c66fe7b
commit f955b76e62
39 changed files with 670 additions and 795 deletions

View File

@@ -1,3 +1,184 @@
<script setup lang="ts">
import type {
FooterMenuItem,
FooterData,
DevCiConfig,
} from '#layers/types/components/footer'
// Configuration
const runtimeConfig = useRuntimeConfig()
const dataResourcesUrl = runtimeConfig.public.dataResourcesUrl as string
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_footer.json'
// Multilingual
const resultGetMultilingual = await useGetMultilingual({
baseApiUrl: dataResourcesUrl,
fileName: multilingualFileName,
})
const { tm, locale }: any = useI18n({
useScope: 'local',
messages: Object(resultGetMultilingual?.value?.multilingual),
})
// Footer_caution 값이 있고 빈 객체가 아닌지 체크
const hasCautionText = computed(() => {
const value = tm('Footer_caution')
// null, undefined 체크
if (value === null || value === undefined) {
return false
}
// 빈 객체 체크
if (
typeof value === 'object' &&
!Array.isArray(value) &&
Object.keys(value).length === 0
) {
return false
}
// 문자열로 변환하여 빈 문자열 또는 '{}' 문자열 체크
const stringValue = String(value).trim()
if (stringValue === '' || stringValue === '{}') {
return false
}
return true
})
const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore)
// const path = ref<string>(`${staticUrl}/local/template/${gameData.value.s3_folder_name}`)
// 공통다국어 data
const footerLinks = computed((): FooterMenuItem[] => {
const menu = (tm as any)('Footer_Menu')
const menuItems = Array.isArray(menu) ? (menu as FooterMenuItem[]) : []
// ja일 때 fund_display_yn에 따라 id가 footerFund인 항목 처리
if (locale.value === 'ja') {
const fundDisplayYn = footerData.value?.fund_display_yn
const fundDisplayUrl = footerData.value?.fund_display_url
// id가 footerFund인 항목의 인덱스 찾기
const fundIndex = menuItems.findIndex(
(item: any) => item.id === 'footerFund'
)
// fund_display_yn이 'y'가 아니면 id가 footerFund인 항목 제거
if (!fundDisplayYn) {
return menuItems.filter((item: any) => item.id !== 'footerFund')
}
// fund_display_yn이 'y'이면 id가 footerFund인 항목의 url 설정
if (fundDisplayYn && fundIndex !== -1) {
const updatedMenuItems = [...menuItems]
updatedMenuItems[fundIndex] = {
...updatedMenuItems[fundIndex],
url: fundDisplayUrl || updatedMenuItems[fundIndex].url,
}
return updatedMenuItems
}
}
return menuItems
})
const footerData = ref(gameData.value?.footer_json as unknown as FooterData)
const setDevCi = ref<DevCiConfig>({
dev_ci_yn: gameData.value?.footer_dev_ci_img_yn as boolean,
dev_ci_img_path: gameData.value?.footer_dev_ci_img_path as string,
})
const useGameRating = computed<boolean>(() => {
return footerData.value.use_game_rating
})
///local/template/common/grades_age
const getGameRatingImage = computed((): { type: string; image: string } => {
// 안전하게 rating_type 값 확인
if (
!footerData.value?.game_rating_info?.rating_type ||
typeof footerData.value.game_rating_info.rating_type !== 'string'
) {
return { type: '', image: '' }
}
const contentInfo = footerData.value.game_rating_info.rating_type
const ratingType = contentInfo.trim()
// 빈 문자열인 경우 처리
if (!ratingType) {
return { type: '', image: '' }
}
const ageTypeMap: Record<string, string> = {
'6': 'Type6',
'12': 'Type12',
'15': 'Type15',
'18': 'Type18',
'19': 'Type19',
all: 'TypeAll',
e: 'TypeExempt',
}
const type = ageTypeMap[ratingType as keyof typeof ageTypeMap] || 'TypeTest'
return {
type,
image: formatPathHost(
`/images/common/grades_age/${locale.value}/${type}.svg`,
{
imageType: 'common',
}
),
}
})
const getContentInfoImage = computed((): string[] => {
// 안전하게 content_info 값 확인
if (
!footerData.value?.game_rating_info?.content_info ||
typeof footerData.value.game_rating_info.content_info !== 'string'
) {
return []
}
const contentInfo = footerData.value.game_rating_info.content_info.split(',')
contentInfo.pop()
const contentTypeMap: Record<string, string> = {
'1': 'Type-sexual',
'2': 'Type-violence',
'3': 'Type-fear',
'4': 'Type-inapposite',
'5': 'Type-drug',
'6': 'Type-crime',
'7': 'Type-speculation',
}
return contentInfo
.map(item => {
const type = contentTypeMap[item]
return type
? formatPathHost(`/images/common/grades_use/${type}.svg`, {
imageType: 'common',
})
: ''
})
.filter(Boolean)
})
const showAgeRating = ref<boolean>(false)
const toggleAgeRating = (): void => {
showAgeRating.value = !showAgeRating.value
}
const footerAgeRatingInfo = computed((): string[] => {
const info = (tm as any)('Footer_AgeRating_Info')
return Array.isArray(info) ? info : []
})
</script>
<template>
<footer id="footer" ref="footerRef" class="relative bg-blac">
<div
@@ -91,13 +272,22 @@
</div>
<!-- 정보 테이블 -->
<div v-if="locale === 'zh-tw'" class="px-6 py-6 rounded-b-lg bg-[#292929]">
<div
v-if="locale === 'zh-tw'"
class="px-6 py-6 rounded-b-lg bg-[#292929]"
>
<div class="space-y-2">
<div v-dompurify-html="tm('Footer_AgeRating_Caution')"></div>
<div
v-dompurify-html="tm('Footer_AgeRating_Caution')"
></div>
</div>
</div>
<div v-else class="px-6 py-6 rounded-b-lg bg-[#A31639]" :class="`bg-${getGameRatingImage.type}`">
<div
v-else
class="px-6 py-6 rounded-b-lg bg-[#A31639]"
:class="`bg-${getGameRatingImage.type}`"
>
<div class="space-y-2">
<div class="flex flex-start border-b border-white/10 pb-2">
<span class="text-white text-sm flex-1">
@@ -159,13 +349,12 @@
<div
class="language-area static md:absolute bottom-7 right-10 text-white mt-5 md:mt-0 md:bottom-5.5 md:right-4"
>
<BlocksLanguageSwitcher :language-order="tm('Footer_Language_Order')" />
<BlocksLanguageSwitcher
:language-order="tm('Footer_Language_Order')"
/>
</div>
<div
v-if="hasCautionText"
class="mt-6 md:mt-6 hidden sm:block"
>
<div v-if="hasCautionText" class="mt-6 md:mt-6 hidden sm:block">
<div
v-dompurify-html="tm('Footer_caution')"
class="text-xs text-white/30"
@@ -178,7 +367,11 @@
<div class="logo-area flex items-center gap-7 mt-6 md:mt-6">
<span>
<a :href="tm('Footer_Smilegate_Link')" target="_blank" class="smilegate">
<a
:href="tm('Footer_Smilegate_Link')"
target="_blank"
class="smilegate"
>
<img
:src="
formatPathHost(`/images/common/logo_smilegate.png`, {
@@ -225,183 +418,6 @@
</footer>
</template>
<script setup lang="ts">
import type {
FooterMenuItem,
FooterData,
DevCiConfig,
} from '#layers/types/Common'
// Configuration
const runtimeConfig = useRuntimeConfig()
const dataResourcesUrl = runtimeConfig.public.dataResourcesUrl as string
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_footer.json'
// Multilingual
const resultGetMultilingual = await useGetMultilingual({
baseApiUrl: dataResourcesUrl,
fileName: multilingualFileName,
})
const { tm, locale }: any = useI18n({
useScope: 'local',
messages: Object(resultGetMultilingual?.value?.multilingual),
})
// Footer_caution 값이 있고 빈 객체가 아닌지 체크
const hasCautionText = computed(() => {
const value = tm('Footer_caution')
// null, undefined 체크
if (value === null || value === undefined) {
return false
}
// 빈 객체 체크
if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {
return false
}
// 문자열로 변환하여 빈 문자열 또는 '{}' 문자열 체크
const stringValue = String(value).trim()
if (stringValue === '' || stringValue === '{}') {
return false
}
return true
})
const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore)
// const path = ref<string>(`${staticUrl}/local/template/${gameData.value.s3_folder_name}`)
// 공통다국어 data
const footerLinks = computed((): FooterMenuItem[] => {
const menu = (tm as any)('Footer_Menu')
const menuItems = Array.isArray(menu) ? (menu as FooterMenuItem[]) : []
// ja일 때 fund_display_yn에 따라 id가 footerFund인 항목 처리
if (locale.value === 'ja') {
const fundDisplayYn = footerData.value?.fund_display_yn
const fundDisplayUrl = footerData.value?.fund_display_url
// id가 footerFund인 항목의 인덱스 찾기
const fundIndex = menuItems.findIndex((item: any) => item.id === 'footerFund')
// fund_display_yn이 'y'가 아니면 id가 footerFund인 항목 제거
if (!fundDisplayYn) {
return menuItems.filter((item: any) => item.id !== 'footerFund')
}
// fund_display_yn이 'y'이면 id가 footerFund인 항목의 url 설정
if (fundDisplayYn && fundIndex !== -1) {
const updatedMenuItems = [...menuItems]
updatedMenuItems[fundIndex] = {
...updatedMenuItems[fundIndex],
url: fundDisplayUrl || updatedMenuItems[fundIndex].url
}
return updatedMenuItems
}
}
return menuItems
})
const footerData = ref(gameData.value?.footer_json as unknown as FooterData)
const setDevCi = ref<DevCiConfig>({
dev_ci_yn: gameData.value?.footer_dev_ci_img_yn as boolean,
dev_ci_img_path: gameData.value?.footer_dev_ci_img_path as string,
})
const useGameRating = computed<boolean>(() => {
return footerData.value.use_game_rating
})
///local/template/common/grades_age
const getGameRatingImage = computed((): { type: string, image: string } => {
// 안전하게 rating_type 값 확인
if (
!footerData.value?.game_rating_info?.rating_type ||
typeof footerData.value.game_rating_info.rating_type !== 'string'
) {
return { type: '', image: '' }
}
const contentInfo = footerData.value.game_rating_info.rating_type
const ratingType = contentInfo.trim()
// 빈 문자열인 경우 처리
if (!ratingType) {
return { type: '', image: '' }
}
const ageTypeMap: Record<string, string> = {
'6': 'Type6',
'12': 'Type12',
'15': 'Type15',
'18': 'Type18',
'19': 'Type19',
all: 'TypeAll',
e: 'TypeExempt',
}
const type = ageTypeMap[ratingType as keyof typeof ageTypeMap] || 'TypeTest'
return {
type,
image: formatPathHost(
`/images/common/grades_age/${locale.value}/${type}.svg`,
{
imageType: 'common',
}
),
}
})
const getContentInfoImage = computed((): string[] => {
// 안전하게 content_info 값 확인
if (
!footerData.value?.game_rating_info?.content_info ||
typeof footerData.value.game_rating_info.content_info !== 'string'
) {
return []
}
const contentInfo = footerData.value.game_rating_info.content_info.split(',')
contentInfo.pop()
const contentTypeMap: Record<string, string> = {
'1': 'Type-sexual',
'2': 'Type-violence',
'3': 'Type-fear',
'4': 'Type-inapposite',
'5': 'Type-drug',
'6': 'Type-crime',
'7': 'Type-speculation',
}
return contentInfo
.map(item => {
const type = contentTypeMap[item]
return type
? formatPathHost(`/images/common/grades_use/${type}.svg`, {
imageType: 'common',
})
: ''
})
.filter(Boolean)
})
const showAgeRating = ref<boolean>(false)
const toggleAgeRating = (): void => {
showAgeRating.value = !showAgeRating.value
}
const footerAgeRatingInfo = computed((): string[] => {
const info = (tm as any)('Footer_AgeRating_Info')
return Array.isArray(info) ? info : []
})
</script>
<style scoped>
em {
font-style: normal;
@@ -412,11 +428,11 @@ em {
}
.bg-Type12 {
background-color: #4369B1;
background-color: #4369b1;
}
.bg-Type15 {
background-color: #F9B846;
background-color: #f9b846;
}
.bg-Type18 {
@@ -424,11 +440,11 @@ em {
}
.bg-Type19 {
background-color: #A31639;
background-color: #a31639;
}
.bg-TypeAll {
background-color: #44A342;
background-color: #44a342;
}
.bg-TypeExempt {