lex il y a 1 an
Parent
commit
2a64c56f0f

+ 117 - 0
src/components/m-video-tcplayer/index.module.less

@@ -0,0 +1,117 @@
+.video-container {
+  position: relative;
+  width: 100%;
+  min-height: 210px;
+  --plyr-color-main: #FF8057;
+
+  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__poster {
+      background-size: cover;
+    }
+
+    .plyr__control--overlaid {
+      border: 1px solid #fff;
+      background-color: rgba(0, 0, 0, 0.2) !important;
+    }
+
+    .plyr--video .plyr__control:hover {
+      background-color: transparent !important;
+    }
+
+    .video-js {
+      width: 100%;
+      height: 100%;
+      min-height: 210px;
+    }
+
+    .tcp-skin .vjs-play-progress {
+      background-color: var(--van-primary) !important;
+    }
+
+    .vjs-poster {
+      background-size: cover;
+    }
+
+    .video-js .vjs-progress-control:hover .vjs-progress-holder {
+      font-size: inherit !important;
+      outline: none;
+    }
+
+    .video-js .vjs-slider:focus {
+      box-shadow: none !important;
+      text-shadow: none !important;
+      outline: none;
+    }
+  }
+
+  .video {
+    position: relative;
+  }
+
+}
+
+.loadingVideo {
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  background: rgba(0, 0, 0, 0.9);
+  z-index: 10;
+}
+
+.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;
+  }
+
+  .btn {
+    margin: 10px 0;
+    min-width: 94px;
+    font-size: 14px;
+    height: 28px;
+    line-height: 28px;
+  }
+
+  .replay {
+    padding-top: 12px;
+  }
+}
+
+.freeTxt {
+  font-size: 15px;
+  color: #ffffff;
+  line-height: 21px;
+  padding-top: 10px;
+}
+
+.freeRate {
+  color: #32ffd8;
+}

+ 181 - 0
src/components/m-video-tcplayer/index.tsx

