thainv-dev: page chi tiết

This commit is contained in:
nguyen van thai
2024-05-31 12:39:53 +07:00
parent 86bebfd66e
commit 6ff759f22a
15 changed files with 348 additions and 14 deletions
@@ -5,3 +5,6 @@ export { default as Article_BasicCollection } from './articles/collections/Basic
// Category
export { default as BasicCategories } from './categories/BasicCategories.vue'
export { default as CollectionPaging } from './pageCategories/collection_page.vue'
export { default as Dynamic_Other } from './other/index.vue'
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { enumPageComponentTemplates } from "@/definitions/enum";
import { Article_BasicCard, BasicCategories, Article_BasicCollection } from "./index";
import { Article_BasicCard, BasicCategories, Article_BasicCollection, Dynamic_Other } from "./index";
const _props = defineProps<{
settings: any;
@@ -11,6 +11,7 @@ const definedDynamicComponent: Record<string, any> = {
[enumPageComponentTemplates.ARTICLE]: Article_BasicCard,
[enumPageComponentTemplates.CATEGORY]: BasicCategories,
[enumPageComponentTemplates.COLLECTION]: Article_BasicCollection,
[enumPageComponentTemplates.OTHER]: Dynamic_Other
};
const getCurrentComponent = computed(() => `${_props.settings.template}`);
@@ -29,9 +30,11 @@ const GET_PROPS = computed(() => {
}
};
});
console.log(_props.component, '12')
</script>
<template>
<!-- <component :is="definedDynamicComponent[getCurrentComponent]" v-bind="{ ...(GET_PROPS()), component: _props.component, settings: _props.settings }" /> -->
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="{ ...(GET_PROPS()), component: _props.component }" />
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="{ ...(GET_PROPS()), component: _props.component, settings: _props.settings }" />
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
</script>
<template>
<div class="content">
<span>Quảng cáo đây</span>
</div>
</template>
<style scoped lang="scss">
.content {
font-size: 18px;
background-color: rgb(245, 245, 245);
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
@@ -0,0 +1,105 @@
<script setup lang="ts">
import { isEmpty } from 'lodash';
const emit = defineEmits(['dropData', 'selectComponent'])
const _props = defineProps<{
dataResult?: any[]
}>()
const SETTING_OPTIONS = {
MAX_ELEMENT: 3
}
</script>
<template>
<div class="breadcrumb">
<ul class="breadcrumb__list">
<li class="breadcrumb__list__item">
<p class="breadcrumb__list__item__title">
<nuxt-link to="/">Trang chủ</nuxt-link>
</p>
</li>
</ul>
<div class="button">
<div class="button__increase">
<i class="ri-font-size"></i>
<i class="ri-add-line"></i>
</div>
<div class="button__decrease">
<i class="ri-font-size"></i>
<i class="ri-subtract-line"></i>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.breadcrumb {
display: flex;
justify-content: space-between;
&__list {
padding: 0px;
display: flex;
overflow-x: auto;
gap: 1.5rem;
align-items: center;
font-size: 0.875rem;
line-height: 1.25rem;
&__item {
display: inline-block;
position: relative;
&:first-child {
color: blue;
}
&:not(:first-child):before {
content: "";
width: 7px;
height: 7px;
border-top: 1px solid #bdbdbd;
border-right: 1px solid #bdbdbd;
transform: rotate(45deg);
position: absolute;
left: -18px;
top: 8px;
}
}
}
.button {
display: flex;
gap: 4px;
&__increase, &__decrease {
width: 32px;
height: 32px;
background-color: rgb(243, 244, 246);
border-radius: 50px;
position: relative;
& .ri-font-size {
font-size: 17px;
position: absolute;
top: 50%;
left: 40%;
transform: translateY(-50%) translateX(-45%);
}
& .ri-add-line, & .ri-subtract-line {
position: absolute;
right: 2px;
}
}
}
}
.empty {
border-radius: 6px;
background: #409eff;
width: 40px;
min-height: 20px;
}
</style>
@@ -0,0 +1,48 @@
<template>
<div class="btn-wrap">
<div class="center-y">
<p title="Quay trở lại" class="class-default">
<Icon name="fa6-solid:arrow-left" />
</p>
<button class="defaultClasses">
<Icon name="fa6-regular:bookmark" />
</button>
</div>
<div class="center-y">
<button title="Copy link" class="class-default text-2xl">
<Icon name="bi:link-45deg" />
</button>
</div>
</div>
</template>
<style scoped lang="scss">
.btn-wrap {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
@media (min-width: 768px) {
flex-direction: row;
}
.class-default {
display: grid;
place-items: center;
border-radius: 9999px;
border-width: 1px;
width: 3rem;
height: 3rem;
background-color: #ffffff;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
&:hover {
color: #2563eb;
}
}
}
.center-y {
display: flex;
gap: 1rem;
align-items: center;
}
</style>
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { isEmpty } from 'lodash';
const emit = defineEmits(['dropData', 'selectComponent'])
const _props = defineProps<{
dataResult?: any[]
}>()
</script>
<template>
<div class="content">
<h3 class="title">Tiêu đề bài viết đây</h3>
<span class="intro">intro bài viết đây</span>
<div class="detail">Nội dung bài viết đây <br>
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
</div>
</template>
<style scoped lang="scss">
.content {
font-size: 14px;
height: 200px;
padding: 8px;
overflow: hidden;
}
.title {
white-space: normal;
}
.intro {
white-space: normal;
padding-bottom: 10px;
display: block;
}
.detail {
white-space: normal;
}
</style>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import { useArticleStore } from '~/stores/articles';
const emit = defineEmits(['dropData', 'selectComponent'])
const { currentArticle } = storeToRefs(useArticleStore());
</script>
<template>
<div class="content" v-if="currentArticle">
<h1 v-html="currentArticle?.sub" class="text-xl font-bold opacity-60 pb-1"></h1>
<h3 class="text-2xl font-bold sm:text-3xl xl:text-4xl pb-1" v-html="currentArticle?.title"></h3>
<div v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold text-xl tracking-widest pb-1"></div>
<div id="article-detail" :class="'text-[15px] tracking-wider'" v-html="currentArticle.detail"
class="[&_img]:mx-auto">
</div>
1
</div>
</template>
@@ -0,0 +1,42 @@
<script setup lang="ts">
import { isEmpty } from 'lodash';
const emit = defineEmits(['dropData', 'selectComponent'])
const _props = defineProps<{
dataResult?: any[]
}>()
</script>
<template>
<div class="content">
<h3 class="title">Tiêu đề bài viết đây</h3>
<div class="author">Tác giả - Thời gian tạo</div>
<span class="intro">intro bài viết đây</span>
<div class="detail">Nội dung bài viết đây <br>
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
</div>
</template>
<style scoped lang="scss">
.content {
font-size: 14px;
height: 200px;
padding: 8px;
overflow: hidden;
}
.title, .author, .intro {
white-space: normal;
}
span {
white-space: normal;
padding-bottom: 10px;
display: block;
}
.detail {
white-space: normal;
}
</style>
@@ -0,0 +1,5 @@
export { default as Article_Button } from './copyLinks/ArticleButton.vue'
export { default as Article_Detail_Emagazine } from './details/emagazine.vue'
export { default as Article_Detail_Default } from './details/default.vue'
export { default as Article_Detail_Infographics } from './details/infographics.vue'
export { default as Default_Breadcrumb} from './breadcrumb/default.vue'
@@ -0,0 +1,42 @@
<script lang="ts" setup>
import { enumPageComponentTemplates } from "@/definitions/enum";
// import { Default_Breadcrumb, Comment, Podcast, Video, Article_Detail_Default, ADS_Default, Article_Button, Article_Detail_Infographics, Article_Detail_Emagazine} from "./index";
import { Article_Button, Article_Detail_Emagazine, Article_Detail_Default, Article_Detail_Infographics, Default_Breadcrumb} from "./index";
const _props = defineProps<{
settings: any;
component?: any;
}>();
const definedDynamicComponent: Record<string, any> = {
'BREADCRUM_DEFAULT': Default_Breadcrumb,
'ARTICLE_DETAIL_DEFAULT': Article_Detail_Default,
'ARTICLE_DETAIL_INFOGRAPHICS': Article_Detail_Infographics,
'ARTICLE_DETAIL_EMAGAZINE': Article_Detail_Emagazine,
// 'ADS_DEFAULT': ADS_Default,
'ARTICLE_BUTTON': Article_Button,
// COMMENT: Comment,
// POCAST: Podcast,
// VIDEO: Video
};
const getCurrentComponent = computed(() => `${_props.settings.layout}`);
const GET_PROPS = computed(() => {
return () => {
let props: any = {};
if (_props.settings) {
for (const [key, value] of Object.entries(_props.settings)) {
props = {
...props,
[key]: value,
};
}
return props;
}
};
});
</script>
<template>
<component :is="definedDynamicComponent[getCurrentComponent]" v-bind="GET_PROPS()" />
</template>
+4
View File
@@ -138,5 +138,9 @@ export const enumPageComponentLayouts = {
},
[`${enumPageComponentTemplates.COLLECTION}`]: {
'ARTICLE-VERTICAL-|HORIZONTAL|-MAX_5': 'TYPE:Article-LAYOUT:vertical-DATA:HORIZONTAL-MAX:5'
},
[`${enumPageComponentTemplates.OTHER}`]: {
'"ARTICLE_BUTTON"': '"ARTICLE_BUTTON"'
}
};
+6 -5
View File
@@ -16,30 +16,31 @@ import { useDynamicPageStore } from '~/stores/dynamic-page';
import { useArticleStore } from '~/stores/articles';
const { currentPage, sectionPublished, componentPublished } = storeToRefs(useDynamicPageStore());
const { currentArticle } = storeToRefs(useArticleStore());
const store = reactive({
dynamicPage: useDynamicPageStore(),
article: useArticleStore(),
});
(async () => {
try {
store.article.getArticleById(route.params.slug);
store.article.getArticleById(Number(route.params.slug));
} catch (error) {
console.error("Error fetching data:", error);
}
})();
const loadPage = async (contentType: string | number) => {
store.dynamicPage.fetchPageByCode('trang-chu');
await store.dynamicPage.fetchPageByCode(contentType);
store.dynamicPage.setSectionPublished();
store.dynamicPage.setComponentPublished();
}
watch(currentArticle, async () => {
let isContentType : string = '';
console.log(currentArticle.value)
switch (currentArticle.value?.contentType) {
case 1:
isContentType = 'ArticleLayoutDefault'
isContentType = 'trang-chi-tiet-emagazine'
case 2:
isContentType = 'ArticleLayoutImage'
case 3:
@@ -65,7 +66,7 @@ useSeoMeta({
</script>
<template>
<main class="h-screen" v-if="currentPage">
<main class="h-screen" v-if="currentPage && currentPage.settings">
<DynamicTemplate :settings="currentPage.settings">
<template v-if="sectionPublished && sectionPublished.length > 0">
<DynamicSection
+4 -3
View File
@@ -62,12 +62,13 @@ export const getArticleById = async (event : any) => {
try {
const { apiUrl } = useRuntimeConfig().public
const id = event.context.params.id;
const { item }: any = await $fetch(`${apiUrl}/cms/digital-Article/${id}`, {
const { item }: any = await $fetch(`${apiUrl}/cms/digital-article/${id}`, {
headers: new Headers({
site: '1' || 1,
}),
})
return item
return { item }
} catch (error) {
handleError(error);
}
@@ -77,7 +78,7 @@ export const getArticleBySlug = async (event : any) => {
try {
const { apiUrl } = useRuntimeConfig().public
const slug = event.context.params.slug;
const { item }: any = await $fetch(`${apiUrl}/cms/digital-Article/slug:${slug}`, {
const { item }: any = await $fetch(`${apiUrl}/cms/digital-article/slug:${slug}`, {
headers: new Headers({
site: '1' || 1,
}),
+3 -2
View File
@@ -3,9 +3,10 @@ export const useArticleStore = defineStore("article", () => {
const getArticleById = async (id: string | number) => {
try {
const { data } = await useFetch(`/api/articles/get-by-id/${id}`)
const { data} = await useFetch(`/api/articles/get-by-id/${id}`)
currentArticle.value = {}
currentArticle.value = data.value
currentArticle.value = data.value.item
} catch (error: any) {}
}
+5 -1
View File
@@ -27,10 +27,13 @@ export const useDynamicPageStore = defineStore("dynamicPageStore", () => {
contentArr.push(section.content && typeof section.content === 'string' && JSON.parse(section.content));
return section;
});
console.log(currentPage.value.sections ,'sectionPublished 2')
sectionPublished.value = currentPage.value.sections && currentPage.value.sections.filter(
(section: any) => section.isPublished && !contentArr.flat().some((_section: any) => _section && _section.data && _section.type === "section" && section.id === _section.data)
);
console.log(sectionPublished.value ,'sectionPublished')
};
const setComponentPublished = () => {
@@ -40,7 +43,8 @@ export const useDynamicPageStore = defineStore("dynamicPageStore", () => {
return section;
});
componentPublished.value = currentPage.value.components && currentPage.value.components.filter((section: any) => section.isPublished);
};
console.log(componentPublished.value, 'componentPublished2')
};
const setDataQuery = (query: any, componentId: number | string) => {
for (const _component of currentPage.value.components && currentPage.value.components) {