thainv-dev: Xóa bớt file, folder thừa
This commit is contained in:
-67
@@ -1,67 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||
import { getInputValue } from '@/utils/parseSQL';
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
|
||||
const _props = defineProps<{
|
||||
dataResult?: any[];
|
||||
dataQuery?: string;
|
||||
layout?: string;
|
||||
}>();
|
||||
|
||||
const SETTING_OPTIONS = {
|
||||
MAX_ELEMENT: 5,
|
||||
TEMPLATE: "Article",
|
||||
LAYOUT: "LAYOUT:vertical"
|
||||
};
|
||||
|
||||
const LAYOUT_PARSE = computed(() => {
|
||||
const parseLayout = _props.layout?.split("-")?.map((_layout: any) => {
|
||||
const parseItem = _layout.split(":");
|
||||
return {
|
||||
[parseItem[0]]: parseItem[1],
|
||||
};
|
||||
});
|
||||
return Object.assign({}, ...parseLayout);
|
||||
});
|
||||
|
||||
const _dataResult = computed(() => {
|
||||
let _components = Array(Number(LAYOUT_PARSE.value.MAX) || SETTING_OPTIONS.MAX_ELEMENT).fill(null);
|
||||
const result = getInputValue(_props.dataResult, 'ARRAY');
|
||||
result && result.length > 0 && _components.map((_ : any, index : any) => {
|
||||
_components[index] = result[index] || null;
|
||||
})
|
||||
return _components;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="collection-container grid gap-5" :class="LAYOUT_PARSE['LAYOUT'] || 'horizontal'"
|
||||
:style="`grid-template-columns: repeat(${LAYOUT_PARSE['COLUMN']}, minmax(0, 1fr))`">
|
||||
<div v-for="(component, index) in _dataResult" :key="index">
|
||||
<template v-if="!isEmpty(component)">
|
||||
<DynamicComponent
|
||||
:settings="{
|
||||
template: LAYOUT_PARSE.TYPE || SETTING_OPTIONS.TEMPLATE,
|
||||
layout: `LAYOUT:${LAYOUT_PARSE.DATA.toLowerCase()}` || SETTING_OPTIONS.LAYOUT,
|
||||
dataResult: { ...component },
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.collection-container {
|
||||
&.vertical {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
&.horizontal {
|
||||
grid-template-rows: auto;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,124 +0,0 @@
|
||||
<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
|
||||
}>()
|
||||
|
||||
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],
|
||||
};
|
||||
}) || [];
|
||||
return Object.assign({}, ...parseLayout);
|
||||
})
|
||||
|
||||
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 gap-x-4" :class="[LAYOUT_PARSE['LAYOUT'] || 'horizontal', !parseData && 'no-data', LAYOUT_PARSE['REVERSE'] ? 'reverse' : '']">
|
||||
<div v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('thumbnail')" class="basic-article_thumbnail">
|
||||
<template v-if="parseData">
|
||||
<img class="object-cover" :src="parseData.thumbnail ? parseData.thumbnail : '/images/default-thumbnail.jpg'" :alt="parseData.title?.replace(/<[^>]+>/g, '')" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="basic-article_content" :class="[!parseData && 'no-data']">
|
||||
<div>
|
||||
<template v-if="parseData">
|
||||
<nuxt-link :to="`/bai-viet/${parseData.slug}`">
|
||||
<h3 v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('title')" class="mb-1 line-clamp-2 text-base font-700 hover:text-primary-600 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-3 text-[14px]">
|
||||
<template v-if="parseData">
|
||||
<template v-if="parseData.intro">
|
||||
{{ parseData.intro?.replace(/<[^>]+>/g, '') }}
|
||||
</template>
|
||||
<template v-if="parseData.sub">
|
||||
{{ parseData.sub?.replace(/<[^>]+>/g, '') }}
|
||||
</template>
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.basic-article {
|
||||
display: grid;
|
||||
height: 100%;
|
||||
|
||||
&.vertical {
|
||||
@apply lg:grid-cols-1 sm:grid-cols-2;
|
||||
.basic-article_content {
|
||||
padding: 10px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
.basic-article_content {
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
&.reverse {
|
||||
.basic-article_thumbnail {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.basic-article_content {
|
||||
grid-row: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_thumbnail {
|
||||
flex: 1;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 6px;
|
||||
aspect-ratio: 16/10;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-block {
|
||||
background-color: #409eff;
|
||||
height: 100px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +19,7 @@ const store = reactive({
|
||||
const { categoryTree } = storeToRefs(store.category);
|
||||
|
||||
|
||||
|
||||
function increase() {
|
||||
const step = ref(Number(getComputedStyle(document.documentElement).getPropertyValue("--step").trim()));
|
||||
step.value += 2;
|
||||
@@ -58,6 +59,8 @@ onMounted(async () => {
|
||||
if (detailEmagazine && breakcrumb) {
|
||||
breakcrumb.classList.add("lg:max-w-640px", "mx-auto");
|
||||
}
|
||||
|
||||
document.documentElement.style.setProperty("--step", '0');
|
||||
});
|
||||
|
||||
function clickElement(type: string, selector: string, attribute: string) {
|
||||
@@ -152,6 +155,9 @@ async function copyLink() {
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:root {
|
||||
--step: 1;
|
||||
}
|
||||
#sub,
|
||||
#intro,
|
||||
#intro + div {
|
||||
|
||||
@@ -77,7 +77,6 @@ async function copyLink() {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(currentArticle, "curetna");
|
||||
</script>
|
||||
<template>
|
||||
<div class="content" v-if="currentArticle">
|
||||
@@ -126,14 +125,14 @@ console.log(currentArticle, "curetna");
|
||||
#sub,
|
||||
#intro,
|
||||
#intro + div {
|
||||
font-size: calc(16px + var(--step) * 1px);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: calc(28px + var(--step) * 1px);
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
#published-on {
|
||||
font-size: calc(14px + var(--step) * 1px);
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -22,9 +22,9 @@ console.log(currentArticle.value ,'curenta')
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3">
|
||||
<div class="md:col-span-2">
|
||||
<video class="w-full h-full" controls="controls" width="100%" height="100%" data-file-id="149" data-resource="https://acp-api.vpress.vn/Resources/Video/983d2f57-7743-472f-b22d-fc73085af6d5.mp4" data-title="Download.mp4">
|
||||
<source src="" type="video/mp4" />
|
||||
</video>
|
||||
<div id="article-detail" class="flex-1 [&_iframe]:w-full [&_iframe]:max-w-full [&_iframe]:max-h-52 md:[&_iframe]:max-h-full [&_video]:max-w-full [&_video]:w-full">
|
||||
<div v-html="currentArticle?.detail" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-4 pt-2 bg-[rgb(248,249,250)]">
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
// Article
|
||||
export { default as Article_BasicCard } from './articles/individuals/Card.vue'
|
||||
|
||||
export { default as Article_BasicCollection } from './articles/collections/BasicCollection.vue'
|
||||
|
||||
// Category
|
||||
export { default as BasicCategories } from './categories/BasicCategories.vue'
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import ADSDefault from '@/assets/images/ads.jpg'
|
||||
</script>
|
||||
<template>
|
||||
<div class="shadow">
|
||||
<img :src="ADSDefault" alt="quảng cáo" class=" object-cover">
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
}
|
||||
</style>
|
||||
@@ -1,91 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
||||
import { useCategoryStore } from "~/stores/category";
|
||||
import { useArticleStore } from "~/stores/articles";
|
||||
|
||||
const store = reactive({
|
||||
dynamicPage: useDynamicPageStore(),
|
||||
article: useArticleStore(),
|
||||
category: useCategoryStore()
|
||||
})
|
||||
|
||||
const { currentArticle } = storeToRefs(store.article)
|
||||
const { categoryTree } = storeToRefs(store.category)
|
||||
if(!localStorage.getItem('step')) {
|
||||
localStorage.setItem('step', '0')
|
||||
}
|
||||
function increase() {
|
||||
|
||||
const step = ref(Number(getComputedStyle(document.documentElement).getPropertyValue('--step').trim()))
|
||||
step.value += 2
|
||||
document.documentElement.style.setProperty('--step', step.value.toString());
|
||||
|
||||
}
|
||||
|
||||
function decrease() {
|
||||
const step = ref(Number(getComputedStyle(document.documentElement).getPropertyValue('--step').trim()))
|
||||
step.value -= 2
|
||||
document.documentElement.style.setProperty('--step', step.value.toString());
|
||||
}
|
||||
|
||||
function findElementPathById(categories: any[], targetId: number, path = []) {
|
||||
for (const category of categories) {
|
||||
const currentPath = [...path, { title: category.title, code: category.code }];
|
||||
if (category.id === targetId) {
|
||||
return currentPath;
|
||||
}
|
||||
if (category.children) {
|
||||
const result: any = findElementPathById(category.children, targetId, currentPath);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
await store.category.fetchBySiteId()
|
||||
console.log(store.category.categoryTree, 'tree')
|
||||
if(!categoryTree.value?.length) {
|
||||
}
|
||||
|
||||
const currentCategoryTree = store.category.currentCategoryTree = findElementPathById(categoryTree.value, currentArticle.value.categoryId)
|
||||
onMounted(() => {
|
||||
let detailEmagazine = document.querySelector('div[layout="ARTICLE_DETAIL_EMAGAZINE"]')
|
||||
let breakcrumb = document.querySelector('div[layout="BREADCRUM_DEFAULT"]')
|
||||
if( detailEmagazine && breakcrumb) {
|
||||
breakcrumb.classList.add('lg:max-w-640px','mx-auto')
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex justify-between items-center my-3">
|
||||
<ul class="flex gap-6 items-center text-md">
|
||||
<template v-for="(category, index) in currentCategoryTree" :key="index">
|
||||
<li class="first:text-primary-600 hover:text-primary-600 font-semibold relative after:absolute after:content-['\003E'] last:after:content-[''] after:right--4 after:text-gray-3">
|
||||
<nuxt-link :to="{ name: 'categories', params: { categories: category.code ?? '/' } }">{{ category.title }}</nuxt-link>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<div @click="increase()" class="w-10 h-10 border-1px border-solid shadow rounded-full relative cursor-pointer hover:bg-primary-100 hover:text-primary-600">
|
||||
<svg class="absolute top-50% left-50% translate-y--50% translate-x--55%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"></path><path d="M11.246 15H4.75416L2.75416 20H0.600098L7.0001 4H9.0001L15.4001 20H13.246L11.246 15ZM10.446 13L8.0001 6.88516L5.55416 13H10.446ZM21.0001 12.5351V12H23.0001V20H21.0001V19.4649C20.4118 19.8052 19.7287 20 19.0001 20C16.791 20 15.0001 18.2091 15.0001 16C15.0001 13.7909 16.791 12 19.0001 12C19.7287 12 20.4118 12.1948 21.0001 12.5351ZM19.0001 18C20.1047 18 21.0001 17.1046 21.0001 16C21.0001 14.8954 20.1047 14 19.0001 14C17.8955 14 17.0001 14.8954 17.0001 16C17.0001 17.1046 17.8955 18 19.0001 18Z"></path></svg>
|
||||
<svg class="absolute right-1.5 top-2 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z"></path></svg>
|
||||
</div>
|
||||
<div @click="decrease()" class="w-10 h-10 border-1px border-solid shadow rounded-full relative cursor-pointer hover:bg-primary-100 hover:text-primary-600">
|
||||
<svg class="absolute top-50% left-50% translate-y--50% translate-x--55%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"></path><path d="M11.246 15H4.75416L2.75416 20H0.600098L7.0001 4H9.0001L15.4001 20H13.246L11.246 15ZM10.446 13L8.0001 6.88516L5.55416 13H10.446ZM21.0001 12.5351V12H23.0001V20H21.0001V19.4649C20.4118 19.8052 19.7287 20 19.0001 20C16.791 20 15.0001 18.2091 15.0001 16C15.0001 13.7909 16.791 12 19.0001 12C19.7287 12 20.4118 12.1948 21.0001 12.5351ZM19.0001 18C20.1047 18 21.0001 17.1046 21.0001 16C21.0001 14.8954 20.1047 14 19.0001 14C17.8955 14 17.0001 14.8954 17.0001 16C17.0001 17.1046 17.8955 18 19.0001 18Z"></path></svg>
|
||||
<svg class="absolute right-1.5 top-2 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5 11V13H19V11H5Z"></path></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
:root {
|
||||
--step: 0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,49 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useCategoryStore } from '@/stores/category';
|
||||
const store = {
|
||||
category: useCategoryStore()
|
||||
}
|
||||
|
||||
const { currentCategoryTree } = storeToRefs(store.category)
|
||||
const isBookmark = ref(false)
|
||||
const onClickBookmark = () => {
|
||||
isBookmark.value = !isBookmark.value
|
||||
}
|
||||
async function copyLink() {
|
||||
try {
|
||||
const url = window.location.href
|
||||
await navigator.clipboard.writeText(url)
|
||||
alert('copy link thành công')
|
||||
|
||||
} catch (error) {
|
||||
alert(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="py-5 flex flex-wrap justify-between items-center">
|
||||
<div class="flex gap-4 items-center">
|
||||
<nuxt-link :to="{ name: 'categories', params: { categories: `${currentCategoryTree[currentCategoryTree.length - 1]?.code}` } }" title="Quay trở lại" class="w-12 h-3rem rounded-full flex items-center justify-center bg-white border-1px shadow hover:bg-primary-100 hover:text-primary-600 cursor-pointer">
|
||||
<Icon name="fa6-solid:arrow-left" />
|
||||
</nuxt-link>
|
||||
<button @click="onClickBookmark()" class="w-8 h-8 rounded-full bg-white hover:bg-primary-100 hover:text-primary-600">
|
||||
<Icon v-if="isBookmark === false" name="fa6-regular:bookmark" />
|
||||
<Icon v-if="isBookmark === true" name="fa6-solid:bookmark" class="text-primary-600" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-4 items-center">
|
||||
<button @click="copyLink()" title="Copy link" class="w-12 h-3rem rounded-full flex items-center justify-center bg-white border-1px shadow hover:bg-primary-100 hover:text-primary-600 cursor-pointer text-2xl">
|
||||
<Icon name="bi:link-45deg" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
|
||||
.center-y {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,6 @@
|
||||
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 Article_Detail_Podcast } from './details/podcast.vue'
|
||||
export { default as Article_Detail_Video } from './details/video.vue'
|
||||
export { default as Default_Breadcrumb} from './breadcrumb/default.vue'
|
||||
export { default as ADS_Default } from './ads/default.vue';
|
||||
export { default as Comment } from './comments/default.vue'
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { enumPageComponentTemplates } from "@/definitions/enum";
|
||||
import { Article_Button, Article_Detail_Emagazine, Article_Detail_Default, Article_Detail_Infographics,
|
||||
Default_Breadcrumb, ADS_Default, Comment, Article_Detail_Podcast, Article_Detail_Video
|
||||
import { Article_Detail_Emagazine, Article_Detail_Default, Article_Detail_Infographics, Comment, Article_Detail_Podcast, Article_Detail_Video
|
||||
} from "./index";
|
||||
const _props = defineProps<{
|
||||
settings: any;
|
||||
@@ -9,12 +8,9 @@ const _props = defineProps<{
|
||||
}>();
|
||||
|
||||
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_DEFAULT': Comment,
|
||||
PODCAST: Article_Detail_Podcast,
|
||||
VIDEO: Article_Detail_Video
|
||||
|
||||
Reference in New Issue
Block a user