Compare commits

...

72 Commits
v3.x ... v2.5.3

Author SHA1 Message Date
haiyangcui
cd2cb684a5 v2.5.3 2020-10-21 12:35:07 +02:00
Hunlongyu
e970074266 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player into master 2020-10-21 15:33:58 +08:00
Hunlongyu
9dc7ab4d1e 🎪 升级最新依赖 2020-10-21 09:13:53 +08:00
haiyangcui
ffe821d107 IPTV函数名更新 2020-10-20 21:57:52 +02:00
Hunlongyu
0f015b26e2 🎢 优化 IPTV 的搜索框样式 2020-10-20 09:27:13 +08:00
haiyangcui
f031f9e7fd 修复确定分组的逻辑 2020-10-19 23:40:50 +02:00
haiyangcui
b38de7f393 IPTV分组 2020-10-19 22:57:53 +02:00
haiyangcui
8b5e8fd072 IPTV添加group 2020-10-19 22:15:50 +02:00
haiyangcui
58e556554e IPTV搜索功能 2020-10-19 21:21:59 +02:00
haiyangcui
cceed30d35 IPTV拖曳功能 2020-10-19 13:46:59 +02:00
haiyangcui
980b0a6e50 el-table实现IPTV页面 2020-10-19 13:46:59 +02:00
Hunlongyu
c98236222d 🎡 修复 Film table 模式下, 不加载的 BUG 2020-10-19 18:37:48 +08:00
Hunlongyu
6a7c2afb2d 🎠 代码优化 2020-10-19 18:31:46 +08:00
Hunlongyu
af482a450a 🎟 新增右键菜单 2020-10-19 18:14:42 +08:00
Hunlongyu
42b81b98cf 🎞 修复 Film 视图报错 BUG 2020-10-19 17:42:00 +08:00
Hunlongyu
da7dfed5ba 🎁 修复视频停止播放后, 下次点击按钮失效的问题 2020-10-19 17:28:17 +08:00
Hunlongyu
7d6c5482af 🎀 新增窗口最小化, 暂停视频. 从最小化恢复窗口, 视频播放 2020-10-19 16:57:32 +08:00
Hunlongyu
11e7ffc554 🎑 新增视频停止播放按钮 2020-10-19 16:31:02 +08:00
Hunlongyu
4974d57fbf 🎑 mini 模式修复 2020-10-19 13:41:50 +08:00
Hunlongyu
037bb1a2ff 🎐 升级electron依赖到最新版 2020-10-19 13:40:12 +08:00
Hunlongyu
b19870d228 🎏 优化 table 滚动条 2020-10-19 11:52:28 +08:00
Hunlongyu
de0161c560 🎎 升级依赖, 修复element 2020-10-19 11:28:52 +08:00
Hunlongyu
623a10bd13 🎎 按需引入 element button 2020-10-19 11:09:14 +08:00
Hunlongyu
c69eadbe3e 🎍 新增清理视频缓存功能 2020-10-19 11:00:11 +08:00
Hunlongyu
5f48f46cbc 🎋 table style 2020-10-19 09:35:50 +08:00
haiyangcui
694986d6c5 用el-button实现header部分的按钮 2020-10-18 22:54:21 +02:00
haiyangcui
d4ad68e030 监听EditSites页面sites数据变化 2020-10-18 21:57:39 +02:00
haiyangcui
72089bf53f Code cleanup 2020-10-18 18:05:48 +02:00
haiyangcui
0401ce6d7e Revert "记录窗口大小及位置"
This reverts commit 381b0a8735.
2020-10-18 10:11:26 +02:00
haiyangcui
09e27d4f40 添加overflow-y: auto;到el-table格式定义中 2020-10-18 09:38:06 +02:00
haiyangcui
45de6650bf 统一EditSites页面格式 2020-10-17 23:59:58 +02:00
haiyangcui
4e0fa4d980 支持sites页面拖曳排序 2020-10-17 23:35:01 +02:00
haiyangcui
7a0f8f9644 支持star页面的拖曳排序 2020-10-17 21:19:05 +02:00
haiyangcui
e43ef98ce7 支持历史页面的拖曳排序 2020-10-17 21:11:50 +02:00
haiyangcui
2abbf41ed1 header上的按钮,鼠标划过更改指针模式 2020-10-17 18:37:49 +02:00
haiyangcui
02139d3d24 header部分加入padding 2020-10-17 18:34:27 +02:00
haiyangcui
d86a10d753 el-table实现EditSites页面 2020-10-17 18:09:17 +02:00
haiyangcui
dc8bdb29dc 解决有更新行高亮的问题 2020-10-17 14:12:24 +02:00
haiyangcui
98b019be5f 更新listpage样式 2020-10-17 13:55:04 +02:00
haiyangcui
e6d1698d62 删除star页面无用格式定义 2020-10-17 13:43:37 +02:00
haiyangcui
6c1e6c511f 删除无用的样式 2020-10-17 12:13:52 +02:00
haiyangcui
1a1393615c 套用listpage样式 2020-10-17 12:08:30 +02:00
cuiocean
5930690144 Merge pull request #292 from buvta/patch-3
el重写Star.vue,用排序替代拖拽
2020-10-17 12:07:09 +02:00
haiyangcui
091493fa77 定义listpage样式 2020-10-17 11:23:53 +02:00
buvta
cd1c4eaffe el重写Star.vue,用排序替代拖拽 2020-10-17 13:03:34 +08:00
cuiocean
1bb217d84f Merge pull request #289 from buvta/patch-4
去掉表格底部横线
2020-10-16 18:02:26 +02:00
buvta
92eac6d2dd 去掉表格底部横线 2020-10-16 23:49:12 +08:00
haiyangcui
b067cfa143 解决History页面自适应问题 2020-10-16 16:16:21 +02:00
haiyangcui
99d21fd7fe 设置不显示table的border,无需响应header-click打开关闭border 2020-10-16 14:46:24 +02:00
Hunlongyu
b167f711d0 🎄 修改历史界面样式 2020-10-16 18:03:20 +08:00
Hunlongyu
7d4ffeed87 🎃 移除 element 全局导入, 修改 star 样式 2020-10-16 18:00:13 +08:00
haiyangcui
7e94ef8025 更新el-table背景色 2020-10-15 22:30:54 +02:00
haiyangcui
1a36bc85b9 更新el-table背景色 2020-10-15 22:21:54 +02:00
haiyangcui
f7ed0e1c29 更新el-button的样式 2020-10-15 21:25:14 +02:00
cuiocean
970a359aba Merge pull request #280 from buvta/forPR1
改写History.vue
2020-10-15 21:15:31 +02:00
haiyangcui
be0441d042 设置不同主题下el-table的css样式 2020-10-15 21:12:42 +02:00
buvta
3fc350e6d6 el改写History.vue 2020-10-16 01:07:08 +08:00
buvta
b26a4d4f27 全局引入elementUI 2020-10-16 01:00:28 +08:00
haiyangcui
454ea48891 格式化Detail.vue 2020-10-14 23:02:02 +02:00
haiyangcui
d564d0928b 播放直播源时VideoTitle显示直播频道的名字 2020-10-13 22:08:40 +02:00
haiyangcui
2562119bad 支持导入源时multiSelections 2020-10-13 21:47:22 +02:00
haiyangcui
1a7aaa8dff 导入源时不删除原有源,但会检查源是否有重复,不添加重复的源 2020-10-13 21:44:24 +02:00
haiyangcui
583a768068 改进函数名 2020-10-12 18:26:27 +02:00
haiyangcui
6216ad96d6 源编辑页面添加清空功能 2020-10-12 18:25:24 +02:00
haiyangcui
766b1d458f IPTV添加置顶功能 2020-10-11 14:46:52 +02:00
haiyangcui
6a0699ec20 添加源置顶功能 2020-10-11 14:46:13 +02:00
haiyangcui
a6fd748e09 统一按钮名称和对话框名称 2020-10-11 13:47:18 +02:00
cuiocean
064ff38650 Merge pull request #271 from buvta/master
使用对话框新增或修改源
2020-10-11 13:39:25 +02:00
buvta
1c74174a3a 使用对话框新增或编辑源
bug已解决
2020-10-11 14:11:30 +08:00
haiyangcui
0625c4945f 支持'极品''喜欢看' 2020-10-11 00:05:49 +02:00
haiyangcui
d485a5733e 支持'喜欢看' 2020-10-10 10:15:09 +02:00
haiyangcui
5ab5cee6dc 支持'极品' 2020-10-09 21:06:11 +02:00
25 changed files with 1716 additions and 1014 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "zy",
"version": "2.5.2-1",
"version": "2.5.3",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
@@ -17,30 +17,30 @@
},
"main": "background.js",
"dependencies": {
"axios": "^0.19.2",
"axios": "^0.20.0",
"cheerio": "^1.0.0-rc.3",
"child_process": "^1.0.2",
"core-js": "^3.6.5",
"cors": "^2.8.5",
"dexie": "^3.0.1",
"dexie": "^3.0.2",
"electron-localshortcut": "^3.2.1",
"element-ui": "^2.13.2",
"express": "^4.17.1",
"fast-xml-parser": "^3.17.4",
"html2canvas": "^1.0.0-rc.5",
"html2canvas": "^1.0.0-rc.7",
"iptv-playlist-parser": "^0.5.0",
"m3u": "0.0.2",
"modern-normalize": "^0.6.0",
"modern-normalize": "^1.0.0",
"mousetrap": "^1.6.5",
"qrcode.vue": "^1.7.0",
"randomstring": "^1.1.5",
"vue": "^2.6.11",
"vue": "^2.6.12",
"vue-infinite-loading": "^2.4.5",
"vue-waterfall-plugin": "^1.0.7",
"vuedraggable": "^2.24.1",
"vuex": "^3.4.0",
"xgplayer": "^2.9.10",
"xgplayer-hls.js": "^2.2.3"
"vue-waterfall-plugin": "^1.1.0",
"vuedraggable": "^2.24.2",
"vuex": "^3.5.1",
"xgplayer": "^2.12.2",
"xgplayer-hls.js": "^2.2.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
@@ -50,7 +50,7 @@
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1",
"electron": "^9.3.1",
"electron": "^10.1.4",
"electron-devtools-installer": "^3.1.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
@@ -61,6 +61,6 @@
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-cli-plugin-electron-builder": "2.0.0-rc.4",
"vue-template-compiler": "^2.6.11"
"vue-template-compiler": "^2.6.12"
}
}

