ps-tcplayer
Version:
Tencent Cloud Player component with Vue2/Vue3 compatibility
190 lines (158 loc) • 5.13 kB
text/typescript
import { createApp, h } from 'vue-demi'
import tcplayer from './tcplayer.vue'
import TcPlayerComponent from './tccomponents'
import { version, isVue2, isVue3 } from 'vue-demi'
interface InstanceData {
app: any
vm: any
mountEl: HTMLElement
container: Element
config: any
playerReady: boolean
readyCallbacks: Function[]
playerInstance: any
}
class TcPlayerSDK {
static version = version
static TcPlayerComponent = TcPlayerComponent
static isVue2 = isVue2
static isVue3 = isVue3
private static instances: Record<string, InstanceData> = {}
static init(selector: string, config: any = {}) {
if (!selector) {
console.error('TcPlayerSDK: 必须提供有效的DOM选择器')
return null
}
const container = document.querySelector(selector)
if (!container) {
console.error(`TcPlayerSDK: 无法找到指定的DOM元素: ${selector}`)
return null
}
const instanceId = `tcplayer-${Date.now()}-${Math.floor(Math.random() * 1000)}`
const mountEl = document.createElement('div')
mountEl.style.width = '100%'
mountEl.style.height = '100%'
container.appendChild(mountEl)
// 添加播放器就绪状态追踪
const instanceData: InstanceData = {
app: null,
vm: null,
mountEl,
container,
config,
playerReady: false,
readyCallbacks: [],
playerInstance: null
}
const app = createApp({
render() {
return h(tcplayer, {
config: {
...config,
onready: (player: any) => {
// 播放器准备就绪时执行
console.log('播放器准备就绪,更新实例状态')
instanceData.playerReady = true
instanceData.playerInstance = player
// 执行所有等待的回调
instanceData.readyCallbacks.forEach(callback => {
try {
callback(player)
} catch (error) {
console.error('播放器就绪回调执行失败:', error)
}
})
instanceData.readyCallbacks = []
// 调用用户原始的onready回调
if (config.onready) {
config.onready(player)
}
}
}
})
}
})
const vm = app.mount(mountEl)
instanceData.app = app
instanceData.vm = vm
this.instances[instanceId] = instanceData
return instanceId
}
static destroy(instanceId: string) {
const instance = this.instances[instanceId]
if (!instance) {
console.warn(`TcPlayerSDK: 找不到ID为 ${instanceId} 的实例`)
return false
}
instance.app.unmount()
if (instance.mountEl && instance.mountEl.parentNode) {
instance.mountEl.parentNode.removeChild(instance.mountEl)
}
delete this.instances[instanceId]
return true
}
static getInstance(instanceId: string) {
return this.instances[instanceId] || null
}
static getAllInstances() {
return Object.keys(this.instances)
}
// 获取播放器实例(可能为空)
static getPlayer(instanceId: string): any {
const instance = this.instances[instanceId]
if (!instance) {
return null
}
// 如果播放器已经准备就绪,直接返回
if (instance.playerReady && instance.playerInstance) {
return instance.playerInstance
}
// 尝试从Vue组件实例中获取
try {
if (instance.vm && instance.vm.$player) {
return instance.vm.$player
}
// Vue 3 Composition API方式
if (instance.vm && instance.vm._ && instance.vm._.$player) {
return instance.vm._.$player
}
} catch (error) {
console.warn('无法从Vue实例获取播放器:', error)
}
return null
}
// 等待播放器就绪(返回Promise)
static waitForPlayerReady(instanceId: string): Promise<any> {
return new Promise((resolve, reject) => {
const instance = this.instances[instanceId]
if (!instance) {
reject(new Error(`找不到ID为 ${instanceId} 的实例`))
return
}
// 如果播放器已经准备就绪,立即返回
if (instance.playerReady && instance.playerInstance) {
resolve(instance.playerInstance)
return
}
// 添加到等待队列
instance.readyCallbacks.push(resolve)
// 设置超时
setTimeout(() => {
const index = instance.readyCallbacks.indexOf(resolve)
if (index > -1) {
instance.readyCallbacks.splice(index, 1)
reject(new Error('等待播放器就绪超时'))
}
}, 10000) // 10秒超时
})
}
// 检查播放器是否就绪
static isPlayerReady(instanceId: string): boolean {
const instance = this.instances[instanceId]
return instance ? instance.playerReady : false
}
}
if (typeof window !== 'undefined') {
(window as any).PsTcPlayer = TcPlayerSDK
}
export default TcPlayerSDK