@@ -0,0 +1,181 @@
+import { defineComponent, PropType } from 'vue';
+import styles from './index.module.less';
+import { Loading } from 'vant';
+
+import TCPlayer from 'tcplayer.js';
+import 'tcplayer.js/dist/tcplayer.css';
+// import { browser } from '@/helpers/utils';
+export default defineComponent({
+  name: 'o-video',
+  props: {
+    setting: {
+      type: Object,
+      default: () => {}
+    },
+    controls: {
+      type: Boolean,
+      default: true
+    },
+    height: String,
+    src: {
+      type: String,
+      default: ''
+    },
+    poster: {
+      type: String,
+      default: ''
+    },
+    styleValue: {
+      type: Object,
+      default: () => ({})
+    },
+    preload: {
+      type: String as PropType<'auto' | 'metadata' | 'none'>,
+      default: 'auto'
+    },
+    currentTime: {
+      type: Boolean,
+      default: true
+    },
+    playsinline: {
+      type: Boolean,
+      default: true
+    },
+    onPlay: {
+      type: Function,
+      default: () => {}
+    }
+  },
+  emits: ['exitfullscreen', 'play', 'ready', 'enterfullscreen'],
+  data() {
+    return {
+      videoID: 'video' + Date.now() + Math.floor(Math.random() * 100),
+      player: null as any,
+      loading: true // 首次进入加载中
+    };
+  },
+  mounted() {
+    this._init();
+  },
+  methods: {
+    _init() {
+      const Button = TCPlayer.getComponent('Button');
+      const BigPlayButton = TCPlayer.getComponent('BigPlayButton');
+      BigPlayButton.prototype.createEl = function () {
+        const el = Button.prototype.createEl.call(this);
+        const _html =
+          '<button><svg width="41px"height="41px"viewBox="0 0 41 41"version="1.1"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"><g stroke="none"stroke-width="1"fill="none"fill-rule="evenodd"><g transform="translate(-167.000000, -155.000000)"><g transform="translate(0.000000, 85.000000)"><g transform="translate(158.000000, 70.000000)"><g transform="translate(9.000000, 0.000000)"><circle id="椭圆形"stroke="#FFFFFF"fill-opacity="0.1"fill="#D8D8D8"cx="20.5"cy="20.5"r="20"></circle><path d="M14.5483871,27.6859997 L14.5483871,13.4342349 C14.5480523,12.8729571 14.8729597,12.356555 15.3949624,12.0887034 C15.9169651,11.8208518 16.5522696,11.8445472 17.0503046,12.1504437 L28.6530473,19.2778563 C29.1119763,19.5602271 29.3887725,20.0426422 29.3887725,20.5601173 C29.3887725,21.0775924 29.1119763,21.5600075 28.6530473,21.8423783 L17.0503046,28.9697909 C16.5522696,29.2756874 15.9169651,29.2993828 15.3949624,29.0315312 C14.8729597,28.7636796 14.5480523,28.2472775 14.5483871,27.6859997 Z"id="路径"fill="#FFFFFF"fill-rule="nonzero"></path></g></g></g></g></g></svg></button>';
+
+        el.appendChild(
+          TCPlayer.dom.createEl('div', {
+            className: 'vjs-button-icon',
+            innerHTML: _html
+          })
+        );
+        return el;
+      };
+      this.player = TCPlayer(this.videoID, {
+        appID: '',
+        controls: this.controls
+      }); // player-container-id 为播放器容器 ID,必须与 html 中一致
+      if (this.player) {
+        this.player.src(this.src); // url 播放地址
+        this.player.poster(this.poster || '');
+
+        if (this.preload === 'none') {
+          this.loading = false;
+        }
+        this.player.on('loadstart', () => {
+          this.loading = false;
+          this.$emit('ready', this.player);
+          this.domPlayVisibility(false);
+        });
+        this.player.on('play', () => {
+          this.$emit('play', this.player);
+          this.onPlay && this.onPlay(this.player);
+        });
+
+        this.player.on('fullscreenchange', () => {
+          if (this.player.isFullscreen()) {
+            //     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.exitFullscreen()
+            //     })
+            //     // console.log(document.getElementsByClassName('video-js'))
+            //     document.getElementsByClassName('video-js')[0].appendChild(i)
+            this.$emit('enterfullscreen');
+          } else {
+            //     console.log('exitfullscreen')
+            //     const i = document.getElementById('fullscreen-back')
+            //     i && i.remove()
+            this.$emit('exitfullscreen');
+          }
+        });
+      }
+    },
+    // 操作功能
+    domPlayVisibility(hide = true) {
+      const controls = document.querySelector('.vjs-big-play-button');
+      const controls2 = document.querySelector('.vjs-control-bar');
+      if (hide) {
+        controls?.setAttribute('style', 'display:none');
+        controls2?.setAttribute('style', 'display:none');
+      } else {
+        controls?.removeAttribute('style');
+        setTimeout(() => {
+          controls2?.removeAttribute('style');
+        }, 200);
+      }
+    },
+
+    onReplay() {
+      this.player.currentTime(0);
+      this.player.play();
+      this.domPlayVisibility(false);
+    },
+    onStop() {
+      this.player.currentTime(0);
+      this.player.pause();
+    }
+  },
+  unmounted() {
+    this.player?.pause();
+    this.player?.src('');
+    this.player?.dispose();
+  },
+  render() {
+    return (
+      <div class={styles['video-container']}>
+        <video
+          ref="video"
+          id={this.videoID}
+          class={styles['video']}
+          src={this.src}
+          playsinline={this.playsinline}
+          poster={this.poster}
+          preload={this.preload}
+          style={{ ...this.styleValue }}></video>
+        {/* </div> */}
+        {/* 加载视频使用 */}
+        {this.loading && (
+          <div
+            class={styles.loadingVideo}
+            style={{
+              height: this.height || '210px'
+            }}>
+            <Loading
+              size={36}
+              color="#FF8057"
+              vertical
+              style={{ height: '100%', justifyContent: 'center' }}>
+              加载中...
+            </Loading>
+          </div>
+        )}
+      </div>
+    );
+  }
+});

+ 2 - 0
src/shims-vue.d.ts

@@ -3,3 +3,5 @@ declare module '*.vue' {
   const component: DefineComponent<{}, {}, any>;
   export default component;
 }
+
+declare module 'tcplayer.js';

+ 4 - 4
vite.config.ts

@@ -4,7 +4,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx';
 import Components from 'unplugin-vue-components/vite';
 import { VantResolver } from 'unplugin-vue-components/resolvers';
 import viteESLint from 'vite-plugin-eslint';
-import legacy from '@vitejs/plugin-legacy'
+import legacy from '@vitejs/plugin-legacy';
 // eslint-disable-next-line @typescript-eslint/no-var-requires
 const path = require('path');
 
@@ -18,8 +18,8 @@ export default defineConfig({
   base: './',
   plugins: [
     legacy({
-			targets: 'last 2 versions and not dead, > 0.3%, Firefox ESR'
-		}),
+      targets: 'last 2 versions and not dead, > 0.3%, Firefox ESR'
+    }),
     vue(),
     vueJsx(),
     viteESLint(),
@@ -38,7 +38,7 @@ export default defineConfig({
   },
   server: {
     host: '0.0.0.0',
-    port: 9002,
+    port: 9003,
     strictPort: true,
     cors: true,
     https: false,