Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a762ef0e | ||
|
|
aa64c4c452 | ||
|
|
7d94cbd114 | ||
|
|
c7d1d208b8 | ||
|
|
122d4bd10c | ||
|
|
3e26f9cb51 | ||
|
|
9012be09ad | ||
|
|
bd85987e72 | ||
|
|
5c28cf19ed | ||
|
|
4e06e30a5c | ||
|
|
15fa6f3bfb | ||
|
|
1e2bc39bde | ||
|
|
551d11c802 | ||
|
|
c4d8662b51 | ||
|
|
dea6306acb | ||
|
|
420bf12c79 | ||
|
|
9b1995e596 | ||
|
|
b89b56cce4 | ||
|
|
84e2f456f8 | ||
|
|
3e345bf57b | ||
|
|
d70da3dc3e | ||
|
|
8f6a8fef07 | ||
|
|
bda6e32b04 | ||
|
|
51fd2c47da | ||
|
|
5b3a2efc42 | ||
|
|
791febea06 | ||
|
|
402aa62589 | ||
|
|
70b49c8424 | ||
|
|
d22d52a317 | ||
|
|
c936e8479a | ||
|
|
ed8ceffd9c | ||
|
|
22c471332d | ||
|
|
99480f82e7 | ||
|
|
7695b6376d | ||
|
|
3e7eab6d5b | ||
|
|
123579cb1a | ||
|
|
b1b55042b5 | ||
|
|
5549b59730 | ||
|
|
474717c2df | ||
|
|
81c17e5104 | ||
|
|
c8e6e8703c | ||
|
|
74a7d6b35b | ||
|
|
055813eabd | ||
|
|
6311cba1d1 | ||
|
|
8ea52857a5 | ||
|
|
0776147a89 | ||
|
|
75cc6dd3c1 | ||
|
|
ba8312b78c | ||
|
|
5b51f18675 | ||
|
|
307391da4d | ||
|
|
8d1d751a3c | ||
|
|
d64a834c7f | ||
|
|
b5778be234 | ||
|
|
5bf514ffcc | ||
|
|
8e380b6463 | ||
|
|
152b654d41 | ||
|
|
8f10dcfb20 | ||
|
|
d0024458ea | ||
|
|
f6d479de21 | ||
|
|
40cb662e7e | ||
|
|
f271d92149 | ||
|
|
4d391dbe14 | ||
|
|
5b52dad32b | ||
|
|
d74485eaaf | ||
|
|
10baba4241 | ||
|
|
90a2c55059 | ||
|
|
aea794bf29 | ||
|
|
636ef602b1 | ||
|
|
b75de05f09 | ||
|
|
9a14219418 | ||
|
|
2a0afa6ce0 | ||
|
|
f003b1b148 | ||
|
|
55ac770461 | ||
|
|
4505186307 | ||
|
|
9ce1a8ddf6 | ||
|
|
ee1fb8fbe5 | ||
|
|
8bee55f706 | ||
|
|
7c5dd0be8d | ||
|
|
ffee7321a0 | ||
|
|
1ab025ccfe | ||
|
|
0e359be8a3 | ||
|
|
d9122fd24e | ||
|
|
a746de8294 | ||
|
|
f56b81ab9b | ||
|
|
be784c9d60 | ||
|
|
fd715b7cfe | ||
|
|
6979d14f35 | ||
|
|
be6b4b0d78 | ||
|
|
90b466e958 | ||
|
|
4b6485a922 | ||
|
|
7e4f1f9127 | ||
|
|
f8c351aa1e | ||
|
|
65fc90819a | ||
|
|
cf634b55d7 | ||
|
|
b6acaf83e0 | ||
|
|
f21d0a6963 | ||
|
|
367bd0ebd7 | ||
|
|
8f89c3db4d | ||
|
|
c8881bec3b |
@@ -1,2 +1,3 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
|
||||
15
.eslintrc.js
@@ -3,16 +3,15 @@ module.exports = {
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
'extends': [
|
||||
extends: [
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard',
|
||||
'@vue/typescript'
|
||||
'@vue/standard'
|
||||
],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser'
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||
}
|
||||
}
|
||||
|
||||
27
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: release-build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*.*.*
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
|
||||
- run: |
|
||||
yarn
|
||||
yarn release
|
||||
shell: pwsh
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
50
README.md
@@ -1,44 +1,42 @@
|
||||
<p align="center">
|
||||
<img src="https://i.loli.net/2020/01/20/WEj3Yw8rPXqTcHe.png" >
|
||||
<img src="https://i.loli.net/2020/05/07/9kLvPnWVCp7538c.png" >
|
||||
</p>
|
||||
<p align="center">
|
||||
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
||||
<img src="https://forthebadge.com/images/badges/made-with-vue.svg">
|
||||
<p>
|
||||
<p align="center">
|
||||
<img alt="GitHub" src="https://img.shields.io/github/license/Hunlongyu/ZY-Player?style=for-the-badge">
|
||||
<img src="https://github.com/aleen42/badges/raw/master/src/visual_studio_code_flat_square.svg?sanitize=true">
|
||||
<img src="https://github.com/aleen42/badges/raw/master/src/vue_flat_square.svg?sanitize=true">
|
||||
<img src="https://github.com/aleen42/badges/raw/master/src/javascript_flat_square.svg?sanitize=true">
|
||||
<img src="https://github.com/aleen42/badges/raw/master/src/eslint_flat_square.svg?sanitize=true">
|
||||
</p>
|
||||
<p align="center">
|
||||
<img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/Hunlongyu/ZY-Player/total?style=for-the-badge">
|
||||
<img alt="GitHub release (latest by date including pre-releases)" src="https://img.shields.io/github/v/release/Hunlongyu/ZY-Player?include_prereleases&style=for-the-badge">
|
||||
<img alt="GitHub" src="https://img.shields.io/github/license/Hunlongyu/ZY-Player?style=for-the-badge">
|
||||
<img src="https://img.shields.io/github/workflow/status/Hunlongyu/ZY-Player/release-build?style=for-the-badge">
|
||||
<p>
|
||||
|
||||
# ZY Player
|
||||
|
||||
资源播放器, 提供影视资源的浏览,搜索,播放,收藏,查看详情等功能.
|
||||
## ZY Player
|
||||
|
||||
### 截图:
|
||||
主界面 ⬇
|
||||

|
||||
暗黑主题 ⬇
|
||||

|
||||
搜索 ⬇
|
||||

|
||||
搜索结果 ⬇
|
||||

|
||||
详情 ⬇
|
||||

|
||||
播放 ⬇
|
||||

|
||||
收藏 ⬇
|
||||

