| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- import { defineComponent, PropType } from 'vue'
- import styles from './index.module.less'
- import Plyr from 'plyr'
- import 'plyr/dist/plyr.css'
- import { Button, Icon, Loading, Toast } from 'vant'
- import TCPlayer from 'tcplayer.js'
- import 'tcplayer.js/dist/tcplayer.css'
- import iconVideoPlay from '@/common/images/icon_video_play.png'
- import { browser } from '@/helpers/utils'
- import { state } from '@/state'
- import { listenerMessage, postMessage } from '@/helpers/native-message'
- export default defineComponent({
- name: 'col-video',
- props: {
- trySee: {
- // 是否试看
- type: Boolean,
- default: false
- },
- freeTitleStatus: {
- type: Boolean,
- default: true
- },
- // 试看比例
- freeRate: {
- type: Number,
- default: 100
- },
- setting: {
- type: Object,
- default: () => {}
- },
- controls: Boolean,
- 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: () => {}
- },
- isBuy: {
- // 是否把购买方法在外部调用
- type: Boolean,
- default: false
- },
- onBuyEmit: {
- type: Function,
- default: () => {}
- }
- },
- data() {
- return {
- videoID: 'video' + Date.now() + Math.floor(Math.random() * 100),
- player: null as any,
- // playTime: 0,
- loading: true, // 首次进入加载中
- trySeeOver: false, // 试看是否结束
- showSeeStatus: true // 是否显示试看状态
- }
- },
- mounted() {
- this._init()
- listenerMessage('setVideoPlayer', result => {
- const content = result?.content
- if (content.status === 'pause') {
- this.player.pause()
- }
- })
- },
- beforeUnmount() {
- postMessage({
- api: 'limitScreenRecord',
- content: {
- type: 0
- }
- })
- },
- computed: {
- computedSeeStatus() {
- // console.log(
- // this.showSeeStatus,
- // this.trySee,
- // this.trySeeOver,
- // 'this.showSeeStatus, this.trySee'
- // )
- return this.showSeeStatus && this.trySee
- },
- playTime() {
- // 允许播放时间
- const player = this.player
- const playTime = (player.duration() * this.freeRate) / 100
- return playTime || 0
- }
- },
- methods: {
- _init() {
- // 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
- // }
- // }
- // this.player = new Plyr((this as any).$refs.video, params)
- // this.player.elements.container
- // ? (this.player.elements.container.style.height = this.height || '210px')
- // : null
- // if (this.preload === 'none') {
- // this.loading = false
- // }
- // this.player.on('loadedmetadata', () => {
- // this.loading = false
- // if (this.trySee) {
- // this.domPlayVisibility()
- // } else {
- // this.domPlayVisibility(false)
- // }
- // // 监听播放事件
- // const _this = this
- // this.player.on('timeupdate', () => {
- // const players = _this.player
- // if (players.currentTime >= this.playTime && _this.trySee) {
- // players.pause()
- // _this.trySeeOver = true
- // _this.showSeeStatus = true
- // _this.domPlayVisibility() // 试看结束后隐藏播放按钮
- // }
- // })
- // })
- // this.player.on('play', () => {
- // postMessage(
- // {
- // api: 'getDeviceStatus',
- // content: {
- // type: 'video'
- // }
- // },
- // (res: any) => {
- // // 判断是否在录屏中, 如果在录屏则不允许播放
- // if (res.content.status == '1') {
- // Toast('为了保证数据安全,请不要录屏')
- // this.player.pause()
- // }
- // }
- // )
- // postMessage({
- // api: 'limitScreenRecord',
- // content: {
- // type: 1
- // }
- // })
- // this.onPlay && this.onPlay()
- // })
- // 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()
- // })
- // 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()
- // })
- 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: true
- }) // 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
- if (this.trySee) {
- this.domPlayVisibility()
- } else {
- this.domPlayVisibility(false)
- }
- // 监听播放事件
- this.player.on('timeupdate', () => {
- const players = this.player
- if (players.currentTime() >= this.playTime && this.trySee) {
- players.pause()
- this.trySeeOver = true
- this.showSeeStatus = true
- this.domPlayVisibility() // 试看结束后隐藏播放按钮
- }
- })
- })
- this.player.on('play', () => {
- postMessage(
- {
- api: 'getDeviceStatus',
- content: {
- type: 'video'
- }
- },
- (res: any) => {
- // 判断是否在录屏中, 如果在录屏则不允许播放
- if (res.content.status == '1') {
- Toast('为了保证数据安全,请不要录屏')
- this.player.pause()
- }
- }
- )
- postMessage({
- api: 'limitScreenRecord',
- content: {
- type: 1
- }
- })
- this.onPlay && this.onPlay()
- })
- 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)
- } else {
- console.log('exitfullscreen')
- const i = document.getElementById('fullscreen-back')
- i && i.remove()
- }
- })
- }
- },
- // 操作功能
- 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)
- }
- },
- onClickPlay() {
- this.player.play()
- this.domPlayVisibility(false)
- this.showSeeStatus = false
- },
- onBuy() {
- if (this.isBuy) {
- this.onBuyEmit()
- return
- }
- this.$router.back()
- },
- onReplay() {
- this.player.currentTime(0)
- this.player.play()
- this.domPlayVisibility(false)
- this.trySeeOver = false
- this.showSeeStatus = false
- }
- },
- unmounted() {
- this.player?.pause()
- this.player?.src('')
- this.player?.dispose()
- },
- render() {
- return (
- <div
- class={[styles['video-container'], 'colVideo']}
- style={{
- height: this.height || '210px'
- }}
- >
- {/* <div ref="video" class={styles['video']} style={{ ...this.styleValue }}> */}
- {/* <Icon
- name="arrow-left"
- class={styles.videoBack}
- size="20"
- color="#fff"
- /> */}
- <video
- ref="video"
- class={styles['video']}
- src={this.src}
- id={this.videoID}
- 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="#2dc7aa"
- vertical
- style={{ height: '100%', justifyContent: 'center' }}
- >
- 加载中...
- </Loading>
- </div>
- )}
- {/* 试看结束 */}
- {this.trySee && this.computedSeeStatus && !this.loading && (
- <div
- class={[styles.loadingVideo, styles.playOver]}
- style={{
- height: this.height || '210px'
- }}
- >
- {!this.trySeeOver ? (
- <>
- <Icon
- name={iconVideoPlay}
- size={50}
- onClick={this.onClickPlay}
- />
- <p class={styles.freeTxt}>
- 免费试看
- {/* {this.freeTitleStatus ? '试看' : '领取'} */}
- </p>
- {/* <p class={styles.freeRate}>每课时可试看{this.freeRate}%</p> */}
- </>
- ) : (
- <>
- {state.platformType === 'STUDENT' ? (
- <p class={styles.tips}>
- {this.freeTitleStatus
- ? '免费试看结束,购买完整课程后继续学习'
- : '试看结束,领取课程后继续学习'}
- </p>
- ) : (
- <p class={styles.tips}>
- 若需完整观看,请下载酷乐秀领取或购买
- </p>
- )}
- {state.platformType === 'STUDENT' && (
- <Button
- class={styles.btn}
- type="primary"
- round
- size="small"
- onClick={this.onBuy}
- >
- {state.platformType === 'STUDENT'
- ? this.freeTitleStatus
- ? '立即购买'
- : '免费领取'
- : '返回免费'}
- </Button>
- )}
- <div
- class={state.platformType !== 'STUDENT' && styles.replay}
- onClick={this.onReplay}
- >
- <Icon
- name="replay"
- style={{ marginRight: '5px' }}
- size={16}
- />
- 重播
- </div>
- </>
- )}
- </div>
- )}
- </div>
- )
- }
- })
|