mirror of
https://github.com/cuiocean/ZY-Player.git
synced 2026-05-11 11:05:56 +08:00
Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player into master
This commit is contained in:
@@ -223,6 +223,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-button{
|
.el-button{
|
||||||
|
font-size: 1rem;
|
||||||
border: none;
|
border: none;
|
||||||
&:hover{
|
&:hover{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -252,6 +253,9 @@
|
|||||||
.el-table .highlight{
|
.el-table .highlight{
|
||||||
color: var(--highlight-color) !important;
|
color: var(--highlight-color) !important;
|
||||||
}
|
}
|
||||||
|
.el-button{
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="listpage" id="editSites">
|
<div class="listpage" id="editSites">
|
||||||
<div class="listpage-content">
|
<div class="listpage-content">
|
||||||
<div class="listpage-header">
|
<div class="listpage-header" v-show="!eableBatchEdit">
|
||||||
|
<el-switch v-model="eableBatchEdit" active-text="批处理分组">></el-switch>
|
||||||
<el-button @click.stop="addSite" type="text">添加</el-button>
|
<el-button @click.stop="addSite" type="text">添加</el-button>
|
||||||
<el-button @click.stop="exportSites" type="text">导出</el-button>
|
<el-button @click.stop="exportSites" type="text">导出</el-button>
|
||||||
<el-button @click.stop="importSites" type="text">导入</el-button>
|
<el-button @click.stop="importSites" type="text">导入</el-button>
|
||||||
<el-button @click.stop="removeAllSites" type="text">清空</el-button>
|
<el-button @click.stop="removeAllSites" type="text">清空</el-button>
|
||||||
<el-button @click.stop="resetSitesEvent" type="text">重置</el-button>
|
<el-button @click.stop="resetSitesEvent" type="text">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="listpage-header" v-show="eableBatchEdit">
|
||||||
|
<el-switch v-model="eableBatchEdit" active-text="批处理分组"></el-switch>
|
||||||
|
<el-input placeholder="新组名" v-model="batchGroupName"></el-input>
|
||||||
|
<el-switch v-model="batchIsActive" :active-value="1" :inactive-value="0" active-text="自选源"></el-switch>
|
||||||
|
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存</el-button>
|
||||||
|
</div>
|
||||||
<div class="listpage-body" id="sites-table">
|
<div class="listpage-body" id="sites-table">
|
||||||
<el-table
|
<el-table
|
||||||
size="mini"
|
size="mini"
|
||||||
:data="sites"
|
:data="sites"
|
||||||
row-key="id">
|
row-key="id"
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
|
<el-table-column
|
||||||
|
type="selection"
|
||||||
|
v-if="eableBatchEdit">
|
||||||
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
label="资源名">
|
label="资源名">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
:sort-by="['isActive', 'name']"
|
||||||
|
sortable
|
||||||
prop="isActive"
|
prop="isActive"
|
||||||
label="自选源">
|
label="自选源">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@@ -29,11 +43,20 @@
|
|||||||
</el-switch>
|
</el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="group"
|
||||||
|
label="分组"
|
||||||
|
:filters="getFilters"
|
||||||
|
:filter-method="filterHandle"
|
||||||
|
filter-placement="bottom-end">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text">{{scope.row.group}}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="操作"
|
label="操作"
|
||||||
header-align="center"
|
header-align="center"
|
||||||
align="right"
|
align="right">
|
||||||
width="140">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
|
<el-button size="mini" @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
|
||||||
<el-button size="mini" @click.stop="editSite(scope.row)" type="text">编辑</el-button>
|
<el-button size="mini" @click.stop="editSite(scope.row)" type="text">编辑</el-button>
|
||||||
@@ -97,7 +120,11 @@ export default {
|
|||||||
download: [
|
download: [
|
||||||
{ required: false, trigger: 'blur' }
|
{ required: false, trigger: 'blur' }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
eableBatchEdit: false,
|
||||||
|
batchGroupName: '',
|
||||||
|
batchIsActive: 1,
|
||||||
|
multipleSelection: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -116,10 +143,37 @@ export default {
|
|||||||
set (val) {
|
set (val) {
|
||||||
this.SET_EDITSITES(val)
|
this.SET_EDITSITES(val)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getFilters () {
|
||||||
|
const groups = [...new Set(this.sites.map(site => site.group))]
|
||||||
|
var filters = []
|
||||||
|
groups.forEach(g => {
|
||||||
|
var doc = {
|
||||||
|
text: g,
|
||||||
|
value: g
|
||||||
|
}
|
||||||
|
filters.push(doc)
|
||||||
|
})
|
||||||
|
return filters
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(['SET_SETTING', 'SET_EDITSITES']),
|
...mapMutations(['SET_SETTING', 'SET_EDITSITES']),
|
||||||
|
filterHandle (value, row) {
|
||||||
|
return row.group === value
|
||||||
|
},
|
||||||
|
handleSelectionChange (rows) {
|
||||||
|
this.multipleSelection = rows
|
||||||
|
},
|
||||||
|
saveBatchEdit () {
|
||||||
|
this.multipleSelection.forEach(ele => {
|
||||||
|
if (this.batchGroupName) {
|
||||||
|
ele.group = this.batchGroupName
|
||||||
|
}
|
||||||
|
ele.isActive = this.batchIsActive
|
||||||
|
})
|
||||||
|
this.updateDatabase()
|
||||||
|
},
|
||||||
getSites () {
|
getSites () {
|
||||||
sites.all().then(res => {
|
sites.all().then(res => {
|
||||||
this.sites = res
|
this.sites = res
|
||||||
@@ -194,7 +248,7 @@ export default {
|
|||||||
exportSites () {
|
exportSites () {
|
||||||
this.getSites()
|
this.getSites()
|
||||||
const arr = [...this.sites]
|
const arr = [...this.sites]
|
||||||
const str = JSON.stringify(arr, null, 4)
|
const str = JSON.stringify(arr, null, 2)
|
||||||
const options = {
|
const options = {
|
||||||
filters: [
|
filters: [
|
||||||
{ name: 'JSON file', extensions: ['json'] },
|
{ name: 'JSON file', extensions: ['json'] },
|
||||||
@@ -226,11 +280,14 @@ export default {
|
|||||||
var str = fs.readFileSync(file)
|
var str = fs.readFileSync(file)
|
||||||
const json = JSON.parse(str)
|
const json = JSON.parse(str)
|
||||||
json.forEach(ele => {
|
json.forEach(ele => {
|
||||||
if (this.sites.filter(x => x.key === ele.key).length === 0 && this.sites.filter(x => x.name === ele.name && x.url === ele.url).length === 0) {
|
if (ele.api && this.sites.filter(x => x.key === ele.key).length === 0 && this.sites.filter(x => x.name === ele.name && x.api === ele.api).length === 0) {
|
||||||
// 不含该key 同时也不含名字和url一样的
|
// 不含该key 同时也不含名字和url一样的
|
||||||
if (ele.isActive === undefined) {
|
if (ele.isActive === undefined) {
|
||||||
ele.isActive = 1
|
ele.isActive = 1
|
||||||
}
|
}
|
||||||
|
if (ele.group === undefined) {
|
||||||
|
ele.group = '导入'
|
||||||
|
}
|
||||||
this.sites.push(ele)
|
this.sites.push(ele)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -248,10 +305,10 @@ export default {
|
|||||||
},
|
},
|
||||||
moveToTopEvent (i) {
|
moveToTopEvent (i) {
|
||||||
this.sites.sort(function (x, y) { return x.key === i.key ? -1 : y.key === i.key ? 1 : 0 })
|
this.sites.sort(function (x, y) { return x.key === i.key ? -1 : y.key === i.key ? 1 : 0 })
|
||||||
this.updateDatabase(this.sites)
|
this.updateDatabase()
|
||||||
},
|
},
|
||||||
isActiveChangeEvent () {
|
isActiveChangeEvent () {
|
||||||
this.updateDatabase(this.sites)
|
this.updateDatabase()
|
||||||
},
|
},
|
||||||
resetId (inArray) {
|
resetId (inArray) {
|
||||||
var id = 1
|
var id = 1
|
||||||
@@ -260,14 +317,14 @@ export default {
|
|||||||
id += 1
|
id += 1
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateDatabase (data) {
|
updateDatabase () {
|
||||||
sites.clear().then(res => {
|
sites.clear().then(res => {
|
||||||
var id = 1
|
var id = 1
|
||||||
data.forEach(ele => {
|
this.sites.forEach(ele => {
|
||||||
ele.id = id
|
ele.id = id
|
||||||
id += 1
|
id += 1
|
||||||
})
|
})
|
||||||
sites.bulkAdd(data).then(this.getSites())
|
sites.bulkAdd(this.sites).then(this.getSites())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
removeAllSites () {
|
removeAllSites () {
|
||||||
@@ -280,7 +337,7 @@ export default {
|
|||||||
onEnd ({ newIndex, oldIndex }) {
|
onEnd ({ newIndex, oldIndex }) {
|
||||||
const currRow = _this.sites.splice(oldIndex, 1)[0]
|
const currRow = _this.sites.splice(oldIndex, 1)[0]
|
||||||
_this.sites.splice(newIndex, 0, currRow)
|
_this.sites.splice(newIndex, 0, currRow)
|
||||||
_this.updateDatabase(_this.sites)
|
_this.updateDatabase()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<div class="listpage" id="history">
|
<div class="listpage" id="history">
|
||||||
<div class="listpage-content">
|
<div class="listpage-content">
|
||||||
<div class="listpage-header">
|
<div class="listpage-header">
|
||||||
<span class="btn"></span>
|
<el-button @click.stop="exportHistory" type="text">导出</el-button>
|
||||||
|
<el-button @click.stop="importHistory" type="text">导入</el-button>
|
||||||
<el-button @click.stop="clearAllHistory" type="text">清空</el-button>
|
<el-button @click.stop="clearAllHistory" type="text">清空</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="listpage-body" id="history-table">
|
<div class="listpage-body" id="history-table">
|
||||||
@@ -30,8 +31,7 @@
|
|||||||
<el-table-column
|
<el-table-column
|
||||||
label="操作"
|
label="操作"
|
||||||
header-align="center"
|
header-align="center"
|
||||||
align="right"
|
align="right">
|
||||||
width="180">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
|
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
|
||||||
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
|
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
|
||||||
@@ -49,6 +49,8 @@ import { mapMutations } from 'vuex'
|
|||||||
import { history, sites } from '../lib/dexie'
|
import { history, sites } from '../lib/dexie'
|
||||||
import zy from '../lib/site/tools'
|
import zy from '../lib/site/tools'
|
||||||
import Sortable from 'sortablejs'
|
import Sortable from 'sortablejs'
|
||||||
|
import { remote } from 'electron'
|
||||||
|
import fs from 'fs'
|
||||||
const { clipboard } = require('electron')
|
const { clipboard } = require('electron')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -170,6 +172,44 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
exportHistory () {
|
||||||
|
this.getAllhistory()
|
||||||
|
const arr = [...this.history]
|
||||||
|
const str = JSON.stringify(arr, null, 2)
|
||||||
|
const options = {
|
||||||
|
filters: [
|
||||||
|
{ name: 'JSON file', extensions: ['json'] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
remote.dialog.showSaveDialog(options).then(result => {
|
||||||
|
if (!result.canceled) {
|
||||||
|
fs.writeFileSync(result.filePath, str)
|
||||||
|
this.$message.success('已保存成功')
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
importHistory () {
|
||||||
|
const options = {
|
||||||
|
filters: [
|
||||||
|
{ name: 'JSON file', extensions: ['json'] }
|
||||||
|
],
|
||||||
|
properties: ['openFile', 'multiSelections']
|
||||||
|
}
|
||||||
|
remote.dialog.showOpenDialog(options).then(result => {
|
||||||
|
if (!result.canceled) {
|
||||||
|
result.filePaths.forEach(file => {
|
||||||
|
var str = fs.readFileSync(file)
|
||||||
|
const json = JSON.parse(str)
|
||||||
|
history.bulkAdd(json).then(res => {
|
||||||
|
this.$message.success('导入成功')
|
||||||
|
this.getAllhistory()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
clearAllHistory () {
|
clearAllHistory () {
|
||||||
history.clear().then(res => {
|
history.clear().then(res => {
|
||||||
this.history = []
|
this.history = []
|
||||||
|
|||||||
@@ -1,52 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="listpage" id="IPTV">
|
<div class="listpage" id="IPTV">
|
||||||
<div class="listpage-content">
|
<div class="listpage-content">
|
||||||
<div class="listpage-header">
|
<div class="listpage-header" v-show="!eableBatchEdit">
|
||||||
|
<el-switch v-model="eableBatchEdit" active-text="批处理分组"></el-switch>
|
||||||
<el-button type="text">总频道数:{{iptvList.length}}</el-button>
|
<el-button type="text">总频道数:{{iptvList.length}}</el-button>
|
||||||
<el-button @click.stop="exportChannels" type="text">导出</el-button>
|
<el-button @click.stop="exportChannels" type="text">导出</el-button>
|
||||||
<el-button @click.stop="importChannels" type="text">导入</el-button>
|
<el-button @click.stop="importChannels" type="text">导入</el-button>
|
||||||
<el-button @click.stop="removeAllChannels" type="text">清空</el-button>
|
<el-button @click.stop="removeAllChannels" type="text">清空</el-button>
|
||||||
<el-button @click.stop="resetChannelsEvent" type="text">重置</el-button>
|
<el-button @click.stop="resetChannelsEvent" type="text">重置</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="listpage-header" v-show="eableBatchEdit">
|
||||||
|
<el-switch v-model="eableBatchEdit" active-text="批处理分组"></el-switch>
|
||||||
|
<el-input placeholder="新组名" v-model="batchGroupName"></el-input>
|
||||||
|
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存</el-button>
|
||||||
|
</div>
|
||||||
<div class="listpage-body" id="iptv-table">
|
<div class="listpage-body" id="iptv-table">
|
||||||
<el-table
|
<el-table
|
||||||
size="mini"
|
:data="filteredTableData"
|
||||||
fit
|
row-key="id"
|
||||||
:data="filteredTableData"
|
@row-click="playEvent"
|
||||||
row-key="id"
|
@selection-change="handleSelectionChange">
|
||||||
@row-click="playEvent">
|
<el-table-column
|
||||||
<el-table-column
|
type="selection"
|
||||||
prop="name"
|
v-if="eableBatchEdit">
|
||||||
label="频道名">
|
</el-table-column>
|
||||||
<template #header>
|
<el-table-column
|
||||||
<el-input
|
prop="name"
|
||||||
placeholder="搜索"
|
label="频道名">
|
||||||
size="mini"
|
<template #header>
|
||||||
v-model.trim="searchTxt">
|
<el-input
|
||||||
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
placeholder="搜索"
|
||||||
</el-input>
|
size="mini"
|
||||||
</template>
|
v-model.trim="searchTxt">
|
||||||
</el-table-column>
|
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||||
<el-table-column
|
</el-input>
|
||||||
prop="group"
|
</template>
|
||||||
label="分组"
|
</el-table-column>
|
||||||
:filters="getFilters"
|
<el-table-column
|
||||||
:filter-method="filterHandle"
|
prop="group"
|
||||||
filter-placement="bottom-end">
|
label="分组"
|
||||||
<template slot-scope="scope">
|
:filters="getFilters"
|
||||||
<el-button type="text">{{scope.row.group}}</el-button>
|
:filter-method="filterHandle"
|
||||||
</template>
|
filter-placement="bottom-end">
|
||||||
</el-table-column>
|
<template slot-scope="scope">
|
||||||
<el-table-column
|
<el-button type="text">{{scope.row.group}}</el-button>
|
||||||
label="操作"
|
</template>
|
||||||
header-align="center"
|
</el-table-column>
|
||||||
align="right"
|
<el-table-column
|
||||||
width="100">
|
label="操作"
|
||||||
<template slot-scope="scope">
|
header-align="center"
|
||||||
<el-button size="mini" @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
|
align="right">
|
||||||
<el-button size="mini" @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
|
<template slot-scope="scope">
|
||||||
</template>
|
<el-button @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
|
||||||
</el-table-column>
|
<el-button @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,6 +74,9 @@ export default {
|
|||||||
iptvList: [],
|
iptvList: [],
|
||||||
searchTxt: '',
|
searchTxt: '',
|
||||||
searchRecordList: [],
|
searchRecordList: [],
|
||||||
|
eableBatchEdit: false,
|
||||||
|
batchGroupName: '',
|
||||||
|
multipleSelection: [],
|
||||||
show: {
|
show: {
|
||||||
search: false
|
search: false
|
||||||
}
|
}
|
||||||
@@ -120,6 +131,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||||
|
handleSelectionChange (rows) {
|
||||||
|
this.multipleSelection = rows
|
||||||
|
},
|
||||||
|
saveBatchEdit () {
|
||||||
|
if (this.multipleSelection && this.batchGroupName) {
|
||||||
|
this.multipleSelection.forEach(ele => {
|
||||||
|
ele.group = this.batchGroupName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.updateDatabase()
|
||||||
|
},
|
||||||
playEvent (e) {
|
playEvent (e) {
|
||||||
this.video = { iptv: { name: e.name, url: e.url } }
|
this.video = { iptv: { name: e.name, url: e.url } }
|
||||||
this.view = 'Play'
|
this.view = 'Play'
|
||||||
@@ -182,7 +204,8 @@ export default {
|
|||||||
importChannels () {
|
importChannels () {
|
||||||
const options = {
|
const options = {
|
||||||
filters: [
|
filters: [
|
||||||
{ name: 'm3u file', extensions: ['m3u', 'm3u8'] }
|
{ name: 'm3u file', extensions: ['m3u', 'm3u8'] },
|
||||||
|
{ name: 'JSON file', extensions: ['json'] }
|
||||||
],
|
],
|
||||||
properties: ['openFile', 'multiSelections']
|
properties: ['openFile', 'multiSelections']
|
||||||
}
|
}
|
||||||
@@ -191,21 +214,39 @@ export default {
|
|||||||
var docs = this.iptvList
|
var docs = this.iptvList
|
||||||
var id = docs.length
|
var id = docs.length
|
||||||
result.filePaths.forEach(file => {
|
result.filePaths.forEach(file => {
|
||||||
const parser = require('iptv-playlist-parser')
|
if (file.endsWith('m3u')) {
|
||||||
const playlist = fs.readFileSync(file, { encoding: 'utf-8' })
|
const parser = require('iptv-playlist-parser')
|
||||||
const result = parser.parse(playlist)
|
const playlist = fs.readFileSync(file, { encoding: 'utf-8' })
|
||||||
result.items.forEach(ele => {
|
const result = parser.parse(playlist)
|
||||||
if (ele.name && ele.url && ele.url.includes('.m3u8')) {
|
result.items.forEach(ele => {
|
||||||
var doc = {
|
if (ele.name && ele.url && ele.url.includes('.m3u8')) {
|
||||||
id: id,
|
var doc = {
|
||||||
name: ele.name,
|
id: id,
|
||||||
url: ele.url,
|
name: ele.name,
|
||||||
group: this.determineGroup(ele.group, ele.name)
|
url: ele.url,
|
||||||
|
group: this.determineGroup(ele.group, ele.name)
|
||||||
|
}
|
||||||
|
id += 1
|
||||||
|
docs.push(doc)
|
||||||
}
|
}
|
||||||
id += 1
|
})
|
||||||
docs.push(doc)
|
} else {
|
||||||
}
|
// Import Json file
|
||||||
})
|
var str = fs.readFileSync(file)
|
||||||
|
const json = JSON.parse(str)
|
||||||
|
json.forEach(ele => {
|
||||||
|
if (ele.name && ele.url && ele.url.includes('.m3u8')) {
|
||||||
|
var doc = {
|
||||||
|
id: id,
|
||||||
|
name: ele.name,
|
||||||
|
url: ele.url,
|
||||||
|
group: ele.group === undefined ? this.determineGroup(ele.group, ele.name) : ele.group
|
||||||
|
}
|
||||||
|
id += 1
|
||||||
|
docs.push(doc)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
// 获取url不重复的列表
|
// 获取url不重复的列表
|
||||||
const uniqueList = [...new Map(docs.map(item => [item.url, item])).values()]
|
const uniqueList = [...new Map(docs.map(item => [item.url, item])).values()]
|
||||||
@@ -270,12 +311,12 @@ export default {
|
|||||||
},
|
},
|
||||||
moveToTopEvent (i) {
|
moveToTopEvent (i) {
|
||||||
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.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.iptvList)
|
this.updateDatabase()
|
||||||
},
|
},
|
||||||
updateDatabase (data) {
|
updateDatabase () {
|
||||||
iptv.clear().then(res => {
|
iptv.clear().then(res => {
|
||||||
this.resetId(data)
|
this.resetId(this.iptvList)
|
||||||
iptv.bulkAdd(data).then(this.getChannels())
|
iptv.bulkAdd(this.iptvList).then(this.getChannels())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
resetId (inArray) {
|
resetId (inArray) {
|
||||||
@@ -292,7 +333,7 @@ export default {
|
|||||||
onEnd ({ newIndex, oldIndex }) {
|
onEnd ({ newIndex, oldIndex }) {
|
||||||
const currRow = _this.iptvList.splice(oldIndex, 1)[0]
|
const currRow = _this.iptvList.splice(oldIndex, 1)[0]
|
||||||
_this.iptvList.splice(newIndex, 0, currRow)
|
_this.iptvList.splice(newIndex, 0, currRow)
|
||||||
_this.updateDatabase(_this.iptvList)
|
_this.updateDatabase()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ export default {
|
|||||||
},
|
},
|
||||||
expShortcut () {
|
expShortcut () {
|
||||||
const arr = [...this.shortcutList]
|
const arr = [...this.shortcutList]
|
||||||
const str = JSON.stringify(arr, null, 4)
|
const str = JSON.stringify(arr, null, 2)
|
||||||
clipboard.writeText(str)
|
clipboard.writeText(str)
|
||||||
this.$message.success('已复制到剪贴板')
|
this.$message.success('已复制到剪贴板')
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,24 +11,30 @@
|
|||||||
<el-table size="mini" fit :data="list" height="100%" row-key="id" :cell-class-name="checkUpdate" @row-click="detailEvent">
|
<el-table size="mini" fit :data="list" height="100%" row-key="id" :cell-class-name="checkUpdate" @row-click="detailEvent">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
sortable
|
sortable
|
||||||
|
:sort-method="sortByName"
|
||||||
prop="name"
|
prop="name"
|
||||||
label="片名">
|
label="片名">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
:sort-by="['type', 'name']"
|
||||||
sortable
|
sortable
|
||||||
|
:sort-method="sortByType"
|
||||||
prop="type"
|
prop="type"
|
||||||
label="类型"
|
label="类型"
|
||||||
width="100">
|
width="100">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
sortable
|
sortable
|
||||||
|
:sort-by="['year', 'name']"
|
||||||
prop="year"
|
prop="year"
|
||||||
label="上映"
|
label="上映"
|
||||||
width="100"
|
width="100"
|
||||||
align="center">
|
align="center">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
|
:sort-by="['site', 'name']"
|
||||||
sortable
|
sortable
|
||||||
|
:sort-method="sortBySite"
|
||||||
prop="site"
|
prop="site"
|
||||||
width="120"
|
width="120"
|
||||||
label="片源">
|
label="片源">
|
||||||
@@ -37,13 +43,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="list.some(e => e.note)"
|
<el-table-column v-if="list.some(e => e.note)"
|
||||||
sortable
|
|
||||||
prop="note"
|
prop="note"
|
||||||
width="120"
|
width="120"
|
||||||
label="备注">
|
label="备注">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="list.some(e => e.index >= 0)"
|
<el-table-column v-if="list.some(e => e.index >= 0)"
|
||||||
sortable
|
|
||||||
prop="index"
|
prop="index"
|
||||||
width="120"
|
width="120"
|
||||||
label="观看至">
|
label="观看至">
|
||||||
@@ -54,8 +58,7 @@
|
|||||||
<el-table-column
|
<el-table-column
|
||||||
label="操作"
|
label="操作"
|
||||||
header-align="center"
|
header-align="center"
|
||||||
align="right"
|
align="right">
|
||||||
width="180">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
|
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
|
||||||
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
|
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
|
||||||
@@ -126,6 +129,20 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||||
|
sortByName (a, b) {
|
||||||
|
return a.name.localeCompare(b.name)
|
||||||
|
},
|
||||||
|
sortByType (a, b) {
|
||||||
|
return a.type.localeCompare(b.type)
|
||||||
|
},
|
||||||
|
sortBySite (a, b) {
|
||||||
|
const siteA = this.getSiteName(a.key)
|
||||||
|
if (!siteA) {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return siteA.localeCompare(this.getSiteName(b.key))
|
||||||
|
}
|
||||||
|
},
|
||||||
detailEvent (e) {
|
detailEvent (e) {
|
||||||
this.detail = {
|
this.detail = {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -284,7 +301,7 @@ export default {
|
|||||||
},
|
},
|
||||||
exportFavoritesEvent () {
|
exportFavoritesEvent () {
|
||||||
const arr = [...this.list]
|
const arr = [...this.list]
|
||||||
const str = JSON.stringify(arr, null, 4)
|
const str = JSON.stringify(arr, null, 2)
|
||||||
const options = {
|
const options = {
|
||||||
filters: [
|
filters: [
|
||||||
{ name: 'JSON file', extensions: ['json'] },
|
{ name: 'JSON file', extensions: ['json'] },
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ db.version(3).stores({
|
|||||||
setting: 'id, theme, site, shortcut, view, externalPlayer, searchAllSites, excludeRootClasses, excludeR18Films, forwardTimeInSec',
|
setting: 'id, theme, site, shortcut, view, externalPlayer, searchAllSites, excludeRootClasses, excludeR18Films, forwardTimeInSec',
|
||||||
shortcut: 'name, key, desc',
|
shortcut: 'name, key, desc',
|
||||||
star: '++id, site, ids, name, type, year, index',
|
star: '++id, site, ids, name, type, year, index',
|
||||||
sites: '++id, key, name, api, download, isActive',
|
sites: '++id, key, name, api, download, isActive, group',
|
||||||
history: '++id, site, ids, name, type, year, index, time',
|
history: '++id, site, ids, name, type, year, index, time',
|
||||||
mini: 'id, site, ids, name, index, time',
|
mini: 'id, site, ids, name, index, time',
|
||||||
iptv: '++id, name, url, group'
|
iptv: '++id, name, url, group'
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ export default {
|
|||||||
async add (doc) {
|
async add (doc) {
|
||||||
return await history.add(doc)
|
return await history.add(doc)
|
||||||
},
|
},
|
||||||
|
async bulkAdd (doc) {
|
||||||
|
return await history.bulkAdd(doc)
|
||||||
|
},
|
||||||
async find (doc) {
|
async find (doc) {
|
||||||
return await history.get(doc)
|
return await history.get(doc)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ const sites = [
|
|||||||
name: 'OK 资源网',
|
name: 'OK 资源网',
|
||||||
api: 'http://cj.okzy.tv/inc/api.php',
|
api: 'http://cj.okzy.tv/inc/api.php',
|
||||||
download: 'http://cj.okzy.tv/inc/apidown.php',
|
download: 'http://cj.okzy.tv/inc/apidown.php',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
@@ -27,7 +28,8 @@ const sites = [
|
|||||||
name: '最大资源网',
|
name: '最大资源网',
|
||||||
api: 'http://www.zdziyuan.com/inc/api.php',
|
api: 'http://www.zdziyuan.com/inc/api.php',
|
||||||
download: 'http://www.zdziyuan.com/inc/apidown.php',
|
download: 'http://www.zdziyuan.com/inc/apidown.php',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
@@ -35,7 +37,8 @@ const sites = [
|
|||||||
name: '豆瓣电影资源',
|
name: '豆瓣电影资源',
|
||||||
api: 'http://v.1988cj.com/inc/api.php',
|
api: 'http://v.1988cj.com/inc/api.php',
|
||||||
download: 'http://v.1988cj.com/inc/apidown.php',
|
download: 'http://v.1988cj.com/inc/apidown.php',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
@@ -43,7 +46,8 @@ const sites = [
|
|||||||
name: '135 资源网',
|
name: '135 资源网',
|
||||||
api: 'http://cj.zycjw1.com/inc/api.php',
|
api: 'http://cj.zycjw1.com/inc/api.php',
|
||||||
download: 'http://cj.zycjw1.com/inc/apidown.php',
|
download: 'http://cj.zycjw1.com/inc/apidown.php',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
@@ -51,7 +55,8 @@ const sites = [
|
|||||||
name: '酷云资源',
|
name: '酷云资源',
|
||||||
api: 'http://caiji.kuyun98.com/inc/ldg_api.php',
|
api: 'http://caiji.kuyun98.com/inc/ldg_api.php',
|
||||||
download: 'http://caiji.kuyun98.com/inc/apidown.php',
|
download: 'http://caiji.kuyun98.com/inc/apidown.php',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
@@ -59,7 +64,8 @@ const sites = [
|
|||||||
name: '芒果 TV 资源网',
|
name: '芒果 TV 资源网',
|
||||||
api: 'https://api.shijiapi.com/api.php/provide/vod/at/xml/',
|
api: 'https://api.shijiapi.com/api.php/provide/vod/at/xml/',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 7,
|
id: 7,
|
||||||
@@ -67,7 +73,8 @@ const sites = [
|
|||||||
name: '速播资源站',
|
name: '速播资源站',
|
||||||
api: 'https://www.subo988.com/inc/api.php',
|
api: 'https://www.subo988.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 8,
|
id: 8,
|
||||||
@@ -75,7 +82,8 @@ const sites = [
|
|||||||
name: '209 资源',
|
name: '209 资源',
|
||||||
api: 'http://cj.1156zy.com/inc/api.php',
|
api: 'http://cj.1156zy.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 9,
|
id: 9,
|
||||||
@@ -83,7 +91,8 @@ const sites = [
|
|||||||
name: '最新资源',
|
name: '最新资源',
|
||||||
api: 'http://api.zuixinapi.com/inc/api.php',
|
api: 'http://api.zuixinapi.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 10,
|
id: 10,
|
||||||
@@ -91,7 +100,8 @@ const sites = [
|
|||||||
name: '酷播资源',
|
name: '酷播资源',
|
||||||
api: 'http://api.kbzyapi.com/inc/api.php',
|
api: 'http://api.kbzyapi.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 11,
|
id: 11,
|
||||||
@@ -99,7 +109,8 @@ const sites = [
|
|||||||
name: '永久资源',
|
name: '永久资源',
|
||||||
api: 'http://cj.yongjiuzyw.com/inc/api.php',
|
api: 'http://cj.yongjiuzyw.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 12,
|
id: 12,
|
||||||
@@ -107,7 +118,8 @@ const sites = [
|
|||||||
name: '123 资源',
|
name: '123 资源',
|
||||||
api: 'http://cj.123ku2.com:12315/inc/api.php',
|
api: 'http://cj.123ku2.com:12315/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 13,
|
id: 13,
|
||||||
@@ -115,7 +127,8 @@ const sites = [
|
|||||||
name: '88 影视资源站',
|
name: '88 影视资源站',
|
||||||
api: 'http://www.88zyw.net/inc/api.php',
|
api: 'http://www.88zyw.net/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 14,
|
id: 14,
|
||||||
@@ -123,7 +136,8 @@ const sites = [
|
|||||||
name: '卧龙资源',
|
name: '卧龙资源',
|
||||||
api: 'http://cj.wlzy.tv/inc/api_mac.php',
|
api: 'http://cj.wlzy.tv/inc/api_mac.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 15,
|
id: 15,
|
||||||
@@ -131,7 +145,8 @@ const sites = [
|
|||||||
name: '麻花资源',
|
name: '麻花资源',
|
||||||
api: 'https://www.mhapi123.com/inc/api.php',
|
api: 'https://www.mhapi123.com/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 16,
|
id: 16,
|
||||||
@@ -139,7 +154,8 @@ const sites = [
|
|||||||
name: '快快资源',
|
name: '快快资源',
|
||||||
api: 'https://api.kkzy.tv/inc/api.php',
|
api: 'https://api.kkzy.tv/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 17,
|
id: 17,
|
||||||
@@ -147,7 +163,8 @@ const sites = [
|
|||||||
name: '壹伍捌资源网',
|
name: '壹伍捌资源网',
|
||||||
api: 'http://cj.158zyz.net:158/inc/api.php',
|
api: 'http://cj.158zyz.net:158/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 18,
|
id: 18,
|
||||||
@@ -155,7 +172,8 @@ const sites = [
|
|||||||
name: '人人资源',
|
name: '人人资源',
|
||||||
api: 'https://www.rrzyw.cc/api.php/provide/vod/from/rrm3u8/at/xml/',
|
api: 'https://www.rrzyw.cc/api.php/provide/vod/from/rrm3u8/at/xml/',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 19,
|
id: 19,
|
||||||
@@ -163,7 +181,8 @@ const sites = [
|
|||||||
name: '魔卡资源网',
|
name: '魔卡资源网',
|
||||||
api: 'https://cj.heiyap.com/api.php/provide/vod/at/xml/',
|
api: 'https://cj.heiyap.com/api.php/provide/vod/at/xml/',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 20,
|
id: 20,
|
||||||
@@ -171,7 +190,8 @@ const sites = [
|
|||||||
name: '快影资源站',
|
name: '快影资源站',
|
||||||
api: 'https://www.kyzy.tv/api.php/kyyun/vod/at/xml/',
|
api: 'https://www.kyzy.tv/api.php/kyyun/vod/at/xml/',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 21,
|
id: 21,
|
||||||
@@ -179,7 +199,8 @@ const sites = [
|
|||||||
name: '搜乐资源网',
|
name: '搜乐资源网',
|
||||||
api: 'https://www.caijizy.vip/api.php/provide/vod/at/xml/',
|
api: 'https://www.caijizy.vip/api.php/provide/vod/at/xml/',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 22,
|
id: 22,
|
||||||
@@ -187,7 +208,8 @@ const sites = [
|
|||||||
name: '步步高顶尖资源网',
|
name: '步步高顶尖资源网',
|
||||||
api: 'http://api.bbkdj.com/api',
|
api: 'http://api.bbkdj.com/api',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 23,
|
id: 23,
|
||||||
@@ -195,7 +217,8 @@ const sites = [
|
|||||||
name: '1886 资源',
|
name: '1886 资源',
|
||||||
api: 'http://cj.1886zy.co/inc/api.php',
|
api: 'http://cj.1886zy.co/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 24,
|
id: 24,
|
||||||
@@ -203,7 +226,8 @@ const sites = [
|
|||||||
name: '秒播资源',
|
name: '秒播资源',
|
||||||
api: 'http://caiji.mb77.vip/inc/api.php',
|
api: 'http://caiji.mb77.vip/inc/api.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 25,
|
id: 25,
|
||||||
@@ -211,7 +235,8 @@ const sites = [
|
|||||||
name: '605资源',
|
name: '605资源',
|
||||||
api: 'http://www.605zy.net/inc/seacmsapi.php',
|
api: 'http://www.605zy.net/inc/seacmsapi.php',
|
||||||
download: '',
|
download: '',
|
||||||
isActive: 1
|
isActive: 1,
|
||||||
|
group: '默认'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user