|
||||
|
||||
### 下载:
|
||||
### 新版内测
|
||||
|
||||
[下载地址](https://github.com/Hunlongyu/ZY-Player/releases)
|
||||
新版本: v0.9.x 已开发完, 现进行内测, [点击查看内测公告](https://github.com/Hunlongyu/ZY-Player/issues/24)
|
||||
|
||||
### 未完成:
|
||||
1. 更新: 手动检测更新
|
||||
2. 图标: 求一个 zy 的logo, 256x256 像素的
|
||||
[点击这里可以查看开发计划](https://github.com/Hunlongyu/ZY-Player/projects/3).
|
||||
|
||||
大家有什么新的需求建议欢迎踊跃提出[点击这里提意见](https://github.com/Hunlongyu/ZY-Player/issues/14)
|
||||
|
||||
1. [Github -- 官方下载](https://github.com/Hunlongyu/ZY-Player/releases)
|
||||
|
||||
2. [蓝奏云 -- 快速下载](https://www.lanzous.com/b04s6a3re) 密码:95px
|
||||
|
||||
#### 截图:
|
||||

|
||||

|
||||

|
||||
|
||||
### 重要:
|
||||
所有资源来自网上, 该软件不参与任何制作, 上传, 储存, 下载等内容. 该软件仅供学习参考, 请于安装后24小时内删除.
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
module.exports = {
|
||||
'presets': [
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
'plugins': [
|
||||
plugins: [
|
||||
[
|
||||
'component',
|
||||
{
|
||||
'libraryName': 'element-ui',
|
||||
'styleLibraryName': 'theme-chalk'
|
||||
libraryName: 'element-ui',
|
||||
styleLibraryName: 'theme-chalk'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 838 B |
|
Before Width: | Height: | Size: 891 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 353 KiB After Width: | Height: | Size: 353 KiB |
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
zyplayer.fun
|
||||
11
docs/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>官网</title>
|
||||
</head>
|
||||
<body>
|
||||
待重建
|
||||
</body>
|
||||
</html>
|
||||
38
docs/player/player.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<title>ZY Player</title>
|
||||
<style type="text/css">
|
||||
html, body {width:100%;height:100%;margin:0;padding:0;overflow:hidden;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mse"></div>
|
||||
<script src="//cdn.jsdelivr.net/npm/xgplayer@1.1.4/browser/index.js" charset="utf-8"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/xgplayer-hls.js/browser/index.js" charset="utf-8"></script><script>
|
||||
function get (name) {
|
||||
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
|
||||
var r = window.location.search.substr(1).match(reg);//search,查询?后面的参数,并匹配正则
|
||||
if (r!=null)return unescape(r[2]); return null;
|
||||
}
|
||||
let link = window.location.href
|
||||
let url = get('url')
|
||||
let player = new HlsJsPlayer({
|
||||
"id": "mse",
|
||||
"url": url,
|
||||
"playsinline": true,
|
||||
"autoplay": true,
|
||||
"fluid": true,
|
||||
"height": window.innerHeight,
|
||||
"width": window.innerWidth,
|
||||
"playbackRate": [ 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3 ],
|
||||
"x5-video-player-type": "h5",
|
||||
"x5-video-player-fullscreen": "true",
|
||||
"x5-video-orientation": "landscape"
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
72
package.json
@@ -1,53 +1,59 @@
|
||||
{
|
||||
"name": "zy",
|
||||
"version": "0.7.20",
|
||||
"author": "Hunlongyu",
|
||||
"description": "ZY Player 资源播放器",
|
||||
"version": "0.9.31",
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "Hunlongyu",
|
||||
"email": "hunlongyu@gmail.com"
|
||||
},
|
||||
"description": "ZY Player 资源播放器",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"dev": "vue-cli-service electron:serve",
|
||||
"electron:build": "vue-cli-service electron:build",
|
||||
"dev": "vue-cli-service electron:serve",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps",
|
||||
"electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten",
|
||||
"bp": "vue-cli-service electron:build --win -p always"
|
||||
"release": "vue-cli-service electron:build -p always"
|
||||
},
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"core-js": "^3.4.4",
|
||||
"axios": "^0.19.2",
|
||||
"core-js": "^3.6.5",
|
||||
"dexie": "^2.0.4",
|
||||
"electron-updater": "^4.2.0",
|
||||
"element-ui": "^2.4.5",
|
||||
"flyio": "^0.6.14",
|
||||
"vue": "^2.6.10",
|
||||
"vue-class-component": "^7.0.2",
|
||||
"vue-property-decorator": "^8.3.0",
|
||||
"vuex": "^3.1.2",
|
||||
"xgplayer": "^2.4.7",
|
||||
"xgplayer-hls.js": "^2.1.6"
|
||||
"electron-updater": "^4.2.5",
|
||||
"element-ui": "^2.13.1",
|
||||
"html2canvas": "^1.0.0-rc.5",
|
||||
"leancloud-storage": "^4.5.3",
|
||||
"macaddress": "^0.2.9",
|
||||
"modern-normalize": "^0.6.0",
|
||||
"qrcode.vue": "^1.7.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-i18n": "^8.17.0",
|
||||
"vuex": "^3.1.3",
|
||||
"xgplayer": "^2.6.19",
|
||||
"xgplayer-hls.js": "^2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
"@vue/cli-plugin-eslint": "^4.1.0",
|
||||
"@vue/cli-plugin-router": "^4.1.0",
|
||||
"@vue/cli-plugin-typescript": "^4.1.0",
|
||||
"@vue/cli-plugin-vuex": "^4.1.0",
|
||||
"@vue/cli-service": "^4.1.0",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"@vue/eslint-config-typescript": "^4.0.0",
|
||||
"@vue/cli-plugin-babel": "~4.3.0",
|
||||
"@vue/cli-plugin-eslint": "~4.3.0",
|
||||
"@vue/cli-plugin-vuex": "~4.3.0",
|
||||
"@vue/cli-service": "~4.3.0",
|
||||
"@vue/eslint-config-standard": "^5.1.2",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"electron": "^7.1.9",
|
||||
"electron-icon-builder": "^1.0.2",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"sass": "^1.23.7",
|
||||
"sass-loader": "^8.0.0",
|
||||
"typescript": "~3.5.3",
|
||||
"vue-cli-plugin-electron-builder": "^1.4.4",
|
||||
"vue-cli-plugin-element": "^1.0.1",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
"electron": "^8.2.5",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"sass": "^1.26.3",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-cli-plugin-electron-builder": "2.0.0-beta.6",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/icon.png
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 42 KiB |
@@ -5,11 +5,20 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>icon.png">
|
||||
<title>ZY Player</title>
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?62aeb2505bfa26a2461d2a7a3b485096";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but zy doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
154
src/App.vue
@@ -1,65 +1,38 @@
|
||||
<template>
|
||||
<el-container id="app" :class="appTheme">
|
||||
<el-header class="Header">
|
||||
<i class="el-icon-minus" @click="clickFrameEvent('min')"></i>
|
||||
<i class="el-icon-plus" @click="clickFrameEvent('max')"></i>
|
||||
<i class="el-icon-close" @click="clickFrameEvent('close')"></i>
|
||||
<el-row class="Header-box">
|
||||
</el-row>
|
||||
</el-header>
|
||||
<el-container>
|
||||
<el-aside class="Aside" width="70px">
|
||||
<el-row class="top">
|
||||
<i :class="Main === 'Film' ? 'el-icon-film active' : 'el-icon-film'" @click="asideMenuClick('Film')"></i>
|
||||
<i :class="Main === 'Search' ? 'el-icon-search active' : 'el-icon-search'" @click="asideMenuClick('Search')"></i>
|
||||
<i :class="Main === 'Player' ? 'el-icon-video-play active' : 'el-icon-video-play'" @click="asideMenuClick('Player')"></i>
|
||||
<i :class="Main === 'Star' ? 'el-icon-star-off active' : 'el-icon-star-off'" @click="asideMenuClick('Star')"></i>
|
||||
</el-row>
|
||||
<el-row class="bottom">
|
||||
<i :class="Main === 'Setting' ? 'el-icon-setting active' : 'el-icon-setting'" @click="asideMenuClick('Setting')"></i>
|
||||
</el-row>
|
||||
</el-aside>
|
||||
<el-main class="Main">
|
||||
<Film v-show="Main === 'Film'" />
|
||||
<Search v-show="Main === 'Search'" />
|
||||
<Player v-show="Main === 'Player'" />
|
||||
<Star v-show="Main === 'Star'" />
|
||||
<Setting v-show="Main === 'Setting'" />
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-drawer class="drawer" :visible.sync="detail.show" :show-close="true" size="90%" :with-header="true" direction="btt" title="详情">
|
||||
<Detail />
|
||||
</el-drawer>
|
||||
</el-container>
|
||||
<div id="app" :class="appTheme">
|
||||
<Aside />
|
||||
<div class="zy-body">
|
||||
<Frame />
|
||||
<Film v-show="view === 'Film'" />
|
||||
<Play v-show="view === 'Play'" />
|
||||
<Star v-show="view === 'Star'" />
|
||||
<Setting v-show="view === 'Setting'" />
|
||||
</div>
|
||||
<transition name="slide">
|
||||
<Detail v-if="detail.show"/>
|
||||
</transition>
|
||||
<transition name="slide">
|
||||
<Share v-if="share.show"/>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import Detail from '@/components/detail.vue'
|
||||
import { mapMutations } from 'vuex'
|
||||
const { ipcRenderer: ipc } = require('electron')
|
||||
export default Vue.extend({
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
data () {
|
||||
return {
|
||||
appTheme: 'theme-light'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
view () {
|
||||
return this.$store.getters.getView
|
||||
},
|
||||
detail: {
|
||||
get () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
set (val) {
|
||||
this.SET_DETAIL(val)
|
||||
}
|
||||
detail () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
share () {
|
||||
return this.$store.getters.getShare
|
||||
},
|
||||
theme () {
|
||||
return this.$store.getters.getTheme
|
||||
@@ -70,71 +43,38 @@ export default Vue.extend({
|
||||
this.changeTheme()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Detail
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_DETAIL', 'SET_MAIN']),
|
||||
clickFrameEvent (e:string) {
|
||||
ipc.send(e)
|
||||
},
|
||||
asideMenuClick (e:string) {
|
||||
this.Main = e
|
||||
},
|
||||
changeTheme () {
|
||||
this.appTheme = `theme-${this.theme}`
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './assets/theme/global.scss';
|
||||
@import './assets/theme/dark.scss';
|
||||
@import './assets/theme/light.scss';
|
||||
*{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,body{
|
||||
@import './assets/scss/theme.scss';
|
||||
html, body, #app{
|
||||
height: 100%;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#app{
|
||||
#app {
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', SimSun, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.Header{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
padding: 0;
|
||||
i{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
-webkit-app-region: no-drag;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.Aside{
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
text-align: center;
|
||||
i{
|
||||
-webkit-app-region: no-drag;
|
||||
font-size: 32px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
line-height: 70px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.Main{
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
.zy-body{
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
BIN
src/assets/image/alipay.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 80 KiB |
BIN
src/assets/image/green.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 75 KiB |
BIN
src/assets/image/logo.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
src/assets/image/wepay.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |
217
src/assets/scss/style.scss
Normal file
@@ -0,0 +1,217 @@
|
||||
// svg
|
||||
.zy-svg{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
svg{
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke-width: 1;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
fill: none;
|
||||
}
|
||||
}
|
||||
|
||||
// select
|
||||
.zy-select{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
.vs-placeholder{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
&::after{
|
||||
display: inline-block;
|
||||
margin-left: .255em;
|
||||
vertical-align: .255em;
|
||||
content: "";
|
||||
border-top: .3em solid;
|
||||
border-right: .3em solid transparent;
|
||||
border-bottom: 0;
|
||||
border-left: .3em solid transparent;
|
||||
}
|
||||
}
|
||||
.vs-options{
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
ul{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
li{
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding-left: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// table
|
||||
.zy-table{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
.tHead{
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid;
|
||||
padding: 0 5px 0 0;
|
||||
font-weight: 600;
|
||||
span{
|
||||
display: flex;
|
||||
width: 180px;
|
||||
font-size: 16px;
|
||||
&.name{
|
||||
flex: 1;
|
||||
padding-left: 15px;
|
||||
}
|
||||
&.type{
|
||||
width: 120px;
|
||||
}
|
||||
&.from{
|
||||
width: 120px;
|
||||
}
|
||||
&.operate{
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tBody{
|
||||
flex: 1;
|
||||
overflow-y: scroll;
|
||||
border-bottom: 1px solid;
|
||||
ul{
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
li{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid;
|
||||
cursor: pointer;
|
||||
span{
|
||||
display: flex;
|
||||
width: 180px;
|
||||
font-size: 13px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
&.name{
|
||||
flex: 1;
|
||||
padding-left: 15px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.type{
|
||||
width: 120px;
|
||||
}
|
||||
&.from{
|
||||
width: 120px;
|
||||
}
|
||||
&.operate{
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tFooter{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
padding-right: 10px;
|
||||
.tFooter-span{
|
||||
padding-left: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scroll
|
||||
.zy-scroll{
|
||||
&::-webkit-scrollbar{
|
||||
width: 5px;
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
// loading
|
||||
.zy-loading{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.loader {
|
||||
font-size: 8px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
animation: load4 1.3s infinite linear;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
@keyframes load4 {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 -3em 0 0.2em, 2em -2em 0 0em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 0;
|
||||
}
|
||||
12.5% {
|
||||
box-shadow: 0 -3em 0 0, 2em -2em 0 0.2em, 3em 0 0 0, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
25% {
|
||||
box-shadow: 0 -3em 0 -0.5em, 2em -2em 0 0, 3em 0 0 0.2em, 2em 2em 0 0, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
37.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 0, 2em 2em 0 0.2em, 0 3em 0 0em, -2em 2em 0 -1em, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 0em, 0 3em 0 0.2em, -2em 2em 0 0, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
62.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 0, -2em 2em 0 0.2em, -3em 0 0 0, -2em -2em 0 -1em;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 0em -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0.2em, -2em -2em 0 0;
|
||||
}
|
||||
87.5% {
|
||||
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/assets/scss/theme.scss
Normal file
@@ -0,0 +1,61 @@
|
||||
:root{
|
||||
// light
|
||||
--l-c-0: #823aa0;
|
||||
--l-c-1: #823aa011;
|
||||
--l-c-2: #823aa022;
|
||||
--l-c-3: #823aa033;
|
||||
--l-c-5: #823aa055;
|
||||
--l-c-8: #823aa088;
|
||||
--l-c-9: #823aa099;
|
||||
--l-fc-1: #808695;
|
||||
--l-fc-2: #332f5c;
|
||||
--l-fc-3: #823aa0;
|
||||
--l-bgc-1: #ffffff;
|
||||
--l-bgc-2: #f2f6f9;
|
||||
--l-bsc: 0 3px 1px -2px #8e8da233, 0 2px 2px 0 #8e8da224, 0 1px 5px 0 #8e8da21f;
|
||||
--l-bsc-2: 0 -4px 23px 0 #8e8da233;
|
||||
--l-bsc-hover: 0 14px 26px -12px #8e8da26b, 0 4px 23px 0 #8e8da21f, 0 8px 10px -5px #8e8da233;
|
||||
--l-bsc-scroll: inset 0 0 5px #823aa005;
|
||||
|
||||
// dark
|
||||
--d-c-0: #38dd77;
|
||||
--d-c-1: #38dd7711;
|
||||
--d-c-2: #38dd7722;
|
||||
--d-c-3: #38dd7733;
|
||||
--d-c-5: #38dd7755;
|
||||
--d-c-8: #38dd7788;
|
||||
--d-c-9: #38dd7799;
|
||||
--d-fc-1: #808695;
|
||||
--d-fc-2: #acacac;
|
||||
--d-fc-3: #38dd77;
|
||||
--d-bgc-1: #222222;
|
||||
--d-bgc-2: #2f2f2f;
|
||||
--d-bsc: 0 3px 1px -2px #38dd7733, 0 2px 2px 0 #38dd7722, 0 1px 5px 0 #38dd7711;
|
||||
--d-bsc-2: 0 -4px 23px 0 #38dd7733;
|
||||
--d-bsc-hover: 0 14px 26px -12px #38dd7733, 0 4px 23px 0 #38dd7722, 0 8px 10px -5px #38dd7711;
|
||||
--d-bsc-scroll: inset 0 0 5px #38dd7705;
|
||||
|
||||
// green
|
||||
--g-c-0: #EAEF9D;
|
||||
--g-c-1: #EAEF9D11;
|
||||
--g-c-2: #EAEF9D22;
|
||||
--g-c-3: #EAEF9D33;
|
||||
--g-c-5: #EAEF9D55;
|
||||
--g-c-8: #EAEF9D88;
|
||||
--g-c-9: #EAEF9D99;
|
||||
--g-fc-1: #80B155;
|
||||
--g-fc-2: #C1D95CAA;
|
||||
--g-fc-3: #C1D95C;
|
||||
--g-bgc-1: #336A29;
|
||||
--g-bgc-2: #498428;
|
||||
--g-bsc: 0 3px 1px -2px #C1D95C33, 0 2px 2px 0 #C1D95C22, 0 1px 5px 0 #C1D95C11;
|
||||
--g-bsc-2: 0 -4px 23px 0 #C1D95C33;
|
||||
--g-bsc-hover: 0 14px 26px -12px #C1D95C33, 0 4px 23px 0 #C1D95C22, 0 8px 10px -5px #C1D95C11;
|
||||
--g-bsc-scroll: inset 0 0 5px #C1D95C05;
|
||||
}
|
||||
|
||||
@import './theme/light.scss';
|
||||
@import './theme/dark.scss';
|
||||
@import './theme/green.scss';
|
||||
|
||||
@import './style.scss';
|
||||
346
src/assets/scss/theme/dark.scss
Normal file
@@ -0,0 +1,346 @@
|
||||
.theme-dark{
|
||||
background-color: var(--d-bgc-1);
|
||||
.el-pagination{
|
||||
background-color: var(--d-bgc-1);
|
||||
color: var(--d-fc-1);
|
||||
.el-pagination__total, .el-pagination__jump, .el-input__inner{
|
||||
color: var(--d-fc-1);
|
||||
background-color: var(--d-bgc-1);
|
||||
}
|
||||
.el-input__inner{
|
||||
border-color: var(--d-c-3);
|
||||
}
|
||||
.el-pager{
|
||||
.number{
|
||||
background-color: var(--d-bgc-1);
|
||||
}
|
||||
.number:hover{
|
||||
color: var(--d-c-8);
|
||||
}
|
||||
.active{
|
||||
color: var(--d-c-9);
|
||||
}
|
||||
}
|
||||
.more, .btn-next, .btn-prev{
|
||||
background-color: var(--d-bgc-1);
|
||||
&:hover{
|
||||
color: var(--d-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-select{
|
||||
color: var(--d-fc-1);
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--d-bsc-hover);
|
||||
}
|
||||
.vs-options{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
ul{
|
||||
li{
|
||||
&:hover{
|
||||
background-color: var(--d-c-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--d-fc-2);
|
||||
.tHead{
|
||||
background-color: var(--d-bgc-1);
|
||||
border-bottom-color: var(--d-c-3);
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--d-c-3);
|
||||
ul{
|
||||
li{
|
||||
border-bottom-color: var(--d-c-2);
|
||||
&:hover{
|
||||
animation: d-tableHoverAni 0.2s ease both;
|
||||
@keyframes d-tableHoverAni {
|
||||
to{
|
||||
box-shadow: var(--d-bsc-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
span{
|
||||
&.btn:hover{
|
||||
color: var(--d-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tFooter{
|
||||
.tFooter-span{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-scroll{
|
||||
&:hover{
|
||||
&::-webkit-scrollbar-thumb {
|
||||
box-shadow: var(--d-bsc-scroll);
|
||||
background: var(--d-c-3);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: var(--d-bsc-scroll);
|
||||
background: var(--bgc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-loading{
|
||||
.loader{
|
||||
color: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
.zy-body{
|
||||
background-color: var(--d-bgc-2);
|
||||
}
|
||||
.aside{
|
||||
.zy-svg{
|
||||
svg{
|
||||
stroke: var(--d-c-0);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-2);
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--d-c-0);
|
||||
stroke-width: 2;
|
||||
fill: var(--d-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame{
|
||||
span{
|
||||
&.min{
|
||||
background-color: #ffbe2a;
|
||||
}
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
color: var(--d-fc-1) !important;
|
||||
background-color:var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc-2);
|
||||
.detail-content{
|
||||
.detail-close{
|
||||
svg{
|
||||
stroke-width: 1;
|
||||
stroke: var(--d-c-8);
|
||||
&:hover{
|
||||
stroke-width: 2px;
|
||||
stroke: var(--d-c-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail-body{
|
||||
.info, .desc, .m3u8_urls, .mp4_urls{
|
||||
border-color: var(--d-c-2);
|
||||
}
|
||||
.m3u8_urls, .mp4_urls{
|
||||
.box{
|
||||
span{
|
||||
border-color: var(--d-c-5);
|
||||
&:hover{
|
||||
color: var(--d-fc-2);
|
||||
background-color: var(--d-c-1);
|
||||
border-color: var(--d-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.film{
|
||||
.top{
|
||||
.search{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--d-bsc-hover);
|
||||
}
|
||||
svg{
|
||||
stroke: var(--d-c-0);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
.search-box{
|
||||
background-color: var(--d-bgc-1);
|
||||
}
|
||||
&.active{
|
||||
box-shadow: var(--d-bsc-hover);
|
||||
svg{
|
||||
stroke-width: 1.5;
|
||||
fill: var(--d-c-2);
|
||||
}
|
||||
}
|
||||
input{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.middle{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
}
|
||||
}
|
||||
.play{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
span{
|
||||
svg{
|
||||
stroke: var(--d-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
&:hover{
|
||||
svg{
|
||||
stroke: var(--d-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--d-c-2);
|
||||
}
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--d-c-9);
|
||||
stroke-width: 2;
|
||||
fill: var(--d-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list{
|
||||
border: 1px solid var(--d-c-3);
|
||||
background-color: var(--d-bgc-2);
|
||||
.list-top{
|
||||
color: var(--d-fc-2);
|
||||
.list-top-close{
|
||||
svg{
|
||||
stroke: var(--d-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
&:hover{
|
||||
stroke: var(--d-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--d-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-body{
|
||||
.list-item{
|
||||
li{
|
||||
color: var(--d-fc-1);
|
||||
&.active{
|
||||
background-color: var(--d-c-2);
|
||||
color: var(--d-fc-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
li{
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--d-c-2);
|
||||
.title{
|
||||
color: var(--d-fc-3);
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--d-c-3);
|
||||
.detail-delete{
|
||||
display: inline-block;
|
||||
color: var(--d-fc-2);
|
||||
}
|
||||
}
|
||||
.detail-delete{
|
||||
&:hover{
|
||||
background-color: var(--d-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.play-mask{
|
||||
background-color: var(--d-bgc-1);
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
}
|
||||
.star{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
}
|
||||
.setting{
|
||||
background-color: var(--d-bgc-1);
|
||||
box-shadow: var(--d-bsc);
|
||||
.info{
|
||||
a{
|
||||
color: var(--d-fc-1);
|
||||
&:hover{
|
||||
color: var(--d-fc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
.theme-item{
|
||||
box-shadow: var(--d-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--d-bsc-hover);
|
||||
.theme-name{
|
||||
color: var(--d-fc-2)
|
||||
}
|
||||
}
|
||||
.theme-name{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.qrcode{
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
.qrcode-item{
|
||||
box-shadow: var(--d-bsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.share{
|
||||
background-color: var(--d-bgc-1);
|
||||
color: var(--d-fc-1);
|
||||
border: 1px solid var(--d-c-8);
|
||||
.right{
|
||||
color: var(--d-fc-1);
|
||||
.tops{
|
||||
color: var(--d-fc-2);
|
||||
}
|
||||
}
|
||||
.share-mask{
|
||||
background-color: var(--d-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
346
src/assets/scss/theme/green.scss
Normal file
@@ -0,0 +1,346 @@
|
||||
.theme-green{
|
||||
background-color: var(--g-bgc-1);
|
||||
.el-pagination{
|
||||
background-color: var(--g-bgc-1);
|
||||
color: var(--g-fc-1);
|
||||
.el-pagination__total, .el-pagination__jump, .el-input__inner{
|
||||
color: var(--g-fc-1);
|
||||
background-color: var(--g-bgc-1);
|
||||
}
|
||||
.el-input__inner{
|
||||
border-color: var(--g-c-3);
|
||||
}
|
||||
.el-pager{
|
||||
.number{
|
||||
background-color: var(--g-bgc-1);
|
||||
}
|
||||
.number:hover{
|
||||
color: var(--g-c-8);
|
||||
}
|
||||
.active{
|
||||
color: var(--g-c-9);
|
||||
}
|
||||
}
|
||||
.more, .btn-next, .btn-prev{
|
||||
background-color: var(--g-bgc-1);
|
||||
&:hover{
|
||||
color: var(--g-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-select{
|
||||
color: var(--g-fc-1);
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--g-bsc-hover);
|
||||
}
|
||||
.vs-options{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
ul{
|
||||
li{
|
||||
&:hover{
|
||||
background-color: var(--g-c-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--g-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--g-fc-2);
|
||||
.tHead{
|
||||
background-color: var(--g-bgc-1);
|
||||
border-bottom-color: var(--g-c-3);
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--g-c-3);
|
||||
ul{
|
||||
li{
|
||||
border-bottom-color: var(--g-c-2);
|
||||
&:hover{
|
||||
animation: d-tableHoverAni 0.2s ease both;
|
||||
@keyframes d-tableHoverAni {
|
||||
to{
|
||||
box-shadow: var(--g-bsc-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
span{
|
||||
&.btn:hover{
|
||||
color: var(--g-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tFooter{
|
||||
.tFooter-span{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-scroll{
|
||||
&:hover{
|
||||
&::-webkit-scrollbar-thumb {
|
||||
box-shadow: var(--g-bsc-scroll);
|
||||
background: var(--g-c-3);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: var(--g-bsc-scroll);
|
||||
background: var(--bgc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-loading{
|
||||
.loader{
|
||||
color: var(--g-c-3);
|
||||
}
|
||||
}
|
||||
.zy-body{
|
||||
background-color: var(--g-bgc-2);
|
||||
}
|
||||
.aside{
|
||||
.zy-svg{
|
||||
svg{
|
||||
stroke: var(--g-c-0);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--g-c-2);
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--g-c-0);
|
||||
stroke-width: 2;
|
||||
fill: var(--g-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame{
|
||||
span{
|
||||
&.min{
|
||||
background-color: #ffbe2a;
|
||||
}
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
color: var(--g-fc-1);
|
||||
background-color:var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc-2);
|
||||
.detail-content{
|
||||
.detail-close{
|
||||
svg{
|
||||
stroke-width: 1;
|
||||
stroke: var(--g-c-8);
|
||||
&:hover{
|
||||
stroke-width: 2px;
|
||||
stroke: var(--g-c-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail-body{
|
||||
.info, .desc, .m3u8_urls, .mp4_urls{
|
||||
border-color: var(--g-c-2);
|
||||
}
|
||||
.m3u8_urls, .mp4_urls{
|
||||
.box{
|
||||
span{
|
||||
border-color: var(--g-c-5);
|
||||
&:hover{
|
||||
color: var(--g-fc-2);
|
||||
background-color: var(--g-c-1);
|
||||
border-color: var(--g-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.film{
|
||||
.top{
|
||||
.search{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--g-bsc-hover);
|
||||
}
|
||||
svg{
|
||||
stroke: var(--g-c-0);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
.search-box{
|
||||
background-color: var(--g-bgc-1);
|
||||
}
|
||||
&.active{
|
||||
box-shadow: var(--g-bsc-hover);
|
||||
svg{
|
||||
stroke-width: 1.5;
|
||||
fill: var(--g-c-2);
|
||||
}
|
||||
}
|
||||
input{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.middle{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
}
|
||||
}
|
||||
.play{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
span{
|
||||
svg{
|
||||
stroke: var(--g-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
&:hover{
|
||||
svg{
|
||||
stroke: var(--g-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--g-c-2);
|
||||
}
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--g-c-9);
|
||||
stroke-width: 2;
|
||||
fill: var(--g-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list{
|
||||
border: 1px solid var(--g-c-3);
|
||||
background-color: var(--g-bgc-2);
|
||||
.list-top{
|
||||
color: var(--g-fc-2);
|
||||
.list-top-close{
|
||||
svg{
|
||||
stroke: var(--g-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
&:hover{
|
||||
stroke: var(--g-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--g-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-body{
|
||||
.list-item{
|
||||
li{
|
||||
color: var(--g-fc-1);
|
||||
&.active{
|
||||
background-color: var(--g-c-2);
|
||||
color: var(--g-fc-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
li{
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--g-c-2);
|
||||
.title{
|
||||
color: var(--g-fc-3);
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--g-c-3);
|
||||
.detail-delete{
|
||||
display: inline-block;
|
||||
color: var(--g-fc-2);
|
||||
}
|
||||
}
|
||||
.detail-delete{
|
||||
&:hover{
|
||||
background-color: var(--g-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.play-mask{
|
||||
background-color: var(--g-bgc-1);
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
}
|
||||
.star{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
}
|
||||
.setting{
|
||||
background-color: var(--g-bgc-1);
|
||||
box-shadow: var(--g-bsc);
|
||||
.info{
|
||||
a{
|
||||
color: var(--g-fc-1);
|
||||
&:hover{
|
||||
color: var(--g-fc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
.theme-item{
|
||||
box-shadow: var(--g-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--g-bsc-hover);
|
||||
.theme-name{
|
||||
color: var(--g-fc-2)
|
||||
}
|
||||
}
|
||||
.theme-name{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.qrcode{
|
||||
.title{
|
||||
color: var(--g-fc-1);
|
||||
}
|
||||
.qrcode-item{
|
||||
box-shadow: var(--g-bsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.share{
|
||||
background-color: var(--g-bgc-1);
|
||||
color: var(--g-fc-1);
|
||||
border: 1px solid var(--g-c-8);
|
||||
.right{
|
||||
color: var(--g-fc-1);
|
||||
.tops{
|
||||
color: var(--g-fc-2);
|
||||
}
|
||||
}
|
||||
.share-mask{
|
||||
background-color: var(--g-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
340
src/assets/scss/theme/light.scss
Normal file
@@ -0,0 +1,340 @@
|
||||
.theme-light{
|
||||
background-color: var(--l-bgc-1);
|
||||
.el-pagination{
|
||||
color: var(--l-fc-1);
|
||||
.el-pagination__total, .el-pagination__jump, .el-input__inner{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
.el-pager{
|
||||
.number:hover{
|
||||
color: var(--l-c-8);
|
||||
}
|
||||
.active{
|
||||
color: var(--l-c-9);
|
||||
}
|
||||
}
|
||||
.more, .btn-next, .btn-prev{
|
||||
&:hover{
|
||||
color: var(--l-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-select{
|
||||
color: var(--l-fc-1);
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--l-bsc-hover);
|
||||
}
|
||||
.vs-options{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
ul{
|
||||
li{
|
||||
&:hover{
|
||||
background-color: var(--l-c-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--l-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-table{
|
||||
color: var(--l-fc-2);
|
||||
.tHead{
|
||||
background-color: var(--l-bgc-1);
|
||||
border-bottom-color: var(--l-c-3);
|
||||
}
|
||||
.tBody{
|
||||
border-bottom-color: var(--l-c-3);
|
||||
ul{
|
||||
li{
|
||||
border-bottom-color: var(--l-c-2);
|
||||
&:hover{
|
||||
animation: l-tableHoverAni 0.2s ease both;
|
||||
@keyframes l-tableHoverAni {
|
||||
to{
|
||||
box-shadow: var(--l-bsc-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
span{
|
||||
&.btn:hover{
|
||||
color: var(--l-fc-3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tFooter{
|
||||
.tFooter-span{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-scroll{
|
||||
&:hover{
|
||||
&::-webkit-scrollbar-thumb {
|
||||
box-shadow: var(--l-bsc-scroll);
|
||||
background: var(--l-c-3);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: var(--l-bsc-scroll);
|
||||
background: var(--bgc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.zy-loading{
|
||||
.loader{
|
||||
color: var(--l-c-3);
|
||||
}
|
||||
}
|
||||
.zy-body{
|
||||
background-color: var(--l-bgc-2);
|
||||
}
|
||||
.aside{
|
||||
.zy-svg{
|
||||
svg{
|
||||
stroke: var(--l-c-0);
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--l-c-2);
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--l-c-0);
|
||||
stroke-width: 2;
|
||||
fill: var(--l-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame{
|
||||
span{
|
||||
&.min{
|
||||
background-color: #ffbe2a;
|
||||
}
|
||||
&.close{
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
color: var(--l-fc-1);
|
||||
background-color:var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc-2);
|
||||
.detail-content{
|
||||
.detail-close{
|
||||
svg{
|
||||
stroke-width: 1;
|
||||
stroke: var(--l-c-8);
|
||||
&:hover{
|
||||
stroke-width: 2px;
|
||||
stroke: var(--l-c-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail-body{
|
||||
.info, .desc, .m3u8_urls, .mp4_urls{
|
||||
border-color: var(--l-c-2);
|
||||
}
|
||||
.m3u8_urls, .mp4_urls{
|
||||
.box{
|
||||
span{
|
||||
border-color: var(--l-c-5);
|
||||
&:hover{
|
||||
color: var(--l-fc-2);
|
||||
background-color: var(--l-c-1);
|
||||
border-color: var(--l-c-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.film{
|
||||
.top{
|
||||
.search{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--l-bsc-hover);
|
||||
}
|
||||
svg{
|
||||
stroke: #823aa099;
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
.search-box{
|
||||
background-color: none;
|
||||
}
|
||||
&.active{
|
||||
box-shadow: var(--l-bsc-hover);
|
||||
svg{
|
||||
stroke-width: 1.5;
|
||||
fill: var(--l-c-2);
|
||||
}
|
||||
}
|
||||
input{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.middle{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
}
|
||||
}
|
||||
.play{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
.title{
|
||||
color: var(--d-fc-1);
|
||||
}
|
||||
.box{
|
||||
.more{
|
||||
span{
|
||||
svg{
|
||||
stroke: var(--l-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
}
|
||||
&:hover{
|
||||
svg{
|
||||
stroke: var(--l-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--l-c-2);
|
||||
}
|
||||
}
|
||||
&.active{
|
||||
svg{
|
||||
stroke: var(--l-c-9);
|
||||
stroke-width: 2;
|
||||
fill: var(--l-c-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mask{
|
||||
background-color: var(--l-bgc-1);
|
||||
}
|
||||
}
|
||||
.list{
|
||||
border: 1px solid var(--l-c-3);
|
||||
background-color: var(--l-bgc-2);
|
||||
.list-top{
|
||||
color: var(--l-fc-2);
|
||||
.list-top-close{
|
||||
svg{
|
||||
stroke: var(--l-c-5);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
&:hover{
|
||||
stroke: var(--l-c-8);
|
||||
stroke-width: 1.5;
|
||||
fill: var(--l-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-body{
|
||||
.list-item{
|
||||
li{
|
||||
color: var(--l-fc-1);
|
||||
&.active{
|
||||
background-color: var(--l-c-2);
|
||||
color: var(--l-fc-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-history{
|
||||
li{
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
&.active{
|
||||
background-color: var(--l-c-2);
|
||||
.title{
|
||||
color: var(--l-fc-3);
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
background-color: var(--l-c-3);
|
||||
.detail-delete{
|
||||
display: inline-block;
|
||||
color: var(--l-fc-2);
|
||||
}
|
||||
}
|
||||
.detail-delete{
|
||||
&:hover{
|
||||
background-color: var(--l-c-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.play-mask{
|
||||
background-color: var(--l-bgc-1);
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
}
|
||||
.star{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
}
|
||||
.setting{
|
||||
background-color: var(--l-bgc-1);
|
||||
box-shadow: var(--l-bsc);
|
||||
.info{
|
||||
a{
|
||||
color: var(--l-fc-1);
|
||||
&:hover{
|
||||
color: var(--l-fc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
.theme-item{
|
||||
box-shadow: var(--l-bsc);
|
||||
&:hover{
|
||||
box-shadow: var(--l-bsc-hover);
|
||||
.theme-name{
|
||||
color: var(--l-fc-2)
|
||||
}
|
||||
}
|
||||
.theme-name{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.qrcode{
|
||||
.title{
|
||||
color: var(--l-fc-1);
|
||||
}
|
||||
.qrcode-item{
|
||||
box-shadow: var(--l-bsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.share{
|
||||
background-color: var(--l-bgc-1);
|
||||
color: var(--l-fc-1);
|
||||
border: 1px solid var(--l-c-8);
|
||||
.right{
|
||||
color: var(--l-fc-1);
|
||||
.tops{
|
||||
color: var(--l-fc-2);
|
||||
}
|
||||
}
|
||||
.share-mask{
|
||||
background-color: var(--l-bgc-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
.theme-dark{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
.el-button, input, select, .el-select{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
border-color: var(--d-bdc);
|
||||
}
|
||||
.el-button--text{
|
||||
border: none;
|
||||
}
|
||||
.el-tabs__item, .el-tabs__nav-wrap::after{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
border-color: var(--d-dbc);
|
||||
}
|
||||
.el-table, .el-table th, .el-table tr,
|
||||
.el-table--striped .el-table__body tr.el-table__row--striped td,
|
||||
.el-table--enable-row-hover .el-table__body tr:hover>td,
|
||||
.el-table td, .el-table th.is-leaf{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
border-color: var(--d-dbc);
|
||||
}
|
||||
.el-pagination, .el-pagination .el-pagination__total, .el-pagination .el-pagination__jump,
|
||||
.el-pagination .btn-next, .el-pagination .btn-prev, .el-pager li{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
}
|
||||
.el-input__inner,
|
||||
.el-input-group__append, .el-input-group__prepend{
|
||||
background-color: var(--d-bgc);
|
||||
border-color: var(--d-dbc);
|
||||
}
|
||||
.el-select-dropdown{
|
||||
color: var(--d-c);
|
||||
}
|
||||
.el-drawer{
|
||||
background-color: var(--d-bgc) !important;
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
.Header, .Aside{
|
||||
i{
|
||||
color: var(--d-icon);
|
||||
&:hover{
|
||||
color: var(--d-icon-h);
|
||||
background-color: var(--d-bgc-h);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Aside{
|
||||
i{
|
||||
&.active{
|
||||
color: var(--d-icon-h);
|
||||
background-color: var(--d-bgc-h);
|
||||
border-left: 4px solid var(--d-icon-h);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Main{
|
||||
.film, .search, .star, .player{
|
||||
.table-box{
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px var(--d-bdc);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--d-icon);
|
||||
outline: 1px solid var(--d-icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
.setting{
|
||||
.el-link, .card{
|
||||
color: var(--d-c);
|
||||
background-color: var(--d-bgc);
|
||||
border-color: var(--d-bdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
color: var(--d-c);
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px var(--d-bdc);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--d-icon);
|
||||
outline: 1px solid var(--d-icon);
|
||||
}
|
||||
.box, .info, .urls{
|
||||
border: 1px solid var(--d-bdc);
|
||||
}
|
||||
.vodInfo{
|
||||
li, span, a{
|
||||
color: var(--d-c);
|
||||
}
|
||||
label{
|
||||
color: #f90;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
:root{
|
||||
// light
|
||||
--l-c: #808695;
|
||||
--l-c-h: #515a6e;
|
||||
--l-icon: #C0C4CC;
|
||||
--l-icon-h: #515a6e;
|
||||
--l-bgc: #ffffff;
|
||||
--l-bgc-h: #efefef;
|
||||
--l-bdc: #dcdee2;
|
||||
|
||||
// dark
|
||||
--d-c: #919191;
|
||||
--d-c-h: #454545;
|
||||
--d-icon: #919191;
|
||||
--d-icon-h: #919191;
|
||||
--d-bgc: #242424;
|
||||
--d-bgc-h: #454545;
|
||||
--d-bdc: #7a7a7a;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
.theme-light{
|
||||
color: var(--l-c);
|
||||
background-color: var(--l-bgc);
|
||||
.el-table, .el-tabs__item, .btn-next, input{
|
||||
color: var(--l-c);
|
||||
}
|
||||
.el-pagination, .el-pagination .el-pagination__total, .el-pagination .el-pagination__jump,
|
||||
.el-pagination .btn-next, .el-pagination .btn-prev{
|
||||
color: var(--l-c);
|
||||
}
|
||||
.el-drawer{
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
.Header, .Aside{
|
||||
i{
|
||||
color: var(--l-icon);
|
||||
&:hover{
|
||||
color: var(--l-icon-h);
|
||||
background-color: var(--l-bgc-h);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Aside{
|
||||
i{
|
||||
&.active{
|
||||
color: var(--l-icon-h);
|
||||
background-color: var(--l-bgc-h);
|
||||
border-left: 4px solid var(--l-icon-h);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Main{
|
||||
.film, .search, .star, .player{
|
||||
.table-box{
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px var(--l-bdc);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--l-icon);
|
||||
outline: 1px solid var(--l-icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
.setting{
|
||||
.el-link, .card{
|
||||
color: var(--l-c);
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail{
|
||||
color: var(--l-c);
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 6px var(--l-bdc);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--l-icon);
|
||||
outline: 1px solid var(--l-icon);
|
||||
}
|
||||
.box, .info, .urls{
|
||||
border: 1px solid var(--l-bdc);
|
||||
}
|
||||
.vodInfo{
|
||||
li, span, a{
|
||||
color: var(--l-c);
|
||||
}
|
||||
label{
|
||||
color: #f90;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
151
src/background.js
Normal file
@@ -0,0 +1,151 @@
|
||||
'use strict'
|
||||
|
||||
import { app, ipcMain, protocol, BrowserWindow } from 'electron'
|
||||
import {
|
||||
createProtocol
|
||||
// installVueDevtools
|
||||
} from 'vue-cli-plugin-electron-builder/lib'
|
||||
import path from 'path'
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let win
|
||||
let mini
|
||||
|
||||
// Scheme must be registered before the app is ready
|
||||
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])
|
||||
|
||||
function createWindow () {
|
||||
win = new BrowserWindow({
|
||||
width: 1080,
|
||||
height: 720,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
transparent: true,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
|
||||
},
|
||||
// eslint-disable-next-line
|
||||
icon: path.join(__static, 'icon.png')
|
||||
})
|
||||
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
|
||||
if (!process.env.IS_TEST) win.webContents.openDevTools()
|
||||
} else {
|
||||
win.loadURL('app://./index.html')
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
}
|
||||
|
||||
win.on('closed', () => {
|
||||
win = null
|
||||
})
|
||||
}
|
||||
|
||||
function createMini () {
|
||||
mini = new BrowserWindow({
|
||||
width: 550,
|
||||
minWidth: 260,
|
||||
height: 340,
|
||||
minHeight: 180,
|
||||
frame: false,
|
||||
resizable: true,
|
||||
transparent: true,
|
||||
alwaysOnTop: true,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
|
||||
},
|
||||
// eslint-disable-next-line
|
||||
icon: path.join(__static, 'icon.png')
|
||||
})
|
||||
|
||||
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 {
|
||||
mini.loadURL('app://./mini.html')
|
||||
}
|
||||
|
||||
mini.on('closed', () => {
|
||||
mini = null
|
||||
})
|
||||
}
|
||||
|
||||
app.allowRendererProcessReuse = true
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (win === null) {
|
||||
createWindow()
|
||||
}
|
||||
if (mini === null) {
|
||||
createMini()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('min', () => {
|
||||
win.minimize()
|
||||
})
|
||||
ipcMain.on('close', () => {
|
||||
win.close()
|
||||
})
|
||||
|
||||
ipcMain.on('mini', () => {
|
||||
createMini()
|
||||
win.close()
|
||||
})
|
||||
ipcMain.on('miniMin', () => {
|
||||
mini.minimize()
|
||||
})
|
||||
ipcMain.on('miniClose', () => {
|
||||
mini.close()
|
||||
createWindow()
|
||||
})
|
||||
ipcMain.on('miniOpacity', (e, arg) => {
|
||||
mini.setOpacity(arg)
|
||||
})
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// 当运行第二个实例时,将会聚焦到win这个窗口
|
||||
if (win) {
|
||||
if (win.isMinimized()) win.restore()
|
||||
win.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// 创建 win, 加载应用的其余部分, etc...
|
||||
app.on('ready', () => {
|
||||
if (!process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
createProtocol('app')
|
||||
}
|
||||
createWindow()
|
||||
})
|
||||
}
|
||||
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
if (process.platform === 'win32') {
|
||||
process.on('message', data => {
|
||||
if (data === 'graceful-exit') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
process.on('SIGTERM', () => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
import { app, protocol, ipcMain, BrowserWindow } from 'electron'
|
||||
import {
|
||||
createProtocol,
|
||||
installVueDevtools
|
||||
} from 'vue-cli-plugin-electron-builder/lib'
|
||||
import path from 'path'
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let win: BrowserWindow | null
|
||||
|
||||
// Scheme must be registered before the app is ready
|
||||
protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
win = new BrowserWindow({
|
||||
width: 1080,
|
||||
height: 720,
|
||||
frame: false,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: true
|
||||
},
|
||||
// @ts-ignore
|
||||
icon: path.join(__static, 'icon.png')
|
||||
})
|
||||
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
// Load the url of the dev server if in development mode
|
||||
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||
if (!process.env.IS_TEST) win.webContents.openDevTools()
|
||||
} else {
|
||||
createProtocol('app')
|
||||
// Load the index.html when not in development
|
||||
win.loadURL('app://./index.html')
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
}
|
||||
|
||||
win.on('closed', () => {
|
||||
win = null
|
||||
})
|
||||
}
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (win === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('min', () => {
|
||||
if (win) {
|
||||
win.minimize()
|
||||
}
|
||||
})
|
||||
ipcMain.on('max', e => {
|
||||
if (win) {
|
||||
if (win.isMaximized()) {
|
||||
win.unmaximize()
|
||||
} else {
|
||||
win.maximize()
|
||||
}
|
||||
}
|
||||
})
|
||||
ipcMain.on('close', e => {
|
||||
if (win) {
|
||||
win.close()
|
||||
}
|
||||
})
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on('ready', async () => {
|
||||
if (isDevelopment && !process.env.IS_TEST) {
|
||||
// Install Vue Devtools
|
||||
// Devtools extensions are broken in Electron 6.0.0 and greater
|
||||
// See https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/378 for more info
|
||||
// Electron will not launch with Devtools extensions installed on Windows 10 with dark mode
|
||||
// If you are not using Windows 10 dark mode, you may uncomment these lines
|
||||
// In addition, if the linked issue is closed, you can upgrade electron and uncomment these lines
|
||||
// try {
|
||||
// await installVueDevtools()
|
||||
// } catch (e) {
|
||||
// console.error('Vue Devtools failed to install:', e.toString())
|
||||
// }
|
||||
}
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
if (process.platform === 'win32') {
|
||||
process.on('message', data => {
|
||||
if (data === 'graceful-exit') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
process.on('SIGTERM', () => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
}
|
||||
77
src/components/Aside.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="aside">
|
||||
<span :class="[view === 'Film' ? 'active ': ''] + 'zy-svg'" @click="changeView('Film')">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="apertureIconTitle">
|
||||
<title id="apertureIconTitle">{{$t('view')}}</title>
|
||||
<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"></path>
|
||||
<g stroke-linecap="round">
|
||||
<path d="M3 16H14.3164"></path>
|
||||
<path d="M4.03589 6.20575L9.68257 15.9861"></path>
|
||||
<path d="M13.0359 2.20575L7.37891 12.004"></path>
|
||||
<path d="M10.9641 21.7942L16.6146 12.0074"></path>
|
||||
<path d="M19.9641 17.7942L14.3086 7.99866"></path>
|
||||
<path d="M21 7.98721H9.71844"></path>
|
||||
</g>
|
||||
</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">{{$t('play')}}</title>
|
||||
<path d="M20 12L5 21V3z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span :class="[view === 'Star' ? 'active ': ''] + 'zy-svg'" @click="changeView('Star')">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="favouriteIconTitle">
|
||||
<title id="favouriteIconTitle">{{$t('star')}}</title>
|
||||
<path d="M12,21 L10.55,19.7051771 C5.4,15.1242507 2,12.1029973 2,8.39509537 C2,5.37384196 4.42,3 7.5,3 C9.24,3 10.91,3.79455041 12,5.05013624 C13.09,3.79455041 14.76,3 16.5,3 C19.58,3 22,5.37384196 22,8.39509537 C22,12.1029973 18.6,15.1242507 13.45,19.7149864 L12,21 Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span :class="[view === 'Setting' ? 'active ': ''] + 'zy-svg'" @click="changeView('Setting')">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="settingsIconTitle">
|
||||
<title id="settingsIconTitle">{{$t('setting')}}</title>
|
||||
<path d="M5.03506429,12.7050339 C5.01187484,12.4731696 5,12.2379716 5,12 C5,11.7620284 5.01187484,11.5268304 5.03506429,11.2949661 L3.20577137,9.23205081 L5.20577137,5.76794919 L7.9069713,6.32070904 C8.28729123,6.0461342 8.69629298,5.80882212 9.12862533,5.61412402 L10,3 L14,3 L14.8713747,5.61412402 C15.303707,5.80882212 15.7127088,6.0461342 16.0930287,6.32070904 L18.7942286,5.76794919 L20.7942286,9.23205081 L18.9649357,11.2949661 C18.9881252,11.5268304 19,11.7620284 19,12 C19,12.2379716 18.9881252,12.4731696 18.9649357,12.7050339 L20.7942286,14.7679492 L18.7942286,18.2320508 L16.0930287,17.679291 C15.7127088,17.9538658 15.303707,18.1911779 14.8713747,18.385876 L14,21 L10,21 L9.12862533,18.385876 C8.69629298,18.1911779 8.28729123,17.9538658 7.9069713,17.679291 L5.20577137,18.2320508 L3.20577137,14.7679492 L5.03506429,12.7050339 Z"></path>
|
||||
<circle cx="12" cy="12" r="1"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
export default {
|
||||
name: 'Aside',
|
||||
computed: {
|
||||
view: {
|
||||
get () {
|
||||
return this.$store.getters.getView
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIEW(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW']),
|
||||
changeView (e) {
|
||||
this.view = e
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.aside{
|
||||
width: 60px;
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
span{
|
||||
-webkit-app-region: no-drag;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
345
src/components/Detail.vue
Normal file
@@ -0,0 +1,345 @@
|
||||
<template>
|
||||
<div class="detail">
|
||||
<div class="detail-content">
|
||||
<div class="detail-header">
|
||||
<span class="detail-title">{{$t('detail')}}</span>
|
||||
<span class="detail-close zy-svg" @click="closeDetail">
|
||||
<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">{{$t('close')}}</title>
|
||||
<path d="M6.34314575 6.34314575L17.6568542 17.6568542M6.34314575 17.6568542L17.6568542 6.34314575"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-body zy-scroll" v-show="!loading" :style="{overflowY:scroll? 'auto' : 'hidden',paddingRight: scroll ? '0': '5px' }" @mouseenter="scroll = true" @mouseleave="scroll = false">
|
||||
<div class="info" v-html="vDetail.info"></div>
|
||||
<div class="desc" v-html="vDetail.desc" v-if="show.desc"></div>
|
||||
<div class="m3u8_urls">
|
||||
<div class="title">{{$t('play')}}:</div>
|
||||
<div class="box">
|
||||
<span v-for="(i, j) in vDetail.m3u8_urls" :key="j" @click="playEvent(j)">{{i | ftName}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mp4_urls" v-if="show.download">
|
||||
<div class="title">{{$t('download')}}:</div>
|
||||
<div class="box">
|
||||
<span v-for="(i, j) in vDetail.mp4_urls" :key="j" @click="download(i)">{{i | ftName}}</span>
|
||||
<span @click="allDownload" v-show="vDetail.mp4_urls.length > 1">{{$t('all_download')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-mask zy-loading" v-show="loading">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import tools from '../lib/site/tools'
|
||||
const { clipboard } = require('electron')
|
||||
export default {
|
||||
name: 'detail',
|
||||
data () {
|
||||
return {
|
||||
scroll: false,
|
||||
loading: true,
|
||||
vDetail: {},
|
||||
show: {
|
||||
desc: false,
|
||||
download: false
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
ftName (e) {
|
||||
const name = e.split('$')[0]
|
||||
return name
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_VIDEO', 'SET_DETAIL']),
|
||||
closeDetail () {
|
||||
this.detail.show = false
|
||||
},
|
||||
getDetail () {
|
||||
tools.detail_get(this.detail.v.site, this.detail.v.detail).then(res => {
|
||||
this.vDetail = res
|
||||
if (res.desc.length > 0) {
|
||||
this.show.desc = true
|
||||
}
|
||||
if (res.mp4_urls.length > 0) {
|
||||
this.show.download = true
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
playEvent (n) {
|
||||
const v = { ...this.detail.v }
|
||||
v.index = n
|
||||
this.video = v
|
||||
this.detail.show = false
|
||||
this.view = 'Play'
|
||||
},
|
||||
download (e) {
|
||||
const name = e.split('$')[0]
|
||||
const txt = encodeURI(e.split('$')[1])
|
||||
clipboard.writeText(txt)
|
||||
this.$m.success(name + this.$t('copy_success'))
|
||||
},
|
||||
allDownload () {
|
||||
const urls = [...this.vDetail.mp4_urls]
|
||||
let txt = ''
|
||||
for (const i of urls) {
|
||||
const url = encodeURI(i.split('$')[1])
|
||||
txt += (url + '\n')
|
||||
}
|
||||
clipboard.writeText(txt)
|
||||
this.$m.success(this.$t('copy_success'))
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.detail{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 680px;
|
||||
z-index: 999;
|
||||
.detail-content{
|
||||
height: 680px;
|
||||
padding: 0 60px;
|
||||
position: relative;
|
||||
.detail-header{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 -40px;
|
||||
.detail-title{
|
||||
font-size: 16px;
|
||||
}
|
||||
.detail-close{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.detail-body{
|
||||
height: 630px;
|
||||
overflow-y: auto;
|
||||
.info{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
width: 955px;
|
||||
padding: 10px;
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 10px;
|
||||
.vodImg{
|
||||
width: 200px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.vodAd{
|
||||
display: none;
|
||||
}
|
||||
.vodInfo{
|
||||
flex: 1;
|
||||
margin-left: 20px;
|
||||
overflow: hidden;
|
||||
.vodh{
|
||||
margin-bottom: 6px;
|
||||
h2{
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
span{
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
label{
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.cont, .tags{
|
||||
display: none;
|
||||
}
|
||||
ul{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
a{
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
li{
|
||||
list-style: none;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
height: 18px;
|
||||
overflow: hidden;
|
||||
span{
|
||||
word-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
.whitetitle{
|
||||
width: 100%;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.people{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
.left{
|
||||
width: 200px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
flex: 1;
|
||||
margin-left: 20px;
|
||||
overflow: hidden;
|
||||
p{
|
||||
font-size: 14px;
|
||||
}
|
||||
a{
|
||||
pointer-events: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc{
|
||||
border: 1px solid;
|
||||
padding: 10px;
|
||||
width: 955px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.m3u8_urls, .mp4_urls{
|
||||
border: 1px solid;
|
||||
padding: 10px;
|
||||
width: 955px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 2px;
|
||||
.title{
|
||||
font-size: 16px;
|
||||
}
|
||||
.box{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
span{
|
||||
font-size: 12px;
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
margin: 6px 6px 0px 0px;
|
||||
padding: 8px 22px;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mp4_urls{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.detail-mask{
|
||||
width: 980px;
|
||||
height: 600px;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.loader {
|
||||
font-size: 8px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
animation: load4 1.3s infinite linear;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
@keyframes load4 {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 -3em 0 0.2em, 2em -2em 0 0em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 0;
|
||||
}
|
||||
12.5% {
|
||||
box-shadow: 0 -3em 0 0, 2em -2em 0 0.2em, 3em 0 0 0, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
25% {
|
||||
box-shadow: 0 -3em 0 -0.5em, 2em -2em 0 0, 3em 0 0 0.2em, 2em 2em 0 0, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
37.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 0, 2em 2em 0 0.2em, 0 3em 0 0em, -2em 2em 0 -1em, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 0em, 0 3em 0 0.2em, -2em 2em 0 0, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
62.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 0, -2em 2em 0 0.2em, -3em 0 0 0, -2em -2em 0 -1em;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 0em -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0.2em, -2em -2em 0 0;
|
||||
}
|
||||
87.5% {
|
||||
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
333
src/components/Film.vue
Normal file
@@ -0,0 +1,333 @@
|
||||
<template>
|
||||
<div class="film">
|
||||
<div class="top" v-if="top">
|
||||
<!-- site -->
|
||||
<div class="zy-select" @mouseleave="show.site = false">
|
||||
<div class="vs-placeholder" @click="show.site = true">{{site.name}}</div>
|
||||
<div class="vs-options" v-show="show.site">
|
||||
<ul>
|
||||
<li :class="site === j ? 'active' : ''" v-for="(i, j) in sites" :key="j" @click="siteClick(i)">{{ i.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- tags -->
|
||||
<div class="zy-select" @mouseleave="show.tags = false" v-if="site.tags.length > 0 && keywords.length <= 0">
|
||||
<div class="vs-placeholder" @click="show.tags = true">{{site.tags[tag].title}}</div>
|
||||
<div class="vs-options" v-show="show.tags">
|
||||
<ul>
|
||||
<li :class="tag === j ? 'active' : ''" v-for="(i, j) in site.tags" :key="j" @click="tagClick(i, j)">{{ i.title }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- type -->
|
||||
<div class="zy-select" @mouseleave="show.type = false" v-if="site.tags[tag].children.length > 0 && keywords.length <= 0">
|
||||
<div class="vs-placeholder" @click="show.type = true">{{typeName}}</div>
|
||||
<div class="vs-options" v-show="show.type">
|
||||
<ul>
|
||||
<li :class="type === j ? 'active' : ''" v-for="(i, j) in site.tags[tag].children" :key="j" @click="typeClick(i, j)">{{ i.title }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[inputFocus ? 'active ': ''] + 'search'" @mouseover="inputFocus = true" @mouseleave="inputFocus = false">
|
||||
<div class="search-icon">
|
||||
<span class="zy-svg">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="searchIconTitle">
|
||||
<title id="searchIconTitle">Search</title>
|
||||
<path d="M14.4121122,14.4121122 L20,20"></path>
|
||||
<circle cx="10" cy="10" r="6"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<input type="text" class="search-box" v-model="keywords" @keypress.enter="searchEvent">
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<div class="zy-table">
|
||||
<div class="tHead">
|
||||
<span class="name">{{$t('videoName')}}</span>
|
||||
<span class="type">{{$t('type')}}</span>
|
||||
<span class="time">{{$t('time')}}</span>
|
||||
<span class="operate">{{$t('operate')}}</span>
|
||||
</div>
|
||||
<div class="tBody zy-scroll">
|
||||
<ul v-show="!tb.loading">
|
||||
<li v-for="(i, j) in tb.list" :key="j" @click="detailEvent(i)">
|
||||
<span class="name">{{i.name}}</span>
|
||||
<span class="type">{{i.type}}</span>
|
||||
<span class="time">{{i.time}}</span>
|
||||
<span class="operate">
|
||||
<span class="btn" @click.stop="playEvent(i)">{{$t('play')}}</span>
|
||||
<span class="btn" @click.stop="starEvent(i)">{{$t('star')}}</span>
|
||||
<span class="btn" @click.stop="shareEvent(i)">{{$t('share')}}</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tBody-mask zy-loading" v-show="tb.loading">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tFooter">
|
||||
<span class="tFooter-span">今日更新: {{ tb.update }} 条</span>
|
||||
<el-pagination small :page-size="tb.size" :total="tb.total" :current-page="tb.page" @current-change="tbPageChange" layout="total, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import { sites, getSite } from '../lib/site/sites'
|
||||
import tools from '../lib/site/tools'
|
||||
import video from '../lib/dexie/video'
|
||||
import setting from '../lib/dexie/setting'
|
||||
export default {
|
||||
name: 'film',
|
||||
data () {
|
||||
return {
|
||||
sites: sites,
|
||||
site: {},
|
||||
top: false,
|
||||
tag: 0,
|
||||
type: 0,
|
||||
typeName: '',
|
||||
keywords: '',
|
||||
id: '',
|
||||
show: {
|
||||
site: false,
|
||||
tags: false,
|
||||
type: false
|
||||
},
|
||||
inputFocus: false,
|
||||
tb: {
|
||||
list: [],
|
||||
page: 1,
|
||||
size: 50,
|
||||
total: 0,
|
||||
update: 0,
|
||||
loading: true
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
view: {
|
||||
get () {
|
||||
return this.$store.getters.getView
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIEW(val)
|
||||
}
|
||||
},
|
||||
gSite: {
|
||||
get () {
|
||||
return this.$store.getters.getSite
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SITE(val)
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
get () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
set (val) {
|
||||
this.SET_DETAIL(val)
|
||||
}
|
||||
},
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
share: {
|
||||
get () {
|
||||
return this.$store.getters.getShare
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SHARE(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
gSite (n, o) {
|
||||
const s = getSite(n)
|
||||
this.siteClick(s)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_SITE', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||
init () {
|
||||
setting.find().then(res => {
|
||||
this.site = getSite(res.site)
|
||||
this.top = true
|
||||
tools.film_get(res.site).then(tRes => {
|
||||
this.tb.list = tRes.list
|
||||
this.tb.total = tRes.total
|
||||
this.tb.update = tRes.update
|
||||
this.tb.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
siteClick (e) {
|
||||
this.site = e
|
||||
this.tag = 0
|
||||
this.id = e.tags[0].id
|
||||
this.show.site = false
|
||||
if (this.keywords.length > 0) {
|
||||
this.searchEvent()
|
||||
} else {
|
||||
this.tb.update = 0
|
||||
this.tb.total = 0
|
||||
this.tb.loading = true
|
||||
tools.film_get(e.key, this.id).then(res => {
|
||||
this.tb.list = res.list
|
||||
this.tb.total = res.total
|
||||
this.tb.update = res.update
|
||||
this.tb.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
tagClick (e, n) {
|
||||
this.tb.update = 0
|
||||
this.tb.total = 0
|
||||
this.tag = n
|
||||
this.id = e.id
|
||||
this.typeName = 'All'
|
||||
this.tb.loading = true
|
||||
this.show.tags = false
|
||||
tools.film_get(this.site.key, this.id).then(res => {
|
||||
this.tb.list = res.list
|
||||
this.tb.total = res.total
|
||||
this.tb.update = res.update
|
||||
this.tb.loading = false
|
||||
})
|
||||
},
|
||||
typeClick (e, n) {
|
||||
this.tb.update = 0
|
||||
this.tb.total = 0
|
||||
this.type = n
|
||||
this.typeName = e.title
|
||||
this.id = e.id
|
||||
this.tb.loading = true
|
||||
this.show.type = false
|
||||
tools.film_get(this.site.key, this.id).then(res => {
|
||||
this.tb.list = res.list
|
||||
this.tb.total = res.total
|
||||
this.tb.update = res.update
|
||||
this.tb.loading = false
|
||||
})
|
||||
},
|
||||
searchEvent () {
|
||||
const flag = this.site.search
|
||||
if (flag === '') {
|
||||
this.$m.warning(this.$t('not_support_search'))
|
||||
return false
|
||||
}
|
||||
this.tb.loading = true
|
||||
this.tb.update = 0
|
||||
this.tb.total = 0
|
||||
tools.search_get(this.site.key, this.keywords).then(res => {
|
||||
this.tb.list = res.list
|
||||
this.tb.total = res.total
|
||||
this.tb.loading = false
|
||||
})
|
||||
},
|
||||
detailEvent (e) {
|
||||
this.detail = {
|
||||
show: true,
|
||||
v: e
|
||||
}
|
||||
},
|
||||
playEvent (e) {
|
||||
this.video = e
|
||||
this.view = 'Play'
|
||||
},
|
||||
starEvent (e) {
|
||||
video.find({ detail: e.detail }).then(res => {
|
||||
if (res) {
|
||||
this.$m.warning(this.$t('exists'))
|
||||
} else {
|
||||
video.add(e).then(res => {
|
||||
this.$m.success(this.$t('star_success'))
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
shareEvent (e) {
|
||||
this.share = {
|
||||
show: true,
|
||||
v: e
|
||||
}
|
||||
},
|
||||
tbPageChange (e) {
|
||||
this.tb.loading = true
|
||||
this.tb.page = e
|
||||
tools.film_get(this.site.key, this.id, this.tb.page).then(res => {
|
||||
this.tb.list = res.list
|
||||
this.tb.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.film{
|
||||
height: 670px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
animation: viewFadeIn 1s ease-in both;
|
||||
.top{
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.search{
|
||||
width: 200px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 15px;
|
||||
svg{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.search-icon{
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.search-box{
|
||||
width: 160px;
|
||||
height: 30px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
text-indent: 2px;
|
||||
font-size: 14px;
|
||||
&:focus{
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.middle{
|
||||
height: 620px;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
padding-bottom: 0px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
65
src/components/Frame.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="frame">
|
||||
<span class="min" @click="frameClickEvent('min')"></span>
|
||||
<span class="close" @click="frameClickEvent('close')"></span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const ipc = require('electron').ipcRenderer
|
||||
export default {
|
||||
name: 'frame',
|
||||
methods: {
|
||||
frameClickEvent (e) {
|
||||
ipc.send(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.frame{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
span{
|
||||
-webkit-app-region: no-drag;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
&: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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
531
src/components/Play.vue
Normal file
@@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<div class="play">
|
||||
<div class="box">
|
||||
<div class="title">{{name}}</div>
|
||||
<div id="xg"></div>
|
||||
<div class="mask zy-loading" v-show="mask">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
<div class="more" v-show="more">
|
||||
<span class="zy-svg" @click="nextEvent" v-show="showNext">
|
||||
<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">{{$t('next')}}</title>
|
||||
<path d="M10 14.74L3 19V5l7 4.26V5l12 7-12 7v-4.26z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="zy-svg" @click="listEvent" :class="right.type === 'list' ? 'active' : ''" v-show="right.listData.length > 0">
|
||||
<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">{{$t('play_list')}}</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="historyEvent" :class="right.type === 'history' ? 'active' : ''">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="timeIconTitle">
|
||||
<title id="timeIconTitle">{{$t('history')}}</title>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<polyline points="12 5 12 12 16 16"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="zy-svg" @click="starEvent" :class="isStar ? 'active' : ''" v-show="right.listData.length > 0">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="favouriteIconTitle">
|
||||
<title id="favouriteIconTitle">{{$t('star')}}</title>
|
||||
<path d="M12,21 L10.55,19.7051771 C5.4,15.1242507 2,12.1029973 2,8.39509537 C2,5.37384196 4.42,3 7.5,3 C9.24,3 10.91,3.79455041 12,5.05013624 C13.09,3.79455041 14.76,3 16.5,3 C19.58,3 22,5.37384196 22,8.39509537 C22,12.1029973 18.6,15.1242507 13.45,19.7149864 L12,21 Z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="zy-svg" @click="detailEvent" v-show="right.listData.length > 0">
|
||||
<svg role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-labelledby="feedIconTitle">
|
||||
<title id="feedIconTitle">{{$t('detail')}}</title>
|
||||
<circle cx="7.5" cy="7.5" r="2.5"></circle>
|
||||
<path d="M22 13H2"></path>
|
||||
<path d="M18 6h-5m5 3h-5"></path>
|
||||
<path d="M5 2h14a3 3 0 0 1 3 3v17H2V5a3 3 0 0 1 3-3z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="zy-svg" @click="smallEvent" v-show="right.listData.length > 0">
|
||||
<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">{{$t('mini')}}</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="zy-svg" @click="shareEvent" v-show="right.listData.length > 0">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-labelledby="qrIconTitle">
|
||||
<title id="qrIconTitle">{{$t('share')}}</title>
|
||||
<rect x="10" y="3" width="7" height="7" transform="rotate(90 10 3)"></rect>
|
||||
<rect width="1" height="1" transform="matrix(-1 0 0 1 7 6)"></rect>
|
||||
<rect x="10" y="14" width="7" height="7" transform="rotate(90 10 14)"></rect>
|
||||
<rect x="6" y="17" width="1" height="1"></rect>
|
||||
<rect x="14" y="20" width="1" height="1"></rect>
|
||||
<rect x="17" y="17" width="1" height="1"></rect>
|
||||
<rect x="14" y="14" width="1" height="1"></rect>
|
||||
<rect x="20" y="17" width="1" height="1"></rect>
|
||||
<rect x="20" y="14" width="1" height="1"></rect>
|
||||
<rect x="20" y="20" width="1" height="1"></rect>
|
||||
<rect x="21" y="3" width="7" height="7" transform="rotate(90 21 3)"></rect>
|
||||
<rect x="17" y="6" width="1" height="1"></rect>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="slideX">
|
||||
<div v-if="right.show" class="list">
|
||||
<div class="list-top">
|
||||
<span class="list-top-title">{{ right.type === 'list' ? $t('play_list') : $t('history') }}</span>
|
||||
<span class="list-top-close zy-svg" @click="closeEvent">
|
||||
<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">{{$t('close')}}</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">
|
||||
<ul v-show="right.type === 'list'" class="list-item">
|
||||
<li v-show="right.listData.length === 0">{{$t('no_data')}}</li>
|
||||
<li @click="listItemEvent(j)" :class="video.index === j ? 'active' : ''" v-for="(i, j) in right.listData" :key="j">{{i | ftName}}</li>
|
||||
</ul>
|
||||
<ul v-show="right.type === 'history'" class="list-history">
|
||||
<li v-show="right.historyData.length > 1" @click="clearAll">{{$t('clear_data')}}</li>
|
||||
<li v-show="right.historyData.length === 0">{{$t('no_data')}}</li>
|
||||
<li @click="historyItemEvent(m)" :class="video.detail === m.detail ? 'active' : ''" v-for="(m, n) in right.historyData" :key="n"><span class="title">{{m.name}}</span><span @click.stop="removeItem(m)" class="detail-delete">{{$t('delete')}}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<div class="play-mask" v-if="right.listData.length === 0 && right.historyData.length === 0">{{$t('no_history')}}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import tools from '../lib/site/tools'
|
||||
import history from '../lib/dexie/history'
|
||||
import video from '../lib/dexie/video'
|
||||
import mini from '../lib/dexie/mini'
|
||||
import 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
const { ipcRenderer: ipc } = require('electron')
|
||||
export default {
|
||||
name: 'play',
|
||||
data () {
|
||||
return {
|
||||
xg: null,
|
||||
right: {
|
||||
show: false,
|
||||
type: '',
|
||||
listData: [],
|
||||
historyData: []
|
||||
},
|
||||
config: {
|
||||
id: 'xg',
|
||||
lang: 'zh-cn',
|
||||
url: '',
|
||||
fluid: true,
|
||||
autoplay: false,
|
||||
videoInit: true,
|
||||
screenShot: true,
|
||||
keyShortcut: 'on',
|
||||
crossOrigin: true,
|
||||
cssFullscreen: true,
|
||||
defaultPlaybackRate: 1,
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5]
|
||||
},
|
||||
name: '',
|
||||
timer: null,
|
||||
scroll: false,
|
||||
more: true,
|
||||
showNext: false,
|
||||
isStar: false,
|
||||
isTop: false,
|
||||
mask: false
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
ftName (e) {
|
||||
return e.split('$')[0]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
view () {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
video: {
|
||||
handler () {
|
||||
this.getUrls()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||
getUrls () {
|
||||
this.mask = true
|
||||
if (this.timer !== null) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
if (this.xg) {
|
||||
this.xg.pause()
|
||||
}
|
||||
this.changeVideo()
|
||||
tools.detail_get(this.video.site, this.video.detail).then(res => {
|
||||
this.name = this.video.name
|
||||
this.right.listData = res.m3u8_urls
|
||||
if (res.m3u8_urls.length > 1) {
|
||||
const m3 = res.m3u8_urls
|
||||
const arr = []
|
||||
for (const i of m3) {
|
||||
arr.push(i.split('$')[1])
|
||||
}
|
||||
this.xg.src = arr[this.video.index]
|
||||
this.showNext = true
|
||||
} else {
|
||||
const link = res.m3u8_urls[this.video.index]
|
||||
const src = link.split('$')[1]
|
||||
this.xg.src = src
|
||||
this.showNext = false
|
||||
}
|
||||
const currentTime = this.video.currentTime
|
||||
if (currentTime !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = currentTime
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
}
|
||||
this.xg.once('play', () => {
|
||||
this.mask = false
|
||||
})
|
||||
this.onPlayVideo()
|
||||
this.xg.once('ended', () => {
|
||||
if (res.m3u8_urls.length > 1 && (res.m3u8_urls.length - 1 > this.video.index)) {
|
||||
this.video.currentTime = 0
|
||||
this.video.index++
|
||||
}
|
||||
this.xg.off('ended')
|
||||
})
|
||||
})
|
||||
},
|
||||
changeVideo () {
|
||||
this.checkStar()
|
||||
this.checkTop()
|
||||
this.name = ''
|
||||
},
|
||||
checkStar () {
|
||||
video.find({ detail: this.video.detail }).then(res => {
|
||||
if (res) {
|
||||
this.isStar = true
|
||||
} else {
|
||||
this.isStar = false
|
||||
}
|
||||
})
|
||||
},
|
||||
checkTop () {
|
||||
ipc.send('checkTop')
|
||||
ipc.on('isTop', (e, flag) => {
|
||||
this.isTop = flag
|
||||
})
|
||||
},
|
||||
onPlayVideo () {
|
||||
this.more = true
|
||||
const h = { ...this.video }
|
||||
history.find({ detail: h.detail }).then(res => {
|
||||
if (res) {
|
||||
h.id = res.id
|
||||
history.update(res.id, h)
|
||||
} else {
|
||||
h.currentTime = ''
|
||||
delete h.id
|
||||
history.add(h)
|
||||
}
|
||||
})
|
||||
this.timerEvent(h.detail)
|
||||
},
|
||||
timerEvent (d) {
|
||||
this.timer = setInterval(() => {
|
||||
history.find({ detail: d }).then(res => {
|
||||
if (res) {
|
||||
const h = { ...this.video }
|
||||
h.currentTime = this.xg.currentTime
|
||||
delete h.id
|
||||
history.update(res.id, h)
|
||||
}
|
||||
})
|
||||
}, 10000)
|
||||
},
|
||||
closeEvent () {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
nextEvent () {
|
||||
const v = { ...this.video }
|
||||
const i = v.index + 1
|
||||
if (i < this.right.listData.length) {
|
||||
this.video.currentTime = 0
|
||||
this.video.index++
|
||||
} else {
|
||||
this.$m.warning(this.$t('last_video'))
|
||||
}
|
||||
},
|
||||
listEvent () {
|
||||
if (this.right.type === 'list') {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
} else {
|
||||
this.right.show = true
|
||||
this.right.type = 'list'
|
||||
}
|
||||
},
|
||||
historyEvent () {
|
||||
if (this.right.type === 'history') {
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
} else {
|
||||
this.right.show = true
|
||||
this.right.type = 'history'
|
||||
}
|
||||
history.all().then(res => {
|
||||
this.right.historyData = res.reverse()
|
||||
})
|
||||
},
|
||||
starEvent () {
|
||||
video.find({ detail: this.video.detail }).then(res => {
|
||||
if (res !== undefined) {
|
||||
video.remove(res.id).then(r => {
|
||||
this.$m.info(this.$t('delete_success'))
|
||||
this.isStar = false
|
||||
})
|
||||
} else {
|
||||
const v = { ...this.video }
|
||||
if (v.id) {
|
||||
delete v.id
|
||||
}
|
||||
video.add(v).then(r => {
|
||||
this.$m.success(this.$t('star_success'))
|
||||
this.isStar = true
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
detailEvent () {
|
||||
this.detail = {
|
||||
show: true,
|
||||
v: this.video
|
||||
}
|
||||
},
|
||||
smallEvent () {
|
||||
this.xg.pause()
|
||||
mini.find().then(res => {
|
||||
const d = { ...this.video }
|
||||
d.currentTime = this.xg.currentTime
|
||||
d.id = 0
|
||||
if (res) {
|
||||
mini.update(d)
|
||||
} else {
|
||||
mini.add(d)
|
||||
}
|
||||
ipc.send('min')
|
||||
ipc.send('mini')
|
||||
})
|
||||
},
|
||||
shareEvent () {
|
||||
this.share = {
|
||||
show: true,
|
||||
v: this.video
|
||||
}
|
||||
},
|
||||
clearAll () {
|
||||
history.clear().then(res => {
|
||||
this.right.historyData = []
|
||||
})
|
||||
},
|
||||
listItemEvent (n) {
|
||||
this.video.currentTime = 0
|
||||
this.video.index = n
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
historyItemEvent (e) {
|
||||
this.video = e
|
||||
this.right.show = false
|
||||
this.right.type = ''
|
||||
},
|
||||
removeItem (e) {
|
||||
history.remove(e.id).then(res => {
|
||||
history.all().then(e => {
|
||||
this.right.historyData = e.reverse()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.xg = new Hls(this.config)
|
||||
history.all().then(res => {
|
||||
this.right.historyData = res
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.play{
|
||||
position: relative;
|
||||
height: 660px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
.box{
|
||||
width: 92%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
.title{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
.more{
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
span{
|
||||
display: flex;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.mask{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 600;
|
||||
opacity: 0.98;
|
||||
}
|
||||
}
|
||||
.list{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
z-index: 555;
|
||||
border-radius: 3px;
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.list-top{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
.list-top-title{
|
||||
font-size: 16px;
|
||||
}
|
||||
.list-top-close{
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.list-body{
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
ul{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
li{
|
||||
position: relative;
|
||||
height: 28px;
|
||||
width: 100%;
|
||||
line-height: 28px;
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
.title{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 231px;
|
||||
}
|
||||
.detail-delete{
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
height: 28px;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.slideX-enter-active, .slideX-leave-active{
|
||||
transition: all .5s ease-in-out;
|
||||
}
|
||||
.slideX-enter, .slideX-leave-to{
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
.play-mask{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 900;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
246
src/components/Setting.vue
Normal file
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<div class="setting">
|
||||
<div class="setting-box zy-scroll" v-if="show.setting">
|
||||
<div class="logo"><img src="@/assets/image/logo.png"></div>
|
||||
<div class="info">
|
||||
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player')">{{$t('website')}}</a>
|
||||
<a @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/issues')">v{{pkg.version}} {{$t('issues')}}</a>
|
||||
</div>
|
||||
<div class="change">
|
||||
<div class="zy-select" @mouseleave="show.language = false">
|
||||
<div class="vs-placeholder" @click="show.language = true">{{$t('language')}}</div>
|
||||
<div class="vs-options" v-show="show.language">
|
||||
<ul>
|
||||
<li :class="s.language === i.key ? 'active' : ''" v-for="(i, j) in languages" :key="j" @click="languageClick(i.key)">{{ i.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="zy-select" @mouseleave="show.site = false">
|
||||
<div class="vs-placeholder" @click="show.site = true">{{$t('default_site')}}</div>
|
||||
<div class="vs-options" v-show="show.site">
|
||||
<ul>
|
||||
<li :class="s.site === i.key ? 'active' : ''" v-for="(i, j) in sites" :key="j" @click="siteClick(i.key)">{{ i.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="theme">
|
||||
<div class="title">{{$t('theme')}}</div>
|
||||
<div class="theme-box">
|
||||
<div @click="changeTheme('light')" class="theme-item light">
|
||||
<div class="theme-image">
|
||||
<img src="../assets/image/light.png" alt="">
|
||||
</div>
|
||||
<div class="theme-name">Light</div>
|
||||
</div>
|
||||
<div @click="changeTheme('dark')" class="theme-item dark">
|
||||
<div class="theme-image">
|
||||
<img src="../assets/image/dark.png" alt="">
|
||||
</div>
|
||||
<div class="theme-name">Dark</div>
|
||||
</div>
|
||||
<div @click="changeTheme('green')" class="theme-item green">
|
||||
<div class="theme-image">
|
||||
<img src="../assets/image/green.png" alt="">
|
||||
</div>
|
||||
<div class="theme-name">Green</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="qrcode">
|
||||
<div class="title">{{$t('donate')}}</div>
|
||||
<div class="qrcode-box">
|
||||
<img class="qrcode-item" src="../assets/image/alipay.png">
|
||||
<img class="qrcode-item" src="../assets/image/wepay.jpg">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import setting from '../lib/dexie/setting'
|
||||
import { sites } from '../lib/site/sites'
|
||||
import '../lib/cloud/index.js'
|
||||
import { shell } from 'electron'
|
||||
import pkg from '../../package.json'
|
||||
export default {
|
||||
name: 'setting',
|
||||
data () {
|
||||
return {
|
||||
pkg: pkg,
|
||||
s: {},
|
||||
languages: [
|
||||
{
|
||||
key: 'zhCn',
|
||||
name: '中文'
|
||||
},
|
||||
{
|
||||
key: 'en',
|
||||
name: 'English'
|
||||
}
|
||||
],
|
||||
sites: sites,
|
||||
show: {
|
||||
setting: false,
|
||||
language: false,
|
||||
site: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
theme: {
|
||||
get () {
|
||||
return this.$store.getters.getTheme
|
||||
},
|
||||
set (val) {
|
||||
this.SET_THEME(val)
|
||||
}
|
||||
},
|
||||
language: {
|
||||
get () {
|
||||
return this.$store.getters.getLanguage
|
||||
},
|
||||
set (val) {
|
||||
this.SET_LANGUAGE(val)
|
||||
}
|
||||
},
|
||||
site: {
|
||||
get () {
|
||||
return this.$store.getters.getSite
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SITE(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_THEME', 'SET_LANGUAGE', 'SET_SITE']),
|
||||
linkOpen (e) {
|
||||
shell.openExternal(e)
|
||||
},
|
||||
languageClick (e) {
|
||||
this.language = e
|
||||
this.show.language = false
|
||||
this.$i18n.locale = e
|
||||
this.s.language = e
|
||||
setting.update(this.s).then(res => {
|
||||
this.$m.success(this.$t('set_success'))
|
||||
})
|
||||
},
|
||||
siteClick (e) {
|
||||
this.site = e
|
||||
this.show.site = false
|
||||
this.s.site = e
|
||||
setting.update(this.s).then(res => {
|
||||
this.$m.success(this.$t('set_success'))
|
||||
})
|
||||
},
|
||||
changeTheme (e) {
|
||||
this.theme = e
|
||||
this.s.theme = e
|
||||
setting.update(this.s).then(res => {
|
||||
this.$m.success(this.$t('set_success'))
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
setting.find().then(res => {
|
||||
this.s = res
|
||||
this.theme = res.theme
|
||||
this.$i18n.locale = this.s.language
|
||||
this.show.setting = true
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.setting{
|
||||
height: 660px;
|
||||
width: 100%;
|
||||
padding: 20px 0;
|
||||
.setting-box{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 5px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.logo{
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
img{
|
||||
width: 120px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.info{
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
a{
|
||||
text-decoration: none;
|
||||
margin: 0 10px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.change{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding-left: 20px;
|
||||
margin-top: 40px;
|
||||
.zy-select{
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
width: 100%;
|
||||
padding-left: 20px;
|
||||
margin-top: 20px;
|
||||
.theme-box{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
.theme-item{
|
||||
width: 200px;
|
||||
height: 180px;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
.theme-image{
|
||||
width: 180px;
|
||||
margin: 10px auto;
|
||||
img{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.theme-name{
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.qrcode{
|
||||
width: 100%;
|
||||
padding-left: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
.qrcode-box{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
.qrcode-item{
|
||||
width: auto;
|
||||
height: 300px;
|
||||
margin-right: 20px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
197
src/components/Share.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="share" id="share" @click="shareClickEvent">
|
||||
<div class="left">
|
||||
<img :src="this.card.img" alt="">
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="title">{{ card.name }}</div>
|
||||
<qrcode-vue id="qr" :value="value" :size="160" level="L" />
|
||||
<div class="tips">
|
||||
<p>{{$t('qr_tips')}}</p>
|
||||
<p><img src="@/assets/image/logo.png"></p>
|
||||
<p class="zy">{{$t('zy_tips')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="share-mask" v-show="loading">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import tools from '../lib/site/tools'
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import html2canvas from 'html2canvas'
|
||||
const { clipboard, nativeImage } = require('electron')
|
||||
export default {
|
||||
name: 'share',
|
||||
data () {
|
||||
return {
|
||||
card: {
|
||||
img: '',
|
||||
name: '',
|
||||
png: ''
|
||||
},
|
||||
value: 'https://www.baidu.com',
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
QrcodeVue
|
||||
},
|
||||
computed: {
|
||||
share: {
|
||||
get () {
|
||||
return this.$store.getters.getShare
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SHARE(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
share: {
|
||||
handler () {
|
||||
this.getDetail()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_SHARE']),
|
||||
getDetail () {
|
||||
this.loading = true
|
||||
tools.detail_get(this.share.v.site, this.share.v.detail).then(res => {
|
||||
const info = res.info
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(info, 'text/html')
|
||||
const img = html.querySelector('img').src
|
||||
this.card.img = img
|
||||
this.card.name = this.share.v.name
|
||||
const urls = res.m3u8_urls
|
||||
const url = urls[this.share.v.index].split('$')[1]
|
||||
this.value = 'http://zyplayer.fun/player/player.html?url=' + url + '&title=' + this.share.v.name
|
||||
this.loading = false
|
||||
this.$nextTick(() => {
|
||||
const dom = document.getElementById('share')
|
||||
html2canvas(dom, { allowTaint: true, useCORS: true }).then(res => {
|
||||
const png = res.toDataURL('image/png')
|
||||
const p = nativeImage.createFromDataURL(png)
|
||||
clipboard.writeImage(p)
|
||||
this.$m.success(this.$t('share_tips'))
|
||||
this.share.show = true
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
shareClickEvent () {
|
||||
this.share = {
|
||||
show: false,
|
||||
v: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.share{
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
width: 540px;
|
||||
height: 360px;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
z-index: 888;
|
||||
.left, .right{
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
}
|
||||
.left{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
img{
|
||||
height: 320px;
|
||||
width: auto;
|
||||
max-width: 240px;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
.title{
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#qr{
|
||||
text-align: center;
|
||||
}
|
||||
.tips{
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
img{
|
||||
width: 50px;
|
||||
}
|
||||
.zy{
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.share-mask{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.loader {
|
||||
color: #823aa055;
|
||||
font-size: 8px;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
animation: load4 1.3s infinite linear;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
@keyframes load4 {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 -3em 0 0.2em, 2em -2em 0 0em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 0;
|
||||
}
|
||||
12.5% {
|
||||
box-shadow: 0 -3em 0 0, 2em -2em 0 0.2em, 3em 0 0 0, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
25% {
|
||||
box-shadow: 0 -3em 0 -0.5em, 2em -2em 0 0, 3em 0 0 0.2em, 2em 2em 0 0, 0 3em 0 -1em, -2em 2em 0 -1em, -3em 0 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
37.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 0, 2em 2em 0 0.2em, 0 3em 0 0em, -2em 2em 0 -1em, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 0em, 0 3em 0 0.2em, -2em 2em 0 0, -3em 0em 0 -1em, -2em -2em 0 -1em;
|
||||
}
|
||||
62.5% {
|
||||
box-shadow: 0 -3em 0 -1em, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 0, -2em 2em 0 0.2em, -3em 0 0 0, -2em -2em 0 -1em;
|
||||
}
|
||||
75% {
|
||||
box-shadow: 0em -3em 0 -1em, 2em -2em 0 -1em, 3em 0em 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0.2em, -2em -2em 0 0;
|
||||
}
|
||||
87.5% {
|
||||
box-shadow: 0em -3em 0 0, 2em -2em 0 -1em, 3em 0 0 -1em, 2em 2em 0 -1em, 0 3em 0 -1em, -2em 2em 0 0, -3em 0em 0 0, -2em -2em 0 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
159
src/components/Star.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div class="star">
|
||||
<div class="zy-table">
|
||||
<div class="tHead">
|
||||
<span class="name">{{$t('videoName')}}</span>
|
||||
<span class="type">{{$t('type')}}</span>
|
||||
<span class="time">{{$t('time')}}</span>
|
||||
<span class="from">{{$t('from')}}</span>
|
||||
<span class="operate" style="width: 170px">{{$t('operate')}}</span>
|
||||
</div>
|
||||
<div class="tBody zy-scroll">
|
||||
<ul v-show="!loading">
|
||||
<li v-for="(i, j) in data" :key="j" @click="detailEvent(i)">
|
||||
<span class="name">{{i.name}}</span>
|
||||
<span class="type">{{i.type}}</span>
|
||||
<span class="time">{{i.time}}</span>
|
||||
<span class="from">{{i.site | ftSite}}</span>
|
||||
<span class="operate" style="width: 170px">
|
||||
<span class="btn" @click.stop="playEvent(i)">{{$t('play')}}</span>
|
||||
<span class="btn" @click.stop="deleteEvent(i)">{{$t('delete')}}</span>
|
||||
<span class="btn" @click.stop="shareEvent(i)">{{$t('share')}}</span>
|
||||
<span class="btn" @click.stop="updateEvent(i)">{{$t('sync')}}</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tBody-mask" v-show="loading">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tFooter">
|
||||
<span class="tFooter-span">{{data.length}} {{$t('total')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import tools from '../lib/site/tools'
|
||||
import video from '../lib/dexie/video'
|
||||
import { sites, getSite } from '../lib/site/sites'
|
||||
export default {
|
||||
name: 'star',
|
||||
data () {
|
||||
return {
|
||||
sites: sites,
|
||||
data: [],
|
||||
loading: true,
|
||||
checkFlag: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
view: {
|
||||
get () {
|
||||
return this.$store.getters.getView
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIEW(val)
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
get () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
set (val) {
|
||||
this.SET_DETAIL(val)
|
||||
}
|
||||
},
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
share: {
|
||||
get () {
|
||||
return this.$store.getters.getShare
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SHARE(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
ftSite (e) {
|
||||
const name = getSite(e).name
|
||||
return name
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
view () {
|
||||
this.getAllStar()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_VIEW', 'SET_DETAIL', 'SET_VIDEO', 'SET_SHARE']),
|
||||
detailEvent (e) {
|
||||
this.detail = {
|
||||
show: true,
|
||||
v: e
|
||||
}
|
||||
},
|
||||
playEvent (e) {
|
||||
this.video = e
|
||||
this.view = 'Play'
|
||||
},
|
||||
deleteEvent (e) {
|
||||
video.remove(e.id).then(res => {
|
||||
if (res) {
|
||||
this.$m.warning(this.$t('delete_failed'))
|
||||
} else {
|
||||
this.$m.success(this.$t('delete_success'))
|
||||
}
|
||||
this.getAllStar()
|
||||
})
|
||||
},
|
||||
shareEvent (e) {
|
||||
this.share = {
|
||||
show: true,
|
||||
v: e
|
||||
}
|
||||
},
|
||||
updateEvent (e) {
|
||||
tools.detail_get(e.site, e.detail).then(res => {
|
||||
const nameOne = e.name.replace(/\s*/g, '')
|
||||
const nameTwo = res.name.replace(/\s*/g, '')
|
||||
if (nameOne === nameTwo) {
|
||||
this.$m.info(this.$t('async_failed'))
|
||||
} else {
|
||||
const h = e
|
||||
h.name = res.name
|
||||
video.update(h.id, h).then(res => {
|
||||
this.$m.success(this.$t('async_success'))
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getAllStar () {
|
||||
video.all().then(res => {
|
||||
this.data = res.reverse()
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getAllStar()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.star{
|
||||
height: 660px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,159 +0,0 @@
|
||||
<template>
|
||||
<el-row class="detail">
|
||||
<el-row class="detail-box" v-loading="loading">
|
||||
<el-row v-html="detail.box" class="box"></el-row>
|
||||
<el-row v-html="detail.info" class="info"></el-row>
|
||||
<el-row class="urls">
|
||||
<el-button size="mini" v-for="(i, j) in detail.urls" :key="j" @click="playBtn(i, j)">{{i | ftLink}}</el-button>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import zy from '@/lib/util.zy'
|
||||
import { mapMutations } from 'vuex'
|
||||
export default Vue.extend({
|
||||
name: 'detail',
|
||||
data () {
|
||||
return {
|
||||
detail: {},
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
d () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
d () {
|
||||
this.getDetailEvent()
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
ftLink (e: string) {
|
||||
let name = e.split('$')[0]
|
||||
return name
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_MAIN', 'SET_VIDEO']),
|
||||
getDetailEvent () {
|
||||
let url = this.d.video.detail
|
||||
this.detail = {}
|
||||
this.loading = true
|
||||
zy.detail(url).then((res: any) => {
|
||||
this.detail = res
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
playBtn (i: string, j: number) {
|
||||
if (this.Main !== 'Player') {
|
||||
this.d.video.index = j
|
||||
this.video = this.d.video
|
||||
this.Main = 'Player'
|
||||
} else {
|
||||
this.d.video.index = j
|
||||
this.video = this.d.video
|
||||
}
|
||||
this.d.show = false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getDetailEvent()
|
||||
},
|
||||
mounted () {}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.detail{
|
||||
box-sizing: border-box;
|
||||
padding: 0 60px;
|
||||
.detail-box{
|
||||
width: 100%;
|
||||
.box{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
.vodImg{
|
||||
width: 200px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.vodAd{
|
||||
display: none;
|
||||
}
|
||||
.vodInfo{
|
||||
flex: 1;
|
||||
margin-left: 20px;
|
||||
.vodh{
|
||||
h2{
|
||||
display: inline-block;
|
||||
}
|
||||
span{
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
label{
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.cont, .tags{
|
||||
display: none;
|
||||
}
|
||||
li{
|
||||
list-style: none;
|
||||
font-size: 14px;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
a{
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
span{
|
||||
word-wrap:break-word
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.info, .urls{
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.info{
|
||||
font-size: 14px;
|
||||
}
|
||||
.urls{
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 0;
|
||||
button{
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
22
src/components/register.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import Vue from 'vue'
|
||||
import Aside from './Aside'
|
||||
import Detail from './Detail'
|
||||
import Film from './Film'
|
||||
import Frame from './Frame'
|
||||
import Play from './Play'
|
||||
import Setting from './Setting'
|
||||
import Share from './Share'
|
||||
import Star from './Star'
|
||||
|
||||
export default {
|
||||
registerComponents () {
|
||||
Vue.component('Aside', Aside)
|
||||
Vue.component('Detail', Detail)
|
||||
Vue.component('Film', Film)
|
||||
Vue.component('Frame', Frame)
|
||||
Vue.component('Play', Play)
|
||||
Vue.component('Setting', Setting)
|
||||
Vue.component('Share', Share)
|
||||
Vue.component('Star', Star)
|
||||
}
|
||||
}
|
||||
32
src/lib/cloud/index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import setting from '../dexie/setting'
|
||||
|
||||
const os = require('os')
|
||||
const macadress = require('macaddress')
|
||||
const AV = require('leancloud-storage')
|
||||
|
||||
setting.find().then(res => {
|
||||
const cloud = res.cloud
|
||||
if (!cloud) {
|
||||
macadress.one((err, mac) => {
|
||||
if (err) {
|
||||
return false
|
||||
}
|
||||
const system = os.hostname() + ' ' + os.type() + ' ' + os.arch()
|
||||
AV.init({
|
||||
appId: 'X6TRIcMjgOG7EJ0t1l5r9In1-gzGzoHsz',
|
||||
appKey: 'JmkGF9UqkWGQNYDcJ2g1QV1b',
|
||||
serverURL: 'https://x6tricmj.lc-cn-n1-shared.com'
|
||||
})
|
||||
const ZYPlayer = AV.Object.extend('ZYPlayer')
|
||||
const zyPlayer = new ZYPlayer()
|
||||
zyPlayer.set('os', system)
|
||||
zyPlayer.set('mac', mac)
|
||||
zyPlayer.save().then(e => {
|
||||
const id = e.id
|
||||
res.cloud = true
|
||||
res.cloudKey = id
|
||||
setting.update(res)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
22
src/lib/dexie/history.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import db from './index'
|
||||
const { history } = db
|
||||
export default {
|
||||
async add (doc) {
|
||||
return await history.add(doc)
|
||||
},
|
||||
async find (doc) {
|
||||
return await history.get(doc)
|
||||
},
|
||||
async update (id, docs) {
|
||||
return await history.update(id, docs)
|
||||
},
|
||||
async all () {
|
||||
return await history.toArray()
|
||||
},
|
||||
async remove (id) {
|
||||
return await history.delete(id)
|
||||
},
|
||||
async clear () {
|
||||
return await history.clear()
|
||||
}
|
||||
}
|
||||
33
src/lib/dexie/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import Dexie from 'dexie'
|
||||
|
||||
const db = new Dexie('zy')
|
||||
|
||||
db.version(1).stores({
|
||||
theme: '++id, theme',
|
||||
site: '++id, site',
|
||||
video: '++id, name, type, time, detail, urls, index'
|
||||
})
|
||||
|
||||
db.version(2).stores({
|
||||
setting: 'id, theme, site, language, cloud, cloudKey',
|
||||
video: '++id, site, name, type, time, detail, index',
|
||||
history: '++id, site, name, type, time, detail, index, currentTime',
|
||||
mini: 'id, site, name, type, time, detail, index, currentTime'
|
||||
})
|
||||
|
||||
const initData = [{
|
||||
id: 0,
|
||||
theme: 'light',
|
||||
site: 'zuidazy',
|
||||
language: 'zhCn',
|
||||
cloud: false,
|
||||
cloudKey: ''
|
||||
}]
|
||||
|
||||
db.on('populate', () => {
|
||||
db.setting.bulkAdd(initData)
|
||||
})
|
||||
|
||||
db.open()
|
||||
|
||||
export default db
|
||||
13
src/lib/dexie/mini.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import db from './index'
|
||||
const { mini } = db
|
||||
export default {
|
||||
async add (doc) {
|
||||
return await mini.add(doc)
|
||||
},
|
||||
async find () {
|
||||
return await mini.get({ id: 0 })
|
||||
},
|
||||
async update (docs) {
|
||||
return await mini.update(0, docs)
|
||||
}
|
||||
}
|
||||
10
src/lib/dexie/setting.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import db from './index'
|
||||
const { setting } = db
|
||||
export default {
|
||||
async find () {
|
||||
return await setting.get({ id: 0 })
|
||||
},
|
||||
async update (docs) {
|
||||
return await setting.update(0, docs)
|
||||
}
|
||||
}
|
||||
19
src/lib/dexie/video.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import db from './index'
|
||||
const { video } = db
|
||||
export default {
|
||||
async add (doc) {
|
||||
return await video.add(doc)
|
||||
},
|
||||
async find (doc) {
|
||||
return await video.get(doc)
|
||||
},
|
||||
async update (id, docs) {
|
||||
return await video.update(id, docs)
|
||||
},
|
||||
async all () {
|
||||
return await video.toArray()
|
||||
},
|
||||
async remove (id) {
|
||||
return await video.delete(id)
|
||||
}
|
||||
}
|
||||
6
src/lib/element/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import Vue from 'vue'
|
||||
import { Message, Pagination } from 'element-ui'
|
||||
|
||||
Vue.use(Pagination)
|
||||
|
||||
Vue.prototype.$m = Message
|
||||
1481
src/lib/site/sites.js
Normal file
478
src/lib/site/tools.js
Normal file
@@ -0,0 +1,478 @@
|
||||
import axios from 'axios'
|
||||
import { getSite } from './sites'
|
||||
const zy = {
|
||||
key: 'zuidazy', // sites[n] 视频源
|
||||
id: 0, // 视频类型
|
||||
page: 1, // 第几页
|
||||
keywords: '', // 搜索关键字
|
||||
// 获取浏览列表
|
||||
film_get (key, id = 0, page = 1) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const site = getSite(key)
|
||||
let url = ''
|
||||
if (id === 0) {
|
||||
url = site.new.replace(/{page}/, page)
|
||||
} else {
|
||||
url = site.view.replace(/{id}/, id).replace(/{page}/, page)
|
||||
}
|
||||
const type = site.type
|
||||
axios.get(url).then(async res => {
|
||||
const data = res.data
|
||||
if (type === 0) {
|
||||
const zeroData = await this.film_get_type_zero(data, key)
|
||||
resolve(zeroData)
|
||||
}
|
||||
if (type === 1) {
|
||||
const oneData = await this.film_get_type_one(data, key)
|
||||
resolve(oneData)
|
||||
}
|
||||
if (type === 2) {
|
||||
const twoData = await this.film_get_type_two(data, key)
|
||||
resolve(twoData)
|
||||
}
|
||||
if (type === 3) {
|
||||
const threeData = await this.film_get_type_three(data, key)
|
||||
resolve(threeData)
|
||||
}
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
film_get_type_zero (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.xing_vb li')
|
||||
const d = { list: [], total: 0, update: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[3].innerText,
|
||||
time: list[i].childNodes[5].innerText,
|
||||
detail: url + list[i].childNodes[1].querySelector('a').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
d.update = parseInt(html.querySelectorAll('.xing_top_right li strong')[0].innerText)
|
||||
let t = html.querySelector('.pages').innerText
|
||||
t = t.split('条')[0]
|
||||
t = t.split('共')[1]
|
||||
d.total = parseInt(t)
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
film_get_type_one (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.videoContent li')
|
||||
const d = { list: [], total: 0, update: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].querySelector('.videoName').innerText,
|
||||
type: list[i].querySelector('.category').innerText,
|
||||
time: list[i].querySelector('.time').innerText,
|
||||
detail: url + list[i].querySelector('.address').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
d.update = parseInt(html.querySelectorAll('.header_list li span')[0].innerText)
|
||||
let t = html.querySelectorAll('.pagination li')
|
||||
t = t[t.length - 2].innerText
|
||||
d.total = parseInt(t) * 50
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
film_get_type_two (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.nr')
|
||||
const d = { list: [], total: 0, update: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: '',
|
||||
type: list[i].querySelector('.btn_span').innerText,
|
||||
time: list[i].querySelector('.hours').innerText,
|
||||
detail: url + list[i].querySelector('.name').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
let name = list[i].querySelector('.name').innerText
|
||||
name = name.replace(/^\s*|\s*$/g, '')
|
||||
info.name = name
|
||||
d.list.push(info)
|
||||
}
|
||||
d.update = parseInt(html.querySelector('.kfs em').innerText)
|
||||
d.total = parseInt(html.querySelector('.date span').innerText)
|
||||
let t = html.querySelector('.pag2').innerText
|
||||
t = t.split('条')[0]
|
||||
t = t.split('共')[1]
|
||||
d.total = parseInt(t)
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
film_get_type_three (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.xing_vb li')
|
||||
const d = { list: [], total: 0, update: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[2].innerText,
|
||||
time: list[i].childNodes[3].innerText,
|
||||
detail: url + list[i].childNodes[1].querySelector('a').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
d.update = parseInt(html.querySelectorAll('.xing_top_right li strong')[0].innerText)
|
||||
let t = html.querySelector('.pages').innerText
|
||||
t = t.split('条')[0]
|
||||
t = t.split('共')[1]
|
||||
d.total = parseInt(t)
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取详情
|
||||
detail_get (key, url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const type = getSite(key).type
|
||||
axios.get(url).then(async res => {
|
||||
if (type === 0) {
|
||||
const zeroData = await this.detail_get_type_zero(res.data, key)
|
||||
resolve(zeroData)
|
||||
}
|
||||
if (type === 1) {
|
||||
const oneData = await this.detail_get_type_one(res.data, key)
|
||||
resolve(oneData)
|
||||
}
|
||||
if (type === 2) {
|
||||
const twoData = await this.detail_get_type_two(res.data, key)
|
||||
resolve(twoData)
|
||||
}
|
||||
if (type === 3) {
|
||||
const threeData = await this.detail_get_type_three(res.data, key)
|
||||
resolve(threeData)
|
||||
}
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
detail_get_type_zero (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const data = {
|
||||
site: key,
|
||||
name: '',
|
||||
info: '',
|
||||
desc: '',
|
||||
m3u8_urls: [],
|
||||
mp4_urls: []
|
||||
}
|
||||
const vodBox = html.querySelector('.vodBox')
|
||||
data.info = vodBox.innerHTML
|
||||
const title = html.querySelector('.vodh h2').innerText
|
||||
const index = html.querySelector('.vodh span').innerText
|
||||
data.name = title + index
|
||||
const vodInfo = html.querySelectorAll('.playBox')
|
||||
for (let i = 0; i < vodInfo.length; i++) {
|
||||
const k = vodInfo[i].innerText
|
||||
if (k.indexOf('剧情介绍') >= 0) {
|
||||
data.desc = vodInfo[i].querySelector('.vodplayinfo').innerText
|
||||
}
|
||||
}
|
||||
const vodLi = html.querySelectorAll('.ibox .vodplayinfo li')
|
||||
const m3u8UrlArr = []
|
||||
const mp4UrlArr = []
|
||||
for (let i = 0; i < vodLi.length; i++) {
|
||||
const j = vodLi[i].innerText
|
||||
if (j.indexOf('.m3u8') >= 0) {
|
||||
m3u8UrlArr.push(j)
|
||||
}
|
||||
if (j.indexOf('.mp4') >= 0) {
|
||||
mp4UrlArr.push(j)
|
||||
}
|
||||
}
|
||||
data.m3u8_urls = m3u8UrlArr
|
||||
data.mp4_urls = mp4UrlArr
|
||||
resolve(data)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
detail_get_type_one (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const data = {
|
||||
site: key,
|
||||
name: '',
|
||||
info: '',
|
||||
desc: '',
|
||||
m3u8_urls: [],
|
||||
mp4_urls: []
|
||||
}
|
||||
let name = html.querySelector('.whitetitle').innerText
|
||||
name = name.split(':')[1].replace(/^\s*|\s*$/g, '')
|
||||
data.name = name
|
||||
const vodBox = html.querySelector('.white').innerHTML
|
||||
data.info = vodBox
|
||||
const vodInfo = html.querySelectorAll('.white')
|
||||
for (let i = 0; i < vodInfo.length; i++) {
|
||||
const k = vodInfo[i].innerText
|
||||
if (k.indexOf('剧情介绍') >= 0) {
|
||||
data.desc = vodInfo[i].querySelector('div').innerText
|
||||
}
|
||||
}
|
||||
const vodLi = html.querySelectorAll('.playlist li #m3u8')
|
||||
const m3u8UrlArr = []
|
||||
const mp4UrlArr = []
|
||||
for (let i = 0; i < vodLi.length; i++) {
|
||||
const j = vodLi[i].value
|
||||
if (j.indexOf('.m3u8') >= 0) {
|
||||
m3u8UrlArr.push(j)
|
||||
}
|
||||
if (j.indexOf('.mp4') >= 0) {
|
||||
mp4UrlArr.push(j)
|
||||
}
|
||||
}
|
||||
data.m3u8_urls = m3u8UrlArr
|
||||
data.mp4_urls = mp4UrlArr
|
||||
resolve(data)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
detail_get_type_two (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const data = {
|
||||
site: key,
|
||||
name: '',
|
||||
info: '',
|
||||
desc: '',
|
||||
m3u8_urls: [],
|
||||
mp4_urls: []
|
||||
}
|
||||
const title = html.querySelector('.vodh h2').innerText
|
||||
const index = html.querySelector('.vodh span').innerText
|
||||
data.name = title + index
|
||||
const vodBox = html.querySelector('.vodBox').innerHTML
|
||||
data.info = vodBox
|
||||
data.desc = html.querySelector('.vodplayinfo').innerText
|
||||
const vodLi = html.querySelectorAll('.vodplayinfo li')
|
||||
const m3u8UrlArr = []
|
||||
const mp4UrlArr = []
|
||||
for (let i = 0; i < vodLi.length; i++) {
|
||||
const j = vodLi[i].innerText
|
||||
if (j.indexOf('.m3u8') >= 0) {
|
||||
m3u8UrlArr.push(j)
|
||||
}
|
||||
if (j.indexOf('.mp4') >= 0) {
|
||||
mp4UrlArr.push(j)
|
||||
}
|
||||
}
|
||||
data.m3u8_urls = m3u8UrlArr
|
||||
data.mp4_urls = mp4UrlArr
|
||||
resolve(data)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
detail_get_type_three (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const data = {
|
||||
site: key,
|
||||
name: '',
|
||||
info: '',
|
||||
desc: '',
|
||||
m3u8_urls: [],
|
||||
mp4_urls: []
|
||||
}
|
||||
const vodBox = html.querySelector('.vodBox')
|
||||
data.info = vodBox.innerHTML
|
||||
const title = html.querySelector('.vodh h2').innerText
|
||||
const index = html.querySelector('.vodh span').innerText
|
||||
data.name = title + index
|
||||
const vodInfo = html.querySelectorAll('.playBox')
|
||||
for (let i = 0; i < vodInfo.length; i++) {
|
||||
const k = vodInfo[i].innerText
|
||||
if (k.indexOf('剧情介绍') >= 0) {
|
||||
data.desc = vodInfo[i].querySelector('.vodplayinfo').innerHTML
|
||||
}
|
||||
}
|
||||
const vodLi = html.querySelectorAll('.ibox .vodplayinfo li')
|
||||
const m3u8UrlArr = []
|
||||
const mp4UrlArr = []
|
||||
for (let i = 0; i < vodLi.length; i++) {
|
||||
const j = vodLi[i].innerText
|
||||
if (j.indexOf('.m3u8') >= 0) {
|
||||
m3u8UrlArr.unshift(j)
|
||||
}
|
||||
if (j.indexOf('.mp4') >= 0) {
|
||||
mp4UrlArr.unshift(j)
|
||||
}
|
||||
}
|
||||
data.m3u8_urls = m3u8UrlArr
|
||||
data.mp4_urls = mp4UrlArr
|
||||
resolve(data)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 搜索列表
|
||||
search_get (key, keywords = '', page = 1) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const site = getSite(key)
|
||||
const type = site.type
|
||||
let url = null
|
||||
if (type === 0) {
|
||||
url = site.search.replace(/{page}/, page).replace(/{keywords}/, keywords)
|
||||
}
|
||||
if (type === 1) {
|
||||
url = site.search.replace(/{keywords}/, keywords)
|
||||
}
|
||||
axios.get(url).then(async res => {
|
||||
const data = res.data
|
||||
if (type === 0) {
|
||||
const zeroData = await this.search_get_type_zero(data, key)
|
||||
resolve(zeroData)
|
||||
}
|
||||
if (type === 1) {
|
||||
const oneData = await this.search_get_type_one(data, key)
|
||||
resolve(oneData)
|
||||
}
|
||||
if (type === 3) {
|
||||
const threeData = await this.search_get_type_three(data, key)
|
||||
resolve(threeData)
|
||||
}
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
search_get_type_zero (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.xing_vb li')
|
||||
const d = { list: [], total: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[3].innerText,
|
||||
time: list[i].childNodes[5].innerText,
|
||||
detail: url + list[i].childNodes[1].querySelector('a').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
const t = html.querySelector('.nvc dd').innerText.replace(/[^\d]/g, '')
|
||||
d.total = parseInt(t)
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
search_get_type_one (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.videoContent li')
|
||||
const d = { list: [], total: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].querySelector('.videoName').innerText,
|
||||
type: list[i].querySelector('.category').innerText,
|
||||
time: list[i].querySelector('.time').innerText,
|
||||
detail: url + list[i].querySelector('.address').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
d.total = list.length
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
search_get_type_three (txt, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list = html.querySelectorAll('.xing_vb li')
|
||||
const d = { list: [], total: 0 }
|
||||
const url = getSite(key).url
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
const info = {
|
||||
site: key,
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[2].innerText,
|
||||
time: list[i].childNodes[3].innerText,
|
||||
detail: url + list[i].childNodes[1].querySelector('a').getAttribute('href'),
|
||||
index: 0
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
const t = html.querySelector('.nvc dd').innerText.replace(/[^\d]/g, '')
|
||||
d.total = parseInt(t)
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default zy
|
||||
@@ -1,41 +0,0 @@
|
||||
interface Site {
|
||||
id: string
|
||||
name: string
|
||||
url: string
|
||||
type: Array<any>
|
||||
}
|
||||
|
||||
const sites:Array<Site> = [
|
||||
{
|
||||
id: 'okzy',
|
||||
name: 'OK资源网',
|
||||
url: 'https://www.okzy.co',
|
||||
type: [[ '最新', '0' ], [ '电影', '1' ], [ '电视剧', '2' ], [ '综艺', '3' ], [ '动漫', '4' ], [ '伦理', '21' ], [ '福利', '22' ], [ '解说', '33' ]]
|
||||
},
|
||||
{
|
||||
id: 'zuidazy',
|
||||
name: '最大资源网',
|
||||
url: 'http://www.zuidazy1.com',
|
||||
type: [[ '最新', '0' ], [ '电影', '1' ], [ '电视剧', '2' ], [ '综艺', '3' ], [ '动漫', '4' ], [ '福利', '16' ], [ '伦理', '17' ], [ '音乐', '18' ]]
|
||||
},
|
||||
{
|
||||
id: 'subo',
|
||||
name: '速播资源站',
|
||||
url: 'https://www.subo988.com',
|
||||
type: [[ '最新', '0' ], [ '电影', '1' ], [ '电视剧', '2' ], [ '综艺', '3' ], [ '动漫', '4' ], [ '伦理', '16' ], [ '音乐', '20' ]]
|
||||
},
|
||||
{
|
||||
id: 'zuixinzy',
|
||||
name: '最新资源网',
|
||||
url: 'http://www.zuixinzy.cc',
|
||||
type: [[ '最新', '0' ], [ '电影', '1' ], [ '电视剧', '2' ], [ '综艺', '3' ], [ '动漫', '4' ], ['伦理', '21'], ['情色', '23'], [ '福利', '30' ], [ '解说', '34' ]]
|
||||
},
|
||||
{
|
||||
id: '123ku',
|
||||
name: '123资源网',
|
||||
url: 'https://www.123ku.com',
|
||||
type: [[ '最新', '0' ], [ '电影', '1' ], [ '电视剧', '2' ], [ '综艺', '3' ], [ '动漫', '4' ], [ '伦理', '16' ]]
|
||||
}
|
||||
]
|
||||
|
||||
export default sites
|
||||
@@ -1,171 +0,0 @@
|
||||
import fly from 'flyio'
|
||||
import sites from './sites'
|
||||
import { TimeSelect } from 'element-ui'
|
||||
|
||||
interface ZY {
|
||||
num: number
|
||||
page: number
|
||||
key: string
|
||||
site: any
|
||||
list: Array<string>
|
||||
getInfoRequire: any
|
||||
getInfoHtml: any
|
||||
info: any
|
||||
detail: any
|
||||
films: any
|
||||
}
|
||||
|
||||
interface info {
|
||||
name?: string
|
||||
type?: string
|
||||
time?: string
|
||||
detail?: string
|
||||
urls?: Array<string>
|
||||
index?: number
|
||||
}
|
||||
|
||||
interface detail {
|
||||
box?: any
|
||||
info?: any
|
||||
urls?: Array<string>
|
||||
}
|
||||
|
||||
const zy: ZY = {
|
||||
num: 0,
|
||||
page: 1,
|
||||
key: '',
|
||||
site: {},
|
||||
list: [],
|
||||
getInfoRequire () {
|
||||
return new Promise((resolve, reject) => {
|
||||
let key = encodeURI(this.key)
|
||||
const params = `${this.site.url}/index.php?m=vod-search-pg-${this.page}-wd-${key}.html`
|
||||
fly.get(params).then(res => {
|
||||
this.getInfoHtml(res.data).then((data: any) => {
|
||||
resolve(data)
|
||||
})
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
getInfoHtml (txt: string): any {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(txt, 'text/html')
|
||||
const list: any = html.querySelectorAll('.xing_vb li')
|
||||
let d: any = { list: [], total: 0 }
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
let info: info = {
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[3].innerText,
|
||||
time: list[i].childNodes[5].innerText,
|
||||
detail: this.site.url + list[i].childNodes[1].childNodes[0].getAttribute('href'),
|
||||
index: 0,
|
||||
urls: []
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
let num: any = (<HTMLImageElement>html.querySelectorAll('.nvc dd span')[1]).innerText
|
||||
num = parseInt(num)
|
||||
d.total = num
|
||||
resolve(d)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
info (n: number = 0, p: number = 1, k: string = '') {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.num = n
|
||||
this.page = p
|
||||
this.key = k
|
||||
this.site = sites[n]
|
||||
this.getInfoRequire().then((res: any) => {
|
||||
resolve(res)
|
||||
}).catch((err: any) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
detail (url: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!url) return
|
||||
fly.get(url).then(res => {
|
||||
const parser = new DOMParser()
|
||||
let html = parser.parseFromString(res.data, 'text/html')
|
||||
let data: detail = {
|
||||
box: '',
|
||||
info: '',
|
||||
urls: []
|
||||
}
|
||||
let vodBox = html.querySelector('.vodBox')
|
||||
if (vodBox) {
|
||||
data.box = vodBox.innerHTML
|
||||
}
|
||||
let vodInfo = {}
|
||||
if (url.indexOf('123ku') !== -1 || url.indexOf('subo988') !== -1) {
|
||||
vodInfo = html.querySelectorAll('.vodplayinfo')[1]
|
||||
} else {
|
||||
vodInfo = <HTMLImageElement>html.querySelector('.vodplayinfo')
|
||||
}
|
||||
data.info = (<HTMLImageElement>vodInfo).innerText
|
||||
let urls = html.querySelectorAll('.vodplayinfo li')
|
||||
let arr = []
|
||||
for (let i in urls) {
|
||||
let j = (<HTMLImageElement>urls[i]).innerText
|
||||
if (j !== undefined && j.indexOf('.m3u8') !== -1) {
|
||||
arr.push((<HTMLImageElement>urls[i]).innerText)
|
||||
}
|
||||
}
|
||||
data.urls = arr
|
||||
resolve(data)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
films (n: number = 0, p: number = 1, type: string = '0') {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.site = sites[n]
|
||||
let url: string = sites[n].url
|
||||
let params: string = ''
|
||||
if (type === '0') {
|
||||
params = `${url}/?m=vod-index-pg-${p}.html`
|
||||
} else {
|
||||
params = `${url}/?m=vod-type-id-${type}-pg-${p}.html`
|
||||
}
|
||||
fly.get(params).then(res => {
|
||||
const parser = new DOMParser()
|
||||
const html = parser.parseFromString(res.data, 'text/html')
|
||||
const list: any = html.querySelectorAll('.xing_vb li')
|
||||
let d: any = { list: [], total: 0 }
|
||||
for (let i = 1; i < list.length - 1; i++) {
|
||||
let info: info = {
|
||||
name: list[i].childNodes[1].innerText,
|
||||
type: list[i].childNodes[3].innerText,
|
||||
time: list[i].childNodes[5].innerText,
|
||||
detail: this.site.url + list[i].querySelector('a').getAttribute('href'),
|
||||
index: 0,
|
||||
urls: []
|
||||
}
|
||||
d.list.push(info)
|
||||
}
|
||||
let num: any = html.querySelectorAll('.pages')
|
||||
if (num) {
|
||||
let n = num[0].innerText
|
||||
n = n.split('条')[0]
|
||||
n = n.split('共')[1]
|
||||
n = parseInt(n)
|
||||
d.total = n
|
||||
}
|
||||
resolve(d)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default zy
|
||||
48
src/locales/en.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"zh": "Chinese",
|
||||
"en": "English",
|
||||
"language": "Language",
|
||||
"default_site": "Default Site",
|
||||
"view": "View",
|
||||
"play": "Play",
|
||||
"star": "Star",
|
||||
"setting": "Setting",
|
||||
"exists": "Already exists",
|
||||
"videoName": "Video Name",
|
||||
"type": "Type",
|
||||
"time": "Time",
|
||||
"operate": "Operate",
|
||||
"share": "Share",
|
||||
"detail": "Detail",
|
||||
"close": "Close",
|
||||
"download": "Download",
|
||||
"all_download": "All Download",
|
||||
"next": "Next",
|
||||
"play_list": "Play List",
|
||||
"history": "History",
|
||||
"top": "Top",
|
||||
"mini": "Mini",
|
||||
"no_data": "No Data",
|
||||
"clear_data": "Clear Data",
|
||||
"delete": "Delete",
|
||||
"from": "From",
|
||||
"sync": "Sync",
|
||||
"total": "Items",
|
||||
"website": "Official Website",
|
||||
"issues": "Issues",
|
||||
"theme": "Theme",
|
||||
"donate": "Donate",
|
||||
"set_success": "Set up successfully.",
|
||||
"delete_success": "Delete successful.",
|
||||
"delete_failed": "Delete failed.",
|
||||
"star_success": "Collection success.",
|
||||
"last_video": "This is the last episode.",
|
||||
"qr_tips": "Long click recognition.",
|
||||
"zy_tips": "Prohibit the dissemination of illegal resources.",
|
||||
"share_tips": "It has been copied to the clipboard. Please share it~",
|
||||
"not_support_search": "Search is not supported on this site.",
|
||||
"copy_success": "has been copied, Download it now",
|
||||
"async_failed": "Synchronization successful, no updates found.",
|
||||
"async_success": "Synchronization succeeded, update found.",
|
||||
"no_history": "No history data."
|
||||
}
|
||||
9
src/locales/index.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import en from './en.json'
|
||||
import zhCn from './zh-cn'
|
||||
|
||||
export const defaultLocal = 'zhCn'
|
||||
|
||||
export const languages = {
|
||||
en: en,
|
||||
zhCn: zhCn
|
||||
}
|
||||
48
src/locales/zh-cn.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"zh": "中文",
|
||||
"en": "英文",
|
||||
"language": "语言",
|
||||
"default_site": "默认源",
|
||||
"view": "浏览",
|
||||
"play": "播放",
|
||||
"star": "收藏",
|
||||
"setting": "设置",
|
||||
"exists": "已存在",
|
||||
"videoName": "视频名称",
|
||||
"type": "类型",
|
||||
"time": "时间",
|
||||
"operate": "操作",
|
||||
"share": "分享",
|
||||
"detail": "详情",
|
||||
"close": "关闭",
|
||||
"download": "下载",
|
||||
"all_download": "全集下载",
|
||||
"next": "下一集",
|
||||
"play_list": "播放列表",
|
||||
"history": "历史记录",
|
||||
"top": "置顶",
|
||||
"mini": "精简模式",
|
||||
"no_data": "无数据",
|
||||
"clear_data": "清空数据",
|
||||
"delete": "删除",
|
||||
"from": "来源",
|
||||
"sync": "同步",
|
||||
"total": "条数据",
|
||||
"website": "官网",
|
||||
"issues": "内测反馈",
|
||||
"theme": "主题",
|
||||
"donate": "捐赠",
|
||||
"set_success": "设置成功。",
|
||||
"delete_success": "删除成功。",
|
||||
"delete_failed": "删除失败。",
|
||||
"star_success": "收藏成功。",
|
||||
"last_video": "这已经是最后一集了。",
|
||||
"qr_tips": "长按二维码,识别播放。",
|
||||
"zy_tips": "『ZY Player』技术支持,严禁传播违法资源。",
|
||||
"share_tips": "已复制到剪贴板,快去分享吧~ 严禁传播违法资源!!!",
|
||||
"not_support_search": "这个网站不支持搜索。",
|
||||
"copy_success": "已复制,快去下载吧。",
|
||||
"async_failed": "同步成功, 未查询到更新。",
|
||||
"async_success": "同步成功, 查询到更新。",
|
||||
"no_history": "无历史记录"
|
||||
}
|
||||
26
src/main.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import store from './store'
|
||||
import 'modern-normalize'
|
||||
import Register from './components/register'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import { languages, defaultLocal } from './locales/index'
|
||||
import './lib/element/index'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Register.registerComponents()
|
||||
|
||||
Vue.use(VueI18n)
|
||||
const messages = Object.assign(languages)
|
||||
const i18n = new VueI18n({
|
||||
locale: defaultLocal,
|
||||
fallbackLocale: 'zhCn',
|
||||
messages
|
||||
})
|
||||
|
||||
new Vue({
|
||||
store,
|
||||
i18n,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
14
src/main.ts
@@ -1,14 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import store from './store'
|
||||
import './plugins/element.ts'
|
||||
import Register from './page/register'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Register.registerComponents()
|
||||
|
||||
new Vue({
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
279
src/mini/Mini.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div class="mini">
|
||||
<div class="top">
|
||||
<div class="left">
|
||||
<span class="number" v-show="show.number">{{index + 1}} / {{length}}</span>
|
||||
<span class="zy-svg" @click="prevEvent" v-show="show.prev">
|
||||
<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="show.next">
|
||||
<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">
|
||||
<input type="number" min="5" max="100" v-model="opacity" @change="opacityChange"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="min" @click="frameClickEvent('miniMin')"></span>
|
||||
<span class="close" @click="frameClickEvent('miniClose')"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div id="xg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import tools from '../lib/site/tools'
|
||||
import mini from '../lib/dexie/mini'
|
||||
import history from '../lib/dexie/history'
|
||||
import 'xgplayer'
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
const ipc = require('electron').ipcRenderer
|
||||
export default {
|
||||
name: 'mini',
|
||||
data () {
|
||||
return {
|
||||
xg: null,
|
||||
config: {
|
||||
id: 'xg',
|
||||
lang: 'zh-cn',
|
||||
url: '',
|
||||
fluid: true,
|
||||
autoplay: false,
|
||||
videoInit: true,
|
||||
screenShot: true,
|
||||
keyShortcut: 'on',
|
||||
crossOrigin: true,
|
||||
defaultPlaybackRate: 1,
|
||||
playbackRate: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 5]
|
||||
},
|
||||
opacity: 100,
|
||||
video: {},
|
||||
d: {},
|
||||
show: {
|
||||
prev: false,
|
||||
next: false,
|
||||
number: false
|
||||
},
|
||||
index: 0,
|
||||
length: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
frameClickEvent (e) {
|
||||
ipc.send(e)
|
||||
},
|
||||
opacityChange (e) {
|
||||
ipc.send('mini-opacity', this.opacity / 100)
|
||||
},
|
||||
getUrls () {
|
||||
mini.find().then(res => {
|
||||
const v = res
|
||||
if (v.index > 0) {
|
||||
this.show.next = true
|
||||
this.show.number = true
|
||||
}
|
||||
this.video = res
|
||||
tools.detail_get(v.site, v.detail).then(res => {
|
||||
this.d = res
|
||||
if (v.index >= this.d.m3u8_urls.length) {
|
||||
this.show.next = false
|
||||
}
|
||||
this.index = v.index
|
||||
this.length = this.d.m3u8_urls.length
|
||||
const link = res.m3u8_urls[v.index]
|
||||
const src = link.split('$')[1]
|
||||
this.xg.src = src
|
||||
const currentTime = v.currentTime
|
||||
if (currentTime !== '') {
|
||||
this.xg.play()
|
||||
this.xg.once('playing', () => {
|
||||
this.xg.currentTime = currentTime
|
||||
})
|
||||
} else {
|
||||
this.xg.play()
|
||||
}
|
||||
this.onPlayVideo()
|
||||
})
|
||||
})
|
||||
},
|
||||
onPlayVideo () {
|
||||
const h = { ...this.video }
|
||||
history.find({ detail: h.detail }).then(res => {
|
||||
if (res) {
|
||||
h.id = res.id
|
||||
history.update(res.id, h)
|
||||
} else {
|
||||
h.currentTime = ''
|
||||
delete h.id
|
||||
history.add(h)
|
||||
}
|
||||
})
|
||||
this.timerEvent(h.detail)
|
||||
},
|
||||
timerEvent (d) {
|
||||
this.timer = setInterval(() => {
|
||||
history.find({ detail: d }).then(res => {
|
||||
if (res) {
|
||||
const h = { ...this.video }
|
||||
h.currentTime = this.xg.currentTime
|
||||
h.id = res.id
|
||||
history.update(res.id, h)
|
||||
}
|
||||
})
|
||||
}, 10000)
|
||||
},
|
||||
prevEvent () {
|
||||
if (this.index > 0) {
|
||||
this.index--
|
||||
let src = this.d.m3u8_urls[this.index]
|
||||
src = src.split('$')[1]
|
||||
this.xg.src = src
|
||||
this.show.next = true
|
||||
}
|
||||
if (this.index === 0) {
|
||||
this.show.prev = false
|
||||
}
|
||||
},
|
||||
nextEvent () {
|
||||
if (this.index < this.d.m3u8_urls.length - 1) {
|
||||
this.index++
|
||||
let src = this.d.m3u8_urls[this.index]
|
||||
src = src.split('$')[1]
|
||||
this.xg.src = src
|
||||
this.show.prev = true
|
||||
}
|
||||
if (this.index === this.d.m3u8_urls.length - 1) {
|
||||
this.show.next = false
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getUrls()
|
||||
},
|
||||
mounted () {
|
||||
this.xg = new Hls(this.config)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
html,body{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background-color: #000;
|
||||
}
|
||||
.mini{
|
||||
box-sizing: border-box;
|
||||
.top{
|
||||
-webkit-app-region: drag;
|
||||
width: 100%;
|
||||
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: #fff;
|
||||
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;
|
||||
.number{
|
||||
color: #fff;
|
||||
margin: 0 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.opacity{
|
||||
-webkit-app-region: no-drag;
|
||||
margin-left: 10px;
|
||||
input{
|
||||
text-indent: 4px;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right{
|
||||
width: 80px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
span{
|
||||
-webkit-app-region: no-drag;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
&.min{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom{
|
||||
width: 100%;
|
||||
height: 305px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
7
src/mini/main.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Vue from 'vue'
|
||||
import Mini from './Mini'
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
render: h => h(Mini)
|
||||
}).$mount('#app')
|
||||
@@ -1,172 +0,0 @@
|
||||
<template>
|
||||
<el-row class="film">
|
||||
<el-row class="film-tabs">
|
||||
<el-tabs v-model="tabs" @tab-click="tabClick">
|
||||
<el-tab-pane class="film-tabpane" v-for="(i, j) in sites[site].type" :key="j" :label="i[0]" :name="i[1]"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-row>
|
||||
<el-row class="film-table-box table-box">
|
||||
<el-table :data="filmData" stripe class="film-table" v-loading="loading" size="mini">
|
||||
<el-table-column prop="name" label="影片名称"></el-table-column>
|
||||
<el-table-column prop="type" label="影片类别" width="120"></el-table-column>
|
||||
<el-table-column prop="time" label="更新时间" width="180"></el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" @click="tableBtnClick('detail', scope.row)">详情</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('star', scope.row)">收藏</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('play', scope.row)">播放</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
<el-row class="film-bottom" type="flex" justify="space-between">
|
||||
<el-select v-model="site" placeholder="请选择" size="small" @change="selectSite">
|
||||
<el-option
|
||||
v-for="(i, j) in sites"
|
||||
:key="i.id"
|
||||
:label="i.name"
|
||||
:value="j">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-pagination
|
||||
small
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:current-page="filmPage"
|
||||
@current-change="pageChange"
|
||||
:page-size="50"
|
||||
:total="filmTotal">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import zy from '@/lib/util.zy'
|
||||
import sites from '@/lib/sites'
|
||||
import { mapMutations } from 'vuex'
|
||||
import video from '@/plugins/dexie/video'
|
||||
export default Vue.extend({
|
||||
data () {
|
||||
return {
|
||||
sites: sites,
|
||||
tabs: '0',
|
||||
filmPage: 1,
|
||||
filmTotal: 0,
|
||||
filmData: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
site: {
|
||||
get () {
|
||||
return this.$store.getters.getSite
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SITE(val)
|
||||
}
|
||||
},
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_SITE', 'SET_DETAIL', 'SET_MAIN', 'SET_VIDEO']),
|
||||
tabClick (tab:any) {
|
||||
this.filmPage = 1
|
||||
this.getFilmList(this.site, this.filmPage, tab.name)
|
||||
},
|
||||
selectSite (e:any) {
|
||||
this.site = e
|
||||
this.tabs = '0'
|
||||
this.filmPage = 1
|
||||
this.getFilmList(e, 1, '0')
|
||||
},
|
||||
pageChange (e:number) {
|
||||
this.filmPage = e
|
||||
this.getFilmList(this.site, this.filmPage, this.tabs)
|
||||
},
|
||||
getFilmList (n: number = 0, p: number = 1, type: string = '0') {
|
||||
this.loading = true
|
||||
this.filmData = []
|
||||
this.tabs = type
|
||||
zy.films(n, p, type).then((res: any) => {
|
||||
this.filmTotal = res.total
|
||||
this.filmData = res.list
|
||||
this.filmPage = p
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
tableBtnClick (type: string, e: any) {
|
||||
if (type === 'detail') {
|
||||
let d = {
|
||||
show: true,
|
||||
video: e
|
||||
}
|
||||
this.SET_DETAIL(d)
|
||||
}
|
||||
if (type === 'star') {
|
||||
video.find({ detail: e.detail }).then(res => {
|
||||
if (res) {
|
||||
this.$message.warning('已存在')
|
||||
} else {
|
||||
video.add(e).then(res => {
|
||||
this.$message.success('收藏成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type === 'play') {
|
||||
this.Main = 'Player'
|
||||
this.video = e
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getFilmList()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.film{
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.film-tabs{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
}
|
||||
.film-table-box{
|
||||
position: absolute;
|
||||
top: 54px;
|
||||
width: 100%;
|
||||
height: calc(100% - 100px);
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 6px;
|
||||
}
|
||||
}
|
||||
.film-bottom{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,237 +0,0 @@
|
||||
<template>
|
||||
<el-row class="player">
|
||||
<el-row class="player-show" v-if="Object.keys(video).length > 0">
|
||||
<el-row class="player-title">
|
||||
<el-row class="player-title-box" type="flex" justify="space-between">
|
||||
<span>
|
||||
<span>{{video.name ? video.name + ' -- ' : '' }}</span>
|
||||
<span>{{ num }}</span>
|
||||
</span>
|
||||
<span>
|
||||
<el-button size="mini" @click="openDetail" icon="el-icon-document" circle></el-button>
|
||||
<el-button size="mini" v-show="!star" @click="starEvent" icon="el-icon-star-off" circle></el-button>
|
||||
<el-button size="mini" v-show="star" @click="starEvent" icon="el-icon-star-on" circle></el-button>
|
||||
</span>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="player-box">
|
||||
<div id="xg"></div>
|
||||
</el-row>
|
||||
<el-row class="player-films table-box">
|
||||
<el-row class="player-films-box">
|
||||
<el-button :type="j === video.index ? 'primary' : ''" size="mini" v-for="(i, j) in urls" :key="j" @click="playBtnClick(i, j)" plain>{{i | ftLink}}</el-button>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="player-none" v-if="Object.keys(video).length <= 0">
|
||||
<el-row class="tips">
|
||||
浏览或者搜索资源, 点击播放视频, 即可观看~
|
||||
</el-row>
|
||||
<el-row class="btns">
|
||||
<el-button size="small" @click="goView('Film')" icon="el-icon-film">浏览</el-button>
|
||||
<el-button size="small" @click="goView('Search')" icon="el-icon-search">搜索</el-button>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import { mapMutations } from 'vuex'
|
||||
import zy from '@/lib/util.zy'
|
||||
import 'xgplayer'
|
||||
// @ts-ignore
|
||||
import Hls from 'xgplayer-hls.js'
|
||||
import video from '@/plugins/dexie/video'
|
||||
export default Vue.extend({
|
||||
data () {
|
||||
return {
|
||||
xg: null,
|
||||
config: {
|
||||
id: 'xg',
|
||||
url: '',
|
||||
fluid: false,
|
||||
autoplay: true,
|
||||
videoInit: true,
|
||||
keyShortcut: 'on',
|
||||
defaultPlaybackRate: 1,
|
||||
playbackRate: [0.5, 0.75, 1, 1.5, 2]
|
||||
},
|
||||
urls: [],
|
||||
num: '',
|
||||
star: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
d () {
|
||||
return this.$store.getters.getDetail
|
||||
},
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
video: {
|
||||
handler () {
|
||||
this.getUrls()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
ftLink (e: string) {
|
||||
let name = e.split('$')[0]
|
||||
return name
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_DETAIL', 'SET_VIDEO', 'SET_MAIN']),
|
||||
goView (e: string) {
|
||||
this.Main = e
|
||||
},
|
||||
openDetail () {
|
||||
let d = {
|
||||
show: true,
|
||||
video: this.video
|
||||
}
|
||||
this.SET_DETAIL(d)
|
||||
},
|
||||
getUrls () {
|
||||
if (this.xg) {
|
||||
// @ts-ignore
|
||||
this.xg.destroy(true)
|
||||
this.xg = null
|
||||
}
|
||||
this.checkStar()
|
||||
zy.detail(this.video.detail).then((res: any) => {
|
||||
this.urls = res.urls
|
||||
if (this.xg === null) {
|
||||
let info: any = this.urls[this.video.index]
|
||||
let url = info.split('$')[1]
|
||||
this.num = info.split('$')[0]
|
||||
this.config.url = url
|
||||
this.$nextTick(() => {
|
||||
this.xg = new Hls(this.config)
|
||||
// @ts-ignore
|
||||
this.xg.on('error', () => {
|
||||
this.$message.error('播放失败请重试~')
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
checkStar () {
|
||||
video.find({ detail: this.video.detail }).then(res => {
|
||||
if (res) {
|
||||
this.star = true
|
||||
} else {
|
||||
this.star = false
|
||||
}
|
||||
})
|
||||
},
|
||||
starEvent () {
|
||||
video.find({ detail: this.video.detail }).then(res => {
|
||||
if (res) {
|
||||
video.remove(res.id).then(res => {
|
||||
if (!res) {
|
||||
this.$message.success('删除成功')
|
||||
this.star = false
|
||||
} else {
|
||||
this.$message.warning('删除失败, 请重试~')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
video.add(this.video).then(res => {
|
||||
this.star = true
|
||||
this.$message.success('收藏成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
playBtnClick (i: string, j: number) {
|
||||
if (this.video.index !== j) {
|
||||
let url = i.split('$')[1]
|
||||
this.num = i.split('$')[0]
|
||||
this.video.index = j
|
||||
// @ts-ignore
|
||||
this.xg.src = url
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.player{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.player-show{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.player-none{
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
.tips{
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.player-title{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
.player-title-box{
|
||||
width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
.player-box{
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
#xg{
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
.player-films{
|
||||
position: absolute;
|
||||
top: 400px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 400px);
|
||||
overflow: auto;
|
||||
button{
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
&::-webkit-scrollbar{
|
||||
width: 6px;
|
||||
}
|
||||
.player-films-box{
|
||||
width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import Film from './film.vue'
|
||||
import Search from './search.vue'
|
||||
import Player from './player.vue'
|
||||
import Star from './star.vue'
|
||||
import Setting from './setting.vue'
|
||||
|
||||
export default {
|
||||
registerComponents () {
|
||||
Vue.component('Film', Film)
|
||||
Vue.component('Search', Search)
|
||||
Vue.component('Player', Player)
|
||||
Vue.component('Star', Star)
|
||||
Vue.component('Setting', Setting)
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
<template>
|
||||
<el-row class="search">
|
||||
<el-row class="search-box" :class="table === true ? 'search-box hasTable' : 'search-box'">
|
||||
<el-input class="search-input" size="medium" clearable placeholder="请输入内容" v-model.trim="keywords" @change="searchEvent">
|
||||
<el-select v-model="site" slot="prepend" placeholder="请选择" @change="selectSite" style="width: 130px;">
|
||||
<el-option v-for="(i, j) in sites" :key="i.id" :label="i.name" :value="j"></el-option>
|
||||
</el-select>
|
||||
<el-button slot="append" icon="el-icon-search" @click="searchEvent"></el-button>
|
||||
</el-input>
|
||||
</el-row>
|
||||
<el-row v-show="table" class="search-table-box table-box">
|
||||
<el-table :data="filmData" stripe class="search-table" size="mini" v-loading="loading">
|
||||
<el-table-column prop="name" label="影片名称"></el-table-column>
|
||||
<el-table-column prop="type" label="影片类别" width="120"></el-table-column>
|
||||
<el-table-column prop="time" label="更新时间" width="180"></el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" @click="tableBtnClick('detail', scope.row)">详情</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('star', scope.row)">收藏</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('play', scope.row)">播放</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
<el-row v-show="table" class="search-bottom" type="flex" justify="end">
|
||||
<el-pagination
|
||||
small
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:current-page="filmPage"
|
||||
:page-size="50"
|
||||
@current-change="pageChange"
|
||||
:total="filmTotal">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import sites from '@/lib/sites'
|
||||
import zy from '@/lib/util.zy'
|
||||
import { mapMutations } from 'vuex'
|
||||
import video from '@/plugins/dexie/video'
|
||||
export default Vue.extend({
|
||||
data () {
|
||||
return {
|
||||
table: false,
|
||||
sites: sites,
|
||||
keywords: '',
|
||||
filmData: [],
|
||||
filmPage: 1,
|
||||
filmTotal: 0,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
site: {
|
||||
get () {
|
||||
return this.$store.getters.getSite
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SITE(val)
|
||||
}
|
||||
},
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_SITE', 'SET_DETAIL', 'SET_MAIN', 'SET_VIDEO']),
|
||||
selectSite (e:number) {
|
||||
this.site = e
|
||||
this.filmData = []
|
||||
this.filmPage = 1
|
||||
this.filmTotal = 0
|
||||
this.searchEvent()
|
||||
},
|
||||
searchEvent () {
|
||||
if (this.keywords !== '') {
|
||||
this.loading = true
|
||||
this.table = true
|
||||
zy.info(this.site, this.filmPage, this.keywords).then((res: any) => {
|
||||
this.filmData = res.list
|
||||
this.filmTotal = res.total
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
pageChange (e:number) {
|
||||
this.filmPage = e
|
||||
this.searchEvent()
|
||||
},
|
||||
tableBtnClick (type: string, e: any) {
|
||||
if (type === 'detail') {
|
||||
let d = {
|
||||
show: true,
|
||||
video: e
|
||||
}
|
||||
this.SET_DETAIL(d)
|
||||
}
|
||||
if (type === 'star') {
|
||||
video.find({ detail: e.detail }).then(res => {
|
||||
if (res) {
|
||||
this.$message.warning('已存在')
|
||||
} else {
|
||||
video.add(e).then(res => {
|
||||
this.$message.success('收藏成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type === 'play') {
|
||||
this.Main = 'Player'
|
||||
this.video = e
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.search{
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.search-box{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
animation: slideDown 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
height: 40px;
|
||||
}
|
||||
to{
|
||||
height: 90%;
|
||||
}
|
||||
}
|
||||
&.hasTable{
|
||||
animation: slideUp 0.2s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
height: 90%;
|
||||
opacity: 0;
|
||||
}
|
||||
to{
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-table-box{
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
width: 100%;
|
||||
height: calc(100% - 100px);
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 6px;
|
||||
}
|
||||
.search-table{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.search-bottom{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,173 +0,0 @@
|
||||
<template>
|
||||
<el-row class="setting">
|
||||
<el-row class="item site">
|
||||
<el-row class="title"><i class="el-icon-set-up"></i><span>默认资源</span></el-row>
|
||||
<el-row class="info">
|
||||
<el-select v-model="dbSite" placeholder="请选择" size="small" @change="selectSite">
|
||||
<el-option
|
||||
v-for="(i, j) in sites"
|
||||
:key="i.id"
|
||||
:label="i.name"
|
||||
:value="j">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="item theme">
|
||||
<el-row class="title"><i class="el-icon-picture-outline-round"></i><span>主题</span></el-row>
|
||||
<el-row class="card-box">
|
||||
<el-card shadow="hover" class="card">
|
||||
<img src="@/assets/image/light.png" class="image" @click="selectTheme('light')">
|
||||
<span size="mini">Light</span>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="card">
|
||||
<img src="@/assets/image/dark.png" class="image" @click="selectTheme('dark')">
|
||||
<span size="mini">Dark</span>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="item update">
|
||||
<el-row class="title"><i class="el-icon-refresh"></i><span>更新</span></el-row>
|
||||
<el-row class="btns">
|
||||
<el-button size="small" @click="checkUpdate">检查更新</el-button>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="item about">
|
||||
<el-row class="title"><i class="el-icon-view"></i><span>关于</span></el-row>
|
||||
<el-row class="info">
|
||||
<ul>
|
||||
<li><el-link :underline="false" @click="linkOpen('https://zy_player.hunlongyu.fun')">官网: ZY Player</el-link></li>
|
||||
<li><el-link :underline="false" @click="linkOpen('https://github.com/Hunlongyu/ZY-Player/issues')">反馈: Issues</el-link></li>
|
||||
</ul>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import sites from '@/lib/sites'
|
||||
import { mapMutations } from 'vuex'
|
||||
import { shell } from 'electron'
|
||||
import site from '@/plugins/dexie/site'
|
||||
import theme from '@/plugins/dexie/theme'
|
||||
import fly from 'flyio'
|
||||
export default Vue.extend({
|
||||
name: 'setting',
|
||||
data () {
|
||||
return {
|
||||
sites: sites,
|
||||
dbSite: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
site: {
|
||||
get () {
|
||||
return this.$store.getters.getSite
|
||||
},
|
||||
set (val) {
|
||||
this.SET_SITE(val)
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
get () {
|
||||
return this.$store.getters.getTheme
|
||||
},
|
||||
set (val) {
|
||||
this.SET_THEME(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_SITE', 'SET_THEME']),
|
||||
linkOpen (e:string) {
|
||||
if (e) {
|
||||
shell.openExternal(e)
|
||||
}
|
||||
},
|
||||
initSetting () {
|
||||
site.find().then(res => {
|
||||
if (!res) {
|
||||
site.add({ site: 0 })
|
||||
} else {
|
||||
this.dbSite = res.site
|
||||
this.site = res.site
|
||||
}
|
||||
})
|
||||
theme.find().then(res => {
|
||||
if (!res) {
|
||||
theme.add({ theme: 'light' })
|
||||
} else {
|
||||
this.theme = res.theme
|
||||
}
|
||||
})
|
||||
},
|
||||
selectSite () {
|
||||
site.update({ site: this.dbSite }).then(res => {
|
||||
this.site = this.dbSite
|
||||
this.$message.success('设置默认资源成功~')
|
||||
}).catch(() => {
|
||||
this.$message.warning('设置默认资源失败~')
|
||||
})
|
||||
},
|
||||
selectTheme (e: string) {
|
||||
theme.update({ theme: e }).then(res => {
|
||||
this.theme = e
|
||||
this.$message.success('切换主题成功~')
|
||||
}).catch(() => {
|
||||
this.$message.warning('切换主题失败~')
|
||||
})
|
||||
},
|
||||
checkUpdate () {
|
||||
fly.get('https://api.github.com/repos/Hunlongyu/ZY-Player/releases/latest').then(() => {}).catch(() => {})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.initSetting()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.setting{
|
||||
.item{
|
||||
margin-bottom: 30px;
|
||||
.title{
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
i{
|
||||
font-size: 24px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.about{
|
||||
ul{
|
||||
list-style: none;
|
||||
li{
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
.card-box{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
.card{
|
||||
width: 160px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
img{
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
span{
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,128 +0,0 @@
|
||||
<template>
|
||||
<el-row class="star">
|
||||
<el-row class="star-table-box table-box">
|
||||
<el-table :data="filmData" stripe class="film-table" size="mini" empty-text="收藏夹里空空的~快去填满我吧~">
|
||||
<el-table-column prop="name" label="影片名称"></el-table-column>
|
||||
<el-table-column prop="type" label="影片类别" width="120"></el-table-column>
|
||||
<el-table-column prop="time" label="更新时间" width="180"></el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" @click="tableBtnClick('detail', scope.row)">详情</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('delete', scope.row)">删除</el-button>
|
||||
<el-button size="small" type="text" @click="tableBtnClick('play', scope.row)">播放</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
<el-row class="star-bottom">
|
||||
<el-pagination
|
||||
small
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:current-page="filmPage"
|
||||
:page-size="50"
|
||||
:total="filmTotal">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import video from '@/plugins/dexie/video'
|
||||
import { mapMutations } from 'vuex'
|
||||
export default Vue.extend({
|
||||
data () {
|
||||
return {
|
||||
filmData: [],
|
||||
filmPage: 1,
|
||||
filmTotal: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
video: {
|
||||
get () {
|
||||
return this.$store.getters.getVideo
|
||||
},
|
||||
set (val) {
|
||||
this.SET_VIDEO(val)
|
||||
}
|
||||
},
|
||||
Main: {
|
||||
get () {
|
||||
return this.$store.getters.getMain
|
||||
},
|
||||
set (val) {
|
||||
this.SET_MAIN(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
Main: {
|
||||
handler () {
|
||||
this.getAllStar()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['SET_DETAIL', 'SET_VIDEO', 'SET_MAIN']),
|
||||
getAllStar () {
|
||||
video.all().then(res => {
|
||||
this.filmData = res
|
||||
this.filmTotal = res.length
|
||||
})
|
||||
},
|
||||
tableBtnClick (type: string, e: any) {
|
||||
if (type === 'detail') {
|
||||
let d = {
|
||||
show: true,
|
||||
video: e
|
||||
}
|
||||
this.SET_DETAIL(d)
|
||||
}
|
||||
if (type === 'delete') {
|
||||
video.remove(e.id).then(res => {
|
||||
if (!res) {
|
||||
this.$message.success('删除成功')
|
||||
} else {
|
||||
this.$message.warning('删除失败, 请重试~')
|
||||
}
|
||||
this.getAllStar()
|
||||
})
|
||||
}
|
||||
if (type === 'play') {
|
||||
this.Main = 'Player'
|
||||
this.video = e
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getAllStar()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.star{
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.star-table-box{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 6px;
|
||||
}
|
||||
}
|
||||
.star-bottom{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,42 +0,0 @@
|
||||
import Dexie from 'dexie'
|
||||
|
||||
class ZYDB extends Dexie {
|
||||
theme: Dexie.Table<theme, number>
|
||||
site: Dexie.Table<site, number>
|
||||
video: Dexie.Table<video, number>
|
||||
|
||||
constructor () {
|
||||
super('ZYDB')
|
||||
this.version(1).stores({
|
||||
theme: '++id, theme',
|
||||
site: '++id, site',
|
||||
video: '++id, name, type, time, detail, urls, index'
|
||||
})
|
||||
|
||||
this.theme = this.table('theme')
|
||||
this.site = this.table('site')
|
||||
this.video = this.table('video')
|
||||
}
|
||||
}
|
||||
|
||||
export interface theme {
|
||||
id: number
|
||||
theme?: string
|
||||
}
|
||||
|
||||
export interface site {
|
||||
id: number
|
||||
site?: number
|
||||
}
|
||||
|
||||
export interface video {
|
||||
id?: number
|
||||
name?: string
|
||||
type?: string
|
||||
time?: string
|
||||
detail?: string
|
||||
urls?: Array<string>
|
||||
index?: number
|
||||
}
|
||||
|
||||
export default new ZYDB()
|
||||
@@ -1,33 +0,0 @@
|
||||
import db from './index'
|
||||
|
||||
export default {
|
||||
add (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.site.add(data).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
find (): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.site.get(1).then((res: any) => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
update (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.site.update(1, data).then(updated => {
|
||||
if (updated) {
|
||||
resolve(updated)
|
||||
} else {
|
||||
reject(updated)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import db from './index'
|
||||
|
||||
export default {
|
||||
add (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.theme.add(data).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
find (): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.theme.get(1).then((res: any) => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
update (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.theme.update(1, data).then(updated => {
|
||||
if (updated) {
|
||||
resolve(updated)
|
||||
} else {
|
||||
reject(updated)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import db from './index'
|
||||
|
||||
export default {
|
||||
add (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.add(data).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
find (data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.get(data).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
all (): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.toArray().then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
update (id: number, data: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.update(id, data).then(updated => {
|
||||
if (updated) {
|
||||
resolve(updated)
|
||||
} else {
|
||||
reject(updated)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
count (): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.count().then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
remove (id: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.delete(id).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
clear () {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.video.clear().then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import {
|
||||
Container, Row, Col, Header, Aside, Main, Drawer,
|
||||
Tabs, TabPane, Button, Select, Option, Pagination,
|
||||
Table, TableColumn, Input, Card, Link, Loading,
|
||||
Notification, Message
|
||||
} from 'element-ui'
|
||||
|
||||
Vue.use(Container)
|
||||
Vue.use(Row)
|
||||
Vue.use(Col)
|
||||
Vue.use(Header)
|
||||
Vue.use(Aside)
|
||||
Vue.use(Main)
|
||||
Vue.use(Drawer)
|
||||
Vue.use(Tabs)
|
||||
Vue.use(TabPane)
|
||||
Vue.use(Button)
|
||||
Vue.use(Select)
|
||||
Vue.use(Option)
|
||||
Vue.use(Pagination)
|
||||
Vue.use(Table)
|
||||
Vue.use(TableColumn)
|
||||
Vue.use(Input)
|
||||
Vue.use(Card)
|
||||
Vue.use(Link)
|
||||
Vue.use(Loading)
|
||||
|
||||
Vue.prototype.$notify = Notification
|
||||
Vue.prototype.$message = Message
|
||||
13
src/shims-tsx.d.ts
vendored
@@ -1,13 +0,0 @@
|
||||
import Vue, { VNode } from 'vue'
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
// tslint:disable no-empty-interface
|
||||
interface Element extends VNode {}
|
||||
// tslint:disable no-empty-interface
|
||||
interface ElementClass extends Vue {}
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any
|
||||
}
|
||||
}
|
||||
}
|
||||
4
src/shims-vue.d.ts
vendored
@@ -1,4 +0,0 @@
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
@@ -5,50 +5,64 @@ Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
Main: 'Search',
|
||||
site: 0,
|
||||
view: 'Film',
|
||||
theme: 'light',
|
||||
site: 'zuidazy',
|
||||
language: 'zhCn',
|
||||
detail: {
|
||||
show: false,
|
||||
video: ''
|
||||
v: {}
|
||||
},
|
||||
share: {
|
||||
show: false,
|
||||
v: {}
|
||||
},
|
||||
dUrl: '',
|
||||
video: {}
|
||||
},
|
||||
getters: {
|
||||
getMain: state => {
|
||||
return state.Main
|
||||
getView: state => {
|
||||
return state.view
|
||||
},
|
||||
getTheme: state => {
|
||||
return state.theme
|
||||
},
|
||||
getSite: state => {
|
||||
return state.site
|
||||
},
|
||||
getTheme: state => {
|
||||
return state.theme
|
||||
getLanguage: state => {
|
||||
return state.language
|
||||
},
|
||||
getDetail: state => {
|
||||
return state.detail
|
||||
},
|
||||
getVideo: state => {
|
||||
return state.video
|
||||
},
|
||||
getShare: state => {
|
||||
return state.share
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
SET_MAIN: (state, payload) => {
|
||||
state.Main = payload
|
||||
SET_VIEW: (state, payload) => {
|
||||
state.view = payload
|
||||
},
|
||||
SET_THEME: (state, payload) => {
|
||||
state.theme = payload
|
||||
},
|
||||
SET_SITE: (state, payload) => {
|
||||
state.site = payload
|
||||
},
|
||||
SET_THEME: (state, payload) => {
|
||||
state.theme = payload
|
||||
SET_LANGUAGE: (state, payload) => {
|
||||
state.language = payload
|
||||
},
|
||||
SET_DETAIL: (state, payload) => {
|
||||
state.detail = payload
|
||||
},
|
||||
SET_VIDEO: (state, payload) => {
|
||||
state.video = payload
|
||||
},
|
||||
SET_SHARE: (state, payload) => {
|
||||
state.share = payload
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
modules: {}
|
||||
}
|
||||
})
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -1,16 +1,43 @@
|
||||
module.exports = {
|
||||
pages: {
|
||||
index: 'src/main.js',
|
||||
mini: 'src/mini/main.js'
|
||||
},
|
||||
pluginOptions: {
|
||||
electronBuilder: {
|
||||
nodeIntegration: true,
|
||||
builderOptions: {
|
||||
win: {
|
||||
icon: './build/icons/icon.ico'
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
allowToChangeInstallationDirectory: true
|
||||
},
|
||||
productName: 'ZY Player',
|
||||
publish: ['github']
|
||||
},
|
||||
chainWebpackRendererProcess: config => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
config.plugins.delete('prefetch')
|
||||
appId: 'com.hunlongyu.zy',
|
||||
copyright: 'Copyright @ 2020 Hunlongyu',
|
||||
productName: 'ZY Player 内测版',
|
||||
publish: [
|
||||
{
|
||||
provider: 'github',
|
||||
owner: 'Hunlongyu',
|
||||
repo: 'ZY-Player'
|
||||
}
|
||||
],
|
||||
mac: {
|
||||
icon: 'build/icon/icon.icns',
|
||||
category: 'public.app-category.developer-tools',
|
||||
target: 'default',
|
||||
extendInfo: {
|
||||
LSUIElement: 1
|
||||
}
|
||||
},
|
||||
win: {
|
||||
icon: 'build/icons/icon.ico',
|
||||
target: 'nsis'
|
||||
},
|
||||
linux: {
|
||||
icon: 'build/icons/'
|
||||
},
|
||||
snap: {
|
||||
publish: ['github']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||