{{ props.title }}
@@ -47,7 +52,7 @@ const handleLinkClick = (title: string) => {
@@ -56,7 +61,7 @@ const handleLinkClick = (title: string) => {
diff --git a/layers/components/blocks/slide/Default.vue b/layers/components/blocks/slide/Default.vue
index 807d501..cdb1102 100644
--- a/layers/components/blocks/slide/Default.vue
+++ b/layers/components/blocks/slide/Default.vue
@@ -8,6 +8,7 @@ interface Props {
slideItemLength?: number
autoplay?: boolean
perPage?: number
+ drag?: boolean
arrows?: boolean
pagination?: boolean
paginationData?: PageDataResourceGroups
@@ -16,6 +17,8 @@ interface Props {
const props = withDefaults(defineProps
(), {
autoplay: false,
+ perPage: 1,
+ drag: true,
arrows: true,
pagination: true,
})
@@ -25,26 +28,25 @@ const emit = defineEmits(['mounted', 'move', 'arrowClick'])
// Splide 화살표 로직을 위한 composable 사용
const { addArrowClickListeners } = useSplideArrow()
-const perPage = computed(() => props.perPage ?? 1)
-const isMultipleItems = computed(
- () => (props.slideItemLength ?? 0) > perPage.value
-)
-const resolvedType = computed(() => {
+const slideType = computed(() => {
if (props.type) return props.type
- return isMultipleItems.value ? 'loop' : 'slide'
+
+ return (props.slideItemLength ?? 0) > 1 ? 'loop' : 'slide'
})
const options = computed((): ResponsiveOptions => {
return {
- type: resolvedType.value,
+ type: slideType.value,
autoWidth: true,
autoHeight: true,
- perPage: perPage.value,
+ perPage: props.perPage,
speed: 500,
updateOnMove: true,
autoplay: props.autoplay,
- arrows: props.arrows && isMultipleItems.value,
- pagination: props.pagination && isMultipleItems.value,
+ drag: props.drag,
+ trimSpace: false,
+ arrows: props.arrows,
+ pagination: props.pagination,
classes: {
arrows: 'splide-arrows',
arrow: 'splide-arrow',
@@ -82,7 +84,7 @@ const handleMove = (
diff --git a/layers/composables/useBreakpoints.ts b/layers/composables/useBreakpoints.ts
index ccbed4e..9c476fc 100644
--- a/layers/composables/useBreakpoints.ts
+++ b/layers/composables/useBreakpoints.ts
@@ -1,8 +1,8 @@
-import { useMediaQuery } from '@vueuse/core'
+import { useBreakpoints } from '@vueuse/core'
import { getDeviceSrc } from '#layers/utils/styleUtil'
import type { PageDataResourceGroupResPath } from '#layers/types/api/pageData'
-const BREAKPOINTS = {
+export const BREAKPOINTS = {
xs: 360,
sm: 768,
md: 1024,
@@ -10,24 +10,16 @@ const BREAKPOINTS = {
} as const
/**
- * useMediaQuery 기반 반응형 브레이크포인트
+ * useBreakpoints 기반 반응형 브레이크포인트
*/
export const useResponsiveBreakpoints = () => {
- const ssrWidth = BREAKPOINTS.xs
- const isXs = useMediaQuery(`(min-width: ${BREAKPOINTS.xs}px)`, { ssrWidth })
- const isSm = useMediaQuery(`(min-width: ${BREAKPOINTS.sm}px)`, { ssrWidth })
- const isMd = useMediaQuery(`(min-width: ${BREAKPOINTS.md}px)`, { ssrWidth })
- const isLg = useMediaQuery(`(min-width: ${BREAKPOINTS.lg}px)`, { ssrWidth })
- const isMobile = useMediaQuery(`(max-width: ${BREAKPOINTS.md - 1}px)`, {
- ssrWidth,
- })
- const isTablet = useMediaQuery(
- `(min-width: ${BREAKPOINTS.sm}px) and (max-width: ${BREAKPOINTS.md - 1}px)`,
- { ssrWidth }
- )
- const isDesktop = useMediaQuery(`(min-width: ${BREAKPOINTS.md}px)`, {
- ssrWidth,
- })
+ const breakpoints = useBreakpoints(BREAKPOINTS)
+ const isXs = breakpoints.smaller('sm') // < 768px
+ const isSm = breakpoints.smaller('md') // < 1024px
+ const isMd = breakpoints.smaller('lg') // < 1440px
+ const isLg = breakpoints.greater('lg') // >= 1440px
+ const isMobile = isXs || isSm
+ const isDesktop = isLg || isMd
return computed(() => ({
isXs: isXs.value,
@@ -35,7 +27,6 @@ export const useResponsiveBreakpoints = () => {
isMd: isMd.value,
isLg: isLg.value,
isMobile: isMobile.value,
- isTablet: isTablet.value,
isDesktop: isDesktop.value,
}))
}
diff --git a/layers/composables/useResourcesData.ts b/layers/composables/useResourcesData.ts
index d850298..b7d9a3a 100644
--- a/layers/composables/useResourcesData.ts
+++ b/layers/composables/useResourcesData.ts
@@ -2,9 +2,18 @@ import type {
getOperateResourcesDataParams,
OperateResourcesDataResponse,
OperateComponents,
+ getCwmsArticleDataParams,
+ CwmsArticleDataResponse,
+ CwmsArticleData,
} from '#layers/types/api/resourcesData'
export const useResourcesData = () => {
+ /**
+ *
+ * @param params getOperateResourcesDataParams
+ * @returns OperateComponents | null
+ * @description 운영 리소스 데이터 조회
+ */
const getOperateResourcesData = async (
params: getOperateResourcesDataParams
): Promise => {
@@ -35,7 +44,60 @@ export const useResourcesData = () => {
return null
}
+ /**
+ *
+ * @param articleGroupCode 게시판 그룹 코드 (예: 128093)
+ * @param options 옵션 객체
+ * @returns 게시판 글 목록 응답
+ */
+ const getCwmsArticleData = async (
+ articleGroupCode: string,
+ articleGroupSeq: number,
+ params: getCwmsArticleDataParams
+ ): Promise => {
+ const {
+ lang,
+ sortTypeCode,
+ interactionTypeCodes,
+ handleCode,
+ contentYn,
+ summaryYn,
+ headlineTitleYn,
+ translationYn,
+ page,
+ size,
+ } = params
+
+ const config = useRuntimeConfig()
+ const stoveApiBaseUrl = config.public.stoveApiUrl
+ const apiUrl = `${stoveApiBaseUrl}/cwms/v3.0/article_group/${articleGroupCode}/${articleGroupSeq}/article/list`
+
+ const queryParams: Record = {
+ lang: lang,
+ sort_type_code: sortTypeCode,
+ interaction_type_code: interactionTypeCodes?.join(','),
+ handle_code: handleCode ? 'Y' : 'N',
+ content_yn: contentYn ? 'Y' : 'N',
+ summary_yn: summaryYn ? 'Y' : 'N',
+ headline_title_yn: headlineTitleYn ? 'Y' : 'N',
+ translation_yn: translationYn ? 'Y' : 'N',
+ page: page,
+ size: size,
+ }
+
+ const response = (await commonFetch('GET', apiUrl, {
+ query: queryParams,
+ loading: true,
+ })) as CwmsArticleDataResponse | null
+
+ if (response?.code === 0 && 'value' in response) {
+ return response.value
+ }
+ return null
+ }
+
return {
getOperateResourcesData,
+ getCwmsArticleData,
}
}
diff --git a/layers/composables/useTemplateRegistry.ts b/layers/composables/useTemplateRegistry.ts
index bbca03e..8f97ba3 100644
--- a/layers/composables/useTemplateRegistry.ts
+++ b/layers/composables/useTemplateRegistry.ts
@@ -7,7 +7,7 @@ import GrGallery03 from '#layers/templates/GrGallery03/index.vue'
import GrDetail01 from '#layers/templates/GrDetail01/index.vue'
import GrDetail02 from '#layers/templates/GrDetail02/index.vue'
import GrDetail03 from '#layers/templates/GrDetail03/index.vue'
-// import GrBoard01 from '#layers/templates/GrBoard01/index.vue'
+import GrBoard01 from '#layers/templates/GrBoard01/index.vue'
import GrContents01 from '#layers/templates/GrContents01/index.vue'
const templateRegistry = {
@@ -17,7 +17,7 @@ const templateRegistry = {
GR_GALLERY_01: { component: GrGallery01 },
GR_GALLERY_02: { component: GrGallery02 },
GR_GALLERY_03: { component: GrGallery03 },
- // GR_BOARD_01: { component: GrBoard01 },
+ GR_BOARD_01: { component: GrBoard01 },
GR_DETAIL_01: { component: GrDetail01 },
GR_DETAIL_02: { component: GrDetail02 },
GR_DETAIL_03: { component: GrDetail03 },
diff --git a/layers/templates/GrBoard01/index.vue b/layers/templates/GrBoard01/index.vue
index b4f5b11..6573aac 100644
--- a/layers/templates/GrBoard01/index.vue
+++ b/layers/templates/GrBoard01/index.vue
@@ -1,12 +1,8 @@
-
+
{
:resources-data="mainTitleData"
class="title-md"
/>
-
-
-
-
-
-
-
-
+ class="mt-[48px] md:mt-[64px]"
+ />
+
diff --git a/layers/templates/GrVisual03/index.vue b/layers/templates/GrVisual03/index.vue
index 08fc306..4765c93 100644
--- a/layers/templates/GrVisual03/index.vue
+++ b/layers/templates/GrVisual03/index.vue
@@ -6,7 +6,6 @@ import {
getComponentGroup,
hasComponentGroup,
} from '#layers/utils/dataUtil'
-import { getPaginationClass } from '#layers/utils/styleUtil'
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
interface Props {
diff --git a/layers/types/api/gameData.ts b/layers/types/api/gameData.ts
index 140c940..b45dae1 100644
--- a/layers/types/api/gameData.ts
+++ b/layers/types/api/gameData.ts
@@ -38,6 +38,7 @@ export interface GameDataValue {
favicon_json: GameDataFavicon
meta_tag_json: GameDataMetaTag
sns_json: GameDataSns
+ url_json: Record
footer_json: string // JSON 문자열로 변경
comm_img_json: GameDataCommImg
market_json: Record
diff --git a/layers/types/api/resourcesData.ts b/layers/types/api/resourcesData.ts
index 82f9cdc..ae0589f 100644
--- a/layers/types/api/resourcesData.ts
+++ b/layers/types/api/resourcesData.ts
@@ -2,7 +2,7 @@
* Resources Data API 타입 정의
*/
-// 리스트 운영 그룹 아이템
+// OperateResources
export interface OperateGroupItem {
seq: number
flag_type?: number
@@ -25,14 +25,12 @@ export interface OperateComponents {
[key: string]: OperateGroupList
}
-// Resources Data API 응답
export interface OperateResourcesDataResponse {
code: number
message: string
value: OperateComponents
}
-// getOperateResourcesData 함수 파라미터
export interface getOperateResourcesDataParams {
pageSeq: string
pageVer: string
@@ -41,3 +39,83 @@ export interface getOperateResourcesDataParams {
q?: string
qc?: string
}
+
+// CwmsArticle
+export interface CwmsArticleAdminOptionSummary {
+ notice_cancel_reservation_yn: 'Y' | 'N'
+ publish_reservation_yn: 'Y' | 'N'
+}
+
+export interface CwmsArticleAttachSummary {
+ image_yn: 'Y' | 'N'
+ movie_yn: 'Y' | 'N'
+ poll_yn: 'Y' | 'N'
+ attach_file_yn: 'Y' | 'N'
+ music_yn: 'Y' | 'N'
+ script_yn: 'Y' | 'N'
+}
+
+export interface CwmsArticleSnapshotUserInfo {
+ nickname: string
+ profile_img: string
+}
+export interface CwmsArticleUserInfo {
+ stove_nickname?: string
+ user_game_info?: Record
+ snapshot_user_info?: CwmsArticleSnapshotUserInfo
+}
+
+export interface CwmsArticleItem {
+ board_seq: number
+ channel_key: string
+ channel_seq: number
+ article_id: string
+ headline_info?: {
+ headline_seq: number
+ headline_name: string
+ }
+ fixed_yn?: 'Y' | 'N'
+ title: string
+ subtitle: string
+ content?: string
+ summary?: string
+ media_thumbnail_url: string | null
+ media_count: number
+ user_interaction_score_info: Record
+ create_datetime: number
+ update_datetime: number
+ article_status_code: string
+ user_info: CwmsArticleUserInfo
+ attach_summary_info: CwmsArticleAttachSummary
+ admin_option_summary_info: CwmsArticleAdminOptionSummary
+ view_mode: string
+ source_lang: string | null
+ target_lang?: string | null
+ translation_status: string | null
+}
+
+export interface CwmsArticleData {
+ total: number
+ page: number
+ size: number
+ list: CwmsArticleItem[]
+}
+
+export interface CwmsArticleDataResponse {
+ code: number
+ message: string
+ value: CwmsArticleData
+}
+
+export interface getCwmsArticleDataParams {
+ lang?: string
+ sortTypeCode?: string
+ interactionTypeCodes?: string[]
+ handleCode?: boolean
+ contentYn?: boolean
+ summaryYn?: boolean
+ headlineTitleYn?: boolean
+ translationYn?: boolean
+ page?: number
+ size?: number
+}