feat. GR_GALLERY_02 템플릿 제작
This commit is contained in:
167
layers/components/blocks/slide/CenterFocus.vue
Normal file
167
layers/components/blocks/slide/CenterFocus.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<script setup lang="ts">
|
||||
import { Splide } from '@splidejs/vue-splide'
|
||||
import type { Splide as SplideType, ResponsiveOptions } from '@splidejs/splide'
|
||||
import type { SlideItemSize } from '#layers/types/components/slide'
|
||||
|
||||
interface Props {
|
||||
slideItemSize: SlideItemSize
|
||||
slideItemLength?: number
|
||||
autoplay?: boolean | string
|
||||
arrows?: boolean
|
||||
pagination?: boolean
|
||||
class?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
autoplay: false,
|
||||
arrows: true,
|
||||
pagination: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['mounted', 'move', 'moved'])
|
||||
|
||||
const isMultipleItems = computed(() => {
|
||||
return props.slideItemLength > 1
|
||||
})
|
||||
|
||||
const options = computed((): ResponsiveOptions => {
|
||||
return {
|
||||
type: isMultipleItems.value ? 'loop' : 'slide',
|
||||
focus: 'center',
|
||||
autoWidth: true,
|
||||
autoHeight: true,
|
||||
speed: 400,
|
||||
updateOnMove: true,
|
||||
arrows: props.arrows && isMultipleItems.value,
|
||||
pagination: props.pagination && isMultipleItems.value,
|
||||
autoplay: props.autoplay,
|
||||
classes: {
|
||||
arrows: 'splide-arrows',
|
||||
arrow: 'splide-arrow',
|
||||
prev: 'arrow-prev',
|
||||
next: 'arrow-next',
|
||||
pagination: 'splide-pagination-bullets',
|
||||
page: 'splide-pagination-bullet',
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
if (!props.slideItemSize) return {}
|
||||
|
||||
const { mo, pc } = props.slideItemSize
|
||||
const moScale = mo?.scale || 1.1429
|
||||
const pcScale = pc?.scale || 1.1429
|
||||
|
||||
const moSize = {
|
||||
'--banner-width-mo': `${mo.width}px`,
|
||||
'--banner-height-mo': `${mo.height}px`,
|
||||
'--banner-gap-mo': `${mo.gap}px`,
|
||||
// 모바일 확대값
|
||||
'--banner-width-mo-active': `${mo.width * moScale}px`,
|
||||
'--banner-height-mo-active': `${mo.height * moScale}px`,
|
||||
'--banner-width-mo-container': `${mo.width * moScale + mo.gap}px`,
|
||||
}
|
||||
|
||||
const pcSize = {
|
||||
'--banner-width-pc': `${pc.width}px`,
|
||||
'--banner-height-pc': `${pc.height}px`,
|
||||
'--banner-gap-pc': `${pc.gap}px`,
|
||||
// PC 확대값
|
||||
'--banner-width-pc-active': `${pc.width * pcScale}px`,
|
||||
'--banner-height-pc-active': `${pc.height * pcScale}px`,
|
||||
'--banner-width-pc-container': `${pc.width * pcScale}px`,
|
||||
}
|
||||
|
||||
return {
|
||||
...moSize,
|
||||
...pcSize,
|
||||
}
|
||||
})
|
||||
|
||||
const handleSplideMounted = (splide: SplideType) => {
|
||||
emit('mounted', splide)
|
||||
splide.refresh()
|
||||
}
|
||||
|
||||
const handleMove = (
|
||||
splide: SplideType,
|
||||
newIndex: number,
|
||||
oldIndex: number,
|
||||
destIndex: number
|
||||
) => {
|
||||
emit('move', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
|
||||
const handleMoved = (
|
||||
splide: SplideType,
|
||||
newIndex: number,
|
||||
oldIndex: number,
|
||||
destIndex: number
|
||||
) => {
|
||||
emit('moved', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`center-highlight ${props.class || ''}`" :style="style">
|
||||
<Splide
|
||||
:options="options"
|
||||
@splide:mounted="handleSplideMounted"
|
||||
@splide:move="handleMove"
|
||||
@splide:moved="handleMoved"
|
||||
>
|
||||
<slot />
|
||||
</Splide>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.center-highlight {
|
||||
@apply w-full;
|
||||
}
|
||||
.center-highlight:deep(.splide__slide) {
|
||||
@apply flex items-center justify-center;
|
||||
width: var(--banner-width-mo);
|
||||
height: var(--banner-height-mo-active);
|
||||
margin-right: var(--banner-gap-mo);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide) .slide-inner {
|
||||
width: var(--banner-width-mo);
|
||||
height: var(--banner-height-mo);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide.is-active) {
|
||||
width: var(--banner-width-mo-container);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide.is-active) .slide-inner {
|
||||
width: var(--banner-width-mo-active);
|
||||
height: var(--banner-height-mo-active);
|
||||
transition: all 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* PC 스타일 */
|
||||
@media (min-width: 1024px) {
|
||||
.center-highlight:deep(.splide__slide) {
|
||||
width: var(--banner-width-pc);
|
||||
height: var(--banner-height-pc-active);
|
||||
margin-right: var(--banner-gap-pc);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide) .slide-inner {
|
||||
width: var(--banner-width-pc);
|
||||
height: var(--banner-height-pc);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide.is-active) {
|
||||
width: var(--banner-width-pc-container);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide.is-active) .slide-inner {
|
||||
width: var(--banner-width-pc-active);
|
||||
height: var(--banner-height-pc-active);
|
||||
}
|
||||
.center-highlight:deep(.arrow-prev) {
|
||||
left: 28px;
|
||||
}
|
||||
.center-highlight:deep(.arrow-next) {
|
||||
right: 28px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -50,28 +50,35 @@ const style = computed(() => {
|
||||
if (!props.slideItemSize) return {}
|
||||
|
||||
const { mo, pc } = props.slideItemSize
|
||||
const scaleFactor = 1.1429
|
||||
const moScale = mo?.scale || 1.1429
|
||||
const pcScale = pc?.scale || 1.1429
|
||||
|
||||
return {
|
||||
// 모바일 기본값
|
||||
const moSize = {
|
||||
'--banner-width-mo': `${mo.width}px`,
|
||||
'--banner-height-mo': `${mo.height}px`,
|
||||
'--banner-gap-mo': `${mo.gap}px`,
|
||||
// 모바일 확대값
|
||||
'--banner-width-mo-active': `${mo.width * scaleFactor}px`,
|
||||
'--banner-height-mo-active': `${mo.height * scaleFactor}px`,
|
||||
'--banner-width-mo-container': `${mo.width * scaleFactor + mo.gap}px`,
|
||||
'--banner-width-mo-active': `${mo.width * moScale}px`,
|
||||
'--banner-height-mo-active': `${mo.height * moScale}px`,
|
||||
'--banner-width-mo-container': `${mo.width * moScale + mo.gap}px`,
|
||||
}
|
||||
|
||||
// PC 기본값
|
||||
const pcSize = {
|
||||
'--banner-width-pc': `${pc.width}px`,
|
||||
'--banner-height-pc': `${pc.height}px`,
|
||||
'--banner-gap-pc': `${pc.gap}px`,
|
||||
// PC 확대값
|
||||
'--banner-width-pc-active': `${pc.width * scaleFactor}px`,
|
||||
'--banner-height-pc-active': `${pc.height * scaleFactor}px`,
|
||||
'--banner-width-pc-container': `${pc.width * scaleFactor + pc.gap * 4}px`,
|
||||
// PC arrow값
|
||||
'--banner-arrow-pc': `${(pc.width * scaleFactor) / 2 + (pc.gap * 3) / 2}px`,
|
||||
'--banner-width-pc-active': `${pc.width * pcScale}px`,
|
||||
'--banner-height-pc-active': `${pc.height * pcScale}px`,
|
||||
'--banner-width-pc-container': props.arrows
|
||||
? `${pc.width * pcScale + pc.gap * 4}px`
|
||||
: `${pc.width * pcScale}px`,
|
||||
'--banner-arrow-pc': `${(pc.width * pcScale) / 2 + (pc.gap * 3) / 2}px`,
|
||||
}
|
||||
|
||||
return {
|
||||
...moSize,
|
||||
...pcSize,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -125,7 +132,6 @@ const handleMoved = (
|
||||
.center-highlight:deep(.splide__slide) .slide-inner {
|
||||
width: var(--banner-width-mo);
|
||||
height: var(--banner-height-mo);
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.center-highlight:deep(.splide__slide.is-active) {
|
||||
width: var(--banner-width-mo-container);
|
||||
@@ -133,6 +139,7 @@ const handleMoved = (
|
||||
.center-highlight:deep(.splide__slide.is-active) .slide-inner {
|
||||
width: var(--banner-width-mo-active);
|
||||
height: var(--banner-height-mo-active);
|
||||
transition: all 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* PC 스타일 */
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Splide as SplideType, Options } from '@splidejs/splide'
|
||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||
|
||||
interface Props {
|
||||
slideItemList: { media: any; set_order: number }[]
|
||||
slideData: { media: any; set_order: number }[]
|
||||
videoPlay?: PageDataResourceGroup
|
||||
arrows?: boolean
|
||||
pagination?: boolean
|
||||
@@ -76,7 +76,7 @@ onBeforeUnmount(() => {
|
||||
<!-- 메인 슬라이드 -->
|
||||
<Splide ref="mainRef" :options="mainOptions" class="main-splide">
|
||||
<SplideSlide
|
||||
v-for="(item, index) in props.slideItemList"
|
||||
v-for="(item, index) in props.slideData"
|
||||
:key="item.set_order || index"
|
||||
class="main-slide"
|
||||
>
|
||||
@@ -108,7 +108,7 @@ onBeforeUnmount(() => {
|
||||
<!-- 썸네일 슬라이드 -->
|
||||
<Splide ref="thumbsRef" :options="thumbOptions" class="thumbnail-splide">
|
||||
<SplideSlide
|
||||
v-for="(item, index) in props.slideItemList"
|
||||
v-for="(item, index) in props.slideData"
|
||||
:key="item.set_order || index"
|
||||
class="thumbnail-slide"
|
||||
>
|
||||
|
||||
199
layers/public/data/GrGallery02.txt
Normal file
199
layers/public/data/GrGallery02.txt
Normal file
@@ -0,0 +1,199 @@
|
||||
const test = {
|
||||
arrow: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: '/local/template/l9/common/btn_system_chevron_prev.svg',
|
||||
},
|
||||
tracking: {
|
||||
click_item: '3. 네비게이션(좌)',
|
||||
action_type: 'click',
|
||||
click_sarea: 'aboutLord_tmpl_01__arrow',
|
||||
},
|
||||
group_code: 'arrow_left',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_COMM_GLOBAL',
|
||||
},
|
||||
{
|
||||
res_path: {
|
||||
path_mo: '/local/template/l9/common/btn_system_chevron_next.svg',
|
||||
},
|
||||
tracking: {
|
||||
click_item: '3. 네비게이션(우)',
|
||||
action_type: 'click',
|
||||
click_sarea: 'aboutLord_tmpl_01__arrow',
|
||||
},
|
||||
group_code: 'arrow_right',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_COMM_GLOBAL',
|
||||
},
|
||||
],
|
||||
},
|
||||
mainTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '캐릭터 소개',
|
||||
color_code: '',
|
||||
color_name: 'text-secondary',
|
||||
},
|
||||
res_scope: 'lang',
|
||||
group_code: 'mainTitle_text',
|
||||
group_type: 'text',
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
background: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: 'https://picsum.photos/800/600',
|
||||
path_pc: 'https://picsum.photos/800/600',
|
||||
},
|
||||
res_scope: 'comm',
|
||||
group_code: 'background_img',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_COMM',
|
||||
},
|
||||
],
|
||||
},
|
||||
group_sets: [
|
||||
{
|
||||
imgList: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: 'https://picsum.photos/800/600',
|
||||
path_pc:
|
||||
'https://dummyimage.com/800x600/cccccc/969696&text=Test+Image',
|
||||
},
|
||||
group_code: 'imgList_img',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
set_order: 1,
|
||||
buttonList: {
|
||||
groups: [
|
||||
{
|
||||
btn_info: {
|
||||
detail: {
|
||||
action: {
|
||||
url: '/ko/about/lord/lael',
|
||||
link_target: '_self',
|
||||
click_action_type: 1,
|
||||
},
|
||||
btn_type: 'URL',
|
||||
},
|
||||
txt_btn_name: '자세히 보기',
|
||||
color_code_btn: '#CECECE',
|
||||
color_code_txt: '#CECECE',
|
||||
color_name_btn: '',
|
||||
color_name_txt: '',
|
||||
},
|
||||
tracking: {
|
||||
click_item: '라엘',
|
||||
action_type: 'click',
|
||||
click_sarea: 'aboutLord_tmpl_01__buttonList_btn',
|
||||
},
|
||||
group_code: 'buttonList_btn',
|
||||
group_type: 'button',
|
||||
resource_type: 'BTN',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
imgList: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: 'https://picsum.photos/800/600',
|
||||
path_pc: 'https://picsum.photos/800/600',
|
||||
},
|
||||
group_code: 'imgList_img',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
set_order: 2,
|
||||
buttonList: {
|
||||
groups: [
|
||||
{
|
||||
btn_info: {
|
||||
detail: {
|
||||
action: {
|
||||
url: '/ko/about/lord/rpwain',
|
||||
link_target: '_self',
|
||||
click_action_type: 1,
|
||||
},
|
||||
btn_type: 'URL',
|
||||
},
|
||||
txt_btn_name: '자세히 보기',
|
||||
color_code_btn: '#CECECE',
|
||||
color_code_txt: '#CECECE',
|
||||
color_name_btn: '',
|
||||
color_name_txt: '',
|
||||
},
|
||||
tracking: {
|
||||
click_item: '로웨인',
|
||||
action_type: 'click',
|
||||
click_sarea: 'aboutLord_tmpl_01__buttonList_btn',
|
||||
},
|
||||
group_code: 'buttonList_btn',
|
||||
group_type: 'button',
|
||||
resource_type: 'BTN',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
imgList: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: 'https://picsum.photos/800/600',
|
||||
path_pc: 'https://picsum.photos/800/600',
|
||||
},
|
||||
group_code: 'imgList_img',
|
||||
group_type: 'image',
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
set_order: 3,
|
||||
buttonList: {
|
||||
groups: [
|
||||
{
|
||||
btn_info: {
|
||||
detail: {
|
||||
action: {
|
||||
url: '/ko/about/lord/morian',
|
||||
link_target: '_self',
|
||||
click_action_type: 1,
|
||||
},
|
||||
btn_type: 'URL',
|
||||
},
|
||||
txt_btn_name: '자세히 보기',
|
||||
color_code_btn: '#CECECE',
|
||||
color_code_txt: '#CECECE',
|
||||
color_name_btn: '',
|
||||
color_name_txt: '',
|
||||
},
|
||||
tracking: {
|
||||
click_item: '모리안',
|
||||
action_type: 'click',
|
||||
click_sarea: 'aboutLord_tmpl_01__buttonList_btn',
|
||||
},
|
||||
group_code: 'buttonList_btn',
|
||||
group_type: 'button',
|
||||
resource_type: 'BTN',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -48,8 +48,10 @@ const test = {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: '/local/template/l9/5/1/1/GR_GALLERY_02/common/bg_m.jpg',
|
||||
path_pc: '/local/template/l9/5/1/1/GR_GALLERY_02/common/bg.jpg',
|
||||
path_mo:
|
||||
'https://dummyimage.com/800x600/abb883/969696&text=Test+Image',
|
||||
path_pc:
|
||||
'https://dummyimage.com/800x600/8c83b8/969696&text=Test+Image',
|
||||
},
|
||||
res_scope: 'comm',
|
||||
group_code: 'background_img',
|
||||
@@ -104,31 +106,6 @@ const test = {
|
||||
},
|
||||
],
|
||||
},
|
||||
subTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 힘',
|
||||
color_code: '#ff0000',
|
||||
color_name: '',
|
||||
},
|
||||
group_code: 'mainTitle_text',
|
||||
group_type: 'text',
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
description: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 00000000',
|
||||
color_code: '#f0f0f0',
|
||||
color_name: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
imgList: {
|
||||
@@ -174,38 +151,14 @@ const test = {
|
||||
},
|
||||
],
|
||||
},
|
||||
subTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 힘',
|
||||
color_code: '#ffffff',
|
||||
color_name: '',
|
||||
},
|
||||
group_code: 'mainTitle_text',
|
||||
group_type: 'text',
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
description: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 힘111111',
|
||||
color_code: '#ffffff',
|
||||
color_name: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
imgList: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: 'https://picsum.photos/800/600',
|
||||
path_mo:
|
||||
'https://dummyimage.com/800x600/b383b8/969696&text=Test+Image',
|
||||
path_pc: 'https://picsum.photos/800/600',
|
||||
},
|
||||
group_code: 'imgList_img',
|
||||
@@ -244,31 +197,6 @@ const test = {
|
||||
},
|
||||
],
|
||||
},
|
||||
subTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 힘',
|
||||
color_code: '#ffffff',
|
||||
color_name: '',
|
||||
},
|
||||
group_code: 'mainTitle_text',
|
||||
group_type: 'text',
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
description: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '강력한 마스터리의 힘22222',
|
||||
color_code: '#ffffff',
|
||||
color_name: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,13 @@ const backgroundData = computed(() =>
|
||||
const mainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const slideThumbnailData = computed(() => props.components.group_sets)
|
||||
const slideData = computed(() => {
|
||||
if (props.components.group_sets.length < 3) {
|
||||
return [...props.components.group_sets, ...props.components.group_sets]
|
||||
}
|
||||
|
||||
return props.components.group_sets
|
||||
})
|
||||
const videoPlayData = computed(() =>
|
||||
getComponentGroup(props.components, 'videoPlay')
|
||||
)
|
||||
@@ -30,7 +36,7 @@ const videoPlayData = computed(() =>
|
||||
class="title-sm"
|
||||
/>
|
||||
<BlocksSlideThumbnail
|
||||
:slide-item-list="slideThumbnailData"
|
||||
:slide-data="slideData"
|
||||
:video-play="videoPlayData"
|
||||
class="mt-[24px] md:mt-[32px]"
|
||||
/>
|
||||
|
||||
92
layers/templates/GrGallery02/index.vue
Normal file
92
layers/templates/GrGallery02/index.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import { getComponentGroup } from '#layers/utils/dataUtil'
|
||||
import type { Splide as SplideType } from '@splidejs/splide'
|
||||
|
||||
interface Props {
|
||||
components: Record<string, any>
|
||||
pageVerTmplSeq: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const backgroundData = computed(() =>
|
||||
getComponentGroup(props.components, 'background')
|
||||
)
|
||||
const mainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const slideData = computed(() => {
|
||||
if (props.components.group_sets.length < 3) {
|
||||
return [...props.components.group_sets, ...props.components.group_sets]
|
||||
}
|
||||
|
||||
return props.components.group_sets
|
||||
})
|
||||
const buttonListData = ref(
|
||||
getComponentGroupAry(slideData?.value[0], 'buttonList')
|
||||
)
|
||||
|
||||
const slideItemSize = {
|
||||
mo: {
|
||||
width: 295,
|
||||
height: 384,
|
||||
gap: 12,
|
||||
scale: 1,
|
||||
},
|
||||
pc: {
|
||||
width: 419,
|
||||
height: 564,
|
||||
gap: 20,
|
||||
scale: 1.0979,
|
||||
},
|
||||
}
|
||||
|
||||
const handleChange = (
|
||||
_splide: SplideType,
|
||||
newIndex: number,
|
||||
_oldIndex: number,
|
||||
_destIndex: number
|
||||
) => {
|
||||
buttonListData.value = getComponentGroupAry(
|
||||
slideData.value[newIndex],
|
||||
'buttonList'
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="section-container">
|
||||
<WidgetsBackground v-if="backgroundData" :resources-data="backgroundData" />
|
||||
<div class="section-content px-0">
|
||||
<WidgetsMainTitle
|
||||
v-if="mainTitleData"
|
||||
:resources-data="mainTitleData"
|
||||
class="title-sm"
|
||||
/>
|
||||
<BlocksSlideCenterFocus
|
||||
v-if="slideData"
|
||||
:slide-item-size="slideItemSize"
|
||||
:slide-item-length="slideData?.length"
|
||||
:pagination="false"
|
||||
class="mt-[24px] md:mt-[48px]"
|
||||
@move="handleChange"
|
||||
>
|
||||
<SplideSlide v-for="(item, index) in slideData" :key="index">
|
||||
<div class="slide-inner border-line mt-auto">
|
||||
<BlocksVisualContent
|
||||
:resources-data="getComponentGroup(item, 'imgList')"
|
||||
object-fit="cover"
|
||||
:alt="getComponentGroup(item, 'subTitle')?.display?.text"
|
||||
/>
|
||||
</div>
|
||||
</SplideSlide>
|
||||
</BlocksSlideCenterFocus>
|
||||
<WidgetsButtonList
|
||||
v-if="buttonListData"
|
||||
:resources-data="buttonListData"
|
||||
class="mt-[40px] md:mt-[56px]"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -16,8 +16,13 @@ const backgroundData = computed(() =>
|
||||
const mainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const slideData = computed(() => props.components.group_sets)
|
||||
const slideData = computed(() => {
|
||||
if (props.components.group_sets.length < 3) {
|
||||
return [...props.components.group_sets, ...props.components.group_sets]
|
||||
}
|
||||
|
||||
return props.components.group_sets
|
||||
})
|
||||
const subTitleData = ref(getComponentGroup(slideData?.value[0], 'subTitle'))
|
||||
const descriptionData = ref(
|
||||
getComponentGroup(slideData?.value[0], 'description')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import { getComponentGroup, getComponentGroupAry } from '#layers/utils/dataUtil'
|
||||
|
||||
interface Props {
|
||||
@@ -47,7 +48,7 @@ const { data: resourcesData } = await useLazyAsyncData(
|
||||
)
|
||||
|
||||
// 배너 리스트 데이터 추출
|
||||
const bannerListData = computed(() => {
|
||||
const slideData = computed(() => {
|
||||
const operateComponents = resourcesData.value?.operate_components
|
||||
|
||||
if (!operateComponents) {
|
||||
@@ -55,10 +56,16 @@ const bannerListData = computed(() => {
|
||||
}
|
||||
|
||||
const firstKey = Object.keys(operateComponents)[0]
|
||||
return operateComponents[firstKey]?.list_operate_groups || []
|
||||
const data = operateComponents[firstKey]?.list_operate_groups || []
|
||||
|
||||
if (data.length < 3) {
|
||||
return [...data, ...data]
|
||||
}
|
||||
|
||||
return data
|
||||
})
|
||||
|
||||
const bannerSize = {
|
||||
const slideItemSize = {
|
||||
mo: {
|
||||
width: 276,
|
||||
height: 174,
|
||||
@@ -100,14 +107,23 @@ const bannerSize = {
|
||||
:resources-data="buttonListData"
|
||||
class="mt-[48px] md:mt-[72px]"
|
||||
/>
|
||||
<WidgetsBannerList
|
||||
v-if="bannerListData.length > 0"
|
||||
:resources-data="bannerListData"
|
||||
:slide-item-size="bannerSize"
|
||||
:arrows="true"
|
||||
<BlocksSlideCenterHighlight
|
||||
:slide-item-size="slideItemSize"
|
||||
:slide-item-length="slideData.length"
|
||||
:pagination="false"
|
||||
class="mt-[36px] md:mt-[60px]"
|
||||
/>
|
||||
>
|
||||
<SplideSlide v-for="(item, index) in slideData" :key="index">
|
||||
<BlocksCardNews
|
||||
:title="item.title"
|
||||
:description="item.option01"
|
||||
:img-path="getResolvedHost(item.img_path)"
|
||||
:url="item.url"
|
||||
:link-target="item.link_target"
|
||||
class="slide-inner"
|
||||
/>
|
||||
</SplideSlide>
|
||||
</BlocksSlideCenterHighlight>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface SlideItemSizeObject {
|
||||
width: number
|
||||
height: number
|
||||
gap: number
|
||||
scale?: number
|
||||
}
|
||||
|
||||
export interface SlideItemSize {
|
||||
|
||||
Reference in New Issue
Block a user