Merge branch 'feature/202501107-all' into feature/20251001-gil
This commit is contained in:
@@ -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,
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export const hasComponentGroup = (
|
||||
* @param components props.components
|
||||
* @param componentName 컴포넌트 이름
|
||||
* @param options 옵션
|
||||
* - hasGroup: groups 속성에서 데이터 가져오기 (기본값: false)
|
||||
* - isGroup: groups 속성에서 데이터 가져오기 (기본값: false)
|
||||
* - maxLength: 최대 길이 제한
|
||||
* - minLength: 최소 길이 보장 (데이터 반복)
|
||||
* @returns 컴포넌트 컨테이너 배열
|
||||
@@ -90,17 +90,17 @@ export const hasComponentGroup = (
|
||||
export const getComponentContainer = (
|
||||
components: PageDataTemplateComponents | OperateComponents,
|
||||
componentName: string,
|
||||
options: { hasGroup?: boolean; maxLength?: number; minLength?: number } = {}
|
||||
options: { isGroup?: boolean; maxLength?: number; minLength?: number } = {}
|
||||
) => {
|
||||
if (!components) return []
|
||||
|
||||
const { hasGroup = false, maxLength, minLength } = options
|
||||
const { isGroup = false, maxLength, minLength } = options
|
||||
|
||||
// 1. 초기 컨테이너 가져오기
|
||||
const component = components[componentName]
|
||||
if (!component) return []
|
||||
|
||||
let result = hasGroup && 'groups' in component ? component.groups : component
|
||||
let result = isGroup && 'groups' in component ? component.groups : component
|
||||
|
||||
// 2. 최소 길이 보장 (데이터 복제)
|
||||
if (minLength && result.length > 1 && result.length < minLength) {
|
||||
|
||||
@@ -24,76 +24,6 @@ export const csrFormatJWT = (base64EncodeVal: string) => {
|
||||
return decodeVal
|
||||
}
|
||||
|
||||
/**
|
||||
* 타임스탬프를 다양한 날짜 형식으로 변환합니다.
|
||||
* @param timestamp 타임스탬프 (밀리초 또는 초)
|
||||
* @param format 날짜 형식 ('YYYY-MM-DD', 'YYYY-MM-DD HH:mm:ss', 'MM/DD/YYYY', 'YYYY년 MM월 DD일' 등)
|
||||
* @param locale 로케일 (기본값: 'ko-KR')
|
||||
* @returns 포맷된 날짜 문자열
|
||||
*/
|
||||
export const formatTimestamp = (
|
||||
timestamp: number | string,
|
||||
format: string = 'YYYY.MM.DD',
|
||||
_locale: string = 'ko-KR'
|
||||
): string => {
|
||||
if (!timestamp) return ''
|
||||
|
||||
// 타임스탬프를 숫자로 변환
|
||||
let ts = typeof timestamp === 'string' ? parseInt(timestamp) : timestamp
|
||||
|
||||
// 초 단위인 경우 밀리초로 변환
|
||||
if (ts < 10000000000) {
|
||||
ts = ts * 1000
|
||||
}
|
||||
|
||||
const date = new Date(ts)
|
||||
|
||||
// 유효하지 않은 날짜인 경우 빈 문자열 반환
|
||||
if (isNaN(date.getTime())) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// 미리 정의된 형식들
|
||||
const predefinedFormats: Record<string, string> = {
|
||||
'YYYY.MM.DD': date.toISOString().split('T')[0].replace(/-/g, '.'),
|
||||
'YYYY-MM-DD': date.toISOString().split('T')[0],
|
||||
'YYYY-MM-DD HH:mm': date.toISOString().replace('T', ' ').substring(0, 16),
|
||||
'YYYY-MM-DD HH:mm:ss': date.toISOString().replace('T', ' ').split('.')[0],
|
||||
'MM/DD/YYYY': date.toLocaleDateString('en-US'),
|
||||
'DD/MM/YYYY': date.toLocaleDateString('en-GB'),
|
||||
'YYYY년 MM월 DD일': date.toLocaleDateString('ko-KR', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
}),
|
||||
'MM월 DD일': date.toLocaleDateString('ko-KR', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
}),
|
||||
}
|
||||
|
||||
// 미리 정의된 형식이 있으면 사용
|
||||
if (predefinedFormats[format]) {
|
||||
return predefinedFormats[format]
|
||||
}
|
||||
|
||||
// 커스텀 형식 처리
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
|
||||
return format
|
||||
.replace('YYYY', String(year))
|
||||
.replace('MM', month)
|
||||
.replace('DD', day)
|
||||
.replace('HH', hours)
|
||||
.replace('mm', minutes)
|
||||
.replace('ss', seconds)
|
||||
}
|
||||
|
||||
/**
|
||||
* 배열 또는 객체를 배열로 변환합니다.
|
||||
* @param value 변환할 값 (배열, 객체, 또는 undefined/null)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -89,7 +99,11 @@ export const ssrGetFinalLocale = (path = '', headers: any, coveragesLocales: str
|
||||
let finalLocale // 기본값 설정
|
||||
try {
|
||||
// coveragesLocales가 빈 배열이거나 유효하지 않은 경우 기본 언어 반환
|
||||
if (!coveragesLocales || !Array.isArray(coveragesLocales) || coveragesLocales.length === 0) {
|
||||
if (
|
||||
!coveragesLocales ||
|
||||
!Array.isArray(coveragesLocales) ||
|
||||
coveragesLocales.length === 0
|
||||
) {
|
||||
return finalLocale
|
||||
}
|
||||
|
||||
@@ -101,7 +115,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 +128,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,17 +23,15 @@ 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 = process.env.NODE_ENV === 'development'
|
||||
const isDevelopment = import.meta.dev
|
||||
const isTypeGame = imageType === 'game'
|
||||
|
||||
// * [TODO] 수정 필요 : 게임별 이미지 로컬에 추가 필요.
|
||||
if (isTypeGame) {
|
||||
return `${staticUrl}${path}`
|
||||
}
|
||||
if (isTypeGame) return `${staticUrl}${path}`
|
||||
|
||||
// 개발 환경일 때는 루트 경로 생략
|
||||
if (isDevelopment) return path
|
||||
@@ -54,12 +52,13 @@ export const getDeviceSrc = (
|
||||
pathArray: PageDataResourceGroupResPath,
|
||||
options?: {
|
||||
resourcesType?: 'image' | 'video'
|
||||
imageType?: 'common' | 'game'
|
||||
}
|
||||
) => {
|
||||
// pathArray가 없으면 null 반환
|
||||
if (!pathArray) return null
|
||||
|
||||
const { resourcesType = 'image' } = options ?? {}
|
||||
const { resourcesType = 'image', imageType = 'game' } = options ?? {}
|
||||
const pcField = resourcesType === 'video' ? 'path_vid_pc' : 'path_pc'
|
||||
const mobileField = resourcesType === 'video' ? 'path_vid_mo' : 'path_mo'
|
||||
|
||||
@@ -70,8 +69,8 @@ export const getDeviceSrc = (
|
||||
if (!pcPath && !mobilePath) return null
|
||||
|
||||
const resolvedImages = {
|
||||
pc: pcPath ? getImageHost(pcPath) : '',
|
||||
mobile: mobilePath ? getImageHost(mobilePath) : '',
|
||||
pc: pcPath ? getImageHost(pcPath, { imageType }) : '',
|
||||
mobile: mobilePath ? getImageHost(mobilePath, { imageType }) : '',
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user