Compare commits

...

98 Commits

Author SHA1 Message Date
haiyangcui
511820f873 修复历史记录里的下载功能 2020-08-27 17:01:22 +02:00
haiyangcui
af6dcb11bf 修复剧集的分享功能 2020-08-27 16:53:46 +02:00
haiyangcui
7ecad1ad8e 同步历史和收藏的operate buttons 2020-08-27 16:45:29 +02:00
haiyangcui
4d169f9d51 删除无用代码 2020-08-27 16:36:04 +02:00
haiyangcui
f3862e8385 格式化快捷键数据 2020-08-27 16:20:03 +02:00
haiyangcui
490d4839b7 没有更新的收藏跳过clearHasUpdateFlag 2020-08-27 16:06:46 +02:00
haiyangcui
033bcb3df7 修复下载功能 2020-08-27 15:52:56 +02:00
haiyangcui
df22efa980 导入收藏时不清空 2020-08-27 15:26:47 +02:00
haiyangcui
5428891297 删除多余信息 2020-08-27 15:14:03 +02:00
haiyangcui
bb3502774b 同步时更新收藏信息 2020-08-27 15:05:57 +02:00
haiyangcui
fa67ad03d2 恢复播放页面的收藏逻辑 2020-08-27 15:03:28 +02:00
haiyangcui
8a196ae52a 解决收藏项无法直接播放的bug 2020-08-27 14:48:11 +02:00
haiyangcui
ebfb681205 导出时先更新数据 2020-08-27 14:32:29 +02:00
haiyangcui
ba9f3246d2 Fix typo bug 2020-08-27 14:25:22 +02:00
haiyangcui
51cb181acd 改进播放页面的收藏功能 2020-08-27 13:58:05 +02:00
haiyangcui
33537638b0 更新version到2.4.3 2020-08-27 13:39:50 +02:00
haiyangcui
fa9f85a177 使用star.key 2020-08-27 13:33:21 +02:00
haiyangcui
3e1ecaac74 Fix bug in checkStar 2020-08-27 13:24:55 +02:00
haiyangcui
5cc9849e8a 导入收藏时升级数据格式 2020-08-27 13:13:45 +02:00
haiyangcui
e353b629c5 添加"更新收藏" 2020-08-27 13:08:41 +02:00
haiyangcui
4d20d5bc68 No need to record site info in star 2020-08-27 13:08:22 +02:00
haiyangcui
a921ce7adf 添加“清空所有收藏” 2020-08-27 12:39:54 +02:00
haiyangcui
1dd8d0dd24 在视图和列表里添加备注 2020-08-26 18:15:02 +02:00
haiyangcui
b90c359670 Reverse the list return by zy.list, to get video list from new to old 2020-08-26 16:24:57 +02:00
haiyangcui
27eb8c06ff 添加“最新”到class列表 2020-08-26 11:42:15 +02:00
haiyangcui
add2bedb61 v2.4.2 2020-08-25 16:59:59 +02:00
haiyangcui
3dc970e198 更新已存在的收藏 2020-08-25 15:54:07 +02:00
haiyangcui
3f2def4455 添加第三方播放器路径设置 2020-08-25 14:38:46 +02:00
haiyangcui
5b8d883af4 Format JSON string 2020-08-25 13:48:33 +02:00
haiyangcui
7113567475 可以使用PotPlayer打开视频 2020-08-25 00:31:34 +02:00
haiyangcui
e30da35e72 Import sites from file 2020-08-24 13:10:30 +02:00
haiyangcui
55b7396a2e Export sites to file 2020-08-24 12:54:31 +02:00
haiyangcui
83568fa499 No need to copy to clipboard 2020-08-24 12:32:51 +02:00
haiyangcui
838d3a64cd v2.4.1 2020-08-23 17:48:10 +02:00
haiyangcui
506be03e3e 从文件中导入收藏 2020-08-23 17:45:19 +02:00
haiyangcui
cfdb561473 加入取消操作识别 2020-08-23 15:03:47 +02:00
haiyangcui
ab2f45189f 导出收藏到文件 2020-08-23 14:33:59 +02:00
haiyangcui
f4b9a73b18 Simple favorites export import 2020-08-22 17:55:10 +02:00
haiyangcui
6f99d789f4 2.4.0 2020-08-22 16:08:38 +02:00
haiyangcui
e71090dad2 Wrap the items in Settings theme-box 2020-08-22 15:54:39 +02:00
haiyangcui
afe3351837 Add left margin to name 2020-08-22 15:35:28 +02:00
haiyangcui
5dc0613aeb 列表自适应 2020-08-22 15:06:10 +02:00
haiyangcui
1c6385ae6c 使用v-show显示隐藏class element,这样可以保持其占位 2020-08-22 10:58:47 +02:00
haiyangcui
88a95a8bfb 保存搜索选项设置 2020-08-22 00:20:18 +02:00
haiyangcui
951e6ffa37 更好的修复bug#183 2020-08-21 23:49:00 +02:00
haiyangcui
b83aed0a97 解决bug #183 2020-08-21 23:36:17 +02:00
haiyangcui
67ce537039 Add search style 2020-08-21 23:00:21 +02:00
haiyangcui
975562a66b Fix a bug in Detail.vue 2020-08-19 23:31:20 +02:00
haiyangcui
8e7015c9d6 调整"搜索所有资源"位置 2020-08-19 23:09:42 +02:00
haiyangcui
b841552dc7 转移"搜索所有资源"到设置页面 2020-08-19 18:07:37 +02:00
haiyangcui
0a9b939dc3 v2.3.8 2020-08-19 11:36:08 +02:00
haiyangcui
14ff252cce 定义--highlight-color 2020-08-19 08:30:18 +02:00
haiyangcui
afd016be93 取消“搜索所有资源”的边框 2020-08-18 23:00:05 +02:00
haiyangcui
9cd7f7d267 高亮有更新的收藏项 2020-08-18 22:51:03 +02:00
haiyangcui
8a76ec4e87 Null check on site 2020-08-18 17:39:39 +02:00
haiyangcui
a00d965ce9 v2.3.7 2020-08-18 16:00:05 +02:00
Hunlongyu
c9eb0c3e22 Merge pull request #178 from cuiocean/master
添加搜索所有资源功能
2020-08-18 16:13:08 +08:00
haiyangcui
c80c0bd948 Video中添加site信息 2020-08-16 23:02:18 +02:00
haiyangcui
65dcfa04ae 在star中添加key信息 2020-08-16 22:58:12 +02:00
haiyangcui
4e4ab82ea2 添加site信息在Detail里 2020-08-16 22:30:54 +02:00
haiyangcui
dd2adf4f99 更新格式 2020-08-15 16:44:43 +02:00
haiyangcui
777fbde528 在历史界面显示资源网站名,而不是资源标识 2020-08-15 16:30:09 +02:00
haiyangcui
472898f978 Fix downloadEvent 2020-08-15 12:27:44 +02:00
haiyangcui
7f41d415f1 删除searchSingleSiteEvent 2020-08-15 12:18:40 +02:00
haiyangcui
5d37a36c21 添加简单的style 2020-08-15 11:23:19 +02:00
haiyangcui
3a499766af playEvent starEvent shareEvent downloadEvent all take site as the input argument 2020-08-15 10:56:48 +02:00
haiyangcui
cea797b6d0 Save whole site data to res.site 2020-08-14 21:55:41 +02:00
haiyangcui
37b41b0e20 无搜索结果时,提示资源网站名字 2020-08-14 19:41:00 +02:00
haiyangcui
1105c46f08 添加“搜索所有资源”checkbox 2020-08-14 19:29:39 +02:00
haiyangcui
1df7b41edd 搜索结果显示资源网名字 2020-08-13 22:04:50 +02:00
haiyangcui
f76c71c950 Merge searchClickEvent and searchEvent 2020-08-13 21:46:23 +02:00
Hunlongyu
cd77384bd9 😄 v2.3.6 😆 2020-08-12 15:47:33 +08:00
Hunlongyu
64adc9d6c1 Merge pull request #170 from cuiocean/master
添加"备注"到搜索结果
2020-08-12 15:46:16 +08:00
haiyangcui
e9095e50a6 添加"备注"到搜索结果 2020-08-06 08:51:39 +02:00
Hunlongyu
acfa742b4f 👮‍♂️ v2.3.5 👨‍🚀 2020-08-06 10:15:34 +08:00
Hunlongyu
a79c48cba0 👨‍🚒👩‍🚒 v2.3.4 👨‍🚀👩‍🚀 2020-08-06 10:13:51 +08:00
Hunlongyu
904ef5ccea modify css 2020-08-06 09:58:39 +08:00
Hunlongyu
3db281c87f Merge pull request #168 from cuiocean/master
添加"备注"列到收藏试图
2020-08-06 09:57:29 +08:00
haiyangcui
076e6e99e4 当有更新时,刷新list列表 2020-08-05 17:06:17 +02:00
haiyangcui
32f6ac0310 添加"备注"列到收藏试图 2020-08-05 16:39:46 +02:00
haiyangcui
b8706ea432 添加播放视频点击事件到历史记录里的片名 2020-08-05 16:27:11 +02:00
haiyangcui
509d6c7900 添加"备注"列到收藏试图 2020-08-05 16:25:45 +02:00
Hunlongyu
51454d828c 🐱💻 v2.3.3 🐱🐉 2020-08-05 11:37:37 +08:00
Hunlongyu
59449886f5 🐱👤 新增一键同步所有收藏, 优化样式 🐱‍🏍 2020-08-05 11:35:39 +08:00
Hunlongyu
601e9895cc Merge pull request #166 from cuiocean/master
添加"同步所有收藏"按钮
2020-08-05 11:03:21 +08:00
haiyangcui
1ba8b46990 Fix typo in the function name 2020-08-04 19:06:17 +02:00
haiyangcui
7ed34caa56 Add UpdateAll button 2020-08-04 17:53:07 +02:00
Hunlongyu
fc40521420 🐱💻🐱🐉 发版 2.2.0 🐱👓🐱🚀 2020-08-04 10:17:19 +08:00
Hunlongyu
cfdd836e01 showHistory change to history 2020-08-04 10:14:11 +08:00
Hunlongyu
083e00ddbf Merge pull request #163 from cuiocean/master
添加“历史记录”到侧边栏
2020-08-04 10:10:07 +08:00
Hunlongyu
c41c7c4857 ✌ 修改为字符串 👌 2020-08-04 10:09:22 +08:00
Hunlongyu
4bde51dc38 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player 2020-08-04 10:03:38 +08:00
Hunlongyu
38c7540145 删除 console 2020-08-04 10:03:33 +08:00
Hunlongyu
a44579d4a1 Merge pull request #160 from hectorqin/master
修复m3u8链接获取问题,修复跨域问题
2020-08-04 10:00:10 +08:00
Hunlongyu
7f2d6f12c0 删除备注, 以及console 2020-08-04 09:51:48 +08:00
haiyangcui
daf1c4ddb6 Add ShowHistory to Aside 2020-08-03 21:13:50 +02:00
hectorqin
c1372c5589 新增复制调试信息功能和上次播放提示 2020-08-02 11:57:36 +08:00
hectorqin
c623533271 修复m3u8链接获取问题,修复跨域问题 2020-08-01 22:04:14 +08:00
21 changed files with 866 additions and 316 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "zy",
"version": "2.1.0",
"version": "2.4.3",
"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",

