|
@@ -0,0 +1,225 @@
|
|
|
+import {
|
|
|
+ PropType,
|
|
|
+ Transition,
|
|
|
+ computed,
|
|
|
+ defineComponent,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ watch
|
|
|
+} from 'vue';
|
|
|
+import styles from './index.module.scss';
|
|
|
+import { NButton, NImage, NProgress, NSlider } from 'naive-ui';
|
|
|
+// import { IMusicItem } from '../../type';
|
|
|
+import icon_pre from '../../img/cloudPractice/icon_pre.png';
|
|
|
+import icon_next from '../../img/cloudPractice/icon_next.png';
|
|
|
+import icon_play from '../../img/cloudPractice/icon_play.png';
|
|
|
+import icon_pause from '../../img/cloudPractice/icon_pause.png';
|
|
|
+import { getSecondRPM } from '@/libs/utils';
|
|
|
+// import TheNoticeBar from '/src/components/TheNoticeBar';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'playItem',
|
|
|
+ props: {
|
|
|
+ item: {
|
|
|
+ type: Object as PropType<any>,
|
|
|
+ default: () => ({})
|
|
|
+ },
|
|
|
+ show: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ playState: {
|
|
|
+ type: String as PropType<'play' | 'pause'>,
|
|
|
+ default: 'pause'
|
|
|
+ },
|
|
|
+ type: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emits: ['change'],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ let timer = null as any;
|
|
|
+ const audioData = reactive({
|
|
|
+ isFirst: true,
|
|
|
+ duration: 0,
|
|
|
+ currentTime: 0
|
|
|
+ });
|
|
|
+ const audioRef = ref();
|
|
|
+ /** 加载成功 */
|
|
|
+ const onLoadedmetadata = () => {
|
|
|
+ audioData.duration = audioRef.value?.duration;
|
|
|
+ if (audioData.isFirst) {
|
|
|
+ audioData.isFirst = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (props.playState === 'play') {
|
|
|
+ audioRef.value.play();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否有链接
|
|
|
+ if (!props.item.audioFileUrl && !props.item.metronomeUrl) {
|
|
|
+ emit('change', 'pause');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /** 改变时间 */
|
|
|
+ const handleChangeTime = (val: number) => {
|
|
|
+ audioRef.value.pause();
|
|
|
+ audioData.currentTime = val;
|
|
|
+ clearTimeout(timer);
|
|
|
+ timer = setTimeout(() => {
|
|
|
+ audioRef.value.currentTime = val;
|
|
|
+ if (props.playState === 'play') {
|
|
|
+ audioRef.value.play();
|
|
|
+ }
|
|
|
+ timer = null;
|
|
|
+ }, 300);
|
|
|
+ };
|
|
|
+ const time = computed(() => {
|
|
|
+ return `${getSecondRPM(audioData.currentTime)} / ${getSecondRPM(
|
|
|
+ audioData.duration
|
|
|
+ )}`;
|
|
|
+ });
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.playState,
|
|
|
+ val => {
|
|
|
+ if (val === 'play') {
|
|
|
+ audioRef.value.play().catch((err: any) => {
|
|
|
+ console.log(err, '22');
|
|
|
+ audioRef.value.play();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ audioRef.value.pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.item,
|
|
|
+ () => {
|
|
|
+ // 判断是否有链接
|
|
|
+ if (!props.item.audioFileUrl && !props.item.metronomeUrl) {
|
|
|
+ emit('change', 'pause');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.container,
|
|
|
+ props.type === 'preview' && styles.previewcontainer,
|
|
|
+ props.type === 'modal' && styles.containerModal,
|
|
|
+ props.show ? styles.show : styles.hidden
|
|
|
+ ]}>
|
|
|
+ <div class={[styles.item]}>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.img,
|
|
|
+ props.playState !== 'play' && styles.imgRotate
|
|
|
+ ]}>
|
|
|
+ <NImage
|
|
|
+ lazy
|
|
|
+ objectFit="cover"
|
|
|
+ previewDisabled={true}
|
|
|
+ src={
|
|
|
+ props.item.titleImg ||
|
|
|
+ 'https://oss.dayaedu.com/klx/16983720423251690789356356.png'
|
|
|
+ }
|
|
|
+ onLoad={(e: any) => {
|
|
|
+ (e.target as any).dataset.loaded = 'true';
|
|
|
+ }}
|
|
|
+ />
|
|
|
+
|
|
|
+ <svg class={styles.svgcontainer}>
|
|
|
+ <defs>
|
|
|
+ <linearGradient id="GradientProgress">
|
|
|
+ <stop stop-color="#5BECFF" offset="0%" />
|
|
|
+ <stop stop-color="#259CFE" offset="100%" />
|
|
|
+ </linearGradient>
|
|
|
+ </defs>
|
|
|
+ </svg>
|
|
|
+
|
|
|
+ <NProgress
|
|
|
+ type="circle"
|
|
|
+ class={styles.progress}
|
|
|
+ showIndicator={false}
|
|
|
+ percentage={(audioData.currentTime / audioData.duration) * 100}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class={styles.title}>
|
|
|
+ <div class={styles.titleName}>
|
|
|
+ {/* <TheNoticeBar text={props.item.musicSheetName} /> */}
|
|
|
+ {props.item.musicSheetName}
|
|
|
+ </div>
|
|
|
+ <div class={styles.titleDes}>{props.item.composer}</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.playBtns}>
|
|
|
+ <NButton
|
|
|
+ color="rgba(246,246,246,1)"
|
|
|
+ circle
|
|
|
+ bordered={false}
|
|
|
+ onClick={() => emit('change', 'pre')}>
|
|
|
+ <img src={icon_pre as any} />
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ color="rgba(57,130,246,1)"
|
|
|
+ class={styles.playBtn}
|
|
|
+ circle
|
|
|
+ bordered={false}
|
|
|
+ onClick={() =>
|
|
|
+ emit('change', props.playState === 'pause' ? 'play' : 'pause')
|
|
|
+ }>
|
|
|
+ <img
|
|
|
+ style={{
|
|
|
+ display: props.playState === 'pause' ? '' : 'none'
|
|
|
+ // transform: 'scale(1.5) translateX(1px)'
|
|
|
+ }}
|
|
|
+ src={icon_play as any}
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ style={{
|
|
|
+ display: props.playState === 'play' ? '' : 'none'
|
|
|
+ // transform: 'scale(1.5)'
|
|
|
+ }}
|
|
|
+ src={icon_pause as any}
|
|
|
+ />
|
|
|
+ </NButton>
|
|
|
+ <NButton
|
|
|
+ color="rgba(246,246,246,1)"
|
|
|
+ circle
|
|
|
+ bordered={false}
|
|
|
+ onClick={() => emit('change', 'next')}>
|
|
|
+ <img src={icon_next as any} />
|
|
|
+ </NButton>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.timeWrap}>
|
|
|
+ <NSlider
|
|
|
+ tooltip={false}
|
|
|
+ step={0.01}
|
|
|
+ class={styles.timeProgress}
|
|
|
+ value={audioData.currentTime}
|
|
|
+ max={audioData.duration}
|
|
|
+ onUpdate:value={(val: any) => handleChangeTime(val)}
|
|
|
+ />
|
|
|
+ <div class={styles.time}>{time.value}</div>
|
|
|
+ <audio
|
|
|
+ ref={audioRef}
|
|
|
+ src={props.item.audioFileUrl || props.item.metronomeUrl}
|
|
|
+ onLoadedmetadata={onLoadedmetadata}
|
|
|
+ onEnded={() => {
|
|
|
+ emit('change', 'pause');
|
|
|
+ }}
|
|
|
+ onTimeupdate={() => {
|
|
|
+ if (timer) return;
|
|
|
+ audioData.currentTime = audioRef.value?.currentTime;
|
|
|
+ }}></audio>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|