Compare commits
21 Commits
thainv-dev
...
81bfa351e8
| Author | SHA1 | Date | |
|---|---|---|---|
| 81bfa351e8 | |||
| a3e20c9445 | |||
| 6806201085 | |||
| 4ec2e425df | |||
| 31175ade27 | |||
| ccd92c86ee | |||
| a47229f44e | |||
| 0ad19bbcfd | |||
| 11ea05de83 | |||
| e738cca263 | |||
| b93f0218a5 | |||
| 3fe4da0ecb | |||
| a9d6bea337 | |||
| df31b7bdef | |||
| a1c6e2872f | |||
| 46b808cf9c | |||
| 367374863e | |||
| 66b5a8ce6a | |||
| adecec9041 | |||
| 984ec50a39 | |||
| a756c91bd0 |
@@ -18,6 +18,7 @@ const { currentPollOptions } = storeToRefs(store.pollOptions);
|
|||||||
const { currentPollResponses } = storeToRefs(store.pollResponse);
|
const { currentPollResponses } = storeToRefs(store.pollResponse);
|
||||||
const poll = reactive<Poll | any>({});
|
const poll = reactive<Poll | any>({});
|
||||||
const options = ref<PollOption[] | any[]>([]);
|
const options = ref<PollOption[] | any[]>([]);
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
await store.poll.fetchById(String(props.dataId));
|
await store.poll.fetchById(String(props.dataId));
|
||||||
await store.pollOptions.fetchByPollId(String(props.dataId));
|
await store.pollOptions.fetchByPollId(String(props.dataId));
|
||||||
@@ -30,13 +31,14 @@ function assignData() {
|
|||||||
options.value = currentPollOptions.value;
|
options.value = currentPollOptions.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
await loadData();
|
||||||
await loadData();
|
// onBeforeMount(async () => {
|
||||||
});
|
// });
|
||||||
|
|
||||||
const selectedOption = ref<any>(-1);
|
// const selectedOption = ref<any>(-1);
|
||||||
const showResult = ref(false);
|
// const showResult = ref(false);
|
||||||
const alreadyVoted = ref(false);
|
const alreadyVoted = ref(false);
|
||||||
|
const showResult = ref(false)
|
||||||
const canShowResult = computed(() => {
|
const canShowResult = computed(() => {
|
||||||
switch (poll.settings?.resultPublication) {
|
switch (poll.settings?.resultPublication) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -49,29 +51,74 @@ const canShowResult = computed(() => {
|
|||||||
return alreadyVoted.value && (!poll.endTime || new Date() > new Date(poll.endTime));
|
return alreadyVoted.value && (!poll.endTime || new Date() > new Date(poll.endTime));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// const toggleResults = () => {
|
||||||
|
// if (canShowResult.value) showResult.value = !showResult.value;
|
||||||
|
// };
|
||||||
|
|
||||||
|
const singleSelect = ref<number>(-1)
|
||||||
|
const multipleSelect = ref<number []>([])
|
||||||
|
|
||||||
const totalResponses = ref(0);
|
const totalResponses = ref(0);
|
||||||
async function submitVote() {
|
async function submitVote() {
|
||||||
if (selectedOption.value >= 0 && !alreadyVoted.value) {
|
// if (selectedOption.value >= 0 && !alreadyVoted.value) {
|
||||||
const result = await store.pollResponse.create({ optionId: selectedOption.value });
|
// const result = await store.pollResponse.create({ optionId: selectedOption.value });
|
||||||
if (result?.id) {
|
// if (result?.id) {
|
||||||
|
// totalResponses.value = options.value?.reduce((sum, option) => sum + Number(option.responseCount ?? 0), 1);
|
||||||
|
// options?.value?.forEach((option: PollOption | any) => {
|
||||||
|
// if (option.id === selectedOption.value) {
|
||||||
|
// option.responseCount = (option.responseCount ?? 0) + 1;
|
||||||
|
// }
|
||||||
|
// option.percentage = Number(((option.responseCount / totalResponses.value) * 100).toFixed(1));
|
||||||
|
// });
|
||||||
|
// alreadyVoted.value = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
switch (poll.type) {
|
||||||
|
case 1:
|
||||||
|
if(singleSelect.value >= 0) {
|
||||||
totalResponses.value = options.value?.reduce((sum, option) => sum + Number(option.responseCount ?? 0), 1);
|
totalResponses.value = options.value?.reduce((sum, option) => sum + Number(option.responseCount ?? 0), 1);
|
||||||
options?.value?.forEach((option: PollOption | any) => {
|
options?.value?.forEach((option: PollOption | any) => {
|
||||||
if (option.id === selectedOption.value) {
|
if (option.id === singleSelect.value) {
|
||||||
option.responseCount = (option.responseCount ?? 0) + 1;
|
option.responseCount = (option.responseCount ?? 0) + 1;
|
||||||
}
|
}
|
||||||
option.percentage = Number(((option.responseCount / totalResponses.value) * 100).toFixed(1));
|
option.percentage = Number(((option.responseCount / totalResponses.value) * 100).toFixed(1));
|
||||||
|
alreadyVoted.value = true
|
||||||
});
|
});
|
||||||
alreadyVoted.value = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleResults = () => {
|
|
||||||
if (canShowResult.value) showResult.value = !showResult.value;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<span class="inline-block px-4 py-2 shadow-xl rounded-lg bg-[#f5f5f5]">
|
|
||||||
|
<div class="inline-block px-4 py-2 mb-5">
|
||||||
|
<h3 class="text-#000 font-raleway font-italic text-16px font-500 leading-140% mb-2">{{ poll?.title }}</h3>
|
||||||
|
<ul class="flex flex-col gap-3">
|
||||||
|
<template v-if="poll.type === 1">
|
||||||
|
<li v-for="(option, index) in options" :key="index">
|
||||||
|
<input :id="`option-${index}`" :disabled="singleSelect >= 0 && alreadyVoted ? true : false" type="radio" class="peer opacity-0" :value="option.id" v-model="singleSelect">
|
||||||
|
<label :for="`option-${index}`" class="font-raleway text-16px relative text-#000 font-400 leading-140% pl-16px before:content-[''] before:inline-block before:w-14px before:h-14px before:rounded-50% before:border-1 before:absolute before:left--3 before:top-10px before:border-1px before:border-#000 before:translate-y--50% after:absolute after:left--10px after:top-10px after:translate-y--50% after:border-#000 after:content-[''] after:inline-block after:w-10px after:h-10px after:rounded-full peer-checked:after:bg-primary peer-checked:before:border-primary ">{{ option?.title }}</label>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center mt-3">
|
||||||
|
<button @click="submitVote()" v-if="!alreadyVoted" :disabled="alreadyVoted && singleSelect >= 0 ? true : false" class="px-5 py-10px rounded-6px bg-primary text-#fff font-raleway text-14px font-400">Gửi kết quả</button>
|
||||||
|
<button @click="showResult = true" v-if="alreadyVoted" class="px-5 py-10px rounded-6px bg-primary text-#fff font-raleway text-14px font-400">Xem kết quả</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-5" v-if="showResult && canShowResult">
|
||||||
|
<h3 class="text-#000 font-raleway font-italic text-16px font-500 leading-140% mb-2">{{ poll?.title }}</h3>
|
||||||
|
<ul>
|
||||||
|
<li v-for="(answer, index) in options" :key="index" class="flex gap-4 items-center text-#000 font-raleway text-12px leading-140%">
|
||||||
|
{{ answer.percentage}}%
|
||||||
|
<div :style="{ width: `${answer.percentage}%` }" :class="answer.id === singleSelect ? 'bg-primary' : 'bg-#AEAEAE'" class="h-1.5 rounded-full"></div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <span class="inline-block px-4 py-2 shadow-xl rounded-lg bg-[#f5f5f5]">
|
||||||
<span class="block">
|
<span class="block">
|
||||||
<span class="underline decoration-gray-500 font-bold">
|
<span class="underline decoration-gray-500 font-bold">
|
||||||
{{ poll?.title }}
|
{{ poll?.title }}
|
||||||
@@ -100,5 +147,5 @@ const toggleResults = () => {
|
|||||||
</span>
|
</span>
|
||||||
<b>Tổng số lượt binh chọn: {{ totalResponses }}</b>
|
<b>Tổng số lượt binh chọn: {{ totalResponses }}</b>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span> -->
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -246,23 +246,33 @@ async function submitSend() {}
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="inline-block px-4 py-2 shadow-xl rounded-lg bg-[#f5f5f5] !text-black-500">
|
<div class="inline-block px-4 py-2 !text-black-500">
|
||||||
<h5 class="underline decoration-gray-500 font-bold mb-2">Câu đố: {{ data?.title }}</h5>
|
<h5 class="underline decoration-gray-500 font-bold mb-2">Câu đố: {{ data?.title }}</h5>
|
||||||
|
|
||||||
<ul class="px-3">
|
<ul class="px-3 flex flex-col gap-3">
|
||||||
<li v-for="(question, questionIndex) in data.questionGeneral" :key="questionIndex" class="mb-2">
|
<li v-for="(question, questionIndex) in data.questionGeneral" :key="questionIndex" class="mb-2">
|
||||||
<h5 class="mb-1 font-700 text-black-500">{{ `${questionIndex + 1}. ${question.title}` }}</h5>
|
<h5 class="text-#000 font-raleway font-italic text-16px font-500 leading-140% mb-2">{{ `${questionIndex + 1}. ${question.title}` }}</h5>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<template v-if="question.type === 1">
|
||||||
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
||||||
<input :id="`answer-${questionIndex}-${answerIndex}`" :type="question.type === 1 ? 'radio' : 'checkbox'" :value="answerIndex" v-model="selectQuizAnswer[questionIndex]" />
|
<input :id="`answer-${questionIndex}-${answerIndex}`" type="radio" :value="answerIndex" class="peer opacity-0" v-model="selectQuizAnswer[questionIndex]" />
|
||||||
<label :for="`answer-${questionIndex}-${answerIndex}`" class="font-semibold">{{ answer.title }}</label>
|
<label :for="`answer-${questionIndex}-${answerIndex}`" class="font-raleway text-16px relative text-#000 font-400 leading-140% pl-16px before:content-[''] before:inline-block before:w-14px before:h-14px before:rounded-50% before:border-1 before:absolute before:left--3 before:top-10px before:border-1px before:border-#000 before:translate-y--50% after:absolute after:left--10px after:top-10px after:translate-y--50% after:border-#000 after:content-[''] after:inline-block after:w-10px after:h-10px after:rounded-full peer-checked:after:bg-primary peer-checked:before:border-primary ">{{ answer.title }}</label>
|
||||||
</li>
|
</li>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
||||||
|
<input :id="`answer-${questionIndex}-${answerIndex}`" type="checkbox" :value="answerIndex" class="peer opacity-0" v-model="selectQuizAnswer[questionIndex]" />
|
||||||
|
<label :for="`answer-${questionIndex}-${answerIndex}`" class="font-raleway text-16px relative text-#000 font-400 leading-140% pl-16px before:content-[''] before:inline-block before:w-14px before:h-14px before:rounded-2px before:border-1 before:absolute before:left--3 before:top-10px before:border-1px before:border-#000 before:translate-y--50% after:absolute after:left--10px after:top-6px after:translate-y--50% after:border-#000 after:content-['✔'] after:text-12px after:text-transparent after:inline-block after:w-14px after:h-14px peer-checked:after:text-white peer-checked:before:border-primary peer-checked:before:bg-primary ">{{ answer.title }}</label>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<button @click="submitSend" class="bg-primary-500 text-white py-1 px-3 rounded-4px cursor-pointer hover:bg-primary-600 float-right">Gửi câu trả lời</button>
|
<div class="flex justify-center">
|
||||||
|
<button @click="submitSend" class="mx-auto px-5 py-10px rounded-6px bg-primary text-#fff font-raleway text-14px font-400">Gửi câu trả lời</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div>
|
<!-- <div>
|
||||||
<h5 class="text-black text-18px font-700">{{ data?.title }}</h5>
|
<h5 class="text-black text-18px font-700">{{ data?.title }}</h5>
|
||||||
|
|||||||
@@ -270,24 +270,41 @@ async function submitSend() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="inline-block px-4 py-2 shadow-xl rounded-lg bg-[#f5f5f5] !text-black-500">
|
<div class="inline-block px-4 py-2 !text-black-500">
|
||||||
<h5 class="underline decoration-gray-500 font-bold mb-2">Khảo sát: {{ dataSurvey?.title }}</h5>
|
<h5 class="underline decoration-gray-500 font-bold mb-2">Khảo sát: {{ dataSurvey?.title }}</h5>
|
||||||
|
|
||||||
<ul class="px-3">
|
<ul class="px-3">
|
||||||
<li v-for="(question, questionIndex) in dataSurvey.questionGeneral" :key="questionIndex" class="mb-2">
|
<li v-for="(question, questionIndex) in dataSurvey.questionGeneral" :key="questionIndex" class="mb-2">
|
||||||
<h5 class="mb-1 font-700 text-black-500">{{ `${questionIndex + 1}. ${question.title}` }}</h5>
|
<h5 class="text-#000 font-raleway font-italic text-16px font-500 leading-140% mb-2">{{ `${questionIndex + 1}. ${question.title}` }}</h5>
|
||||||
|
|
||||||
<ul>
|
<!-- <ul>
|
||||||
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
||||||
<input :id="`answer-survey-${questionIndex}-${answerIndex}`" :type="question.type === 1 ? 'radio' : 'checkbox'" :value="answerIndex" v-model="selectSurveyAnswer[questionIndex]">
|
<input :id="`answer-survey-${questionIndex}-${answerIndex}`" :type="question.type === 1 ? 'radio' : 'checkbox'" :value="answerIndex" v-model="selectSurveyAnswer[questionIndex]">
|
||||||
<label :for="`answer-survey-${questionIndex}-${answerIndex}`" class="font-semibold">{{ answer.title }}</label>
|
<label :for="`answer-survey-${questionIndex}-${answerIndex}`" class="font-semibold">{{ answer.title }}</label>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
</ul> -->
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<template v-if="question.type === 1">
|
||||||
|
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
||||||
|
<input :id="`answer-survey-${questionIndex}-${answerIndex}`" type="radio" :value="answerIndex" class="peer opacity-0" v-model="selectSurveyAnswer[questionIndex]" />
|
||||||
|
<label :for="`answer-survey-${questionIndex}-${answerIndex}`" class="font-raleway text-16px relative text-#000 font-400 leading-140% pl-16px before:content-[''] before:inline-block before:w-14px before:h-14px before:rounded-50% before:border-1 before:absolute before:left--3 before:top-10px before:border-1px before:border-#000 before:translate-y--50% after:absolute after:left--10px after:top-10px after:translate-y--50% after:border-#000 after:content-[''] after:inline-block after:w-10px after:h-10px after:rounded-full peer-checked:after:bg-primary peer-checked:before:border-primary ">{{ answer.title }}</label>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<li v-for="(answer, answerIndex) in question.answers" :key="answerIndex" class="flex items-center gap-1 py-1">
|
||||||
|
<input :id="`answer-survey-${questionIndex}-${answerIndex}`" type="checkbox" :value="answerIndex" class="peer opacity-0" v-model="selectSurveyAnswer[questionIndex]" />
|
||||||
|
<label :for="`answer-survey-${questionIndex}-${answerIndex}`" class="font-raleway text-16px relative text-#000 font-400 leading-140% pl-16px before:content-[''] before:inline-block before:w-14px before:h-14px before:rounded-2px before:border-1 before:absolute before:left--3 before:top-10px before:border-1px before:border-#000 before:translate-y--50% after:absolute after:left--10px after:top-6px after:translate-y--50% after:border-#000 after:content-['✔'] after:text-12px after:text-transparent after:inline-block after:w-14px after:h-14px peer-checked:after:text-white peer-checked:before:border-primary peer-checked:before:bg-primary ">{{ answer.title }}</label>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<button @click="submitSend" class="bg-primary-500 text-white py-1 px-3 rounded-4px cursor-pointer hover:bg-primary-600 float-right">Gửi câu trả lời</button>
|
<div class="flex justify-center">
|
||||||
|
<button @click="submitSend" class="mx-auto px-5 py-10px rounded-6px bg-primary text-#fff font-raleway text-14px font-400">Gửi câu trả lời</button>
|
||||||
|
</div>
|
||||||
|
<!-- <button @click="submitSend" class="bg-primary-500 text-white py-1 px-3 rounded-4px cursor-pointer hover:bg-primary-600 float-right">Gửi câu trả lời</button> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ const parseData = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const playVideo = ref<boolean>(false)
|
const playVideo = ref<boolean>(false)
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getResource(JSON.parse(props.dataResult).detail)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -41,6 +37,7 @@ onMounted(() => {
|
|||||||
v-if="!playVideo"
|
v-if="!playVideo"
|
||||||
class="article_video_thumb h-full"
|
class="article_video_thumb h-full"
|
||||||
:style="{ backgroundImage: `url('${parseData.thumbnail ? parseData.thumbnail : '/images/default-thumbnail.jpg'}')` }"
|
:style="{ backgroundImage: `url('${parseData.thumbnail ? parseData.thumbnail : '/images/default-thumbnail.jpg'}')` }"
|
||||||
|
@click="playVideo = true"
|
||||||
>
|
>
|
||||||
<div></div>
|
<div></div>
|
||||||
<div class="article_video_content">
|
<div class="article_video_content">
|
||||||
@@ -53,7 +50,8 @@ onMounted(() => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<video src=""></video>
|
<div v-else v-html="getResource('HIGHLIGHT_VIDEO', JSON.parse(props.dataResult).detail)">
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||||
import { COLLECTION_QUERY_DROP, getValueStringWithKeyAndColon, getInputValue } from "@/utils/parseSQL";
|
import { COLLECTION_QUERY_DROP, getValueStringWithKeyAndColon, getInputValue } from "@/utils/parseSQL";
|
||||||
import { isEmpty, groupBy } from "lodash";
|
import { isEmpty } from "@/utils/lodash";
|
||||||
import { enumPageComponentTemplates } from "@/definitions/enum";
|
import { enumPageComponentTemplates } from "@/definitions/enum";
|
||||||
const emit = defineEmits(["dropComponent", "dropData", "selectComponent"]);
|
const emit = defineEmits(["dropComponent", "dropData", "selectComponent"]);
|
||||||
const _props = defineProps<{
|
const _props = defineProps<{
|
||||||
|
|||||||
@@ -1,31 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
import JSWidget from '@/components/widget/JSwidget.vue';
|
import JSWidget from '@/components/widget/JSwidget.vue';
|
||||||
|
|
||||||
const widgetOptions = {
|
const widgetOptions = {
|
||||||
"locale": "vi",
|
"locale": "vi",
|
||||||
|
"width": "334px",
|
||||||
|
"height": "250px",
|
||||||
"price_line_color": "#71BDDF",
|
"price_line_color": "#71BDDF",
|
||||||
"grid_color": "#999999",
|
"grid_color": "#999999",
|
||||||
"label_color": "#999999",
|
"label_color": "#999999",
|
||||||
"width": "350px",
|
|
||||||
"height": "250px"
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<JSWidget
|
<JSWidget
|
||||||
CONTAINER_ID="default_widget_[123123]"
|
:CONTAINER_ID="nanoid(10)"
|
||||||
SCRIPT_ID="12312312"
|
:SCRIPT_ID="nanoid(10)"
|
||||||
SCRIPT_SRC="https://www.fireant.vn/Scripts/web/widgets.js"
|
SCRIPT_SRC="https://www.fireant.vn/Scripts/web/widgets.js"
|
||||||
:options="widgetOptions"
|
:options="widgetOptions"
|
||||||
|
:inside="false"
|
||||||
widgetKey="FireAnt"
|
widgetKey="FireAnt"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
div {
|
div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 200px;
|
|
||||||
background-color: #ededed;
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
import JSWidget from '@/components/widget/JSwidget.vue';
|
||||||
|
|
||||||
|
const widgetOptions = {
|
||||||
|
"symbols": [
|
||||||
|
{
|
||||||
|
"proName": "FOREXCOM:SPXUSD",
|
||||||
|
"title": "S&P 500 Index"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proName": "FOREXCOM:NSXUSD",
|
||||||
|
"title": "US 100 Cash CFD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proName": "FX_IDC:EURUSD",
|
||||||
|
"title": "EUR to USD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proName": "BITSTAMP:BTCUSD",
|
||||||
|
"title": "Bitcoin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proName": "BITSTAMP:ETHUSD",
|
||||||
|
"title": "Ethereum"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isTransparent": false,
|
||||||
|
"showSymbolLogo": true,
|
||||||
|
"colorTheme": "dark",
|
||||||
|
"locale": "en"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<JSWidget
|
||||||
|
:CONTAINER_ID="nanoid(10)"
|
||||||
|
:SCRIPT_ID="nanoid(10)"
|
||||||
|
SCRIPT_SRC="https://s3.tradingview.com/external-embedding/embed-widget-tickers.js"
|
||||||
|
:options="widgetOptions"
|
||||||
|
:inside="true"
|
||||||
|
widgetKey="TradingView"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
export { default as Stock_Default } from './334x641.vue'
|
export { default as Stock_Default } from './334x641.vue'
|
||||||
|
export { default as Stock_FullSize } from './Full.vue'
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { enumPageComponentTemplate, enumPageComponentKey, enumPageComponentLayouts } from "@/definitions/enum";
|
import { enumPageComponentTemplate, enumPageComponentKey, enumPageComponentLayouts } from "@/definitions/enum";
|
||||||
import { Stock_Default } from "./index";
|
import { Stock_Default, Stock_FullSize } from "./index";
|
||||||
|
|
||||||
const _props = defineProps<{
|
const _props = defineProps<{
|
||||||
settings: any;
|
settings: any;
|
||||||
@@ -9,6 +9,7 @@ const _props = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
const definedDynamicComponent: Record<string, any> = {
|
const definedDynamicComponent: Record<string, any> = {
|
||||||
[enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']]['STOCK_DEFAULT']]: Stock_Default,
|
[enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']]['STOCK_DEFAULT']]: Stock_Default,
|
||||||
|
[enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.OTHER]["STOCK"]]["STOCK_FULLSIZE"]]: Stock_FullSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCurrentComponent = computed(() => `${_props.settings.layout}`);
|
const getCurrentComponent = computed(() => `${_props.settings.layout}`);
|
||||||
|
|||||||
@@ -1,25 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { isEmpty } from "@/utils/lodash";
|
|
||||||
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
|
||||||
import { COLLECTION_PAGING_QUERY_DROP, getInputValue } from "@/utils/parseSQL";
|
import { getInputValue } from "@/utils/parseSQL";
|
||||||
|
import { enumPageComponentTemplates } from "@/definitions/enum";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
// const store = reactive({
|
const store = reactive({
|
||||||
// component: usePageComponentStore(),
|
component: useDynamicPageStore(),
|
||||||
// });
|
});
|
||||||
|
|
||||||
const _props = defineProps<{
|
const _props = defineProps<{
|
||||||
dataResult?: any;
|
dataResult?: any[];
|
||||||
dataQuery?: string;
|
dataQuery?: string;
|
||||||
component?: any;
|
component?: any;
|
||||||
label?: any;
|
label?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const SETTING_OPTIONS = {
|
const SETTING_OPTIONS = {
|
||||||
MAX_ELEMENT: 5,
|
MAX_ELEMENT: 5,
|
||||||
TEMPLATE: "Article",
|
TEMPLATE: "TYPE:Card",
|
||||||
LAYOUT: "TYPE:Card",
|
LAYOUT: "TYPE:Card_Default",
|
||||||
|
};
|
||||||
|
|
||||||
|
const COMPONENT = {
|
||||||
|
taxonomy: enumPageComponentTemplates.ARTICLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
@@ -60,14 +64,11 @@ const handleRouteChange = async (query: any) => {
|
|||||||
const param = query[`cpn_${_props.component?.id}`];
|
const param = query[`cpn_${_props.component?.id}`];
|
||||||
if (param) {
|
if (param) {
|
||||||
const [_, value] = param.split(":") || [];
|
const [_, value] = param.split(":") || [];
|
||||||
page.value = value;
|
page.value = Number(value);
|
||||||
await loadPage(value);
|
await loadPage(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
if (route.query[`cpn_${_props.component?.id}`]) handleRouteChange(route.query);
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadPage = async (page: number) => {
|
const loadPage = async (page: number) => {
|
||||||
let newDataQuery = "";
|
let newDataQuery = "";
|
||||||
@@ -79,14 +80,17 @@ const loadPage = async (page: number) => {
|
|||||||
} else {
|
} else {
|
||||||
newDataQuery = _props.component?.settings?.dataQuery + ` Page[${page}]`;
|
newDataQuery = _props.component?.settings?.dataQuery + ` Page[${page}]`;
|
||||||
}
|
}
|
||||||
// const res = await store.component.getOverviewPageComponentById(Number(_props.component?.id), newDataQuery);
|
const {item} = await store.component.getOverviewPageComponentById(Number(_props.component?.id), newDataQuery);
|
||||||
// const data = getInputValue(res?.settings?.dataResult, "OBJECT");
|
const data = getInputValue(item?.settings?.dataResult, "OBJECT");
|
||||||
// if (Object.keys(data).length > 0) {
|
|
||||||
// totals.value = data.Total;
|
if (Object.keys(data).length > 0) {
|
||||||
// listArticlePaging.value = data?.Data || [];
|
totals.value = data.Total;
|
||||||
// }
|
listArticlePaging.value = data?.Data || [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (route.query[`cpn_${_props.component?.id}`]) handleRouteChange(route.query);
|
||||||
|
|
||||||
const handleNextPrev = (type: "+" | "-") => {
|
const handleNextPrev = (type: "+" | "-") => {
|
||||||
if (listArticleByCategory.value?.length > 0) {
|
if (listArticleByCategory.value?.length > 0) {
|
||||||
if (type === "+") {
|
if (type === "+") {
|
||||||
@@ -107,51 +111,32 @@ const mapActivesToItems = (index: number) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section v-if="listArticleByCategory?.length > 0">
|
||||||
<div class="section-container" :class="[listArticleByCategory && listArticleByCategory?.length > 0 ? '' : 'noData']">
|
<div class="section-container">
|
||||||
<div class="section-layout" :style="designObject['div.section']">
|
<div class="section-layout" :style="designObject['div.section']">
|
||||||
<template v-if="listArticleByCategory?.length > 0">
|
<template v-for="(component, index) in listArticlePaging?.length > 0 ? listArticlePaging : listArticleByCategory" :key="index">
|
||||||
<template v-for="(component, index) in listArticlePaging?.length > 0 ? listArticlePaging : listArticleByCategory">
|
|
||||||
<DynamicComponent
|
<DynamicComponent
|
||||||
:key="index"
|
|
||||||
v-if="!isEmpty(component)"
|
|
||||||
:settings="{
|
:settings="{
|
||||||
template: SETTING_OPTIONS.TEMPLATE,
|
template: SETTING_OPTIONS.TEMPLATE,
|
||||||
layout: SETTING_OPTIONS.LAYOUT,
|
layout: SETTING_OPTIONS.LAYOUT,
|
||||||
dataResult: { ...component },
|
dataResult: { ...component },
|
||||||
label: mapActivesToItems(Number(index)),
|
label: mapActivesToItems(Number(index)),
|
||||||
}"
|
}"
|
||||||
|
:component="COMPONENT"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="empty"><h6 class="px-2 text-center">Nội dung danh sách bài viết của danh mục sẽ ở đây</h6></div>
|
|
||||||
</template>
|
|
||||||
<div class="button-page flex">
|
<div class="button-page flex">
|
||||||
<a class="btn-page prev-page" @click.stop="() => handleNextPrev('-')" v-if="page > 1">
|
<span class="btn-page prev-page" @click.stop="() => handleNextPrev('-')" v-if="page > 1">
|
||||||
<i class="el-icon">
|
<Icon name="ooui:previous-ltr"></Icon>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
|
</span>
|
||||||
<path
|
<span :class="['btn-page', page === index + 1 && 'active']" @click.stop="() => select(index + 1)" v-for="(_, index) in Math.ceil(totals / limit)">{{ index + 1 }}</span>
|
||||||
fill="currentColor"
|
<span class="btn-page next-page" @click.stop="() => handleNextPrev('+')" v-if="page < Math.ceil(totals / limit)">
|
||||||
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"
|
<Icon name="ooui:previous-rtl"></Icon>
|
||||||
></path>
|
</span>
|
||||||
</svg>
|
|
||||||
</i>
|
|
||||||
</a>
|
|
||||||
<a v-if="listArticleByCategory?.length > 0" :class="['btn-page', page === index + 1 && 'active']" @click.stop="() => select(index + 1)" v-for="(_, index) in Math.ceil(totals / limit)">{{ index + 1 }}</a>
|
|
||||||
<a class="btn-page next-page" @click.stop="() => handleNextPrev('+')" v-if="page < Math.ceil(totals / limit)">
|
|
||||||
<i class="el-icon">
|
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-html="designObject.styleClasses" style="display: none" v-if="designObject.styles"></div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -161,35 +146,9 @@ const mapActivesToItems = (index: number) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* gap: 10px; */
|
/* gap: 10px; */
|
||||||
overflow-x: scroll;
|
|
||||||
&.border-custom {
|
&.border-custom {
|
||||||
border-color: #e5e5e5 !important;
|
border-color: #e5e5e5 !important;
|
||||||
}
|
}
|
||||||
&.borderLeft {
|
|
||||||
border-left: 1px solid;
|
|
||||||
}
|
|
||||||
&.borderRight {
|
|
||||||
border-right: 1px solid;
|
|
||||||
}
|
|
||||||
&.borderTop {
|
|
||||||
border-top: 1px solid;
|
|
||||||
}
|
|
||||||
&.borderBottom {
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.empty {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-height: 50px;
|
|
||||||
background-color: #409eff;
|
|
||||||
display: flex;
|
|
||||||
white-space: normal;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
h6 {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.basic-article {
|
.basic-article {
|
||||||
&.article {
|
&.article {
|
||||||
@@ -198,9 +157,6 @@ const mapActivesToItems = (index: number) => {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.noData {
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -218,17 +174,21 @@ const mapActivesToItems = (index: number) => {
|
|||||||
.btn-page {
|
.btn-page {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
padding: 9px 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
border: 1px solid #409eff;
|
border-radius: 4px;
|
||||||
border-radius: 3px;
|
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: #f2f2f2;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
color: #222222;
|
||||||
&.active {
|
&.active {
|
||||||
background: #409eff;
|
background: #ed1c24;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
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";
|
||||||
import RecusiveSection from "@/components/dynamic-page/page-section/RecusiveSection.vue";
|
import RecusiveSection from "@/components/dynamic-page/page-section/RecusiveSection.vue";
|
||||||
import { getInputValue } from "@/utils/parseSQL";
|
import { getInputValue } from "@/utils/parseSQL";
|
||||||
import { enumPageSectionLayouts, enumPageSectionTemplate, enumPageSectionKey } from "~/definitions/enum";
|
import { enumPageSectionLayouts, enumPageSectionTemplate, enumPageSectionKey } from "~/definitions/enum";
|
||||||
@@ -92,6 +99,8 @@ function findElementPathById(categories: any[], targetId: number, path: any[] =
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(currentArticle.value ,'currentArticle')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -296,7 +305,8 @@ function findElementPathById(categories: any[], targetId: number, path: any[] =
|
|||||||
<p class="my-10px" v-if="currentArticle.intro" v-html="currentArticle.intro">
|
<p class="my-10px" v-if="currentArticle.intro" v-html="currentArticle.intro">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-html="currentArticle.detail" class="[&_p_>_span]:!font-raleway [&_p]:mb-10px"></div>
|
<!-- <div v-html="currentArticle.detail" class="[&_p_>_span]:!font-raleway [&_p]:mb-10px"></div> -->
|
||||||
|
<component :is="{ template: currentArticle.detail, components: { Poll, Quiz, Survey, Document, Attachment, Tag } }" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content__bottom__right">
|
<div class="content__bottom__right">
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import { enumPageComponentLayouts, enumPageComponentTemplate, enumPageComponentK
|
|||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="material-symbols:call-outline" /></span>
|
<span><Icon name="material-symbols:call-outline" /></span>
|
||||||
<span>024.39434341</span>
|
<span>0123456789</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="material-symbols:mail-outline" /></span>
|
<span><Icon name="material-symbols:mail-outline" /></span>
|
||||||
<span>toasoan@baotienphong.vn</span>
|
<span>toasoan@vpress.vn</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -42,19 +42,19 @@ import { enumPageComponentLayouts, enumPageComponentTemplate, enumPageComponentK
|
|||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="ic:baseline-facebook" /></span>
|
<span><Icon name="ic:baseline-facebook" /></span>
|
||||||
<span>facebook.com/baotienphong</span>
|
<span>facebook.com/vpress</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="uil:youtube" /></span>
|
<span><Icon name="uil:youtube" /></span>
|
||||||
<span>youtube.com/baotienphong</span>
|
<span>youtube.com/vpress</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="ic:baseline-tiktok" /></span>
|
<span><Icon name="ic:baseline-tiktok" /></span>
|
||||||
<span>tiktok.com/baotienphong</span>
|
<span>tiktok.com/vpress</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="arcticons:zalo" /></span>
|
<span><Icon name="arcticons:zalo" /></span>
|
||||||
<span>zalo.vn/baotienphong</span>
|
<span>zalo.vn/vpress</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,13 +68,13 @@ import { enumPageComponentLayouts, enumPageComponentTemplate, enumPageComponentK
|
|||||||
<div class="align-items-center">
|
<div class="align-items-center">
|
||||||
<span><Icon name="material-symbols:call-outline" /></span>
|
<span><Icon name="material-symbols:call-outline" /></span>
|
||||||
<span class="flex flex-column">
|
<span class="flex flex-column">
|
||||||
<span>024.39434340</span>
|
<span>0123456789 - </span>
|
||||||
<span>0909559988</span>
|
<span>0123456789</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span><Icon name="material-symbols:mail-outline" /></span>
|
<span><Icon name="material-symbols:mail-outline" /></span>
|
||||||
<span>kinhdoanh@baotienphong.vn</span>
|
<span>kinhdoanh@vpress.vn</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-ads-price">
|
<div class="button-ads-price">
|
||||||
<span><Icon name="ic:outline-format-list-bulleted" /></span>
|
<span><Icon name="ic:outline-format-list-bulleted" /></span>
|
||||||
@@ -96,23 +96,23 @@ import { enumPageComponentLayouts, enumPageComponentTemplate, enumPageComponentK
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer-bottomtab-relations w-1/2">
|
<div class="footer-bottomtab-relations w-1/2">
|
||||||
<img src="~/assets/images/tienphong/sinhvien-logo.png" alt="" />
|
<!-- <img src="~/assets/images/tienphong/sinhvien-logo.png" alt="" />
|
||||||
<img src="~/assets/images/tienphong/hht-online-logo.png" alt="" />
|
<img src="~/assets/images/tienphong/hht-online-logo.png" alt="" />
|
||||||
<img src="~/assets/images/tienphong/tamviet-logo.png" alt="" />
|
<img src="~/assets/images/tienphong/tamviet-logo.png" alt="" /> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-end footer-bottomtab-description">
|
<div class="flex justify-between items-end footer-bottomtab-description">
|
||||||
<div class="w-1/2 space-y-10px">
|
<div class="w-1/2 space-y-10px">
|
||||||
<p>© Bản quyền thuộc báo điện tử <span class="fw-bold">Tiền Phong</span></p>
|
<p>© Bản quyền thuộc báo điện tử <span class="fw-bold">....</span></p>
|
||||||
<p><span class="fw-bold">Tổng Biên tập</span>: LÊ XUÂN SƠN</p>
|
<p><span class="fw-bold">Tổng Biên tập</span>: ...</p>
|
||||||
<p>Tòa soạn: 15 Hồ Xuân Hương, Hà Nội - Điện thoại: 024.39431250</p>
|
<p>Tòa soạn: Hà Nội - Điện thoại: 0123456789</p>
|
||||||
<p>Email: <span class="fw-bold">online.baotienphong@gmail.com</span> - Hotline: <span class="fw-bold">0865.015.015 - 0977.456.112</span></p>
|
<p>Email: <span class="fw-bold">online.vpress@gmail.com</span> - Hotline: <span class="fw-bold">0123456789</span></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-1/2 space-y-10px">
|
<div class="w-1/2 space-y-10px">
|
||||||
<p>Giấy phép số <span class="fw-bold">76/GP-BTTTT</span>, cấp ngày 26/02/2020.</p>
|
<p>Giấy phép số <span class="fw-bold">...</span>, cấp ngày ....</p>
|
||||||
<p>Cơ quan chủ quản: <span class="fw-bold">Trung ương Đoàn TNCS Hồ Chí Minh</span></p>
|
<p>Cơ quan chủ quản: <span class="fw-bold">....</span></p>
|
||||||
<p>Cấm sao chép dưới mọi hình thức nếu không có sự chấp thuận bằng văn bản</p>
|
<p>Cấm sao chép dưới mọi hình thức nếu không có sự chấp thuận bằng văn bản</p>
|
||||||
<p>Powered by Hemera Media</p>
|
<p>Powered by GCT</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ onMounted(() => {
|
|||||||
<div>
|
<div>
|
||||||
<div class="text-white text-12px">
|
<div class="text-white text-12px">
|
||||||
<span>HOTLINE: </span>
|
<span>HOTLINE: </span>
|
||||||
<a href="tel:0865015015"> 0865.015.015</a>
|
<a href="tel:0865015015"> 0123456789</a>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
<a href="tel:0977456112">0977.456.112</a>
|
<a href="tel:0977456112">0123456789</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@@ -41,9 +41,9 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="main-header-control">
|
<div class="main-header-control">
|
||||||
<div class="main-header-relations">
|
<div class="main-header-relations">
|
||||||
<img src="~/assets/images/tienphong/sinhvien-logo.png" alt="">
|
<!-- <img src="~/assets/images/tienphong/sinhvien-logo.png" alt="">
|
||||||
<img src="~/assets/images/tienphong/hht-online-logo.png" alt="">
|
<img src="~/assets/images/tienphong/hht-online-logo.png" alt="">
|
||||||
<img src="~/assets/images/tienphong/tamviet-logo.png" alt="">
|
<img src="~/assets/images/tienphong/tamviet-logo.png" alt=""> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="main-header-navbar">
|
<div class="main-header-navbar">
|
||||||
<AssignComponent :type="enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.NAVIGATION]['TOP']}`]['NAVIGATION_TOP_DEFAULT']" />
|
<AssignComponent :type="enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.NAVIGATION]['TOP']}`]['NAVIGATION_TOP_DEFAULT']" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
SCRIPT_SRC?: any,
|
SCRIPT_SRC?: any,
|
||||||
CONTAINER_ID?: any,
|
CONTAINER_ID?: any,
|
||||||
options?: any,
|
options?: any,
|
||||||
|
inside?: boolean,
|
||||||
widgetKey?: any
|
widgetKey?: any
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@@ -48,7 +48,10 @@
|
|||||||
script.async = true;
|
script.async = true;
|
||||||
script.src = props.SCRIPT_SRC;
|
script.src = props.SCRIPT_SRC;
|
||||||
script.onload = onload;
|
script.onload = onload;
|
||||||
document.getElementsByTagName('head')[0].appendChild(script);
|
if (props.inside) document.getElementById(props.CONTAINER_ID) && document.getElementById(props.CONTAINER_ID).appendChild(script);
|
||||||
|
else {
|
||||||
|
document.getElementsByTagName('body')[0].appendChild(script);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const initWidget = (key: any) => {
|
const initWidget = (key: any) => {
|
||||||
if (typeof widgets[key].key === 'undefined') {
|
if (typeof widgets[key].key === 'undefined') {
|
||||||
@@ -60,16 +63,18 @@
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await Object.assign(widgets, {
|
await Object.assign(widgets, {
|
||||||
FireAnt: {
|
FireAnt: {
|
||||||
script: () => new window.FireAnt.MarketsWidget(Object.assign({ container_id: props.CONTAINER_ID }, props.options)),
|
script: () => new window.FireAnt.MarketsWidget({ container_id: props.CONTAINER_ID, ...props.options }),
|
||||||
key: window.FireAnt
|
key: window.FireAnt
|
||||||
}})
|
},
|
||||||
|
TradingView: {
|
||||||
|
script: () => new window.TradingView.widget({ container_id: props.CONTAINER_ID, ...props.options }),
|
||||||
|
key: window.TradingView
|
||||||
|
}
|
||||||
|
})
|
||||||
appendScript(initWidget(props.widgetKey));
|
appendScript(initWidget(props.widgetKey));
|
||||||
// instance.proxy.$forceUpdate();
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ClientOnly>
|
|
||||||
<div :key="props.CONTAINER_ID" :id="props.CONTAINER_ID"></div>
|
<div :key="props.CONTAINER_ID" :id="props.CONTAINER_ID"></div>
|
||||||
</ClientOnly>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// <div class="tradingview-widget-container">
|
||||||
|
// <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-ticker-tape.js" async>
|
||||||
|
// {
|
||||||
|
// "symbols": [
|
||||||
|
// {
|
||||||
|
// "proName": "FOREXCOM:SPXUSD",
|
||||||
|
// "title": "S&P 500 Index"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "proName": "FOREXCOM:NSXUSD",
|
||||||
|
// "title": "US 100 Cash CFD"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "proName": "FX_IDC:EURUSD",
|
||||||
|
// "title": "EUR to USD"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "proName": "BITSTAMP:BTCUSD",
|
||||||
|
// "title": "Bitcoin"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "proName": "BITSTAMP:ETHUSD",
|
||||||
|
// "title": "Ethereum"
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "showSymbolLogo": true,
|
||||||
|
// "isTransparent": false,
|
||||||
|
// "displayMode": "adaptive",
|
||||||
|
// "colorTheme": "dark",
|
||||||
|
// "locale": "en"
|
||||||
|
// }
|
||||||
|
// </script>
|
||||||
|
// </div>
|
||||||
@@ -244,13 +244,13 @@ export const pageComponentLayouts = {
|
|||||||
{ title: "Thẻ bài viết Video Hightlight", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_CARD']}`]['CARD_VIDEO_HIGHLIGHT'] },
|
{ title: "Thẻ bài viết Video Hightlight", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_CARD']}`]['CARD_VIDEO_HIGHLIGHT'] },
|
||||||
{ title: "Thẻ bài viết Hoa hậu Hightlight", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_CARD']}`]['CARD_MISS_HIGHLIGHT'] },
|
{ title: "Thẻ bài viết Hoa hậu Hightlight", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_CARD']}`]['CARD_MISS_HIGHLIGHT'] },
|
||||||
],
|
],
|
||||||
[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]: [
|
[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]: [
|
||||||
{ title: "Chi tiết bài viết", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_GENERAL'] },
|
{ title: "Chi tiết bài viết", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_GENERAL'] },
|
||||||
{ title: "Chi tiết bài Podcast", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_PODCAST'] },
|
{ title: "Chi tiết bài Podcast", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_PODCAST'] },
|
||||||
{ title: "Chi tiết bài Video", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_VIDEO'] },
|
{ title: "Chi tiết bài Video", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_VIDEO'] },
|
||||||
{ title: "Chi tiết bài Image", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_IMAGE'] },
|
{ title: "Chi tiết bài Image", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_IMAGE'] },
|
||||||
{ title: "Chi tiết bài eMagazine", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_EMAGAZINE'] },
|
{ title: "Chi tiết bài eMagazine", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_EMAGAZINE'] },
|
||||||
{ title: "Chi tiết bài Inforgraphic", value: enumPageComponentLayouts[enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']]['DETAIL_INFOGRAPHIC'] },
|
{ title: "Chi tiết bài Inforgraphic", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.ARTICLE]['ARTICLE_DETAIL']}`]['DETAIL_INFOGRAPHIC'] },
|
||||||
],
|
],
|
||||||
/* NAVIGATION */
|
/* NAVIGATION */
|
||||||
[`${enumPageComponentTemplate[enumPageComponentKey.NAVIGATION]['TOP']}`]: [
|
[`${enumPageComponentTemplate[enumPageComponentKey.NAVIGATION]['TOP']}`]: [
|
||||||
@@ -294,6 +294,7 @@ export const pageComponentLayouts = {
|
|||||||
{ title: "Thời tiết", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['WEATHER']}`]['WEATHER_DEFAULT'] }
|
{ title: "Thời tiết", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['WEATHER']}`]['WEATHER_DEFAULT'] }
|
||||||
],
|
],
|
||||||
[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]: [
|
[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]: [
|
||||||
{ title: "Chứng khoán", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]['STOCK_DEFAULT'] }
|
{ title: "Chứng khoán", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]['STOCK_DEFAULT'] },
|
||||||
|
{ title: "Chứng khoán Full Size", value: enumPageComponentLayouts[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]['STOCK_FULLSIZE'] }
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -382,6 +382,7 @@ export const enumPageComponentLayouts = {
|
|||||||
},
|
},
|
||||||
[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]: {
|
[`${enumPageComponentTemplate[enumPageComponentKey.OTHER]['STOCK']}`]: {
|
||||||
'STOCK_DEFAULT': "TYPE:Stock_Default",
|
'STOCK_DEFAULT': "TYPE:Stock_Default",
|
||||||
|
'STOCK_FULLSIZE': "TYPE:Stock_Fullsize",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
"@vueuse/nuxt": "10.5.0",
|
"@vueuse/nuxt": "10.5.0",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.5.1",
|
||||||
"cheerio": "^1.0.0-rc.12",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
|
"nanoid": "^5.0.7",
|
||||||
"nuxt-delay-hydration": "latest",
|
"nuxt-delay-hydration": "latest",
|
||||||
"sass": "latest",
|
"sass": "latest",
|
||||||
"sass-loader": "latest",
|
"sass-loader": "latest",
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ interface Page extends Base {
|
|||||||
sections?: PageSection[];
|
sections?: PageSection[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDynamicPageByCode = async (event : any) => {
|
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;
|
||||||
@@ -112,7 +112,7 @@ export const getDynamicPageByCode = async (event : any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDynamicPageById = async (event : any) => {
|
export const getDynamicPageById = async (event: any) => {
|
||||||
try {
|
try {
|
||||||
const { apiUrl } = useRuntimeConfig().public
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
const id = event.context.params.id;
|
const id = event.context.params.id;
|
||||||
@@ -122,3 +122,18 @@ export const getDynamicPageById = async (event : any) => {
|
|||||||
handleError(error);
|
handleError(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export async function getOverviewPageComponentById(event: any) {
|
||||||
|
try {
|
||||||
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
|
const { componentId, dataQuery } = getQuery(event)
|
||||||
|
return await $fetch(`${apiUrl}/cms/overview-page-component/${componentId}`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: dataQuery,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
handleError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,6 +60,23 @@ export const useDynamicPageStore = defineStore("dynamicPageStore", () => {
|
|||||||
} catch (error: any) {}
|
} catch (error: any) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getOverviewPageComponentById(componentId, dataQuery) {
|
||||||
|
try {
|
||||||
|
const { apiUrl } = useRuntimeConfig().public
|
||||||
|
const res = await $fetch(`${apiUrl}/cms/page-component/overview-page-component/${componentId}`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(dataQuery),
|
||||||
|
});
|
||||||
|
return res
|
||||||
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentPage,
|
currentPage,
|
||||||
sectionPublished,
|
sectionPublished,
|
||||||
@@ -69,6 +86,7 @@ export const useDynamicPageStore = defineStore("dynamicPageStore", () => {
|
|||||||
setSectionPublished,
|
setSectionPublished,
|
||||||
setComponentPublished,
|
setComponentPublished,
|
||||||
setDataQuery,
|
setDataQuery,
|
||||||
|
getOverviewPageComponentById
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+12
-20
@@ -1,27 +1,19 @@
|
|||||||
import * as cherrio from 'cheerio'
|
import * as cherrio from 'cheerio'
|
||||||
|
|
||||||
const getResource = (data: any) => {
|
const getResource = (key: any, data: any) => {
|
||||||
// const result = {
|
const $ = cherrio.load(`<div class="">${data}</div>`)
|
||||||
// videoHightlight: null,
|
let result = null;
|
||||||
// imageHightlight: null,
|
switch (key) {
|
||||||
// resources: [],
|
case 'HIGHLIGHT_VIDEO':
|
||||||
// };
|
result = $('video').first().parent().html();
|
||||||
// const $ = cherrio.load(`<div class="get-resource">${data}</div>`)
|
break;
|
||||||
// const html : any = $('.get-resource').html();
|
default:
|
||||||
// html.find('video, figure img, img').each((index : any, element: any) => {
|
result = $.html();
|
||||||
// // if (index === 0) result.videoHightlight =
|
}
|
||||||
// });
|
console.log(result)
|
||||||
|
return result;
|
||||||
// console.log(html)
|
|
||||||
|
|
||||||
// <div>
|
|
||||||
// <video controls="controls" width="100%" height="auto" data-id="578" data-resource="https://resource.vpress.vn/resources/1/private/13cee27a2bd93915479f049378cffdd3/video/28thi-tot-nghiep-ptth-2024-1719829616.mp4" data-title="28thi-tot-nghiep-ptth-2024">
|
|
||||||
// <source src="https://resource.vpress.vn/resources/1/private/13cee27a2bd93915479f049378cffdd3/video/28thi-tot-nghiep-ptth-2024-1719829616.mp4" type="video/mp4">
|
|
||||||
// </video>
|
|
||||||
// </div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getResource
|
getResource
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user