mirror of
https://github.com/cuiocean/ZY-Player.git
synced 2026-02-10 22:15:12 +08:00
@@ -33,7 +33,7 @@
|
||||
"vue-infinite-loading": "^2.4.5",
|
||||
"vue-waterfall-plugin": "^1.0.7",
|
||||
"vuex": "^3.4.0",
|
||||
"xgplayer": "^2.9.8",
|
||||
"xgplayer": "^2.9.10",
|
||||
"xgplayer-hls.js": "^2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
<template>
|
||||
<div class="frame">
|
||||
<span class="min" @click="frameClickEvent('min')"></span>
|
||||
<span class="max" @click="frameClickEvent('max')"></span>
|
||||
<span class="close" @click="frameClickEvent('close')"></span>
|
||||
<span class="min" @click="frameClickEvent('min')" title="最小化">
|
||||
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:8px;height:14px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="max" @click="frameClickEvent('max')" title="最大化">
|
||||
<svg t="1595917343956" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1540" style="width:8px;height:14px"><path d="M416 416 64.064 416C28.448 416 0 444.64 0 479.936L0 544.064C0 579.264 28.672 608 64.064 608L416 608 416 959.936C416 995.552 444.64 1024 479.936 1024L544.064 1024C579.264 1024 608 995.328 608 959.936L608 608 959.936 608C995.552 608 1024 579.36 1024 544.064L1024 479.936C1024 444.736 995.328 416 959.936 416L608 416 608 64.064C608 28.448 579.36 0 544.064 0L479.936 0C444.736 0 416 28.672 416 64.064L416 416Z" p-id="1541" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="close" @click="frameClickEvent('close')" title="关闭">
|
||||
<svg t="1595917372551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" style="width:8px;height:14px"><path d="M511.968 376.224 796.096 92.096C833.536 54.624 894.4 54.624 931.84 92.096 969.312 129.568 969.312 190.4 931.84 227.872L647.744 512 931.84 796.096C969.312 833.568 969.312 894.4 931.84 931.872 894.4 969.344 833.536 969.344 796.096 931.872L511.968 647.744 227.84 931.872C190.4 969.344 129.536 969.344 92.096 931.872 54.624 894.4 54.624 833.568 92.096 796.096L376.224 512 92.096 227.872C54.624 190.4 54.624 129.568 92.096 92.096 129.536 54.624 190.4 54.624 227.84 92.096L511.968 376.224Z" p-id="1686" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="top" @click="frameClickEvent('top')" title="置顶">
|
||||
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:10px;height:14px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const { remote } = require('electron')
|
||||
export default {
|
||||
name: 'frame',
|
||||
data () {
|
||||
const win = remote.getCurrentWindow()
|
||||
return {
|
||||
isAlwaysOnTop: win.isAlwaysOnTop()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
frameClickEvent (e) {
|
||||
const win = remote.getCurrentWindow()
|
||||
@@ -21,6 +36,10 @@ export default {
|
||||
if (e === 'close') {
|
||||
win.destroy()
|
||||
}
|
||||
if (e === 'top') {
|
||||
this.isAlwaysOnTop = !this.isAlwaysOnTop
|
||||
win.setAlwaysOnTop(this.isAlwaysOnTop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +59,8 @@ export default {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
display: inline-block;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
@@ -85,13 +85,14 @@
|
||||
</div>
|
||||
<div class="list-body zy-scroll" :style="{overflowY:scroll? 'auto' : 'hidden',paddingRight: scroll ? '0': '5px' }" @mouseenter="scroll = true" @mouseleave="scroll = false">
|
||||
<ul v-show="right.type === 'list'" class="list-item">
|
||||
<li v-show="right.history.length > 1" @click="exportM3u8">导出</li>
|
||||
<li v-show="right.list.length === 0">无数据</li>
|
||||
<li @click="listItemEvent(j)" :class="video.info.index === j ? 'active' : ''" v-for="(i, j) in right.list" :key="j">{{i | ftName(j)}}</li>
|
||||
</ul>
|
||||
<ul v-show="right.type === 'history'" class="list-history">
|
||||
<li v-show="right.history.length > 1" @click="clearAllHistory">清空</li>
|
||||
<li v-show="right.history.length === 0">无数据</li>
|
||||
<li @click="historyItemEvent(m)" :class="video.info.id === m.ids ? 'active' : ''" v-for="(m, n) in right.history" :key="n"><span class="title">{{m.name}}</span><span @click.stop="removeHistoryItem(m)" class="detail-delete">删除</span></li>
|
||||
<li @click="historyItemEvent(m)" :class="video.info.id === m.ids ? 'active' : ''" v-for="(m, n) in right.history" :key="n"><span class="title" :title="'【' + m.site + '】' + m.name + ' 第' + (m.index+1) + '集'">【{{m.site}}】{{m.name}} 第{{m.index+1}}集</span><span @click.stop="removeHistoryItem(m)" class="detail-delete">删除</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,10 +103,54 @@
|
||||
import { mapMutations } from 'vuex'
|
||||
import { star, history, setting, shortcut, mini } from '../lib/dexie'
|
||||
import zy from '../lib/site/tools'
|
||||
import 'xgplayer'
|
||||
import Player from 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
import mt from 'mousetrap'
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
|
||||
const VIDEO_DETAIL_CACHE = {}
|
||||
|
||||
const addPlayerBtn = function (event, svg, attrs) {
|
||||
const player = this
|
||||
const util = Player.util
|
||||
const controlEl = player.controls
|
||||
const btnConfig = player.config[event]
|
||||
if (btnConfig) {
|
||||
const btnName = 'xg-btn-' + event
|
||||
const btn = util.createDom(btnName, svg || btnConfig.svg, attrs || {}, btnName)
|
||||
controlEl.appendChild(btn)
|
||||
const ev = ['click', 'touchend']
|
||||
ev.forEach(item => {
|
||||
btn.addEventListener(item, function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
player.emit(event)
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const addPlayerView = function (event, tpl, attrs) {
|
||||
const player = this
|
||||
console.log(player)
|
||||
const util = Player.util
|
||||
const rootEl = player.root
|
||||
const viewConfig = player.config[event]
|
||||
if (viewConfig) {
|
||||
const viewName = 'xg-view-' + event
|
||||
const view = util.createDom(viewName, tpl, attrs || {}, viewName)
|
||||
rootEl.appendChild(view)
|
||||
const ev = ['click', 'touchend']
|
||||
ev.forEach(item => {
|
||||
view.addEventListener(item, function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
player.emit(event)
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'play',
|
||||
data () {
|
||||
@@ -130,7 +175,16 @@ export default {
|
||||
crossOrigin: true,
|
||||
cssFullscreen: true,
|
||||
defaultPlaybackRate: 1,
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5]
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5],
|
||||
playPrev: true,
|
||||
playNextOne: true,
|
||||
showList: true,
|
||||
showHistory: true,
|
||||
videoTitle: true
|
||||
},
|
||||
state: {
|
||||
showList: false,
|
||||
showHistory: false
|
||||
},
|
||||
name: '',
|
||||
length: 0,
|
||||
@@ -205,6 +259,17 @@ export default {
|
||||
this.changeSetting()
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
name () {
|
||||
const span = document.querySelector('.xg-view-videoTitle span')
|
||||
if (!span) {
|
||||
return
|
||||
}
|
||||
if (this.right.list.length > 1) {
|
||||
span.innerText = `『第 ${this.video.info.index + 1} 集』${this.name}`
|
||||
} else {
|
||||
span.innerText = `${this.name}`
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -234,36 +299,7 @@ export default {
|
||||
})
|
||||
},
|
||||
playVideo (index = 0, time = 0) {
|
||||
const id = this.video.info.id
|
||||
zy.detail(this.video.key, id).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._t.indexOf('m3u8') >= 0) {
|
||||
m3u8Txt = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Txt = dd._t.split('#')
|
||||
}
|
||||
this.right.list = m3u8Txt
|
||||
const m3u8Arr = []
|
||||
for (const i of m3u8Txt) {
|
||||
const j = i.split('$')
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('m3u8') >= 0) {
|
||||
m3u8Arr.push(j[m])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
|
||||
this.fetchM3u8List().then(m3u8Arr => {
|
||||
this.xg.src = m3u8Arr[index]
|
||||
this.showNext = m3u8Arr.length > 1
|
||||
|
||||
@@ -285,6 +321,102 @@ export default {
|
||||
this.xg.off('ended')
|
||||
})
|
||||
})
|
||||
// const id = this.video.info.id
|
||||
// zy.detail(this.video.key, id).then(res => {
|
||||
// this.name = res.name
|
||||
// const dd = res.dl.dd
|
||||
// const type = Object.prototype.toString.call(dd)
|
||||
// let m3u8Txt = []
|
||||
// if (type === '[object Array]') {
|
||||
// for (const i of dd) {
|
||||
// if (i._t.indexOf('m3u8') >= 0) {
|
||||
// m3u8Txt = i._t.split('#')
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Txt = dd._t.split('#')
|
||||
// }
|
||||
// this.right.list = m3u8Txt
|
||||
// const m3u8Arr = []
|
||||
// for (const i of m3u8Txt) {
|
||||
// const j = i.split('$')
|
||||
// if (j.length > 1) {
|
||||
// for (let m = 0; m < j.length; m++) {
|
||||
// if (j[m].indexOf('m3u8') >= 0) {
|
||||
// m3u8Arr.push(j[m])
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Arr.push(j[0])
|
||||
// }
|
||||
// }
|
||||
|
||||
// this.xg.src = m3u8Arr[index]
|
||||
// this.showNext = m3u8Arr.length > 1
|
||||
|
||||
// if (time !== 0) {
|
||||
// this.xg.play()
|
||||
// this.xg.once('playing', () => {
|
||||
// this.xg.currentTime = time
|
||||
// })
|
||||
// } else {
|
||||
// this.xg.play()
|
||||
// }
|
||||
|
||||
// this.videoPlaying()
|
||||
// this.xg.once('ended', () => {
|
||||
// if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
|
||||
// this.video.info.time = 0
|
||||
// this.video.info.index++
|
||||
// }
|
||||
// this.xg.off('ended')
|
||||
// })
|
||||
// })
|
||||
},
|
||||
fetchM3u8List () {
|
||||
return new Promise((resolve) => {
|
||||
const cacheKey = this.video.key + '@' + this.video.info.id
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey]) {
|
||||
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
|
||||
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
|
||||
return
|
||||
}
|
||||
zy.detail(this.video.key, this.video.info.id).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._t.indexOf('m3u8') >= 0) {
|
||||
m3u8Txt = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Txt = dd._t.split('#')
|
||||
}
|
||||
this.right.list = m3u8Txt
|
||||
const m3u8Arr = []
|
||||
for (const i of m3u8Txt) {
|
||||
const j = i.split('$')
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('m3u8') >= 0) {
|
||||
m3u8Arr.push(j[m])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = {
|
||||
list: m3u8Arr,
|
||||
name: res.name
|
||||
}
|
||||
resolve(m3u8Arr)
|
||||
})
|
||||
})
|
||||
},
|
||||
videoPlaying () {
|
||||
this.changeVideo()
|
||||
@@ -456,6 +588,47 @@ export default {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
exportM3u8 () {
|
||||
const m3u8Arr = []
|
||||
for (const i of this.right.list) {
|
||||
const j = i.split('$')
|
||||
let link, name
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('m3u8') >= 0) {
|
||||
link = j[m]
|
||||
}
|
||||
}
|
||||
name = j[0]
|
||||
} else {
|
||||
name = `第${m3u8Arr.length + 1}集`
|
||||
link = j[0]
|
||||
}
|
||||
m3u8Arr.push({
|
||||
name: name,
|
||||
link: link
|
||||
})
|
||||
}
|
||||
|
||||
console.log(m3u8Arr)
|
||||
|
||||
let m3u8Content = `#EXTM3U
|
||||
`
|
||||
for (const item of m3u8Arr) {
|
||||
m3u8Content += `#EXTINF:-1, ${item.name}
|
||||
${item.link}
|
||||
`
|
||||
}
|
||||
const blob = new Blob([m3u8Content], { type: 'application/vnd.apple.mpegurl' })
|
||||
const downloadElement = document.createElement('a') // 创建下载的链接
|
||||
const href = window.URL.createObjectURL(blob)
|
||||
downloadElement.href = href
|
||||
downloadElement.download = `${this.name}.m3u8` // 下载后的文件名
|
||||
document.body.appendChild(downloadElement)
|
||||
downloadElement.click() // 下载
|
||||
document.body.removeChild(downloadElement) // 下载完成 移除 a
|
||||
window.URL.revokeObjectURL(href) // 释放blob对象
|
||||
},
|
||||
clearAllHistory () {
|
||||
history.clear().then(res => {
|
||||
this.right.history = []
|
||||
@@ -570,8 +743,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'escape') {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
if (this.xg.fullscreen) {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'next') {
|
||||
@@ -636,6 +811,133 @@ export default {
|
||||
},
|
||||
changeSetting () {
|
||||
this.mtEvent()
|
||||
},
|
||||
toggleList () {
|
||||
if (this.state.showList) {
|
||||
document.querySelector('xg-btn-showlist ul').style.display = 'none'
|
||||
this.state.showList = false
|
||||
} else {
|
||||
this.refreshList()
|
||||
document.querySelector('xg-btn-showlist ul').style.display = 'block'
|
||||
this.state.showList = true
|
||||
}
|
||||
},
|
||||
refreshList () {
|
||||
let ul = document.querySelector('xg-btn-showlist ul')
|
||||
if (!ul) {
|
||||
ul = document.createElement('ul')
|
||||
document.querySelector('xg-btn-showlist').appendChild(ul)
|
||||
ul.addEventListener('click', (ev) => {
|
||||
ev = ev || window.event
|
||||
const target = ev.target || ev.srcElement // target表示在事件冒泡中触发事件的源元素,在IE中是srcElement
|
||||
if (target.nodeName.toLowerCase() === 'li') {
|
||||
this.listItemEvent(parseInt(target.dataset.index))
|
||||
}
|
||||
})
|
||||
}
|
||||
ul.style.display = 'none'
|
||||
let li = ''
|
||||
if (this.right.list.length === 0) {
|
||||
li = '<li>无数据</li>'
|
||||
} else {
|
||||
for (let index = 0; index < this.right.list.length; index++) {
|
||||
const item = this.right.list[index]
|
||||
const num = item.split('$')
|
||||
let title
|
||||
if (num.length > 1) {
|
||||
title = num[0]
|
||||
} else {
|
||||
title = `第${(index + 1)}集`
|
||||
}
|
||||
if (index === this.video.info.index) {
|
||||
li += `<li class="selected" data-index="${index}" title="${title}">${title}</li>`
|
||||
} else {
|
||||
li += `<li data-index="${index}" title="${title}">${title}</li>`
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.innerHTML = li
|
||||
},
|
||||
toggleHistory () {
|
||||
if (this.state.showHistory) {
|
||||
document.querySelector('xg-btn-showhistory ul').style.display = 'none'
|
||||
this.state.showHistory = false
|
||||
} else {
|
||||
this.refreshHistory()
|
||||
document.querySelector('xg-btn-showhistory ul').style.display = 'block'
|
||||
this.state.showHistory = true
|
||||
}
|
||||
},
|
||||
refreshHistory () {
|
||||
let ul = document.querySelector('xg-btn-showhistory ul')
|
||||
if (!ul) {
|
||||
ul = document.createElement('ul')
|
||||
document.querySelector('xg-btn-showhistory').appendChild(ul)
|
||||
ul.addEventListener('click', (ev) => {
|
||||
ev = ev || window.event
|
||||
const target = ev.target || ev.srcElement // target表示在事件冒泡中触发事件的源元素,在IE中是srcElement
|
||||
if (target.nodeName.toLowerCase() === 'li') {
|
||||
this.historyItemEvent(this.right.history[parseInt(target.dataset.index)])
|
||||
}
|
||||
})
|
||||
}
|
||||
ul.style.display = 'none'
|
||||
let li = ''
|
||||
if (this.right.history.length === 0) {
|
||||
li = '<li>无数据</li>'
|
||||
} else {
|
||||
window.historyItemEvent = this.historyItemEvent.bind(this)
|
||||
for (let index = 0; index < this.right.history.length; index++) {
|
||||
const item = this.right.history[index]
|
||||
const text = `【${item.site}】${item.name} 第${item.index + 1}集`
|
||||
if (this.video.info.id === item.ids) {
|
||||
li += `<li class="selected" data-index="${index}" title="${text}">${text}</li>`
|
||||
} else {
|
||||
li += `<li data-index="${index}" title="${text}">${text}</li>`
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.innerHTML = li
|
||||
},
|
||||
bindEvent () {
|
||||
this.xg.on('playNextOne', () => {
|
||||
this.nextEvent()
|
||||
})
|
||||
|
||||
this.xg.on('playPrev', () => {
|
||||
this.prevEvent()
|
||||
})
|
||||
|
||||
this.xg.on('showList', () => {
|
||||
this.toggleList()
|
||||
})
|
||||
|
||||
this.xg.on('showHistory', () => {
|
||||
this.toggleHistory()
|
||||
})
|
||||
|
||||
const ev = ['click', 'touchend', 'mousemove']
|
||||
let timerID
|
||||
ev.forEach(item => {
|
||||
this.xg.root.addEventListener(item, () => {
|
||||
if (!this.xg.fullscreen) {
|
||||
return
|
||||
}
|
||||
const videoTitle = document.querySelector('.xg-view-videoTitle')
|
||||
videoTitle.style.display = 'block'
|
||||
clearTimeout(timerID)
|
||||
timerID = setTimeout(() => {
|
||||
// 播放中自动消失
|
||||
if (this.xg && !this.xg.paused) {
|
||||
videoTitle.style.display = 'none'
|
||||
}
|
||||
}, 3000)
|
||||
})
|
||||
})
|
||||
|
||||
this.xg.on('exitFullscreen', () => {
|
||||
document.querySelector('.xg-view-videoTitle').style.display = 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
@@ -643,18 +945,184 @@ export default {
|
||||
this.mtEvent()
|
||||
},
|
||||
mounted () {
|
||||
console.log(this)
|
||||
Player.install('playPrev', function () {
|
||||
addPlayerBtn.bind(this, 'playPrev', '<svg t="1595866093990" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3657" style="width: 20px;height: 20px;margin-top: 11px;margin-left: 9px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M98.583851 3.180124h190.807453a31.801242 31.801242 0 0 1 31.801243 31.801242v387.021118L902.201242 10.176398l11.130435-7.632299A31.801242 31.801242 0 0 1 957.217391 31.801242v960.397516a31.801242 31.801242 0 0 1-43.885714 29.257143l-11.130435-7.632299L321.192547 601.997516V989.018634a31.801242 31.801242 0 0 1-31.801243 31.801242H98.583851a31.801242 31.801242 0 0 1-31.801242-31.801242v-954.037268a31.801242 31.801242 0 0 1 31.801242-31.801242z" p-id="3658" fill="#ffffff"></path></svg>', { title: '上一集' })()
|
||||
})
|
||||
Player.install('playNextOne', function () {
|
||||
addPlayerBtn.bind(this, 'playNextOne', '<svg t="1595866110378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3946" style="width: 20px;height: 20px;margin-top: 11px;margin-left: 0px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M925.416149 3.180124h-190.807453a31.801242 31.801242 0 0 0-31.801243 31.801242v387.021118L121.798758 10.176398 110.668323 2.544099A31.801242 31.801242 0 0 0 98.583851 0a31.801242 31.801242 0 0 0-31.801242 31.801242v960.397516a31.801242 31.801242 0 0 0 31.801242 31.801242 31.801242 31.801242 0 0 0 12.084472-2.544099l11.130435-7.632299L702.807453 601.997516V989.018634a31.801242 31.801242 0 0 0 31.801243 31.801242h190.807453a31.801242 31.801242 0 0 0 31.801242-31.801242v-954.037268a31.801242 31.801242 0 0 0-31.801242-31.801242z" p-id="3947" fill="#ffffff"></path></svg>', { title: '下一集' })()
|
||||
})
|
||||
Player.install('showList', function () {
|
||||
addPlayerBtn.bind(this, 'showList', '<svg t="1595866128681" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M0 0h1316.571429v146.285714H0zM0 438.857143h1316.571429v146.285714H0zM0 877.714286h1316.571429v146.285714H0z" p-id="4188" fill="#ffffff"></path></svg>', { title: '播放列表' })()
|
||||
})
|
||||
Player.install('showHistory', function () {
|
||||
addPlayerBtn.bind(this, 'showHistory', '<svg t="1595866015473" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3282" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m0 910.222222a398.222222 398.222222 0 1 1 398.222222-398.222222 398.222222 398.222222 0 0 1-398.222222 398.222222z" p-id="3283" fill="#ffffff"></path><path d="M568.888889 227.555556h-113.777778v341.333333h227.555556v-113.777778h-113.777778V227.555556z" p-id="3284" fill="#ffffff"></path></svg>', { title: '播放历史' })()
|
||||
})
|
||||
const that = this
|
||||
Player.install('videoTitle', function () {
|
||||
let title
|
||||
if (that.right.list.length > 1) {
|
||||
title = `『第 ${that.video.info.index + 1} 集』${that.name}`
|
||||
} else {
|
||||
title = `${that.name}`
|
||||
}
|
||||
addPlayerView.bind(this, 'videoTitle', `<span>${title}</span>`, {})()
|
||||
})
|
||||
|
||||
this.xg = new Hls(this.config)
|
||||
ipcRenderer.on('miniClosed', () => {
|
||||
this.xg.destroy()
|
||||
this.xg = new Hls(this.config)
|
||||
this.getUrls()
|
||||
// this.xg.destroy()
|
||||
// this.xg = new Hls(this.config)
|
||||
// this.bindEvent()
|
||||
// 同步进度
|
||||
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
|
||||
if (res) {
|
||||
if (this.video.info.index !== res.index) {
|
||||
this.video.info.index = res.index
|
||||
} else {
|
||||
this.getUrls()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
this.bindEvent()
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.xgplayer-skin-default .xg-btn-playPrev {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 0;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 0;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playPrev:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playNextOne {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 2;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 2;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playNextOne:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-play, .xgplayer-skin-default .xgplayer-play-img {
|
||||
order: 1 !important;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 4;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 4;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showHistory {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 4;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 4;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showHistory:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul, .xgplayer-skin-default .xg-btn-showHistory ul {
|
||||
display: none;
|
||||
list-style: none;
|
||||
min-width: 85px;
|
||||
max-width: 300px;
|
||||
max-height: 60vh;
|
||||
overflow-y: scroll;
|
||||
background: rgba(0,0,0,.54);
|
||||
border-radius: 1px;
|
||||
position: absolute;
|
||||
bottom: 45px;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
z-index: 26;
|
||||
cursor: pointer;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li, .xgplayer-skin-default .xg-btn-showHistory ul li {
|
||||
opacity: .7;
|
||||
font-family: PingFangSC-Regular;
|
||||
font-size: 13px;
|
||||
color: hsla(0,0%,100%,.8);
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li:first-child, .xgplayer-skin-default .xg-btn-showHistory ul li:first-child {
|
||||
position: relative;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li:last-child, .xgplayer-skin-default .xg-btn-showHistory ul li:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li.selected, .xgplayer-skin-default .xg-btn-showHistory ul li.selected, .xgplayer-skin-default .xg-btn-showList ul li:hover, .xgplayer-skin-default .xg-btn-showHistory ul li:hover {
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-volume {
|
||||
width: 32px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate {
|
||||
width: 40px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate .name {
|
||||
top: 10px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate ul {
|
||||
bottom: 25px;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate ul li {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-screenshot .name span {
|
||||
width: 40px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xg-view-videoTitle {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 40px;
|
||||
padding-left: 10px;
|
||||
background-image: linear-gradient(180deg,rgba(0,0,0,.75),rgba(0,0,0,.75),rgba(0,0,0,.37),transparent);
|
||||
z-index: 10;
|
||||
}
|
||||
.xgplayer-skin-default .xg-view-videoTitle span {
|
||||
font-size: 16px;
|
||||
line-height: 40px;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.play{
|
||||
position: relative;
|
||||
|
||||
@@ -5,7 +5,7 @@ const Axios = require('axios')
|
||||
const app = express()
|
||||
app.use(cors())
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded())
|
||||
app.use(express.urlencoded({ extended: true }))
|
||||
|
||||
app.post('/api', async (req, res) => {
|
||||
const result = await Axios.get(req.body.url)
|
||||
|
||||
@@ -22,8 +22,15 @@
|
||||
<span class="progress" v-show="progress > 0">播放进度: {{progress}}%</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="min" @click="frameClickEvent('min')"></span>
|
||||
<span class="close" @click="frameClickEvent('close')"></span>
|
||||
<span class="min" @click="frameClickEvent('min')" title="最小化">
|
||||
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:10px;height:16px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="close" @click="frameClickEvent('close')" title="关闭">
|
||||
<svg t="1595917372551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" style="width:10px;height:16px"><path d="M511.968 376.224 796.096 92.096C833.536 54.624 894.4 54.624 931.84 92.096 969.312 129.568 969.312 190.4 931.84 227.872L647.744 512 931.84 796.096C969.312 833.568 969.312 894.4 931.84 931.872 894.4 969.344 833.536 969.344 796.096 931.872L511.968 647.744 227.84 931.872C190.4 969.344 129.536 969.344 92.096 931.872 54.624 894.4 54.624 833.568 92.096 796.096L376.224 512 92.096 227.872C54.624 190.4 54.624 129.568 92.096 92.096 129.536 54.624 190.4 54.624 227.84 92.096L511.968 376.224Z" p-id="1686" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="top" @click="frameClickEvent('top')" title="置顶">
|
||||
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:12px;height:16px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
@@ -38,9 +45,11 @@ import mt from 'mousetrap'
|
||||
import 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
const VIDEO_DETAIL_CACHE = {}
|
||||
export default {
|
||||
name: 'mini',
|
||||
data () {
|
||||
const win = remote.getCurrentWindow()
|
||||
return {
|
||||
xg: null,
|
||||
config: {
|
||||
@@ -65,7 +74,8 @@ export default {
|
||||
detail: {},
|
||||
m3u8Arr: [],
|
||||
rate: 1,
|
||||
progress: 0
|
||||
progress: 0,
|
||||
isAlwaysOnTop: win.isAlwaysOnTop()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -79,6 +89,11 @@ export default {
|
||||
ipcRenderer.send('win')
|
||||
return false
|
||||
}
|
||||
if (e === 'top') {
|
||||
this.isAlwaysOnTop = !this.isAlwaysOnTop
|
||||
const win = remote.getCurrentWindow()
|
||||
win.setAlwaysOnTop(this.isAlwaysOnTop)
|
||||
}
|
||||
},
|
||||
opacityChange (val) {
|
||||
const win = remote.getCurrentWindow()
|
||||
@@ -89,10 +104,88 @@ export default {
|
||||
getUrls () {
|
||||
mini.find().then(res => {
|
||||
this.video = res
|
||||
zy.detail(res.site, res.ids).then(e => {
|
||||
this.name = e.name
|
||||
this.detail = e
|
||||
const dd = e.dl.dd
|
||||
this.fetchM3u8List(res).then(m3u8Arr => {
|
||||
this.m3u8Arr = m3u8Arr
|
||||
this.xg.src = m3u8Arr[res.index]
|
||||
if (res.time !== 0 || res.time !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = res.time
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
}
|
||||
this.videoPlaying()
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
this.video.time = 0
|
||||
this.video.index++
|
||||
this.xg.src = m3u8Arr[this.video.index]
|
||||
this.xg.play()
|
||||
}
|
||||
})
|
||||
})
|
||||
// zy.detail(res.site, res.ids).then(e => {
|
||||
// this.name = e.name
|
||||
// this.detail = e
|
||||
// const dd = e.dl.dd
|
||||
// const type = Object.prototype.toString.call(dd)
|
||||
// let m3u8Txt = []
|
||||
// if (type === '[object Array]') {
|
||||
// for (const i of dd) {
|
||||
// if (i._t.indexOf('m3u8') >= 0) {
|
||||
// m3u8Txt = i._t.split('#')
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Txt = dd._t.split('#')
|
||||
// }
|
||||
// const m3u8Arr = []
|
||||
// for (const i of m3u8Txt) {
|
||||
// const j = i.split('$')
|
||||
// if (j.length > 1) {
|
||||
// for (let m = 0; m < j.length; m++) {
|
||||
// if (j[m].indexOf('m3u8') >= 0) {
|
||||
// m3u8Arr.push(j[m])
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Arr.push(j[0])
|
||||
// }
|
||||
// }
|
||||
// this.m3u8Arr = m3u8Arr
|
||||
// this.xg.src = m3u8Arr[res.index]
|
||||
// if (res.time !== 0 || res.time !== '') {
|
||||
// this.xg.play()
|
||||
// this.xg.once('playing', () => {
|
||||
// this.xg.currentTime = res.time
|
||||
// })
|
||||
// } else {
|
||||
// this.xg.play()
|
||||
// }
|
||||
// this.videoPlaying()
|
||||
// this.xg.once('ended', () => {
|
||||
// if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
// this.video.time = 0
|
||||
// this.video.index++
|
||||
// this.xg.src = m3u8Arr[this.video.index]
|
||||
// this.xg.play()
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
})
|
||||
},
|
||||
fetchM3u8List (info) {
|
||||
return new Promise((resolve) => {
|
||||
const cacheKey = info.site + '@' + info.ids
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey]) {
|
||||
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
|
||||
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
|
||||
return
|
||||
}
|
||||
zy.detail(info.site, info.ids).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
@@ -117,25 +210,12 @@ export default {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
this.m3u8Arr = m3u8Arr
|
||||
this.xg.src = m3u8Arr[res.index]
|
||||
if (res.time !== 0 || res.time !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = res.time
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = {
|
||||
list: m3u8Arr,
|
||||
name: res.name
|
||||
}
|
||||
this.videoPlaying()
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
this.video.time = 0
|
||||
this.video.index++
|
||||
this.xg.src = m3u8Arr[this.video.index]
|
||||
this.xg.play()
|
||||
}
|
||||
})
|
||||
resolve(m3u8Arr)
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -286,8 +366,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'escape') {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
if (this.xg.fullscreen) {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'next') {
|
||||
@@ -427,6 +509,8 @@ html,body{
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
text-align: center;
|
||||
line-height: 16px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
@@ -437,6 +521,9 @@ html,body{
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
&:hover{
|
||||
animation: heartbeat 3s ease-in-out infinite both;
|
||||
}
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -9918,16 +9918,16 @@ xdg-basedir@^4.0.0:
|
||||
|
||||
xgplayer-hls.js@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.npmjs.org/xgplayer-hls.js/-/xgplayer-hls.js-2.2.3.tgz#bf538911145346c447528d609fc95dd267a24d81"
|
||||
resolved "https://registry.yarnpkg.com/xgplayer-hls.js/-/xgplayer-hls.js-2.2.3.tgz#bf538911145346c447528d609fc95dd267a24d81"
|
||||
integrity sha512-CFsZanBHHRbqTmqYCFFONk76oWwJwbn+8LK/XkwBBrUrqGPQPmrXfjelGjKDDGfZ+w3xReC1nGom3IpN+lLoaQ==
|
||||
dependencies:
|
||||
deepmerge "2.0.1"
|
||||
event-emitter "^0.3.5"
|
||||
|
||||
xgplayer@^2.9.8:
|
||||
version "2.9.8"
|
||||
resolved "https://registry.npmjs.org/xgplayer/-/xgplayer-2.9.8.tgz#ce6646f8ef99594ca9414449f83f816320c4ec83"
|
||||
integrity sha512-MICegbLRMNdOa9kRcsY5BVfwKmwvO+quJST/ejSJngdvDrB4E9dX53zhL3OT6KH4n9aCifl5qCYzTRWD6qH22w==
|
||||
xgplayer@^2.9.10:
|
||||
version "2.9.10"
|
||||
resolved "https://registry.yarnpkg.com/xgplayer/-/xgplayer-2.9.10.tgz#4e79b889621f829b773c118ab93da55f829d4490"
|
||||
integrity sha512-5a7Xm0AY8qPRXZFxrPRErjzCERsENaskQ8Fq5Sy4ht13TMzYp0VIRREU7XF8efpJGcPsOOuFlCiMrqSpYEIAUA==
|
||||
dependencies:
|
||||
chalk "^2.3.2"
|
||||
commander "^2.15.1"
|
||||
|
||||
Reference in New Issue
Block a user