View File

@@ -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">

View File

@@ -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%;

View File

@@ -1,4 +1,6 @@
:root{
// general
--highlight-color: #38dd77;
// light
--l-c-0: #823aa0;
--l-c-1: #823aa011;

View File

@@ -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{
@@ -169,6 +181,11 @@
box-shadow: var(--d-bsc);
.title{
color: var(--d-fc-1);
.right {
svg {
fill: var(--d-fc-1);
}
}
}
.box{
.more{
@@ -192,6 +209,10 @@
fill: var(--d-c-3);
}
}
&.last-tip {
color: var(--d-fc-1);
font-size: 14px;
}
}
}
}
@@ -221,6 +242,9 @@
background-color: var(--d-c-2);
color: var(--d-fc-3);
}
&:hover{
background-color: var(--d-c-3);
}
}
}
.list-history{
@@ -266,7 +290,7 @@
}
}
}
.view, .shortcut, .site{
.view, .search, .shortcut, .site{
.title{
color: var(--d-fc-1);
}
@@ -316,4 +340,8 @@
background-color: var(--d-bgc-1);
}
}
.history{
background-color: var(--d-bgc-1);
box-shadow: var(--d-bsc);
}
}

View File

@@ -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{
@@ -169,6 +180,11 @@
box-shadow: var(--g-bsc);
.title{
color: var(--g-fc-1);
.right {
svg {
fill: var(--g-fc-1);
}
}
}
.box{
.more{
@@ -192,6 +208,10 @@
fill: var(--g-c-3);
}
}
&.last-tip {
color: var(--g-fc-1);
font-size: 14px;
}
}
}
}
@@ -221,6 +241,9 @@
background-color: var(--g-c-2);
color: var(--g-fc-3);
}
&:hover{
background-color: var(--d-c-3);
}
}
}
.list-history{
@@ -266,7 +289,7 @@
}
}
}
.view, .shortcut, .site{
.view, .search, .shortcut, .site{
.title{
color: var(--g-fc-1);
}
@@ -316,4 +339,8 @@
background-color: var(--g-bgc-1);
}
}
.history{
background-color: var(--g-bgc-1);
box-shadow: var(--g-bsc);
}
}

