Compare commits

...

29 Commits

Author SHA1 Message Date
haiyangcui
d647d2ecec v2.5.0 2020-10-04 12:49:21 +02:00
haiyangcui
7f9f847d73 内置腾讯云直播源 2020-10-04 12:29:10 +02:00
haiyangcui
36e0b140cd 解决中文乱码问题 2020-10-04 12:20:24 +02:00
haiyangcui
99948770ff 读取m3u文件 2020-10-04 11:08:21 +02:00
haiyangcui
5300d777ce 移除无用链接 2020-10-04 10:30:49 +02:00
haiyangcui
64da42524d 添加赞赏码 2020-10-04 10:30:29 +02:00
haiyangcui
1ebdfee7bc 支持播放器内播放直播 2020-10-03 23:17:19 +02:00
haiyangcui
17ba319157 添加"导入" "导出" "重置" 2020-10-01 23:33:24 +02:00
haiyangcui
27bdc3559d 添加新频道页面 2020-10-01 23:33:21 +02:00
haiyangcui
ca53a22598 添加删除功能 2020-10-01 23:33:18 +02:00
haiyangcui
6632318cf6 添加简单的IPTV页面 2020-10-01 23:33:15 +02:00
haiyangcui
cb7a4af7ae 2.4.10.1 国庆版 2020-10-01 13:34:21 +02:00
haiyangcui
25340b79aa v2.4.9 2020-09-30 21:33:08 +02:00
haiyangcui
381b0a8735 记录窗口大小及位置 2020-09-30 21:11:54 +02:00
haiyangcui
c7b99244bb 更新style 2020-09-29 23:08:23 +02:00
haiyangcui
5b5826e9a6 改进checkbox的点击效果 2020-09-29 17:43:14 +02:00
haiyangcui
03e2f2673b 更新style 2020-09-29 17:37:47 +02:00
haiyangcui
503a90d8da 转移收藏相关操作到收藏页面 2020-09-29 15:23:09 +02:00
haiyangcui
afb92d59ff 可设置快进快退的步长 2020-09-28 23:30:24 +02:00
haiyangcui
d26f1cbdf7 简影 2020-09-28 21:11:48 +02:00
haiyangcui
7f821b05ad 哆咪动漫 2020-09-28 20:53:48 +02:00
haiyangcui
746c93c9d2 樱花动漫 2020-09-28 20:53:15 +02:00
haiyangcui
9fb51ed8fc 点击'播放在线高清视频'也可以控制check box的开关 2020-09-28 17:51:56 +02:00
haiyangcui
6a1c045e0b 解析网站的代码放到onlineVideo里 2020-09-28 16:38:31 +02:00
haiyangcui
756b8ecc33 添加"素白白"的支持 2020-09-27 17:59:13 +02:00
haiyangcui
b4946a6c99 比较在线搜索结果时,忽略空格 2020-09-27 15:11:56 +02:00
haiyangcui
cbde4180ab 2.4.8 2020-09-27 15:02:24 +02:00
haiyangcui
00dab782e8 搜索的时候设置timeout,解决全局搜索结果无法打开的问题 2020-09-27 14:55:56 +02:00
haiyangcui
89d6183841 支持播放在线高清视频 2020-09-27 13:44:38 +02:00
23 changed files with 1330 additions and 152 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "zy",
"version": "2.4.7",
"version": "2.5.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
@@ -28,6 +28,7 @@
"express": "^4.17.1",
"fast-xml-parser": "^3.17.4",
"html2canvas": "^1.0.0-rc.5",
"m3u8": "0.0.10",
"modern-normalize": "^0.6.0",
"mousetrap": "^1.6.5",
"qrcode.vue": "^1.7.0",

View File

@@ -5,6 +5,7 @@
<Frame />
<Film v-show="view === 'Film'" />
<Play v-show="view === 'Play'" />
<IPTV v-show="view === 'IPTV'" />
<Star v-show="view === 'Star'" />
<History v-show="view === 'History'" />
<Setting v-show="view === 'Setting'" />
@@ -22,11 +23,61 @@
</template>
<script>
import { setting } from './lib/dexie'
const { remote } = require('electron')
export default {
name: 'App',
data () {
return {
appTheme: 'theme-light'
appTheme: 'theme-light',
winSizePosition: {
x: 0,
y: 0,
width: 0,
height: 0
}
}
},
created () {
// 窗口创建口,检查是否有窗口大小位置的记录,如果有的话,更新窗口位置及大小
setting.find().then(res => {
if (res.windowSizePosition) {
var win = remote.getCurrentWindow()
win.setBounds({
x: res.windowSizePosition.x,
y: res.windowSizePosition.y,
width: res.windowSizePosition.width,
height: res.windowSizePosition.height
})
}
})
var win = remote.getCurrentWindow()
this.winSizePosition = {
x: win.getPosition()[0],
y: win.getPosition()[1],
width: win.getSize()[0],
height: win.getSize()[1]
}
},
updated () {
// 本来想hook up到beforedestroy 但不工作
// 每当窗口更新时检查窗口大小及位置记录到setting数据库中
const win = remote.getCurrentWindow()
var newWinSizePosition = {
x: win.getPosition()[0],
y: win.getPosition()[1],
width: win.getSize()[0],
height: win.getSize()[1]
}
if (newWinSizePosition.x !== this.winSizePosition.x ||
newWinSizePosition.y !== this.winSizePosition.y ||
newWinSizePosition.width !== this.winSizePosition.width ||
newWinSizePosition.height !== this.winSizePosition.height) {
this.winSizePosition = newWinSizePosition
setting.find().then(res => {
res.windowSizePosition = newWinSizePosition
setting.update(res)
})
}
},
computed: {

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -78,15 +78,21 @@
}
}
}
.zy-checkbox{
.zy-input{
position: relative;
display: inline-block;
white-space: nowrap;
width: 200px;
height: 30px;
vertical-align: middle;
align-items: center;
.search-all-check-input{
cursor: pointer;
cursor: pointer;
input{
vertical-align: bottom;
position: relative;
border: none;
width: 20px;
height: 15px;
background-color: #ffffff00;
text-indent: 10px;
}
}
.zy-highlighted{
@@ -101,13 +107,14 @@
.tHeader{
display: flex;
align-items: center;
justify-content: flex-end;
justify-content: space-between;
height: 50px;
min-height: 50px;
width: 100%;
border-bottom: 1px solid;
.btn{
user-select: none;
margin-left: 15px;
margin-right: 15px;
cursor: pointer;
font-size: 14px;

View File

@@ -24,6 +24,8 @@
}
}
.vs-input{
color: var(--d-fc-1);
background-color: var(--d-bgc-1);
input{
color: var(--d-fc-1);
&::-webkit-input-placeholder{
@@ -32,6 +34,13 @@
}
}
}
.zy-input{
color: var(--d-fc-1);
background-color: var(--d-bgc-1);
input{
color: var(--d-fc-1);
}
}
.zy-checkbox{
color: var(--d-fc-1);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);

View File

@@ -32,6 +32,14 @@
}
}
}
.zy-input{
color: var(--g-fc-1);
background-color: var(--g-bgc-1);
input{
color: var(--g-fc-1);
background-color: var(--g-bgc-1);
}
}
.zy-checkbox{
color: var(--g-fc-1);
}

View File

@@ -32,6 +32,14 @@
}
}
}
.zy-input{
color: var(--l-fc-1);
background-color: var(--l-bgc-1);
input{
color: var(--l-fc-1);
background-color: var(--l-bgc-1);
}
}
.zy-checkbox{
color: var(--l-fc-1);
}

View File

@@ -32,6 +32,13 @@
}
}
}
.zy-input{
color: var(--p-fc-1);
background-color: var(--p-bgc-1);
input{
color: var(--p-fc-1);
}
}
.zy-checkbox{
color: var(--p-fc-1);
}

View File

@@ -2,7 +2,7 @@
<div class="aside">
<span :class="[view === 'Film' ? 'active ': ''] + 'zy-svg'" @click="changeView('Film')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="apertureIconTitle">
<title id="apertureIconTitle">view</title>
<title id="apertureIconTitle">电影</title>
<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"></path>
<g stroke-linecap="round">
<path d="M3 16H14.3164"></path>
@@ -16,7 +16,7 @@
</span>
<span :class="[view === 'Play' ? 'active ': ''] + 'zy-svg'" @click="changeView('Play')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="playIconTitle">
<title id="playIconTitle">play</title>
<title id="playIconTitle">播放</title>
<path d="M20 12L5 21V3z"></path>
</svg>
</span>
@@ -26,6 +26,13 @@
<path d="M12,21 L10.55,19.7051771 C5.4,15.1242507 2,12.1029973 2,8.39509537 C2,5.37384196 4.42,3 7.5,3 C9.24,3 10.91,3.79455041 12,5.05013624 C13.09,3.79455041 14.76,3 16.5,3 C19.58,3 22,5.37384196 22,8.39509537 C22,12.1029973 18.6,15.1242507 13.45,19.7149864 L12,21 Z"></path>
</svg>
</span>
<span :class="[view === 'IPTV' ? 'active ': ''] + 'zy-svg'" @click="changeView('IPTV')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="tvIconTitle">
<title id="tvIconTitle">IPTV</title>
<polygon points="20 8 20 20 4 20 4 8"></polygon>
<polyline stroke-linejoin="round" points="8 4 12 7.917 16 4"></polyline>
</svg>
</span>
<span :class="[view === 'History' ? 'active ': ''] + 'zy-svg'" @click="changeView('History')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="timeIconTitle">
<title id="timeIconTitle">历史记录</title>
@@ -35,7 +42,7 @@
</span>
<span :class="[view === 'Setting' ? 'active ': ''] + 'zy-svg'" @click="changeView('Setting')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="settingsIconTitle">
<title id="settingsIconTitle">setting</title>
<title id="settingsIconTitle">设置</title>
<path d="M5.03506429,12.7050339 C5.01187484,12.4731696 5,12.2379716 5,12 C5,11.7620284 5.01187484,11.5268304 5.03506429,11.2949661 L3.20577137,9.23205081 L5.20577137,5.76794919 L7.9069713,6.32070904 C8.28729123,6.0461342 8.69629298,5.80882212 9.12862533,5.61412402 L10,3 L14,3 L14.8713747,5.61412402 C15.303707,5.80882212 15.7127088,6.0461342 16.0930287,6.32070904 L18.7942286,5.76794919 L20.7942286,9.23205081 L18.9649357,11.2949661 C18.9881252,11.5268304 19,11.7620284 19,12 C19,12.2379716 18.9881252,12.4731696 18.9649357,12.7050339 L20.7942286,14.7679492 L18.7942286,18.2320508 L16.0930287,17.679291 C15.7127088,17.9538658 15.303707,18.1911779 14.8713747,18.385876 L14,21 L10,21 L9.12862533,18.385876 C8.69629298,18.1911779 8.28729123,17.9538658 7.9069713,17.679291 L5.20577137,18.2320508 L3.20577137,14.7679492 L5.03506429,12.7050339 Z"></path>
<circle cx="12" cy="12" r="1"></circle>
</svg>

View File

