minhnt-dev: article api
This commit is contained in:
@@ -55,13 +55,13 @@ const drop = (e: any) => {
|
||||
<div class="basic-article_content" :class="[!parseData && 'no-data']">
|
||||
<div>
|
||||
<template v-if="parseData">
|
||||
<nuxt-link :to="`/bai-viet/${parseData.slug}`">
|
||||
<nuxt-link :to="`/bai-viet/${parseData.id}`">
|
||||
<h3 v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('title')" class="mb-1 line-clamp-2 text-base font-700 hover:text-primary-100 transition-all duration-300">
|
||||
{{ parseData.title?.replace(/<[^>]+>/g, '') }}
|
||||
</h3>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
<p v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('paragraph')" class="mb-0 line-clamp-3 sm:line-clamp-5 text-[14px]">
|
||||
<p v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('paragraph')" class="mb-0 line-clamp-3 sm:line-clamp-3 text-[14px]">
|
||||
<template v-if="parseData">
|
||||
<template v-if="parseData.intro">
|
||||
{{ parseData.intro?.replace(/<[^>]+>/g, '') }}
|
||||
|
||||
@@ -25,7 +25,7 @@ const _dataResult = computed(() => {
|
||||
<div>
|
||||
<div class="flex gap-4 items-end py-2">
|
||||
<template v-for="(component, index) in _dataResult">
|
||||
<nuxt-link v-if="component" :key="index" :to="`/${component.code}`" class=" py-1 font-400 text-[16px] first:font-600 first:text-[20px] sm:block hidden first:block first:border-b-[1px] first:border-b-solid first:border-b-[#409eff]">
|
||||
<nuxt-link v-if="component" :key="index" :to="`/${component.code}`" class=" py-1 font-400 text-[16px] first:font-600 first:text-[20px] sm:block hidden first:block">
|
||||
<h3 class="m-0 leading-none hover:text-primary-100 transition-all duration-300">{{ component.title }}</h3>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
- LayoutType: None=0 | Normal=1 | Short=2 | Long=3 | Page=4 | Other=5
|
||||
- ContentType: None=0 | Normal=1 | Photo=2 | Video=3 | Graphic=4 | Document=5 | Reaction=6 (Poll,Quiz) | Other=7
|
||||
- Type: None=0 | Editorial=1 | General=2 | Reportage=3 | Interview=4 | Survey=5 | Tutorial=6 | Podcast=7 | Broadcast=8 | TalkShow=9 | LiveStream=10 | Translation=11 | Promotion=12 | Other=13
|
||||
*/
|
||||
|
||||
<script setup lang="ts">
|
||||
import _cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
import DynamicTemplate from "~/components/dynamic-page/page/templates/index.vue";
|
||||
import DynamicSection from "~/components/dynamic-page/page-section/templates/index.vue";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
const loadPage = async (contentType: string | number) => {
|
||||
store.dynamicPage.fetchPageByCode('trang-chu');
|
||||
store.dynamicPage.setSectionPublished();
|
||||
store.dynamicPage.setComponentPublished();
|
||||
}
|
||||
|
||||
watch(currentArticle, async () => {
|
||||
let isContentType : string = '';
|
||||
switch (currentArticle.value?.contentType) {
|
||||
case 1:
|
||||
isContentType = 'ArticleLayoutDefault'
|
||||
case 2:
|
||||
isContentType = 'ArticleLayoutImage'
|
||||
case 3:
|
||||
isContentType = 'ArticleLayoutPodcast'
|
||||
case 4:
|
||||
isContentType = 'ArticleLayoutVideo'
|
||||
case 5:
|
||||
if (currentArticle.value?.layoutType === 3) isContentType = 'ArticleLayoutInfographics'
|
||||
else isContentType = 'ArticleLayoutFullPage'
|
||||
default:
|
||||
isContentType = 'ArticleLayoutDefault'
|
||||
}
|
||||
await loadPage(isContentType)
|
||||
}, { deep: true })
|
||||
|
||||
useSeoMeta({
|
||||
title: currentArticle.value?.title,
|
||||
ogTitle: currentArticle.value?.title,
|
||||
description: currentArticle.value?.intro,
|
||||
ogDescription: currentArticle.value?.intro,
|
||||
ogImage: currentArticle.value?.thumbnail,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="h-screen" v-if="currentPage">
|
||||
<DynamicTemplate :settings="currentPage.settings">
|
||||
<template v-if="sectionPublished && sectionPublished.length > 0">
|
||||
<DynamicSection
|
||||
v-for="(section, index) in sectionPublished"
|
||||
:key="index"
|
||||
:settings="section.settings"
|
||||
:content="section.content ? JSON.parse(section.content) : null"
|
||||
:section="section"
|
||||
/>
|
||||
</template>
|
||||
</DynamicTemplate>
|
||||
</main>
|
||||
</template>
|
||||
+9
-5
@@ -10,14 +10,18 @@ const { currentPage, sectionPublished, componentPublished } = storeToRefs(useDyn
|
||||
const store = reactive({
|
||||
dynamicPage: useDynamicPageStore(),
|
||||
});
|
||||
(async () => {
|
||||
try {
|
||||
store.dynamicPage.fetchPageByCode('trang-chu');
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
const loadData = async () => {
|
||||
store.dynamicPage.fetchPageById(1);
|
||||
|
||||
watch(currentPage, () => {
|
||||
store.dynamicPage.setSectionPublished();
|
||||
store.dynamicPage.setComponentPublished()
|
||||
}
|
||||
await loadData()
|
||||
}, { deep: true })
|
||||
|
||||
useHead({
|
||||
title: 'Trang chủ'
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createRouter, defineEventHandler, useBase } from 'h3'
|
||||
import * as DynamicArticleCtrl from '~/server/models/articles'
|
||||
|
||||
const router = createRouter()
|
||||
|
||||
router.get('/get-by-id/:id', defineEventHandler(DynamicArticleCtrl.getArticleById))
|
||||
router.get('/get-by-slug/:slug', defineEventHandler(DynamicArticleCtrl.getArticleBySlug))
|
||||
|
||||
export default useBase('/api/articles', router.handler)
|
||||
@@ -3,7 +3,7 @@ import * as DynamicPageCtrl from '~/server/models/dynamic-page'
|
||||
|
||||
const router = createRouter()
|
||||
|
||||
router.get('/getByCode/:code', defineEventHandler(DynamicPageCtrl.getDynamicPageByCode))
|
||||
router.get('/get-by-code/:slug', defineEventHandler(DynamicPageCtrl.getDynamicPageByCode))
|
||||
router.get('/get-by-id/:id', defineEventHandler(DynamicPageCtrl.getDynamicPageById))
|
||||
|
||||
export default useBase('/api/services', router.handler)
|
||||
export default useBase('/api/dynamic-page', router.handler)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { createRouter, defineEventHandler, useBase } from 'h3'
|
||||
import * as DynamicPageCtrl from '~/server/models/dynamic-page'
|
||||
|
||||
const router = createRouter()
|
||||
|
||||
router.get('/get-by-code/:slug', defineEventHandler(async (event : any) => {
|
||||
try {
|
||||
const { apiUrl } = useRuntimeConfig().public
|
||||
const slug = event.context.params.slug;
|
||||
const { item } : any = await $fetch(`${apiUrl}/cms/overview-page/1`)
|
||||
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
}))
|
||||
|
||||
router.get('/get-by-id/:id', defineEventHandler(async (event : any) => {
|
||||
try {
|
||||
const { apiUrl } = useRuntimeConfig().public
|
||||
const id = event.context.params.id;
|
||||
const { item } : any = await $fetch(`${apiUrl}/cms/overview-page/${id}`)
|
||||
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
}))
|
||||
|
||||
export default useBase('/api/services', router.handler)
|
||||
@@ -0,0 +1,89 @@
|
||||
interface Base {
|
||||
createdBy?: string | number
|
||||
createdOn?: string
|
||||
updatedBy?: string | number
|
||||
updatedOn?: string
|
||||
}
|
||||
interface Article extends Base {
|
||||
id?: number; // ID của bài viết
|
||||
siteId?: number; // ID của trang web
|
||||
articleId?: number; // ID của bài viết
|
||||
originalId?: number; // ID còn bài viết gốc
|
||||
sub?: string; // Tiêu đề phụ
|
||||
title?: string; // Tiêu đề
|
||||
slug?: string; // Đường dẫn thân thiện cho SEO
|
||||
code?: string; // Mã bài viết
|
||||
intro?: string; // Phần giới thiệu
|
||||
brief?: string; // Tóm tắt
|
||||
detail?: string; // Nội dung chi tiết
|
||||
summary?: string; // Tóm tắt ngắn gọn
|
||||
thumbnail?: string; // Đường dẫn hình ảnh đại diện
|
||||
represent?: string; // Đại diện cho bài viết
|
||||
redirect?: string; // Đường dẫn chuyển hướng
|
||||
keywords?: string; // Từ khóa
|
||||
description?: string; // Mô tả
|
||||
type?: number; // Loại bài viết
|
||||
layoutType?: number; // Loại giao diện
|
||||
contentType?: number; // Loại nội dung
|
||||
priority?: number; // Ưu tiên
|
||||
features?: string; // Các tính năng
|
||||
taxonomy?: string; // Phân loại
|
||||
interaction?: string; // Tương tác
|
||||
language?: string; // Ngôn ngữ
|
||||
settings?: string; // Các tùy chọn
|
||||
categoryId?: number; // ID của danh mục
|
||||
categoryIds?: string; // Các ID danh mục liên quan
|
||||
topicIds?: string; // Các ID chủ đề liên quan
|
||||
eventIds?: string; // Các ID sự kiện liên quan
|
||||
collectionIds?: string; // Các ID bộ sưu tập liên quan
|
||||
urlIds?: string; // Các ID URL liên quan
|
||||
sourceIds?: string; // Các ID nguồn liên quan
|
||||
relatedArticleIds?: string; // Các ID liên quan
|
||||
advertisementIds?: string; // Các ID quảng cáo liên quan
|
||||
attachmentIds?: string; // Các ID tệp đính kèm liên quan
|
||||
authorIds?: string; // Các ID tác giả liên quan
|
||||
views?: number; // Số lượt xem
|
||||
likes?: number; // Số lượt thích
|
||||
rates?: number; // Đánh giá
|
||||
follows?: number; // Số lượt theo dõi
|
||||
shares?: number; // Số lượt chia sẻ
|
||||
reports?: number; // Số lượt báo cáo
|
||||
comments?: number; // Số lượt bình luận
|
||||
statistics?: string; // Thống kê khác
|
||||
isPublished?: boolean; // Đã xuất bản hay chưa
|
||||
publishedBy?: number; // ID người xuất bản
|
||||
publishedOn?: Date; // Ngày xuất bản
|
||||
expiresOn?: Date; // Ngày hết hạn
|
||||
order?: number; // Thứ tự
|
||||
status?: number; // Trạng thái
|
||||
}
|
||||
|
||||
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}`, {
|
||||
headers: new Headers({
|
||||
site: '1' || 1,
|
||||
}),
|
||||
})
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
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}`, {
|
||||
headers: new Headers({
|
||||
site: '1' || 1,
|
||||
}),
|
||||
})
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ interface PageComponentSettings {
|
||||
dataQuery?: string; // Truy vấn dữ liệu: IDS | NEW | VIEW | SQL | REQUEST | ...
|
||||
dataResult?: string; // Kết quả dữ liệu (Json)
|
||||
}
|
||||
|
||||
interface PageSection extends Base {
|
||||
id?: number; // Mã định danh
|
||||
siteId?: number; // Mã hệ thống
|
||||
@@ -102,12 +101,12 @@ export const getDynamicPageByCode = async (event : any) => {
|
||||
try {
|
||||
const { apiUrl } = useRuntimeConfig().public
|
||||
const slug = event.context.params.slug;
|
||||
|
||||
const { item }: any = await $fetch(`${apiUrl}/cms/overview-page/slug:${slug}`)
|
||||
console.log('============')
|
||||
console.log(item)
|
||||
console.log('============')
|
||||
return { item }
|
||||
const { item }: any = await $fetch(`${apiUrl}/cms/overview-page/slug:${slug}`, {
|
||||
headers: new Headers({
|
||||
site: '1' || 1,
|
||||
}),
|
||||
})
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
@@ -117,11 +116,8 @@ export const getDynamicPageById = async (event : any) => {
|
||||
try {
|
||||
const { apiUrl } = useRuntimeConfig().public
|
||||
const id = event.context.params.id;
|
||||
|
||||
const { item }: any = await $fetch(`${apiUrl}/cms/overview-page/${id}`, {
|
||||
method: 'GET',
|
||||
})
|
||||
return { item }
|
||||
const { item }: any = await $fetch(`${apiUrl}/cms/overview-page/${id}`)
|
||||
return item
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export const useArticleStore = defineStore("article", () => {
|
||||
const currentArticle = ref<any>({});
|
||||
|
||||
const getArticleById = async (id: string | number) => {
|
||||
try {
|
||||
const { data } = await useFetch(`/api/articles/get-by-id/${id}`)
|
||||
currentArticle.value = {}
|
||||
currentArticle.value = data.value
|
||||
} catch (error: any) {}
|
||||
}
|
||||
|
||||
return {
|
||||
currentArticle,
|
||||
getArticleById
|
||||
}
|
||||
});
|
||||
|
||||
import.meta.hot && import.meta.hot.accept(acceptHMRUpdate(useArticleStore, import.meta.hot));
|
||||
+10
-8
@@ -6,17 +6,19 @@ export const useDynamicPageStore = defineStore("dynamicPageStore", () => {
|
||||
const componentPublished = ref<any[]>([]);
|
||||
|
||||
async function fetchPageByCode(slug: any) {
|
||||
try {
|
||||
const { data } = await useFetch(`/api/services/get-by-code/${slug}`)
|
||||
currentPage.value = data.value
|
||||
} catch (error: any) {}
|
||||
try {
|
||||
const { data } = await useFetch(`/api/dynamic-page/get-by-code/${slug}`)
|
||||
currentPage.value = {}
|
||||
currentPage.value = data.value
|
||||
} catch (error: any) {}
|
||||
}
|
||||
|
||||
async function fetchPageById(id: string | number) {
|
||||
try {
|
||||
const {data} = await useFetch(`/api/services/get-by-id/${id}`)
|
||||
currentPage.value = data.value
|
||||
} catch (error: any) {}
|
||||
try {
|
||||
const { data } = await useFetch(`/api/dynamic-page/get-by-id/${id}`)
|
||||
currentPage.value = {}
|
||||
currentPage.value = data.value
|
||||
} catch (error: any) {}
|
||||
}
|
||||
|
||||
const setSectionPublished = () => {
|
||||
|
||||
Reference in New Issue
Block a user