Compare commits
No commits in common. "master" and "v0.3.3" have entirely different histories.
|
|
@ -1,16 +0,0 @@
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
Dockerfile*
|
|
||||||
docker-compose*
|
|
||||||
.dockerignore
|
|
||||||
.git
|
|
||||||
.github
|
|
||||||
.gitignore
|
|
||||||
README.md
|
|
||||||
LICENSE
|
|
||||||
.vscode
|
|
||||||
dist
|
|
||||||
dist_electron
|
|
||||||
build
|
|
||||||
images
|
|
||||||
script
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
VUE_APP_NETEASE_API_URL=/api
|
VUE_APP_NETEASE_API_URL=http://127.0.0.1:3000
|
||||||
VUE_APP_ELECTRON_API_URL=/api
|
VUE_APP_ELECTRON_API_URL=/api
|
||||||
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:10754
|
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:3000
|
||||||
VUE_APP_LASTFM_API_KEY=09c55292403d961aa517ff7f5e8a3d9c
|
VUE_APP_ENABLE_SENTRY=false
|
||||||
VUE_APP_LASTFM_API_SHARED_SECRET=307c9fda32b3904e53654baff215cb67
|
|
||||||
DEV_SERVER_PORT=20201
|
DEV_SERVER_PORT=20201
|
||||||
|
|
||||||
|
|
|
||||||
4
.envrc
|
|
@ -1,4 +0,0 @@
|
||||||
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
|
|
||||||
|
|
||||||
export NIXPKGS_ALLOW_INSECURE=1
|
|
||||||
use devenv
|
|
||||||
7
.gitattributes
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
* text eol=lf
|
|
||||||
# Denote all files that are truly binary and should not be modified.
|
|
||||||
*.png binary
|
|
||||||
*.jpg binary
|
|
||||||
*.mp3 binary
|
|
||||||
*.icns binary
|
|
||||||
*.gif binary
|
|
||||||
93
.github/workflows/build.yaml
vendored
|
|
@ -1,15 +1,6 @@
|
||||||
name: Release
|
name: Build/release
|
||||||
|
|
||||||
env:
|
on: [push, pull_request]
|
||||||
YARN_INSTALL_NOPT: yarn add --ignore-platform --ignore-optional
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
tags:
|
|
||||||
- v*
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
|
@ -17,75 +8,19 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, windows-latest, ubuntu-22.04]
|
os: [macos-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
submodules: "recursive"
|
|
||||||
|
|
||||||
- name: Install Node.js, NPM and Yarn
|
- name: Install Node.js, NPM and Yarn
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 12.16.3
|
||||||
cache: 'yarn'
|
|
||||||
|
|
||||||
- name: Install RPM & Pacman (on Ubuntu)
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update &&
|
|
||||||
sudo apt-get install --no-install-recommends -y rpm &&
|
|
||||||
sudo apt-get install --no-install-recommends -y libarchive-tools &&
|
|
||||||
sudo apt-get install --no-install-recommends -y libopenjp2-tools
|
|
||||||
|
|
||||||
- name: Install Snapcraft (on Ubuntu)
|
|
||||||
uses: samuelmeuli/action-snapcraft@v1
|
|
||||||
if: startsWith(matrix.os, 'ubuntu')
|
|
||||||
with:
|
|
||||||
snapcraft_token: ${{ secrets.snapcraft_token }}
|
|
||||||
|
|
||||||
- id: get_unm_version
|
|
||||||
name: Get the installed UNM version
|
|
||||||
run: |
|
|
||||||
yarn --ignore-optional
|
|
||||||
unm_version=$(node -e "console.log(require('./node_modules/@unblockneteasemusic/rust-napi/package.json').version)")
|
|
||||||
echo "::set-output name=unmver::${unm_version}"
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install UNM dependencies for Windows
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
run: |
|
|
||||||
${{ env.YARN_INSTALL_NOPT }} \
|
|
||||||
@unblockneteasemusic/rust-napi-win32-x64-msvc@${{steps.get_unm_version.outputs.unmver}}
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install UNM dependencies for macOS
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
${{ env.YARN_INSTALL_NOPT }} \
|
|
||||||
@unblockneteasemusic/rust-napi-darwin-x64@${{steps.get_unm_version.outputs.unmver}} \
|
|
||||||
@unblockneteasemusic/rust-napi-darwin-arm64@${{steps.get_unm_version.outputs.unmver}} \
|
|
||||||
dmg-license
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install UNM dependencies for Linux
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
${{ env.YARN_INSTALL_NOPT }} \
|
|
||||||
@unblockneteasemusic/rust-napi-linux-x64-gnu@${{steps.get_unm_version.outputs.unmver}} \
|
|
||||||
@unblockneteasemusic/rust-napi-linux-arm64-gnu@${{steps.get_unm_version.outputs.unmver}} \
|
|
||||||
@unblockneteasemusic/rust-napi-linux-arm-gnueabihf@${{steps.get_unm_version.outputs.unmver}}
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Build/release Electron app
|
- name: Build/release Electron app
|
||||||
uses: samuelmeuli/action-electron-builder@v1.6.0
|
uses: samuelmeuli/action-electron-builder@v1
|
||||||
env:
|
|
||||||
VUE_APP_NETEASE_API_URL: /api
|
|
||||||
VUE_APP_ELECTRON_API_URL: /api
|
|
||||||
VUE_APP_ELECTRON_API_URL_DEV: http://127.0.0.1:10754
|
|
||||||
VUE_APP_LASTFM_API_KEY: 09c55292403d961aa517ff7f5e8a3d9c
|
|
||||||
VUE_APP_LASTFM_API_SHARED_SECRET: 307c9fda32b3904e53654baff215cb67
|
|
||||||
with:
|
with:
|
||||||
# GitHub token, automatically provided to the action
|
# GitHub token, automatically provided to the action
|
||||||
# (No need to define this secret in the repo settings)
|
# (No need to define this secret in the repo settings)
|
||||||
|
|
@ -97,20 +32,14 @@ jobs:
|
||||||
|
|
||||||
use_vue_cli: true
|
use_vue_cli: true
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: YesPlayMusic-mac
|
name: YesPlayMusic-mac
|
||||||
path: dist_electron/*-universal.dmg
|
path: dist_electron/*.dmg
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: YesPlayMusic-win
|
name: YesPlayMusic-win
|
||||||
path: dist_electron/*Setup*.exe
|
path: dist_electron/*.exe
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: YesPlayMusic-linux
|
|
||||||
path: dist_electron/*.AppImage
|
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
|
||||||
48
.github/workflows/sync.yml
vendored
|
|
@ -1,48 +0,0 @@
|
||||||
name: Upstream Sync
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
issues: write
|
|
||||||
actions: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 * * * *' # every hour
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync_latest_from_upstream:
|
|
||||||
name: Sync latest commits from upstream repo
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.event.repository.fork }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Clean issue notice
|
|
||||||
uses: actions-cool/issues-helper@v3
|
|
||||||
with:
|
|
||||||
actions: 'close-issues'
|
|
||||||
labels: '🚨 Sync Fail'
|
|
||||||
|
|
||||||
- name: Sync upstream changes
|
|
||||||
id: sync
|
|
||||||
uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
|
|
||||||
with:
|
|
||||||
upstream_sync_repo: qier222/YesPlayMusic
|
|
||||||
upstream_sync_branch: master
|
|
||||||
target_sync_branch: master
|
|
||||||
target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set
|
|
||||||
test_mode: false
|
|
||||||
|
|
||||||
- name: Sync check
|
|
||||||
if: failure()
|
|
||||||
uses: actions-cool/issues-helper@v3
|
|
||||||
with:
|
|
||||||
actions: 'create-issue'
|
|
||||||
title: '🚨 同步失败 | Sync Fail'
|
|
||||||
labels: '🚨 Sync Fail'
|
|
||||||
body: |
|
|
||||||
Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork.
|
|
||||||
|
|
||||||
由于上游仓库的 workflow 文件变更,导致 GitHub 自动暂停了本次自动更新,你需要手动 Sync Fork 一次。
|
|
||||||
16
.gitignore
vendored
|
|
@ -1,6 +1,8 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
/dist
|
/dist
|
||||||
|
dist_electron
|
||||||
|
Icon?
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env
|
.env
|
||||||
|
|
@ -23,21 +25,9 @@ pnpm-debug.log*
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
.vercel
|
.vercel
|
||||||
|
/netease_api
|
||||||
|
|
||||||
#Electron-builder output
|
#Electron-builder output
|
||||||
/dist_electron
|
/dist_electron
|
||||||
NeteaseCloudMusicApi-master
|
NeteaseCloudMusicApi-master
|
||||||
NeteaseCloudMusicApi-master.zip
|
NeteaseCloudMusicApi-master.zip
|
||||||
|
|
||||||
# Local Netlify folder
|
|
||||||
.netlify
|
|
||||||
vercel.json
|
|
||||||
# Devenv
|
|
||||||
.devenv*
|
|
||||||
devenv.local.nix
|
|
||||||
|
|
||||||
# direnv
|
|
||||||
.direnv
|
|
||||||
|
|
||||||
# pre-commit
|
|
||||||
.pre-commit-config.yaml
|
|
||||||
|
|
|
||||||
4
.npmrc
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# 如果发现 npm / yarn 安装太慢,可以解除注释
|
||||||
|
# registry=https://registry.npm.taobao.org/
|
||||||
|
# ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron
|
||||||
|
# phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs
|
||||||
1
.nvmrc
|
|
@ -1 +0,0 @@
|
||||||
14
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
build
|
build
|
||||||
coverage
|
coverage
|
||||||
dist
|
dist
|
||||||
|
netease_api
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"singleQuote": true,
|
"singleQuote": false,
|
||||||
"jsxSingleQuote": true,
|
"jsxSingleQuote": true,
|
||||||
"arrowParens": "avoid",
|
"jsxBracketSameLine": false,
|
||||||
|
"arrowParens": "always",
|
||||||
"endOfLine": "lf",
|
"endOfLine": "lf",
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"htmlWhitespaceSensitivity": "strict"
|
"htmlWhitespaceSensitivity": "strict"
|
||||||
|
|
|
||||||
25
Dockerfile
|
|
@ -1,25 +0,0 @@
|
||||||
FROM node:16.13.1-alpine as build
|
|
||||||
ENV VUE_APP_NETEASE_API_URL=/api
|
|
||||||
WORKDIR /app
|
|
||||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
|
|
||||||
apk add --no-cache python3 make g++ git
|
|
||||||
COPY package.json yarn.lock ./
|
|
||||||
RUN yarn install
|
|
||||||
COPY . .
|
|
||||||
RUN yarn config set electron_mirror https://npmmirror.com/mirrors/electron/ && \
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
FROM nginx:1.20.2-alpine as app
|
|
||||||
|
|
||||||
COPY --from=build /app/package.json /usr/local/lib/
|
|
||||||
|
|
||||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
|
|
||||||
apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main libuv \
|
|
||||||
&& apk add --no-cache --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main nodejs npm \
|
|
||||||
&& npm i -g $(awk -F \" '{if($2=="NeteaseCloudMusicApi") print $2"@"$4}' /usr/local/lib/package.json) \
|
|
||||||
&& rm -f /usr/local/lib/package.json
|
|
||||||
|
|
||||||
COPY --from=build /app/docker/nginx.conf.example /etc/nginx/conf.d/default.conf
|
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
CMD nginx ; exec npx NeteaseCloudMusicApi
|
|
||||||
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020-2023 qier222
|
Copyright (c) 2020 qier222
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
204
README.md
|
|
@ -8,221 +8,69 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
高颜值的第三方网易云播放器
|
高颜值的第三方网易云播放器
|
||||||
<br />
|
<br />
|
||||||
<a href="https://music.ineko.cc" target="blank"><strong>🌎 访问DEMO</strong></a> |
|
<a href="https://music.qier222.com" target="blank"><strong>🌎 访问DEMO</strong></a> |
|
||||||
<a href="#%EF%B8%8F-安装" target="blank"><strong>📦️ 下载安装包</strong></a> |
|
<a href="#%EF%B8%8F-安装" target="blank"><strong>📦️ 下载安装包</strong></a>
|
||||||
<a href="https://t.me/yesplaymusic" target="blank"><strong>💬 加入交流群</strong></a>
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[![Library][library-screenshot]](https://music.ineko.cc)
|
[![Library][library-screenshot]](https://music.qier222.com)
|
||||||
|
|
||||||
|
|
||||||
## 全新版本
|
|
||||||
全新2.0 Alpha测试版已发布,欢迎前往 [Releases](https://github.com/qier222/YesPlayMusic/releases) 页面下载。
|
|
||||||
当前版本将会进入维护模式,除重大bug修复外,不会再更新新功能。
|
|
||||||
|
|
||||||
## ✨ 特性
|
## ✨ 特性
|
||||||
|
|
||||||
- ✅ 使用 Vue.js 全家桶开发
|
- ✅ 使用 Vue.js 全家桶开发
|
||||||
- 🔴 网易云账号登录(扫码/手机/邮箱登录)
|
- 🔴 网易云账号登录
|
||||||
- 📺 支持 MV 播放
|
- 📺 MV 播放
|
||||||
- 📃 支持歌词显示
|
- 📃 支持歌词显示
|
||||||
- 📻 支持私人 FM / 每日推荐歌曲
|
|
||||||
- 🚫🤝 无任何社交功能
|
- 🚫🤝 无任何社交功能
|
||||||
- 🌎️ 海外用户可直接播放(需要登录网易云账号)
|
- 🌎️ 海外用户可直接播放(需要登录网易云账号)
|
||||||
- 🔐 支持 [UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server#音源清单),自动使用[各类音源](https://github.com/UnblockNeteaseMusic/server#音源清单)替换变灰歌曲链接 (网页版不支持)
|
- 🔐 支持 [UnblockNeteaseMusic](https://github.com/nondanee/UnblockNeteaseMusic),自动使用 QQ/酷狗/酷我音源替换变灰歌曲链接 (网页版不支持)
|
||||||
- 「各类音源」指默认启用的音源。
|
- ⏭️ 支持 MediaSession API,可以使用系统快捷键操作上一首下一首
|
||||||
- YouTube 音源需自行安装 `yt-dlp`。
|
|
||||||
- ✔️ 每日自动签到(手机端和电脑端同时签到)
|
- ✔️ 每日自动签到(手机端和电脑端同时签到)
|
||||||
- 🌚 Light/Dark Mode 自动切换
|
- 🌚 Light/Dark Mode 自动切换
|
||||||
- 👆 支持 Touch Bar
|
- 👆 支持 Touch Bar
|
||||||
- 🖥️ 支持 PWA,可在 Chrome/Edge 里点击地址栏右边的 ➕ 安装到电脑
|
- 🖥️ 支持 PWA,可在 Chrome/Edge 里点击地址栏右边的 ➕ 安装到电脑
|
||||||
- 🟥 支持 Last.fm Scrobble
|
- 🙉 支持显示歌曲和专辑的 Explicit 标志
|
||||||
- ☁️ 支持音乐云盘
|
|
||||||
- ⌨️ 自定义快捷键和全局快捷键
|
|
||||||
- 🎧 支持 Mpris
|
|
||||||
- 🛠 更多特性开发中
|
- 🛠 更多特性开发中
|
||||||
|
|
||||||
## 📦️ 安装
|
## 📦️ 安装
|
||||||
|
|
||||||
Electron 版本由 [@hawtim](https://github.com/hawtim) 和 [@qier222](https://github.com/qier222) 适配并维护,支持 macOS、Windows、Linux。
|
Electron 版本由 [@hawtim](https://github.com/hawtim) 和 [@qier222](https://github.com/qier222) 适配并维护,支持 macOS、Windows、Linux。
|
||||||
|
|
||||||
访问本项目的 [Releases](https://github.com/qier222/YesPlayMusic/releases)
|
访问本项目的 [Releases](https://github.com/qier222/YesPlayMusic/releases) 页面下载安装包,或者访问 [镜像下载站 (大陆访问更快)](https://dl.qier222.com/YesPlayMusic/) 下载。
|
||||||
页面下载安装包。
|
|
||||||
|
|
||||||
- macOS 用户可以通过 Homebrew 来安装:`brew install --cask yesplaymusic`
|
## ⚙️ 部署至服务器
|
||||||
|
|
||||||
- Windows 用户可以通过 Scoop 来安装:`scoop install extras/yesplaymusic`
|
除了下载安装包使用,你还可以将本项目部署到你的服务器上。
|
||||||
|
|
||||||
## ⚙️ 部署至 Vercel
|
|
||||||
|
|
||||||
除了下载安装包使用,你还可以将本项目部署到 Vercel 或你的服务器上。下面是部署到 Vercel 的方法。
|
|
||||||
|
|
||||||
本项目的 Demo (https://music.qier222.com) 就是部署在 Vercel 上的网站。
|
|
||||||
|
|
||||||
[](https://vercel.com/?utm_source=ohmusic&utm_campaign=oss)
|
|
||||||
|
|
||||||
1. 部署网易云 API,详情参见 [Binaryify/NeteaseCloudMusicApi](https://neteasecloudmusicapi.vercel.app/#/?id=%e5%ae%89%e8%a3%85)
|
|
||||||
。你也可以将 API 部署到 Vercel。
|
|
||||||
|
|
||||||
2. 点击本仓库右上角的 Fork,复制本仓库到你的 GitHub 账号。
|
|
||||||
|
|
||||||
3. 点击仓库的 Add File,选择 Create new file,输入 `vercel.json`,将下面的内容复制粘贴到文件中,并将 `https://your-netease-api.example.com` 替换为你刚刚部署的网易云 API 地址:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"rewrites": [
|
|
||||||
{
|
|
||||||
"source": "/api/:match*",
|
|
||||||
"destination": "https://your-netease-api.example.com/:match*"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. 打开 [Vercel.com](https://vercel.com),使用 GitHub 登录。
|
|
||||||
|
|
||||||
5. 点击 Import Git Repository 并选择你刚刚复制的仓库并点击 Import。
|
|
||||||
|
|
||||||
6. 点击 PERSONAL ACCOUNT 旁边的 Select。
|
|
||||||
|
|
||||||
7. 点击 Environment Variables,填写 Name 为 `VUE_APP_NETEASE_API_URL`,Value 为 `/api`,点击 Add。最后点击底部的 Deploy 就可以部署到
|
|
||||||
Vercel 了。
|
|
||||||
|
|
||||||
## ⚙️ 部署到自己的服务器
|
|
||||||
|
|
||||||
除了部署到 Vercel,你还可以部署到自己的服务器上
|
|
||||||
|
|
||||||
1. 部署网易云 API,详情参见 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
|
1. 部署网易云 API,详情参见 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
|
||||||
|
|
||||||
2. 克隆本仓库
|
2. 克隆本仓库
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone --recursive https://github.com/qier222/YesPlayMusic.git
|
git clone https://github.com/qier222/YesPlayMusic.git
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 安装依赖
|
3. 安装依赖
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4. (可选)使用 Nginx 反向代理 API,将 API 路径映射为 `/api`,如果 API 和网页不在同一个域名下的话(跨域),会有一些 bug。
|
4. 复制 `/.env.example` 文件为 `/.env`,修改里面 `VUE_APP_NETEASE_API_URL` 的值为网易云 API 地址。本地开发的话可以填写 API 地址为 `http://localhost:3000`,YesPlayMusic 地址为 `http://localhost:8080`
|
||||||
|
|
||||||
5. 复制 `/.env.example` 文件为 `/.env`,修改里面 `VUE_APP_NETEASE_API_URL` 的值为网易云 API 地址。本地开发的话可以填写 API 地址为 `http://localhost:3000`,YesPlayMusic 地址为 `http://localhost:8080`。如果你使用了反向代理 API,可以填写 API 地址为 `/api`。
|
|
||||||
|
|
||||||
```
|
```
|
||||||
VUE_APP_NETEASE_API_URL=http://localhost:3000
|
VUE_APP_NETEASE_API_URL=http://localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
6. 编译打包
|
5. 编译打包
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn run build
|
yarn run build
|
||||||
```
|
```
|
||||||
|
|
||||||
7. 将 `/dist` 目录下的文件上传到你的 Web 服务器
|
6. 将 `/dist` 目录下的文件上传到你的 Web 服务器
|
||||||
|
|
||||||
## ⚙️ 宝塔面板 docker应用商店 部署
|
|
||||||
|
|
||||||
1. 安装宝塔面板,前往[宝塔面板官网](https://www.bt.cn/new/download.html) ,选择正式版的脚本下载安装。
|
|
||||||
|
|
||||||
2. 安装后登录宝塔面板,在左侧导航栏中点击 Docker,首次进入会提示安装Docker服务,点击立即安装,按提示完成安装
|
|
||||||
|
|
||||||
3. 安装完成后在应用商店中找到YesPlayMusic,点击安装,配置域名、端口等基本信息即可完成安装。
|
|
||||||
|
|
||||||
4. 安装后在浏览器输入上一步骤设置的域名即可访问。
|
|
||||||
|
|
||||||
## ⚙️ Docker 部署
|
|
||||||
|
|
||||||
1. 构建 Docker Image
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker build -t yesplaymusic .
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 启动 Docker Container
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -d --name YesPlayMusic -p 80:80 yesplaymusic
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Docker Compose 启动
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
YesPlayMusic 地址为 `http://localhost`
|
|
||||||
|
|
||||||
## ⚙️ 部署至 Replit
|
|
||||||
|
|
||||||
1. 新建 Repl,选择 Bash 模板
|
|
||||||
|
|
||||||
2. 在 Replit shell 中运行以下命令
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -s -L https://raw.githubusercontent.com/qier222/YesPlayMusic/main/install-replit.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 首次运行成功后,只需点击绿色按钮 `Run` 即可再次运行
|
|
||||||
|
|
||||||
4. 由于 replit 个人版限制内存为 1G(教育版为 3G),构建过程中可能会失败,请再次运行上述命令或运行以下命令:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 👷♂️ 打包客户端
|
|
||||||
|
|
||||||
如果在 Release 页面没有找到适合你的设备的安装包的话,你可以根据下面的步骤来打包自己的客户端。
|
|
||||||
|
|
||||||
1. 打包 Electron 需要用到 Node.js 和 Yarn。可前往 [Node.js 官网](https://nodejs.org/zh-cn/) 下载安装包。安装 Node.js
|
|
||||||
后可在终端里执行 `npm install -g yarn` 来安装 Yarn。
|
|
||||||
|
|
||||||
2. 使用 `git clone --recursive https://github.com/qier222/YesPlayMusic.git` 克隆本仓库到本地。
|
|
||||||
|
|
||||||
3. 使用 `yarn install` 安装项目依赖。
|
|
||||||
|
|
||||||
4. 复制 `/.env.example` 文件为 `/.env` 。
|
|
||||||
|
|
||||||
5. 选择下列表格的命令来打包适合的你的安装包,打包出来的文件在 `/dist_electron` 目录下。了解更多信息可访问 [electron-builder 文档](https://www.electron.build/cli)
|
|
||||||
|
|
||||||
| 命令 | 说明 |
|
|
||||||
| ------------------------------------------ | ------------------------- |
|
|
||||||
| `yarn electron:build --windows nsis:ia32` | Windows 32 位 |
|
|
||||||
| `yarn electron:build --windows nsis:arm64` | Windows ARM |
|
|
||||||
| `yarn electron:build --linux deb:armv7l` | Debian armv7l(树莓派等) |
|
|
||||||
| `yarn electron:build --macos dir:arm64` | macOS ARM |
|
|
||||||
|
|
||||||
## :computer: 配置开发环境
|
|
||||||
|
|
||||||
本项目由 [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 提供 API。
|
|
||||||
|
|
||||||
运行本项目
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 安装依赖
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
# 创建本地环境变量
|
|
||||||
cp .env.example .env
|
|
||||||
|
|
||||||
# 运行(网页端)
|
|
||||||
yarn serve
|
|
||||||
|
|
||||||
# 运行(electron)
|
|
||||||
yarn electron:serve
|
|
||||||
```
|
|
||||||
|
|
||||||
本地运行 NeteaseCloudMusicApi,或者将 API [部署至 Vercel](#%EF%B8%8F-部署至-vercel)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 运行 API (默认 3000 端口)
|
|
||||||
yarn netease_api:run
|
|
||||||
```
|
|
||||||
|
|
||||||
## ☑️ Todo
|
## ☑️ Todo
|
||||||
|
|
||||||
|
|
@ -238,8 +86,6 @@ yarn netease_api:run
|
||||||
|
|
||||||
## 灵感来源
|
## 灵感来源
|
||||||
|
|
||||||
API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
|
|
||||||
|
|
||||||
- [Apple Music](https://music.apple.com)
|
- [Apple Music](https://music.apple.com)
|
||||||
- [YouTube Music](https://music.youtube.com)
|
- [YouTube Music](https://music.youtube.com)
|
||||||
- [Spotify](https://www.spotify.com)
|
- [Spotify](https://www.spotify.com)
|
||||||
|
|
@ -247,14 +93,12 @@ API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryif
|
||||||
|
|
||||||
## 🖼️ 截图
|
## 🖼️ 截图
|
||||||
|
|
||||||
![lyrics][lyrics-screenshot]
|
[![artist][artist-screenshot]](https://music.qier222.com)
|
||||||
![library-dark][library-dark-screenshot]
|
[![album][album-screenshot]](https://music.qier222.com)
|
||||||
![album][album-screenshot]
|
[![playlist][playlist-screenshot]](https://music.qier222.com)
|
||||||
![home-2][home-2-screenshot]
|
[![explore][explore-screenshot]](https://music.qier222.com)
|
||||||
![artist][artist-screenshot]
|
[![search][search-screenshot]](https://music.qier222.com)
|
||||||
![search][search-screenshot]
|
[![home][home-screenshot]](https://music.qier222.com)
|
||||||
![home][home-screenshot]
|
|
||||||
![explore][explore-screenshot]
|
|
||||||
|
|
||||||
<!-- MARKDOWN LINKS & IMAGES -->
|
<!-- MARKDOWN LINKS & IMAGES -->
|
||||||
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
||||||
|
|
@ -263,8 +107,6 @@ API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryif
|
||||||
[artist-screenshot]: images/artist.png
|
[artist-screenshot]: images/artist.png
|
||||||
[explore-screenshot]: images/explore.png
|
[explore-screenshot]: images/explore.png
|
||||||
[home-screenshot]: images/home.png
|
[home-screenshot]: images/home.png
|
||||||
[home-2-screenshot]: images/home-2.png
|
|
||||||
[lyrics-screenshot]: images/lyrics.png
|
|
||||||
[library-screenshot]: images/library.png
|
[library-screenshot]: images/library.png
|
||||||
[library-dark-screenshot]: images/library-dark.png
|
[playlist-screenshot]: images/playlist.png
|
||||||
[search-screenshot]: images/search.png
|
[search-screenshot]: images/search.png
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: ["@vue/cli-plugin-babel/preset"],
|
||||||
[
|
plugins: [
|
||||||
'@vue/cli-plugin-babel/preset',
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
{
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
useBuiltIns: 'usage',
|
|
||||||
shippedProposals: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
132
devenv.lock
|
|
@ -1,132 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"devenv": {
|
|
||||||
"locked": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"lastModified": 1730412360,
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"rev": "45847cb1f14a6d8cfa86ea943703c54a8798ae7e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"dir": "src/modules",
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "devenv",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"gitignore": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"pre-commit-hooks",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1709087332,
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "gitignore.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1730272153,
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1730327045,
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "080166c15633801df010977d9d7474b4a6c549d7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-24.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nodejs16": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1700230496,
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "a71323f68d4377d12c04a5410e214495ec598d4c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "a71323f68d4377d12c04a5410e214495ec598d4c",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pre-commit-hooks": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"gitignore": "gitignore",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1730302582,
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "cachix",
|
|
||||||
"repo": "pre-commit-hooks.nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"devenv": "devenv",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nodejs16": "nodejs16",
|
|
||||||
"pre-commit-hooks": "pre-commit-hooks"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
53
devenv.nix
|
|
@ -1,53 +0,0 @@
|
||||||
{ pkgs, lib, config, inputs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
nodejs16 = import inputs.nodejs16 { system = pkgs.stdenv.system; };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# https://devenv.sh/basics/
|
|
||||||
env.GREET = "devenv";
|
|
||||||
|
|
||||||
# https://devenv.sh/packages/
|
|
||||||
packages = [ pkgs.git ] ++ lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk; [
|
|
||||||
frameworks.AppKit
|
|
||||||
]);
|
|
||||||
|
|
||||||
# https://devenv.sh/languages/
|
|
||||||
languages.javascript.enable = true;
|
|
||||||
languages.javascript.package = nodejs16.pkgs.nodejs_16;
|
|
||||||
languages.javascript.corepack.enable = true;
|
|
||||||
# languages.rust.enable = true;
|
|
||||||
|
|
||||||
# https://devenv.sh/processes/
|
|
||||||
# processes.cargo-watch.exec = "cargo-watch";
|
|
||||||
|
|
||||||
# https://devenv.sh/services/
|
|
||||||
# services.postgres.enable = true;
|
|
||||||
|
|
||||||
# https://devenv.sh/scripts/
|
|
||||||
scripts.hello.exec = ''
|
|
||||||
echo hello from $GREET
|
|
||||||
'';
|
|
||||||
|
|
||||||
enterShell = ''
|
|
||||||
hello
|
|
||||||
git --version
|
|
||||||
'';
|
|
||||||
|
|
||||||
# https://devenv.sh/tasks/
|
|
||||||
# tasks = {
|
|
||||||
# "myproj:setup".exec = "mytool build";
|
|
||||||
# "devenv:enterShell".after = [ "myproj:setup" ];
|
|
||||||
# };
|
|
||||||
|
|
||||||
# https://devenv.sh/tests/
|
|
||||||
enterTest = ''
|
|
||||||
echo "Running tests"
|
|
||||||
git --version | grep --color=auto "${pkgs.git.version}"
|
|
||||||
'';
|
|
||||||
|
|
||||||
# https://devenv.sh/pre-commit-hooks/
|
|
||||||
# pre-commit.hooks.shellcheck.enable = true;
|
|
||||||
|
|
||||||
# See full reference at https://devenv.sh/reference/options/
|
|
||||||
}
|
|
||||||
19
devenv.yaml
|
|
@ -1,19 +0,0 @@
|
||||||
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
|
||||||
inputs:
|
|
||||||
nixpkgs:
|
|
||||||
url: github:nixos/nixpkgs/nixpkgs-unstable
|
|
||||||
nodejs16:
|
|
||||||
url: github:nixos/nixpkgs/a71323f68d4377d12c04a5410e214495ec598d4c
|
|
||||||
|
|
||||||
# https://github.com/cachix/devenv/issues/792#issuecomment-2043166453
|
|
||||||
impure: true
|
|
||||||
# If you're using non-OSS software, you can set allowUnfree to true.
|
|
||||||
# allowUnfree: true
|
|
||||||
|
|
||||||
# If you're willing to use a package that's vulnerable
|
|
||||||
# permittedInsecurePackages:
|
|
||||||
# - "openssl-1.1.1w"
|
|
||||||
|
|
||||||
# If you have more than one devenv you can merge them
|
|
||||||
#imports:
|
|
||||||
# - ./backend
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
services:
|
|
||||||
YesPlayMusic:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
image: yesplaymusic
|
|
||||||
container_name: YesPlayMusic
|
|
||||||
volumes:
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
- /etc/timezone:/etc/timezone:ro
|
|
||||||
- ./docker/nginx.conf.example:/etc/nginx/conf.d/default.conf:ro
|
|
||||||
ports:
|
|
||||||
- 80:80
|
|
||||||
restart: always
|
|
||||||
depends_on:
|
|
||||||
- UnblockNeteaseMusic
|
|
||||||
environment:
|
|
||||||
- NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
||||||
networks:
|
|
||||||
my_network:
|
|
||||||
|
|
||||||
UnblockNeteaseMusic:
|
|
||||||
image: pan93412/unblock-netease-music-enhanced
|
|
||||||
command: -o kugou kuwo migu bilibili pyncmd -p 80:443 -f 45.127.129.53 -e -
|
|
||||||
# environment:
|
|
||||||
# JSON_LOG: true
|
|
||||||
# LOG_LEVEL: debug
|
|
||||||
networks:
|
|
||||||
my_network:
|
|
||||||
aliases:
|
|
||||||
- music.163.com
|
|
||||||
- interface.music.163.com
|
|
||||||
- interface3.music.163.com
|
|
||||||
- interface.music.163.com.163jiasu.com
|
|
||||||
- interface3.music.163.com.163jiasu.com
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
networks:
|
|
||||||
my_network:
|
|
||||||
driver: bridge
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
server {
|
|
||||||
gzip on;
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location @rewrites {
|
|
||||||
rewrite ^(.*)$ /index.html last;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
proxy_buffers 16 32k;
|
|
||||||
proxy_buffer_size 128k;
|
|
||||||
proxy_busy_buffers_size 128k;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-Host $remote_addr;
|
|
||||||
proxy_set_header X-NginX-Proxy true;
|
|
||||||
proxy_pass http://localhost:3000/;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
images/album.png
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 804 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 730 KiB |
|
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 312 KiB |
BIN
images/home.png
|
Before Width: | Height: | Size: 389 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 335 KiB |
|
Before Width: | Height: | Size: 324 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 339 KiB |
BIN
images/playlist.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 1 MiB |
|
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/bash
|
|
||||||
|
|
||||||
# 初始化 .replit 和 replit.nix
|
|
||||||
if [[ $1 == i ]];then
|
|
||||||
echo -e 'run = ["bash", "main.sh"]\n\nentrypoint = "main.sh"' >.replit
|
|
||||||
echo -e "{ pkgs }: {\n\t\tdeps = [\n\t\t\tpkgs.nodejs-16_x\n\t\t\tpkgs.yarn\n\t\t\tpkgs.bashInteractive\n\t\t];\n}" > replit.nix
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 安装
|
|
||||||
if [[ ! -d api ]];then
|
|
||||||
mkdir api
|
|
||||||
git clone https://github.com/Binaryify/NeteaseCloudMusicApi ./api && \
|
|
||||||
cd api && npm install && cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d music ]];then
|
|
||||||
mkdir music
|
|
||||||
git clone https://github.com/qier222/YesPlayMusic ./music && \
|
|
||||||
cd music && cp .env.example .env && npm install --force && npm run build && cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
PID=`ps -ef | grep npm | awk '{print $2}' | sed '$d'`
|
|
||||||
|
|
||||||
if [[ ! -z ${PID} ]];then echo $PID | xargs kill;fi
|
|
||||||
nohup bash -c 'cd api && PORT=35216 node app.js' > api.log 2>&1
|
|
||||||
nohup bash -c 'npx serve music/dist/' > music.log 2>&1
|
|
||||||
|
|
@ -7,8 +7,7 @@
|
||||||
},
|
},
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true
|
||||||
"jsx": "preserve"
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
|
|
||||||
83
package.json
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "yesplaymusic",
|
"name": "YesPlayMusic",
|
||||||
"version": "0.4.9",
|
"version": "0.3.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A third party music player for Netease Music",
|
"description": "A third party music application for Netease Music",
|
||||||
"author": "qier222<qier222@outlook.com>",
|
"author": "hawtim<hawtimzhang@gmail.com>",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
|
|
@ -18,68 +18,57 @@
|
||||||
"electron:publish": "vue-cli-service electron:build -mwl -p always",
|
"electron:publish": "vue-cli-service electron:build -mwl -p always",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"postuninstall": "electron-builder install-app-deps",
|
"postuninstall": "electron-builder install-app-deps",
|
||||||
"prettier": "npx prettier --write ./src",
|
"prettier": "npx prettier --write ./src ./script",
|
||||||
"netease_api:run": "npx NeteaseCloudMusicApi"
|
"netease_api:run": "cd ./netease_api && npm run start",
|
||||||
|
"netease_api:pull": "node script/pull.js",
|
||||||
|
"netease_api:install": "cd ./netease_api && npm install",
|
||||||
|
"netease_api:setup": "npm run netease_api:pull && npm run netease_api:install"
|
||||||
},
|
},
|
||||||
"main": "background.js",
|
"main": "background.js",
|
||||||
"engines": {
|
|
||||||
"node": "14 || 16"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@unblockneteasemusic/rust-napi": "^0.4.0",
|
"@njzy/unblockneteasemusic": "^0.25.3",
|
||||||
"NeteaseCloudMusicApi": "^4.23.3",
|
"axios": "^0.21.0",
|
||||||
"axios": "^0.26.1",
|
"big-integer": "^1.6.48",
|
||||||
"change-case": "^4.1.2",
|
"change-case": "^4.1.2",
|
||||||
"cli-color": "^2.0.0",
|
|
||||||
"color": "^4.2.3",
|
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"crypto-js": "^4.0.0",
|
"crypto-js": "^4.0.0",
|
||||||
"dayjs": "^1.8.36",
|
"dayjs": "^1.8.36",
|
||||||
"dexie": "^3.0.3",
|
"electron": "11.0.2",
|
||||||
"discord-rich-presence": "^0.0.8",
|
"electron-context-menu": "^2.3.0",
|
||||||
"electron": "^13.6.7",
|
|
||||||
"electron-builder": "^23.0.0",
|
|
||||||
"electron-context-menu": "^3.1.2",
|
|
||||||
"electron-debug": "^3.1.0",
|
"electron-debug": "^3.1.0",
|
||||||
"electron-devtools-installer": "^3.2",
|
"electron-devtools-installer": "^3.1.1",
|
||||||
"electron-icon-builder": "^2.0.1",
|
"electron-icon-builder": "^1.0.2",
|
||||||
"electron-is-dev": "^2.0.0",
|
"electron-is-dev": "^1.2.0",
|
||||||
"electron-log": "^4.3.0",
|
"electron-log": "^4.3.0",
|
||||||
"electron-store": "^8.0.1",
|
"electron-store": "^6.0.1",
|
||||||
"electron-updater": "^5.0.1",
|
"electron-updater": "^4.3.5",
|
||||||
"esbuild": "^0.20.1",
|
|
||||||
"esbuild-loader": "^4.0.3",
|
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-fileupload": "^1.2.0",
|
"express-fileupload": "^1.2.0",
|
||||||
"express-http-proxy": "^1.6.2",
|
"express-http-proxy": "^1.6.2",
|
||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"howler": "^2.2.3",
|
"howler": "^2.2.0",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"jsbi": "^4.1.0",
|
"localforage": "^1.9.0",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"md5": "^2.3.0",
|
|
||||||
"mpris-service": "^2.1.2",
|
|
||||||
"music-metadata": "^7.5.3",
|
|
||||||
"node-vibrant": "^3.2.1-alpha.1",
|
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pac-proxy-agent": "^4.1.0",
|
"pac-proxy-agent": "^4.1.0",
|
||||||
"plyr": "^3.6.2",
|
"plyr": "^3.6.2",
|
||||||
"qrcode": "^1.4.4",
|
"prettier": "2.1.2",
|
||||||
"register-service-worker": "^1.7.1",
|
"register-service-worker": "^1.7.1",
|
||||||
"svg-sprite-loader": "^6.0.11",
|
"svg-sprite-loader": "^5.0.0",
|
||||||
"tunnel": "^0.0.6",
|
"tunnel": "^0.0.6",
|
||||||
"vscode-codicons": "^0.0.17",
|
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-clipboard2": "^0.3.1",
|
"vue-analytics": "^5.22.1",
|
||||||
"vue-gtag": "1",
|
"vue-electron": "^1.0.6",
|
||||||
"vue-i18n": "^8.22.0",
|
"vue-i18n": "^8.22.0",
|
||||||
"vue-router": "^3.4.3",
|
"vue-router": "^3.4.3",
|
||||||
"vue-slider-component": "^3.2.5",
|
"vue-slider-component": "^3.2.5",
|
||||||
"vuex": "^3.4.0",
|
"vuex": "^3.4.0"
|
||||||
"x11": "^2.3.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.0",
|
"@sentry/browser": "^5.27.0",
|
||||||
|
"@sentry/integrations": "^5.27.0",
|
||||||
|
"@sentry/tracing": "^5.27.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
"@vue/cli-plugin-pwa": "~4.5.0",
|
"@vue/cli-plugin-pwa": "~4.5.0",
|
||||||
|
|
@ -87,21 +76,13 @@
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
|
||||||
"eslint-plugin-vue": "^7.9.0",
|
|
||||||
"husky": "^4.3.0",
|
"husky": "^4.3.0",
|
||||||
"prettier": "2.5.1",
|
|
||||||
"sass": "^1.26.11",
|
"sass": "^1.26.11",
|
||||||
"sass-loader": "^10.0.2",
|
"sass-loader": "^10.0.2",
|
||||||
"vue-cli-plugin-electron-builder": "~2.1.1",
|
"vue-cli-plugin-electron-builder": "~2.0.0-rc.4",
|
||||||
"vue-template-compiler": "^2.6.11"
|
"vue-template-compiler": "^2.6.11"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
|
||||||
"icon-gen": "3.0.0",
|
|
||||||
"degenerator": "2.2.0",
|
|
||||||
"electron-builder": "^23.0.0"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
"env": {
|
"env": {
|
||||||
|
|
@ -110,8 +91,6 @@
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:vue/essential",
|
"plugin:vue/essential",
|
||||||
"plugin:vue/recommended",
|
|
||||||
"plugin:prettier/recommended",
|
|
||||||
"eslint:recommended"
|
"eslint:recommended"
|
||||||
],
|
],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 223 B |
|
Before Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 308 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 396 B |
|
Before Width: | Height: | Size: 344 B |
|
Before Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 932 B |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 750 B |
|
Before Width: | Height: | Size: 801 B |
|
Before Width: | Height: | Size: 779 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 871 B |
|
Before Width: | Height: | Size: 855 B |
|
Before Width: | Height: | Size: 656 B |
|
Before Width: | Height: | Size: 610 B |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 746 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,25 +1,23 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="referrer" content="no-referrer" />
|
<meta name="referrer" content="no-referrer" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||||
<title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
<%= htmlWebpackPlugin.options.title %>
|
|
||||||
</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
<strong
|
||||||
|
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||||
properly without JavaScript enabled. Please enable it to
|
properly without JavaScript enabled. Please enable it to
|
||||||
continue.</strong>
|
continue.</strong
|
||||||
|
>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow: /
|
Disallow:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
commit_template: 'style: with ${restyler.name}'
|
|
||||||
restylers:
|
|
||||||
- prettier
|
|
||||||
- prettier-json
|
|
||||||
- prettier-markdown
|
|
||||||
- prettier-yaml
|
|
||||||
- whitespace
|
|
||||||
103
script/pull.js
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// node module
|
||||||
|
const fs = require("fs");
|
||||||
|
const https = require("https");
|
||||||
|
const resolve = require("path").resolve;
|
||||||
|
const join = require("path").resolve;
|
||||||
|
const extract = require("extract-zip");
|
||||||
|
|
||||||
|
// 函数参数
|
||||||
|
const dest = resolve(__dirname, "../");
|
||||||
|
const fileName = "NeteaseCloudMusicApi-master.zip";
|
||||||
|
const options = {
|
||||||
|
hostname: "github.91chifun.workers.dev",
|
||||||
|
path: `//https://github.com/Binaryify/NeteaseCloudMusicApi/archive/master.zip`,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 完整的流程控制
|
||||||
|
/**
|
||||||
|
* 1. 检查本地文件是否已有
|
||||||
|
* 2. 下载默认/指定版本的 zip 压缩包,等待下载
|
||||||
|
* 3. 解压缩
|
||||||
|
* 4. 进入目录安装依赖 npm install
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fix2(number) {
|
||||||
|
return number.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function download(options, fileName, callback) {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
const destPath = join(__dirname, "../" + fileName);
|
||||||
|
// Check if exist
|
||||||
|
if (fs.existsSync(destPath)) return resolve(destPath);
|
||||||
|
|
||||||
|
const file = fs.createWriteStream(destPath);
|
||||||
|
const request = https.get(options, (res) => {
|
||||||
|
let len = res.headers && parseInt(res.headers["content-length"], 10);
|
||||||
|
let cur = 0;
|
||||||
|
// 1048576 - bytes in 1Megabyte
|
||||||
|
const MEGA = 1048576;
|
||||||
|
let total = 0;
|
||||||
|
if (len) {
|
||||||
|
total = len / MEGA;
|
||||||
|
}
|
||||||
|
if (!len) {
|
||||||
|
console.log(
|
||||||
|
"Downloading, but can not get content-length, please be patient."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res.on("data", (chunk) => {
|
||||||
|
if (len) {
|
||||||
|
cur += chunk.length;
|
||||||
|
console.log(
|
||||||
|
`Downloading ${fix2((100.0 * cur) / len)}% ${fix2(
|
||||||
|
cur / MEGA
|
||||||
|
)}/${fix2(total)}mb`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.on("end", () => {
|
||||||
|
callback("Downloading complete!");
|
||||||
|
});
|
||||||
|
res.pipe(file);
|
||||||
|
file.on("finish", () => {
|
||||||
|
file.close(() => {
|
||||||
|
callback("File wrote complete!");
|
||||||
|
resolve(destPath);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
file.on("error", (err) => {
|
||||||
|
fs.unlink(destPath);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
request.on("error", (err) => {
|
||||||
|
console.log("Error: " + err.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unzip(source, target) {
|
||||||
|
try {
|
||||||
|
await extract(source, {
|
||||||
|
dir: target,
|
||||||
|
});
|
||||||
|
console.log("Extraction complete");
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
// handle any errors
|
||||||
|
if (err.message === "end of central directory record signature not found") {
|
||||||
|
console.log("Not a full_downloaded zip file, removed!");
|
||||||
|
fs.unlinkSync(source);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Download process
|
||||||
|
download(options, fileName, (text) => {
|
||||||
|
console.log(text);
|
||||||
|
}).then((path) => {
|
||||||
|
console.log(path);
|
||||||
|
// Unzip process
|
||||||
|
return unzip(path, dest);
|
||||||
|
});
|
||||||
207
src/App.vue
|
|
@ -1,43 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app" :class="{ 'user-select-none': userSelectNone }">
|
<div id="app">
|
||||||
<Scrollbar v-show="!showLyrics" ref="scrollbar" />
|
<Navbar ref="navbar" />
|
||||||
<Navbar v-show="showNavbar" ref="navbar" />
|
<main v-show="!this.$store.state.showLyrics">
|
||||||
<main
|
|
||||||
ref="main"
|
|
||||||
:style="{ overflow: enableScrolling ? 'auto' : 'hidden' }"
|
|
||||||
@scroll="handleScroll"
|
|
||||||
>
|
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view v-if="$route.meta.keepAlive"></router-view>
|
<router-view v-if="$route.meta.keepAlive"></router-view>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<router-view v-if="!$route.meta.keepAlive"></router-view>
|
<router-view v-if="!$route.meta.keepAlive"></router-view>
|
||||||
</main>
|
</main>
|
||||||
<transition name="slide-up">
|
<transition name="slide-up">
|
||||||
<Player v-if="enablePlayer" v-show="showPlayer" ref="player" />
|
<Player
|
||||||
</transition>
|
v-if="this.$store.state.player.enabled"
|
||||||
|
ref="player"
|
||||||
|
v-show="showPlayer"
|
||||||
|
/></transition>
|
||||||
<Toast />
|
<Toast />
|
||||||
<ModalAddTrackToPlaylist v-if="isAccountLoggedIn" />
|
<ModalAddTrackToPlaylist v-if="isAccountLoggedIn" />
|
||||||
<ModalNewPlaylist v-if="isAccountLoggedIn" />
|
<ModalNewPlaylist v-if="isAccountLoggedIn" />
|
||||||
<transition v-if="enablePlayer" name="slide-up">
|
<transition name="slide-up" v-if="this.$store.state.player.enabled">
|
||||||
<Lyrics v-show="showLyrics" />
|
<Lyrics v-show="this.$store.state.showLyrics" />
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ModalAddTrackToPlaylist from './components/ModalAddTrackToPlaylist.vue';
|
import ModalAddTrackToPlaylist from "./components/ModalAddTrackToPlaylist.vue";
|
||||||
import ModalNewPlaylist from './components/ModalNewPlaylist.vue';
|
import ModalNewPlaylist from "./components/ModalNewPlaylist.vue";
|
||||||
import Scrollbar from './components/Scrollbar.vue';
|
import Navbar from "./components/Navbar.vue";
|
||||||
import Navbar from './components/Navbar.vue';
|
import Player from "./components/Player.vue";
|
||||||
import Player from './components/Player.vue';
|
import Toast from "./components/Toast.vue";
|
||||||
import Toast from './components/Toast.vue';
|
import { ipcRenderer } from "./electron/ipcRenderer";
|
||||||
import { ipcRenderer } from './electron/ipcRenderer';
|
import { isAccountLoggedIn } from "@/utils/auth";
|
||||||
import { isAccountLoggedIn, isLooseLoggedIn } from '@/utils/auth';
|
import Lyrics from "./views/lyrics.vue";
|
||||||
import Lyrics from './views/lyrics.vue';
|
|
||||||
import { mapState } from 'vuex';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
Navbar,
|
Navbar,
|
||||||
Player,
|
Player,
|
||||||
|
|
@ -45,104 +41,163 @@ export default {
|
||||||
ModalAddTrackToPlaylist,
|
ModalAddTrackToPlaylist,
|
||||||
ModalNewPlaylist,
|
ModalNewPlaylist,
|
||||||
Lyrics,
|
Lyrics,
|
||||||
Scrollbar,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isElectron: process.env.IS_ELECTRON, // true || undefined
|
isElectron: process.env.IS_ELECTRON, // true || undefined
|
||||||
userSelectNone: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['showLyrics', 'settings', 'player', 'enableScrolling']),
|
|
||||||
isAccountLoggedIn() {
|
isAccountLoggedIn() {
|
||||||
return isAccountLoggedIn();
|
return isAccountLoggedIn();
|
||||||
},
|
},
|
||||||
showPlayer() {
|
showPlayer() {
|
||||||
return (
|
return (
|
||||||
[
|
["mv", "loginUsername", "login", "loginAccount"].includes(
|
||||||
'mv',
|
this.$route.name
|
||||||
'loginUsername',
|
) === false
|
||||||
'login',
|
|
||||||
'loginAccount',
|
|
||||||
'lastfmCallback',
|
|
||||||
].includes(this.$route.name) === false
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
enablePlayer() {
|
|
||||||
return this.player.enabled && this.$route.name !== 'lastfmCallback';
|
|
||||||
},
|
|
||||||
showNavbar() {
|
|
||||||
return this.$route.name !== 'lastfmCallback';
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.isElectron) ipcRenderer(this);
|
if (this.isElectron) {
|
||||||
window.addEventListener('keydown', this.handleKeydown);
|
ipcRenderer(this);
|
||||||
this.fetchData();
|
}
|
||||||
|
window.addEventListener("keydown", this.handleKeydown);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleKeydown(e) {
|
handleKeydown(e) {
|
||||||
if (e.code === 'Space') {
|
if (e.code === "Space") {
|
||||||
if (e.target.tagName === 'INPUT') return false;
|
if (e.target.tagName === "INPUT") return false;
|
||||||
if (this.$route.name === 'mv') return false;
|
if (this.$route.name === "mv") return false;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.player.playOrPause();
|
this.$refs.player.play();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchData() {
|
|
||||||
if (!isLooseLoggedIn()) return;
|
|
||||||
this.$store.dispatch('fetchLikedSongs');
|
|
||||||
this.$store.dispatch('fetchLikedSongsWithDetails');
|
|
||||||
this.$store.dispatch('fetchLikedPlaylist');
|
|
||||||
if (isAccountLoggedIn()) {
|
|
||||||
this.$store.dispatch('fetchLikedAlbums');
|
|
||||||
this.$store.dispatch('fetchLikedArtists');
|
|
||||||
this.$store.dispatch('fetchLikedMVs');
|
|
||||||
this.$store.dispatch('fetchCloudDisk');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleScroll() {
|
|
||||||
this.$refs.scrollbar.handleScroll();
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Barlow:ital,wght@0,500;0,600;0,700;0,800;0,900;1,500;1,600;1,700;1,800;1,900&display=swap");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--color-body-bg: #ffffff;
|
||||||
|
--color-text: #000;
|
||||||
|
--color-primary: #335eea;
|
||||||
|
--color-primary-bg: #eaeffd;
|
||||||
|
--color-secondary: #7a7a7b;
|
||||||
|
--color-secondary-bg: #f5f5f7;
|
||||||
|
--color-navbar-bg: rgba(255, 255, 255, 0.86);
|
||||||
|
--color-primary-bg-for-transparent: rgba(189, 207, 255, 0.28);
|
||||||
|
--color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--color-body-bg: #222222;
|
||||||
|
--color-text: #ffffff;
|
||||||
|
--color-primary: #335eea;
|
||||||
|
--color-primary-bg: #bbcdff;
|
||||||
|
--color-secondary: #7a7a7b;
|
||||||
|
--color-secondary-bg: #323232;
|
||||||
|
--color-navbar-bg: rgba(34, 34, 34, 0.86);
|
||||||
|
--color-primary-bg-for-transparent: rgba(255, 255, 255, 0.12);
|
||||||
|
--color-secondary-bg-for-transparent: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: all 0.4s;
|
transition: all 0.4s;
|
||||||
}
|
}
|
||||||
|
#app,
|
||||||
|
input {
|
||||||
|
font-family: "Barlow", -apple-system, BlinkMacSystemFont, Helvetica Neue,
|
||||||
|
PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC,
|
||||||
|
WenQuanYi Micro Hei, sans-serif;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: var(--color-body-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y: overlay;
|
||||||
|
min-width: 768px;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
position: fixed;
|
margin-top: 84px;
|
||||||
top: 0;
|
margin-bottom: 96px;
|
||||||
bottom: 0;
|
padding: {
|
||||||
right: 0;
|
right: 10vw;
|
||||||
left: 0;
|
left: 10vw;
|
||||||
overflow: auto;
|
}
|
||||||
padding: 64px 10vw 96px 10vw;
|
|
||||||
box-sizing: border-box;
|
|
||||||
scrollbar-width: none; // firefox
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1336px) {
|
@media (max-width: 1336px) {
|
||||||
main {
|
main {
|
||||||
padding: 64px 5vw 96px 5vw;
|
padding: 0 5vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main::-webkit-scrollbar {
|
select,
|
||||||
width: 0px;
|
button {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
input,
|
||||||
|
button {
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let's get this party started */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
border-left: 1px solid rgba(128, 128, 128, 0.18);
|
||||||
|
background: var(--color-body-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(128, 128, 128, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] ::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--color-secondary-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-up-enter-active,
|
.slide-up-enter-active,
|
||||||
.slide-up-leave-active {
|
.slide-up-leave-active {
|
||||||
transition: transform 0.4s;
|
transition: all 0.4s;
|
||||||
}
|
}
|
||||||
.slide-up-enter,
|
.slide-up-enter, .slide-up-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||||
.slide-up-leave-to {
|
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-electron="yes"] {
|
||||||
|
button,
|
||||||
|
.navigation-links a,
|
||||||
|
.playlist-info .description {
|
||||||
|
cursor: default !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { mapTrackPlayableStatus } from '@/utils/common';
|
import { mapTrackPlayableStatus } from "@/utils/common";
|
||||||
import { cacheAlbum, getAlbumFromCache } from '@/utils/db';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取专辑内容
|
* 获取专辑内容
|
||||||
|
|
@ -8,24 +7,16 @@ import { cacheAlbum, getAlbumFromCache } from '@/utils/db';
|
||||||
* @param {number} id
|
* @param {number} id
|
||||||
*/
|
*/
|
||||||
export function getAlbum(id) {
|
export function getAlbum(id) {
|
||||||
const fetchLatest = () => {
|
|
||||||
return request({
|
return request({
|
||||||
url: '/album',
|
url: "/album",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
}).then(data => {
|
}).then((data) => {
|
||||||
cacheAlbum(id, data);
|
|
||||||
data.songs = mapTrackPlayableStatus(data.songs);
|
data.songs = mapTrackPlayableStatus(data.songs);
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
};
|
|
||||||
fetchLatest();
|
|
||||||
|
|
||||||
return getAlbumFromCache(id).then(result => {
|
|
||||||
return result ?? fetchLatest();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -41,8 +32,8 @@ export function getAlbum(id) {
|
||||||
*/
|
*/
|
||||||
export function newAlbums(params) {
|
export function newAlbums(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/album/new',
|
url: "/album/new",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -55,8 +46,8 @@ export function newAlbums(params) {
|
||||||
*/
|
*/
|
||||||
export function albumDynamicDetail(id) {
|
export function albumDynamicDetail(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/album/detail/dynamic',
|
url: "/album/detail/dynamic",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { id, timestamp: new Date().getTime() },
|
params: { id, timestamp: new Date().getTime() },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +63,8 @@ export function albumDynamicDetail(id) {
|
||||||
*/
|
*/
|
||||||
export function likeAAlbum(params) {
|
export function likeAAlbum(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/album/sub',
|
url: "/album/sub",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { mapTrackPlayableStatus } from '@/utils/common';
|
import { mapTrackPlayableStatus } from "@/utils/common";
|
||||||
import { isAccountLoggedIn } from '@/utils/auth';
|
|
||||||
import { getTrackDetail } from '@/api/track';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取歌手单曲
|
* 获取歌手单曲
|
||||||
|
|
@ -10,19 +8,13 @@ import { getTrackDetail } from '@/api/track';
|
||||||
*/
|
*/
|
||||||
export function getArtist(id) {
|
export function getArtist(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/artists',
|
url: "/artists",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
id,
|
id,
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
}).then(async data => {
|
}).then((data) => {
|
||||||
if (!isAccountLoggedIn()) {
|
|
||||||
const trackIDs = data.hotSongs.map(t => t.id);
|
|
||||||
const tracks = await getTrackDetail(trackIDs.join(','));
|
|
||||||
data.hotSongs = tracks.songs;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
data.hotSongs = mapTrackPlayableStatus(data.hotSongs);
|
data.hotSongs = mapTrackPlayableStatus(data.hotSongs);
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
|
|
@ -41,8 +33,8 @@ export function getArtist(id) {
|
||||||
*/
|
*/
|
||||||
export function getArtistAlbum(params) {
|
export function getArtistAlbum(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/artist/album',
|
url: "/artist/album",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -58,14 +50,12 @@ export function getArtistAlbum(params) {
|
||||||
* @param {number=} type
|
* @param {number=} type
|
||||||
*/
|
*/
|
||||||
export function toplistOfArtists(type = null) {
|
export function toplistOfArtists(type = null) {
|
||||||
let params = {};
|
|
||||||
if (type) {
|
|
||||||
params.type = type;
|
|
||||||
}
|
|
||||||
return request({
|
return request({
|
||||||
url: '/toplist/artist',
|
url: "/toplist/artist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params: {
|
||||||
|
type,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
@ -77,8 +67,8 @@ export function toplistOfArtists(type = null) {
|
||||||
*/
|
*/
|
||||||
export function artistMv(params) {
|
export function artistMv(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/artist/mv',
|
url: "/artist/mv",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -94,8 +84,8 @@ export function artistMv(params) {
|
||||||
*/
|
*/
|
||||||
export function followAArtist(params) {
|
export function followAArtist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/artist/sub',
|
url: "/artist/sub",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -108,8 +98,8 @@ export function followAArtist(params) {
|
||||||
*/
|
*/
|
||||||
export function similarArtists(id) {
|
export function similarArtists(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/simi/artist',
|
url: "/simi/artist",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params: { id },
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手机登录
|
* 手机登录
|
||||||
|
|
@ -14,12 +14,11 @@ import request from '@/utils/request';
|
||||||
*/
|
*/
|
||||||
export function loginWithPhone(params) {
|
export function loginWithPhone(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/login/cellphone',
|
url: "/login/cellphone",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邮箱登录
|
* 邮箱登录
|
||||||
* - email: 163 网易邮箱
|
* - email: 163 网易邮箱
|
||||||
|
|
@ -32,60 +31,12 @@ export function loginWithPhone(params) {
|
||||||
*/
|
*/
|
||||||
export function loginWithEmail(params) {
|
export function loginWithEmail(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/login',
|
url: "/login",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 二维码key生成接口
|
|
||||||
*/
|
|
||||||
export function loginQrCodeKey() {
|
|
||||||
return request({
|
|
||||||
url: '/login/qr/key',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 二维码生成接口
|
|
||||||
* 说明: 调用此接口传入上一个接口生成的key可生成二维码图片的base64和二维码信息,
|
|
||||||
* 可使用base64展示图片,或者使用二维码信息内容自行使用第三方二维码生产库渲染二维码
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {string} params.key
|
|
||||||
* @param {string=} params.qrimg 传入后会额外返回二维码图片base64编码
|
|
||||||
*/
|
|
||||||
export function loginQrCodeCreate(params) {
|
|
||||||
return request({
|
|
||||||
url: '/login/qr/create',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
...params,
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 二维码检测扫码状态接口
|
|
||||||
* 说明: 轮询此接口可获取二维码扫码状态,800为二维码过期,801为等待扫码,802为待确认,803为授权登录成功(803状态码下会返回cookies)
|
|
||||||
* @param {string} key
|
|
||||||
*/
|
|
||||||
export function loginQrCodeCheck(key) {
|
|
||||||
return request({
|
|
||||||
url: '/login/qr/check',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
key,
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新登录
|
* 刷新登录
|
||||||
* 说明 : 调用此接口 , 可刷新登录状态
|
* 说明 : 调用此接口 , 可刷新登录状态
|
||||||
|
|
@ -93,8 +44,8 @@ export function loginQrCodeCheck(key) {
|
||||||
*/
|
*/
|
||||||
export function refreshCookie() {
|
export function refreshCookie() {
|
||||||
return request({
|
return request({
|
||||||
url: '/login/refresh',
|
url: "/login/refresh",
|
||||||
method: 'post',
|
method: "post",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +55,7 @@ export function refreshCookie() {
|
||||||
*/
|
*/
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/logout',
|
url: "/logout",
|
||||||
method: 'post',
|
method: "post",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
// Last.fm API documents 👉 https://www.last.fm/api
|
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
import md5 from 'crypto-js/md5';
|
|
||||||
|
|
||||||
const apiKey = process.env.VUE_APP_LASTFM_API_KEY;
|
|
||||||
const apiSharedSecret = process.env.VUE_APP_LASTFM_API_SHARED_SECRET;
|
|
||||||
const baseUrl = window.location.origin;
|
|
||||||
const url = 'https://ws.audioscrobbler.com/2.0/';
|
|
||||||
|
|
||||||
const sign = params => {
|
|
||||||
const sortParamsKeys = Object.keys(params).sort();
|
|
||||||
const sortedParams = sortParamsKeys.reduce((acc, key) => {
|
|
||||||
acc[key] = params[key];
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
let signature = '';
|
|
||||||
for (const [key, value] of Object.entries(sortedParams)) {
|
|
||||||
signature += `${key}${value}`;
|
|
||||||
}
|
|
||||||
return md5(signature + apiSharedSecret).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
export function auth() {
|
|
||||||
const url = process.env.IS_ELECTRON
|
|
||||||
? `https://www.last.fm/api/auth/?api_key=${apiKey}&cb=${baseUrl}/#/lastfm/callback`
|
|
||||||
: `https://www.last.fm/api/auth/?api_key=${apiKey}&cb=${baseUrl}/lastfm/callback`;
|
|
||||||
window.open(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function authGetSession(token) {
|
|
||||||
const signature = md5(
|
|
||||||
`api_key${apiKey}methodauth.getSessiontoken${token}${apiSharedSecret}`
|
|
||||||
).toString();
|
|
||||||
return axios({
|
|
||||||
url,
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
method: 'auth.getSession',
|
|
||||||
format: 'json',
|
|
||||||
api_key: apiKey,
|
|
||||||
api_sig: signature,
|
|
||||||
token,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUpdateNowPlaying(params) {
|
|
||||||
params.api_key = apiKey;
|
|
||||||
params.method = 'track.updateNowPlaying';
|
|
||||||
params.sk = JSON.parse(localStorage.getItem('lastfm'))['key'];
|
|
||||||
const signature = sign(params);
|
|
||||||
|
|
||||||
return axios({
|
|
||||||
url,
|
|
||||||
method: 'POST',
|
|
||||||
params: {
|
|
||||||
...params,
|
|
||||||
api_sig: signature,
|
|
||||||
format: 'json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackScrobble(params) {
|
|
||||||
params.api_key = apiKey;
|
|
||||||
params.method = 'track.scrobble';
|
|
||||||
params.sk = JSON.parse(localStorage.getItem('lastfm'))['key'];
|
|
||||||
const signature = sign(params);
|
|
||||||
|
|
||||||
return axios({
|
|
||||||
url,
|
|
||||||
method: 'POST',
|
|
||||||
params: {
|
|
||||||
...params,
|
|
||||||
api_sig: signature,
|
|
||||||
format: 'json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 mv 数据
|
* 获取 mv 数据
|
||||||
|
|
@ -9,8 +9,8 @@ import request from '@/utils/request';
|
||||||
*/
|
*/
|
||||||
export function mvDetail(mvid) {
|
export function mvDetail(mvid) {
|
||||||
return request({
|
return request({
|
||||||
url: '/mv/detail',
|
url: "/mv/detail",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
mvid,
|
mvid,
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
|
|
@ -30,8 +30,8 @@ export function mvDetail(mvid) {
|
||||||
*/
|
*/
|
||||||
export function mvUrl(params) {
|
export function mvUrl(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/mv/url',
|
url: "/mv/url",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -43,8 +43,8 @@ export function mvUrl(params) {
|
||||||
*/
|
*/
|
||||||
export function simiMv(mvid) {
|
export function simiMv(mvid) {
|
||||||
return request({
|
return request({
|
||||||
url: '/simi/mv',
|
url: "/simi/mv",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { mvid },
|
params: { mvid },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -62,8 +62,8 @@ export function simiMv(mvid) {
|
||||||
export function likeAMV(params) {
|
export function likeAMV(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/mv/sub',
|
url: "/mv/sub",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { mapTrackPlayableStatus } from '@/utils/common';
|
import { mapTrackPlayableStatus } from "@/utils/common";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索
|
* 搜索
|
||||||
|
|
@ -18,33 +18,12 @@ import { mapTrackPlayableStatus } from '@/utils/common';
|
||||||
*/
|
*/
|
||||||
export function search(params) {
|
export function search(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/search',
|
url: "/search",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
}).then(data => {
|
}).then((data) => {
|
||||||
if (data.result?.song !== undefined)
|
if (data.result?.song !== undefined)
|
||||||
data.result.song.songs = mapTrackPlayableStatus(data.result.song.songs);
|
data.result.song.songs = mapTrackPlayableStatus(data.result.song.songs);
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function personalFM() {
|
|
||||||
return request({
|
|
||||||
url: '/personal_fm',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fmTrash(id) {
|
|
||||||
return request({
|
|
||||||
url: '/fm_trash',
|
|
||||||
method: 'post',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { mapTrackPlayableStatus } from '@/utils/common';
|
import { mapTrackPlayableStatus } from "@/utils/common";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 推荐歌单
|
* 推荐歌单
|
||||||
|
|
@ -11,8 +11,8 @@ import { mapTrackPlayableStatus } from '@/utils/common';
|
||||||
*/
|
*/
|
||||||
export function recommendPlaylist(params) {
|
export function recommendPlaylist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/personalized',
|
url: "/personalized",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -24,12 +24,9 @@ export function recommendPlaylist(params) {
|
||||||
*/
|
*/
|
||||||
export function dailyRecommendPlaylist(params) {
|
export function dailyRecommendPlaylist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/recommend/resource',
|
url: "/recommend/resource",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
|
||||||
params,
|
params,
|
||||||
timestamp: Date.now(),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
@ -46,16 +43,14 @@ export function getPlaylistDetail(id, noCache = false) {
|
||||||
let params = { id };
|
let params = { id };
|
||||||
if (noCache) params.timestamp = new Date().getTime();
|
if (noCache) params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/detail',
|
url: "/playlist/detail",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
}).then(data => {
|
}).then((data) => {
|
||||||
if (data.playlist) {
|
|
||||||
data.playlist.tracks = mapTrackPlayableStatus(
|
data.playlist.tracks = mapTrackPlayableStatus(
|
||||||
data.playlist.tracks,
|
data.playlist.tracks,
|
||||||
data.privileges || []
|
data.privileges || []
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +67,8 @@ export function getPlaylistDetail(id, noCache = false) {
|
||||||
*/
|
*/
|
||||||
export function highQualityPlaylist(params) {
|
export function highQualityPlaylist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/top/playlist/highquality',
|
url: "/top/playlist/highquality",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -91,8 +86,8 @@ export function highQualityPlaylist(params) {
|
||||||
*/
|
*/
|
||||||
export function topPlaylist(params) {
|
export function topPlaylist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/top/playlist',
|
url: "/top/playlist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -103,8 +98,8 @@ export function topPlaylist(params) {
|
||||||
*/
|
*/
|
||||||
export function playlistCatlist() {
|
export function playlistCatlist() {
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/catlist',
|
url: "/playlist/catlist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,8 +109,8 @@ export function playlistCatlist() {
|
||||||
*/
|
*/
|
||||||
export function toplists() {
|
export function toplists() {
|
||||||
return request({
|
return request({
|
||||||
url: '/toplist',
|
url: "/toplist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,8 +126,8 @@ export function toplists() {
|
||||||
export function subscribePlaylist(params) {
|
export function subscribePlaylist(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/subscribe',
|
url: "/playlist/subscribe",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -145,8 +140,8 @@ export function subscribePlaylist(params) {
|
||||||
*/
|
*/
|
||||||
export function deletePlaylist(id) {
|
export function deletePlaylist(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/delete',
|
url: "/playlist/delete",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params: { id },
|
params: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -165,8 +160,8 @@ export function deletePlaylist(id) {
|
||||||
export function createPlaylist(params) {
|
export function createPlaylist(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/create',
|
url: "/playlist/create",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -183,47 +178,8 @@ export function createPlaylist(params) {
|
||||||
export function addOrRemoveTrackFromPlaylist(params) {
|
export function addOrRemoveTrackFromPlaylist(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/playlist/tracks',
|
url: "/playlist/tracks",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 每日推荐歌曲
|
|
||||||
* 说明 : 调用此接口 , 可获得每日推荐歌曲 ( 需要登录 )
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {string} params.op
|
|
||||||
* @param {string} params.pid
|
|
||||||
*/
|
|
||||||
export function dailyRecommendTracks() {
|
|
||||||
return request({
|
|
||||||
url: '/recommend/songs',
|
|
||||||
method: 'get',
|
|
||||||
params: { timestamp: new Date().getTime() },
|
|
||||||
}).then(result => {
|
|
||||||
result.data.dailySongs = mapTrackPlayableStatus(
|
|
||||||
result.data.dailySongs,
|
|
||||||
result.data.privileges
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 心动模式/智能播放
|
|
||||||
* 说明 : 登录后调用此接口 , 可获取心动模式/智能播放列表 必选参数 : id : 歌曲 id
|
|
||||||
* - id : 歌曲 id
|
|
||||||
* - pid : 歌单 id
|
|
||||||
* - sid : 要开始播放的歌曲的 id (可选参数)
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {number=} params.id
|
|
||||||
* @param {number=} params.pid
|
|
||||||
*/
|
|
||||||
export function intelligencePlaylist(params) {
|
|
||||||
return request({
|
|
||||||
url: '/playmode/intelligence/list',
|
|
||||||
method: 'get',
|
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
import store from '@/store';
|
import store from "@/store";
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { mapTrackPlayableStatus } from '@/utils/common';
|
import { mapTrackPlayableStatus } from "@/utils/common";
|
||||||
import {
|
|
||||||
cacheTrackDetail,
|
|
||||||
getTrackDetailFromCache,
|
|
||||||
cacheLyric,
|
|
||||||
getLyricFromCache,
|
|
||||||
} from '@/utils/db';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取音乐 url
|
* 获取音乐 url
|
||||||
* 说明 : 使用歌单详情接口后 , 能得到的音乐的 id, 但不能得到的音乐 url, 调用此接口, 传入的音乐 id( 可多个 , 用逗号隔开 ), 可以获取对应的音乐的 url,
|
* 说明 : 使用歌单详情接口后 , 能得到的音乐的 id, 但不能得到的音乐 url, 调用此接口, 传入的音乐 id( 可多个 , 用逗号隔开 ), 可以获取对应的音乐的 url,
|
||||||
|
|
@ -15,85 +8,51 @@ import {
|
||||||
* @param {string} id - 音乐的 id,例如 id=405998841,33894312
|
* @param {string} id - 音乐的 id,例如 id=405998841,33894312
|
||||||
*/
|
*/
|
||||||
export function getMP3(id) {
|
export function getMP3(id) {
|
||||||
const getBr = () => {
|
let br =
|
||||||
// 当返回的 quality >= 400000时,就会优先返回 hi-res
|
store.state.settings?.musicQuality !== undefined
|
||||||
const quality = store.state.settings?.musicQuality ?? '320000';
|
? store.state.settings.musicQuality
|
||||||
return quality === 'flac' ? '350000' : quality;
|
: 320000;
|
||||||
};
|
|
||||||
|
|
||||||
return request({
|
return request({
|
||||||
url: '/song/url',
|
url: "/song/url",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
id,
|
id,
|
||||||
br: getBr(),
|
br,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取歌曲详情
|
* 获取歌曲详情
|
||||||
* 说明 : 调用此接口 , 传入音乐 id(支持多个 id, 用 , 隔开), 可获得歌曲详情(注意:歌曲封面现在需要通过专辑内容接口获取)
|
* 说明 : 调用此接口 , 传入音乐 id(支持多个 id, 用 , 隔开), 可获得歌曲详情(注意:歌曲封面现在需要通过专辑内容接口获取)
|
||||||
* @param {string} ids - 音乐 id, 例如 ids=405998841,33894312
|
* @param {string} ids - 音乐 id, 例如 ids=405998841,33894312
|
||||||
*/
|
*/
|
||||||
export function getTrackDetail(ids) {
|
export function getTrackDetail(ids) {
|
||||||
const fetchLatest = () => {
|
|
||||||
return request({
|
return request({
|
||||||
url: '/song/detail',
|
url: "/song/detail",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
ids,
|
ids,
|
||||||
},
|
},
|
||||||
}).then(data => {
|
}).then((data) => {
|
||||||
data.songs.map(song => {
|
|
||||||
const privileges = data.privileges.find(t => t.id === song.id);
|
|
||||||
cacheTrackDetail(song, privileges);
|
|
||||||
});
|
|
||||||
data.songs = mapTrackPlayableStatus(data.songs, data.privileges);
|
data.songs = mapTrackPlayableStatus(data.songs, data.privileges);
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
};
|
|
||||||
fetchLatest();
|
|
||||||
|
|
||||||
let idsInArray = [String(ids)];
|
|
||||||
if (typeof ids === 'string') {
|
|
||||||
idsInArray = ids.split(',');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getTrackDetailFromCache(idsInArray).then(result => {
|
|
||||||
if (result) {
|
|
||||||
result.songs = mapTrackPlayableStatus(result.songs, result.privileges);
|
|
||||||
}
|
|
||||||
return result ?? fetchLatest();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取歌词
|
* 获取歌词
|
||||||
* 说明 : 调用此接口 , 传入音乐 id 可获得对应音乐的歌词 ( 不需要登录 )
|
* 说明 : 调用此接口 , 传入音乐 id 可获得对应音乐的歌词 ( 不需要登录 )
|
||||||
* @param {number} id - 音乐 id
|
* @param {number} id - 音乐 id
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function getLyric(id) {
|
export function getLyric(id) {
|
||||||
const fetchLatest = () => {
|
|
||||||
return request({
|
return request({
|
||||||
url: '/lyric',
|
url: "/lyric",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
}).then(result => {
|
|
||||||
cacheLyric(id, result);
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchLatest();
|
|
||||||
|
|
||||||
return getLyricFromCache(id).then(result => {
|
|
||||||
return result ?? fetchLatest();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新歌速递
|
* 新歌速递
|
||||||
* 说明 : 调用此接口 , 可获取新歌速递
|
* 说明 : 调用此接口 , 可获取新歌速递
|
||||||
|
|
@ -101,14 +60,13 @@ export function getLyric(id) {
|
||||||
*/
|
*/
|
||||||
export function topSong(type) {
|
export function topSong(type) {
|
||||||
return request({
|
return request({
|
||||||
url: '/top/song',
|
url: "/top/song",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
type,
|
type,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 喜欢音乐
|
* 喜欢音乐
|
||||||
* 说明 : 调用此接口 , 传入音乐 id, 可喜欢该音乐
|
* 说明 : 调用此接口 , 传入音乐 id, 可喜欢该音乐
|
||||||
|
|
@ -121,8 +79,8 @@ export function topSong(type) {
|
||||||
export function likeATrack(params) {
|
export function likeATrack(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/like',
|
url: "/like",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -141,8 +99,8 @@ export function likeATrack(params) {
|
||||||
export function scrobble(params) {
|
export function scrobble(params) {
|
||||||
params.timestamp = new Date().getTime();
|
params.timestamp = new Date().getTime();
|
||||||
return request({
|
return request({
|
||||||
url: '/scrobble',
|
url: "/scrobble",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
144
src/api/user.js
|
|
@ -1,4 +1,4 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户详情
|
* 获取用户详情
|
||||||
|
|
@ -8,25 +8,10 @@ import request from '@/utils/request';
|
||||||
*/
|
*/
|
||||||
export function userDetail(uid) {
|
export function userDetail(uid) {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/detail',
|
url: "/user/detail",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
uid,
|
uid,
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取账号详情
|
|
||||||
* 说明 : 登录后调用此接口 ,可获取用户账号信息
|
|
||||||
*/
|
|
||||||
export function userAccount() {
|
|
||||||
return request({
|
|
||||||
url: '/user/account',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -44,25 +29,8 @@ export function userAccount() {
|
||||||
*/
|
*/
|
||||||
export function userPlaylist(params) {
|
export function userPlaylist(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/playlist',
|
url: "/user/playlist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取用户播放记录
|
|
||||||
* 说明 : 登录后调用此接口 , 传入用户 id, 可获取用户播放记录
|
|
||||||
* - uid : 用户 id
|
|
||||||
* - type : type=1 时只返回 weekData, type=0 时返回 allData
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {number} params.uid
|
|
||||||
* @param {number} params.type
|
|
||||||
*/
|
|
||||||
export function userPlayHistory(params) {
|
|
||||||
return request({
|
|
||||||
url: '/user/record',
|
|
||||||
method: 'get',
|
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -75,8 +43,8 @@ export function userPlayHistory(params) {
|
||||||
*/
|
*/
|
||||||
export function userLikedSongsIDs(uid) {
|
export function userLikedSongsIDs(uid) {
|
||||||
return request({
|
return request({
|
||||||
url: '/likelist',
|
url: "/likelist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
uid,
|
uid,
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
|
|
@ -92,8 +60,8 @@ export function userLikedSongsIDs(uid) {
|
||||||
*/
|
*/
|
||||||
export function dailySignin(type = 0) {
|
export function dailySignin(type = 0) {
|
||||||
return request({
|
return request({
|
||||||
url: '/daily_signin',
|
url: "/daily_signin",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params: {
|
params: {
|
||||||
type,
|
type,
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
|
|
@ -104,18 +72,17 @@ export function dailySignin(type = 0) {
|
||||||
/**
|
/**
|
||||||
* 获取收藏的专辑(需要登录)
|
* 获取收藏的专辑(需要登录)
|
||||||
* 说明 : 调用此接口可获取到用户收藏的专辑
|
* 说明 : 调用此接口可获取到用户收藏的专辑
|
||||||
* - limit : 返回数量 , 默认为 25
|
* - limit : 返回数量 , 默认为 30
|
||||||
* - offset : 偏移数量,用于分页 , 如 :( 页数 -1)*25, 其中 25 为 limit 的值 , 默认为 0
|
* - offset : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0
|
||||||
* @param {Object} params
|
* @param {Object} params
|
||||||
* @param {number} params.limit
|
* @param {number} params.limit
|
||||||
* @param {number=} params.offset
|
* @param {number=} params.offset
|
||||||
*/
|
*/
|
||||||
export function likedAlbums(params) {
|
export function likedAlbums() {
|
||||||
return request({
|
return request({
|
||||||
url: '/album/sublist',
|
url: "/album/sublist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
limit: params.limit,
|
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -125,12 +92,11 @@ export function likedAlbums(params) {
|
||||||
* 获取收藏的歌手(需要登录)
|
* 获取收藏的歌手(需要登录)
|
||||||
* 说明 : 调用此接口可获取到用户收藏的歌手
|
* 说明 : 调用此接口可获取到用户收藏的歌手
|
||||||
*/
|
*/
|
||||||
export function likedArtists(params) {
|
export function likedArtists() {
|
||||||
return request({
|
return request({
|
||||||
url: '/artist/sublist',
|
url: "/artist/sublist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
limit: params.limit,
|
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -140,82 +106,12 @@ export function likedArtists(params) {
|
||||||
* 获取收藏的MV(需要登录)
|
* 获取收藏的MV(需要登录)
|
||||||
* 说明 : 调用此接口可获取到用户收藏的MV
|
* 说明 : 调用此接口可获取到用户收藏的MV
|
||||||
*/
|
*/
|
||||||
export function likedMVs(params) {
|
export function likedMVs() {
|
||||||
return request({
|
return request({
|
||||||
url: '/mv/sublist',
|
url: "/mv/sublist",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: {
|
|
||||||
limit: params.limit,
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传歌曲到云盘(需要登录)
|
|
||||||
*/
|
|
||||||
export function uploadSong(file) {
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append('songFile', file);
|
|
||||||
return request({
|
|
||||||
url: '/cloud',
|
|
||||||
method: 'post',
|
|
||||||
params: {
|
params: {
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
data: formData,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data',
|
|
||||||
},
|
|
||||||
timeout: 200000,
|
|
||||||
}).catch(error => {
|
|
||||||
alert(`上传失败,Error: ${error}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取云盘歌曲(需要登录)
|
|
||||||
* 说明 : 登录后调用此接口 , 可获取云盘数据 , 获取的数据没有对应 url, 需要再调用一 次 /song/url 获取 url
|
|
||||||
* - limit : 返回数量 , 默认为 200
|
|
||||||
* - offset : 偏移数量,用于分页 , 如 :( 页数 -1)*200, 其中 200 为 limit 的值 , 默认为 0
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {number} params.limit
|
|
||||||
* @param {number=} params.offset
|
|
||||||
*/
|
|
||||||
export function cloudDisk(params = {}) {
|
|
||||||
params.timestamp = new Date().getTime();
|
|
||||||
return request({
|
|
||||||
url: '/user/cloud',
|
|
||||||
method: 'get',
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取云盘歌曲详情(需要登录)
|
|
||||||
*/
|
|
||||||
export function cloudDiskTrackDetail(id) {
|
|
||||||
return request({
|
|
||||||
url: '/user/cloud/detail',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除云盘歌曲(需要登录)
|
|
||||||
* @param {Array} id
|
|
||||||
*/
|
|
||||||
export function cloudDiskTrackDelete(id) {
|
|
||||||
return request({
|
|
||||||
url: '/user/cloud/del',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: normal;
|
|
||||||
src: url('~@/assets/fonts/Barlow-Regular.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-Regular.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: medium;
|
|
||||||
src: url('~@/assets/fonts/Barlow-Medium.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-Medium.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: 600;
|
|
||||||
src: url('~@/assets/fonts/Barlow-SemiBold.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-SemiBold.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: bold;
|
|
||||||
src: url('~@/assets/fonts/Barlow-Bold.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-Bold.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: 800;
|
|
||||||
src: url('~@/assets/fonts/Barlow-ExtraBold.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-ExtraBold.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Barlow';
|
|
||||||
font-weight: 900;
|
|
||||||
src: url('~@/assets/fonts/Barlow-Black.woff2') format('woff2'),
|
|
||||||
url('~@/assets/fonts/Barlow-Black.ttf') format('truetype');
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--color-body-bg: #ffffff;
|
|
||||||
--color-text: #000;
|
|
||||||
--color-primary: #335eea;
|
|
||||||
--color-primary-bg: #eaeffd;
|
|
||||||
--color-secondary: #7a7a7b;
|
|
||||||
--color-secondary-bg: #f5f5f7;
|
|
||||||
--color-navbar-bg: rgba(255, 255, 255, 0.86);
|
|
||||||
--color-primary-bg-for-transparent: rgba(189, 207, 255, 0.28);
|
|
||||||
--color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
|
|
||||||
--html-overflow-y: overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme='dark'] {
|
|
||||||
--color-body-bg: #222222;
|
|
||||||
--color-text: #ffffff;
|
|
||||||
--color-primary: #335eea;
|
|
||||||
--color-primary-bg: #bbcdff;
|
|
||||||
--color-secondary: #7a7a7b;
|
|
||||||
--color-secondary-bg: #323232;
|
|
||||||
--color-navbar-bg: rgba(34, 34, 34, 0.86);
|
|
||||||
--color-primary-bg-for-transparent: rgba(255, 255, 255, 0.12);
|
|
||||||
--color-secondary-bg-for-transparent: rgba(255, 255, 255, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
#app,
|
|
||||||
input {
|
|
||||||
font-family: 'Barlow', ui-sans-serif, system-ui, -apple-system,
|
|
||||||
BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei,
|
|
||||||
Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif,
|
|
||||||
microsoft uighur;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
background-color: var(--color-body-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
overflow-y: var(--html-overflow-y);
|
|
||||||
min-width: 768px;
|
|
||||||
overscroll-behavior: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
select,
|
|
||||||
button {
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
input,
|
|
||||||
button {
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-electron='yes'] {
|
|
||||||
button,
|
|
||||||
.navigation-links a,
|
|
||||||
.playlist-info .description {
|
|
||||||
cursor: default !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
border-left: 1px solid rgba(128, 128, 128, 0.18);
|
|
||||||
background: var(--color-body-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
-webkit-border-radius: 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: rgba(128, 128, 128, 0.38);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme='dark'] ::-webkit-scrollbar-thumb {
|
|
||||||
background: var(--color-secondary-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-select-none {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
@ -265,17 +265,17 @@ a.plyr__control::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr [data-plyr='airplay'],
|
.plyr [data-plyr="airplay"],
|
||||||
.plyr [data-plyr='captions'],
|
.plyr [data-plyr="captions"],
|
||||||
.plyr [data-plyr='fullscreen'],
|
.plyr [data-plyr="fullscreen"],
|
||||||
.plyr [data-plyr='pip'] {
|
.plyr [data-plyr="pip"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--airplay-supported [data-plyr='airplay'],
|
.plyr--airplay-supported [data-plyr="airplay"],
|
||||||
.plyr--captions-enabled [data-plyr='captions'],
|
.plyr--captions-enabled [data-plyr="captions"],
|
||||||
.plyr--fullscreen-enabled [data-plyr='fullscreen'],
|
.plyr--fullscreen-enabled [data-plyr="fullscreen"],
|
||||||
.plyr--pip-supported [data-plyr='pip'] {
|
.plyr--pip-supported [data-plyr="pip"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,11 +288,11 @@ a.plyr__control::before {
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu .plyr__control[aria-expanded='true'] svg {
|
.plyr__menu .plyr__control[aria-expanded="true"] svg {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu .plyr__control[aria-expanded='true'] .plyr__tooltip {
|
.plyr__menu .plyr__control[aria-expanded="true"] .plyr__tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,7 +327,7 @@ a.plyr__control::before {
|
||||||
border: var(--plyr-menu-arrow-size, 4px) solid transparent;
|
border: var(--plyr-menu-arrow-size, 4px) solid transparent;
|
||||||
border-top-color: rgba(255, 255, 255, 0.9);
|
border-top-color: rgba(255, 255, 255, 0.9);
|
||||||
border-top-color: var(--plyr-menu-background, rgba(255, 255, 255, 0.9));
|
border-top-color: var(--plyr-menu-background, rgba(255, 255, 255, 0.9));
|
||||||
content: '';
|
content: "";
|
||||||
height: 0;
|
height: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: calc(((18px / 2) + calc(10px * 0.7)) - (4px / 2));
|
right: calc(((18px / 2) + calc(10px * 0.7)) - (4px / 2));
|
||||||
|
|
@ -341,18 +341,18 @@ a.plyr__control::before {
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container [role='menu'] {
|
.plyr__menu__container [role="menu"] {
|
||||||
padding: calc(10px * 0.7);
|
padding: calc(10px * 0.7);
|
||||||
padding: calc(var(--plyr-control-spacing, 10px) * 0.7);
|
padding: calc(var(--plyr-control-spacing, 10px) * 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container [role='menuitem'],
|
.plyr__menu__container [role="menuitem"],
|
||||||
.plyr__menu__container [role='menuitemradio'] {
|
.plyr__menu__container [role="menuitemradio"] {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container [role='menuitem']:first-child,
|
.plyr__menu__container [role="menuitem"]:first-child,
|
||||||
.plyr__menu__container [role='menuitemradio']:first-child {
|
.plyr__menu__container [role="menuitemradio"]:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +386,7 @@ a.plyr__control::before {
|
||||||
.plyr__menu__container .plyr__control::after {
|
.plyr__menu__container .plyr__control::after {
|
||||||
border: 4px solid transparent;
|
border: 4px solid transparent;
|
||||||
border: var(--plyr-menu-item-arrow-size, 4px) solid transparent;
|
border: var(--plyr-menu-item-arrow-size, 4px) solid transparent;
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
|
|
@ -441,7 +441,7 @@ a.plyr__control::before {
|
||||||
background: var(--plyr-menu-back-border-color, #dcdfe5);
|
background: var(--plyr-menu-back-border-color, #dcdfe5);
|
||||||
box-shadow: 0 1px 0 #fff;
|
box-shadow: 0 1px 0 #fff;
|
||||||
box-shadow: 0 1px 0 var(--plyr-menu-back-border-shadow-color, #fff);
|
box-shadow: 0 1px 0 var(--plyr-menu-back-border-shadow-color, #fff);
|
||||||
content: '';
|
content: "";
|
||||||
height: 1px;
|
height: 1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
margin-top: calc(calc(10px * 0.7) / 2);
|
margin-top: calc(calc(10px * 0.7) / 2);
|
||||||
|
|
@ -457,19 +457,19 @@ a.plyr__control::before {
|
||||||
border-right-color: currentColor;
|
border-right-color: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio'] {
|
.plyr__menu__container .plyr__control[role="menuitemradio"] {
|
||||||
padding-left: calc(10px * 0.7);
|
padding-left: calc(10px * 0.7);
|
||||||
padding-left: calc(var(--plyr-control-spacing, 10px) * 0.7);
|
padding-left: calc(var(--plyr-control-spacing, 10px) * 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio']::after,
|
.plyr__menu__container .plyr__control[role="menuitemradio"]::after,
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio']::before {
|
.plyr__menu__container .plyr__control[role="menuitemradio"]::before {
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio']::before {
|
.plyr__menu__container .plyr__control[role="menuitemradio"]::before {
|
||||||
background: rgba(0, 0, 0, 0.1);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
content: '';
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|
@ -479,7 +479,7 @@ a.plyr__control::before {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio']::after {
|
.plyr__menu__container .plyr__control[role="menuitemradio"]::after {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
|
|
@ -492,7 +492,7 @@ a.plyr__control::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container
|
.plyr__menu__container
|
||||||
.plyr__control[role='menuitemradio'][aria-checked='true']::before {
|
.plyr__control[role="menuitemradio"][aria-checked="true"]::before {
|
||||||
background: #00b3ff;
|
background: #00b3ff;
|
||||||
background: var(
|
background: var(
|
||||||
--plyr-control-toggle-checked-background,
|
--plyr-control-toggle-checked-background,
|
||||||
|
|
@ -501,14 +501,14 @@ a.plyr__control::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container
|
.plyr__menu__container
|
||||||
.plyr__control[role='menuitemradio'][aria-checked='true']::after {
|
.plyr__control[role="menuitemradio"][aria-checked="true"]::after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(-50%) scale(1);
|
transform: translateY(-50%) scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__menu__container
|
.plyr__menu__container
|
||||||
.plyr__control[role='menuitemradio'].plyr__tab-focus::before,
|
.plyr__control[role="menuitemradio"].plyr__tab-focus::before,
|
||||||
.plyr__menu__container .plyr__control[role='menuitemradio']:hover::before {
|
.plyr__menu__container .plyr__control[role="menuitemradio"]:hover::before {
|
||||||
background: rgba(35, 40, 47, 0.1);
|
background: rgba(35, 40, 47, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -524,7 +524,7 @@ a.plyr__control::before {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range'] {
|
.plyr--full-ui input[type="range"] {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
@ -547,7 +547,7 @@ a.plyr__control::before {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-webkit-slider-runnable-track {
|
.plyr--full-ui input[type="range"]::-webkit-slider-runnable-track {
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
|
|
@ -566,7 +566,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-webkit-slider-thumb {
|
.plyr--full-ui input[type="range"]::-webkit-slider-thumb {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
background: var(--plyr-range-thumb-background, #fff);
|
background: var(--plyr-range-thumb-background, #fff);
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
@ -596,7 +596,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-moz-range-track {
|
.plyr--full-ui input[type="range"]::-moz-range-track {
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
|
|
@ -608,7 +608,7 @@ a.plyr__control::before {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-moz-range-thumb {
|
.plyr--full-ui input[type="range"]::-moz-range-thumb {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
background: var(--plyr-range-thumb-background, #fff);
|
background: var(--plyr-range-thumb-background, #fff);
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
@ -628,7 +628,7 @@ a.plyr__control::before {
|
||||||
width: var(--plyr-range-thumb-height, 13px);
|
width: var(--plyr-range-thumb-height, 13px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-moz-range-progress {
|
.plyr--full-ui input[type="range"]::-moz-range-progress {
|
||||||
background: currentColor;
|
background: currentColor;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
border-radius: calc(var(--plyr-range-track-height, 5px) / 2);
|
border-radius: calc(var(--plyr-range-track-height, 5px) / 2);
|
||||||
|
|
@ -636,7 +636,7 @@ a.plyr__control::before {
|
||||||
height: var(--plyr-range-track-height, 5px);
|
height: var(--plyr-range-track-height, 5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-ms-track {
|
.plyr--full-ui input[type="range"]::-ms-track {
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
|
|
@ -650,7 +650,7 @@ a.plyr__control::before {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-ms-fill-upper {
|
.plyr--full-ui input[type="range"]::-ms-fill-upper {
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
|
|
@ -663,7 +663,7 @@ a.plyr__control::before {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-ms-fill-lower {
|
.plyr--full-ui input[type="range"]::-ms-fill-lower {
|
||||||
background: 0 0;
|
background: 0 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: calc(5px / 2);
|
border-radius: calc(5px / 2);
|
||||||
|
|
@ -677,7 +677,7 @@ a.plyr__control::before {
|
||||||
background: currentColor;
|
background: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-ms-thumb {
|
.plyr--full-ui input[type="range"]::-ms-thumb {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
background: var(--plyr-range-thumb-background, #fff);
|
background: var(--plyr-range-thumb-background, #fff);
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
@ -698,20 +698,20 @@ a.plyr__control::before {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-ms-tooltip {
|
.plyr--full-ui input[type="range"]::-ms-tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']:focus {
|
.plyr--full-ui input[type="range"]:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range']::-moz-focus-outer {
|
.plyr--full-ui input[type="range"]::-moz-focus-outer {
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui
|
.plyr--full-ui
|
||||||
input[type='range'].plyr__tab-focus::-webkit-slider-runnable-track {
|
input[type="range"].plyr__tab-focus::-webkit-slider-runnable-track {
|
||||||
outline-color: #00b3ff;
|
outline-color: #00b3ff;
|
||||||
outline-color: var(
|
outline-color: var(
|
||||||
--plyr-tab-focus-color,
|
--plyr-tab-focus-color,
|
||||||
|
|
@ -722,7 +722,7 @@ a.plyr__control::before {
|
||||||
outline-width: 3px;
|
outline-width: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range'].plyr__tab-focus::-moz-range-track {
|
.plyr--full-ui input[type="range"].plyr__tab-focus::-moz-range-track {
|
||||||
outline-color: #00b3ff;
|
outline-color: #00b3ff;
|
||||||
outline-color: var(
|
outline-color: var(
|
||||||
--plyr-tab-focus-color,
|
--plyr-tab-focus-color,
|
||||||
|
|
@ -733,7 +733,7 @@ a.plyr__control::before {
|
||||||
outline-width: 3px;
|
outline-width: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui input[type='range'].plyr__tab-focus::-ms-track {
|
.plyr--full-ui input[type="range"].plyr__tab-focus::-ms-track {
|
||||||
outline-color: #00b3ff;
|
outline-color: #00b3ff;
|
||||||
outline-color: var(
|
outline-color: var(
|
||||||
--plyr-tab-focus-color,
|
--plyr-tab-focus-color,
|
||||||
|
|
@ -769,7 +769,7 @@ a.plyr__control::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__time + .plyr__time::before {
|
.plyr__time + .plyr__time::before {
|
||||||
content: '\2044';
|
content: "\2044";
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-right: var(--plyr-control-spacing, 10px);
|
margin-right: var(--plyr-control-spacing, 10px);
|
||||||
}
|
}
|
||||||
|
|
@ -821,7 +821,7 @@ a.plyr__control::before {
|
||||||
var(--plyr-tooltip-background, rgba(255, 255, 255, 0.9));
|
var(--plyr-tooltip-background, rgba(255, 255, 255, 0.9));
|
||||||
bottom: calc(4px * -1);
|
bottom: calc(4px * -1);
|
||||||
bottom: calc(var(--plyr-tooltip-arrow-size, 4px) * -1);
|
bottom: calc(var(--plyr-tooltip-arrow-size, 4px) * -1);
|
||||||
content: '';
|
content: "";
|
||||||
height: 0;
|
height: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -906,7 +906,7 @@ a.plyr__control::before {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__progress input[type='range'],
|
.plyr__progress input[type="range"],
|
||||||
.plyr__progress__buffer {
|
.plyr__progress__buffer {
|
||||||
margin-left: calc(13px * -0.5);
|
margin-left: calc(13px * -0.5);
|
||||||
margin-left: calc(var(--plyr-range-thumb-height, 13px) * -0.5);
|
margin-left: calc(var(--plyr-range-thumb-height, 13px) * -0.5);
|
||||||
|
|
@ -916,7 +916,7 @@ a.plyr__control::before {
|
||||||
width: calc(100% + var(--plyr-range-thumb-height, 13px));
|
width: calc(100% + var(--plyr-range-thumb-height, 13px));
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__progress input[type='range'] {
|
.plyr__progress input[type="range"] {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
@ -1024,7 +1024,7 @@ a.plyr__control::before {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__volume input[type='range'] {
|
.plyr__volume input[type="range"] {
|
||||||
margin-left: calc(10px / 2);
|
margin-left: calc(10px / 2);
|
||||||
margin-left: calc(var(--plyr-control-spacing, 10px) / 2);
|
margin-left: calc(var(--plyr-control-spacing, 10px) / 2);
|
||||||
margin-right: calc(10px / 2);
|
margin-right: calc(10px / 2);
|
||||||
|
|
@ -1054,7 +1054,7 @@ a.plyr__control::before {
|
||||||
|
|
||||||
.plyr--audio .plyr__control.plyr__tab-focus,
|
.plyr--audio .plyr__control.plyr__tab-focus,
|
||||||
.plyr--audio .plyr__control:hover,
|
.plyr--audio .plyr__control:hover,
|
||||||
.plyr--audio .plyr__control[aria-expanded='true'] {
|
.plyr--audio .plyr__control[aria-expanded="true"] {
|
||||||
background: #00b3ff;
|
background: #00b3ff;
|
||||||
background: var(
|
background: var(
|
||||||
--plyr-audio-control-background-hover,
|
--plyr-audio-control-background-hover,
|
||||||
|
|
@ -1064,7 +1064,7 @@ a.plyr__control::before {
|
||||||
color: var(--plyr-audio-control-color-hover, #fff);
|
color: var(--plyr-audio-control-color-hover, #fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']::-webkit-slider-runnable-track {
|
.plyr--full-ui.plyr--audio input[type="range"]::-webkit-slider-runnable-track {
|
||||||
background-color: rgba(193, 200, 209, 0.6);
|
background-color: rgba(193, 200, 209, 0.6);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-audio-range-track-background,
|
--plyr-audio-range-track-background,
|
||||||
|
|
@ -1072,7 +1072,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']::-moz-range-track {
|
.plyr--full-ui.plyr--audio input[type="range"]::-moz-range-track {
|
||||||
background-color: rgba(193, 200, 209, 0.6);
|
background-color: rgba(193, 200, 209, 0.6);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-audio-range-track-background,
|
--plyr-audio-range-track-background,
|
||||||
|
|
@ -1080,7 +1080,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']::-ms-track {
|
.plyr--full-ui.plyr--audio input[type="range"]::-ms-track {
|
||||||
background-color: rgba(193, 200, 209, 0.6);
|
background-color: rgba(193, 200, 209, 0.6);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-audio-range-track-background,
|
--plyr-audio-range-track-background,
|
||||||
|
|
@ -1088,7 +1088,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']:active::-webkit-slider-thumb {
|
.plyr--full-ui.plyr--audio input[type="range"]:active::-webkit-slider-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(35, 40, 47, 0.1);
|
0 0 0 3px rgba(35, 40, 47, 0.1);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1100,7 +1100,7 @@ a.plyr__control::before {
|
||||||
var(--plyr-audio-range-thumb-active-shadow-color, rgba(35, 40, 47, 0.1));
|
var(--plyr-audio-range-thumb-active-shadow-color, rgba(35, 40, 47, 0.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']:active::-moz-range-thumb {
|
.plyr--full-ui.plyr--audio input[type="range"]:active::-moz-range-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(35, 40, 47, 0.1);
|
0 0 0 3px rgba(35, 40, 47, 0.1);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1112,7 +1112,7 @@ a.plyr__control::before {
|
||||||
var(--plyr-audio-range-thumb-active-shadow-color, rgba(35, 40, 47, 0.1));
|
var(--plyr-audio-range-thumb-active-shadow-color, rgba(35, 40, 47, 0.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--audio input[type='range']:active::-ms-thumb {
|
.plyr--full-ui.plyr--audio input[type="range"]:active::-ms-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(35, 40, 47, 0.1);
|
0 0 0 3px rgba(35, 40, 47, 0.1);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1207,7 +1207,7 @@ a.plyr__control::before {
|
||||||
|
|
||||||
.plyr--video .plyr__control.plyr__tab-focus,
|
.plyr--video .plyr__control.plyr__tab-focus,
|
||||||
.plyr--video .plyr__control:hover,
|
.plyr--video .plyr__control:hover,
|
||||||
.plyr--video .plyr__control[aria-expanded='true'] {
|
.plyr--video .plyr__control[aria-expanded="true"] {
|
||||||
background: #00b3ff;
|
background: #00b3ff;
|
||||||
background: var(
|
background: var(
|
||||||
--plyr-video-control-background-hover,
|
--plyr-video-control-background-hover,
|
||||||
|
|
@ -1258,7 +1258,7 @@ a.plyr__control::before {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']::-webkit-slider-runnable-track {
|
.plyr--full-ui.plyr--video input[type="range"]::-webkit-slider-runnable-track {
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-video-range-track-background,
|
--plyr-video-range-track-background,
|
||||||
|
|
@ -1266,7 +1266,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']::-moz-range-track {
|
.plyr--full-ui.plyr--video input[type="range"]::-moz-range-track {
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-video-range-track-background,
|
--plyr-video-range-track-background,
|
||||||
|
|
@ -1274,7 +1274,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']::-ms-track {
|
.plyr--full-ui.plyr--video input[type="range"]::-ms-track {
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
background-color: var(
|
background-color: var(
|
||||||
--plyr-video-range-track-background,
|
--plyr-video-range-track-background,
|
||||||
|
|
@ -1282,7 +1282,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']:active::-webkit-slider-thumb {
|
.plyr--full-ui.plyr--video input[type="range"]:active::-webkit-slider-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(255, 255, 255, 0.5);
|
0 0 0 3px rgba(255, 255, 255, 0.5);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1297,7 +1297,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']:active::-moz-range-thumb {
|
.plyr--full-ui.plyr--video input[type="range"]:active::-moz-range-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(255, 255, 255, 0.5);
|
0 0 0 3px rgba(255, 255, 255, 0.5);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1312,7 +1312,7 @@ a.plyr__control::before {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--full-ui.plyr--video input[type='range']:active::-ms-thumb {
|
.plyr--full-ui.plyr--video input[type="range"]:active::-ms-thumb {
|
||||||
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
box-shadow: 0 1px 1px rgba(35, 40, 47, 0.15), 0 0 0 1px rgba(35, 40, 47, 0.2),
|
||||||
0 0 0 3px rgba(255, 255, 255, 0.5);
|
0 0 0 3px rgba(255, 255, 255, 0.5);
|
||||||
box-shadow: var(
|
box-shadow: var(
|
||||||
|
|
@ -1713,7 +1713,7 @@ a.plyr__control::before {
|
||||||
var(--plyr-tooltip-background, rgba(255, 255, 255, 0.9));
|
var(--plyr-tooltip-background, rgba(255, 255, 255, 0.9));
|
||||||
bottom: calc(4px * -1);
|
bottom: calc(4px * -1);
|
||||||
bottom: calc(var(--plyr-tooltip-arrow-size, 4px) * -1);
|
bottom: calc(var(--plyr-tooltip-arrow-size, 4px) * -1);
|
||||||
content: '';
|
content: "";
|
||||||
height: 0;
|
height: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nyancat .vue-slider-dot-handle {
|
.nyancat .vue-slider-dot-handle {
|
||||||
background: url('/img/logos/nyancat.gif');
|
background: url("/img/logos/nyancat.gif");
|
||||||
background-size: 36px;
|
background-size: 36px;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
@ -100,11 +100,6 @@
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nyancat-stop .vue-slider-dot-handle {
|
|
||||||
background-image: url('/img/logos/nyancat-stop.png');
|
|
||||||
transition: 300ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* lyrics */
|
/* lyrics */
|
||||||
.lyrics-page .vue-slider-rail {
|
.lyrics-page .vue-slider-rail {
|
||||||
background-color: rgba(128, 128, 128, 0.18);
|
background-color: rgba(128, 128, 128, 0.18);
|
||||||
|
|
@ -126,19 +121,10 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-theme='dark'] .lyrics-page .vue-slider-process {
|
body[data-theme="dark"] .lyrics-page .vue-slider-process {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-theme='dark'] .lyrics-page .vue-slider-dot-handle {
|
body[data-theme="dark"] .lyrics-page .vue-slider-dot-handle {
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lyrics-page[data-theme='dark'] .vue-slider-rail {
|
|
||||||
background-color: rgba(255, 255, 255, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.lyrics-page[data-theme='dark'] .vue-slider-process,
|
|
||||||
.lyrics-page[data-theme='dark'] .vue-slider-dot-handle {
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 32 32" height="32px" id="Layer_1" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M14.77,23.795L5.185,14.21c-0.879-0.879-0.879-2.317,0-3.195l0.8-0.801c0.877-0.878,2.316-0.878,3.194,0 l7.315,7.315l7.316-7.315c0.878-0.878,2.317-0.878,3.194,0l0.8,0.801c0.879,0.878,0.879,2.316,0,3.195l-9.587,9.585 c-0.471,0.472-1.104,0.682-1.723,0.647C15.875,24.477,15.243,24.267,14.77,23.795z" fill="currentColor"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 666 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="arrow-up" class="svg-inline--fa fa-arrow-up fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 487 B |
|
|
@ -1 +0,0 @@
|
||||||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 32 32" height="32px" id="Layer_1" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M18.221,7.206l9.585,9.585c0.879,0.879,0.879,2.317,0,3.195l-0.8,0.801c-0.877,0.878-2.316,0.878-3.194,0 l-7.315-7.315l-7.315,7.315c-0.878,0.878-2.317,0.878-3.194,0l-0.8-0.801c-0.879-0.878-0.879-2.316,0-3.195l9.587-9.585 c0.471-0.472,1.103-0.682,1.723-0.647C17.115,6.524,17.748,6.734,18.221,7.206z" fill="currentColor"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 668 B |
1
src/assets/icons/circle.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="circle" class="svg-inline--fa fa-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 301 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="caret-down" class="svg-inline--fa fa-caret-down fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 359 B |
1
src/assets/icons/expand.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="expand-alt" class="svg-inline--fa fa-expand-alt fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M212.686 315.314L120 408l32.922 31.029c15.12 15.12 4.412 40.971-16.97 40.971h-112C10.697 480 0 469.255 0 456V344c0-21.382 25.803-32.09 40.922-16.971L72 360l92.686-92.686c6.248-6.248 16.379-6.248 22.627 0l25.373 25.373c6.249 6.248 6.249 16.378 0 22.627zm22.628-118.628L328 104l-32.922-31.029C279.958 57.851 290.666 32 312.048 32h112C437.303 32 448 42.745 448 56v112c0 21.382-25.803 32.09-40.922 16.971L376 152l-92.686 92.686c-6.248 6.248-16.379 6.248-22.627 0l-25.373-25.373c-6.249-6.248-6.249-16.378 0-22.627z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 749 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="radio-alt" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-radio-alt fa-w-16 fa-7x"><path fill="currentColor" d="M209 368h-64a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-16a16 16 0 0 0-16-16zm144 56a72 72 0 1 0-72-72 72.09 72.09 0 0 0 72 72zm96-296H212.5l288.83-81.21a16 16 0 0 0 11.07-19.74l-4.33-15.38A16 16 0 0 0 488.33.6L47.68 124.5A64 64 0 0 0 1 186.11V448a64 64 0 0 0 64 64h384a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm16 320a16 16 0 0 1-16 16H65a16 16 0 0 1-16-16V256h416zM113 336h128a16 16 0 0 0 16-16v-16a16 16 0 0 0-16-16H113a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16z" class=""></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 733 B |
|
|
@ -1,3 +0,0 @@
|
||||||
<svg width="14" height="14" viewBox="0 0 14 14" data-darkreader-inline-fill="" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path id="path" d="M1 11L3 11L3 13C3 13.55 3.45 14 4 14C4.55 14 5 13.55 5 13L5 10C5 9.45 4.55 9 4 9L1 9C0.45 9 0 9.45 0 10C0 10.55 0.45 11 1 11ZM11 3L11 1C11 0.45 10.55 0 10 0C9.45 0 9 0.45 9 1L9 4C9 4.54 9.45 5 10 5L13 5C13.55 5 14 4.54 14 4C14 3.45 13.55 3 13 3L11 3Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 396 B |
|
|
@ -1,3 +0,0 @@
|
||||||
<svg width="14" height="14" viewBox="0 0 14 14" data-darkreader-inline-fill="" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path id="path" d="M1 9C0.45 9 0 9.45 0 10L0 13C0 13.55 0.45 14 1 14L4 14C4.55 14 5 13.55 5 13C5 12.45 4.55 12 4 12L2 12L2 10C2 9.45 1.55 9 1 9ZM9 1C9 1.54 9.45 2 10 2L12 2L12 4C12 4.54 12.45 5 13 5C13.55 5 14 4.54 14 4L14 1C14 0.45 13.55 0 13 0L10 0C9.45 0 9 0.45 9 1Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 396 B |
|
|
@ -1,7 +1,8 @@
|
||||||
import Vue from 'vue';
|
import Vue from "vue";
|
||||||
import SvgIcon from '@/components/SvgIcon';
|
import SvgIcon from "@/components/SvgIcon";
|
||||||
|
|
||||||
Vue.component('svg-icon', SvgIcon);
|
Vue.component("svg-icon", SvgIcon);
|
||||||
const requireAll = requireContext => requireContext.keys().map(requireContext);
|
const requireAll = (requireContext) =>
|
||||||
const req = require.context('./', true, /\.svg$/);
|
requireContext.keys().map(requireContext);
|
||||||
|
const req = require.context("./", true, /\.svg$/);
|
||||||
requireAll(req);
|
requireAll(req);
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sign-in-alt" class="svg-inline--fa fa-sign-in-alt fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M416 448h-84c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h84c17.7 0 32-14.3 32-32V160c0-17.7-14.3-32-32-32h-84c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h84c53 0 96 43 96 96v192c0 53-43 96-96 96zm-47-201L201 79c-15-15-41-4.5-41 17v96H24c-13.3 0-24 10.7-24 24v96c0 13.3 10.7 24 24 24h136v96c0 21.5 26 32 41 17l168-168c9.3-9.4 9.3-24.6 0-34z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 579 B |
|
|
@ -1 +0,0 @@
|
||||||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="512px" id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M417.4,224H288V94.6c0-16.9-14.3-30.6-32-30.6c-17.7,0-32,13.7-32,30.6V224H94.6C77.7,224,64,238.3,64,256 c0,17.7,13.7,32,30.6,32H224v129.4c0,16.9,14.3,30.6,32,30.6c17.7,0,32-13.7,32-30.6V288h129.4c16.9,0,30.6-14.3,30.6-32 C448,238.3,434.3,224,417.4,224z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 618 B |
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sort-amount-up" class="svg-inline--fa fa-sort-amount-up fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M304 416h-64a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h48v304a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V160h48c14.21 0 21.38-17.24 11.31-27.31l-80-96a16 16 0 0 0-22.62 0l-80 96C-5.35 142.74 1.77 160 16 160zm416 0H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h192a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm-64 128H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM496 32H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h256a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 784 B |
|
|
@ -1 +0,0 @@
|
||||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="thumbs-down" class="svg-inline--fa fa-thumbs-down fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M0 56v240c0 13.255 10.745 24 24 24h80c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H24C10.745 32 0 42.745 0 56zm40 200c0-13.255 10.745-24 24-24s24 10.745 24 24-10.745 24-24 24-24-10.745-24-24zm272 256c-20.183 0-29.485-39.293-33.931-57.795-5.206-21.666-10.589-44.07-25.393-58.902-32.469-32.524-49.503-73.967-89.117-113.111a11.98 11.98 0 0 1-3.558-8.521V59.901c0-6.541 5.243-11.878 11.783-11.998 15.831-.29 36.694-9.079 52.651-16.178C256.189 17.598 295.709.017 343.995 0h2.844c42.777 0 93.363.413 113.774 29.737 8.392 12.057 10.446 27.034 6.148 44.632 16.312 17.053 25.063 48.863 16.382 74.757 17.544 23.432 19.143 56.132 9.308 79.469l.11.11c11.893 11.949 19.523 31.259 19.439 49.197-.156 30.352-26.157 58.098-59.553 58.098H350.723C358.03 364.34 384 388.132 384 430.548 384 504 336 512 312 512z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1 KiB |
3
src/assets/icons/translation.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg fill="currentColor" viewBox="0 0 1024 500">
|
||||||
|
<path d="M152.1 236.2c-3.5-12.1-7.8-33.2-7.8-33.2h-.5s-4.3 21.1-7.8 33.2l-11.1 37.5H163zM616 96H336v320h280c13.3 0 24-10.7 24-24V120c0-13.3-10.7-24-24-24zm-24 120c0 6.6-5.4 12-12 12h-11.4c-6.9 23.6-21.7 47.4-42.7 69.9 8.4 6.4 17.1 12.5 26.1 18 5.5 3.4 7.3 10.5 4.1 16.2l-7.9 13.9c-3.4 5.9-10.9 7.8-16.7 4.3-12.6-7.8-24.5-16.1-35.4-24.9-10.9 8.7-22.7 17.1-35.4 24.9-5.8 3.5-13.3 1.6-16.7-4.3l-7.9-13.9c-3.2-5.6-1.4-12.8 4.2-16.2 9.3-5.7 18-11.7 26.1-18-7.9-8.4-14.9-17-21-25.7-4-5.7-2.2-13.6 3.7-17.1l6.5-3.9 7.3-4.3c5.4-3.2 12.4-1.7 16 3.4 5 7 10.8 14 17.4 20.9 13.5-14.2 23.8-28.9 30-43.2H412c-6.6 0-12-5.4-12-12v-16c0-6.6 5.4-12 12-12h64v-16c0-6.6 5.4-12 12-12h16c6.6 0 12 5.4 12 12v16h64c6.6 0 12 5.4 12 12zM0 120v272c0 13.3 10.7 24 24 24h280V96H24c-13.3 0-24 10.7-24 24zm58.9 216.1L116.4 167c1.7-4.9 6.2-8.1 11.4-8.1h32.5c5.1 0 9.7 3.3 11.4 8.1l57.5 169.1c2.6 7.8-3.1 15.9-11.4 15.9h-22.9a12 12 0 0 1-11.5-8.6l-9.4-31.9h-60.2l-9.1 31.8c-1.5 5.1-6.2 8.7-11.5 8.7H70.3c-8.2 0-14-8.1-11.4-15.9z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |