Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27773be1c7 | ||
|
|
fadb50a28b | ||
|
|
518a9c3492 | ||
|
|
d5eb4dc49f | ||
|
|
e76bee574f | ||
|
|
b7779a3e6f | ||
|
|
4cb5b48985 | ||
|
|
b2128113ba | ||
|
|
58d0ae6da1 | ||
|
|
2bd821f59d | ||
|
|
8d002225fd | ||
|
|
0243c2f0fe | ||
|
|
b8edd7f440 | ||
|
|
4683aecf7b | ||
|
|
16d38ba2b4 | ||
|
|
fe7fe06d48 | ||
|
|
c1220ef752 | ||
|
|
f0c221a863 | ||
|
|
1df6726a3b | ||
|
|
1a9e939f9c | ||
|
|
39cb188604 | ||
|
|
aba4d12302 | ||
|
|
17c77fd48a | ||
|
|
1cfc12ec19 | ||
|
|
b0aa1dc28a | ||
|
|
0c12b394a7 | ||
|
|
9e468bc82e | ||
|
|
973a15b593 | ||
|
|
253c1e7723 | ||
|
|
7b44051190 | ||
|
|
a25ac77ebc | ||
|
|
d187167fbe | ||
|
|
b34347cf43 | ||
|
|
829d9447a4 | ||
|
|
39067c6a35 | ||
|
|
6dbb64a4f2 | ||
|
|
f8041290d2 | ||
|
|
f772ac2e9d | ||
|
|
ef485ef64a | ||
|
|
b164d5e83e | ||
|
|
8a5800df93 | ||
|
|
8cd2b920c8 | ||
|
|
5b4cb43aa5 | ||
|
|
de1472e668 | ||
|
|
0f846b996b | ||
|
|
2bd5e31a28 | ||
|
|
9d8dc9ecb1 | ||
|
|
2a073e4092 | ||
|
|
b1daa73afe | ||
|
|
18940ff9f7 | ||
|
|
76d4d68401 | ||
|
|
f91200e609 | ||
|
|
b64f500710 | ||
|
|
cf1cfe9f77 | ||
|
|
da4fe162f6 | ||
|
|
d949c52020 | ||
|
|
1ce9e0525b | ||
|
|
4ebf82eae0 | ||
|
|
e0b1a5332d | ||
|
|
3ecb4302ba | ||
|
|
5c39db8ca6 | ||
|
|
4f45045d18 | ||
|
|
b7733179f2 | ||
|
|
e1f7044ae0 | ||
|
|
93e76db444 | ||
|
|
6eaa281e4a | ||
|
|
490d34e1fb | ||
|
|
0d0d6bd90f | ||
|
|
ecdc96d2f3 | ||
|
|
234f6dd069 | ||
|
|
f80fe7ecf1 | ||
|
|
6876721567 | ||
|
|
bedd1339df | ||
|
|
0a3a7a4d57 | ||
|
|
786e23f5a2 | ||
|
|
418f14bcc1 | ||
|
|
a9e4a34e4f | ||
|
|
fede7e4ef2 | ||
|
|
956ebbf8b8 | ||
|
|
014dac0b64 | ||
|
|
5fc1020e79 | ||
|
|
aca487f796 | ||
|
|
429eb4aac0 | ||
|
|
e032f86d3d | ||
|
|
f92af48a4e | ||
|
|
eff69db063 | ||
|
|
a5c8d20635 | ||
|
|
da22abd25d | ||
|
|
2dd91f78c9 | ||
|
|
a8b0e7e6a8 |
20
README.md
@@ -46,6 +46,17 @@
|
||||
- 🍉 [蓝奏云 -- 快速下载](https://www.lanzoux.com/b04s6a3re) 密码:95px
|
||||
- 🍒 适用于32位操作系统的x86软件,在蓝奏云网盘里, 后缀名: ZY Player * 32位.exe
|
||||
|
||||
### 🎠 平台
|
||||
|
||||
| 平台 | 链接 |
|
||||
| :------------------------------------ | :---------------------------------------------------------- |
|
||||
| 🖥️ 电脑端 ( Windows & Mac & Linux ) | [ZY Player](https://github.com/Hunlongyu/ZY-Player) |
|
||||
| 📱 手机端 ( Android & IOS ) | [ZY Player APP](https://github.com/Hunlongyu/ZY-Player-APP) |
|
||||
| 📺 电视端 ( Android & Mac ) ( 进行中 ) | [ZY Player TV](https://github.com/cuiocean/ZY-Player-TV) |
|
||||
| 🌐 浏览器 ( Web ) | [ZY Player Web](https://github.com/Hunlongyu/ZY-Player-Web) |
|
||||
|
||||
|
||||
|
||||
### 🚀 快捷键
|
||||
|
||||
播放窗口 和 Mini窗口
|
||||
@@ -81,7 +92,8 @@
|
||||
|
||||
### 🍭 开发者
|
||||
|
||||
| [Hunlongyu](https://github.com/Hunlongyu) | [cuiocean](https://github.com/cuiocean) |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <img width="120" src="https://avatars2.githubusercontent.com/u/15273630?s=460&u=48cf3299e2a842c0252233d8be42ef4c5d792138&v=4"/> | <img width="120" src="https://avatars0.githubusercontent.com/u/5760235?s=460&u=9d969dd8d83f069ce7ebd60516770c93ac07a330&v=4" /> |
|
||||
| 💻 🎨 🐛 | 💻 🐛 |
|
||||
| [Hunlongyu](https://github.com/Hunlongyu) | [cuiocean](https://github.com/cuiocean) | [buvta](https://github.com/buvta) |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <img width="120" src="https://avatars2.githubusercontent.com/u/15273630?s=460&u=48cf3299e2a842c0252233d8be42ef4c5d792138&v=4"/> | <img width="120" src="https://avatars0.githubusercontent.com/u/5760235?s=460&u=9d969dd8d83f069ce7ebd60516770c93ac07a330&v=4" /> | <img width="120" src="https://avatars3.githubusercontent.com/u/12312540?s=400&v=4" /> |
|
||||
| 💻 🎨 🐛 | 💻 🐛 | 💻 🐛 |
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 224 KiB |
BIN
docs/assets/img/gallery/01.png
Normal file
|
After Width: | Height: | Size: 944 KiB |
BIN
docs/assets/img/gallery/02.png
Normal file
|
After Width: | Height: | Size: 927 KiB |
BIN
docs/assets/img/gallery/03.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
docs/assets/img/gallery/04.png
Normal file
|
After Width: | Height: | Size: 691 KiB |
BIN
docs/assets/img/gallery/05.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/assets/img/gallery/06.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
docs/assets/img/gallery/07.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/assets/img/gallery/08.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 1.1 MiB |
@@ -89,7 +89,7 @@
|
||||
|
||||
<div class="section-title">
|
||||
<h2>软件特色</h2>
|
||||
<p>经过三个大版本更迭, 软件功能丰富, 操作简单.</p>
|
||||
<p>软件功能丰富, 操作简单.</p>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters">
|
||||
@@ -99,7 +99,7 @@
|
||||
<div class="col-md-6 icon-box" data-aos="fade-up">
|
||||
<i class="bx bx-receipt"></i>
|
||||
<h4>浏览</h4>
|
||||
<p>浏览全网热门视频, 支持切换视频源. 详细的电影分类.支持搜索电影名和演员名称. </p>
|
||||
<p>浏览全网热门视频, 支持切换视频源. 详细的电影分类. </p>
|
||||
</div>
|
||||
<div class="col-md-6 icon-box" data-aos="fade-up" data-aos-delay="100">
|
||||
<i class="icofont-play-alt-3"></i>
|
||||
@@ -124,7 +124,7 @@
|
||||
<div class="col-md-6 icon-box" data-aos="fade-up" data-aos-delay="500">
|
||||
<i class="icofont-cubes"></i>
|
||||
<h4>其他</h4>
|
||||
<p>多主题, 多语言, 自动更新</p>
|
||||
<p>多主题, 自动更新</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,14 +146,14 @@
|
||||
</div>
|
||||
|
||||
<div class="owl-carousel gallery-carousel" data-aos="fade-up">
|
||||
<a href="assets/img/gallery/001.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/001.png" alt=""></a>
|
||||
<a href="assets/img/gallery/002.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/002.png" alt=""></a>
|
||||
<a href="assets/img/gallery/003.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/003.png" alt=""></a>
|
||||
<a href="assets/img/gallery/004.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/004.png" alt=""></a>
|
||||
<a href="assets/img/gallery/005.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/005.png" alt=""></a>
|
||||
<a href="assets/img/gallery/006.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/006.png" alt=""></a>
|
||||
<a href="assets/img/gallery/007.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/007.png" alt=""></a>
|
||||
<a href="assets/img/gallery/008.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/008.png" alt=""></a>
|
||||
<a href="assets/img/gallery/01.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/01.png" alt=""></a>
|
||||
<a href="assets/img/gallery/02.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/02.png" alt=""></a>
|
||||
<a href="assets/img/gallery/03.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/03.png" alt=""></a>
|
||||
<a href="assets/img/gallery/04.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/04.png" alt=""></a>
|
||||
<a href="assets/img/gallery/05.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/05.png" alt=""></a>
|
||||
<a href="assets/img/gallery/06.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/06.png" alt=""></a>
|
||||
<a href="assets/img/gallery/07.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/07.png" alt=""></a>
|
||||
<a href="assets/img/gallery/08.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/08.png" alt=""></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -193,7 +193,7 @@
|
||||
<i class="bx bx-help-circle icon-help"></i> <a data-toggle="collapse" href="#accordion-list-3" class="collapsed">跨平台<i class="bx bx-chevron-down icon-show"></i><i class="bx bx-chevron-up icon-close"></i></a>
|
||||
<div id="accordion-list-3" class="collapse" data-parent=".accordion-list">
|
||||
<p>
|
||||
目前支持 Windows, Mac, Linux 桌面系统. 暂不支持手机端或者电视端. 未来会考虑实现全平台.
|
||||
目前支持 Windows, Mac, Linux, Android, IOS, TV, Web 全平台.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
34
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zy",
|
||||
"version": "2.6.6",
|
||||
"version": "2.6.9",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -19,13 +19,13 @@
|
||||
"dependencies": {
|
||||
"axios": "^0.21.0",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"core-js": "^3.7.0",
|
||||
"core-js": "^3.8.0",
|
||||
"cors": "^2.8.5",
|
||||
"dexie": "^3.0.2",
|
||||
"dexie": "^3.0.3",
|
||||
"electron-localshortcut": "^3.2.1",
|
||||
"electron-proxy-agent": "^1.2.0",
|
||||
"electron-updater": "^4.3.5",
|
||||
"element-ui": "^2.14.0",
|
||||
"element-ui": "^2.14.1",
|
||||
"express": "^4.17.1",
|
||||
"fast-xml-parser": "^3.17.4",
|
||||
"html2canvas": "^1.0.0-rc.7",
|
||||
@@ -46,29 +46,29 @@
|
||||
"vue-infinite-loading": "^2.4.5",
|
||||
"vue-waterfall-plugin": "^1.1.0",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"vuex": "^3.5.1",
|
||||
"xgplayer": "^2.13.0",
|
||||
"vuex": "^3.6.0",
|
||||
"xgplayer": "^2.13.2",
|
||||
"xgplayer-hls.js": "^2.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.4.0",
|
||||
"@vue/cli-plugin-eslint": "~4.4.0",
|
||||
"@vue/cli-plugin-vuex": "~4.4.0",
|
||||
"@vue/cli-service": "~4.4.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.9",
|
||||
"@vue/cli-plugin-eslint": "~4.5.9",
|
||||
"@vue/cli-plugin-vuex": "~4.5.9",
|
||||
"@vue/cli-service": "~4.5.9",
|
||||
"@vue/eslint-config-standard": "^5.1.2",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"electron": "^10.1.5",
|
||||
"electron-devtools-installer": "^3.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"electron": "^11.0.3",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"eslint": "^7.14.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-plugin-vue": "^7.1.0",
|
||||
"sass": "^1.29.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-cli-plugin-electron-builder": "2.0.0-rc.4",
|
||||
"sass-loader": "^10.1.0",
|
||||
"vue-cli-plugin-electron-builder": "2.0.0-rc.5",
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,16 +111,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.play{
|
||||
.popper {
|
||||
font-size: 1rem;;
|
||||
border: none;
|
||||
li {
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Page of list using el-table
|
||||
.listpage{
|
||||
position: absolute;
|
||||
@@ -133,7 +123,7 @@
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.listpage-header{
|
||||
.listpage-header, .toolbar{
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -185,7 +175,35 @@
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
}
|
||||
.el-select-dropdown__item.selected.hover{ //是上游的bug吗?临时性修补
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
> span{
|
||||
.el-input-number{
|
||||
width:120px;
|
||||
.el-input{
|
||||
width: 100px;
|
||||
}
|
||||
.el-input__inner{
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
width: 88px;
|
||||
}
|
||||
.el-input-number__increase, .el-input-number__decrease {
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-divider{
|
||||
.el-divider--horizontal{
|
||||
margin: 12px 0;
|
||||
}
|
||||
}
|
||||
.toolbar{
|
||||
z-index: 5;
|
||||
}
|
||||
.listpage-body{
|
||||
height: calc(100% - 60px);
|
||||
|
||||
@@ -139,6 +139,13 @@
|
||||
.play{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--d-bgc-1);
|
||||
border: 1px solid var(--d-bgc-1);
|
||||
color: var(--d-fc-2);
|
||||
}
|
||||
}
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
.right {
|
||||
@@ -309,34 +316,10 @@
|
||||
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);
|
||||
.listpage-header{
|
||||
.listpage-header, .toolbar{
|
||||
border-bottom-color: var(--d-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
|
||||
@@ -139,6 +139,13 @@
|
||||
.play{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--g-bgc-1);
|
||||
border: 1px solid var(--g-bgc-1);
|
||||
color: var(--g-fc-2);
|
||||
}
|
||||
}
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
.right {
|
||||
@@ -309,34 +316,10 @@
|
||||
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);
|
||||
.listpage-header{
|
||||
.listpage-header, .toolbar{
|
||||
border-bottom-color: var(--g-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
|
||||
@@ -139,6 +139,13 @@
|
||||
.play{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--l-bgc-1);
|
||||
border: 1px solid var(--l-bgc-1);
|
||||
color: var(--l-fc-2);
|
||||
}
|
||||
}
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
.right {
|
||||
@@ -309,34 +316,10 @@
|
||||
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);
|
||||
.listpage-header{
|
||||
.listpage-header, .toolbar{
|
||||
border-bottom-color: var(--l-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
|
||||
@@ -139,6 +139,13 @@
|
||||
.play{
|
||||
background-color: var(--p-bgc-1);
|
||||
box-shadow: var(--p-bsc);
|
||||
.el-input{
|
||||
input{
|
||||
background-color: var(--p-bgc-1);
|
||||
border: 1px solid var(--p-bgc-1);
|
||||
color: var(--p-fc-2);
|
||||
}
|
||||
}
|
||||
.title{
|
||||
color: var(--p-fc-1);
|
||||
.right {
|
||||
@@ -309,34 +316,10 @@
|
||||
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);
|
||||
.listpage-header{
|
||||
.listpage-header, .toolbar{
|
||||
border-bottom-color: var(--p-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
import './lib/site/server'
|
||||
import { app, protocol, BrowserWindow, globalShortcut, ipcMain } from 'electron'
|
||||
import { app, protocol, BrowserWindow, globalShortcut } from 'electron'
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
import { initUpdater } from './lib/update/update'
|
||||
@@ -34,7 +34,7 @@ function createWindow () {
|
||||
createProtocol('app')
|
||||
win.loadURL('app://./index.html')
|
||||
}
|
||||
|
||||
|
||||
initUpdater(win)
|
||||
|
||||
win.on('closed', () => {
|
||||
|
||||
@@ -211,30 +211,29 @@ export default {
|
||||
}
|
||||
},
|
||||
downloadEvent () {
|
||||
zy.download(this.detail.key, this.info.id).then(res => {
|
||||
if (res && res.dl && res.dl.dd) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
let downloadUrl = res.name + '\n'
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
}
|
||||
} else {
|
||||
const list = [...this.m3u8List]
|
||||
let downloadUrl = this.detail.info.name + '\n'
|
||||
const key = this.detail.key
|
||||
const id = this.info.id
|
||||
zy.download(key, id).then(res => {
|
||||
if (res && res.m3u8List) {
|
||||
const list = res.m3u8List.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
zy.detail(key, id).then(res => {
|
||||
const list = [...res.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-switch v-model="searchViewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="table" @change="updateSearchViewMode"
|
||||
v-if="show.find"></el-switch>
|
||||
v-if="show.find">
|
||||
</el-switch>
|
||||
<el-select v-model="selectedClassName" size="small" placeholder="类型" :popper-append-to-body="false" popper-class="popper" @change="classClick" v-show="show.class">
|
||||
<el-option
|
||||
v-for="item in classList"
|
||||
@@ -47,9 +48,36 @@
|
||||
<el-button icon="el-icon-search" @click.stop="searchEvent" slot="append" />
|
||||
</el-autocomplete>
|
||||
</div>
|
||||
<div class="toolbar" v-if="!show.find && showToolbar">
|
||||
<el-select v-model="selectedAreas" size="small" multiple collapse-tags placeholder="地区" popper-class="popper" :popper-append-to-body="false" @remove-tag="refreshFilteredList" @visible-change="refreshFilteredList($event)">
|
||||
<el-option
|
||||
v-for="item in areas"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select v-model="sortKeyword" size="small" placeholder="排序" popper-class="popper" :popper-append-to-body="false" @change="refreshFilteredList">
|
||||
<el-option
|
||||
v-for="item in sortKeywords"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<span>
|
||||
上映区间:
|
||||
<el-input-number size="small" v-model="selectedYears.start" :min=0 :max="new Date().getFullYear()" controls-position="right" step-strictly @change="refreshFilteredList"></el-input-number>
|
||||
至
|
||||
<el-input-number size="small" v-model="selectedYears.end" :min=0 :max="new Date().getFullYear()" controls-position="right" step-strictly @change="refreshFilteredList"></el-input-number>
|
||||
</span>
|
||||
</div>
|
||||
<el-divider content-position="center" v-if="!show.find">
|
||||
<el-button type="text" size="mini" @click='() => { showToolbar = !showToolbar; if (!showToolbar) this.refreshFilteredList() }'>{{ showToolbar ? '隐藏工具栏' : '显示工具栏' }}</el-button>
|
||||
</el-divider>
|
||||
<div class="listpage-body" id="film-body" infinite-wrapper>
|
||||
<div class="show-picture" v-if="setting.view === 'picture' && !show.find">
|
||||
<Waterfall ref="filmWaterfall" :list="list" :gutter="20" :width="240"
|
||||
<Waterfall ref="filmWaterfall" :list="filteredList" :gutter="20" :width="240"
|
||||
:breakpoints="{
|
||||
1200: { //当屏幕宽度小于等于1200
|
||||
rowPerView: 4,
|
||||
@@ -64,7 +92,7 @@
|
||||
animationEffect="fadeIn"
|
||||
backgroundColor="rgba(0, 0, 0, 0)">
|
||||
<template slot="item" slot-scope="props">
|
||||
<div class="card" v-show="!setting.excludeR18Films || !containsR18Keywords(props.data.type)">
|
||||
<div class="card">
|
||||
<div class="img">
|
||||
<img style="width: 100%" :src="props.data.pic" alt="" @load="$refs.filmWaterfall.refresh()" @click="detailEvent(site, props.data)">
|
||||
<div class="operate">
|
||||
@@ -90,7 +118,7 @@
|
||||
<div class="show-table" v-if="setting.view === 'table' && !show.find">
|
||||
<el-table
|
||||
size="mini"
|
||||
:data="list.filter(res => !setting.excludeR18Films || !containsR18Keywords(res.type))"
|
||||
:data="filteredList"
|
||||
height="100%"
|
||||
:empty-text="statusText"
|
||||
@row-click="(row) => detailEvent(site, row)"
|
||||
@@ -152,7 +180,7 @@
|
||||
</infinite-loading>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="show-table" v-show="searchViewMode=== 'table' && show.find">
|
||||
<div class="show-table" v-if="searchViewMode=== 'table' && show.find">
|
||||
<el-table size="mini"
|
||||
ref="searchResultTable"
|
||||
:data="searchContents.filter(res => !setting.excludeR18Films || (res.type !== undefined && !containsR18Keywords(res.type)))"
|
||||
@@ -226,7 +254,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="show-picture" v-show="searchViewMode === 'picture' && show.find">
|
||||
<div class="show-picture" v-if="searchViewMode === 'picture' && show.find">
|
||||
<Waterfall ref="filmSearchWaterfall" :list="searchContents.filter(res => !setting.excludeR18Films || (res.type !== undefined && !containsR18Keywords(res.type)))" :gutter="20" :width="240"
|
||||
:breakpoints="{
|
||||
1200: { //当屏幕宽度小于等于1200
|
||||
@@ -277,6 +305,7 @@ import zy from '../lib/site/tools'
|
||||
import Waterfall from 'vue-waterfall-plugin'
|
||||
import InfiniteLoading from 'vue-infinite-loading'
|
||||
const { clipboard } = require('electron')
|
||||
const FILM_DATA_CACHE = {} // key = site.key, value = classList; key = site.key + '@' + type.tid, value = {list, pageCount}
|
||||
export default {
|
||||
name: 'film',
|
||||
data () {
|
||||
@@ -292,9 +321,10 @@ export default {
|
||||
site: {},
|
||||
classList: [],
|
||||
type: {},
|
||||
selectedClassName: '最新',
|
||||
selectedSiteName: '',
|
||||
selectedClassName: '',
|
||||
pagecount: 0,
|
||||
recordcount: 0,
|
||||
list: [],
|
||||
statusText: ' ',
|
||||
infiniteId: +new Date(),
|
||||
@@ -307,7 +337,14 @@ export default {
|
||||
searchGroups: [],
|
||||
// 福利片关键词
|
||||
r18KeyWords: ['伦理', '论理', '倫理', '福利', '激情', '理论', '写真', '情色', '美女', '街拍', '赤足', '性感', '里番'],
|
||||
searchViewMode: 'picture'
|
||||
searchViewMode: 'picture',
|
||||
filteredList: [],
|
||||
areas: [],
|
||||
selectedAreas: [],
|
||||
sortKeyword: '',
|
||||
sortKeywords: ['按片名', '按上映年份', '按更新时间'],
|
||||
selectedYears: { start: 0, end: new Date().getFullYear() },
|
||||
showToolbar: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -378,10 +415,50 @@ export default {
|
||||
},
|
||||
filterSettings () {
|
||||
this.siteClick(this.site.name)
|
||||
},
|
||||
list: {
|
||||
handler (list) {
|
||||
this.areas = [...new Set(list.map(ele => ele.area))].filter(x => x)
|
||||
this.refreshFilteredList()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
|
||||
refreshFilteredList (popperVisible) {
|
||||
if (popperVisible === true) return
|
||||
if (!this.showToolbar) {
|
||||
this.sortKeyword = ''
|
||||
this.selectedYears.start = 0
|
||||
this.selectedYears.end = new Date().getFullYear()
|
||||
}
|
||||
let filteredData = this.list.filter(x => (this.selectedAreas.length === 0) || this.selectedAreas.includes(x.area))
|
||||
filteredData = filteredData.filter(res => !this.setting.excludeR18Films || !this.containsR18Keywords(res.type))
|
||||
filteredData = filteredData.filter(res => res.year >= this.selectedYears.start)
|
||||
filteredData = filteredData.filter(res => res.year <= this.selectedYears.end)
|
||||
this.selectedClassName = this.type.name + ' ' + filteredData.length + '/' + this.recordcount
|
||||
switch (this.sortKeyword) {
|
||||
case '按上映年份':
|
||||
filteredData.sort(function (a, b) {
|
||||
return a.year - b.year
|
||||
})
|
||||
break
|
||||
case '按片名':
|
||||
filteredData.sort(function (a, b) {
|
||||
return a.name.localeCompare(b.name, 'zh')
|
||||
})
|
||||
break
|
||||
case '按更新时间':
|
||||
filteredData.sort(function (a, b) {
|
||||
return new Date(b.last) - new Date(a.last)
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
this.filteredList = filteredData
|
||||
},
|
||||
updateSearchViewMode () {
|
||||
setting.find().then(res => {
|
||||
res.searchViewMode = this.searchViewMode
|
||||
@@ -417,16 +494,22 @@ export default {
|
||||
siteClick (siteName) {
|
||||
this.list = []
|
||||
this.site = this.sites.find(x => x.name === siteName)
|
||||
if (this.searchTxt.length > 0 && this.searchGroup === '站内') {
|
||||
this.searchEvent()
|
||||
this.searchTxt = ''
|
||||
this.show.find = false
|
||||
this.classList = []
|
||||
if (FILM_DATA_CACHE[this.site.key]) {
|
||||
this.classList = FILM_DATA_CACHE[this.site.key].classList
|
||||
this.show.class = true
|
||||
this.classClick(this.type.name)
|
||||
} else {
|
||||
this.searchTxt = ''
|
||||
this.show.find = false
|
||||
this.classList = []
|
||||
this.type = {}
|
||||
this.getClass().then(res => {
|
||||
this.infiniteId += 1
|
||||
this.classClick(this.classList[0].name)
|
||||
this.classList = res
|
||||
this.show.class = true
|
||||
// cache classList data
|
||||
FILM_DATA_CACHE[this.site.key] = {
|
||||
classList: this.classList
|
||||
}
|
||||
this.classClick(this.type.name)
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -434,11 +517,22 @@ export default {
|
||||
this.show.classList = false
|
||||
this.list = []
|
||||
this.type = this.classList.find(x => x.name === className)
|
||||
this.getPage().then(res => {
|
||||
if (res) {
|
||||
if (!this.type) {
|
||||
this.type = this.classList[0]
|
||||
}
|
||||
const cacheKey = this.site.key + '@' + this.type.tid
|
||||
if (FILM_DATA_CACHE[cacheKey]) {
|
||||
this.pagecount = FILM_DATA_CACHE[cacheKey].pagecount
|
||||
this.recordcount = FILM_DATA_CACHE[cacheKey].recordcount
|
||||
this.list = FILM_DATA_CACHE[cacheKey].list
|
||||
this.areas = FILM_DATA_CACHE[cacheKey].areas
|
||||
} else {
|
||||
zy.page(this.site.key, this.type.tid).then(res => {
|
||||
this.pagecount = res.pagecount
|
||||
this.recordcount = res.recordcount
|
||||
this.infiniteId += 1
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
getClass () {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -459,11 +553,7 @@ export default {
|
||||
}
|
||||
}
|
||||
})
|
||||
this.classList = allClass
|
||||
this.show.class = true
|
||||
this.pagecount = res.pagecount
|
||||
this.type = this.classList[0]
|
||||
resolve(true)
|
||||
resolve(allClass)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
@@ -476,30 +566,17 @@ export default {
|
||||
}
|
||||
return this.r18KeyWords.some(v => name.includes(v))
|
||||
},
|
||||
getPage () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const key = this.site.key
|
||||
const type = this.type.tid
|
||||
zy.page(key, type).then(res => {
|
||||
this.pagecount = res.pagecount
|
||||
this.show.body = true
|
||||
resolve(true)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
infiniteHandler ($state) {
|
||||
const key = this.site.key
|
||||
const type = this.type.tid
|
||||
const typeTid = this.type.tid
|
||||
const page = this.pagecount
|
||||
this.statusText = ' '
|
||||
if (key && page < 1) { // OK资源前几类硬是去不掉
|
||||
if (key === undefined || page < 1 || typeTid === undefined) {
|
||||
$state.complete()
|
||||
this.statusText = '暂无数据'
|
||||
return false
|
||||
}
|
||||
zy.list(key, page, type).then(res => {
|
||||
zy.list(key, page, typeTid).then(res => {
|
||||
if (res) {
|
||||
this.pagecount -= 1
|
||||
const type = Object.prototype.toString.call(res)
|
||||
@@ -514,9 +591,17 @@ export default {
|
||||
this.list.push(res)
|
||||
}
|
||||
$state.loaded()
|
||||
} else {
|
||||
$state.complete()
|
||||
this.statusText = '暂无数据'
|
||||
// 数据更新后,刷新页面
|
||||
if (this.setting.view === 'picture' && this.$refs.filmWaterfall) {
|
||||
this.$refs.filmWaterfall.refresh()
|
||||
}
|
||||
// 更新缓存数据
|
||||
const cacheKey = this.site.key + '@' + typeTid
|
||||
FILM_DATA_CACHE[cacheKey] = {
|
||||
pagecount: this.pagecount,
|
||||
recordcount: this.recordcount,
|
||||
list: this.list
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -567,41 +652,29 @@ export default {
|
||||
}
|
||||
},
|
||||
downloadEvent (site, row) {
|
||||
zy.download(site.key, row.id).then(res => {
|
||||
if (res && res.length > 0) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
let downloadUrl = res.name + '\n'
|
||||
const key = site.key
|
||||
const id = row.id
|
||||
zy.download(key, id).then(res => {
|
||||
if (res && res.m3u8List) {
|
||||
const list = res.m3u8List.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
zy.detail(key, id).then(res => {
|
||||
const list = [...res.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
}
|
||||
} else {
|
||||
let m3u8List = []
|
||||
const dd = row.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
let downloadUrl = row.name + '\n'
|
||||
for (const i of m3u8List) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
|
||||
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -612,9 +685,6 @@ export default {
|
||||
if (this.$refs.filmWaterfall) {
|
||||
this.$refs.filmWaterfall.refresh()
|
||||
}
|
||||
this.getPage().then(() => {
|
||||
this.infiniteId += 1
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -666,7 +736,6 @@ export default {
|
||||
searchSites = this.sites.filter(site => site.group === this.searchGroup)
|
||||
}
|
||||
this.searchContents = []
|
||||
this.pagecount = 0
|
||||
this.show.find = true
|
||||
this.show.class = false
|
||||
this.statusText = ' '
|
||||
@@ -717,12 +786,6 @@ export default {
|
||||
this.show.find = false
|
||||
if (this.setting.view === 'picture' && this.$refs.filmWaterfall) {
|
||||
this.$refs.filmWaterfall.refresh()
|
||||
} else {
|
||||
this.getClass().then(res => {
|
||||
if (res) {
|
||||
this.infiniteId += 1
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -196,36 +196,21 @@ export default {
|
||||
}
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(e.site, e.ids).then(res => {
|
||||
if (res && res.dl && res.dl.dd) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
const key = e.site
|
||||
const id = e.ids
|
||||
zy.download(key, id).then(res => {
|
||||
if (res && res.m3u8List) {
|
||||
const list = res.m3u8List.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
var m3u8List = {}
|
||||
zy.detail(e.site, e.ids).then(res => {
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
const list = [...m3u8List]
|
||||
zy.detail(key, id).then(res => {
|
||||
const list = [...res.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
: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">
|
||||
@@ -95,6 +94,7 @@
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-button @click.stop="moveToTopEvent(scope.row)" type="text" v-if="scope.row.channels">置顶</el-button>
|
||||
<el-button @click.stop="playEvent(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>
|
||||
@@ -107,7 +107,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { iptv, iptvSearch, channelList } from '../lib/dexie'
|
||||
import { iptv, channelList } from '../lib/dexie'
|
||||
import { iptv as defaultChannels } from '../lib/dexie/initData'
|
||||
import zy from '../lib/site/tools'
|
||||
import { remote } from 'electron'
|
||||
@@ -120,7 +120,6 @@ export default {
|
||||
iptvList: [],
|
||||
channelList: [],
|
||||
searchTxt: '',
|
||||
searchRecordList: [],
|
||||
enableBatchEdit: false,
|
||||
inputContent: '',
|
||||
batchIsActive: true,
|
||||
@@ -132,10 +131,7 @@ export default {
|
||||
checkAllChannelsLoading: false,
|
||||
checkProgress: 0,
|
||||
stopFlag: false,
|
||||
sortableTable: '',
|
||||
show: {
|
||||
search: false
|
||||
}
|
||||
sortableTable: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -180,7 +176,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
view () {
|
||||
if (this.view === 'IPTV') {
|
||||
if (this.view === 'IPTV' && !this.checkAllChannelsLoading) {
|
||||
this.getChannelList()
|
||||
}
|
||||
},
|
||||
@@ -293,6 +289,7 @@ export default {
|
||||
ele.channels.splice(ele.channels.findIndex(e => e.id === row.id), 1)
|
||||
channelList.remove(row.channelID)
|
||||
if (ele.channels.length) {
|
||||
if (ele.channels.length === 1) ele.hasChildren = false
|
||||
channelList.add(ele)
|
||||
this.$set(this.$refs.iptvTable.store.states.lazyTreeNodeMap, ele.id, ele.channels)
|
||||
}
|
||||
@@ -348,21 +345,25 @@ export default {
|
||||
result.filePaths.forEach(file => {
|
||||
if (file.endsWith('m3u') || file.endsWith('m3u8')) {
|
||||
const docs = []
|
||||
const URL = require('url')
|
||||
let id = this.channelList.length ? this.channelList.slice(-1)[0].id + 1 : 1
|
||||
const parser = require('iptv-playlist-parser')
|
||||
const playlist = fs.readFileSync(file, { encoding: 'utf-8' })
|
||||
const result = parser.parse(playlist)
|
||||
result.items.forEach(ele => {
|
||||
if (ele.name && ele.url && ele.url.endsWith('.m3u8')) {
|
||||
var doc = {
|
||||
id: id,
|
||||
name: ele.name,
|
||||
url: ele.url,
|
||||
isActive: true
|
||||
const urls = ele.url.split('#').filter(e => e.startsWith('http')) // 网址带#时自动分割
|
||||
urls.forEach(url => {
|
||||
if (ele.name && url && new URL.URL(url).pathname.endsWith('.m3u8')) { // 网址可能带参数
|
||||
var doc = {
|
||||
id: id,
|
||||
name: ele.name,
|
||||
url: url,
|
||||
isActive: true
|
||||
}
|
||||
id += 1
|
||||
docs.push(doc)
|
||||
}
|
||||
id += 1
|
||||
docs.push(doc)
|
||||
}
|
||||
})
|
||||
})
|
||||
// 获取url不重复的列表
|
||||
const uniqueList = [...new Map(docs.map(item => [item.url, item])).values()]
|
||||
@@ -393,14 +394,12 @@ export default {
|
||||
})
|
||||
},
|
||||
determineGroup (name) {
|
||||
if (name.toLowerCase().includes('cctv') && (name.includes('蓝光') || name.includes('高清'))) {
|
||||
return '央视高清'
|
||||
} else if (name.toLowerCase().includes('cctv')) {
|
||||
if (name.toLowerCase().includes('cctv') || name.toLowerCase().includes('cgtn')) {
|
||||
return '央视'
|
||||
} else if (name.includes('香港') || name.includes('澳门') || name.includes('台湾') || name.includes('凤凰') || name.includes('翡翠')) {
|
||||
return '港澳台'
|
||||
} else if (name.includes('卫视')) {
|
||||
return '卫视'
|
||||
} else if (name.includes('香港') || name.includes('澳门') || name.includes('台湾') || name.includes('凤凰')) {
|
||||
return '港澳台'
|
||||
} else if (name.includes('高清') || name.includes('蓝光') || name.includes('1080P')) {
|
||||
return '高清'
|
||||
} else {
|
||||
@@ -468,8 +467,8 @@ export default {
|
||||
iptv.clear() // iptv默认清空状态
|
||||
})
|
||||
},
|
||||
getChannelList () {
|
||||
channelList.all().then(res => {
|
||||
async getChannelList () {
|
||||
await channelList.all().then(res => {
|
||||
this.channelList = res
|
||||
this.getIptvList()
|
||||
})
|
||||
@@ -477,28 +476,6 @@ export default {
|
||||
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()
|
||||
})
|
||||
},
|
||||
clearSearch () {
|
||||
iptvSearch.clear().then(res => {
|
||||
this.getSearchRecordList()
|
||||
})
|
||||
},
|
||||
searchEvent (wd) {
|
||||
this.searchTxt = wd
|
||||
this.show.search = false
|
||||
if (wd) {
|
||||
iptvSearch.find({ keywords: wd }).then(res => {
|
||||
if (!res) {
|
||||
iptvSearch.add({ keywords: wd })
|
||||
}
|
||||
this.getSearchRecordList()
|
||||
})
|
||||
}
|
||||
},
|
||||
moveToTopEvent (row) {
|
||||
if (this.checkAllChannelsLoading) {
|
||||
this.$message.info('正在检测, 请勿操作.')
|
||||
@@ -537,6 +514,11 @@ export default {
|
||||
ele.channels.forEach((e, index) => { e.id = embedChannelID + index }) // 为避免混杂,给内置iptv重起id
|
||||
if (prefer) ele.prefer = prefer.id
|
||||
})
|
||||
if (ele.channels.length === 1) {
|
||||
ele.hasChildren = false
|
||||
} else {
|
||||
ele.hasChildren = true
|
||||
}
|
||||
})
|
||||
},
|
||||
rowDrop () {
|
||||
@@ -562,6 +544,7 @@ export default {
|
||||
channelList.remove(row.channelID)
|
||||
channelList.add(ele)
|
||||
} else {
|
||||
if (row.channels.length === 1) row.channels[0].isActive = row.isActive
|
||||
channelList.remove(row.id)
|
||||
channelList.add(row)
|
||||
}
|
||||
@@ -570,13 +553,13 @@ export default {
|
||||
this.checkAllChannelsLoading = true
|
||||
this.stopFlag = false
|
||||
this.checkProgress = 0
|
||||
this.channelList.forEach(e => { e.status = ' '; e.hasCheckedNum = 0 })
|
||||
this.channelList.filter(e => e.channels.length).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.checkChannelsBySite(uncheckedList)
|
||||
await this.checkChannelsBySite(other).then(res => {
|
||||
this.checkAllChannelsLoading = false
|
||||
this.updateChannelList()
|
||||
this.getChannelList()
|
||||
})
|
||||
},
|
||||
async checkChannelsBySite (channels) {
|
||||
@@ -598,6 +581,10 @@ export default {
|
||||
}
|
||||
},
|
||||
async checkSingleChannel (channel) {
|
||||
if (this.setting.allowPassWhenIptvCheck && !channel.isActive) {
|
||||
this.checkProgress += 1
|
||||
return
|
||||
}
|
||||
channel.status = ' '
|
||||
const ele = this.channelList.find(e => e.id === channel.channelID)
|
||||
if (this.stopFlag) {
|
||||
@@ -612,12 +599,17 @@ export default {
|
||||
} else {
|
||||
channel.status = '失效'
|
||||
channel.isActive = false
|
||||
if (this.setting.autocleanWhenIptvCheck) {
|
||||
ele.channels.splice(ele.channels.findIndex(e => e.id === channel.id), 1)
|
||||
ele.hasCheckedNum--
|
||||
}
|
||||
}
|
||||
if (ele.hasCheckedNum === ele.channels.length) {
|
||||
ele.status = ele.channels.some(channel => channel.status === '可用') ? '可用' : '失效'
|
||||
if (ele.status === '失效') ele.isActive = false
|
||||
channelList.remove(channel.channelID)
|
||||
channelList.add(ele)
|
||||
if (ele.channels.length === 1) ele.hasChildren = false
|
||||
if (ele.channels.length) channelList.add(ele)
|
||||
}
|
||||
return channel.status
|
||||
},
|
||||
@@ -635,10 +627,9 @@ export default {
|
||||
addEventListener('keydown', code => { if (code.keyCode === 16) this.shiftDown = true })
|
||||
addEventListener('keyup', code => { if (code.keyCode === 16) this.shiftDown = false })
|
||||
},
|
||||
created () {
|
||||
this.getChannelList()
|
||||
async created () {
|
||||
await this.getChannelList()
|
||||
if (!this.channelList.length) this.resetChannelsEvent()
|
||||
this.getSearchRecordList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -98,6 +98,21 @@
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="timespan" v-if="right.list.length > 1">
|
||||
<label>片头长度:</label>
|
||||
<input type="number" v-model="startPosition.min" style="width:45px" min="00" max="59" placeholder="00" required>
|
||||
<label>:</label>
|
||||
<input type="number" v-model="startPosition.sec" style="width:45px" min="00" max="59" placeholder="00" required>
|
||||
<span></span>
|
||||
<label>片尾长度:</label>
|
||||
<input type="number" v-model="endPosition.min" style="width:45px" min="00" max="59" placeholder="00" required>
|
||||
<label>:</label>
|
||||
<input type="number" v-model="endPosition.sec" style="width:45px" min="00" max="59" placeholder="00" required>
|
||||
<span></span>
|
||||
<input type="button" value="确定" @click="setProgressDotByInput" title="还可以通过快捷键设置">
|
||||
<span></span>
|
||||
<input type="button" value="重置" @click="() => { startPosition.min = startPosition.sec = endPosition.min = endPosition.sec = '00'; this.clearPosition() }">
|
||||
</span>
|
||||
<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)">
|
||||
@@ -195,18 +210,13 @@
|
||||
</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
|
||||
<el-input
|
||||
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">
|
||||
placeholder="搜索">
|
||||
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||
</el-autocomplete>
|
||||
</el-input>
|
||||
<el-tree ref="channelTree"
|
||||
:data="channelListForShow"
|
||||
:props="defaultProps"
|
||||
@@ -221,7 +231,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { star, history, setting, shortcut, mini, channelList, iptvSearch, sites } from '../lib/dexie'
|
||||
import { star, history, setting, shortcut, mini, channelList, sites } from '../lib/dexie'
|
||||
import zy from '../lib/site/tools'
|
||||
import Player from 'xgplayer'
|
||||
import HlsJsPlayer from 'xgplayer-hls.js'
|
||||
@@ -309,10 +319,12 @@ export default {
|
||||
videoStop: true,
|
||||
showList: true,
|
||||
showHistory: true,
|
||||
quitMiniMode: true,
|
||||
videoTitle: true,
|
||||
airplay: true,
|
||||
closeVideoTouch: true,
|
||||
ignores: ['cssFullscreen']
|
||||
ignores: ['cssFullscreen', 'replay'],
|
||||
preloadTime: 300
|
||||
},
|
||||
state: {
|
||||
showList: false,
|
||||
@@ -327,14 +339,15 @@ export default {
|
||||
miniMode: false,
|
||||
mainWindowBounds: {},
|
||||
searchTxt: '',
|
||||
searchRecordList: [],
|
||||
channelList: [],
|
||||
channelListForShow: [],
|
||||
channelListShow: false,
|
||||
defaultProps: {
|
||||
label: 'label',
|
||||
children: 'children'
|
||||
}
|
||||
},
|
||||
startPosition: { min: '00', sec: '00' },
|
||||
endPosition: { min: '00', sec: '00' }
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
@@ -401,7 +414,9 @@ export default {
|
||||
this.right.type = ''
|
||||
if (this.view === 'Play') {
|
||||
this.getChannelList()
|
||||
if (this.video.key === '' && !this.video.iptv) this.channelListShow = true
|
||||
if (this.video.key === '' && !this.video.iptv) {
|
||||
this.channelListShow = true
|
||||
}
|
||||
}
|
||||
},
|
||||
video: {
|
||||
@@ -428,15 +443,35 @@ export default {
|
||||
}
|
||||
},
|
||||
searchTxt () {
|
||||
if (this.searchTxt === '清除历史记录...') {
|
||||
this.clearSearchRecords()
|
||||
this.searchTxt = ''
|
||||
}
|
||||
this.searchEvent()
|
||||
this.$refs.channelTree.filter(this.searchTxt)
|
||||
},
|
||||
startPosition: {
|
||||
handler (time) {
|
||||
this.leadingZero(time)
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
endPosition: {
|
||||
handler (time) {
|
||||
this.leadingZero(time)
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_APPSTATE']),
|
||||
leadingZero (time) {
|
||||
Object.keys(time).forEach(key => {
|
||||
if (time[key] > 59 || time[key] < 0) {
|
||||
time[key] = '00'
|
||||
} else if (time[key].length > 2) {
|
||||
time[key] = '' + parseInt(time[key])
|
||||
// time[key] = time[key].replace(/^0+/, '')
|
||||
} else if (time[key] < 10 && time[key].length === 1) {
|
||||
time[key] = '0' + time[key]
|
||||
}
|
||||
})
|
||||
},
|
||||
handleNodeClick (node) {
|
||||
if (node.channel) {
|
||||
this.playChannel(node.channel)
|
||||
@@ -444,47 +479,7 @@ export default {
|
||||
},
|
||||
filterNode (value, data) {
|
||||
if (!value) return true
|
||||
return data.label.toLowerCase().includes(value.toLowerCase()) || PinyinMatch.match(data.label, value)
|
||||
},
|
||||
querySearch (queryString, cb) {
|
||||
var searchRecordList = this.searchRecordList.slice(0, -1)
|
||||
var results = queryString ? searchRecordList.filter(this.createFilter(queryString)) : this.searchRecordList
|
||||
// 调用 callback 返回建议列表的数据
|
||||
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()
|
||||
return PinyinMatch.match(data.label, value)
|
||||
},
|
||||
async getUrls () {
|
||||
if (this.video.key === '') {
|
||||
@@ -505,15 +500,24 @@ export default {
|
||||
this.playChannel(this.video.iptv)
|
||||
} else {
|
||||
this.channelListShow = false
|
||||
const index = this.video.info.index | 0
|
||||
const index = this.video.info.index || 0
|
||||
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
|
||||
const key = this.video.key + '@' + this.video.info.id
|
||||
var time = this.video.info.time
|
||||
if (!time) {
|
||||
// 如果video.info.time没有设定的话,从历史中读取时间进度
|
||||
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
|
||||
if (db) {
|
||||
if (db.index === index) {
|
||||
time = db.time
|
||||
}
|
||||
this.xg.removeAllProgressDot()
|
||||
this.startPosition = this.endPosition = { min: '00', sec: '00' }
|
||||
if (db) {
|
||||
if (!time && db.index === index) { // 如果video.info.time没有设定的话,从历史中读取时间进度
|
||||
time = db.time
|
||||
}
|
||||
if (!VIDEO_DETAIL_CACHE[key]) VIDEO_DETAIL_CACHE[key] = {}
|
||||
if (db.startPosition) {
|
||||
VIDEO_DETAIL_CACHE[key].startPosition = db.startPosition
|
||||
this.startPosition = { min: '' + parseInt(db.startPosition / 60), sec: '' + parseInt(db.startPosition % 60) }
|
||||
}
|
||||
if (db.endPosition) {
|
||||
VIDEO_DETAIL_CACHE[key].endPosition = db.endPosition
|
||||
this.endPosition = { min: '' + parseInt(db.endPosition / 60), sec: '' + parseInt(db.endPosition % 60) }
|
||||
}
|
||||
}
|
||||
this.playVideo(index, time)
|
||||
@@ -528,7 +532,6 @@ export default {
|
||||
ele.isActive = ele.channels.some(e => e.isActive)
|
||||
channelList.remove(ele.id)
|
||||
channelList.add(ele)
|
||||
this.getChannelList()
|
||||
},
|
||||
playChannel (channel) {
|
||||
if (channel.channels) {
|
||||
@@ -539,69 +542,65 @@ export default {
|
||||
ele.prefer = channel.id
|
||||
channelList.remove(ele.id)
|
||||
channelList.add(ele)
|
||||
this.getChannelList()
|
||||
this.right.sources = ele.channels.filter(e => e.isActive)
|
||||
}
|
||||
this.video.iptv = channel
|
||||
this.name = channel.name
|
||||
this.xg.src = channel.url
|
||||
this.xg.play()
|
||||
document.querySelector('xg-btn-quitMiniMode').style.display = 'none'
|
||||
document.querySelector('xg-btn-showhistory').style.display = 'none'
|
||||
document.querySelector('.xgplayer-playbackrate').style.display = 'none'
|
||||
},
|
||||
playVideo (index = 0, time = 0) {
|
||||
document.querySelector('xg-btn-quitMiniMode').style.display = 'none'
|
||||
document.querySelector('xg-btn-showhistory').style.display = 'block'
|
||||
document.querySelector('.xgplayer-playbackrate').style.display = 'inline-block'
|
||||
this.fetchM3u8List().then(m3u8Arr => {
|
||||
this.xg.src = m3u8Arr[index]
|
||||
|
||||
if (time !== 0) {
|
||||
const url = m3u8Arr[index]
|
||||
if (!m3u8Arr[index].endsWith('.m3u8')) {
|
||||
const onlineUrl = 'https://www.1717yun.com/jiexi/?url=' + url
|
||||
const open = require('open')
|
||||
open(onlineUrl)
|
||||
} else {
|
||||
this.xg.src = m3u8Arr[index]
|
||||
const key = this.video.key + '@' + this.video.info.id
|
||||
const startTime = VIDEO_DETAIL_CACHE[key].startPosition || 0
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = time
|
||||
this.xg.currentTime = time > startTime ? time : startTime
|
||||
if (VIDEO_DETAIL_CACHE[key].startPosition) this.xg.addProgressDot(VIDEO_DETAIL_CACHE[key].startPosition, '片头')
|
||||
if (VIDEO_DETAIL_CACHE[key].endPosition) this.xg.addProgressDot(this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition, '片尾')
|
||||
})
|
||||
this.videoPlaying()
|
||||
VIDEO_DETAIL_CACHE[key].skipend = false
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
|
||||
this.video.info.time = 0
|
||||
this.video.info.index++
|
||||
}
|
||||
this.xg.off('ended')
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
}
|
||||
|
||||
this.videoPlaying()
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
|
||||
this.video.info.time = 0
|
||||
this.video.info.index++
|
||||
}
|
||||
this.xg.off('ended')
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchM3u8List () {
|
||||
return new Promise((resolve) => {
|
||||
const cacheKey = this.video.key + '@' + this.video.info.id
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey]) {
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey] && VIDEO_DETAIL_CACHE[cacheKey].list && VIDEO_DETAIL_CACHE[cacheKey].list.length) {
|
||||
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
|
||||
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
|
||||
}
|
||||
zy.detail(this.video.key, this.video.info.id).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._t.indexOf('m3u8') >= 0) {
|
||||
m3u8Txt = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Txt = dd._t.split('#')
|
||||
}
|
||||
const m3u8Txt = res.m3u8List
|
||||
this.right.list = m3u8Txt
|
||||
const m3u8Arr = []
|
||||
for (const i of m3u8Txt) {
|
||||
const j = i.split('$')
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
|
||||
if (j[m].startsWith('http')) {
|
||||
m3u8Arr.push(j[m])
|
||||
break
|
||||
}
|
||||
@@ -611,10 +610,10 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = {
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = Object.assign(VIDEO_DETAIL_CACHE[cacheKey] || {}, {
|
||||
list: m3u8Arr,
|
||||
name: res.name
|
||||
}
|
||||
})
|
||||
resolve(m3u8Arr)
|
||||
})
|
||||
})
|
||||
@@ -655,6 +654,37 @@ export default {
|
||||
this.checkStar()
|
||||
this.checkTop()
|
||||
},
|
||||
async setProgressDotEvent (position, timespan, text) {
|
||||
const key = this.video.key + '@' + this.video.info.id
|
||||
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
|
||||
if (db && this.xg && VIDEO_DETAIL_CACHE[key].list.length > 1) {
|
||||
this[position] = { min: '' + parseInt(timespan / 60), sec: '' + parseInt(timespan % 60) }
|
||||
const positionTime = position === 'endPosition' ? this.xg.duration - timespan : timespan
|
||||
if (db[position]) this.xg.removeProgressDot(position === 'endPosition' ? this.xg.duration - db[position] : db[position])
|
||||
this.xg.addProgressDot(positionTime, text)
|
||||
const doc = { ...db }
|
||||
doc[position] = timespan
|
||||
delete doc.id
|
||||
history.update(db.id, doc)
|
||||
VIDEO_DETAIL_CACHE[key][position] = timespan
|
||||
}
|
||||
},
|
||||
async setProgressDotByInput () {
|
||||
this.xg.removeAllProgressDot()
|
||||
const startTime = parseInt(this.startPosition.min) * 60 + parseInt(this.startPosition.sec)
|
||||
const endTime = parseInt(this.endPosition.min) * 60 + parseInt(this.endPosition.sec)
|
||||
if (startTime > this.xg.duration || endTime > this.xg.duration) {
|
||||
this.$message.error('设置的跳跃时间长度已超过视频播放时长,请调整设置!')
|
||||
return
|
||||
}
|
||||
await this.setProgressDotEvent('startPosition', startTime)
|
||||
await this.setProgressDotEvent('endPosition', endTime)
|
||||
},
|
||||
async clearPosition () {
|
||||
await this.setProgressDotEvent('startPosition', 0)
|
||||
await this.setProgressDotEvent('endPosition', 0)
|
||||
this.xg.removeAllProgressDot()
|
||||
},
|
||||
timerEvent () {
|
||||
this.timer = setInterval(async () => {
|
||||
const endTime = this.xg.duration
|
||||
@@ -673,7 +703,7 @@ export default {
|
||||
},
|
||||
prevEvent () {
|
||||
if (this.video.iptv) {
|
||||
var index = this.channelList.findIndex(obj => obj.prefer === this.video.iptv.id)
|
||||
var index = this.channelList.findIndex(obj => obj.id === this.video.iptv.channelID)
|
||||
if (index >= 1) {
|
||||
var channel = this.channelList[index - 1]
|
||||
this.playChannel(channel)
|
||||
@@ -691,7 +721,7 @@ export default {
|
||||
},
|
||||
nextEvent () {
|
||||
if (this.video.iptv) {
|
||||
var index = this.channelList.findIndex(obj => obj.prefer === this.video.iptv.id)
|
||||
var index = this.channelList.findIndex(obj => obj.id === this.video.iptv.channelID)
|
||||
if (index < (this.channelList.length - 1)) {
|
||||
var channel = this.channelList[index + 1]
|
||||
this.playChannel(channel)
|
||||
@@ -781,6 +811,7 @@ export default {
|
||||
if (!miniWindowBounds) miniWindowBounds = { x: win.getPosition()[0], y: win.getPosition()[1], width: 550, height: 340 }
|
||||
win.setBounds(miniWindowBounds)
|
||||
this.xg.getCssFullscreen()
|
||||
document.querySelector('xg-btn-quitMiniMode').style.display = 'block'
|
||||
this.miniMode = true
|
||||
},
|
||||
async exitMiniEvent () {
|
||||
@@ -798,6 +829,7 @@ export default {
|
||||
})
|
||||
win.setBounds(this.mainWindowBounds)
|
||||
this.xg.exitCssFullscreen()
|
||||
document.querySelector('xg-btn-quitMiniMode').style.display = 'none'
|
||||
this.miniMode = false
|
||||
},
|
||||
shareEvent () {
|
||||
@@ -1021,7 +1053,7 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
shortcutEvent (e) {
|
||||
async shortcutEvent (e) {
|
||||
if (e === 'playAndPause') {
|
||||
if (this.xg) {
|
||||
if (this.xg.paused) {
|
||||
@@ -1113,6 +1145,18 @@ export default {
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'startPosition') {
|
||||
this.setProgressDotEvent('startPosition', this.xg.currentTime, '片头')
|
||||
return false
|
||||
}
|
||||
if (e === 'endPosition') {
|
||||
this.setProgressDotEvent('endPosition', this.xg.duration - this.xg.currentTime, '片尾')
|
||||
return false
|
||||
}
|
||||
if (e === 'clearPosition') {
|
||||
this.clearPosition()
|
||||
return false
|
||||
}
|
||||
if (e === 'opacityUp') {
|
||||
const num = win.getOpacity()
|
||||
if (num > 0.1) {
|
||||
@@ -1146,7 +1190,18 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'mini') {
|
||||
this.miniEvent()
|
||||
if (!this.miniMode) {
|
||||
this.miniEvent()
|
||||
} else {
|
||||
this.exitMiniEvent()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'resetMini') {
|
||||
if (this.miniMode) {
|
||||
const miniWindowBounds = { x: this.mainWindowBounds.x, y: this.mainWindowBounds.y, width: 550, height: 340 }
|
||||
win.setBounds(miniWindowBounds)
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
@@ -1278,6 +1333,19 @@ export default {
|
||||
setting.find().then(res => { res.volume = this.config.volume; setting.update(res) })
|
||||
})
|
||||
|
||||
this.xg.on('timeupdate', () => {
|
||||
const key = this.video.key + '@' + this.video.info.id
|
||||
if (VIDEO_DETAIL_CACHE[key] && VIDEO_DETAIL_CACHE[key].endPosition) {
|
||||
const time = this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition - this.xg.currentTime
|
||||
if (time > 0 && time < 0.3) {
|
||||
if (!VIDEO_DETAIL_CACHE[key].skipend) {
|
||||
VIDEO_DETAIL_CACHE[key].skipend = true
|
||||
this.xg.emit('ended')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.xg.on('playNextOne', () => {
|
||||
this.nextEvent()
|
||||
})
|
||||
@@ -1299,6 +1367,10 @@ export default {
|
||||
this.videoStop()
|
||||
})
|
||||
|
||||
this.xg.on('quitMiniMode', () => {
|
||||
if (this.miniMode) this.exitMiniEvent()
|
||||
})
|
||||
|
||||
const ev = ['click', 'touchend', 'mousemove']
|
||||
let timerID
|
||||
ev.forEach(item => {
|
||||
@@ -1329,7 +1401,7 @@ export default {
|
||||
clearInterval(this.timer)
|
||||
this.video.key = ''
|
||||
this.xg.src = ''
|
||||
this.config.src = ''
|
||||
this.config.url = ''
|
||||
this.xg.destroy(false)
|
||||
this.xg = null
|
||||
this.name = ''
|
||||
@@ -1365,6 +1437,10 @@ export default {
|
||||
Player.install('videoStop', function () {
|
||||
addPlayerBtn.bind(this, 'videoStop', '<svg t="1603093629102" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3621" style="width: 25px;height: 25px;margin-top: 8px;margin-left: 0px;"><path d="M768 768H256V256h512v512z" p-id="3622" fill="#ffffff"></path></svg>', { title: '停止播放' })()
|
||||
})
|
||||
Player.install('quitMiniMode', function () {
|
||||
addPlayerBtn.bind(this, 'quitMiniMode', '<svg t="1606051549980" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2510" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;"><path d="M224 704c-8 0-16-3.2-22.4-9.6l-160-160c-12.8-12.8-12.8-32 0-44.8l160-160c12.8-12.8 32-12.8 44.8 0 12.8 12.8 12.8 32 0 44.8L108.8 512l137.6 137.6c12.8 12.8 12.8 32 0 44.8-6.4 6.4-14.4 9.6-22.4 9.6z m416-160H80c-17.6 0-32-14.4-32-32s14.4-32 32-32h560c17.6 0 32 14.4 32 32s-14.4 32-32 32z m192 384H480c-52.8 0-96-43.2-96-96V704c0-17.6 14.4-32 32-32s32 14.4 32 32v128c0 17.6 14.4 32 32 32h352c17.6 0 32-14.4 32-32V192c0-17.6-14.4-32-32-32H480c-17.6 0-32 14.4-32 32v128c0 17.6-14.4 32-32 32s-32-14.4-32-32V192c0-52.8 43.2-96 96-96h352c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96z" p-id="2511" fill="#ffffff"></path></svg>',
|
||||
{ title: '退出精简模式' })()
|
||||
})
|
||||
Player.install('showList', function () {
|
||||
addPlayerBtn.bind(this, 'showList', '<svg t="1595866128681" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M0 0h1316.571429v146.285714H0zM0 438.857143h1316.571429v146.285714H0zM0 877.714286h1316.571429v146.285714H0z" p-id="4188" fill="#ffffff"></path></svg>', { title: '播放列表' })()
|
||||
})
|
||||
@@ -1421,7 +1497,8 @@ export default {
|
||||
.xgplayer-skin-default .xg-btn-playNextOne,
|
||||
.xgplayer-skin-default .xg-btn-showList,
|
||||
.xgplayer-skin-default .xg-btn-showHistory,
|
||||
.xgplayer-skin-default .xg-btn-videoStop {
|
||||
.xgplayer-skin-default .xg-btn-videoStop,
|
||||
.xgplayer-skin-default .xg-btn-quitMiniMode {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 0;
|
||||
@@ -1435,7 +1512,8 @@ export default {
|
||||
.xgplayer-skin-default .xg-btn-playNextOne:hover,
|
||||
.xgplayer-skin-default .xg-btn-showList:hover,
|
||||
.xgplayer-skin-default .xg-btn-showHistory:hover,
|
||||
.xgplayer-skin-default .xg-btn-videoStop:hover {
|
||||
.xgplayer-skin-default .xg-btn-videoStop:hover,
|
||||
.xgplayer-skin-default .xg-btn-quitMiniMode:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playNextOne {
|
||||
@@ -1444,15 +1522,22 @@ export default {
|
||||
.xgplayer-skin-default .xgplayer-play, .xgplayer-skin-default .xgplayer-play-img {
|
||||
order: 1 !important;
|
||||
}
|
||||
|
||||
.xgplayer-skin-default .xg-btn-videoStop {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.xgplayer-skin-default .xg-btn-quitMiniMode {
|
||||
order: 4;
|
||||
}
|
||||
|
||||
.xgplayer-skin-default .xg-btn-showList {
|
||||
order: 4;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showHistory {
|
||||
order: 4;
|
||||
}
|
||||
|
||||
.xgplayer-skin-default .xg-btn-showList ul, .xgplayer-skin-default .xg-btn-showHistory ul {
|
||||
display: none;
|
||||
list-style: none;
|
||||
@@ -1575,6 +1660,16 @@ export default {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.timespan{
|
||||
margin-left: auto;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
input{
|
||||
&::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list{
|
||||
|
||||
@@ -276,36 +276,21 @@ export default {
|
||||
}
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(e.key, e.ids).then(res => {
|
||||
if (res && res.dl && res.dl.dd) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
const key = e.key
|
||||
const id = e.ids
|
||||
zy.download(key, id).then(res => {
|
||||
if (res && res.m3u8List) {
|
||||
const list = res.m3u8List.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
var m3u8List = {}
|
||||
zy.detail(e.key, e.ids).then(res => {
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
const list = [...m3u8List]
|
||||
zy.detail(key, id).then(res => {
|
||||
const list = [...res.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
|
||||
@@ -78,6 +78,12 @@
|
||||
<div class="zy-select">
|
||||
<div class="vs-placeholder vs-noAfter" @click="view = 'IPTV'">编辑直播源</div>
|
||||
</div>
|
||||
<div class="zy-input">
|
||||
<input type="checkbox" v-model = "d.allowPassWhenIptvCheck" @change="updateSettingEvent"> 检测时自动跳过停用源
|
||||
</div>
|
||||
<div class="zy-input">
|
||||
<input type="checkbox" v-model = "d.autocleanWhenIptvCheck" @change="updateSettingEvent"> 检测时自动清理无效源
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="site">
|
||||
|
||||
@@ -74,20 +74,9 @@ export default {
|
||||
zy.detail(this.share.key, id).then(res => {
|
||||
if (res) {
|
||||
this.pic = res.pic
|
||||
var m3u8List = {}
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
var m3u8List = res.m3u8List
|
||||
const url = m3u8List[1]
|
||||
this.link = 'http://zyplayer.fun/player/player.html?url=' + url + '&title=' + this.share.info.name
|
||||
this.link = 'http://hunlongyu.gitee.io/zy-player-web?url=' + url + '&name=' + this.share.info.name
|
||||
}
|
||||
this.loading = false
|
||||
})
|
||||
|
||||
@@ -299,36 +299,21 @@ export default {
|
||||
})
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(e.key, e.ids).then(res => {
|
||||
if (res && res.dl && res.dl.dd) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
const key = e.key
|
||||
const id = e.id
|
||||
zy.download(key, id).then(res => {
|
||||
if (res && res.m3u8List) {
|
||||
const list = res.m3u8List.split('#')
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
|
||||
} else {
|
||||
var m3u8List = {}
|
||||
zy.detail(e.key, e.ids).then(res => {
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
const list = [...m3u8List]
|
||||
zy.detail(key, id).then(res => {
|
||||
const list = [...res.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
|
||||
@@ -5,14 +5,12 @@ const db = new Dexie('zy')
|
||||
|
||||
db.version(4).stores({
|
||||
search: '++id, keywords',
|
||||
iptvSearch: '++id, keywords',
|
||||
setting: 'id, theme, site, shortcut, view, volume, externalPlayer, searchGroup, excludeRootClasses, excludeR18Films, forwardTimeInSec, starViewMode, recommandationViewMode, searchViewMode, password, proxy',
|
||||
setting: 'id, theme, site, shortcut, view, volume, externalPlayer, searchGroup, excludeRootClasses, excludeR18Films, forwardTimeInSec, starViewMode, recommandationViewMode, searchViewMode, password, proxy, allowPassWhenIptvCheck, autocleanWhenIptvCheck',
|
||||
shortcut: 'name, key, desc',
|
||||
star: '++id, [key+ids], site, name, detail, index, rate, hasUpdate',
|
||||
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',
|
||||
mini: 'id, bounds',
|
||||
iptv: '++id, name, url, isActive',
|
||||
channelList: '++id, name, prefer, channels, group, isActive'
|
||||
|
||||
@@ -5,7 +5,6 @@ import shortcut from './shortcut'
|
||||
import star from './star'
|
||||
import sites from './sites'
|
||||
import search from './search'
|
||||
import iptvSearch from './iptvSearch'
|
||||
import iptv from './iptv'
|
||||
import channelList from './channelList'
|
||||
import recommendation from './recommendation'
|
||||
@@ -20,6 +19,5 @@ export {
|
||||
iptv,
|
||||
channelList,
|
||||
search,
|
||||
iptvSearch,
|
||||
recommendation
|
||||
}
|
||||
|
||||
@@ -1,5 +1,259 @@
|
||||
[
|
||||
{
|
||||
"key": "1886zy",
|
||||
"ids": 16944,
|
||||
"site": {
|
||||
"id": 2,
|
||||
"key": "1886zy",
|
||||
"name": "1886 资源",
|
||||
"api": "http://cj.1886zy.co/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
"name": "柯明斯基理论",
|
||||
"detail": {
|
||||
"last": "2018-11-23 18:13:07",
|
||||
"id": 16944,
|
||||
"tid": 15,
|
||||
"name": "柯明斯基理论",
|
||||
"type": "欧美剧",
|
||||
"pic": "http://pic.yc370.com/upload/vod/2019-01-19/15479133688.jpg",
|
||||
"lang": "",
|
||||
"area": "美国",
|
||||
"year": 2018,
|
||||
"state": 8,
|
||||
"note": "08",
|
||||
"actor": "迈克尔·道格拉斯,艾伦·阿金,莎拉·贝克,南希·特拉维斯",
|
||||
"director": "安迪·坦纳特,查克·罗瑞,唐纳德·佩特瑞,贝丝·麦卡锡-米勒",
|
||||
"dl": {
|
||||
"dd": [
|
||||
{
|
||||
"_t": "08$https://zuikzy.51moca.com/share/XoIqsGnIP7IED2LS#07$https://zkcdn.yiya520.com/share/kJOL42dTmm6VJkqK#06$https://zkcdn.yiya520.com/share/f8gxIqAchIPyxlAg#05$https://zkcdn.yiya520.com/share/mTG5GkXpB7yro1sQ#04$https://zkcdn.yiya520.com/share/HjQAbC0lzzHAusIw#03$https://zkcdn.yiya520.com/share/qlN7TvZUDDueiefE#02$https://zkcdn.yiya520.com/share/2P9HAA5H1KvkMgm2#01$https://zkcdn.yiya520.com/share/KUD3QMMS4UGnNA3Y",
|
||||
"_flag": "zkyun"
|
||||
},
|
||||
{
|
||||
"_t": "08$https://zuikzy.51moca.com/2018/11/23/XoIqsGnIP7IED2LS/playlist.m3u8#07$https://zkcdn.yiya520.com/2018/11/21/kJOL42dTmm6VJkqK/playlist.m3u8#06$https://zkcdn.yiya520.com/2018/11/21/f8gxIqAchIPyxlAg/playlist.m3u8#05$https://zkcdn.yiya520.com/2018/11/21/mTG5GkXpB7yro1sQ/playlist.m3u8#04$https://zkcdn.yiya520.com/2018/11/19/HjQAbC0lzzHAusIw/playlist.m3u8#03$https://zkcdn.yiya520.com/2018/11/19/qlN7TvZUDDueiefE/playlist.m3u8#02$https://zkcdn.yiya520.com/2018/11/18/2P9HAA5H1KvkMgm2/playlist.m3u8#01$https://zkcdn.yiya520.com/2018/11/18/KUD3QMMS4UGnNA3Y/playlist.m3u8",
|
||||
"_flag": "zkm3u8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"des": "迈克尔·道格拉斯、艾伦·阿金有望加盟Netflix喜剧剧集《柯明斯基理论》(The Kominsky Method,暂译)!该剧由《生活大爆炸》联合编剧查克·罗瑞担任制片。道格拉斯剧中饰演曾经红极一时的明星,现下却只能靠教授表演课程为生,阿金饰演他的老友。道格拉斯上次出演电视剧集还是上世纪70年代的《旧金山风物记》,而阿金上一部荧屏作品则是2001年的犯罪剧集《百厦街》。",
|
||||
"m3u8List": [
|
||||
"08$https://zuikzy.51moca.com/2018/11/23/XoIqsGnIP7IED2LS/playlist.m3u8",
|
||||
"07$https://zkcdn.yiya520.com/2018/11/21/kJOL42dTmm6VJkqK/playlist.m3u8",
|
||||
"06$https://zkcdn.yiya520.com/2018/11/21/f8gxIqAchIPyxlAg/playlist.m3u8",
|
||||
"05$https://zkcdn.yiya520.com/2018/11/21/mTG5GkXpB7yro1sQ/playlist.m3u8",
|
||||
"04$https://zkcdn.yiya520.com/2018/11/19/HjQAbC0lzzHAusIw/playlist.m3u8",
|
||||
"03$https://zkcdn.yiya520.com/2018/11/19/qlN7TvZUDDueiefE/playlist.m3u8",
|
||||
"02$https://zkcdn.yiya520.com/2018/11/18/2P9HAA5H1KvkMgm2/playlist.m3u8",
|
||||
"01$https://zkcdn.yiya520.com/2018/11/18/KUD3QMMS4UGnNA3Y/playlist.m3u8"
|
||||
],
|
||||
"rate": "9.2"
|
||||
},
|
||||
"rate": "9.2",
|
||||
"id": 255
|
||||
},
|
||||
{
|
||||
"key": "mahuazy",
|
||||
"ids": 21869,
|
||||
"site": {
|
||||
"id": 1,
|
||||
"key": "mahuazy",
|
||||
"name": "麻花资源",
|
||||
"api": "http://www.mhapi123.com/inc/ldg_api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
"name": "海上钢琴师",
|
||||
"detail": {
|
||||
"last": "2019-12-26 17:45:44",
|
||||
"id": 21869,
|
||||
"tid": 10,
|
||||
"name": "海上钢琴师",
|
||||
"type": "剧情片",
|
||||
"pic": "https://mahuapic.com/upload/vod/2019-12-26/201912261577353503.png",
|
||||
"lang": "英语",
|
||||
"area": "其它",
|
||||
"year": 2019,
|
||||
"state": 0,
|
||||
"note": "HD",
|
||||
"actor": "蒂姆·罗斯",
|
||||
"director": "朱塞佩·托纳多雷",
|
||||
"dl": {
|
||||
"dd": {
|
||||
"_t": "HD$https://mhkuaibo.com/20191226/4s3AkbXZ/index.m3u8$mahua",
|
||||
"_flag": "mahua"
|
||||
}
|
||||
},
|
||||
"des": "<span style=\"color: rgb(51, 51, 51); font-family: Tahoma, Helvetica, Arial, 微软雅黑, sans-serif; font-size: 14px; line-height: 22px; background-color: rgb(248, 248, 248);\">1900年,Virginian号豪华邮轮上,一个孤儿被遗弃在头等舱,由船上的水手抚养长大,取名1900。1900慢慢长大,显示出了无师自通的非凡钢琴天赋,在船上的乐队表演钢琴,每个听过他演奏的人,都被深深打动。爵士乐鼻祖杰尼听说了1900的高超技艺,专门上船和他比赛,最后自叹弗如,黯然离去。可惜,这一切的事情都发生在海上,1900从来不愿踏上陆地,直到有一天,他爱上了一个女孩,情愫在琴键上流淌。他会不会为了爱情,踏上陆地开始新的生活,用他的琴声惊艳世界?他将怎样谱写自己非凡的人生。</span><br />",
|
||||
"m3u8List": [
|
||||
"HD$https://mhkuaibo.com/20191226/4s3AkbXZ/index.m3u8$mahua"
|
||||
],
|
||||
"rate": "9.3"
|
||||
},
|
||||
"rate": "9.3",
|
||||
"id": 254
|
||||
},
|
||||
{
|
||||
"key": "mahuazy",
|
||||
"ids": 22567,
|
||||
"site": {
|
||||
"id": 1,
|
||||
"key": "mahuazy",
|
||||
"name": "麻花资源",
|
||||
"api": "http://www.mhapi123.com/inc/ldg_api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
"name": "王冠第一季",
|
||||
"detail": {
|
||||
"last": "2019-12-19 11:41:40",
|
||||
"id": 22567,
|
||||
"tid": 15,
|
||||
"name": "王冠第一季",
|
||||
"type": "欧美剧",
|
||||
"pic": "https://mahuapic.com/upload/vod/2019-12-19/15767269760.jpg",
|
||||
"lang": "英语",
|
||||
"area": "美国",
|
||||
"year": 2016,
|
||||
"state": 0,
|
||||
"note": "完结",
|
||||
"actor": "克莱尔·芙伊,马特·史密斯,约翰·利思戈,凡妮莎·柯比",
|
||||
"director": "本·卡隆,史蒂芬·戴德利,菲利普·马丁,朱里安·杰拉德",
|
||||
"dl": {
|
||||
"dd": {
|
||||
"_t": "第01集$https://mhyunbo.com/20191218/5vUSpghQ/index.m3u8$mahua#第02集$https://mhyunbo.com/20191218/jC9O5JXb/index.m3u8$mahua#第03集$https://mhyunbo.com/20191218/yHN6zIDc/index.m3u8$mahua#第04集$https://mhyunbo.com/20191218/q47c0tVo/index.m3u8$mahua#第05集$https://mhyunbo.com/20191218/PBckT1Qt/index.m3u8$mahua#第06集$https://mhyunbo.com/20191218/BSy4h1fR/index.m3u8$mahua#第07集$https://mhyunbo.com/20191218/gn2peH5k/index.m3u8$mahua#第08集$https://mhyunbo.com/20191218/2UNcvDq5/index.m3u8$mahua#第09集$https://mhyunbo.com/20191218/ROV7hhdI/index.m3u8$mahua#第10集$https://mhyunbo.com/20191218/VnSKiBc4/index.m3u8$mahua",
|
||||
"_flag": "mahua"
|
||||
}
|
||||
},
|
||||
"des": "马特·史密斯和约翰·利斯高加盟Netflix剧集《王冠》(The Crown,暂译),二人分别饰演菲利普亲王和丘吉尔。剧集剧本由《女王》编剧彼得·摩根创作,首播集由《时时刻刻》导演史蒂芬·戴德利执导,讲述伊丽莎白二世与丘吉尔在二战后,重塑英伦的故事。之前确定由克莱尔·福伊出演伊丽莎白二世。",
|
||||
"m3u8List": [
|
||||
"第01集$https://mhyunbo.com/20191218/5vUSpghQ/index.m3u8$mahua",
|
||||
"第02集$https://mhyunbo.com/20191218/jC9O5JXb/index.m3u8$mahua",
|
||||
"第03集$https://mhyunbo.com/20191218/yHN6zIDc/index.m3u8$mahua",
|
||||
"第04集$https://mhyunbo.com/20191218/q47c0tVo/index.m3u8$mahua",
|
||||
"第05集$https://mhyunbo.com/20191218/PBckT1Qt/index.m3u8$mahua",
|
||||
"第06集$https://mhyunbo.com/20191218/BSy4h1fR/index.m3u8$mahua",
|
||||
"第07集$https://mhyunbo.com/20191218/gn2peH5k/index.m3u8$mahua",
|
||||
"第08集$https://mhyunbo.com/20191218/2UNcvDq5/index.m3u8$mahua",
|
||||
"第09集$https://mhyunbo.com/20191218/ROV7hhdI/index.m3u8$mahua",
|
||||
"第10集$https://mhyunbo.com/20191218/VnSKiBc4/index.m3u8$mahua"
|
||||
],
|
||||
"rate": "9.2"
|
||||
},
|
||||
"rate": "9.2",
|
||||
"id": 253
|
||||
},
|
||||
{
|
||||
"id": 252,
|
||||
"key": "mahuazy",
|
||||
"ids": 29806,
|
||||
"site": {
|
||||
"id": 1,
|
||||
"key": "mahuazy",
|
||||
"name": "麻花资源",
|
||||
"api": "https://www.mhapi123.com/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
"name": "最后的棒棒",
|
||||
"rate": "9.6",
|
||||
"detail": {
|
||||
"last": "2020-04-12 15:43:02",
|
||||
"id": 29806,
|
||||
"tid": 20,
|
||||
"name": "最后的棒棒",
|
||||
"type": "记录片",
|
||||
"pic": "https://mahuapic.com/upload/vod/2020-04-12/15866774000.jpg",
|
||||
"lang": "国语",
|
||||
"area": "大陆",
|
||||
"year": 2016,
|
||||
"state": 0,
|
||||
"note": "完结",
|
||||
"actor": "何苦",
|
||||
"director": "何苦",
|
||||
"dl": {
|
||||
"dd": {
|
||||
"_t": "第01集$https://mahua-kb.com/20200412/vpFPIG1f/index.m3u8#第02集$https://mahua-kb.com/20200412/K0b5AvUp/index.m3u8#第03集$https://mahua-kb.com/20200412/tgpvWhFj/index.m3u8#第04集$https://mahua-kb.com/20200412/9mc4bPsO/index.m3u8#第05集$https://mahua-kb.com/20200412/gs0qmble/index.m3u8#第06集$https://mahua-kb.com/20200412/l2eDtPPY/index.m3u8#第07集$https://mahua-kb.com/20200412/7LrOTyqT/index.m3u8#第08集$https://mahua-kb.com/20200412/rnLFz9kO/index.m3u8#第09集$https://mahua-kb.com/20200412/nOTSjrba/index.m3u8#第10集$https://mahua-kb.com/20200412/qrfl8OzL/index.m3u8#第11集$https://mahua-kb.com/20200412/Y4sTsCWm/index.m3u8#第12集$https://mahua-kb.com/20200412/w5L2lXpy/index.m3u8#第13集$https://mahua-kb.com/20200412/Up2AGSWE/index.m3u8",
|
||||
"_flag": "mahua"
|
||||
}
|
||||
},
|
||||
"des": "改革开放之初,山城重庆特殊的地理环境孕育了一个特殊的行业——山城棒棒军。爬坡上坎,负重前行的三十多年,数十万棒棒大军不仅挑走了汗水浸泡的年华,也挑走了属于自己的年代。癸巳岁末,几个佝偻背影即将道别正在消逝的行业,一名退役中校扛起一根棒棒开始了自己的追寻——辉煌与尴尬,艰韧和无奈,他们的人生无须评说,他们的故事值得铭记。",
|
||||
"m3u8List": [
|
||||
"第01集$https://mahua-kb.com/20200412/vpFPIG1f/index.m3u8",
|
||||
"第02集$https://mahua-kb.com/20200412/K0b5AvUp/index.m3u8",
|
||||
"第03集$https://mahua-kb.com/20200412/tgpvWhFj/index.m3u8",
|
||||
"第04集$https://mahua-kb.com/20200412/9mc4bPsO/index.m3u8",
|
||||
"第05集$https://mahua-kb.com/20200412/gs0qmble/index.m3u8",
|
||||
"第06集$https://mahua-kb.com/20200412/l2eDtPPY/index.m3u8",
|
||||
"第07集$https://mahua-kb.com/20200412/7LrOTyqT/index.m3u8",
|
||||
"第08集$https://mahua-kb.com/20200412/rnLFz9kO/index.m3u8",
|
||||
"第09集$https://mahua-kb.com/20200412/nOTSjrba/index.m3u8",
|
||||
"第10集$https://mahua-kb.com/20200412/qrfl8OzL/index.m3u8",
|
||||
"第11集$https://mahua-kb.com/20200412/Y4sTsCWm/index.m3u8",
|
||||
"第12集$https://mahua-kb.com/20200412/w5L2lXpy/index.m3u8",
|
||||
"第13集$https://mahua-kb.com/20200412/Up2AGSWE/index.m3u8"
|
||||
],
|
||||
"rate": "9.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 251,
|
||||
"key": "mahuazy",
|
||||
"ids": 50694,
|
||||
"site": {
|
||||
"id": 1,
|
||||
"key": "mahuazy",
|
||||
"name": "麻花资源",
|
||||
"api": "https://www.mhapi123.com/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
"name": "以你的心诠释我的爱",
|
||||
"index": 2,
|
||||
"rate": "9.5",
|
||||
"detail": {
|
||||
"last": "2020-11-13 09:34:47",
|
||||
"id": 50694,
|
||||
"tid": 17,
|
||||
"name": "以你的心诠释我的爱",
|
||||
"type": "泰剧",
|
||||
"pic": "https://mahuapic.com/upload/vod/2020-10-23/16034119330.jpg",
|
||||
"lang": "泰语",
|
||||
"area": "泰国",
|
||||
"year": 2020,
|
||||
"state": 0,
|
||||
"note": "更新至04集",
|
||||
"actor": "克里特·安努艾德奇康,普提蓬·阿萨拉塔纳功",
|
||||
"director": "纳卢拜·库诺",
|
||||
"dl": {
|
||||
"dd": {
|
||||
"_t": "第01集$https://b.mhqiyi.com/20201022/K4gdEqpu/index.m3u8#第02集$https://b.mhqiyi.com/20201029/h3maf38g/index.m3u8#第03集$https://e.mahua-kb.com/20201105/HVK7wMlM/index.m3u8#第04集$https://b.mhqiyi.com/20201112/pOl6JaA7/index.m3u8",
|
||||
"_flag": "mahua"
|
||||
}
|
||||
},
|
||||
"des": "这部电视剧是BKPP project的一部分",
|
||||
"m3u8List": [
|
||||
"第01集$https://b.mhqiyi.com/20201022/K4gdEqpu/index.m3u8",
|
||||
"第02集$https://b.mhqiyi.com/20201029/h3maf38g/index.m3u8",
|
||||
"第03集$https://e.mahua-kb.com/20201105/HVK7wMlM/index.m3u8",
|
||||
"第04集$https://b.mhqiyi.com/20201112/pOl6JaA7/index.m3u8"
|
||||
],
|
||||
"rate": "9.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 250,
|
||||
"key": "niuniucj",
|
||||
"ids": 20044,
|
||||
"site": {
|
||||
@@ -12,6 +266,7 @@
|
||||
"isActive": 1
|
||||
},
|
||||
"name": "此画怎讲",
|
||||
"rate": "8.1",
|
||||
"detail": {
|
||||
"last": "2020-09-23 23:23:36",
|
||||
"id": 20044,
|
||||
@@ -72,11 +327,10 @@
|
||||
"第30集$https://s6.niuniu-baidu.com/2020/09/23/37H4vtEiTXcjSzoa/index.m3u8"
|
||||
],
|
||||
"rate": "8.1"
|
||||
},
|
||||
"rate": "8.1",
|
||||
"id": 250
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 249,
|
||||
"key": "niuniucj",
|
||||
"ids": 4255,
|
||||
"site": {
|
||||
@@ -89,6 +343,7 @@
|
||||
"isActive": 1
|
||||
},
|
||||
"name": "紧急呼救第一季",
|
||||
"rate": "8.6",
|
||||
"detail": {
|
||||
"last": "2019-10-10 19:19:15",
|
||||
"id": 4255,
|
||||
@@ -129,11 +384,10 @@
|
||||
"第10集$https://s1.niuniu-baidu.com/20191010/XZjWRMxLgh8nyFlT/index.m3u8"
|
||||
],
|
||||
"rate": "8.6"
|
||||
},
|
||||
"rate": "8.6",
|
||||
"id": 249
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 248,
|
||||
"key": "niuniucj",
|
||||
"ids": 20632,
|
||||
"site": {
|
||||
@@ -146,6 +400,7 @@
|
||||
"isActive": 1
|
||||
},
|
||||
"name": "小小世界",
|
||||
"rate": "9.4",
|
||||
"detail": {
|
||||
"last": "2020-10-03 12:00:49",
|
||||
"id": 20632,
|
||||
@@ -182,9 +437,7 @@
|
||||
"第06集$https://s6.niuniu-baidu.com/2020/10/03/U0JFALI1lHOjWCfw/index.m3u8"
|
||||
],
|
||||
"rate": "9.4"
|
||||
},
|
||||
"rate": "9.4",
|
||||
"id": 248
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 247,
|
||||
@@ -9238,6 +9491,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"key": "mahuazy",
|
||||
"ids": 20868,
|
||||
"site": {
|
||||
@@ -9250,6 +9504,7 @@
|
||||
"group": "默认"
|
||||
},
|
||||
"name": "铁血战士(1987)",
|
||||
"rate": "7.7",
|
||||
"detail": {
|
||||
"last": "2019-11-23 10:59:36",
|
||||
"id": 20868,
|
||||
@@ -9275,9 +9530,7 @@
|
||||
"HD$https://mhbobo.com/20191121/vyWmCGRH/index.m3u8"
|
||||
],
|
||||
"rate": "7.7"
|
||||
},
|
||||
"rate": "7.7",
|
||||
"id": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": 1,
|
||||
"key": "mahuazy",
|
||||
"name": "麻花资源",
|
||||
"api": "https://www.mhapi123.com/inc/api.php",
|
||||
"api": "http://www.mhapi123.com/inc/ldg_api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
@@ -11,9 +11,9 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"key": "niuniucj",
|
||||
"name": "牛牛资源",
|
||||
"api": "http://v.niuniucj.com/inc/api.php",
|
||||
"key": "1886zy",
|
||||
"name": "1886 资源",
|
||||
"api": "http://cj.1886zy.co/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
@@ -21,46 +21,6 @@
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"key": "88zyw",
|
||||
"name": "88 影视资源站",
|
||||
"api": "http://www.88zyw.net/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"key": "apibdzy",
|
||||
"name": "百度云资源",
|
||||
"api": "https://api.apibdzy.com/api.php/provide/vod/at/xml",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"key": "mbo",
|
||||
"name": "秒播资源",
|
||||
"api": "http://caiji.mb77.vip/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"key": "zuidazy",
|
||||
"name": "最大资源网",
|
||||
"api": "http://www.zdziyuan.com/inc/api.php",
|
||||
"download": "http://www.zdziyuan.com/inc/apidown.php",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"key": "123ku",
|
||||
"name": "123 资源",
|
||||
"api": "http://cj.123ku2.com:12315/inc/api.php",
|
||||
@@ -69,8 +29,58 @@
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"key": "subo988",
|
||||
"name": "速播资源站",
|
||||
"api": "https://www.subo988.com/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"key": "88zyw",
|
||||
"name": "88 影视资源站",
|
||||
"api": "http://www.88zyw.net/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"key": "zuidazy",
|
||||
"id": 6,
|
||||
"name": "最大资源网",
|
||||
"api": "http://www.zdziyuan.com/inc/ldg_sea.php",
|
||||
"download": "http://www.zdziyuan.com/inc/apidown.php",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"key": "mbo",
|
||||
"id": 7,
|
||||
"name": "秒播资源",
|
||||
"api": "http://caiji.mb77.vip/inc/seacmsapi.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"key": "apibdzy",
|
||||
"name": "百度云资源",
|
||||
"api": "https://api.apibdzy.com/api.php/provide/vod/at/xml",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"key": "okzy",
|
||||
"name": "OK 资源网",
|
||||
"api": "http://cj.okzy.tv/inc/api.php",
|
||||
@@ -80,7 +90,7 @@
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"id": 10,
|
||||
"key": "kuyunzy",
|
||||
"name": "酷云资源",
|
||||
"api": "http://caiji.kuyun98.com/inc/ldg_api.php",
|
||||
@@ -90,7 +100,7 @@
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"id": 11,
|
||||
"key": "kubozy",
|
||||
"name": "酷播资源",
|
||||
"api": "http://api.kbzyapi.com/inc/api.php",
|
||||
@@ -100,7 +110,7 @@
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"id": 12,
|
||||
"key": "yongjiuzy",
|
||||
"name": "永久资源",
|
||||
"api": "http://cj.yongjiuzyw.com/inc/api.php",
|
||||
@@ -110,7 +120,7 @@
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"id": 13,
|
||||
"key": "rrzy",
|
||||
"name": "人人资源",
|
||||
"api": "https://www.rrzyw.cc/api.php/provide/vod/from/rrm3u8/at/xml/",
|
||||
@@ -120,7 +130,7 @@
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"id": 14,
|
||||
"key": "bbkdj",
|
||||
"name": "步步高顶尖资源网",
|
||||
"api": "http://api.bbkdj.com/api",
|
||||
@@ -129,16 +139,6 @@
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"key": "solezy",
|
||||
"name": "搜乐资源网",
|
||||
"api": "https://www.caijizy.vip/api.php/provide/vod/at/xml/",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"key": "zuixinzy",
|
||||
@@ -151,66 +151,6 @@
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"key": "605zy",
|
||||
"name": "605资源",
|
||||
"api": "http://www.605zy.net/inc/seacmsapi.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"key": "subo988",
|
||||
"name": "速播资源站",
|
||||
"api": "https://www.subo988.com/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"key": "1886zy",
|
||||
"name": "1886 资源",
|
||||
"api": "http://cj.1886zy.co/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"key": "doubanzy",
|
||||
"name": "豆瓣电影资源",
|
||||
"api": "http://v.1988cj.com/inc/api.php",
|
||||
"download": "http://v.1988cj.com/inc/apidown.php",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"key": "135zy",
|
||||
"name": "135 资源网",
|
||||
"api": "http://cj.zycjw1.com/inc/api.php",
|
||||
"download": "http://cj.zycjw1.com/inc/apidown.php",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"key": "mgtvzy",
|
||||
"name": "芒果 TV 资源网",
|
||||
"api": "https://api.shijiapi.com/api.php/provide/vod/at/xml/",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"key": "209zy",
|
||||
"name": "209 资源",
|
||||
"api": "http://cj.1156zy.com/inc/api.php",
|
||||
@@ -218,55 +158,5 @@
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"key": "kkzy",
|
||||
"name": "快快资源",
|
||||
"api": "https://api.kkzy.tv/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"key": "wolongzy",
|
||||
"name": "卧龙资源",
|
||||
"api": "http://cj.wlzy.tv/inc/api_mac.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"key": "mokazy",
|
||||
"name": "魔卡资源网",
|
||||
"api": "https://cj.heiyap.com/api.php/provide/vod/at/xml/",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"key": "158zy",
|
||||
"name": "壹伍捌资源网",
|
||||
"api": "http://cj.158zyz.net:158/inc/api.php",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"key": "kyzy",
|
||||
"name": "快影资源站",
|
||||
"api": "https://www.kyzy.tv/api.php/kyyun/vod/at/xml/",
|
||||
"download": "",
|
||||
"group": "默认",
|
||||
"isActive": true,
|
||||
"status": "可用"
|
||||
}
|
||||
]
|
||||
@@ -19,7 +19,9 @@ const setting = [
|
||||
scheme: '',
|
||||
url: '',
|
||||
port: ''
|
||||
}
|
||||
},
|
||||
allowPassWhenIptvCheck: true,
|
||||
autocleanWhenIptvCheck: false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -66,7 +68,7 @@ const localKey = [
|
||||
},
|
||||
{
|
||||
name: 'escape',
|
||||
desc: '退出全屏',
|
||||
desc: '退出全屏/精简模式',
|
||||
key: 'esc'
|
||||
},
|
||||
{
|
||||
@@ -89,6 +91,21 @@ const localKey = [
|
||||
desc: '跳到视频结束位置',
|
||||
key: 'end'
|
||||
},
|
||||
{
|
||||
name: 'startPosition',
|
||||
desc: '标记片头',
|
||||
key: 'ctrl+home'
|
||||
},
|
||||
{
|
||||
name: 'endPosition',
|
||||
desc: '标记片尾',
|
||||
key: 'ctrl+end'
|
||||
},
|
||||
{
|
||||
name: 'clearPosition',
|
||||
desc: '清除标记',
|
||||
key: 'ctrl+del'
|
||||
},
|
||||
{
|
||||
name: 'opacityUp',
|
||||
desc: '透明度调高',
|
||||
@@ -113,6 +130,11 @@ const localKey = [
|
||||
name: 'mini',
|
||||
desc: '进入或退出mini模式',
|
||||
key: 'alt+m'
|
||||
},
|
||||
{
|
||||
name: 'resetMini',
|
||||
desc: '重置mini窗口',
|
||||
key: 'ctrl+0'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import db from './dexie'
|
||||
const { iptvSearch } = db
|
||||
export default {
|
||||
async add (doc) {
|
||||
return await iptvSearch.add(doc)
|
||||
},
|
||||
async find (doc) {
|
||||
return await iptvSearch.get(doc)
|
||||
},
|
||||
async update (id, docs) {
|
||||
return await iptvSearch.update(id, docs)
|
||||
},
|
||||
async all () {
|
||||
return await iptvSearch.toArray()
|
||||
},
|
||||
async remove (id) {
|
||||
return await iptvSearch.delete(id)
|
||||
},
|
||||
async clear () {
|
||||
return await iptvSearch.clear()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { Message, Button, Table, TableColumn, Tag, Input, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete, Col, Tree } from 'element-ui'
|
||||
import { Message, Button, Table, TableColumn, Tag, Input, InputNumber, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete, Col, Tree, Divider } from 'element-ui'
|
||||
import Plugin from 'v-fit-columns'
|
||||
Vue.use(Button)
|
||||
Vue.use(Col)
|
||||
@@ -7,6 +7,7 @@ Vue.use(Table)
|
||||
Vue.use(TableColumn)
|
||||
Vue.use(Tag)
|
||||
Vue.use(Input)
|
||||
Vue.use(InputNumber)
|
||||
Vue.use(Dialog)
|
||||
Vue.use(Form)
|
||||
Vue.use(FormItem)
|
||||
@@ -17,4 +18,5 @@ Vue.use(Option)
|
||||
Vue.use(Checkbox)
|
||||
Vue.use(Autocomplete)
|
||||
Vue.use(Tree)
|
||||
Vue.use(Divider)
|
||||
Vue.prototype.$message = Message
|
||||
|
||||
@@ -92,9 +92,10 @@ const zy = {
|
||||
axios.post(url).then(res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
const arr = []
|
||||
if (json.rss.class) {
|
||||
for (const i of json.rss.class.ty) {
|
||||
if (jsondata.class) {
|
||||
for (const i of jsondata.class.ty) {
|
||||
const j = {
|
||||
tid: i._id,
|
||||
name: i._t
|
||||
@@ -104,10 +105,10 @@ const zy = {
|
||||
}
|
||||
const doc = {
|
||||
class: arr,
|
||||
page: json.rss.list._page,
|
||||
pagecount: json.rss.list._pagecount,
|
||||
pagesize: json.rss.list._pagesize,
|
||||
recordcount: json.rss.list._recordcount
|
||||
page: jsondata.list._page,
|
||||
pagecount: jsondata.list._pagecount,
|
||||
pagesize: jsondata.list._pagesize,
|
||||
recordcount: jsondata.list._recordcount
|
||||
}
|
||||
resolve(doc)
|
||||
}).catch(err => {
|
||||
@@ -136,7 +137,8 @@ const zy = {
|
||||
axios.post(url).then(async res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
const videoList = json.rss.list.video
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
const videoList = jsondata.list.video
|
||||
resolve(videoList)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
@@ -163,11 +165,12 @@ const zy = {
|
||||
axios.post(url).then(async res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
const pg = {
|
||||
page: json.rss.list._page,
|
||||
pagecount: json.rss.list._pagecount,
|
||||
pagesize: json.rss.list._pagesize,
|
||||
recordcount: json.rss.list._recordcount
|
||||
page: jsondata.list._page,
|
||||
pagecount: jsondata.list._pagecount,
|
||||
pagesize: jsondata.list._pagesize,
|
||||
recordcount: jsondata.list._recordcount
|
||||
}
|
||||
resolve(pg)
|
||||
}).catch(err => {
|
||||
@@ -191,8 +194,9 @@ const zy = {
|
||||
axios.post(url, { timeout: 3000 }).then(res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
if (json && json.rss && json.rss.list) {
|
||||
const videoList = json.rss.list.video
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
if (json && jsondata && jsondata.list) {
|
||||
const videoList = jsondata.list.video
|
||||
resolve(videoList)
|
||||
}
|
||||
}).catch(err => {
|
||||
@@ -216,14 +220,16 @@ const zy = {
|
||||
axios.post(url).then(res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
const videoList = json.rss.list.video
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
const videoList = jsondata.list.video
|
||||
// Parse m3u8List
|
||||
var m3u8List = []
|
||||
const dd = videoList.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._flag.indexOf('m3u8') >= 0) {
|
||||
// 如果含有多个视频列表的话, 仅获取m3u8列表
|
||||
if (i._flag.includes('m3u8')) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
}
|
||||
@@ -255,7 +261,20 @@ const zy = {
|
||||
axios.post(url).then(res => {
|
||||
const data = res.data
|
||||
const json = parser.parse(data, this.xmlConfig)
|
||||
const videoList = json.rss.list.video
|
||||
const jsondata = json.rss === undefined ? json : json.rss
|
||||
const videoList = jsondata.list.video
|
||||
// Parse m3u8List
|
||||
var m3u8List = []
|
||||
const dd = videoList.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
m3u8List = i._t.split('#')
|
||||
}
|
||||
} else {
|
||||
m3u8List = dd._t.split('#')
|
||||
}
|
||||
videoList.m3u8List = m3u8List
|
||||
resolve(videoList)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
@@ -374,17 +393,15 @@ const zy = {
|
||||
async proxy () {
|
||||
return new Promise((resolve, reject) => {
|
||||
setting.find().then(db => {
|
||||
if (db.proxy) {
|
||||
if (db.proxy.type === 'none') {
|
||||
session.setProxy({ proxyRules: 'direct://' })
|
||||
if (db && db.proxy && db.proxy.type === 'manual') {
|
||||
if (db.proxy.scheme && db.proxy.url && db.proxy.port) {
|
||||
const proxyURL = db.proxy.scheme + '://' + db.proxy.url.trim() + ':' + db.proxy.port.trim()
|
||||
session.setProxy({ proxyRules: proxyURL })
|
||||
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
|
||||
} else if (db.proxy.type === 'manual') {
|
||||
if (db.proxy.scheme && db.proxy.url && db.proxy.port) {
|
||||
const proxyURL = db.proxy.scheme + '://' + db.proxy.url.trim() + ':' + db.proxy.port.trim()
|
||||
session.setProxy({ proxyRules: proxyURL })
|
||||
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session.setProxy({ proxyRules: 'direct://' })
|
||||
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
|
||||
}
|
||||
// 不要删了,留着测试用
|
||||
// axios.get('https://api.my-ip.io/ip').then(res => console.log(res))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
pages: {
|
||||
index: 'src/main.js',
|
||||
index: 'src/main.js'
|
||||
},
|
||||
pluginOptions: {
|
||||
electronBuilder: {
|
||||
|
||||