mirror of
https://github.com/cuiocean/ZY-Player.git
synced 2026-07-27 00:30:19 +08:00
Merge pull request #353 from Hunlongyu/mergeChannelDev
频道合并及播放页面的频道列表及精简模式
This commit is contained in:
@@ -111,6 +111,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
.play{
|
||||
.popper {
|
||||
font-size: 1rem;;
|
||||
border: none;
|
||||
li {
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using el-table
|
||||
.listpage{
|
||||
position: absolute;
|
||||
@@ -222,6 +232,9 @@
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.disableExpand div.el-table__expand-icon{
|
||||
display: none;
|
||||
}
|
||||
.el-input{
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
@@ -301,6 +301,30 @@
|
||||
box-shadow: var(--d-bsc);
|
||||
}
|
||||
|
||||
.play{
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--d-bgc-1);
|
||||
border: 1px solid var(--d-bgc-1);
|
||||
color: var(--d-fc-2);
|
||||
}
|
||||
}
|
||||
.popper {
|
||||
color: var(--d-fc-1);
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
li {
|
||||
color: var(--d-fc-1);
|
||||
background-color: var(--d-bgc-1);
|
||||
&:hover{
|
||||
background-color: var(--d-bgc-2);
|
||||
}
|
||||
}
|
||||
.popper__arrow, .popper__arrow::after{
|
||||
border-bottom-color: var(--d-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using table and picture
|
||||
.listpage{
|
||||
color: var(--d-fc-2);
|
||||
|
||||
@@ -301,6 +301,30 @@
|
||||
box-shadow: var(--g-bsc);
|
||||
}
|
||||
|
||||
.play{
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--g-bgc-1);
|
||||
border: 1px solid var(--g-bgc-1);
|
||||
color: var(--g-fc-2);
|
||||
}
|
||||
}
|
||||
.popper {
|
||||
color: var(--g-fc-1);
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
li {
|
||||
color: var(--g-fc-1);
|
||||
background-color: var(--g-bgc-1);
|
||||
&:hover{
|
||||
background-color: var(--g-bgc-2);
|
||||
}
|
||||
}
|
||||
.popper__arrow, .popper__arrow::after{
|
||||
border-bottom-color: var(--g-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using table and picture
|
||||
.listpage{
|
||||
color: var(--g-fc-2);
|
||||
|
||||
@@ -301,6 +301,30 @@
|
||||
box-shadow: var(--l-bsc);
|
||||
}
|
||||
|
||||
.play{
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--l-bgc-1);
|
||||
border: 1px solid var(--l-bgc-1);
|
||||
color: var(--l-fc-2);
|
||||
}
|
||||
}
|
||||
.popper {
|
||||
color: var(--l-fc-1);
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
li {
|
||||
color: var(--l-fc-1);
|
||||
background-color: var(--l-bgc-1);
|
||||
&:hover{
|
||||
background-color: var(--l-bgc-2);
|
||||
}
|
||||
}
|
||||
.popper__arrow, .popper__arrow::after{
|
||||
border-bottom-color: var(--l-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using table and picture
|
||||
.listpage{
|
||||
color: var(--l-fc-2);
|
||||
|
||||
@@ -301,6 +301,30 @@
|
||||
box-shadow: var(--p-bsc);
|
||||
}
|
||||
|
||||
.play{
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--p-bgc-1);
|
||||
border: 1px solid var(--p-bgc-1);
|
||||
color: var(--p-fc-2);
|
||||
}
|
||||
}
|
||||
.popper {
|
||||
color: var(--p-fc-1);
|
||||
background-color: var(--p-bgc-1);
|
||||
box-shadow: var(--p-bsc);
|
||||
li {
|
||||
color: var(--p-fc-1);
|
||||
background-color: var(--p-bgc-1);
|
||||
&:hover{
|
||||
background-color: var(--p-bgc-2);
|
||||
}
|
||||
}
|
||||
.popper__arrow, .popper__arrow::after{
|
||||
border-bottom-color: var(--p-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using table and picture
|
||||
.listpage{
|
||||
color: var(--p-fc-2);
|
||||
|
||||
@@ -199,9 +199,9 @@ export default {
|
||||
selectionCellClick (selection, row) {
|
||||
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
|
||||
this.selectionEnd = row.id
|
||||
const start = Math.min(this.selectionBegin, this.selectionEnd) - 1
|
||||
const end = Math.max(this.selectionBegin, this.selectionEnd)
|
||||
const selections = this.sites.slice(start, end)
|
||||
const start = this.sites.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
|
||||
const end = this.sites.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
|
||||
const selections = this.sites.slice(start, end + 1)
|
||||
this.$nextTick(() => {
|
||||
selections.forEach(e => this.$refs.editSitesTable.toggleRowSelection(e, true))
|
||||
})
|
||||
@@ -314,7 +314,7 @@ export default {
|
||||
var randomstring = require('randomstring')
|
||||
var doc = {
|
||||
key: this.dialogType === 'edit' ? this.siteInfo.key : this.siteInfo.key ? this.siteInfo.key : randomstring.generate(6),
|
||||
id: this.dialogType === 'edit' ? this.siteInfo.id : this.sites[this.sites.length - 1].id + 1,
|
||||
id: this.dialogType === 'edit' ? this.siteInfo.id : this.sites.length ? this.sites[this.sites.length - 1].id + 1 : 1,
|
||||
name: this.siteInfo.name,
|
||||
api: this.siteInfo.api,
|
||||
download: this.siteInfo.download,
|
||||
@@ -412,7 +412,7 @@ export default {
|
||||
this.updateDatabase()
|
||||
},
|
||||
syncTableData () {
|
||||
if (this.$refs.editSitesTable.tableData) {
|
||||
if (this.$refs.editSitesTable.tableData && this.$refs.editSitesTable.tableData.length === this.sites.length) {
|
||||
this.sites = this.$refs.editSitesTable.tableData
|
||||
}
|
||||
},
|
||||
|
||||
@@ -619,7 +619,6 @@ export default {
|
||||
}
|
||||
},
|
||||
querySearch (queryString, cb) {
|
||||
if (this.searchList.length === 0) return
|
||||
var searchList = this.searchList.slice(0, -1)
|
||||
var results = queryString ? searchList.filter(this.createFilter(queryString)) : this.searchList
|
||||
// 调用 callback 返回建议列表的数据
|
||||
@@ -748,7 +747,7 @@ export default {
|
||||
if (this.searchGroup === undefined) setting.find().then(res => { this.searchGroup = res.searchGroup })
|
||||
})
|
||||
},
|
||||
getSearchViewMode() {
|
||||
getSearchViewMode () {
|
||||
setting.find().then(res => {
|
||||
this.searchViewMode = res.searchViewMode === undefined ? 'picture' : res.searchViewMode
|
||||
})
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
</div>
|
||||
<div class="listpage-header" id="iptv-header" v-show="enableBatchEdit">
|
||||
<el-switch v-model="enableBatchEdit" active-text="批处理分组"></el-switch>
|
||||
<el-input placeholder="新组名" v-model="batchGroupName"></el-input>
|
||||
<el-input placeholder="新组名/新频道名" v-model="inputContent"></el-input>
|
||||
<el-switch v-model="batchIsActive" active-text="启用"></el-switch>
|
||||
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存</el-button>
|
||||
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存分组</el-button>
|
||||
<el-button type="primary" icon="el-icon-film" @click.stop="mergeChannel">频道合并</el-button>
|
||||
<el-button @click.stop="removeSelectedChannels" icon="el-icon-delete-solid">删除</el-button>
|
||||
</div>
|
||||
<div class="listpage-body" id="iptv-table">
|
||||
@@ -20,10 +21,14 @@
|
||||
ref="iptvTable"
|
||||
size="mini" fit height="100%" row-key="id"
|
||||
:data="filteredTableData"
|
||||
lazy
|
||||
:load="(row, treeNode, resolve) => resolve(row.channels)"
|
||||
:tree-props="{hasChildren: 'hasChildren'}"
|
||||
@expand-change="expandChange"
|
||||
@row-click="playEvent"
|
||||
@select="selectionCellClick"
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="handleSortChange">>
|
||||
@sort-change="handleSortChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
v-if="enableBatchEdit">
|
||||
@@ -31,6 +36,7 @@
|
||||
<el-table-column
|
||||
default-sort="ascending"
|
||||
prop="name"
|
||||
:class-name="enableBatchEdit ? 'disableExpand' : ''"
|
||||
label="频道名">
|
||||
<template #header>
|
||||
<el-input
|
||||
@@ -88,9 +94,9 @@
|
||||
<span>总频道数:{{ iptvList.length }}</span>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-button @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
|
||||
<el-button @click.stop="moveToTopEvent(scope.row)" type="text" v-if="scope.row.channels">置顶</el-button>
|
||||
<!-- 检测时先强制批量检测一遍,如果不强制直接单个检测时第一次不会显示“检测中”-->
|
||||
<el-button size="mini" v-if="iptvList.every(channel => channel.status)" v-show="!checkAllChannelsLoading" @click.stop="checkSingleChannel(scope.row)" type="text">检测</el-button>
|
||||
<el-button size="mini" v-if="iptvList.every(channel => channel.status)" v-show="!checkAllChannelsLoading" @click.stop="checkChannel(scope.row)" type="text">检测</el-button>
|
||||
<el-button @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -101,7 +107,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { iptv, iptvSearch } from '../lib/dexie'
|
||||
import { iptv, iptvSearch, channelList } from '../lib/dexie'
|
||||
import { iptv as defaultChannels } from '../lib/dexie/initData'
|
||||
import zy from '../lib/site/tools'
|
||||
import { remote } from 'electron'
|
||||
@@ -112,18 +118,21 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
iptvList: [],
|
||||
channelList: [],
|
||||
searchTxt: '',
|
||||
searchRecordList: [],
|
||||
enableBatchEdit: false,
|
||||
batchGroupName: '',
|
||||
inputContent: '',
|
||||
batchIsActive: true,
|
||||
shiftDown: false,
|
||||
selectionBegin: '',
|
||||
selectionEnd: '',
|
||||
multipleSelection: [],
|
||||
expandedRows: [],
|
||||
checkAllChannelsLoading: false,
|
||||
checkProgress: 0,
|
||||
stopFlag: false,
|
||||
sortableTable: '',
|
||||
show: {
|
||||
search: false
|
||||
}
|
||||
@@ -151,13 +160,13 @@ export default {
|
||||
},
|
||||
filteredTableData () {
|
||||
if (this.searchTxt) {
|
||||
return this.iptvList.filter(x => x.name.toLowerCase().includes(this.searchTxt.toLowerCase()))
|
||||
return this.channelList.filter(x => x.name.toLowerCase().includes(this.searchTxt.toLowerCase()))
|
||||
} else {
|
||||
return this.iptvList
|
||||
return this.channelList
|
||||
}
|
||||
},
|
||||
getFilters () {
|
||||
const groups = [...new Set(this.iptvList.map(iptv => iptv.group))]
|
||||
const groups = [...new Set(this.channelList.map(iptv => iptv.group))]
|
||||
var filters = []
|
||||
groups.forEach(g => {
|
||||
var doc = {
|
||||
@@ -172,13 +181,22 @@ export default {
|
||||
watch: {
|
||||
view () {
|
||||
if (this.view === 'IPTV') {
|
||||
this.getChannels()
|
||||
this.getChannelList()
|
||||
}
|
||||
},
|
||||
enableBatchEdit () {
|
||||
if (this.checkAllChannelsLoading) {
|
||||
this.$message.info('正在检测, 请勿操作.')
|
||||
this.enableBatchEdit = false
|
||||
return
|
||||
}
|
||||
if (this.enableBatchEdit) {
|
||||
this.$nextTick(() => {
|
||||
this.expandedRows.forEach(e => this.$refs.iptvTable.toggleRowExpansion(e, false))
|
||||
})
|
||||
this.rowDrop()
|
||||
} else {
|
||||
this.sortableTable.destroy()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -190,9 +208,9 @@ export default {
|
||||
selectionCellClick (selection, row) {
|
||||
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
|
||||
this.selectionEnd = row.id
|
||||
const start = Math.min(this.selectionBegin, this.selectionEnd) - 1
|
||||
const end = Math.max(this.selectionBegin, this.selectionEnd)
|
||||
const selections = this.iptvList.slice(start, end)
|
||||
const start = this.channelList.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
|
||||
const end = this.channelList.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
|
||||
const selections = this.channelList.slice(start, end + 1) // 多选时强制不让展开
|
||||
this.$nextTick(() => {
|
||||
selections.forEach(e => this.$refs.iptvTable.toggleRowSelection(e, true))
|
||||
})
|
||||
@@ -205,27 +223,56 @@ export default {
|
||||
this.selectionBegin = ''
|
||||
}
|
||||
},
|
||||
expandChange (row, expanded) {
|
||||
const index = this.expandedRows.indexOf(row)
|
||||
if (expanded && index === -1) {
|
||||
this.expandedRows.push(row)
|
||||
} else if (!expanded && index !== -1) {
|
||||
this.expandedRows.splice(index, 1)
|
||||
}
|
||||
},
|
||||
handleSelectionChange (rows) {
|
||||
this.multipleSelection = rows
|
||||
},
|
||||
handleSortChange (column, prop, order) {
|
||||
if (this.checkAllChannelsLoading) {
|
||||
this.$message.info('正在检测, 请勿操作.')
|
||||
this.enableBatchEdit = false
|
||||
return
|
||||
}
|
||||
this.updateDatabase()
|
||||
},
|
||||
saveBatchEdit () {
|
||||
this.multipleSelection.forEach(ele => {
|
||||
if (this.batchGroupName) {
|
||||
ele.group = this.batchGroupName
|
||||
if (this.inputContent) {
|
||||
ele.group = this.inputContent
|
||||
}
|
||||
ele.isActive = this.batchIsActive
|
||||
})
|
||||
this.updateDatabase()
|
||||
},
|
||||
playEvent (e) {
|
||||
this.video = { iptv: { name: e.name, url: e.url, id: e.id } }
|
||||
mergeChannel () {
|
||||
if (this.inputContent && this.multipleSelection.length) {
|
||||
var channels = []
|
||||
const id = this.multipleSelection[0].id
|
||||
this.multipleSelection.forEach(ele => {
|
||||
channels = channels.concat(ele.channels)
|
||||
channels.forEach(e => { e.channelID = id })
|
||||
channelList.remove(ele.id)
|
||||
})
|
||||
const mergeChannel = { id: id, name: this.inputContent, isActive: channels.some(c => c.isActive), group: this.determineGroup(this.inputContent), hasChildren: channels.length > 1, channels: channels }
|
||||
channelList.add(mergeChannel)
|
||||
this.getChannelList()
|
||||
this.updateDatabase()
|
||||
}
|
||||
},
|
||||
playEvent (e) { // 下一步与Play联动prefer
|
||||
if (e.url) {
|
||||
this.video = { iptv: e }
|
||||
} else {
|
||||
const prefer = e.prefer ? e.channels.find(c => c.id === e.prefer) : e.channels.filter(c => c.isActive)[0]
|
||||
if (!prefer) return
|
||||
this.video = { iptv: prefer }
|
||||
}
|
||||
this.view = 'Play'
|
||||
},
|
||||
containsearchTxt (i) {
|
||||
@@ -235,18 +282,31 @@ export default {
|
||||
return true
|
||||
}
|
||||
},
|
||||
removeEvent (e) {
|
||||
removeEvent (row) {
|
||||
if (this.checkAllChannelsLoading) {
|
||||
this.$message.info('正在检测, 请勿操作.')
|
||||
return false
|
||||
}
|
||||
iptv.remove(e.id).then(res => {
|
||||
this.getChannels()
|
||||
}).catch(err => {
|
||||
try {
|
||||
if (row.url) { // tree树形控件节点一旦展开,就不再重新加载节点数据
|
||||
iptv.remove(row.id)
|
||||
const parent = this.channelList.find(e => e.id === row.channelID)
|
||||
parent.channels.splice(parent.channels.findIndex(e => e.id === row.id), 1)
|
||||
channelList.remove(row.channelID)
|
||||
if (parent.channels.length) channelList.add(parent)
|
||||
this.$set(this.$refs.iptvTable.store.states.lazyTreeNodeMap, parent.id, parent.channels)
|
||||
} else {
|
||||
channelList.remove(row.id)
|
||||
row.channels.forEach(e => {
|
||||
iptv.remove(e.id)
|
||||
})
|
||||
}
|
||||
this.getChannelList()
|
||||
} catch (err) {
|
||||
this.$message.warning('删除频道失败, 错误信息: ' + err)
|
||||
})
|
||||
}
|
||||
},
|
||||
exportChannels () {
|
||||
exportChannels () { // 导出导入应为iptvList,然后自动转换为channelList
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'm3u file', extensions: ['m3u'] },
|
||||
@@ -287,6 +347,8 @@ export default {
|
||||
}
|
||||
remote.dialog.showOpenDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
var _id = 1
|
||||
this.iptvList.forEach(e => { e.id = _id++ }) // 导入时需重置iptvList的id
|
||||
var docs = this.iptvList
|
||||
var id = docs.length + 1
|
||||
result.filePaths.forEach(file => {
|
||||
@@ -300,8 +362,7 @@ export default {
|
||||
id: id,
|
||||
name: ele.name,
|
||||
url: ele.url,
|
||||
isActive: true,
|
||||
group: this.determineGroup(ele.name)
|
||||
isActive: true
|
||||
}
|
||||
id += 1
|
||||
docs.push(doc)
|
||||
@@ -317,8 +378,7 @@ export default {
|
||||
id: id,
|
||||
name: ele.name,
|
||||
url: ele.url,
|
||||
isActive: ele.isActive === undefined ? true : ele.isActive,
|
||||
group: this.determineGroup(ele.name)
|
||||
isActive: ele.isActive === undefined ? true : ele.isActive
|
||||
}
|
||||
id += 1
|
||||
docs.push(doc)
|
||||
@@ -330,14 +390,14 @@ export default {
|
||||
// const uniqueList = [...new Map(docs.map(item => [item.name, item])).values()]
|
||||
iptv.clear().then(res => {
|
||||
iptv.bulkAdd(docs).then(e => { // 支持导入同名频道,群里反馈
|
||||
this.getChannels()
|
||||
this.updateChannelList()
|
||||
this.$message.success('导入成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
determineGroup (name) {
|
||||
determineGroup (name) { // iptvList不再需要group,而是通过channelID来追踪归属
|
||||
if (name.toLowerCase().includes('cctv') && (name.includes('蓝光') || name.includes('高清'))) {
|
||||
return '央视高清'
|
||||
} else if (name.toLowerCase().includes('cctv')) {
|
||||
@@ -358,25 +418,59 @@ export default {
|
||||
this.$message.info('部分检测还未完全终止, 请稍等...')
|
||||
return
|
||||
}
|
||||
iptv.clear().then(iptv.bulkAdd(defaultChannels).then(this.getChannels()))
|
||||
iptv.clear().then(iptv.bulkAdd(defaultChannels).then(this.updateChannelList()))
|
||||
},
|
||||
removeSelectedChannels () {
|
||||
this.multipleSelection.forEach(e => iptv.remove(e.id))
|
||||
this.multipleSelection.forEach(e => { channelList.remove(e.id); e.channels.forEach(c => iptv.remove(c.id)) })
|
||||
this.$refs.iptvTable.clearFilter()
|
||||
this.getChannels()
|
||||
this.getChannelList()
|
||||
this.updateDatabase()
|
||||
this.enableBatchEdit = false
|
||||
},
|
||||
getChannels () {
|
||||
updateChannelList () {
|
||||
iptv.all().then(res => {
|
||||
const resClone = JSON.parse(JSON.stringify(res))
|
||||
const uniqueChannelName = {}
|
||||
for (var i = 0; i < resClone.length; i++) {
|
||||
var channelName = resClone[i].name.trim().replace(/[- ]?(1080p|蓝光|超清|高清|标清|hd|cq|4k)(\d{1,2})?$/i, '')
|
||||
if (channelName.match(/cctv/i)) channelName = channelName.replace('-', '')
|
||||
if (Object.keys(uniqueChannelName).some(name => channelName.match(new RegExp(`${name}(1080p|4k|(?!\\d))`, 'i')))) continue // 避免重复
|
||||
const matchRule = new RegExp(`${channelName}(1080p|4k|(?!\\d))`, 'i')
|
||||
for (var j = i; j < resClone.length; j++) {
|
||||
if (resClone[j].name.match(/cctv/i)) {
|
||||
resClone[j].name = resClone[j].name.replace('-', '')
|
||||
}
|
||||
if (matchRule.test(resClone[j].name)) {
|
||||
if (uniqueChannelName[channelName]) {
|
||||
!uniqueChannelName[channelName].includes(res[j]) && uniqueChannelName[channelName].push(res[j])
|
||||
} else {
|
||||
uniqueChannelName[channelName] = [res[j]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res.forEach(ele => {
|
||||
if (ele.isActive === undefined) {
|
||||
ele.isActive = true
|
||||
}
|
||||
})
|
||||
this.iptvList = res
|
||||
let id = res.length // channelList全部放在末尾
|
||||
this.channelList = Object.keys(uniqueChannelName).map(e => { return { id: ++id, name: e, isActive: uniqueChannelName[e].some(c => c.isActive), group: this.determineGroup(e), hasChildren: uniqueChannelName[e].length > 1, channels: uniqueChannelName[e] } })
|
||||
this.getIptvList()
|
||||
Object.values(this.$refs.iptvTable.store.states.treeData).forEach(e => { e.loaded = false })
|
||||
channelList.clear().then(channelList.bulkAdd(this.channelList))
|
||||
iptv.clear().then(iptv.bulkAdd(this.iptvList))
|
||||
// 用于验证
|
||||
// console.log(res.length, Array.from(new Set(this.iptvList)))
|
||||
// res.forEach(e => { if (!this.iptvList.includes(e)) console.log(e) })
|
||||
})
|
||||
},
|
||||
getChannelList () {
|
||||
channelList.all().then(res => { if (res && res.length === 0) this.updateChannelList(); this.channelList = res; this.getIptvList() })
|
||||
},
|
||||
getIptvList () {
|
||||
this.iptvList = this.channelList.reduce((result, item) => { item.channels.forEach(e => { e.channelID = item.id }); return result.concat(item.channels) }, [])
|
||||
},
|
||||
getSearchRecordList () {
|
||||
iptvSearch.all().then(res => {
|
||||
this.searchRecordList = res.reverse()
|
||||
@@ -399,31 +493,40 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
moveToTopEvent (i) {
|
||||
moveToTopEvent (row) {
|
||||
if (this.checkAllChannelsLoading) {
|
||||
this.$message.info('正在检测, 请勿操作.')
|
||||
return false
|
||||
}
|
||||
this.iptvList.sort(function (x, y) { return (x.name === i.name && x.url === i.url) ? -1 : (y.name === i.name && y.url === i.url) ? 1 : 0 })
|
||||
this.updateDatabase()
|
||||
// this.channelList.sort(function (x, y) { return (x.name === i.name && x.url === i.url) ? -1 : (y.name === i.name && y.url === i.url) ? 1 : 0 })
|
||||
if (row.channels) {
|
||||
this.channelList.splice(this.channelList.findIndex(e => e.id === row.id), 1)
|
||||
this.channelList.unshift(row)
|
||||
this.updateDatabase()
|
||||
}
|
||||
},
|
||||
syncTableData () {
|
||||
if (this.$refs.iptvTable.tableData) {
|
||||
this.iptvList = this.$refs.iptvTable.tableData
|
||||
if (this.$refs.iptvTable.tableData && this.$refs.iptvTable.tableData.length === this.channelList.length) {
|
||||
this.channelList = this.$refs.iptvTable.tableData
|
||||
}
|
||||
},
|
||||
updateDatabase () {
|
||||
this.syncTableData()
|
||||
iptv.clear().then(res => {
|
||||
this.resetId(this.iptvList)
|
||||
iptv.bulkAdd(this.iptvList)
|
||||
Object.values(this.$refs.iptvTable.store.states.treeData).forEach(e => { e.loaded = false })
|
||||
channelList.clear().then(res => {
|
||||
this.resetId(this.channelList)
|
||||
channelList.bulkAdd(this.channelList)
|
||||
iptv.clear().then(iptv.bulkAdd(this.iptvList))
|
||||
this.getChannelList()
|
||||
})
|
||||
},
|
||||
resetId (inArray) {
|
||||
var id = 1
|
||||
inArray.forEach(ele => {
|
||||
resetId (channelList) {
|
||||
this.getIptvList()
|
||||
var id = this.iptvList.length + 1
|
||||
channelList.forEach(ele => {
|
||||
ele.id = id
|
||||
id += 1
|
||||
ele.channels.forEach(e => { e.channelID = ele.id })
|
||||
})
|
||||
},
|
||||
rowDrop () {
|
||||
@@ -433,33 +536,49 @@ export default {
|
||||
}
|
||||
const tbody = document.getElementById('iptv-table').querySelector('.el-table__body-wrapper tbody')
|
||||
const _this = this
|
||||
Sortable.create(tbody, {
|
||||
this.sortableTable = new Sortable(tbody, {
|
||||
filter: '.el-table__row--level-1', // 禁止children拖动
|
||||
onEnd ({ newIndex, oldIndex }) {
|
||||
const currRow = _this.iptvList.splice(oldIndex, 1)[0]
|
||||
_this.iptvList.splice(newIndex, 0, currRow)
|
||||
const currRow = _this.channelList.splice(oldIndex, 1)[0]
|
||||
_this.channelList.splice(newIndex, 0, currRow)
|
||||
_this.updateDatabase()
|
||||
}
|
||||
})
|
||||
},
|
||||
isActiveChangeEvent (row) {
|
||||
iptv.remove(row.id)
|
||||
iptv.add(row)
|
||||
if (row.url) {
|
||||
iptv.remove(row.id)
|
||||
iptv.add(row)
|
||||
const parent = this.channelList.find(e => e.id === row.channelID)
|
||||
parent.isActive = parent.channels.some(e => e.isActive)
|
||||
channelList.remove(row.channelID)
|
||||
channelList.add(parent)
|
||||
} else {
|
||||
channelList.remove(row.id)
|
||||
channelList.add(row)
|
||||
row.channels.forEach(e => {
|
||||
e.isActive = row.isActive
|
||||
iptv.remove(e.id)
|
||||
iptv.add(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
async checkAllChannels () {
|
||||
this.checkAllChannelsLoading = true
|
||||
this.stopFlag = false
|
||||
this.checkProgress = 0
|
||||
this.channelList.forEach(e => { e.status = ' '; e.hasCheckedNum = 0 })
|
||||
const uncheckedList = this.iptvList.filter(e => e.status === undefined || e.status === ' ') // 未检测过的优先
|
||||
const other = this.iptvList.filter(e => !uncheckedList.includes(e))
|
||||
await this.checkChannelList(uncheckedList)
|
||||
await this.checkChannelList(other).then(res => {
|
||||
await this.checkChannelsBySite(uncheckedList)
|
||||
await this.checkChannelsBySite(other).then(res => {
|
||||
this.checkAllChannelsLoading = false
|
||||
this.getChannels()
|
||||
this.updateChannelList()
|
||||
})
|
||||
},
|
||||
async checkChannelList (channelList) {
|
||||
async checkChannelsBySite (channels) {
|
||||
var siteList = {}
|
||||
channelList.forEach(channel => {
|
||||
channels.forEach(channel => {
|
||||
const site = channel.url.split('/')[2]
|
||||
if (siteList[site]) {
|
||||
siteList[site].push(channel)
|
||||
@@ -475,32 +594,48 @@ export default {
|
||||
await this.checkSingleChannel(c)
|
||||
}
|
||||
},
|
||||
async checkSingleChannel (row) {
|
||||
row.status = ' '
|
||||
async checkSingleChannel (channel) {
|
||||
channel.status = ' '
|
||||
const parent = this.channelList.find(e => e.id === channel.channelID)
|
||||
if (this.stopFlag) {
|
||||
this.checkProgress += 1
|
||||
return row.status
|
||||
return channel.status
|
||||
}
|
||||
const flag = await zy.checkChannel(row.url)
|
||||
const flag = await zy.checkChannel(channel.url)
|
||||
this.checkProgress += 1
|
||||
parent.hasCheckedNum++
|
||||
if (flag) {
|
||||
row.status = '可用'
|
||||
channel.status = '可用'
|
||||
} else {
|
||||
row.status = '失效'
|
||||
row.isActive = false
|
||||
channel.status = '失效'
|
||||
channel.isActive = false
|
||||
}
|
||||
if (parent.hasCheckedNum === parent.channels.length) {
|
||||
parent.status = parent.channels.some(channel => channel.status === '可用') ? '可用' : '失效'
|
||||
if (parent.status === '失效') parent.isActive = false
|
||||
channelList.remove(channel.channelID)
|
||||
channelList.add(parent)
|
||||
}
|
||||
iptv.remove(channel.id)
|
||||
iptv.add(channel)
|
||||
return channel.status
|
||||
},
|
||||
async checkChannel (row) {
|
||||
if (row.channels) {
|
||||
row.status = ' '
|
||||
row.hasCheckedNum = 0
|
||||
row.channels.forEach(e => this.checkSingleChannel(e))
|
||||
} else {
|
||||
this.checkSingleChannel(row)
|
||||
}
|
||||
iptv.remove(row.id)
|
||||
iptv.add(row)
|
||||
return row.status
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.rowDrop()
|
||||
addEventListener('keydown', code => { if (code.keyCode === 16) this.shiftDown = true })
|
||||
addEventListener('keyup', code => { if (code.keyCode === 16) this.shiftDown = false })
|
||||
},
|
||||
created () {
|
||||
this.getChannels()
|
||||
this.getChannelList()
|
||||
this.getSearchRecordList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,17 @@
|
||||
<span class="last-tip" v-if="!video.key && right.history.length > 0" @click="historyItemEvent(right.history[0])">上次播放到【{{right.history[0].site}}】{{right.history[0].name}} 第{{right.history[0].index+1}}集</span>
|
||||
</div>
|
||||
<div class="more" v-if="video.iptv" :key="Boolean(video.iptv)">
|
||||
<span class="zy-svg" @click="otherEvent" v-if="right.otherChannels.length">
|
||||
<span class="zy-svg" @click="channelListShow = !channelListShow">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="dashboardIconTitle">
|
||||
<title id="dashboardIconTitle">频道列表</title>
|
||||
<rect width="20" height="20" x="2" y="2"></rect>
|
||||
<path d="M11 7L17 7M11 12L17 12M11 17L17 17"></path>
|
||||
<line x1="7" y1="7" x2="7" y2="7"></line>
|
||||
<line x1="7" y1="12" x2="7" y2="12"></line>
|
||||
<line x1="7" y1="17" x2="7" y2="17"></line>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="zy-svg" @click="otherEvent" v-if="right.sources.length > 1">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="coloursIconTitle">
|
||||
<title id="coloursIconTitle">换源</title>
|
||||
<circle cx="12" cy="9" r="5"></circle>
|
||||
@@ -137,7 +147,7 @@
|
||||
<span class="list-top-title" v-if="right.type === 'history'">历史记录</span>
|
||||
<span class="list-top-title" v-if="right.type === 'shortcut'">快捷键指南{{ this.video.iptv ? '(直播时部分功能不可用)' : '' }}</span>
|
||||
<span class="list-top-title" v-if="right.type === 'other'">同组其他源的视频</span>
|
||||
<span class="list-top-title" v-if="right.type === 'otherChannels'">该频道其它源</span>
|
||||
<span class="list-top-title" v-if="right.type === 'sources'">该频道可用源</span>
|
||||
<span class="list-top-close zy-svg" @click="closeListEvent">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="closeIconTitle">
|
||||
<title id="closeIconTitle">关闭</title>
|
||||
@@ -163,18 +173,52 @@
|
||||
<li v-if="right.other.length === 0">无数据</li>
|
||||
<li @click="otherItemEvent(m)" v-for="(m, n) in right.other" :key="n"><span class="title">{{m.name}} - [{{m.site.name}}]</span></li>
|
||||
</ul>
|
||||
<ul v-if="right.type === 'otherChannels'" class="list-other" v-on-clickaway="closeListEvent">
|
||||
<li v-if="right.otherChannels.length === 0">无数据</li>
|
||||
<li @click="playChannel(channel)" v-for="(channel, index) in right.otherChannels" :key="index"><span class="title">{{channel.name}}</span></li>
|
||||
<ul v-if="right.type === 'sources'" class="list-other" v-on-clickaway="closeListEvent">
|
||||
<li v-if="right.sources.length === 0">无数据</li>
|
||||
<li @click="playChannel(channel)" v-for="(channel, index) in right.sources" :key="index">
|
||||
<span class="title">{{ channel.id === video.iptv.id ? channel.name + '[当前]' : channel.name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="channelListShow" class="list">
|
||||
<div class="list-top">
|
||||
<span class="list-top-title">频道列表</span>
|
||||
<span class="list-top-close zy-svg" @click="channelListShow = false">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="closeIconTitle">
|
||||
<title id="closeIconTitle">关闭</title>
|
||||
<path d="M6.34314575 6.34314575L17.6568542 17.6568542M6.34314575 17.6568542L17.6568542 6.34314575"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="list-body zy-scroll" :style="{overflowY:scroll? 'auto' : 'hidden',paddingRight: scroll ? '0': '5px' }" @mouseenter="scroll = true" @mouseleave="scroll = false">
|
||||
<el-autocomplete
|
||||
clearable
|
||||
size="small"
|
||||
v-model.trim="searchTxt"
|
||||
value-key="keywords"
|
||||
:fetch-suggestions="querySearch"
|
||||
:popper-append-to-body="false"
|
||||
popper-class="popper"
|
||||
placeholder="搜索"
|
||||
@keyup.enter.native="searchAndRecord">
|
||||
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||
</el-autocomplete>
|
||||
<el-tree ref="channelTree"
|
||||
:data="channelListForShow"
|
||||
:props="defaultProps"
|
||||
accordion
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick">
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { star, history, setting, shortcut, mini, iptv, sites } from '../lib/dexie'
|
||||
import { star, history, setting, shortcut, mini, channelList, iptvSearch, sites } from '../lib/dexie'
|
||||
import zy from '../lib/site/tools'
|
||||
import Player from 'xgplayer'
|
||||
import HlsJsPlayer from 'xgplayer-hls.js'
|
||||
@@ -238,7 +282,7 @@ export default {
|
||||
history: [],
|
||||
shortcut: [],
|
||||
other: [],
|
||||
otherChannels: [],
|
||||
sources: [],
|
||||
currentTime: 0
|
||||
},
|
||||
config: {
|
||||
@@ -262,7 +306,8 @@ export default {
|
||||
showHistory: true,
|
||||
videoTitle: true,
|
||||
airplay: true,
|
||||
closeVideoTouch: true
|
||||
closeVideoTouch: true,
|
||||
ignores: ['cssFullscreen']
|
||||
},
|
||||
state: {
|
||||
showList: false,
|
||||
@@ -274,8 +319,17 @@ export default {
|
||||
scroll: false,
|
||||
isStar: false,
|
||||
isTop: false,
|
||||
mini: {},
|
||||
iptvList: []
|
||||
miniMode: false,
|
||||
mainWindowBounds: {},
|
||||
searchTxt: '',
|
||||
searchRecordList: [],
|
||||
channelList: [],
|
||||
channelListForShow: [],
|
||||
channelListShow: false,
|
||||
defaultProps: {
|
||||
label: 'label',
|
||||
children: 'children'
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
@@ -332,6 +386,7 @@ export default {
|
||||
view () {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
this.getChannelList()
|
||||
},
|
||||
video: {
|
||||
handler () {
|
||||
@@ -355,10 +410,67 @@ export default {
|
||||
} else {
|
||||
span.innerText = `${this.name}`
|
||||
}
|
||||
},
|
||||
searchTxt () {
|
||||
if (this.searchTxt === '清除历史记录...') {
|
||||
this.clearSearchRecords()
|
||||
this.searchTxt = ''
|
||||
}
|
||||
this.searchEvent()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||
handleNodeClick (node) {
|
||||
if (node.channel) {
|
||||
this.playChannel(node.channel)
|
||||
}
|
||||
},
|
||||
filterNode (value, data) {
|
||||
if (!value) return true
|
||||
return data.label.toLowerCase().includes(value.toLowerCase())
|
||||
},
|
||||
querySearch (queryString, cb) {
|
||||
var searchRecordList = this.searchRecordList.slice(0, -1)
|
||||
var results = queryString ? searchRecordList.filter(this.createFilter(queryString)) : this.searchRecordList
|
||||
// 调用 callback 返回建议列表的数据
|
||||
console.log(results)
|
||||
cb(results)
|
||||
},
|
||||
createFilter (queryString) {
|
||||
return (item) => {
|
||||
return (item.keywords.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
|
||||
}
|
||||
},
|
||||
getSearchRecordList () {
|
||||
iptvSearch.all().then(res => {
|
||||
this.searchRecordList = res.reverse()
|
||||
this.searchRecordList.push({ id: this.searchRecordList.length + 1, keywords: '清除历史记录...' })
|
||||
})
|
||||
},
|
||||
addSearchRecord () {
|
||||
const wd = this.searchTxt
|
||||
if (wd) {
|
||||
iptvSearch.find({ keywords: wd }).then(res => {
|
||||
if (!res) {
|
||||
iptvSearch.add({ keywords: wd })
|
||||
}
|
||||
this.getSearchRecordList()
|
||||
})
|
||||
}
|
||||
},
|
||||
clearSearchRecords () {
|
||||
iptvSearch.clear().then(res => {
|
||||
this.getSearchRecordList()
|
||||
})
|
||||
},
|
||||
searchEvent () {
|
||||
this.$refs.channelTree.filter(this.searchTxt)
|
||||
},
|
||||
searchAndRecord () {
|
||||
this.addSearchRecord()
|
||||
this.searchEvent()
|
||||
},
|
||||
async getUrls () {
|
||||
if (this.video.key === '') {
|
||||
return false
|
||||
@@ -376,6 +488,7 @@ export default {
|
||||
// 是直播源,直接播放
|
||||
this.playChannel(this.video.iptv)
|
||||
} else {
|
||||
this.iptvMode = false
|
||||
const index = this.video.info.index | 0
|
||||
var time = this.video.info.time
|
||||
if (!time) {
|
||||
@@ -391,7 +504,17 @@ export default {
|
||||
}
|
||||
},
|
||||
playChannel (channel) {
|
||||
this.getIptvList()
|
||||
if (channel.channels) {
|
||||
this.right.sources = channel.channels.filter(e => e.isActive)
|
||||
channel = channel.channels.find(e => e.id === channel.prefer) || channel.channels.filter(e => e.isActive)[0]
|
||||
} else {
|
||||
const parent = this.channelList.find(e => e.id === channel.channelID)
|
||||
parent.prefer = channel.id
|
||||
channelList.remove(parent.id)
|
||||
channelList.add(parent)
|
||||
this.getChannelList()
|
||||
this.right.sources = parent.channels.filter(e => e.isActive)
|
||||
}
|
||||
this.video.iptv = channel
|
||||
this.name = channel.name
|
||||
this.xg.src = channel.url
|
||||
@@ -521,9 +644,9 @@ export default {
|
||||
},
|
||||
prevEvent () {
|
||||
if (this.video.iptv) {
|
||||
var index = this.iptvList.findIndex(obj => obj.name === this.video.iptv.name && obj.url === this.video.iptv.url)
|
||||
var index = this.channelList.findIndex(obj => obj.prefer === this.video.iptv.id)
|
||||
if (index >= 1) {
|
||||
var channel = this.iptvList[index - 1]
|
||||
var channel = this.channelList[index - 1]
|
||||
this.playChannel(channel)
|
||||
} else {
|
||||
this.$message.warning('这已经是第一个频道了。')
|
||||
@@ -539,9 +662,9 @@ export default {
|
||||
},
|
||||
nextEvent () {
|
||||
if (this.video.iptv) {
|
||||
var index = this.iptvList.findIndex(obj => obj.name === this.video.iptv.name && obj.url === this.video.iptv.url)
|
||||
if (index < (this.iptvList.length - 1)) {
|
||||
var channel = this.iptvList[index + 1]
|
||||
var index = this.channelList.findIndex(obj => obj.prefer === this.video.iptv.id)
|
||||
if (index < (this.channelList.length - 1)) {
|
||||
var channel = this.channelList[index + 1]
|
||||
this.playChannel(channel)
|
||||
} else {
|
||||
this.$message.warning('这已经是最后一个频道了。')
|
||||
@@ -622,40 +745,33 @@ export default {
|
||||
info: this.video.info
|
||||
}
|
||||
},
|
||||
miniEvent () {
|
||||
if (this.xg) {
|
||||
this.xg.pause()
|
||||
}
|
||||
mini.find().then(res => {
|
||||
var doc = {}
|
||||
if (!this.video.iptv) {
|
||||
doc = {
|
||||
id: 0,
|
||||
mode: 'video',
|
||||
site: this.video.key,
|
||||
ids: this.video.info.id,
|
||||
name: this.video.info.name,
|
||||
index: this.video.info.index,
|
||||
time: this.xg.currentTime
|
||||
}
|
||||
} else {
|
||||
doc = {
|
||||
id: 0,
|
||||
mode: 'iptv',
|
||||
url: this.video.iptv.url
|
||||
}
|
||||
async miniEvent () {
|
||||
const win = remote.getCurrentWindow()
|
||||
this.mainWindowBounds = JSON.parse(JSON.stringify(win.getBounds()))
|
||||
let miniWindowBounds
|
||||
await mini.find().then(res => { if (res) miniWindowBounds = res.bounds })
|
||||
if (!miniWindowBounds) miniWindowBounds = { x: win.getPosition()[0], y: win.getPosition()[1], width: 550, height: 340 }
|
||||
win.setBounds(miniWindowBounds)
|
||||
this.xg.getCssFullscreen()
|
||||
this.miniMode = true
|
||||
},
|
||||
async exitMiniEvent () {
|
||||
const win = remote.getCurrentWindow()
|
||||
await mini.find().then(res => {
|
||||
let doc = {}
|
||||
doc = {
|
||||
id: 0,
|
||||
bounds: win.getBounds()
|
||||
}
|
||||
if (res) {
|
||||
mini.update(doc)
|
||||
} else {
|
||||
mini.add(doc)
|
||||
}
|
||||
this.mini = doc
|
||||
clearInterval(this.timer)
|
||||
const win = remote.getCurrentWindow()
|
||||
win.hide()
|
||||
ipcRenderer.send('mini')
|
||||
})
|
||||
win.setBounds(this.mainWindowBounds)
|
||||
this.xg.exitCssFullscreen()
|
||||
this.miniMode = false
|
||||
},
|
||||
shareEvent () {
|
||||
this.share = {
|
||||
@@ -785,7 +901,7 @@ export default {
|
||||
},
|
||||
listItemEvent (n) {
|
||||
if (this.video.iptv) {
|
||||
var channel = this.iptvList[n]
|
||||
var channel = this.channelList[n]
|
||||
// 是直播源,直接播放
|
||||
this.playChannel(channel)
|
||||
} else {
|
||||
@@ -849,7 +965,8 @@ export default {
|
||||
this.getOtherSites()
|
||||
this.right.currentTime = this.xg.currentTime
|
||||
} else {
|
||||
this.right.type = 'otherChannels'
|
||||
this.right.type = 'sources'
|
||||
console.log(this.right.sources)
|
||||
}
|
||||
this.right.show = true
|
||||
},
|
||||
@@ -939,6 +1056,9 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'escape') {
|
||||
if (this.miniMode) {
|
||||
this.exitMiniEvent()
|
||||
}
|
||||
if (this.xg.fullscreen) {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
@@ -1035,10 +1155,9 @@ export default {
|
||||
let li = ''
|
||||
if (this.video.iptv) {
|
||||
// 直播频道列表
|
||||
this.getIptvList()
|
||||
let index = 0
|
||||
this.iptvList.forEach(e => {
|
||||
if (e.name === this.video.iptv.name && e.url === this.video.iptv.url) {
|
||||
this.channelList.forEach(e => {
|
||||
if (e.prefer === this.video.iptv.id) {
|
||||
li += `<li class="selected" data-index="${index}" title="${e.name}">${e.name}</li>`
|
||||
} else {
|
||||
li += `<li data-index="${index}" title="${e.name}">${e.name}</li>`
|
||||
@@ -1110,25 +1229,25 @@ export default {
|
||||
}
|
||||
ul.innerHTML = li
|
||||
},
|
||||
getIptvList () {
|
||||
iptv.all().then(res => {
|
||||
this.iptvList = res.filter(e => e.isActive)
|
||||
this.right.otherChannels = []
|
||||
const iptvList = JSON.parse(JSON.stringify(this.iptvList))
|
||||
var currentChannelName = this.video.iptv.name.trim().replace(/[- ]?(1080p|蓝光|超清|高清|标清|hd|cq|4k)(\d{1,2})?/i, '')
|
||||
if (currentChannelName.match(/cctv/i)) currentChannelName = currentChannelName.replace('-', '')
|
||||
const matchRule = new RegExp(`${currentChannelName}(1080p|4k|(?!\\d))`, 'i')
|
||||
for (var i = 0; i < iptvList.length; i++) {
|
||||
if (iptvList[i].name.match(/cctv/i)) {
|
||||
iptvList[i].name = iptvList[i].name.replace('-', '')
|
||||
getChannelList () {
|
||||
channelList.all().then(res => {
|
||||
this.channelList = res.filter(e => e.isActive)
|
||||
this.channelListForShow = []
|
||||
const groups = [...new Set(this.channelList.map(iptv => iptv.group))]
|
||||
groups.forEach(g => {
|
||||
var doc = {
|
||||
label: g,
|
||||
children: this.channelList.filter(x => x.group === g).map(i => { return { label: i.name, channel: i } })
|
||||
}
|
||||
if (matchRule.test(iptvList[i].name) && iptvList[i].id !== this.video.iptv.id) {
|
||||
this.right.otherChannels.push(this.iptvList[i])
|
||||
}
|
||||
}
|
||||
this.channelListForShow.push(doc)
|
||||
})
|
||||
})
|
||||
},
|
||||
bindEvent () {
|
||||
this.xg.on('exitFullscreen', () => {
|
||||
if (this.miniMode) this.xg.getCssFullscreen()
|
||||
})
|
||||
|
||||
this.xg.on('playNextOne', () => {
|
||||
this.nextEvent()
|
||||
})
|
||||
@@ -1447,6 +1566,9 @@ export default {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tree{
|
||||
background-color: inherit;
|
||||
}
|
||||
.list-top{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
25
src/lib/dexie/channelList.js
Normal file
25
src/lib/dexie/channelList.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import db from './dexie'
|
||||
const { channelList } = db
|
||||
export default {
|
||||
async all () {
|
||||
return await channelList.toArray()
|
||||
},
|
||||
async clear () {
|
||||
return await channelList.clear()
|
||||
},
|
||||
async add (doc) {
|
||||
return await channelList.add(doc)
|
||||
},
|
||||
async bulkAdd (doc) {
|
||||
return await channelList.bulkAdd(doc)
|
||||
},
|
||||
async find (doc) {
|
||||
return await channelList.get(doc)
|
||||
},
|
||||
async update (id, docs) {
|
||||
return await channelList.update(id, docs)
|
||||
},
|
||||
async remove (id) {
|
||||
return await channelList.delete(id)
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,10 @@ db.version(4).stores({
|
||||
recommendation: '++id, [key+ids], site, name, detail, index, rate, hasUpdate',
|
||||
sites: '++id, key, name, api, download, isActive, group',
|
||||
history: '++id, [site+ids], name, type, year, index, time, duration, detail',
|
||||
mini: 'id, mode, site, ids, name, index, time, url',
|
||||
iptv: '++id, name, url, group, isActive'
|
||||
// mini: 'id, mode, site, ids, name, index, time, url',
|
||||
mini: 'id, bounds',
|
||||
iptv: '++id, name, url, channelID, isActive',
|
||||
channelList: '++id, name, prefer, channels, group, isActive'
|
||||
})
|
||||
|
||||
db.on('populate', () => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import sites from './sites'
|
||||
import search from './search'
|
||||
import iptvSearch from './iptvSearch'
|
||||
import iptv from './iptv'
|
||||
import channelList from './channelList'
|
||||
import recommendation from './recommendation'
|
||||
|
||||
export {
|
||||
@@ -17,6 +18,7 @@ export {
|
||||
star,
|
||||
sites,
|
||||
iptv,
|
||||
channelList,
|
||||
search,
|
||||
iptvSearch,
|
||||
recommendation
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { Message, Button, Table, TableColumn, Tag, Input, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete, Col } from 'element-ui'
|
||||
import { Message, Button, Table, TableColumn, Tag, Input, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete, Col, Tree } from 'element-ui'
|
||||
import Plugin from 'v-fit-columns'
|
||||
Vue.use(Button)
|
||||
Vue.use(Col)
|
||||
@@ -16,4 +16,5 @@ Vue.use(Select)
|
||||
Vue.use(Option)
|
||||
Vue.use(Checkbox)
|
||||
Vue.use(Autocomplete)
|
||||
Vue.use(Tree)
|
||||
Vue.prototype.$message = Message
|
||||
|
||||
Reference in New Issue
Block a user