181 lines
5.1 KiB
Vue
181 lines
5.1 KiB
Vue
<script lang="ts" setup>
|
|
import { enumPageComponentTemplates } from "@/definitions/enum";
|
|
import { DEFAULT_QUERY_DROP, getInputValue } from "@/utils/parseSQL";
|
|
|
|
const props = defineProps<{
|
|
dataResult?: any;
|
|
dataType?: any;
|
|
dataQuery?: any;
|
|
layout?: string;
|
|
label?: string;
|
|
}>();
|
|
|
|
const LAYOUT_PARSE = computed(() => {
|
|
const parseLayout =
|
|
props.layout?.split("-")?.map((_layout: any) => {
|
|
const parseItem = _layout.split(":");
|
|
return {
|
|
[parseItem[0]]: parseItem[0] === "HIDE" ? parseItem[1].split(",") : parseItem[1],
|
|
};
|
|
}) || [];
|
|
const designObject = props.label ? getInputValue(props.label, "OBJECT") : {};
|
|
return Object.assign({}, ...parseLayout, designObject);
|
|
});
|
|
|
|
const emit = defineEmits(["selectComponent", "dropData"]);
|
|
|
|
const selectComponent = () => {
|
|
emit("selectComponent");
|
|
};
|
|
|
|
const parseData = computed(() => {
|
|
if (!props.dataResult) return;
|
|
const result = getInputValue(props.dataResult, "OBJECT");
|
|
return result;
|
|
});
|
|
|
|
const drop = (e: any) => {
|
|
if (e.dataTransfer.getData(`${enumPageComponentTemplates.ARTICLE}`)) {
|
|
const data = e.dataTransfer.getData(`${enumPageComponentTemplates.ARTICLE}`);
|
|
const { dataType, dataResult } = JSON.parse(data);
|
|
const dataQuery = DEFAULT_QUERY_DROP(dataType, dataResult.id);
|
|
emit("dropData", {
|
|
dataType,
|
|
dataResult,
|
|
dataQuery: dataQuery,
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<article
|
|
class="basic-article border-custom"
|
|
@click="selectComponent"
|
|
@dragover.prevent
|
|
@drop.stop.prevent="drop"
|
|
:class="[LAYOUT_PARSE['LAYOUT'] || 'horizontal', !parseData && 'no-data', LAYOUT_PARSE['REVERSE'] ? 'reverse' : '', ...(LAYOUT_PARSE['border']?.length > 0 ? LAYOUT_PARSE['border'] : [])]"
|
|
:style="[LAYOUT_PARSE['background'] && `background: ${LAYOUT_PARSE['background']}`]"
|
|
>
|
|
<div v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('thumbnail')" class="basic-article_thumbnail" :style="[LAYOUT_PARSE['LAYOUT'] === 'horizontal' && LAYOUT_PARSE['WidthImg'] && `width: ${LAYOUT_PARSE['WidthImg']}%`]">
|
|
<template v-if="parseData">
|
|
<nuxt-link :to="`bai-viet/${parseData?.slug}`">
|
|
<img class="object-fit-cover" :src="parseData.thumbnail ? parseData.thumbnail : '/images/default-thumbnail.jpg'" :alt="parseData.title?.replace(/<[^>]+>/g, '')" />
|
|
</nuxt-link>
|
|
</template>
|
|
</div>
|
|
<div class="basic-article_content" :class="[!parseData && 'no-data']">
|
|
<div>
|
|
<nuxt-link :to="`bai-viet/${parseData?.slug}`"
|
|
v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('title')"
|
|
class="line-clamp hover:text-primary-600"
|
|
:style="[
|
|
LAYOUT_PARSE['fontSizeTitle'] && `font-size: ${LAYOUT_PARSE['fontSizeTitle']}px`,
|
|
LAYOUT_PARSE['fontWeightTitle'] && `font-weight: ${LAYOUT_PARSE['fontWeightTitle']}`,
|
|
LAYOUT_PARSE['color'] && `color: ${LAYOUT_PARSE['color']}`,
|
|
LAYOUT_PARSE['lineClampTitle'] && `-webkit-line-clamp: ${LAYOUT_PARSE['lineClampTitle']}`
|
|
]"
|
|
>
|
|
<template v-if="parseData">
|
|
{{ parseData.title?.replace(/<[^>]+>/g, "") }}
|
|
</template>
|
|
|
|
</nuxt-link>
|
|
<p
|
|
v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('paragraph')"
|
|
class="mb-0 line-clamp font-arial"
|
|
:style="[
|
|
LAYOUT_PARSE['fontSizeIntro'] && `font-size: ${LAYOUT_PARSE['fontSizeIntro']}px`,
|
|
LAYOUT_PARSE['fontWeightIntro'] && `font-weight: ${LAYOUT_PARSE['fontWeightIntro']}`,
|
|
LAYOUT_PARSE['color'] && `color: ${LAYOUT_PARSE['color']}`,
|
|
LAYOUT_PARSE['lineClampIntro'] && `-webkit-line-clamp: ${LAYOUT_PARSE['lineClampIntro']}`
|
|
]"
|
|
>
|
|
<template v-if="parseData">
|
|
{{ parseData.intro?.replace(/<[^>]+>/g, "") }}
|
|
</template>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.basic-article {
|
|
display: flex;
|
|
gap: 16px;
|
|
height: 100%;
|
|
padding: 20px;
|
|
&.no-data {
|
|
gap: 5px !important;
|
|
}
|
|
.line-clamp {
|
|
display: -webkit-box;
|
|
/* -webkit-line-clamp: 3; */
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
&.vertical {
|
|
flex-direction: column;
|
|
.basic-article_thumbnail {
|
|
width: 100%;
|
|
}
|
|
&.reverse {
|
|
flex-direction: column-reverse;
|
|
}
|
|
}
|
|
&.border-custom {
|
|
border-color: #e5e5e5 !important;
|
|
}
|
|
&.borderLeft {
|
|
border-left: 1px solid;
|
|
}
|
|
&.borderRight {
|
|
border-right: 1px solid;
|
|
}
|
|
&.borderTop {
|
|
border-top: 1px solid;
|
|
}
|
|
&.borderBottom {
|
|
border-bottom: 1px solid;
|
|
}
|
|
&.horizontal {
|
|
flex-direction: row;
|
|
.basic-article_thumbnail {
|
|
width: 40%;
|
|
}
|
|
&.reverse {
|
|
flex-direction: row-reverse;
|
|
}
|
|
}
|
|
|
|
&_thumbnail {
|
|
img {
|
|
width: 100%;
|
|
border-radius: 2px;
|
|
aspect-ratio: 16/10;
|
|
}
|
|
}
|
|
|
|
&_content {
|
|
/* padding: 10px 0px; */
|
|
flex: 1;
|
|
&.no-data {
|
|
padding: 0px;
|
|
}
|
|
|
|
h3 {
|
|
font-size: 16px;
|
|
}
|
|
|
|
p {
|
|
font-size: 14px;
|
|
margin-top: 10px;
|
|
opacity: 85%;
|
|
}
|
|
}
|
|
}
|
|
</style>
|