fix. config -> runtimeConfig 명칭 통일
This commit is contained in:
@@ -1,28 +1,39 @@
|
||||
<template>
|
||||
<header class="header">
|
||||
<BlocksStoveGnbNew class="min-h-[48px]" />
|
||||
|
||||
</header>
|
||||
<section class="inspection-section">
|
||||
<clientOnly>
|
||||
<!-- 로고 -->
|
||||
<div class="inspection-logo">
|
||||
<img :src="logoImgUrl" alt="logo" class="w-full h-full object-contain" />
|
||||
<img
|
||||
:src="logoImgUrl"
|
||||
alt="logo"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="inspection-content">
|
||||
<!-- 점검 메시지 -->
|
||||
|
||||
|
||||
<h1 class="inspection-title text-lg md:text-2xl">
|
||||
{{ tm('Inspection_Now_Maintenance') }}
|
||||
</h1>
|
||||
|
||||
<div class="inspection-cards">
|
||||
<!-- 점검 시간 카드 -->
|
||||
<div v-if="webInspectionData" class="inspection-card inspection-time-card">
|
||||
<h2 class="card-title text-base text-md md:text-lg">{{ tm('Inspection_Maintenance_Time') }}</h2>
|
||||
<div
|
||||
v-if="webInspectionData"
|
||||
class="inspection-card inspection-time-card"
|
||||
>
|
||||
<h2 class="card-title text-base text-md md:text-lg">
|
||||
{{ tm('Inspection_Maintenance_Time') }}
|
||||
</h2>
|
||||
<div class="inspection-time text-sm md:text-base font-medium">
|
||||
<div v-dompurify-html="getLocaleTimezone('', '')" class="time-row"></div>
|
||||
<div
|
||||
v-dompurify-html="getLocaleTimezone('', '')"
|
||||
class="time-row"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,12 +41,21 @@
|
||||
<div class="inspection-bottom-cards">
|
||||
<!-- 온스토브 카드 -->
|
||||
<div class="inspection-card inspection-stove-card">
|
||||
<h3 :class="{ 'text-center': !launchingStatus }" class="card-title text-base md:text-lg">
|
||||
<span v-if="!launchingStatus" v-dompurify-html="inspectionGameDuringMaintenance"></span>
|
||||
<span v-else v-dompurify-html="orgInspectionDuringMaintenance"></span>
|
||||
<h3
|
||||
:class="{ 'text-center': !launchingStatus }"
|
||||
class="card-title text-base md:text-lg"
|
||||
>
|
||||
<span
|
||||
v-if="!launchingStatus"
|
||||
v-dompurify-html="inspectionGameDuringMaintenance"
|
||||
></span>
|
||||
<span
|
||||
v-else
|
||||
v-dompurify-html="orgInspectionDuringMaintenance"
|
||||
></span>
|
||||
</h3>
|
||||
<div class="button-group justify-center">
|
||||
<!-- <a
|
||||
<!-- <a
|
||||
:href="communityUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@@ -46,49 +66,63 @@
|
||||
<AtomsIconsLongArrowRightLine :size="16" color="#1F1F1F" />
|
||||
</a> -->
|
||||
|
||||
<AtomsButtonVariant
|
||||
type="custom"
|
||||
class="inspection-btn inspection-btn-community color-black text-sm md:text-base"
|
||||
:class="{ 'inspection-btn-outline flex-1' : launchingStatus }"
|
||||
@click="handleCommunityClick"
|
||||
<AtomsButtonVariant
|
||||
type="custom"
|
||||
class="inspection-btn inspection-btn-community color-black text-sm md:text-base"
|
||||
:class="{ 'inspection-btn-outline flex-1': launchingStatus }"
|
||||
@click="handleCommunityClick"
|
||||
>
|
||||
<span>{{ tm('Inspection_Community_Btn') }}</span>
|
||||
<AtomsIconsLongArrowRightLine :size="16" color="#1F1F1F" />
|
||||
</AtomsButtonVariant>
|
||||
|
||||
<AtomsButtonVariant
|
||||
v-if="launchingStatus"
|
||||
type="custom"
|
||||
platform="pc"
|
||||
class="inspection-btn inspection-btn-primary w-auto color-black text-sm md:text-base flex-1"
|
||||
@click="handleGameStart"
|
||||
>
|
||||
<span>게임 시작</span>
|
||||
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<span>{{ tm('Inspection_Community_Btn') }}</span>
|
||||
<AtomsIconsLongArrowRightLine :size="16" color="#1F1F1F" />
|
||||
|
||||
</AtomsButtonVariant>
|
||||
|
||||
<AtomsButtonVariant
|
||||
v-if="launchingStatus"
|
||||
type="custom"
|
||||
platform="pc"
|
||||
class="inspection-btn inspection-btn-primary w-auto color-black text-sm md:text-base flex-1"
|
||||
@click="handleGameStart"
|
||||
>
|
||||
<span>게임 시작</span>
|
||||
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3098 1.49172C8.86574 1.28049 7.15098 1.28055 5.70176 1.49167C3.50821 1.81315 1.81986 3.50786 1.49213 5.69168L1.4918 5.69391C1.38564 6.41904 1.33331 7.19181 1.33331 7.99998C1.33331 8.80815 1.3857 9.58136 1.49187 10.3065C1.81362 12.4934 3.50335 14.1805 5.69381 14.5079L5.69577 14.5082C6.42109 14.6143 7.19417 14.6666 7.99717 14.6666C8.80032 14.6666 9.57311 14.6143 10.3035 14.5083L10.3046 14.5082C12.4928 14.1865 14.1802 12.4917 14.5078 10.3083L14.5082 10.3061C14.6143 9.58092 14.6666 8.80815 14.6666 7.99998C14.6666 7.19527 14.6203 6.42148 14.5137 5.69347C14.1921 3.50726 12.4966 1.81316 10.3098 1.49172ZM6.38756 8.95267C6.39301 9.15365 6.40004 9.35195 6.40866 9.54742L6.40968 9.57054C6.41945 9.78867 6.43118 10.0033 6.44489 10.2141C6.45959 10.4433 6.68743 10.5836 6.88293 10.4823C7.22837 10.3029 7.58116 10.1096 7.9413 9.90379C8.20002 9.7541 8.46167 9.6013 8.72479 9.43914C8.98791 9.27854 9.24516 9.11482 9.49505 8.95111C9.84196 8.72502 10.1771 8.49581 10.4961 8.26817C10.6769 8.14031 10.6769 7.85965 10.4961 7.7318C10.1771 7.50415 9.84343 7.2765 9.49505 7.04886C9.24516 6.88514 8.98791 6.72298 8.72479 6.56082C8.46167 6.39866 8.20002 6.2443 7.9413 6.09618C7.58263 5.89036 7.22837 5.69702 6.88293 5.5177C6.68743 5.41636 6.45959 5.55669 6.44489 5.78589C6.43118 5.99671 6.41945 6.21129 6.40968 6.42943L6.40866 6.45254C6.40004 6.64801 6.39301 6.84631 6.38756 7.0473C6.37874 7.3607 6.37433 7.67722 6.37433 7.99998C6.37433 8.32274 6.37874 8.64082 6.38756 8.95267Z" fill="#332C2A"/>
|
||||
</svg>
|
||||
</AtomsButtonVariant>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M10.3098 1.49172C8.86574 1.28049 7.15098 1.28055 5.70176 1.49167C3.50821 1.81315 1.81986 3.50786 1.49213 5.69168L1.4918 5.69391C1.38564 6.41904 1.33331 7.19181 1.33331 7.99998C1.33331 8.80815 1.3857 9.58136 1.49187 10.3065C1.81362 12.4934 3.50335 14.1805 5.69381 14.5079L5.69577 14.5082C6.42109 14.6143 7.19417 14.6666 7.99717 14.6666C8.80032 14.6666 9.57311 14.6143 10.3035 14.5083L10.3046 14.5082C12.4928 14.1865 14.1802 12.4917 14.5078 10.3083L14.5082 10.3061C14.6143 9.58092 14.6666 8.80815 14.6666 7.99998C14.6666 7.19527 14.6203 6.42148 14.5137 5.69347C14.1921 3.50726 12.4966 1.81316 10.3098 1.49172ZM6.38756 8.95267C6.39301 9.15365 6.40004 9.35195 6.40866 9.54742L6.40968 9.57054C6.41945 9.78867 6.43118 10.0033 6.44489 10.2141C6.45959 10.4433 6.68743 10.5836 6.88293 10.4823C7.22837 10.3029 7.58116 10.1096 7.9413 9.90379C8.20002 9.7541 8.46167 9.6013 8.72479 9.43914C8.98791 9.27854 9.24516 9.11482 9.49505 8.95111C9.84196 8.72502 10.1771 8.49581 10.4961 8.26817C10.6769 8.14031 10.6769 7.85965 10.4961 7.7318C10.1771 7.50415 9.84343 7.2765 9.49505 7.04886C9.24516 6.88514 8.98791 6.72298 8.72479 6.56082C8.46167 6.39866 8.20002 6.2443 7.9413 6.09618C7.58263 5.89036 7.22837 5.69702 6.88293 5.5177C6.68743 5.41636 6.45959 5.55669 6.44489 5.78589C6.43118 5.99671 6.41945 6.21129 6.40968 6.42943L6.40866 6.45254C6.40004 6.64801 6.39301 6.84631 6.38756 7.0473C6.37874 7.3607 6.37433 7.67722 6.37433 7.99998C6.37433 8.32274 6.37874 8.64082 6.38756 8.95267Z"
|
||||
fill="#332C2A"
|
||||
/>
|
||||
</svg>
|
||||
</AtomsButtonVariant>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 다운로드 카드 -->
|
||||
<div v-if="launchingStatus" class="inspection-card inspection-download-card">
|
||||
<div
|
||||
v-if="launchingStatus"
|
||||
class="inspection-card inspection-download-card"
|
||||
>
|
||||
<h3 class="card-title text-base md:text-lg">
|
||||
{{ tm('Inspection_Txt_Download') || '게임 다운로드' }}
|
||||
</h3>
|
||||
<div class="flex flex-row gap-3">
|
||||
<AtomsButtonLauncher
|
||||
v-for="(btn, index) in enabledMarkets" :key="index"
|
||||
:class="getButtonClass(btn.platform)"
|
||||
<AtomsButtonLauncher
|
||||
v-for="(btn, index) in enabledMarkets"
|
||||
:key="index"
|
||||
:class="getButtonClass(btn.platform)"
|
||||
class="h-[48px]"
|
||||
:platform="btn.platform as any"
|
||||
:url="btn.url"
|
||||
:type="btn.platform === 'pc' ? 'default' : 'single'"
|
||||
:platform="btn.platform as any"
|
||||
:url="btn.url"
|
||||
:type="btn.platform === 'pc' ? 'default' : 'single'"
|
||||
variant="outlined"
|
||||
>
|
||||
{{ getButtonText(btn.platform) }}
|
||||
{{ getButtonText(btn.platform) }}
|
||||
</AtomsButtonLauncher>
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,18 +131,17 @@
|
||||
</div>
|
||||
</clientOnly>
|
||||
</section>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { globalDateFormat } from '@seed-next/date';
|
||||
import { globalDateFormat } from '@seed-next/date'
|
||||
import { useCheckGameStart } from '#layers/composables/useGameStart'
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const rootPath = config.public.staticUrl
|
||||
const runType = config.public.runType
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const rootPath = runtimeConfig.public.staticUrl
|
||||
const runType = runtimeConfig.public.runType
|
||||
const translationApi = `${rootPath}/${runType}/test`
|
||||
|
||||
|
||||
// const isClient = import.meta.client
|
||||
|
||||
const inspectionStore = useInspectionStore()
|
||||
@@ -116,14 +149,13 @@ const { webInspectionData } = storeToRefs(inspectionStore)
|
||||
const gameDataStore = useGameDataStore()
|
||||
const { gameData } = storeToRefs(gameDataStore)
|
||||
|
||||
|
||||
const resultGetMultilingual = await useGetMultilingual({
|
||||
baseApiUrl: translationApi,
|
||||
fileName: 'test_common_inspection.json'
|
||||
fileName: 'test_common_inspection.json',
|
||||
})
|
||||
const i18n = useI18n({
|
||||
useScope: 'local',
|
||||
messages: Object(resultGetMultilingual.value.multilingual)
|
||||
const i18n = useI18n({
|
||||
useScope: 'local',
|
||||
messages: Object(resultGetMultilingual.value.multilingual),
|
||||
})
|
||||
const { locale } = i18n
|
||||
|
||||
@@ -133,8 +165,12 @@ const tm = ((key: string): string => {
|
||||
}) as (key: string) => string
|
||||
|
||||
// 타입 오류 해결을 위한 computed 속성
|
||||
const inspectionGameDuringMaintenance = computed(() => tm('Inspection_Game_During_Maintenance'))
|
||||
const orgInspectionDuringMaintenance = computed(() => tm('org_Inspection_During_Maintenance'))
|
||||
const inspectionGameDuringMaintenance = computed(() =>
|
||||
tm('Inspection_Game_During_Maintenance')
|
||||
)
|
||||
const orgInspectionDuringMaintenance = computed(() =>
|
||||
tm('org_Inspection_During_Maintenance')
|
||||
)
|
||||
|
||||
// locale에 따라 뒤에 KST 또는 UTC 추가 ko, en, zh-tw, ja
|
||||
// ko: (KST)
|
||||
@@ -149,25 +185,25 @@ const getLocaleTimezone = (localeType: string, region) => {
|
||||
switch (currentLocale) {
|
||||
case 'ko':
|
||||
return `
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || 'KR', {useFullDate: true})} (KST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', {useFullDate: true})} (UTC)
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || 'KR', { useFullDate: true })} (KST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', { useFullDate: true })} (UTC)
|
||||
`
|
||||
case 'en':
|
||||
return `${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', {useFullDate: true})} (UTC)`
|
||||
return `${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', { useFullDate: true })} (UTC)`
|
||||
case 'zh-tw':
|
||||
return `
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', {useFullDate: true})} (台灣時間)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', {useFullDate: true})} (UTC)
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', { useFullDate: true })} (台灣時間)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', { useFullDate: true })} (UTC)
|
||||
`
|
||||
case 'ja':
|
||||
return `
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', {useFullDate: true})} (JST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', {useFullDate: true})} (UTC)
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', { useFullDate: true })} (JST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', { useFullDate: true })} (UTC)
|
||||
`
|
||||
default:
|
||||
return `
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', {useFullDate: true})} (KST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', {useFullDate: true})} (UTC)
|
||||
${globalDateFormat(new Date(tsStartDate), currentLocale, region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), currentLocale, region || '', { useFullDate: true })} (KST)<br>
|
||||
${globalDateFormat(new Date(tsStartDate), 'en', region || '', { useFullDate: true })} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), 'en', region || '', { useFullDate: true })} (UTC)
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -176,7 +212,6 @@ const launchingStatus = computed(() => {
|
||||
return webInspectionData.value?.launching_status
|
||||
})
|
||||
|
||||
|
||||
// const market_json = {
|
||||
// pc: { url: 'https://apps.apple.com/app/id1234567890', use_yn: 0 },
|
||||
// app_store: { url: 'https://apps.apple.com/app/id1234567890', use_yn: 0 },
|
||||
@@ -185,21 +220,25 @@ const launchingStatus = computed(() => {
|
||||
|
||||
//gameData.value.market_json 값 중 use_yn === 1 인 항목만 배열로 변환
|
||||
const enabledMarkets = computed(() => {
|
||||
return Object.entries(gameData.value.market_json)
|
||||
// return Object.entries(market_json)
|
||||
.filter(([, info]: [string, any]) => info && info.use_yn === 1)
|
||||
.map(([platform, info]: [string, any]) => ({ platform, url: info.url as string }))
|
||||
return (
|
||||
Object.entries(gameData.value.market_json)
|
||||
// return Object.entries(market_json)
|
||||
.filter(([, info]: [string, any]) => info && info.use_yn === 1)
|
||||
.map(([platform, info]: [string, any]) => ({
|
||||
platform,
|
||||
url: info.url as string,
|
||||
}))
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
const logoImgUrl = computed(() => {
|
||||
const currentLocale = locale.value || 'ko'
|
||||
const currentLocale = locale.value || 'ko'
|
||||
const localeData = (webInspectionData.value as any)?.[currentLocale]
|
||||
return getImageHost(localeData.img_json.bi_large)
|
||||
})
|
||||
|
||||
const communityUrl = computed(() => {
|
||||
const currentLocale = locale.value || 'ko'
|
||||
const currentLocale = locale.value || 'ko'
|
||||
const localeData = (webInspectionData.value as any)?.[currentLocale]
|
||||
return localeData?.url_json?.community
|
||||
})
|
||||
@@ -211,7 +250,7 @@ const handleCommunityClick = () => {
|
||||
const getButtonClass = (platform: string) => {
|
||||
// pc가 있으면 pc만 flex-1, 나머지는 기본
|
||||
const hasPc = enabledMarkets.value.some(btn => btn.platform === 'pc')
|
||||
if(hasPc) {
|
||||
if (hasPc) {
|
||||
return platform === 'pc' ? `flex-1 btn-platform-pc` : ``
|
||||
}
|
||||
//pc가 없으면서 하나만 있으면 ''
|
||||
@@ -234,7 +273,7 @@ const getButtonText = (platform: string) => {
|
||||
if (platform === 'app_store') {
|
||||
return tm('platform_app_store')
|
||||
}
|
||||
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -246,15 +285,14 @@ const handleGameStart = () => {
|
||||
definePageMeta({
|
||||
middleware: ['inspection'],
|
||||
layout: 'only-stove',
|
||||
showLoading: false
|
||||
showLoading: false,
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.inspection-section {
|
||||
@apply flex flex-col items-center gap-10 px-10 py-[120px] pb-[200px] min-h-[calc(100vh-48px)];
|
||||
background-color: #F0F0F0;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.inspection-logo {
|
||||
@@ -283,7 +321,6 @@ definePageMeta({
|
||||
|
||||
.inspection-time-card {
|
||||
@apply flex flex-col items-center gap-4;
|
||||
|
||||
}
|
||||
|
||||
.card-title {
|
||||
@@ -328,7 +365,6 @@ definePageMeta({
|
||||
@apply flex items-center justify-center gap-1 px-6 md:px-8 w-auto h-10 md:h-12 rounded-lg;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
}
|
||||
|
||||
.inspection-btn span {
|
||||
|
||||
@@ -1,95 +1,146 @@
|
||||
<template>
|
||||
<div class="select-language" :class="{ 'language-changing': isChanging }">
|
||||
|
||||
<button
|
||||
:disabled="isChanging"
|
||||
class="flex items-center gap-2 px-3 py-2 rounded-lg text-[#CCCCCC] transition-all duration-300 w-[180px] bg-[#292929] border border-[#595959]"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': isChanging }"
|
||||
@click="toggleDropdown"
|
||||
>
|
||||
<!-- 지구본 아이콘 -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- 지구본 아이콘 -->
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clip-path="url(#clip0_5964_1685)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6666 8.00065C14.6666 11.6825 11.6818 14.6673 7.99992 14.6673C4.31802 14.6673 1.33325 11.6825 1.33325 8.00065C1.33325 4.31875 4.31802 1.33398 7.99992 1.33398C11.6818 1.33398 14.6666 4.31875 14.6666 8.00065ZM6.89756 13.2199C6.03596 11.8504 5.50924 10.2901 5.36895 8.66732H2.70785C2.99033 10.9326 4.69347 12.7567 6.89756 13.2199ZM2.70785 7.33398H5.36895C5.50924 5.71116 6.03596 4.15086 6.89756 2.78138C4.69347 3.24458 2.99033 5.06868 2.70785 7.33398ZM13.292 8.66732C13.0095 10.9326 11.3064 12.7567 9.10228 13.2199C9.96388 11.8504 10.4906 10.2901 10.6309 8.66732H13.292ZM13.292 7.33398C13.0095 5.06868 11.3064 3.24458 9.10228 2.78138C9.96388 4.15086 10.4906 5.71116 10.6309 7.33398H13.292ZM7.99992 12.468C7.28662 11.3201 6.84273 10.0202 6.70801 8.66732H9.29183C9.15711 10.0202 8.71322 11.3201 7.99992 12.468ZM6.70801 7.33398H9.29183C9.15711 5.98112 8.71322 4.68121 7.99992 3.5333C7.28662 4.68121 6.84273 5.98112 6.70801 7.33398Z" fill="#CCCCCC"/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M14.6666 8.00065C14.6666 11.6825 11.6818 14.6673 7.99992 14.6673C4.31802 14.6673 1.33325 11.6825 1.33325 8.00065C1.33325 4.31875 4.31802 1.33398 7.99992 1.33398C11.6818 1.33398 14.6666 4.31875 14.6666 8.00065ZM6.89756 13.2199C6.03596 11.8504 5.50924 10.2901 5.36895 8.66732H2.70785C2.99033 10.9326 4.69347 12.7567 6.89756 13.2199ZM2.70785 7.33398H5.36895C5.50924 5.71116 6.03596 4.15086 6.89756 2.78138C4.69347 3.24458 2.99033 5.06868 2.70785 7.33398ZM13.292 8.66732C13.0095 10.9326 11.3064 12.7567 9.10228 13.2199C9.96388 11.8504 10.4906 10.2901 10.6309 8.66732H13.292ZM13.292 7.33398C13.0095 5.06868 11.3064 3.24458 9.10228 2.78138C9.96388 4.15086 10.4906 5.71116 10.6309 7.33398H13.292ZM7.99992 12.468C7.28662 11.3201 6.84273 10.0202 6.70801 8.66732H9.29183C9.15711 10.0202 8.71322 11.3201 7.99992 12.468ZM6.70801 7.33398H9.29183C9.15711 5.98112 8.71322 4.68121 7.99992 3.5333C7.28662 4.68121 6.84273 5.98112 6.70801 7.33398Z"
|
||||
fill="#CCCCCC"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_5964_1685">
|
||||
<rect width="16" height="16" fill="#CCCCCC"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip0_5964_1685">
|
||||
<rect width="16" height="16" fill="#CCCCCC" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
<span class="flex-1 text-sm text-left transition-all duration-300">
|
||||
{{ isChanging ? '언어 변경 중...' : getLanguageName(selectedLocale) }}
|
||||
</span>
|
||||
<!-- 로딩 스피너 -->
|
||||
<svg v-if="isChanging" class="w-3 h-3 animate-spin" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" stroke="#CCCCCC" stroke-width="2" stroke-linecap="round" stroke-dasharray="31.416" stroke-dashoffset="31.416">
|
||||
<animate attributeName="stroke-dasharray" dur="2s" values="0 31.416;15.708 15.708;0 31.416" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-dashoffset" dur="2s" values="0;-15.708;-31.416" repeatCount="indefinite"/>
|
||||
<svg
|
||||
v-if="isChanging"
|
||||
class="w-3 h-3 animate-spin"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="#CCCCCC"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray="31.416"
|
||||
stroke-dashoffset="31.416"
|
||||
>
|
||||
<animate
|
||||
attributeName="stroke-dasharray"
|
||||
dur="2s"
|
||||
values="0 31.416;15.708 15.708;0 31.416"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
<animate
|
||||
attributeName="stroke-dashoffset"
|
||||
dur="2s"
|
||||
values="0;-15.708;-31.416"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</circle>
|
||||
</svg>
|
||||
<!-- 드롭다운 화살표 -->
|
||||
<svg
|
||||
v-else
|
||||
class="w-3 h-3 text-gray-300 transition-transform duration-200"
|
||||
<svg
|
||||
v-else
|
||||
class="w-3 h-3 text-gray-300 transition-transform duration-200"
|
||||
:class="{ 'rotate-180': isDropdownOpen }"
|
||||
viewBox="0 0 12 12" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.69999 4.285L9.59499 7.125C9.91999 7.445 9.69499 8 9.23499 8H2.75999C2.29999 8 2.07499 7.445 2.39999 7.125L5.29499 4.285C5.68499 3.905 6.30499 3.905 6.69499 4.285H6.69999Z" fill="#EBEBEB"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div v-if="isDropdownOpen" class="dropdown-menu">
|
||||
<div v-for="localeItem in availableLanguages" :key="localeItem.code" class="dropdown-menu-item">
|
||||
<button
|
||||
class="dropdown-menu-item-button"
|
||||
:class="{ 'current': localeItem.code === selectedLocale }"
|
||||
@click="selectLanguage(localeItem.code)"
|
||||
viewBox="0 0 12 12"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg
|
||||
width="15"
|
||||
height="11"
|
||||
viewBox="0 0 15 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="transition-opacity duration-200"
|
||||
<path
|
||||
d="M6.69999 4.285L9.59499 7.125C9.91999 7.445 9.69499 8 9.23499 8H2.75999C2.29999 8 2.07499 7.445 2.39999 7.125L5.29499 4.285C5.68499 3.905 6.30499 3.905 6.69499 4.285H6.69999Z"
|
||||
fill="#EBEBEB"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<div v-if="isDropdownOpen" class="dropdown-menu">
|
||||
<div
|
||||
v-for="localeItem in availableLanguages"
|
||||
:key="localeItem.code"
|
||||
class="dropdown-menu-item"
|
||||
>
|
||||
<button
|
||||
class="dropdown-menu-item-button"
|
||||
:class="{ current: localeItem.code === selectedLocale }"
|
||||
@click="selectLanguage(localeItem.code)"
|
||||
>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6339 0.366117C15.1221 0.854272 15.1221 1.64573 14.6339 2.13388L6.30057 10.4672C6.05437 10.7134 5.71664 10.8458 5.36872 10.8324C5.0208 10.8191 4.69421 10.6612 4.46762 10.3968L0.300952 5.53571C-0.148326 5.01155 -0.0876239 4.22243 0.436533 3.77315C0.960691 3.32387 1.74982 3.38458 2.19909 3.90873L5.48729 7.74496L12.8661 0.366117C13.3543 -0.122039 14.1458 -0.122039 14.6339 0.366117Z" fill="#FC4420"/>
|
||||
</svg>
|
||||
<span class="text-sm">{{ localeItem.name }}</span>
|
||||
</button>
|
||||
<svg
|
||||
width="15"
|
||||
height="11"
|
||||
viewBox="0 0 15 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="transition-opacity duration-200"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M14.6339 0.366117C15.1221 0.854272 15.1221 1.64573 14.6339 2.13388L6.30057 10.4672C6.05437 10.7134 5.71664 10.8458 5.36872 10.8324C5.0208 10.8191 4.69421 10.6612 4.46762 10.3968L0.300952 5.53571C-0.148326 5.01155 -0.0876239 4.22243 0.436533 3.77315C0.960691 3.32387 1.74982 3.38458 2.19909 3.90873L5.48729 7.74496L12.8661 0.366117C13.3543 -0.122039 14.1458 -0.122039 14.6339 0.366117Z"
|
||||
fill="#FC4420"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text-sm">{{ localeItem.name }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const config = useRuntimeConfig()
|
||||
const baseDomain = `${config.public.baseDomain}`
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const baseDomain = `${runtimeConfig.public.baseDomain}`
|
||||
|
||||
const gameDataStore = useGameDataStore()
|
||||
const { gameData } = storeToRefs(gameDataStore)
|
||||
// 사용 가능한 언어 목록
|
||||
const availableLanguages = computed(() => {
|
||||
return gameData.value?.lang_codes?.map(localeCode => ({
|
||||
code: localeCode,
|
||||
name: getLanguageName(localeCode)
|
||||
})) || [{ code: 'ko', name: '한국어' }]
|
||||
return (
|
||||
gameData.value?.lang_codes?.map(localeCode => ({
|
||||
code: localeCode,
|
||||
name: getLanguageName(localeCode),
|
||||
})) || [{ code: 'ko', name: '한국어' }]
|
||||
)
|
||||
})
|
||||
|
||||
// 언어 코드를 한국어 이름으로 변환하는 함수
|
||||
const getLanguageName = (localeCode: string) => {
|
||||
const languageNames: Record<string, string> = {
|
||||
'ko': '한국어',
|
||||
'en': 'English',
|
||||
'ja': '日本語',
|
||||
ko: '한국어',
|
||||
en: 'English',
|
||||
ja: '日本語',
|
||||
'zh-cn': '简体中文',
|
||||
'zh-tw': '繁體中文',
|
||||
'es': 'Español',
|
||||
'fr': 'Français',
|
||||
'de': 'Deutsch',
|
||||
'pt': 'Português',
|
||||
'th': 'ไทย',
|
||||
'it': 'Italiano'
|
||||
es: 'Español',
|
||||
fr: 'Français',
|
||||
de: 'Deutsch',
|
||||
pt: 'Português',
|
||||
th: 'ไทย',
|
||||
it: 'Italiano',
|
||||
}
|
||||
return languageNames[localeCode] || localeCode
|
||||
}
|
||||
@@ -113,7 +164,7 @@ const selectLanguage = async (localeCode: string) => {
|
||||
isDropdownOpen.value = false
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
selectedLocale.value = localeCode as any
|
||||
isDropdownOpen.value = false
|
||||
await switchLanguage()
|
||||
@@ -121,38 +172,37 @@ const selectLanguage = async (localeCode: string) => {
|
||||
// 언어 변경 함수 (서버 미드웨어를 통한 gameData 갱신)
|
||||
const switchLanguage = async () => {
|
||||
if (!selectedLocale.value || isChanging.value) return
|
||||
|
||||
|
||||
isChanging.value = true
|
||||
|
||||
|
||||
try {
|
||||
// URL 경로를 통해 언어 변경
|
||||
const path = switchLocalePath(selectedLocale.value as any)
|
||||
if (path) {
|
||||
// 언어 쿠키 설정 (클라이언트 사이드) - 페이지 이동 전에 설정
|
||||
const localeCookie = useCookie('LOCALE', {
|
||||
domain: baseDomain,
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 365, // 1년 (초 단위)
|
||||
sameSite: 'lax'
|
||||
})
|
||||
localeCookie.value = selectedLocale.value.toUpperCase()
|
||||
|
||||
// 페이지 데이터 초기화 (새로운 언어로 다시 로드되도록)
|
||||
pageDataStore.clearPageData()
|
||||
window.location.href = path
|
||||
// URL 경로를 통해 언어 변경
|
||||
const path = switchLocalePath(selectedLocale.value as any)
|
||||
if (path) {
|
||||
// 언어 쿠키 설정 (클라이언트 사이드) - 페이지 이동 전에 설정
|
||||
const localeCookie = useCookie('LOCALE', {
|
||||
domain: baseDomain,
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 365, // 1년 (초 단위)
|
||||
sameSite: 'lax',
|
||||
})
|
||||
localeCookie.value = selectedLocale.value.toUpperCase()
|
||||
|
||||
// 페이지 데이터 초기화 (새로운 언어로 다시 로드되도록)
|
||||
pageDataStore.clearPageData()
|
||||
window.location.href = path
|
||||
// 언어 변경 및 라우팅
|
||||
// await setLocale(selectedLocale.value as any)
|
||||
|
||||
|
||||
// 전체 페이지에 페이드 아웃 효과 적용
|
||||
// document.body.style.transition = 'opacity 0.1s ease-out'
|
||||
// document.body.style.opacity = '0'
|
||||
|
||||
|
||||
// // 페이드 아웃 완료 후 페이지 이동
|
||||
// await new Promise(resolve => setTimeout(resolve, 100))
|
||||
|
||||
|
||||
// 서버 미드웨어를 통해 gameData 갱신을 위해 페이지 새로고침
|
||||
// 이렇게 하면 서버 미드웨어가 새로운 언어로 gameData를 다시 가져옴
|
||||
|
||||
}
|
||||
} catch {
|
||||
// 오류 발생 시 이전 언어로 복원
|
||||
@@ -248,5 +298,4 @@ body {
|
||||
.dropdown-menu-item-button.current svg {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -66,8 +66,8 @@ const useGds = () => {
|
||||
},
|
||||
} as ResGetGdsClientPolicyTotal
|
||||
} else {
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
|
||||
const url = `${stoveApiBaseUrl}/gds/v2/client/policy/total`
|
||||
const query = {
|
||||
|
||||
@@ -13,9 +13,8 @@ export const useGetGameDataExternal = () => {
|
||||
|
||||
const getGameDataExternal = async (req: GameDataRequest) => {
|
||||
console.log('🚀 ~ getGameDataExternal ~ req:', req)
|
||||
// const config = useRuntimeConfig()
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v1.0/template/game?game_domain=${req.gameDomain}&lang_code=${req.langCode}`
|
||||
|
||||
try {
|
||||
@@ -23,7 +22,7 @@ export const useGetGameDataExternal = () => {
|
||||
console.log('🚀 ~ getGameDataExternal ~ response:', response)
|
||||
|
||||
// FIXME: 테스트용 데이터 ---------------------------------------------------
|
||||
/* if (['local', 'local-gate8', 'dev'].includes(`${config.public.runType}`)) {
|
||||
/* if (['local', 'local-gate8', 'dev'].includes(`${runtimeConfig.public.runType}`)) {
|
||||
response.value = {
|
||||
inspection_status: 1,
|
||||
inspection: {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import type { ReqGameMaintenance, ResGameMaintenance } from '#layers/types/GameMaintenanceType'
|
||||
import type {
|
||||
ReqGameMaintenance,
|
||||
ResGameMaintenance,
|
||||
} from '#layers/types/GameMaintenanceType'
|
||||
|
||||
/**
|
||||
* 게임 점검
|
||||
@@ -7,7 +10,7 @@ const useGetGameMaintenance = () => {
|
||||
const inspectionStore = useInspectionStore()
|
||||
const logPrefix = {
|
||||
exception: '[Exception] /composables/useGetGameMaintenance',
|
||||
failure: '[Failure] /composables/useGetGameMaintenance'
|
||||
failure: '[Failure] /composables/useGetGameMaintenance',
|
||||
}
|
||||
const isGameMaintenance = ref(false) // 게임 서버 점검 여부
|
||||
|
||||
@@ -20,7 +23,11 @@ const useGetGameMaintenance = () => {
|
||||
const setGameMaintenanceFalse = () => {
|
||||
setIsGameMaintenance(false)
|
||||
inspectionStore.setGameMaintenanceStatus(false)
|
||||
inspectionStore.setGameMaintenanceData({ ts_start_date: 0, ts_end_date: 0, detail_link: '' })
|
||||
inspectionStore.setGameMaintenanceData({
|
||||
ts_start_date: 0,
|
||||
ts_end_date: 0,
|
||||
detail_link: '',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +52,8 @@ const useGetGameMaintenance = () => {
|
||||
|
||||
if (res != null && res.code === 0) {
|
||||
// FIXME: 테스트용 데이터 ---------------------------------------------------
|
||||
/* const config = useRuntimeConfig()
|
||||
if (['local', 'local-gate8', 'dev'].includes(`${config.public.runType}`)) {
|
||||
/* const runtimeConfig = useRuntimeConfig()
|
||||
if (['local', 'local-gate8', 'dev'].includes(`${runtimeConfig.public.runType}`)) {
|
||||
res.value = {
|
||||
total_count: 1,
|
||||
list: [
|
||||
@@ -65,12 +72,16 @@ const useGetGameMaintenance = () => {
|
||||
}
|
||||
} */
|
||||
// ------------------------------------------------------------------------
|
||||
if (Number(res.value?.total_count) > 0 && res.value?.list != null && res.value?.list.length > 0) {
|
||||
if (
|
||||
Number(res.value?.total_count) > 0 &&
|
||||
res.value?.list != null &&
|
||||
res.value?.list.length > 0
|
||||
) {
|
||||
setIsGameMaintenance(true) // 서버 1개 이상 점검일 경우 점검 중으로 간주
|
||||
inspectionStore.setGameMaintenanceData({
|
||||
ts_start_date: res.value?.list[0].start_at || 0,
|
||||
ts_end_date: res.value?.list[0].end_at || 0,
|
||||
detail_link: res.value?.list[0].languages[0].link || ''
|
||||
detail_link: res.value?.list[0].languages[0].link || '',
|
||||
})
|
||||
inspectionStore.setGameMaintenanceStatus(true)
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import type { WebInspectionData, ReqGetInspectionData, ResGetInspectionData } from '#layers/types/InspectionType'
|
||||
import type {
|
||||
WebInspectionData,
|
||||
ReqGetInspectionData,
|
||||
ResGetInspectionData,
|
||||
} from '#layers/types/InspectionType'
|
||||
|
||||
/**
|
||||
* 웹 점검
|
||||
@@ -7,7 +11,7 @@ export const useGetInspectionDataExternal = () => {
|
||||
const inspectionStore = useInspectionStore()
|
||||
const logPrefix = {
|
||||
exception: '[Exception] /composables/useGetInspectionDataExternal',
|
||||
failure: '[Failure] /composables/useGetInspectionDataExternal'
|
||||
failure: '[Failure] /composables/useGetInspectionDataExternal',
|
||||
}
|
||||
const webInspectionData = ref<WebInspectionData | null>(null)
|
||||
const isWebInspection = ref(false) // 웹 점검 여부
|
||||
@@ -24,15 +28,18 @@ export const useGetInspectionDataExternal = () => {
|
||||
* @description https://wiki.smilegate.net/pages/viewpage.action?pageId=563198067
|
||||
*/
|
||||
const getInspectionDataExternal = async (req: ReqGetInspectionData) => {
|
||||
// const config = useRuntimeConfig()
|
||||
// const runtimeConfig = useRuntimeConfig()
|
||||
const apiUrl = `${req.baseApiUrl}/pub-comm/v3.0/inspection/${req.gameId}`
|
||||
|
||||
try {
|
||||
const response = (await commonFetch('GET', apiUrl)) as ResGetInspectionData
|
||||
console.log("🚀 ~ getInspectionDataExternal ~ response:", response)
|
||||
const response = (await commonFetch(
|
||||
'GET',
|
||||
apiUrl
|
||||
)) as ResGetInspectionData
|
||||
console.log('🚀 ~ getInspectionDataExternal ~ response:', response)
|
||||
|
||||
// FIXME: 테스트용 데이터 ---------------------------------------------------
|
||||
/* if (['local', 'local-gate8', 'dev'].includes(`${config.public.runType}`)) {
|
||||
/* if (['local', 'local-gate8', 'dev'].includes(`${runtimeConfig.public.runType}`)) {
|
||||
response.value = {
|
||||
inspection_status: 1,
|
||||
inspection: {
|
||||
|
||||
@@ -37,8 +37,8 @@ const usePreregist = () => {
|
||||
const getPreregist = async (req: ReqPreorderSelectEvent) => {
|
||||
let res: ResPreorderSelectEvent = {} as ResPreorderSelectEvent
|
||||
try {
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
|
||||
const url = `${stoveApiBaseUrl}/pub-comm/v1.0/Preorder/SelectEvent`
|
||||
const headers = {
|
||||
@@ -99,8 +99,8 @@ const usePreregist = () => {
|
||||
const setPreregist = async (req: ReqPreorderReserveDataUpdate) => {
|
||||
let res: ResPreorderReserveDataUpdate = {} as ResPreorderReserveDataUpdate
|
||||
try {
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
|
||||
const url = `${stoveApiBaseUrl}/pub-comm/v1.0/Preorder/ReserveDataUpdate`
|
||||
const headers = {
|
||||
|
||||
@@ -19,8 +19,8 @@ export const useResourcesData = () => {
|
||||
): Promise<OperateComponents | null> => {
|
||||
const { pageSeq, pageVer, pageVerTmplSeq, langCode, q, qc } = params
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v1.0/template/operateResources`
|
||||
|
||||
const queryParams: Record<string, string | number> = {
|
||||
@@ -68,8 +68,8 @@ export const useResourcesData = () => {
|
||||
size,
|
||||
} = params
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const apiUrl = `${stoveApiBaseUrl}/cwms/v3.0/article_group/${articleGroupCode}/${articleGroupSeq}/article/list`
|
||||
|
||||
const queryParams: Record<string, string | number | boolean> = {
|
||||
|
||||
@@ -14,14 +14,14 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
|
||||
const currentLangCode = match ? match[1] : null
|
||||
|
||||
//현재 url에서 게임 도메인만 추출
|
||||
const currentDomain = window.location.hostname;
|
||||
const config = useRuntimeConfig()
|
||||
const currentDomain = window.location.hostname
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const req: GameDataRequest = {
|
||||
gameDomain: `${currentDomain}`,
|
||||
langCode: `${currentLangCode}`,
|
||||
game_alias: '',
|
||||
lang_code: `${currentLangCode}`,
|
||||
baseApiUrl: `${config.public.stoveApiUrl}`,
|
||||
baseApiUrl: `${runtimeConfig.public.stoveApiUrl}`,
|
||||
gameId: '',
|
||||
}
|
||||
const { getGameDataExternal } = useGetGameDataExternal()
|
||||
@@ -30,7 +30,7 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
|
||||
const gameDataStore = useGameDataStore()
|
||||
const gameData = gameDataStore.gameData as GameDataValue
|
||||
const langCodes = gameData?.lang_codes
|
||||
|
||||
|
||||
// 허용된 언어 코드 목록
|
||||
const allowedLangCodes = langCodes || []
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
export default defineNuxtRouteMiddleware(async (to) => {
|
||||
export default defineNuxtRouteMiddleware(async to => {
|
||||
try {
|
||||
if (import.meta.client) {
|
||||
const gameDataStore = useGameDataStore()
|
||||
const { gameData } = storeToRefs(gameDataStore)
|
||||
console.log("🚀 ~ 00000 gameData:", gameData.value)
|
||||
console.log('🚀 ~ 00000 gameData:', gameData.value)
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
// const baseDomain = `${config.public.baseDomain}`
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
// const baseDomain = `${runtimeConfig.public.baseDomain}`
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const stoveGameId = gameData.value.game_id
|
||||
// const stoveMaintenanceApiUrl = `${config.public.stoveMaintenanceApiUrl}`
|
||||
// const stoveMaintenanceApiUrl = `${runtimeConfig.public.stoveMaintenanceApiUrl}`
|
||||
|
||||
// const localeCookie = useCookie('LOCALE', {
|
||||
// domain: baseDomain
|
||||
@@ -19,9 +19,12 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
||||
// localeCookie.value = finalLocale.toUpperCase()
|
||||
|
||||
// 웹 점검 -----
|
||||
const { isWebInspection, getInspectionDataExternal } = useGetInspectionDataExternal()
|
||||
await getInspectionDataExternal({ baseApiUrl: stoveApiBaseUrl, gameId: stoveGameId })
|
||||
|
||||
const { isWebInspection, getInspectionDataExternal } =
|
||||
useGetInspectionDataExternal()
|
||||
await getInspectionDataExternal({
|
||||
baseApiUrl: stoveApiBaseUrl,
|
||||
gameId: stoveGameId,
|
||||
})
|
||||
|
||||
// 게임 점검 -----
|
||||
// const { checkGameMaintenance } = useGetGameMaintenance()
|
||||
@@ -32,10 +35,17 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
||||
// lang: `${finalLocale}`.toLowerCase()
|
||||
// })
|
||||
|
||||
if (isWebInspection.value && !to.path.includes('inspection') && !to.path.includes('api')) {
|
||||
if (
|
||||
isWebInspection.value &&
|
||||
!to.path.includes('inspection') &&
|
||||
!to.path.includes('api')
|
||||
) {
|
||||
// 점검 중인 경우
|
||||
return navigateTo(`/${finalLocale}/inspection`, { external: true })
|
||||
} else if (!isWebInspection.value && to.path?.indexOf('inspection') !== -1) {
|
||||
} else if (
|
||||
!isWebInspection.value &&
|
||||
to.path?.indexOf('inspection') !== -1
|
||||
) {
|
||||
// 점검이 종료된 후 점검 페이지 접근시 메인으로 리다이렉트
|
||||
return navigateTo(`/${finalLocale}`, { external: true })
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
|
||||
// [TODO] 하이드레이션 에러 처리
|
||||
if (!import.meta.client) return
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v2.0/template/page`
|
||||
|
||||
const store = usePageDataStore()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* i18n 다국어 로더 플러그인
|
||||
* S3에서 공통 다국어 파일을 로드하여 i18n 메시지에 주입합니다.
|
||||
*/
|
||||
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
export default defineNuxtPlugin(async nuxtApp => {
|
||||
const $i18n = nuxtApp.$i18n as any
|
||||
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
@@ -31,7 +31,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
'zh-cn': 'zh-CN',
|
||||
}
|
||||
|
||||
langCodes.forEach((langCode) => {
|
||||
langCodes.forEach(langCode => {
|
||||
// 로케일 코드 변환 (필요한 경우)
|
||||
const normalizedLangCode = localeMap[langCode] || langCode
|
||||
|
||||
@@ -47,6 +47,9 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('[Exception] i18n-loader: Failed to load translations:', error)
|
||||
console.error(
|
||||
'[Exception] i18n-loader: Failed to load translations:',
|
||||
error
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { LRUCache } from 'lru-cache'
|
||||
import {
|
||||
getHeader,
|
||||
getRequestHost,
|
||||
defineEventHandler,
|
||||
} from 'h3'
|
||||
import { getHeader, getRequestHost, defineEventHandler } from 'h3'
|
||||
import { ssrGetFinalLocale } from '../../utils/localeUtil'
|
||||
import type { GameDataResponse } from '../../types/api/gameData'
|
||||
import type { ResGetInspectionData } from '../../types/InspectionType'
|
||||
@@ -17,7 +13,9 @@ import { isStaticFile } from '#layers/utils/commonUtil'
|
||||
* @param customMaxAge - 커스텀 max-age 값 (초 단위)
|
||||
*/
|
||||
function setCacheHeaders(
|
||||
event: { node: { res: { setHeader: (name: string, value: string) => void } } },
|
||||
event: {
|
||||
node: { res: { setHeader: (name: string, value: string) => void } }
|
||||
},
|
||||
cacheMode: 'no-cache' | 'short' | 'medium' | 'default',
|
||||
customMaxAge?: number
|
||||
): void {
|
||||
@@ -59,7 +57,7 @@ function setCacheHeaders(
|
||||
|
||||
const cache = new LRUCache({
|
||||
max: 100, // 캐시에 저장할 최대 항목 수
|
||||
ttl: 1000 * 30 // 30초 동안 캐시 유지
|
||||
ttl: 1000 * 30, // 30초 동안 캐시 유지
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -69,11 +67,15 @@ const cache = new LRUCache({
|
||||
* @param finalLocale - 최종 언어
|
||||
* @param baseDomain - 기본 도메인
|
||||
*/
|
||||
function setFinalLocaleCookie(event: any, finalLocale: string, baseDomain: string) {
|
||||
function setFinalLocaleCookie(
|
||||
event: any,
|
||||
finalLocale: string,
|
||||
baseDomain: string
|
||||
) {
|
||||
setCookie(event, 'LOCALE', finalLocale.toUpperCase(), {
|
||||
domain: baseDomain,
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 365 // 1년 (초 단위)
|
||||
maxAge: 60 * 60 * 24 * 365, // 1년 (초 단위)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -121,32 +123,30 @@ function fnLocaleMiddleware(event: any, finalLocale: string) {
|
||||
}
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
// const runType = `${config.public.runType}`
|
||||
// console.log("🚀 ~ baseDomain:", config.public.baseDomain)
|
||||
// const runType = `${runtimeConfig.public.runType}`
|
||||
// const url = getRequestURL(event)
|
||||
|
||||
// if (['local', 'local-gate8', 'dev'].includes(runType)) {
|
||||
// Sandbox 이상 환경에서만 동작 및 확인 가능 (local, dev는 통과 처리)
|
||||
// try {
|
||||
// 언어 코드 추출
|
||||
// const finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers)
|
||||
// console.log("🚀 ~ finalLocale:", finalLocale)
|
||||
// setFinalLocaleCookie(event, finalLocale, baseDomain)
|
||||
// Sandbox 이상 환경에서만 동작 및 확인 가능 (local, dev는 통과 처리)
|
||||
// try {
|
||||
// 언어 코드 추출
|
||||
// const finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers)
|
||||
// console.log("🚀 ~ finalLocale:", finalLocale)
|
||||
// setFinalLocaleCookie(event, finalLocale, baseDomain)
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
// fnLocaleMiddleware(event, finalLocale)
|
||||
// } catch (e) {
|
||||
// console.error('[Exception] /server/middleware/middleware-02-global: ', e)
|
||||
// }
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
// fnLocaleMiddleware(event, finalLocale)
|
||||
// } catch (e) {
|
||||
// console.error('[Exception] /server/middleware/middleware-02-global: ', e)
|
||||
// }
|
||||
// }
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const iBaseApiUrl = `${config.public.stoveApiUrlServer}`
|
||||
const baseDomain = `${config.public.baseDomain}`
|
||||
const stoveApiUrlBaseServer = config.public.stoveApiUrlServer
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const iBaseApiUrl = `${runtimeConfig.public.stoveApiUrlServer}`
|
||||
const baseDomain = `${runtimeConfig.public.baseDomain}`
|
||||
const stoveApiUrlBaseServer = runtimeConfig.public.stoveApiUrlServer
|
||||
const apiUrl = `${stoveApiUrlBaseServer}/pub-comm/v1.0/template/game`
|
||||
|
||||
const initGameData: GameDataResponse | null = null
|
||||
@@ -165,7 +165,6 @@ export default defineEventHandler(async event => {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
const queryParams: Record<string, string> = {
|
||||
game_domain: cleanHost || '',
|
||||
lang_code: '',
|
||||
@@ -177,13 +176,13 @@ export default defineEventHandler(async event => {
|
||||
// console.log("🚀 ~ 00000 initGameData:", initGameData)
|
||||
initLangCodes = initResponse?.value?.lang_codes || null
|
||||
initDefaultLocale = initResponse?.value?.default_lang_code || null
|
||||
console.log("🚀 ~ 000111 initLangCodes:", initLangCodes)
|
||||
console.log('🚀 ~ 000111 initLangCodes:', initLangCodes)
|
||||
} catch (error) {
|
||||
console.error('init gameData load error:', error)
|
||||
}
|
||||
|
||||
const fullPath = event.path
|
||||
|
||||
|
||||
// 1-1. 정적 파일 패스
|
||||
if (isStaticFile(event.path)) {
|
||||
return
|
||||
@@ -192,7 +191,12 @@ export default defineEventHandler(async event => {
|
||||
// 1-2. /inspection 패스
|
||||
if (fullPath.includes('/inspection')) {
|
||||
// 리턴 되기 전 언어 쿠키 세팅
|
||||
finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers, initLangCodes, initDefaultLocale)
|
||||
finalLocale = ssrGetFinalLocale(
|
||||
event?.node.req.url,
|
||||
event.node.req.headers,
|
||||
initLangCodes,
|
||||
initDefaultLocale
|
||||
)
|
||||
setFinalLocaleCookie(event, finalLocale, baseDomain)
|
||||
return
|
||||
}
|
||||
@@ -213,14 +217,17 @@ export default defineEventHandler(async event => {
|
||||
const cacheKey = 'inspection'
|
||||
// console.log("🚀 11111 ~ cacheKey:", cacheKey)
|
||||
|
||||
|
||||
// gameData를 직접 가져와서 context에 저장 (API 호출 없이)
|
||||
try {
|
||||
|
||||
// 2. 언어 코드 추출
|
||||
finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers, initLangCodes, initDefaultLocale)
|
||||
console.log("🚀 222 finalLocale:", finalLocale)
|
||||
|
||||
// 2. 언어 코드 추출
|
||||
finalLocale = ssrGetFinalLocale(
|
||||
event?.node.req.url,
|
||||
event.node.req.headers,
|
||||
initLangCodes,
|
||||
initDefaultLocale
|
||||
)
|
||||
console.log('🚀 222 finalLocale:', finalLocale)
|
||||
|
||||
const queryParams: Record<string, string> = {
|
||||
game_domain: cleanHost || '',
|
||||
lang_code: finalLocale,
|
||||
@@ -230,18 +237,16 @@ export default defineEventHandler(async event => {
|
||||
})) as GameDataResponse | null
|
||||
|
||||
// 언어패스 쿠키 굽기 - 장기방안에서는 굽지않음
|
||||
if(initLangCodes?.includes(finalLocale)) {
|
||||
if (initLangCodes?.includes(finalLocale)) {
|
||||
setFinalLocaleCookie(event, finalLocale, baseDomain)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (response?.code === 0 && 'value' in response) {
|
||||
event.context.gameData = response.value
|
||||
event.context.googleAnalyticsId = response.value?.ga_code
|
||||
|
||||
// console.log('🚀 ~ gameData:', response.value)
|
||||
|
||||
|
||||
// 점검 데이터 조회
|
||||
let inspectionData
|
||||
if (cache.has(cacheKey)) {
|
||||
@@ -251,104 +256,109 @@ export default defineEventHandler(async event => {
|
||||
if (response?.value?.game_id) {
|
||||
const inspectionApiUrl = `${iBaseApiUrl}/pub-comm/v3.0/inspection/${response?.value?.game_id}`
|
||||
// 직접 $fetch 사용 (composable 사용하지 않음)
|
||||
const inspectionResponse = await $fetch<ResGetInspectionData>(inspectionApiUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
const inspectionResponse = await $fetch<ResGetInspectionData>(
|
||||
inspectionApiUrl,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
inspectionData = inspectionResponse?.value?.inspection
|
||||
cache.set(cacheKey, inspectionData) // 캐시에 저장
|
||||
// console.log("🚀 ~ inspectionData:", inspectionData)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 현재 시간과 점검 기간 비교
|
||||
const currentTime = Date.now()
|
||||
const tsStartDate = inspectionData?.ts_start_date || 0
|
||||
const tsEndDate = inspectionData?.ts_end_date || 0
|
||||
const timeUntilInspectionSeconds = Math.floor(
|
||||
(tsStartDate - currentTime) / 1000
|
||||
)
|
||||
|
||||
// 4. 현재 시간과 점검 기간 비교
|
||||
const currentTime = Date.now()
|
||||
const tsStartDate = inspectionData?.ts_start_date || 0
|
||||
const tsEndDate = inspectionData?.ts_end_date || 0
|
||||
const timeUntilInspectionSeconds = Math.floor((tsStartDate - currentTime) / 1000)
|
||||
// 5. 점검 상태별 캐시 설정
|
||||
if (
|
||||
inspectionData?.inspection_status === 1 &&
|
||||
currentTime >= tsStartDate &&
|
||||
currentTime <= tsEndDate
|
||||
) {
|
||||
/**
|
||||
* 점검 중인 경우
|
||||
* - 점검 상태가 1이고 현재 시간이 점검 시작과 종료 사이에 있는지 확인ㄹ
|
||||
* - 점검 URL 경로가 아닐 경우 no-cache 설정
|
||||
* - 화이트 리스트 체크
|
||||
*/
|
||||
// 현재 경로가 점검 페이지가 아닐 경우 리다이렉트
|
||||
const inspectionPath = `/${finalLocale}/inspection`
|
||||
if (fullPath !== inspectionPath) {
|
||||
setCacheHeaders(event, 'no-cache')
|
||||
}
|
||||
|
||||
// 5. 점검 상태별 캐시 설정
|
||||
if (inspectionData?.inspection_status === 1 && currentTime >= tsStartDate && currentTime <= tsEndDate) {
|
||||
/**
|
||||
* 점검 중인 경우
|
||||
* - 점검 상태가 1이고 현재 시간이 점검 시작과 종료 사이에 있는지 확인ㄹ
|
||||
* - 점검 URL 경로가 아닐 경우 no-cache 설정
|
||||
* - 화이트 리스트 체크
|
||||
*/
|
||||
// 현재 경로가 점검 페이지가 아닐 경우 리다이렉트
|
||||
const inspectionPath = `/${finalLocale}/inspection`
|
||||
if (fullPath !== inspectionPath) {
|
||||
setCacheHeaders(event, 'no-cache')
|
||||
}
|
||||
// 점검 중일 때 IP 필터링 활성화 여부 확인
|
||||
if (inspectionData?.ip_filter_use_yn === 'Y') {
|
||||
const clientIP = getTrueClientIp(event.node.req as any)
|
||||
|
||||
// 점검 중일 때 IP 필터링 활성화 여부 확인
|
||||
if (inspectionData?.ip_filter_use_yn === 'Y') {
|
||||
const clientIP = getTrueClientIp(event.node.req as any)
|
||||
|
||||
// 허용된 IP 목록 확인
|
||||
if (!inspectionData?.ip_filter_list?.includes(clientIP)) {
|
||||
// 허용되지 않은 IP인 경우 점검 페이지로 이동
|
||||
event.node.res.statusCode = 302
|
||||
event.node.res.setHeader('Location', inspectionPath)
|
||||
event.node.res.end()
|
||||
} else {
|
||||
// 화이트 리스트인 경우
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
fnLocaleMiddleware(event, finalLocale)
|
||||
}
|
||||
} else {
|
||||
// 허용된 IP 목록 확인
|
||||
if (!inspectionData?.ip_filter_list?.includes(clientIP)) {
|
||||
// 허용되지 않은 IP인 경우 점검 페이지로 이동
|
||||
event.node.res.statusCode = 302
|
||||
event.node.res.setHeader('Location', inspectionPath)
|
||||
event.node.res.end()
|
||||
} else {
|
||||
// 화이트 리스트인 경우
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
fnLocaleMiddleware(event, finalLocale)
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* 점검이 아닌 경우
|
||||
* - 홈 경로는 no-cache
|
||||
* - 점검 예정 시간에 따른 캐시 설정
|
||||
* - 점검 5분 전: 짧은 캐시 (10초)
|
||||
* - 점검 30분 전: 중간 캐시 (15초)
|
||||
* - 점검 30분 이후: 기본 캐시 (60초)
|
||||
*/
|
||||
// 홈 경로: 캐시 없음
|
||||
const isHomePath = [
|
||||
'',
|
||||
'/'
|
||||
//, ...Object.values(DEFAULT_LOCALE_COVERAGES).flatMap((locale) => [`/${locale}`, `/${locale}/`])
|
||||
].includes(fullPath)
|
||||
event.node.res.statusCode = 302
|
||||
event.node.res.setHeader('Location', inspectionPath)
|
||||
event.node.res.end()
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* 점검이 아닌 경우
|
||||
* - 홈 경로는 no-cache
|
||||
* - 점검 예정 시간에 따른 캐시 설정
|
||||
* - 점검 5분 전: 짧은 캐시 (10초)
|
||||
* - 점검 30분 전: 중간 캐시 (15초)
|
||||
* - 점검 30분 이후: 기본 캐시 (60초)
|
||||
*/
|
||||
// 홈 경로: 캐시 없음
|
||||
const isHomePath = [
|
||||
'',
|
||||
'/',
|
||||
//, ...Object.values(DEFAULT_LOCALE_COVERAGES).flatMap((locale) => [`/${locale}`, `/${locale}/`])
|
||||
].includes(fullPath)
|
||||
|
||||
if (isHomePath) {
|
||||
setCacheHeaders(event, 'no-cache')
|
||||
} else {
|
||||
// 점검 예정 시간에 따른 캐시 설정
|
||||
|
||||
if (tsStartDate > 0 && timeUntilInspectionSeconds > 0) {
|
||||
if (timeUntilInspectionSeconds < 300) {
|
||||
// 점검 5분 전: 짧은 캐시 (10초)
|
||||
setCacheHeaders(event, 'short', 10)
|
||||
} else if (timeUntilInspectionSeconds < 1800) {
|
||||
// 점검 30분 전: 중간 캐시 (15초)
|
||||
setCacheHeaders(event, 'medium', 15)
|
||||
} else {
|
||||
// 점검 30분 이후: 기본 캐시 (60초)
|
||||
setCacheHeaders(event, 'default')
|
||||
}
|
||||
if (isHomePath) {
|
||||
setCacheHeaders(event, 'no-cache')
|
||||
} else {
|
||||
// 점검 예정 시간에 따른 캐시 설정
|
||||
|
||||
if (tsStartDate > 0 && timeUntilInspectionSeconds > 0) {
|
||||
if (timeUntilInspectionSeconds < 300) {
|
||||
// 점검 5분 전: 짧은 캐시 (10초)
|
||||
setCacheHeaders(event, 'short', 10)
|
||||
} else if (timeUntilInspectionSeconds < 1800) {
|
||||
// 점검 30분 전: 중간 캐시 (15초)
|
||||
setCacheHeaders(event, 'medium', 15)
|
||||
} else {
|
||||
// 점검 30분 이후: 기본 캐시 (60초)
|
||||
setCacheHeaders(event, 'default')
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
fnLocaleMiddleware(event, finalLocale)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// [Locale Middleware]
|
||||
// -------------------------------------------------------------------------------
|
||||
fnLocaleMiddleware(event, finalLocale)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('gameData load error:', error)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@ export const useGameDataStore = defineStore('gameData', () => {
|
||||
gameData.value = data
|
||||
}
|
||||
|
||||
const setLangCode = (data: string) => {
|
||||
langCode.value = data
|
||||
}
|
||||
|
||||
const clearGameData = () => {
|
||||
gameData.value = null
|
||||
}
|
||||
@@ -20,7 +16,6 @@ export const useGameDataStore = defineStore('gameData', () => {
|
||||
langCode,
|
||||
gameData,
|
||||
setGameData,
|
||||
setLangCode,
|
||||
clearGameData,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -13,10 +13,10 @@ const props = defineProps<Props>()
|
||||
const { handleTokenValidation } = useTokenValidation()
|
||||
|
||||
// Configuration
|
||||
const config = useRuntimeConfig()
|
||||
const dataResourcesUrl = config.public.dataResourcesUrl as string
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const dataResourcesUrl = runtimeConfig.public.dataResourcesUrl as string
|
||||
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
|
||||
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_secure.json'
|
||||
const stoveApiBaseUrl = config.public.stoveApiUrl
|
||||
|
||||
// Multilingual
|
||||
const resultGetMultilingual = await useGetMultilingual({
|
||||
@@ -33,7 +33,7 @@ const isLogin = ref(false)
|
||||
const secureSetting = ref({
|
||||
otpLoginYn: 'N',
|
||||
abroadLoginBlockYn: 'N',
|
||||
pcRegisterYn: 'N'
|
||||
pcRegisterYn: 'N',
|
||||
})
|
||||
|
||||
// 회원 보안 설정 설정
|
||||
@@ -52,26 +52,28 @@ const checkLoginValidation = async () => {
|
||||
|
||||
// 회원 보안 설정 조회
|
||||
const fnGetSecuritySetting = async () => {
|
||||
|
||||
const accessToken = useCookie('SUAT')
|
||||
checkLoginValidation()
|
||||
|
||||
const apiBase = `${stoveApiBaseUrl}/auth-secure/v1.0`
|
||||
const headers = {
|
||||
Authorization: `Bearer ${accessToken.value}`,
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
}
|
||||
try {
|
||||
const result = await commonFetch('GET', `${apiBase}/security/setting`, { headers })
|
||||
const result = await commonFetch('GET', `${apiBase}/security/setting`, {
|
||||
headers,
|
||||
})
|
||||
|
||||
if (result?.code === 0 && Array.isArray(result.value)) {
|
||||
const arrSecure = result.value
|
||||
const getValue = (key: string) => arrSecure.find((f: any) => f.key === key)?.value ?? 'N'
|
||||
const getValue = (key: string) =>
|
||||
arrSecure.find((f: any) => f.key === key)?.value ?? 'N'
|
||||
|
||||
secureSetting.value = {
|
||||
otpLoginYn: getValue('OTP_LOGIN_YN'),
|
||||
abroadLoginBlockYn: getValue('ABROAD_LOGIN_BLOCK_YN'),
|
||||
pcRegisterYn: getValue('PC_REGISTER_YN')
|
||||
pcRegisterYn: getValue('PC_REGISTER_YN'),
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -89,7 +91,9 @@ const secureCards = computed(() => {
|
||||
{
|
||||
id: 'SECURE_CARD_0',
|
||||
title: tm('Secure_Stove_otp') || '스토브 인증기 (OTP)',
|
||||
description: tm('Secure_Stove_otp_desc') || '스토브 앱으로 인증 후 안전하게 로그인하세요.',
|
||||
description:
|
||||
tm('Secure_Stove_otp_desc') ||
|
||||
'스토브 앱으로 인증 후 안전하게 로그인하세요.',
|
||||
status: secureSetting.value.otpLoginYn,
|
||||
benefitTitle: tm('Secure_Stove_otp_benefits') || '스토브 OTP 혜택',
|
||||
benefitDesc: tm('Secure_Defense_bonus_10') || '방어력 +10',
|
||||
@@ -100,7 +104,9 @@ const secureCards = computed(() => {
|
||||
{
|
||||
id: 'SECURE_CARD_1',
|
||||
title: tm('Secure_Block_foreign_login') || '해외 로그인 차단',
|
||||
description: tm('Secure_Block_foreign_login_desc') || '접속 국가를 제한하여 의심 로그인을 차단해요.',
|
||||
description:
|
||||
tm('Secure_Block_foreign_login_desc') ||
|
||||
'접속 국가를 제한하여 의심 로그인을 차단해요.',
|
||||
status: secureSetting.value.abroadLoginBlockYn,
|
||||
benefitTitle: '',
|
||||
benefitDesc: '',
|
||||
@@ -111,7 +117,9 @@ const secureCards = computed(() => {
|
||||
{
|
||||
id: 'SECURE_CARD_2',
|
||||
title: tm('Secure_Trusted_pc_management') || '지정 PC 관리',
|
||||
description: tm('Secure_Trusted_pc_desc') || '지정 PC에서만 로그인할 수 있게 설정해 보세요.',
|
||||
description:
|
||||
tm('Secure_Trusted_pc_desc') ||
|
||||
'지정 PC에서만 로그인할 수 있게 설정해 보세요.',
|
||||
status: secureSetting.value.pcRegisterYn,
|
||||
benefitTitle: '',
|
||||
benefitDesc: '',
|
||||
@@ -126,7 +134,6 @@ const cautionText = computed(() => {
|
||||
return tm('Secure_Notice_Content') || []
|
||||
})
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
fnGetSecuritySetting()
|
||||
})
|
||||
@@ -143,12 +150,21 @@ onMounted(() => {
|
||||
<section class="section-secure bg-[#F0F0F0] pb-50">
|
||||
<div class="section-static content-standa md:max-w-[1300px] mx-auto">
|
||||
<!-- Title Section -->
|
||||
<div class="flex flex-col md:flex-row w-full md:items-end justify-between gap-5 mb-6">
|
||||
<h3 class="text-[#1F1F1F] text-2xl font-bold leading-8 tracking-[-0.72px]">
|
||||
<div
|
||||
class="flex flex-col md:flex-row w-full md:items-end justify-between gap-5 mb-6"
|
||||
>
|
||||
<h3
|
||||
class="text-[#1F1F1F] text-2xl font-bold leading-8 tracking-[-0.72px]"
|
||||
>
|
||||
{{ tm('Secure_Section_Title') || '보안 서비스' }}
|
||||
</h3>
|
||||
<p class="text-gray-500 text-[14px] font-[400] leading-[24px] tracking-[-0.42px] text-left md:text-right">
|
||||
{{ tm('Secure_Section_Description') || '*OTP / 해외 로그인 차단 / 지정 PC 관리 설정하고, 로드나인 계정을 보다 안전하게 보호하세요.' }}
|
||||
<p
|
||||
class="text-gray-500 text-[14px] font-[400] leading-[24px] tracking-[-0.42px] text-left md:text-right"
|
||||
>
|
||||
{{
|
||||
tm('Secure_Section_Description') ||
|
||||
'*OTP / 해외 로그인 차단 / 지정 PC 관리 설정하고, 로드나인 계정을 보다 안전하게 보호하세요.'
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -160,7 +176,9 @@ onMounted(() => {
|
||||
class="flex-1 min-h-[308px] md:min-h-[384px] p-[10px] md:p-4 bg-[#FFFFFF] rounded-2xl flex flex-col gap-3 transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<!-- Card Content -->
|
||||
<div class="flex-1 p-[10px] md:p-8 flex flex-col gap-[8px] md:gap-3 text-left">
|
||||
<div
|
||||
class="flex-1 p-[10px] md:p-8 flex flex-col gap-[8px] md:gap-3 text-left"
|
||||
>
|
||||
<!-- Badge -->
|
||||
<div class="inline-flex">
|
||||
<span
|
||||
@@ -171,17 +189,25 @@ onMounted(() => {
|
||||
: 'bg-[#EBEBEB] text-[#999999]',
|
||||
]"
|
||||
>
|
||||
{{ card.status === 'Y' ? tm('Secure_Enabled') : tm('Secure_Disabled') }}
|
||||
{{
|
||||
card.status === 'Y'
|
||||
? tm('Secure_Enabled')
|
||||
: tm('Secure_Disabled')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h4 class="text-[#1F1F1F] text-[18px] md:text-[24px] font-bold leading-[26px] md:leading-[34px] tracking-[-0.54px] md:tracking-[-0.72px]">
|
||||
<h4
|
||||
class="text-[#1F1F1F] text-[18px] md:text-[24px] font-bold leading-[26px] md:leading-[34px] tracking-[-0.54px] md:tracking-[-0.72px]"
|
||||
>
|
||||
{{ card.title }}
|
||||
</h4>
|
||||
|
||||
<!-- Description -->
|
||||
<p class="flex-1 text-[#999999] text-[14px] md:text-base font-[400] leading-[22px] md:leading-[26px] tracking-[-0.42px] md:tracking-[-0.48px]">
|
||||
<p
|
||||
class="flex-1 text-[#999999] text-[14px] md:text-base font-[400] leading-[22px] md:leading-[26px] tracking-[-0.42px] md:tracking-[-0.48px]"
|
||||
>
|
||||
{{ card.description }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -203,7 +229,9 @@ onMounted(() => {
|
||||
class="w-[48px] h-[48px] bg-[#3C75FF] rounded-[8px] flex items-center justify-center"
|
||||
>
|
||||
<img
|
||||
:src="getImageHost(card.benefitIcon, { imageType: 'common' })"
|
||||
:src="
|
||||
getImageHost(card.benefitIcon, { imageType: 'common' })
|
||||
"
|
||||
:alt="card.benefitTitle"
|
||||
class="w-[48px] h-[48px] object-contain rounded-2xl"
|
||||
loading="lazy"
|
||||
@@ -211,7 +239,9 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col text-left">
|
||||
<div class="text-[#3C75FF] text-[14px] md:text-[18px] font-bold leading-[22px] md:leading-[26px] tracking-[-0.42px] md:tracking-[-0.54px]">
|
||||
<div
|
||||
class="text-[#3C75FF] text-[14px] md:text-[18px] font-bold leading-[22px] md:leading-[26px] tracking-[-0.42px] md:tracking-[-0.54px]"
|
||||
>
|
||||
{{ card.benefitTitle }}
|
||||
</div>
|
||||
<div
|
||||
@@ -230,7 +260,11 @@ onMounted(() => {
|
||||
button-size="size-small md:size-large"
|
||||
background-color="#000000"
|
||||
text-color="#FFFFFF"
|
||||
@click="isLogin ? handleSecureSetting(card.url) : checkLoginValidation()"
|
||||
@click="
|
||||
isLogin
|
||||
? handleSecureSetting(card.url)
|
||||
: checkLoginValidation()
|
||||
"
|
||||
>
|
||||
<span>{{ tm('Secure_Action_setup') }}</span>
|
||||
</AtomsButton>
|
||||
@@ -243,8 +277,19 @@ onMounted(() => {
|
||||
disabled
|
||||
>
|
||||
<span>{{ tm('Secure_Action_complete') }}</span>
|
||||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.4298 2.80644L6.84645 0.240655C7.52385 -0.0802185 8.30948 -0.0802184 8.98688 0.240655L14.4035 2.80645C15.2767 3.22003 15.8333 4.09952 15.8333 5.06564V7.65038C15.8333 13.399 10.6191 16.1288 8.65401 16.9535C8.18024 17.1523 7.6531 17.1523 7.17932 16.9535C5.21423 16.1288 -0.000131724 13.399 2.49573e-09 7.65038L1.11287e-05 5.06566C6.95637e-06 4.09953 0.556675 3.22002 1.4298 2.80644ZM11.4226 7.4063C11.748 7.08086 11.748 6.55323 11.4226 6.22779C11.0972 5.90235 10.5695 5.90235 10.2441 6.22779L7.5 8.97187L6.00592 7.47779C5.68049 7.15235 5.15285 7.15235 4.82741 7.47779C4.50197 7.80323 4.50197 8.33086 4.82741 8.6563L6.91074 10.7396C7.23618 11.0651 7.76382 11.0651 8.08926 10.7396L11.4226 7.4063Z" fill="#999999"/>
|
||||
<svg
|
||||
width="16"
|
||||
height="18"
|
||||
viewBox="0 0 16 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M1.4298 2.80644L6.84645 0.240655C7.52385 -0.0802185 8.30948 -0.0802184 8.98688 0.240655L14.4035 2.80645C15.2767 3.22003 15.8333 4.09952 15.8333 5.06564V7.65038C15.8333 13.399 10.6191 16.1288 8.65401 16.9535C8.18024 17.1523 7.6531 17.1523 7.17932 16.9535C5.21423 16.1288 -0.000131724 13.399 2.49573e-09 7.65038L1.11287e-05 5.06566C6.95637e-06 4.09953 0.556675 3.22002 1.4298 2.80644ZM11.4226 7.4063C11.748 7.08086 11.748 6.55323 11.4226 6.22779C11.0972 5.90235 10.5695 5.90235 10.2441 6.22779L7.5 8.97187L6.00592 7.47779C5.68049 7.15235 5.15285 7.15235 4.82741 7.47779C4.50197 7.80323 4.50197 8.33086 4.82741 8.6563L6.91074 10.7396C7.23618 11.0651 7.76382 11.0651 8.08926 10.7396L11.4226 7.4063Z"
|
||||
fill="#999999"
|
||||
/>
|
||||
</svg>
|
||||
</AtomsButton>
|
||||
</div>
|
||||
@@ -252,8 +297,12 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<!-- Caution Section -->
|
||||
<div class="self-stretch p-8 bg-[#FAFAFA] rounded-2xl flex flex-col gap-3 text-left">
|
||||
<h5 class="text-[#333333] text-[20px] font-bold leading-[30px] tracking-[-0.6px]">
|
||||
<div
|
||||
class="self-stretch p-8 bg-[#FAFAFA] rounded-2xl flex flex-col gap-3 text-left"
|
||||
>
|
||||
<h5
|
||||
class="text-[#333333] text-[20px] font-bold leading-[30px] tracking-[-0.6px]"
|
||||
>
|
||||
{{ tm('Secure_Notice') }}
|
||||
</h5>
|
||||
<ul class="relative flex flex-col items-start justify-start w-full">
|
||||
@@ -262,11 +311,10 @@ onMounted(() => {
|
||||
:key="caution"
|
||||
v-dompurify-html="caution"
|
||||
class="relative pl-[22px] before:content-[''] before:absolute before:top-[10px] before:left-[9px] before:w-[3px] before:h-[3px] before:rounded-full before:bg-[#999999] text-[#999999] text-[14px] font-[400] leading-[24px] tracking-[-0.42px]"
|
||||
>
|
||||
</li>
|
||||
></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -44,7 +44,9 @@ const csrDownloadFile = (fileUrl: string, fileName?: string) => {
|
||||
*/
|
||||
const csrGetMarketingCode = () => {
|
||||
const route = useRoute()
|
||||
const mcode = Number(`${route.query.mcode != null && route.query.mcode !== '' ? route.query.mcode : ''}`)
|
||||
const mcode = Number(
|
||||
`${route.query.mcode != null && route.query.mcode !== '' ? route.query.mcode : ''}`
|
||||
)
|
||||
return isNaN(mcode) ? undefined : mcode
|
||||
}
|
||||
|
||||
@@ -82,15 +84,20 @@ const isNumeric = (str: string): boolean => {
|
||||
* @param {Function} tm - i18n의 tm 함수 (예: (key) => ({ txt: string }))
|
||||
* @param {any} query - 추가 쿼리 파라미터
|
||||
*/
|
||||
const getParsedCustomLink = (link: string, { tm, query = {} }: ParsedCustomLinkOptions) => {
|
||||
const config = useRuntimeConfig()
|
||||
const getParsedCustomLink = (
|
||||
link: string,
|
||||
{ tm, query = {} }: ParsedCustomLinkOptions
|
||||
) => {
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
let result = `${link || ''}`
|
||||
|
||||
// @c{key} 패턴 치환 (예: @c{stoveCommunityUrl})
|
||||
if (link.includes('@c')) {
|
||||
result = result.replace(/@c\{(.*?)\}/g, (_, key) => {
|
||||
// config.public에서 해당 key 값을 찾아 치환
|
||||
return typeof config.public[key] === 'string' ? config.public[key] : ''
|
||||
// runtimeConfig.public에서 해당 key 값을 찾아 치환
|
||||
return typeof runtimeConfig.public[key] === 'string'
|
||||
? runtimeConfig.public[key]
|
||||
: ''
|
||||
})
|
||||
}
|
||||
|
||||
@@ -132,7 +139,7 @@ const setCookieForDay = (name: string, value: string, exp?: number) => {
|
||||
|
||||
const setCookie = useCookie(name, {
|
||||
expires: new Date(date),
|
||||
path: '/'
|
||||
path: '/',
|
||||
})
|
||||
|
||||
setCookie.value = value
|
||||
@@ -140,7 +147,9 @@ const setCookieForDay = (name: string, value: string, exp?: number) => {
|
||||
|
||||
// 정적 파일인지 확인하는 함수
|
||||
const isStaticFile = (path: string): boolean => {
|
||||
return /\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|scss)$/i.test(path)
|
||||
return /\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|scss)$/i.test(
|
||||
path
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,5 +173,5 @@ export {
|
||||
getParsedCustomLink,
|
||||
setCookieForDay,
|
||||
isStaticFile,
|
||||
isInRange
|
||||
isInRange,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DEFAULT_LOCALE_CODE } from '../../i18n.config'
|
||||
export const getPreferredLanguage = (acceptLanguageHeader = '') => {
|
||||
const languages = acceptLanguageHeader
|
||||
.split(',')
|
||||
.map((lang) => {
|
||||
.map(lang => {
|
||||
const [code, priority = 'q=1'] = lang.trim().split(';q=')
|
||||
return { code, priority: parseFloat(priority) }
|
||||
})
|
||||
@@ -17,7 +17,7 @@ export const getPreferredLanguage = (acceptLanguageHeader = '') => {
|
||||
const parseCookies = (cookieHeader: string) => {
|
||||
const cookies: Record<string, string> = {}
|
||||
if (cookieHeader) {
|
||||
cookieHeader.split(';').forEach((cookie) => {
|
||||
cookieHeader.split(';').forEach(cookie => {
|
||||
const [name, value] = cookie.trim().split('=')
|
||||
if (name && value) {
|
||||
cookies[name] = decodeURIComponent(value)
|
||||
@@ -33,13 +33,17 @@ const parseCookies = (cookieHeader: string) => {
|
||||
* @param {string} path - 현재 URL 경로
|
||||
*/
|
||||
export const csrGetFinalLocale = (path = '', coveragesLocales: string[]) => {
|
||||
const config = useRuntimeConfig()
|
||||
const baseDomain = `${config.public.baseDomain}`
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const baseDomain = `${runtimeConfig.public.baseDomain}`
|
||||
|
||||
let finalLocale = DEFAULT_LOCALE_CODE // 기본값 설정
|
||||
|
||||
// coveragesLocales가 빈 배열이거나 유효하지 않은 경우 기본 언어 반환
|
||||
if (!coveragesLocales || !Array.isArray(coveragesLocales) || coveragesLocales.length === 0) {
|
||||
if (
|
||||
!coveragesLocales ||
|
||||
!Array.isArray(coveragesLocales) ||
|
||||
coveragesLocales.length === 0
|
||||
) {
|
||||
return finalLocale
|
||||
}
|
||||
|
||||
@@ -60,15 +64,21 @@ export const csrGetFinalLocale = (path = '', coveragesLocales: string[]) => {
|
||||
}
|
||||
|
||||
// 2. LOCALE 쿠키 언어
|
||||
const cookieLanguage = `${useCookie('LOCALE', { domain: baseDomain }).value}`.toLowerCase()
|
||||
const cookieLanguage =
|
||||
`${useCookie('LOCALE', { domain: baseDomain }).value}`.toLowerCase()
|
||||
if (cookieLanguage && cookieLanguage !== '') {
|
||||
finalLocale = cookieLanguage
|
||||
return finalLocale
|
||||
}
|
||||
|
||||
// 3. 브라우저 언어
|
||||
const browserLanguage = `${navigator.language || navigator.languages[0]}`.toLowerCase()
|
||||
if (browserLanguage && browserLanguage !== '' && coveragesLocales.includes(browserLanguage)) {
|
||||
const browserLanguage =
|
||||
`${navigator.language || navigator.languages[0]}`.toLowerCase()
|
||||
if (
|
||||
browserLanguage &&
|
||||
browserLanguage !== '' &&
|
||||
coveragesLocales.includes(browserLanguage)
|
||||
) {
|
||||
finalLocale = browserLanguage
|
||||
return finalLocale
|
||||
}
|
||||
@@ -85,11 +95,20 @@ export const csrGetFinalLocale = (path = '', coveragesLocales: string[]) => {
|
||||
* @param {string} path - 현재 URL 경로
|
||||
* @param {any} headers - 요청 헤더
|
||||
*/
|
||||
export const ssrGetFinalLocale = (path = '', headers: any, coveragesLocales: string[], defaultLocale: string) => {
|
||||
export const ssrGetFinalLocale = (
|
||||
path = '',
|
||||
headers: any,
|
||||
coveragesLocales: string[],
|
||||
defaultLocale: string
|
||||
) => {
|
||||
let finalLocale = defaultLocale || DEFAULT_LOCALE_CODE // 기본값 설정
|
||||
try {
|
||||
// coveragesLocales가 빈 배열이거나 유효하지 않은 경우 기본 언어 반환
|
||||
if (!coveragesLocales || !Array.isArray(coveragesLocales) || coveragesLocales.length === 0) {
|
||||
if (
|
||||
!coveragesLocales ||
|
||||
!Array.isArray(coveragesLocales) ||
|
||||
coveragesLocales.length === 0
|
||||
) {
|
||||
return finalLocale
|
||||
}
|
||||
|
||||
@@ -101,7 +120,11 @@ export const ssrGetFinalLocale = (path = '', headers: any, coveragesLocales: str
|
||||
}
|
||||
const pathLocalee = `${path.split('/')[1]}`.toLowerCase()
|
||||
// URL path에 포함된 언어 정보가 지원하는 언어인지 체크
|
||||
if (pathLocalee && pathLocalee !== '' && coveragesLocales.includes(pathLocalee)) {
|
||||
if (
|
||||
pathLocalee &&
|
||||
pathLocalee !== '' &&
|
||||
coveragesLocales.includes(pathLocalee)
|
||||
) {
|
||||
finalLocale = pathLocalee
|
||||
return finalLocale
|
||||
}
|
||||
@@ -110,8 +133,14 @@ export const ssrGetFinalLocale = (path = '', headers: any, coveragesLocales: str
|
||||
// 2. LOCALE 쿠키 언어 (SSR에서는 headers에서 직접 파싱)
|
||||
const cookieHeader = headers.cookie || ''
|
||||
const cookies = parseCookies(cookieHeader)
|
||||
const cookieLanguage = cookies.LOCALE ? `${cookies.LOCALE}`.toLowerCase() : ''
|
||||
if (cookieLanguage && cookieLanguage !== '' && coveragesLocales.includes(cookieLanguage)) {
|
||||
const cookieLanguage = cookies.LOCALE
|
||||
? `${cookies.LOCALE}`.toLowerCase()
|
||||
: ''
|
||||
if (
|
||||
cookieLanguage &&
|
||||
cookieLanguage !== '' &&
|
||||
coveragesLocales.includes(cookieLanguage)
|
||||
) {
|
||||
finalLocale = cookieLanguage
|
||||
return finalLocale
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import { csrFormatJWT } from '#layers/utils/formatUtil'
|
||||
* Stove 로그인
|
||||
*/
|
||||
export const csrGoStoveLogin = () => {
|
||||
const config = useRuntimeConfig()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const gameDataStore = useGameDataStore()
|
||||
|
||||
const loginUrl = config.public.stoveLoginUrl
|
||||
const loginUrl = runtimeConfig.public.stoveLoginUrl
|
||||
const stoveGameId = gameDataStore.gameData?.game_id
|
||||
const stoveGameNo = gameDataStore.gameData?.game_code
|
||||
const redirectUrl = encodeURIComponent(location.href)
|
||||
|
||||
@@ -23,8 +23,8 @@ export const getImageHost = (
|
||||
|
||||
if (/^(https?:\/\/|www\.)/.test(path)) return path
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const { staticUrl, assetsUrl } = config.public
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const { staticUrl, assetsUrl } = runtimeConfig.public
|
||||
const { imageType = 'game' } = options
|
||||
|
||||
const isDevelopment = import.meta.dev
|
||||
|
||||
Reference in New Issue
Block a user