mirror of
https://github.com/cuiocean/ZY-Player.git
synced 2026-02-15 00:16:26 +08:00
Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
add2bedb61 | ||
|
|
3dc970e198 | ||
|
|
3f2def4455 | ||
|
|
5b8d883af4 | ||
|
|
7113567475 | ||
|
|
e30da35e72 | ||
|
|
55b7396a2e | ||
|
|
83568fa499 | ||
|
|
838d3a64cd | ||
|
|
506be03e3e | ||
|
|
cfdb561473 | ||
|
|
ab2f45189f | ||
|
|
f4b9a73b18 | ||
|
|
6f99d789f4 | ||
|
|
e71090dad2 | ||
|
|
afe3351837 | ||
|
|
5dc0613aeb | ||
|
|
1c6385ae6c | ||
|
|
88a95a8bfb | ||
|
|
951e6ffa37 | ||
|
|
b83aed0a97 | ||
|
|
67ce537039 | ||
|
|
975562a66b | ||
|
|
8e7015c9d6 | ||
|
|
b841552dc7 | ||
|
|
0a9b939dc3 | ||
|
|
14ff252cce | ||
|
|
afd016be93 | ||
|
|
9cd7f7d267 | ||
|
|
8a76ec4e87 | ||
|
|
a00d965ce9 | ||
|
|
c9eb0c3e22 | ||
|
|
c80c0bd948 | ||
|
|
65dcfa04ae | ||
|
|
4e4ab82ea2 | ||
|
|
dd2adf4f99 | ||
|
|
777fbde528 | ||
|
|
472898f978 | ||
|
|
7f41d415f1 | ||
|
|
5d37a36c21 | ||
|
|
3a499766af | ||
|
|
cea797b6d0 | ||
|
|
37b41b0e20 | ||
|
|
1105c46f08 | ||
|
|
1df7b41edd | ||
|
|
f76c71c950 | ||
|
|
cd77384bd9 | ||
|
|
64adc9d6c1 | ||
|
|
e9095e50a6 | ||
|
|
acfa742b4f | ||
|
|
a79c48cba0 | ||
|
|
904ef5ccea | ||
|
|
3db281c87f | ||
|
|
076e6e99e4 | ||
|
|
32f6ac0310 | ||
|
|
b8706ea432 | ||
|
|
509d6c7900 | ||
|
|
51454d828c | ||
|
|
59449886f5 | ||
|
|
601e9895cc | ||
|
|
1ba8b46990 | ||
|
|
7ed34caa56 | ||
|
|
fc40521420 | ||
|
|
cfdd836e01 | ||
|
|
083e00ddbf | ||
|
|
c41c7c4857 | ||
|
|
4bde51dc38 | ||
|
|
38c7540145 | ||
|
|
a44579d4a1 | ||
|
|
7f2d6f12c0 | ||
|
|
daf1c4ddb6 | ||
|
|
c1372c5589 | ||
|
|
c623533271 | ||
|
|
069e7e16d6 | ||
|
|
cabe4240f4 | ||
|
|
5448e86109 | ||
|
|
536f6dad7d | ||
|
|
bf2796779f | ||
|
|
3a29147fd6 | ||
|
|
e987ecc446 | ||
|
|
9aee6d8527 | ||
|
|
4d438fcdd3 | ||
|
|
36e40f4778 | ||
|
|
422def0702 | ||
|
|
fc52d79d88 | ||
|
|
cc09d0aca0 | ||
|
|
b514f1c04e | ||
|
|
189e67eb22 | ||
|
|
e5c3adf1c5 | ||
|
|
299367f0b8 | ||
|
|
0d67474459 | ||
|
|
15a188aa85 | ||
|
|
0555badcfa |
2
.github/workflows/x86.yml
vendored
2
.github/workflows/x86.yml
vendored
@@ -3,7 +3,7 @@ name: release-build
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- x86 *
|
||||
- x86-v*
|
||||
|
||||
jobs:
|
||||
release:
|
||||
|
||||
37
README.md
37
README.md
@@ -25,13 +25,15 @@
|
||||
|
||||
# 目录
|
||||
- [特性](#特性)
|
||||
- [全局快捷键](#全局快捷键)
|
||||
- [重要](#重要)
|
||||
- [快捷键](#快捷键)
|
||||
- [下载](#下载)
|
||||
- [赞助](#赞助)
|
||||
- [截图](#截图)
|
||||
- [开发向导](#开发向导)
|
||||
- [准备环境](#准备环境)
|
||||
- [nodejs安装](#nodejs安装)
|
||||
- [yarn新一代包管理器安利](#yarn新一代包管理器安利)
|
||||
- [npm配置](#npm配置)
|
||||
- [翻墙代理设置](#翻墙代理设置)
|
||||
- [镜像源设置](#镜像源设置)
|
||||
@@ -57,7 +59,10 @@
|
||||
|
||||
觉得软件不错的, 点击右上角 star 收藏关注一波呀~
|
||||
|
||||
#### 快捷键:
|
||||
## 重要
|
||||
从 V1.x 版本升级到 V2.x 版本, 需要重置软件, 由于数据库改动较大, 重置后收藏的资源会丢失. 重置功能在设置界面里.
|
||||
|
||||
#### 快捷键
|
||||
|
||||
播放窗口 和 Mini窗口
|
||||
|
||||
@@ -76,9 +81,9 @@
|
||||
|
||||
#### 下载:
|
||||
|
||||
1. [Github -- 官方下载(最新版)](https://github.com/Hunlongyu/ZY-Player/releases)
|
||||
1. [Github -- 官方下载](https://github.com/Hunlongyu/ZY-Player/releases)
|
||||
|
||||
2. [蓝奏云 -- 快速下载(老版本)](https://www.lanzous.com/b04s6a3re) 密码:95px
|
||||
2. [蓝奏云 -- 快速下载](https://www.lanzous.com/b04s6a3re) 密码:95px
|
||||
|
||||
3. 适用于32位操作系统的x86软件,在蓝奏云网盘里, 后缀名: ZY Player * 32位.exe
|
||||
|
||||
@@ -87,25 +92,24 @@
|
||||
|
||||
#### 截图:
|
||||
|
||||
0. 分享 ⇣ ↓
|
||||

|
||||
|
||||
1. 浏览 ⇣ ↓
|
||||

|
||||

|
||||

|
||||
2. 搜索 ⇣ ↓
|
||||

|
||||

|
||||
3. 详情 ⇣ ↓
|
||||

|
||||

|
||||
4. 播放 ⇣ ↓
|
||||

|
||||

|
||||

|
||||
5. 收藏 ⇣ ↓
|
||||

|
||||

|
||||
6. 白色主题皮肤 ⇣ ↓
|
||||

|
||||

|
||||
7. 绿色主题皮肤 ⇣ ↓
|
||||

|
||||

|
||||
8. 粉色色主题皮肤 ⇣ ↓
|
||||

|
||||

|
||||
|
||||
### 重要:
|
||||
所有资源来自网上, 该软件不参与任何制作, 上传, 储存, 下载等内容. 该软件仅供学习参考, 请于安装后24小时内删除.
|
||||
@@ -119,6 +123,9 @@
|
||||
* [LINK1](https://nodejs.org/zh-cn/)
|
||||
* [LINK2](https://www.jianshu.com/p/13f45e24b1de/)
|
||||
|
||||
#### yarn新一代包管理器安利
|
||||
最近管理员用[yarn](https://yarn.bootcss.com/)替换了npm,本人测试后表示非常好用。。连翻墙都不想要了,强烈推荐, 安装好使用yarn代理npm命令即可, [官网安装向导](https://yarn.bootcss.com/docs/install/)
|
||||
|
||||
#### npm配置
|
||||
天朝的网络环境都有耳闻,想顺利开发,要么翻墙,要么镜像源,以下按照自己的水平二选一
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zy",
|
||||
"version": "1.2.2",
|
||||
"version": "2.4.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -18,6 +18,7 @@
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"child_process": "^1.0.2",
|
||||
"core-js": "^3.6.5",
|
||||
"cors": "^2.8.5",
|
||||
"dexie": "^3.0.1",
|
||||
@@ -33,7 +34,7 @@
|
||||
"vue-infinite-loading": "^2.4.5",
|
||||
"vue-waterfall-plugin": "^1.0.7",
|
||||
"vuex": "^3.4.0",
|
||||
"xgplayer": "^2.9.8",
|
||||
"xgplayer": "^2.9.10",
|
||||
"xgplayer-hls.js": "^2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<Film v-show="view === 'Film'" />
|
||||
<Play v-show="view === 'Play'" />
|
||||
<Star v-show="view === 'Star'" />
|
||||
<History v-show="view === 'History'" />
|
||||
<Setting v-show="view === 'Setting'" />
|
||||
</div>
|
||||
<transition name="slide">
|
||||
@@ -59,7 +60,7 @@ export default {
|
||||
@import './assets/scss/theme.scss';
|
||||
html, body, #app{
|
||||
height: 100%;
|
||||
border-radius: 6px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
#app {
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', SimSun, sans-serif;
|
||||
|
||||
@@ -78,16 +78,45 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.zy-checkbox{
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 200px;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
align-items: center;
|
||||
.search-all-check-input{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.zy-highlighted{
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
// table
|
||||
.zy-table{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
.tHeader{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
height: 50px;
|
||||
min-height: 50px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid;
|
||||
.btn{
|
||||
user-select: none;
|
||||
margin-right: 15px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
flex: 1;
|
||||
border-bottom: 1px solid;
|
||||
overflow: auto;
|
||||
ul{
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
@@ -102,41 +131,42 @@
|
||||
cursor: pointer;
|
||||
span{
|
||||
display: flex;
|
||||
width: 180px;
|
||||
font-size: 13px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
margin-right: 5px;
|
||||
&.name{
|
||||
flex: 1;
|
||||
padding-left: 15px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 100px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.note{
|
||||
width: 180px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
&.type{
|
||||
width: 120px;
|
||||
}
|
||||
&.last{
|
||||
width: 160px;
|
||||
width: 10%;
|
||||
}
|
||||
&.time{
|
||||
width: 60px;
|
||||
width: 10%;
|
||||
}
|
||||
&.from{
|
||||
width: 120px;
|
||||
&.last{
|
||||
width: 10%;
|
||||
}
|
||||
&.site{
|
||||
width: 10%;
|
||||
}
|
||||
&.note{
|
||||
width: 10%;
|
||||
}
|
||||
&.operate{
|
||||
width: 170px;
|
||||
.btn{
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scroll
|
||||
.zy-scroll{
|
||||
&::-webkit-scrollbar{
|
||||
@@ -152,7 +182,6 @@
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
// loading
|
||||
.zy-loading{
|
||||
width: 100%;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
:root{
|
||||
// general
|
||||
--highlight-color: #38dd77;
|
||||
// light
|
||||
--l-c-0: #823aa0;
|
||||
--l-c-1: #823aa011;
|
||||
|
||||
@@ -32,8 +32,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-checkbox{
|
||||
color: var(--d-fc-1);
|
||||
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--d-fc-2);
|
||||
.tHeader{
|
||||
border-bottom-color: var(--d-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
color: var(--d-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--d-c-3);
|
||||
ul{
|
||||
@@ -101,6 +113,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
@@ -166,6 +181,11 @@
|
||||
box-shadow: var(--d-bsc);
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
.right {
|
||||
svg {
|
||||
fill: var(--d-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
@@ -189,6 +209,10 @@
|
||||
fill: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
&.last-tip {
|
||||
color: var(--d-fc-1);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +242,9 @@
|
||||
background-color: var(--d-c-2);
|
||||
color: var(--d-fc-3);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
@@ -263,7 +290,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.view, .shortcut, .site{
|
||||
.view, .search, .shortcut, .site{
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
@@ -313,4 +340,8 @@
|
||||
background-color: var(--d-bgc-1);
|
||||
}
|
||||
}
|
||||
.history{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-checkbox{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--g-fc-2);
|
||||
.tHeader{
|
||||
border-bottom-color: var(--g-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
color: var(--g-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--g-c-3);
|
||||
ul{
|
||||
@@ -101,6 +112,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
@@ -166,6 +180,11 @@
|
||||
box-shadow: var(--g-bsc);
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
.right {
|
||||
svg {
|
||||
fill: var(--g-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
@@ -189,6 +208,10 @@
|
||||
fill: var(--g-c-3);
|
||||
}
|
||||
}
|
||||
&.last-tip {
|
||||
color: var(--g-fc-1);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +241,9 @@
|
||||
background-color: var(--g-c-2);
|
||||
color: var(--g-fc-3);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
@@ -263,7 +289,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.view, .shortcut, .site{
|
||||
.view, .search, .shortcut, .site{
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
@@ -313,4 +339,8 @@
|
||||
background-color: var(--g-bgc-1);
|
||||
}
|
||||
}
|
||||
.history{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-checkbox{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--l-fc-2);
|
||||
.tHeader{
|
||||
border-bottom-color: var(--l-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
color: var(--l-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--l-c-3);
|
||||
ul{
|
||||
@@ -101,6 +112,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
@@ -166,6 +180,11 @@
|
||||
box-shadow: var(--l-bsc);
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
.right {
|
||||
svg {
|
||||
fill: var(--l-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
@@ -189,6 +208,10 @@
|
||||
fill: var(--l-c-3);
|
||||
}
|
||||
}
|
||||
&.last-tip {
|
||||
color: var(--l-fc-1);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +241,9 @@
|
||||
background-color: var(--l-c-2);
|
||||
color: var(--l-fc-3);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
@@ -263,7 +289,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.view, .shortcut, .site{
|
||||
.view, .search, .shortcut, .site{
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
@@ -313,4 +339,8 @@
|
||||
background-color: var(--l-bgc-1);
|
||||
}
|
||||
}
|
||||
.history{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-checkbox{
|
||||
color: var(--p-fc-1);
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--p-fc-2);
|
||||
.tHeader{
|
||||
border-bottom-color: var(--p-c-3);
|
||||
.btn{
|
||||
&:hover{
|
||||
color: var(--p-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--p-c-3);
|
||||
ul{
|
||||
@@ -101,6 +112,9 @@
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
@@ -166,6 +180,11 @@
|
||||
box-shadow: var(--p-bsc);
|
||||
.title{
|
||||
color: var(--p-fc-1);
|
||||
.right {
|
||||
svg {
|
||||
fill: var(--p-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
@@ -189,6 +208,10 @@
|
||||
fill: var(--p-c-3);
|
||||
}
|
||||
}
|
||||
&.last-tip {
|
||||
color: var(--p-fc-1);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +241,9 @@
|
||||
background-color: var(--p-c-2);
|
||||
color: var(--p-fc-3);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
@@ -263,7 +289,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.view, .shortcut, .site{
|
||||
.view, .search, .shortcut, .site{
|
||||
.title{
|
||||
color: var(--p-fc-1);
|
||||
}
|
||||
@@ -313,4 +339,8 @@
|
||||
background-color: var(--p-bgc-1);
|
||||
}
|
||||
}
|
||||
.history{
|
||||
background-color: var(--p-bgc-1);
|
||||
box-shadow: var(--p-bsc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// 允许跨域
|
||||
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')
|
||||
|
||||
let win
|
||||
let mini
|
||||
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
<path d="M12,21 L10.55,19.7051771 C5.4,15.1242507 2,12.1029973 2,8.39509537 C2,5.37384196 4.42,3 7.5,3 C9.24,3 10.91,3.79455041 12,5.05013624 C13.09,3.79455041 14.76,3 16.5,3 C19.58,3 22,5.37384196 22,8.39509537 C22,12.1029973 18.6,15.1242507 13.45,19.7149864 L12,21 Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span :class="[view === 'History' ? 'active ': ''] + 'zy-svg'" @click="changeView('History')">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="timeIconTitle">
|
||||
<title id="timeIconTitle">历史记录</title>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<polyline points="12 5 12 12 16 16"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
<span :class="[view === 'Setting' ? 'active ': ''] + 'zy-svg'" @click="changeView('Setting')">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="settingsIconTitle">
|
||||
<title id="settingsIconTitle">setting</title>
|
||||
|
||||
@@ -121,9 +121,9 @@ export default {
|
||||
playEvent (n) {
|
||||
history.find({ site: this.detail.key, ids: this.detail.info.id }).then(res => {
|
||||
if (res) {
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: n } }
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: n, site: this.detail.site } }
|
||||
} else {
|
||||
this.video = { key: this.detail.key, info: { id: this.detail.info.id, name: this.detail.info.name, index: n } }
|
||||
this.video = { key: this.detail.key, info: { id: this.detail.info.id, name: this.detail.info.name, index: n, site: this.detail.site } }
|
||||
}
|
||||
})
|
||||
|
||||
@@ -131,18 +131,22 @@ export default {
|
||||
this.detail.show = false
|
||||
},
|
||||
starEvent () {
|
||||
star.find({ site: this.detail.key, ids: this.info.id }).then(res => {
|
||||
star.find({ key: this.detail.key, ids: this.info.id }).then(res => {
|
||||
const docs = {
|
||||
key: this.detail.site.key,
|
||||
site: this.detail.site,
|
||||
ids: this.info.id,
|
||||
name: this.info.name,
|
||||
type: this.info.type,
|
||||
year: this.info.year,
|
||||
last: this.info.last,
|
||||
note: this.info.note
|
||||
}
|
||||
if (res) {
|
||||
this.$message.info('已存在')
|
||||
star.update(res.id, docs).then(res => {
|
||||
this.$message.success('已存在,更新成功')
|
||||
})
|
||||
} else {
|
||||
const docs = {
|
||||
site: this.detail.key,
|
||||
ids: this.info.id,
|
||||
name: this.info.name,
|
||||
type: this.info.type,
|
||||
year: this.info.year,
|
||||
last: this.info.last
|
||||
}
|
||||
star.add(docs).then(res => {
|
||||
this.$message.success('收藏成功')
|
||||
})
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="zy-select" @mouseleave="show.classList = false" v-if="show.class">
|
||||
<div class="zy-select" @mouseleave="show.classList = false" v-show="show.class">
|
||||
<div class="vs-placeholder" @click="show.classList = true">{{type.name}}</div>
|
||||
<div class="vs-options" v-show="show.classList">
|
||||
<ul class="zy-scroll" style="max-height: 600px;">
|
||||
@@ -18,10 +18,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="zy-select" @mouseleave="show.search = false">
|
||||
<div class="vs-input" @click="show.search = true"><input v-model.trim="searchTxt" type="text" placeholder="搜索" @keyup.enter="searchEvent"></div>
|
||||
<div class="vs-input" @click="show.search = true"><input v-model.trim="searchTxt" type="text" placeholder="搜索" @keyup.enter="searchEvent(searchTxt)"></div>
|
||||
<div class="vs-options" v-show="show.search">
|
||||
<ul class="zy-scroll" style="max-height: 600px">
|
||||
<li v-for="(i, j) in searchList" :key="j" @click="searchClickEvent(i)">{{i.keywords}}</li>
|
||||
<li v-for="(i, j) in searchList" :key="j" @click="searchEvent(i.keywords)">{{i.keywords}}</li>
|
||||
<li v-show="searchList.length >= 1" @click="clearSearch">清空历史记录</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -37,16 +37,16 @@
|
||||
<template slot="item" slot-scope="props">
|
||||
<div class="card">
|
||||
<div class="img">
|
||||
<img style="width: 100%" :src="props.data.pic" alt="" @load="$refs.waterfall.refresh()" @click="detailEvent(props.data)">
|
||||
<img style="width: 100%" :src="props.data.pic" alt="" @load="$refs.waterfall.refresh()" @click="detailEvent(site, props.data)">
|
||||
<div class="operate">
|
||||
<div class="operate-wrap">
|
||||
<span class="o-play" @click="playEvent(props.data)">播放</span>
|
||||
<span class="o-star" @click="starEvent(props.data)">收藏</span>
|
||||
<span class="o-share" @click="shareEvent(props.data)">分享</span>
|
||||
<span class="o-play" @click="playEvent(site, props.data)">播放</span>
|
||||
<span class="o-star" @click="starEvent(site, props.data)">收藏</span>
|
||||
<span class="o-share" @click="shareEvent(site, props.data)">分享</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name" @click="detailEvent(props.data)">{{props.data.name}}</div>
|
||||
<div class="name" @click="detailEvent(site, props.data)">{{props.data.name}}</div>
|
||||
<div class="info">
|
||||
<span>{{props.data.year}}</span>
|
||||
<span>{{props.data.type}}</span>
|
||||
@@ -60,16 +60,16 @@
|
||||
<div class="zy-table">
|
||||
<div class="tBody">
|
||||
<ul>
|
||||
<li v-for="(i, j) in list" :key="j" @click="detailEvent(i)">
|
||||
<li v-for="(i, j) in list" :key="j" @click="detailEvent(site, i)">
|
||||
<span class="name">{{i.name}}</span>
|
||||
<span class="type">{{i.type}}</span>
|
||||
<span class="time">{{i.year}}</span>
|
||||
<span class="last">{{i.last}}</span>
|
||||
<span class="operate">
|
||||
<span class="btn" @click.stop="playEvent(i)">播放</span>
|
||||
<span class="btn" @click.stop="starEvent(i)">收藏</span>
|
||||
<span class="btn" @click.stop="shareEvent(i)">分享</span>
|
||||
<span class="btn" @click.stop="downloadEvent(i)">下载</span>
|
||||
<span class="btn" @click.stop="playEvent(site, i)">播放</span>
|
||||
<span class="btn" @click.stop="starEvent(site, i)">收藏</span>
|
||||
<span class="btn" @click.stop="shareEvent(site, i)">分享</span>
|
||||
<span class="btn" @click.stop="downloadEvent(site, i)">下载</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -81,18 +81,19 @@
|
||||
<div class="body-box" v-show="show.find">
|
||||
<div class="show-table">
|
||||
<div class="zy-table">
|
||||
<div class="tBody">
|
||||
<div class="tBody zy-scroll">
|
||||
<ul>
|
||||
<li v-for="(i, j) in searchContents" :key="j" @click="detailEvent(i)">
|
||||
<li v-for="(i, j) in searchContents" :key="j" @click="detailEvent(i.site, i)">
|
||||
<span class="name">{{i.name}}</span>
|
||||
<span class="type">{{i.type}}</span>
|
||||
<span class="time">{{i.year}}</span>
|
||||
<span class="last">{{i.last}}</span>
|
||||
<span class="site">{{i.site.name}}</span>
|
||||
<span class="note">{{i.note}}</span>
|
||||
<span class="operate">
|
||||
<span class="btn" @click.stop="playEvent(i)">播放</span>
|
||||
<span class="btn" @click.stop="starEvent(i)">收藏</span>
|
||||
<span class="btn" @click.stop="shareEvent(i)">分享</span>
|
||||
<span class="btn" @click.stop="downloadEvent(i)">下载</span>
|
||||
<span class="btn" @click.stop="playEvent(i.site, i)">播放</span>
|
||||
<span class="btn" @click.stop="starEvent(i.site, i)">收藏</span>
|
||||
<span class="btn" @click.stop="shareEvent(i.site, i)">分享</span>
|
||||
<span class="btn" @click.stop="downloadEvent(i.site, i)">下载</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -199,7 +200,7 @@ export default {
|
||||
this.show.site = false
|
||||
this.show.class = false
|
||||
if (this.searchTxt.length > 0) {
|
||||
this.searchEvent()
|
||||
this.searchSingleSiteEvent(this.site, this.searchTxt)
|
||||
} else {
|
||||
this.classList = []
|
||||
this.type = {}
|
||||
@@ -275,35 +276,38 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
detailEvent (e) {
|
||||
detailEvent (site, e) {
|
||||
this.detail = {
|
||||
show: true,
|
||||
key: this.site.key,
|
||||
key: site.key,
|
||||
site: site,
|
||||
info: e
|
||||
}
|
||||
},
|
||||
playEvent (e) {
|
||||
history.find({ site: this.site.key, ids: e.id }).then(res => {
|
||||
playEvent (site, e) {
|
||||
history.find({ site: site.key, ids: e.id }).then(res => {
|
||||
if (res) {
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: res.index } }
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: res.index, site: site } }
|
||||
} else {
|
||||
this.video = { key: this.site.key, info: { id: e.id, name: e.name, index: 0 } }
|
||||
this.video = { key: site.key, info: { id: e.id, name: e.name, index: 0, site: site } }
|
||||
}
|
||||
})
|
||||
this.view = 'Play'
|
||||
},
|
||||
starEvent (e) {
|
||||
star.find({ site: this.site.key, ids: e.id }).then(res => {
|
||||
starEvent (site, e) {
|
||||
star.find({ key: site.key, ids: e.id }).then(res => {
|
||||
if (res) {
|
||||
this.$message.info('已存在')
|
||||
} else {
|
||||
const docs = {
|
||||
site: this.site.key,
|
||||
key: site.key,
|
||||
site: site,
|
||||
ids: e.id,
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
year: e.year,
|
||||
last: e.last
|
||||
last: e.last,
|
||||
note: e.note
|
||||
}
|
||||
star.add(docs).then(res => {
|
||||
this.$message.success('收藏成功')
|
||||
@@ -313,16 +317,16 @@ export default {
|
||||
this.$message.warning('收藏失败')
|
||||
})
|
||||
},
|
||||
shareEvent (e) {
|
||||
shareEvent (site, e) {
|
||||
this.share = {
|
||||
show: true,
|
||||
key: this.site.key,
|
||||
key: site.key,
|
||||
info: e
|
||||
}
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(this.site.key, e.id).then(res => {
|
||||
if (res) {
|
||||
downloadEvent (site, e) {
|
||||
zy.download(site.key, e.id).then(res => {
|
||||
if (res.length > 0) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
const list = text.split('#')
|
||||
@@ -337,9 +341,20 @@ export default {
|
||||
this.$message.warning('没有查询到下载链接.')
|
||||
}
|
||||
} else {
|
||||
const list = [...this.m3u8List]
|
||||
let 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('#')
|
||||
}
|
||||
let downloadUrl = e.name + '\n'
|
||||
for (const i of list) {
|
||||
for (const i of m3u8List) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
@@ -365,8 +380,8 @@ export default {
|
||||
this.searchList = res.reverse()
|
||||
})
|
||||
},
|
||||
searchEvent () {
|
||||
const wd = this.searchTxt
|
||||
searchAllSitesEvent (sites, wd) {
|
||||
this.searchTxt = wd
|
||||
this.searchContents = []
|
||||
this.pagecount = 0
|
||||
this.show.search = false
|
||||
@@ -378,18 +393,24 @@ export default {
|
||||
}
|
||||
this.getAllSearch()
|
||||
})
|
||||
zy.search(this.site.key, wd).then(res => {
|
||||
const type = Object.prototype.toString.call(res)
|
||||
if (type === '[object Undefined]') {
|
||||
this.$message.info('无搜索结果')
|
||||
}
|
||||
if (type === '[object Array]') {
|
||||
this.searchContents.push(...res)
|
||||
}
|
||||
if (type === '[object Object]') {
|
||||
this.searchContents.push(res)
|
||||
}
|
||||
})
|
||||
sites.forEach(site =>
|
||||
zy.search(site.key, wd).then(res => {
|
||||
const type = Object.prototype.toString.call(res)
|
||||
if (type === '[object Undefined]') {
|
||||
this.$message.info(site.name + ' 无搜索结果')
|
||||
}
|
||||
if (type === '[object Array]') {
|
||||
res.forEach(element => {
|
||||
element.site = site
|
||||
this.searchContents.push(element)
|
||||
})
|
||||
}
|
||||
if (type === '[object Object]') {
|
||||
res.site = site
|
||||
this.searchContents.push(res)
|
||||
}
|
||||
})
|
||||
)
|
||||
} else {
|
||||
this.show.find = false
|
||||
this.getClass().then(res => {
|
||||
@@ -399,28 +420,17 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
searchClickEvent (e) {
|
||||
this.searchContents = []
|
||||
this.pagecount = 0
|
||||
this.searchTxt = e.keywords
|
||||
this.show.search = false
|
||||
this.show.find = true
|
||||
search.remove(e.id).then(res => {
|
||||
search.add({ keywords: e.keywords })
|
||||
this.getAllSearch()
|
||||
})
|
||||
zy.search(this.site.key, e.keywords).then(res => {
|
||||
const type = Object.prototype.toString.call(res)
|
||||
if (type === '[object Undefined]') {
|
||||
this.$message.info('无搜索结果')
|
||||
}
|
||||
if (type === '[object Array]') {
|
||||
this.searchContents.push(...res)
|
||||
}
|
||||
if (type === '[object Object]') {
|
||||
this.searchContents.push(res)
|
||||
}
|
||||
})
|
||||
searchEvent (wd) {
|
||||
if (this.setting.searchAllSites) {
|
||||
this.searchAllSitesEvent(this.sites, wd)
|
||||
} else {
|
||||
this.searchSingleSiteEvent(this.site, wd)
|
||||
}
|
||||
},
|
||||
searchSingleSiteEvent (site, wd) {
|
||||
var sites = []
|
||||
sites.push(this.site)
|
||||
this.searchAllSitesEvent(sites, wd)
|
||||
},
|
||||
clearSearch () {
|
||||
search.clear().then(res => {
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
<template>
|
||||
<div class="frame">
|
||||
<span class="min" @click="frameClickEvent('min')"></span>
|
||||
<span class="max" @click="frameClickEvent('max')"></span>
|
||||
<span class="close" @click="frameClickEvent('close')"></span>
|
||||
<span class="top" @click="frameClickEvent('top')" title="置顶">
|
||||
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:10px;height:14px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
|
||||
</span>
|
||||
<span class="min" @click="frameClickEvent('min')" title="最小化">
|
||||
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:8px;height:14px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="max" @click="frameClickEvent('max')" title="最大化">
|
||||
<svg t="1595917343956" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1540" style="width:8px;height:14px"><path d="M416 416 64.064 416C28.448 416 0 444.64 0 479.936L0 544.064C0 579.264 28.672 608 64.064 608L416 608 416 959.936C416 995.552 444.64 1024 479.936 1024L544.064 1024C579.264 1024 608 995.328 608 959.936L608 608 959.936 608C995.552 608 1024 579.36 1024 544.064L1024 479.936C1024 444.736 995.328 416 959.936 416L608 416 608 64.064C608 28.448 579.36 0 544.064 0L479.936 0C444.736 0 416 28.672 416 64.064L416 416Z" p-id="1541" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="close" @click="frameClickEvent('close')" title="关闭">
|
||||
<svg t="1595917372551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" style="width:8px;height:14px"><path d="M511.968 376.224 796.096 92.096C833.536 54.624 894.4 54.624 931.84 92.096 969.312 129.568 969.312 190.4 931.84 227.872L647.744 512 931.84 796.096C969.312 833.568 969.312 894.4 931.84 931.872 894.4 969.344 833.536 969.344 796.096 931.872L511.968 647.744 227.84 931.872C190.4 969.344 129.536 969.344 92.096 931.872 54.624 894.4 54.624 833.568 92.096 796.096L376.224 512 92.096 227.872C54.624 190.4 54.624 129.568 92.096 92.096 129.536 54.624 190.4 54.624 227.84 92.096L511.968 376.224Z" p-id="1686" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const { remote } = require('electron')
|
||||
export default {
|
||||
name: 'frame',
|
||||
data () {
|
||||
const win = remote.getCurrentWindow()
|
||||
return {
|
||||
isAlwaysOnTop: win.isAlwaysOnTop()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
frameClickEvent (e) {
|
||||
const win = remote.getCurrentWindow()
|
||||
@@ -21,6 +36,10 @@ export default {
|
||||
if (e === 'close') {
|
||||
win.destroy()
|
||||
}
|
||||
if (e === 'top') {
|
||||
this.isAlwaysOnTop = !this.isAlwaysOnTop
|
||||
win.setAlwaysOnTop(this.isAlwaysOnTop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +59,8 @@ export default {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
display: inline-block;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
191
src/components/History.vue
Normal file
191
src/components/History.vue
Normal file
@@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div class="history">
|
||||
<div class="body zy-scroll">
|
||||
<div class="zy-table">
|
||||
<div class="tHeader">
|
||||
<span class="btn" @click="clearAllHistory">清空</span>
|
||||
</div>
|
||||
<div class="tBody zy-scroll">
|
||||
<ul>
|
||||
<li v-show="this.history.length === 0">无数据</li>
|
||||
<li v-for="(i, j) in history" :key="j" @click="historyItemEvent(i)">
|
||||
<span class="name" @click.stop="playEvent(i)">{{i.name}}</span>
|
||||
<span class="site">{{getSiteName(i.site)}}</span>
|
||||
<span class="note">第{{i.index+1}}集</span>
|
||||
<span class="operate">
|
||||
<span class="btn" @click.stop="playEvent(i)">播放</span>
|
||||
<span class="btn" @click.stop="downloadEvent(i)">下载</span>
|
||||
<span class="btn" @click.stop="removeHistoryItem(i)">删除</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { history, sites } from '../lib/dexie'
|
||||
import zy from '../lib/site/tools'
|
||||
const { clipboard } = require('electron')
|
||||
export default {
|
||||
name: 'history',
|
||||
data () {
|
||||
return {
|
||||
history: history,
|
||||
sites: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
view: {
|
||||
get () {
|
||||
return this.$store.getters.getView
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIEW(val)
|
||||
}
|
||||
},
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
get () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
set (val) {
|
||||
this.SET_DETAIL(val)
|
||||
}
|
||||
},
|
||||
share: {
|
||||
get () {
|
||||
return this.$store.getters.getShare
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SHARE(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
view () {
|
||||
this.getAllhistory()
|
||||
this.getAllsites()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||
detailEvent (e) {
|
||||
this.detail = {
|
||||
show: true,
|
||||
key: e.site,
|
||||
info: {
|
||||
id: e.ids,
|
||||
name: e.name
|
||||
}
|
||||
}
|
||||
},
|
||||
playEvent (e) {
|
||||
history.find({ site: e.site, ids: e.ids }).then(res => {
|
||||
if (res) {
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: res.index } }
|
||||
} else {
|
||||
this.video = { key: e.site, info: { id: e.ids, name: e.name, index: 0 } }
|
||||
}
|
||||
})
|
||||
this.view = 'Play'
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(e.site, e.ids).then(res => {
|
||||
if (res) {
|
||||
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('没有查询到下载链接.')
|
||||
}
|
||||
} else {
|
||||
const list = [...this.m3u8List]
|
||||
let downloadUrl = ''
|
||||
for (const i of list) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
downloadUrl += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(downloadUrl)
|
||||
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
|
||||
}
|
||||
})
|
||||
},
|
||||
clearAllHistory () {
|
||||
history.clear().then(res => {
|
||||
this.history = []
|
||||
})
|
||||
},
|
||||
getAllhistory () {
|
||||
history.all().then(res => {
|
||||
this.history = res.reverse()
|
||||
})
|
||||
},
|
||||
getAllsites () {
|
||||
sites.all().then(res => {
|
||||
this.sites = res
|
||||
})
|
||||
},
|
||||
getSiteName (key) {
|
||||
var site = this.sites.find(e => e.key === key)
|
||||
if (site) {
|
||||
return site.name
|
||||
}
|
||||
},
|
||||
historyItemEvent (e) {
|
||||
this.video = {
|
||||
key: e.site,
|
||||
info: {
|
||||
id: e.ids,
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
year: e.year,
|
||||
index: e.index,
|
||||
time: e.time
|
||||
}
|
||||
}
|
||||
},
|
||||
removeHistoryItem (e) {
|
||||
history.remove(e.id).then(res => {
|
||||
this.getAllhistory()
|
||||
}).catch(err => {
|
||||
this.$message.warning('删除历史记录失败, 错误信息: ' + err)
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getAllhistory()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.history{
|
||||
position: relative;
|
||||
height: calc(100% - 40px);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
.body{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,6 +3,17 @@
|
||||
<div class="box">
|
||||
<div class="title">
|
||||
<span v-if="this.right.list.length > 1">『第 {{(video.info.index + 1)}} 集』</span>{{name}}
|
||||
<span v-if="video.key" class="right" @click="playWithExternalPalyerEvent" title="使用第三方播放器">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<polygon points="20 8 20 20 4 20 4 8"></polygon>
|
||||
<polyline stroke-linejoin="round" points="8 4 12 7.917 16 4"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
<span v-if="video.key" class="right" @click="issueEvent" title="复制调试信息">
|
||||
<svg t="1596338860607" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3127" width="24" height="24">
|
||||
<path d="M503.803829 63.578014c-247.050676 0-447.328072 200.277396-447.328072 447.327048 0 247.054769 200.277396 447.333188 447.328072 447.333188 247.054769 0 447.332165-200.278419 447.332165-447.333188C951.13497 263.85541 750.858598 63.578014 503.803829 63.578014L503.803829 63.578014zM503.803829 894.313336c-211.749682 0-383.408273-171.659615-383.408273-383.408273 0-211.749682 171.659615-383.40725 383.408273-383.40725 211.753775 0 383.412366 171.658591 383.412366 383.40725C887.216195 722.653721 715.557604 894.313336 503.803829 894.313336L503.803829 894.313336zM447.745069 255.897158l127.914298 0L575.659367 383.576095 447.745069 383.576095 447.745069 255.897158 447.745069 255.897158zM447.745069 425.470251l127.914298 0 0 342.058516L447.745069 767.528767 447.745069 425.470251 447.745069 425.470251zM447.745069 425.470251" p-id="3128"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="player">
|
||||
<div id="xgplayer"></div>
|
||||
@@ -70,6 +81,7 @@
|
||||
<rect x="17" y="6" width="1" height="1"></rect>
|
||||
</svg>
|
||||
</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>
|
||||
<transition name="slideX">
|
||||
@@ -85,13 +97,14 @@
|
||||
</div>
|
||||
<div class="list-body zy-scroll" :style="{overflowY:scroll? 'auto' : 'hidden',paddingRight: scroll ? '0': '5px' }" @mouseenter="scroll = true" @mouseleave="scroll = false">
|
||||
<ul v-show="right.type === 'list'" class="list-item">
|
||||
<li v-show="right.list.length > 0" @click="exportM3u8">导出</li>
|
||||
<li v-show="right.list.length === 0">无数据</li>
|
||||
<li @click="listItemEvent(j)" :class="video.info.index === j ? 'active' : ''" v-for="(i, j) in right.list" :key="j">{{i | ftName(j)}}</li>
|
||||
</ul>
|
||||
<ul v-show="right.type === 'history'" class="list-history">
|
||||
<li v-show="right.history.length > 1" @click="clearAllHistory">清空</li>
|
||||
<li v-show="right.history.length > 0" @click="clearAllHistory">清空</li>
|
||||
<li v-show="right.history.length === 0">无数据</li>
|
||||
<li @click="historyItemEvent(m)" :class="video.info.id === m.ids ? 'active' : ''" v-for="(m, n) in right.history" :key="n"><span class="title">{{m.name}}</span><span @click.stop="removeHistoryItem(m)" class="detail-delete">删除</span></li>
|
||||
<li @click="historyItemEvent(m)" :class="video.info.id === m.ids ? 'active' : ''" v-for="(m, n) in right.history" :key="n"><span class="title" :title="'【' + m.site + '】' + m.name + ' 第' + (m.index+1) + '集'">【{{m.site}}】{{m.name}} 第{{m.index+1}}集</span><span @click.stop="removeHistoryItem(m)" class="detail-delete">删除</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,10 +115,53 @@
|
||||
import { mapMutations } from 'vuex'
|
||||
import { star, history, setting, shortcut, mini } from '../lib/dexie'
|
||||
import zy from '../lib/site/tools'
|
||||
import 'xgplayer'
|
||||
import Player from 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
import mt from 'mousetrap'
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
const { remote, ipcRenderer, clipboard } = require('electron')
|
||||
|
||||
const VIDEO_DETAIL_CACHE = {}
|
||||
|
||||
const addPlayerBtn = function (event, svg, attrs) {
|
||||
const player = this
|
||||
const util = Player.util
|
||||
const controlEl = player.controls
|
||||
const btnConfig = player.config[event]
|
||||
if (btnConfig) {
|
||||
const btnName = 'xg-btn-' + event
|
||||
const btn = util.createDom(btnName, svg || btnConfig.svg, attrs || {}, btnName)
|
||||
controlEl.appendChild(btn)
|
||||
const ev = ['click', 'touchend']
|
||||
ev.forEach(item => {
|
||||
btn.addEventListener(item, function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
player.emit(event)
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const addPlayerView = function (event, tpl, attrs) {
|
||||
const player = this
|
||||
const util = Player.util
|
||||
const rootEl = player.root
|
||||
const viewConfig = player.config[event]
|
||||
if (viewConfig) {
|
||||
const viewName = 'xg-view-' + event
|
||||
const view = util.createDom(viewName, tpl, attrs || {}, viewName)
|
||||
rootEl.appendChild(view)
|
||||
const ev = ['click', 'touchend']
|
||||
ev.forEach(item => {
|
||||
view.addEventListener(item, function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
player.emit(event)
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'play',
|
||||
data () {
|
||||
@@ -130,7 +186,16 @@ export default {
|
||||
crossOrigin: true,
|
||||
cssFullscreen: true,
|
||||
defaultPlaybackRate: 1,
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5]
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5],
|
||||
playPrev: true,
|
||||
playNextOne: true,
|
||||
showList: true,
|
||||
showHistory: true,
|
||||
videoTitle: true
|
||||
},
|
||||
state: {
|
||||
showList: false,
|
||||
showHistory: false
|
||||
},
|
||||
name: '',
|
||||
length: 0,
|
||||
@@ -205,6 +270,17 @@ export default {
|
||||
this.changeSetting()
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
name () {
|
||||
const span = document.querySelector('.xg-view-videoTitle span')
|
||||
if (!span) {
|
||||
return
|
||||
}
|
||||
if (this.right.list.length > 1) {
|
||||
span.innerText = `『第 ${this.video.info.index + 1} 集』${this.name}`
|
||||
} else {
|
||||
span.innerText = `${this.name}`
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -234,36 +310,7 @@ export default {
|
||||
})
|
||||
},
|
||||
playVideo (index = 0, time = 0) {
|
||||
const id = this.video.info.id
|
||||
zy.detail(this.video.key, id).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._t.indexOf('m3u8') >= 0) {
|
||||
m3u8Txt = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Txt = dd._t.split('#')
|
||||
}
|
||||
this.right.list = m3u8Txt
|
||||
const m3u8Arr = []
|
||||
for (const i of m3u8Txt) {
|
||||
const j = i.split('$')
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('m3u8') >= 0) {
|
||||
m3u8Arr.push(j[m])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
|
||||
this.fetchM3u8List().then(m3u8Arr => {
|
||||
this.xg.src = m3u8Arr[index]
|
||||
this.showNext = m3u8Arr.length > 1
|
||||
|
||||
@@ -286,6 +333,52 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchM3u8List () {
|
||||
return new Promise((resolve) => {
|
||||
const cacheKey = this.video.key + '@' + this.video.info.id
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey]) {
|
||||
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
|
||||
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
|
||||
return
|
||||
}
|
||||
zy.detail(this.video.key, this.video.info.id).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
for (const i of dd) {
|
||||
if (i._t.indexOf('m3u8') >= 0) {
|
||||
m3u8Txt = i._t.split('#')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Txt = dd._t.split('#')
|
||||
}
|
||||
this.right.list = m3u8Txt
|
||||
const m3u8Arr = []
|
||||
for (const i of m3u8Txt) {
|
||||
const j = i.split('$')
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
|
||||
m3u8Arr.push(j[m])
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = {
|
||||
list: m3u8Arr,
|
||||
name: res.name
|
||||
}
|
||||
resolve(m3u8Arr)
|
||||
})
|
||||
})
|
||||
},
|
||||
videoPlaying () {
|
||||
this.changeVideo()
|
||||
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
|
||||
@@ -365,9 +458,7 @@ export default {
|
||||
this.right.show = true
|
||||
this.right.type = 'history'
|
||||
}
|
||||
history.all().then(res => {
|
||||
this.right.history = res.reverse()
|
||||
})
|
||||
this.getAllhistory()
|
||||
},
|
||||
getAllhistory () {
|
||||
history.all().then(res => {
|
||||
@@ -376,20 +467,19 @@ export default {
|
||||
},
|
||||
starEvent () {
|
||||
const info = this.video.info
|
||||
star.find({ site: this.video.key, ids: info.id }).then(res => {
|
||||
star.find({ key: this.video.key, ids: info.id }).then(res => {
|
||||
if (res) {
|
||||
star.remove(res.id).then(e => {
|
||||
this.$message.info('取消收藏')
|
||||
this.isStar = false
|
||||
})
|
||||
this.$message.info('已存在')
|
||||
} else {
|
||||
const docs = {
|
||||
site: this.video.key,
|
||||
key: this.video.key,
|
||||
site: this.video.site,
|
||||
ids: info.id,
|
||||
name: info.name,
|
||||
type: info.type,
|
||||
year: info.year,
|
||||
last: info.last
|
||||
last: info.last,
|
||||
note: info.note
|
||||
}
|
||||
star.add(docs).then(res => {
|
||||
this.$message.success('收藏成功')
|
||||
@@ -439,6 +529,31 @@ export default {
|
||||
info: this.video.info
|
||||
}
|
||||
},
|
||||
issueEvent () {
|
||||
const info = {
|
||||
video: this.video,
|
||||
list: this.right.list,
|
||||
m3u8List: VIDEO_DETAIL_CACHE[this.video.key + '@' + this.video.info.id] || [],
|
||||
playerError: this.xg.error || '',
|
||||
playerState: this.xg.readyState || '',
|
||||
networkState: this.xg.networkState || ''
|
||||
}
|
||||
clipboard.writeText(JSON.stringify(info, null, 4))
|
||||
this.$message.success('视频信息复制成功')
|
||||
},
|
||||
playWithExternalPalyerEvent () {
|
||||
this.fetchM3u8List().then(m3u8Arr => {
|
||||
var m3u8Link = m3u8Arr[this.video.info.index]
|
||||
const fs = require('fs')
|
||||
var externalPlayer = this.setting.externalPlayer
|
||||
if (fs.existsSync(externalPlayer)) {
|
||||
var exec = require('child_process').execFile
|
||||
exec(externalPlayer, [m3u8Link])
|
||||
} else {
|
||||
this.$message.error('请设置第三方播放器路径')
|
||||
}
|
||||
})
|
||||
},
|
||||
checkStar () {
|
||||
star.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
|
||||
if (res) {
|
||||
@@ -456,6 +571,42 @@ export default {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
exportM3u8 () {
|
||||
const m3u8Arr = []
|
||||
for (const i of this.right.list) {
|
||||
const j = i.split('$')
|
||||
let link, name
|
||||
if (j.length > 1) {
|
||||
for (let m = 0; m < j.length; m++) {
|
||||
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
|
||||
link = j[m]
|
||||
break
|
||||
}
|
||||
}
|
||||
name = j[0]
|
||||
} else {
|
||||
name = `第${m3u8Arr.length + 1}集`
|
||||
link = j[0]
|
||||
}
|
||||
m3u8Arr.push({
|
||||
name: name,
|
||||
link: link
|
||||
})
|
||||
}
|
||||
let m3u8Content = '#EXTM3U'
|
||||
for (const item of m3u8Arr) {
|
||||
m3u8Content += `#EXTINF:-1, ${item.name}\n${item.link}`
|
||||
}
|
||||
const blob = new Blob([m3u8Content], { type: 'application/vnd.apple.mpegurl' })
|
||||
const downloadElement = document.createElement('a')
|
||||
const href = window.URL.createObjectURL(blob)
|
||||
downloadElement.href = href
|
||||
downloadElement.download = `${this.name}.m3u8`
|
||||
document.body.appendChild(downloadElement)
|
||||
downloadElement.click()
|
||||
document.body.removeChild(downloadElement)
|
||||
window.URL.revokeObjectURL(href)
|
||||
},
|
||||
clearAllHistory () {
|
||||
history.clear().then(res => {
|
||||
this.right.history = []
|
||||
@@ -570,8 +721,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'escape') {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
if (this.xg.fullscreen) {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'next') {
|
||||
@@ -636,6 +789,134 @@ export default {
|
||||
},
|
||||
changeSetting () {
|
||||
this.mtEvent()
|
||||
},
|
||||
toggleList () {
|
||||
if (this.state.showList) {
|
||||
document.querySelector('xg-btn-showlist ul').style.display = 'none'
|
||||
this.state.showList = false
|
||||
} else {
|
||||
this.refreshList()
|
||||
document.querySelector('xg-btn-showlist ul').style.display = 'block'
|
||||
this.state.showList = true
|
||||
}
|
||||
},
|
||||
refreshList () {
|
||||
let ul = document.querySelector('xg-btn-showlist ul')
|
||||
if (!ul) {
|
||||
ul = document.createElement('ul')
|
||||
document.querySelector('xg-btn-showlist').appendChild(ul)
|
||||
ul.addEventListener('click', (ev) => {
|
||||
ev = ev || window.event
|
||||
const target = ev.target || ev.srcElement // target表示在事件冒泡中触发事件的源元素,在IE中是srcElement
|
||||
if (target.nodeName.toLowerCase() === 'li') {
|
||||
this.listItemEvent(parseInt(target.dataset.index))
|
||||
}
|
||||
})
|
||||
}
|
||||
ul.style.display = 'none'
|
||||
let li = ''
|
||||
if (this.right.list.length === 0) {
|
||||
li = '<li>无数据</li>'
|
||||
} else {
|
||||
for (let index = 0; index < this.right.list.length; index++) {
|
||||
const item = this.right.list[index]
|
||||
const num = item.split('$')
|
||||
let title
|
||||
if (num.length > 1) {
|
||||
title = num[0]
|
||||
} else {
|
||||
title = `第${(index + 1)}集`
|
||||
}
|
||||
if (index === this.video.info.index) {
|
||||
li += `<li class="selected" data-index="${index}" title="${title}">${title}</li>`
|
||||
} else {
|
||||
li += `<li data-index="${index}" title="${title}">${title}</li>`
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.innerHTML = li
|
||||
},
|
||||
toggleHistory () {
|
||||
if (this.state.showHistory) {
|
||||
document.querySelector('xg-btn-showhistory ul').style.display = 'none'
|
||||
this.state.showHistory = false
|
||||
} else {
|
||||
this.refreshHistory()
|
||||
document.querySelector('xg-btn-showhistory ul').style.display = 'block'
|
||||
this.state.showHistory = true
|
||||
}
|
||||
},
|
||||
refreshHistory () {
|
||||
this.getAllhistory()
|
||||
let ul = document.querySelector('xg-btn-showhistory ul')
|
||||
if (!ul) {
|
||||
ul = document.createElement('ul')
|
||||
document.querySelector('xg-btn-showhistory').appendChild(ul)
|
||||
ul.addEventListener('click', (ev) => {
|
||||
ev = ev || window.event
|
||||
const target = ev.target || ev.srcElement // target表示在事件冒泡中触发事件的源元素,在IE中是srcElement
|
||||
if (target.nodeName.toLowerCase() === 'li') {
|
||||
this.historyItemEvent(this.right.history[parseInt(target.dataset.index)])
|
||||
}
|
||||
})
|
||||
}
|
||||
ul.style.display = 'none'
|
||||
let li = ''
|
||||
if (this.right.history.length === 0) {
|
||||
li = '<li>无数据</li>'
|
||||
} else {
|
||||
window.historyItemEvent = this.historyItemEvent.bind(this)
|
||||
for (let index = 0; index < this.right.history.length; index++) {
|
||||
const item = this.right.history[index]
|
||||
const text = `【${item.site}】${item.name} 第${item.index + 1}集`
|
||||
if (this.video.info.id === item.ids) {
|
||||
li += `<li class="selected" data-index="${index}" title="${text}">${text}</li>`
|
||||
} else {
|
||||
li += `<li data-index="${index}" title="${text}">${text}</li>`
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.innerHTML = li
|
||||
},
|
||||
bindEvent () {
|
||||
this.xg.on('playNextOne', () => {
|
||||
this.nextEvent()
|
||||
})
|
||||
|
||||
this.xg.on('playPrev', () => {
|
||||
this.prevEvent()
|
||||
})
|
||||
|
||||
this.xg.on('showList', () => {
|
||||
this.toggleList()
|
||||
})
|
||||
|
||||
this.xg.on('showHistory', () => {
|
||||
this.toggleHistory()
|
||||
})
|
||||
|
||||
const ev = ['click', 'touchend', 'mousemove']
|
||||
let timerID
|
||||
ev.forEach(item => {
|
||||
this.xg.root.addEventListener(item, () => {
|
||||
if (!this.xg.fullscreen) {
|
||||
return
|
||||
}
|
||||
const videoTitle = document.querySelector('.xg-view-videoTitle')
|
||||
videoTitle.style.display = 'block'
|
||||
clearTimeout(timerID)
|
||||
timerID = setTimeout(() => {
|
||||
// 播放中自动消失
|
||||
if (this.xg && !this.xg.paused) {
|
||||
videoTitle.style.display = 'none'
|
||||
}
|
||||
}, 3000)
|
||||
})
|
||||
})
|
||||
|
||||
this.xg.on('exitFullscreen', () => {
|
||||
document.querySelector('.xg-view-videoTitle').style.display = 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
@@ -643,18 +924,179 @@ export default {
|
||||
this.mtEvent()
|
||||
},
|
||||
mounted () {
|
||||
Player.install('playPrev', function () {
|
||||
addPlayerBtn.bind(this, 'playPrev', '<svg t="1595866093990" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3657" style="width: 20px;height: 20px;margin-top: 11px;margin-left: 9px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M98.583851 3.180124h190.807453a31.801242 31.801242 0 0 1 31.801243 31.801242v387.021118L902.201242 10.176398l11.130435-7.632299A31.801242 31.801242 0 0 1 957.217391 31.801242v960.397516a31.801242 31.801242 0 0 1-43.885714 29.257143l-11.130435-7.632299L321.192547 601.997516V989.018634a31.801242 31.801242 0 0 1-31.801243 31.801242H98.583851a31.801242 31.801242 0 0 1-31.801242-31.801242v-954.037268a31.801242 31.801242 0 0 1 31.801242-31.801242z" p-id="3658" fill="#ffffff"></path></svg>', { title: '上一集' })()
|
||||
})
|
||||
Player.install('playNextOne', function () {
|
||||
addPlayerBtn.bind(this, 'playNextOne', '<svg t="1595866110378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3946" style="width: 20px;height: 20px;margin-top: 11px;margin-left: 0px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M925.416149 3.180124h-190.807453a31.801242 31.801242 0 0 0-31.801243 31.801242v387.021118L121.798758 10.176398 110.668323 2.544099A31.801242 31.801242 0 0 0 98.583851 0a31.801242 31.801242 0 0 0-31.801242 31.801242v960.397516a31.801242 31.801242 0 0 0 31.801242 31.801242 31.801242 31.801242 0 0 0 12.084472-2.544099l11.130435-7.632299L702.807453 601.997516V989.018634a31.801242 31.801242 0 0 0 31.801243 31.801242h190.807453a31.801242 31.801242 0 0 0 31.801242-31.801242v-954.037268a31.801242 31.801242 0 0 0-31.801242-31.801242z" p-id="3947" fill="#ffffff"></path></svg>', { title: '下一集' })()
|
||||
})
|
||||
Player.install('showList', function () {
|
||||
addPlayerBtn.bind(this, 'showList', '<svg t="1595866128681" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M0 0h1316.571429v146.285714H0zM0 438.857143h1316.571429v146.285714H0zM0 877.714286h1316.571429v146.285714H0z" p-id="4188" fill="#ffffff"></path></svg>', { title: '播放列表' })()
|
||||
})
|
||||
Player.install('showHistory', function () {
|
||||
addPlayerBtn.bind(this, 'showHistory', '<svg t="1595866015473" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3282" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m0 910.222222a398.222222 398.222222 0 1 1 398.222222-398.222222 398.222222 398.222222 0 0 1-398.222222 398.222222z" p-id="3283" fill="#ffffff"></path><path d="M568.888889 227.555556h-113.777778v341.333333h227.555556v-113.777778h-113.777778V227.555556z" p-id="3284" fill="#ffffff"></path></svg>', { title: '播放历史' })()
|
||||
})
|
||||
const that = this
|
||||
Player.install('videoTitle', function () {
|
||||
let title
|
||||
if (that.right.list.length > 1) {
|
||||
title = `『第 ${that.video.info.index + 1} 集』${that.name}`
|
||||
} else {
|
||||
title = `${that.name}`
|
||||
}
|
||||
addPlayerView.bind(this, 'videoTitle', `<span>${title}</span>`, {})()
|
||||
})
|
||||
|
||||
this.xg = new Hls(this.config)
|
||||
ipcRenderer.on('miniClosed', () => {
|
||||
this.xg.destroy()
|
||||
this.xg = new Hls(this.config)
|
||||
this.getUrls()
|
||||
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
|
||||
if (res) {
|
||||
if (this.video.info.index !== res.index) {
|
||||
this.video.info.index = res.index
|
||||
} else {
|
||||
this.getUrls()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
this.bindEvent()
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.xgplayer-skin-default .xg-btn-playPrev {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 0;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 0;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playPrev:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playNextOne {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 2;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 2;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-playNextOne:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-play, .xgplayer-skin-default .xgplayer-play-img {
|
||||
order: 1 !important;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 4;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 4;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showHistory {
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-webkit-order: 4;
|
||||
-moz-box-ordinal-group: 1;
|
||||
order: 4;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showHistory:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul, .xgplayer-skin-default .xg-btn-showHistory ul {
|
||||
display: none;
|
||||
list-style: none;
|
||||
min-width: 85px;
|
||||
max-width: 300px;
|
||||
max-height: 60vh;
|
||||
overflow-y: scroll;
|
||||
background: rgba(0,0,0,.54);
|
||||
border-radius: 1px;
|
||||
position: absolute;
|
||||
bottom: 45px;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
z-index: 26;
|
||||
cursor: pointer;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li, .xgplayer-skin-default .xg-btn-showHistory ul li {
|
||||
opacity: .7;
|
||||
font-family: PingFangSC-Regular;
|
||||
font-size: 13px;
|
||||
color: hsla(0,0%,100%,.8);
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li:first-child, .xgplayer-skin-default .xg-btn-showHistory ul li:first-child {
|
||||
position: relative;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li:last-child, .xgplayer-skin-default .xg-btn-showHistory ul li:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.xgplayer-skin-default .xg-btn-showList ul li.selected, .xgplayer-skin-default .xg-btn-showHistory ul li.selected, .xgplayer-skin-default .xg-btn-showList ul li:hover, .xgplayer-skin-default .xg-btn-showHistory ul li:hover {
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-volume {
|
||||
width: 32px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate {
|
||||
width: 40px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate .name {
|
||||
top: 10px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate ul {
|
||||
bottom: 25px;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-playbackrate ul li {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xgplayer-screenshot .name span {
|
||||
width: 40px !important;
|
||||
}
|
||||
.xgplayer-skin-default .xg-view-videoTitle {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 40px;
|
||||
padding-left: 10px;
|
||||
background-image: linear-gradient(180deg,rgba(0,0,0,.75),rgba(0,0,0,.75),rgba(0,0,0,.37),transparent);
|
||||
z-index: 10;
|
||||
}
|
||||
.xgplayer-skin-default .xg-view-videoTitle span {
|
||||
font-size: 16px;
|
||||
line-height: 40px;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.play{
|
||||
position: relative;
|
||||
@@ -677,6 +1119,13 @@ export default {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
.right {
|
||||
float: right;
|
||||
svg {
|
||||
margin-top: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.player{
|
||||
width: 100%;
|
||||
|
||||
@@ -44,6 +44,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='site'>
|
||||
<div class="title">收藏管理</div>
|
||||
<div class="site-box">
|
||||
<div class="zy-select">
|
||||
<div class="vs-placeholder vs-noAfter" @click="exportFavorites">导出</div>
|
||||
</div>
|
||||
<div class="zy-select">
|
||||
<div class="vs-placeholder vs-noAfter" @click="importFavorites">导入</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='search'>
|
||||
<div class="title">搜索</div>
|
||||
<div class="zy-checkbox">
|
||||
<input type="checkbox" v-model="setting.searchAllSites" @change="updateSearchOption($event)"> 搜索所有资源
|
||||
</div>
|
||||
</div>
|
||||
<div class='site'>
|
||||
<div class="title">第三方播放器</div>
|
||||
<div class="site-box">
|
||||
<div class="zy-select">
|
||||
<div class="vs-placeholder vs-noAfter" @click="selectExternalPlayer">选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="site">
|
||||
<div class="title">源管理</div>
|
||||
<div class="site-box">
|
||||
@@ -104,7 +129,7 @@
|
||||
</div>
|
||||
<div class="clearDB">
|
||||
<span @click="clearDBEvent" class="clearBtn">软件重置</span>
|
||||
<span class="clearTips">如非必要, 切勿点击. 会清空用户数据, 恢复默认设置. 点击即软件重置, 并关闭软件.</span>
|
||||
<span class="clearTips">如果新安装用户, 无法显示资源, 请点击软件重置. 如非必要, 切勿点击. 会清空用户数据, 恢复默认设置. 点击即软件重置, 并关闭软件.</span>
|
||||
</div>
|
||||
<div class="Tips">
|
||||
<span>所有资源来自网上, 该软件不参与任何制作, 上传, 储存等内容, 禁止传播违法资源. 该软件仅供学习参考, 请于安装后24小时内删除.</span>
|
||||
@@ -115,9 +140,10 @@
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import pkg from '../../package.json'
|
||||
import { setting, sites, shortcut } from '../lib/dexie'
|
||||
import { setting, sites, shortcut, star } from '../lib/dexie'
|
||||
import { shell, clipboard, remote } from 'electron'
|
||||
import db from '../lib/dexie/dexie'
|
||||
import fs from 'fs'
|
||||
export default {
|
||||
name: 'setting',
|
||||
data () {
|
||||
@@ -125,6 +151,7 @@ export default {
|
||||
pkg: pkg,
|
||||
sitesList: [],
|
||||
shortcutList: [],
|
||||
favoritesList: [],
|
||||
show: {
|
||||
site: false,
|
||||
shortcut: false,
|
||||
@@ -135,7 +162,9 @@ export default {
|
||||
site: '',
|
||||
theme: '',
|
||||
shortcut: true,
|
||||
view: 'picture'
|
||||
searchAllSites: true,
|
||||
view: 'picture',
|
||||
externalPlayer: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -161,7 +190,9 @@ export default {
|
||||
site: res.site,
|
||||
theme: res.theme,
|
||||
shortcut: res.shortcut,
|
||||
view: res.view
|
||||
view: res.view,
|
||||
searchAllSites: res.searchAllSites,
|
||||
externalPlayer: res.externalPlayer
|
||||
}
|
||||
this.setting = this.d
|
||||
})
|
||||
@@ -176,6 +207,11 @@ export default {
|
||||
this.shortcutList = res
|
||||
})
|
||||
},
|
||||
getFavorites () {
|
||||
star.all().then(res => {
|
||||
this.favoritesList = res
|
||||
})
|
||||
},
|
||||
changeView (e) {
|
||||
this.d.view = e
|
||||
setting.update(this.d).then(res => {
|
||||
@@ -192,25 +228,123 @@ export default {
|
||||
this.show.site = false
|
||||
})
|
||||
},
|
||||
expSites () {
|
||||
const arr = [...this.sitesList]
|
||||
const str = JSON.stringify(arr)
|
||||
clipboard.writeText(str)
|
||||
this.$message.success('已复制到剪贴板')
|
||||
updateSearchOption (e) {
|
||||
this.d.searchAllSites = this.setting.searchAllSites
|
||||
setting.update(this.d).then(res => {
|
||||
this.setting = this.d
|
||||
})
|
||||
},
|
||||
impSites () {
|
||||
const str = clipboard.readText()
|
||||
const json = JSON.parse(str)
|
||||
sites.clear().then(res => {
|
||||
this.$message.info('已清空原数据')
|
||||
sites.add(json).then(e => {
|
||||
this.$message.success('已添加成功')
|
||||
this.getSites()
|
||||
this.d.site = json[0].key
|
||||
exportFavorites () {
|
||||
const arr = [...this.favoritesList]
|
||||
const str = JSON.stringify(arr, null, 4)
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'JSON file', extensions: ['json'] },
|
||||
{ name: 'Normal text file', extensions: ['txt'] },
|
||||
{ name: 'All types', extensions: ['*'] }
|
||||
]
|
||||
}
|
||||
remote.dialog.showSaveDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
fs.writeFileSync(result.filePath, str)
|
||||
this.$message.success('已保存成功')
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$message.error(err)
|
||||
})
|
||||
},
|
||||
importFavorites () {
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'JSON file', extensions: ['json'] },
|
||||
{ name: 'Normal text file', extensions: ['txt'] },
|
||||
{ name: 'All types', extensions: ['*'] }
|
||||
],
|
||||
properties: ['openFile', 'multiSelections']
|
||||
}
|
||||
remote.dialog.showOpenDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
result.filePaths.forEach(file => {
|
||||
var str = fs.readFileSync(file)
|
||||
const json = JSON.parse(str)
|
||||
star.bulkAdd(json).then(e => {
|
||||
this.getFavorites()
|
||||
})
|
||||
})
|
||||
this.$message.success('导入收藏成功')
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$message.error(err)
|
||||
})
|
||||
},
|
||||
selectExternalPlayer () {
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'Executable file', extensions: ['exe'] },
|
||||
{ name: 'All types', extensions: ['*'] }
|
||||
],
|
||||
properties: ['openFile']
|
||||
}
|
||||
remote.dialog.showOpenDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
var playerPath = result.filePaths[0].replace(/\\/g, '/')
|
||||
this.$message.success(result.filePaths[0])
|
||||
this.$message.success('设定第三方播放器路径为:' + result.filePaths[0])
|
||||
this.d.externalPlayer = playerPath
|
||||
setting.update(this.d).then(res => {
|
||||
this.setting = this.d
|
||||
})
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$message.error(err)
|
||||
})
|
||||
},
|
||||
expSites () {
|
||||
const arr = [...this.sitesList]
|
||||
const str = JSON.stringify(arr, null, 4)
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'JSON file', extensions: ['json'] },
|
||||
{ name: 'Normal text file', extensions: ['txt'] },
|
||||
{ name: 'All types', extensions: ['*'] }
|
||||
]
|
||||
}
|
||||
remote.dialog.showSaveDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
fs.writeFileSync(result.filePath, str)
|
||||
this.$message.success('已保存成功')
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$message.error(err)
|
||||
})
|
||||
},
|
||||
impSites () {
|
||||
const options = {
|
||||
filters: [
|
||||
{ name: 'JSON file', extensions: ['json'] },
|
||||
{ name: 'Normal text file', extensions: ['txt'] },
|
||||
{ name: 'All types', extensions: ['*'] }
|
||||
],
|
||||
properties: ['openFile']
|
||||
}
|
||||
remote.dialog.showOpenDialog(options).then(result => {
|
||||
if (!result.canceled) {
|
||||
sites.clear()
|
||||
result.filePaths.forEach(file => {
|
||||
var str = fs.readFileSync(file)
|
||||
const json = JSON.parse(str)
|
||||
sites.add(json).then(e => {
|
||||
this.getSites()
|
||||
this.d.site = json[0].key
|
||||
setting.update(this.d).then(res => {
|
||||
this.setting = this.d
|
||||
})
|
||||
})
|
||||
this.$message.success('导入成功')
|
||||
}).catch(err => {
|
||||
this.$message.error(err)
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
changeTheme (e) {
|
||||
@@ -266,6 +400,7 @@ export default {
|
||||
this.getSetting()
|
||||
this.getSites()
|
||||
this.getShortcut()
|
||||
this.getFavorites()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -313,6 +448,11 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.search{
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.site{
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
@@ -341,6 +481,7 @@ export default {
|
||||
margin-top: 20px;
|
||||
.theme-box{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
.theme-item{
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
<template>
|
||||
<div class="star">
|
||||
<div class="body zy-scroll">
|
||||
<div class="body">
|
||||
<div class="zy-table">
|
||||
<div class="tBody">
|
||||
<div class="tHeader">
|
||||
<span class="btn" @click="updateAllEvent(list)">同步所有收藏</span>
|
||||
</div>
|
||||
<div class="tBody zy-scroll">
|
||||
<ul>
|
||||
<li v-for="(i, j) in list" :key="j" @click="detailEvent(i)">
|
||||
<li v-for="(i, j) in list" :key="j" @click="detailEvent(i)" :class="[i.hasUpdate ? 'zy-highlighted': '']">
|
||||
<span class="name">{{i.name}}</span>
|
||||
<span class="type">{{i.type}}</span>
|
||||
<span class="time">{{i.year}}</span>
|
||||
<span class="from">{{i.site}}</span>
|
||||
<span class="operate" style="width: 220px">
|
||||
<span class="site">{{i.site.name}}</span>
|
||||
<span class="note">{{i.note}}</span>
|
||||
<span class="operate">
|
||||
<span class="btn" @click.stop="playEvent(i)">播放</span>
|
||||
<span class="btn" @click.stop="deleteEvent(i)">删除</span>
|
||||
<span class="btn" @click.stop="shareEvent(i)">分享</span>
|
||||
@@ -79,18 +83,23 @@ export default {
|
||||
detailEvent (e) {
|
||||
this.detail = {
|
||||
show: true,
|
||||
key: e.site,
|
||||
info: e
|
||||
key: e.site.key,
|
||||
info: {
|
||||
id: e.ids,
|
||||
name: e.name
|
||||
}
|
||||
}
|
||||
this.clearHasUpdateFlag(e)
|
||||
},
|
||||
playEvent (e) {
|
||||
history.find({ site: e.site, ids: e.ids }).then(res => {
|
||||
history.find({ site: e.site.key, ids: e.ids }).then(res => {
|
||||
if (res) {
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: res.index } }
|
||||
this.video = { key: res.site, info: { id: res.ids, name: res.name, index: res.index, site: e.site } }
|
||||
} else {
|
||||
this.video = { key: e.site, info: { id: e.ids, name: e.name, index: 0 } }
|
||||
this.video = { key: e.site.key, info: { id: e.ids, name: e.name, index: 0, site: e.site } }
|
||||
}
|
||||
})
|
||||
this.clearHasUpdateFlag(e)
|
||||
this.view = 'Play'
|
||||
},
|
||||
deleteEvent (e) {
|
||||
@@ -106,14 +115,22 @@ export default {
|
||||
shareEvent (e) {
|
||||
this.share = {
|
||||
show: true,
|
||||
key: e.site,
|
||||
key: e.site.key,
|
||||
info: e
|
||||
}
|
||||
},
|
||||
clearHasUpdateFlag (e) {
|
||||
star.find({ id: e.id }).then(res => {
|
||||
res.hasUpdate = false
|
||||
star.update(e.id, res)
|
||||
this.getStarList()
|
||||
})
|
||||
},
|
||||
updateEvent (e) {
|
||||
zy.detail(e.site, e.ids).then(res => {
|
||||
zy.detail(e.site.key, e.ids).then(res => {
|
||||
if (e.last === res.last) {
|
||||
this.$message.info('同步成功, 未查询到更新。')
|
||||
var msg = `同步"${e.name}"成功, 未查询到更新。`
|
||||
this.$message.info(msg)
|
||||
} else {
|
||||
const doc = {
|
||||
id: e.id,
|
||||
@@ -122,18 +139,28 @@ export default {
|
||||
name: res.name,
|
||||
site: e.site,
|
||||
type: res.type,
|
||||
year: res.year
|
||||
year: res.year,
|
||||
note: res.note,
|
||||
hasUpdate: true
|
||||
}
|
||||
star.update(e.id, doc).then(res => {
|
||||
this.$message.success('同步成功, 检查到更新.')
|
||||
var msg = `同步"${e.name}"成功, 检查到更新。`
|
||||
this.$message.success(msg)
|
||||
})
|
||||
this.getStarList()
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$message.warning('同步失败, 请重试', err)
|
||||
var msg = `同步"${e.name}"失败, 请重试。`
|
||||
this.$message.warning(msg, err)
|
||||
})
|
||||
},
|
||||
updateAllEvent (list) {
|
||||
list.forEach(e => {
|
||||
this.updateEvent(e)
|
||||
})
|
||||
},
|
||||
downloadEvent (e) {
|
||||
zy.download(e.site, e.ids).then(res => {
|
||||
zy.download(e.site.key, e.ids).then(res => {
|
||||
if (res) {
|
||||
const text = res.dl.dd._t
|
||||
if (text) {
|
||||
@@ -183,7 +210,6 @@ export default {
|
||||
.body{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,7 @@ import Star from './Star'
|
||||
import Setting from './Setting'
|
||||
import Detail from './Detail'
|
||||
import Share from './Share'
|
||||
import History from './History'
|
||||
|
||||
export default {
|
||||
registerComponents () {
|
||||
@@ -18,5 +19,6 @@ export default {
|
||||
Vue.component('Setting', Setting)
|
||||
Vue.component('Detail', Detail)
|
||||
Vue.component('Share', Share)
|
||||
Vue.component('History', History)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ export default {
|
||||
async add (doc) {
|
||||
return await star.add(doc)
|
||||
},
|
||||
async bulkAdd (doc) {
|
||||
return await star.bulkAdd(doc)
|
||||
},
|
||||
async find (doc) {
|
||||
return await star.get(doc)
|
||||
},
|
||||
@@ -15,5 +18,8 @@ export default {
|
||||
},
|
||||
async remove (id) {
|
||||
return await star.delete(id)
|
||||
},
|
||||
async clear () {
|
||||
return await star.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const Axios = require('axios')
|
||||
const app = express()
|
||||
app.use(cors())
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded())
|
||||
app.use(express.urlencoded({ extended: true }))
|
||||
|
||||
app.post('/api', async (req, res) => {
|
||||
const result = await Axios.get(req.body.url)
|
||||
@@ -15,4 +15,4 @@ app.post('/api', async (req, res) => {
|
||||
})
|
||||
})
|
||||
|
||||
app.listen(48484)
|
||||
app.listen(44444)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { sites } from '../dexie'
|
||||
import axios from 'axios'
|
||||
import parser from 'fast-xml-parser'
|
||||
const zy = {
|
||||
ports: 48484, // 端口号
|
||||
ports: 44444, // 端口号
|
||||
xmlConfig: { // XML 转 JSON 配置
|
||||
trimValues: true,
|
||||
textNodeName: '_t',
|
||||
@@ -184,7 +184,7 @@ const zy = {
|
||||
reject(err)
|
||||
})
|
||||
} else {
|
||||
resolve(null)
|
||||
resolve([])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -22,8 +22,15 @@
|
||||
<span class="progress" v-show="progress > 0">播放进度: {{progress}}%</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="min" @click="frameClickEvent('min')"></span>
|
||||
<span class="close" @click="frameClickEvent('close')"></span>
|
||||
<span class="top" @click="frameClickEvent('top')" title="置顶">
|
||||
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:12px;height:16px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
|
||||
</span>
|
||||
<span class="min" @click="frameClickEvent('min')" title="最小化">
|
||||
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:10px;height:16px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
<span class="close" @click="frameClickEvent('close')" title="关闭">
|
||||
<svg t="1595917372551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" style="width:10px;height:16px"><path d="M511.968 376.224 796.096 92.096C833.536 54.624 894.4 54.624 931.84 92.096 969.312 129.568 969.312 190.4 931.84 227.872L647.744 512 931.84 796.096C969.312 833.568 969.312 894.4 931.84 931.872 894.4 969.344 833.536 969.344 796.096 931.872L511.968 647.744 227.84 931.872C190.4 969.344 129.536 969.344 92.096 931.872 54.624 894.4 54.624 833.568 92.096 796.096L376.224 512 92.096 227.872C54.624 190.4 54.624 129.568 92.096 92.096 129.536 54.624 190.4 54.624 227.84 92.096L511.968 376.224Z" p-id="1686" fill="#ffffff"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
@@ -38,9 +45,11 @@ import mt from 'mousetrap'
|
||||
import 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
const VIDEO_DETAIL_CACHE = {}
|
||||
export default {
|
||||
name: 'mini',
|
||||
data () {
|
||||
const win = remote.getCurrentWindow()
|
||||
return {
|
||||
xg: null,
|
||||
config: {
|
||||
@@ -65,7 +74,8 @@ export default {
|
||||
detail: {},
|
||||
m3u8Arr: [],
|
||||
rate: 1,
|
||||
progress: 0
|
||||
progress: 0,
|
||||
isAlwaysOnTop: win.isAlwaysOnTop()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -79,6 +89,11 @@ export default {
|
||||
ipcRenderer.send('win')
|
||||
return false
|
||||
}
|
||||
if (e === 'top') {
|
||||
this.isAlwaysOnTop = !this.isAlwaysOnTop
|
||||
const win = remote.getCurrentWindow()
|
||||
win.setAlwaysOnTop(this.isAlwaysOnTop)
|
||||
}
|
||||
},
|
||||
opacityChange (val) {
|
||||
const win = remote.getCurrentWindow()
|
||||
@@ -89,10 +104,88 @@ export default {
|
||||
getUrls () {
|
||||
mini.find().then(res => {
|
||||
this.video = res
|
||||
zy.detail(res.site, res.ids).then(e => {
|
||||
this.name = e.name
|
||||
this.detail = e
|
||||
const dd = e.dl.dd
|
||||
this.fetchM3u8List(res).then(m3u8Arr => {
|
||||
this.m3u8Arr = m3u8Arr
|
||||
this.xg.src = m3u8Arr[res.index]
|
||||
if (res.time !== 0 || res.time !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = res.time
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
}
|
||||
this.videoPlaying()
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
this.video.time = 0
|
||||
this.video.index++
|
||||
this.xg.src = m3u8Arr[this.video.index]
|
||||
this.xg.play()
|
||||
}
|
||||
})
|
||||
})
|
||||
// zy.detail(res.site, res.ids).then(e => {
|
||||
// this.name = e.name
|
||||
// this.detail = e
|
||||
// const dd = e.dl.dd
|
||||
// const type = Object.prototype.toString.call(dd)
|
||||
// let m3u8Txt = []
|
||||
// if (type === '[object Array]') {
|
||||
// for (const i of dd) {
|
||||
// if (i._t.indexOf('m3u8') >= 0) {
|
||||
// m3u8Txt = i._t.split('#')
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Txt = dd._t.split('#')
|
||||
// }
|
||||
// const m3u8Arr = []
|
||||
// for (const i of m3u8Txt) {
|
||||
// const j = i.split('$')
|
||||
// if (j.length > 1) {
|
||||
// for (let m = 0; m < j.length; m++) {
|
||||
// if (j[m].indexOf('m3u8') >= 0) {
|
||||
// m3u8Arr.push(j[m])
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// m3u8Arr.push(j[0])
|
||||
// }
|
||||
// }
|
||||
// this.m3u8Arr = m3u8Arr
|
||||
// this.xg.src = m3u8Arr[res.index]
|
||||
// if (res.time !== 0 || res.time !== '') {
|
||||
// this.xg.play()
|
||||
// this.xg.once('playing', () => {
|
||||
// this.xg.currentTime = res.time
|
||||
// })
|
||||
// } else {
|
||||
// this.xg.play()
|
||||
// }
|
||||
// this.videoPlaying()
|
||||
// this.xg.once('ended', () => {
|
||||
// if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
// this.video.time = 0
|
||||
// this.video.index++
|
||||
// this.xg.src = m3u8Arr[this.video.index]
|
||||
// this.xg.play()
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
})
|
||||
},
|
||||
fetchM3u8List (info) {
|
||||
return new Promise((resolve) => {
|
||||
const cacheKey = info.site + '@' + info.ids
|
||||
if (VIDEO_DETAIL_CACHE[cacheKey]) {
|
||||
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
|
||||
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
|
||||
return
|
||||
}
|
||||
zy.detail(info.site, info.ids).then(res => {
|
||||
this.name = res.name
|
||||
const dd = res.dl.dd
|
||||
const type = Object.prototype.toString.call(dd)
|
||||
let m3u8Txt = []
|
||||
if (type === '[object Array]') {
|
||||
@@ -117,25 +210,12 @@ export default {
|
||||
m3u8Arr.push(j[0])
|
||||
}
|
||||
}
|
||||
this.m3u8Arr = m3u8Arr
|
||||
this.xg.src = m3u8Arr[res.index]
|
||||
if (res.time !== 0 || res.time !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = res.time
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
|
||||
VIDEO_DETAIL_CACHE[cacheKey] = {
|
||||
list: m3u8Arr,
|
||||
name: res.name
|
||||
}
|
||||
this.videoPlaying()
|
||||
this.xg.once('ended', () => {
|
||||
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
|
||||
this.video.time = 0
|
||||
this.video.index++
|
||||
this.xg.src = m3u8Arr[this.video.index]
|
||||
this.xg.play()
|
||||
}
|
||||
})
|
||||
resolve(m3u8Arr)
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -177,6 +257,7 @@ export default {
|
||||
},
|
||||
prevEvent () {
|
||||
if (this.video.index === 0) {
|
||||
this.$message.info('已是第一集.')
|
||||
return false
|
||||
}
|
||||
history.find({ site: this.video.site, ids: this.video.ids }).then(res => {
|
||||
@@ -192,6 +273,7 @@ export default {
|
||||
},
|
||||
nextEvent () {
|
||||
if (this.video.index >= this.m3u8Arr.length - 1) {
|
||||
this.$message.info('已是最后一集.')
|
||||
return false
|
||||
}
|
||||
history.find({ site: this.video.site, ids: this.video.ids }).then(res => {
|
||||
@@ -284,8 +366,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
if (e === 'escape') {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
if (this.xg.fullscreen) {
|
||||
this.xg.exitFullscreen()
|
||||
this.xg.exitCssFullscreen()
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (e === 'next') {
|
||||
@@ -351,12 +435,10 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getUrls()
|
||||
this.mtEvent()
|
||||
},
|
||||
mounted () {
|
||||
this.xg = new Hls(this.config)
|
||||
this.mtEvent()
|
||||
this.getUrls()
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearInterval(this.timer)
|
||||
@@ -427,6 +509,8 @@ html,body{
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
text-align: center;
|
||||
line-height: 16px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
@@ -437,6 +521,9 @@ html,body{
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
&.top{
|
||||
background-color: #f3bab7;
|
||||
}
|
||||
&:hover{
|
||||
animation: heartbeat 3s ease-in-out infinite both;
|
||||
}
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -9918,16 +9918,16 @@ xdg-basedir@^4.0.0:
|
||||
|
||||
xgplayer-hls.js@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.npmjs.org/xgplayer-hls.js/-/xgplayer-hls.js-2.2.3.tgz#bf538911145346c447528d609fc95dd267a24d81"
|
||||
resolved "https://registry.yarnpkg.com/xgplayer-hls.js/-/xgplayer-hls.js-2.2.3.tgz#bf538911145346c447528d609fc95dd267a24d81"
|
||||
integrity sha512-CFsZanBHHRbqTmqYCFFONk76oWwJwbn+8LK/XkwBBrUrqGPQPmrXfjelGjKDDGfZ+w3xReC1nGom3IpN+lLoaQ==
|
||||
dependencies:
|
||||
deepmerge "2.0.1"
|
||||
event-emitter "^0.3.5"
|
||||
|
||||
xgplayer@^2.9.8:
|
||||
version "2.9.8"
|
||||
resolved "https://registry.npmjs.org/xgplayer/-/xgplayer-2.9.8.tgz#ce6646f8ef99594ca9414449f83f816320c4ec83"
|
||||
integrity sha512-MICegbLRMNdOa9kRcsY5BVfwKmwvO+quJST/ejSJngdvDrB4E9dX53zhL3OT6KH4n9aCifl5qCYzTRWD6qH22w==
|
||||
xgplayer@^2.9.10:
|
||||
version "2.9.10"
|
||||
resolved "https://registry.yarnpkg.com/xgplayer/-/xgplayer-2.9.10.tgz#4e79b889621f829b773c118ab93da55f829d4490"
|
||||
integrity sha512-5a7Xm0AY8qPRXZFxrPRErjzCERsENaskQ8Fq5Sy4ht13TMzYp0VIRREU7XF8efpJGcPsOOuFlCiMrqSpYEIAUA==
|
||||
dependencies:
|
||||
chalk "^2.3.2"
|
||||
commander "^2.15.1"
|
||||
|
||||
Reference in New Issue
Block a user