1016 lines
30 KiB
Vue
1016 lines
30 KiB
Vue
<template>
|
||
<view class="container" style="background-color: #000; position: relative">
|
||
<view style="width: 100%; height: 200px">
|
||
<!-- 倒计时提示 -->
|
||
<view v-if="showCountDown" class="showCountDownd">
|
||
<view class="">
|
||
<text class="nextText">{{ secondCountDown }} 秒后播放下一个视频</text><br />
|
||
<view>
|
||
<text class="cancelNext" @click="hideNextVideo">取消下一个</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 错误提示 -->
|
||
<view
|
||
v-if="show"
|
||
style="height: 100%;display: flex;align-items:center;justify-content:center;color: #fff;font-size: 38rpx;text-align: center;"
|
||
>
|
||
{{ errorTxt }}
|
||
</view>
|
||
|
||
<!-- 视频播放器容器 -->
|
||
<div
|
||
v-else
|
||
style="background-color: #000"
|
||
ref="videoContent"
|
||
@tap="renderScript.handleClick"
|
||
id="url-player-test"
|
||
:videoData="videoData"
|
||
:winWidth="winWidth"
|
||
:winHeight="winHeight"
|
||
:currentVideoList="currentVideoList"
|
||
:firstTime="firstTime"
|
||
:isfresh="isfresh"
|
||
:platform="platform"
|
||
:isSetFirstTime="isSetFirstTime"
|
||
:isChange="isChange"
|
||
:change:videoData="renderScript.receiveMsg"
|
||
:replayVideoFlag="replayVideoFlag"
|
||
:change:winWidth="renderScript.receiveWinWidth"
|
||
:change:winHeight="renderScript.receiveWinHeight"
|
||
:change:firstTime="renderScript.receiveFirstTime"
|
||
:change:replayVideoFlag="renderScript.receiveReplayVideoFlag"
|
||
:change:isSetFirstTime="renderScript.receiveisSetFirstTime"
|
||
:change:isfresh="renderScript.receiveIsfresh"
|
||
:change:platform="renderScript.receiveplatform"
|
||
:change:isChange="renderScript.receiveIsChange"
|
||
:change:currentVideoList="renderScript.receiveVideoList"
|
||
></div>
|
||
|
||
<!-- 隐藏的通信元素 -->
|
||
<div @tap="renderScript.emitData" ref="videoContent1" v-show="false" class="videoContent1">
|
||
直接调用renderjs中的emitData的方法,传递当前播放时长
|
||
</div>
|
||
<div @tap="renderScript.endEmitData" ref="videoContent2" v-show="false" class="videoContent2">
|
||
监听结束方法,记录播放时长
|
||
</div>
|
||
<div @tap="renderScript.changeVideoData" ref="videoContent3" v-show="false" class="videoContent3">
|
||
监听切换视频方法
|
||
</div>
|
||
<div @tap="renderScript.emitSetData" ref="videoContent4" v-show="false" class="videoContent4">
|
||
监听切换视频方法
|
||
</div>
|
||
<div @tap="renderScript.emitopenShow" ref="videoContent5" v-show="false" class="videoContent5">
|
||
打开视频提示
|
||
</div>
|
||
<div @tap="renderScript.emitLoadNextVideo" ref="videoContent6" v-show="false" class="videoContent6">
|
||
播放下一条
|
||
</div>
|
||
<div @tap="renderScript.emitHideNextVideo" ref="videoContent7" v-show="false" class="videoContent7">
|
||
隐藏播放下一条界面
|
||
</div>
|
||
<div @tap="renderScript.emitReplayVideoFlagFalse" ref="videoContent8" v-show="false" class="videoContent8">
|
||
隐藏播放下一条界面
|
||
</div>
|
||
<div @tap="renderScript.emitUnlockChangeVideo" ref="videoContent9" v-show="false" class="videoContent9">
|
||
释放切换键锁
|
||
</div>
|
||
|
||
<!-- 全屏按钮 -->
|
||
<div class="fullScreenButton-container">
|
||
<div
|
||
:class="`prism-fullscreen-btn ${isFullScreen ? 'fullscreen' : ''}`"
|
||
@tap="renderScript.changeVideoScreen"
|
||
></div>
|
||
</div>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, getCurrentInstance } from 'vue'
|
||
import { videoApi } from '@/api/modules/video'
|
||
import type {
|
||
IVideoInfo,
|
||
IVideoData,
|
||
IRecordTimeData,
|
||
IScreenChangeData,
|
||
IOpenShowData,
|
||
PlatformType
|
||
} from '@/types/video'
|
||
|
||
// Props 定义
|
||
interface Props {
|
||
currentVideo?: IVideoInfo
|
||
currentVideoList?: IVideoInfo[]
|
||
videoTitle?: string
|
||
secondCountDown?: number
|
||
noRecored?: boolean
|
||
}
|
||
|
||
const props = defineProps<Props>()
|
||
|
||
// 使用 computed 来处理默认值
|
||
const secondCountDown = computed(() => props.secondCountDown ?? 10)
|
||
const noRecored = computed(() => props.noRecored ?? false)
|
||
|
||
// Emits 定义
|
||
const emit = defineEmits<{
|
||
'child-event': [timer: any]
|
||
'changeScreen': [isFullScreen: boolean]
|
||
'changeScreenLoading': [loading: boolean]
|
||
'hideNextVideo': []
|
||
'startNextVideoCountDown': []
|
||
'unlockChangeVideo': []
|
||
}>()
|
||
|
||
// 获取当前实例
|
||
const instance = getCurrentInstance()
|
||
|
||
// 响应式数据
|
||
// 响应式数据
|
||
const reaquestFlag = ref(false)
|
||
const show = ref(false)
|
||
const platform = ref<PlatformType>(null)
|
||
const isFullScreen = ref(false)
|
||
const isfresh = ref(false)
|
||
const isChange = ref(false)
|
||
const isControl = ref(true)
|
||
const timer = ref<any>(null)
|
||
const replayVideoFlag = ref(false)
|
||
const showCountDown = ref(false)
|
||
const playEndBlank = ref(false)
|
||
const videoList = ref<any[]>([])
|
||
const replayVideoLock = ref(false)
|
||
const firstTime = ref(0)
|
||
const options = ref<any>({})
|
||
const playAuth = ref('')
|
||
const currentTime = ref<string>('')
|
||
const videoId = ref('')
|
||
const videoData = ref<IVideoData>({} as IVideoData)
|
||
const isSetFirstTime = ref(false)
|
||
const screenType = ref<any>(null)
|
||
const videoUrl = ref<string | null>(null)
|
||
const errorTxt = ref('此设备暂不支持观看当前视频请移步到安卓手机进行学习!')
|
||
const winWidth = ref(0)
|
||
const winHeight = ref(0)
|
||
const changeVideoLock = ref(false)
|
||
|
||
// 方法: 重播视频
|
||
const replayVideo = () => {
|
||
if (!replayVideoLock.value) {
|
||
replayVideoLock.value = true
|
||
getLive(true, props.currentVideo)
|
||
console.log('重播视频:', props.currentVideo.id)
|
||
hideNextVideo()
|
||
replayVideoFlag.value = true
|
||
setTimeout(() => {
|
||
replayVideoLock.value = false
|
||
}, 1000)
|
||
}
|
||
}
|
||
|
||
// 方法: 重置重播标志
|
||
const replayVideoFlagFalse = () => {
|
||
console.log('复原replayVideoFlag', replayVideoFlag.value)
|
||
replayVideoFlag.value = false
|
||
}
|
||
|
||
// 方法: 解锁视频切换
|
||
const UnlockChangeVideo = () => {
|
||
emit('unlockChangeVideo')
|
||
}
|
||
|
||
// 方法: 隐藏下一个视频提示
|
||
const hideNextVideo = () => {
|
||
console.log(11111111111111)
|
||
showCountDown.value = false
|
||
playEndBlank.value = false
|
||
emit('hideNextVideo')
|
||
}
|
||
|
||
// 方法: 加载下一个视频
|
||
const loadNextVideo = () => {
|
||
playEndBlank.value = true
|
||
const _list = [...props.currentVideoList].map(item => item.id)
|
||
|
||
const thisIndex = _list.findIndex(item => item == props.currentVideo.id)
|
||
console.log('播放列表', _list, props.currentVideo.id, thisIndex)
|
||
|
||
if (thisIndex < props.currentVideoList.length - 1) {
|
||
showCountDown.value = true
|
||
emit('startNextVideoCountDown')
|
||
}
|
||
}
|
||
|
||
// 方法: 显示错误提示
|
||
const openShow = (data: IOpenShowData) => {
|
||
errorTxt.value = data.msg || '此设备暂不支持观看当前视频请移步到安卓手机进行学习'
|
||
show.value = true
|
||
}
|
||
|
||
// 方法: 切换视频数据
|
||
const changeVideoData = () => {
|
||
show.value = false
|
||
isChange.value = false
|
||
}
|
||
|
||
// 方法: 切换视频
|
||
const changeVideo = async (data: IVideoInfo) => {
|
||
console.log('changeVideo+++++++++', data)
|
||
currentTime.value = ''
|
||
firstTime.value = 0
|
||
isSetFirstTime.value = false
|
||
|
||
// 先设置为 false,然后在 getData 中切换为 true 来触发 renderjs
|
||
isChange.value = false
|
||
|
||
await getLive(true, data)
|
||
}
|
||
|
||
// 方法: 屏幕状态改变
|
||
const screenChange = (data: IScreenChangeData) => {
|
||
console.log('status at line 这是当前的状态158:', data.status, data.primary)
|
||
isFullScreen.value = !data.status
|
||
emit('changeScreen', isFullScreen.value)
|
||
}
|
||
|
||
// 方法: 控制器显示隐藏
|
||
const controlChange = (e: any) => {
|
||
isControl.value = e.detail.show
|
||
}
|
||
|
||
// 方法: 播放器初始化
|
||
const init = async (data: any, isChangeParam: boolean) => {
|
||
try {
|
||
console.log('===== init() 方法被调用 =====', data)
|
||
show.value = false
|
||
|
||
// 获取平台信息
|
||
// @ts-ignore
|
||
platform.value = (typeof uni !== 'undefined' && uni.getSystemInfoSync)
|
||
? uni.getSystemInfoSync().platform === 'ios' ? 'ios' : 'android'
|
||
: 'h5'
|
||
|
||
isfresh.value = true
|
||
isChange.value = false // 先设置为 false,后面切换时才能触发 change
|
||
console.log('初始化播放器, 平台:', platform.value)
|
||
|
||
// 获取本地存储的播放记录
|
||
try {
|
||
const storedList = uni.getStorageSync('videoOssList')
|
||
if (storedList) {
|
||
videoList.value = JSON.parse(storedList)
|
||
}
|
||
} catch (e) {
|
||
console.warn('读取本地播放记录失败:', e)
|
||
videoList.value = []
|
||
}
|
||
|
||
options.value = data.currentVideo || {}
|
||
videoId.value = options.value.video || options.value.videoId || ''
|
||
console.log('视频ID:', videoId.value)
|
||
|
||
await getLive(isChangeParam, options.value)
|
||
} catch (error) {
|
||
console.error('初始化播放器失败:', error)
|
||
show.value = true
|
||
errorTxt.value = '播放器初始化失败'
|
||
}
|
||
}
|
||
|
||
// 方法: 配置播放项
|
||
const getData = async (data: IVideoData, isChangeParam: boolean) => {
|
||
try {
|
||
if (!isSetFirstTime.value) {
|
||
const netWork = data.userCourseVideoPositionEntity?.position || 0
|
||
let list: any[] = []
|
||
|
||
// 安全地获取本地存储
|
||
try {
|
||
const storedList = uni.getStorageSync('videoOssList')
|
||
if (storedList) {
|
||
list = JSON.parse(storedList)
|
||
}
|
||
} catch (e) {
|
||
console.warn('读取本地播放记录失败:', e)
|
||
list = []
|
||
}
|
||
|
||
const index = list.findIndex((e) => e.id == data.id)
|
||
console.log('视频ID:', data.id, '本地记录索引:', index)
|
||
|
||
// 计算初始播放时间(取本地和服务器的最大值)
|
||
if (netWork > 0) {
|
||
if (index >= 0) {
|
||
firstTime.value = Math.max(list[index].time || 0, netWork)
|
||
} else {
|
||
firstTime.value = netWork
|
||
}
|
||
} else {
|
||
if (index >= 0) {
|
||
firstTime.value = list[index].time || 0
|
||
} else {
|
||
firstTime.value = 0
|
||
}
|
||
}
|
||
|
||
videoData.value = {
|
||
...data,
|
||
firstTime: firstTime.value
|
||
}
|
||
|
||
console.log('初始播放时间:', firstTime.value)
|
||
console.log('videoData 已设置:', videoData.value)
|
||
console.log('videoData.value.playAuth:', videoData.value.playAuth)
|
||
console.log('videoData.value.videoId:', videoData.value.videoId)
|
||
|
||
// 触发 renderjs 更新 - 切换 isChange 的值(从 false 到 true)
|
||
isChange.value = true
|
||
console.log('触发 isChange:', isChange.value)
|
||
|
||
// 强制更新以触发 renderjs 响应
|
||
if (instance?.proxy) {
|
||
instance.proxy.$forceUpdate()
|
||
console.log('已调用 $forceUpdate()')
|
||
}
|
||
|
||
// 安全地保存到本地存储
|
||
try {
|
||
uni.setStorageSync('videoOssList', JSON.stringify(list))
|
||
} catch (e) {
|
||
console.warn('保存本地播放记录失败:', e)
|
||
}
|
||
}
|
||
isSetFirstTime.value = true
|
||
} catch (error) {
|
||
console.error('配置播放数据失败:', error)
|
||
// 设置默认值
|
||
videoData.value = { ...data, firstTime: 0 }
|
||
firstTime.value = 0
|
||
isSetFirstTime.value = true
|
||
}
|
||
}
|
||
|
||
// 方法: 记录播放时间到本地
|
||
const recordTime = (data: IRecordTimeData) => {
|
||
currentTime.value = data.time
|
||
|
||
let list: any[] = []
|
||
if (uni.getStorageSync('videoOssList')) {
|
||
list = JSON.parse(uni.getStorageSync('videoOssList'))
|
||
}
|
||
|
||
const index = list.findIndex((e) => e.id == videoData.value.id)
|
||
|
||
if (list.length > 0 && index >= 0) {
|
||
list[index] = {
|
||
...videoData.value,
|
||
time: data.time
|
||
}
|
||
} else {
|
||
list.push({
|
||
...videoData.value,
|
||
time: data.time
|
||
})
|
||
}
|
||
|
||
uni.setStorageSync('videoOssList', JSON.stringify(list))
|
||
}
|
||
|
||
// 方法: 获取播放凭证
|
||
const getLive = async (isChangeParam: boolean, newVideoData?: IVideoInfo) => {
|
||
if (reaquestFlag.value) {
|
||
uni.showToast({
|
||
title: '操作太快了,歇一下吧',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
reaquestFlag.value = true
|
||
isfresh.value = false
|
||
|
||
let data: any = { ...options.value }
|
||
if (isChangeParam && newVideoData) {
|
||
data = { ...newVideoData }
|
||
}
|
||
|
||
try {
|
||
const res = await videoApi.checkVideo(data)
|
||
console.log('获取播放凭证成功', res.video)
|
||
reaquestFlag.value = false
|
||
|
||
// iOS 兼容性处理
|
||
if (platform.value === 'ios') {
|
||
if (res.video.type == '1' && (!res.video.m3u8Url || res.video.m3u8Url === '')) {
|
||
show.value = true
|
||
errorTxt.value = '抱歉,苹果手机不支持此加密视频格式'
|
||
|
||
// 记录 iOS 不支持的视频
|
||
try {
|
||
await videoApi.addErrorCourse({
|
||
chapterId: res.video.chapterId || 0,
|
||
videoId: res.video.id,
|
||
sort: res.video.sort || 0
|
||
})
|
||
console.log('记录iOS不支持的视频成功')
|
||
} catch (error) {
|
||
console.log('记录iOS不支持的视频失败:', error)
|
||
}
|
||
|
||
UnlockChangeVideo()
|
||
|
||
uni.showModal({
|
||
content: '抱歉,苹果手机不支持此加密视频格式,您可以在安卓端观看本视频',
|
||
confirmText: '知道了',
|
||
showCancel: false
|
||
})
|
||
return
|
||
}
|
||
}
|
||
|
||
let videoDataTemp: any = { ...res.video }
|
||
|
||
if (res.video.type == '1') {
|
||
const playAuthValue = (res.video.playAuth || '').replace(/=/g, '')
|
||
videoDataTemp = {
|
||
...videoDataTemp,
|
||
videoId: res.video.video || res.video.videoId,
|
||
playAuth: playAuthValue
|
||
}
|
||
playAuth.value = playAuthValue
|
||
await getData(videoDataTemp, isChangeParam)
|
||
} else {
|
||
console.log('普通视频处理', res.video)
|
||
videoDataTemp = {
|
||
...videoDataTemp,
|
||
playAuth: String(new Date().getTime())
|
||
}
|
||
await getData(videoDataTemp, isChangeParam)
|
||
}
|
||
|
||
console.log('视频数据处理完成', videoDataTemp)
|
||
} catch (e) {
|
||
console.error('获取播放凭证失败:', e)
|
||
reaquestFlag.value = false
|
||
show.value = true
|
||
errorTxt.value = '获取播放地址失败'
|
||
}
|
||
}
|
||
|
||
// 方法: 处理播放结束
|
||
const handleEnd = async () => {
|
||
const list = JSON.parse(uni.getStorageSync('videoOssList'))
|
||
const data = list.find((e: any) => e.id == videoData.value.id)
|
||
currentTime.value = data.time
|
||
console.log('this.currentTime at line 这是结束的时候掉的存储视频:', currentTime.value)
|
||
await setVideoTime()
|
||
}
|
||
|
||
// 方法: 保存播放时间到服务器
|
||
const setVideoTime = async (time?: number) => {
|
||
console.log('是否走了存储视屏,' + videoData.value.id, time, currentTime.value)
|
||
const _time = time || currentTime.value
|
||
|
||
const data = {
|
||
videoId: videoData.value.id,
|
||
position: _time
|
||
}
|
||
|
||
try {
|
||
const res = await videoApi.saveCoursePosition(data)
|
||
console.log('存储视屏时长接口返回信息', res)
|
||
} catch (e) {
|
||
console.log('存储进度报错', e)
|
||
}
|
||
}
|
||
|
||
// 方法: 设置初始播放时间
|
||
const setVideoFirtsetTime = async (data: { time: number }) => {
|
||
currentTime.value = firstTime.value
|
||
console.log('setVideoFirtsetTime播放时间:', data.time)
|
||
await setVideoTime(data.time)
|
||
}
|
||
|
||
// 监听 timer 变化
|
||
watch(timer, (newValue) => {
|
||
emit('child-event', newValue)
|
||
})
|
||
|
||
// 生命周期: 挂载
|
||
onMounted(() => {
|
||
console.log('视频播放器组件已挂载')
|
||
|
||
// 获取窗口尺寸
|
||
try {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
winWidth.value = systemInfo.windowWidth
|
||
winHeight.value = systemInfo.windowHeight
|
||
} catch (e) {
|
||
console.warn('获取系统信息失败:', e)
|
||
}
|
||
})
|
||
|
||
// 生命周期: 卸载前
|
||
onBeforeUnmount(async () => {
|
||
console.log('视频播放器组件即将卸载')
|
||
|
||
try {
|
||
// 保存播放进度
|
||
await handleEnd()
|
||
|
||
// 清除定时器
|
||
if (timer.value) {
|
||
clearInterval(timer.value)
|
||
timer.value = null
|
||
}
|
||
|
||
// 恢复屏幕方向
|
||
if (typeof plus !== 'undefined' && plus.screen) {
|
||
plus.screen.lockOrientation('portrait-primary')
|
||
}
|
||
} catch (error) {
|
||
console.error('组件卸载处理失败:', error)
|
||
}
|
||
})
|
||
|
||
// 暴露方法给父组件
|
||
defineExpose({
|
||
init,
|
||
changeVideo,
|
||
replayVideo,
|
||
hideNextVideo,
|
||
loadNextVideo
|
||
})
|
||
</script>
|
||
|
||
|
||
<script module="renderScript" lang="renderjs">
|
||
// RenderJS 模块 - 保持 Vue2 写法
|
||
var videoData = null
|
||
var currentVideoList = null
|
||
var _seconds = 0
|
||
var ReplayVideoFlag = false
|
||
var curStatus = null
|
||
var diff = 0
|
||
var pauseTime = 0
|
||
var myplayer = undefined
|
||
|
||
// jQuery 在 RenderJS 中通过全局变量访问
|
||
var $ = window.jQuery || window.$
|
||
|
||
export default {
|
||
mounted() {
|
||
console.log(this.options, '这是monted')
|
||
this.loadWebPlayerSDK()
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
player: null,
|
||
videoTimer: null
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
handleClick(event, ownerInstance) {
|
||
console.log('是否了走了点击video事件', event)
|
||
},
|
||
|
||
emitData(event, ownerInstance) {
|
||
ownerInstance.callMethod('recordTime', {
|
||
time: _seconds,
|
||
status: curStatus
|
||
})
|
||
},
|
||
|
||
receiveReplayVideoFlag(newValue, oldValue, ownerVm, vm) {
|
||
console.log('newValue重新播放', newValue, myplayer)
|
||
ReplayVideoFlag = newValue
|
||
if (newValue) {
|
||
$('.videoContent8').click()
|
||
}
|
||
},
|
||
|
||
emitReplayVideoFlagFalse(event, ownerInstance) {
|
||
ownerInstance.callMethod('replayVideoFlagFalse')
|
||
},
|
||
|
||
emitUnlockChangeVideo(event, ownerInstance) {
|
||
ownerInstance.callMethod('UnlockChangeVideo')
|
||
},
|
||
|
||
async receiveFirstTime(newValue, oldValue, ownerVm, vm) {
|
||
// 接收 firstTime 变化
|
||
},
|
||
|
||
async receiveisSetFirstTime(newValue, oldValue, ownerVm, vm) {
|
||
console.log('是否刚开始设置播放时间', newValue, this.firstTime, myplayer)
|
||
},
|
||
|
||
emitSetData(event, ownerInstance) {
|
||
ownerInstance.callMethod('setVideoFirtsetTime', {
|
||
time: _seconds
|
||
})
|
||
},
|
||
|
||
emitHideNextVideo(event, ownerInstance) {
|
||
ownerInstance.callMethod('hideNextVideo')
|
||
},
|
||
|
||
emitLoadNextVideo(event, ownerInstance) {
|
||
ownerInstance.callMethod('loadNextVideo')
|
||
},
|
||
|
||
emitopenShow(event, ownerInstance) {
|
||
ownerInstance.callMethod('openShow', {
|
||
msg: '播放出错啦!'
|
||
})
|
||
},
|
||
|
||
// 全屏切换事件
|
||
changeVideoScreen(event, ownerInstance) {
|
||
var status = myplayer.fullscreenService.getIsFullScreen()
|
||
console.log('this.$platform--------', this.platform)
|
||
|
||
if (this.platform != 'ios') {
|
||
ownerInstance.callMethod('screenChange', {
|
||
status: status,
|
||
primary: status ? 'portrait' : 'landscape'
|
||
})
|
||
}
|
||
|
||
if (status) {
|
||
if (this.platform != 'ios') {
|
||
console.log('恢复竖版')
|
||
setTimeout(() => {
|
||
plus.screen.lockOrientation('portrait-primary')
|
||
myplayer.fullscreenService.cancelFullScreen()
|
||
}, 100)
|
||
}
|
||
} else {
|
||
myplayer.fullscreenService.requestFullScreen()
|
||
if (this.platform != 'ios') {
|
||
setTimeout(() => {
|
||
plus.screen.lockOrientation('landscape-primary')
|
||
}, 100)
|
||
} else {
|
||
console.log('不要旋转, 使用原生全屏')
|
||
}
|
||
}
|
||
},
|
||
|
||
changeVideoData(event, ownerInstance) {
|
||
ownerInstance.callMethod('changeVideoData')
|
||
},
|
||
|
||
endEmitData(event, ownerInstance) {
|
||
ownerInstance.callMethod('handleEnd')
|
||
},
|
||
|
||
// renderjs阿里云播放器引入与配置
|
||
getLive() {
|
||
console.log('阿里云播放器引入与配置:', this.firstTime, videoData)
|
||
|
||
$('#url-player-test').empty()
|
||
pauseTime = 0
|
||
|
||
var fullScreenButtonComponent = Aliplayer.Component({
|
||
init: function(status, toAddress) {
|
||
this.fullScreenStatus = status
|
||
this.$html = $('.fullScreenButton-container')
|
||
},
|
||
|
||
createEl: function(el) {
|
||
this.$html.find('.ad').attr('src', this.adAddress)
|
||
var $adWrapper = this.$html.find('.ad-wrapper')
|
||
$adWrapper.attr('href', this.toAddress)
|
||
$adWrapper.click(function() {})
|
||
$(el).find('.prism-time-display').after(this.$html)
|
||
},
|
||
|
||
playing: function(player, e) {
|
||
this.$html.show()
|
||
}
|
||
})
|
||
|
||
var playerOptions = {
|
||
id: 'url-player-test',
|
||
width: '100%',
|
||
height: '100%',
|
||
qualitySort: 'asc',
|
||
cover: '',
|
||
autoplay: true,
|
||
isLive: false,
|
||
rePlay: false,
|
||
playsinline: true,
|
||
controlBarVisibility: 'hover',
|
||
useH5Prism: true,
|
||
components: [
|
||
{
|
||
name: 'adComponent',
|
||
type: fullScreenButtonComponent,
|
||
args: ['http://101.201.146.165:8088/Pf-EH/statics/uploadFile/2024-05-10/b0f420c7-9178-41ad-9dd6-f59a64a6e190.png']
|
||
},
|
||
{
|
||
name: 'RateComponent',
|
||
type: AliPlayerComponent.RateComponent
|
||
}
|
||
],
|
||
skinLayout: [
|
||
{ name: 'bigPlayButton', align: 'blabs', x: 30, y: 80 },
|
||
{ name: 'H5Loading', align: 'cc' },
|
||
{ name: 'errorDisplay', align: 'tlabs', x: 0, y: 0 },
|
||
{ name: 'infoDisplay' },
|
||
{ name: 'tooltip', align: 'blabs', x: 0, y: 56 },
|
||
{ name: 'thumbnail' },
|
||
{
|
||
name: 'controlBar',
|
||
align: 'blabs',
|
||
x: 0,
|
||
y: 0,
|
||
children: [
|
||
{ name: 'progress', align: 'blabs', x: 0, y: 44 },
|
||
{ name: 'playButton', align: 'tl', x: 15, y: 12 },
|
||
{ name: 'timeDisplay', align: 'tl', x: 10, y: 7 },
|
||
{ name: 'prism-speed-selector', align: 'tr', x: 15, y: 12 },
|
||
{ name: 'volume', align: 'tr', x: 5, y: 10 }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
|
||
// 根据视频类型配置播放器
|
||
console.log('视频类型判断:', 'type=', videoData.type, 'm3u8Url=', videoData.m3u8Url, 'videoUrl=', videoData.videoUrl)
|
||
|
||
if (videoData.type == 1) {
|
||
if (videoData.m3u8Url == null || videoData.m3u8Url == '') {
|
||
console.log('这是私有加密的视频')
|
||
if (this.platform == 'ios') {
|
||
$('.videoContent5').click()
|
||
} else {
|
||
playerOptions = {
|
||
...playerOptions,
|
||
vid: videoData.videoId,
|
||
playauth: videoData.playAuth,
|
||
encryptType: 1,
|
||
playConfig: {
|
||
EncryptType: 'AliyunVoDEncryption'
|
||
}
|
||
}
|
||
console.log('配置私有加密播放器:', playerOptions)
|
||
}
|
||
} else if (videoData.m3u8Url != null && videoData.m3u8Url != '') {
|
||
playerOptions = {
|
||
...playerOptions,
|
||
source: videoData.m3u8Url
|
||
}
|
||
console.log('这是标准加密的视频', videoData.id, videoData.m3u8Url)
|
||
console.log('播放器配置:', playerOptions)
|
||
}
|
||
} else {
|
||
playerOptions = {
|
||
...playerOptions,
|
||
source: videoData.videoUrl
|
||
}
|
||
console.log('这是没有加密的视频')
|
||
}
|
||
|
||
var player = new Aliplayer(playerOptions, function(player) {})
|
||
this.player = player
|
||
myplayer = player
|
||
|
||
// 播放器事件监听
|
||
player.on('ready', function() {
|
||
console.log('播放器准备就绪,开始播放')
|
||
player.play()
|
||
$('.videoContent9').click()
|
||
})
|
||
|
||
player.on('play', function() {
|
||
var videoDurationTimes = parseInt(player.getDuration())
|
||
console.log('开始播放------', videoDurationTimes, pauseTime)
|
||
$('.videoContent7').click()
|
||
|
||
if (pauseTime > 0) {
|
||
if (pauseTime == videoDurationTimes) {
|
||
return
|
||
} else {
|
||
player.seek(pauseTime)
|
||
}
|
||
}
|
||
})
|
||
|
||
player.one('canplay', function() {
|
||
var videoDurationTimes = parseInt(player.getDuration())
|
||
console.log('视频总长度', parseInt(player.getDuration()), parseInt(player.getCurrentTime()))
|
||
if (videoData.firstTime < videoDurationTimes) {
|
||
player.seek(videoData.firstTime)
|
||
} else {
|
||
player.seek(0)
|
||
}
|
||
})
|
||
|
||
myplayer.on('playing', function() {
|
||
console.log('正在播放...')
|
||
})
|
||
|
||
myplayer.on('timeupdate', function() {
|
||
var _time = parseInt(player.getCurrentTime())
|
||
curStatus = player.getStatus()
|
||
|
||
if (_seconds != _time) {
|
||
_seconds = _time
|
||
diff++
|
||
if (diff % 60 === 0) {
|
||
console.log('符合---------')
|
||
$('.videoContent4').click()
|
||
diff = 0
|
||
}
|
||
$('.videoContent1').click()
|
||
}
|
||
})
|
||
|
||
myplayer.on('ended', function() {
|
||
console.log('播放完毕')
|
||
$('.videoContent2').click()
|
||
$('.videoContent6').click()
|
||
})
|
||
|
||
player.on('pause', function() {
|
||
pauseTime = parseInt(player.getCurrentTime())
|
||
player.pause(true)
|
||
console.log('触发暂停', pauseTime)
|
||
})
|
||
|
||
myplayer.on('error', function() {
|
||
console.log('播放出错')
|
||
$('.videoContent5').click()
|
||
})
|
||
},
|
||
|
||
async receiveIsfresh(newValue) {
|
||
console.log('是否走了刷新销毁方法:', myplayer)
|
||
if (myplayer) {
|
||
myplayer.dispose()
|
||
}
|
||
},
|
||
|
||
async receiveplatform(newValue) {
|
||
// 接收 platform 变化
|
||
},
|
||
|
||
async receiveIsChange(newValue) {
|
||
console.log('receiveIsChange 触发:', newValue, 'videoData:', videoData, 'currentVideoList:', currentVideoList)
|
||
if (newValue) {
|
||
// 检查数据是否准备好
|
||
if (videoData && videoData.playAuth && currentVideoList) {
|
||
console.log('数据已准备好,开始播放')
|
||
this.getLive()
|
||
} else {
|
||
console.log('数据未准备好,等待...', 'videoData:', !!videoData, 'playAuth:', !!videoData?.playAuth, 'currentVideoList:', !!currentVideoList)
|
||
}
|
||
}
|
||
},
|
||
|
||
receiveVideoList(newValue, oldValue, ownerVm, vm) {
|
||
console.log('receiveVideoList 接收到视频列表:', newValue)
|
||
currentVideoList = newValue
|
||
// 只赋值,不触发播放,等待 isChange 触发
|
||
},
|
||
|
||
receiveMsg(newValue, oldValue, ownerVm, vm) {
|
||
console.log('receiveMsg 接收到新数据:', newValue)
|
||
videoData = newValue
|
||
// 只赋值,不触发播放,等待 isChange 触发
|
||
},
|
||
|
||
receiveWinWidth(newValue, oldValue, ownerVm, vm) {
|
||
console.log('newValue', newValue)
|
||
},
|
||
|
||
receiveWinHeight(newValue, oldValue, ownerVm, vm) {
|
||
console.log('newValue', newValue)
|
||
},
|
||
|
||
checkValue() {
|
||
console.log('checkValue 检查:', 'videoData=', videoData, 'currentVideoList=', currentVideoList)
|
||
// 不再无限循环检查,而是等待 receiveMsg 和 receiveVideoList 触发
|
||
if (videoData && videoData.playAuth && currentVideoList && currentVideoList.length > 0) {
|
||
console.log('数据已准备好,开始播放')
|
||
this.getLive()
|
||
} else {
|
||
console.log('等待数据准备...')
|
||
}
|
||
},
|
||
|
||
loadWebPlayerSDK() {
|
||
return new Promise((resolve, reject) => {
|
||
// 先加载 jQuery
|
||
if (!window.jQuery && !window.$) {
|
||
const jquery_tag = document.createElement('script')
|
||
jquery_tag.type = 'text/javascript'
|
||
jquery_tag.src = 'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js'
|
||
jquery_tag.charset = 'utf-8'
|
||
jquery_tag.onload = () => {
|
||
// jQuery 加载完成后,更新全局变量
|
||
$ = window.jQuery || window.$
|
||
this.loadAliPlayerSDK(resolve, reject)
|
||
}
|
||
jquery_tag.onerror = () => {
|
||
console.error('jQuery 加载失败')
|
||
reject(new Error('jQuery 加载失败'))
|
||
}
|
||
document.body.appendChild(jquery_tag)
|
||
} else {
|
||
// jQuery 已存在
|
||
$ = window.jQuery || window.$
|
||
this.loadAliPlayerSDK(resolve, reject)
|
||
}
|
||
})
|
||
},
|
||
|
||
loadAliPlayerSDK(resolve, reject) {
|
||
const s_tag = document.createElement('script')
|
||
s_tag.type = 'text/javascript'
|
||
s_tag.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/aliplayer-min.js'
|
||
s_tag.charset = 'utf-8'
|
||
s_tag.onload = () => {
|
||
const s_tag1 = document.createElement('script')
|
||
s_tag1.type = 'text/javascript'
|
||
s_tag1.src = 'https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js'
|
||
s_tag1.charset = 'utf-8'
|
||
s_tag1.onload = () => {
|
||
this.checkValue()
|
||
resolve()
|
||
}
|
||
s_tag1.onerror = () => {
|
||
console.error('阿里云播放器组件加载失败')
|
||
reject(new Error('阿里云播放器组件加载失败'))
|
||
}
|
||
document.body.appendChild(s_tag1)
|
||
}
|
||
s_tag.onerror = () => {
|
||
console.error('阿里云播放器 SDK 加载失败')
|
||
reject(new Error('阿里云播放器 SDK 加载失败'))
|
||
}
|
||
document.body.appendChild(s_tag)
|
||
|
||
const l_tag = document.createElement('link')
|
||
l_tag.rel = 'stylesheet'
|
||
l_tag.href = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/skins/default/aliplayer-min.css'
|
||
document.body.appendChild(l_tag)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.cancelNext {
|
||
display: inline-block;
|
||
margin-right: 20rpx;
|
||
border-radius: 10rpx;
|
||
margin-top: 10rpx;
|
||
padding: 10rpx 20rpx !important;
|
||
background-color: #fff !important;
|
||
color: #000;
|
||
text-align: center;
|
||
line-height: 50rpx;
|
||
}
|
||
|
||
.showCountDownd {
|
||
box-sizing: border-box;
|
||
height: 100%;
|
||
width: 100%;
|
||
background-color: rgba(0, 0, 0, 0.6);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
color: #fff;
|
||
font-size: 38rpx;
|
||
text-align: center;
|
||
position: absolute;
|
||
top: 0;
|
||
right: 10rpx;
|
||
z-index: 4;
|
||
}
|
||
|
||
.container {
|
||
width: 100vw;
|
||
height: auto;
|
||
}
|
||
|
||
.fullScreenButton-container {
|
||
color: #fff;
|
||
float: right;
|
||
height: 35px;
|
||
margin-top: 6px;
|
||
margin-right: 5px;
|
||
display: flex;
|
||
align-items: center;
|
||
position: relative;
|
||
}
|
||
</style>
|