Fix
This commit is contained in:
@@ -1,93 +1,254 @@
|
||||
<script setup lang="ts">
|
||||
import { useArticleStore } from "~/stores/articles";
|
||||
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";
|
||||
const { currentArticle } = storeToRefs(useArticleStore());
|
||||
import { useDynamicPageStore } from "~/stores/dynamic-page";
|
||||
import { useCategoryStore } from "~/stores/category";
|
||||
|
||||
const store = reactive({
|
||||
dynamicPage: useDynamicPageStore(),
|
||||
article: useArticleStore(),
|
||||
category: useCategoryStore(),
|
||||
});
|
||||
|
||||
const { categoryTree } = storeToRefs(store.category);
|
||||
|
||||
await store.category.fetchBySiteId();
|
||||
const currentCategoryTree = (store.category.currentCategoryTree = findElementPathById(categoryTree.value, currentArticle.value.categoryId));
|
||||
function findElementPathById(categories: any[], targetId: number, path: any[] = []) {
|
||||
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;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
clickElement("figure", "custom-figure", "data-code");
|
||||
clickElement("author", "author", "data-code");
|
||||
|
||||
let detailEmagazine = document.querySelector('div[layout="ARTICLE_DETAIL_EMAGAZINE"]');
|
||||
let breadcrumb = document.querySelector('div[layout="BREADCRUM_DEFAULT"]');
|
||||
if (detailEmagazine && breadcrumb) {
|
||||
breadcrumb.classList.add("lg:max-w-640px", "mx-auto");
|
||||
}
|
||||
});
|
||||
|
||||
function clickElement(type: string, selector: string, attribute: string) {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
elements.forEach((element) => {
|
||||
element.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
const url = `${window.location.protocol}//${window.location.host}/${type}/${element.getAttribute(attribute)}`;
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
const getSrc = (htmlString: string) => {
|
||||
const srcRegex = /src="([^"]+)"/;
|
||||
return htmlString?.match(srcRegex);
|
||||
};
|
||||
|
||||
const isMoreControl = ref(false);
|
||||
const isPlayed = ref(true);
|
||||
const isVolume = ref(true);
|
||||
const speedList = ref<{ [key: number]: string }>({
|
||||
1: "0.5x",
|
||||
2: "0.75x",
|
||||
3: "1.0x",
|
||||
4: "1.25x",
|
||||
5: "1.50x",
|
||||
});
|
||||
const speedIndexDefault = ref(3);
|
||||
const speedDefault = ref(speedList.value[speedIndexDefault.value]);
|
||||
const volume = ref(1.0);
|
||||
const audioPlayer = ref<HTMLAudioElement | null>(null);
|
||||
const currentTime = ref(0);
|
||||
const duration = ref(0);
|
||||
|
||||
function setUpVolums() {
|
||||
isVolume.value = !isVolume.value;
|
||||
if (audioPlayer.value) {
|
||||
if (isVolume.value) {
|
||||
audioPlayer.value.volume = 1;
|
||||
} else {
|
||||
audioPlayer.value.volume = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updateVolume = (num?: number) => {
|
||||
if (audioPlayer.value) {
|
||||
if(num) {
|
||||
volume.value += num
|
||||
}
|
||||
// console.log('1231321')
|
||||
audioPlayer.value.volume = volume.value;
|
||||
}
|
||||
};
|
||||
|
||||
function chanageSpeed() {
|
||||
if (speedIndexDefault.value < 5) {
|
||||
speedIndexDefault.value += 1;
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.playbackRate += 0.25;
|
||||
}
|
||||
speedDefault.value = speedList.value[speedIndexDefault.value];
|
||||
} else {
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.playbackRate = 0.5;
|
||||
}
|
||||
speedIndexDefault.value = 1;
|
||||
speedDefault.value = speedList.value[1];
|
||||
}
|
||||
}
|
||||
|
||||
function togglePlayer() {
|
||||
isPlayed.value = !isPlayed.value;
|
||||
if (audioPlayer.value) {
|
||||
if (isPlayed.value) {
|
||||
audioPlayer.value.pause();
|
||||
} else {
|
||||
audioPlayer.value.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replayAndForward(time: number) {
|
||||
if (audioPlayer.value) {
|
||||
if (audioPlayer.value.currentTime == audioPlayer.value.duration) {
|
||||
isPlayed.value = true;
|
||||
} else {
|
||||
audioPlayer.value.currentTime = audioPlayer.value.currentTime + time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const seekToTime = () => {
|
||||
if (audioPlayer.value) {
|
||||
audioPlayer.value.currentTime = currentTime.value;
|
||||
}
|
||||
};
|
||||
|
||||
const updateCurrentTime = () => {
|
||||
if (audioPlayer.value) {
|
||||
currentTime.value = audioPlayer.value.currentTime;
|
||||
}
|
||||
};
|
||||
|
||||
const updateDuration = () => {
|
||||
if (audioPlayer.value) {
|
||||
duration.value = audioPlayer.value.duration;
|
||||
}
|
||||
};
|
||||
|
||||
const currrentTimeComputed = computed(() => {
|
||||
return utils.formattedTime(currentTime.value);
|
||||
});
|
||||
|
||||
const durationComputed = computed(() => {
|
||||
return utils.formattedTime(duration.value);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="podcast__wrapper overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="podcast"
|
||||
>
|
||||
<p
|
||||
class="podcast__content__time"
|
||||
>
|
||||
Ngày tạo podcast
|
||||
<div class="lg:p-40px md:p-30px p-5 border-1px border-solid border-black/10 rounded-8px">
|
||||
<div class="flex md:flex-row flex-col md:gap-6 gap-2 justify-between mb-10px">
|
||||
<p class="text-#9f9f9f text-14px mb-2 md:hidden block text-center">
|
||||
{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}
|
||||
</p>
|
||||
<figure><img src="http://picsum.photos/1024/600?random=1'" alt="Ảnh podcast" title="Ảnh podcast" /></figure>
|
||||
<div
|
||||
class="podcast__content"
|
||||
>
|
||||
<p
|
||||
class="podcast__content__time"
|
||||
>
|
||||
Ngày tạo podcast
|
||||
</p>
|
||||
<h1 class="podcast__content__title">Tiêu đề podcast</h1>
|
||||
<p
|
||||
class="podcast__content__text"
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
<figure class="!w-auto"><img class="w-150px h-150px rounded-8px shadow-md cursor-pointer" :src="currentArticle?.thumbnail" alt="Ảnh podcast" title="Ảnh podcast" /></figure>
|
||||
<div class="flex-1 text-#222 m-0 md:text-left text-center">
|
||||
<p class="text-#9f9f9f text-14px mb-2 md:block hidden">
|
||||
{{ utils.dateFormat(currentArticle?.publishedOn, "dddd, DD/MM/YYYY - HH:mm") }}
|
||||
</p>
|
||||
<h1 class="text-24px md:mb-4 mb-2 font-bold" v-html="currentArticle?.title"></h1>
|
||||
<p class="hidden md:line-clamp-3" v-html="currentArticle?.intro"></p>
|
||||
</div>
|
||||
|
||||
<ul
|
||||
class="buttons"
|
||||
>
|
||||
<li><Icon name="mdi:bookmark-outline" /></li>
|
||||
<li><Icon name="material-symbols:mode-comment-outline" /></li>
|
||||
<ul class="items-start gap-2 m-0 p-0 md:flex hidden">
|
||||
<li class="w-9 h-9 bg-white border-1 border-solid border-[rgb(229, 231, 235)] cursor-pointer shadow-md rounded-50px relative hover:bg-primary-100 hover:text-primary-600">
|
||||
<Icon class="text-18px absolute top-50% left-50% translate-x--50% translate-y--50%" name="mdi:bookmark-outline" />
|
||||
</li>
|
||||
<li class="w-9 h-9 bg-white border-1 border-solid border-[rgb(229, 231, 235)] cursor-pointer shadow-md rounded-50px relative hover:bg-primary-100 hover:text-primary-600">
|
||||
<Icon class="text-18px absolute top-50% left-50% translate-x--50% translate-y--50%" name="material-symbols:mode-comment-outline" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="playlist">
|
||||
<div class="playlist__time">
|
||||
<span>5:00</span>
|
||||
<span>10:00</span>
|
||||
<audio :src="getSrc(currentArticle?.detail)?.[1]" preload="auto" ref="audioPlayer" @timeupdate="updateCurrentTime" @loadedmetadata="updateDuration" />
|
||||
<div class="p-2">
|
||||
<input class="w-full accent-primary-600 cursor-pointer" type="range" v-model="currentTime" @input="seekToTime" :max="duration" />
|
||||
<div class="flex justify-between">
|
||||
<span>{{ currrentTimeComputed }}</span>
|
||||
<span>{{ durationComputed }}</span>
|
||||
</div>
|
||||
<div class="playlist__buttons">
|
||||
<div class="playlist__buttons__left">
|
||||
<div
|
||||
class="button__prev"
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="md:w-150px text-left">
|
||||
<div class="text-28px text-primary-600 md:hidden block">
|
||||
<Icon name="material-symbols:skip-previous" />
|
||||
</div>
|
||||
<div
|
||||
class="sound"
|
||||
>
|
||||
<Icon name="material-symbols:volume-mute"></Icon>
|
||||
<div></div>
|
||||
<Icon name="material-symbols:volume-up"></Icon>
|
||||
<div class="md:inline-flex hidden items-center gap-2 ml--10px h9 text-primary-600 rounded-8px text-28px cursor-pointer hover:bg-primary-100">
|
||||
<Icon @click="updateVolume(-0.1)" name="material-symbols:volume-mute"></Icon>
|
||||
<input v-if="isVolume" class="accent-primary-600 h-1 w-12 lg:w-20 cursor-pointer" type="range" v-model="volume" @input="updateVolume()" min="0.1" max="1" step="0.1" />
|
||||
<Icon @click="updateVolume(0.1)" name="material-symbols:volume-up"></Icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="play">
|
||||
<Icon name="fluent:skip-back-10-48-filled" />
|
||||
<Icon name="material-symbols:play-arrow" class="button" />
|
||||
<Icon name="fluent:skip-forward-10-48-filled" />
|
||||
<div class="flex items-center justify-center gap-4 flex-1 text-28px text-primary-600">
|
||||
<Icon @click="replayAndForward(-10)" name="fluent:skip-back-10-48-filled" />
|
||||
<button @click="togglePlayer" class="bg-transparent">
|
||||
<Icon v-if="isPlayed" name="material-symbols:play-arrow-rounded" class="text-64px" />
|
||||
<Icon v-if="!isPlayed" name="material-symbols:pause" class="text-64px" />
|
||||
</button>
|
||||
|
||||
<Icon @click="replayAndForward(10)" name="fluent:skip-forward-10-48-filled" />
|
||||
</div>
|
||||
|
||||
<div class="playlist__buttons__right">
|
||||
<div
|
||||
class="button__next"
|
||||
>
|
||||
<div class="md:w-150px text-right">
|
||||
<div class="text-28px text-primary-600 md:hidden block">
|
||||
<Icon name="material-symbols:skip-next" />
|
||||
</div>
|
||||
<div
|
||||
class="speed"
|
||||
>
|
||||
<span>Tốc độ phát: </span>
|
||||
<strong>1x</strong>
|
||||
<div class="text-14px text-primary-600 md:block hidden cursor-pointer" @click="chanageSpeed">
|
||||
<span class="font-300">Tốc độ phát: </span>
|
||||
<strong class="font-bold text-20px ml-1">{{ speedDefault }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="podcast__content__text"
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
<p class="md:hidden block" v-html="currentArticle?.intro"></p>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user