feat: 점검 페이지 추가, external gamedata 호출 추가

This commit is contained in:
“hyeonggkim”
2025-11-03 13:06:58 +09:00
parent 9062e45fff
commit 33aece1011
8 changed files with 114 additions and 47 deletions

View File

@@ -1,6 +1,9 @@
<template>
<header class="header">
<BlocksStoveGnbNew class="min-h-[48px]" />
</header>
<section class="inspection-section">
<clientOnly>
<!-- 로고 -->
<div class="inspection-logo">
@@ -19,10 +22,7 @@
<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('ko', '')" class="time-row"></div>
<div v-dompurify-html="getLocaleTimezone('en', 'US')" class="time-row"></div>
<div v-dompurify-html="getLocaleTimezone('zh-tw', '')" class="time-row"></div>
<div v-dompurify-html="getLocaleTimezone('ja', '')" class="time-row"></div>
<div v-dompurify-html="getLocaleTimezone('', '')" class="time-row"></div>
</div>
</div>
@@ -109,7 +109,7 @@ const rootPath = config.public.staticUrl
const runType = config.public.runType
const translationApi = `${rootPath}/${runType}/test`
const isClient = import.meta.client
// const isClient = import.meta.client
const inspectionStore = useInspectionStore()
const { webInspectionData } = storeToRefs(inspectionStore)
@@ -133,19 +133,32 @@ const { tm, locale } = useI18n({
// ja: (JST)
// 나머지: (KST)
const getLocaleTimezone = (localeType: string, region) => {
const tsStartDate = webInspectionData.value?.start_date || 0
const tsEndDate = webInspectionData.value?.end_date || 0
switch (localeType) {
const tsStartDate = webInspectionData.value?.ts_start_date || 0
const tsEndDate = webInspectionData.value?.ts_end_date || 0
const currentLocale = localeType ? localeType : locale.value
switch (currentLocale) {
case 'ko':
return `${globalDateFormat(new Date(tsStartDate), localeType, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), localeType, region || 'KR', {useFullDate: true})} (KST)`
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)
`
case 'en':
return `${globalDateFormat(new Date(tsStartDate), localeType, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), localeType, 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), localeType, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), localeType, region || '', {useFullDate: true})} (台灣時間)`
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)
`
case 'ja':
return `${globalDateFormat(new Date(tsStartDate), localeType, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), localeType, region || '', {useFullDate: true})} (JST)`
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)
`
default:
return `${globalDateFormat(new Date(tsStartDate), localeType, region || '', {useFullDate: true})} <br class="md:hidden">~ ${globalDateFormat(new Date(tsEndDate), localeType, region || '', {useFullDate: true})} (KST)`
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)
`
}
}
@@ -222,7 +235,7 @@ const handleGameStart = () => {
definePageMeta({
middleware: ['inspection'],
layout: 'inspection',
layout: 'only-stove',
showLoading: false
})
@@ -230,7 +243,7 @@ definePageMeta({
<style scoped>
.inspection-section {
@apply flex flex-col items-center gap-10 px-10 py-[120px] pb-[200px] min-h-screen;
@apply flex flex-col items-center gap-10 px-10 py-[120px] pb-[200px] min-h-[calc(100vh-48px)];
background-color: #F0F0F0;
}

View File

@@ -67,10 +67,10 @@ const config = useRuntimeConfig()
const baseDomain = `${config.public.baseDomain}`
const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore)
// 사용 가능한 언어 목록
const availableLanguages = computed(() => {
return gameDataStore.gameData?.lang_codes?.map(localeCode => ({
return gameData.value?.lang_codes?.map(localeCode => ({
code: localeCode,
name: getLanguageName(localeCode)
})) || [{ code: 'ko', name: '한국어' }]

View File

@@ -0,0 +1,54 @@
import type { GameDataResponse, GameDataRequest } from '#layers/types/api/gameData'
export const useGetGameDataExternal = () => {
const { setGameData } = useGameDataStore()
const logPrefix = {
exception: '[Exception] /composables/useGetGameDataExternal',
failure: '[Failure] /composables/useGetGameDataExternal'
}
const webGameData = ref<GameDataResponse | null>(null)
const getGameDataExternal = async (req: GameDataRequest) => {
console.log("🚀 ~ getGameDataExternal ~ req:", req)
// const config = useRuntimeConfig()
const config = useRuntimeConfig()
const stoveApiUrl = `${config.public.stoveApiUrl}`
const apiUrl = `${stoveApiUrl}/pub-comm/v1.0/template/game?game_domain=${req.gameDomain}&lang_code=${req.langCode}`
try {
const response = (await commonFetch('GET', apiUrl)) as GameDataResponse
console.log("🚀 ~ getGameDataExternal ~ response:", response)
// FIXME: 테스트용 데이터 ---------------------------------------------------
/* if (['local', 'local-gate8', 'dev'].includes(`${config.public.runType}`)) {
response.value = {
inspection_status: 1,
inspection: {
inspection_status: 1,
start_date: '2025-09-19 10:00:00',
end_date: '2025-09-19 12:00:00',
ts_start_date: new Date().getTime(),
ts_end_date: new Date().getTime(),
back_ground_image_type: 'image',
back_ground_image_url: 'https://www.onstove.com',
inspection_title1: '',
inspection_title2: ''
}
}
} */
// ------------------------------------------------------------------------
if (response?.value) {
webGameData.value = response
setGameData(response.value)
}
} catch (e) {
console.error(`${logPrefix.exception}.getGameDataExternal: `, e)
}
}
return { webGameData, getGameDataExternal }
}

View File

@@ -29,6 +29,7 @@ export const useGetInspectionDataExternal = () => {
try {
const response = (await commonFetch('GET', apiUrl)) as ResGetInspectionData
console.log("🚀 ~ getInspectionDataExternal ~ response:", response)
// FIXME: 테스트용 데이터 ---------------------------------------------------
/* if (['local', 'local-gate8', 'dev'].includes(`${config.public.runType}`)) {

View File

@@ -1,4 +1,4 @@
import { useGameDataStore } from '#layers/stores/useGameDataStore'
import type { GameDataRequest, GameDataValue } from '#layers/types/api/gameData'
export default defineNuxtRouteMiddleware(async (to, _from) => {
// 서버 사이드에서는 스킵
@@ -6,13 +6,6 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
return
}
const gameDataStore = useGameDataStore()
// gameData가 로드되지 않았으면 스킵 (다른 미들웨어에서 로드됨)
if (!gameDataStore.gameData) {
return
}
// 현재 경로에서 언어 코드 추출
// 예: /ko/about/story -> ko
// 예: /en/test/page -> en
@@ -20,8 +13,21 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
const match = to.path.match(languagePattern)
const currentLangCode = match ? match[1] : null
//현재 url에서 게임 도메인만 추출
const currentDomain = window.location.hostname;
const req: GameDataRequest = {
gameDomain: `${currentDomain}`,
langCode: `${currentLangCode}`,
}
const { getGameDataExternal } = useGetGameDataExternal()
await getGameDataExternal(req)
const gameDataStore = useGameDataStore()
const gameData = gameDataStore.gameData as GameDataValue
const langCodes = gameData?.lang_codes
// 허용된 언어 코드 목록
const allowedLangCodes = gameDataStore.gameData.lang_codes || []
const allowedLangCodes = langCodes || []
// 현재 언어가 허용된 언어 목록에 없으면 에러 페이지로 이동
if (currentLangCode && !allowedLangCodes.includes(currentLangCode)) {

View File

@@ -3,6 +3,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
if (import.meta.client) {
const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore)
console.log("🚀 ~ 00000 gameData:", gameData.value)
const config = useRuntimeConfig()
// const baseDomain = `${config.public.baseDomain}`
@@ -15,13 +16,13 @@ export default defineNuxtRouteMiddleware(async (to) => {
// })
const finalLocale = csrGetFinalLocale(to.path)
console.log("🚀 ~ finalLocale:", finalLocale)
// localeCookie.value = finalLocale.toUpperCase()
// 웹 점검 -----
const { isWebInspection, getInspectionDataExternal } = useGetInspectionDataExternal()
await getInspectionDataExternal({ baseApiUrl: stoveApiUrl, gameId: stoveGameId })
// 게임 점검 -----
// const { checkGameMaintenance } = useGetGameMaintenance()
// await checkGameMaintenance({

View File

@@ -127,7 +127,7 @@ export default defineEventHandler(async event => {
// const runType = `${config.public.runType}`
const iBaseApiUrl = `${config.public.stoveApiUrlServer}`
const baseDomain = `${config.public.baseDomain}`
console.log("🚀 ~ baseDomain:", config.public.baseDomain)
// console.log("🚀 ~ baseDomain:", config.public.baseDomain)
// const url = getRequestURL(event)
// if (['local', 'local-gate8', 'dev'].includes(runType)) {
@@ -158,7 +158,6 @@ export default defineEventHandler(async event => {
if (fullPath.includes('/inspection')) {
// 리턴 되기 전 언어 쿠키 세팅
const finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers)
console.log("🚀 0000 ~ finalLocale:", finalLocale)
setFinalLocaleCookie(event, finalLocale, baseDomain)
return
}
@@ -177,7 +176,7 @@ export default defineEventHandler(async event => {
// 캐시 키 생성
const cacheKey = 'inspection'
console.log("🚀 11111 ~ cacheKey:", cacheKey)
// console.log("🚀 11111 ~ cacheKey:", cacheKey)
const host =
(getHeader(event, 'host') || getRequestHost(event)).toString() || ''
@@ -194,7 +193,7 @@ export default defineEventHandler(async event => {
const stoveApiUrlServer = config.public.stoveApiUrlServer
const apiUrl = `${stoveApiUrlServer}/pub-comm/v1.0/template/game`
console.log("🚀 ~ apiUrl:", apiUrl)
// console.log("🚀 ~ apiUrl:", apiUrl)
// 2. 언어 코드 추출
const finalLocale = ssrGetFinalLocale(event?.node.req.url, event.node.req.headers)
@@ -218,21 +217,16 @@ export default defineEventHandler(async event => {
event.context.gameData = response.value
event.context.googleAnalyticsId = response.value?.ga_code
console.log('🚀 ~ gameData:', response.value)
// console.log('🚀 ~ gameData:', response.value)
// 점검 데이터 조회
let inspectionData
if (cache.has(cacheKey)) {
inspectionData = cache.get(cacheKey) as WebInspectionData
console.log("🚀 ~ response.value.game_id:", response.value.game_id)
console.log("🚀 22222 ~ 캐시키 있어 inspectionData:", inspectionData)
} else {
// 점검 데이터 조회
if (response.value.game_id) {
const inspectionApiUrl = `${iBaseApiUrl}/pub-comm/v3.0/inspection/${response.value.game_id}`
console.log("🚀 ~ inspectionApiUrl:", inspectionApiUrl)
console.log("🚀 33333 ~ 캐시키 없어 inspectionData:", inspectionData)
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',
@@ -245,6 +239,7 @@ export default defineEventHandler(async event => {
// console.log("🚀 ~ inspectionData:", inspectionData)
}
}
// 4. 현재 시간과 점검 기간 비교
@@ -253,7 +248,6 @@ export default defineEventHandler(async event => {
const tsEndDate = inspectionData?.ts_end_date || 0
const timeUntilInspectionSeconds = Math.floor((tsStartDate - currentTime) / 1000)
// 5. 점검 상태별 캐시 설정
if (inspectionData?.inspection_status === 1 && currentTime >= tsStartDate && currentTime <= tsEndDate) {
/**
@@ -264,8 +258,6 @@ export default defineEventHandler(async event => {
*/
// 현재 경로가 점검 페이지가 아닐 경우 리다이렉트
const inspectionPath = `/${finalLocale}/inspection`
console.log("🚀 44444 ~ fullPath:", fullPath)
console.log("🚀 44444 ~ inspectionPath:", inspectionPath)
if (fullPath !== inspectionPath) {
setCacheHeaders(event, 'no-cache')
}
@@ -332,11 +324,7 @@ export default defineEventHandler(async event => {
fnLocaleMiddleware(event, finalLocale)
}
}
}
} catch (error) {
console.error('gameData load error:', error)

View File

@@ -4,6 +4,10 @@ export interface GameDataRequest {
lang_code: string
q?: string
qc?: string
baseApiUrl: string
gameId: string
gameDomain: string
langCode: string
}
// API 응답 데이터 타입