@@ -34,6 +34,15 @@
<span @click="downloadEvent">下载</span>
<span @click="shareEvent">分享</span>
<span @click="doubanLinkEvent">豆瓣</span>
<span @click="togglePlayOnlineEvent">
<input type="checkbox" v-model="playOnline"> 播放在线高清视频
</span>
<span>
<select v-model="selectedOnlineSite" class="vs-options">
<option disabled value="">Please select one</option>
<option v-for="(i, j) in onlineSites" :key="j">{{i}}</option>
</select>
</span>
</div>
<div class="desc" v-show="info.des">{{info.des}}</div>
<div class="m3u8">
@@ -51,6 +60,7 @@
<script>
import { mapMutations } from 'vuex'
import zy from '../lib/site/tools'
import onlineVideo from '../lib/site/onlineVideo'
import { star, history } from '../lib/dexie'
const { clipboard } = require('electron')
export default {
@@ -59,7 +69,10 @@ export default {
return {
loading: true,
m3u8List: [],
info: {}
info: {},
playOnline: false,
selectedOnlineSite: '哔嘀',
onlineSites: ['哔嘀', '素白白', '简影', '1080影视']
}
},
filters: {
@@ -121,16 +134,36 @@ export default {
}
},
playEvent (n) {
history.find({ site: this.detail.key, ids: this.detail.info.id }).then(res => {
if (res) {
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: n, site: this.detail.site } }
} else {
this.video = { key: this.detail.key, info: { id: this.detail.info.id, name: this.detail.info.name, index: n, site: this.detail.site } }
}
})
this.view = 'Play'
this.detail.show = false
if (!this.playOnline) {
history.find({ site: this.detail.key, ids: this.detail.info.id }).then(res => {
if (res) {
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: n, site: this.detail.site } }
} else {
this.video = { key: this.detail.key, info: { id: this.detail.info.id, name: this.detail.info.name, index: n, site: this.detail.site } }
}
})
this.view = 'Play'
this.detail.show = false
} else {
history.find({ site: this.detail.key, ids: this.detail.info.id }).then(res => {
if (res) {
res.index = n
history.update(res.id, res)
} else {
const doc = {
site: this.detail.key,
ids: this.detail.info.id,
name: this.detail.info.name,
type: this.detail.info.type,
year: this.detail.info.year,
index: n,
time: ''
}
history.add(doc)
}
})
this.playVideoOnline(this.detail.info.name, n)
}
},
starEvent () {
star.find({ key: this.detail.key, ids: this.info.id }).then(res => {
@@ -154,6 +187,33 @@ export default {
this.$message.warning('收藏失败')
})
},
togglePlayOnlineEvent () {
this.playOnline = !this.playOnline
},
playVideoOnline (videoName, videoIndex) {
switch (this.selectedOnlineSite) {
case '哔嘀':
onlineVideo.playVideoOnBde4(videoName, videoIndex)
break
case '1080影视':
onlineVideo.playVideoOnK1080(videoName, videoIndex)
break
case '素白白':
onlineVideo.playVideoOnSubaibai(videoName, videoIndex)
break
case '哆咪动漫':
onlineVideo.playVideoOndmdm2020(videoName, videoIndex)
break
case '樱花动漫':
onlineVideo.playVideoOnYhdm(videoName, videoIndex)
break
case '简影':
onlineVideo.playVideoOnSyrme(videoName, videoIndex)
break
default:
this.$message.console.error(`不支持该网站:${this.selectedOnlineSite}`)
}
},
downloadEvent () {
zy.download(this.detail.key, this.info.id).then(res => {
if (res && res.dl && res.dl.dd) {

View File

@@ -422,7 +422,7 @@ export default {
}
this.getAllSearch()
})
sites.forEach(site =>
sites.forEach(site => {
zy.search(site.key, wd).then(res => {
const type = Object.prototype.toString.call(res)
if (type === '[object Array]') {
@@ -436,7 +436,7 @@ export default {
this.searchContents.push(res)
}
})
)
})
} else {
this.show.find = false
this.getClass().then(res => {

View File

@@ -3,6 +3,7 @@
<div class="body zy-scroll">
<div class="zy-table">
<div class="tHeader">
<span class="btn"></span>
<span class="btn" @click="clearAllHistory">清空</span>
</div>
<div class="tBody zy-scroll">

279
src/components/IPTV.vue Normal file
View File

@@ -0,0 +1,279 @@
<template>
<div class="detail">
<div class="detail-content">
<div class="detail-header">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="openAddSite">添加新频道</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportSites">导出</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importSites">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="resetSites">重置</div>
</div>
</div>
<div class="detail-body zy-scroll">
<div class="zy-table">
<div class="tBody zy-scroll">
<div class="iptv-box zy-scroll" v-show="showAddSite">
<ul>
<li >
<span class="name">频道名</span>
<span class="name">Url</span>
<span class="operate">
<span class="btn"></span>
<span class="btn"></span>
</span>
</li>
<li>
<span class="name" style="display:inline-block;vertical-align:middle">
<input style="height: 30px" v-model="newSite.name">
</span>
<span class="name" style="display:inline-block;vertical-align:middle">
<input style="height: 30px" v-model="newSite.url">
</span>
<span class="operate">
<span class="btn" @click="addNewSite">添加</span>
<span class="btn" @click="closeAddSite">关闭</span>
</span>
</li>
<li ></li>
</ul>
</div>
<ul>
<draggable v-model="iptvList" @change="listUpdatedEvent">
<transition-group>
<li v-for="(i, j) in iptvList" :key="j" @click.stop="playEvent(i)">
<span class="name">{{i.name}}</span>
<span class="operate">
<span class="btn" @click.stop="playEvent(i)">播放</span>
<span class="btn" @click.stop="removeEvent(i)">删除</span>
</span>
</li>
</transition-group>
</draggable>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { iptv } from '../lib/dexie'
import draggable from 'vuedraggable'
import { iptv as defaultSites } from '../lib/dexie/initData'
import { remote } from 'electron'
import fs from 'fs'
export default {
name: 'iptv',
data () {
return {
iptvList: [],
showAddSite: false,
newSite:
{
name: '',
site: ''
}
}
},
components: {
draggable
},
computed: {
view: {
get () {
return this.$store.getters.getView
},
set (val) {
this.SET_VIEW(val)
}
},
setting () {
return this.$store.getters.getSetting
},
video: {
get () {
return this.$store.getters.getVideo
},
set (val) {
this.SET_VIDEO(val)
}
}
},
watch: {
view () {
this.getAllSites()
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
playEvent (e) {
this.video = { info: { url: e.url } }
this.view = 'Play'
},
removeEvent (e) {
iptv.remove(e.id).then(res => {
this.getAllSites()
}).catch(err => {
this.$message.warning('删除频道失败, 错误信息: ' + err)
})
},
closeAddSite () {
this.showAddSite = false
},
openAddSite () {
this.showAddSite = true
},
addNewSite () {
if (!this.newSite.name || !this.newSite.url) {
this.$message.error('名称和API接口不能为空。')
return
}
var doc = {
name: this.newSite.name,
url: this.newSite.url
}
iptv.add(doc).then(res => {
this.newSite = {
name: '',
url: ''
}
this.$message.success('添加新源成功!')
this.getAllSites()
})
},
listUpdatedEvent () {
iptv.clear().then(res1 => {
// 重新排序
var id = 1
this.iptvList.forEach(element => {
element.id = id
iptv.add(element)
id += 1
})
})
},
exportSites () {
this.getAllSites()
const arr = [...this.iptvList]
const str = JSON.stringify(arr, null, 4)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
}).catch(err => {
this.$message.error(err)
})
},
importSites () {
const options = {
filters: [
{ name: 'm3u file', extensions: ['m3u'] },
{ name: 'JSON file', extensions: ['json'] }
],
properties: ['openFile']
}
remote.dialog.showOpenDialog(options).then(result => {
if (!result.canceled) {
result.filePaths.forEach(file => {
if (file.endsWith('json')) {
var str = fs.readFileSync(file)
const json = JSON.parse(str)
iptv.clear().then(res => {
iptv.bulkAdd(json).then(e => {
this.getAllSites()
this.$message.success('导入成功')
})
})
} else if (file.endsWith('m3u')) {
var m3u8 = require('m3u8')
var parser = m3u8.createStream()
var m3ufile = fs.createReadStream(file, { encoding: 'utf-8' })
m3ufile.pipe(parser)
var docs = []
parser.on('item', function (item) {
var prop = item.properties
if (prop.title && prop.uri && prop.uri.endsWith('m3u8')) {
var doc = {
name: prop.title,
url: prop.uri
}
docs.push(doc)
}
})
iptv.clear().then(res => {
iptv.bulkAdd(docs).then(e => {
this.getAllSites()
this.$message.success('导入成功')
})
})
}
})
}
})
},
resetSites () {
iptv.clear()
iptv.bulkAdd(defaultSites).then(e => {
this.getAllSites()
this.$message.success('重置成功')
})
},
getAllSites () {
iptv.all().then(res => {
this.iptvList = res
})
}
},
created () {
this.getAllSites()
}
}
</script>
<style lang="scss" scoped>
.detail{
position: absolute;
left: 80px;
right: 20px;
bottom: 0;
width: calc(100% - 100px);
height: calc(100% - 40px);
z-index: 888;
.detail-content{
height: calc(100% - 10px);
padding: 0 60px;
position: relative;
.detail-header{
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.detail-title{
font-size: 16px;
}
.detail-close{
cursor: pointer;
}
}
}
.detail-body{
height: calc(100% - 50px);
overflow-y: auto;
}
}
</style>

View File

@@ -297,17 +297,25 @@ export default {
}
}
const index = this.video.info.index | 0
let time = 0
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
if (res) {
if (res.index === index) {
time = res.time
if (this.video.info.url) {
// 如果info里含有有url是直播源直接播放
this.playUrl(this.video.info.url)
} else {
const index = this.video.info.index | 0
let time = 0
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
if (res) {
if (res.index === index) {
time = res.time
}
}
}
this.playVideo(index, time)
})
this.playVideo(index, time)
})
}
},
playUrl (url) {
this.xg.src = url
this.xg.play()
},
playVideo (index = 0, time = 0) {
this.fetchM3u8List().then(m3u8Arr => {
@@ -713,13 +721,13 @@ export default {
}
if (e === 'forward') {
if (this.xg && !this.xg.paused) {
this.xg.currentTime += 5
this.xg.currentTime += parseInt(this.setting.forwardTimeInSec)
}
return false
}
if (e === 'back') {
if (this.xg && !this.xg.paused) {
this.xg.currentTime -= 5
this.xg.currentTime -= parseInt(this.setting.forwardTimeInSec)
}
return false
}

View File

@@ -42,24 +42,16 @@
</div>
</div>
</div>
<div class='site'>
<div class="title">收藏管理</div>
<div class="site-box">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportFavorites">导出</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importFavorites">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="clearFavorites">清空收藏</div>
</div>
</div>
<div class="site">
<div class="title">定位时间设置</div>
<div class="zy-input">
/右方向键:<input style="width:50px" type="number" v-model = "d.forwardTimeInSec" @change="updateSettingEvent($event)">
</div>
</div>
<div class='search'>
<div class="title">搜索</div>
<div class="zy-checkbox">
<input type="checkbox" v-model="setting.searchAllSites" @change="updateSearchOption($event)"> 搜索所有资源
<div class="zy-input" @click="toggleSearchAllSites">
<input type="checkbox" v-model="d.searchAllSites" @change="updateSettingEvent($event)"> 搜索所有资源
</div>
</div>
<div class='site'>
@@ -72,9 +64,9 @@
<div class="vs-placeholder vs-noAfter" v-show = "editPlayerPath == false">
<label>编辑</label>
</div>
<input class="vs-input" v-show = "editPlayerPath == true" v-model = "d.externalPlayer"
@blur= "updatePlayerPath"
@keyup.enter = "updatePlayerPath">
<input class="zy-input" v-show = "editPlayerPath == true" v-model = "d.externalPlayer"
@blur= "updateSettingEvent"
@keyup.enter = "updateSettingEvent">
</div>
</div>
</div>
@@ -93,8 +85,8 @@
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="resetSites">重置源</div>
</div>
<div class="zy-checkbox">
<input type="checkbox" v-model="setting.excludeR18Films" @change="updateExcludeR18FilmOption($event)"> 屏蔽福利片
<div class="zy-input" @click="toggleExcludeR18Films">
<input type="checkbox" v-model="d.excludeR18Films" @change="updateSettingEvent($event)"> 屏蔽福利片
</div>
</div>
</div>
@@ -132,6 +124,7 @@
<div class="qrcode-box">
<img class="qrcode-item" src="../assets/image/alipay.png">
<img class="qrcode-item" src="../assets/image/wepay.jpg">
<img class="qrcode-item" src="../assets/image/wepay_cuiocean.jpg">
</div>
</div>
<div class="clearDB">
@@ -169,6 +162,7 @@ export default {
editPlayerPath: false,
excludeR18Films: false,
latestVersion: pkg.version,
forwardTimeInSec: 5,
d: {
id: 0,
site: '',
@@ -178,7 +172,8 @@ export default {
view: 'picture',
externalPlayer: '',
editPlayerPath: false,
excludeR18Films: true
excludeR18Films: true,
forwardTimeInSec: 5
}
}
},
@@ -213,10 +208,11 @@ export default {
theme: res.theme,
shortcut: res.shortcut,
view: res.view,
searchAllSites: res.searchAllSites,
searchAllSites: res.searchAllSites ? res.searchAllSites : true,
externalPlayer: res.externalPlayer,
editPlayerPath: false,
excludeR18Films: res.excludeR18Films
excludeR18Films: res.excludeR18Films ? res.excludeR18Films : true,
forwardTimeInSec: res.forwardTimeInSec ? res.forwardTimeInSec : 5
}
this.setting = this.d
})
@@ -252,85 +248,17 @@ export default {
this.show.site = false
})
},
updateSearchOption (e) {
this.d.searchAllSites = this.setting.searchAllSites
setting.update(this.setting)
updateSettingEvent (e) {
this.editPlayerPath = false
setting.update(this.d)
},
updateExcludeR18FilmOption (e) {
this.d.excludeR18Films = this.setting.excludeR18Films
setting.update(this.setting)
toggleSearchAllSites () {
this.d.searchAllSites = !this.d.searchAllSites
setting.update(this.d)
},
exportFavorites () {
this.getFavorites()
const arr = [...this.favoritesList]
const str = JSON.stringify(arr, null, 4)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
}).catch(err => {
this.$message.error(err)
})
},
importFavorites () {
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
],
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)
star.bulkAdd(json).then(e => {
this.getFavorites()
})
this.upgradeFavorites()
})
this.$message.success('导入收藏成功')
}
}).catch(err => {
this.$message.error(err)
})
},
clearFavorites () {
star.clear().then(e => {
this.getFavorites()
this.$message.success('清空所有收藏成功')
})
},
upgradeFavorites () {
star.all().then(res => {
res.forEach(element => {
const docs = {
key: element.key,
ids: element.ids,
name: element.name,
type: element.type,
year: element.year,
last: element.last,
note: element.note
}
star.find({ key: element.key, ids: element.ids }).then(res => {
if (!res) {
star.add(docs)
}
})
})
this.getFavorites()
})
toggleExcludeR18Films () {
this.d.excludeR18Films = !this.d.excludeR18Films
setting.update(this.d)
},
selectLocalPlayer () {
const options = {
@@ -345,7 +273,6 @@ export default {
var playerPath = result.filePaths[0].replace(/\\/g, '/')
this.$message.success('设定第三方播放器路径为:' + result.filePaths[0])
this.d.externalPlayer = playerPath
this.externalPlayer = playerPath
setting.update(this.d).then(res => {
this.setting = this.d
})

View File

@@ -3,7 +3,11 @@
<div class="body">
<div class="zy-table">
<div class="tHeader">
<span class="btn" @click="updateAllEvent(list)">同步所有收藏</span>
<span class="btn" @click="exportFavoritesEvent()">导出</span>
<span class="btn" @click="importFavoritesEvent()">导入</span>
<span class="btn" @click="clearFavoritesEvent()">清空</span>
<span class="btn"></span>
<span class="btn" @click="updateAllEvent()">同步所有收藏</span>
</div>
<div class="tBody zy-scroll">
<ul>
@@ -33,7 +37,7 @@
<span class="note">{{getHistoryNote(i.index)}}</span>
<span class="operate">
<span class="btn" @click.stop="playEvent(i)">播放</span>
<span class="btn" @click.stop="shareEvent(i)">分享</span>
<span class="btn" @click.stop="shareEvent(i)">分享</span>
<span class="btn" @click.stop="updateEvent(i)">同步</span>
<span class="btn" @click.stop="downloadEvent(i)">下载</span>
<span class="btn" @click.stop="deleteEvent(i)">删除</span>
@@ -52,6 +56,8 @@ import { mapMutations } from 'vuex'
import { star, history, sites } from '../lib/dexie'
import zy from '../lib/site/tools'
import draggable from 'vuedraggable'
import { remote } from 'electron'
import fs from 'fs'
const { clipboard } = require('electron')
export default {
@@ -101,7 +107,7 @@ export default {
},
watch: {
view () {
this.getStarList()
this.getFavorites()
this.getAllsites()
}
},
@@ -140,7 +146,7 @@ export default {
} else {
this.$message.success('删除成功')
}
this.getStarList()
this.getFavorites()
})
},
shareEvent (e) {
@@ -154,7 +160,7 @@ export default {
star.find({ id: e.id }).then(res => {
res.hasUpdate = false
star.update(e.id, res)
this.getStarList()
this.getFavorites()
})
},
listUpdatedEvent () {
@@ -192,15 +198,15 @@ export default {
this.$message.success(msg)
}
star.update(e.id, doc)
this.getStarList()
this.getFavorites()
})
}).catch(err => {
var msg = `同步"${e.name}"失败, 请重试。`
this.$message.warning(msg, err)
})
},
updateAllEvent (list) {
list.forEach(e => {
updateAllEvent () {
this.list.forEach(e => {
this.updateEvent(e)
})
},
@@ -259,7 +265,7 @@ export default {
return ''
}
},
getStarList () {
getFavorites () {
star.all().then(res => {
this.list = res.reverse()
})
@@ -268,10 +274,81 @@ export default {
sites.all().then(res => {
this.sites = res
})
},
exportFavoritesEvent () {
const arr = [...this.list]
const str = JSON.stringify(arr, null, 4)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
}).catch(err => {
this.$message.error(err)
})
},
importFavoritesEvent () {
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
],
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)
star.bulkAdd(json).then(e => {
this.getFavorites()
})
this.upgradeFavorites()
})
this.$message.success('导入收藏成功')
}
}).catch(err => {
this.$message.error(err)
})
},
upgradeFavorites () {
star.all().then(res => {
res.forEach(element => {
const docs = {
key: element.key,
ids: element.ids,
name: element.name,
type: element.type,
year: element.year,
last: element.last,
note: element.note
}
star.find({ key: element.key, ids: element.ids }).then(res => {
if (!res) {
star.add(docs)
}
})
})
this.getFavorites()
})
},
clearFavoritesEvent () {
star.clear().then(e => {
this.getFavorites()
this.$message.success('清空所有收藏成功')
})
}
},
created () {
this.getStarList()
this.getFavorites()
window.Sortable = require('sortablejs').Sortable
}
}

