feat. GR_VISUAL_01 컴포넌트 제작
This commit is contained in:
@@ -1,37 +1,87 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface ImageSource {
|
import { getResponsiveSrc } from '#layers/utils/dataUtil'
|
||||||
mobileSrc?: string
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
pcSrc?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
text?: string
|
resourcesData?: PageDataResourceGroup
|
||||||
imageSrc?: ImageSource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
// 텍스트 데이터 추출
|
||||||
|
// [TODO] txt 대신 text 사용
|
||||||
|
const displayText = computed(() => {
|
||||||
|
return props.resourcesData?.display?.txt || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 이미지 소스 추출
|
||||||
|
const imageSrc = computed(() => {
|
||||||
|
return getResponsiveSrc(props.resourcesData?.res_path)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 색상 코드 추출 (우선순위: color_code_txt > color_code)
|
||||||
|
const colorCode = computed(() => {
|
||||||
|
return (
|
||||||
|
props.resourcesData?.display?.color_code_txt ||
|
||||||
|
props.resourcesData?.display?.color_code
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 색상 이름 추출 (우선순위: color_name_txt > color_name)
|
||||||
|
const colorName = computed(() => {
|
||||||
|
return (
|
||||||
|
props.resourcesData?.display?.color_name_txt ||
|
||||||
|
props.resourcesData?.display?.color_name
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 색상 스타일 계산
|
||||||
|
const textStyles = computed(() => {
|
||||||
|
const styles: Record<string, string> = {}
|
||||||
|
|
||||||
|
if (colorName.value) {
|
||||||
|
styles.color = `var(--${colorName.value})`
|
||||||
|
} else if (colorCode.value) {
|
||||||
|
styles.color = colorCode.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return styles
|
||||||
|
})
|
||||||
|
|
||||||
|
// HTML 콘텐츠 정리 (줄바꿈 처리)
|
||||||
const sanitizedContent = computed(() => {
|
const sanitizedContent = computed(() => {
|
||||||
return props.text?.replace(/\n/g, '<br/>') || ''
|
return displayText.value?.replace(/\n/g, '<br/>') || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 이미지가 있는지 확인
|
||||||
|
const hasImage = computed(() => {
|
||||||
|
return imageSrc.value && (imageSrc.value.mobileSrc || imageSrc.value.pcSrc)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="imageSrc && 'mobileSrc' in imageSrc">
|
<!-- 이미지가 있는 경우 -->
|
||||||
|
<template v-if="hasImage">
|
||||||
<!-- 모바일 이미지 (sm 미만) -->
|
<!-- 모바일 이미지 (sm 미만) -->
|
||||||
<img
|
<img
|
||||||
v-if="imageSrc.mobileSrc"
|
v-if="imageSrc.mobileSrc"
|
||||||
:src="imageSrc.mobileSrc"
|
:src="imageSrc.mobileSrc"
|
||||||
:alt="text"
|
:alt="displayText"
|
||||||
class="sm:hidden w-full h-full object-contain"
|
class="sm:hidden w-full h-full object-contain"
|
||||||
/>
|
/>
|
||||||
<!-- PC 이미지 (sm 이상) -->
|
<!-- PC 이미지 (sm 이상) -->
|
||||||
<img
|
<img
|
||||||
v-if="imageSrc.pcSrc"
|
v-if="imageSrc.pcSrc"
|
||||||
:src="imageSrc.pcSrc"
|
:src="imageSrc.pcSrc"
|
||||||
:alt="text"
|
:alt="displayText"
|
||||||
class="hidden sm:block w-full h-full object-contain"
|
class="hidden sm:block w-full h-full object-contain"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<span v-else-if="text" v-dompurify-html="sanitizedContent" />
|
|
||||||
|
<!-- 텍스트가 있는 경우 -->
|
||||||
|
<span
|
||||||
|
v-else-if="displayText"
|
||||||
|
v-dompurify-html="sanitizedContent"
|
||||||
|
:style="textStyles"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,10 +2,14 @@
|
|||||||
import { getResponsiveClass, getResponsiveSrc } from '#layers/utils/dataUtil'
|
import { getResponsiveClass, getResponsiveSrc } from '#layers/utils/dataUtil'
|
||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
const props = defineProps<{
|
interface Props {
|
||||||
resourcesData: PageDataResourceGroup
|
resourcesData: PageDataResourceGroup
|
||||||
gradientClass?: string
|
gradient?: boolean
|
||||||
}>()
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
gradient: false,
|
||||||
|
})
|
||||||
|
|
||||||
const resPath = computed(() => {
|
const resPath = computed(() => {
|
||||||
return props.resourcesData?.res_path
|
return props.resourcesData?.res_path
|
||||||
@@ -37,10 +41,10 @@ const posterSrc = computed(() => {
|
|||||||
|
|
||||||
<!-- 비디오 타입 -->
|
<!-- 비디오 타입 -->
|
||||||
<template v-else-if="resourcesData?.group_type === 'video'">
|
<template v-else-if="resourcesData?.group_type === 'video'">
|
||||||
<!-- 모바일 비디오 (sm 미만) -->
|
<!-- 모바일 비디오 (md 미만) -->
|
||||||
<video
|
<video
|
||||||
v-if="videoSrc?.mobileSrc"
|
v-if="videoSrc?.mobileSrc"
|
||||||
class="w-full h-full object-cover sm:hidden"
|
class="w-full h-full object-cover md:hidden"
|
||||||
:poster="posterSrc?.mobileSrc"
|
:poster="posterSrc?.mobileSrc"
|
||||||
autoplay
|
autoplay
|
||||||
muted
|
muted
|
||||||
@@ -50,10 +54,10 @@ const posterSrc = computed(() => {
|
|||||||
<source :src="videoSrc.mobileSrc" type="video/mp4" />
|
<source :src="videoSrc.mobileSrc" type="video/mp4" />
|
||||||
<source :src="videoSrc.mobileSrc" type="video/webm" />
|
<source :src="videoSrc.mobileSrc" type="video/webm" />
|
||||||
</video>
|
</video>
|
||||||
<!-- PC 비디오 (sm 이상) -->
|
<!-- PC 비디오 (md 이상) -->
|
||||||
<video
|
<video
|
||||||
v-if="videoSrc?.pcSrc"
|
v-if="videoSrc?.pcSrc"
|
||||||
class="w-full h-full object-cover hidden sm:block"
|
class="w-full h-full object-cover hidden md:block"
|
||||||
:poster="posterSrc?.pcSrc"
|
:poster="posterSrc?.pcSrc"
|
||||||
autoplay
|
autoplay
|
||||||
muted
|
muted
|
||||||
@@ -65,6 +69,17 @@ const posterSrc = computed(() => {
|
|||||||
</video>
|
</video>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="absolute inset-0" :class="gradientClass" />
|
<!-- 그라디언트 오버레이 (gradient가 true일 때만) -->
|
||||||
|
<div
|
||||||
|
v-if="props.gradient"
|
||||||
|
class="absolute bottom-0 left-0 right-0 h-[342px] md:h-[720px] bg-gradient-to-b from-[#100d0f]/0 to-[#100d0f]"
|
||||||
|
style="
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(16, 13, 15, 0) 0%,
|
||||||
|
#100d0f 30%
|
||||||
|
);
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
import type { ButtonSize } from '#layers/types/components/button'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
groupsData: PageDataResourceGroup[]
|
groupsData: PageDataResourceGroup[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const breakpoints = useResponsiveBreakpoints()
|
||||||
|
|
||||||
|
const buttonSize = computed<ButtonSize>(() => {
|
||||||
|
return breakpoints.md.value ? 'medium' : 'extra-small'
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="props.groupsData">
|
<div
|
||||||
|
v-if="props.groupsData"
|
||||||
|
class="flex flex-wrap justify-center gap-3 sm:gap-4"
|
||||||
|
>
|
||||||
<AtomsButton
|
<AtomsButton
|
||||||
v-for="button in props.groupsData"
|
v-for="button in props.groupsData"
|
||||||
:key="button.group_code"
|
:key="button.group_code"
|
||||||
|
:size="buttonSize"
|
||||||
:background-color="button.btn_info?.color_code_btn"
|
:background-color="button.btn_info?.color_code_btn"
|
||||||
:text-color="button.btn_info?.color_code_txt"
|
:text-color="button.btn_info?.color_code_txt"
|
||||||
:disabled="button.btn_info?.disabled"
|
:disabled="button.btn_info?.disabled"
|
||||||
>
|
>
|
||||||
{{ button.btn_info?.txt_btn_name }}
|
{{ button.btn_info?.txt_btn_name }}
|
||||||
</AtomsButton>
|
</AtomsButton>
|
||||||
</template>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getResponsiveSrc } from '#layers/utils/dataUtil'
|
|
||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
resourcesData: PageDataResourceGroup
|
resourcesData: PageDataResourceGroup
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const displayText = props.resourcesData?.display?.text
|
|
||||||
const imageSrc = getResponsiveSrc(props.resourcesData?.res_path)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p>
|
<p>
|
||||||
<BlocksVisualContent :text="displayText" :image-src="imageSrc" />
|
<BlocksVisualContent :resources-data="props.resourcesData" />
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getResponsiveSrc } from '#layers/utils/dataUtil'
|
|
||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
resourcesData: PageDataResourceGroup
|
resourcesData: PageDataResourceGroup
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const displayText = props.resourcesData?.display?.text
|
|
||||||
const imageSrc = getResponsiveSrc(props.resourcesData?.res_path)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h2>
|
<h2>
|
||||||
<BlocksVisualContent :text="displayText" :image-src="imageSrc" />
|
<BlocksVisualContent :resources-data="props.resourcesData" />
|
||||||
</h2>
|
</h2>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getResponsiveSrc } from '#layers/utils/dataUtil'
|
|
||||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
resourcesData: PageDataResourceGroup
|
resourcesData: PageDataResourceGroup
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const displayText = props.resourcesData?.display?.text
|
|
||||||
const imageSrc = getResponsiveSrc(props.resourcesData?.res_path)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h3>
|
<h3>
|
||||||
<BlocksVisualContent :text="displayText" :image-src="imageSrc" />
|
<BlocksVisualContent :resources-data="props.resourcesData" />
|
||||||
</h3>
|
</h3>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -21,11 +21,14 @@ const handleVideoPlayClick = () => {
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-if="resourcesData && bgStyles"
|
v-if="resourcesData && bgStyles"
|
||||||
class="bg-cover bg-center bg-no-repeat w-[66px] h-[66px] lg:w-[100px] lg:h-[100px]"
|
class="relative group bg-cover bg-center bg-no-repeat w-[66px] h-[66px] sm:w-[100px] sm:h-[100px]"
|
||||||
:class="getResponsiveClass()"
|
:class="getResponsiveClass()"
|
||||||
:style="bgStyles"
|
:style="bgStyles"
|
||||||
@click="handleVideoPlayClick"
|
@click="handleVideoPlayClick"
|
||||||
>
|
>
|
||||||
|
<span
|
||||||
|
class="absolute inset-0 m-[10px] bg-white opacity-0 group-hover:opacity-10 transition-opacity duration-300 ease-in-out rounded-[50%]"
|
||||||
|
/>
|
||||||
<span class="sr-only">videoPlay</span>
|
<span class="sr-only">videoPlay</span>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
11
layers/composables/useBreakpoints.ts
Normal file
11
layers/composables/useBreakpoints.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 반응형 브레이크포인트 계산 헬퍼
|
||||||
|
*/
|
||||||
|
export const useResponsiveBreakpoints = () => {
|
||||||
|
return useBreakpoints({
|
||||||
|
xs: 360, // Mobile: 360px ~ 767px
|
||||||
|
sm: 768, // Tablet: 768px ~ 1023px
|
||||||
|
md: 1024, // PC: 1024px ~ 1439px
|
||||||
|
lg: 1440, // Large PC: 1440px+
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,78 +1,88 @@
|
|||||||
// server/routes/robots.txt.ts
|
// server/routes/robots.txt.ts
|
||||||
type RobotsConfig = {
|
type RobotsConfig = {
|
||||||
userAgent?: string | string[]
|
userAgent?: string | string[]
|
||||||
allow?: string[]
|
allow?: string[]
|
||||||
disallow?: string[]
|
disallow?: string[]
|
||||||
sitemap?: string | string[]
|
sitemap?: string | string[]
|
||||||
host?: string
|
host?: string
|
||||||
cache?: { sMaxAge?: number; staleWhileRevalidate?: number }
|
cache?: { sMaxAge?: number; staleWhileRevalidate?: number }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async event => {
|
||||||
const host =
|
const host =
|
||||||
(getHeader(event, "host") || getRequestHost(event)).toString() || "";
|
(getHeader(event, 'host') || getRequestHost(event)).toString() || ''
|
||||||
const baseDomain = process.env.BASE_DOMAIN || ".onstove.com";
|
const baseDomain = process.env.BASE_DOMAIN || '.onstove.com'
|
||||||
const isGameAliasExtractable = host.includes(baseDomain);
|
const isGameAliasExtractable = host.includes(baseDomain)
|
||||||
|
|
||||||
let gameAlias = "";
|
let gameAlias = ''
|
||||||
if (isGameAliasExtractable) {
|
if (isGameAliasExtractable) {
|
||||||
gameAlias = host.split(".")[0];
|
gameAlias = host.split('.')[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (gameAlias && gameAlias !== "www") {
|
// if (gameAlias && gameAlias !== "www") {
|
||||||
// event.context.gameAlias = gameAlias;
|
// event.context.gameAlias = gameAlias;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// robots 설정을 직접 가져오기 (미들웨어 context 사용)
|
// robots 설정을 직접 가져오기 (미들웨어 context 사용)
|
||||||
|
|
||||||
let config: RobotsConfig;
|
let config: RobotsConfig
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// robots 설정 추출
|
||||||
// robots 설정 추출
|
config = {
|
||||||
config = {
|
userAgent: '*',
|
||||||
userAgent: "*",
|
allow: ['/'],
|
||||||
allow: ["/"],
|
disallow: ['/error', '/inspection/', '/inspection/*', '/html/*'],
|
||||||
disallow: ["/error", "/inspection/", "/inspection/*", "/html/*"],
|
sitemap: [
|
||||||
sitemap: [`https://static-pubcomm.gate8.com/local/template/${gameAlias}/sitemap.xml`],
|
`https://static-pubcomm.gate8.com/local/template/${gameAlias}/sitemap.xml`,
|
||||||
host: `${gameAlias}.onstove.com`,
|
],
|
||||||
cache: { sMaxAge: 300, staleWhileRevalidate: 600 }
|
host: `${gameAlias}.onstove.com`,
|
||||||
};
|
cache: { sMaxAge: 300, staleWhileRevalidate: 600 },
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to fetch robots config:', error);
|
|
||||||
|
|
||||||
// 에러 발생 시 기본값 반환
|
|
||||||
config = {
|
|
||||||
userAgent: "*",
|
|
||||||
allow: ["/"],
|
|
||||||
disallow: ["/error", "/inspection/", "/inspection/*", "/html/*"],
|
|
||||||
cache: { sMaxAge: 300, staleWhileRevalidate: 600 }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
setHeader(event, "Content-Type", "text/plain; charset=utf-8")
|
console.error('Failed to fetch robots config:', error)
|
||||||
|
|
||||||
// 캐시 헤더 (CDN 친화)
|
// 에러 발생 시 기본값 반환
|
||||||
const sMax = config.cache?.sMaxAge ?? 300
|
config = {
|
||||||
const swr = config.cache?.staleWhileRevalidate ?? 600
|
userAgent: '*',
|
||||||
setHeader(event, "Cache-Control", `public, s-maxage=${sMax}, stale-while-revalidate=${swr}`)
|
allow: ['/'],
|
||||||
|
disallow: ['/error', '/inspection/', '/inspection/*', '/html/*'],
|
||||||
// 여러 user-agent 지원
|
cache: { sMaxAge: 300, staleWhileRevalidate: 600 },
|
||||||
const agents = Array.isArray(config.userAgent) ? config.userAgent : [config.userAgent ?? "*"]
|
|
||||||
|
|
||||||
const lines: string[] = []
|
|
||||||
for (const ua of agents) {
|
|
||||||
lines.push(`User-agent: ${ua}`)
|
|
||||||
for (const p of config.allow ?? []) lines.push(`Allow: ${p}`)
|
|
||||||
for (const p of config.disallow ?? []) lines.push(`Disallow: ${p}`)
|
|
||||||
lines.push("") // 블록 구분 공백
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const sitemaps = Array.isArray(config.sitemap) ? config.sitemap : (config.sitemap ? [config.sitemap] : [])
|
|
||||||
for (const sm of sitemaps) lines.push(`Sitemap: ${sm}`)
|
setHeader(event, 'Content-Type', 'text/plain; charset=utf-8')
|
||||||
if (config.host) lines.push(`Host: ${config.host}`)
|
|
||||||
|
// 캐시 헤더 (CDN 친화)
|
||||||
// 마지막 개행
|
const sMax = config.cache?.sMaxAge ?? 300
|
||||||
return lines.join("\n").trim() + "\n"
|
const swr = config.cache?.staleWhileRevalidate ?? 600
|
||||||
})
|
setHeader(
|
||||||
|
event,
|
||||||
|
'Cache-Control',
|
||||||
|
`public, s-maxage=${sMax}, stale-while-revalidate=${swr}`
|
||||||
|
)
|
||||||
|
|
||||||
|
// 여러 user-agent 지원
|
||||||
|
const agents = Array.isArray(config.userAgent)
|
||||||
|
? config.userAgent
|
||||||
|
: [config.userAgent ?? '*']
|
||||||
|
|
||||||
|
const lines: string[] = []
|
||||||
|
for (const ua of agents) {
|
||||||
|
lines.push(`User-agent: ${ua}`)
|
||||||
|
for (const p of config.allow ?? []) lines.push(`Allow: ${p}`)
|
||||||
|
for (const p of config.disallow ?? []) lines.push(`Disallow: ${p}`)
|
||||||
|
lines.push('') // 블록 구분 공백
|
||||||
|
}
|
||||||
|
|
||||||
|
const sitemaps = Array.isArray(config.sitemap)
|
||||||
|
? config.sitemap
|
||||||
|
: config.sitemap
|
||||||
|
? [config.sitemap]
|
||||||
|
: []
|
||||||
|
for (const sm of sitemaps) lines.push(`Sitemap: ${sm}`)
|
||||||
|
if (config.host) lines.push(`Host: ${config.host}`)
|
||||||
|
|
||||||
|
// 마지막 개행
|
||||||
|
return lines.join('\n').trim() + '\n'
|
||||||
|
})
|
||||||
|
|||||||
@@ -7,28 +7,36 @@ const props = defineProps<Props>()
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="relative h-[640px] lg:h-[1000px]">
|
<section class="relative h-[640px] md:h-[1000px]">
|
||||||
<WidgetsBackground
|
<WidgetsBackground
|
||||||
v-if="props.components?.background"
|
v-if="props.components?.background"
|
||||||
:resources-data="props.components?.background.groups[0]"
|
:resources-data="props.components?.background.groups[0]"
|
||||||
gradient-class="bg-gradient-to-b from-[#100d0f]/0 to-[#100d0f]"
|
:gradient="true"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="relative h-full flex flex-col items-center justify-center gap-4"
|
class="relative h-full flex flex-col items-center justify-center gap-4 md:gap-5"
|
||||||
>
|
>
|
||||||
<WidgetsMainTitle
|
<WidgetsMainTitle
|
||||||
v-if="props.components.mainTitle"
|
v-if="props.components.mainTitle && props.components.mainTitle.groups"
|
||||||
:resources-data="props.components.mainTitle.groups[0]"
|
:resources-data="props.components.mainTitle.groups[0]"
|
||||||
class="w-[355px] lg:w-[944px]"
|
class="w-[355px] md:w-[944px]"
|
||||||
/>
|
/>
|
||||||
<WidgetsDescription
|
<WidgetsDescription
|
||||||
v-if="props.components.description"
|
v-if="
|
||||||
|
props.components.description && props.components.description.groups
|
||||||
|
"
|
||||||
:resources-data="props.components.description.groups[0]"
|
:resources-data="props.components.description.groups[0]"
|
||||||
|
class="w-[355px] md:w-[944px]"
|
||||||
/>
|
/>
|
||||||
<WidgetsVideoPlay
|
<WidgetsVideoPlay
|
||||||
v-if="props.components.videoPlay"
|
v-if="props.components.videoPlay && props.components.videoPlay.groups"
|
||||||
:resources-data="props.components.videoPlay.groups[0]"
|
:resources-data="props.components.videoPlay.groups[0]"
|
||||||
/>
|
/>
|
||||||
|
<WidgetsButtonList
|
||||||
|
v-if="props.components.buttonList && props.components.buttonList.groups"
|
||||||
|
:groups-data="props.components.buttonList.groups"
|
||||||
|
class="mt-[48px] md:mt-[72px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user