lex 1 năm trước cách đây
mục cha
commit
60beacd2e8

+ 0 - 134
src/components/card-preview/audio-modal/index.module.less

@@ -1,134 +0,0 @@
-.audioWrap {
-  width: 100%;
-  height: 518px;
-  background-color: #fff;
-}
-
-.audioContainer {
-  position: relative;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  height: 100%;
-  padding: 0;
-
-  &>div {
-    flex: 1;
-  }
-
-  .audio {
-    position: absolute;
-    top: 0;
-    opacity: 0;
-  }
-
-  .tempVudio {
-    position: absolute;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    left: 0;
-    padding: 0;
-  }
-
-  canvas {
-    width: 100%;
-    height: 100%;
-  }
-}
-
-.controls {
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  width: 100%;
-  background: rgba(0, 0, 0, 0.6);
-  backdrop-filter: blur(26px);
-  height: 80px;
-  padding: 0 40px 0 40px !important;
-  transition: all 0.5s;
-  display: flex;
-  align-items: center;
-  transition: all .5s;
-
-  .time {
-    display: flex;
-    justify-content: space-between;
-    color: #fff;
-    padding: 4px 12px 4px;
-    font-size: 24px;
-    font-weight: 600;
-    line-height: 33px;
-    min-width: 140px;
-
-    .line {
-      font-size: 12px;
-    }
-
-    :global {
-      .plyr__time+.plyr__time:before {
-        content: '';
-        margin-right: 0;
-      }
-    }
-  }
-}
-
-.actions {
-  display: flex;
-  justify-content: space-between;
-  height: 100%;
-  color: #fff;
-  font-size: 12px;
-  align-items: center;
-
-  .actionWrap {
-    display: flex;
-  }
-
-  .actionBtn {
-    display: flex;
-    width: 52px;
-    height: 52px;
-    padding: 4px 0;
-    background: transparent;
-
-    &>img {
-      width: 100%;
-      height: 100%;
-    }
-  }
-
-
-  .iconReplay {
-    width: 31px;
-    height: 29px;
-    background-color: transparent;
-
-    &>img {
-      width: 100%;
-      height: 100%;
-    }
-  }
-}
-
-.slider {
-  width: 100%;
-  padding: 0 20px 0 12px;
-
-  :global {
-
-    .n-slider .n-slider-rail .n-slider-rail__fill,
-    .n-slider .n-slider-handles .n-slider-handle-wrapper {
-      transition: all .2s;
-    }
-  }
-}
-
-.sectionAnimate {
-  opacity: 0;
-  pointer-events: none;
-  transform: translateY(100%);
-  transition: all .5s;
-}

+ 0 - 204
src/components/card-preview/audio-modal/index.tsx