View File

@@ -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{
@@ -169,6 +180,11 @@
box-shadow: var(--l-bsc);
.title{
color: var(--l-fc-1);
.right {
svg {
fill: var(--l-fc-1);
}
}
}
.box{
.more{
@@ -192,6 +208,10 @@
fill: var(--l-c-3);
}
}
&.last-tip {
color: var(--l-fc-1);
font-size: 14px;
}
}
}
}
@@ -221,6 +241,9 @@
background-color: var(--l-c-2);
color: var(--l-fc-3);
}
&:hover{
background-color: var(--d-c-3);
}
}
}
.list-history{
@@ -266,7 +289,7 @@
}
}
}
.view, .shortcut, .site{
.view, .search, .shortcut, .site{
.title{
color: var(--l-fc-1);
}
@@ -316,4 +339,8 @@
background-color: var(--l-bgc-1);
}
}
.history{
background-color: var(--l-bgc-1);
box-shadow: var(--l-bsc);
}
}

View File

@@ -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{
@@ -169,6 +180,11 @@
box-shadow: var(--p-bsc);
.title{
color: var(--p-fc-1);
.right {
svg {
fill: var(--p-fc-1);
}
}
}
.box{
.more{
@@ -192,6 +208,10 @@
fill: var(--p-c-3);
}
}
&.last-tip {
color: var(--p-fc-1);
font-size: 14px;
}
}
}
}
@@ -221,6 +241,9 @@
background-color: var(--p-c-2);
color: var(--p-fc-3);
}
&:hover{
background-color: var(--d-c-3);
}
}
}
.list-history{
@@ -266,7 +289,7 @@
}
}
}
.view, .shortcut, .site{
.view, .search, .shortcut, .site{
.title{
color: var(--p-fc-1);
}
@@ -316,4 +339,8 @@
background-color: var(--p-bgc-1);
}
}
.history{
background-color: var(--p-bgc-1);
box-shadow: var(--p-bsc);
}
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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,21 @@ 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.key,
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('收藏成功')
})
@@ -153,7 +156,7 @@ export default {
},
downloadEvent () {
zy.download(this.detail.key, this.info.id).then(res => {
if (res) {
if (res && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')

View File

@@ -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,18 +37,19 @@
<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.note}}</span>
<span>{{props.data.type}}</span>
</div>
</div>
@@ -60,16 +61,17 @@
<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="time">{{i.note}}</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 +83,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 +202,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 = {}
@@ -225,10 +228,11 @@ export default {
return new Promise((resolve, reject) => {
const key = this.site.key
zy.class(key).then(res => {
this.classList = res.class
var allClass = [{ name: '最新', tid: 0 }].concat(res.class)
this.classList = allClass
this.show.class = true
this.pagecount = res.pagecount
this.type = { name: '最新', tid: 0 }
this.type = this.classList[0]
resolve(true)
}).catch(err => {
reject(err)
@@ -264,7 +268,8 @@ export default {
$state.complete()
}
if (type === '[object Array]') {
this.list.push(...res)
// zy.list 返回的是按时间从旧到新排列, 我门需要翻转为从新到旧
this.list.push(...res.reverse())
}
if (type === '[object Object]') {
this.list.push(res)
@@ -275,35 +280,37 @@ 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,
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 +320,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.length > 0) {
downloadEvent (site, e) {
zy.download(site.key, e.id).then(res => {
if (res && res.length > 0 && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')
@@ -338,7 +345,7 @@ export default {
}
} else {
let m3u8List = []
const dd = e.dl.dd
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
@@ -376,8 +383,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
@@ -389,18 +396,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 => {
@@ -410,28 +423,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 => {

213
src/components/History.vue Normal file
View File

@@ -0,0 +1,213 @@
<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="detailEvent(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="shareEvent(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'
},
shareEvent (e) {
this.share = {
show: true,
key: e.site,
info: e
}
},
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('没有查询到下载链接.')
}
} 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]
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>

View File

@@ -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,12 +97,12 @@
</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.history.length > 1" @click="exportM3u8">导出</li>
<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" :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>
@@ -106,7 +118,7 @@ import zy from '../lib/site/tools'
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 = {}
@@ -132,7 +144,6 @@ const addPlayerBtn = function (event, svg, attrs) {
const addPlayerView = function (event, tpl, attrs) {
const player = this
console.log(player)
const util = Player.util
const rootEl = player.root
const viewConfig = player.config[event]
@@ -321,57 +332,6 @@ export default {
this.xg.off('ended')
})
})
// 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.xg.src = m3u8Arr[index]
// this.showNext = m3u8Arr.length > 1
// if (time !== 0) {
// this.xg.play()
// this.xg.once('playing', () => {
// this.xg.currentTime = time
// })
// } 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) => {
@@ -401,8 +361,9 @@ export default {
const j = i.split('$')
if (j.length > 1) {
for (let m = 0; m < j.length; m++) {
if (j[m].indexOf('m3u8') >= 0) {
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
m3u8Arr.push(j[m])
break
}
}
} else {
@@ -497,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 => {
@@ -508,22 +467,20 @@ 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,
const doc = {
key: this.video.key,
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 => {
star.add(doc).then(starRes => {
this.$message.success('收藏成功')
this.isStar = true
})
@@ -571,8 +528,33 @@ 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 => {
star.find({ key: this.video.key, ids: this.video.info.id }).then(res => {
if (res) {
this.isStar = true
} else {
@@ -595,8 +577,9 @@ export default {
let link, name
if (j.length > 1) {
for (let m = 0; m < j.length; m++) {
if (j[m].indexOf('m3u8') >= 0) {
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
link = j[m]
break
}
}
name = j[0]
@@ -609,25 +592,19 @@ export default {
link: link
})
}
console.log(m3u8Arr)
let m3u8Content = `#EXTM3U
`
let m3u8Content = '#EXTM3U'
for (const item of m3u8Arr) {
m3u8Content += `#EXTINF:-1, ${item.name}
${item.link}
`
m3u8Content += `#EXTINF:-1, ${item.name}\n${item.link}`
}
const blob = new Blob([m3u8Content], { type: 'application/vnd.apple.mpegurl' })
const downloadElement = document.createElement('a') // 创建下载的链接
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = `${this.name}.m3u8` // 下载后的文件名
downloadElement.download = `${this.name}.m3u8`
document.body.appendChild(downloadElement)
downloadElement.click() // 下载
document.body.removeChild(downloadElement) // 下载完成 移除 a
window.URL.revokeObjectURL(href) // 释放blob对象
downloadElement.click()
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
},
clearAllHistory () {
history.clear().then(res => {
@@ -869,6 +846,7 @@ ${item.link}
}
},
refreshHistory () {
this.getAllhistory()
let ul = document.querySelector('xg-btn-showhistory ul')
if (!ul) {
ul = document.createElement('ul')
@@ -945,7 +923,6 @@ ${item.link}
this.mtEvent()
},
mounted () {
console.log(this)
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: '上一集' })()
})
@@ -971,10 +948,6 @@ ${item.link}
this.xg = new Hls(this.config)
ipcRenderer.on('miniClosed', () => {
// this.xg.destroy()
// this.xg = new Hls(this.config)
// this.bindEvent()
// 同步进度
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
if (res) {
if (this.video.info.index !== res.index) {
@@ -1145,6 +1118,13 @@ ${item.link}
height: 40px;
line-height: 40px;
padding: 0 10px;
.right {
float: right;
svg {
margin-top: 8px;
cursor: pointer;
}
}
}
.player{
width: 100%;

View File

@@ -44,6 +44,34 @@
</div>
</div>
</div>
<div class='site'>
<div class="title">收藏管理</div>
<div class="site-box">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportFavorites">导出</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importFavorites">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="clearFavorites">清空收藏</div>
</div>
</div>
</div>
<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 +132,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 +143,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 +154,7 @@ export default {
pkg: pkg,
sitesList: [],
shortcutList: [],
favoritesList: [],
show: {
site: false,
shortcut: false,
@@ -135,7 +165,9 @@ export default {
site: '',
theme: '',
shortcut: true,
view: 'picture'
searchAllSites: true,
view: 'picture',
externalPlayer: ''
}
}
},
@@ -161,7 +193,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 +210,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 +231,153 @@ 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 () {
this.getFavorites()
const arr = [...this.favoritesList]
const str = JSON.stringify(arr, null, 4)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
}).catch(err => {
this.$message.error(err)
})
},
importFavorites () {
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
],
properties: ['openFile', 'multiSelections']
}
remote.dialog.showOpenDialog(options).then(result => {
if (!result.canceled) {
result.filePaths.forEach(file => {
var str = fs.readFileSync(file)
const json = JSON.parse(str)
star.bulkAdd(json).then(e => {
this.getFavorites()
})
this.upgradeFavorites()
})
this.$message.success('导入收藏成功')
}
}).catch(err => {
this.$message.error(err)
})
},
clearFavorites () {
star.clear().then(e => {
this.getFavorites()
this.$message.success('清空所有收藏成功')
})
},
upgradeFavorites () {
star.all().then(res => {
res.forEach(element => {
const docs = {
key: element.key,
ids: element.ids,
name: element.name,
type: element.type,
year: element.year,
last: element.last,
note: element.note
}
star.find({ key: element.key, ids: element.ids }).then(res => {
if (!res) {
star.add(docs)
}
})
})
this.getFavorites()
})
},
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 () {
this.getSites()
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) {
@@ -229,7 +396,7 @@ export default {
},
expShortcut () {
const arr = [...this.shortcutList]
const str = JSON.stringify(arr)
const str = JSON.stringify(arr, null, 4)
clipboard.writeText(str)
this.$message.success('已复制到剪贴板')
},
@@ -266,6 +433,7 @@ export default {
this.getSetting()
this.getSites()
this.getShortcut()
this.getFavorites()
}
}
</script>
@@ -313,6 +481,11 @@ export default {
}
}
}
.search{
width: 100%;
padding: 20px;
margin-top: 20px;
}
.site{
width: 100%;
padding: 20px;
@@ -341,6 +514,7 @@ export default {
margin-top: 20px;
.theme-box{
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin-top: 10px;
.theme-item{

View File

@@ -70,16 +70,22 @@ export default {
zy.detail(this.share.key, id).then(res => {
if (res) {
this.pic = res.pic
const text = res.dl.dd
for (const i of text) {
if (i._flag.indexOf('m3u8') >= 0) {
const arr = i._t.split('#')
const url = arr[0].split('$')[1]
this.link = 'http://zyplayer.fun/player/player.html?url=' + url + '&title=' + this.share.info.name
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('#')
}
this.loading = false
const url = m3u8List[1]
this.link = 'http://zyplayer.fun/player/player.html?url=' + url + '&title=' + this.share.info.name
}
this.loading = false
})
},
picLoadEvent () {

View File

@@ -1,20 +1,24 @@
<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">{{getSiteName(i.key)}}</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>
<span class="btn" @click.stop="updateEvent(i)">同步</span>
<span class="btn" @click.stop="downloadEvent(i)">下载</span>
<span class="btn" @click.stop="deleteEvent(i)">删除</span>
</span>
</li>
</ul>
@@ -25,14 +29,15 @@
</template>
<script>
import { mapMutations } from 'vuex'
import { star, history } from '../lib/dexie'
import { star, history, sites } from '../lib/dexie'
import zy from '../lib/site/tools'
const { clipboard } = require('electron')
export default {
name: 'star',
data () {
return {
list: []
list: [],
sites: []
}
},
computed: {
@@ -72,6 +77,7 @@ export default {
watch: {
view () {
this.getStarList()
this.getAllsites()
}
},
methods: {
@@ -79,21 +85,27 @@ export default {
detailEvent (e) {
this.detail = {
show: true,
key: e.site,
key: e.key,
info: {
id: e.ids,
name: e.name
}
}
if (e.hasUpdate) {
this.clearHasUpdateFlag(e)
}
},
playEvent (e) {
history.find({ site: e.site, ids: e.ids }).then(res => {
history.find({ site: e.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: e.key, 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.video = { key: e.key, info: { id: e.ids, name: e.name, index: 0 } }
}
})
if (e.hasUpdate) {
this.clearHasUpdateFlag(e)
}
this.view = 'Play'
},
deleteEvent (e) {
@@ -109,35 +121,56 @@ export default {
shareEvent (e) {
this.share = {
show: true,
key: e.site,
key: e.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.key, e.ids).then(res => {
var doc = {
key: e.key,
id: e.id,
ids: res.id,
last: res.last,
name: res.name,
type: res.type,
year: res.year,
note: res.note
}
if (e.last === res.last) {
this.$message.info('同步成功, 未查询到更新。')
} else {
const doc = {
id: e.id,
ids: res.id,
last: res.last,
name: res.name,
site: e.site,
type: res.type,
year: res.year
}
doc.hasUpdate = false
star.update(e.id, doc).then(res => {
this.$message.success('同步成功, 检查到更新.')
var msg = `同步"${e.name}"成功, 未查询到更新。`
this.$message.info(msg)
})
} else {
doc.hasUpdate = true
star.update(e.id, doc).then(res => {
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 => {
if (res) {
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('#')
@@ -152,21 +185,46 @@ export default {
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』格式的链接已复制, 快去下载吧!')
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]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
})
}
})
},
getSiteName (key) {
var site = this.sites.find(e => e.key === key)
if (site) {
return site.name
}
},
getStarList () {
star.all().then(res => {
this.list = res.reverse()
})
},
getAllsites () {
sites.all().then(res => {
this.sites = res
})
}
},
created () {
@@ -186,7 +244,6 @@ export default {
.body{
width: 100%;
height: 100%;
overflow: auto;
}
}
</style>

View File

@@ -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)
}
}

View File

@@ -9,5 +9,8 @@ export default {
},
async add (doc) {
return await sites.bulkAdd(doc)
},
async find (doc) {
return await sites.get(doc)
}
}

View File

@@ -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()
}
}

View File

@@ -22,15 +22,15 @@
<span class="progress" v-show="progress > 0">播放进度: {{progress}}%</span>
</div>
<div class="right">
<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>
<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>
</div>
</div>
<div class="bottom">
@@ -125,54 +125,6 @@ export default {
}
})
})
// 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) {