View File

@@ -9,6 +9,7 @@ import Detail from './Detail'
import Share from './Share'
import History from './History'
import EditSites from './EditSites'
import IPTV from './IPTV'
export default {
registerComponents () {
@@ -22,5 +23,6 @@ export default {
Vue.component('Share', Share)
Vue.component('History', History)
Vue.component('EditSites', EditSites)
Vue.component('IPTV', IPTV)
}
}

View File

@@ -1,5 +1,5 @@
import Dexie from 'dexie'
import { setting, sites, localKey } from './initData'
import { setting, sites, localKey, iptv } from './initData'
const db = new Dexie('zy')
@@ -10,13 +10,15 @@ db.version(3).stores({
star: '++id, site, ids, name, type, year, index',
sites: '++id, key, name, json, xml, down, level',
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'
})
db.on('populate', () => {
db.setting.bulkAdd(setting)
db.sites.bulkAdd(sites)
db.shortcut.bulkAdd(localKey)
db.iptv.bulkAdd(iptv)
})
db.open()

View File

@@ -5,6 +5,7 @@ import shortcut from './shortcut'
import star from './star'
import sites from './sites'
import search from './search'
import iptv from './iptv'
export {
history,
@@ -13,5 +14,6 @@ export {
shortcut,
star,
sites,
iptv,
search
}

View File

@@ -280,9 +280,483 @@ const getSite = (key) => {
}
}
const iptv = [
{
name: 'CCTV1-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv1hd/4000000/mnf.m3u8',
id: 5910
},
{
name: '北京卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/4000000/mnf.m3u8',
id: 5911
},
{
name: '江苏卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/4000000/mnf.m3u8',
id: 5912
},
{
name: '浙江卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/4000000/mnf.m3u8',
id: 5913
},
{
name: '深圳卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/4000000/mnf.m3u8',
id: 5914
},
{
name: '山东卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/4000000/mnf.m3u8',
id: 5915
},
{
name: '湖北卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/4000000/mnf.m3u8',
id: 5916
},
{
name: '广东卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/4000000/mnf.m3u8',
id: 5917
},
{
name: '东方卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hddfws/4000000/mnf.m3u8',
id: 5918
},
{
name: '黑龙江卫视1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/4000000/mnf.m3u8',
id: 5919
},
{
name: '五星体育1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/4000000/mnf.m3u8',
id: 5920
},
{
name: '上海Knews24 1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba8/4000000/mnf.m3u8',
id: 5921
},
{
name: 'CCTV-1HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv1hd/2300000/mnf.m3u8',
id: 5922
},
{
name: 'CCTV-2',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv2/1300000/mnf.m3u8',
id: 5923
},
{
name: 'CCTV-3',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv3/1300000/mnf.m3u8',
id: 5924
},
{
name: 'CCTV-4',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv4/1300000/mnf.m3u8',
id: 5925
},
{
name: 'CCTV-5',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv5/1300000/mnf.m3u8',
id: 5926
},
{
name: 'CCTV-6',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv6/1300000/mnf.m3u8',
id: 5927
},
{
name: 'CCTV-7',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv7/1300000/mnf.m3u8',
id: 5928
},
{
name: 'CCTV-8',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv8/1300000/mnf.m3u8',
id: 5929
},
{
name: 'CCTV-10',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv10/1300000/mnf.m3u8',
id: 5930
},
{
name: 'CCTV-11',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv11/1300000/mnf.m3u8',
id: 5931
},
{
name: 'CCTV-12',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv12/1300000/mnf.m3u8',
id: 5932
},
{
name: 'CCTV-13',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctvxw/1300000/mnf.m3u8',
id: 5933
},
{
name: 'CCTV-14',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctvse//1300000/mnf.m3u8',
id: 5934
},
{
name: 'CCTV-15',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cctvyy/1300000/mnf.m3u8',
id: 5935
},
{
name: '北京卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/1300000/mnf.m3u8',
id: 5936
},
{
name: '东方卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hddfws/1300000/mnf.m3u8',
id: 5937
},
{
name: '浙江卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/1300000/mnf.m3u8',
id: 5938
},
{
name: '湖北卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/1300000/mnf.m3u8',
id: 5939
},
{
name: '湖南卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hnwshd/1300000/mnf.m3u8',
id: 5940
},
{
name: '山东卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/1300000/mnf.m3u8',
id: 5941
},
{
name: '江苏卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/1300000/mnf.m3u8',
id: 5942
},
{
name: '深圳卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/1300000/mnf.m3u8',
id: 5943
},
{
name: '广东卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/1300000/mnf.m3u8',
id: 5944
},
{
name: '黑龙江卫视高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/1300000/mnf.m3u8',
id: 5945
},
{
name: '五星体育高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/1300000/mnf.m3u8',
id: 5946
},
{
name: '新闻24高清',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba8/1300000/mnf.m3u8',
id: 5947
},
{
name: '湖南卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hnwshd/2300000/mnf.m3u8',
id: 5948
},
{
name: '北京卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/2300000/mnf.m3u8',
id: 5949
},
{
name: '江苏卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/2300000/mnf.m3u8',
id: 5950
},
{
name: '浙江卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/2300000/mnf.m3u8',
id: 5951
},
{
name: '深圳卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/2300000/mnf.m3u8',
id: 5952
},
{
name: '山东卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/2300000/mnf.m3u8',
id: 5953
},
{
name: '湖北卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/2300000/mnf.m3u8',
id: 5954
},
{
name: '广东卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/2300000/mnf.m3u8',
id: 5955
},
{
name: '黑龙江卫视HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/2300000/mnf.m3u8',
id: 5956
},
{
name: '五星体育HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/2300000/mnf.m3u8',
id: 5957
},
{
name: '法治天地HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/fztd/1300000/mnf.m3u8',
id: 5958
},
{
name: '欢笑剧场HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hxjc/1300000/mnf.m3u8',
id: 5959
},
{
name: '都市剧场HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dsjc/1300000/mnf.m3u8',
id: 5960
},
{
name: '七彩戏剧HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/qcxj/1300000/mnf.m3u8',
id: 5961
},
{
name: '动漫秀场HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dmxc/1300000/mnf.m3u8',
id: 5962
},
{
name: '劲爆体育HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jbty/1300000/mnf.m3u8',
id: 5963
},
{
name: '极速汽车',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jsqc/1300000/mnf.m3u8',
id: 5964
},
{
name: '游戏风云',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/yxfy/1300000/mnf.m3u8',
id: 5965
},
{
name: '金鹰卡通',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jykt/1300000/mnf.m3u8',
id: 5966
},
{
name: '炫动卡通',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/xdkt/1300000/mnf.m3u8',
id: 5967
},
{
name: '嘉佳卡通',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jjkt/1300000/mnf.m3u8',
id: 5968
},
{
name: '星尚',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/shss/1300000/mnf.m3u8',
id: 5969
},
{
name: '上海纪实',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jspd/1300000/mnf.m3u8',
id: 5970
},
{
name: '上海新闻',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/xwzh/1300000/mnf.m3u8',
id: 5971
},
{
name: '上海娱乐',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ylpd/1300000/mnf.m3u8',
id: 5972
},
{
name: '上海电视剧',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dsjpd/1300000/mnf.m3u8',
id: 5973
},
{
name: '上海ICS外语频道',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/wypd/1300000/mnf.m3u8',
id: 5974
},
{
name: '上海艺术人文',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ysrw/1300000/mnf.m3u8',
id: 5975
},
{
name: '东方财经浦东',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dfcj/1300000/mnf.m3u8',
id: 5976
},
{
name: '第一财经',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dycj/1300000/mnf.m3u8',
id: 5977
},
{
name: '安徽卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ahws/1300000/mnf.m3u8',
id: 5978
},
{
name: '兵团卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/btws/1300000/mnf.m3u8',
id: 5979
},
{
name: '甘肃卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gsws/1300000/mnf.m3u8',
id: 5980
},
{
name: '陕西卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/sxws/1300000/mnf.m3u8',
id: 5981
},
{
name: '山西卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/shanxiws/1300000/mnf.m3u8',
id: 5982
},
{
name: '吉林卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jlws/1300000/mnf.m3u8',
id: 5983
},
{
name: '河北卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hbws/1300000/mnf.m3u8',
id: 5984
},
{
name: '四川卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/scws/1300000/mnf.m3u8',
id: 5985
},
{
name: '贵州卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gzws/1300000/mnf.m3u8',
id: 5986
},
{
name: '云南卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ynws/1300000/mnf.m3u8',
id: 5987
},
{
name: '辽宁卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/lnws/1300000/mnf.m3u8',
id: 5988
},
{
name: '旅游卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/lyws/1300000/mnf.m3u8',
id: 5989
},
{
name: '东南卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/dnws/1300000/mnf.m3u8',
id: 5990
},
{
name: '重庆卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/cqws/1300000/mnf.m3u8',
id: 5991
},
{
name: '广西卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/gxws/1300000/mnf.m3u8',
id: 5992
},
{
name: '青海卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/qhws/1300000/mnf.m3u8',
id: 5993
},
{
name: '江西卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/jxws/1300000/mnf.m3u8',
id: 5994
},
{
name: '内蒙古卫视',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/nmgws/1300000/mnf.m3u8',
id: 5995
},
{
name: '五星体育HD',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/1300000/mnf.m3u8',
id: 5996
},
{
name: '直播1-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba1/4000000/mnf.m3u8',
id: 5997
},
{
name: '直播2-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba2/4000000/mnf.m3u8',
id: 5998
},
{
name: '直播3-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba3/4000000/mnf.m3u8',
id: 5999
},
{
name: '直播4-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba4/4000000/mnf.m3u8',
id: 6000
},
{
name: '直播5-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba5/4000000/mnf.m3u8',
id: 6001
},
{
name: '直播6-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba6/4000000/mnf.m3u8',
id: 6002
},
{
name: '直播7-1080P',
url: 'http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba7/4000000/mnf.m3u8',
id: 6003
}
]
export {
setting,
sites,
iptv,
localKey,
getSite
}

25
src/lib/dexie/iptv.js Normal file
View File

@@ -0,0 +1,25 @@
import db from './dexie'
const { iptv } = db
export default {
async all () {
return await iptv.toArray()
},
async clear () {
return await iptv.clear()
},
async add (doc) {
return await iptv.add(doc)
},
async bulkAdd (doc) {
return await iptv.bulkAdd(doc)
},
async find (doc) {
return await iptv.get(doc)
},
async update (id, docs) {
return await iptv.update(id, docs)
},
async remove (id) {
return await iptv.delete(id)
}
}

219
src/lib/site/onlineVideo.js Normal file
View File

@@ -0,0 +1,219 @@
import open from 'open'
import axios from 'axios'
import cheerio from 'cheerio'
const onlineVideo = {
playVideoOnBde4 (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://bde4.com/search/${videoName}`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('div.search-list')
var searchResult = $(e).find('div>div>div>div>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).attr('title')
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
var detailPageFullLink = 'https://bde4.com/' + detailPageLink
// 解析详情页面
axios.get(detailPageFullLink).then(res => {
const $ = cheerio.load(res.data)
var e = $('div.info1')
var videoList = $(e).find('a').toArray()
var videoFullLink = detailPageFullLink
// 获取index视频链接
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
if (indexVideoLink.includes('.htm')) {
videoFullLink = 'https://bde4.com' + indexVideoLink
}
}
open(videoFullLink)
})
}
})
},
playVideoOnK1080 (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://k1080.net/vodsearch123/-------------.html?wd=${videoName}&submit=`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('#searchList')
var searchResult = $(e).find('li>div>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).attr('title')
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = 'https://k1080.net' + detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('#playlist1')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
var videoFullLink = detailPageFullLink
// 获取index视频链接
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
if (indexVideoLink.includes('.htm')) {
videoFullLink = 'https://k1080.net' + indexVideoLink
}
}
open(videoFullLink)
})
}
})
},
playVideoOnSubaibai (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://www.subaibai.com/xssearch?q=${videoName}`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('div.search_list')
var searchResult = $(e).find('div>ul>li>h3>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).text()
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('div.paly_list_btn')
// 获取所有视频链接
var videoList = $(e).find('a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
if (indexVideoLink.includes('.htm')) {
videoFullLink = indexVideoLink
}
}
open(videoFullLink)
})
}
})
},
playVideoOnYhdm (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `http://www.yhdm.tv/search/${videoName}`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('div.lpic')
var searchResult = $(e).find('div>ul>li>h2>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).attr('title')
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = 'http://www.yhdm.tv/' + detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('div.movurl')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
if (indexVideoLink.includes('.htm')) {
videoFullLink = 'http://www.yhdm.tv/' + indexVideoLink
}
}
open(videoFullLink)
})
}
})
},
playVideoOndmdm2020 (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `http://www.dmdm2020.com/dongmansearch.html?wd=${videoName}&submit=`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('#searchList')
var searchResult = $(e).find('ul>li>div>h4>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).text()
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = 'http://www.dmdm2020.com' + detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('#playlist1')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
if (indexVideoLink.includes('.htm')) {
videoFullLink = 'http://www.dmdm2020.com' + indexVideoLink
}
}
open(videoFullLink)
})
}
})
},
playVideoOnSyrme (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://syrme.top/searchs?q=${videoName}`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('ul.MovieList')
var searchResult = $(e).find('ul>li>article>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).find('a>h2').text()
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = 'https://syrme.top' + detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('#categories-2')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
videoFullLink = 'https://syrme.top' + indexVideoLink
}
open(videoFullLink)
})
}
})
}
}
export default onlineVideo

View File

@@ -130,14 +130,18 @@ const zy = {
this.getSite(key).then(res => {
const site = res
wd = encodeURI(wd)
axios.post(`http://localhost:${this.ports}/api`, { url: site.api + '?wd=' + wd }).then(res => {
axios.post(`http://localhost:${this.ports}/api`, { url: site.api + '?wd=' + wd }, { timeout: 2000 }).then(res => {
const data = res.data.info
const json = parser.parse(data, this.xmlConfig)
const videoList = json.rss.list.video
resolve(videoList)
if (json && json.rss && json.rss.list) {
const videoList = json.rss.list.video
resolve(videoList)
}
}).catch(err => {
reject(err)
})
}).catch(err => {
reject(err)
})
})
},