Compare commits

..

234 Commits

Author SHA1 Message Date
buvta
f2f58fb888 调整版本号到v2.6.10 2020-12-18 18:03:35 +08:00
buvta
5286568801 允许证书错误v2.7.0rc 2020-12-18 17:16:23 +08:00
buvta
2a9f8ed0dc 避免改动数据库时重置软件 2020-12-18 16:25:04 +08:00
buvta
eb3d064cb5 改动shortcut数据库,避免快捷键指南太过杂乱 2020-12-17 20:33:56 +08:00
buvta
a0ec282cc2 fix:改动快捷键设置时未及时生效 2020-12-17 20:15:16 +08:00
buvta
ea61dca27b film下el-select的visible-change事件改为change 2020-12-17 16:54:21 +08:00
buvta
fd0be9e96b film搜索调整隐藏列 2020-12-17 16:49:49 +08:00
buvta
775247e28b 设置快捷键添加重置功能 2020-12-17 16:47:57 +08:00
buvta
ded5c39790 Play频道列表添加clickaway事件 2020-12-17 16:36:40 +08:00
buvta
16e44d71bd 海报模式下不提醒支持shift 2020-12-17 16:22:20 +08:00
buvta
ae0858319f 完善导入导出的title提示 2020-12-15 20:35:50 +08:00
buvta
3c6733648b 再次调整resize事件 2020-12-15 20:22:01 +08:00
buvta
06bd915964 调大el-select下拉框高度 2020-12-15 17:15:25 +08:00
buvta
dfcd786f53 fix:收藏批量删除 2020-12-15 16:24:12 +08:00
buvta
d0f6282b81 批量检测完成时提示 2020-12-15 15:42:13 +08:00
buvta
ab3a6e1fd2 各页面完善按钮提示 2020-12-15 15:20:55 +08:00
buvta
0cb540d3e5 历史收藏添加支持shift提示 2020-12-15 14:34:14 +08:00
buvta
1d0123d69f fix:历史收藏列表模式拖拽调序 2020-12-15 14:23:31 +08:00
buvta
6dbcb8e621 历史与收藏添加批量删除 2020-12-15 14:17:13 +08:00
buvta
b1a6d58974 清除iptv的watch view 2020-12-15 14:12:02 +08:00
haiyangcui
bb45006ff7 Revert "删除跳过片头片尾里的无用代码"
This reverts commit e9f81faf70.
2020-12-14 17:11:47 +01:00
haiyangcui
e9f81faf70 删除跳过片头片尾里的无用代码 2020-12-14 16:26:47 +01:00
cuiocean
b864c6ca15 Merge pull request #383 from Hunlongyu/dependabot/npm_and_yarn/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8
2020-12-14 16:12:49 +01:00
buvta
9f98231eed 添加提示次数限制 2020-12-14 22:27:21 +08:00
buvta
3bcf5b1618 添加多选支持shift提示 2020-12-14 21:21:29 +08:00
buvta
d7a6245f8a 导出为json格式时自动添加扩展名 2020-12-14 21:19:32 +08:00
buvta
2abf2aeda7 设置页添加更新日志与常见问题链接 2020-12-14 17:18:19 +08:00
buvta
c3129c7cee 调整Play页面某些变量的命名 2020-12-14 17:08:38 +08:00
buvta
3b0ec94d2b 直播停止时亦可弹出频道列表 2020-12-14 17:03:24 +08:00
buvta
9902d98342 调整海报模式延时间隔 2020-12-13 23:17:28 +08:00
buvta
b5f5baeb8f 点击播放历史记录按钮时隐藏频道列表 2020-12-13 22:59:17 +08:00
buvta
f396d5ea05 停止时隐藏跳过片头片尾 2020-12-13 22:51:46 +08:00
buvta
e616aa5e2a 播放器初始状态点播放,历史记录为空时直接停止重置 2020-12-13 22:25:58 +08:00
buvta
f041093fe9 清除播放窗口还原时hasStart变量 2020-12-13 22:25:58 +08:00
buvta
e66c056283 稍微调整跳过片头片尾,并添加注释 2020-12-13 22:25:52 +08:00
haiyangcui
d33bbcff06 设置片头片尾按钮的文字提示改为tooltips提示 2020-12-13 14:49:11 +01:00
buvta
992c2f152f 推荐页切换页面时没必要重新读取数据库,并修正换行符 2020-12-13 18:36:31 +08:00
buvta
118bc5058c 调整历史播放页面watch监测view的事件 2020-12-13 18:21:38 +08:00
buvta
19c11f2694 fix:海报模式film页面加载图片时来回切换页面偶尔有卡片被部分遮掩,其它页面是重新加载数据故而不用 2020-12-13 18:12:47 +08:00
buvta
0a812ff6c4 el-select多选时显示全部标签 2020-12-13 16:30:12 +08:00
buvta
1e6a98df88 海报模式重新加上resize事件 2020-12-13 16:08:57 +08:00
buvta
b1b4e61244 fix:改造时调整rowDrop触发时机 2020-12-13 15:38:36 +08:00
buvta
2a05b2abdb 推荐、历史、收藏页面进行类film改造 2020-12-13 15:37:10 +08:00
buvta
74beb47ad5 fix: film搜索切换回海报模式时部分卡片被遮掩显示不全的bug 2020-12-13 15:08:32 +08:00
buvta
325a7f3b0d 调小播放器重置延时 2020-12-13 13:10:52 +08:00
buvta
9b5b5a1334 修复播放器初始状态时点击播放时的bug,并给直播加上对应功能 2020-12-13 13:09:36 +08:00
buvta
74dee7a892 调整film窗口resize事件触发机制 2020-12-13 11:53:35 +08:00
dependabot[bot]
d07436d876 Bump ini from 1.3.5 to 1.3.8
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-13 01:04:59 +00:00
buvta
e283152a89 去除多余代码,Waterfall在数据及窗口变动时会自动刷新 2020-12-12 23:02:20 +08:00
buvta
bdeeccedb9 film列表模式窗口宽度足够时显示“最近更新” 2020-12-12 23:01:31 +08:00
haiyangcui
5931266770 播放页面,显示历史时间信息 2020-12-12 13:51:58 +01:00
haiyangcui
bbeb75631d 打开ZY,直接播放的话,或者是视频停止后再点击播放的话,播放最近的历史记录 2020-12-12 13:39:44 +01:00
haiyangcui
c0f4940289 设置quitMiniMode按钮默认不显示,这样每次播放视频的时候就无需设置'xg-btn-quitMiniMode'的样式 2020-12-12 13:01:27 +01:00
buvta
db1b81243a 修复“站内”时切换站点可搜索 2020-12-12 12:56:55 +08:00
buvta
97b6a8259f 继续调整 2020-12-12 12:52:27 +08:00
buvta
4c92ff9e70 fix:优化film停止搜索时的自动切换searchRunning问题 2020-12-12 12:25:04 +08:00
buvta
b8dc7f4526 film工具栏分割线添加"回到顶部" 2020-12-11 23:42:28 +08:00
buvta
0d6e0d6e9f film停止搜索优化 2020-12-11 23:07:13 +08:00
buvta
1a5bac68ad 调整film搜索表格过滤器设置 2020-12-11 16:11:12 +08:00
buvta
83e302aeb7 film搜索使用工具栏实现过滤(功能实现) 2020-12-11 15:45:36 +08:00
buvta
2196eaa68c 视图模式切换转移到工具栏分割线,搜索亦可用工具栏(功能待实现) 2020-12-11 15:41:28 +08:00
haiyangcui
40aae02af6 修复收藏页的共享功能 2020-12-10 17:17:28 +01:00
haiyangcui
f078df6f8e 修复推荐页的分享功能 2020-12-10 17:14:49 +01:00
haiyangcui
ee44bfe0a8 支持停止搜索,虽然实际上是停止把搜索结果加入searchContents,但对于用户来说应该是足够了. 2020-12-10 16:59:07 +01:00
hunlongyu
9d9a808226 修复分享二维码地址为空的bug 2020-12-10 23:17:55 +08:00
buvta
d78784c0d9 fix:精简模式切换内容时quitMini图标消失 2020-12-10 16:10:51 +08:00
buvta
1ead8a5594 开启过滤切换分类数据过少时加大请求间隔 2020-12-10 16:10:51 +08:00
Hunlongyu
b63c8f4daf 优化自动更新功能, 增加进度条 2020-12-10 14:59:49 +08:00
Hunlongyu
011400f714 删除 server.js 文件 2020-12-10 10:00:20 +08:00
Hunlongyu
1d725579de Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player into master 2020-12-10 09:59:07 +08:00
Hunlongyu
93749c3841 移除 node 代理 2020-12-10 09:59:01 +08:00
haiyangcui
4b0c67b8fa 添加"跳略设置"按钮,避免一直显示片头片尾设置 2020-12-08 18:08:03 +01:00
buvta
165040872c fix:工具栏收起时重置selectedArea 2020-12-08 22:06:09 +08:00
buvta
27773be1c7 v2.6.9 2020-12-08 18:26:05 +08:00
buvta
fadb50a28b film调整areas刷新策略 2020-12-08 18:14:21 +08:00
buvta
518a9c3492 播放视频开始时重置片头片尾输入框数据 2020-12-08 17:36:33 +08:00
buvta
d5eb4dc49f film搜索不加载工具栏开关 2020-12-08 16:48:27 +08:00
buvta
e76bee574f film避免列表模式下加载图片 2020-12-08 16:46:02 +08:00
buvta
b7779a3e6f 疑似el-select弹窗bug,临时性修补 2020-12-08 15:45:25 +08:00
buvta
4cb5b48985 收起工具栏时重置列表 2020-12-08 15:37:21 +08:00
buvta
b2128113ba 调整工具栏refreshFilteredList触发方式 2020-12-08 15:24:36 +08:00
buvta
58d0ae6da1 工具栏"语言"替换为"排序" 2020-12-08 13:03:58 +08:00
buvta
2bd821f59d 调整工具栏打开方式 2020-12-08 12:20:12 +08:00
haiyangcui
8d002225fd 添加'过滤器'按钮,控制过滤选项按钮组的显示 2020-12-07 16:47:45 +01:00
haiyangcui
0243c2f0fe Fix: 切换类型时,总是调用refreshFilteredList 2020-12-07 16:28:30 +01:00
buvta
b8edd7f440 Revert "fix:海报模式切换分类时偶尔空白页"
This reverts commit 1df6726a3b.
2020-12-07 20:22:22 +08:00
buvta
4683aecf7b fix:上层弹窗被过滤工具栏遮蔽 2020-12-07 20:22:22 +08:00
buvta
16d38ba2b4 调整相应样式 2020-12-07 19:43:36 +08:00
buvta
fe7fe06d48 film添加过滤工具栏 2020-12-07 19:43:36 +08:00
buvta
c1220ef752 手动设置跳过片头片尾时间长度 2020-12-07 07:01:22 +08:00
buvta
f0c221a863 修复福利屏蔽 2020-12-06 18:40:18 +08:00
buvta
1df6726a3b fix:海报模式切换分类时偶尔空白页 2020-12-06 18:29:45 +08:00
buvta
1a9e939f9c 更新直播源 2020-12-06 15:53:55 +08:00
buvta
39cb188604 调整iptv分组命名规则 2020-12-06 15:53:13 +08:00
buvta
aba4d12302 确保不会意外引入代理 2020-12-05 23:54:29 +08:00
buvta
17c77fd48a 禁止xgplayer显示重播 2020-12-05 23:48:24 +08:00
buvta
1cfc12ec19 fix:确保不会跳过多集 2020-12-05 23:46:03 +08:00
buvta
b0aa1dc28a 视频多集时可通过快捷键设置跳过片头片尾,保存在相应的历史记录中 2020-12-05 19:10:05 +08:00
haiyangcui
0c12b394a7 视频列表页,支持按地区过滤数据 2020-12-04 14:06:30 +01:00
haiyangcui
9e468bc82e 在类型框内显示视频数信息 2020-12-04 13:48:31 +01:00
haiyangcui
973a15b593 统一downloadEvent函数 2020-12-02 15:19:50 +01:00
Hunlongyu
253c1e7723 分享的网址改为 gitee, 国内用户打开更快 2020-12-02 10:21:54 +08:00
Hunlongyu
7b44051190 更新官网截图,, 修改部分描述 2020-12-02 10:19:12 +08:00
Hunlongyu
a25ac77ebc 更新 README 2020-12-02 10:02:42 +08:00
haiyangcui
d187167fbe 解决换源时视频类型不正常更新的问题 2020-12-01 16:01:47 +01:00
haiyangcui
b34347cf43 添加视频数信息 2020-12-01 13:20:50 +01:00
haiyangcui
829d9447a4 删除重复和不可用的源站 2020-12-01 13:07:11 +01:00
haiyangcui
39067c6a35 缓存视频列表信息 2020-12-01 00:24:38 +01:00
haiyangcui
6dbb64a4f2 重构 2020-11-30 23:58:12 +01:00
haiyangcui
f8041290d2 无需定义getPage函数 2020-11-30 23:49:56 +01:00
haiyangcui
f772ac2e9d 从搜索界面返回时,无需再重新加载数据 2020-11-30 17:13:10 +01:00
haiyangcui
ef485ef64a 删除无用代码 2020-11-30 16:48:43 +01:00
haiyangcui
b164d5e83e Revert "降级xgplayer回2.13.1,新版居然不支持缓冲了."
This reverts commit 8cd2b920c8.
2020-11-30 15:48:13 +01:00
haiyangcui
8a5800df93 v2.6.8 2020-11-30 12:37:40 +01:00
haiyangcui
8cd2b920c8 降级xgplayer回2.13.1,新版居然不支持缓冲了. 2020-11-30 11:37:13 +01:00
haiyangcui
5b4cb43aa5 如果源站返回多个视频列表的话, 仅获取m3u8列表 2020-11-30 11:21:55 +01:00
haiyangcui
de1472e668 升级依赖 2020-11-30 10:56:24 +01:00
haiyangcui
0f846b996b 设置播放器默认预加载300秒 2020-11-29 20:11:23 +01:00
cuiocean
2bd5e31a28 Merge pull request #362 from Hunlongyu/dependabot/npm_and_yarn/highlight.js-9.18.5
Bump highlight.js from 9.18.1 to 9.18.5
2020-11-29 20:04:32 +01:00
haiyangcui
9d8dc9ecb1 删除不工作的cctv蓝光源 2020-11-29 16:53:24 +01:00
haiyangcui
2a073e4092 v2.6.7 2020-11-29 16:26:37 +01:00
haiyangcui
b1daa73afe 更新推荐 2020-11-29 16:23:15 +01:00
haiyangcui
18940ff9f7 Revert "更新视频源,删除无效源,添加需要解析的腾讯,搜狐视频等源"
This reverts commit 76d4d68401.
2020-11-29 13:27:20 +01:00
haiyangcui
76d4d68401 更新视频源,删除无效源,添加需要解析的腾讯,搜狐视频等源 2020-11-28 13:00:29 +01:00
haiyangcui
f91200e609 非m3u8视频,使用在线解析网站播放 2020-11-28 12:46:10 +01:00
haiyangcui
b64f500710 Download函数内解析m3u8List,改进downloadEvent函数 2020-11-28 12:30:43 +01:00
haiyangcui
cf1cfe9f77 支持某些源返回json数据不包含rss层 2020-11-28 11:47:48 +01:00
Hunlongyu
da4fe162f6 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player into master 2020-11-28 09:44:37 +08:00
Hunlongyu
d949c52020 代码优化 2020-11-28 09:44:32 +08:00
buvta
1ce9e0525b Merge branch 'master' into master 2020-11-25 23:38:06 +08:00
dependabot[bot]
4ebf82eae0 Bump highlight.js from 9.18.1 to 9.18.5
Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 9.18.1 to 9.18.5.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/9.18.5/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/9.18.1...9.18.5)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-25 06:15:54 +00:00
buvta
e0b1a5332d iptv优化 2020-11-24 22:27:49 +08:00
buvta
3ecb4302ba iptv优化 2020-11-24 16:46:29 +08:00
buvta
5c39db8ca6 iptv恢复"播放",避免行点击时误操作 2020-11-23 16:34:53 +08:00
buvta
4f45045d18 精简模式alt+m切换进入退出 2020-11-23 16:34:53 +08:00
buvta
b7733179f2 导入直播源时允许网址带参数 2020-11-23 16:34:53 +08:00
haiyangcui
e1f7044ae0 数据更新后,刷新页面 2020-11-22 20:57:27 +01:00
buvta
93e76db444 恢复记录mini窗口状态
This reverts commit bedd1339df.
2020-11-22 23:48:50 +08:00
buvta
6eaa281e4a 直播主窗口隐藏退出mini图标 2020-11-22 23:31:30 +08:00
buvta
490d34e1fb 移除iptvSearch数据库 2020-11-22 22:39:42 +08:00
buvta
0d0d6bd90f iptv移除iptvSearch 2020-11-22 22:35:48 +08:00
buvta
ecdc96d2f3 Play样式相应调整 2020-11-22 22:35:48 +08:00
buvta
234f6dd069 Play频道搜索用el-input替代 2020-11-22 22:35:38 +08:00
haiyangcui
f80fe7ecf1 添加退出精简模式按钮 2020-11-22 14:37:30 +01:00
haiyangcui
6876721567 进入精简模式,无需设置大小位置,直接调用getCssFullscreen即可 2020-11-22 12:41:22 +01:00
haiyangcui
bedd1339df Revert "记录mini窗口大小" 2020-11-22 12:09:36 +01:00
hunlongyu
0a3a7a4d57 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player 2020-11-22 16:38:49 +08:00
hunlongyu
786e23f5a2 删除冗余代码 2020-11-22 16:38:43 +08:00
buvta
418f14bcc1 调整Ctrl+0描述(弹窗容不下) 2020-11-22 11:20:00 +08:00
buvta
a9e4a34e4f 精简模式添加快捷键Ctrl+0用于恢复默认 2020-11-22 10:56:30 +08:00
buvta
fede7e4ef2 Revert "mini模式,大小直接设置为当前窗口大小,无需记录到数据库中"
This reverts commit f92af48a4e.
2020-11-22 10:41:19 +08:00
buvta
956ebbf8b8 调整Play页面channelList加载策略 2020-11-22 10:32:26 +08:00
haiyangcui
014dac0b64 排序源站,把可用的放上面 2020-11-21 23:37:05 +01:00
haiyangcui
5fc1020e79 升级所有依赖到最新版 2020-11-21 22:48:44 +01:00
haiyangcui
aca487f796 升级依赖 2020-11-21 22:41:09 +01:00
haiyangcui
429eb4aac0 移动getChannelList到if里,避免不必要的开销 2020-11-21 22:27:26 +01:00
haiyangcui
e032f86d3d 切换视图时,无需更新页面和改变infiniteId 2020-11-21 22:16:06 +01:00
haiyangcui
f92af48a4e mini模式,大小直接设置为当前窗口大小,无需记录到数据库中 2020-11-21 19:07:05 +01:00
haiyangcui
eff69db063 infiniteId会在classClick里更新 2020-11-21 18:52:33 +01:00
haiyangcui
a5c8d20635 更新麻花资源的api链接 2020-11-21 18:39:33 +01:00
haiyangcui
da22abd25d 避免不必要的资源访问 2020-11-21 18:38:53 +01:00
haiyangcui
2dd91f78c9 牛牛资源已失效,删除 2020-11-21 18:38:51 +01:00
buvta
a8b0e7e6a8 fix:直播时上下切换频道时的bug 2020-11-21 23:20:17 +08:00
buvta
39edb9ce35 v2.6.6 2020-11-21 16:44:50 +08:00
buvta
3323a56671 fix:置顶图标联动 2020-11-21 16:22:06 +08:00
buvta
4dc88469e8 调整iptv操作列表头,两种显示模式 2020-11-21 15:55:08 +08:00
buvta
b04201f803 Play将win常量提取出来,避免重复获取 2020-11-21 15:52:51 +08:00
buvta
f34da7ff85 Play支持按拼音首字母搜索频道 2020-11-21 13:38:03 +08:00
buvta
b8f010c4f5 调整Play初始化 2020-11-21 13:20:39 +08:00
buvta
f876b863e7 直播换源时可隐藏频道 2020-11-21 13:20:29 +08:00
buvta
384ae10475 iptv移到设置界面,播放界面不加载视频时自动弹出频道列表 2020-11-20 22:50:57 +08:00
buvta
647c540f0b 直播时隐藏历史及播放速率按钮 2020-11-20 22:30:33 +08:00
buvta
87d01da241 精简模式停止时回到主窗口 2020-11-20 22:30:33 +08:00
buvta
641bdf00d3 保存音量 2020-11-20 22:30:33 +08:00
buvta
31510624c1 Update feature.md 2020-11-20 21:14:45 +08:00
buvta
d5c4e296c3 Update bug.md 2020-11-20 21:13:59 +08:00
buvta
f55065472d 调整IPTV批处理时的按钮标签 2020-11-20 15:05:39 +08:00
buvta
525da05c5f iptv导入json时bug修复 2020-11-20 15:00:00 +08:00
buvta
de8c51918f 再次调整 2020-11-20 13:59:18 +08:00
buvta
17229eb6b4 fix:初次切换到Play播放频道时channelList为空 2020-11-20 13:45:17 +08:00
buvta
d4530eef89 iptv导入json时合并而非覆盖 2020-11-20 12:52:13 +08:00
buvta
cb68da5a22 Play调整下代码 2020-11-20 12:06:44 +08:00
buvta
c21f6538f3 iptv改为以channelList为主,导入不再丢失配置
仅在生成channelList时使用iptv数据库,平时清空
导入导出格式为m3u时使用iptvList,json使用channelList
2020-11-20 12:05:20 +08:00
buvta
729dab765c 清理多余的mini窗口代码 2020-11-20 12:02:21 +08:00
buvta
8521de2844 Merge pull request #353 from Hunlongyu/mergeChannelDev
频道合并及播放页面的频道列表及精简模式
2020-11-19 21:31:35 +08:00
buvta
6ec7dffd59 窗口合二为一,更完美的精简模式,按Esc键退出 2020-11-19 18:13:44 +08:00
buvta
51fccb699a Play频道搜索样式调整 2020-11-19 18:13:44 +08:00
buvta
525d6af888 Play支持频道搜索 2020-11-19 18:13:44 +08:00
buvta
5a17d1b991 播放页面支持频道分组(外置) 2020-11-19 18:13:44 +08:00
buvta
edef20d171 fix:源管理清空时亦可添加 2020-11-19 18:13:44 +08:00
buvta
e912804fcc IPTV播放添加prefer 2020-11-19 18:13:44 +08:00
buvta
3165345839 Play做相应调整以使用channelList代替iptvList 2020-11-19 18:13:44 +08:00
buvta
7133c8982a 调整iptv拖拽仅在"不可展开"即批处理模式可用 2020-11-19 18:13:44 +08:00
buvta
26c1ba1e62 解决懒加载带来的bug 2020-11-19 18:13:44 +08:00
buvta
4e83e365a6 移除对iptvList.length的依赖 2020-11-19 18:13:44 +08:00
buvta
03775b091d 调整shift多选时获取首尾位置的方法 2020-11-19 18:13:43 +08:00
buvta
9147a8e1fb Revert "改动syncTableData以便删除可用"
This reverts commit 25d65866ae.
2020-11-19 18:13:43 +08:00
buvta
0d84e20326 支持手动合并 2020-11-19 18:13:43 +08:00
buvta
d421a5cfe4 bug修复 2020-11-19 18:13:43 +08:00
buvta
46fc5a0942 频道合并bug待修复 2020-11-19 18:13:43 +08:00
buvta
60aac3944e 进一步完善合并功能,注释部分及联动待实现 2020-11-19 18:13:43 +08:00
buvta
4683223a68 数据库调整,新增channelList,根据iptvList自动生成 2020-11-19 18:13:43 +08:00
buvta
86856397f6 IPTV实现自动合并懒加载,其它待调整以适应合并 2020-11-19 18:13:43 +08:00
haiyangcui
09e6af6f18 删除无用的extraResources文件夹 2020-11-16 14:30:15 +01:00
haiyangcui
18db5a1eb0 实体化HlsJsPlayer,而非更底层一点的Hls 2020-11-15 16:05:08 +01:00
haiyangcui
d116f08550 更新"更新推荐"提示语 2020-11-15 15:18:07 +01:00
haiyangcui
7441341658 删除记录,成功的话结果很明显,无需消息提醒 2020-11-15 09:48:10 +01:00
haiyangcui
9b71355803 Recommendations都是cuiocean一个人在维护,故将该资源转移到独立的repository里,避免继续污染本repo的commit信息 2020-11-15 09:30:41 +01:00
buvta
aba07ea20b 添加issue模版 2020-11-15 15:07:19 +08:00
buvta
790ea92180 issue模版 2020-11-15 14:57:54 +08:00
haiyangcui
1dc683e332 再次解决恢复窗口不继续播放视频的问题 2020-11-14 20:23:37 +01:00
haiyangcui
82df96e4d0 解决恢复窗口视频不恢复播放的问题 2020-11-14 20:07:46 +01:00
haiyangcui
bb1e31a270 默认video触发touchend事件后视频切换播放/暂停状态,通过closeVideoTouch关闭 2020-11-14 18:09:51 +01:00
haiyangcui
1d8d9ae72f 改变高亮颜色,以适应不同主题 2020-11-14 15:59:10 +01:00
haiyangcui
6dfe3bea95 统一viewMode为列表时的值为table 2020-11-14 15:59:03 +01:00
haiyangcui
6fcb6ad16c 搜索结果支持海报和列表两种模式 2020-11-14 15:58:52 +01:00
haiyangcui
c692ed2100 显示引入使用的依赖,否则编译有警告 2020-11-14 15:58:43 +01:00
hunlongyu
26bcdd4101 🗃 修复download为空时下载出错 2020-11-14 12:46:44 +08:00
buvta
5104f9a85d v2.6.4.1 2020-11-14 11:47:36 +08:00
hunlongyu
d61ee76e58 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player 2020-11-13 21:33:13 +08:00
hunlongyu
b1a683a8db 🗑 修复 developer 报错 2020-11-13 21:33:07 +08:00
buvta
5d0dc1bed7 补上落下的async 2020-11-13 21:26:03 +08:00
buvta
3481a5346e 取消时等待数据库更新再刷新代理 2020-11-13 21:05:49 +08:00
buvta
c957fe33e2 取消时更新代理 2020-11-13 21:00:57 +08:00
buvta
51aa21e551 稍微调整 2020-11-13 20:55:11 +08:00
buvta
a887968458 设置增加代理,功能实现 2020-11-13 20:36:33 +08:00
Hunlongyu
380d31c0d3 🌿 新增代理设置界面 ( 功能未完成 ) 2020-11-13 16:28:11 +08:00
Hunlongyu
46b5f82348 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player into master 2020-11-13 13:52:45 +08:00
Hunlongyu
675622e9ee npm yarn 2020-11-13 13:52:36 +08:00
haiyangcui
9a67821984 移除无用log 2020-11-12 23:35:21 +01:00
haiyangcui
e457574755 开启airplay选项 2020-11-12 22:58:45 +01:00
haiyangcui
50f5154628 Merge branch 'master' of https://github.com/Hunlongyu/ZY-Player 2020-11-12 17:35:43 +01:00
haiyangcui
9da7ffc451 Revert "移除"搜索所有资源"开关,搜索变总是搜索所有资源", 解决推荐排序不工作的问题 2020-11-12 17:35:31 +01:00
buvta
35adae51cc 调整"正在直播"样式 2020-11-12 23:52:47 +08:00
65 changed files with 5746 additions and 13941 deletions

28
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: 报告Bug(请先查看常见问题及搜索issue列表中有无你要提的问题)
about: 创建报告以帮助我们改进
title: '(未回答的问题请删除)'
labels: bug
assignees: ''
---
**描述错误**
清楚简洁地说明错误是什么。
**重现**
重现行为的步骤
**预期行为**
对您期望发生的事情的简洁明了的描述。
**截图**
如果适用,请添加屏幕截图以帮助解释您的问题(直接把图片拖到编辑框即可添加图片)。
**环境:**
-操作系统及版本:[例如Windows 10 64位 18362.156]
-软件安装包及版本:[例如Windows 64位绿色版 1.0.0]
**其他内容**
在此处添加有关该问题的任何其他上下文。

17
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View File

@@ -0,0 +1,17 @@
---
name: 功能请求(请先查看常见问题及搜索issue列表中有无你要提的问题)
about: 为这个项目提出一个想法
title: 例如添加xxx功能、优化xxx功能未回答的问题请删除
labels: enhancement
assignees: ''
---
**描述您想要的解决方案**
简洁明了地描述您要发生的事情。
**描述您考虑过的替代方案**
对您考虑过的所有替代解决方案或功能的简洁明了的描述。
**其他内容**
在此处添加有关功能请求的任何其他上下文或屏幕截图(直接把图片拖到编辑框即可添加图片)。

19
.github/ISSUE_TEMPLATE/help.md vendored Normal file
View File

@@ -0,0 +1,19 @@
---
name: 需要帮助
about: "其它问题"
labels: help wanted
---
### 版本、安装方式、系统
1. 你在使用什么版本的
2. 你通过什么方式安装
3. 你所使用的操作系统
### 描述问题:
<!-- 在下方描述问题 -->

View File

@@ -46,6 +46,17 @@
- 🍉 [蓝奏云 -- 快速下载](https://www.lanzoux.com/b04s6a3re) 密码:95px
- 🍒 适用于32位操作系统的x86软件,在蓝奏云网盘里, 后缀名: ZY Player * 32位.exe
### 🎠 平台
| 平台 | 链接 |
| :------------------------------------ | :---------------------------------------------------------- |
| 🖥️ 电脑端 ( Windows & Mac & Linux ) | [ZY Player](https://github.com/Hunlongyu/ZY-Player) |
| 📱 手机端 ( Android & IOS ) | [ZY Player APP](https://github.com/Hunlongyu/ZY-Player-APP) |
| 📺 电视端 ( Android & Mac ) ( 进行中 ) | [ZY Player TV](https://github.com/cuiocean/ZY-Player-TV) |
| 🌐 浏览器 ( Web ) | [ZY Player Web](https://github.com/Hunlongyu/ZY-Player-Web) |
### 🚀 快捷键
播放窗口 和 Mini窗口
@@ -81,7 +92,8 @@
### 🍭 开发者
| [Hunlongyu](https://github.com/Hunlongyu) | [cuiocean](https://github.com/cuiocean) |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| <img width="120" src="https://avatars2.githubusercontent.com/u/15273630?s=460&u=48cf3299e2a842c0252233d8be42ef4c5d792138&v=4"/> | <img width="120" src="https://avatars0.githubusercontent.com/u/5760235?s=460&u=9d969dd8d83f069ce7ebd60516770c93ac07a330&v=4" /> |
| 💻 🎨 🐛 | 💻 🐛 |
| [Hunlongyu](https://github.com/Hunlongyu) | [cuiocean](https://github.com/cuiocean) | [buvta](https://github.com/buvta) |
| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
| <img width="120" src="https://avatars2.githubusercontent.com/u/15273630?s=460&u=48cf3299e2a842c0252233d8be42ef4c5d792138&v=4"/> | <img width="120" src="https://avatars0.githubusercontent.com/u/5760235?s=460&u=9d969dd8d83f069ce7ebd60516770c93ac07a330&v=4" /> | <img width="120" src="https://avatars3.githubusercontent.com/u/12312540?s=400&v=4" /> |
| 💻 🎨 🐛 | 💻 🐛 | 💻 🐛 |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 944 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -89,7 +89,7 @@
<div class="section-title">
<h2>软件特色</h2>
<p>经过三个大版本更迭, 软件功能丰富, 操作简单.</p>
<p>软件功能丰富, 操作简单.</p>
</div>
<div class="row no-gutters">
@@ -99,7 +99,7 @@
<div class="col-md-6 icon-box" data-aos="fade-up">
<i class="bx bx-receipt"></i>
<h4>浏览</h4>
<p>浏览全网热门视频, 支持切换视频源. 详细的电影分类.支持搜索电影名和演员名称. </p>
<p>浏览全网热门视频, 支持切换视频源. 详细的电影分类. </p>
</div>
<div class="col-md-6 icon-box" data-aos="fade-up" data-aos-delay="100">
<i class="icofont-play-alt-3"></i>
@@ -124,7 +124,7 @@
<div class="col-md-6 icon-box" data-aos="fade-up" data-aos-delay="500">
<i class="icofont-cubes"></i>
<h4>其他</h4>
<p>多主题, 多语言, 自动更新</p>
<p>多主题, 自动更新</p>
</div>
</div>
</div>
@@ -146,14 +146,14 @@
</div>
<div class="owl-carousel gallery-carousel" data-aos="fade-up">
<a href="assets/img/gallery/001.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/001.png" alt=""></a>
<a href="assets/img/gallery/002.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/002.png" alt=""></a>
<a href="assets/img/gallery/003.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/003.png" alt=""></a>
<a href="assets/img/gallery/004.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/004.png" alt=""></a>
<a href="assets/img/gallery/005.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/005.png" alt=""></a>
<a href="assets/img/gallery/006.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/006.png" alt=""></a>
<a href="assets/img/gallery/007.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/007.png" alt=""></a>
<a href="assets/img/gallery/008.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/008.png" alt=""></a>
<a href="assets/img/gallery/01.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/01.png" alt=""></a>
<a href="assets/img/gallery/02.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/02.png" alt=""></a>
<a href="assets/img/gallery/03.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/03.png" alt=""></a>
<a href="assets/img/gallery/04.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/04.png" alt=""></a>
<a href="assets/img/gallery/05.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/05.png" alt=""></a>
<a href="assets/img/gallery/06.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/06.png" alt=""></a>
<a href="assets/img/gallery/07.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/07.png" alt=""></a>
<a href="assets/img/gallery/08.png" class="venobox" data-gall="gallery-carousel"><img src="assets/img/gallery/08.png" alt=""></a>
</div>
</div>
@@ -193,7 +193,7 @@
<i class="bx bx-help-circle icon-help"></i> <a data-toggle="collapse" href="#accordion-list-3" class="collapsed">跨平台<i class="bx bx-chevron-down icon-show"></i><i class="bx bx-chevron-up icon-close"></i></a>
<div id="accordion-list-3" class="collapse" data-parent=".accordion-list">
<p>
目前支持 Windows, Mac, Linux 桌面系统. 暂不支持手机端或者电视端. 未来会考虑实现全平台.
目前支持 Windows, Mac, Linux, Android, IOS, TV, Web 全平台.
</p>
</div>
</li>

View File

@@ -1,571 +0,0 @@
#EXTM3U
#EXTINF:-1,CCTV1-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv1hd/4000000/mnf.m3u8
#EXTINF:-1,CCTV-1HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/cctv1hd/2300000/mnf.m3u8
#EXTINF:-1,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225924/1.m3u8
#EXTINF:-1,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226154/1.m3u8
#EXTINF:-1,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226155/1.m3u8
#EXTINF:-1,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226226/1.m3u8
#EXTINF:-1,CCTV1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226346/1.m3u8
#EXTINF:-1,CCTV1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226431/1.m3u8
#EXTINF:-1,CCTV2 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226230/1.m3u8
#EXTINF:-1,CCTV2 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226371/1.m3u8
#EXTINF:-1,CCTV2 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226472/1.m3u8
#EXTINF:-1,CCTV3 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226471/1.m3u8
#EXTINF:-1,CCTV4 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226314/1.m3u8
#EXTINF:-1,CCTV4 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226335/1.m3u8
#EXTINF:-1,CCTV4 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226470/1.m3u8
#EXTINF:-1,CCTV5 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226469/1.m3u8
#EXTINF:-1,CCTV5+ HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226225/1.m3u8
#EXTINF:-1,CCTV5+ CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226349/1.m3u8
#EXTINF:-1,CCTV5+ CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226458/1.m3u8
#EXTINF:-1,CCTV6 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226468/1.m3u8
#EXTINF:-1,CCTV7 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226234/1.m3u8
#EXTINF:-1,CCTV7 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226467/1.m3u8
#EXTINF:-1,CCTV8 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226485/1.m3u8
#EXTINF:-1,CCTV9 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226236/1.m3u8
#EXTINF:-1,CCTV9 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226465/1.m3u8
#EXTINF:-1,CCTV10 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226227/1.m3u8
#EXTINF:-1,CCTV10 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226464/1.m3u8
#EXTINF:-1,CCTV11 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226334/1.m3u8
#EXTINF:-1,CCTV11 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226315/1.m3u8
#EXTINF:-1,CCTV11 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226463/1.m3u8
#EXTINF:-1,CCTV12 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226228/1.m3u8
#EXTINF:-1,CCTV12 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226462/1.m3u8
#EXTINF:-1,CCTV13 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226316/1.m3u8
#EXTINF:-1,CCTV14 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226229/1.m3u8
#EXTINF:-1,CCTV14 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226461/1.m3u8
#EXTINF:-1,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226460/1.m3u8
#EXTINF:-1,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226317/1.m3u8
#EXTINF:-1,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226333/1.m3u8
#EXTINF:-1,CCTV17 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226318/1.m3u8
#EXTINF:-1,CCTV17 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226459/1.m3u8
#EXTINF:-1,CCTV-4K
http://112.17.40.12/PLTV/88888888/224/3221226758/1.m3u8
#EXTINF:-1,CCTV-4K
http://112.17.40.140/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1,CCTV-4K
http://39.134.176.148/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1,CCTV-4K
http://117.148.187.83/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1,北京卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/4000000/mnf.m3u8
#EXTINF:-1,江苏卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/4000000/mnf.m3u8
#EXTINF:-1,浙江卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/4000000/mnf.m3u8
#EXTINF:-1,深圳卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/4000000/mnf.m3u8
#EXTINF:-1,山东卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/4000000/mnf.m3u8
#EXTINF:-1,湖北卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/4000000/mnf.m3u8
#EXTINF:-1,广东卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/4000000/mnf.m3u8
#EXTINF:-1,东方卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hddfws/4000000/mnf.m3u8
#EXTINF:-1,黑龙江卫视1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/4000000/mnf.m3u8
#EXTINF:-1,五星体育1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/4000000/mnf.m3u8
#EXTINF:-1,北京卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/1300000/mnf.m3u8
#EXTINF:-1,东方卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/hddfws/1300000/mnf.m3u8
#EXTINF:-1,浙江卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/1300000/mnf.m3u8
#EXTINF:-1,湖北卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/1300000/mnf.m3u8
#EXTINF:-1,湖南卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/hnwshd/1300000/mnf.m3u8
#EXTINF:-1,山东卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/1300000/mnf.m3u8
#EXTINF:-1,江苏卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/1300000/mnf.m3u8
#EXTINF:-1,深圳卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/1300000/mnf.m3u8
#EXTINF:-1,广东卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/1300000/mnf.m3u8
#EXTINF:-1,黑龙江卫视高清
http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/1300000/mnf.m3u8
#EXTINF:-1,湖南卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/hnwshd/2300000/mnf.m3u8
#EXTINF:-1,北京卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/bjwshd/2300000/mnf.m3u8
#EXTINF:-1,江苏卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/jswshd/2300000/mnf.m3u8
#EXTINF:-1,浙江卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/zjwshd/2300000/mnf.m3u8
#EXTINF:-1,深圳卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/szwshd/2300000/mnf.m3u8
#EXTINF:-1,山东卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/sdwshd/2300000/mnf.m3u8
#EXTINF:-1,湖北卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/hbwshd/2300000/mnf.m3u8
#EXTINF:-1,广东卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/gdwshd/2300000/mnf.m3u8
#EXTINF:-1,黑龙江卫视HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/hljwshd/2300000/mnf.m3u8
#EXTINF:-1,五星体育HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/2300000/mnf.m3u8
#EXTINF:-1,中国教育1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226494/1.m3u8
#EXTINF:-1,东南卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226406/1.m3u8
#EXTINF:-1,东南卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226496/1.m3u8
#EXTINF:-1,东方卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226237/1.m3u8
#EXTINF:-1,东方卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226364/1.m3u8
#EXTINF:-1,东方卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226505/1.m3u8
#EXTINF:-1,北京卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226224/1.m3u8
#EXTINF:-1,北京卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226367/1.m3u8
#EXTINF:-1,北京卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226441/1.m3u8
#EXTINF:-1,天津卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226246/1.m3u8
#EXTINF:-1,天津卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226502/1.m3u8
#EXTINF:-1,安徽卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226223/1.m3u8
#EXTINF:-1,安徽卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226499/1.m3u8
#EXTINF:-1,山东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225894/1.m3u8
#EXTINF:-1,山东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226244/1.m3u8
#EXTINF:-1,山东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226308/1.m3u8
#EXTINF:-1,山东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226501/1.m3u8
#EXTINF:-1,广东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225878/1.m3u8
#EXTINF:-1,广东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226238/1.m3u8
#EXTINF:-1,广东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226508/1.m3u8
#EXTINF:-1,江苏卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226242/1.m3u8
#EXTINF:-1,江苏卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226366/1.m3u8
#EXTINF:-1,江苏卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226506/1.m3u8
#EXTINF:-1,江西卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226243/1.m3u8
#EXTINF:-1,河北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226507/1.m3u8
#EXTINF:-1,浙江卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226247/1.m3u8
#EXTINF:-1,浙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226365/1.m3u8
#EXTINF:-1,浙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226504/1.m3u8
#EXTINF:-1,深圳卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225897/1.m3u8
#EXTINF:-1,深圳卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226245/1.m3u8
#EXTINF:-1,深圳卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226495/1.m3u8
#EXTINF:-1,湖北卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226240/1.m3u8
#EXTINF:-1,湖北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226310/1.m3u8
#EXTINF:-1,湖北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226503/1.m3u8
#EXTINF:-1,湖南卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226241/1.m3u8
#EXTINF:-1,湖南卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226509/1.m3u8
#EXTINF:-1,贵州卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226497/1.m3u8
#EXTINF:-1,辽宁卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226500/1.m3u8
#EXTINF:-1,黑龙江卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226239/1.m3u8
#EXTINF:-1,黑龙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226498/1.m3u8
#EXTINF:-1,北京冬奥纪实 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226438/1.m3u8
#EXTINF:-1,北京影视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226486/1.m3u8
#EXTINF:-1,北京文艺 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226440/1.m3u8
#EXTINF:-1,北京新闻 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226437/1.m3u8
#EXTINF:-1,安徽卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/ahws/1300000/mnf.m3u8
#EXTINF:-1,兵团卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/btws/1300000/mnf.m3u8
#EXTINF:-1,甘肃卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/gsws/1300000/mnf.m3u8
#EXTINF:-1,陕西卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/sxws/1300000/mnf.m3u8
#EXTINF:-1,山西卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/shanxiws/1300000/mnf.m3u8
#EXTINF:-1,吉林卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/jlws/1300000/mnf.m3u8
#EXTINF:-1,河北卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/hbws/1300000/mnf.m3u8
#EXTINF:-1,四川卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/scws/1300000/mnf.m3u8
#EXTINF:-1,贵州卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/gzws/1300000/mnf.m3u8
#EXTINF:-1,云南卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/ynws/1300000/mnf.m3u8
#EXTINF:-1,辽宁卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/lnws/1300000/mnf.m3u8
#EXTINF:-1,旅游卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/lyws/1300000/mnf.m3u8
#EXTINF:-1,东南卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/dnws/1300000/mnf.m3u8
#EXTINF:-1,重庆卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/cqws/1300000/mnf.m3u8
#EXTINF:-1,广西卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/gxws/1300000/mnf.m3u8
#EXTINF:-1,青海卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/qhws/1300000/mnf.m3u8
#EXTINF:-1,江西卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/jxws/1300000/mnf.m3u8
#EXTINF:-1,内蒙古卫视
http://keonline.shanghai.liveplay.qq.com/live/program/live/nmgws/1300000/mnf.m3u8
#EXTINF:-1,天津卫视
http://112.17.40.140/PLTV/88888888/224/3221226412/index.m3u8
#EXTINF:-1,河北卫视超清1
http://223.110.245.149/ott.js.chinamobile.com/PLTV/3/224/3221225840/index.m3u8
#EXTINF:-1,湖南卫视
http://112.17.40.140/PLTV/88888888/224/3221226553/index.m3u8
#EXTINF:-1,浙江卫视
http://223.110.243.173/PLTV/3/224/3221227215/index.m3u8
#EXTINF:-1,江苏卫视
http://112.17.40.140/PLTV/88888888/224/3221226414/index.m3u8
#EXTINF:-1,东南卫视
http://117.169.124.37:6610/ysten-businessmobile/live/dongnanstv/yst.m3u8
#EXTINF:-1,湖北卫视
http://223.110.243.171/PLTV/3/224/3221227211/index.m3u8
#EXTINF:-1,广东卫视
http://112.17.40.140/PLTV/88888888/224/3221226225/index.m3u8
#EXTINF:-1,深圳卫视
http://223.110.243.171/PLTV/3/224/3221227217/index.m3u8
#EXTINF:-1,辽宁卫视
http://223.110.245.145/ott.js.chinamobile.com/PLTV/3/224/3221227410/index.m3u8
#EXTINF:-1,龙江卫视
http://112.17.40.140/PLTV/88888888/224/3221226555/index.m3u8
#EXTINF:-1,江西卫视
http://112.17.40.140/PLTV/88888888/224/3221226557/index.m3u8
#EXTINF:-1,四川卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221227006/1.m3u8
#EXTINF:-1,重庆卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225949/1.m3u8
#EXTINF:-1,重庆卫视
http://ivi.bupt.edu.cn/hls/cqhd.m3u8
#EXTINF:-1,河南卫视超清2
http://223.110.245.157/ott.js.chinamobile.com/PLTV/3/224/3221225815/index.m3u8
#EXTINF:-1,贵州卫视超清2
http://223.110.245.149/ott.js.chinamobile.com/PLTV/3/224/3221225787/index.m3u8
#EXTINF:-1,海南卫视
http://112.50.243.8/PLTV/88888888/224/3221225855/1.m3u8
#EXTINF:-1,云南卫视超清1
http://223.110.245.159/ott.js.chinamobile.com/PLTV/3/224/3221225838/index.m3u8
#EXTINF:-1,宁夏卫视超清1
http://223.110.245.151/ott.js.chinamobile.com/PLTV/3/224/3221225842/index.m3u8
#EXTINF:-1,内蒙卫视超清1
http://223.110.245.161/ott.js.chinamobile.com/PLTV/3/224/3221225836/index.m3u8
#EXTINF:-1,广西卫视
http://112.50.243.8/PLTV/88888888/224/3221225836/1.m3u8
#EXTINF:-1,五星体育HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/ssty/1300000/mnf.m3u8
#EXTINF:-1,北京卡酷少儿 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226558/1.m3u8
#EXTINF:-1,法治天地HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/fztd/1300000/mnf.m3u8
#EXTINF:-1,欢笑剧场HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/hxjc/1300000/mnf.m3u8
#EXTINF:-1,都市剧场HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/dsjc/1300000/mnf.m3u8
#EXTINF:-1,七彩戏剧HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/qcxj/1300000/mnf.m3u8
#EXTINF:-1,动漫秀场HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/dmxc/1300000/mnf.m3u8
#EXTINF:-1,劲爆体育HD
http://keonline.shanghai.liveplay.qq.com/live/program/live/jbty/1300000/mnf.m3u8
#EXTINF:-1,极速汽车
http://keonline.shanghai.liveplay.qq.com/live/program/live/jsqc/1300000/mnf.m3u8
#EXTINF:-1,游戏风云
http://keonline.shanghai.liveplay.qq.com/live/program/live/yxfy/1300000/mnf.m3u8
#EXTINF:-1,金鹰卡通
http://keonline.shanghai.liveplay.qq.com/live/program/live/jykt/1300000/mnf.m3u8
#EXTINF:-1,炫动卡通
http://keonline.shanghai.liveplay.qq.com/live/program/live/xdkt/1300000/mnf.m3u8
#EXTINF:-1,嘉佳卡通
http://keonline.shanghai.liveplay.qq.com/live/program/live/jjkt/1300000/mnf.m3u8
#EXTINF:-1,星尚
http://keonline.shanghai.liveplay.qq.com/live/program/live/shss/1300000/mnf.m3u8
#EXTINF:-1,上海纪实
http://keonline.shanghai.liveplay.qq.com/live/program/live/jspd/1300000/mnf.m3u8
#EXTINF:-1,上海新闻
http://keonline.shanghai.liveplay.qq.com/live/program/live/xwzh/1300000/mnf.m3u8
#EXTINF:-1,上海娱乐
http://keonline.shanghai.liveplay.qq.com/live/program/live/ylpd/1300000/mnf.m3u8
#EXTINF:-1,上海电视剧
http://keonline.shanghai.liveplay.qq.com/live/program/live/dsjpd/1300000/mnf.m3u8
#EXTINF:-1,上海ICS外语频道
http://keonline.shanghai.liveplay.qq.com/live/program/live/wypd/1300000/mnf.m3u8
#EXTINF:-1,上海艺术人文
http://keonline.shanghai.liveplay.qq.com/live/program/live/ysrw/1300000/mnf.m3u8
#EXTINF:-1,东方财经浦东
http://keonline.shanghai.liveplay.qq.com/live/program/live/dfcj/1300000/mnf.m3u8
#EXTINF:-1,第一财经
http://keonline.shanghai.liveplay.qq.com/live/program/live/dycj/1300000/mnf.m3u8
#EXTINF:-1,直播1-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba1/4000000/mnf.m3u8
#EXTINF:-1,直播2-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba2/4000000/mnf.m3u8
#EXTINF:-1,直播3-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba3/4000000/mnf.m3u8
#EXTINF:-1,直播4-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba4/4000000/mnf.m3u8
#EXTINF:-1,直播5-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba5/4000000/mnf.m3u8
#EXTINF:-1,直播6-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba6/4000000/mnf.m3u8
#EXTINF:-1,直播7-1080P
http://keonline.shanghai.liveplay.qq.com/live/program/live/hdnba7/4000000/mnf.m3u8
#EXTINF:-1,纯享4K源码1
http://112.50.243.8/PLTV/88888888/224/3221226825/1.m3u8
#EXTINF:-1,百事4K频道
http://112.17.40.145/PLTV/88888888/224/3221226718/index.m3u8
#EXTINF:-1,凤凰资讯
http://112.17.40.140/PLTV/88888888/224/3221226491/index.m3u8
#EXTINF:-1,凤凰资讯
http://117.169.124.37:6610/ysten-businessmobile/live/fhzixun/1.m3u8
#EXTINF:-1,凤凰中文
http://117.169.124.37:6610/ysten-businessmobile/live/fhchinese/1.m3u8
#EXTINF:-1,凤凰中文
http://117.169.120.138:8080/live/fhchinese/index.m3u8
#EXTINF:-1,高清影视1台
http://112.50.243.8/PLTV/88888888/224/3221226736/1.m3u8
#EXTINF:-1,高清影视2台
http://112.50.243.8/PLTV/88888888/224/3221225881/1.m3u8
#EXTINF:-1,高清影视3台
http://112.50.243.8/PLTV/88888888/224/3221226708/1.m3u8
#EXTINF:-1,高清影视4台
http://112.50.243.8/PLTV/88888888/224/3221226712/1.m3u8
#EXTINF:-1,高清影视5台
http://112.50.243.8/PLTV/88888888/224/3221225893/1.m3u8
#EXTINF:-1,高清影视6台
http://112.50.243.8/PLTV/88888888/224/3221226692/1.m3u8
#EXTINF:-1,高清影视7台
http://112.50.243.8/PLTV/88888888/224/3221226754/1.m3u8
#EXTINF:-1,高清影视8台
http://112.17.40.145/PLTV/88888888/224/3221226608/index.m3u8
#EXTINF:-1,高清影视9台
http://112.17.40.145/PLTV/88888888/224/3221226606/index.m3u8
#EXTINF:-1,高清影视10台
http://112.17.40.145/PLTV/88888888/224/3221226360/index.m3u8
#EXTINF:-1,高清动画11台
http://112.50.243.8/PLTV/88888888/224/3221226732/1.m3u8
#EXTINF:-1,高清动画12台
http://112.50.243.8/PLTV/88888888/224/3221226741/1.m3u8
#EXTINF:-1,高清动漫13台
http://112.50.243.8/PLTV/88888888/224/3221226743/1.m3u8
#EXTINF:-1,高清影视14台
http://ivi.bupt.edu.cn/hls/chchd.m3u8
#EXTINF:-1,北京纪实高清
http://112.50.243.8/PLTV/88888888/224/3221225944/1.m3u8
#EXTINF:-1,峨眉电影高清
http://scgctvshow.sctv.com/hdlive/emei/1.m3u8
#EXTINF:-1,欢笑剧场高清
http://112.50.243.8/PLTV/88888888/224/3221226729/1.m3u8
#EXTINF:-1,纪实频道高清
http://112.50.243.8/PLTV/88888888/224/3221225946/1.m3u8
#EXTINF:-1,极速汽车高清
http://112.50.243.8/PLTV/88888888/224/3221226140/1.m3u8
#EXTINF:-1,动漫秀场高清
http://112.50.243.8/PLTV/88888888/224/3221226141/1.m3u8
#EXTINF:-1,求索纪录
http://112.17.40.145/PLTV/88888888/224/3221226610/index.m3u8
#EXTINF:-1,求索科学
http://125.210.152.18:9090/live/QSKX_1200.m3u8
#EXTINF:-1,求索动物
http://125.210.152.18:9090/live/QSDW_1200.m3u8
#EXTINF:-1,求索生活
http://125.210.152.18:9090/live/QSSH_1200.m3u8
#EXTINF:-1,日本天気预报
http://movie.mcas.jp/mcas/wn1_2/master.m3u8
#EXTINF:-1,奥林匹克高清
http://ott-live.olympicchannel.com/out/u/OC1_2.m3u8?fluxustv.m3u8
#EXTINF:-1,奥铃匹克高清
http://ott-live.olympicchannel.com/out/u/OC1_1.m3u8?fluxustv.m3u8
#EXTINF:-1,爱青春
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230130/index.m3u8
#EXTINF:-1,爱家庭
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230118/index.m3u8
#EXTINF:-1,爱探索
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230112/index.m3u8
#EXTINF:-1,爱科学
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230106/index.m3u8
#EXTINF:-1,爱猎奇
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230097/index.m3u8
#EXTINF:-1,爱谍战
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230092/index.m3u8
#EXTINF:-1,爱娱乐
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230077/index.m3u8
#EXTINF:-1,爱旅行
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230052/index.m3u8
#EXTINF:-1,爱怀旧
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230049/index.m3u8
#EXTINF:-1,爱体育
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230034/index.m3u8
#EXTINF:-1,爱赛车
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230032/index.m3u8
#EXTINF:-1,北京少儿
http://ivi.bupt.edu.cn/hls/btv10.m3u8
#EXTINF:-1,动漫电影
http://112.17.40.140/PLTV/88888888/224/3221226178/index.m3u8
#EXTINF:-1,重庆少儿
http://219.153.252.50/PLTV/88888888/224/3221225646/1.m3u8
#EXTINF:-1,嘉佳卡通
http://112.17.40.140/PLTV/88888888/224/3221226461/index.m3u8
#EXTINF:-1,耀才财经
http://202.69.67.66:443/webcast/bshdlive-mobile/playlist.m3u8
#EXTINF:-1,亚旅卫视
http://hls.jingchangkan.tv/jingchangkan/156722438_0HaM/index.m3u8
#EXTINF:-1,信吉电视
http://220.130.241.203:1935/sjtv/livestream_360p/playlist.m3u8
#EXTINF:-1,唯心電視
http://mobile.ccdntech.com/transcoder/_definst_/vod164_Live/live/chunklist_w1177047531.m3u8
#EXTINF:-1,百事通台
http://112.17.40.145/PLTV/88888888/224/3221226596/index.m3u8
#EXTINF:-1,HBO2台
http://161.0.157.5/PLTV/88888888/224/3221227026/03.m3u8fluxustv.m3u8
#EXTINF:-1,点掌财经
http://cclive2.aniu.tv/live/anzb.m3u8
#EXTINF:-1,日本NHK华语
https://nhkw-zh-hlscomp.akamaized.net/ixxemlzk1vqvy44o/playlist.m3u8
#EXTINF:-1,日本NHK英语
https://nhkwlive-ojp.akamaized.net/hls/live/2003459/nhkwlive-ojp/index_1M.m3u8
#EXTINF:-1,日本Japan News 24
http://www.news24.jp/livestream/index.m3u8
#EXTINF:-1,日本JapanetChannelDX
http://bcsecurelivehls-i.akamaihd.net/hls/live/265320/5043843989001/140130JTDX/index_1200.m3u8
#EXTINF:-1,日本QVC
http://cdn-live1.qvc.jp/iPhone/800/800.m3u8
#EXTINF:-1,韩国EBS 第一频道
http://ebsonairios.ebs.co.kr/groundwavetablet500k/tablet500k/playlist.m3u8
#EXTINF:-1,韩国EBS 少儿频道
http://ebsonairios.ebs.co.kr/ebsutablet500k/tablet500k/playlist.m3u8
#EXTINF:-1,韩国KCTV
http://119.77.96.184:1935/chn21/chn21/chunklist_w252131137.m3u8
#EXTINF:-1,朝鲜中央台
http://119.77.96.184:1935/chn05/chn05/chunklist_w644291506.m3u8
#EXTINF:-1,韩国KTV 韩国电视
http://218.38.152.31:1935/klive/klive.stream/playlist.m3u8
#EXTINF:-1,韩国EBS 儿童频道
http://ebsonairios.ebs.co.kr/ebsutablet500k/_definst_/tablet500k/chunklist_w1965791004.m3u8
#EXTINF:-1,韩国阿里郎WORLDworld
http://amdlive.ctnd.com.edgesuite.net/arirang_1ch/smil:arirang_1ch.smil/playlist.m3u8
#EXTINF:-1,韩国阿里郎WORLD
http://amdlive.ctnd.com.edgesuite.net/arirang_1ch/smil:arirang_1ch/master.m3u8
#EXTINF:-1,KOREA YTN Science
http://slive.sciencetv.kr:1935/science/yslive_20140419_1/playlist.m3u8
#EXTINF:-1,Luxury World
http://nano.teleservice.su:8080/hls/luxury.m3u8
#EXTINF:-1,韩国BBS佛教广播
http://bbstv.clouducs.com:1935/bbstv-live/livestream/chunklist_w1403706733.m3u8
#EXTINF:-1,CPAC
http://bcoveliveios-i.akamaihd.net/hls/live/248519/1242843915001_1/master.m3u8
#EXTINF:-1,中国环球
http://live.cgtn.com/1000/prog_index.m3u8
#EXTINF:-1,狗狗宠物
http://video.blivenyc.com/broadcast/prod/2061/22/file-3192k.m3u8
#EXTINF:-1,法国时尚
http://lb.streaming.sk/fashiontv/stream/chunklist_w1702070444.m3u8
#EXTINF:-1,亚洲新闻
http://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_4.m3u8
#EXTINF:-1,越南人民报
http://vietcago.net/vstv/thnd.m3u8
#EXTINF:-1,印度音乐电视
http://104.237.60.234/live/gabruutv.m3u8?dsjtv.m3u8
#EXTINF:-1,法国第五世界台
http://v3plusinfo247hls-i.akamaihd.net/hls/live/218877-b/v3plusinfo247hls/v3plusinfo247hls_1_1.m3u8
#EXTINF:-1,俄罗斯HD时尚频道
http://95.67.47.115/hls/hdfashion_ua_hi/index.m3u8
#EXTINF:-1,乌克兰M2 音乐频道
http://live.m2.tv/hls3/stream.m3u8
#EXTINF:-1,西班牙中国环球
http://livees.cgtn.com/1000e/prog_index.m3u8
#EXTINF:-1,意大利意大利电台
http://radioitaliatv-lh.akamaihd.net/i/radioitaliatv_1@329645/index_720x480_av-p.m3u8
#EXTINF:-1,意大利V2 音乐频道
http://de1se01.v2beat.live/playlist.m3u8
#EXTINF:-1,墨西哥墨西哥电视
http://bcoveliveios-i.akamaihd.net/hls/live/201661/57828478001/milenio_center_512k@51752.m3u8
#EXTINF:-1,音乐20TV
http://m2otv-lh.akamaihd.net/i/m2oTv_1@186074/index_600_av-p.m3u8
#EXTINF:-1,当红MTV
http://unilivemtveu-lh.akamaihd.net/i/mtvno_1@346424/index_3500_av-b.m3u8
#EXTINF:-1,酷酷频道
http://edge1.tikilive.com:1935/unrestricted_tikilive/25947/amlst:NWKlw6jwyXpz/chunklist_w981409619_b1105254.m3u8?fluxustv.m3u8
#EXTINF:-1,红牛电视
http://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_1660.m3u8
#EXTINF:-1,NBC电视
http://161.0.157.51/PLTV/88888888/224/3221227040/index.m3u8?fluxustv.m3u8
#EXTINF:-1,Jewelry电视
http://wowzaprod134-i.akamaihd.net/hls/live/577814/ccddaf02/playlist.m3u8
#EXTINF:-1,Darcizzle电视
http://30a-tv.com/darcizzle.m3u8
#EXTINF:-1,CBS新闻
http://cbsnewshd-lh.akamaihd.net/i/CBSNHD_7@199302/master.m3u8
#EXTINF:-1,美国Deutsche Welle
http://dwstream4-lh.akamaihd.net/i/dwstream4_live@131329/master.m3u8
#EXTINF:-1,美国360 North
http://wowzaprod3-i.akamaihd.net/hls/live/252236/2147483647_360north_247/playlist.m3u8
#EXTINF:-1,美国Fox News Talk Radio
http://fnurtmp-f.akamaihd.net/i/FNRADIO_1@92141/master.m3u8
#EXTINF:-1,日本cgntv
http://cgntv-glive.ofsdelivery.net/live/_definst_/cgntv_jp/playlist.m3u8
#EXTINF:-1,日本Japanet Channel DX
http://bcsecurelivehls-i.akamaihd.net/hls/live/265320/5043843989001/140130JTDX/index_600.m3u8

View File

@@ -1,723 +0,0 @@
#EXTM3U
#EXTINF:-1 ,====== =北京移动= ======
http://0/0.m3u8
#EXTINF:-1 ,咪咕4K
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226399/1.m3u8
#EXTINF:-1 ,咪咕4K
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226400/1.m3u8
#EXTINF:-1 ,北京IPTV4K超清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226550/1.m3u8
#EXTINF:-1 ,北京IPTV淘BABY CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226554/1.m3u8
#EXTINF:-1 ,北京IPTV淘剧场 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226553/1.m3u8
#EXTINF:-1 ,北京IPTV淘娱乐 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226551/1.m3u8
#EXTINF:-1 ,北京IPTV淘电影 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226552/1.m3u8
#EXTINF:-1 ,北京IPTV萌宠TV CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226555/1.m3u8
#EXTINF:-1 ,老伙计-laoguy.com
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226555/1.m3u8
#EXTINF:-1 ,大健康 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226556/1.m3u8
#EXTINF:-1 ,凤凰中文 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225942/1.m3u8
#EXTINF:-1 ,凤凰中文 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225948/1.m3u8
#EXTINF:-1 ,凤凰资讯 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225949/1.m3u8
#EXTINF:-1 ,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225924/1.m3u8
#EXTINF:-1 ,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226154/1.m3u8
#EXTINF:-1 ,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226155/1.m3u8
#EXTINF:-1 ,CCTV1 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226226/1.m3u8
#EXTINF:-1 ,CCTV1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226346/1.m3u8
#EXTINF:-1 ,CCTV1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226431/1.m3u8
#EXTINF:-1 ,CCTV2 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226230/1.m3u8
#EXTINF:-1 ,CCTV2 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226371/1.m3u8
#EXTINF:-1 ,CCTV2 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226472/1.m3u8
#EXTINF:-1 ,CCTV3 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226471/1.m3u8
#EXTINF:-1 ,CCTV4 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226314/1.m3u8
#EXTINF:-1 ,CCTV4 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226335/1.m3u8
#EXTINF:-1 ,CCTV4 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226470/1.m3u8
#EXTINF:-1 ,CCTV5 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226469/1.m3u8
#EXTINF:-1 ,CCTV5+ HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226225/1.m3u8
#EXTINF:-1 ,CCTV5+ CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226349/1.m3u8
#EXTINF:-1 ,CCTV5+ CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226458/1.m3u8
#EXTINF:-1 ,CCTV6 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226468/1.m3u8
#EXTINF:-1 ,CCTV7 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226234/1.m3u8
#EXTINF:-1 ,CCTV7 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226467/1.m3u8
#EXTINF:-1 ,CCTV8 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226485/1.m3u8
#EXTINF:-1 ,CCTV9 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226236/1.m3u8
#EXTINF:-1 ,CCTV9 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226465/1.m3u8
#EXTINF:-1 ,CCTV10 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226227/1.m3u8
#EXTINF:-1 ,CCTV10 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226464/1.m3u8
#EXTINF:-1 ,CCTV11 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226334/1.m3u8
#EXTINF:-1 ,CCTV11 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226315/1.m3u8
#EXTINF:-1 ,CCTV11 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226463/1.m3u8
#EXTINF:-1 ,CCTV12 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226228/1.m3u8
#EXTINF:-1 ,CCTV12 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226462/1.m3u8
#EXTINF:-1 ,CCTV13 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226316/1.m3u8
#EXTINF:-1 ,CCTV14 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226229/1.m3u8
#EXTINF:-1 ,CCTV14 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226461/1.m3u8
#EXTINF:-1 ,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226460/1.m3u8
#EXTINF:-1 ,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226317/1.m3u8
#EXTINF:-1 ,CCTV15 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226333/1.m3u8
#EXTINF:-1 ,CCTV17 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226318/1.m3u8
#EXTINF:-1 ,CCTV17 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226459/1.m3u8
#EXTINF:-1 ,中国教育1 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226494/1.m3u8
#EXTINF:-1 ,东南卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226406/1.m3u8
#EXTINF:-1 ,东南卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226496/1.m3u8
#EXTINF:-1 ,东方卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226237/1.m3u8
#EXTINF:-1 ,东方卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226364/1.m3u8
#EXTINF:-1 ,东方卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226505/1.m3u8
#EXTINF:-1 ,北京卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226224/1.m3u8
#EXTINF:-1 ,北京卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226367/1.m3u8
#EXTINF:-1 ,北京卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226441/1.m3u8
#EXTINF:-1 ,天津卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226246/1.m3u8
#EXTINF:-1 ,天津卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226502/1.m3u8
#EXTINF:-1 ,安徽卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226223/1.m3u8
#EXTINF:-1 ,安徽卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226499/1.m3u8
#EXTINF:-1 ,山东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225894/1.m3u8
#EXTINF:-1 ,山东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226244/1.m3u8
#EXTINF:-1 ,山东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226308/1.m3u8
#EXTINF:-1 ,山东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226501/1.m3u8
#EXTINF:-1 ,广东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225878/1.m3u8
#EXTINF:-1 ,广东卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226238/1.m3u8
#EXTINF:-1 ,广东卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226508/1.m3u8
#EXTINF:-1 ,江苏卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226242/1.m3u8
#EXTINF:-1 ,江苏卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226366/1.m3u8
#EXTINF:-1 ,江苏卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226506/1.m3u8
#EXTINF:-1 ,江西卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226243/1.m3u8
#EXTINF:-1 ,河北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226507/1.m3u8
#EXTINF:-1 ,浙江卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226247/1.m3u8
#EXTINF:-1 ,浙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226365/1.m3u8
#EXTINF:-1 ,浙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226504/1.m3u8
#EXTINF:-1 ,深圳卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225897/1.m3u8
#EXTINF:-1 ,深圳卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226245/1.m3u8
#EXTINF:-1 ,深圳卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226495/1.m3u8
#EXTINF:-1 ,湖北卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226240/1.m3u8
#EXTINF:-1 ,湖北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226310/1.m3u8
#EXTINF:-1 ,湖北卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226503/1.m3u8
#EXTINF:-1 ,湖南卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226241/1.m3u8
#EXTINF:-1 ,湖南卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226509/1.m3u8
#EXTINF:-1 ,贵州卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226497/1.m3u8
#EXTINF:-1 ,辽宁卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226500/1.m3u8
#EXTINF:-1 ,黑龙江卫视 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226239/1.m3u8
#EXTINF:-1 ,黑龙江卫视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226498/1.m3u8
#EXTINF:-1 ,北京冬奥纪实 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226438/1.m3u8
#EXTINF:-1 ,北京影视 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226486/1.m3u8
#EXTINF:-1 ,北京文艺 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226440/1.m3u8
#EXTINF:-1 ,北京新闻 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226437/1.m3u8
#EXTINF:-1 ,北京卡酷少儿 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226558/1.m3u8
#EXTINF:-1 ,湖南快乐垂钓 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226549/1.m3u8
#EXTINF:-1 ,湖南茶频道 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226548/1.m3u8
#EXTINF:-1 ,黑莓动画 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225914/1.m3u8
#EXTINF:-1 ,黑莓动画 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226289/1.m3u8
#EXTINF:-1 ,黑莓电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225927/1.m3u8
#EXTINF:-1 ,黑莓电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226292/1.m3u8
#EXTINF:-1 ,黑莓电竞 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225931/1.m3u8
#EXTINF:-1 ,黑莓电竞 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226250/1.m3u8
#EXTINF:-1 ,黑莓电竞 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226262/1.m3u8
#EXTINF:-1 ,黑莓电竞 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226307/1.m3u8
#EXTINF:-1 ,NewTV中国功夫 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225951/1.m3u8
#EXTINF:-1 ,NewTV中国功夫 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226298/1.m3u8
#EXTINF:-1 ,NewTV中国功夫 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226321/1.m3u8
#EXTINF:-1 ,NewTV怡伴健康 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225919/1.m3u8
#EXTINF:-1 ,NewTV怡伴健康 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226306/1.m3u8
#EXTINF:-1 ,NewTV怡伴健康 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226327/1.m3u8
#EXTINF:-1 ,NewTV军事评论 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225926/1.m3u8
#EXTINF:-1 ,NewTV军事评论 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226303/1.m3u8
#EXTINF:-1 ,NewTV军事评论 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226326/1.m3u8
#EXTINF:-1 ,NewTV军旅剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225923/1.m3u8
#EXTINF:-1 ,NewTV军旅剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226301/1.m3u8
#EXTINF:-1 ,NewTV军旅剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226324/1.m3u8
#EXTINF:-1 ,NewTV农业致富 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225930/1.m3u8
#EXTINF:-1 ,NewTV农业致富 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226304/1.m3u8
#EXTINF:-1 ,NewTV动作电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225915/1.m3u8
#EXTINF:-1 ,NewTV动作电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226288/1.m3u8
#EXTINF:-1 ,NewTV动作电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226329/1.m3u8
#EXTINF:-1 ,NewTV古装剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225916/1.m3u8
#EXTINF:-1 ,NewTV古装剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226300/1.m3u8
#EXTINF:-1 ,NewTV古装剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226323/1.m3u8
#EXTINF:-1 ,NewTV家庭剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225918/1.m3u8
#EXTINF:-1 ,NewTV家庭剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226290/1.m3u8
#EXTINF:-1 ,NewTV家庭剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226330/1.m3u8
#EXTINF:-1 ,NewTV惊悚悬疑 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225921/1.m3u8
#EXTINF:-1 ,NewTV惊悚悬疑 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226294/1.m3u8
#EXTINF:-1 ,NewTV惊悚悬疑 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226423/1.m3u8
#EXTINF:-1 ,NewTV明星大片 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225929/1.m3u8
#EXTINF:-1 ,NewTV明星大片 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226295/1.m3u8
#EXTINF:-1 ,NewTV明星大片 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226425/1.m3u8
#EXTINF:-1 ,NewTV武搏世界 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226171/1.m3u8
#EXTINF:-1 ,NewTV武搏世界 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226297/1.m3u8
#EXTINF:-1 ,NewTV武搏世界 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226320/1.m3u8
#EXTINF:-1 ,NewTV海外剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225917/1.m3u8
#EXTINF:-1 ,NewTV海外剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226302/1.m3u8
#EXTINF:-1 ,NewTV海外剧场 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226325/1.m3u8
#EXTINF:-1 ,NewTV潮妈辣婆 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225957/1.m3u8
#EXTINF:-1 ,NewTV潮妈辣婆 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226286/1.m3u8
#EXTINF:-1 ,NewTV炫舞未来 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226248/1.m3u8
#EXTINF:-1 ,NewTV爱情喜剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225913/1.m3u8
#EXTINF:-1 ,NewTV爱情喜剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226299/1.m3u8
#EXTINF:-1 ,NewTV爱情喜剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226322/1.m3u8
#EXTINF:-1 ,NewTV精品体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226287/1.m3u8
#EXTINF:-1 ,NewTV精品体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226328/1.m3u8
#EXTINF:-1 ,NewTV精品体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225922/1.m3u8
#EXTINF:-1 ,NewTV精品大剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225925/1.m3u8
#EXTINF:-1 ,NewTV精品大剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226291/1.m3u8
#EXTINF:-1 ,NewTV精品大剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226331/1.m3u8
#EXTINF:-1 ,NewTV精品纪录 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226293/1.m3u8
#EXTINF:-1 ,NewTV精品纪录 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226332/1.m3u8
#EXTINF:-1 ,NewTV超级体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226157/1.m3u8
#EXTINF:-1 ,NewTV超级体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226158/1.m3u8
#EXTINF:-1 ,NewTV超级体育 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226232/1.m3u8
#EXTINF:-1 ,NewTV超级体育 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226348/1.m3u8
#EXTINF:-1 ,NewTV超级电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226133/1.m3u8
#EXTINF:-1 ,NewTV超级电影 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226233/1.m3u8
#EXTINF:-1 ,NewTV超级电影 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226369/1.m3u8
#EXTINF:-1 ,NewTV超级电视剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225864/1.m3u8
#EXTINF:-1 ,NewTV超级电视剧 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226253/1.m3u8
#EXTINF:-1 ,NewTV超级电视剧 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226368/1.m3u8
#EXTINF:-1 ,NewTV超级综艺 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226127/1.m3u8
#EXTINF:-1 ,NewTV超级综艺 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226231/1.m3u8
#EXTINF:-1 ,NewTV超级综艺 CQ
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226370/1.m3u8
#EXTINF:-1 ,NewTV金牌综艺 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225920/1.m3u8
#EXTINF:-1 ,NewTV金牌综艺 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226296/1.m3u8
#EXTINF:-1 ,NewTV金牌综艺 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226347/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226374/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226375/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226377/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226378/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226379/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226380/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226381/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226382/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226394/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226395/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226396/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226397/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226398/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226393/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226392/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226391/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226390/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226372/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226373/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226376/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226383/1.m3u8
#EXTINF:-1 ,咪咕视频 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226384/1.m3u8
#EXTINF:-1 ,北京家有购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226429/1.m3u8
#EXTINF:-1 ,山西优购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226386/1.m3u8
#EXTINF:-1 ,中视购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226547/1.m3u8
#EXTINF:-1 ,央广购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226319/1.m3u8
#EXTINF:-1 ,央广购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226363/1.m3u8
#EXTINF:-1 ,江苏好享购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226312/1.m3u8
#EXTINF:-1 ,江苏好享购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226344/1.m3u8
#EXTINF:-1 ,湖南快乐购 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226341/1.m3u8
#EXTINF:-1 ,江西风尚购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225911/1.m3u8
#EXTINF:-1 ,江西风尚购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226305/1.m3u8
#EXTINF:-1 ,江西风尚购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226342/1.m3u8
#EXTINF:-1 ,江苏好享购物 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226313/1.m3u8
#EXTINF:-1 ,5GO美妆个护 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226387/1.m3u8
#EXTINF:-1 ,5GO美妆个护 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226389/1.m3u8
#EXTINF:-1 ,5GO服饰内衣 HD
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226388/1.m3u8
#EXTINF:-1 ,CCTV1 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226432/1.m3u8
#EXTINF:-1 ,CCTV1 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226338/1.m3u8
#EXTINF:-1 ,CCTV2 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225934/1.m3u8
#EXTINF:-1 ,CCTV2 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226457/1.m3u8
#EXTINF:-1 ,CCTV3 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226456/1.m3u8
#EXTINF:-1 ,CCTV4 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226156/1.m3u8
#EXTINF:-1 ,CCTV4 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226455/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226454/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226256/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226257/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226258/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226259/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226260/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226261/1.m3u8
#EXTINF:-1 ,CCTV5 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226340/1.m3u8
#EXTINF:-1 ,CCTV5+ 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225938/1.m3u8
#EXTINF:-1 ,CCTV6 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226453/1.m3u8
#EXTINF:-1 ,CCTV7 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225863/1.m3u8
#EXTINF:-1 ,CCTV7 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226452/1.m3u8
#EXTINF:-1 ,CCTV8 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226451/1.m3u8
#EXTINF:-1 ,CCTV9 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226450/1.m3u8
#EXTINF:-1 ,CCTV9 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225865/1.m3u8
#EXTINF:-1 ,CCTV10 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225868/1.m3u8
#EXTINF:-1 ,CCTV10 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226449/1.m3u8
#EXTINF:-1 ,CCTV11 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225869/1.m3u8
#EXTINF:-1 ,CCTV11 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226448/1.m3u8
#EXTINF:-1 ,CCTV12 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225870/1.m3u8
#EXTINF:-1 ,CCTV12 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226447/1.m3u8
#EXTINF:-1 ,CCTV13 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226446/1.m3u8
#EXTINF:-1 ,CCTV13 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226159/1.m3u8
#EXTINF:-1 ,CCTV13 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226339/1.m3u8
#EXTINF:-1 ,CCTV14 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225872/1.m3u8
#EXTINF:-1 ,CCTV14 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226445/1.m3u8
#EXTINF:-1 ,CCTV14 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225928/1.m3u8
#EXTINF:-1 ,CCTV15 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225940/1.m3u8
#EXTINF:-1 ,CCTV15 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226444/1.m3u8
#EXTINF:-1 ,CCTV17 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226442/1.m3u8
#EXTINF:-1 ,CGTN 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226404/1.m3u8
#EXTINF:-1 ,CGTN 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225867/1.m3u8
#EXTINF:-1 ,CGTN 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226443/1.m3u8
#EXTINF:-1 ,CGTN纪录 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226403/1.m3u8
#EXTINF:-1 ,CGTN纪录 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225866/1.m3u8
#EXTINF:-1 ,中国教育1 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226417/1.m3u8
#EXTINF:-1 ,中国教育1 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226538/1.m3u8
#EXTINF:-1 ,中国教育1 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225905/1.m3u8
#EXTINF:-1 ,中国教育2 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226537/1.m3u8
#EXTINF:-1 ,中国教育4 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226362/1.m3u8
#EXTINF:-1 ,中国教育4 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226557/1.m3u8
#EXTINF:-1 ,东南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226517/1.m3u8
#EXTINF:-1 ,东南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225876/1.m3u8
#EXTINF:-1 ,东方卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226519/1.m3u8
#EXTINF:-1 ,东方卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226161/1.m3u8
#EXTINF:-1 ,云南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226424/1.m3u8
#EXTINF:-1 ,云南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225902/1.m3u8
#EXTINF:-1 ,云南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226543/1.m3u8
#EXTINF:-1 ,内蒙古卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226415/1.m3u8
#EXTINF:-1 ,内蒙古卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226530/1.m3u8
#EXTINF:-1 ,内蒙古卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225891/1.m3u8
#EXTINF:-1 ,北京卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226436/1.m3u8
#EXTINF:-1 ,北京卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226160/1.m3u8
#EXTINF:-1 ,厦门卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226542/1.m3u8
#EXTINF:-1 ,吉林卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226426/1.m3u8
#EXTINF:-1 ,吉林卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226533/1.m3u8
#EXTINF:-1 ,吉林卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225886/1.m3u8
#EXTINF:-1 ,四川卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226407/1.m3u8
#EXTINF:-1 ,四川卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225898/1.m3u8
#EXTINF:-1 ,四川卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226523/1.m3u8
#EXTINF:-1 ,天津卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226489/1.m3u8
#EXTINF:-1 ,天津卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225899/1.m3u8
#EXTINF:-1 ,宁夏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226413/1.m3u8
#EXTINF:-1 ,宁夏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226528/1.m3u8
#EXTINF:-1 ,宁夏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225892/1.m3u8
#EXTINF:-1 ,安徽卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225873/1.m3u8
#EXTINF:-1 ,安徽卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226490/1.m3u8
#EXTINF:-1 ,山东卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226487/1.m3u8
#EXTINF:-1 ,山西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226410/1.m3u8
#EXTINF:-1 ,山西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225895/1.m3u8
#EXTINF:-1 ,山西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226531/1.m3u8
#EXTINF:-1 ,广东卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226535/1.m3u8
#EXTINF:-1 ,广西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226408/1.m3u8
#EXTINF:-1 ,广西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225879/1.m3u8
#EXTINF:-1 ,广西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226534/1.m3u8
#EXTINF:-1 ,新疆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226422/1.m3u8
#EXTINF:-1 ,新疆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225901/1.m3u8
#EXTINF:-1 ,新疆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226546/1.m3u8
#EXTINF:-1 ,江苏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226491/1.m3u8
#EXTINF:-1 ,江苏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225887/1.m3u8
#EXTINF:-1 ,江西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226522/1.m3u8
#EXTINF:-1 ,江西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225888/1.m3u8
#EXTINF:-1 ,河北卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226409/1.m3u8
#EXTINF:-1 ,河北卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225881/1.m3u8
#EXTINF:-1 ,河北卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226536/1.m3u8
#EXTINF:-1 ,河南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225882/1.m3u8
#EXTINF:-1 ,河南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226525/1.m3u8
#EXTINF:-1 ,浙江卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226492/1.m3u8
#EXTINF:-1 ,浙江卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225903/1.m3u8
#EXTINF:-1 ,海南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226427/1.m3u8
#EXTINF:-1 ,海南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225890/1.m3u8
#EXTINF:-1 ,湖北卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226520/1.m3u8
#EXTINF:-1 ,湖北卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225884/1.m3u8
#EXTINF:-1 ,湖南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226493/1.m3u8
#EXTINF:-1 ,湖南卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226162/1.m3u8
#EXTINF:-1 ,甘肃卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226414/1.m3u8
#EXTINF:-1 ,甘肃卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225877/1.m3u8
#EXTINF:-1 ,甘肃卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226545/1.m3u8
#EXTINF:-1 ,西藏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226428/1.m3u8
#EXTINF:-1 ,西藏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225900/1.m3u8
#EXTINF:-1 ,西藏卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226527/1.m3u8
#EXTINF:-1 ,贵州卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226405/1.m3u8
#EXTINF:-1 ,贵州卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225880/1.m3u8
#EXTINF:-1 ,贵州卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226521/1.m3u8
#EXTINF:-1 ,辽宁卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226488/1.m3u8
#EXTINF:-1 ,辽宁卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226336/1.m3u8
#EXTINF:-1 ,辽宁卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225889/1.m3u8
#EXTINF:-1 ,重庆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225904/1.m3u8
#EXTINF:-1 ,重庆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226337/1.m3u8
#EXTINF:-1 ,重庆卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226518/1.m3u8
#EXTINF:-1 ,陕西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226411/1.m3u8
#EXTINF:-1 ,陕西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225896/1.m3u8
#EXTINF:-1 ,陕西卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226532/1.m3u8
#EXTINF:-1 ,青海卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226412/1.m3u8
#EXTINF:-1 ,青海卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225893/1.m3u8
#EXTINF:-1 ,青海卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226529/1.m3u8
#EXTINF:-1 ,黑龙江卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226524/1.m3u8
#EXTINF:-1 ,黑龙江卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225883/1.m3u8
#EXTINF:-1 ,山东教育卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226419/1.m3u8
#EXTINF:-1 ,山东教育卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225908/1.m3u8
#EXTINF:-1 ,山东教育卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226526/1.m3u8
#EXTINF:-1 ,广东南方卫视地面 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226540/1.m3u8
#EXTINF:-1 ,新疆兵团卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226541/1.m3u8
#EXTINF:-1 ,海南三沙卫视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226544/1.m3u8
#EXTINF:-1 ,北京卡酷少儿 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225907/1.m3u8
#EXTINF:-1 ,北京卡酷少儿 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226511/1.m3u8
#EXTINF:-1 ,北京国际 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226510/1.m3u8
#EXTINF:-1 ,北京影视 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226433/1.m3u8
#EXTINF:-1 ,北京文艺 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226435/1.m3u8
#EXTINF:-1 ,北京新闻 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226512/1.m3u8
#EXTINF:-1 ,北京生活 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226514/1.m3u8
#EXTINF:-1 ,北京科教 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226434/1.m3u8
#EXTINF:-1 ,北京财经 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226516/1.m3u8
#EXTINF:-1 ,北京青年 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226513/1.m3u8
#EXTINF:-1 ,上海哈哈炫动 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226421/1.m3u8
#EXTINF:-1 ,上海哈哈炫动 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225909/1.m3u8
#EXTINF:-1 ,广东嘉佳卡通 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226539/1.m3u8
#EXTINF:-1 ,江苏优漫卡通 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226420/1.m3u8
#EXTINF:-1 ,江苏优漫卡通 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225910/1.m3u8
#EXTINF:-1 ,湖南金鹰卡通 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225906/1.m3u8
#EXTINF:-1 ,CCTV中视购物 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226385/1.m3u8
#EXTINF:-1 ,北京家有购物 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225912/1.m3u8
#EXTINF:-1 ,北京家有购物 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226343/1.m3u8
#EXTINF:-1 ,聚鲨环球精选 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226311/1.m3u8
#EXTINF:-1 ,聚鲨环球精选 标清
http://221.179.217.9/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226345/1.m3u8

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,816 +0,0 @@
#EXTM3U
#EXTINF:-1 logo="" group-title="" ,CCTV-1
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226226/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-1
http://112.50.243.8/PLTV/88888888/224/3221225922/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-1
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/8380729188125675257/1.m3u8?stbId=005301FF001589101611549359B92C46&channel-id=shvoolive&Contentid=8380729188125675257&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=8380729188125675257&owchid=shvoolive&owsid=9810361579531242552&AuthInfo=2TOfGIahP4HrGWrHbpJXVOhAZZf%2B%2BRvFCOimr7PCGr9K%2B8TGA2jGwhx%2FP%2B9zbDc6lyCFd7nUPkjV5yhX4M591q%2Bjz%2FVPZBSXzMBonFGRPep2MwYhKpmBifYKbDBIkjbE
#EXTINF:-1 logo="" group-title="" ,CCTV-2
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226230/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-2
http://112.50.243.8/PLTV/88888888/224/3221225923/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-2
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/9059700522149664924/1.m3u8?stbId=005301FF00158910000000212621A0DD&channel-id=shvoolive&Contentid=9059700522149664924&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=9059700522149664924&owchid=shvoolive&owsid=9176631579531299298&AuthInfo=2TOfGIahP4HrGWrHbpJXVOJq5SVvpOdgyIf7tzyuJqdYhL2umVWk4VA%2BiWro6vS%2FGYbJQ4PkF2oGSeOSrHR8kErWftutbDOGxkGeSWuC8HvRlxrsJs3srD2VEDgCtlA%2B
#EXTINF:-1 logo="" group-title="" ,CCTV-3
http://117.169.124.36:6610/ysten-businessmobile/live/cctv-3/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-3
http://223.110.241.130:6610/gitv/live1/G_CCTV-3-HQ/.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-3
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/7583927553614607925/1.m3u8?stbId=005301FF001589101611549359B9531C&channel-id=shvoolive&Contentid=7583927553614607925&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=7583927553614607925&owchid=shvoolive&owsid=4975061579531175360&AuthInfo=2TOfGIahP4HrGWrHbpJXVMtGfw%2Bi1RmSk6DRVWhSYHpPQhuPB3gB9HD2kYmj6h2ghYJH%2BZemKqNLOjvtazNyyelvyYAlIu0Li8OHrMDUf9T6xYM6NbVkTDG8Dli2hoZV
#EXTINF:-1 logo="" group-title="" ,CCTV-4
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226314/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-4
http://112.50.243.8/PLTV/88888888/224/3221225802/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-4
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000002000031664/1.m3u8?channel-id=ystenlive&Contentid=1000000002000031664&livemode=1&stbId=00000250001B50800001B401420BC069&userToken=&usergroup=&version=1.0&owaccmark=1000000002000031664&owchid=ystenlive&owsid=4493204828580187354&AuthInfo=zmDeINsczUw%2bXOm6icTIplPJYM0PdJZ7nyJeCqAhmgD4h2W12vkSCe%2bw8qoQi5%2fj1BMuqFcEHMRAJlgQD47XRVqqHN3O4Si9Wv7MjAX%2b8AK0eHLMDmPByGK0oSB43DB7
#EXTINF:-1 logo="" group-title="" ,CCTV-5
http://223.110.241.130:6610/gitv/live1/G_CCTV-5-HQ/G_CCTV-5-HQ/
#EXTINF:-1 logo="" group-title="" ,CCTV-5
http://112.17.40.145/PLTV/88888888/224/3221226687/index.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-5
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/8134369599538150431/1.m3u8?stbId=005301FF001589101611549359B91F12&channel-id=shvoolive&Contentid=8134369599538150431&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=8134369599538150431&owchid=shvoolive&owsid=9856681579531396965&AuthInfo=2TOfGIahP4HrGWrHbpJXVHgbCHVZZF5UUv019%2FSsh88KJM1EuxjKGjHOptOCA%2B9qy7SUSUSlFcfpzdjGKbaNwXQPpC5RWUW%2BWPXxlyqlAmmp3eZqD0kAJRbC1HQjeP48
#EXTINF:-1 logo="" group-title="" ,CCTV-5+
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226225/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-5+
http://117.169.124.46:6410/ysten-businessmobile/live/hdcctv05plus/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-5+
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000020505/1.m3u8?stbId=005301FF001589101611549359B92F26&channel-id=ystenlive&Contentid=1000000001000020505&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000001000020505&owchid=ystenlive&owsid=3007521579531929012&AuthInfo=2TOfGIahP4HrGWrHbpJXVPo6e%2BHF%2BrVo6xQQtyKDSuqu3lLj0NrV6tPDBIsVEpn3e3h8FJNoRfXgk2fJ%2B8A%2BC9FKxw7DogGmhnFazyXoBZJZPx01aV9Q%2Bs%2B%2FVnd4tZOQ
#EXTINF:-1 logo="" group-title="" ,CCTV-6
http://223.110.243.139/PLTV/3/224/3221225548/index.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-6
http://117.169.124.36:6610/ysten-businessmobile/live/cctv-6/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-6
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6705015643145867202/1.m3u8?stbId=005301FF00158910000000212621A501&channel-id=shvoolive&Contentid=6705015643145867202&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=6705015643145867202&owchid=shvoolive&owsid=7641431579531463387&AuthInfo=2TOfGIahP4HrGWrHbpJXVGtyhHJPIcRRegoBYBxkr5gU2nvM3aYRu9pk6g1cfGsxitbm7ri6Y%2BkjLjny72IEdjBnss%2Faslq1wPHTyGHeHFYaAuxUDnXfdynLgAo%2FAhgd
#EXTINF:-1 logo="" group-title="" ,CCTV-7
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226234/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-7
http://112.50.243.8/PLTV/88888888/224/3221225927/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-7
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/9021776916726275968/1.m3u8?stbId=005303FF00010060000100E400EDD522&channel-id=shvoolive&Contentid=9021776916726275968&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=9021776916726275968&owchid=shvoolive&owsid=1117721579531499433&AuthInfo=dIshjDc3shv8ei%2BWF5V%2F4V6lf0HKCsUdpGR8CeY5ZvwycVHGQkBt0T4Mgr0s8ldsXtd9fDrW5osGZSl1tYFcN4xKXGPanSFGs4GR6kXBOyjKyNYEmAQ7njzvrMpDpEoy
#EXTINF:-1 logo="" group-title="" ,CCTV-8
http://117.169.124.36:6610/ysten-businessmobile/live/cctv-8/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-8
http://223.110.247.161:6610/cntv/live1/HD-2500k-1080P-cctv8/HD-2500k-1080P-cctv8
#EXTINF:-1 logo="" group-title="" ,CCTV-8
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6718199708332952607/1.m3u8?stbId=005303FF00010060000100E400EDD522&channel-id=shvoolive&Contentid=6718199708332952607&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=6718199708332952607&owchid=shvoolive&owsid=5415971579531545952&AuthInfo=dIshjDc3shv8ei%2BWF5V%2F4V6lf0HKCsUdpGR8CeY5ZvwhPD49%2ByoYvwp35mAdL%2Fiv3IhMa6%2BWOwlWxbCOH9ParUjWZpISKyxZZPoQtekRP1dMl%2BCp9T%2BIEdj1ckDKKfLV
#EXTINF:-1 logo="" group-title="" ,CCTV-9
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226236/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-9
http://112.50.243.8/PLTV/88888888/224/3221225820/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-9
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000014583/1.m3u8?stbId=005303FF00010060000100E400EDD522&channel-id=ystenlive&Contentid=1000000001000014583&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000001000014583&owchid=ystenlive&owsid=7167961579531601678&AuthInfo=dIshjDc3shv8ei%2BWF5V%2F4V6lf0HKCsUdpGR8CeY5Zvyu3lLj0NrV6tPDBIsVEpn34sImpRHeOmdxmKUDLs1%2BcZ4JMWbvuFdY7IsuWCFdW392C%2BvFQjyH4LwQq4yRWFvT
#EXTINF:-1 logo="" group-title="" ,CCTV-10
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226227/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-10
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225814/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-10
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5505774374187257095/1.m3u8?stbId=005301FF001589101611549359B928C9&channel-id=shvoolive&Contentid=5505774374187257095&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=5505774374187257095&owchid=shvoolive&owsid=1848841579531638041&AuthInfo=2TOfGIahP4HrGWrHbpJXVO9dhnpYCD6yZADsu%2BE3e1z0TmJ04Et2oauQoqLXutIbfy6yerDX1KNDnX4OGB2ZvZf3QlZMt7Oj%2B5HhHlpl0nNoTgXky6K2iYWb1eX3xCek
#EXTINF:-1 logo="" group-title="" ,CCTV-11
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226315/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-11
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225815/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-11
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000002000019789/1.m3u8?stbId=005301FF001589101611549359B96031&channel-id=ystenlive&Contentid=1000000002000019789&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000002000019789&owchid=ystenlive&owsid=5070431579531812673&AuthInfo=2TOfGIahP4HrGWrHbpJXVDOD3a2KOxiKxQ3OD0iK1ACjKNizoRlMOkuvsTe1URoeoCCSRcfgLDg%2FiG7BT3%2BNlEIMer5%2BuzAqyByddFhoQVMoMRKerLoSM5qM9Az%2Bea7u
#EXTINF:-1 logo="" group-title="" ,CCTV-12
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226228/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-12
http://112.50.243.8/PLTV/88888888/224/3221225816/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-12
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6417486185316863297/1.m3u8?stbId=005301FF001589101611549359B92F26&channel-id=shvoolive&Contentid=6417486185316863297&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=6417486185316863297&owchid=shvoolive&owsid=9153671579531878340&AuthInfo=2TOfGIahP4HrGWrHbpJXVPo6e%2BHF%2BrVo6xQQtyKDSurAX3PB%2FnVIr3xix20cl8xPdgGi1rpRM1DYWZnyEDgQSmvEeryqwyIWUPNfICRzKqmuU3YFsCIaBI4jHMacn12g
#EXTINF:-1 logo="" group-title="" ,CCTV-13
http://223.110.241.130:6610/gitv/live1/G_CCTV-13-HQ/.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-13
http://223.110.247.161:6610/gitv/live1/G_CCTV-13-HQ/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-14
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226229/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-14
http://117.148.187.37/PLTV/88888888/224/3221226126/index.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-14
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5554452538079056392/1.m3u8?stbId=005301FF001589101611549359B92F26&channel-id=shvoolive&Contentid=5554452538079056392&mos=jbjhhzstsl&livemode=1&proto=7&version=1.0&owaccmark=5554452538079056392&owchid=shvoolive&owsid=1386521579531934459&AuthInfo=2TOfGIahP4HrGWrHbpJXVPo6e%2BHF%2BrVo6xQQtyKDSuraKH2KM768ZNQcj3PAdtOdSSlj5RtbM3onnzvUC8Txgj%2BRYROAJoRcjfZ4YOPHclFuVVM2CqA1FqqLFpU5t7y%2B
#EXTINF:-1 logo="" group-title="" ,CCTV-15
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226333/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-15
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225818/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-15
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000002000008163/1.m3u8?stbId=005301FF00158910000000212621B0EF&channel-id=ystenlive&Contentid=1000000002000008163&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000002000008163&owchid=ystenlive&owsid=8159411579531758075&AuthInfo=2TOfGIahP4HrGWrHbpJXVCfBjPWQNL5VnKaoeN%2FnWIWjKNizoRlMOkuvsTe1URoev67GfI1oIH4w2vVjbaVRzv3Enx1RBixVDhCnZtdnlMixFs9te0%2Bpvr2OpfN5d0VT
#EXTINF:-1 logo="" group-title="" ,CCTV-17
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226318/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-17
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221226990/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-17
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000005000056836/1.m3u8?stbId=005301FF001589101611549359B9325E&channel-id=ystenlive&Contentid=1000000005000056836&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000005000056836&owchid=ystenlive&owsid=9164551579532003738&AuthInfo=2TOfGIahP4HrGWrHbpJXVGO0L8hMYc%2BQSE26r5BPa9COQyZOTKfJypXfULnzEX8ov4wHfTVtjr5%2BH1gBPIHFdZVbPTqDjqKmcARryOXhfL7mPOk1Na7QiYpdWHg0hz19
#EXTINF:-1 logo="" group-title="" ,CCTV-4K
http://112.17.40.12/PLTV/88888888/224/3221226758/1.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-4K
http://112.17.40.140/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-4K
http://39.134.176.148/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1 logo="" group-title="" ,CCTV-4K
http://117.148.187.83/PLTV/88888888/224/3221226758/index.m3u8
#EXTINF:-1 logo="" group-title="" ,纯享4K源码1
http://112.50.243.8/PLTV/88888888/224/3221226825/1.m3u8
#EXTINF:-1 logo="" group-title="" ,纯享4K源码2
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn/000000001000/1000000004000011651/index.m3u8?channel-id=ystenlive&Contentid=1000000004000011651&livemode=1&authCode=3a&stbId=8A3603DD004735200000049573C4E39B&version=1.0&owaccmark=1000000004000011651&owchid=ystenlive&owsid=6721581571186720581&AuthInfo=QejU%2ByFkapDLEHjn7Vi7Bsh98cz5RjIeOqbMi0Qqlame2O8Id%2BgCUUdS4cJUD1ieqKIx8wFJ0pPdF5P8MGRzRrjFLuuRCIZ2D2ha%2Fr9iiM%2BAnSOfyc4s5zWrjzUdrEbf
#EXTINF:-1 logo="" group-title="" ,百事4K频道
http://112.17.40.145/PLTV/88888888/224/3221226718/index.m3u8
#EXTINF:-1 logo="" group-title="" ,凤凰资讯
http://112.17.40.140/PLTV/88888888/224/3221226491/index.m3u8
#EXTINF:-1 logo="" group-title="" ,凤凰资讯
http://117.169.124.37:6610/ysten-businessmobile/live/fhzixun/1.m3u8
#EXTINF:-1 logo="" group-title="" ,凤凰中文
http://117.169.124.37:6610/ysten-businessmobile/live/fhchinese/1.m3u8
#EXTINF:-1 logo="" group-title="" ,凤凰中文
http://117.169.120.138:8080/live/fhchinese/index.m3u8
#EXTINF:-1 logo="" group-title="" ,北京卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226224/1.m3u8
#EXTINF:-1 logo="" group-title="" ,北京卫视
http://111.40.205.87/PLTV/88888888/224/3221225728/index.m3u8
#EXTINF:-1 logo="" group-title="" ,天津卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226246/1.m3u8
#EXTINF:-1 logo="" group-title="" ,天津卫视
http://112.17.40.140/PLTV/88888888/224/3221226412/index.m3u8
#EXTINF:-1 logo="" group-title="" ,河北卫视超清1
http://223.110.245.149/ott.js.chinamobile.com/PLTV/3/224/3221225840/index.m3u8
#EXTINF:-1 logo="" group-title="" ,河北卫视超清2
http://223.110.247.161:6610/gitv/live1/G_HEBEI/G_HEBEI
#EXTINF:-1 logo="" group-title="" ,东方卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226237/1.m3u8
#EXTINF:-1 logo="" group-title="" ,东方卫视
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000005866/1.m3u8?stbId=005301FF001589101611549359B9656A&channel-id=ystenlive&Contentid=1000000001000005866&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000001000005866&owchid=ystenlive&owsid=6312751579529792174&AuthInfo=2TOfGIahP4HrGWrHbpJXVB51rvh1oS437liFJd26gOOu3lLj0NrV6tPDBIsVEpn3OZnoLrZwa8b70lofXkPptSAmb4xhM2tKBJ0VUyBQsWCEzNrIVXcTeS%2F12UFJevdi
#EXTINF:-1 logo="" group-title="" ,湖南卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226241/1.m3u8
#EXTINF:-1 logo="" group-title="" ,湖南卫视
http://112.17.40.140/PLTV/88888888/224/3221226553/index.m3u8
#EXTINF:-1 logo="" group-title="" ,浙江卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226247/1.m3u8
#EXTINF:-1 logo="" group-title="" ,浙江卫视
http://223.110.243.173/PLTV/3/224/3221227215/index.m3u8
#EXTINF:-1 logo="" group-title="" ,江苏卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226242/1.m3u8
#EXTINF:-1 logo="" group-title="" ,江苏卫视
http://112.17.40.140/PLTV/88888888/224/3221226414/index.m3u8
#EXTINF:-1 logo="" group-title="" ,东南卫视
http://117.169.124.37:6610/ysten-businessmobile/live/dongnanstv/yst.m3u8
#EXTINF:-1 logo="" group-title="" ,东南卫视
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000002000009263/1.m3u8?channel-id=ystenlive&Contentid=1000000002000009263&livemode=1&stbId=005203FF000360100001001A34C0CD33&userToken=bd8bb70bdb2b54bd84b587dffa024f7621vv&usergroup=g21077200000&version=1.0&owaccmark=1000000002000009263&owchid=ystenlive&owsid=1106497909461310172&AuthInfo=yOLXJswzZFfV3FvB8MhHuElKGJKLbU5H0jB3qAhfSE5oj7lZFbEKIj3xJcvQPkjhM1XYZKCRYYY%2ff447%2bzETLijqfFgMTSA9x9T2lf3pyhagZIF%2fdE1lc49i65lODYA%2f
#EXTINF:-1 logo="" group-title="" ,山东卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226308/1.m3u8
#EXTINF:-1 logo="" group-title="" ,山东卫视
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000012807/1.m3u8?channel-id=ystenlive&Contentid=1000000001000012807&livemode=1&stbId=005203FF000360100001001A34C0CD33&userToken=bd8bb70bdb2b54bd84b587dffa024f7621vv&usergroup=g21077200000&version=1.0&owaccmark=1000000001000012807&owchid=ystenlive&owsid=1106497909461291586&AuthInfo=yOLXJswzZFfV3FvB8MhHuElKGJKLbU5H0jB3qAhfSE7AORAoVDZDWbFnJ0sXJEaR3cBsIsjm7UHdGO3a4NjD1C4TiYtYt%2by66pvMI%2bkz57DAkgjzetftIzpJRR8RWa0K
#EXTINF:-1 logo="" group-title="" ,湖北卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226310/1.m3u8
#EXTINF:-1 logo="" group-title="" ,湖北卫视
http://223.110.243.171/PLTV/3/224/3221227211/index.m3u8
#EXTINF:-1 logo="" group-title="" ,安徽卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226223/1.m3u8
#EXTINF:-1 logo="" group-title="" ,安徽卫视
http://223.110.247.161:6610/gitv/live1/G_ANHUI-CQ/G_ANHUI-CQ
#EXTINF:-1 logo="" group-title="" ,广东卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226238/1.m3u8
#EXTINF:-1 logo="" group-title="" ,广东卫视
http://112.17.40.140/PLTV/88888888/224/3221226225/index.m3u8
#EXTINF:-1 logo="" group-title="" ,深圳卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226245/1.m3u8
#EXTINF:-1 logo="" group-title="" ,深圳卫视
http://223.110.243.171/PLTV/3/224/3221227217/index.m3u8
#EXTINF:-1 logo="" group-title="" ,辽宁卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225947/1.m3u8
#EXTINF:-1 logo="" group-title="" ,辽宁卫视
http://223.110.245.145/ott.js.chinamobile.com/PLTV/3/224/3221227410/index.m3u8
#EXTINF:-1 logo="" group-title="" ,龙江卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226239/1.m3u8
#EXTINF:-1 logo="" group-title="" ,龙江卫视
http://112.17.40.140/PLTV/88888888/224/3221226555/index.m3u8
#EXTINF:-1 logo="" group-title="" ,吉林卫视
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=25&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,吉林卫视
http://223.110.247.161:6610/gitv/live1/G_JILIN/G_JILIN
#EXTINF:-1 logo="" group-title="" ,江西卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226243/1.m3u8
#EXTINF:-1 logo="" group-title="" ,江西卫视
http://112.17.40.140/PLTV/88888888/224/3221226557/index.m3u8
#EXTINF:-1 logo="" group-title="" ,四川卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221227006/1.m3u8
#EXTINF:-1 logo="" group-title="" ,四川卫视
http://223.110.247.161:6610/gitv/live1/SCWS/SCWS
#EXTINF:-1 logo="" group-title="" ,重庆卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221225949/1.m3u8
#EXTINF:-1 logo="" group-title="" ,重庆卫视
http://ivi.bupt.edu.cn/hls/cqhd.m3u8
#EXTINF:-1 logo="" group-title="" ,厦门卫视
http://ott.fj.chinamobile.com/PLTV/88888888/224/3221226781/1.m3u8
#EXTINF:-1 logo="" group-title="" ,厦门卫视
http://223.110.247.161:6610/gitv/live1/G_XIAMEN/G_XIAMEN
#EXTINF:-1 logo="" group-title="" ,河南卫视
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=19&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,河南卫视超清2
http://223.110.245.157/ott.js.chinamobile.com/PLTV/3/224/3221225815/index.m3u8
#EXTINF:-1 logo="" group-title="" ,贵州卫视
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=41&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,贵州卫视超清2
http://223.110.245.149/ott.js.chinamobile.com/PLTV/3/224/3221225787/index.m3u8
#EXTINF:-1 logo="" group-title="" ,海南卫视超清1
http://hnhbxww.com/live.php?http://mlive1.91kds.cn/b9/hitv.m3u8?id=lywshd
#EXTINF:-1 logo="" group-title="" ,海南卫视
http://112.50.243.8/PLTV/88888888/224/3221225855/1.m3u8
#EXTINF:-1 logo="" group-title="" ,甘肃卫视超清1
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=142&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,甘肃卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225877/1.m3u8
#EXTINF:-1 logo="" group-title="" ,青海卫视超清1
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=206&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,青海卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225893/1.m3u8
#EXTINF:-1 logo="" group-title="" ,云南卫视超清1
http://223.110.245.159/ott.js.chinamobile.com/PLTV/3/224/3221225838/index.m3u8
#EXTINF:-1 logo="" group-title="" ,云南卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225902/1.m3u8
#EXTINF:-1 logo="" group-title="" ,陕西卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225896/1.m3u8
#EXTINF:-1 logo="" group-title="" ,陕西卫视
http://223.110.247.161:6610/gitv/live1/G_SHANXI/G_SHANXI
#EXTINF:-1 logo="" group-title="" ,宁夏卫视超清1
http://223.110.245.151/ott.js.chinamobile.com/PLTV/3/224/3221225842/index.m3u8
#EXTINF:-1 logo="" group-title="" ,宁夏卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225892/1.m3u8
#EXTINF:-1 logo="" group-title="" ,内蒙卫视超清1
http://223.110.245.161/ott.js.chinamobile.com/PLTV/3/224/3221225836/index.m3u8
#EXTINF:-1 logo="" group-title="" ,内蒙卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225891/1.m3u8
#EXTINF:-1 logo="" group-title="" ,西藏卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225900/1.m3u8
#EXTINF:-1 logo="" group-title="" ,西藏卫视
http://223.110.247.161:6610/gitv/live1/G_XIZANG/G_XIZANG
#EXTINF:-1 logo="" group-title="" ,山西卫视
http://223.110.247.161:6610/gitv/live1/SXWS/SXWS
#EXTINF:-1 logo="" group-title="" ,山西卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225895/1.m3u8
#EXTINF:-1 logo="" group-title="" ,广西卫视
http://112.50.243.8/PLTV/88888888/224/3221225836/1.m3u8
#EXTINF:-1 logo="" group-title="" ,广西卫视
http://223.110.247.161:6610/gitv/live1/GXWS/GXWS
#EXTINF:-1 logo="" group-title="" ,新疆卫视
http://223.110.247.161:6610/gitv/live1/G_XINJIANG/G_XINJIANG
#EXTINF:-1 logo="" group-title="" ,新疆卫视
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225901/1.m3u8
#EXTINF:-1 logo="" group-title="" ,南方卫视高清
http://223.110.247.161:6610/gitv/live1/G_NANFANG/G_NANFANG
#EXTINF:-1 logo="" group-title="" ,兵团卫视高清
http://223.110.247.161:6610/gitv/live1/G_BINGTUAN/G_BINGTUAN
#EXTINF:-1 logo="" group-title="" ,延边卫视高清
http://223.110.247.161:6610/gitv/live1/G_YANBIAN/G_YANBIAN
#EXTINF:-1 logo="" group-title="" ,农林卫视高清
http://223.110.247.161:6610/gitv/live1/G_NONGLIN/G_NONGLIN
#EXTINF:-1 logo="" group-title="" ,康巴卫视高清
http://223.110.247.161:6610/gitv/live1/G_KANGBA/G_KANGBA
#EXTINF:-1 logo="" group-title="" ,安多卫视高清
http://223.110.247.161:6610/gitv/live1/G_ANDUO/G_ANDUO
#EXTINF:-1 logo="" group-title="" ,高清影视1台
http://112.50.243.8/PLTV/88888888/224/3221226736/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视2台
http://112.50.243.8/PLTV/88888888/224/3221225881/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视3台
http://112.50.243.8/PLTV/88888888/224/3221226708/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视4台
http://112.50.243.8/PLTV/88888888/224/3221226712/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视5台
http://112.50.243.8/PLTV/88888888/224/3221225893/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视6台
http://112.50.243.8/PLTV/88888888/224/3221226692/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视7台
http://112.50.243.8/PLTV/88888888/224/3221226754/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视8台
http://112.17.40.145/PLTV/88888888/224/3221226608/index.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视9台
http://112.17.40.145/PLTV/88888888/224/3221226606/index.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视10台
http://112.17.40.145/PLTV/88888888/224/3221226360/index.m3u8
#EXTINF:-1 logo="" group-title="" ,高清动画11台
http://112.50.243.8/PLTV/88888888/224/3221226732/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清动画12台
http://112.50.243.8/PLTV/88888888/224/3221226741/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清动漫13台
http://112.50.243.8/PLTV/88888888/224/3221226743/1.m3u8
#EXTINF:-1 logo="" group-title="" ,高清影视14台
http://ivi.bupt.edu.cn/hls/chchd.m3u8
#EXTINF:-1 logo="" group-title="" ,东方影视高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5000000010000032212/index.m3u8?channel-id=bestzb&Contentid=5000000010000032212&livemode=1&authCode=3a&stbId=005301FF00158910000000212621B1F2&version=1.0&owaccmark=5000000010000032212&owchid=bestzb&owsid=2093431579530013084&AuthInfo=2TOfGIahP4HrGWrHbpJXVC70y2PVjmhUubUspsIcpqbPt3njBIzWc%2Fam35vTsnvWPWGkzpZH3A16MnnNHKq3GxKdDnIii87ggbdt%2FwooaevY4cuAtO0vMGGwXuHO%2Biok
#EXTINF:-1 logo="" group-title="" ,纪实人文高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000010606/1.m3u8?stbId=005301FF001589101611549359B92C46&channel-id=ystenlive&Contentid=1000000001000010606&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000001000010606&owchid=ystenlive&owsid=5474771579530255373&AuthInfo=2TOfGIahP4HrGWrHbpJXVOhAZZf%2B%2BRvFCOimr7PCGr%2Bu3lLj0NrV6tPDBIsVEpn3QZdNn969VxaznG4qedKIxPvWqo6nkyvxK0SnJLSEP%2FF4Wxm5gCchMH9VO%2BhWyofF
#EXTINF:-1 logo="" group-title="" ,上海外语高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5000000010000030951/index.m3u8?channel-id=bestzb&Contentid=5000000010000030951&livemode=1&authCode=3a&stbId=005303FF0002189018212C1875540E0E&version=1.0&owaccmark=5000000010000030951&owchid=bestzb&owsid=5275181579530295306&AuthInfo=%2FcylGCbqLdFJuk2wbal8%2B%2FwyUq8npJ58oVaJUzBhF9PPt3njBIzWc%2Fam35vTsnvW6JhDYuiodydLTeMKHTm0L2zYfQnHdO1Iw0VU34c0CqRBZ788c%2Fr%2FVjoxJ5D0QVcG
#EXTINF:-1 logo="" group-title="" ,第一财经高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5000000010000027146/index.m3u8?channel-id=bestzb&Contentid=5000000010000027146&livemode=1&authCode=3a&stbId=005301FF00158910000000212621B272&version=1.0&owaccmark=5000000010000027146&owchid=bestzb&owsid=2047321579530436324&AuthInfo=2TOfGIahP4HrGWrHbpJXVGQxu5HMK%2BIheH%2BppAJUFQfPt3njBIzWc%2Fam35vTsnvW%2Bh72VHwN1p1HFLVpAXsbYI0I2J%2FhJvUENkmrKWvJBWHflOM1WROOndOSHiRR8ilK
#EXTINF:-1 logo="" group-title="" ,冬奥纪实高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/1000000001000001910/1.m3u8?stbId=005301FF001589101611549359B93B82&channel-id=ystenlive&Contentid=1000000001000001910&mos=jbjhhzstsl&livemode=1&version=1.0&owaccmark=1000000001000001910&owchid=ystenlive&owsid=6204131579532167784&AuthInfo=2TOfGIahP4HrGWrHbpJXVB3TJIR2vriLvDYSdNB63hOu3lLj0NrV6tPDBIsVEpn3tQTMvk8FXaCJplQYdE%2FaRS95e%2BAlAk4PMAmwzVuVNoUAyrBQjkJ2X3eTsBSYe8ta
#EXTINF:-1 logo="" group-title="" ,北京纪实高清
http://112.50.243.8/PLTV/88888888/224/3221225944/1.m3u8
#EXTINF:-1 logo="" group-title="" ,五星体育高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5000000010000017540/index.m3u8?channel-id=bestzb&Contentid=5000000010000017540&livemode=1&stbId=004003FF0017301364008422F151297C&userToken=22da83031e59d012e61af366ad30871e02vv&usergroup=g02020000000&version=1.0&owaccmark=5000000010000017540&owchid=bestzb&owsid=4493204831455228383&AuthInfo=N%2biD7%2bHgi9LcszGFRGa51uAqiHNpkS5d0%2fEIXqMyy8J6GNpZ%2bE47AWi696WsOzmj7u8gynrDaeemmd3KgHvW7jm8s%2fkPykV1GmMdpMkc7doBK82U9CVAXx34x1%2fYjl4A
#EXTINF:-1 logo="" group-title="" ,生活时尚高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/8538616372715313491/index.m3u8?channel-id=bestzb&Contentid=8538616372715313491&livemode=1&authCode=3a&stbId=005301FF001589101611549359B95001&version=1.0&owaccmark=8538616372715313491&owchid=bestzb&owsid=9384351579529030195&AuthInfo=2TOfGIahP4HrGWrHbpJXVMf9GKsKSOxo3z9oMCSFNzfvIfeh1IeRuYy1UKStuEqgLEq69vAaIVm8yJ1Bv9Ubfc12nlc%2FSga%2FjQ8%2F3mwUrQxWfqFwePA0JQWqj9IZCH10
#EXTINF:-1 logo="" group-title="" ,五星体育高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/4612233678249154892/index.m3u8?channel-id=bestzb&Contentid=4612233678249154892&livemode=1&authCode=3a&stbId=005301FF001589101611549359B95001&version=1.0&owaccmark=4612233678249154892&owchid=bestzb&owsid=1779721579529023740&AuthInfo=2TOfGIahP4HrGWrHbpJXVMf9GKsKSOxo3z9oMCSFNzd9hkuYOs2VB84It64D80NJi4eXOKW3GuNNz9Fm%2FKg8xywLT7mM729fPyVIkI9Esx1ZNxN%2F6BsKFZl0vwsL8fqK
#EXTINF:-1 logo="" group-title="" ,上海都市高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6789517052815334336/index.m3u8?channel-id=bestzb&Contentid=6789517052815334336&livemode=1&authCode=3a&stbId=005301FF001589101611549359B94488&version=1.0&owaccmark=6789517052815334336&owchid=bestzb&owsid=3529791579529328057&AuthInfo=2TOfGIahP4HrGWrHbpJXVG%2BEERpEQIU%2FdtpJfuYgRAZD6434P427oxBuLbFRCJn4JFqerLYeYbaWyhUzdTsyRsJkPPbC14Prjj67uIG3APHUBp7pkUo1m6jlajTP1QwT
#EXTINF:-1 logo="" group-title="" ,风尚音乐高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5529729098703832176/z.m3u8?authCode=07110409322147352675&stbId=005301FF001589101611549359B92801&Contentid=5529729098703832176&mos=jbjhhzstsl&livemode=1&channel-id=wasusyt&version=1.0&owaccmark=5529729098703832176&owchid=wasusyt&owsid=3246571579530794909&AuthInfo=2TOfGIahP4HrGWrHbpJXVM8tIjUabzvkQw3IFgi64wePjBmkxCliyfsNixolB3vk0fJDbsUHwM4ZMkLD2%2FuFtJVT%2FBKMSil0ujuXkiQNzBbZ5U6pNSIVxD4YjUWtTd0X
#EXTINF:-1 logo="" group-title="" ,精品剧场高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/8230197131234717902/z.m3u8?authCode=07110409322147352675&stbId=005303FF000218901813C88F26C4CD9A&Contentid=8230197131234717902&mos=jbjhhzstsl&livemode=1&channel-id=wasusyt&version=1.0&owaccmark=8230197131234717902&owchid=wasusyt&owsid=7188071579532237669&AuthInfo=%2FcylGCbqLdFJuk2wbal8%2B0%2FXYYDGLpWdBEstTIR1PqI%2FOctjqHm7uarF9hdI%2FegylabK%2B2Kjwr6YmfYB%2B0U4%2FVMlD9%2BUH6H5BTAiFyR%2BGJWsoX2Ruwovu0ZMFHxX6702
#EXTINF:-1 logo="" group-title="" ,亚洲影院高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5841816227539527643/z.m3u8?authCode=07110409322147352675&stbId=005301FF001589101611549359B93B82&Contentid=5841816227539527643&mos=jbjhhzstsl&livemode=1&channel-id=wasusyt&version=1.0&owaccmark=5841816227539527643&owchid=wasusyt&owsid=1431411579532174401&AuthInfo=2TOfGIahP4HrGWrHbpJXVB3TJIR2vriLvDYSdNB63hPyA9qk2%2BTKLoJATlqPnb0MXm7l%2FiHeo2whk7VLomWH7w5GNiHxzOX6JECr7x0TLTmTY895HMYgWz4jiaElB1nN
#EXTINF:-1 logo="" group-title="" ,上海都市高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6789517052815334336/index.m3u8?channel-id=bestzb&Contentid=6789517052815334336&livemode=1&stbId=004003FF0041848666008422F155939C&userToken=22da83031e59d012e61af366ad30871e02vv&usergroup=g02020000000&version=1.0&owaccmark=6789517052815334336&owchid=bestzb&owsid=4493204831455331826&AuthInfo=zI7Ouajzmvoo0pGb64%2fbgLE2RFvrprmD90MrWZVi%2bL3HPQnDcXoFLI6SzbzVwjU3sNLudmh14A4CtBNHjWANkrrgGz1D3dYfcKudsIt%2bpr%2fjXiUqpuQHmAckVE8okPuA
#EXTINF:-1 logo="" group-title="" ,上海ICS高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/6032059665143203976/index.m3u8?channel-id=bestzb&Contentid=6032059665143203976&livemode=1&authCode=3a&stbId=8A3603DD004735200000049573C4E39B&version=1.0&owaccmark=6032059665143203976&owchid=bestzb&owsid=8862091567733940095&AuthInfo=QejU%2ByFkapDLEHjn7Vi7Bsh98cz5RjIeOqbMi0QqlalAzdP65EW1KAjwws9eqr8onRppCkq5lhXK46o%2BFK3dV%2BCK3fxe9S11%2B88%2FynrqkhlXX%2BzVbd%2F5J%2FreUEsqODX5
#EXTINF:-1 logo="" group-title="" ,生活时尚高清
http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/8538616372715313491/index.m3u8?channel-id=bestzb&Contentid=8538616372715313491&livemode=1&authCode=3a&stbId=8A3603DD004735200000049573C4E39B&version=1.0&owaccmark=8538616372715313491&owchid=bestzb&owsid=5457861567734659356&AuthInfo=QejU%2ByFkapDLEHjn7Vi7Bsh98cz5RjIeOqbMi0QqlakS%2FOYtRGR5wcGJDIS9OeTlipH2OO8alDz%2F1TUrW3QAaMFdRScr5Z2333r7naICD73KmBnoU9%2B3A5Ot%2BJeysO4p
#EXTINF:-1 logo="" group-title="" ,峨眉电影高清
http://scgctvshow.sctv.com/hdlive/emei/1.m3u8
#EXTINF:-1 logo="" group-title="" ,欢笑剧场高清
http://112.50.243.8/PLTV/88888888/224/3221226729/1.m3u8
#EXTINF:-1 logo="" group-title="" ,纪实频道高清
http://112.50.243.8/PLTV/88888888/224/3221225946/1.m3u8
#EXTINF:-1 logo="" group-title="" ,极速汽车高清
http://112.50.243.8/PLTV/88888888/224/3221226140/1.m3u8
#EXTINF:-1 logo="" group-title="" ,动漫秀场高清
http://112.50.243.8/PLTV/88888888/224/3221226141/1.m3u8
#EXTINF:-1 logo="" group-title="" ,黑莓动画高清
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225914/1.m3u8
#EXTINF:-1 logo="" group-title="" ,黑莓电竞高清
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225931/1.m3u8
#EXTINF:-1 logo="" group-title="" ,黑莓电影高清
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225927/1.m3u8
#EXTINF:-1 logo="" group-title="" ,求索纪录
http://112.17.40.145/PLTV/88888888/224/3221226610/index.m3u8
#EXTINF:-1 logo="" group-title="" ,求索科学
http://125.210.152.18:9090/live/QSKX_1200.m3u8
#EXTINF:-1 logo="" group-title="" ,求索动物
http://125.210.152.18:9090/live/QSDW_1200.m3u8
#EXTINF:-1 logo="" group-title="" ,求索生活
http://125.210.152.18:9090/live/QSSH_1200.m3u8
#EXTINF:-1 logo="" group-title="" ,日本天気预报
http://movie.mcas.jp/mcas/wn1_2/master.m3u8
#EXTINF:-1 logo="" group-title="" ,中国教育1台
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225905/1.m3u8
#EXTINF:-1 logo="" group-title="" ,中国教育2台
http://cctvalih5ca.v.myalicdn.com/cstv/cetv2_2/index.m3u8
#EXTINF:-1 logo="" group-title="" ,中国教育3台
http://cctvalih5ca.v.myalicdn.com/cstv/cetv3_2/index.m3u8
#EXTINF:-1 logo="" group-title="" ,中国教育4台
http://cctvalih5ca.v.myalicdn.com/cstv/cetv4_2/index.m3u8
#EXTINF:-1 logo="" group-title="" ,山东教育
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225908/1.m3u8
#EXTINF:-1 logo="" group-title="" ,奥林匹克高清
http://ott-live.olympicchannel.com/out/u/OC1_2.m3u8?fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,奥铃匹克高清
http://ott-live.olympicchannel.com/out/u/OC1_1.m3u8?fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,超级电影
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226233/1.m3u8
#EXTINF:-1 logo="" group-title="" ,超级综艺
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226231/1.m3u8
#EXTINF:-1 logo="" group-title="" ,超级体育
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226232/1.m3u8
#EXTINF:-1 logo="" group-title="" ,超级剧集
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225864/1.m3u8
#EXTINF:-1 logo="" group-title="" ,中国功夫
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226298/1.m3u8
#EXTINF:-1 logo="" group-title="" ,金牌综艺
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226296/1.m3u8
#EXTINF:-1 logo="" group-title="" ,农业致富
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226304/1.m3u8
#EXTINF:-1 logo="" group-title="" ,潮妈辣婆
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226286/1.m3u8
#EXTINF:-1 logo="" group-title="" ,炫舞未来
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226248/1.m3u8
#EXTINF:-1 logo="" group-title="" ,明星大片
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226295/1.m3u8
#EXTINF:-1 logo="" group-title="" ,自由搏击
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226297/1.m3u8
#EXTINF:-1 logo="" group-title="" ,海外综合
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226302/1.m3u8
#EXTINF:-1 logo="" group-title="" ,惊梀悬疑
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226294/1.m3u8
#EXTINF:-1 logo="" group-title="" ,爱情喜剧
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226299/1.m3u8
#EXTINF:-1 logo="" group-title="" ,精品记录
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226293/1.m3u8
#EXTINF:-1 logo="" group-title="" ,精品体育
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226328/1.m3u8
#EXTINF:-1 logo="" group-title="" ,精品大剧
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226331/1.m3u8
#EXTINF:-1 logo="" group-title="" ,古装剧场
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226323/1.m3u8
#EXTINF:-1 logo="" group-title="" ,军旅剧场
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226324/1.m3u8
#EXTINF:-1 logo="" group-title="" ,军事评论
http://111.13.111.167/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226326/1.m3u8
#EXTINF:-1 logo="" group-title="" ,健康有约
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225919/1.m3u8
#EXTINF:-1 logo="" group-title="" ,家庭剧场
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225918/1.m3u8
#EXTINF:-1 logo="" group-title="" ,动作电影
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221226288/1.m3u8
#EXTINF:-1 logo="" group-title="" ,爱电竞
http://101.71.255.229:6610/zjhs/2/10110/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱动漫
http://101.71.255.229:6610/zjhs/2/10107/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱都市
http://101.71.255.229:6610/zjhs/2/10111/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱江湖
http://101.71.255.229:6610/zjhs/2/10114/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱解密
http://101.71.255.229:6610/zjhs/2/10109/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱经典
http://101.71.255.229:6610/zjhs/2/10106/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱军武
http://101.71.255.229:6610/zjhs/2/10119/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱科幻
http://101.71.255.229:6610/zjhs/2/10113/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱历史
http://101.71.255.229:6610/zjhs/2/10120/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱美食
http://101.71.255.229:6610/zjhs/2/10108/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱奇谈
http://101.71.255.229:6610/zjhs/2/10103/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱时尚
http://101.71.255.229:6610/zjhs/2/10118/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱世界
http://101.71.255.229:6610/zjhs/2/10121/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱玩具
http://101.71.255.229:6610/zjhs/2/10117/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱喜剧
http://101.71.255.229:6610/zjhs/2/10105/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱悬疑
http://101.71.255.229:6610/zjhs/2/10104/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱幼教
http://101.71.255.229:6610/zjhs/2/10112/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱院线
http://101.71.255.229:6610/zjhs/2/10116/index.m3u8?virtualDomain=zjhs.live_hls.zte.com
#EXTINF:-1 logo="" group-title="" ,爱青春
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230130/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱家庭
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230118/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱探索
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230112/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱科学
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230106/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱猎奇
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230097/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱谍战
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230092/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱娱乐
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230077/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱旅行
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230052/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱怀旧
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230049/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱体育
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230034/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱赛车
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230032/index.m3u8
#EXTINF:-1 logo="" group-title="" ,爱浪漫
http://112.17.40.140/hwltc.tv.cdn.zj.chinamobile.com/PLTV/88888888/224/3221230005/index.m3u8?fmt=ts2hls
#EXTINF:-1 logo="" group-title="" ,票房大片
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_heibangdianying_1080p_t10/c16_lb_heibangdianying_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,惊悚午夜
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_jingnawuyechang_1080p_t10/c16_lb_jingnawuyechang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,动画电影
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_donghuadianying_1080p_t10/c16_lb_donghuadianying_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,怀旧剧场
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_huaijiujuchang_1080p_t10/c16_lb_huaijiujuchang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,温情影院
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c15_lb_chenglong_1080p_t10/c15_lb_chenglong_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,周末影院
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_fengxiaogang_1080p_t10/c16_lb_fengxiaogang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,经典重温
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_jingdianjuchang_1080p_t10/c16_lb_jingdianjuchang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,谍战剧场
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_diezhanjuchang_1080p_t10/c16_lb_diezhanjuchang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,军旅剧场
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_junlvjuchang_1080p_t10/c16_lb_junlvjuchang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,青春剧场
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c15_lb_weizhangzhe_1080p_t10/c15_lb_weizhangzhe_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,抗战剧场
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c15_lb_kangzhanjuchang_1080p_t10/c15_lb_kangzhanjuchang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,侦探柯南
http://jvc.flashapp.cn/baiducdnct.inter.iqiyi.com/tslive/c20_lb_mingzhentankenan_720p_t10/c20_lb_mingzhentankenan_720p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,喜羊灰狼
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c15_lb_xiyangyang_1080p_t10/c15_lb_xiyangyang_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,儿子爸爸
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c16_lb_datouerzi_1080p_t10/c16_lb_datouerzi_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,儿歌大全
http://101.72.196.41/r/baiducdnct.inter.iqiyi.com/tslive/c15_lb_ergedaquan_1080p_t10/c15_lb_ergedaquan_1080p_t10.m3u8
#EXTINF:-1 logo="" group-title="" ,北京少儿
http://ivi.bupt.edu.cn/hls/btv10.m3u8
#EXTINF:-1 logo="" group-title="" ,动漫电影
http://112.17.40.140/PLTV/88888888/224/3221226178/index.m3u8
#EXTINF:-1 logo="" group-title="" ,云南少儿
http://edge2.yntv.cn/channels/yntv/ynse/flv:sd/live
#EXTINF:-1 logo="" group-title="" ,重庆少儿
http://219.153.252.50/PLTV/88888888/224/3221225646/1.m3u8
#EXTINF:-1 logo="" group-title="" ,嘉佳卡通
http://112.17.40.140/PLTV/88888888/224/3221226461/index.m3u8
#EXTINF:-1 logo="" group-title="" ,金鹰卡通
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225906/1.m3u8
#EXTINF:-1 logo="" group-title="" ,哈哈卡通
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225909/1.m3u8
#EXTINF:-1 logo="" group-title="" ,优漫卡通
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225910/1.m3u8
#EXTINF:-1 logo="" group-title="" ,卡酷少儿
http://111.13.111.242/otttv.bj.chinamobile.com/PLTV/88888888/224/3221225907/1.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导一年级
http://live-edu.wasu.tv/live/QiEFuDao-lv1.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导二年级
http://live-edu.wasu.tv/live/QiEFuDao-lv2.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导三年级
http://live-edu.wasu.tv/live/QiEFuDao-lv3.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导四年级
http://live-edu.wasu.tv/live/QiEFuDao-lv4.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导五年级
http://live-edu.wasu.tv/live/QiEFuDao-lv5.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导六年级
http://live-edu.wasu.tv/live/QiEFuDao-lv6.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导初一
http://live-edu.wasu.tv/live/QiEFuDao-lv7.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导初二
http://live-edu.wasu.tv/live/QiEFuDao-lv8.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导初三
http://live-edu.wasu.tv/live/QiEFuDao-lv9.m3u8
#EXTINF:-1 logo="" group-title="" ,企鹅辅导高一
http://live-edu.wasu.tv/live/QiEFuDao-lv10.m3u8
#EXTINF:-1 logo="" group-title="" ,八大精彩台
http://hdtv.ub1818.com/ublive/index_1.m3u8
#EXTINF:-1 logo="" group-title="" ,民视第一台
http://hdtv.ub1818.com/ublive/index_2.m3u8
#EXTINF:-1 logo="" group-title="" ,民视台湾台
http://hdtv.ub1818.com/ublive/index_3.m3u8
#EXTINF:-1 logo="" group-title="" ,民视HD
http://hdtv.ub1818.com/ublive/index_4.m3u8
#EXTINF:-1 logo="" group-title="" ,TvbsHD
http://hdtv.ub1818.com/ublive/index_5.m3u8
#EXTINF:-1 logo="" group-title="" ,非凡新闻HD
http://hdtv.ub1818.com/ublive/index_8.m3u8
#EXTINF:-1 logo="" group-title="" ,中视新闻HD
http://hdtv.ub1818.com/ublive/index_9.m3u8
#EXTINF:-1 logo="" group-title="" ,华视新闻资讯HD
http://hdtv.ub1818.com/ublive/index_10.m3u8
#EXTINF:-1 logo="" group-title="" ,FTV综艺
http://hdtv.ub1818.com/ublive/index_11.m3u8
#EXTINF:-1 logo="" group-title="" ,八大综合台
http://hdtv.ub1818.com/ublive/index_12.m3u8
#EXTINF:-1 logo="" group-title="" ,ELTA娱乐
http://hdtv.ub1818.com/ublive/index_13.m3u8
#EXTINF:-1 logo="" group-title="" ,亮社
http://hdtv.ub1818.com/ublive/index_14.m3u8
#EXTINF:-1 logo="" group-title="" ,华视CTS
http://hdtv.ub1818.com/ublive/index_15.m3u8
#EXTINF:-1 logo="" group-title="" ,公视戏剧
http://hdtv.ub1818.com/ublive/index_16.m3u8
#EXTINF:-1 logo="" group-title="" ,动漫
http://hdtv.ub1818.com/ublive/index_17.m3u8
#EXTINF:-1 logo="" group-title="" ,靖洋卡通台
http://hdtv.ub1818.com/ublive/index_18.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天综合台
http://hdtv.ub1818.com/ublive/index_19.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天日本台
http://hdtv.ub1818.com/ublive/index_20.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天卡通台
http://hdtv.ub1818.com/ublive/index_21.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天戏剧台
http://hdtv.ub1818.com/ublive/index_22.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天电影台
http://hdtv.ub1818.com/ublive/index_23.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天音乐台
http://hdtv.ub1818.com/ublive/index_24.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天国际台
http://hdtv.ub1818.com/ublive/index_25.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天映画
http://hdtv.ub1818.com/ublive/index_26.m3u8
#EXTINF:-1 logo="" group-title="" ,台湾采昌
http://hdtv.ub1818.com/ublive/index_27.m3u8
#EXTINF:-1 logo="" group-title="" ,台湾影迷电影
http://hdtv.ub1818.com/ublive/index_28.m3u8
#EXTINF:-1 logo="" group-title="" ,台湾CNEX
http://hdtv.ub1818.com/ublive/index_29.m3u8
#EXTINF:-1 logo="" group-title="" ,台湾AMC电影
http://hdtv.ub1818.com/ublive/index_30.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天资讯台
http://hdtv.ub1818.com/ublive/index_31.m3u8
#EXTINF:-1 logo="" group-title="" ,靖天欢乐台
http://hdtv.ub1818.com/ublive/index_32.m3u8
#EXTINF:-1 logo="" group-title="" ,靖洋戏剧台
http://hdtv.ub1818.com/ublive/index_33.m3u8
#EXTINF:-1 logo="" group-title="" ,台湾音乐
http://hdtv.ub1818.com/ublive/index_34.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国娱乐台
http://hdtv.ub1818.com/ublive/index_35.m3u8
#EXTINF:-1 logo="" group-title="" ,旅游频道
http://hdtv.ub1818.com/ublive/index_36.m3u8
#EXTINF:-1 logo="" group-title="" ,户外频道
http://hdtv.ub1818.com/ublive/index_37.m3u8
#EXTINF:-1 logo="" group-title="" ,台视财经HD
http://hdtv.ub1818.com/ublive/index_38.m3u8
#EXTINF:-1 logo="" group-title="" ,TRACE体育
http://hdtv.ub1818.com/ublive/index_39.m3u8
#EXTINF:-1 logo="" group-title="" ,TVB明珠
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Pcontent_id=&Provider_id=&Fsv_chan_hls_se_idx=12
#EXTINF:-1 logo="" group-title="" ,香港卫视
http://zhibo.hkstv.tv/livestream/mutfysrq.flv
#EXTINF:-1 logo="" group-title="" ,翡翠明珠
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=12&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,翡翠综合
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=188&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv&_res_tag_=video
#EXTINF:-1 logo="" group-title="" ,耀才财经
http://202.69.67.66:443/webcast/bshdlive-mobile/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,亚旅卫视
http://hls.jingchangkan.tv/jingchangkan/156722438_0HaM/index.m3u8
#EXTINF:-1 logo="" group-title="" ,赛马频道
http://tvbilive11-i.akamaihd.net/hls/live/494672/CH88/CH88-01.m3u8
#EXTINF:-1 logo="" group-title="" ,東森新聞
http://104.250.154.42:8080/ZZ_dongsenxinwen/ZZ_dongsenxinwen.m3u8
#EXTINF:-1 logo="" group-title="" ,東森電影
http://104.250.154.42:8080/ZZ_dongsendianying/ZZ_dongsendianying.m3u8
#EXTINF:-1 logo="" group-title="" ,東森洋片
http://192.154.103.75:8080/ZZ_dongsenyangpian/ZZ_dongsenyangpian.m3u8
#EXTINF:-1 logo="" group-title="" ,東森洋片
http://104.250.154.42:8080/ZZ_dongsenyangpian/ZZ_dongsenyangpian.m3u8
#EXTINF:-1 logo="" group-title="" ,中天新闻
http://104.250.154.42:8080/ZZ_zhongtiannews/ZZ_zhongtiannews.m3u8
#EXTINF:-1 logo="" group-title="" ,中天综合
http://104.250.154.42:8080/ZZ_zhongtianzonghe/ZZ_zhongtianzonghe.m3u8
#EXTINF:-1 logo="" group-title="" ,中天綜合
http://192.154.103.75:8080//ZZ_zhongtianzonghe/ZZ_zhongtianzonghe.m3u8
#EXTINF:-1 logo="" group-title="" ,中天娱乐
http://192.154.103.75:8080//ZZ_zhongtianyule/ZZ_zhongtianyule.m3u8
#EXTINF:-1 logo="" group-title="" ,中天娱乐
http://104.250.154.42:8080/ZZ_zhongtianyule/ZZ_zhongtianyule.m3u8
#EXTINF:-1 logo="" group-title="" ,中視综合
http://192.154.103.75:8080//ZZ_zhongshi/ZZ_zhongshi.m3u8
#EXTINF:-1 logo="" group-title="" ,中视综合
http://104.250.154.42:8080/ZZ_zhongshi/ZZ_zhongshi.m3u8
#EXTINF:-1 logo="" group-title="" ,华视综合
http://104.250.154.42:8080/ZZ_huashi/ZZ_huashi.m3u8
#EXTINF:-1 logo="" group-title="" ,华视综合
http://192.154.103.75:8080//ZZ_huashi/ZZ_huashi.m3u8
#EXTINF:-1 logo="" group-title="" ,年代新聞
http://192.154.103.75:8080/ZZ_niandaixinwen/ZZ_niandianxinwen.m3u8
#EXTINF:-1 logo="" group-title="" ,年代新闻
http://104.250.154.42:8080/ZZ_niandaixinwen/ZZ_niandianxinwen.m3u8
#EXTINF:-1 logo="" group-title="" ,八大綜合
http://192.154.103.75:8080//ZZ_zhongtianyazhou/ZZ_zhongtianyazhou.m3u8
#EXTINF:-1 logo="" group-title="" ,八大综合
http://104.250.154.42:8080/ZZ_zhongtianyazhou/ZZ_zhongtianyazhou.m3u8
#EXTINF:-1 logo="" group-title="" ,信吉电视
http://220.130.241.203:1935/sjtv/livestream_360p/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,人間衛視
http://54.64.23.79:1935/live/vod/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,唯心電視
http://mobile.ccdntech.com/transcoder/_definst_/vod164_Live/live/chunklist_w1177047531.m3u8
#EXTINF:-1 logo="" group-title="" ,卫视卡视
http://iliketot.dyndns.tv/c8233976dbba4a06a101780907447375.m3u8?&wmsAuthSign=c2VydmVyX3RpbWU9MTAvMjIvMjAxNyAxOjM2OjExIEFNJmhhc2hfdmFsdWU9T1lvZDZ5TjFaWk53M3J4OWZOTWtFUT09JnZhbGlkbWludXRlcz0yJmlkPW1jZ2x5bWFyfDc2MXxpcHR2aGVyb3wxNTA4NjM2MTcxfDIyMy4yMDUuMTIyLjE2Nw
#EXTINF:-1 logo="" group-title="" ,国家地理
http://104.250.154.42:8080/ZZ_hbo/ZZ_hbo.m3u8
#EXTINF:-1 logo="" group-title="" ,百事通台
http://112.17.40.145/PLTV/88888888/224/3221226596/index.m3u8
#EXTINF:-1 logo="" group-title="" ,MTV音乐
http://116.199.5.52:8114/00000000/index.m3u8?&Fsv_ctype=LIVES&Fsv_otype=1&FvSeid=5abd1660af1babb4&Fsv_filetype=1&Fsv_ctype=LIVES&Fsv_cid=0&Fsv_chan_hls_se_idx=202&Fsv_rate_id=0&Fsv_SV_PARAM1=0&Fsv_ShiftEnable=0&Fsv_ShiftTsp=0&Provider_id=&Pcontent_id=&Fsv_CMSID=&Fsv_otype=1
#EXTINF:-1 logo="" group-title="" ,HBO2台
http://161.0.157.5/PLTV/88888888/224/3221227026/03.m3u8fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,动物星球
http://104.250.154.42:8080/ZZ_dongwuxingqiu/ZZ_dongwuxingqiu.m3u8
#EXTINF:-1 logo="" group-title="" ,歐美影院
http://101.71.255.229:6610/zjhs/2/10037/z.m3u8?ZTEUPSTREAM=1&IASHttpSessionId=SLB4328320190321203540013412&m3u8_level=2&ztecid=10037&virtualDomain=zjhs.live_hls.zte.com&ispcode=3&tid=Q894B3E8EEZ3T19UG09L8B03GSWB&ts=1553493266
#EXTINF:-1 logo="" group-title="" ,亞洲影院
http://101.71.255.229:6610/zjhs/2/10052/z.m3u8?ZTEUPSTREAM=1&IASHttpSessionId=SLB4328320190321203540013412&m3u8_level=2&ztecid=10052&virtualDomain=zjhs.live_hls.zte.com&ispcode=3&tid=C3V7K4ET1VFDUJY6C1IASRV55G66&ts=1553493153
#EXTINF:-1 logo="" group-title="" ,华纳电视
http://104.250.154.42:8080/ZZ_huanadianying/ZZ_huanadianying.m3u8
#EXTINF:-1 logo="" group-title="" ,福克斯动作
http://104.250.154.42:8080/ZZ_foxaction/ZZ_foxaction.m3u8
#EXTINF:-1 logo="" group-title="" ,福克斯动作
http://192.154.103.75:8080/ZZ_foxaction/ZZ_foxaction.m3u8
#EXTINF:-1 logo="" group-title="" ,大众影视
http://39.134.52.206/wh7f454c46tw2522585283_-1736190513/hwottcdn.ln.chinamobile.com/PLTV/88888890/224/3221226752/index.m3u8?icpid=88888890&RTS=1575014274&from=1&ocs=2_39.134.52.206_80&hms_devid=835&vqe=3
#EXTINF:-1 logo="" group-title="" ,点掌财经
http://cclive2.aniu.tv/live/anzb.m3u8
#EXTINF:-1 logo="" group-title="" ,澳门卫视
http://stream.mastvnet.com/MSTV/SD/live.m3u8
#EXTINF:-1 logo="" group-title="" ,澳亚卫视
http://stream.mastvnet.com/MSTV/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,日本NHK华语
https://nhkw-zh-hlscomp.akamaized.net/ixxemlzk1vqvy44o/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,日本NHK英语
https://nhkwlive-ojp.akamaized.net/hls/live/2003459/nhkwlive-ojp/index_1M.m3u8
#EXTINF:-1 logo="" group-title="" ,日本Japan News 24
http://www.news24.jp/livestream/index.m3u8
#EXTINF:-1 logo="" group-title="" ,日本JapanetChannelDX
http://bcsecurelivehls-i.akamaihd.net/hls/live/265320/5043843989001/140130JTDX/index_1200.m3u8
#EXTINF:-1 logo="" group-title="" ,日本QVC
http://cdn-live1.qvc.jp/iPhone/800/800.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国EBS 第一频道
http://ebsonairios.ebs.co.kr/groundwavetablet500k/tablet500k/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国EBS 少儿频道
http://ebsonairios.ebs.co.kr/ebsutablet500k/tablet500k/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国KCTV
http://119.77.96.184:1935/chn21/chn21/chunklist_w252131137.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国UBC SBS
http://59.25.202.81:1935/live/UBCstream/chunklist_w1495115977.m3u8
#EXTINF:-1 logo="" group-title="" ,朝鲜中央台
http://119.77.96.184:1935/chn05/chn05/chunklist_w644291506.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国KTV 韩国电视
http://218.38.152.31:1935/klive/klive.stream/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国EBS 儿童频道
http://ebsonairios.ebs.co.kr/ebsutablet500k/_definst_/tablet500k/chunklist_w1965791004.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国YTN 联合新闻
http://ytnmmd.mmdlive.lldns.net/ytnmmd/9484b70302db4786886ae40308bf45a1/chunklist_b2592000.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国阿里郎WORLDworld
http://amdlive.ctnd.com.edgesuite.net/arirang_1ch/smil:arirang_1ch.smil/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国阿里郎WORLD
http://amdlive.ctnd.com.edgesuite.net/arirang_1ch/smil:arirang_1ch/master.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国MBC MAX
http://63.237.48.3/ios/MBC_MAX/MBC_MAX.m3u8
#EXTINF:-1 logo="" group-title="" ,KOREA YTN Science
http://slive.sciencetv.kr:1935/science/yslive_20140419_1/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,Luxury World
http://nano.teleservice.su:8080/hls/luxury.m3u8
#EXTINF:-1 logo="" group-title="" ,韩国BBS佛教广播
http://bbstv.clouducs.com:1935/bbstv-live/livestream/chunklist_w1403706733.m3u8
#EXTINF:-1 logo="" group-title="" ,CPAC
http://bcoveliveios-i.akamaihd.net/hls/live/248519/1242843915001_1/master.m3u8
#EXTINF:-1 logo="" group-title="" ,CGTN 记录频道
http://live.cgtn.com/1000d/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,中国环球
http://live.cgtn.com/1000/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,狗狗宠物
http://video.blivenyc.com/broadcast/prod/2061/22/file-3192k.m3u8
#EXTINF:-1 logo="" group-title="" ,法国时尚
http://lb.streaming.sk/fashiontv/stream/chunklist_w1702070444.m3u8
#EXTINF:-1 logo="" group-title="" ,亚洲新闻
http://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_4.m3u8
#EXTINF:-1 logo="" group-title="" ,朝阳频道
http://d11h6a6nhl9kj9.cloudfront.net/hls/suriactv/master02.m3u8
#EXTINF:-1 logo="" group-title="" ,越南人民报
http://27.118.16.98:1935/live/truyenhinhnhandan720/chunklist_w2006762604.m3u8
#EXTINF:-1 logo="" group-title="" ,越南人民报
http://vietcago.net/vstv/thnd.m3u8
#EXTINF:-1 logo="" group-title="" ,印度音乐电视
http://104.237.60.234/live/gabruutv.m3u8?dsjtv.m3u8
#EXTINF:-1 logo="" group-title="" ,法国中国环球
http://live.cgtn.com/1000f/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,法国第五世界台
http://v3plusinfo247hls-i.akamaihd.net/hls/live/218877-b/v3plusinfo247hls/v3plusinfo247hls_1_1.m3u8
#EXTINF:-1 logo="" group-title="" ,阿拉伯中国环球
http://live.cgtn.com/1000a/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,俄罗斯中国环球
http://live.cgtn.com/1000r/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,俄罗斯HD时尚频道
http://95.67.47.115/hls/hdfashion_ua_hi/index.m3u8
#EXTINF:-1 logo="" group-title="" ,乌克兰M2 音乐频道
http://live.m2.tv/hls3/stream.m3u8
#EXTINF:-1 logo="" group-title="" ,西班牙中国环球
http://livees.cgtn.com/1000e/prog_index.m3u8
#EXTINF:-1 logo="" group-title="" ,意大利Rai高清
http://b2everyrai-lh.akamaihd.net/i/raigulp_1@66350/master.m3u8
#EXTINF:-1 logo="" group-title="" ,意大利Rai 少儿
http://b2everyrai-lh.akamaihd.net/i/raiyoyo_1@191405/master.m3u8
#EXTINF:-1 logo="" group-title="" ,意大利Rai 电影
http://b2everyrai-lh.akamaihd.net/i/raimovie_1@67348/master.m3u8
#EXTINF:-1 logo="" group-title="" ,意大利意大利电台
http://radioitaliatv-lh.akamaihd.net/i/radioitaliatv_1@329645/index_720x480_av-p.m3u8
#EXTINF:-1 logo="" group-title="" ,意大利V2 音乐频道
http://de1se01.v2beat.live/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,墨西哥墨西哥电视
http://bcoveliveios-i.akamaihd.net/hls/live/201661/57828478001/milenio_center_512k@51752.m3u8
#EXTINF:-1 logo="" group-title="" ,音乐20TV
http://m2otv-lh.akamaihd.net/i/m2oTv_1@186074/index_600_av-p.m3u8
#EXTINF:-1 logo="" group-title="" ,当红MTV
http://unilivemtveu-lh.akamaihd.net/i/mtvno_1@346424/index_3500_av-b.m3u8
#EXTINF:-1 logo="" group-title="" ,WSVI-TV
http://dcunilive30-lh.akamaihd.net/i/dclive_1@534251/master.m3u8?fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,酷酷频道
http://edge1.tikilive.com:1935/unrestricted_tikilive/25947/amlst:NWKlw6jwyXpz/chunklist_w981409619_b1105254.m3u8?fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,红牛电视
http://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_1660.m3u8
#EXTINF:-1 logo="" group-title="" ,NBC电视
http://161.0.157.51/PLTV/88888888/224/3221227040/index.m3u8?fluxustv.m3u8
#EXTINF:-1 logo="" group-title="" ,Jewelry电视
http://wowzaprod134-i.akamaihd.net/hls/live/577814/ccddaf02/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,Darcizzle电视
http://30a-tv.com/darcizzle.m3u8
#EXTINF:-1 logo="" group-title="" ,CBS新闻
http://cbsnewshd-lh.akamaihd.net/i/CBSNHD_7@199302/master.m3u8
#EXTINF:-1 logo="" group-title="" ,美国Deutsche Welle
http://dwstream4-lh.akamaihd.net/i/dwstream4_live@131329/master.m3u8
#EXTINF:-1 logo="" group-title="" ,美国360 North
http://wowzaprod3-i.akamaihd.net/hls/live/252236/2147483647_360north_247/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,美国Fox News Talk Radio
http://fnurtmp-f.akamaihd.net/i/FNRADIO_1@92141/master.m3u8
#EXTINF:-1 logo="" group-title="" ,日本NHK台
http://nhkwtvglobal-i.akamaihd.net/hls/live/263941/nhkwtvglobal/index_600.m3u8
#EXTINF:-1 logo="" group-title="" ,日本cgntv
http://cgntv-glive.ofsdelivery.net/live/_definst_/cgntv_jp/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,日本映画
http://192.240.127.34:1935/live/cs19.stream/playlist.m3u8
#EXTINF:-1 logo="" group-title="" ,日本Japanet Channel DX
http://bcsecurelivehls-i.akamaihd.net/hls/live/265320/5043843989001/140130JTDX/index_600.m3u8

View File

@@ -1,6 +1,6 @@
{
"name": "zy",
"version": "2.6.4",
"version": "2.6.10",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
@@ -13,20 +13,18 @@
"postuninstall": "electron-builder install-app-deps",
"electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten",
"release": "vue-cli-service electron:build -p always",
"dist": "vue-cli-service electron:build --win --ia32"
"dist": "vue-cli-service electron:build --win --x64"
},
"main": "background.js",
"dependencies": {
"@imjs/electron-differential-updater": "^5.1.3",
"axios": "^0.21.0",
"cheerio": "^1.0.0-rc.3",
"core-js": "^3.7.0",
"cors": "^2.8.5",
"dexie": "^3.0.2",
"core-js": "^3.8.0",
"dexie": "^3.0.3",
"electron-localshortcut": "^3.2.1",
"electron-proxy-agent": "^1.2.0",
"electron-updater": "^4.3.5",
"element-ui": "^2.14.0",
"express": "^4.17.1",
"element-ui": "^2.14.1",
"fast-xml-parser": "^3.17.4",
"html2canvas": "^1.0.0-rc.7",
"iptv-playlist-parser": "^0.5.0",
@@ -35,38 +33,40 @@
"memcached": "^2.2.2",
"modern-normalize": "^1.0.0",
"mousetrap": "^1.6.5",
"pinyin-match": "^1.1.1",
"qrcode.vue": "^1.7.0",
"randomstring": "^1.1.5",
"session": "^0.1.0",
"sortablejs": "^1.12.0",
"v-fit-columns": "^0.2.0",
"vue": "^2.6.12",
"vue-clickaway": "^2.2.2",
"vue-infinite-loading": "^2.4.5",
"vue-waterfall-plugin": "^1.1.0",
"vuedraggable": "^2.24.3",
"vuex": "^3.5.1",
"xgplayer": "^2.13.0",
"vuex": "^3.6.0",
"xgplayer": "^2.13.2",
"xgplayer-hls.js": "^2.2.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"@vue/cli-plugin-babel": "~4.5.9",
"@vue/cli-plugin-eslint": "~4.5.9",
"@vue/cli-plugin-vuex": "~4.5.9",
"@vue/cli-service": "~4.5.9",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1",
"electron": "^10.1.5",
"electron-devtools-installer": "^3.1.0",
"eslint": "^6.7.2",
"electron": "^11.0.3",
"electron-devtools-installer": "^3.1.1",
"eslint": "^7.14.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.2",
"eslint-plugin-vue": "^6.2.2",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^7.1.0",
"sass": "^1.29.0",
"sass-loader": "^8.0.2",
"vue-cli-plugin-electron-builder": "2.0.0-rc.4",
"sass-loader": "^10.1.0",
"vue-cli-plugin-electron-builder": "2.0.0-rc.5",
"vue-template-compiler": "^2.6.12"
}
}

View File

@@ -5,10 +5,10 @@
<Frame />
<Film v-show="view === 'Film'" />
<Play v-show="view === 'Play'" />
<IPTV v-show="view === 'IPTV'" />
<Star v-show="view === 'Star'" />
<History v-show="view === 'History'" />
<Setting v-show="view === 'Setting'" />
<IPTV v-show="view === 'IPTV'" />
<EditSites v-if="view === 'EditSites'"/>
<Recommendation v-show="view === 'Recommendation'" />
</div>

View File

@@ -95,9 +95,6 @@
text-indent: 10px;
}
}
.zy-highlighted{
color: var(--highlight-color);
}
// scroll
.zy-scroll{
&::-webkit-scrollbar{
@@ -126,7 +123,7 @@
border-radius: 5px;
display: flex;
flex-direction: column;
.listpage-header{
.listpage-header, .toolbar{
height: 60px;
width: 100%;
display: flex;
@@ -178,7 +175,39 @@
font-size: 1rem;
border: none;
}
.el-select-dropdown__item.selected.hover{ //是上游的bug吗临时性修补
background-color: transparent;
}
.el-select-dropdown__wrap{
max-height: 574px
}
}
> span{
.el-input-number{
width:120px;
.el-input{
width: 100px;
}
.el-input__inner{
padding-left: 5px;
padding-right: 5px;
width: 88px;
}
.el-input-number__increase, .el-input-number__decrease {
background-color: inherit;
border: none;
}
}
}
}
.el-divider{
.el-divider--horizontal{
margin: 12px 0;
}
}
.toolbar{
z-index: 5;
}
.listpage-body{
height: calc(100% - 60px);
@@ -225,6 +254,9 @@
position: absolute;
}
}
.disableExpand div.el-table__expand-icon{
display: none;
}
.el-input{
width: 200px;
}
@@ -235,7 +267,7 @@
transform: scale(1.02);
}
.el-table .highlight{
background-color: var(--highlight-color) !important; // 改为背景色,原来某些主题下看不清字
color: var(--highlight-color) !important;
}
.el-button{
font-size: 1rem;
@@ -276,6 +308,19 @@
text-align: center;
transform: rotate(45deg);
}
.site{
position: absolute;
top: 0%;
left: 0%;
width: 100%;
background-color: #111111aa;
color:#2f90b9;
height: 30px;
line-height: 30px;
font-size: 14px;
font-weight: bolder;
text-align: center;
}
.progress{
position: absolute;
bottom: 10%;

View File

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

View File

@@ -139,6 +139,13 @@
.play{
background-color: var(--d-bgc-1);
box-shadow: var(--d-bsc);
.el-input{
input{
background-color: var(--d-bgc-1);
border: 1px solid var(--d-bgc-1);
color: var(--d-fc-2);
}
}
.title{
color: var(--d-fc-1);
.right {
@@ -207,6 +214,14 @@
}
}
}
.list-channels{
.btn{
color: var(--d-fc-1);
&:hover{
text-decoration:underline;
}
}
}
.list-history{
li{
.title{
@@ -304,7 +319,7 @@
// Page of list using table and picture
.listpage{
color: var(--d-fc-2);
.listpage-header{
.listpage-header, .toolbar{
border-bottom-color: var(--d-c-3);
.btn{
&:hover{

View File

@@ -139,6 +139,13 @@
.play{
background-color: var(--g-bgc-1);
box-shadow: var(--g-bsc);
.el-input{
input{
background-color: var(--g-bgc-1);
border: 1px solid var(--g-bgc-1);
color: var(--g-fc-2);
}
}
.title{
color: var(--g-fc-1);
.right {
@@ -207,6 +214,14 @@
}
}
}
.list-channels{
.btn{
color: var(--g-fc-1);
&:hover{
text-decoration:underline;
}
}
}
.list-history{
li{
.title{
@@ -304,7 +319,7 @@
// Page of list using table and picture
.listpage{
color: var(--g-fc-2);
.listpage-header{
.listpage-header, .toolbar{
border-bottom-color: var(--g-c-3);
.btn{
&:hover{

View File

@@ -139,6 +139,13 @@
.play{
background-color: var(--l-bgc-1);
box-shadow: var(--l-bsc);
.el-input{
input{
background-color: var(--l-bgc-1);
border: 1px solid var(--l-bgc-1);
color: var(--l-fc-2);
}
}
.title{
color: var(--l-fc-1);
.right {
@@ -207,6 +214,14 @@
}
}
}
.list-channels{
.btn{
color: var(--l-fc-1);
&:hover{
text-decoration:underline;
}
}
}
.list-history{
li{
.title{
@@ -304,7 +319,7 @@
// Page of list using table and picture
.listpage{
color: var(--l-fc-2);
.listpage-header{
.listpage-header, .toolbar{
border-bottom-color: var(--l-c-3);
.btn{
&:hover{

View File

@@ -139,6 +139,13 @@
.play{
background-color: var(--p-bgc-1);
box-shadow: var(--p-bsc);
.el-input{
input{
background-color: var(--p-bgc-1);
border: 1px solid var(--p-bgc-1);
color: var(--p-fc-2);
}
}
.title{
color: var(--p-fc-1);
.right {
@@ -207,6 +214,14 @@
}
}
}
.list-channels{
.btn{
color: var(--p-fc-1);
&:hover{
text-decoration:underline;
}
}
}
.list-history{
li{
.title{
@@ -304,7 +319,7 @@
// Page of list using table and picture
.listpage{
color: var(--p-fc-2);
.listpage-header{
.listpage-header, .toolbar{
border-bottom-color: var(--p-c-3);
.btn{
&:hover{

View File

@@ -1,17 +1,15 @@
'use strict'
import './lib/site/server'
import { app, protocol, BrowserWindow, globalShortcut, ipcMain } from 'electron'
import { app, protocol, BrowserWindow, globalShortcut } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import { initUpdater } from './lib/update/update'
const isDevelopment = process.env.NODE_ENV !== 'production'
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors') // 允许跨域
// app.commandLine.appendSwitch('--ignore-certificate-errors', 'true') // 忽略证书相关错误
app.commandLine.appendSwitch('--ignore-certificate-errors', 'true') // 忽略证书相关错误
let win
let mini
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])
@@ -43,35 +41,6 @@ function createWindow () {
})
}
function createMini () {
mini = new BrowserWindow({
width: 550,
miniWidth: 860,
height: 340,
miniHeight: 180,
frame: false,
resizable: true,
webPreferences: {
sandbox: false,
webSecurity: false,
enableRemoteModule: true,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
mini.loadURL(process.env.WEBPACK_DEV_SERVER_URL + 'mini')
if (!process.env.IS_TEST) mini.webContents.openDevTools()
} else {
createProtocol('app')
mini.loadURL('app://./mini.html')
}
mini.on('closed', () => {
mini = null
})
}
if (process.platform === 'darwin') {
app.dock.show()
}
@@ -91,17 +60,6 @@ app.on('activate', () => {
}
})
ipcMain.on('mini', () => {
createMini()
win.hide()
})
ipcMain.on('win', () => {
mini.destroy()
win.show()
win.webContents.send('miniClosed')
})
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
@@ -125,9 +83,6 @@ if (!gotTheLock) {
if (win) {
win.isFocused() ? win.blur() : win.focus()
}
if (mini) {
mini.isFocused() ? mini.blur() : mini.focus()
}
})
})
}

View File

@@ -21,13 +21,6 @@
<path d="M4,18 L4,9"/>
</svg>
</span>
<span :class="[view === 'IPTV' ? 'active ': ''] + 'zy-svg'" @click="changeView('IPTV')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="tvIconTitle">
<title id="tvIconTitle">电视直播</title>
<polygon points="20 8 20 20 4 20 4 8"></polygon>
<polyline stroke-linejoin="round" points="8 4 12 7.917 16 4"></polyline>
</svg>
</span>
<span :class="[view === 'Play' ? 'active ': ''] + 'zy-svg'" @click="changeView('Play')">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="playIconTitle">
<title id="playIconTitle">播放</title>

View File

@@ -130,7 +130,6 @@ export default {
},
async playEvent (n) {
if (!this.playOnline) {
console.log(this.detail)
const db = await history.find({ site: this.detail.key, ids: this.detail.info.id })
if (db) {
this.video = { key: db.site, info: { id: db.ids, name: db.name, index: n, site: this.detail.site } }
@@ -212,30 +211,29 @@ export default {
}
},
downloadEvent () {
zy.download(this.detail.key, this.info.id).then(res => {
if (res && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')
let downloadUrl = res.name + '\n'
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
this.$message.warning('没有查询到下载链接.')
}
} else {
const list = [...this.m3u8List]
let downloadUrl = this.detail.info.name + '\n'
const key = this.detail.key
const id = this.info.id
zy.download(key, id).then(res => {
if (res && res.m3u8List) {
const list = res.m3u8List.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
zy.detail(key, id).then(res => {
const list = [...res.m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
})
}
})
},

View File

@@ -4,16 +4,16 @@
<el-switch v-model="enableBatchEdit" active-text="批处理分组">></el-switch>
<el-checkbox v-model="setting.excludeR18Films" @change="excludeR18FilmsChangeEvent">屏蔽福利片</el-checkbox>
<el-button @click="addSite" icon="el-icon-document-add">新增</el-button>
<el-button @click="exportSites" icon="el-icon-upload2" >导出</el-button>
<el-button @click="importSites" icon="el-icon-download">导入</el-button>
<el-button @click="checkAllSite" icon="el-icon-refresh" :loading="checkAllSitesLoading">检测{{ this.checkAllSitesLoading ? this.checkProgress + '/' + this.sites.length : '' }}</el-button>
<el-button @click="exportSites" icon="el-icon-upload2" title="导出全部,自动添加扩展名">导出</el-button>
<el-button @click="importSites" icon="el-icon-download" title="支持同时导入多个文件">导入</el-button>
<el-button @click="checkAllSite" icon="el-icon-refresh" :loading="checkAllSitesLoading" title="可在后台运行">检测{{ this.checkAllSitesLoading ? this.checkProgress + '/' + this.sites.length : '' }}</el-button>
<el-button @click="resetSitesEvent" icon="el-icon-refresh-left">重置</el-button>
</div>
<div class="listpage-header" v-show="enableBatchEdit">
<el-switch v-model="enableBatchEdit" active-text="批处理分组"></el-switch>
<el-input placeholder="新组名" v-model="batchGroupName"></el-input>
<el-switch v-model="batchIsActive" active-text="启用"></el-switch>
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存</el-button>
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit" title="输入框组名为空时仅保存开关状态">保存分组与开关状态</el-button>
<el-button @click="removeSelectedSites" icon="el-icon-delete-solid">删除</el-button>
</div>
<div class="listpage-body" id="sites-body">
@@ -186,6 +186,17 @@ export default {
this.$message.info('正在检测, 请勿操作.')
this.enableBatchEdit = false
}
if (this.enableBatchEdit) {
if (this.setting.shiftTooltipLimitTimes === undefined) this.setting.shiftTooltipLimitTimes = 5
if (this.setting.shiftTooltipLimitTimes) {
this.$message.info('多选时支持shift快捷键')
this.setting.shiftTooltipLimitTimes--
setting.find().then(res => {
res.shiftTooltipLimitTimes = this.setting.shiftTooltipLimitTimes
setting.update(res)
})
}
}
}
},
methods: {
@@ -199,9 +210,9 @@ export default {
selectionCellClick (selection, row) {
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
this.selectionEnd = row.id
const start = Math.min(this.selectionBegin, this.selectionEnd) - 1
const end = Math.max(this.selectionBegin, this.selectionEnd)
const selections = this.sites.slice(start, end)
const start = this.sites.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
const end = this.sites.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
const selections = this.sites.slice(start, end + 1)
this.$nextTick(() => {
selections.forEach(e => this.$refs.editSitesTable.toggleRowSelection(e, true))
})
@@ -314,7 +325,7 @@ export default {
var randomstring = require('randomstring')
var doc = {
key: this.dialogType === 'edit' ? this.siteInfo.key : this.siteInfo.key ? this.siteInfo.key : randomstring.generate(6),
id: this.dialogType === 'edit' ? this.siteInfo.id : this.sites[this.sites.length - 1].id + 1,
id: this.dialogType === 'edit' ? this.siteInfo.id : this.sites.length ? this.sites[this.sites.length - 1].id + 1 : 1,
name: this.siteInfo.name,
api: this.siteInfo.api,
download: this.siteInfo.download,
@@ -342,13 +353,12 @@ export default {
const str = JSON.stringify(arr, null, 2)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
{ name: 'JSON file', extensions: ['json'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
if (!result.filePath.endsWith('.json')) result.filePath += '.json'
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
@@ -363,9 +373,7 @@ export default {
}
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
{ name: 'JSON file', extensions: ['json'] }
],
properties: ['openFile', 'multiSelections']
}
@@ -412,7 +420,7 @@ export default {
this.updateDatabase()
},
syncTableData () {
if (this.$refs.editSitesTable.tableData) {
if (this.$refs.editSitesTable.tableData && this.$refs.editSitesTable.tableData.length === this.sites.length) {
this.sites = this.$refs.editSitesTable.tableData
}
},
@@ -462,6 +470,7 @@ export default {
})
},
async checkAllSite () {
if (this.checkAllSitesLoading) return
this.checkAllSitesLoading = true
this.stopFlag = false
this.checkProgress = 0
@@ -471,6 +480,7 @@ export default {
await Promise.all(other.map(site => this.checkSingleSite(site))).then(res => {
this.checkAllSitesLoading = false
this.getSites()
if (!this.stopFlag) this.$message.success('视频点播源站批量检测已完成!')
})
},
async checkSingleSite (row) {

View File

@@ -9,7 +9,7 @@
:value="item.name">
</el-option>
</el-select>
<el-select v-model="selectedClassName" size="small" placeholder="类型" :popper-append-to-body="false" popper-class="popper" @change="classClick" v-show="show.class">
<el-select v-model="selectedClassName" size="small" placeholder="类型" :popper-append-to-body="false" popper-class="popper" @change="classClick" v-if="classList && classList.length" v-show="!showFind">
<el-option
v-for="item in classList"
:key="item.tid"
@@ -17,6 +17,14 @@
:value="item.name">
</el-option>
</el-select>
<el-select v-model="selectedSearchClassNames" size="small" multiple placeholder="类型" :popper-append-to-body="false" popper-class="popper" v-if="searchClassList && searchClassList.length" v-show="showFind && showToolbar" @remove-tag="refreshFilteredList" @change="refreshFilteredList">
<el-option
v-for="(item, index) in searchClassList"
:key='index'
:label="item"
:value="item">
</el-option>
</el-select>
<el-autocomplete
clearable
size="small"
@@ -42,12 +50,42 @@
</el-option>
</el-select>
<!--方便触屏-->
<el-button icon="el-icon-search" @click.stop="searchEvent" slot="append" />
<el-button icon="el-icon-search" @click.stop="searchEvent" slot="append" v-if="!searchRunning"/>
<el-button icon="el-icon-loading" @click.stop="stopSearchEvent" slot="append" v-if="searchRunning" title='点击可停止搜索'/>
</el-autocomplete>
</div>
<div class="toolbar" v-show="showToolbar">
<el-select v-model="selectedAreas" size="small" multiple placeholder="地区" popper-class="popper" :popper-append-to-body="false" @remove-tag="refreshFilteredList" @change="refreshFilteredList">
<el-option
v-for="item in areas"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="sortKeyword" size="small" placeholder="排序" popper-class="popper" :popper-append-to-body="false" @change="refreshFilteredList">
<el-option
v-for="item in sortKeywords"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<span>
上映区间
<el-input-number size="small" v-model="selectedYears.start" :min=0 :max="new Date().getFullYear()" controls-position="right" step-strictly @change="refreshFilteredList"></el-input-number>
<el-input-number size="small" v-model="selectedYears.end" :min=0 :max="new Date().getFullYear()" controls-position="right" step-strictly @change="refreshFilteredList"></el-input-number>
</span>
</div>
<el-divider content-position="center">
<el-button type="text" size="mini" @click="toggleViewMode">视图切换</el-button>
<el-button type="text" size="mini" @click='() => { showToolbar = !showToolbar; if (!showToolbar) this.refreshFilteredList() }' title="收起工具栏会重置筛选排序">{{ showToolbar ? '隐藏工具栏' : '显示工具栏' }}</el-button>
<el-button type="text" size="mini" @click="backTop">回到顶部</el-button>
</el-divider>
<div class="listpage-body" id="film-body" infinite-wrapper>
<div class="show-picture" v-if="setting.view === 'picture' && !show.find">
<Waterfall ref="filmWaterfall" :list="list" :gutter="20" :width="240"
<div class="show-picture" v-if="setting.view === 'picture' && !showFind">
<Waterfall ref="filmWaterfall" :list="filteredList" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
rowPerView: 4,
@@ -62,7 +100,7 @@
animationEffect="fadeIn"
backgroundColor="rgba(0, 0, 0, 0)">
<template slot="item" slot-scope="props">
<div class="card" v-show="!setting.excludeR18Films || !containsR18Keywords(props.data.type)">
<div class="card">
<div class="img">
<img style="width: 100%" :src="props.data.pic" alt="" @load="$refs.filmWaterfall.refresh()" @click="detailEvent(site, props.data)">
<div class="operate">
@@ -85,10 +123,11 @@
</Waterfall>
<infinite-loading force-use-infinite-wrapper :identifier="infiniteId" @infinite="infiniteHandler"></infinite-loading>
</div>
<div class="show-table" v-if="setting.view === 'table' && !show.find">
<div class="show-table" v-if="setting.view === 'table' && !showFind">
<el-table
size="mini"
:data="list.filter(res => !setting.excludeR18Films || !containsR18Keywords(res.type))"
:data="filteredList"
ref="filmTable"
height="100%"
:empty-text="statusText"
@row-click="(row) => detailEvent(site, row)"
@@ -97,7 +136,7 @@
prop="name"
label="片名">
</el-table-column>
<el-table-column
<el-table-column v-if="type.name === '最新'"
prop="type"
label="类型"
width="100">
@@ -118,16 +157,16 @@
label="语言"
width="100">
</el-table-column>
<el-table-column
prop="note"
label="备注"
width="120">
</el-table-column>
<el-table-column
<el-table-column v-if="showTableLastColumn"
prop="last"
label="最近更新"
:formatter="dateFormat"
align="left">
align="left"
width="120">
</el-table-column>
<el-table-column
prop="note"
label="备注">
</el-table-column>
<el-table-column
label="操作"
@@ -150,10 +189,10 @@
</infinite-loading>
</el-table>
</div>
<div class="show-table" v-show="show.find">
<div class="show-table" v-if="setting.searchViewMode === 'table' && showFind">
<el-table size="mini"
ref="searchResultTable"
:data="searchContents.filter(res => !setting.excludeR18Films || (res.type !== undefined && !containsR18Keywords(res.type)))"
:data="filteredSearchContents"
height="100%"
:empty-text="statusText"
@filter-change="filterChange"
@@ -179,8 +218,6 @@
</el-table-column>
<el-table-column
prop="type"
:filters="getFilters('type')"
:filter-method="(value, row, column) => { this.currentColumn = column; return value === row.type }"
label="类型"
width="100">
</el-table-column>
@@ -192,8 +229,6 @@
</el-table-column>
<el-table-column
prop="area"
:filters="getFilters('area')"
:filter-method="(value, row, column) => { this.currentColumn = column; return value === row.area }"
label="地区"
width="100">
</el-table-column>
@@ -204,18 +239,17 @@
label="语言"
width="100">
</el-table-column>
<el-table-column
sortable
prop="note"
label="备注"
width="120">
</el-table-column>
<el-table-column key="last"
sortable
<el-table-column v-if="showTableLastColumn"
prop="last"
label="最近更新"
:formatter="dateFormat"
align="left">
align="left"
width="120">
</el-table-column>
<el-table-column
sortable
prop="note"
label="备注">
</el-table-column>
<el-table-column
label="操作"
@@ -231,6 +265,47 @@
</el-table-column>
</el-table>
</div>
<div class="show-picture" v-if="setting.searchViewMode === 'picture' && showFind">
<Waterfall ref="filmSearchWaterfall" :list="filteredSearchContents" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
rowPerView: 4,
},
800: { //当屏幕宽度小于等于800
rowPerView: 3,
},
500: { //当屏幕宽度小于等于500
rowPerView: 2,
}
}"
animationEffect="fadeIn"
backgroundColor="rgba(0, 0, 0, 0)">
<template slot="item" slot-scope="props">
<div class="card" v-show="!setting.excludeR18Films || !containsR18Keywords(props.data.type)">
<div class="img">
<div class="site">
<span>{{props.data.site.name}}</span>
</div>
<img style="width: 100%" :src="props.data.pic" alt="" @load="$refs.filmSearchWaterfall.refresh()" @click="detailEvent(props.data.site, props.data)">
<div class="operate">
<div class="operate-wrap">
<span class="o-play" @click="playEvent(props.data.site, props.data)">播放</span>
<span class="o-star" @click="starEvent(props.data.site, props.data)">收藏</span>
<span class="o-share" @click="shareEvent(props.data.site, props.data)">分享</span>
</div>
</div>
</div>
<div class="name" @click="detailEvent(props.data.site, props.data)">{{props.data.name}}</div>
<div class="info">
<span>{{props.data.area}}</span>
<span>{{props.data.year}}</span>
<span>{{props.data.note}}</span>
<span>{{props.data.type}}</span>
</div>
</div>
</template>
</Waterfall>
</div>
</div>
</div>
</template>
@@ -241,24 +316,24 @@ import zy from '../lib/site/tools'
import Waterfall from 'vue-waterfall-plugin'
import InfiniteLoading from 'vue-infinite-loading'
const { clipboard } = require('electron')
const FILM_DATA_CACHE = {} // key = site.key, value = classList; key = site.key + '@' + type.tid, value = {list, pageCount}
export default {
name: 'film',
data () {
return {
show: {
body: false,
site: false,
class: false,
classList: false,
find: false
},
showFind: false,
showToolbar: false,
showTableLastColumn: false,
sites: [],
site: {},
classList: [],
searchClassList: [],
type: {},
selectedClassName: '最新',
selectedSiteName: '',
selectedClassName: '',
selectedSearchClassNames: [],
pagecount: 0,
recordcount: 0,
list: [],
statusText: ' ',
infiniteId: +new Date(),
@@ -266,11 +341,21 @@ export default {
searchList: [],
searchTxt: '',
searchContents: [],
filteredSearchContents: [],
currentColumn: '',
searchGroup: '',
searchGroups: [],
// 福利片关键词
r18KeyWords: ['伦理', '论理', '倫理', '福利', '激情', '理论', '写真', '情色', '美女', '街拍', '赤足', '性感', '里番']
r18KeyWords: ['伦理', '论理', '倫理', '福利', '激情', '理论', '写真', '情色', '美女', '街拍', '赤足', '性感', '里番'],
filteredList: [],
areas: [],
selectedAreas: [],
sortKeyword: '',
sortKeywords: ['按片名', '按上映年份', '按更新时间'],
selectedYears: { start: 0, end: new Date().getFullYear() },
searchRunning: false,
siteSearchCount: 0,
infiniteHandlerCount: 0
}
},
components: {
@@ -320,6 +405,11 @@ export default {
},
filterSettings () {
return this.$store.getters.getSetting.excludeR18Films // 需要监听的数据
},
searchSites () {
if (this.searchGroup === '站内') return [this.site]
if (this.searchGroup === '全站') return this.sites
return this.sites.filter(site => site.group === this.searchGroup)
}
},
filters: {
@@ -330,7 +420,11 @@ export default {
},
watch: {
view () {
this.changeView()
if (this.view === 'Film') {
this.getAllSites()
if (this.$refs.filmWaterfall) this.$refs.filmWaterfall.resize() // 瀑布插件resize和refresh功能相同只是延时不同
if (this.$refs.filmSearchWaterfall) this.$refs.filmSearchWaterfall.resize()
}
},
searchTxt () {
if (this.searchTxt === '清除历史记录...') {
@@ -341,10 +435,102 @@ export default {
},
filterSettings () {
this.siteClick(this.site.name)
},
list: {
handler (list) {
this.areas = [...new Set(list.map(ele => ele.area))].filter(x => x)
this.refreshFilteredList()
},
deep: true
},
siteSearchCount () {
if (this.siteSearchCount === this.searchSites.length) this.searchRunning = false
},
searchContents: {
handler (list) {
this.areas = [...new Set(list.map(ele => ele.area))].filter(x => x)
this.searchClassList = [...new Set(list.map(ele => ele.type))].filter(x => x)
this.refreshFilteredList()
},
deep: true
},
selectedAreas: {
handler () {
this.infiniteHandlerCount = 0
},
deep: true
},
selectedYears: {
handler () {
this.infiniteHandlerCount = 0
},
deep: true
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
backTop () {
const viewMode = this.showFind ? this.setting.searchViewMode : this.setting.view
if (viewMode === 'picture') {
document.getElementById('film-body').scrollTop = 0
} else {
const table = this.showFind ? this.$refs.searchResultTable : this.$refs.filmTable
table.bodyWrapper.scrollTop = 0
}
},
refreshFilteredList () {
if (!this.showToolbar) {
this.sortKeyword = ''
this.selectedAreas = []
this.selectedSearchClassNames = []
this.selectedYears.start = 0
this.selectedYears.end = new Date().getFullYear()
}
let filteredData = this.showFind ? this.searchContents : this.list
if (this.showFind) filteredData = filteredData.filter(x => (this.selectedSearchClassNames.length === 0) || this.selectedSearchClassNames.includes(x.type))
filteredData = filteredData.filter(x => (this.selectedAreas.length === 0) || this.selectedAreas.includes(x.area))
filteredData = filteredData.filter(res => !this.setting.excludeR18Films || !this.containsR18Keywords(res.type))
filteredData = filteredData.filter(res => res.year >= this.selectedYears.start)
filteredData = filteredData.filter(res => res.year <= this.selectedYears.end)
if (!this.showFind) this.selectedClassName = this.type.name + ' ' + filteredData.length + '/' + this.recordcount
switch (this.sortKeyword) {
case '按上映年份':
filteredData.sort(function (a, b) {
return a.year - b.year
})
break
case '按片名':
filteredData.sort(function (a, b) {
return a.name.localeCompare(b.name, 'zh')
})
break
case '按更新时间':
filteredData.sort(function (a, b) {
return new Date(b.last) - new Date(a.last)
})
break
default:
break
}
if (this.showFind) {
this.filteredSearchContents = filteredData
} else {
this.filteredList = filteredData
}
},
toggleViewMode () {
if (this.showFind) {
this.setting.searchViewMode = this.setting.searchViewMode === 'picture' ? 'table' : 'picture'
setTimeout(() => { if (this.$refs.filmSearchWaterfall) this.$refs.filmSearchWaterfall.refresh() }, 700)
} else {
this.setting.view = this.setting.view === 'picture' ? 'table' : 'picture'
}
setting.find().then(res => {
res.searchViewMode = this.setting.searchViewMode
res.view = this.setting.view
setting.update(res)
})
},
sortByLocaleCompare (a, b) {
return a.localeCompare(b, 'zh')
},
@@ -356,9 +542,8 @@ export default {
return date.split(/\s/)[0]
},
getFilters (column) {
const searchContents = this.searchContents.filter(res => !this.setting.excludeR18Films || (res.type !== undefined && !this.containsR18Keywords(res.type)))
if (column === 'siteName') return [...new Set(searchContents.map(row => row.site.name))].map(e => { return { text: e, value: e } }) // 有方法合并这两行吗?
return [...new Set(searchContents.map(row => row[column]))].map(e => { return { text: e, value: e } })
if (column === 'siteName') return [...new Set(this.filteredSearchContents.map(row => row.site.name))].map(e => { return { text: e, value: e } }) // 有方法合并这两行吗?
return [...new Set(this.filteredSearchContents.map(row => row[column]))].map(e => { return { text: e, value: e } })
},
filterChange (filters) {
// 一次只能一列
@@ -366,7 +551,7 @@ export default {
const otherColumns = this.$refs.searchResultTable.columns.filter(col => col.id !== this.currentColumn.id)
otherColumns.forEach(col => { col.filterable = false })
} else {
const filterLabels = ['源站', '类型', '地区', '语言']
const filterLabels = ['源站', '语言']
const columns = this.$refs.searchResultTable.columns.filter(col => filterLabels.includes(col.label))
columns.forEach(col => { col.filterable = true })
}
@@ -374,28 +559,49 @@ export default {
siteClick (siteName) {
this.list = []
this.site = this.sites.find(x => x.name === siteName)
if (this.searchTxt.length > 0 && this.searchGroup === '站内') {
if (this.searchGroup === '站内' && this.searchTxt) {
this.searchEvent()
return
} else {
this.searchTxt = ''
this.show.find = false
this.classList = []
this.type = {}
}
this.showFind = false
this.classList = []
if (FILM_DATA_CACHE[this.site.key]) {
this.classList = FILM_DATA_CACHE[this.site.key].classList
this.classClick(this.type.name)
} else {
this.getClass().then(res => {
this.infiniteId += 1
this.classClick(this.classList[0].name)
this.classList = res
// cache classList data
FILM_DATA_CACHE[this.site.key] = {
classList: this.classList
}
this.classClick(this.type.name)
})
}
},
classClick (className) {
this.show.classList = false
this.list = []
this.type = this.classList.find(x => x.name === className)
this.getPage().then(res => {
if (res) {
this.infiniteHandlerCount = 0
if (!this.type) {
this.type = this.classList[0]
}
if (this.type.name.endsWith('剧')) this.selectedAreas = []
const cacheKey = this.site.key + '@' + this.type.tid
if (FILM_DATA_CACHE[cacheKey]) {
this.pagecount = FILM_DATA_CACHE[cacheKey].pagecount
this.recordcount = FILM_DATA_CACHE[cacheKey].recordcount
this.list = FILM_DATA_CACHE[cacheKey].list
this.areas = FILM_DATA_CACHE[cacheKey].areas
} else {
zy.page(this.site.key, this.type.tid).then(res => {
this.pagecount = res.pagecount
this.recordcount = res.recordcount
this.infiniteId += 1
}
})
})
}
},
getClass () {
return new Promise((resolve, reject) => {
@@ -416,11 +622,7 @@ export default {
}
}
})
this.classList = allClass
this.show.class = true
this.pagecount = res.pagecount
this.type = this.classList[0]
resolve(true)
resolve(allClass)
}).catch(err => {
reject(err)
})
@@ -433,50 +635,46 @@ export default {
}
return this.r18KeyWords.some(v => name.includes(v))
},
getPage () {
return new Promise((resolve, reject) => {
const key = this.site.key
const type = this.type.tid
zy.page(key, type).then(res => {
this.pagecount = res.pagecount
this.show.body = true
resolve(true)
}).catch(err => {
reject(err)
})
})
},
infiniteHandler ($state) {
const key = this.site.key
const type = this.type.tid
const typeTid = this.type.tid
const page = this.pagecount
console.log(key, type, page, 'infiniteHandler') // TODO: 初次进入会重复请求两次, 导致数据重复, 代码报错.
this.statusText = ' '
if (key && page < 1) { // OK资源前几类硬是去不掉
if (key === undefined || page < 1 || typeTid === undefined) {
$state.complete()
this.statusText = '暂无数据'
return false
}
zy.list(key, page, type).then(res => {
if (res) {
this.pagecount -= 1
const type = Object.prototype.toString.call(res)
if (type === '[object Undefined]') {
$state.complete()
if (this.showToolbar && this.filteredList.length && this.filteredList.length < 10) {
this.infiniteHandlerCount++
}
const interval = this.setting.view === 'picture' ? 1200 : 300
setTimeout(() => {
zy.list(key, page, typeTid).then(res => {
if (res) {
this.pagecount -= 1
const type = Object.prototype.toString.call(res)
if (type === '[object Undefined]') {
$state.complete()
}
if (type === '[object Array]') {
// zy.list 返回的是按时间从旧到新排列, 我门需要翻转为从新到旧
this.list.push(...res.reverse())
}
if (type === '[object Object]') {
this.list.push(res)
}
$state.loaded()
// 更新缓存数据
const cacheKey = this.site.key + '@' + typeTid
FILM_DATA_CACHE[cacheKey] = {
pagecount: this.pagecount,
recordcount: this.recordcount,
list: this.list
}
}
if (type === '[object Array]') {
// zy.list 返回的是按时间从旧到新排列, 我门需要翻转为从新到旧
this.list.push(...res.reverse())
}
if (type === '[object Object]') {
this.list.push(res)
}
$state.loaded()
} else {
$state.complete()
this.statusText = '暂无数据'
}
})
})
}, (this.infiniteHandlerCount <= 1 ? 0 : this.infiniteHandlerCount - 1) * interval)
},
detailEvent (site, e) {
this.detail = {
@@ -524,60 +722,34 @@ export default {
info: e
}
},
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('#')
let downloadUrl = res.name + '\n'
downloadEvent (site, row) {
const key = site.key
const id = row.id
zy.download(key, id).then(res => {
if (res && res.m3u8List) {
const list = res.m3u8List.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
zy.detail(key, id).then(res => {
const list = [...res.m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
this.$message.warning('没有查询到下载链接.')
}
} else {
let m3u8List = []
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
m3u8List = i._t.split('#')
}
}
} else {
m3u8List = dd._t.split('#')
}
let downloadUrl = e.name + '\n'
for (const i of m3u8List) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
})
}
})
},
changeView () {
if (this.view === 'Film') {
this.getAllSites()
if (this.setting.view === 'picture') {
if (this.$refs.filmWaterfall) {
this.$refs.filmWaterfall.refresh()
}
this.getPage().then(() => {
this.infiniteId += 1
})
}
}
},
querySearch (queryString, cb) {
if (this.searchList.length === 0) return
var searchList = this.searchList.slice(0, -1)
var results = queryString ? searchList.filter(this.createFilter(queryString)) : this.searchList
// 调用 callback 返回建议列表的数据
@@ -610,6 +782,9 @@ export default {
this.searchList.push({ id: this.searchList.length + 1, keywords: '清除历史记录...' })
})
},
stopSearchEvent () {
this.searchRunning = false
},
searchEvent () {
const wd = this.searchTxt
if (this.setting.searchGroup !== this.searchGroup) {
@@ -618,71 +793,53 @@ export default {
}
if (!wd) return
this.searchID += 1
var searchSites = []
if (this.searchGroup === '站内') searchSites.push(this.site)
if (this.searchGroup === '全站') searchSites = this.sites
if (!searchSites.length) {
searchSites = this.sites.filter(site => site.group === this.searchGroup)
}
this.searchContents = []
this.pagecount = 0
this.show.find = true
this.show.class = false
this.showFind = true
this.statusText = ' '
if (wd) {
searchSites.forEach(site => {
const id = this.searchID
zy.search(site.key, wd).then(res => {
if (id !== this.searchID) return
const type = Object.prototype.toString.call(res)
if (type === '[object Array]') {
res.forEach(element => {
zy.detail(site.key, element.id).then(detailRes => {
detailRes.site = site
if (id !== this.searchID) return
this.searchContents.push(detailRes)
this.searchContents.sort(function (a, b) {
return a.site.id - b.site.id
})
this.statusText = '暂无数据'
})
})
}
if (type === '[object Object]') {
zy.detail(site.key, res.id).then(detailRes => {
this.searchRunning = true
this.siteSearchCount = 0
this.searchSites.forEach(site => {
const id = this.searchID
zy.search(site.key, wd).then(res => {
if (id !== this.searchID || !this.searchRunning) return
const type = Object.prototype.toString.call(res)
if (type === '[object Array]') {
let count = 0
res.forEach(element => {
zy.detail(site.key, element.id).then(detailRes => {
if (id !== this.searchID || !this.searchRunning) return
detailRes.site = site
if (id !== this.searchID) return
this.searchContents.push(detailRes)
this.searchContents.sort(function (a, b) {
return a.site.id - b.site.id
})
this.statusText = '暂无数据'
}).finally(() => { count++; if (count === res.length) { this.siteSearchCount++; this.statusText = '暂无数据' } })
})
} else if (type === '[object Object]') {
zy.detail(site.key, res.id).then(detailRes => {
if (id !== this.searchID || !this.searchRunning) return
detailRes.site = site
this.searchContents.push(detailRes)
this.searchContents.sort(function (a, b) {
return a.site.id - b.site.id
})
}
})
})
}
}).finally(() => { this.siteSearchCount++; this.statusText = '暂无数据' })
} else if (res === undefined) {
this.siteSearchCount++
this.statusText = '暂无数据'
if (this.searchGroup === '站内') this.$message.info('没有查询到数据!')
}
}).catch(() => { this.siteSearchCount++; if (this.searchGroup === '站内') this.$message.error('本次查询状态异常,未获取到数据!') })
})
},
searchAndRecord () {
this.addSearchRecord()
this.searchEvent()
},
searchChangeEvent () {
if (this.searchTxt.length >= 1) {
this.show.class = false
} else {
this.show.class = true
if (!this.searchTxt.length) {
this.searchContents = []
this.show.find = false
if (this.setting.view === 'picture' && this.$refs.filmWaterfall) {
this.$refs.filmWaterfall.refresh()
} else {
this.getClass().then(res => {
if (res) {
this.infiniteId += 1
}
})
}
this.showFind = false
}
},
getAllSites () {
@@ -712,15 +869,13 @@ export default {
this.getSearchHistory()
},
mounted () {
window.addEventListener('resize', () => {
if (this.$refs.filmWaterfall && this.view === 'Film') {
this.$refs.filmWaterfall.resize()
this.$refs.filmWaterfall.refresh()
setTimeout(() => {
this.$refs.filmWaterfall.refresh()
}, 500)
}
}, false)
addEventListener('resize', () => {
setTimeout(() => {
this.showTableLastColumn = window.outerWidth >= 1200
if (this.$refs.filmWaterfall) this.$refs.filmWaterfall.resize()
if (this.$refs.filmSearchWaterfall) this.$refs.filmSearchWaterfall.resize()
}, 500)
})
}
}
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div class="frame">
<span class="top" @click="frameClickEvent('top')" title="置顶">
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:10px;height:14px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:10px;height:14px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="appState.windowIsOnTop ? '#555555' : '#ffffff'"></path></svg>
</span>
<span class="min" @click="frameClickEvent('min')" title="最小化">
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:8px;height:14px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
@@ -18,10 +18,14 @@
const { remote } = require('electron')
export default {
name: 'frame',
data () {
const win = remote.getCurrentWindow()
return {
isAlwaysOnTop: win.isAlwaysOnTop()
computed: {
appState: {
get () {
return this.$store.getters.getAppState
},
set (val) {
this.SET_APPSTATE(val)
}
}
},
methods: {
@@ -37,8 +41,8 @@ export default {
win.destroy()
}
if (e === 'top') {
this.isAlwaysOnTop = !this.isAlwaysOnTop
win.setAlwaysOnTop(this.isAlwaysOnTop)
this.appState.windowIsOnTop = !this.appState.windowIsOnTop
win.setAlwaysOnTop(this.appState.windowIsOnTop)
}
}
}

View File

@@ -1,14 +1,23 @@
<template>
<div class="listpage" id="history">
<div class="listpage-header" id="history-header">
<el-switch v-model="viewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="list" @change="updateViewMode"></el-switch>
<el-button @click.stop="exportHistory" icon="el-icon-upload2">导出</el-button>
<el-button @click.stop="importHistory" icon="el-icon-download">导入</el-button>
<el-button @click.stop="clearAllHistory" icon="el-icon-delete-solid">清空</el-button>
<el-switch v-model="setting.historyViewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="table" @change="updateViewMode"></el-switch>
<el-button @click.stop="exportHistory" icon="el-icon-upload2" title="导出全部,自动添加扩展名">导出</el-button>
<el-button @click.stop="importHistory" icon="el-icon-download" title="支持同时导入多个文件">导入</el-button>
<el-button @click.stop="removeSelectedItems" icon="el-icon-delete-solid">{{ multipleSelection.length === 0 ? "清空" : "删除所选" }}</el-button>
</div>
<div class="listpage-body" id="history-body">
<div class="show-table" id="history-table" v-show="viewMode === 'list'">
<el-table size="mini" fit height="100%" :data="history" row-key="id" @row-click="detailEvent">
<div class="show-table" id="history-table" v-if="setting.historyViewMode === 'table'">
<el-table size="mini" fit height="100%"
:data="history"
row-key="id"
ref="historyTable"
@select="selectionCellClick"
@selection-change="handleSelectionChange"
@row-click="detailEvent">
<el-table-column
type="selection">
</el-table-column>
<el-table-column
prop="name"
label="片名">
@@ -52,7 +61,7 @@
</el-table-column>
</el-table>
</div>
<div class="show-picture" id="star-picture" v-show="viewMode === 'picture'">
<div class="show-picture" id="star-picture" v-if="setting.historyViewMode === 'picture'">
<Waterfall ref="historyWaterfall" :list="history" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
@@ -112,7 +121,10 @@ export default {
return {
history: [],
sites: [],
viewMode: setting.historyViewMode
shiftDown: false,
selectionBegin: '',
selectionEnd: '',
multipleSelection: []
}
},
components: {
@@ -150,22 +162,57 @@ export default {
set (val) {
this.SET_SHARE(val)
}
},
setting: {
get () {
return this.$store.getters.getSetting
},
set (val) {
this.SET_SETTING(val)
}
}
},
watch: {
view () {
this.getAllhistory()
this.getAllsites()
if (this.$refs.historyWaterfall) {
this.$refs.historyWaterfall.refresh()
if (this.view === 'History') {
this.getAllhistory()
this.getAllsites()
if (this.setting.historyViewMode === 'table') this.showShiftPrompt()
}
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
fmtMSS (s) {
return (s - (s %= 60)) / 60 + (s > 9 ? ':' : ':0') + s
},
selectionCellClick (selection, row) { // 历史id与顺序刚好相反大的反而在前面
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
this.selectionEnd = row.id
const start = this.history.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
const end = this.history.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
const selections = this.history.slice(start, end + 1)
this.$nextTick(() => {
selections.forEach(e => this.$refs.historyTable.toggleRowSelection(e, true))
})
this.selectionBegin = this.selectionEnd = ''
return
}
if (selection.includes(row)) {
this.selectionBegin = row.id
} else {
this.selectionBegin = ''
}
},
handleSelectionChange (rows) {
this.multipleSelection = rows
},
removeSelectedItems () {
if (!this.multipleSelection.length) this.multipleSelection = this.history
this.multipleSelection.forEach(e => history.remove(e.id))
this.getAllhistory()
this.updateDatabase()
},
detailEvent (e) {
this.detail = {
show: true,
@@ -196,36 +243,21 @@ export default {
}
},
downloadEvent (e) {
zy.download(e.site, e.ids).then(res => {
if (res && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
this.$message.warning('没有查询到下载链接.')
const key = e.site
const id = e.ids
zy.download(key, id).then(res => {
if (res && res.m3u8List) {
const list = res.m3u8List.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
var m3u8List = {}
zy.detail(e.site, e.ids).then(res => {
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
m3u8List = i._t.split('#')
}
}
} else {
m3u8List = dd._t.split('#')
}
const list = [...m3u8List]
zy.detail(key, id).then(res => {
const list = [...res.m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
@@ -248,6 +280,7 @@ export default {
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
if (!result.filePath.endsWith('.json')) result.filePath += '.json'
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
}
@@ -275,11 +308,6 @@ export default {
}
})
},
clearAllHistory () {
history.clear().then(res => {
this.history = []
})
},
getAllhistory () {
history.all().then(res => {
this.history = res.reverse()
@@ -303,10 +331,10 @@ export default {
this.$message.warning('删除历史记录失败, 错误信息: ' + err)
})
},
updateDatabase (data) {
updateDatabase () {
history.clear().then(res => {
var id = length
data.forEach(ele => {
this.history.forEach(ele => {
ele.id = id
id -= 1
history.add(ele)
@@ -320,37 +348,44 @@ export default {
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.history.splice(oldIndex, 1)[0]
_this.history.splice(newIndex, 0, currRow)
_this.updateDatabase(_this.history)
_this.updateDatabase()
}
})
},
getViewMode () {
setting.find().then(res => {
this.viewMode = res.historyViewMode
})
},
updateViewMode () {
if (this.setting.historyViewMode === 'table') {
setTimeout(() => { this.rowDrop() }, 100)
this.showShiftPrompt()
} else {
setTimeout(() => { if (this.$refs.historyWaterfall) this.$refs.historyWaterfall.refresh() }, 700)
}
setting.find().then(res => {
res.historyViewMode = this.viewMode
res.historyViewMode = this.setting.historyViewMode
setting.update(res)
})
},
showShiftPrompt () {
if (this.setting.shiftTooltipLimitTimes === undefined) this.setting.shiftTooltipLimitTimes = 5
if (this.setting.shiftTooltipLimitTimes) {
this.$message.info('多选时支持shift快捷键')
this.setting.shiftTooltipLimitTimes--
setting.find().then(res => {
res.shiftTooltipLimitTimes = this.setting.shiftTooltipLimitTimes
setting.update(res)
})
}
}
},
mounted () {
this.rowDrop()
window.addEventListener('resize', () => {
if (this.$refs.historyWaterfall && this.view === 'History') {
this.$refs.historyWaterfall.resize()
this.$refs.historyWaterfall.refresh()
setTimeout(() => {
this.$refs.historyWaterfall.refresh()
}, 500)
}
}, false)
if (this.setting.historyViewMode === 'table') setTimeout(() => { this.rowDrop() }, 100)
addEventListener('keydown', code => { if (code.keyCode === 16) this.shiftDown = true })
addEventListener('keyup', code => { if (code.keyCode === 16) this.shiftDown = false })
addEventListener('resize', () => {
setTimeout(() => { if (this.$refs.historyWaterfall) this.$refs.historyWaterfall.resize() }, 500)
})
},
created () {
this.getAllhistory()
this.getViewMode()
}
}
</script>

View File

@@ -1,17 +1,18 @@
<template>
<div class="listpage" id="iptv">
<div class="listpage-header" id="iptv-header" v-show="!enableBatchEdit">
<el-switch v-model="enableBatchEdit" active-text="批处理分组"></el-switch>
<el-button @click.stop="exportChannels" icon="el-icon-upload2" >导出</el-button>
<el-button @click.stop="importChannels" icon="el-icon-download">导入</el-button>
<el-button @click="checkAllChannels" icon="el-icon-refresh" :loading="checkAllChannelsLoading">检测{{ this.checkAllChannelsLoading ? this.checkProgress + '/' + this.iptvList.length : '' }}</el-button>
<el-switch v-model="enableBatchEdit" active-text="批处理及频道调整"></el-switch>
<el-button @click.stop="exportChannels" icon="el-icon-upload2" title="导出m3u时必须手动添加扩展名要保存频道配置信息请选择json格式">导出</el-button>
<el-button @click.stop="importChannels" icon="el-icon-download" title='支持同时导入多个文件,导入m3u时网址可带参数、含有"#"号时自动分割'>导入</el-button>
<el-button @click="checkAllChannels" icon="el-icon-refresh" :loading="checkAllChannelsLoading" title="可在后台运行">检测{{ this.checkAllChannelsLoading ? this.checkProgress + '/' + this.iptvList.length : '' }}</el-button>
<el-button @click.stop="resetChannelsEvent" icon="el-icon-refresh-left">重置</el-button>
</div>
<div class="listpage-header" id="iptv-header" v-show="enableBatchEdit">
<el-switch v-model="enableBatchEdit" active-text="批处理分组"></el-switch>
<el-input placeholder="新组名" v-model="batchGroupName"></el-input>
<el-switch v-model="enableBatchEdit" active-text="批处理及频道调整"></el-switch>
<el-input placeholder="新组名/新频道名" v-model="inputContent"></el-input>
<el-switch v-model="batchIsActive" active-text="启用"></el-switch>
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit">保存</el-button>
<el-button type="primary" icon="el-icon-edit" @click.stop="saveBatchEdit" title="输入框组名为空时仅保存开关状态">保存分组与开关状态</el-button>
<el-button type="primary" icon="el-icon-film" @click.stop="mergeChannel" title="勾选单个时可重命名频道">{{ this.multipleSelection.length === 1 ? '频道重命名' : '频道合并' }}</el-button>
<el-button @click.stop="removeSelectedChannels" icon="el-icon-delete-solid">删除</el-button>
</div>
<div class="listpage-body" id="iptv-table">
@@ -20,10 +21,13 @@
ref="iptvTable"
size="mini" fit height="100%" row-key="id"
:data="filteredTableData"
@row-click="playEvent"
lazy
:load="(row, treeNode, resolve) => resolve(row.channels)"
:tree-props="{hasChildren: 'hasChildren'}"
@expand-change="expandChange"
@select="selectionCellClick"
@selection-change="handleSelectionChange"
@sort-change="handleSortChange">>
@sort-change="handleSortChange">
<el-table-column
type="selection"
v-if="enableBatchEdit">
@@ -31,6 +35,7 @@
<el-table-column
default-sort="ascending"
prop="name"
:class-name="enableBatchEdit ? 'disableExpand' : ''"
label="频道名">
<template #header>
<el-input
@@ -85,12 +90,13 @@
align="right"
:width="200">
<template #header>
<span>频道数:{{ iptvList.length }}</span>
<span>{{ enableBatchEdit ? `频道数:${channelList.length}` : `资源总数:${iptvList.length}` }}</span>
</template>
<template slot-scope="scope">
<el-button @click.stop="moveToTopEvent(scope.row)" type="text">置顶</el-button>
<el-button @click.stop="moveToTopEvent(scope.row)" type="text" v-if="scope.row.channels">置顶</el-button>
<el-button @click.stop="playEvent(scope.row)" type="text">播放</el-button>
<!-- 检测时先强制批量检测一遍,如果不强制直接单个检测时第一次不会显示“检测中”-->
<el-button size="mini" v-if="iptvList.every(channel => channel.status)" v-show="!checkAllChannelsLoading" @click.stop="checkSingleChannel(scope.row)" type="text">检测</el-button>
<el-button size="mini" v-if="iptvList.every(channel => channel.status)" v-show="!checkAllChannelsLoading" @click.stop="checkChannel(scope.row)" type="text">检测</el-button>
<el-button @click.stop="removeEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
@@ -101,7 +107,7 @@
</template>
<script>
import { mapMutations } from 'vuex'
import { iptv, iptvSearch } from '../lib/dexie'
import { iptv, channelList, setting } from '../lib/dexie'
import { iptv as defaultChannels } from '../lib/dexie/initData'
import zy from '../lib/site/tools'
import { remote } from 'electron'
@@ -112,21 +118,20 @@ export default {
data () {
return {
iptvList: [],
channelList: [],
searchTxt: '',
searchRecordList: [],
enableBatchEdit: false,
batchGroupName: '',
inputContent: '',
batchIsActive: true,
shiftDown: false,
selectionBegin: '',
selectionEnd: '',
multipleSelection: [],
expandedRows: [],
checkAllChannelsLoading: false,
checkProgress: 0,
stopFlag: false,
show: {
search: false
}
sortableTable: ''
}
},
computed: {
@@ -138,8 +143,13 @@ export default {
this.SET_VIEW(val)
}
},
setting () {
return this.$store.getters.getSetting
setting: {
get () {
return this.$store.getters.getSetting
},
set (val) {
this.SET_SETTING(val)
}
},
video: {
get () {
@@ -151,13 +161,13 @@ export default {
},
filteredTableData () {
if (this.searchTxt) {
return this.iptvList.filter(x => x.name.toLowerCase().includes(this.searchTxt.toLowerCase()))
return this.channelList.filter(x => x.name.toLowerCase().includes(this.searchTxt.toLowerCase()))
} else {
return this.iptvList
return this.channelList
}
},
getFilters () {
const groups = [...new Set(this.iptvList.map(iptv => iptv.group))]
const groups = [...new Set(this.channelList.map(iptv => iptv.group))]
var filters = []
groups.forEach(g => {
var doc = {
@@ -170,29 +180,42 @@ export default {
}
},
watch: {
view () {
if (this.view === 'IPTV') {
this.getChannels()
}
},
enableBatchEdit () {
if (this.checkAllChannelsLoading) {
this.$message.info('正在检测, 请勿操作.')
this.enableBatchEdit = false
return
}
if (this.enableBatchEdit) {
if (this.setting.shiftTooltipLimitTimes === undefined) this.setting.shiftTooltipLimitTimes = 5
if (this.setting.shiftTooltipLimitTimes) {
this.$message.info('多选时支持shift快捷键')
this.setting.shiftTooltipLimitTimes--
setting.find().then(res => {
res.shiftTooltipLimitTimes = this.setting.shiftTooltipLimitTimes
setting.update(res)
})
}
this.$nextTick(() => {
this.expandedRows.forEach(e => this.$refs.iptvTable.toggleRowExpansion(e, false))
})
this.rowDrop()
} else {
this.sortableTable.destroy()
}
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
sortByLocaleCompare (a, b) {
return a.localeCompare(b, 'zh')
},
selectionCellClick (selection, row) {
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
this.selectionEnd = row.id
const start = Math.min(this.selectionBegin, this.selectionEnd) - 1
const end = Math.max(this.selectionBegin, this.selectionEnd)
const selections = this.iptvList.slice(start, end)
const start = this.channelList.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
const end = this.channelList.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
const selections = this.channelList.slice(start, end + 1) // 多选时强制不让展开
this.$nextTick(() => {
selections.forEach(e => this.$refs.iptvTable.toggleRowSelection(e, true))
})
@@ -205,27 +228,56 @@ export default {
this.selectionBegin = ''
}
},
expandChange (row, expanded) {
const index = this.expandedRows.indexOf(row)
if (expanded && index === -1) {
this.expandedRows.push(row)
} else if (!expanded && index !== -1) {
this.expandedRows.splice(index, 1)
}
},
handleSelectionChange (rows) {
this.multipleSelection = rows
},
handleSortChange (column, prop, order) {
if (this.checkAllChannelsLoading) {
this.$message.info('正在检测, 请勿操作.')
this.enableBatchEdit = false
return
}
this.updateDatabase()
},
saveBatchEdit () {
this.multipleSelection.forEach(ele => {
if (this.batchGroupName) {
ele.group = this.batchGroupName
if (this.inputContent) {
ele.group = this.inputContent
}
ele.isActive = this.batchIsActive
})
this.updateDatabase()
},
mergeChannel () {
if (this.inputContent && this.multipleSelection.length) {
var channels = []
const id = this.multipleSelection[0].id
this.multipleSelection.forEach(ele => {
channels = channels.concat(ele.channels)
channels.forEach(e => { e.channelID = id })
channelList.remove(ele.id)
})
const mergeChannel = { id: id, name: this.inputContent, isActive: channels.some(c => c.isActive), group: this.determineGroup(this.inputContent), hasChildren: channels.length > 1, channels: channels }
channelList.add(mergeChannel)
this.getChannelList()
this.updateDatabase()
}
},
playEvent (e) {
this.video = { iptv: { name: e.name, url: e.url, id: e.id } }
if (e.url) {
this.video = { iptv: e }
} else {
const prefer = e.prefer ? e.channels.find(c => c.id === e.prefer) : e.channels.filter(c => c.isActive)[0]
if (!prefer) return
this.video = { iptv: prefer }
}
this.view = 'Play'
},
containsearchTxt (i) {
@@ -235,18 +287,30 @@ export default {
return true
}
},
removeEvent (e) {
removeEvent (row) {
if (this.checkAllChannelsLoading) {
this.$message.info('正在检测, 请勿操作.')
return false
}
iptv.remove(e.id).then(res => {
this.getChannels()
}).catch(err => {
try {
if (row.url) { // tree树形控件节点一旦展开就不再重新加载节点数据
const ele = this.channelList.find(e => e.id === row.channelID)
ele.channels.splice(ele.channels.findIndex(e => e.id === row.id), 1)
channelList.remove(row.channelID)
if (ele.channels.length) {
if (ele.channels.length === 1) ele.hasChildren = false
channelList.add(ele)
this.$set(this.$refs.iptvTable.store.states.lazyTreeNodeMap, ele.id, ele.channels)
}
} else {
channelList.remove(row.id)
}
this.getChannelList()
} catch (err) {
this.$message.warning('删除频道失败, 错误信息: ' + err)
})
}
},
exportChannels () {
exportChannels () { // 导出导入m3u为iptvListjson为channelList
const options = {
filters: [
{ name: 'm3u file', extensions: ['m3u'] },
@@ -263,7 +327,8 @@ export default {
fs.writeFileSync(result.filePath, writer.toString())
this.$message.success('已保存成功')
} else {
const arr = [...this.iptvList]
if (!result.filePath.endsWith('.json')) result.filePath += '.json'
const arr = [...this.channelList] // 要保存channelList必须选json
const str = JSON.stringify(arr, null, 2)
fs.writeFileSync(result.filePath, str)
this.$message.success('已保存成功')
@@ -287,65 +352,64 @@ export default {
}
remote.dialog.showOpenDialog(options).then(result => {
if (!result.canceled) {
var docs = this.iptvList
var id = docs.length + 1
result.filePaths.forEach(file => {
if (file.endsWith('m3u') || file.endsWith('m3u8')) {
const docs = []
const URL = require('url')
let id = this.channelList.length ? this.channelList.slice(-1)[0].id + 1 : 1
const parser = require('iptv-playlist-parser')
const playlist = fs.readFileSync(file, { encoding: 'utf-8' })
const result = parser.parse(playlist)
result.items.forEach(ele => {
if (ele.name && ele.url && ele.url.endsWith('.m3u8')) {
var doc = {
id: id,
name: ele.name,
url: ele.url,
isActive: true,
group: this.determineGroup(ele.name)
const urls = ele.url.split('#').filter(e => e.startsWith('http')) // 网址带#时自动分割
urls.forEach(url => {
if (ele.name && url && new URL.URL(url).pathname.endsWith('.m3u8')) { // 网址可能带参数
var doc = {
id: id,
name: ele.name,
url: url,
isActive: true
}
id += 1
docs.push(doc)
}
id += 1
docs.push(doc)
}
})
})
// 获取url不重复的列表
const uniqueList = [...new Map(docs.map(item => [item.url, item])).values()]
iptv.clear().then(res => {
iptv.bulkAdd(uniqueList).then(e => { // 支持导入同名频道,群里反馈
this.updateChannelList()
})
})
} else {
// Import Json file
var str = fs.readFileSync(file)
const json = JSON.parse(str)
json.forEach(ele => {
if (ele.name && ele.url && ele.url.endsWith('.m3u8')) {
var doc = {
id: id,
name: ele.name,
url: ele.url,
isActive: ele.isActive === undefined ? true : ele.isActive,
group: this.determineGroup(ele.name)
}
id += 1
docs.push(doc)
const importedList = JSON.parse(fs.readFileSync(file))
importedList.forEach(ele => {
const commonEle = this.channelList.find(e => e.name === ele.name)
if (commonEle) {
const urls = commonEle.channels.map(c => c.url)
const channels = ele.channels.filter(e => !urls.includes(e.url))
commonEle.channels = commonEle.channels.concat(channels)
} else {
ele.id = this.channelList.length ? this.channelList.slice(-1)[0].id + 1 : 1
this.channelList.push(ele)
}
})
this.updateDatabase()
}
})
// 获取name不重复的列表
// const uniqueList = [...new Map(docs.map(item => [item.name, item])).values()]
iptv.clear().then(res => {
iptv.bulkAdd(docs).then(e => { // 支持导入同名频道,群里反馈
this.getChannels()
this.$message.success('导入成功')
})
})
this.$message.success('导入成功')
}
})
},
determineGroup (name) {
if (name.toLowerCase().includes('cctv') && (name.includes('蓝光') || name.includes('高清'))) {
return '央视高清'
} else if (name.toLowerCase().includes('cctv')) {
if (name.toLowerCase().includes('cctv') || name.toLowerCase().includes('cgtn')) {
return '央视'
} else if (name.includes('香港') || name.includes('澳门') || name.includes('台湾') || name.includes('凤凰') || name.includes('翡翠')) {
return '港澳台'
} else if (name.includes('卫视')) {
return '卫视'
} else if (name.includes('香港') || name.includes('澳门') || name.includes('台湾') || name.includes('凤凰')) {
return '港澳台'
} else if (name.includes('高清') || name.includes('蓝光') || name.includes('1080P')) {
return '高清'
} else {
@@ -358,72 +422,113 @@ export default {
this.$message.info('部分检测还未完全终止, 请稍等...')
return
}
iptv.clear().then(iptv.bulkAdd(defaultChannels).then(this.getChannels()))
this.channelList = []
this.iptvList = []
iptv.clear().then(iptv.bulkAdd(defaultChannels).then(this.updateChannelList()))
},
removeSelectedChannels () {
this.multipleSelection.forEach(e => iptv.remove(e.id))
this.multipleSelection.forEach(e => channelList.remove(e.id))
this.$refs.iptvTable.clearFilter()
this.getChannels()
this.getChannelList()
this.updateDatabase()
this.enableBatchEdit = false
},
getChannels () {
updateChannelList () {
iptv.all().then(res => {
res = res.filter(o => !this.iptvList.find(e => o.url === e.url))
const resClone = JSON.parse(JSON.stringify(res))
const uniqueChannelName = {}
for (var i = 0; i < resClone.length; i++) {
var channelName = resClone[i].name.trim().replace(/[- ]?(1080p|蓝光|超清|高清|标清|hd|cq|4k)(\d{1,2})?$/i, '')
if (channelName.match(/cctv/i)) channelName = channelName.replace('-', '')
if (Object.keys(uniqueChannelName).some(name => channelName.match(new RegExp(`${name}(1080p|4k|(?!\\d))`, 'i')))) continue // 避免重复
const matchRule = new RegExp(`${channelName}(1080p|4k|(?!\\d))`, 'i')
for (var j = i; j < resClone.length; j++) {
if (resClone[j].name.match(/cctv/i)) {
resClone[j].name = resClone[j].name.replace('-', '')
}
if (matchRule.test(resClone[j].name)) {
if (uniqueChannelName[channelName]) {
!uniqueChannelName[channelName].includes(res[j]) && uniqueChannelName[channelName].push(res[j])
} else {
uniqueChannelName[channelName] = [res[j]]
}
}
}
}
res.forEach(ele => {
if (ele.isActive === undefined) {
ele.isActive = true
}
})
this.iptvList = res
})
},
getSearchRecordList () {
iptvSearch.all().then(res => {
this.searchRecordList = res.reverse()
})
},
clearSearch () {
iptvSearch.clear().then(res => {
this.getSearchRecordList()
})
},
searchEvent (wd) {
this.searchTxt = wd
this.show.search = false
if (wd) {
iptvSearch.find({ keywords: wd }).then(res => {
if (!res) {
iptvSearch.add({ keywords: wd })
Object.keys(uniqueChannelName).forEach(k => {
const ele = this.channelList.find(e => e.name === k)
if (ele) {
ele.channels = ele.channels.concat(uniqueChannelName[k])
delete uniqueChannelName[k]
}
this.getSearchRecordList()
})
}
if (Object.keys(uniqueChannelName).length) {
let id = this.channelList.length ? this.channelList.slice(-1)[0].id + 1 : 1
const channelList = Object.keys(uniqueChannelName).map(e => { return { id: id++, name: e, isActive: uniqueChannelName[e].some(c => c.isActive), group: this.determineGroup(e), hasChildren: uniqueChannelName[e].length > 1, channels: uniqueChannelName[e] } })
this.channelList = this.channelList.concat(channelList)
}
this.updateDatabase()
iptv.clear() // iptv默认清空状态
})
},
moveToTopEvent (i) {
async getChannelList () {
await channelList.all().then(res => {
this.channelList = res
this.getIptvList()
})
},
getIptvList () {
this.iptvList = this.channelList.reduce((result, item) => { item.channels.forEach(e => { e.channelID = item.id }); return result.concat(item.channels) }, [])
},
moveToTopEvent (row) {
if (this.checkAllChannelsLoading) {
this.$message.info('正在检测, 请勿操作.')
return false
}
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.channelList.sort(function (x, y) { return (x.name === i.name && x.url === i.url) ? -1 : (y.name === i.name && y.url === i.url) ? 1 : 0 })
if (row.channels) {
this.channelList.splice(this.channelList.findIndex(e => e.id === row.id), 1)
this.channelList.unshift(row)
this.updateDatabase()
}
},
syncTableData () {
if (this.$refs.iptvTable.tableData) {
this.iptvList = this.$refs.iptvTable.tableData
if (this.$refs.iptvTable.tableData && this.$refs.iptvTable.tableData.length === this.channelList.length) {
this.channelList = this.$refs.iptvTable.tableData
}
},
updateDatabase () {
this.syncTableData()
iptv.clear().then(res => {
this.resetId(this.iptvList)
iptv.bulkAdd(this.iptvList)
Object.values(this.$refs.iptvTable.store.states.treeData).forEach(e => { e.loaded = false })
channelList.clear().then(res => {
this.resetId(this.channelList)
channelList.bulkAdd(this.channelList)
this.getChannelList()
})
},
resetId (inArray) {
resetId (channelList) {
var id = 1
inArray.forEach(ele => {
channelList.forEach(ele => {
ele.id = id
id += 1
ele.channels.forEach(e => {
e.channelID = ele.id
const embedChannelID = ele.id + '_'
const prefer = ele.prefer ? ele.channels.find(e => e.id === ele.prefer) : ''
ele.channels.forEach((e, index) => { e.id = embedChannelID + index }) // 为避免混杂给内置iptv重起id
if (prefer) ele.prefer = prefer.id
})
if (ele.channels.length === 1) {
ele.hasChildren = false
} else {
ele.hasChildren = true
}
})
},
rowDrop () {
@@ -433,33 +538,45 @@ export default {
}
const tbody = document.getElementById('iptv-table').querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
this.sortableTable = new Sortable(tbody, {
filter: '.el-table__row--level-1', // 禁止children拖动
onEnd ({ newIndex, oldIndex }) {
const currRow = _this.iptvList.splice(oldIndex, 1)[0]
_this.iptvList.splice(newIndex, 0, currRow)
const currRow = _this.channelList.splice(oldIndex, 1)[0]
_this.channelList.splice(newIndex, 0, currRow)
_this.updateDatabase()
}
})
},
isActiveChangeEvent (row) {
iptv.remove(row.id)
iptv.add(row)
if (row.url) {
const ele = this.channelList.find(e => e.id === row.channelID)
ele.isActive = ele.channels.some(e => e.isActive)
channelList.remove(row.channelID)
channelList.add(ele)
} else {
if (row.channels.length === 1) row.channels[0].isActive = row.isActive
channelList.remove(row.id)
channelList.add(row)
}
},
async checkAllChannels () {
if (this.checkAllChannelsLoading) return
this.checkAllChannelsLoading = true
this.stopFlag = false
this.checkProgress = 0
this.channelList.filter(e => e.channels.length).forEach(e => { e.status = ' '; e.hasCheckedNum = 0 })
const uncheckedList = this.iptvList.filter(e => e.status === undefined || e.status === ' ') // 未检测过的优先
const other = this.iptvList.filter(e => !uncheckedList.includes(e))
await this.checkChannelList(uncheckedList)
await this.checkChannelList(other).then(res => {
await this.checkChannelsBySite(uncheckedList)
await this.checkChannelsBySite(other).then(res => {
this.checkAllChannelsLoading = false
this.getChannels()
this.getChannelList()
if (!this.stopFlag) this.$message.success('直播频道批量检测已完成!')
})
},
async checkChannelList (channelList) {
async checkChannelsBySite (channels) {
var siteList = {}
channelList.forEach(channel => {
channels.forEach(channel => {
const site = channel.url.split('/')[2]
if (siteList[site]) {
siteList[site].push(channel)
@@ -475,33 +592,56 @@ export default {
await this.checkSingleChannel(c)
}
},
async checkSingleChannel (row) {
row.status = ' '
async checkSingleChannel (channel) {
if (this.setting.allowPassWhenIptvCheck && !channel.isActive) {
this.checkProgress += 1
return
}
channel.status = ' '
const ele = this.channelList.find(e => e.id === channel.channelID)
if (this.stopFlag) {
this.checkProgress += 1
return row.status
return channel.status
}
const flag = await zy.checkChannel(row.url)
const flag = await zy.checkChannel(channel.url)
this.checkProgress += 1
ele.hasCheckedNum++
if (flag) {
row.status = '可用'
channel.status = '可用'
} else {
row.status = '失效'
row.isActive = false
channel.status = '失效'
channel.isActive = false
if (this.setting.autocleanWhenIptvCheck) {
ele.channels.splice(ele.channels.findIndex(e => e.id === channel.id), 1)
ele.hasCheckedNum--
}
}
if (ele.hasCheckedNum === ele.channels.length) {
ele.status = ele.channels.some(channel => channel.status === '可用') ? '可用' : '失效'
if (ele.status === '失效') ele.isActive = false
channelList.remove(channel.channelID)
if (ele.channels.length === 1) ele.hasChildren = false
if (ele.channels.length) channelList.add(ele)
}
return channel.status
},
async checkChannel (row) {
if (row.channels) {
row.status = ' '
row.hasCheckedNum = 0
row.channels.forEach(e => this.checkSingleChannel(e))
} else {
this.checkSingleChannel(row)
}
iptv.remove(row.id)
iptv.add(row)
return row.status
}
},
mounted () {
this.rowDrop()
addEventListener('keydown', code => { if (code.keyCode === 16) this.shiftDown = true })
addEventListener('keyup', code => { if (code.keyCode === 16) this.shiftDown = false })
},
created () {
this.getChannels()
this.getSearchRecordList()
async created () {
await this.getChannelList()
if (!this.channelList.length) this.resetChannelsEvent()
}
}
</script>

View File

@@ -98,10 +98,39 @@
<circle cx="12" cy="12" r="10"></circle>
</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>
<span class="timespanSwitch" v-if="right.list.length > 1" title="跳过片头片尾,建议优先通过快捷键设置,更便捷更精准">
<el-switch v-model="state.showTimespanSetting" active-text="手动跳略时长"></el-switch>
</span>
<span class="timespan" v-if="state.showTimespanSetting">
<label>片头</label>
<input type="number" v-model="startPosition.min" style="width:45px" min="00" max="59" placeholder="00" required>
<label>:</label>
<input type="number" v-model="startPosition.sec" style="width:45px" min="00" max="59" placeholder="00" required>
<span></span>
<label>片尾</label>
<input type="number" v-model="endPosition.min" style="width:45px" min="00" max="59" placeholder="00" required>
<label>:</label>
<input type="number" v-model="endPosition.sec" style="width:45px" min="00" max="59" placeholder="00" required>
<span></span>
<input type="button" value="确定" @click="setProgressDotByInput">
<span></span>
<input type="button" value="重置" @click="() => { startPosition.min = startPosition.sec = endPosition.min = endPosition.sec = '00'; this.clearPosition() }">
</span>
<span class="last-tip" v-if="!video.key && right.history.length > 0" @click="historyItemEvent(right.history[0])">
上次播放到:{{right.history[0].site}}{{right.history[0].name}} {{right.history[0].index+1}} {{fmtMSS(right.history[0].time.toFixed(0))}}/{{fmtMSS(right.history[0].duration.toFixed(0))}}</span>
</div>
<div class="more" v-if="video.iptv" :key="Boolean(video.iptv)">
<span class="zy-svg" @click="otherEvent" v-if="right.otherChannels.length">
<span class="zy-svg" @click="state.showChannelList = !state.showChannelList">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="dashboardIconTitle">
<title id="dashboardIconTitle">频道列表</title>
<rect width="20" height="20" x="2" y="2"></rect>
<path d="M11 7L17 7M11 12L17 12M11 17L17 17"></path>
<line x1="7" y1="7" x2="7" y2="7"></line>
<line x1="7" y1="12" x2="7" y2="12"></line>
<line x1="7" y1="17" x2="7" y2="17"></line>
</svg>
</span>
<span class="zy-svg" @click="otherEvent">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="coloursIconTitle">
<title id="coloursIconTitle">换源</title>
<circle cx="12" cy="9" r="5"></circle>
@@ -137,7 +166,7 @@
<span class="list-top-title" v-if="right.type === 'history'">历史记录</span>
<span class="list-top-title" v-if="right.type === 'shortcut'">快捷键指南{{ this.video.iptv ? '(直播时部分功能不可用)' : '' }}</span>
<span class="list-top-title" v-if="right.type === 'other'">同组其他源的视频</span>
<span class="list-top-title" v-if="right.type === 'otherChannels'">该频道其它</span>
<span class="list-top-title" v-if="right.type === 'sources'">该频道可用</span>
<span class="list-top-close zy-svg" @click="closeListEvent">
<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>
@@ -163,26 +192,60 @@
<li v-if="right.other.length === 0">无数据</li>
<li @click="otherItemEvent(m)" v-for="(m, n) in right.other" :key="n"><span class="title">{{m.name}} - [{{m.site.name}}]</span></li>
</ul>
<ul v-if="right.type === 'otherChannels'" class="list-other" v-on-clickaway="closeListEvent">
<li v-if="right.otherChannels.length === 0">无数据</li>
<li @click="playChannel(channel)" v-for="(channel, index) in right.otherChannels" :key="index"><span class="title">{{channel.name}}</span></li>
<ul v-if="right.type === 'sources'" class="list-channels" v-on-clickaway="closeListEvent">
<li v-if="right.sources.length === 0">当前频道已关闭</li>
<li v-for="(channel, index) in right.sources" :key="index">
<span @click="playChannel(channel)" class="title">{{ channel.id === video.iptv.id ? channel.name + '[当前]' : channel.name }}</span>
<span @click="disableChannel(channel)" class="btn" title="关闭频道">隐藏</span>
</li>
</ul>
</div>
</div>
</transition>
<transition name="slideX">
<div v-if="state.showChannelList" class="list" v-on-clickaway="closeListEvent">
<div class="list-top">
<span class="list-top-title">频道列表</span>
<span class="list-top-close zy-svg" @click="state.showChannelList = false">
<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="list-body zy-scroll" :style="{overflowY:scroll? 'auto' : 'hidden',paddingRight: scroll ? '0': '5px' }" @mouseenter="scroll = true" @mouseleave="scroll = false">
<el-input
clearable
size="small" title="支持按拼音首字母搜索"
v-model.trim="searchTxt"
placeholder="搜索">
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
<el-tree ref="channelTree"
:data="channelTree"
:props="defaultProps"
accordion
:filter-node-method="filterNode"
@node-click="handleNodeClick">
</el-tree>
</div>
</div>
</transition>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { star, history, setting, shortcut, mini, iptv, sites } from '../lib/dexie'
import { star, history, setting, shortcut, mini, channelList, sites } from '../lib/dexie'
import zy from '../lib/site/tools'
import Player from 'xgplayer'
import Hls from 'xgplayer-hls.js'
import HlsJsPlayer from 'xgplayer-hls.js'
import mt from 'mousetrap'
import { directive as onClickaway } from 'vue-clickaway'
import { exec, execFile } from 'child_process'
const { remote, ipcRenderer, clipboard } = require('electron')
const { remote, clipboard } = require('electron')
const win = remote.getCurrentWindow()
const PinyinMatch = require('pinyin-match')
const VIDEO_DETAIL_CACHE = {}
@@ -238,7 +301,7 @@ export default {
history: [],
shortcut: [],
other: [],
otherChannels: [],
sources: [],
currentTime: 0
},
config: {
@@ -260,11 +323,18 @@ export default {
videoStop: true,
showList: true,
showHistory: true,
videoTitle: true
quitMiniMode: true,
videoTitle: true,
airplay: true,
closeVideoTouch: true,
ignores: ['cssFullscreen', 'replay'],
preloadTime: 300
},
state: {
showList: false,
showHistory: false
showHistory: false,
showChannelList: false,
showTimespanSetting: false
},
name: '',
length: 0,
@@ -272,8 +342,20 @@ export default {
scroll: false,
isStar: false,
isTop: false,
mini: {},
iptvList: []
miniMode: false,
mainWindowBounds: {},
searchTxt: '',
channelList: [],
channelTree: [],
isLive: false,
defaultProps: {
label: 'label',
children: 'children'
},
startPosition: { min: '00', sec: '00' }, // 对应调略输入框
endPosition: { min: '00', sec: '00' },
skipendStatus: false, // 是否跳过了片尾
currentShortcutList: []
}
},
filters: {
@@ -322,14 +404,33 @@ export default {
this.SET_SHARE(val)
}
},
setting () {
return this.$store.getters.getSetting
appState: {
get () {
return this.$store.getters.getAppState
},
set (val) {
this.SET_APPSTATE(val)
}
},
setting: {
get () {
return this.$store.getters.getSetting
},
set (val) {
this.SET_SETTING(val)
}
}
},
watch: {
view () {
this.right.show = false
this.right.type = ''
if (this.view === 'Play') {
this.right.show = false
this.right.type = ''
this.getChannelList()
if (this.video.key === '' && !this.isLive) {
this.state.showChannelList = true
}
}
},
video: {
handler () {
@@ -353,12 +454,51 @@ export default {
} else {
span.innerText = `${this.name}`
}
},
searchTxt () {
this.$refs.channelTree.filter(this.searchTxt)
},
startPosition: {
handler (time) {
this.leadingZero(time)
},
deep: true
},
endPosition: {
handler (time) {
this.leadingZero(time)
},
deep: true
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_APPSTATE']),
fmtMSS (s) {
return (s - (s %= 60)) / 60 + (s > 9 ? ':' : ':0') + s
},
leadingZero (time) { // 格式化单个调略输入框
Object.keys(time).forEach(key => {
if (time[key] > 59 || time[key] < 0) {
time[key] = '00'
} else if (time[key].length > 2) {
time[key] = '' + parseInt(time[key])
} else if (time[key] < 10 && time[key].length === 1) {
time[key] = '0' + time[key]
}
})
},
handleNodeClick (node) {
if (node.channel) {
this.playChannel(node.channel)
}
},
filterNode (value, data) {
if (!value) return true
return PinyinMatch.match(data.label, value)
},
async getUrls () {
if (this.video.key === '') {
if (!this.video.iptv) this.state.showChannelList = true
return false
}
this.name = ''
@@ -374,78 +514,108 @@ export default {
// 是直播源,直接播放
this.playChannel(this.video.iptv)
} else {
const index = this.video.info.index | 0
this.state.showChannelList = false
const index = this.video.info.index || 0
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
const key = this.video.key + '@' + this.video.info.id
var time = this.video.info.time
if (!time) {
// 如果video.info.time没有设定的话从历史中读取时间进度
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
if (db) {
if (db.index === index) {
time = db.time
}
this.xg.removeAllProgressDot()
this.startPosition = this.endPosition = { min: '00', sec: '00' }
if (db) {
if (!time && db.index === index) { // 如果video.info.time没有设定的话从历史中读取时间进度
time = db.time
}
if (!VIDEO_DETAIL_CACHE[key]) VIDEO_DETAIL_CACHE[key] = {}
if (db.startPosition) { // 数据库保存的时长通过快捷键设置时可能为小数, this.startPosition为object对应输入框分秒转化到数据库后肯定为整数
VIDEO_DETAIL_CACHE[key].startPosition = db.startPosition
this.startPosition = { min: '' + parseInt(db.startPosition / 60), sec: '' + parseInt(db.startPosition % 60) }
}
if (db.endPosition) {
VIDEO_DETAIL_CACHE[key].endPosition = db.endPosition
this.endPosition = { min: '' + parseInt(db.endPosition / 60), sec: '' + parseInt(db.endPosition % 60) }
}
}
this.playVideo(index, time)
}
},
disableChannel (channel) {
const index = this.right.sources.indexOf(channel)
this.right.sources.splice(index, 1)
const ele = this.channelList.find(e => e.id === channel.channelID)
const origin = ele.channels.find(e => e.id === channel.id)
origin.isActive = false
ele.isActive = ele.channels.some(e => e.isActive)
channelList.remove(ele.id)
channelList.add(ele)
},
playChannel (channel) {
this.getIptvList()
this.isLive = true
if (channel.channels) {
this.right.sources = channel.channels.filter(e => e.isActive)
channel = channel.prefer ? channel.channels.find(e => e.id === channel.prefer) : channel.channels.filter(e => e.isActive)[0]
} else {
const ele = this.channelList.find(e => e.id === channel.channelID)
ele.prefer = channel.id
channelList.remove(ele.id)
channelList.add(ele)
this.right.sources = ele.channels.filter(e => e.isActive)
}
this.video.iptv = channel
this.name = channel.name
this.xg.src = channel.url
this.xg.play()
document.querySelector('xg-btn-showhistory').style.display = 'none'
document.querySelector('.xgplayer-playbackrate').style.display = 'none'
},
playVideo (index = 0, time = 0) {
this.isLive = false
document.querySelector('xg-btn-showhistory').style.display = 'block'
document.querySelector('.xgplayer-playbackrate').style.display = 'inline-block'
this.fetchM3u8List().then(m3u8Arr => {
this.xg.src = m3u8Arr[index]
if (time !== 0) {
const url = m3u8Arr[index]
if (!m3u8Arr[index].endsWith('.m3u8')) {
const onlineUrl = 'https://www.1717yun.com/jiexi/?url=' + url
const open = require('open')
open(onlineUrl)
} else {
this.xg.src = m3u8Arr[index]
const key = this.video.key + '@' + this.video.info.id
const startTime = VIDEO_DETAIL_CACHE[key].startPosition || 0
this.xg.play()
this.xg.once('playing', () => {
this.xg.currentTime = time
this.xg.currentTime = time > startTime ? time : startTime
if (VIDEO_DETAIL_CACHE[key].startPosition) this.xg.addProgressDot(VIDEO_DETAIL_CACHE[key].startPosition, '片头')
if (VIDEO_DETAIL_CACHE[key].endPosition) this.xg.addProgressDot(this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition, '片尾')
})
this.videoPlaying()
this.skipendStatus = false
this.xg.once('ended', () => {
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
this.video.info.time = 0
this.video.info.index++
}
this.xg.off('ended') // 明明是once为何会触发多次得注销掉以真正只执行一次
})
} else {
this.xg.play()
}
this.videoPlaying()
this.xg.once('ended', () => {
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
this.video.info.time = 0
this.video.info.index++
}
this.xg.off('ended')
})
})
},
fetchM3u8List () {
return new Promise((resolve) => {
const cacheKey = this.video.key + '@' + this.video.info.id
if (VIDEO_DETAIL_CACHE[cacheKey]) {
if (VIDEO_DETAIL_CACHE[cacheKey] && VIDEO_DETAIL_CACHE[cacheKey].list && VIDEO_DETAIL_CACHE[cacheKey].list.length) {
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
}
zy.detail(this.video.key, this.video.info.id).then(res => {
this.name = res.name
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
let m3u8Txt = []
if (type === '[object Array]') {
for (const i of dd) {
if (i._t.indexOf('m3u8') >= 0) {
m3u8Txt = i._t.split('#')
}
}
} else {
m3u8Txt = dd._t.split('#')
}
const m3u8Txt = res.m3u8List
this.right.list = m3u8Txt
const m3u8Arr = []
for (const i of m3u8Txt) {
const j = i.split('$')
if (j.length > 1) {
for (let m = 0; m < j.length; m++) {
if (j[m].indexOf('.m3u8') >= 0 && j[m].startsWith('http')) {
if (j[m].startsWith('http')) {
m3u8Arr.push(j[m])
break
}
@@ -455,10 +625,10 @@ export default {
}
}
VIDEO_DETAIL_CACHE[cacheKey] = {
VIDEO_DETAIL_CACHE[cacheKey] = Object.assign(VIDEO_DETAIL_CACHE[cacheKey] || {}, {
list: m3u8Arr,
name: res.name
}
})
resolve(m3u8Arr)
})
})
@@ -495,17 +665,46 @@ export default {
this.timerEvent()
},
changeVideo () {
const win = remote.getCurrentWindow()
win.setProgressBar(-1)
this.checkStar()
this.checkTop()
},
async setProgressDotEvent (position, timespan, text) { // 根据跳略时长在进度条上添加标记, position为位置, timespan为时长text为标记文本(title)
const key = this.video.key + '@' + this.video.info.id
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
if (db && this.xg && VIDEO_DETAIL_CACHE[key].list.length > 1) {
this[position] = { min: '' + parseInt(timespan / 60), sec: '' + parseInt(timespan % 60) }
const positionTime = position === 'endPosition' ? this.xg.duration - timespan : timespan
if (db[position]) this.xg.removeProgressDot(position === 'endPosition' ? this.xg.duration - db[position] : db[position])
if (parseInt(this[position].min) || parseInt(this[position].sec)) this.xg.addProgressDot(positionTime, text) // 均为0时不添加标记
const doc = { ...db }
doc[position] = timespan
delete doc.id
history.update(db.id, doc)
VIDEO_DETAIL_CACHE[key][position] = timespan
}
},
async setProgressDotByInput () { // 对应调略输入框后的“确定”
this.xg.removeAllProgressDot()
const startTime = parseInt(this.startPosition.min) * 60 + parseInt(this.startPosition.sec)
const endTime = parseInt(this.endPosition.min) * 60 + parseInt(this.endPosition.sec)
if (startTime > this.xg.duration || endTime > this.xg.duration) {
this.$message.error('设置的跳跃时间长度已超过视频播放时长,请调整设置!')
return
}
await this.setProgressDotEvent('startPosition', startTime)
await this.setProgressDotEvent('endPosition', endTime)
},
async clearPosition () {
await this.setProgressDotEvent('startPosition', 0)
await this.setProgressDotEvent('endPosition', 0)
this.xg.removeAllProgressDot()
},
timerEvent () {
this.timer = setInterval(async () => {
const endTime = this.xg.duration
const currentTime = this.xg.currentTime
const progress = parseFloat((currentTime / endTime).toFixed(2))
const win = remote.getCurrentWindow()
win.setProgressBar(progress)
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
if (db) {
@@ -519,9 +718,9 @@ export default {
},
prevEvent () {
if (this.video.iptv) {
var index = this.iptvList.findIndex(obj => obj.name === this.video.iptv.name && obj.url === this.video.iptv.url)
var index = this.channelList.findIndex(obj => obj.id === this.video.iptv.channelID)
if (index >= 1) {
var channel = this.iptvList[index - 1]
var channel = this.channelList[index - 1]
this.playChannel(channel)
} else {
this.$message.warning('这已经是第一个频道了。')
@@ -537,9 +736,9 @@ export default {
},
nextEvent () {
if (this.video.iptv) {
var index = this.iptvList.findIndex(obj => obj.name === this.video.iptv.name && obj.url === this.video.iptv.url)
if (index < (this.iptvList.length - 1)) {
var channel = this.iptvList[index + 1]
var index = this.channelList.findIndex(obj => obj.id === this.video.iptv.channelID)
if (index < (this.channelList.length - 1)) {
var channel = this.channelList[index + 1]
this.playChannel(channel)
} else {
this.$message.warning('这已经是最后一个频道了。')
@@ -563,6 +762,7 @@ export default {
}
},
historyEvent () {
this.state.showChannelList = false
if (this.right.type === 'history') {
this.right.show = false
this.right.type = ''
@@ -620,40 +820,33 @@ export default {
info: this.video.info
}
},
miniEvent () {
if (this.xg) {
this.xg.pause()
}
mini.find().then(res => {
var doc = {}
if (!this.video.iptv) {
doc = {
id: 0,
mode: 'video',
site: this.video.key,
ids: this.video.info.id,
name: this.video.info.name,
index: this.video.info.index,
time: this.xg.currentTime
}
} else {
doc = {
id: 0,
mode: 'iptv',
url: this.video.iptv.url
}
async miniEvent () {
this.mainWindowBounds = JSON.parse(JSON.stringify(win.getBounds()))
let miniWindowBounds
await mini.find().then(res => { if (res) miniWindowBounds = res.bounds })
if (!miniWindowBounds) miniWindowBounds = { x: win.getPosition()[0], y: win.getPosition()[1], width: 550, height: 340 }
win.setBounds(miniWindowBounds)
this.xg.getCssFullscreen()
document.querySelector('xg-btn-quitMiniMode').style.display = 'block'
this.miniMode = true
},
async exitMiniEvent () {
await mini.find().then(res => {
let doc = {}
doc = {
id: 0,
bounds: win.getBounds()
}
if (res) {
mini.update(doc)
} else {
mini.add(doc)
}
this.mini = doc
clearInterval(this.timer)
const win = remote.getCurrentWindow()
win.hide()
ipcRenderer.send('mini')
})
win.setBounds(this.mainWindowBounds)
this.xg.exitCssFullscreen()
document.querySelector('xg-btn-quitMiniMode').style.display = 'none'
this.miniMode = false
},
shareEvent () {
this.share = {
@@ -733,12 +926,12 @@ export default {
}
},
checkTop () {
const win = remote.getCurrentWindow()
this.isTop = win.isAlwaysOnTop()
this.isTop = this.appState.windowIsOnTop
},
closeListEvent () {
this.right.show = false
this.right.type = ''
this.state.showChannelList = false
},
exportM3u8 () {
const m3u8Arr = []
@@ -783,7 +976,7 @@ export default {
},
listItemEvent (n) {
if (this.video.iptv) {
var channel = this.iptvList[n]
var channel = this.channelList[n]
// 是直播源,直接播放
this.playChannel(channel)
} else {
@@ -810,7 +1003,6 @@ export default {
},
removeHistoryItem (e) {
history.remove(e.id).then(res => {
this.$message.success('删除历史记录成功~')
this.getAllhistory()
}).catch(err => {
this.$message.warning('删除历史记录失败, 错误信息: ' + err)
@@ -848,7 +1040,8 @@ export default {
this.getOtherSites()
this.right.currentTime = this.xg.currentTime
} else {
this.right.type = 'otherChannels'
this.state.showChannelList = false
this.right.type = 'sources'
}
this.right.show = true
},
@@ -857,6 +1050,7 @@ export default {
this.video = { key: e.key, info: { id: e.id, name: e.name, site: e.site, index: this.video.info.index, time: this.right.currentTime } }
},
mtEvent () {
if (this.setting.shortcutModified) this.currentShortcutList.forEach(e => mt.unbind(e.key))
setting.find().then(res => {
if (res.shortcut) {
shortcut.all().then(res => {
@@ -867,23 +1061,31 @@ export default {
}
})
}
this.currentShortcutList = res
})
} else {
shortcut.all().then(res => {
for (const i of res) {
mt.unbind(i.key)
}
this.currentShortcutList = []
})
}
}).finally(() => {
this.setting.shortcutModified = false
setting.find().then(res => {
res.shortcutModified = this.setting.shortcutModified
setting.update(res)
})
})
},
shortcutEvent (e) {
async shortcutEvent (e) {
if (e === 'playAndPause') {
if (this.xg) {
if (this.xg.paused) {
this.xg.play()
// 继续播放时,隐藏进度条
remote.getCurrentWindow().setProgressBar(-1)
win.setProgressBar(-1)
} else {
this.xg.pause()
}
@@ -921,11 +1123,12 @@ export default {
return false
}
if (e === 'top') {
const win = remote.getCurrentWindow()
if (win.isAlwaysOnTop()) {
if (this.appState.windowIsOnTop) {
win.setAlwaysOnTop(false)
this.appState.windowIsOnTop = false
} else {
win.setAlwaysOnTop(true)
this.appState.windowIsOnTop = true
}
return false
}
@@ -938,6 +1141,9 @@ export default {
return false
}
if (e === 'escape') {
if (this.miniMode) {
this.exitMiniEvent()
}
if (this.xg.fullscreen) {
this.xg.exitFullscreen()
this.xg.exitCssFullscreen()
@@ -965,8 +1171,19 @@ export default {
}
return false
}
if (e === 'startPosition') {
this.setProgressDotEvent('startPosition', this.xg.currentTime, '片头')
return false
}
if (e === 'endPosition') {
this.setProgressDotEvent('endPosition', this.xg.duration - this.xg.currentTime, '片尾')
return false
}
if (e === 'clearPosition') {
this.clearPosition()
return false
}
if (e === 'opacityUp') {
const win = remote.getCurrentWindow()
const num = win.getOpacity()
if (num > 0.1) {
win.setOpacity(num - 0.1)
@@ -974,7 +1191,6 @@ export default {
return false
}
if (e === 'opacityDown') {
const win = remote.getCurrentWindow()
const num = win.getOpacity()
if (num < 1) {
win.setOpacity(num + 0.1)
@@ -1000,7 +1216,18 @@ export default {
return false
}
if (e === 'mini') {
this.miniEvent()
if (!this.miniMode) {
this.miniEvent()
} else {
this.exitMiniEvent()
}
return false
}
if (e === 'resetMini') {
if (this.miniMode) {
const miniWindowBounds = { x: this.mainWindowBounds.x, y: this.mainWindowBounds.y, width: 550, height: 340 }
win.setBounds(miniWindowBounds)
}
return false
}
},
@@ -1034,10 +1261,9 @@ export default {
let li = ''
if (this.video.iptv) {
// 直播频道列表
this.getIptvList()
let index = 0
this.iptvList.forEach(e => {
if (e.name === this.video.iptv.name && e.url === this.video.iptv.url) {
this.channelList.forEach(e => {
if (e.prefer === this.video.iptv.id) {
li += `<li class="selected" data-index="${index}" title="${e.name}">${e.name}</li>`
} else {
li += `<li data-index="${index}" title="${e.name}">${e.name}</li>`
@@ -1109,25 +1335,43 @@ export default {
}
ul.innerHTML = li
},
getIptvList () {
iptv.all().then(res => {
this.iptvList = res.filter(e => e.isActive)
this.right.otherChannels = []
const iptvList = JSON.parse(JSON.stringify(this.iptvList))
var currentChannelName = this.video.iptv.name.trim().replace(/[- ]?(1080p|蓝光|超清|高清|标清|hd|cq|4k)(\d{1,2})?/i, '')
if (currentChannelName.match(/cctv/i)) currentChannelName = currentChannelName.replace('-', '')
const matchRule = new RegExp(`${currentChannelName}(1080p|4k|(?!\\d))`, 'i')
for (var i = 0; i < iptvList.length; i++) {
if (iptvList[i].name.match(/cctv/i)) {
iptvList[i].name = iptvList[i].name.replace('-', '')
async getChannelList () {
await channelList.all().then(res => {
this.channelList = res.filter(e => e.isActive)
this.channelTree = []
const groups = [...new Set(this.channelList.map(iptv => iptv.group))]
groups.forEach(g => {
var doc = {
label: g,
children: this.channelList.filter(x => x.group === g).map(i => { return { label: i.name, channel: i } })
}
if (matchRule.test(iptvList[i].name) && iptvList[i].id !== this.video.iptv.id) {
this.right.otherChannels.push(this.iptvList[i])
}
}
this.channelTree.push(doc)
})
})
},
bindEvent () {
this.xg.on('exitFullscreen', () => {
if (this.miniMode) this.xg.getCssFullscreen()
})
this.xg.on('volumechange', () => {
this.config.volume = this.xg.volume.toFixed(2)
setting.find().then(res => { res.volume = this.config.volume; setting.update(res) })
})
this.xg.on('timeupdate', () => {
const key = this.video.key + '@' + this.video.info.id
if (VIDEO_DETAIL_CACHE[key] && VIDEO_DETAIL_CACHE[key].endPosition) {
const time = this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition - this.xg.currentTime
if (time > 0 && time < 0.3) { // timeupdate每0.25秒触发一次,只有自然播放到该点时才会跳过片尾
if (!this.skipendStatus) {
this.skipendStatus = true
this.xg.emit('ended')
}
}
}
})
this.xg.on('playNextOne', () => {
this.nextEvent()
})
@@ -1145,9 +1389,14 @@ export default {
})
this.xg.on('videoStop', () => {
if (this.miniMode) this.exitMiniEvent()
this.videoStop()
})
this.xg.on('quitMiniMode', () => {
if (this.miniMode) this.exitMiniEvent()
})
const ev = ['click', 'touchend', 'mousemove']
let timerID
ev.forEach(item => {
@@ -1169,9 +1418,27 @@ export default {
this.xg.on('exitFullscreen', () => {
document.querySelector('.xg-view-videoTitle').style.display = 'none'
})
this.xg.on('play', () => {
if (!this.video.key) {
if (!this.video.iptv && !this.video.info.ids) {
// 如果当前播放页面的播放信息没有被赋值,播放历史记录
if (this.right.history.length === 0) {
this.$message.error('历史记录为空,无法播放!')
this.videoStop()
return
}
var historyItem = this.right.history[0]
this.video = { key: historyItem.site, info: { id: historyItem.ids, name: historyItem.name, index: historyItem.index } }
this.getUrls()
} else if (this.video.iptv && !this.isLive) {
this.playChannel(this.video.iptv)
this.state.showChannelList = false
}
}
})
},
videoStop () {
const win = remote.getCurrentWindow()
win.setProgressBar(-1)
if (this.xg.fullscreen) {
this.xg.exitFullscreen()
@@ -1179,27 +1446,29 @@ export default {
clearInterval(this.timer)
this.video.key = ''
this.xg.src = ''
this.config.src = ''
this.config.url = ''
this.xg.destroy(false)
this.xg = null
this.name = ''
this.isLive = false
this.state.showChannelList = true
this.state.showTimespanSetting = false
this.right.list = []
this.getAllhistory()
setTimeout(() => {
this.xg = new Hls(this.config)
this.xg = new HlsJsPlayer(this.config)
this.playerInstall()
this.bindEvent()
}, 1000)
}, 100)
},
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) {
if (this.xg && this.xg.hasStart) {
this.xg.play()
}
})
@@ -1214,6 +1483,10 @@ export default {
Player.install('videoStop', function () {
addPlayerBtn.bind(this, 'videoStop', '<svg t="1603093629102" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3621" style="width: 25px;height: 25px;margin-top: 8px;margin-left: 0px;"><path d="M768 768H256V256h512v512z" p-id="3622" fill="#ffffff"></path></svg>', { title: '停止播放' })()
})
Player.install('quitMiniMode', function () {
addPlayerBtn.bind(this, 'quitMiniMode', '<svg t="1606051549980" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2510" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;"><path d="M224 704c-8 0-16-3.2-22.4-9.6l-160-160c-12.8-12.8-12.8-32 0-44.8l160-160c12.8-12.8 32-12.8 44.8 0 12.8 12.8 12.8 32 0 44.8L108.8 512l137.6 137.6c12.8 12.8 12.8 32 0 44.8-6.4 6.4-14.4 9.6-22.4 9.6z m416-160H80c-17.6 0-32-14.4-32-32s14.4-32 32-32h560c17.6 0 32 14.4 32 32s-14.4 32-32 32z m192 384H480c-52.8 0-96-43.2-96-96V704c0-17.6 14.4-32 32-32s32 14.4 32 32v128c0 17.6 14.4 32 32 32h352c17.6 0 32-14.4 32-32V192c0-17.6-14.4-32-32-32H480c-17.6 0-32 14.4-32 32v128c0 17.6-14.4 32-32 32s-32-14.4-32-32V192c0-52.8 43.2-96 96-96h352c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96z" p-id="2511" fill="#ffffff"></path></svg>',
{ title: '退出精简模式' })()
})
Player.install('showList', function () {
addPlayerBtn.bind(this, 'showList', '<svg t="1595866128681" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" style="width: 22px;height: 22px;margin-top: 9px;margin-left: 6px;" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M0 0h1316.571429v146.285714H0zM0 438.857143h1316.571429v146.285714H0zM0 877.714286h1316.571429v146.285714H0z" p-id="4188" fill="#ffffff"></path></svg>', { title: '播放列表' })()
})
@@ -1241,21 +1514,14 @@ export default {
},
created () {
this.getAllhistory()
this.getChannelList()
this.mtEvent()
},
mounted () {
async mounted () {
const db = await setting.find()
this.playerInstall()
this.xg = new Hls(this.config)
ipcRenderer.on('miniClosed', async () => {
const db = await history.find({ site: this.video.key, ids: this.video.info.id })
if (db) {
if (this.video.info.index !== db.index) {
this.video.info.index = db.index
} else {
this.getUrls()
}
}
})
this.config.volume = db.volume ? db.volume : 0.6
this.xg = new HlsJsPlayer(this.config)
this.bindEvent()
this.minMaxEvent()
},
@@ -1265,11 +1531,20 @@ export default {
}
</script>
<style>
.xgplayer-skin-default .xgplayer-live {
width: 100px;
position: absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
font-size: 18px !important;
}
.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 {
.xgplayer-skin-default .xg-btn-videoStop,
.xgplayer-skin-default .xg-btn-quitMiniMode {
width: 32px;
position: relative;
-webkit-order: 0;
@@ -1279,11 +1554,15 @@ export default {
cursor: pointer;
margin-left: 3px;
}
.xgplayer-skin-default .xg-btn-quitMiniMode {
display: none;
}
.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 {
.xgplayer-skin-default .xg-btn-videoStop:hover,
.xgplayer-skin-default .xg-btn-quitMiniMode:hover {
opacity: 0.8;
}
.xgplayer-skin-default .xg-btn-playNextOne {
@@ -1292,15 +1571,22 @@ export default {
.xgplayer-skin-default .xgplayer-play, .xgplayer-skin-default .xgplayer-play-img {
order: 1 !important;
}
.xgplayer-skin-default .xg-btn-videoStop {
order: 2;
}
.xgplayer-skin-default .xg-btn-quitMiniMode {
order: 4;
}
.xgplayer-skin-default .xg-btn-showList {
order: 4;
}
.xgplayer-skin-default .xg-btn-showHistory {
order: 4;
}
.xgplayer-skin-default .xg-btn-showList ul, .xgplayer-skin-default .xg-btn-showHistory ul {
display: none;
list-style: none;
@@ -1423,6 +1709,16 @@ export default {
margin-right: 10px;
cursor: pointer;
}
.timespan{
margin-left: auto;
justify-content: space-between;
align-items: center;
input{
&::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
opacity: 1;
}
}
}
}
}
.list{
@@ -1436,6 +1732,9 @@ export default {
padding: 6px;
display: flex;
flex-direction: column;
.el-tree{
background-color: inherit;
}
.list-top{
display: flex;
justify-content: space-between;
@@ -1464,6 +1763,7 @@ export default {
padding-left: 10px;
font-size: 14px;
cursor: pointer;
display: flex;
.title{
display: inline-block;
overflow: hidden;
@@ -1471,6 +1771,9 @@ export default {
white-space: nowrap;
width: 231px;
}
.btn{
display: inline-block;
}
.detail-delete{
display: none;
position: absolute;

View File

@@ -1,383 +1,338 @@
<template>
<div class="listpage" id="recommendataions">
<div class="listpage-header" id="recommendataions-header">
<el-switch v-model="viewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="list" @change="updateViewMode"></el-switch>
<el-button type="text">视频数{{ recommendations.length }}</el-button>
<el-select v-model="selectedAreas" size="small" multiple collapse-tags placeholder="地区" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in areas"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="selectedTypes" size="small" multiple collapse-tags placeholder="类型" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in types"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="sortKeyword" size="small" placeholder="排序" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in sortKeywords"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-button :loading="loading" @click.stop="updateEvent" icon="el-icon-refresh">更新推荐</el-button>
</div>
<div class="listpage-body" id="recommendataions-body" infinite-wrapper>
<div class="show-table" id="star-table" v-show="viewMode === 'list'">
<el-table size="mini" fit height="100%" row-key="id"
ref="recommendataionsTable"
:data="filteredRecommendations"
@row-click="detailEvent">
<el-table-column
prop="name"
label="片名">
</el-table-column>
<el-table-column
prop="detail.area"
label="地区"
width="100">
</el-table-column>
<el-table-column
prop="detail.type"
label="类型"
width="100">
</el-table-column>
<el-table-column
prop="detail.year"
label="上映"
width="100"
align="center">
</el-table-column>
<el-table-column v-if="filteredRecommendations.some(e => e.rate)"
prop="rate"
align="center"
width="100"
label="豆瓣评分">
</el-table-column>
<el-table-column v-if="filteredRecommendations.some(e => e.detail.note)"
prop="detail.note"
label="备注">
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="200">
<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="deleteEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="show-picture" id="star-picture" v-show="viewMode === 'picture'">
<Waterfall ref="recommendataionsWaterfall" :list="loadedRecommendations" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
rowPerView: 4,
},
800: { //当屏幕宽度小于等于800
rowPerView: 3,
},
500: { //当屏幕宽度小于等于500
rowPerView: 2,
}
}"
animationDuration="0.5s"
backgroundColor="rgba(0, 0, 0, 0)">
<template slot="item" slot-scope="props">
<div class="card">
<div class="img">
<div class="rate" v-if="props.data.rate && props.data.rate !== '暂无评分'">
<span>{{props.data.rate}}</span>
</div>
<img style="width: 100%" :src="props.data.detail.pic" alt="" @load="$refs.recommendataionsWaterfall.refresh()" @click="detailEvent(props.data)">
<div class="operate">
<div class="operate-wrap">
<span class="o-play" @click="playEvent(props.data)">播放</span>
<span class="o-share" @click="shareEvent(props.data)">分享</span>
<span class="o-star" @click="downloadEvent(props.data)">下载</span>
<span class="o-star" @click="deleteEvent(props.data)">删除</span>
</div>
</div>
</div>
<div class="name" @click="detailEvent(props.data)">{{props.data.name}}</div>
<div class="info">
<span>{{props.data.detail.area}}</span>
<span>{{props.data.detail.year}}</span>
<span>{{props.data.detail.note}}</span>
<span>{{props.data.detail.type}}</span>
</div>
</div>
</template>
</Waterfall>
<infinite-loading force-use-infinite-wrapper :identifier="infiniteId" @infinite="infiniteHandler"></infinite-loading>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { history, recommendation, setting } from '../lib/dexie'
import zy from '../lib/site/tools'
import Waterfall from 'vue-waterfall-plugin'
import InfiniteLoading from 'vue-infinite-loading'
const { clipboard } = require('electron')
export default {
name: 'recommendations',
data () {
return {
recommendations: [],
loadedRecommendations: [],
sites: [],
viewMode: 'picture',
loading: false,
types: [],
selectedTypes: [],
areas: [],
selectedAreas: [],
sortKeyword: '',
sortKeywords: ['上映', '评分', '默认'],
infiniteId: +new Date(),
batchSize: 50
}
},
components: {
Waterfall,
InfiniteLoading
},
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)
}
},
filteredRecommendations () {
var filteredData = this.loadedRecommendations.filter(x => (this.selectedAreas.length === 0) || this.selectedAreas.includes(x.detail.area))
filteredData = filteredData.filter(x => (this.selectedTypes.length === 0) || this.selectedTypes.includes(x.detail.type))
return filteredData
}
},
watch: {
view () {
if (this.view === 'Recommendation') {
this.getRecommendations()
if (this.$refs.recommendataionsWaterfall) {
this.$refs.recommendataionsWaterfall.refresh()
}
}
},
sortKeyword () {
switch (this.sortKeyword) {
case '上映':
this.recommendations = this.recommendations.sort(function (a, b) {
return b.detail.year - a.detail.year
})
break
case '评分':
this.recommendations.sort(function (a, b) {
return b.rate - a.rate
})
break
case '默认':
this.recommendations.sort(function (a, b) {
return b.id - a.id
})
break
default:
break
}
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
infiniteHandler ($state) {
console.log('infiniteHandler' + this.loadedRecommendations.length)
if (this.loadedRecommendations.length === this.recommendations.length) {
console.log('complete')
$state.complete()
} else {
var nextBatch = this.recommendations.slice(this.loadedRecommendations.length, this.loadedRecommendations.length + this.batchSize)
this.loadedRecommendations.push(...nextBatch)
$state.loaded()
console.log('loaded' + this.loadedRecommendations.length)
}
},
detailEvent (e) {
this.detail = {
show: true,
key: e.key,
info: {
id: e.ids,
name: e.name
}
}
},
updateEvent () {
const url = 'https://raw.githubusercontent.com/Hunlongyu/ZY-Player/master/src/lib/dexie/iniData/Recommendations.json'
this.loading = true
const axios = require('axios')
axios.get(url).then(res => {
if (res.status === 200) {
if (res.data.length > 0) {
this.recommendations = res.data.sort(function (a, b) {
return b.detail.year - a.detail.year
})
recommendation.clear().then(recommendation.bulkAdd(this.recommendations))
this.getFilterData()
this.$message.success('更新推荐成功')
}
}
this.loading = false
}).catch(error => {
this.loading = false
this.$message.error('更新推荐失败. ' + error)
})
},
async playEvent (e) {
const db = await history.find({ site: e.key, ids: e.ids })
if (db) {
this.video = { key: e.key, info: { id: db.ids, name: db.name, index: db.index }, detail: db.detail }
} else {
this.video = { key: e.key, info: { id: e.ids, name: e.name, index: 0 }, detail: e.detail }
}
this.view = 'Play'
},
deleteEvent (e) {
recommendation.remove(e.id).then(res => {
if (res) {
this.$message.warning('删除失败')
} else {
this.$message.success('删除成功')
}
this.getRecommendations()
})
},
shareEvent (e) {
this.share = {
show: true,
key: e.key,
info: e
}
},
downloadEvent (e) {
zy.download(e.key, e.ids).then(res => {
if (res && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
this.$message.warning('没有查询到下载链接.')
}
} else {
var m3u8List = {}
zy.detail(e.key, e.ids).then(res => {
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
m3u8List = i._t.split('#')
}
}
} else {
m3u8List = dd._t.split('#')
}
const list = [...m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
})
}
})
},
getRecommendations () {
recommendation.all().then(res => {
this.recommendations = res.sort(function (a, b) {
return b.id - a.id
})
this.loadedRecommendations = this.recommendations.slice(0, this.batchSize)
this.infiniteId += 1
this.getFilterData()
})
},
getFilterData () {
this.types = [...new Set(this.recommendations.map(ele => ele.detail.type))].filter(x => x)
this.areas = [...new Set(this.recommendations.map(ele => ele.detail.area))].filter(x => x)
},
getViewMode () {
setting.find().then(res => {
this.viewMode = res.recommendationViewMode
})
},
updateViewMode () {
setting.find().then(res => {
res.recommendationViewMode = this.viewMode
setting.update(res)
})
}
},
created () {
this.getRecommendations()
this.getViewMode()
},
mounted () {
window.addEventListener('resize', () => {
if (this.$refs.recommendataionsWaterfall && this.view === 'Recommendation') {
this.$refs.recommendataionsWaterfall.resize()
this.$refs.recommendataionsWaterfall.refresh()
setTimeout(() => {
this.$refs.recommendataionsWaterfall.refresh()
}, 500)
}
}, false)
}
}
</script>
<template>
<div class="listpage" id="recommendataions">
<div class="listpage-header" id="recommendataions-header">
<el-switch v-model="setting.recommendationViewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="table" @change="updateViewMode"></el-switch>
<el-button type="text">视频数{{ recommendations.length }}</el-button>
<el-select v-model="selectedAreas" size="small" multiple placeholder="地区" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in areas"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="selectedTypes" size="small" multiple placeholder="类型" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in types"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="sortKeyword" size="small" placeholder="排序" popper-class="popper" :popper-append-to-body="false">
<el-option
v-for="item in sortKeywords"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-button :loading="loading" @click.stop="updateEvent" icon="el-icon-refresh">更新推荐</el-button>
</div>
<div class="listpage-body" id="recommendataions-body" >
<div class="show-table" id="star-table" v-if="setting.recommendationViewMode === 'table'">
<el-table size="mini" fit height="100%" row-key="id"
ref="recommendataionsTable"
:data="filteredRecommendations"
@row-click="detailEvent">
<el-table-column
prop="name"
label="片名">
</el-table-column>
<el-table-column
prop="detail.area"
label="地区"
width="100">
</el-table-column>
<el-table-column
prop="detail.type"
label="类型"
width="100">
</el-table-column>
<el-table-column
prop="detail.year"
label="上映"
width="100"
align="center">
</el-table-column>
<el-table-column v-if="filteredRecommendations.some(e => e.rate)"
prop="rate"
align="center"
width="100"
label="豆瓣评分">
</el-table-column>
<el-table-column v-if="filteredRecommendations.some(e => e.detail.note)"
prop="detail.note"
label="备注">
</el-table-column>
<el-table-column
label="操作"
header-align="center"
align="right"
width="200">
<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="deleteEvent(scope.row)" type="text">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="show-picture" id="star-picture" v-if="setting.recommendationViewMode === 'picture'">
<Waterfall ref="recommendataionsWaterfall" :list="filteredRecommendations" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
rowPerView: 4,
},
800: { //当屏幕宽度小于等于800
rowPerView: 3,
},
500: { //当屏幕宽度小于等于500
rowPerView: 2,
}
}"
animationDuration="0.5s"
backgroundColor="rgba(0, 0, 0, 0)">
<template slot="item" slot-scope="props">
<div class="card">
<div class="img">
<div class="rate" v-if="props.data.rate && props.data.rate !== '暂无评分'">
<span>{{props.data.rate}}</span>
</div>
<img style="width: 100%" :src="props.data.detail.pic" alt="" @load="$refs.recommendataionsWaterfall.refresh()" @click="detailEvent(props.data)">
<div class="operate">
<div class="operate-wrap">
<span class="o-play" @click="playEvent(props.data)">播放</span>
<span class="o-share" @click="shareEvent(props.data)">分享</span>
<span class="o-star" @click="downloadEvent(props.data)">下载</span>
<span class="o-star" @click="deleteEvent(props.data)">删除</span>
</div>
</div>
</div>
<div class="name" @click="detailEvent(props.data)">{{props.data.name}}</div>
<div class="info">
<span>{{props.data.detail.area}}</span>
<span>{{props.data.detail.year}}</span>
<span>{{props.data.detail.note}}</span>
<span>{{props.data.detail.type}}</span>
</div>
</div>
</template>
</Waterfall>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { history, recommendation, setting } from '../lib/dexie'
import zy from '../lib/site/tools'
import Waterfall from 'vue-waterfall-plugin'
const { clipboard } = require('electron')
export default {
name: 'recommendations',
data () {
return {
recommendations: [],
sites: [],
loading: false,
types: [],
selectedTypes: [],
areas: [],
selectedAreas: [],
sortKeyword: '',
sortKeywords: ['上映', '评分', '默认']
}
},
components: {
Waterfall
},
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)
}
},
setting: {
get () {
return this.$store.getters.getSetting
},
set (val) {
this.SET_SETTING(val)
}
},
filteredRecommendations () {
var filteredData = this.recommendations.filter(x => (this.selectedAreas.length === 0) || this.selectedAreas.includes(x.detail.area))
filteredData = filteredData.filter(x => (this.selectedTypes.length === 0) || this.selectedTypes.includes(x.detail.type))
return filteredData
}
},
watch: {
view () {
if (this.view === 'Recommendation') {
if (this.$refs.recommendataionsWaterfall) this.$refs.recommendataionsWaterfall.resize()
}
},
sortKeyword () {
switch (this.sortKeyword) {
case '上映':
this.recommendations = this.recommendations.sort(function (a, b) {
return b.detail.year - a.detail.year
})
break
case '评分':
this.recommendations.sort(function (a, b) {
return b.rate - a.rate
})
break
case '默认':
this.recommendations.sort(function (a, b) {
return b.id - a.id
})
break
default:
break
}
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
detailEvent (e) {
this.detail = {
show: true,
key: e.key,
info: {
id: e.ids,
name: e.name
}
}
},
updateEvent () {
const url = 'https://raw.githubusercontent.com/cuiocean/ZY-Player-Resources/main/Recommendations/Recommendations.json'
this.loading = true
const axios = require('axios')
axios.get(url).then(res => {
if (res.status === 200) {
if (res.data.length > 0) {
this.recommendations = res.data
recommendation.clear().then(recommendation.bulkAdd(this.recommendations))
this.getFilterData()
this.$message.success('更新推荐成功. 仅根据作者cuiocean个人喜好推荐,不喜请无视.')
}
}
this.loading = false
}).catch(error => {
this.loading = false
this.$message.error('更新推荐失败. ' + error)
this.$message.warning('最新的推荐数据保存在Github上,请考虑使用代理或者等待下一版本内置数据更新.')
})
},
async playEvent (e) {
const db = await history.find({ site: e.key, ids: e.ids })
if (db) {
this.video = { key: e.key, info: { id: db.ids, name: db.name, index: db.index }, detail: db.detail }
} else {
this.video = { key: e.key, info: { id: e.ids, name: e.name, index: 0 }, detail: e.detail }
}
this.view = 'Play'
},
deleteEvent (e) {
recommendation.remove(e.id).then(res => {
if (res) {
this.$message.warning('删除失败')
}
this.getRecommendations()
})
},
shareEvent (e) {
this.share = {
show: true,
key: e.key,
info: e.detail
}
},
downloadEvent (e) {
const key = e.key
const id = e.ids
zy.download(key, id).then(res => {
if (res && res.m3u8List) {
const list = res.m3u8List.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
zy.detail(key, id).then(res => {
const list = [...res.m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『M3U8』格式的链接已复制, 快去下载吧!')
})
}
})
},
getRecommendations () {
recommendation.all().then(res => {
this.recommendations = res.sort(function (a, b) {
return b.id - a.id
})
this.getFilterData()
})
},
getFilterData () {
this.types = [...new Set(this.recommendations.map(ele => ele.detail.type))].filter(x => x)
this.areas = [...new Set(this.recommendations.map(ele => ele.detail.area))].filter(x => x)
},
updateViewMode () {
setTimeout(() => { if (this.$refs.recommendataionsWaterfall) this.$refs.recommendataionsWaterfall.refresh() }, 700)
setting.find().then(res => {
res.recommendationViewMode = this.setting.recommendationViewMode
setting.update(res)
})
}
},
created () {
this.getRecommendations()
},
mounted () {
addEventListener('resize', () => {
setTimeout(() => { if (this.$refs.recommendataionsWaterfall) this.$refs.recommendataionsWaterfall.resize() }, 500)
})
}
}
</script>

View File

@@ -5,22 +5,10 @@
<div class="info">
<a @click="linkOpen('http://zyplayer.fun/')">官网</a>
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player')">Github</a>
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/issues')">当前版本v{{pkg.version}} 反馈</a>
<a style="color:#38dd77" @click="quitAndInstall()" v-show="latestVersion !== pkg.version" >最新版本v{{latestVersion}}</a>
</div>
<div class="view">
<div class="title">视图</div>
<div class="view-box">
<div class="zy-select" @mouseleave="show.view = false">
<div class="vs-placeholder" @click="show.view = true">默认视图</div>
<div class="vs-options" v-show="show.view">
<ul class="zy-scroll">
<li :class="d.view === 'picture' ? 'active' : ''" @click="changeView('picture')">海报</li>
<li :class="d.view === 'table' ? 'active' : ''" @click="changeView('table')">列表</li>
</ul>
</div>
</div>
</div>
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/releases/tag/v' + pkg.version)">v{{pkg.version}}更新日志</a>
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/issues/80')">常见问题</a>
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/issues')">反馈建议</a>
<a style="color:#38dd77" @click="openUpdate()" v-show="update.find" >最新版本v{{update.version}}</a>
</div>
<div class="shortcut">
<div class="title">快捷键</div>
@@ -40,6 +28,9 @@
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="impShortcut">导入</div>
</div>
<div class="zy-select">
<div class="vs-placeholder vs-noAfter" @click="resetShortcut">重置</div>
</div>
</div>
</div>
<div class="shortcut">
@@ -72,6 +63,20 @@
</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="view = 'IPTV'">编辑直播源</div>
</div>
<div class="zy-input">
<input type="checkbox" v-model = "d.allowPassWhenIptvCheck" @change="updateSettingEvent"> 检测时自动跳过停用源
</div>
<div class="zy-input">
<input type="checkbox" v-model = "d.autocleanWhenIptvCheck" @change="updateSettingEvent"> 检测时自动清理无效源
</div>
</div>
</div>
<div class="site">
<div class="title">源管理</div>
<div class="site-box">
@@ -83,6 +88,21 @@
</div>
</div>
</div>
<div class="site">
<div class="title">网络</div>
<div class="site-box">
<div class="zy-select" @mouseleave="show.proxy = false">
<div class="vs-placeholder" @click="show.proxy = true">代理设置</div>
<div class="vs-options" v-if="show.proxy">
<ul class="zy-scroll">
<li :class="d.proxy.type === 'none' ? 'active' : ''" @click="changeProxyType('none')">不使用代理</li>
<!-- <li :class="d.proxy.type === 'system' ? 'active' : ''" @click="changeProxyType('system')">使用系统代理</li> -->
<li :class="d.proxy.type === 'manual' ? 'active' : ''" @click="changeProxyType('manual')">手动指定代理</li>
</ul>
</div>
</div>
</div>
</div>
<div class="theme">
<div class="title">主题</div>
<div class="theme-box">
@@ -154,15 +174,59 @@
</span>
</el-dialog>
</div>
<div> <!-- 代理设置界面 -->
<el-dialog :visible.sync="show.proxyDialog" :append-to-body="true" @close="closeDialog" width="400px">
<el-form label-width="50px" label-position="left" size="small">
<el-form-item label="协议: " prop='scheme'>
<el-col :span="15">
<el-select v-model="proxy.scheme" placeholder="请选择协议类型">
<el-option label="http" value="http"></el-option>
<el-option label="socks5" value="socks5"></el-option>
</el-select>
</el-col>
</el-form-item>
<el-form-item label="地址: " prop='url'>
<el-col :span="15">
<el-input v-model="proxy.url" placeholder="地址" />
</el-col>
<el-col class="line" :span="2" style="text-align: center;">:</el-col>
<el-col :span="7">
<el-input v-model="proxy.port" placeholder="端口" width="80px" />
</el-col>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="proxyConfirm">确定</el-button>
</span>
</el-dialog>
</div>
<div class="update" v-if="update.show">
<div class="wrapper">
<div class="body">
<div class="content" v-html="update.html"></div>
<div class="progress" v-show="update.percent > 0">
<el-progress :percentage="update.percent"></el-progress>
<div class="size" style="font-size: 14px">更新包大小: {{update.size}} KB</div>
</div>
</div>
<div class="footer">
<el-button size="small" @click="cancelUpdate">取消</el-button>
<el-button size="small" v-show="!update.downloaded" @click="startUpdate">更新</el-button>
<el-button size="small" v-show="update.downloaded" @click="installUpdate">安装</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import pkg from '../../package.json'
import { setting, sites, shortcut } from '../lib/dexie'
import { sites as defaultSites } from '../lib/dexie/initData'
import { sites as defaultSites, localKey as defaultShortcuts } from '../lib/dexie/initData'
import { shell, clipboard, remote, ipcRenderer } from 'electron'
import db from '../lib/dexie/dexie'
import zy from '../lib/site/tools'
export default {
name: 'setting',
data () {
@@ -175,12 +239,29 @@ export default {
view: false,
editPlayerPath: false,
checkPasswordDialog: false,
changePasswordDialog: false
changePasswordDialog: false,
proxy: false,
proxyDialog: false
},
d: { },
latestVersion: pkg.version,
inputPassword: '',
action: ''
action: '',
proxy: {
type: '',
scheme: '',
url: '',
port: ''
},
update: {
find: false,
version: '',
show: false,
html: '',
percent: 0,
size: 0,
downloaded: false
}
}
},
computed: {
@@ -225,11 +306,6 @@ export default {
this.shortcutList = res
})
},
changeView (e) {
this.d.view = e
this.updateSettingEvent()
this.show.view = false
},
async clearCache () {
const win = remote.getCurrentWindow()
const ses = win.webContents.session
@@ -290,9 +366,16 @@ export default {
this.view = 'EditSites'
}
},
closeDialog () {
async closeDialog () {
this.show.checkPasswordDialog = false
this.show.changePasswordDialog = false
if (this.show.proxyDialog) {
this.show.proxyDialog = false
this.setting.proxy.type = 'none'
await this.updateSettingEvent()
this.$message.info('取消使用代理')
zy.proxy()
}
this.inputPassword = ''
},
checkPasswordEvent () {
@@ -344,10 +427,41 @@ export default {
this.$message.info('已清空原数据')
shortcut.add(json).then(e => {
this.$message.success('已添加成功')
this.getSites()
this.getShortcut()
this.d.shortcutModified = true
this.updateSettingEvent()
})
})
},
resetShortcut () {
shortcut.clear().then(shortcut.add(defaultShortcuts)).then(res => {
this.getShortcut()
this.$message.success('快捷键已重置')
this.d.shortcutModified = true
this.updateSettingEvent()
})
},
async changeProxyType (e) {
this.d.proxy.type = e
if (e === 'manual') {
this.show.proxyDialog = true
this.proxy.scheme = this.setting.proxy.scheme
this.proxy.url = this.setting.proxy.url
this.proxy.port = this.setting.proxy.port
}
await this.updateSettingEvent()
this.show.proxy = false
zy.proxy()
},
async proxyConfirm () {
this.d.proxy.scheme = this.proxy.scheme
this.d.proxy.url = this.proxy.url
this.d.proxy.port = this.proxy.port
await this.updateSettingEvent()
this.show.proxyDialog = false
zy.proxy()
this.$message.info('开始使用代理')
},
clearDBEvent () {
if (this.d.password) {
this.action = 'CleanDB'
@@ -373,20 +487,31 @@ export default {
return false
}
},
getLatestVersion () {
checkUpdate () {
ipcRenderer.send('checkForUpdate')
ipcRenderer.on('update-available', (e, info) => {
this.latestVersion = info.version
})
ipcRenderer.on('update-error', () => {
this.$message.warning = '更新出错.'
})
ipcRenderer.on('update-downloaded', () => {
this.$message.info = '下载完毕, 退出安装'
this.update.find = true
this.update.version = info.version
this.update.html = info.releaseNotes
})
},
quitAndInstall () {
this.$message.success('已开始下载更新,下载完毕后,将自动退出安装。')
openUpdate () {
this.update.show = true
},
cancelUpdate () {
this.update.show = false
},
startUpdate () {
ipcRenderer.send('downloadUpdate')
ipcRenderer.on('download-progress', (info, progress) => {
this.update.size = progress.total
this.update.percent = parseFloat(progress.percent).toFixed(1)
})
ipcRenderer.on('update-downloaded', () => {
this.update.downloaded = true
})
},
installUpdate () {
ipcRenderer.send('quitAndInstall')
},
createContextMenu () {
@@ -405,7 +530,7 @@ export default {
this.getSites()
this.getSetting()
this.getShortcut()
this.getLatestVersion()
this.checkUpdate()
this.createContextMenu()
}
}
@@ -443,17 +568,6 @@ export default {
cursor: pointer;
}
}
.view{
width: 100%;
padding: 20px;
margin-top: 20px;
.view-box{
margin-top: 10px;
.zy-select{
margin-right: 20px;
}
}
}
.site{
width: 100%;
padding: 20px;
@@ -548,5 +662,28 @@ export default {
font-size: 12px;
color: #ff000066;
}
.update{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(7, 17, 27, 0.7);
display: flex;
align-items: center;
justify-content: center;
.wrapper{
background-color: #fff;
padding: 20px 50px 40px;
border-radius: 4px;
max-width: 500px;
max-height: 90%;
overflow: auto;
.footer{
display: flex;
justify-content: flex-end;
}
}
}
}
</style>

View File

@@ -5,7 +5,7 @@
</div>
<div class="right" id="right">
<div class="title">{{ share.info.name }}</div>
<qrcode-vue id="qr" :value="link" :size="160" level="L" />
<qrcode-vue v-if="link !== ''" id="qr" :value="link" :size="160" level="L" />
<div class="tips">
<p>长按二维码识别播放</p>
<p><img src="@/assets/image/logo.png"></p>
@@ -68,33 +68,28 @@ export default {
info: {}
}
},
getDetail () {
this.loading = true
const id = this.share.info.ids || this.share.info.id
zy.detail(this.share.key, id).then(res => {
async getUrl (dl) {
const t = dl.dd._t
if (t) {
return t.split('#')[0].split('$')[1]
} else {
const id = this.share.info.ids || this.share.info.id
const res = await zy.detail(this.share.key, id)
if (res) {
this.pic = res.pic
var m3u8List = {}
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
m3u8List = i._t.split('#')
}
}
} else {
m3u8List = dd._t.split('#')
}
const url = m3u8List[1]
this.link = 'http://zyplayer.fun/player/player.html?url=' + url + '&title=' + this.share.info.name
return res.m3u8List[1]
}
this.loading = false
})
}
},
async getDetail () {
this.loading = true
this.pic = this.share.info.pic
const url = await this.getUrl(this.share.info.dl)
this.link = 'http://hunlongyu.gitee.io/zy-player-web?url=' + url + '&name=' + this.share.info.name
this.loading = false
},
picLoadEvent () {
const dom = document.getElementById('share')
html2canvas(dom, { useCORS: true, allowTaint: true }).then(res => {
html2canvas(dom).then(res => {
const png = res.toDataURL('image/png')
const p = nativeImage.createFromDataURL(png)
clipboard.writeImage(p)

View File

@@ -1,20 +1,25 @@
<template>
<div class="listpage" id="star">
<div class="listpage-header" id="star-header">
<el-switch v-model="viewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="list" @change="updateViewMode"></el-switch>
<el-button @click.stop="exportFavoritesEvent" icon="el-icon-upload2">导出</el-button>
<el-button @click.stop="importFavoritesEvent" icon="el-icon-download">导入</el-button>
<el-button @click.stop="clearFavoritesEvent" icon="el-icon-delete-solid">清空</el-button>
<el-switch v-model="setting.starViewMode" active-text="海报" active-value="picture" inactive-text="列表" inactive-value="table" @change="updateViewMode"></el-switch>
<el-button @click.stop="exportFavoritesEvent" icon="el-icon-upload2" title="导出全部,自动添加扩展名">导出</el-button>
<el-button @click.stop="importFavoritesEvent" icon="el-icon-download" title="支持同时导入多个文件">导入</el-button>
<el-button @click.stop="removeSelectedItems" icon="el-icon-delete-solid">{{ multipleSelection.length === 0 ? "清空" : "删除所选" }}</el-button>
<el-button @click.stop="updateAllEvent" icon="el-icon-refresh">同步所有收藏</el-button>
</div>
<div class="listpage-body" id="star-body">
<div class="show-table" id="star-table" v-show="viewMode === 'list'">
<div class="show-table" id="star-table" v-if="setting.starViewMode === 'table'">
<el-table size="mini" fit height="100%" row-key="id"
ref="starTable"
:data="list"
:cell-class-name="checkUpdate"
@row-click="detailEvent"
@sort-change="handleSortChange">
ref="starTable"
:data="list"
:cell-class-name="checkUpdate"
@row-click="detailEvent"
@sort-change="handleSortChange"
@select="selectionCellClick"
@selection-change="handleSelectionChange">
<el-table-column
type="selection">
</el-table-column>
<el-table-column
sortable
:sort-method="(a , b) => sortByLocaleCompare(a.name, b.name)"
@@ -78,7 +83,7 @@
</el-table-column>
</el-table>
</div>
<div class="show-picture" id="star-picture" v-show="viewMode === 'picture'">
<div class="show-picture" id="star-picture" v-if="setting.starViewMode === 'picture'">
<Waterfall ref="starWaterfall" :list="list" :gutter="20" :width="240"
:breakpoints="{
1200: { //当屏幕宽度小于等于1200
@@ -146,8 +151,11 @@ export default {
return {
list: [],
sites: [],
viewMode: 'picture',
numNoUpdate: 0
numNoUpdate: 0,
shiftDown: false,
selectionBegin: '',
selectionEnd: '',
multipleSelection: []
}
},
components: {
@@ -185,6 +193,14 @@ export default {
set (val) {
this.SET_SHARE(val)
}
},
setting: {
get () {
return this.$store.getters.getSetting
},
set (val) {
this.SET_SETTING(val)
}
}
},
watch: {
@@ -192,9 +208,7 @@ export default {
if (this.view === 'Star') {
this.getAllsites()
this.getFavorites()
if (this.$refs.starWaterfall) {
this.$refs.starWaterfall.refresh()
}
if (this.setting.starViewMode === 'table') this.showShiftPrompt()
}
},
numNoUpdate () {
@@ -206,13 +220,40 @@ export default {
}
},
methods: {
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE', 'SET_SETTING']),
handleSortChange (column, prop, order) {
this.updateDatabase()
},
sortByLocaleCompare (a, b) {
return a.localeCompare(b, 'zh')
},
selectionCellClick (selection, row) { // 同history一样逆序
if (this.shiftDown && this.selectionBegin !== '' && selection.includes(row)) {
this.selectionEnd = row.id
const start = this.list.findIndex(e => e.id === Math.max(this.selectionBegin, this.selectionEnd))
const end = this.list.findIndex(e => e.id === Math.min(this.selectionBegin, this.selectionEnd))
const selections = this.list.slice(start, end + 1)
this.$nextTick(() => {
selections.forEach(e => this.$refs.starTable.toggleRowSelection(e, true))
})
this.selectionBegin = this.selectionEnd = ''
return
}
if (selection.includes(row)) {
this.selectionBegin = row.id
} else {
this.selectionBegin = ''
}
},
handleSelectionChange (rows) {
this.multipleSelection = rows
},
removeSelectedItems () {
if (!this.multipleSelection.length) this.multipleSelection = this.list
this.multipleSelection.forEach(e => star.remove(e.id))
this.getFavorites()
this.updateDatabase()
},
detailEvent (e) {
this.detail = {
show: true,
@@ -241,8 +282,6 @@ export default {
star.remove(e.id).then(res => {
if (res) {
this.$message.warning('删除失败')
} else {
this.$message.success('删除成功')
}
this.getFavorites()
})
@@ -251,7 +290,7 @@ export default {
this.share = {
show: true,
key: e.key,
info: e
info: e.detail
}
},
checkUpdate ({ row, rowIndex }) {
@@ -301,36 +340,21 @@ export default {
})
},
downloadEvent (e) {
zy.download(e.key, e.ids).then(res => {
if (res && res.dl && res.dl.dd) {
const text = res.dl.dd._t
if (text) {
const list = text.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
this.$message.warning('没有查询到下载链接.')
const key = e.key
const id = e.id
zy.download(key, id).then(res => {
if (res && res.m3u8List) {
const list = res.m3u8List.split('#')
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
downloadUrl += (url + '\n')
}
clipboard.writeText(downloadUrl)
this.$message.success('『MP4』格式的链接已复制, 快去下载吧!')
} else {
var m3u8List = {}
zy.detail(e.key, e.ids).then(res => {
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
m3u8List = i._t.split('#')
}
}
} else {
m3u8List = dd._t.split('#')
}
const list = [...m3u8List]
zy.detail(key, id).then(res => {
const list = [...res.m3u8List]
let downloadUrl = ''
for (const i of list) {
const url = encodeURI(i.split('$')[1])
@@ -376,13 +400,12 @@ export default {
const str = JSON.stringify(arr, null, 2)
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
{ name: 'JSON file', extensions: ['json'] }
]
}
remote.dialog.showSaveDialog(options).then(result => {
if (!result.canceled) {
if (!result.filePath.endsWith('.json')) result.filePath += '.json'
fs.writeFileSync(result.filePath, str)
this.$message.success('导出收藏成功')
}
@@ -393,9 +416,7 @@ export default {
importFavoritesEvent () {
const options = {
filters: [
{ name: 'JSON file', extensions: ['json'] },
{ name: 'Normal text file', extensions: ['txt'] },
{ name: 'All types', extensions: ['*'] }
{ name: 'JSON file', extensions: ['json'] }
],
properties: ['openFile', 'multiSelections']
}
@@ -443,11 +464,6 @@ export default {
this.$message.error(err)
})
},
clearFavoritesEvent () {
star.clear().then(e => {
this.getFavorites()
})
},
syncTableData () {
if (this.$refs.starTable.tableData && this.$refs.starTable.tableData.length === this.list.length) {
this.list = this.$refs.starTable.tableData
@@ -475,33 +491,40 @@ export default {
}
})
},
getViewMode () {
setting.find().then(res => {
this.viewMode = res.starViewMode
})
},
updateViewMode () {
if (this.setting.starViewMode === 'table') {
setTimeout(() => { this.rowDrop() }, 100)
this.showShiftPrompt()
} else {
setTimeout(() => { if (this.$refs.starWaterfall) this.$refs.starWaterfall.refresh() }, 700)
}
setting.find().then(res => {
res.starViewMode = this.viewMode
res.starViewMode = this.setting.starViewMode
setting.update(res)
})
},
showShiftPrompt () {
if (this.setting.shiftTooltipLimitTimes === undefined) this.setting.shiftTooltipLimitTimes = 5
if (this.setting.shiftTooltipLimitTimes) {
this.$message.info('多选时支持shift快捷键')
this.setting.shiftTooltipLimitTimes--
setting.find().then(res => {
res.shiftTooltipLimitTimes = this.setting.shiftTooltipLimitTimes
setting.update(res)
})
}
}
},
created () {
this.getFavorites()
this.getViewMode()
},
mounted () {
this.rowDrop()
window.addEventListener('resize', () => {
if (this.$refs.starWaterfall && this.view === 'Star') {
this.$refs.starWaterfall.resize()
this.$refs.starWaterfall.refresh()
setTimeout(() => {
this.$refs.starWaterfall.refresh()
}, 500)
}
}, false)
if (this.setting.starViewMode === 'table') setTimeout(() => { this.rowDrop() }, 100)
addEventListener('keydown', code => { if (code.keyCode === 16) this.shiftDown = true })
addEventListener('keyup', code => { if (code.keyCode === 16) this.shiftDown = false })
addEventListener('resize', () => {
setTimeout(() => { if (this.$refs.starWaterfall) this.$refs.starWaterfall.resize() }, 500)
})
}
}
</script>

View File

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

View File

@@ -5,15 +5,29 @@ const db = new Dexie('zy')
db.version(4).stores({
search: '++id, keywords',
iptvSearch: '++id, keywords',
setting: 'id, theme, site, shortcut, view, externalPlayer, searchGroup, excludeRootClasses, excludeR18Films, forwardTimeInSec, starViewMode, recommandationViewMode, password',
setting: 'id, theme, site, shortcut, view, volume, externalPlayer, searchGroup, excludeRootClasses, excludeR18Films, forwardTimeInSec, starViewMode, recommandationViewMode, searchViewMode, password, proxy, allowPassWhenIptvCheck, autocleanWhenIptvCheck',
shortcut: 'name, key, desc',
star: '++id, [key+ids], site, name, detail, index, rate, hasUpdate',
recommendation: '++id, [key+ids], site, name, detail, index, rate, hasUpdate',
sites: '++id, key, name, api, download, isActive, group',
history: '++id, [site+ids], name, type, year, index, time, duration, detail',
mini: 'id, mode, site, ids, name, index, time, url',
iptv: '++id, name, url, group, isActive'
mini: 'id, bounds',
iptv: '++id, name, url, isActive',
channelList: '++id, name, prefer, channels, group, isActive'
})
// 参考https://github.com/dfahlander/Dexie.js/releases/tag/v3.0.0-alpha.3 upgrade可以改变主键和表名了
// https://dexie.org/docs/Version/Version.stores()
// https://dexie.org/docs/Version/Version.upgrade()
// https://ahuigo.github.io/b/ria/js-indexedDB#/ 比较旧,适当参考
db.version(5).stores({
shortcut: null
})
db.version(6).stores({
shortcut: '++id, name, key, desc'
}).upgrade(async tx => {
await tx.shortcut.bulkAdd(localKey)
})
db.on('populate', () => {

View File

@@ -5,8 +5,8 @@ import shortcut from './shortcut'
import star from './star'
import sites from './sites'
import search from './search'
import iptvSearch from './iptvSearch'
import iptv from './iptv'
import channelList from './channelList'
import recommendation from './recommendation'
export {
@@ -17,7 +17,7 @@ export {
star,
sites,
iptv,
channelList,
search,
iptvSearch,
recommendation
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,259 @@
[
{
"key": "1886zy",
"ids": 16944,
"site": {
"id": 2,
"key": "1886zy",
"name": "1886 资源",
"api": "http://cj.1886zy.co/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
"name": "柯明斯基理论",
"detail": {
"last": "2018-11-23 18:13:07",
"id": 16944,
"tid": 15,
"name": "柯明斯基理论",
"type": "欧美剧",
"pic": "http://pic.yc370.com/upload/vod/2019-01-19/15479133688.jpg",
"lang": "",
"area": "美国",
"year": 2018,
"state": 8,
"note": "08",
"actor": "迈克尔·道格拉斯,艾伦·阿金,莎拉·贝克,南希·特拉维斯",
"director": "安迪·坦纳特,查克·罗瑞,唐纳德·佩特瑞,贝丝·麦卡锡-米勒",
"dl": {
"dd": [
{
"_t": "08$https://zuikzy.51moca.com/share/XoIqsGnIP7IED2LS#07$https://zkcdn.yiya520.com/share/kJOL42dTmm6VJkqK#06$https://zkcdn.yiya520.com/share/f8gxIqAchIPyxlAg#05$https://zkcdn.yiya520.com/share/mTG5GkXpB7yro1sQ#04$https://zkcdn.yiya520.com/share/HjQAbC0lzzHAusIw#03$https://zkcdn.yiya520.com/share/qlN7TvZUDDueiefE#02$https://zkcdn.yiya520.com/share/2P9HAA5H1KvkMgm2#01$https://zkcdn.yiya520.com/share/KUD3QMMS4UGnNA3Y",
"_flag": "zkyun"
},
{
"_t": "08$https://zuikzy.51moca.com/2018/11/23/XoIqsGnIP7IED2LS/playlist.m3u8#07$https://zkcdn.yiya520.com/2018/11/21/kJOL42dTmm6VJkqK/playlist.m3u8#06$https://zkcdn.yiya520.com/2018/11/21/f8gxIqAchIPyxlAg/playlist.m3u8#05$https://zkcdn.yiya520.com/2018/11/21/mTG5GkXpB7yro1sQ/playlist.m3u8#04$https://zkcdn.yiya520.com/2018/11/19/HjQAbC0lzzHAusIw/playlist.m3u8#03$https://zkcdn.yiya520.com/2018/11/19/qlN7TvZUDDueiefE/playlist.m3u8#02$https://zkcdn.yiya520.com/2018/11/18/2P9HAA5H1KvkMgm2/playlist.m3u8#01$https://zkcdn.yiya520.com/2018/11/18/KUD3QMMS4UGnNA3Y/playlist.m3u8",
"_flag": "zkm3u8"
}
]
},
"des": "迈克尔·道格拉斯、艾伦·阿金有望加盟Netflix喜剧剧集《柯明斯基理论》(The Kominsky Method暂译)该剧由《生活大爆炸》联合编剧查克·罗瑞担任制片。道格拉斯剧中饰演曾经红极一时的明星现下却只能靠教授表演课程为生阿金饰演他的老友。道格拉斯上次出演电视剧集还是上世纪70年代的《旧金山风物记》而阿金上一部荧屏作品则是2001年的犯罪剧集《百厦街》。",
"m3u8List": [
"08$https://zuikzy.51moca.com/2018/11/23/XoIqsGnIP7IED2LS/playlist.m3u8",
"07$https://zkcdn.yiya520.com/2018/11/21/kJOL42dTmm6VJkqK/playlist.m3u8",
"06$https://zkcdn.yiya520.com/2018/11/21/f8gxIqAchIPyxlAg/playlist.m3u8",
"05$https://zkcdn.yiya520.com/2018/11/21/mTG5GkXpB7yro1sQ/playlist.m3u8",
"04$https://zkcdn.yiya520.com/2018/11/19/HjQAbC0lzzHAusIw/playlist.m3u8",
"03$https://zkcdn.yiya520.com/2018/11/19/qlN7TvZUDDueiefE/playlist.m3u8",
"02$https://zkcdn.yiya520.com/2018/11/18/2P9HAA5H1KvkMgm2/playlist.m3u8",
"01$https://zkcdn.yiya520.com/2018/11/18/KUD3QMMS4UGnNA3Y/playlist.m3u8"
],
"rate": "9.2"
},
"rate": "9.2",
"id": 255
},
{
"key": "mahuazy",
"ids": 21869,
"site": {
"id": 1,
"key": "mahuazy",
"name": "麻花资源",
"api": "http://www.mhapi123.com/inc/ldg_api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
"name": "海上钢琴师",
"detail": {
"last": "2019-12-26 17:45:44",
"id": 21869,
"tid": 10,
"name": "海上钢琴师",
"type": "剧情片",
"pic": "https://mahuapic.com/upload/vod/2019-12-26/201912261577353503.png",
"lang": "英语",
"area": "其它",
"year": 2019,
"state": 0,
"note": "HD",
"actor": "蒂姆·罗斯",
"director": "朱塞佩·托纳多雷",
"dl": {
"dd": {
"_t": "HD$https://mhkuaibo.com/20191226/4s3AkbXZ/index.m3u8$mahua",
"_flag": "mahua"
}
},
"des": "<span style=\"color: rgb(51, 51, 51); font-family: Tahoma, Helvetica, Arial, 微软雅黑, sans-serif; font-size: 14px; line-height: 22px; background-color: rgb(248, 248, 248);\">1900年Virginian号豪华邮轮上一个孤儿被遗弃在头等舱由船上的水手抚养长大取名1900。1900慢慢长大显示出了无师自通的非凡钢琴天赋在船上的乐队表演钢琴每个听过他演奏的人都被深深打动。爵士乐鼻祖杰尼听说了1900的高超技艺专门上船和他比赛最后自叹弗如黯然离去。可惜这一切的事情都发生在海上1900从来不愿踏上陆地直到有一天他爱上了一个女孩情愫在琴键上流淌。他会不会为了爱情踏上陆地开始新的生活用他的琴声惊艳世界他将怎样谱写自己非凡的人生。</span><br />",
"m3u8List": [
"HD$https://mhkuaibo.com/20191226/4s3AkbXZ/index.m3u8$mahua"
],
"rate": "9.3"
},
"rate": "9.3",
"id": 254
},
{
"key": "mahuazy",
"ids": 22567,
"site": {
"id": 1,
"key": "mahuazy",
"name": "麻花资源",
"api": "http://www.mhapi123.com/inc/ldg_api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
"name": "王冠第一季",
"detail": {
"last": "2019-12-19 11:41:40",
"id": 22567,
"tid": 15,
"name": "王冠第一季",
"type": "欧美剧",
"pic": "https://mahuapic.com/upload/vod/2019-12-19/15767269760.jpg",
"lang": "英语",
"area": "美国",
"year": 2016,
"state": 0,
"note": "完结",
"actor": "克莱尔·芙伊,马特·史密斯,约翰·利思戈,凡妮莎·柯比",
"director": "本·卡隆,史蒂芬·戴德利,菲利普·马丁,朱里安·杰拉德",
"dl": {
"dd": {
"_t": "第01集$https://mhyunbo.com/20191218/5vUSpghQ/index.m3u8$mahua#第02集$https://mhyunbo.com/20191218/jC9O5JXb/index.m3u8$mahua#第03集$https://mhyunbo.com/20191218/yHN6zIDc/index.m3u8$mahua#第04集$https://mhyunbo.com/20191218/q47c0tVo/index.m3u8$mahua#第05集$https://mhyunbo.com/20191218/PBckT1Qt/index.m3u8$mahua#第06集$https://mhyunbo.com/20191218/BSy4h1fR/index.m3u8$mahua#第07集$https://mhyunbo.com/20191218/gn2peH5k/index.m3u8$mahua#第08集$https://mhyunbo.com/20191218/2UNcvDq5/index.m3u8$mahua#第09集$https://mhyunbo.com/20191218/ROV7hhdI/index.m3u8$mahua#第10集$https://mhyunbo.com/20191218/VnSKiBc4/index.m3u8$mahua",
"_flag": "mahua"
}
},
"des": "马特·史密斯和约翰·利斯高加盟Netflix剧集《王冠》(The Crown暂译),二人分别饰演菲利普亲王和丘吉尔。剧集剧本由《女王》编剧彼得·摩根创作,首播集由《时时刻刻》导演史蒂芬·戴德利执导,讲述伊丽莎白二世与丘吉尔在二战后,重塑英伦的故事。之前确定由克莱尔·福伊出演伊丽莎白二世。",
"m3u8List": [
"第01集$https://mhyunbo.com/20191218/5vUSpghQ/index.m3u8$mahua",
"第02集$https://mhyunbo.com/20191218/jC9O5JXb/index.m3u8$mahua",
"第03集$https://mhyunbo.com/20191218/yHN6zIDc/index.m3u8$mahua",
"第04集$https://mhyunbo.com/20191218/q47c0tVo/index.m3u8$mahua",
"第05集$https://mhyunbo.com/20191218/PBckT1Qt/index.m3u8$mahua",
"第06集$https://mhyunbo.com/20191218/BSy4h1fR/index.m3u8$mahua",
"第07集$https://mhyunbo.com/20191218/gn2peH5k/index.m3u8$mahua",
"第08集$https://mhyunbo.com/20191218/2UNcvDq5/index.m3u8$mahua",
"第09集$https://mhyunbo.com/20191218/ROV7hhdI/index.m3u8$mahua",
"第10集$https://mhyunbo.com/20191218/VnSKiBc4/index.m3u8$mahua"
],
"rate": "9.2"
},
"rate": "9.2",
"id": 253
},
{
"id": 252,
"key": "mahuazy",
"ids": 29806,
"site": {
"id": 1,
"key": "mahuazy",
"name": "麻花资源",
"api": "https://www.mhapi123.com/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
"name": "最后的棒棒",
"rate": "9.6",
"detail": {
"last": "2020-04-12 15:43:02",
"id": 29806,
"tid": 20,
"name": "最后的棒棒",
"type": "记录片",
"pic": "https://mahuapic.com/upload/vod/2020-04-12/15866774000.jpg",
"lang": "国语",
"area": "大陆",
"year": 2016,
"state": 0,
"note": "完结",
"actor": "何苦",
"director": "何苦",
"dl": {
"dd": {
"_t": "第01集$https://mahua-kb.com/20200412/vpFPIG1f/index.m3u8#第02集$https://mahua-kb.com/20200412/K0b5AvUp/index.m3u8#第03集$https://mahua-kb.com/20200412/tgpvWhFj/index.m3u8#第04集$https://mahua-kb.com/20200412/9mc4bPsO/index.m3u8#第05集$https://mahua-kb.com/20200412/gs0qmble/index.m3u8#第06集$https://mahua-kb.com/20200412/l2eDtPPY/index.m3u8#第07集$https://mahua-kb.com/20200412/7LrOTyqT/index.m3u8#第08集$https://mahua-kb.com/20200412/rnLFz9kO/index.m3u8#第09集$https://mahua-kb.com/20200412/nOTSjrba/index.m3u8#第10集$https://mahua-kb.com/20200412/qrfl8OzL/index.m3u8#第11集$https://mahua-kb.com/20200412/Y4sTsCWm/index.m3u8#第12集$https://mahua-kb.com/20200412/w5L2lXpy/index.m3u8#第13集$https://mahua-kb.com/20200412/Up2AGSWE/index.m3u8",
"_flag": "mahua"
}
},
"des": "改革开放之初,山城重庆特殊的地理环境孕育了一个特殊的行业——山城棒棒军。爬坡上坎,负重前行的三十多年,数十万棒棒大军不仅挑走了汗水浸泡的年华,也挑走了属于自己的年代。癸巳岁末,几个佝偻背影即将道别正在消逝的行业,一名退役中校扛起一根棒棒开始了自己的追寻——辉煌与尴尬,艰韧和无奈,他们的人生无须评说,他们的故事值得铭记。",
"m3u8List": [
"第01集$https://mahua-kb.com/20200412/vpFPIG1f/index.m3u8",
"第02集$https://mahua-kb.com/20200412/K0b5AvUp/index.m3u8",
"第03集$https://mahua-kb.com/20200412/tgpvWhFj/index.m3u8",
"第04集$https://mahua-kb.com/20200412/9mc4bPsO/index.m3u8",
"第05集$https://mahua-kb.com/20200412/gs0qmble/index.m3u8",
"第06集$https://mahua-kb.com/20200412/l2eDtPPY/index.m3u8",
"第07集$https://mahua-kb.com/20200412/7LrOTyqT/index.m3u8",
"第08集$https://mahua-kb.com/20200412/rnLFz9kO/index.m3u8",
"第09集$https://mahua-kb.com/20200412/nOTSjrba/index.m3u8",
"第10集$https://mahua-kb.com/20200412/qrfl8OzL/index.m3u8",
"第11集$https://mahua-kb.com/20200412/Y4sTsCWm/index.m3u8",
"第12集$https://mahua-kb.com/20200412/w5L2lXpy/index.m3u8",
"第13集$https://mahua-kb.com/20200412/Up2AGSWE/index.m3u8"
],
"rate": "9.6"
}
},
{
"id": 251,
"key": "mahuazy",
"ids": 50694,
"site": {
"id": 1,
"key": "mahuazy",
"name": "麻花资源",
"api": "https://www.mhapi123.com/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
"name": "以你的心诠释我的爱",
"index": 2,
"rate": "9.5",
"detail": {
"last": "2020-11-13 09:34:47",
"id": 50694,
"tid": 17,
"name": "以你的心诠释我的爱",
"type": "泰剧",
"pic": "https://mahuapic.com/upload/vod/2020-10-23/16034119330.jpg",
"lang": "泰语",
"area": "泰国",
"year": 2020,
"state": 0,
"note": "更新至04集",
"actor": "克里特·安努艾德奇康,普提蓬·阿萨拉塔纳功",
"director": "纳卢拜·库诺",
"dl": {
"dd": {
"_t": "第01集$https://b.mhqiyi.com/20201022/K4gdEqpu/index.m3u8#第02集$https://b.mhqiyi.com/20201029/h3maf38g/index.m3u8#第03集$https://e.mahua-kb.com/20201105/HVK7wMlM/index.m3u8#第04集$https://b.mhqiyi.com/20201112/pOl6JaA7/index.m3u8",
"_flag": "mahua"
}
},
"des": "这部电视剧是BKPP project的一部分",
"m3u8List": [
"第01集$https://b.mhqiyi.com/20201022/K4gdEqpu/index.m3u8",
"第02集$https://b.mhqiyi.com/20201029/h3maf38g/index.m3u8",
"第03集$https://e.mahua-kb.com/20201105/HVK7wMlM/index.m3u8",
"第04集$https://b.mhqiyi.com/20201112/pOl6JaA7/index.m3u8"
],
"rate": "9.5"
}
},
{
"id": 250,
"key": "niuniucj",
"ids": 20044,
"site": {
@@ -12,6 +266,7 @@
"isActive": 1
},
"name": "此画怎讲",
"rate": "8.1",
"detail": {
"last": "2020-09-23 23:23:36",
"id": 20044,
@@ -72,11 +327,10 @@
"第30集$https://s6.niuniu-baidu.com/2020/09/23/37H4vtEiTXcjSzoa/index.m3u8"
],
"rate": "8.1"
},
"rate": "8.1",
"id": 250
}
},
{
"id": 249,
"key": "niuniucj",
"ids": 4255,
"site": {
@@ -89,6 +343,7 @@
"isActive": 1
},
"name": "紧急呼救第一季",
"rate": "8.6",
"detail": {
"last": "2019-10-10 19:19:15",
"id": 4255,
@@ -129,11 +384,10 @@
"第10集$https://s1.niuniu-baidu.com/20191010/XZjWRMxLgh8nyFlT/index.m3u8"
],
"rate": "8.6"
},
"rate": "8.6",
"id": 249
}
},
{
"id": 248,
"key": "niuniucj",
"ids": 20632,
"site": {
@@ -146,6 +400,7 @@
"isActive": 1
},
"name": "小小世界",
"rate": "9.4",
"detail": {
"last": "2020-10-03 12:00:49",
"id": 20632,
@@ -182,9 +437,7 @@
"第06集$https://s6.niuniu-baidu.com/2020/10/03/U0JFALI1lHOjWCfw/index.m3u8"
],
"rate": "9.4"
},
"rate": "9.4",
"id": 248
}
},
{
"id": 247,
@@ -9238,6 +9491,7 @@
}
},
{
"id": 22,
"key": "mahuazy",
"ids": 20868,
"site": {
@@ -9250,6 +9504,7 @@
"group": "默认"
},
"name": "铁血战士(1987)",
"rate": "7.7",
"detail": {
"last": "2019-11-23 10:59:36",
"id": 20868,
@@ -9275,9 +9530,7 @@
"HD$https://mhbobo.com/20191121/vyWmCGRH/index.m3u8"
],
"rate": "7.7"
},
"rate": "7.7",
"id": 22
}
},
{
"id": 21,

View File

@@ -3,7 +3,7 @@
"id": 1,
"key": "mahuazy",
"name": "麻花资源",
"api": "https://www.mhapi123.com/inc/api.php",
"api": "http://www.mhapi123.com/inc/ldg_api.php",
"download": "",
"group": "默认",
"isActive": true,
@@ -11,9 +11,9 @@
},
{
"id": 2,
"key": "niuniucj",
"name": "牛牛资源",
"api": "http://v.niuniucj.com/inc/api.php",
"key": "1886zy",
"name": "1886 资源",
"api": "http://cj.1886zy.co/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
@@ -21,46 +21,6 @@
},
{
"id": 3,
"key": "88zyw",
"name": "88 影视资源站",
"api": "http://www.88zyw.net/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 4,
"key": "apibdzy",
"name": "百度云资源",
"api": "https://api.apibdzy.com/api.php/provide/vod/at/xml",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 5,
"key": "mbo",
"name": "秒播资源",
"api": "http://caiji.mb77.vip/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 6,
"key": "zuidazy",
"name": "最大资源网",
"api": "http://www.zdziyuan.com/inc/api.php",
"download": "http://www.zdziyuan.com/inc/apidown.php",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 7,
"key": "123ku",
"name": "123 资源",
"api": "http://cj.123ku2.com:12315/inc/api.php",
@@ -69,8 +29,58 @@
"isActive": true,
"status": "可用"
},
{
"id": 4,
"key": "subo988",
"name": "速播资源站",
"api": "https://www.subo988.com/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 5,
"key": "88zyw",
"name": "88 影视资源站",
"api": "http://www.88zyw.net/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"key": "zuidazy",
"id": 6,
"name": "最大资源网",
"api": "http://www.zdziyuan.com/inc/ldg_sea.php",
"download": "http://www.zdziyuan.com/inc/apidown.php",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"key": "mbo",
"id": 7,
"name": "秒播资源",
"api": "http://caiji.mb77.vip/inc/seacmsapi.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 8,
"key": "apibdzy",
"name": "百度云资源",
"api": "https://api.apibdzy.com/api.php/provide/vod/at/xml",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 9,
"key": "okzy",
"name": "OK 资源网",
"api": "http://cj.okzy.tv/inc/api.php",
@@ -80,7 +90,7 @@
"status": "可用"
},
{
"id": 9,
"id": 10,
"key": "kuyunzy",
"name": "酷云资源",
"api": "http://caiji.kuyun98.com/inc/ldg_api.php",
@@ -90,7 +100,7 @@
"status": "可用"
},
{
"id": 10,
"id": 11,
"key": "kubozy",
"name": "酷播资源",
"api": "http://api.kbzyapi.com/inc/api.php",
@@ -100,7 +110,7 @@
"status": "可用"
},
{
"id": 11,
"id": 12,
"key": "yongjiuzy",
"name": "永久资源",
"api": "http://cj.yongjiuzyw.com/inc/api.php",
@@ -110,7 +120,7 @@
"status": "可用"
},
{
"id": 12,
"id": 13,
"key": "rrzy",
"name": "人人资源",
"api": "https://www.rrzyw.cc/api.php/provide/vod/from/rrm3u8/at/xml/",
@@ -120,7 +130,7 @@
"status": "可用"
},
{
"id": 13,
"id": 14,
"key": "bbkdj",
"name": "步步高顶尖资源网",
"api": "http://api.bbkdj.com/api",
@@ -129,16 +139,6 @@
"isActive": true,
"status": "可用"
},
{
"id": 14,
"key": "solezy",
"name": "搜乐资源网",
"api": "https://www.caijizy.vip/api.php/provide/vod/at/xml/",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 15,
"key": "zuixinzy",
@@ -151,66 +151,6 @@
},
{
"id": 16,
"key": "605zy",
"name": "605资源",
"api": "http://www.605zy.net/inc/seacmsapi.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 17,
"key": "subo988",
"name": "速播资源站",
"api": "https://www.subo988.com/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 18,
"key": "1886zy",
"name": "1886 资源",
"api": "http://cj.1886zy.co/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 19,
"key": "doubanzy",
"name": "豆瓣电影资源",
"api": "http://v.1988cj.com/inc/api.php",
"download": "http://v.1988cj.com/inc/apidown.php",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 20,
"key": "135zy",
"name": "135 资源网",
"api": "http://cj.zycjw1.com/inc/api.php",
"download": "http://cj.zycjw1.com/inc/apidown.php",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 21,
"key": "mgtvzy",
"name": "芒果 TV 资源网",
"api": "https://api.shijiapi.com/api.php/provide/vod/at/xml/",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 22,
"key": "209zy",
"name": "209 资源",
"api": "http://cj.1156zy.com/inc/api.php",
@@ -218,55 +158,5 @@
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 23,
"key": "kkzy",
"name": "快快资源",
"api": "https://api.kkzy.tv/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 24,
"key": "wolongzy",
"name": "卧龙资源",
"api": "http://cj.wlzy.tv/inc/api_mac.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 25,
"key": "mokazy",
"name": "魔卡资源网",
"api": "https://cj.heiyap.com/api.php/provide/vod/at/xml/",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 26,
"key": "158zy",
"name": "壹伍捌资源网",
"api": "http://cj.158zyz.net:158/inc/api.php",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
},
{
"id": 27,
"key": "kyzy",
"name": "快影资源站",
"api": "https://www.kyzy.tv/api.php/kyyun/vod/at/xml/",
"download": "",
"group": "默认",
"isActive": true,
"status": "可用"
}
]

View File

@@ -12,7 +12,16 @@ const setting = [
starViewMode: 'picture',
recommendationViewMode: 'picture',
historyViewMode: 'picture',
password: ''
searchViewMode: 'picture',
password: '',
proxy: {
type: 'none',
scheme: '',
url: '',
port: ''
},
allowPassWhenIptvCheck: true,
autocleanWhenIptvCheck: false
}
]
@@ -59,7 +68,7 @@ const localKey = [
},
{
name: 'escape',
desc: '退出全屏',
desc: '退出全屏/精简模式',
key: 'esc'
},
{
@@ -82,6 +91,21 @@ const localKey = [
desc: '跳到视频结束位置',
key: 'end'
},
{
name: 'startPosition',
desc: '标记片头',
key: 'ctrl+home'
},
{
name: 'endPosition',
desc: '标记片尾',
key: 'ctrl+end'
},
{
name: 'clearPosition',
desc: '清除标记',
key: 'ctrl+del'
},
{
name: 'opacityUp',
desc: '透明度调高',
@@ -106,6 +130,11 @@ const localKey = [
name: 'mini',
desc: '进入或退出mini模式',
key: 'alt+m'
},
{
name: 'resetMini',
desc: '重置mini窗口',
key: 'ctrl+0'
}
]

View File

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

View File

@@ -1,11 +1,13 @@
import Vue from 'vue'
import { Message, Button, Table, TableColumn, Tag, Input, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete } from 'element-ui'
import { Message, Button, Table, TableColumn, Tag, Input, InputNumber, Dialog, Form, FormItem, Switch, Select, Option, Checkbox, Autocomplete, Col, Tree, Divider, Progress } from 'element-ui'
import Plugin from 'v-fit-columns'
Vue.use(Button)
Vue.use(Col)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Tag)
Vue.use(Input)
Vue.use(InputNumber)
Vue.use(Dialog)
Vue.use(Form)
Vue.use(FormItem)
@@ -15,4 +17,7 @@ Vue.use(Select)
Vue.use(Option)
Vue.use(Checkbox)
Vue.use(Autocomplete)
Vue.use(Tree)
Vue.use(Divider)
Vue.use(Progress)
Vue.prototype.$message = Message

View File

@@ -1,18 +0,0 @@
import express from 'express'
import cors from 'cors'
const Axios = require('axios')
const app = express()
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.post('/api', async (req, res) => {
const result = await Axios.get(req.body.url)
res.json({
code: 1,
info: result.data
})
})
app.listen(44444)

View File

@@ -1,4 +1,4 @@
import { sites } from '../dexie'
import { sites, setting } from '../dexie'
import axios from 'axios'
import parser from 'fast-xml-parser'
import cheerio from 'cheerio'
@@ -14,9 +14,6 @@ var win = remote.getCurrentWindow()
var session = win.webContents.session
var ElectronProxyAgent = require('electron-proxy-agent')
// use ElectronProxyAgent as http and https globalAgents
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
// 请求超时时限
axios.defaults.timeout = 10000 // 可能使用代理,增长超时
@@ -95,9 +92,10 @@ const zy = {
axios.post(url).then(res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
const jsondata = json.rss === undefined ? json : json.rss
const arr = []
if (json.rss.class) {
for (const i of json.rss.class.ty) {
if (jsondata.class) {
for (const i of jsondata.class.ty) {
const j = {
tid: i._id,
name: i._t
@@ -107,10 +105,10 @@ const zy = {
}
const doc = {
class: arr,
page: json.rss.list._page,
pagecount: json.rss.list._pagecount,
pagesize: json.rss.list._pagesize,
recordcount: json.rss.list._recordcount
page: jsondata.list._page,
pagecount: jsondata.list._pagecount,
pagesize: jsondata.list._pagesize,
recordcount: jsondata.list._recordcount
}
resolve(doc)
}).catch(err => {
@@ -139,7 +137,8 @@ const zy = {
axios.post(url).then(async res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
const videoList = json.rss.list.video
const jsondata = json.rss === undefined ? json : json.rss
const videoList = jsondata.list.video
resolve(videoList)
}).catch(err => {
reject(err)
@@ -166,11 +165,12 @@ const zy = {
axios.post(url).then(async res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
const jsondata = json.rss === undefined ? json : json.rss
const pg = {
page: json.rss.list._page,
pagecount: json.rss.list._pagecount,
pagesize: json.rss.list._pagesize,
recordcount: json.rss.list._recordcount
page: jsondata.list._page,
pagecount: jsondata.list._pagecount,
pagesize: jsondata.list._pagesize,
recordcount: jsondata.list._recordcount
}
resolve(pg)
}).catch(err => {
@@ -194,8 +194,9 @@ const zy = {
axios.post(url, { timeout: 3000 }).then(res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
if (json && json.rss && json.rss.list) {
const videoList = json.rss.list.video
const jsondata = json.rss === undefined ? json : json.rss
if (json && jsondata && jsondata.list) {
const videoList = jsondata.list.video
resolve(videoList)
}
}).catch(err => {
@@ -219,14 +220,16 @@ const zy = {
axios.post(url).then(res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
const videoList = json.rss.list.video
const jsondata = json.rss === undefined ? json : json.rss
const videoList = jsondata.list.video
// Parse m3u8List
var m3u8List = []
const dd = videoList.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
if (i._flag.indexOf('m3u8') >= 0) {
// 如果含有多个视频列表的话, 仅获取m3u8列表
if (i._flag.includes('m3u8')) {
m3u8List = i._t.split('#')
}
}
@@ -253,12 +256,25 @@ const zy = {
return new Promise((resolve, reject) => {
this.getSite(key).then(res => {
const site = res
const url = `${site.download}?ac=videolist&ids=${id}&ct=1`
if (url) {
if (site.download) {
const url = `${site.download}?ac=videolist&ids=${id}&ct=1`
axios.post(url).then(res => {
const data = res.data
const json = parser.parse(data, this.xmlConfig)
const videoList = json.rss.list.video
const jsondata = json.rss === undefined ? json : json.rss
const videoList = jsondata.list.video
// Parse m3u8List
var m3u8List = []
const dd = videoList.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
for (const i of dd) {
m3u8List = i._t.split('#')
}
} else {
m3u8List = dd._t.split('#')
}
videoList.m3u8List = m3u8List
resolve(videoList)
}).catch(err => {
reject(err)
@@ -373,7 +389,27 @@ const zy = {
reject(err)
})
})
},
async proxy () {
return new Promise((resolve, reject) => {
setting.find().then(db => {
if (db && db.proxy && db.proxy.type === 'manual') {
if (db.proxy.scheme && db.proxy.url && db.proxy.port) {
const proxyURL = db.proxy.scheme + '://' + db.proxy.url.trim() + ':' + db.proxy.port.trim()
session.setProxy({ proxyRules: proxyURL })
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
}
} else {
session.setProxy({ proxyRules: 'direct://' })
http.globalAgent = https.globalAgent = new ElectronProxyAgent(session)
}
// 不要删了,留着测试用
// axios.get('https://api.my-ip.io/ip').then(res => console.log(res))
})
})
}
}
zy.proxy()
export default zy

View File

@@ -1,5 +1,5 @@
import { BrowserWindow, ipcMain } from 'electron'
import { autoUpdater } from 'electron-updater'
const { autoUpdater } = require('@imjs/electron-differential-updater')
export function initUpdater (win = BrowserWindow) {
autoUpdater.autoDownload = false
@@ -10,9 +10,14 @@ export function initUpdater (win = BrowserWindow) {
autoUpdater.checkForUpdates()
})
// 主进程监听开始下载事件
ipcMain.on('downloadUpdate', () => {
autoUpdater.downloadUpdate()
})
// 主进程监听退出并安装事件
ipcMain.on('quitAndInstall', () => {
autoUpdater.downloadUpdate()
autoUpdater.quitAndInstall()
})
// 开始检测是否有更新
@@ -36,13 +41,12 @@ export function initUpdater (win = BrowserWindow) {
})
// 下载更新进度
autoUpdater.on('download-progress', (progressObj) => {
win.webContents.send('download-progress', progressObj)
autoUpdater.on('download-progress', (info, progress) => {
win.webContents.send('download-progress', info, progress)
})
// 下载完成并退出安装
// 下载完成
autoUpdater.on('update-downloaded', () => {
win.webContents.send('update-downloaded')
autoUpdater.quitAndInstall()
})
}

View File

@@ -1,535 +0,0 @@
<template>
<div class="mini">
<div class="header">
<div class="left">
<span class="title">
<span v-if="m3u8Arr.length > 1"> {{(video.index + 1)}} </span>{{name}}
</span>
<span class="zy-svg" @click="prevEvent" v-show="video.index > 0">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="backIconTitle">
<title id="backIconTitle">上一集</title>
<path d="M14 14.74L21 19V5l-7 4.26V5L2 12l12 7v-4.26z"></path>
</svg>
</span>
<span class="zy-svg" @click="nextEvent" v-show="video.index < (m3u8Arr.length - 1)">
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="forwardIconTitle">
<title id="forwardIconTitle">下一集</title>
<path d="M10 14.74L3 19V5l7 4.26V5l12 7-12 7v-4.26z"></path>
</svg>
</span>
<span class="opacity" v-show="opacity !== 100">透明度: {{opacity}}</span>
<span class="rate" v-show="rate !== 1">播放速率: {{rate}}</span>
<span class="progress" v-show="progress > 0">播放进度: {{progress}}%</span>
</div>
<div class="right">
<span class="topping" @click="frameClickEvent('top')" title="置顶">
<svg t="1595919317571" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1188" style="width:10px;height:14px"><path d="M43.072 974.72l380.864-301.952 151.936 161.6c0 0 63.424 17.28 67.328-30.72l-3.904-163.584 225.088-259.648 98.048-5.696c0 0 76.928-15.488 21.184-82.752l-275.072-276.928c0 0-74.944-9.6-69.248 59.584l0 75.008L383.552 367.104 225.856 376.64c0 0-57.728 19.2-36.608 69.248l148.16 146.176L43.072 974.72 43.072 974.72z" p-id="1189" :fill="isAlwaysOnTop ? '#555555' : '#ffffff'"></path></svg>
</span>
<span class="min" @click="frameClickEvent('min')" title="最小化">
<svg t="1595917239849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1155" style="width:8px;height:14px"><path d="M0 479.936C0 444.64 28.448 416 64.064 416L959.936 416C995.328 416 1024 444.736 1024 479.936L1024 544.064C1024 579.392 995.552 608 959.936 608L64.064 608C28.672 608 0 579.264 0 544.064L0 479.936Z" p-id="1156" fill="#ffffff"></path></svg>
</span>
<span class="max" @click="frameClickEvent('max')" title="最大化">
<svg t="1595917343956" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1540" style="width:8px;height:14px"><path d="M416 416 64.064 416C28.448 416 0 444.64 0 479.936L0 544.064C0 579.264 28.672 608 64.064 608L416 608 416 959.936C416 995.552 444.64 1024 479.936 1024L544.064 1024C579.264 1024 608 995.328 608 959.936L608 608 959.936 608C995.552 608 1024 579.36 1024 544.064L1024 479.936C1024 444.736 995.328 416 959.936 416L608 416 608 64.064C608 28.448 579.36 0 544.064 0L479.936 0C444.736 0 416 28.672 416 64.064L416 416Z" p-id="1541" fill="#ffffff"></path></svg>
</span>
<span class="close" @click="frameClickEvent('close')" title="退出精简模式">
<svg t="1595917372551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1685" style="width:8px;height:14px"><path d="M511.968 376.224 796.096 92.096C833.536 54.624 894.4 54.624 931.84 92.096 969.312 129.568 969.312 190.4 931.84 227.872L647.744 512 931.84 796.096C969.312 833.568 969.312 894.4 931.84 931.872 894.4 969.344 833.536 969.344 796.096 931.872L511.968 647.744 227.84 931.872C190.4 969.344 129.536 969.344 92.096 931.872 54.624 894.4 54.624 833.568 92.096 796.096L376.224 512 92.096 227.872C54.624 190.4 54.624 129.568 92.096 92.096 129.536 54.624 190.4 54.624 227.84 92.096L511.968 376.224Z" p-id="1686" fill="#ffffff"></path></svg>
</span>
</div>
</div>
<div class="footer">
<div id="xg"></div>
</div>
</div>
</template>
<script>
import zy from '../lib/site/tools'
import { history, setting, shortcut, mini } from '../lib/dexie'
import mt from 'mousetrap'
import 'xgplayer'
import Hls from 'xgplayer-hls.js'
const { remote, ipcRenderer } = require('electron')
const VIDEO_DETAIL_CACHE = {}
export default {
name: 'mini',
data () {
const win = remote.getCurrentWindow()
return {
xg: null,
config: {
id: 'xg',
url: '',
lang: 'zh-cn',
width: '100%',
height: '100%',
autoplay: false,
videoInit: true,
screenShot: true,
keyShortcut: 'off',
crossOrigin: true,
cssFullscreen: true,
defaultPlaybackRate: 1,
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5],
controls: false
},
opacity: 100,
name: '',
video: {},
detail: {},
m3u8Arr: [],
rate: 1,
progress: 0,
isAlwaysOnTop: win.isAlwaysOnTop()
}
},
methods: {
frameClickEvent (e) {
const win = remote.getCurrentWindow()
if (e === 'min') {
win.minimize()
}
if (e === 'max') {
win.isMaximized() ? win.unmaximize() : win.maximize()
}
if (e === 'close') {
ipcRenderer.send('win')
return false
}
if (e === 'top') {
this.isAlwaysOnTop = !this.isAlwaysOnTop
win.setAlwaysOnTop(this.isAlwaysOnTop)
}
},
opacityChange (val) {
const win = remote.getCurrentWindow()
const num = val / 100
win.setOpacity(num)
return false
},
getUrls () {
mini.find().then(res => {
if (res.mode === 'iptv') {
this.xg.src = res.url
this.xg.play()
return
}
this.video = res
this.fetchM3u8List(res).then(m3u8Arr => {
this.m3u8Arr = m3u8Arr
this.xg.src = m3u8Arr[res.index]
if (res.time !== 0 || res.time !== '') {
this.xg.play()
this.xg.once('playing', () => {
this.xg.currentTime = res.time
})
} else {
this.xg.play()
}
this.videoPlaying()
this.xg.once('ended', () => {
if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > res.index)) {
this.video.time = 0
this.video.index++
this.xg.src = m3u8Arr[this.video.index]
this.xg.play()
}
})
})
})
},
fetchM3u8List (info) {
return new Promise((resolve) => {
const cacheKey = info.site + '@' + info.ids
if (VIDEO_DETAIL_CACHE[cacheKey]) {
this.name = VIDEO_DETAIL_CACHE[cacheKey].name
resolve(VIDEO_DETAIL_CACHE[cacheKey].list)
return
}
zy.detail(info.site, info.ids).then(res => {
this.name = res.name
const dd = res.dl.dd
const type = Object.prototype.toString.call(dd)
let m3u8Txt = []
if (type === '[object Array]') {
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])
}
}
VIDEO_DETAIL_CACHE[cacheKey] = {
list: m3u8Arr,
name: res.name
}
resolve(m3u8Arr)
})
})
},
async videoPlaying () {
const db = await history.find({ site: this.video.site, ids: this.video.ids })
if (db) {
db.index = this.video.index
history.update(db.id, db)
} else {
const doc = {
site: this.video.site,
ids: this.video.ids,
name: this.video.name,
index: this.video.index,
time: 0
}
history.add(doc)
}
this.timerEvent()
},
timerEvent () {
this.timer = setInterval(async () => {
const endTime = this.xg.duration
const currentTime = this.xg.currentTime
const progress = (currentTime / endTime) * 100
this.progress = progress.toFixed(2)
const percent = parseFloat((currentTime / endTime).toFixed(2))
const win = remote.getCurrentWindow()
win.setProgressBar(percent)
const db = await history.find({ site: this.video.site, ids: this.video.ids })
if (db) {
const v = db
v.time = this.xg.currentTime
v.index = this.video.index
const id = v.id
delete v.id
history.update(id, v)
}
}, 10000)
},
async prevEvent () {
if (this.video.index === 0) {
this.$message.info('已是第一集.')
return false
}
const db = await history.find({ site: this.video.site, ids: this.video.ids })
if (db) {
const v = db
const id = v.id
v.index--
delete v.id
history.update(id, v).then(e => {
this.xg.src = this.m3u8Arr[v.index]
this.video.index--
})
}
},
async nextEvent () {
if (this.video.index >= this.m3u8Arr.length - 1) {
this.$message.info('已是最后一集.')
return false
}
const db = await history.find({ site: this.video.site, ids: this.video.ids })
if (db) {
const v = db
v.index++
const id = v.id
delete v.id
history.update(id, v).then(e => {
this.xg.src = this.m3u8Arr[v.index]
this.video.index++
})
}
},
playbackRateEvent (e) {
let rate = this.xg.playbackRate
if (rate > 0.25) {
rate = rate + e
this.xg.playbackRate = rate
}
},
mtEvent () {
setting.find().then(res => {
if (res.shortcut) {
shortcut.all().then(res => {
for (const i of res) {
mt.bind(i.key, () => {
this.shortcutEvent(i.name)
})
}
})
}
})
},
shortcutEvent (e) {
if (e === 'playAndPause') {
if (this.xg) {
if (this.xg.paused) {
this.xg.play()
} else {
this.xg.pause()
}
}
return false
}
if (e === 'forward') {
if (this.xg && !this.xg.paused) {
this.xg.currentTime += 5
}
return false
}
if (e === 'back') {
if (this.xg && !this.xg.paused) {
this.xg.currentTime -= 5
}
return false
}
if (e === 'volumeUp') {
if (this.xg && this.xg.volume < 0.9) {
this.xg.volume += 0.1
}
return false
}
if (e === 'volumeDown') {
if (this.xg && this.xg.volume > 0.2) {
this.xg.volume -= 0.1
}
return false
}
if (e === 'mute') {
if (this.xg) {
this.xg.volume = 0
}
return false
}
if (e === 'top') {
const win = remote.getCurrentWindow()
if (win.isAlwaysOnTop()) {
win.setAlwaysOnTop(false)
} else {
win.setAlwaysOnTop(true)
}
return false
}
if (e === 'fullscreen') {
if (this.xg.fullscreen) {
this.xg.exitFullscreen()
} else {
this.xg.getFullscreen(this.xg.root)
}
return false
}
if (e === 'escape') {
if (this.xg.fullscreen) {
this.xg.exitFullscreen()
this.xg.exitCssFullscreen()
}
return false
}
if (e === 'next') {
this.nextEvent()
return false
}
if (e === 'prev') {
this.prevEvent()
return false
}
if (e === 'home') {
if (this.xg && !this.xg.paused) {
this.xg.currentTime = 0
}
return false
}
if (e === 'end') {
if (this.xg && !this.xg.paused) {
const endTime = this.xg.duration
this.xg.currentTime = endTime
}
return false
}
if (e === 'opacityUp') {
const win = remote.getCurrentWindow()
if (this.opacity >= 10) {
this.opacity -= 5
const num = this.opacity / 100
win.setOpacity(num)
}
return false
}
if (e === 'opacityDown') {
const win = remote.getCurrentWindow()
if (this.opacity <= 95) {
this.opacity += 5
const num = this.opacity / 100
win.setOpacity(num)
}
return false
}
if (e === 'playbackRateUp') {
if (this.xg && !this.xg.paused) {
const rate = this.xg.playbackRate
this.xg.playbackRate = rate + 0.25
this.rate = this.xg.playbackRate
}
return false
}
if (e === 'playbackRateDown') {
if (this.xg && !this.xg.paused) {
const rate = this.xg.playbackRate
if (rate > 0.25) {
this.xg.playbackRate = rate - 0.25
this.rate = this.xg.playbackRate
}
}
return false
}
if (e === 'mini') {
ipcRenderer.send('win')
return false
}
}
},
mounted () {
this.xg = new Hls(this.config)
this.mtEvent()
this.getUrls()
},
beforeDestroy () {
clearInterval(this.timer)
}
}
</script>
<style lang="scss">
html,body{
padding: 1px;
margin: 0;
height: 100%;
width: 100%;
overflow: hidden;
background-color: #000;
}
.mini{
-webkit-app-region: drag;
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
.header{
width: 100%;
height: 30px;
min-height: 30px;
display: flex;
justify-content: space-between;
align-items: center;
user-select: none;
.zy-svg{
-webkit-app-region: no-drag;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
svg{
width: 24px;
height: 24px;
stroke: #888;
stroke-width: 1;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
}
.left{
display: flex;
justify-content: flex-start;
align-items: center;
height: 100%;
flex: 1;
.title, .opacity, .rate, .progress{
color: #888;
font-size: 12px;
margin: 0 10px;
}
}
.right{
width: 100px;
height: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
span{
-webkit-app-region: no-drag;
display: flex;
align-items: center;
justify-content: center;
width: 15px;
height: 15px;
text-align: center;
line-height: 15px;
border-radius: 50%;
margin-right: 10px;
cursor: pointer;
opacity: 0.4;
&.topping{
background-color: #f3bab7;
}
&.min{
background-color: #32dc36;
}
&.max{
background-color: #ffbe2a;
}
&.close{
background-color: #ff5f56;
}
&:hover{
animation: heartbeat 3s ease-in-out infinite both;
}
@keyframes heartbeat {
from {
transform: scale(1);
transform-origin: center center;
animation-timing-function: ease-out;
}
10% {
opacity: 1;
transform: scale(0.91);
animation-timing-function: ease-in;
}
17% {
transform: scale(0.98);
animation-timing-function: ease-out;
}
33% {
transform: scale(0.87);
animation-timing-function: ease-in;
}
45% {
transform: scale(1);
animation-timing-function: ease-out;
}
}
}
}
}
.footer{
width: 100%;
flex: 1;
.xgplayer-start{
-webkit-app-region: no-drag;
}
}
}
</style>

View File

@@ -1,10 +0,0 @@
import Vue from 'vue'
import Mini from './Mini'
import 'modern-normalize'
import '../lib/element/index'
Vue.config.productionTip = false
new Vue({
render: h => h(Mini)
}).$mount('#app')

View File

@@ -26,8 +26,8 @@ export default new Vuex.Store({
key: '',
info: {}
},
editSites: {
sites: []
appState: {
windowIsOnTop: false
}
},
getters: {
@@ -46,8 +46,8 @@ export default new Vuex.Store({
getVideo: state => {
return state.video
},
getEditSites: state => {
return state.editSites
getAppState: state => {
return state.appState
}
},
mutations: {
@@ -66,8 +66,8 @@ export default new Vuex.Store({
SET_VIDEO: (state, payload) => {
state.video = payload
},
SET_EDITSITES: (state, payload) => {
state.editSites = payload
SET_APPSTATE: (state, payload) => {
state.appState = payload
}
}
})

View File

@@ -1,7 +1,6 @@
module.exports = {
pages: {
index: 'src/main.js',
mini: 'src/mini/main.js'
index: 'src/main.js'
},
pluginOptions: {
electronBuilder: {

1721
yarn.lock

File diff suppressed because it is too large Load Diff