View File

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

View File

@@ -124,6 +124,12 @@
flex: 1;
border-bottom: 1px solid;
overflow: auto;
.el-table__row td{
border: none;
}
.el-table::before{
height: 0px;
}
ul{
list-style: none;
padding: 0;
@@ -189,6 +195,63 @@
position: absolute;
}
}
// Page of list using el-table
.listpage{
position: absolute;
left: 80px;
right: 20px;
top: 40px;
bottom: 20px;
width: calc(100% - 100px);
height: calc(100% - 60px);
border-radius: 5px;
.listpage-content{
height: 100%;
position: relative;
.listpage-header{
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 50px;
padding-right: 50px;
.btn{
&:hover{
cursor: pointer;
}
}
.el-button{
border: none;
&:hover{
cursor: pointer;
}
}
.el-input{
width: 200px;
}
}
.listpage-body{
height: calc(100% - 40px);
overflow-y: auto;
.el-table::before{
height: 0px;
}
.el-table{
height: 100%;
overflow-y: auto;
}
.el-table__body td,.el-table__body th{
height: 50px;
border-bottom: 1px solid;
}
.el-table .highlight{
color: var(--highlight-color) !important;
}
}
}
}
// loading
.zy-loading{
width: 100%;
@@ -233,4 +296,19 @@
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
}
}
}
.el-table, .el-table__body-wrapper{
&::-webkit-scrollbar{
width: 5px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 10px;
position: absolute;
}
&::-webkit-scrollbar-track {
border-radius: 10px;
position: absolute;
}
}

View File

@@ -65,7 +65,7 @@
--p-c-9: #f4f7f799;
--p-fc-1: #ffffff;
--p-fc-2: #FFFFF3;
--p-fc-3: #f15c5c;
--p-fc-3: #177ea7;
--p-bgc-1: #ff8499;
--p-bgc-2: #fea1b2;
--p-bsc: 0 1px 3px #ef528533, 0 1px 2px #ef528544;

View File

@@ -62,7 +62,9 @@
border-bottom-color: var(--d-c-2);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
&:hover{
box-shadow: var(--d-bsc-hover);
box-shadow: var(--d-bsc);
background-color: var(--d-bgc-2);
color: #fff;
}
span{
&.btn:hover{
@@ -353,4 +355,53 @@
background-color: var(--d-bgc-1);
box-shadow: var(--d-bsc);
}
// Page of list using el-table
.listpage{
color: var(--d-fc-2);
.listpage-content{
.listpage-header{
border-bottom-color: var(--d-c-3);
.btn{
&:hover{
color: var(--d-fc-3)
}
}
.el-button{
background-color: var(--d-bgc-2);
color: var(--d-fc-2);
&:hover{
color: var(--d-fc-3)
}
}
.el-input{
input{
background-color: var(--d-bgc-1);
border: 1px solid var(--d-bgc-1);
color: var(--d-fc-2);
}
}
}
.listpage-body{
/* 设置el-table的样式*/
.el-table{
color: var(--d-fc-1);
background-color: var(--d-bgc-1);
}
.el-table__header th, .el-table__header tr, .el-table__body td,.el-table__body th{
color: var(--d-fc-1);
background-color: var(--d-bgc-1);
border-bottom-color: var(--d-c-2);
}
.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: var(--d-bgc-2);
}
.el-button{
color: var(--d-fc-1);
&:hover{
color: var(--d-fc-3)
}
}
}
}
}
}

View File

@@ -250,7 +250,7 @@
color: var(--g-fc-3);
}
&:hover{
background-color: var(--d-c-3);
background-color: var(--g-c-3);
}
}
}
@@ -351,4 +351,53 @@
background-color: var(--g-bgc-1);
box-shadow: var(--g-bsc);
}
// Page of list using el-table
.listpage{
color: var(--g-fc-2);
.listpage-content{
.listpage-header{
border-bottom-color: var(--g-c-3);
.btn{
&:hover{
color: var(--g-fc-3)
}
}
.el-button{
background-color: var(--g-bgc-2);
color: var(--g-fc-2);
&:hover{
color: var(--g-fc-3)
}
}
.el-input{
input{
background-color: var(--g-bgc-1);
border: 1px solid var(--g-bgc-1);
color: var(--g-fc-2);
}
}
}
.listpage-body{
/* 设置el-table的样式*/
.el-table{
color: var(--g-fc-1);
background-color: var(--g-bgc-1);
}
.el-table__header th, .el-table__header tr, .el-table__body td,.el-table__body th{
color: var(--g-fc-1);
background-color: var(--g-bgc-1);
border-bottom-color: var(--g-c-2);
}
.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: var(--g-bgc-2);
}
.el-button{
color: var(--g-fc-1);
&:hover{
color: var(--g-fc-3)
}
}
}
}
}
}

View File

@@ -250,7 +250,7 @@
color: var(--l-fc-3);
}
&:hover{
background-color: var(--d-c-3);
background-color: var(--l-c-3);
}
}
}
@@ -351,4 +351,53 @@
background-color: var(--l-bgc-1);
box-shadow: var(--l-bsc);
}
// Page of list using el-table
.listpage{
color: var(--l-fc-2);
.listpage-content{
.listpage-header{
border-bottom-color: var(--l-c-3);
.btn{
&:hover{
color: var(--l-fc-3)
}
}
.el-button{
background-color: var(--l-bgc-2);
color: var(--l-fc-2);
&:hover{
color: var(--l-fc-3)
}
}
.el-input{
input{
background-color: var(--l-bgc-1);
border: 1px solid var(--l-bgc-1);
color: var(--l-fc-2);
}
}
}
.listpage-body{
/* 设置el-table的样式*/
.el-table{
color: var(--l-fc-1);
background-color: var(--l-bgc-1);
}
.el-table__header th, .el-table__header tr, .el-table__body td,.el-table__body th{
color: var(--l-fc-1);
background-color: var(--l-bgc-1);
border-bottom-color: var(--l-c-2);
}
.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: var(--l-bgc-2);
}
.el-button{
color: var(--l-fc-1);
&:hover{
color: var(--l-fc-3)
}
}
}
}
}
}

View File

@@ -249,7 +249,7 @@
color: var(--p-fc-3);
}
&:hover{
background-color: var(--d-c-3);
background-color: var(--p-c-3);
}
}
}
@@ -350,4 +350,53 @@
background-color: var(--p-bgc-1);
box-shadow: var(--p-bsc);
}
// Page of list using el-table
.listpage{
color: var(--p-fc-2);
.listpage-content{
.listpage-header{
border-bottom-color: var(--p-c-3);
.btn{
&:hover{
color: var(--p-fc-3)
}
}
.el-button{
background-color: var(--p-bgc-2);
color: var(--p-fc-2);
&:hover{
color: var(--p-fc-3)
}
}
.el-input{
input{
background-color: var(--p-bgc-1);
border: 1px solid var(--p-bgc-1);
color: var(--p-fc-2);
}
}
}
.listpage-body{
/* 设置el-table的样式*/
.el-table{
color: var(--p-fc-1);
background-color: var(--p-bgc-1);
}
.el-table__header th, .el-table__header tr, .el-table__body td,.el-table__body th{
color: var(--p-fc-1);
background-color: var(--p-bgc-1);
border-bottom-color: var(--p-c-2);
}
.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: var(--p-bgc-2);
}
.el-button{
color: var(--p-fc-1);
&:hover{
color: var(--p-fc-3)
}
}
}
}
}
}

View File

@@ -22,6 +22,7 @@ function createWindow () {
resizable: true,
webPreferences: {
webSecurity: false,
enableRemoteModule: true,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
}
})
@@ -49,6 +50,7 @@ function createMini () {
resizable: true,
webPreferences: {
webSecurity: false,
enableRemoteModule: true,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
}
})

