mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Fri Nov 1 19:37:39 CET 2024
This commit is contained in:
4
yesplaymusic/.envrc
Normal file
4
yesplaymusic/.envrc
Normal file
@@ -0,0 +1,4 @@
|
||||
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
|
||||
|
||||
export NIXPKGS_ALLOW_INSECURE=1
|
||||
use devenv
|
9
yesplaymusic/.gitignore
vendored
9
yesplaymusic/.gitignore
vendored
@@ -32,3 +32,12 @@ NeteaseCloudMusicApi-master.zip
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
vercel.json
|
||||
# Devenv
|
||||
.devenv*
|
||||
devenv.local.nix
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
|
@@ -125,6 +125,16 @@ yarn run build
|
||||
|
||||
7. 将 `/dist` 目录下的文件上传到你的 Web 服务器
|
||||
|
||||
## ⚙️ 宝塔面板 docker应用商店 部署
|
||||
|
||||
1. 安装宝塔面板,前往[宝塔面板官网](https://www.bt.cn/new/download.html) ,选择正式版的脚本下载安装。
|
||||
|
||||
2. 安装后登录宝塔面板,在左侧导航栏中点击 Docker,首次进入会提示安装Docker服务,点击立即安装,按提示完成安装
|
||||
|
||||
3. 安装完成后在应用商店中找到YesPlayMusic,点击安装,配置域名、端口等基本信息即可完成安装。
|
||||
|
||||
4. 安装后在浏览器输入上一步骤设置的域名即可访问。
|
||||
|
||||
## ⚙️ Docker 部署
|
||||
|
||||
1. 构建 Docker Image
|
||||
|
132
yesplaymusic/devenv.lock
Normal file
132
yesplaymusic/devenv.lock
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"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
yesplaymusic/devenv.nix
Normal file
53
yesplaymusic/devenv.nix
Normal file
@@ -0,0 +1,53 @@
|
||||
{ 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
yesplaymusic/devenv.yaml
Normal file
19
yesplaymusic/devenv.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
# 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
|
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@unblockneteasemusic/rust-napi": "^0.4.0",
|
||||
"NeteaseCloudMusicApi": "^4.8.7",
|
||||
"NeteaseCloudMusicApi": "^4.23.3",
|
||||
"axios": "^0.26.1",
|
||||
"change-case": "^4.1.2",
|
||||
"cli-color": "^2.0.0",
|
||||
|
@@ -42,7 +42,9 @@
|
||||
:exclude="$parent.albumObject.artist.name"
|
||||
prefix="-"
|
||||
/></span>
|
||||
<span v-if="isAlbum && (track.mark & 1048576) === 1048576" class="explicit-symbol"
|
||||
<span
|
||||
v-if="isAlbum && (track.mark & 1048576) === 1048576"
|
||||
class="explicit-symbol"
|
||||
><ExplicitSymbol
|
||||
/></span>
|
||||
</div>
|
||||
|
@@ -240,7 +240,7 @@ export function initIpcMain(win, store, trayEventEmitter) {
|
||||
details: track.name + ' - ' + track.ar.map(ar => ar.name).join(','),
|
||||
state: track.al.name,
|
||||
endTimestamp: Date.now() + track.dt,
|
||||
largeImageKey: 'logo',
|
||||
largeImageKey: track.al.picUrl,
|
||||
largeImageText: 'Listening ' + track.name,
|
||||
smallImageKey: 'play',
|
||||
smallImageText: 'Playing',
|
||||
@@ -252,7 +252,7 @@ export function initIpcMain(win, store, trayEventEmitter) {
|
||||
client.updatePresence({
|
||||
details: track.name + ' - ' + track.ar.map(ar => ar.name).join(','),
|
||||
state: track.al.name,
|
||||
largeImageKey: 'logo',
|
||||
largeImageKey: track.al.picUrl,
|
||||
largeImageText: 'YesPlayMusic',
|
||||
smallImageKey: 'pause',
|
||||
smallImageText: 'Pause',
|
||||
|
@@ -244,6 +244,8 @@ export default {
|
||||
minePlaylists: 'My Playlists',
|
||||
likedPlaylists: 'Liked Playlists',
|
||||
cardiacMode: 'Cardiac Mode',
|
||||
copyLyric: 'Copy Lyric',
|
||||
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: 'Saved to playlist',
|
||||
|
@@ -230,6 +230,8 @@ export default {
|
||||
minePlaylists: 'My Playlists',
|
||||
likedPlaylists: 'Liked Playlists',
|
||||
cardiacMode: 'Cardiac Mode',
|
||||
copyLyric: 'Copy Lyric',
|
||||
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||
},
|
||||
toast: {
|
||||
savedToMyLikedSongs: 'Beğendiğim Müziklere Kaydet',
|
||||
|
@@ -243,6 +243,8 @@ export default {
|
||||
minePlaylists: '创建的歌单',
|
||||
likedPlaylists: '收藏的歌单',
|
||||
cardiacMode: '心动模式',
|
||||
copyLyric: '复制歌词',
|
||||
copyLyricWithTranslation: '复制歌词(含翻译)',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: '已添加到歌单',
|
||||
|
@@ -240,6 +240,8 @@ export default {
|
||||
minePlaylists: '我建立的歌單',
|
||||
likedPlaylists: '收藏的歌單',
|
||||
cardiacMode: '心動模式',
|
||||
copyLyric: '複製歌詞',
|
||||
copyLyricWithTranslation: '複製歌詞(含翻譯)',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: '已新增至歌單',
|
||||
|
@@ -36,6 +36,8 @@ let localStorage = {
|
||||
server: '',
|
||||
port: null,
|
||||
},
|
||||
enableRealIP: false,
|
||||
realIP: null,
|
||||
shortcuts: shortcuts,
|
||||
},
|
||||
data: {
|
||||
|
@@ -84,3 +84,30 @@ function trimContent(content) {
|
||||
let t = content.trim();
|
||||
return t.length < 1 ? content : t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} lyric
|
||||
*/
|
||||
export async function copyLyric(lyric) {
|
||||
const textToCopy = lyric;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(textToCopy);
|
||||
} catch (err) {
|
||||
alert('复制失败,请手动复制!');
|
||||
}
|
||||
} else {
|
||||
const tempInput = document.createElement('textarea');
|
||||
tempInput.value = textToCopy;
|
||||
tempInput.style.position = 'absolute';
|
||||
tempInput.style.left = '-9999px';
|
||||
document.body.appendChild(tempInput);
|
||||
tempInput.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
} catch (err) {
|
||||
alert('复制失败,请手动复制!');
|
||||
}
|
||||
document.body.removeChild(tempInput);
|
||||
}
|
||||
}
|
||||
|
@@ -38,8 +38,15 @@ service.interceptors.request.use(function (config) {
|
||||
config.params.realIP = '211.161.244.70';
|
||||
}
|
||||
|
||||
// Force real_ip
|
||||
const enableRealIP = JSON.parse(
|
||||
localStorage.getItem('settings')
|
||||
).enableRealIP;
|
||||
const realIP = JSON.parse(localStorage.getItem('settings')).realIP;
|
||||
if (process.env.VUE_APP_REAL_IP) {
|
||||
config.params.realIP = process.env.VUE_APP_REAL_IP;
|
||||
} else if (enableRealIP) {
|
||||
config.params.realIP = realIP;
|
||||
}
|
||||
|
||||
const proxy = JSON.parse(localStorage.getItem('settings')).proxyConfig;
|
||||
|
@@ -28,7 +28,9 @@
|
||||
<span v-else>Compilation by Various Artists</span>
|
||||
</div>
|
||||
<div class="date-and-count">
|
||||
<span v-if="(album.mark & 1048576) === 1048576" class="explicit-symbol"
|
||||
<span
|
||||
v-if="(album.mark & 1048576) === 1048576"
|
||||
class="explicit-symbol"
|
||||
><ExplicitSymbol
|
||||
/></span>
|
||||
<span :title="album.publishTime | formatDate">{{
|
||||
|
@@ -248,7 +248,11 @@
|
||||
@dblclick="clickLyricLine(line.time, true)"
|
||||
>
|
||||
<div class="content">
|
||||
<span v-if="line.contents[0]">{{ line.contents[0] }}</span>
|
||||
<span
|
||||
v-if="line.contents[0]"
|
||||
@click.right="openLyricMenu($event, line, 0)"
|
||||
>{{ line.contents[0] }}</span
|
||||
>
|
||||
<br />
|
||||
<span
|
||||
v-if="
|
||||
@@ -256,10 +260,26 @@
|
||||
$store.state.settings.showLyricsTranslation
|
||||
"
|
||||
class="translation"
|
||||
@click.right="openLyricMenu($event, line, 1)"
|
||||
>{{ line.contents[1] }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<ContextMenu v-if="!noLyric" ref="lyricMenu">
|
||||
<div class="item" @click="copyLyric(false)">{{
|
||||
$t('contextMenu.copyLyric')
|
||||
}}</div>
|
||||
<div
|
||||
v-if="
|
||||
rightClickLyric &&
|
||||
rightClickLyric.contents[1] &&
|
||||
$store.state.settings.showLyricsTranslation
|
||||
"
|
||||
class="item"
|
||||
@click="copyLyric(true)"
|
||||
>{{ $t('contextMenu.copyLyricWithTranslation') }}</div
|
||||
>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
@@ -284,9 +304,10 @@
|
||||
|
||||
import { mapState, mapMutations, mapActions } from 'vuex';
|
||||
import VueSlider from 'vue-slider-component';
|
||||
import ContextMenu from '@/components/ContextMenu.vue';
|
||||
import { formatTrackTime } from '@/utils/common';
|
||||
import { getLyric } from '@/api/track';
|
||||
import { lyricParser } from '@/utils/lyrics';
|
||||
import { lyricParser, copyLyric } from '@/utils/lyrics';
|
||||
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||
import * as Vibrant from 'node-vibrant/dist/vibrant.worker.min.js';
|
||||
import Color from 'color';
|
||||
@@ -299,6 +320,7 @@ export default {
|
||||
components: {
|
||||
VueSlider,
|
||||
ButtonIcon,
|
||||
ContextMenu,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -312,6 +334,7 @@ export default {
|
||||
background: '',
|
||||
date: this.formatTime(new Date()),
|
||||
isFullscreen: !!document.fullscreenElement,
|
||||
rightClickLyric: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -587,6 +610,21 @@ export default {
|
||||
this.player.play();
|
||||
}
|
||||
},
|
||||
openLyricMenu(e, lyric, idx) {
|
||||
this.rightClickLyric = { ...lyric, idx };
|
||||
this.$refs.lyricMenu.openMenu(e);
|
||||
e.preventDefault();
|
||||
},
|
||||
copyLyric(withTranslation) {
|
||||
if (this.rightClickLyric) {
|
||||
const idx = this.rightClickLyric.idx;
|
||||
if (!withTranslation) {
|
||||
copyLyric(this.rightClickLyric.contents[idx]);
|
||||
} else {
|
||||
copyLyric(this.rightClickLyric.contents.join(' '));
|
||||
}
|
||||
}
|
||||
},
|
||||
setLyricsInterval() {
|
||||
this.lyricsInterval = setInterval(() => {
|
||||
const progress = this.player.seek(null, false) ?? 0;
|
||||
@@ -926,6 +964,7 @@ export default {
|
||||
transform-origin: center left;
|
||||
transform: scale(0.95);
|
||||
transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
user-select: none;
|
||||
|
||||
span {
|
||||
opacity: 0.28;
|
||||
|
@@ -641,6 +641,33 @@
|
||||
<button @click="sendProxyConfig">更新代理</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isElectron">
|
||||
<h3>Real IP</h3>
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div class="title"> Real IP </div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="toggle">
|
||||
<input
|
||||
id="enable-real-ip"
|
||||
v-model="enableRealIP"
|
||||
type="checkbox"
|
||||
name="enable-real-ip"
|
||||
/>
|
||||
<label for="enable-real-ip"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="real-ip" :class="{ disabled: !enableRealIP }">
|
||||
<input
|
||||
v-model="realIP"
|
||||
class="text-input"
|
||||
placeholder="IP地址"
|
||||
:disabled="!enableRealIP"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isElectron">
|
||||
<h3>快捷键</h3>
|
||||
@@ -1124,6 +1151,28 @@ export default {
|
||||
});
|
||||
},
|
||||
},
|
||||
enableRealIP: {
|
||||
get() {
|
||||
return this.settings.enableRealIP || false;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('updateSettings', {
|
||||
key: 'enableRealIP',
|
||||
value: value,
|
||||
});
|
||||
},
|
||||
},
|
||||
realIP: {
|
||||
get() {
|
||||
return this.settings.realIP || '';
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('updateSettings', {
|
||||
key: 'realIP',
|
||||
value: value,
|
||||
});
|
||||
},
|
||||
},
|
||||
proxyPort: {
|
||||
get() {
|
||||
return this.settings.proxyConfig?.port || '';
|
||||
@@ -1566,11 +1615,13 @@ input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#proxy-form {
|
||||
#proxy-form,
|
||||
#real-ip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#proxy-form.disabled {
|
||||
#proxy-form.disabled,
|
||||
#real-ip.disabled {
|
||||
opacity: 0.47;
|
||||
button:hover {
|
||||
transform: unset;
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user