@@ -1,204 +0,0 @@
-import { defineComponent, reactive, ref, nextTick } from 'vue';
-import styles from './index.module.less';
-import iconplay from '@views/attend-class/image/icon-pause.svg';
-import iconpause from '@views/attend-class/image/icon-play.svg';
-import iconReplay from '@views/attend-class/image/icon-replay.svg';
-import { NSlider } from 'naive-ui';
-import Vudio from 'vudio.js';
-import tickMp3 from '@views/attend-class/image/tick.mp3';
-
-export default defineComponent({
-  name: 'audio-play',
-  props: {
-    item: {
-      type: Object,
-      default: () => {
-        return {};
-      }
-    },
-    isEmtry: {
-      type: Boolean,
-      default: false
-    }
-  },
-
-  setup(props) {
-    const audioForms = reactive({
-      paused: true,
-      currentTimeNum: 0,
-      currentTime: '00:00',
-      durationNum: 0,
-      duration: '00:00',
-      showBar: true,
-      afterMa3: true
-    });
-    const canvas: any = ref();
-    const audio: any = ref();
-    let vudio: any = null;
-
-    // 切换音频播放
-    const onToggleAudio = (e?: MouseEvent) => {
-      e?.stopPropagation();
-      if (audio.value.paused) {
-        onInit(audio.value, canvas.value);
-        audio.value.play();
-        audioForms.afterMa3 = false;
-      } else {
-        audio.value.pause();
-      }
-      audioForms.paused = audio.value.paused;
-    };
-
-    const onInit = (audio: undefined, canvas: undefined) => {
-      if (!vudio) {
-        vudio = new Vudio(audio, canvas, {
-          effect: 'waveform',
-          accuracy: 256,
-          width: 1024,
-          height: 600,
-          waveform: {
-            maxHeight: 200,
-            color: [
-              [0, '#44D1FF'],
-              [0.5, '#44D1FF'],
-              [0.5, '#198CFE'],
-              [1, '#198CFE']
-            ],
-            prettify: false
-          }
-        });
-        vudio.dance();
-      }
-    };
-
-    // 对时间进行格式化
-    const timeFormat = (num: number) => {
-      if (num > 0) {
-        const m = Math.floor(num / 60);
-        const s = num % 60;
-        return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
-      } else {
-        return '00:00';
-      }
-    };
-
-    const onReplay = () => {
-      if (!audio.value) return;
-      audio.value.currentTime = 0;
-    };
-
-    let vudio1 = null;
-    const canvas1: any = ref();
-    const audio1: any = ref();
-    nextTick(() => {
-      vudio1 = new Vudio(audio1.value, canvas1.value, {
-        effect: 'waveform',
-        accuracy: 256,
-        width: 1024,
-        height: 600,
-        waveform: {
-          maxHeight: 200,
-          color: [
-            [0, '#44D1FF'],
-            [0.5, '#44D1FF'],
-            [0.5, '#198CFE'],
-            [1, '#198CFE']
-          ],
-          prettify: false
-        }
-      });
-      vudio1.dance();
-    });
-
-    return () => (
-      <div class={styles.audioWrap}>
-        <div class={styles.audioContainer}>
-          <audio
-            ref={audio}
-            crossorigin="anonymous"
-            src={props.item.content + '?time=1'}
-            onEnded={() => {
-              audioForms.paused = true;
-            }}
-            onTimeupdate={() => {
-              audioForms.currentTime = timeFormat(
-                Math.round(audio.value?.currentTime || 0)
-              );
-              audioForms.currentTimeNum = audio.value.currentTime;
-            }}
-            onLoadedmetadata={() => {
-              audioForms.duration = timeFormat(
-                Math.round(audio.value.duration)
-              );
-              audioForms.durationNum = audio.value.duration;
-            }}></audio>
-
-          <canvas ref={canvas}></canvas>
-
-          {audioForms.afterMa3 && (
-            <div class={styles.tempVudio}>
-              <audio ref={audio1} src={tickMp3} />
-              <canvas ref={canvas1}></canvas>
-            </div>
-          )}
-        </div>
-
-        <div
-          class={[
-            styles.controls,
-            audioForms.showBar ? '' : styles.sectionAnimate
-          ]}
-          onClick={(e: MouseEvent) => {
-            e.stopPropagation();
-          }}>
-          <div class={styles.actions}>
-            <div class={styles.actionWrap}>
-              <button class={styles.actionBtn} onClick={onToggleAudio}>
-                {audioForms.paused ? (
-                  <img class={styles.playIcon} src={iconplay} />
-                ) : (
-                  <img class={styles.playIcon} src={iconpause} />
-                )}
-              </button>
-            </div>
-            <div class={styles.time}>
-              <div
-                class="plyr__time plyr__time--current"
-                aria-label="Current time">
-                {audioForms.currentTime}
-              </div>
-              <span class={styles.line}>/</span>
-              <div
-                class="plyr__time plyr__time--duration"
-                aria-label="Duration">
-                {audioForms.duration}
-              </div>
-            </div>
-          </div>
-
-          <div class={styles.slider}>
-            <NSlider
-              value={audioForms.currentTimeNum}
-              step={0.01}
-              max={audioForms.durationNum}
-              tooltip={false}
-              onUpdate:value={(val: number) => {
-                audio.value.currentTime = val;
-                audioForms.currentTimeNum = val;
-                audioForms.currentTime = timeFormat(Math.round(val || 0));
-              }}
-            />
-          </div>
-
-          <div class={styles.actions}>
-            <div class={styles.actionWrap}>
-              <button class={styles.iconReplay} onClick={onReplay}>
-                <img src={iconReplay} />
-              </button>
-            </div>
-          </div>
-        </div>
-      </div>
-    );
-  }
-});

