thainnv-dev: Nhúng
This commit is contained in:
@@ -40,7 +40,7 @@ img.wide {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
transform: translateX(20%);
|
/* transform: translateX(20%); */
|
||||||
}
|
}
|
||||||
|
|
||||||
figure.image.wide {
|
figure.image.wide {
|
||||||
|
|||||||
@@ -11,17 +11,27 @@
|
|||||||
figure {
|
figure {
|
||||||
margin: auto !important;
|
margin: auto !important;
|
||||||
}
|
}
|
||||||
|
.content {
|
||||||
|
& p {
|
||||||
|
@apply mb-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
& audio {
|
||||||
|
@apply w-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
& a {
|
||||||
|
@apply text-primary-600 underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
& document {
|
||||||
|
@apply cursor-pointer text-primary-600 underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
div[layout="ARTICLE_DETAIL_EMAGAZINE"] {
|
div[layout="ARTICLE_DETAIL_EMAGAZINE"] {
|
||||||
& p,& figure.align-center-image, & #sub, & #title, & #intro {
|
& p,& figure.align-center-image, & #sub, & #title, & #intro {
|
||||||
@apply lg:max-w-640px mx-auto;
|
@apply lg:max-w-640px mx-auto;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @at-root .section_layout{
|
|
||||||
|
|
||||||
// & div[layout="BREADCRUM_DEFAULT"] {
|
|
||||||
// @apply lg:max-w-640px mx-auto;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useArticleStore } from '~/stores/articles';
|
||||||
|
const { currentArticle } = storeToRefs(useArticleStore());
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
dataId?: string,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const store = reactive({
|
||||||
|
article: useArticleStore()
|
||||||
|
})
|
||||||
|
|
||||||
|
// onBeforeMount(async () => {
|
||||||
|
// await store.article.getArticleById(Number(props.dataId))
|
||||||
|
// })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
12
|
||||||
|
<!-- {{ currentArticle }} 12 -->
|
||||||
|
<!-- <a href="#" :style="style" class="!no-underline !px-2">{{ title }} 1</a> -->
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
dataResource?: string,
|
||||||
|
dataTitle?: string,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const resource = computed(() => props.dataResource ?? '')
|
||||||
|
const title = computed(() => props.dataTitle ?? '')
|
||||||
|
const fileName = computed(() => `${title.value}.${resource.value.split('.').pop()}`)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a :href="resource" :download="fileName">{{fileName}}</a>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
dataResource?: string,
|
||||||
|
dataTitle?: string,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const resource = computed(() => props.dataResource ?? '')
|
||||||
|
const title = computed(() => props.dataTitle ?? '')
|
||||||
|
const fileName = computed(() => `${title.value}.${resource.value.split('.').pop()}`)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a :href="resource" :download="fileName">{{fileName}}</a>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { usePollStore } from '~/stores/poll'
|
||||||
|
import { usePollOptionStore } from '~/stores/poll-option'
|
||||||
|
import type { Poll } from '~/server/models/poll';
|
||||||
|
const props = defineProps<{ dataId?: string }>();
|
||||||
|
|
||||||
|
const store = reactive({
|
||||||
|
poll: usePollStore(),
|
||||||
|
pollOptions: usePollOptionStore()
|
||||||
|
})
|
||||||
|
|
||||||
|
const poll = reactive<Poll>(await store.poll.fetchById((String(props.dataId))))
|
||||||
|
const options = ref<any []>(await store.pollOptions.fetchByPollId((String(props.dataId))))
|
||||||
|
|
||||||
|
const selectedOption = ref<any>(null);
|
||||||
|
|
||||||
|
function submitVote () {
|
||||||
|
console.log(selectedOption, 'id')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<span class="inline-block px-4 py-2 shadow-xl rounded-lg bg-[#f5f5f5]">
|
||||||
|
<span class="block">
|
||||||
|
<span class="underline decoration-gray-500 font-bold">
|
||||||
|
{{ poll?.title }}
|
||||||
|
</span>
|
||||||
|
<!-- <button v-if="showResult && canShowResult" type="button" class="underline text-blue-400" @click="toggleResults">
|
||||||
|
Câu hỏi
|
||||||
|
</button>
|
||||||
|
<button class="underline text-blue-400" v-if="!showResult && canShowResult" type="button" @click="toggleResults">
|
||||||
|
Kết quả
|
||||||
|
</button> -->
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="p-1 block">
|
||||||
|
<span v-for="(option, index) in options" :key="index" class="block">
|
||||||
|
<label class="flex gap-2 m-2">
|
||||||
|
<input type="radio" :value="option.id" v-model="selectedOption" />
|
||||||
|
<span class="font-semibold">{{ option?.title }}</span>
|
||||||
|
</label>
|
||||||
|
</span>
|
||||||
|
<button @click="submitVote" class="bg-primary-500 text-white py-1 px-3 rounded-4px cursor-pointer hover:bg-primary-600 float-right">Bình chọn </button>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- <span v-else class="block">
|
||||||
|
<span v-for="(answer, index) in options" :key="index" class="block poll-result relative rounded-3xl overflow-hidden my-3">
|
||||||
|
<span class="absolute top-0 start-0 bottom-0 bg-gradient-to-r from-sky-500 to-indigo-500"
|
||||||
|
:style="{ width: `${calculatePercentage(answer?.voteCount)}%` }"></span>
|
||||||
|
<span class="block relative z-0 ps-1">
|
||||||
|
<span>{{ calculatePercentage(answer?.voteCount).toFixed(2) }}%</span>
|
||||||
|
<span class="">({{ answer?.voteCount }})</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span> -->
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
quiz
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
Survey
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
dataCode?: string,
|
||||||
|
dataTitle?: string,
|
||||||
|
style?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const title = computed(() => props.dataTitle ?? '')
|
||||||
|
const code = computed(() => props.dataCode ?? '')
|
||||||
|
const style = computed(() => props.style ?? '')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a href="#" :style="style" class="!no-underline !px-2">{{ title }} 1</a>
|
||||||
|
</template>
|
||||||
@@ -2,30 +2,40 @@
|
|||||||
|
|
||||||
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
||||||
if(!localStorage.getItem('step')) {
|
if(!localStorage.getItem('step')) {
|
||||||
localStorage.setItem('step', 0)
|
localStorage.setItem('step', '0')
|
||||||
}
|
}
|
||||||
useDynamicPageStore().step = localStorage.getItem('step') ?? 0
|
useDynamicPageStore().step = Number(localStorage.getItem('step')) ?? 0
|
||||||
function increase() {
|
function increase() {
|
||||||
useDynamicPageStore().step = Number(useDynamicPageStore().step) + 2
|
useDynamicPageStore().step = Number(useDynamicPageStore().step) + 2
|
||||||
localStorage.setItem('step', useDynamicPageStore().step)
|
localStorage.setItem('step', useDynamicPageStore().step.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrease() {
|
function decrease() {
|
||||||
useDynamicPageStore().step = Number(useDynamicPageStore().step) - 2
|
useDynamicPageStore().step = Number(useDynamicPageStore().step) - 2
|
||||||
localStorage.setItem('step', useDynamicPageStore().step)
|
localStorage.setItem('step', useDynamicPageStore().step.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('b')
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center my-3">
|
||||||
<ul class="flex gap-6 items-center text-md">
|
<ul class="flex gap-6 items-center text-md">
|
||||||
<li class="first:text-primary-600 font-semibold">
|
<li class="first:text-primary-600 font-semibold">
|
||||||
<nuxt-link to="/">Trang chủ</nuxt-link>
|
<nuxt-link to="/">Trang chủ</nuxt-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="flex gap-1.5">
|
<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">
|
<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 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>
|
<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>
|
||||||
|
|||||||
@@ -4,21 +4,59 @@ import { useWindowSize } from '@vueuse/core'
|
|||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
import { useArticleStore } from '~/stores/articles';
|
import { useArticleStore } from '~/stores/articles';
|
||||||
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
||||||
|
import Poll from '~/components/article/immerse/Poll.vue'
|
||||||
|
import Quiz from '~/components/article/immerse/Quiz.vue'
|
||||||
|
import Survey from '~/components/article/immerse/Survey.vue'
|
||||||
|
import Document from '~/components/article/immerse/Document.vue'
|
||||||
|
import Attachment from '@/components/article/immerse/Attachment.vue'
|
||||||
|
import Tag from '@/components/article/immerse/Tag.vue'
|
||||||
|
import Articlerelation from '~/components/article/immerse/ArticleRelation.vue'
|
||||||
|
|
||||||
const { currentArticle } = storeToRefs(useArticleStore());
|
const { currentArticle } = storeToRefs(useArticleStore());
|
||||||
const { step } = storeToRefs(useDynamicPageStore());
|
const { step } = storeToRefs(useDynamicPageStore());
|
||||||
|
import * as cherrio from 'cheerio'
|
||||||
|
|
||||||
|
const $ = cherrio.load(currentArticle.value.detail)
|
||||||
|
// console.log($, 'cherrip')
|
||||||
// onBeforeMount(async () => {
|
// onBeforeMount(async () => {
|
||||||
// await useArticleStore().getArticleCondition({ids: [1, 2, 3]})
|
// await useArticleStore().getArticleCondition({ids: [1, 2, 3]})
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
// onMounted(() => {
|
||||||
|
// const documentElements = document.querySelectorAll('document, attachment')
|
||||||
|
|
||||||
|
// console.log(documentElements, 'doc')
|
||||||
|
|
||||||
|
// if(documentElements.length > 0) {
|
||||||
|
// documentElements.forEach((doc) => {
|
||||||
|
// doc.addEventListener('click', (event) => {
|
||||||
|
// event.preventDefault();
|
||||||
|
// const url = doc.getAttribute('data-resource');
|
||||||
|
// const file = doc.getAttribute('data-resource') ? doc.getAttribute('data-resource')?.toString().split('.').pop() : 'docx'
|
||||||
|
// fileName.value = `${doc.getAttribute('data-title')}.${file}` ;
|
||||||
|
// console.log(url , fileName.value, '123')
|
||||||
|
// if(url && fileName.value) {
|
||||||
|
// const a = document.createElement('a');
|
||||||
|
// a.href = url?.toString();
|
||||||
|
// a.download = fileName.value;
|
||||||
|
// document.body.appendChild(a);
|
||||||
|
// a.click();
|
||||||
|
// document.body.removeChild(a);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="content" v-if="currentArticle">
|
<div class="content" v-if="currentArticle">
|
||||||
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
||||||
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${36 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${32 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
||||||
<p id="published-on" class="text-gray-600" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
<p id="published-on" class="text-gray-600 mb-3" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
||||||
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest pb-1" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest pb-1 mb-3" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
||||||
<div id="article-detail" :class="'tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div>
|
<!-- <div id="article-detail" :class="'tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div> -->
|
||||||
|
<component :is="{template: currentArticle.detail, components: { Poll, Document, Attachment, Tag} }" />
|
||||||
|
<!-- <component :is="{template: currentArticle.detail, components: { Poll, Quiz, Survey, Document, Attachment, Tag} }" /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ const { step } = storeToRefs(useDynamicPageStore());
|
|||||||
<template>
|
<template>
|
||||||
<div class="content" v-if="currentArticle">
|
<div class="content" v-if="currentArticle">
|
||||||
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
||||||
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${36 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${32 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
||||||
<p id="published-on" class="text-gray-600" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
<p id="published-on" class="text-gray-600 mb-3" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
||||||
|
|
||||||
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest pb-1" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest pb-1 mb-3" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
||||||
<div id="article-detail" :class="' tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div>
|
<div id="article-detail" :class="' tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ const { step } = storeToRefs(useDynamicPageStore());
|
|||||||
<template>
|
<template>
|
||||||
<div class="content" v-if="currentArticle">
|
<div class="content" v-if="currentArticle">
|
||||||
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
<h1 id="sub" v-html="currentArticle?.sub" class=" font-bold opacity-60 pb-1" :style="{ 'font-size': `${16 + Number(step)}px`}"></h1>
|
||||||
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${36 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
<h3 id="title" :style="{ 'font-size': width > breakpoint.lg ? `${32 + Number(step)}px` : `${20 + Number(step)}px`}" class="font-bold pb-1" v-html="currentArticle?.title"></h3>
|
||||||
<p id="published-on" class="text-gray-600" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
<p id="published-on" class="text-gray-600 mb-3" :style="{ 'font-size': `${14 + Number(step)}px` }">{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}</p>
|
||||||
|
|
||||||
<!-- <div class="author">Tác giả - Thời gian tạo</div> -->
|
<!-- <div class="author">Tác giả - Thời gian tạo</div> -->
|
||||||
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest pb-1" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
<div id="intro" v-if="currentArticle?.intro" v-html="currentArticle?.intro" class="font-semibold tracking-widest mb-3" :style="{'font-size': `${16 + Number(step)}px`}"></div>
|
||||||
<div id="article-detail" :class="'text-[16px] tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div>
|
<div id="article-detail" :class="'text-[16px] tracking-wider'" v-html="currentArticle.detail" class="[&_img]:mx-auto" :style="{ 'font-size': `${16 + Number(step)}px`}"> </div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+3
-16
@@ -84,25 +84,11 @@ watch(
|
|||||||
</template>
|
</template>
|
||||||
<div class="button-page flex">
|
<div class="button-page flex">
|
||||||
<a class="btn-page prev-page">
|
<a class="btn-page prev-page">
|
||||||
<i class="el-icon">
|
<Icon name="material-symbols:arrow-back-ios-new-rounded"/>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</i>
|
|
||||||
</a>
|
</a>
|
||||||
<a class="btn-page" @click="() => select(index + 1)" v-for="(_, index) in totals" :key="index">{{ index + 1 }}</a>
|
<a class="btn-page" @click="() => select(index + 1)" v-for="(_, index) in totals" :key="index">{{ index + 1 }}</a>
|
||||||
<a class="btn-page next-page">
|
<a class="btn-page next-page">
|
||||||
<i class="el-icon">
|
<Icon class="rotate-180deg" name="material-symbols:arrow-back-ios-new-rounded"/>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M340.864 149.312a30.592 30.592 0 0 0 0 42.752L652.736 512 340.864 831.872a30.592 30.592 0 0 0 0 42.752 29.12 29.12 0 0 0 41.728 0L714.24 534.336a32 32 0 0 0 0-44.672L382.592 149.376a29.12 29.12 0 0 0-41.728 0z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</i>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -164,6 +150,7 @@ watch(
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
color:#409eff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-empty {
|
.el-empty {
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ useSeoMeta({
|
|||||||
ogDescription: () => currentArticle.value?.intro,
|
ogDescription: () => currentArticle.value?.intro,
|
||||||
twitterCard: 'summary_large_image',
|
twitterCard: 'summary_large_image',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(document.querySelectorAll('document'), '12')
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ watch(currentPage, () => {
|
|||||||
useHead({
|
useHead({
|
||||||
title: 'Trang chủ'
|
title: 'Trang chủ'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import * as navigationCtrl from '~/server/models/navigation'
|
|||||||
import * as eventCtrl from '~/server/models/event'
|
import * as eventCtrl from '~/server/models/event'
|
||||||
import * as tagCtrl from '~/server/models/tag'
|
import * as tagCtrl from '~/server/models/tag'
|
||||||
import * as topicCtrl from '~/server/models/topic'
|
import * as topicCtrl from '~/server/models/topic'
|
||||||
|
import * as pollCtrl from '~/server/models/poll'
|
||||||
|
import * as pollOptionCtrl from '~/server/models/poll-option'
|
||||||
|
import * as pollResponseCtrl from '~/server/models/poll-response'
|
||||||
|
|
||||||
const router = createRouter()
|
const router = createRouter()
|
||||||
|
|
||||||
@@ -10,5 +13,7 @@ router.get('/navigation', defineEventHandler(navigationCtrl.get))
|
|||||||
router.get('/tag', defineEventHandler(tagCtrl.fetchById))
|
router.get('/tag', defineEventHandler(tagCtrl.fetchById))
|
||||||
router.get('/topic', defineEventHandler(topicCtrl.fetchById))
|
router.get('/topic', defineEventHandler(topicCtrl.fetchById))
|
||||||
router.get('/event', defineEventHandler(eventCtrl.fetchById))
|
router.get('/event', defineEventHandler(eventCtrl.fetchById))
|
||||||
|
router.get('/poll-by-id', defineEventHandler(pollCtrl.fetchById))
|
||||||
|
router.get('/poll-option/pollId', defineEventHandler(pollOptionCtrl.fetchByPollId))
|
||||||
|
router.post('/poll-response', defineEventHandler(pollResponseCtrl.create))
|
||||||
export default useBase('/api/services', router.handler)
|
export default useBase('/api/services', router.handler)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export const listArticleCondition = async (event: H3Event) => {
|
|||||||
try {
|
try {
|
||||||
const payload = await readBody<any>(event)
|
const payload = await readBody<any>(event)
|
||||||
const { apiUrl } = useRuntimeConfig().public
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
const { items }: any = await $fetch(`${apiUrl}/cms/article/condition`, {
|
const { items }: any = await $fetch(`${apiUrl}/cms/digital-article/condition`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Site: 1
|
Site: 1
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export const getDynamicPageByCode = async (event : any) => {
|
|||||||
try {
|
try {
|
||||||
const { apiUrl } = useRuntimeConfig().public
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
const slug = event.context.params.slug;
|
const slug = event.context.params.slug;
|
||||||
const { item }: any = await $fetch(`${apiUrl}/cms/overview-page/slug:${slug}`, {
|
const { item }: any = await $fetch(`${apiUrl}/cms/page/overview-page/slug:${slug}`, {
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
site: '1' || 1,
|
site: '1' || 1,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { H3Event } from 'h3';
|
||||||
|
import Base from './base'
|
||||||
|
|
||||||
|
|
||||||
|
export const fetchByPollId = async (event: H3Event) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
|
const { pollId}: any = getQuery(event)
|
||||||
|
const { items }: any = await $fetch(`${apiUrl}/cms/poll-option/poll:${pollId}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
site: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { H3Event } from 'h3';
|
||||||
|
import Base from './base'
|
||||||
|
|
||||||
|
|
||||||
|
export const create = async (event: H3Event) => {
|
||||||
|
try {
|
||||||
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
|
const payload = await readBody<any>(event)
|
||||||
|
const { item }: any = await $fetch(`${apiUrl}/cms/poll-response`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
site: 1
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
payload
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return item
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { H3Event } from 'h3';
|
||||||
|
import Base from './base'
|
||||||
|
|
||||||
|
export type Poll = {
|
||||||
|
id?: number; // Mã định danh
|
||||||
|
siteId?: number; // Mã hệ thống
|
||||||
|
title?: string; // Tiêu đề
|
||||||
|
code?: string; // Nhận diện
|
||||||
|
keywords?: string; // Từ khóa
|
||||||
|
thumbnail?: string; // Ảnh nhỏ
|
||||||
|
description?: string; // Mô tả
|
||||||
|
startTime?: string; // Bắt đầu (string)
|
||||||
|
endTime?: string; // Kết thúc (string)
|
||||||
|
type?: number; // Phân loại
|
||||||
|
settings?: object; // Thiết lập: PollSettings (Json)
|
||||||
|
features?: string; // Đặc trưng: Featured (nổi bật)
|
||||||
|
taxonomy?: string; // Phân nhóm
|
||||||
|
isPublished?: boolean; // Đã xuất bản
|
||||||
|
publishedBy?: number; // Xuất bản bởi
|
||||||
|
publishedOn?: string; // Xuất bản vào lúc (string)
|
||||||
|
expiresOn?: string; // Đã hết hạn vào lúc (string)
|
||||||
|
order?: number; // Thứ tự sắp xếp
|
||||||
|
status?: number; // Trạng thái
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchById = async (event: H3Event) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
|
const { pollId}: any = getQuery(event)
|
||||||
|
const { item }: any = await $fetch(`${apiUrl}/cms/poll/${pollId}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
site: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return item
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const usePollOptionStore = defineStore('usepollOptionStore', () => {
|
||||||
|
async function fetchByPollId(id: string) {
|
||||||
|
const { data, error } = await useFetch<any>(`/api/services/poll-option/pollId`, {
|
||||||
|
query: {
|
||||||
|
pollId: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(error.value) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return { fetchByPollId }
|
||||||
|
})
|
||||||
|
|
||||||
|
if(import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useTagStore, import.meta.hot))
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
export const usePollResponseStore = defineStore('usepollResponseStore', () => {
|
||||||
|
async function create(pollResponse: any) {
|
||||||
|
const { data, error } = await useFetch<any>(`/api/services/poll-response`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: pollResponse
|
||||||
|
})
|
||||||
|
if(error.value) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return { create }
|
||||||
|
})
|
||||||
|
|
||||||
|
if(import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useTagStore, import.meta.hot))
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const usePollStore = defineStore('usepollStore', () => {
|
||||||
|
async function fetchById(id: string) {
|
||||||
|
const { data, error } = await useFetch<any>(`/api/services/poll-by-id`, {
|
||||||
|
query: {
|
||||||
|
pollId: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(error.value) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return { fetchById }
|
||||||
|
})
|
||||||
|
|
||||||
|
if(import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useTagStore, import.meta.hot))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user