|
@@ -0,0 +1,372 @@
|
|
|
+import {
|
|
|
+ NBreadcrumb,
|
|
|
+ NBreadcrumbItem,
|
|
|
+ NButton,
|
|
|
+ NImage,
|
|
|
+ NSlider,
|
|
|
+ NSpace,
|
|
|
+ NSpin
|
|
|
+} from 'naive-ui';
|
|
|
+import { computed, defineComponent, onMounted, reactive, watch } from 'vue';
|
|
|
+import styles from './detail.module.less';
|
|
|
+import icon_back from '../../../xiaoku-music/images/icon_back.png';
|
|
|
+import icon_arrow from '../../../xiaoku-music/images/icon_arrow.png';
|
|
|
+import icon_play from '../../../xiaoku-music/images/icon_play.png';
|
|
|
+import icon_pause from '../../../xiaoku-music/images/icon_pause.png';
|
|
|
+import icon_default from '../../../xiaoku-music/images/icon_default.png';
|
|
|
+import icon_separator from '../../../xiaoku-music/images/icon_separator.png';
|
|
|
+import iconT from '/src/views/content-information/images/icon-t.png';
|
|
|
+import iconAddT from '/src/views/content-information/images/icon-add-t.png';
|
|
|
+import iconPlusT from '/src/views/content-information/images/icon-plus-t.png';
|
|
|
+import musicBg from '../../../xiaoku-music/images/icon_default.png';
|
|
|
+import iconPan from '/src/views/content-information/images/icon-pan.png';
|
|
|
+import { useRoute, useRouter } from 'vue-router';
|
|
|
+import PlayLoading from '../../../xiaoku-music/component/play-loading';
|
|
|
+import TheNoticeBar from '/src/components/TheNoticeBar';
|
|
|
+import TheEmpty from '/src/components/TheEmpty';
|
|
|
+import PlayItem from '../../../xiaoku-music/component/play-item';
|
|
|
+import { api_knowledgeWiki_detail } from '/src/views/content-information/api';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'music-detail',
|
|
|
+ props: {
|
|
|
+ id: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ type: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ activeStatus: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ contentType: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ setup(props, { expose }) {
|
|
|
+ const route = useRoute();
|
|
|
+ const data = reactive({
|
|
|
+ loading: false,
|
|
|
+ finshed: false,
|
|
|
+ reshing: false,
|
|
|
+ details: {} as any,
|
|
|
+ list: [] as any,
|
|
|
+ listActive: 0,
|
|
|
+ playState: 'pause' as 'play' | 'pause',
|
|
|
+ showPlayer: false,
|
|
|
+ showPreivew: false,
|
|
|
+ previewUrl: '',
|
|
|
+ showCloseBtn: true,
|
|
|
+ fontSize: 18 // 默认18
|
|
|
+ });
|
|
|
+
|
|
|
+ /** 选中的item */
|
|
|
+ const activeItem = computed(() => {
|
|
|
+ return data.list[data.listActive] || {};
|
|
|
+ });
|
|
|
+
|
|
|
+ /** 播放曲目 */
|
|
|
+ const handlePlay = (item: any) => {
|
|
|
+ const index = data.list.findIndex((_item: any) => _item.id === item.id);
|
|
|
+ if (index > -1) {
|
|
|
+ if (data.listActive === index) {
|
|
|
+ data.playState = data.playState === 'play' ? 'pause' : 'play';
|
|
|
+ } else {
|
|
|
+ data.playState = 'play';
|
|
|
+ }
|
|
|
+ data.showPlayer = true;
|
|
|
+ data.listActive = index;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 音频控制 */
|
|
|
+ const handleChangeAudio = (
|
|
|
+ type: 'play' | 'pause' | 'pre' | 'next' | 'favitor'
|
|
|
+ ) => {
|
|
|
+ if (type === 'play') {
|
|
|
+ data.playState = 'play';
|
|
|
+ } else if (type === 'pause') {
|
|
|
+ data.playState = 'pause';
|
|
|
+ } else if (type === 'pre') {
|
|
|
+ if (data.list[data.listActive - 1]) {
|
|
|
+ handlePlay(data.list[data.listActive - 1]);
|
|
|
+ }
|
|
|
+ } else if (type === 'next') {
|
|
|
+ if (data.list[data.listActive + 1]) {
|
|
|
+ handlePlay(data.list[data.listActive + 1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const getDetail = async () => {
|
|
|
+ data.loading = true;
|
|
|
+ let res = {} as any;
|
|
|
+ try {
|
|
|
+ res = await api_knowledgeWiki_detail({
|
|
|
+ id: props.id || route.query.id
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error);
|
|
|
+ }
|
|
|
+ if (data.reshing) {
|
|
|
+ data.list = [];
|
|
|
+ data.reshing = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ data.finshed = true;
|
|
|
+ try {
|
|
|
+ data.list = res.data?.knowledgeWikiResources || [];
|
|
|
+ data.list.forEach((item: any) => {
|
|
|
+ item.audioFileUrl = item.url;
|
|
|
+ item.musicSheetName = item.name;
|
|
|
+ });
|
|
|
+ const knowledgeWikiCategories = res.data?.knowledgeWikiCategories || [];
|
|
|
+ res.data.knowledgeName =
|
|
|
+ knowledgeWikiCategories.length > 0
|
|
|
+ ? knowledgeWikiCategories[0].name
|
|
|
+ : '';
|
|
|
+ res.data.intros = res.data.intros.replace(
|
|
|
+ /<video/gi,
|
|
|
+ '<video class="video-music" style="width: 100% !important;" controlslist="nodownload"'
|
|
|
+ );
|
|
|
+ data.details = res.data;
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+
|
|
|
+ data.loading = false;
|
|
|
+ };
|
|
|
+
|
|
|
+ const onStopAll = (type: 'play' | 'pause' | 'pre' | 'next' | 'favitor') => {
|
|
|
+ handleChangeAudio(type);
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 暂停视频
|
|
|
+ const doms = document.querySelectorAll('.video-music');
|
|
|
+ if (doms && doms.length > 0) {
|
|
|
+ doms.forEach((dom: any) => {
|
|
|
+ dom.pause();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ getDetail();
|
|
|
+ });
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.activeStatus,
|
|
|
+ () => {
|
|
|
+ if (!props.activeStatus) {
|
|
|
+ onStopAll('pause');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ expose({
|
|
|
+ handleChangeAudio: onStopAll
|
|
|
+ });
|
|
|
+ return () => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.container,
|
|
|
+ props.type === 'preview' && styles.containerPreview,
|
|
|
+ props.type === 'modal' && styles.containerModal
|
|
|
+ ]}>
|
|
|
+ <div class={[styles.wrap, data.showPlayer ? styles.wrapBottom : '']}>
|
|
|
+ <div class={styles.content}>
|
|
|
+ <div class={styles.contentWrap}>
|
|
|
+ <div class={[styles.musicList, 'musicList-container']}>
|
|
|
+ <div class={styles.wrapList}>
|
|
|
+ <div class={styles.musicInfo}>
|
|
|
+ <div class={styles.musicImg}>
|
|
|
+ <img
|
|
|
+ src={data.details?.avatar || musicBg}
|
|
|
+ class={styles.img}
|
|
|
+ />
|
|
|
+ <div class={styles.panSection}>
|
|
|
+ <img src={iconPan} class={styles.iconPan} />
|
|
|
+ <img
|
|
|
+ src={data.details?.avatar || musicBg}
|
|
|
+ class={styles.img2}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.info}>
|
|
|
+ <div class={styles.name}>
|
|
|
+ <TheNoticeBar
|
|
|
+ text={data.details.name}
|
|
|
+ style={{ marginRight: '0' }}
|
|
|
+ />
|
|
|
+ {/* {data.details.name} */}
|
|
|
+ </div>
|
|
|
+ <div class={styles.c}>
|
|
|
+ {data.details.composers ? (
|
|
|
+ <div>
|
|
|
+ <span>作曲:</span>
|
|
|
+ <TheNoticeBar
|
|
|
+ text={data.details.composers}
|
|
|
+ style={{ marginRight: '0' }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ ''
|
|
|
+ )}
|
|
|
+ {data.details.lyricists ? (
|
|
|
+ <div>
|
|
|
+ <span>作词:</span>
|
|
|
+ <TheNoticeBar
|
|
|
+ text={data.details.lyricists}
|
|
|
+ style={{ marginRight: '0' }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ ''
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.titlec}>
|
|
|
+ <i class={styles.icon2}></i>名曲鉴赏
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {data.list.map((item: any, index: any) => {
|
|
|
+ return (
|
|
|
+ <div class={styles.itemContainer}>
|
|
|
+ <div
|
|
|
+ class={[styles.item]}
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ handlePlay(item);
|
|
|
+ }}>
|
|
|
+ <div class={styles.img}>
|
|
|
+ <NImage
|
|
|
+ lazy
|
|
|
+ objectFit="cover"
|
|
|
+ previewDisabled={true}
|
|
|
+ src={item.titleImg || icon_default}
|
|
|
+ onLoad={e => {
|
|
|
+ (e.target as any).dataset.loaded = 'true';
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <PlayLoading
|
|
|
+ class={[
|
|
|
+ data.listActive === index &&
|
|
|
+ data.playState === 'play'
|
|
|
+ ? ''
|
|
|
+ : styles.showPlayLoading
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class={styles.title}>
|
|
|
+ <div class={styles.titleName}>
|
|
|
+ <TheNoticeBar
|
|
|
+ text={item.name}
|
|
|
+ style={{ marginRight: '12px' }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <NButton
|
|
|
+ color="#259CFE"
|
|
|
+ textColor="#fff"
|
|
|
+ round
|
|
|
+ class={styles.btn}
|
|
|
+ type="primary"
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ handlePlay(item);
|
|
|
+ }}>
|
|
|
+ 播放
|
|
|
+ <img
|
|
|
+ src={
|
|
|
+ data.listActive === index &&
|
|
|
+ data.playState === 'play'
|
|
|
+ ? icon_pause
|
|
|
+ : icon_play
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </NButton>
|
|
|
+
|
|
|
+ <img class={styles.arrow} src={icon_arrow} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ {!data.finshed && (
|
|
|
+ <div class={styles.loadingWrap}>
|
|
|
+ <NSpin show={true}></NSpin>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ {!data.loading && data.list.length === 0 && (
|
|
|
+ <div class={styles.empty}>
|
|
|
+ <TheEmpty
|
|
|
+ description="暂无名曲鉴赏"
|
|
|
+ style={{ paddingTop: '0px' }}></TheEmpty>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.musicStaff}>
|
|
|
+ <div class={styles.musicTitle}>
|
|
|
+ <i class={styles.icon1}></i>名曲故事
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class={styles.musicContent}
|
|
|
+ v-html={data.details?.intros}
|
|
|
+ style={{ fontSize: data.fontSize + 'px' }}></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.changeSizeSection}>
|
|
|
+ <img src={iconT} class={styles.iconT} />
|
|
|
+ <img
|
|
|
+ src={iconAddT}
|
|
|
+ class={styles.iconAddT}
|
|
|
+ onClick={() => {
|
|
|
+ if (data.fontSize >= 32) return;
|
|
|
+ data.fontSize += 1;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <NSlider
|
|
|
+ v-model:value={data.fontSize}
|
|
|
+ placement="left"
|
|
|
+ vertical
|
|
|
+ min={12}
|
|
|
+ max={32}
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ src={iconPlusT}
|
|
|
+ class={styles.iconPlusT}
|
|
|
+ onClick={() => {
|
|
|
+ if (data.fontSize <= 12) return;
|
|
|
+ data.fontSize -= 1;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {data.list.length !== 0 && (
|
|
|
+ <PlayItem
|
|
|
+ type={props.type}
|
|
|
+ show={data.showPlayer}
|
|
|
+ playState={data.playState}
|
|
|
+ item={activeItem.value}
|
|
|
+ onChange={value => handleChangeAudio(value)}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|