+ 3 - 3
src/components/card-preview/index.tsx

@@ -2,8 +2,8 @@ import { NModal } from 'naive-ui';
 import { defineComponent, toRef, watch } from 'vue';
 import styles from './index.module.less';
 import VideoModal from './video-modal';
+import MusicModal from './music-modal';
 import SongModal from './song-modal';
-import AudioModal from './audio-modal';
 
 export default defineComponent({
   name: 'card-preview',
@@ -50,8 +50,8 @@ export default defineComponent({
           {item.value.type === 'VIDEO' && (
             <VideoModal poster={item.value.url} src={item.value.content} />
           )}
-          {item.value.type === 'SONG' && <SongModal item={item.value} />}
-          {item.value.type === 'AUDIO' && <AudioModal item={item.value} />}
+          {item.value.type === 'SONG' && <MusicModal item={item.value} />}
+          {item.value.type === 'AUDIO' && <SongModal item={item.value} />}
         </NModal>
       </>
     );

+ 15 - 0
src/components/card-preview/music-modal/index.module.less

@@ -0,0 +1,15 @@
+.musicScore {
+  width: 100%;
+  height: 518px;
+
+  iframe {
+    width: inherit;
+    height: inherit;
+
+    :global {
+      .headTopBackBtn {
+        display: none;
+      }
+    }
+  }
+}

+ 33 - 0
src/components/card-preview/music-modal/index.tsx

@@ -0,0 +1,33 @@
+import { defineComponent, ref, watch } from 'vue';
+import styles from './index.module.less';
+
+export default defineComponent({
+  name: 'song-modal',
+  props: {
+    item: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  setup(props) {
+    const iframeRef = ref();
+    const isLoaded = ref(false);
+    const origin = /(localhost|192)/.test(location.host)
+      ? 'https://dev.kt.colexiu.com'
+      : location.origin;
+    const src = `${origin}/instrument?id=${props.item.content}&modelType=practise`;
+    return () => (
+      <div class={styles.musicScore}>
+        <iframe
+          ref={iframeRef}
+          onLoad={() => {
+            // emit('setIframe', iframeRef.value);
+            isLoaded.value = true;
+          }}
+          class={[styles.container, 'musicIframe']}
+          frameborder="0"
+          src={src}></iframe>
+      </div>
+    );
+  }
+});

+ 125 - 6
src/components/card-preview/song-modal/index.module.less

@@ -1,15 +1,134 @@
-.musicScore {
+.audioWrap {
   width: 100%;
   height: 518px;
+  background-color: #fff;
+}
+
+.audioContainer {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  padding: 0;
+
+  &>div {
+    flex: 1;
+  }
+
+  .audio {
+    position: absolute;
+    top: 0;
+    opacity: 0;
+  }
+
+  .tempVudio {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    padding: 0;
+  }
 
-  iframe {
-    width: inherit;
-    height: inherit;
+  canvas {
+    width: 100%;
+    height: 100%;
+  }
+}
+
+.controls {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  width: 100%;
+  background: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(26px);
+  height: 80px;
+  padding: 0 40px 0 40px !important;
+  transition: all 0.5s;
+  display: flex;
+  align-items: center;
+  transition: all .5s;
+
+  .time {
+    display: flex;
+    justify-content: space-between;
+    color: #fff;
+    padding: 4px 12px 4px;
+    font-size: 24px;
+    font-weight: 600;
+    line-height: 33px;
+    min-width: 140px;
+
+    .line {
+      font-size: 12px;
+    }
 
     :global {
-      .headTopBackBtn {
-        display: none;
+      .plyr__time+.plyr__time:before {
+        content: '';
+        margin-right: 0;
       }
     }
   }
 }
+
+.actions {
+  display: flex;
+  justify-content: space-between;
+  height: 100%;
+  color: #fff;
+  font-size: 12px;
+  align-items: center;
+
+  .actionWrap {
+    display: flex;
+  }
+
+  .actionBtn {
+    display: flex;
+    width: 52px;
+    height: 52px;
+    padding: 4px 0;
+    background: transparent;
+
+    &>img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+
+  .iconReplay {
+    width: 31px;
+    height: 29px;
+    background-color: transparent;
+
+    &>img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+
+.slider {
+  width: 100%;
+  padding: 0 20px 0 12px;
+
+  :global {
+
+    .n-slider .n-slider-rail .n-slider-rail__fill,
+    .n-slider .n-slider-handles .n-slider-handle-wrapper {
+      transition: all .2s;
+    }
+  }
+}
+
+.sectionAnimate {
+  opacity: 0;
+  pointer-events: none;
+  transform: translateY(100%);
+  transition: all .5s;
+}

+ 190 - 19
src/components/card-preview/song-modal/index.tsx

@@ -1,32 +1,203 @@
-import { defineComponent, ref, watch } from 'vue';
+import { defineComponent, reactive, ref, nextTick } from 'vue';
 import styles from './index.module.less';
+import iconplay from '@views/attend-class/image/icon-pause.svg';
+import iconpause from '@views/attend-class/image/icon-play.svg';
+import iconReplay from '@views/attend-class/image/icon-replay.svg';
+import { NSlider } from 'naive-ui';
+import Vudio from 'vudio.js';
+import tickMp3 from '@views/attend-class/image/tick.mp3';
 
 export default defineComponent({
-  name: 'song-modal',
+  name: 'audio-play',
   props: {
     item: {
       type: Object,
-      default: () => ({})
+      default: () => {
+        return {};
+      }
+    },
+    isEmtry: {
+      type: Boolean,
+      default: false
     }
   },
+
   setup(props) {
-    const iframeRef = ref();
-    const isLoaded = ref(false);
-    const origin = /(localhost|192)/.test(location.host)
-      ? 'https://dev.kt.colexiu.com'
-      : location.origin;
-    const src = `${origin}/instrument?id=${props.item.content}&modelType=practise`;
+    const audioForms = reactive({
+      paused: true,
+      currentTimeNum: 0,
+      currentTime: '00:00',
+      durationNum: 0,
+      duration: '00:00',
+      showBar: true,
+      afterMa3: true
+    });
+    const canvas: any = ref();
+    const audio: any = ref();
+    let vudio: any = null;
+
+    // 切换音频播放
+    const onToggleAudio = (e?: MouseEvent) => {
+      e?.stopPropagation();
+      if (audio.value.paused) {
+        onInit(audio.value, canvas.value);
+        audio.value.play();
+        audioForms.afterMa3 = false;
+      } else {
+        audio.value.pause();
+      }
+      audioForms.paused = audio.value.paused;
+    };
+
+    const onInit = (audio: undefined, canvas: undefined) => {
+      if (!vudio) {
+        vudio = new Vudio(audio, canvas, {
+          effect: 'waveform',
+          accuracy: 256,
+          width: 1024,
+          height: 600,
+          waveform: {
+            maxHeight: 200,
+            color: [
+              [0, '#44D1FF'],
+              [0.5, '#44D1FF'],
+              [0.5, '#198CFE'],
+              [1, '#198CFE']
+            ],
+            prettify: false
+          }
+        });
+        vudio.dance();
+      }
+    };
+
+    // 对时间进行格式化
+    const timeFormat = (num: number) => {
+      if (num > 0) {
+        const m = Math.floor(num / 60);
+        const s = num % 60;
+        return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
+      } else {
+        return '00:00';
+      }
+    };
+
+    const onReplay = () => {
+      if (!audio.value) return;
+      audio.value.currentTime = 0;
+    };
+
+    let vudio1 = null;
+    const canvas1: any = ref();
+    const audio1: any = ref();
+    nextTick(() => {
+      vudio1 = new Vudio(audio1.value, canvas1.value, {
+        effect: 'waveform',
+        accuracy: 256,
+        width: 1024,
+        height: 600,
+        waveform: {
+          maxHeight: 200,
+          color: [
+            [0, '#44D1FF'],
+            [0.5, '#44D1FF'],
+            [0.5, '#198CFE'],
+            [1, '#198CFE']
+          ],
+          prettify: false
+        }
+      });
+      vudio1.dance();
+    });
+
     return () => (
-      <div class={styles.musicScore}>
-        <iframe
-          ref={iframeRef}
-          onLoad={() => {
-            // emit('setIframe', iframeRef.value);
-            isLoaded.value = true;
-          }}
-          class={[styles.container, 'musicIframe']}
-          frameborder="0"
-          src={src}></iframe>
+      <div class={styles.audioWrap}>
+        <div class={styles.audioContainer}>
+          <audio
+            ref={audio}
+            crossorigin="anonymous"
+            src={props.item.content + '?time=1'}
+            onEnded={() => {
+              audioForms.paused = true;
+            }}
+            onTimeupdate={() => {
+              audioForms.currentTime = timeFormat(
+                Math.round(audio.value?.currentTime || 0)
+              );
+              audioForms.currentTimeNum = audio.value.currentTime;
+            }}
+            onLoadedmetadata={() => {
+              audioForms.duration = timeFormat(
+                Math.round(audio.value.duration)
+              );
+              audioForms.durationNum = audio.value.duration;
+            }}></audio>
+
+          <canvas ref={canvas}></canvas>
+
+          {audioForms.afterMa3 && (
+            <div class={styles.tempVudio}>
+              <audio ref={audio1} src={tickMp3} />
+              <canvas ref={canvas1}></canvas>
+            </div>
+          )}
+        </div>
+
+        <div
+          class={[
+            styles.controls,
+            audioForms.showBar ? '' : styles.sectionAnimate
+          ]}
+          onClick={(e: MouseEvent) => {
+            e.stopPropagation();
+          }}>
+          <div class={styles.actions}>
+            <div class={styles.actionWrap}>
+              <button class={styles.actionBtn} onClick={onToggleAudio}>
+                {audioForms.paused ? (
+                  <img class={styles.playIcon} src={iconplay} />
+                ) : (
+                  <img class={styles.playIcon} src={iconpause} />
+                )}
+              </button>
+            </div>
+            <div class={styles.time}>
+              <div
+                class="plyr__time plyr__time--current"
+                aria-label="Current time">
+                {audioForms.currentTime}
+              </div>
+              <span class={styles.line}>/</span>
+              <div
+                class="plyr__time plyr__time--duration"
+                aria-label="Duration">
+                {audioForms.duration}
+              </div>
+            </div>
+          </div>
+
+          <div class={styles.slider}>
+            <NSlider
+              value={audioForms.currentTimeNum}
+              step={0.01}
+              max={audioForms.durationNum}
+              tooltip={false}
+              onUpdate:value={(val: number) => {
+                audio.value.currentTime = val;
+                audioForms.currentTimeNum = val;
+                audioForms.currentTime = timeFormat(Math.round(val || 0));
+              }}
+            />
+          </div>
+
+          <div class={styles.actions}>
+            <div class={styles.actionWrap}>
+              <button class={styles.iconReplay} onClick={onReplay}>
+                <img src={iconReplay} />
+              </button>
+            </div>
+          </div>
+        </div>
       </div>
     );
   }

+ 119 - 68
src/components/card-preview/video-modal/index.module.less

@@ -1,90 +1,141 @@
-.video-container {
-  position: relative;
+.videoWrap {
   width: 100%;
+  height: 100%;
   --plyr-color-main: #198CFE;
+  --plyr-range-track-height: 6px;
+  --plyr-tooltip-radius: 3px;
+  --plyr-range-thumb-height: 24px;
 
-  video {
-    width: 100%;
-    // object-fit: cover;
-  }
 
   :global {
-    .video-back {
-      position: absolute;
-      left: 20px;
-      top: 20px;
-      color: #fff;
-      z-index: 99;
-      font-size: 24px;
-      width: 30px;
-      height: 30px;
-      background-color: rgba(0, 0, 0, 0.5);
-      border-radius: 50%;
-      padding: 4px 5px 4px 3px;
+    .plyr--video {
+      width: 100%;
+      height: 100%;
     }
 
-    .plyr__poster {
-      background-size: cover;
+    .plyr__time {
+      display: block !important;
     }
 
-    .plyr__control--overlaid {
-      border: 1px solid #fff;
-      background-color: rgba(0, 0, 0, 0.2) !important;
+    .plyr__video-wrapper {
+      pointer-events: none;
     }
+  }
+}
+
+:global(.bottomFixed).controls {
+  width: 100% !important;
+  background: rgba(0, 0, 0, 0.6) !important;
+  backdrop-filter: blur(26px);
+  height: 80px !important;
+  padding: 0 40px 0 40px !important;
+  transition: all 0.5s;
 
-    .plyr--video .plyr__control:hover {
-      background-color: transparent !important;
+  .time {
+    display: flex;
+    justify-content: space-between;
+    color: #fff;
+    padding: 4px 12px 4px;
+    font-size: 24px;
+    font-weight: 600;
+    line-height: 33px;
+    min-width: 140px;
+
+    .line {
+      font-size: 12px;
     }
-  }
 
-  .video {
-    position: relative;
+    :global {
+      .plyr__time+.plyr__time:before {
+        content: '';
+        margin-right: 0;
+      }
+    }
   }
-}
 
-.loadingVideo {
-  position: absolute;
-  top: 0;
-  left: 0;
-  bottom: 0;
-  right: 0;
-  background: rgba(0, 0, 0, 0.9);
-  z-index: 10;
-}
+  .slider {
+    width: 100%;
+    padding: 0 20px 0 12px;
 
-.playOver {
-  background: rgba(0, 0, 0, 0.5);
-  color: #fff;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-direction: column;
-
-  .tips {
-    font-size: 15px;
-    color: #ffffff;
-  }
+    :global {
+      .van-slider__button {
+        background: var(--van-primary);
+      }
 
-  .btn {
-    margin: 10px 0;
-    min-width: 94px;
-    font-size: 14px;
-    height: 28px;
-    line-height: 28px;
+      .van-loading {
+        width: 100%;
+        height: 100%;
+      }
+    }
   }
 
-  .replay {
-    padding-top: 12px;
-  }
-}
+  .actions {
+    display: flex;
+    justify-content: space-between;
+    color: #fff;
+    font-size: 12px;
+    align-items: center;
 
-.freeTxt {
-  font-size: 15px;
-  color: #ffffff;
-  line-height: 21px;
-  padding-top: 10px;
-}
+    .actionWrap {
+      display: flex;
+    }
 
-.freeRate {
-  color: #32ffd8;
+    .actionBtn {
+      display: flex;
+      width: 52px;
+      height: 52px;
+      padding: 4px 0;
+      background: transparent;
+    }
+
+    .actionBtn>img {
+      width: 100%;
+      height: 100%;
+    }
+
+    :global {
+      .van-loading__circular {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    .playIcon {
+      display: none;
+    }
+
+    .btnPlay img:nth-child(2) {
+      display: block;
+    }
+
+    .btnPause img:nth-child(3) {
+      display: block;
+    }
+
+    .btnPlay,
+    .btnPause {
+      :global {
+        .van-loading {
+          display: none;
+        }
+      }
+    }
+
+    .loopBtn {
+      background-color: transparent;
+      width: 31px;
+      height: 29px;
+      cursor: pointer;
+
+      :global {
+        .loop {
+          display: block;
+        }
+
+        .loopActive {
+          display: none;
+        }
+      }
+    }
+  }
 }

+ 122 - 122
src/components/card-preview/video-modal/index.tsx

@@ -1,17 +1,15 @@
-import { defineComponent, PropType } from 'vue';
-import styles from './index.module.less';
-import Plyr from 'plyr';
+import { defineComponent, nextTick, onMounted, toRefs } from 'vue';
 import 'plyr/dist/plyr.css';
-import { browser } from '@/helpers/utils';
+import Plyr from 'plyr';
+import { ref } from 'vue';
+import styles from './index.module.less';
+import iconplay from '@views/attend-class/image/icon-pause.svg';
+import iconpause from '@views/attend-class/image/icon-play.svg';
+import iconReplay from '@views/attend-class/image/icon-replay.svg';
+
 export default defineComponent({
-  name: 'o-video',
+  name: 'video-play',
   props: {
-    setting: {
-      type: Object,
-      default: () => ({})
-    },
-    controls: Boolean,
-    height: String,
     src: {
       type: String,
       default: ''
@@ -20,130 +18,132 @@ export default defineComponent({
       type: String,
       default: ''
     },
-    styleValue: {
-      type: Object,
-      default: () => ({})
-    },
-    preload: {
-      type: String as PropType<'auto' | 'metadata' | 'none'>,
-      default: 'auto'
-    },
-    currentTime: {
+    isEmtry: {
       type: Boolean,
-      default: true
-    },
-    playsinline: {
-      type: Boolean,
-      default: true
-    },
-    onPlay: {
-      type: Function,
-      default: () => ({})
+      default: false
     }
   },
-  emits: ['exitfullscreen'],
-  data() {
-    return {
-      player: null as any,
-      loading: true // 首次进入加载中
+  emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset'],
+  setup(props, { emit, expose }) {
+    const { src, poster, isEmtry } = toRefs(props);
+    const videoRef = ref();
+    const videoItem = ref<Plyr>();
+    const controlID = 'v' + Date.now() + Math.floor(Math.random() * 100);
+    const playBtnId = 'play' + Date.now() + Math.floor(Math.random() * 100);
+    const replayBtnId = 'replay' + Date.now() + Math.floor(Math.random() * 100);
+    const toggleHideControl = (isShow: false) => {
+      videoItem.value?.toggleControls(isShow);
+    };
+    const togglePlay = (e: Event) => {
+      e.stopPropagation();
+      videoItem.value?.togglePlay();
+    };
+    const toggleReplay = () => {
+      const replayBtn = document.getElementById(replayBtnId);
+      if (!replayBtn || !videoItem.value) return;
+      videoItem.value.restart();
+    };
+    const onDefault = () => {
+      document
+        .getElementById(controlID)
+        ?.addEventListener('click', (e: Event) => {
+          e.stopPropagation();
+          emit('reset');
+        });
+      document.getElementById(playBtnId)?.addEventListener('click', togglePlay);
+      document
+        .getElementById(replayBtnId)
+        ?.addEventListener('click', toggleReplay);
     };
-  },
-  mounted() {
-    this._init();
-  },
-  methods: {
-    _init() {
-      // controls: [
-      //   'play-large' ,  // 中间的大播放按钮
-      //   'restart' ,  // 重新开始播放
-      //   'rewind' ,  // 按寻道时间倒带(默认 10 秒)
-      //   'play' ,  // 播放/暂停播放
-      //   'fast-forward' ,  // 快进查找时间(默认 10 秒)
-      //   'progress' ,  // 播放和缓冲的进度条和滑动条
-      //   'current-time' ,  // 播放的当前时间
-      //   ' duration' ,  // 媒体的完整持续时间
-      //   'mute' ,  // 切换静音
-      //   'volume', // 音量控制
-      //   'captions' ,  // 切换字幕
-      //   'settings' ,  // 设置菜单
-      //   'pip' ,  // 画中画(当前仅 Safari)
-      //   'airplay' ,  // Airplay(当前仅 Safari)
-      //   'download ' ,  // 显示一个下载按钮,其中包含指向当前源或您在选项中指定的自定义 URL 的链接
-      //   'fullscreen' ,  // 切换全屏
-      // ] ;
-      const controls = [
-        'play-large',
-        'play',
-        'progress',
-        'captions',
-        'fullscreen'
-      ];
-      if (this.currentTime) {
-        controls.push('current-time');
-      }
-      const params: any = {
-        controls: controls,
-        ...this.setting,
-        invertTime: false
-      };
 
-      if (browser().iPhone) {
-        params.fullscreen = {
-          enabled: true,
-          fallback: 'force',
-          iosNative: true
-        };
+    const changePlayBtn = (code: string) => {
+      const playBtn = document.getElementById(playBtnId);
+      if (!playBtn) return;
+      if (code == 'play') {
+        playBtn.classList.remove(styles.btnPause);
+        playBtn.classList.add(styles.btnPlay);
+      } else {
+        playBtn.classList.remove(styles.btnPlay);
+        playBtn.classList.add(styles.btnPause);
       }
+    };
+    const controls = `
+            <div id="${controlID}" class="plyr__controls bottomFixed ${styles.controls}">
+                <div class="${styles.actions}">
+                    <div class="${styles.actionWrap}">
+                        <button id="${playBtnId}" class="${styles.actionBtn}">
+                            <div class="van-loading van-loading--circular" aria-live="polite" aria-busy="true"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(255, 255, 255);"><svg class="van-loading__circular" viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
+                            <img class="${styles.playIcon}" src="${iconplay}" />
+                            <img class="${styles.playIcon}" src="${iconpause}" />
+                        </button>
+                    </div>
+                    <div class="${styles.time}">
+                        <div class="plyr__time plyr__time--current" aria-label="Current time">00:00</div><span class="${styles.line}">/</span>
+                        <div class="plyr__time plyr__time--duration" aria-label="Duration">00:00</div>
+                    </div>
+                </div>
+                <div class="${styles.slider}">
+                    <div class="plyr__progress">
+                        <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="0" aria-label="Seek">
+                        <progress class="plyr__progress__buffer" min="0" max="100" value="0">% buffered</progress>
+                        <span role="tooltip" class="plyr__tooltip">00:00</span>
+                    </div>
 
-      this.player = new Plyr((this as any).$refs.video, params);
+                </div>
+                <div class="${styles.actions}" style="padding-right: 0;">
+                    <button id="${replayBtnId}" class="${styles.actionBtn} ${styles.loopBtn}">
+                        <img class="loop" src="${iconReplay}" />
+                    </button>
+                </div>
+            </div>`;
 
-      this.player.on('play', () => {
-        this.onPlay && this.onPlay(this.player);
+    onMounted(() => {
+      videoItem.value = new Plyr(videoRef.value, {
+        autoplay: false,
+        controls: controls,
+        autopause: true, // 一次只允许
+        ratio: '16:9', // 强制所有视频的纵横比
+        // hideControls: false, // 在 2 秒没有鼠标或焦点移动、控制元素模糊(制表符退出)、播放开始或进入全屏时自动隐藏视频控件。只要移动鼠标、聚焦控制元素或暂停播放,控件就会立即重新出现。
+        clickToPlay: false, // 单击(或点击)视频容器将切换播放/暂停
+        fullscreen: { enabled: false, fallback: false, iosNative: false } // 不适用全屏
       });
+      if (videoItem.value) {
+        videoItem.value.on('play', () => {
+          if (videoItem.value) {
+            videoItem.value.muted = false;
+            videoItem.value.volume = 1;
+          }
 
-      this.player.on('enterfullscreen', () => {
-        console.log('fullscreen');
-        const i = document.createElement('i');
-        i.id = 'fullscreen-back';
-        i.className = 'van-icon van-icon-arrow-left video-back';
-        i.addEventListener('click', () => {
-          this.player.fullscreen.exit();
+          changePlayBtn('');
+        });
+        videoItem.value.on('pause', () => {
+          changePlayBtn('play');
+        });
+        videoItem.value.on('ended', () => {
+          emit('ended');
+          changePlayBtn('play');
+        });
+        videoItem.value.once('loadedmetadata', () => {
+          changePlayBtn('play');
         });
-        console.log(document.getElementsByClassName('plyr'));
-        document.getElementsByClassName('plyr')[0].appendChild(i);
-      });
-
-      this.player.on('exitfullscreen', () => {
-        console.log('exitfullscreen');
-        const i = document.getElementById('fullscreen-back');
-        i && i.remove();
-        this.$emit('exitfullscreen');
-      });
-    },
 
-    onReplay() {
-      this.player.restart();
-      this.player.play();
-    },
-    onStop() {
-      this.player.stop();
-    }
-  },
-  unmounted() {
-    this.player?.destroy();
-  },
-  render() {
-    return (
-      <div class={styles['video-container']}>
+        nextTick(() => {
+          onDefault();
+        });
+      }
+    });
+    expose({
+      changePlayBtn,
+      toggleHideControl
+    });
+    return () => (
+      <div class={styles.videoWrap}>
         <video
-          ref="video"
-          class={styles['video']}
-          src={this.src}
-          playsinline={this.playsinline}
-          poster={this.poster}
-          preload={this.preload}
-          style={{ ...this.styleValue }}></video>
-        {/* </div> */}
+          style={{ width: '100%', height: '100%' }}
+          src={isEmtry.value ? '' : src.value}
+          poster={poster.value}
+          ref={videoRef}
+          playsinline="false"></video>
       </div>
     );
   }