View File

@@ -83,15 +83,10 @@ export default {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_EDITSITES']),
changeView (e) {
this.view = e
// ChangeView 的时候关闭Detail和EditSites页面
// ChangeView 的时候关闭Detail页面
this.detail = {
show: false
}
if (this.editSites.show === true) {
this.editSites = {
show: false
}
}
}
}
}

View File

@@ -4,7 +4,14 @@
<div class="detail-header">
<span class="detail-title">详情</span>
<span class="detail-close zy-svg" @click="close">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="closeIconTitle">
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
aria-labelledby="closeIconTitle"
>
<title id="closeIconTitle">关闭</title>
<path d="M6.34314575 6.34314575L17.6568542 17.6568542M6.34314575 17.6568542L17.6568542 6.34314575"></path>
</svg>
@@ -44,7 +51,8 @@
</select>
</span>
</div>
<div class="desc" v-show="info.des">{{info.des}}</div>
<div
class="desc" v-show="info.des">{{info.des}}</div>
<div class="m3u8">
<div class="box">
<span v-for="(i, j) in m3u8List" :key="j" @click="playEvent(j)">{{i | ftName}}</span>
@@ -72,7 +80,7 @@ export default {
info: {},
playOnline: false,
selectedOnlineSite: '哔嘀',
onlineSites: ['哔嘀', '素白白', '简影', '1080影视']
onlineSites: ['哔嘀', '素白白', '简影', '极品', '喜欢看', '1080影视']
}
},
filters: {
@@ -162,7 +170,7 @@ export default {
history.add(doc)
}
})
this.playVideoOnline(this.detail.info.name, n)
onlineVideo.playVideoOnline(this.selectedOnlineSite, this.detail.info.name, n)
}
},
starEvent () {
@@ -210,6 +218,9 @@ export default {
case '简影':
onlineVideo.playVideoOnSyrme(videoName, videoIndex)
break
case '极品':
onlineVideo.playVideoOnJpysvip(videoName, videoIndex)
break
default:
this.$message.console.error(`不支持该网站:${this.selectedOnlineSite}`)
}
@@ -326,7 +337,7 @@ export default {
}
</script>
<style lang="scss" scoped>
.detail{
.detail {
position: absolute;
left: 80px;
right: 20px;
@@ -334,28 +345,28 @@ export default {
width: calc(100% - 100px);
height: calc(100% - 40px);
z-index: 888;
.detail-content{
.detail-content {
height: calc(100% - 10px);
padding: 0 60px;
position: relative;
.detail-header{
.detail-header {
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.detail-title{
.detail-title {
font-size: 16px;
}
.detail-close{
.detail-close {
cursor: pointer;
}
}
}
.detail-body{
.detail-body {
height: calc(100% - 50px);
overflow-y: auto;
.info{
.info {
width: 100%;
padding: 10px;
display: flex;
@@ -366,47 +377,54 @@ export default {
border-radius: 2px;
margin-bottom: 10px;
height: auto;
.info-left{
.info-left {
width: 200px;
height: 100%;
img{
img {
width: 100%;
height: auto;
}
}
.info-right{
.info-right {
flex: 1;
margin-left: 20px;
.name{
.name {
font-size: 20px;
margin-bottom: 10px;
font-weight: bold;
}
.director, .actor, .type, .area, .lang, .year, .last, .note{
.director,
.actor,
.type,
.area,
.lang,
.year,
.last,
.note {
font-size: 14px;
line-height: 26px;
}
.rate{
.rate {
font-size: 16px;
line-height: 26px;
font-weight: bolder;
}
}
}
.operate{
.operate {
border: 1px solid;
padding: 10px;
width: 100%;
margin-bottom: 10px;
border-radius: 2px;
span{
span {
margin-right: 20px;
font-size: 14px;
cursor: pointer;
user-select: none;
}
}
.desc{
.desc {
border: 1px solid;
padding: 10px;
width: 100%;
@@ -415,15 +433,15 @@ export default {
font-size: 14px;
line-height: 20px;
}
.m3u8{
.m3u8 {
border: 1px solid;
padding: 10px 0 10px 10px;
width: 100%;
margin-bottom: 10px;
border-radius: 2px;
.box{
.box {
width: 100%;
span{
span {
display: inline-block;
font-size: 12px;
border: 1px solid;
@@ -435,7 +453,7 @@ export default {
}
}
}
.detail-mask{
.detail-mask {
position: absolute;
top: 50px;
left: 0;
@@ -457,28 +475,37 @@ export default {
@keyframes load4 {
0%,
100% {
box-shadow: 0 -3em 0 0.2em, 2em -2em 0 0em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 0;
box-shadow: 0 -3em 0 0.2em, 2em -2em 0 0em, 3em 0 0 -1em, 2em 2em 0 -1em,
0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 0;
}
12.5% {
box-shadow: 0 -3em 0 0, 2em -2em 0 0.2em, 3em 0 0 0, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
box-shadow: 0 -3em 0 0, 2em -2em 0 0.2em, 3em 0 0 0, 2em 2em 0 -1em,
0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
}
25% {
box-shadow: 0 -3em 0 -0.5em, 2em -2em 0 0, 3em 0 0 0.2em, 2em 2em 0 0, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
box-shadow: 0 -3em 0 -0.5em, 2em -2em 0 0, 3em 0 0 0.2em, 2em 2em 0 0,
0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
}
37.5% {
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 0, 2em 2em 0 0.2em, 0 3em 0 0em, -2em 2em 0 -1em, -3em 0em 0 -1em, -2em -2em 0 -1em;
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 0, 2em 2em 0 0.2em,
0 3em 0 0em, -2em 2em 0 -1em, -3em 0em 0 -1em, -2em -2em 0 -1em;
}
50% {
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 0em, 0 3em 0 0.2em, -2em 2em 0 0, -3em 0em 0 -1em, -2em -2em 0 -1em;
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 0em,
0 3em 0 0.2em, -2em 2em 0 0, -3em 0em 0 -1em, -2em -2em 0 -1em;
}
62.5% {
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 0, -2em 2em 0 0.2em, -3em 0 0 0, -2em -2em 0 -1em;
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em,
0 3em 0 0, -2em 2em 0 0.2em, -3em 0 0 0, -2em -2em 0 -1em;
}
75% {
box-shadow: 0em -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0.2em, -2em -2em 0 0;
box-shadow: 0em -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 -1em,
2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0.2em,
-2em -2em 0 0;
}
87.5% {
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em,
0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
}
}
}

View File

@@ -1,100 +1,94 @@
<template>
<div class="detail">
<div class="detail-content">
<div class="detail-header">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="openAddSite">添加新源</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportSites">导出</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importSites">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="resetSites">重置</div>
</div>
<span class="detail-close zy-svg" @click="close">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="closeIconTitle">
<title id="closeIconTitle">关闭</title>
<path d="M6.34314575 6.34314575L17.6568542 17.6568542M6.34314575 17.6568542L17.6568542 6.34314575"></path>
</svg>
</span>
</div>
<div class="detail-body zy-scroll">
<div class="zy-table">
<div class="tBody zy-scroll">
<div class="addSites-box zy-scroll" v-show="showAddSite">
<ul>
<li >
<span class="name">源名称</span>
<span class="name">API接口</span>
<span class="name">DOWNLOAD接口</span>
<span class="operate">
<span class="btn"></span>
<span class="btn"></span>
</span>
</li>
<li>
<span class="name" style="display:inline-block;vertical-align:middle">
<input style="height: 30px" v-model="newSite.name">
</span>
<span class="name" style="display:inline-block;vertical-align:middle">
<input style="height: 30px" v-model="newSite.api">
</span>
<span class="name" style="display:inline-block;vertical-align:middle">
<input style="height: 30px" v-model="newSite.download" placeholder="可以为空">
</span>
<span class="operate">
<span class="btn" @click="addNewSite">添加</span>
<span class="btn" @click="closeAddSite">关闭</span>
</span>
</li>
<li ></li>
</ul>
</div>
<ul>
<draggable v-model="sites" @change="listUpdatedEvent">
<transition-group>
<li v-for="(i, j) in sites" :key="j">
<span class="name">{{i.name}}</span>
<span class="operate">
<span class="btn" @click.stop="removeEvent(i)">删除</span>
</span>
</li>
</transition-group>
</draggable>
</ul>
</div>
</div>
<div class="listpage" id="editSites">
<div class="listpage-content">
<div class="listpage-header">
<el-button @click.stop="addSite" type="text">添加</el-button>
<el-button @click.stop="exportSites" type="text">导出</el-button>
<el-button @click.stop="importSites" type="text">导入</el-button>
<el-button @click.stop="removeAllSites" type="text">清空</el-button>
<el-button @click.stop="resetSitesEvent" type="text">重置</el-button>
</div>
<div class="listpage-body" id="sites-table">
<el-table
:data="sites"
row-key="id"
style="width: 100%">
<el-table-column
prop="name"
label="资源名"
min-width="200">
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="140">
<template slot-scope="scope">
<el-button @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
<el-button @click.stop="editSite(scope.row)" type="text">编辑</el-button>
<el-button @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 编辑页面 -->
<div>
<el-dialog :visible.sync="dialogVisible" v-if='dialogVisible' :title="dialogType==='edit'?'编辑源':'添加源'" :append-to-body="true" @close="closeDialog">
<el-form :model="siteInfo" ref='siteInfo' label-width="75px" label-position="left" :rules="rules">
<el-form-item label="源站名" prop='name'>
<el-input v-model="siteInfo.name" placeholder="请输入源站名" />
</el-form-item>
<el-form-item label="API接口" prop='api'>
<el-input v-model="siteInfo.api" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="请输入API接口地址"/>
</el-form-item>
<el-form-item label="下载接口" prop='download'>
<el-input v-model="siteInfo.download" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="请输入Download接口地址可以空着"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="addOrEditSite">保存</el-button>
</span>
</el-dialog>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { sites, setting } from '../lib/dexie'
import draggable from 'vuedraggable'
import { sites } from '../lib/dexie'
import { remote } from 'electron'
import { sites as defaultSites } from '../lib/dexie/initData'
import fs from 'fs'
import Sortable from 'sortablejs'
export default {
name: 'editSites',
data () {
return {
show: false,
sites: [],
showAddSite: false,
newSite: {
dialogType: 'new',
dialogVisible: false,
siteInfo: {
name: '',
api: '',
download: ''
},
rules: {
name: [
{ required: true, message: '源站名不能为空', trigger: 'blur' }
],
api: [
{ required: true, message: 'API地址不能为空', trigger: 'blur' }
],
download: [
{ required: false, trigger: 'blur' }
]
}
}
},
components: {
draggable
},
computed: {
setting: {
get () {
@@ -115,13 +109,31 @@ export default {
},
methods: {
...mapMutations(['SET_SETTING', 'SET_EDITSITES']),
close () {
this.editSites.show = false
},
getSites () {
sites.all().then(res => {
this.sites = res
})
this.editSites = {
sites: this.sites
}
},
addSite () {
this.dialogType = 'new'
this.dialogVisible = true
this.siteInfo = {
name: '',
api: '',
download: ''
}
},
editSite (siteInfo) {
this.dialogType = 'edit'
this.dialogVisible = true
this.siteInfo = siteInfo
},
closeDialog () {
this.dialogVisible = false
this.getSites()
},
removeEvent (e) {
sites.remove(e.id).then(res => {
@@ -141,32 +153,28 @@ export default {
})
})
},
openAddSite () {
this.showAddSite = true
},
closeAddSite () {
this.showAddSite = false
},
addNewSite () {
if (!this.newSite.name || !this.newSite.api) {
addOrEditSite () {
if (!this.siteInfo.name || !this.siteInfo.api) {
this.$message.error('名称和API接口不能为空。')
return
}
var randomstring = require('randomstring')
var doc = {
key: randomstring.generate(6),
id: this.sites[this.sites.length - 1].id + 1,
name: this.newSite.name,
api: this.newSite.api,
download: this.newSite.download
key: this.dialogType === 'edit' ? this.siteInfo.key : randomstring.generate(6),
id: this.dialogType === 'edit' ? this.siteInfo.id : this.sites[this.sites.length - 1].id + 1,
name: this.siteInfo.name,
api: this.siteInfo.api,
download: this.siteInfo.download
}
if (this.dialogType === 'edit') sites.remove(this.siteInfo.id)
sites.add(doc).then(res => {
this.newSite = {
this.siteInfo = {
name: '',
api: '',
download: ''
}
this.$message.success('添加新源成功!')
this.dialogType === 'edit' ? this.$message.success('修改成功!') : this.$message.success('添加新源成功!')
this.dialogVisible = false
this.getSites()
})
},
@@ -197,72 +205,71 @@ export default {
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
],
properties: ['openFile']
properties: ['openFile', 'multiSelections']
}
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.bulkAdd(json).then(e => {
this.getSites()
this.d.site = json[0].key
setting.update(this.d).then(res => {
this.setting = this.d
})
json.forEach(ele => {
if (this.sites.filter(x => x.key === ele.key).length === 0 && this.sites.filter(x => x.name === ele.name && x.url === ele.url).length === 0) {
// 不含该key 同时也不含名字和url一样的
this.sites.push(ele)
}
})
this.resetId(this.sites)
sites.clear().then(sites.bulkAdd(this.sites))
this.$message.success('导入成功')
}).catch(err => {
this.$message.error(err)
})
}
})
},
resetSites () {
sites.clear()
sites.bulkAdd(defaultSites).then(e => {
this.getSites()
this.$message.success('重置源成功')
resetSitesEvent () {
sites.clear().then(sites.bulkAdd(defaultSites).then(this.getSites()))
this.$message.success('重置源成功')
},
moveToTopEvent (i) {
this.sites.sort(function (x, y) { return x.key === i.key ? -1 : y.key === i.key ? 1 : 0 })
this.updateDatabase(this.sites)
},
resetId (inArray) {
var id = 1
inArray.forEach(ele => {
ele.id = id
id += 1
})
},
updateDatabase (data) {
sites.clear().then(res => {
var id = 1
data.forEach(ele => {
ele.id = id
id += 1
})
sites.bulkAdd(data).then(this.getSites())
})
},
removeAllSites () {
sites.clear().then(this.getSites())
},
rowDrop () {
const tbody = document.getElementById('sites-table').querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.sites.splice(oldIndex, 1)[0]
_this.sites.splice(newIndex, 0, currRow)
_this.updateDatabase(_this.sites)
}
})
}
},
mounted () {
this.rowDrop()
},
created () {
this.getSites()
}
}
</script>
<style lang="scss" scoped>
.detail{
position: absolute;
left: 80px;
right: 20px;
bottom: 0;
width: calc(100% - 100px);
height: calc(100% - 40px);
z-index: 888;
.detail-content{
height: calc(100% - 10px);
padding: 0 60px;
position: relative;
.detail-header{
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.detail-title{
font-size: 16px;
}
.detail-close{
cursor: pointer;
}
}
}
.detail-body{
height: calc(100% - 50px);
overflow-y: auto;
}
}
</style>

View File

@@ -75,7 +75,7 @@
</span>
</li>
</ul>
<infinite-loading force-use-infinite-wrapper="tBody" :identifier="infiniteId" @infinite="infiniteHandler"></infinite-loading>
<infinite-loading force-use-infinite-wrapper :identifier="infiniteId" @infinite="infiniteHandler"></infinite-loading>
</div>
</div>
</div>
@@ -123,8 +123,6 @@ export default {
class: false,
classList: false,
search: false,
img: true,
table: false,
find: false
},
sites: [],
@@ -180,6 +178,9 @@ export default {
},
setting () {
return this.$store.getters.getSetting
},
sitesList () {
return this.$store.getters.getEditSites.sites // 需要监听的数据
}
},
watch: {
@@ -189,7 +190,7 @@ export default {
searchTxt () {
this.searchChangeEvent()
},
'$store.state.editSites.sites': function () {
sitesList () {
this.getAllsites()
}
},
@@ -388,13 +389,11 @@ export default {
},
changeView () {
if (this.view === 'Film') {
if (this.show.img) {
if (this.setting.view === 'picture') {
this.$refs.waterfall.refresh()
}
this.getPage().then(() => {
this.infiniteId += 1
if (this.show.img || this.show.table) {
}
})
}
},
@@ -464,7 +463,7 @@ export default {
this.show.class = true
this.searchContents = []
this.show.find = false
if (this.show.img) {
if (this.setting.view === 'picture') {
this.$refs.waterfall.refresh()
}
}

View File

@@ -1,52 +1,65 @@
<template>
<div class="history">
<div class="body zy-scroll">
<div class="zy-table">
<div class="tHeader">
<span class="btn"></span>
<span class="btn" @click="clearAllHistory">清空</span>
</div>
<div class="tBody zy-scroll">
<ul>
<li v-show="this.history.length === 0">无数据</li>
<li v-show="this.history.length > 0">
<span class="name">名字</span>
<span class="site">片源</span>
<span class="note">观看至</span>
<span class="operate">
<span class="btn"></span>
<span class="btn"></span>
<span class="btn"></span>
<span class="btn"></span>
</span>
</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 class="listpage" id="history">
<div class="listpage-content">
<div class="listpage-header">
<span class="btn"></span>
<el-button @click.stop="clearAllHistory" type="text">清空</el-button>
</div>
<div class="listpage-body" id="history-table">
<el-table
:data="history"
row-key="id"
@row-click="detailEvent"
style="width: 100%">
<el-table-column
prop="name"
label="片名"
min-width="200">
</el-table-column>
<el-table-column
prop="site"
label="片源"
width="120">
<template slot-scope="scope">
<span>{{ getSiteName(scope.row.site) }}</span>
</template>
</el-table-column>
<el-table-column
prop="index"
label="观看至">
<template slot-scope="scope">
<span>{{ scope.row.index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="180">
<template slot-scope="scope">
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
<el-button @click.stop="downloadEvent(scope.row)" type="text">下载</el-button>
<el-button @click.stop="removeHistoryItem(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { history, sites } from '../lib/dexie'
import zy from '../lib/site/tools'
import Sortable from 'sortablejs'
const { clipboard } = require('electron')
export default {
name: 'history',
data () {
return {
history: history,
history: [],
sites: []
}
},
@@ -182,44 +195,40 @@ export default {
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)
})
},
updateDatabase (data) {
history.clear().then(res => {
var id = length
data.forEach(ele => {
ele.id = id
id -= 1
history.add(ele)
})
})
},
rowDrop () {
const tbody = document.getElementById('history-table').querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.history.splice(oldIndex, 1)[0]
_this.history.splice(newIndex, 0, currRow)
_this.updateDatabase(_this.history)
}
})
}
},
mounted () {
this.rowDrop()
},
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

@@ -1,54 +1,52 @@
<template>
<div class="detail">
<div class="detail-content">
<div class="detail-header">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportSites">导出</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importSites">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="removeAllSites">清空</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="resetSites">重置</div>
</div>
<div style="width: 200px; height: 30px;">
</div>
<div class="listpage" id="IPTV">
<div class="listpage-content">
<div class="listpage-header">
<el-button type="text">总频道数:{{iptvList.length}}</el-button>
<el-button @click.stop="exportChannels" type="text">导出</el-button>
<el-button @click.stop="importChannels" type="text">导入</el-button>
<el-button @click.stop="removeAllChannels" type="text">清空</el-button>
<el-button @click.stop="resetChannelsEvent" type="text">重置</el-button>
<el-input
placeholder="搜索"
size="mini"
v-model.trim="searchTxt">
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
</div>
<div class="detail-header">
<div>
<div class="vs-placeholder vs-noAfter" @click="exportSites">总频道数:{{iptvList.length}}</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(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="searchEvent(i.keywords)">{{i.keywords}}</li>
<li v-show="searchList.length >= 1" @click="clearSearch">清空历史记录</li>
</ul>
</div>
</div>
</div>
<div class="detail-body zy-scroll">
<div class="zy-table">
<div class="tBody zy-scroll">
<ul>
<draggable v-model="iptvList" @change="listUpdatedEvent">
<transition-group>
<li v-for="(i, j) in iptvList" :key="j" @click.stop="playEvent(i)" v-show="containsearchTxt(i)">
<span class="name">{{i.name}}</span>
<span class="operate">
<span class="btn" @click.stop="playEvent(i)">播放</span>
<span class="btn" @click.stop="removeEvent(i)">删除</span>
</span>
</li>
</transition-group>
</draggable>
</ul>
</div>
</div>
<div class="listpage-body" id="iptv-table">
<el-table
:data="filteredTableData"
row-key="id"
@row-click="playEvent"
style="width: 100%">
<el-table-column
prop="name"
label="频道名"
min-width="200">
</el-table-column>
<el-table-column
prop="group"
label="分组"
width="100"
:filters="getFilters"
:filter-method="filterHandle"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-button type="text">{{scope.row.group}}</el-button>
</template>
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="140">
<template slot-scope="scope">
<el-button @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
<el-button @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
@@ -56,25 +54,22 @@
<script>
import { mapMutations } from 'vuex'
import { iptv, iptvSearch } from '../lib/dexie'
import draggable from 'vuedraggable'
import { iptv as defaultSites } from '../lib/dexie/initData'
import { remote } from 'electron'
import fs from 'fs'
import Sortable from 'sortablejs'
export default {
name: 'iptv',
data () {
return {
iptvList: [],
searchTxt: '',
searchList: [],
searchRecordList: [],
show: {
search: false
}
}
},
components: {
draggable
},
computed: {
view: {
get () {
@@ -94,11 +89,30 @@ export default {
set (val) {
this.SET_VIDEO(val)
}
},
filteredTableData () {
if (this.searchTxt) {
return this.iptvList.filter(x => x.name.toLowerCase().includes(this.searchTxt.toLowerCase()))
} else {
return this.iptvList
}
},
getFilters () {
const groups = [...new Set(this.iptvList.map(iptv => iptv.group))]
var filters = []
groups.forEach(g => {
var doc = {
text: g,
value: g
}
filters.push(doc)
})
return filters
}
},
watch: {
view () {
this.getAllSites()
this.getChannels()
},
searchTxt () {
}
@@ -109,6 +123,9 @@ export default {
this.video = { iptv: { name: e.name, url: e.url } }
this.view = 'Play'
},
filterHandle (value, row) {
return row.group === value
},
containsearchTxt (i) {
if (this.searchTxt) {
return i.name.toLowerCase().includes(this.searchTxt.toLowerCase())
@@ -118,7 +135,7 @@ export default {
},
removeEvent (e) {
iptv.remove(e.id).then(res => {
this.getAllSites()
this.getChannels()
}).catch(err => {
this.$message.warning('删除频道失败, 错误信息: ' + err)
})
@@ -134,7 +151,7 @@ export default {
})
})
},
exportSites () {
exportChannels () {
const options = {
filters: [
{ name: 'm3u file', extensions: ['m3u'] },
@@ -152,7 +169,7 @@ export default {
this.$message.success('已保存成功')
} else {
const arr = [...this.iptvList]
const str = JSON.stringify(arr, null, 4)
const str = JSON.stringify(arr, null, 2)
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
@@ -161,7 +178,7 @@ export default {
this.$message.error(err)
})
},
importSites () {
importChannels () {
const options = {
filters: [
{ name: 'm3u file', extensions: ['m3u', 'm3u8'] }
@@ -171,6 +188,7 @@ export default {
remote.dialog.showOpenDialog(options).then(result => {
if (!result.canceled) {
var docs = this.iptvList
var id = docs.length
result.filePaths.forEach(file => {
const parser = require('iptv-playlist-parser')
const playlist = fs.readFileSync(file, { encoding: 'utf-8' })
@@ -178,9 +196,12 @@ export default {
result.items.forEach(ele => {
if (ele.name && ele.url && ele.url.includes('.m3u8')) {
var doc = {
id: id,
name: ele.name,
url: ele.url
url: ele.url,
group: this.determineGroup(ele.group, ele.name)
}
id += 1
docs.push(doc)
}
})
@@ -189,37 +210,49 @@ export default {
const uniqueList = [...new Map(docs.map(item => [item.url, item])).values()]
iptv.clear().then(res => {
iptv.bulkAdd(uniqueList).then(e => {
this.getAllSites()
this.getChannels()
this.$message.success('导入成功')
})
})
}
})
},
resetSites () {
iptv.clear()
iptv.bulkAdd(defaultSites).then(e => {
this.getAllSites()
})
determineGroup (group, name) {
if (!group) {
return group
} else if (name.toLowerCase().includes('cctv')) {
return '央视'
} else if (name.includes('卫视')) {
return '卫视'
} else {
return '其他'
}
},
removeAllSites () {
resetChannelsEvent () {
this.resetChannels(defaultSites)
},
resetChannels (newSites) {
this.resetId(newSites)
iptv.clear().then(iptv.bulkAdd(newSites).then(this.getChannels()))
},
removeAllChannels () {
iptv.clear().then(res => {
this.getAllSites()
this.getChannels()
})
},
getAllSites () {
getChannels () {
iptv.all().then(res => {
this.iptvList = res
})
},
getAllSearch () {
getSearchRecordList () {
iptvSearch.all().then(res => {
this.searchList = res.reverse()
this.searchRecordList = res.reverse()
})
},
clearSearch () {
iptvSearch.clear().then(res => {
this.getAllSearch()
this.getSearchRecordList()
})
},
searchEvent (wd) {
@@ -230,47 +263,45 @@ export default {
if (!res) {
iptvSearch.add({ keywords: wd })
}
this.getAllSearch()
this.getSearchRecordList()
})
}
},
moveToTopEvent (i) {
this.iptvList.sort(function (x, y) { return (x.name === i.name && x.url === i.url) ? -1 : (y.name === i.name && y.url === i.url) ? 1 : 0 })
this.updateDatabase(this.iptvList)
},
updateDatabase (data) {
iptv.clear().then(res => {
this.resetId(data)
iptv.bulkAdd(data).then(this.getChannels())
})
},
resetId (inArray) {
var id = 1
inArray.forEach(ele => {
ele.id = id
id += 1
})
},
rowDrop () {
const tbody = document.getElementById('iptv-table').querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.iptvList.splice(oldIndex, 1)[0]
_this.iptvList.splice(newIndex, 0, currRow)
_this.updateDatabase(_this.iptvList)
}
})
}
},
mounted () {
this.rowDrop()
},
created () {
this.getAllSites()
this.getAllSearch()
this.getChannels()
this.getSearchRecordList()
}
}
</script>
<style lang="scss" scoped>
.detail{
position: absolute;
left: 80px;
right: 20px;
bottom: 0;
width: calc(100% - 100px);
height: calc(100% - 40px);
z-index: 888;
.detail-content{
height: calc(100% - 10px);
padding: 0 60px;
position: relative;
.detail-header{
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.detail-title{
font-size: 16px;
}
.detail-close{
cursor: pointer;
}
}
}
.detail-body{
height: calc(100% - 100px);
overflow-y: auto;
}
}
</style>

View File

@@ -189,6 +189,7 @@ export default {
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5],
playPrev: true,
playNextOne: true,
videoStop: true,
showList: true,
showHistory: true,
videoTitle: true
@@ -292,14 +293,14 @@ export default {
clearInterval(this.timer)
this.timer = null
}
if (this.xg) {
if (this.xg.hasStart) {
this.xg.pause()
}
if (this.xg && this.xg.hasStart) {
this.xg.pause()
}
if (this.video.iptv) {
// 是直播源,直接播放
this.playUrl(this.video.iptv.url)
this.name = this.video.iptv.name
this.getIptvList()
} else {
const index = this.video.info.index | 0
@@ -989,6 +990,10 @@ export default {
this.toggleHistory()
})
this.xg.on('videoStop', () => {
this.videoStop()
})
const ev = ['click', 'touchend', 'mousemove']
let timerID
ev.forEach(item => {
@@ -1011,6 +1016,61 @@ export default {
this.xg.on('exitFullscreen', () => {
document.querySelector('.xg-view-videoTitle').style.display = 'none'
})
},
videoStop () {
if (this.xg.fullscreen) {
this.xg.exitFullscreen()
}
this.xg.destroy()
this.config.src = ''
this.name = ''
this.right.list = []
this.showNext = false
setTimeout(() => {
this.playerInstall()
this.xg = new Hls(this.config)
this.bindEvent()
}, 500)
},
minMaxEvent () {
const win = remote.getCurrentWindow()
win.on('minimize', () => {
if (this.xg && this.xg.hasStart) {
this.xg.pause()
}
})
win.on('restore', () => {
if (this.xg && this.config.src) {
this.xg.play()
}
})
},
playerInstall () {
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('videoStop', function () {
addPlayerBtn.bind(this, 'videoStop', '<svg t="1603093629102" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3621" style="width: 25px;height: 25px;margin-top: 8px;margin-left: 0px;"><path d="M768 768H256V256h512v512z" p-id="3622" fill="#ffffff"></path></svg>', { title: '停止播放' })()
})
Player.install('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>`, {})()
})
}
},
created () {
@@ -1018,29 +1078,7 @@ 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.playerInstall()
this.xg = new Hls(this.config)
ipcRenderer.on('miniClosed', () => {
history.find({ site: this.video.key, ids: this.video.info.id }).then(res => {
@@ -1054,6 +1092,7 @@ export default {
})
})
this.bindEvent()
this.minMaxEvent()
},
beforeDestroy () {
clearInterval(this.timer)
@@ -1061,7 +1100,11 @@ export default {
}
</script>
<style>
.xgplayer-skin-default .xg-btn-playPrev {
.xgplayer-skin-default .xg-btn-playPrev,
.xgplayer-skin-default .xg-btn-playNextOne,
.xgplayer-skin-default .xg-btn-showList,
.xgplayer-skin-default .xg-btn-showHistory,
.xgplayer-skin-default .xg-btn-videoStop {
width: 32px;
position: relative;
-webkit-order: 0;
@@ -1071,79 +1114,54 @@ export default {
cursor: pointer;
margin-left: 3px;
}
.xgplayer-skin-default .xg-btn-playPrev:hover {
.xgplayer-skin-default .xg-btn-playPrev:hover,
.xgplayer-skin-default .xg-btn-playNextOne:hover,
.xgplayer-skin-default .xg-btn-showList:hover,
.xgplayer-skin-default .xg-btn-showHistory:hover,
.xgplayer-skin-default .xg-btn-videoStop:hover {
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-videoStop {
order: 2;
}
.xgplayer-skin-default .xg-btn-showList:hover {
opacity: 0.8;
.xgplayer-skin-default .xg-btn-showList {
order: 4;
}
.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;
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%;
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;
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;
@@ -1153,26 +1171,26 @@ export default {
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;
color: #fff;
opacity: 1;
}
.xgplayer-skin-default .xgplayer-volume {
width: 32px !important;
width: 32px !important;
}
.xgplayer-skin-default .xgplayer-playbackrate {
width: 40px !important;
width: 40px !important;
}
.xgplayer-skin-default .xgplayer-playbackrate .name {
top: 10px !important;
top: 10px !important;
}
.xgplayer-skin-default .xgplayer-playbackrate ul {
bottom: 25px;
}
.xgplayer-skin-default .xgplayer-playbackrate ul li {
font-size: 13px !important;
font-size: 13px !important;
}
.xgplayer-skin-default .xgplayer-screenshot .name span {
width: 40px !important;
width: 40px !important;
}
.xgplayer-skin-default .xg-view-videoTitle {
display: none;

View File

@@ -42,6 +42,14 @@
</div>
</div>
</div>
<div class="shortcut">
<div class="title">缓存</div>
<div class="shortcut-box">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="clearCache">清理视频缓存</div>
</div>
</div>
</div>
<div class="site">
<div class="title">定位时间设置</div>
<div class="zy-input">
@@ -170,6 +178,14 @@ export default {
}
},
computed: {
view: {
get () {
return this.$store.getters.getView
},
set (val) {
this.SET_VIEW(val)
}
},
setting: {
get () {
return this.$store.getters.getSetting
@@ -177,18 +193,10 @@ export default {
set (val) {
this.SET_SETTING(val)
}
},
editSites: {
get () {
return this.$store.getters.getEditSites
},
set (val) {
this.SET_EDITSITES(val)
}
}
},
methods: {
...mapMutations(['SET_SETTING', 'SET_EDITSITES']),
...mapMutations(['SET_SETTING', 'SET_VIEW']),
linkOpen (e) {
shell.openExternal(e)
},
@@ -228,6 +236,14 @@ export default {
this.updateSettingEvent()
this.show.view = false
},
async clearCache () {
const win = remote.getCurrentWindow()
const ses = win.webContents.session
const size = await ses.getCacheSize() / 1024 / 1024
const mb = size.toFixed(2)
await ses.clearCache()
this.$message.success(`清除缓存成功, 共清理 ${mb} MB`)
},
updateSettingEvent () {
this.editPlayerPath = false
this.setting = this.d
@@ -277,10 +293,7 @@ export default {
this.updateSettingEvent()
},
editSitesEvent () {
this.editSites = {
show: true,
sites: this.sitesList
}
this.view = 'EditSites'
},
changeTheme (e) {
this.d.theme = e
@@ -335,6 +348,17 @@ export default {
var firstResult = $(e).find('div>div>a')
this.latestVersion = firstResult.text()
})
},
createContextMenu () {
const { Menu, MenuItem } = remote
const menu = new Menu()
menu.append(new MenuItem({ label: '快速复制', role: 'copy' }))
menu.append(new MenuItem({ label: '快速粘贴', role: 'paste' }))
menu.append(new MenuItem({ label: '编辑', role: 'editMenu' }))
window.addEventListener('contextmenu', e => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
})
}
},
created () {
@@ -343,6 +367,7 @@ export default {
this.getShortcut()
this.getFavorites()
this.getLatestVersion()
this.createContextMenu()
}
}
</script>

View File

@@ -1,88 +1,88 @@
<template>
<div class="detail">
<div class="detail-content">
<div class="detail-header">
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="exportFavoritesEvent">
导出
</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="importFavoritesEvent">
导入
</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="clearFavoritesEvent">
清空
</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="updateAllEvent">
同步所有收藏
</div>
</div>
</div>
<div class="detail-body zy-scroll">
<div class="zy-table">
<div class="tBody zy-scroll">
<ul>
<li v-show="this.list.length > 0">
<span class="name">名字</span>
<span class="type">类型</span>
<span class="time">上映</span>
<span class="site">片源</span>
<span class="note">备注</span>
<span class="note">观看至</span>
<span class="operate">
<span class="btn"></span>
<span class="btn"></span>
<span class="btn"></span>
<span class="btn"></span>
<span class="btn"></span>
</span>
</li>
<draggable v-model="list" @change="listUpdatedEvent">
<transition-group>
<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="site">{{ getSiteName(i.key) }}</span>
<span class="note">{{ i.note }}</span>
<span class="note">{{ getHistoryNote(i.index) }}</span>
<span class="operate">
<span class="btn" @click.stop="playEvent(i)">播放</span>
<span class="btn" @click.stop="shareEvent(i)">分享</span>
<span class="btn" @click.stop="updateEvent(i)">同步</span>
<span class="btn" @click.stop="downloadEvent(i)"
>下载</span
>
<span class="btn" @click.stop="deleteEvent(i)">删除</span>
</span>
</li>
</transition-group>
</draggable>
</ul>
</div>
</div>
<div class="listpage" id="star">
<div class="listpage-content">
<div class="listpage-header">
<el-button @click.stop="exportFavoritesEvent" type="text">导出</el-button>
<el-button @click.stop="importFavoritesEvent" type="text">导入</el-button>
<el-button @click.stop="clearFavoritesEvent" type="text">清空</el-button>
<el-button @click.stop="updateAllEvent" type="text">同步所有收藏</el-button>
</div>
<div class="listpage-body" id="star-table">
<el-table
:data="list"
height="100%"
row-key="id"
:cell-class-name="checkUpdate"
@row-click="detailEvent"
style="width: 100%">
<el-table-column
sortable
prop="name"
label="片名"
min-width="200">
</el-table-column>
<el-table-column
sortable
prop="type"
label="类型"
width="100">
</el-table-column>
<el-table-column
sortable
prop="year"
label="上映"
align="center"
width="100">
</el-table-column>
<el-table-column
sortable
prop="site"
label="片源"
width="100">
<template slot-scope="scope">
<span>{{ getSiteName(scope.row.key) }}</span>
</template>
</el-table-column>
<el-table-column v-if="list.some(e => e.note)"
sortable
prop="note"
label="备注"
min-width="100">
</el-table-column>
<el-table-column v-if="list.some(e => e.index >= 0)"
sortable
prop="index"
label="观看至"
width="100">
<template slot-scope="scope">
<span>{{ getHistoryNote(scope.row.index) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="220">
<template slot-scope="scope">
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
<el-button @click.stop="shareEvent(scope.row)" type="text">分享</el-button>
<el-button @click.stop="updateEvent(scope.row)" type="text">同步</el-button>
<el-button @click.stop="downloadEvent(scope.row)" type="text">下载</el-button>
<el-button @click.stop="deleteEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { star, history, sites } from '../lib/dexie'
import zy from '../lib/site/tools'
import draggable from 'vuedraggable'
import { remote } from 'electron'
import fs from 'fs'
import Sortable from 'sortablejs'
const { clipboard } = require('electron')
export default {
name: 'star',
@@ -92,9 +92,6 @@ export default {
sites: []
}
},
components: {
draggable
},
computed: {
view: {
get () {
@@ -180,6 +177,11 @@ export default {
info: e
}
},
checkUpdate ({ row, rowIndex }) {
if (this.list[rowIndex].hasUpdate) {
return 'highlight'
}
},
clearHasUpdateFlag (e) {
star.find({ id: e.id }).then(res => {
res.hasUpdate = false
@@ -187,17 +189,6 @@ export default {
this.getFavorites()
})
},
listUpdatedEvent () {
star.clear().then(res1 => {
// 重新排序
var id = this.list.length
this.list.forEach(element => {
element.id = id
star.add(element)
id -= 1
})
})
},
updateEvent (e) {
zy.detail(e.key, e.ids).then(res => {
var doc = {
@@ -367,46 +358,35 @@ export default {
clearFavoritesEvent () {
star.clear().then(e => {
this.getFavorites()
this.$message.success('清空所有收藏成功')
})
},
updateDatabase (data) {
star.clear().then(res => {
var id = length
data.forEach(ele => {
ele.id = id
id -= 1
})
star.bulkAdd(data)
})
},
rowDrop () {
const tbody = document.getElementById('star-table').querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.list.splice(oldIndex, 1)[0]
_this.list.splice(newIndex, 0, currRow)
_this.updateDatabase(_this.list)
}
})
}
},
mounted () {
this.rowDrop()
},
created () {
this.getFavorites()
window.Sortable = require('sortablejs').Sortable
}
}
</script>
<style lang="scss" scoped>
.detail{
position: absolute;
left: 80px;
right: 20px;
bottom: 0;
width: calc(100% - 100px);
height: calc(100% - 40px);
z-index: 888;
.detail-content{
height: calc(100% - 10px);
padding: 0 60px;
position: relative;
.detail-header{
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
.detail-title{
font-size: 16px;
}
.detail-close{
cursor: pointer;
}
}
}
.detail-body{
height: calc(100% - 50px);
overflow-y: auto;
}
}
</style>

View File

@@ -12,7 +12,7 @@ db.version(3).stores({
sites: '++id, key, name, json, xml, down, level',
history: '++id, site, ids, name, type, year, index, time',
mini: 'id, site, ids, name, index, time',
iptv: '++id, name, url'
iptv: '++id, name, url, group'
})
db.on('populate', () => {

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,8 @@
import Vue from 'vue'
import { Message } from 'element-ui'
import { Message, Button, Table, TableColumn, Tag, Input } from 'element-ui'
Vue.use(Button)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Tag)
Vue.use(Input)
Vue.prototype.$message = Message

View File

@@ -3,6 +3,36 @@ import axios from 'axios'
import cheerio from 'cheerio'
const onlineVideo = {
playVideoOnline (selectedOnlineSite, videoName, videoIndex) {
switch (selectedOnlineSite) {
case '哔嘀':
onlineVideo.playVideoOnBde4(videoName, videoIndex)
break
case '1080影视':
onlineVideo.playVideoOnK1080(videoName, videoIndex)
break
case '素白白':
onlineVideo.playVideoOnSubaibai(videoName, videoIndex)
break
case '哆咪动漫':
onlineVideo.playVideoOndmdm2020(videoName, videoIndex)
break
case '樱花动漫':
onlineVideo.playVideoOnYhdm(videoName, videoIndex)
break
case '简影':
onlineVideo.playVideoOnSyrme(videoName, videoIndex)
break
case '极品':
onlineVideo.playVideoOnJpysvip(videoName, videoIndex)
break
case '喜欢看':
onlineVideo.playVideoOnXhkan(videoName, videoIndex)
break
default:
this.$message.console.error(`不支持该网站:${this.selectedOnlineSite}`)
}
},
playVideoOnBde4 (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://bde4.com/search/${videoName}`
@@ -214,6 +244,74 @@ const onlineVideo = {
})
}
})
},
playVideoOnJpysvip (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://www.jpysvip.net/vodsearch/-------------.html?wd=${videoName}&submit=`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('#searchList')
var searchResult = $(e).find('ul>li>div>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).attr('title')
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = 'https://www.jpysvip.net' + detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('#playlist1')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
videoFullLink = 'https://www.jpysvip.net/' + indexVideoLink
}
open(videoFullLink)
})
}
})
},
playVideoOnXhkan (videoName, videoIndex) {
videoName = videoName.replace(/\s/g, '')
var url = `https://www.xhkan.com/vodsearch.html?wd=${videoName}&submit=`
axios.get(url).then(res => {
const $ = cheerio.load(res.data)
var e = $('#searchList')
var searchResult = $(e).find('ul>li>div>a').toArray()
// 获取第一个搜索结果的视频链接
var detailPageLink = $(searchResult[0]).attr('href')
// 获取第一个搜索结果的title
var title = $(searchResult[0]).attr('title')
if (title === null || title === undefined || !title.replace(/\s/g, '').includes(videoName)) {
// 如果第一个搜索结果不符合,打开搜索页面
open(url)
} else {
// 解析详情页面
var detailPageFullLink = detailPageLink
axios.get(detailPageFullLink).then(res2 => {
const $ = cheerio.load(res2.data)
// 获取playlist1
var e = $('#playlist1')
// 获取所有视频链接
var videoList = $(e).find('div>ul>li>a').toArray()
// 获取index视频链接
var videoFullLink = detailPageFullLink
if (videoIndex < videoList.length) {
var indexVideoLink = $(videoList[videoIndex]).attr('href')
videoFullLink = indexVideoLink
}
open(videoFullLink)
})
}
})
}
}
export default onlineVideo

View File

@@ -4,6 +4,7 @@ import store from './store'
import 'modern-normalize'
import Register from './components/register'
import './lib/element/index'
Register.registerComponents()
Vue.config.productionTip = false
new Vue({

View File

@@ -27,7 +27,6 @@ export default new Vuex.Store({
info: {}
},
editSites: {
show: false,
sites: []
}
},

131
yarn.lock
View File

@@ -1809,12 +1809,12 @@ aws4@^1.8.0:
resolved "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2"
integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==
axios@^0.19.2:
version "0.19.2"
resolved "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
axios@^0.20.0:
version "0.20.0"
resolved "https://registry.npm.taobao.org/axios/download/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
integrity sha1-BXujDwSIRpSZOozQf6OUz/EcUL0=
dependencies:
follow-redirects "1.5.10"
follow-redirects "^1.10.0"
babel-eslint@^10.1.0:
version "10.1.0"
@@ -3175,10 +3175,10 @@ d@1, d@^1.0.1:
es5-ext "^0.10.50"
type "^1.0.1"
danmu.js@^0.2.17:
version "0.2.18"
resolved "https://registry.npmjs.org/danmu.js/-/danmu.js-0.2.18.tgz#fd688e7df50367a8a68630d1a189a0132c08dd9c"
integrity sha512-ALfB4o0eQoK5pceEQCwyHmmg2wcxOOGqOflxodVtuc9Prq9Fyb2MAiyrfA+q/4WV1E4CnjoCep/8YHKy1X9IQg==
danmu.js@0.2.23:
version "0.2.23"
resolved "https://registry.npm.taobao.org/danmu.js/download/danmu.js-0.2.23.tgz#339b512152ed5a8253829be007c5be5bd3821856"
integrity sha1-M5tRIVLtWoJTgpvgB8W+W9OCGFY=
dependencies:
event-emitter "^0.3.5"
@@ -3201,13 +3201,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -3382,10 +3375,10 @@ detect-node@^2.0.4:
resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
dexie@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/dexie/-/dexie-3.0.1.tgz#faafeb94be0d5e18b25d700546a2c05725511cfc"
integrity sha512-/s4KzlaerQnCad/uY1ZNdFckTrbdMVhLlziYQzz62Ff9Ick1lHGomvTXNfwh4ApEZATyXRyVk5F6/y8UU84B0w==
dexie@^3.0.2:
version "3.0.2"
resolved "https://registry.npm.taobao.org/dexie/download/dexie-3.0.2.tgz#4b979904d739e0530b68352005f175a82633a075"
integrity sha1-S5eZBNc54FMLaDUgBfF1qCYzoHU=
diffie-hellman@^5.0.0:
version "5.0.3"
@@ -3664,10 +3657,10 @@ electron-to-chromium@^1.3.488:
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz#3f43d32930481d82ad3663d79658e7c59a58af0b"
integrity sha512-TXY4mwoyowwi4Lsrq9vcTUYBThyc1b2hXaTZI13p8/FRhY2CTaq5lK+DVjhYkKiTLsKt569Xes+0J5JsVXFurQ==
electron@^9.3.1:
version "9.3.1"
resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.1.tgz#e301932c5c0537d8c9a8850d216d3ba454dbf55c"
integrity sha512-DScrhqBT4a54KfdF0EoipALpHmdQTn3m7SSCtbpTcEcG+UDUiXad2cOfW6DHeVH7N+CVDKDG12q2PhVJjXkFAA==
electron@^10.1.4:
version "10.1.4"
resolved "https://registry.npm.taobao.org/electron/download/electron-10.1.4.tgz?cache=0&sync_timestamp=1603157068707&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron%2Fdownload%2Felectron-10.1.4.tgz#5462c5fac5b4728691042d0f62133ea2c133e6fd"
integrity sha1-VGLF+sW0coaRBC0PYhM+osEz5v0=
dependencies:
"@electron/get" "^1.0.1"
"@types/node" "^12.0.12"
@@ -4121,6 +4114,11 @@ eventemitter3@^4.0.0:
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==
eventemitter3@^4.0.7:
version "4.0.7"
resolved "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha1-Lem2j2Uo1WRO9cWVJqG0oHMGFp8=
events@^3.0.0:
version "3.1.0"
resolved "https://registry.npmjs.org/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59"
@@ -4528,18 +4526,16 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.0.0:
version "1.12.1"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6"
integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg==
follow-redirects@^1.10.0:
version "1.13.0"
resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
integrity sha1-tC6Nk6Kn7qXtiGM2dtZZe8jjhNs=
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -5081,10 +5077,10 @@ html-webpack-plugin@^3.2.0:
toposort "^1.0.0"
util.promisify "1.0.0"
html2canvas@^1.0.0-rc.5:
version "1.0.0-rc.5"
resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.5.tgz#4ee3cac9f6e20a0fa0c2f35a6f99c960ae7ec4c1"
integrity sha512-DtNqPxJNXPoTajs+lVQzGS1SULRI4GQaROeU5R41xH8acffHukxRh/NBVcTBsfCkJSkLq91rih5TpbEwUP9yWA==
html2canvas@^1.0.0-rc.7:
version "1.0.0-rc.7"
resolved "https://registry.npm.taobao.org/html2canvas/download/html2canvas-1.0.0-rc.7.tgz#70c159ce0e63954a91169531894d08ad5627ac98"
integrity sha1-cMFZzg5jlUqRFpUxiU0IrVYnrJg=
dependencies:
css-line-break "1.1.1"
@@ -6440,10 +6436,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
modern-normalize@^0.6.0:
version "0.6.0"
resolved "https://registry.npmjs.org/modern-normalize/-/modern-normalize-0.6.0.tgz#21a469988edfc7c9020348e7a3b5b3583a1c9406"
integrity sha512-gzvL1uFLV4EErHhaKoqTcrx52/sea6AIcMFWz/GBCuFrDBp485wSgyX5M+MZsj+grfcuqYLQGfHjDRrCvvwZLw==
modern-normalize@^1.0.0:
version "1.0.0"
resolved "https://registry.npm.taobao.org/modern-normalize/download/modern-normalize-1.0.0.tgz#539d84a1e141338b01b346f3e27396d0ed17601e"
integrity sha1-U52EoeFBM4sBs0bz4nOW0O0XYB4=
mousetrap@^1.6.5:
version "1.6.5"
@@ -9687,10 +9683,10 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
vue-template-compiler@^2.6.11:
version "2.6.11"
resolved "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080"
integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==
vue-template-compiler@^2.6.12:
version "2.6.12"
resolved "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.12.tgz?cache=0&sync_timestamp=1602239010008&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-template-compiler%2Fdownload%2Fvue-template-compiler-2.6.12.tgz#947ed7196744c8a5285ebe1233fe960437fcc57e"
integrity sha1-lH7XGWdEyKUoXr4SM/6WBDf8xX4=
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@@ -9700,27 +9696,27 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue-waterfall-plugin@^1.0.7:
version "1.0.7"
resolved "https://registry.npmjs.org/vue-waterfall-plugin/-/vue-waterfall-plugin-1.0.7.tgz#bd351e8d3015b9ce71320e00a88443929d63465f"
integrity sha512-60JlBvrQbIOapGwc9AW9cXV064uzIEV1bjzc1ApNGt+MI4PI0Xs9aDvFgRMsGdynV9UlsLNtplX0bRwJ1syT9A==
vue-waterfall-plugin@^1.1.0:
version "1.1.0"
resolved "https://registry.npm.taobao.org/vue-waterfall-plugin/download/vue-waterfall-plugin-1.1.0.tgz#a4d87c74b72f1e36de5bbbadf1d645eb549ed592"
integrity sha1-pNh8dLcvHjbeW7ut8dZF61Se1ZI=
vue@^2.6.11:
version "2.6.11"
resolved "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
vue@^2.6.12:
version "2.6.12"
resolved "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1602778254831&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
integrity sha1-9evU+mvShpQD4pqJau1JBEVskSM=
vuedraggable@^2.24.1:
version "2.24.1"
resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.24.1.tgz#304abd7644dde05c1f199a227bf9e9107f56197a"
integrity sha512-G1fxO1oshx+WLdieSGl6jSJdlHOQFga1FpjuUpgXldbpKNzxpjsGn4xYNnRHVrOAqm8aG5FfpdQlh5LHesxCeA==
vuedraggable@^2.24.2:
version "2.24.2"
resolved "https://registry.npm.taobao.org/vuedraggable/download/vuedraggable-2.24.2.tgz#cd98faec99905238469e9b4d235fba5a59fb7da2"
integrity sha1-zZj67JmQUjhGnptNI1+6Wln7faI=
dependencies:
sortablejs "^1.10.1"
vuex@^3.4.0:
vuex@^3.5.1:
version "3.5.1"
resolved "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
integrity sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==
resolved "https://registry.npm.taobao.org/vuex/download/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
integrity sha1-8bjc6mSbwlJUz09DWAgdv12hiz0=
watchpack-chokidar2@^2.0.0:
version "2.0.0"
@@ -9994,22 +9990,23 @@ xdg-basedir@^4.0.0:
resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
xgplayer-hls.js@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/xgplayer-hls.js/-/xgplayer-hls.js-2.2.3.tgz#bf538911145346c447528d609fc95dd267a24d81"
integrity sha512-CFsZanBHHRbqTmqYCFFONk76oWwJwbn+8LK/XkwBBrUrqGPQPmrXfjelGjKDDGfZ+w3xReC1nGom3IpN+lLoaQ==
xgplayer-hls.js@^2.2.5:
version "2.2.5"
resolved "https://registry.npm.taobao.org/xgplayer-hls.js/download/xgplayer-hls.js-2.2.5.tgz?cache=0&sync_timestamp=1600935842683&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxgplayer-hls.js%2Fdownload%2Fxgplayer-hls.js-2.2.5.tgz#8f90980cf2b6b4610b5449a3a55a4e7d87335cc8"
integrity sha1-j5CYDPK2tGELVEmjpVpOfYczXMg=
dependencies:
deepmerge "2.0.1"
event-emitter "^0.3.5"
eventemitter3 "^4.0.7"
xgplayer@^2.9.10:
version "2.9.10"
resolved "https://registry.yarnpkg.com/xgplayer/-/xgplayer-2.9.10.tgz#4e79b889621f829b773c118ab93da55f829d4490"
integrity sha512-5a7Xm0AY8qPRXZFxrPRErjzCERsENaskQ8Fq5Sy4ht13TMzYp0VIRREU7XF8efpJGcPsOOuFlCiMrqSpYEIAUA==
xgplayer@^2.12.2:
version "2.12.2"
resolved "https://registry.npm.taobao.org/xgplayer/download/xgplayer-2.12.2.tgz#72111cfbb21f97cbe454b0f5d17e85f720892b2a"
integrity sha1-chEc+7Ifl8vkVLD10X6F9yCJKyo=
dependencies:
chalk "^2.3.2"
commander "^2.15.1"
danmu.js "^0.2.17"
danmu.js "0.2.23"
deepmerge "^1.5.0"
downloadjs "1.4.7"
draggabilly "^2.2.0"