mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 21:28:06 +00:00
refactor: library page
This commit is contained in:
parent
b537081f2a
commit
603e39f362
10 changed files with 474 additions and 462 deletions
72
src/App.vue
72
src/App.vue
|
|
@ -20,18 +20,18 @@
|
||||||
</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 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";
|
import { mapState } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: 'App',
|
||||||
components: {
|
components: {
|
||||||
Navbar,
|
Navbar,
|
||||||
Player,
|
Player,
|
||||||
|
|
@ -46,50 +46,60 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["showLyrics", "showLibraryDefault", "player"]),
|
...mapState(['showLyrics', 'showLibraryDefault', 'player']),
|
||||||
isAccountLoggedIn() {
|
isAccountLoggedIn() {
|
||||||
return isAccountLoggedIn();
|
return isAccountLoggedIn();
|
||||||
},
|
},
|
||||||
showPlayer() {
|
showPlayer() {
|
||||||
return (
|
return (
|
||||||
[
|
[
|
||||||
"mv",
|
'mv',
|
||||||
"loginUsername",
|
'loginUsername',
|
||||||
"login",
|
'login',
|
||||||
"loginAccount",
|
'loginAccount',
|
||||||
"lastfmCallback",
|
'lastfmCallback',
|
||||||
].includes(this.$route.name) === false
|
].includes(this.$route.name) === false
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
enablePlayer() {
|
enablePlayer() {
|
||||||
return this.player.enabled && this.$route.name !== "lastfmCallback";
|
return this.player.enabled && this.$route.name !== 'lastfmCallback';
|
||||||
},
|
},
|
||||||
showNavbar() {
|
showNavbar() {
|
||||||
return this.$route.name !== "lastfmCallback";
|
return this.$route.name !== 'lastfmCallback';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.showLibraryDefault && this.$router.push("/library");
|
this.showLibraryDefault && this.$router.push('/library');
|
||||||
if (this.isElectron) {
|
if (this.isElectron) ipcRenderer(this);
|
||||||
ipcRenderer(this);
|
window.addEventListener('keydown', this.handleKeydown);
|
||||||
}
|
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.play();
|
this.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');
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</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");
|
@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 {
|
:root {
|
||||||
--color-body-bg: #ffffff;
|
--color-body-bg: #ffffff;
|
||||||
|
|
@ -103,7 +113,7 @@ export default {
|
||||||
--color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
|
--color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] {
|
[data-theme='dark'] {
|
||||||
--color-body-bg: #222222;
|
--color-body-bg: #222222;
|
||||||
--color-text: #ffffff;
|
--color-text: #ffffff;
|
||||||
--color-primary: #335eea;
|
--color-primary: #335eea;
|
||||||
|
|
@ -121,7 +131,7 @@ export default {
|
||||||
}
|
}
|
||||||
#app,
|
#app,
|
||||||
input {
|
input {
|
||||||
font-family: "Barlow", -apple-system, BlinkMacSystemFont, Helvetica Neue,
|
font-family: 'Barlow', -apple-system, BlinkMacSystemFont, Helvetica Neue,
|
||||||
PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC,
|
PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC,
|
||||||
WenQuanYi Micro Hei, sans-serif;
|
WenQuanYi Micro Hei, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +205,7 @@ main::-webkit-scrollbar {
|
||||||
background: rgba(128, 128, 128, 0.38);
|
background: rgba(128, 128, 128, 0.38);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] ::-webkit-scrollbar-thumb {
|
[data-theme='dark'] ::-webkit-scrollbar-thumb {
|
||||||
background: var(--color-secondary-bg);
|
background: var(--color-secondary-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,7 +217,7 @@ main::-webkit-scrollbar {
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-electron="yes"] {
|
[data-electron='yes'] {
|
||||||
button,
|
button,
|
||||||
.navigation-links a,
|
.navigation-links a,
|
||||||
.playlist-info .description {
|
.playlist-info .description {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import request from "@/utils/request";
|
import request from '@/utils/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户详情
|
* 获取用户详情
|
||||||
|
|
@ -8,10 +8,11 @@ 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(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +23,8 @@ export function userDetail(uid) {
|
||||||
*/
|
*/
|
||||||
export function userAccount() {
|
export function userAccount() {
|
||||||
return request({
|
return request({
|
||||||
url: "/user/account",
|
url: '/user/account',
|
||||||
method: "get",
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
|
|
@ -43,8 +44,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,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -57,8 +58,8 @@ export function userPlaylist(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(),
|
||||||
|
|
@ -74,8 +75,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(),
|
||||||
|
|
@ -94,8 +95,8 @@ export function dailySignin(type = 0) {
|
||||||
*/
|
*/
|
||||||
export function likedAlbums() {
|
export function likedAlbums() {
|
||||||
return request({
|
return request({
|
||||||
url: "/album/sublist",
|
url: '/album/sublist',
|
||||||
method: "get",
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
|
|
@ -108,8 +109,8 @@ export function likedAlbums() {
|
||||||
*/
|
*/
|
||||||
export function likedArtists() {
|
export function likedArtists() {
|
||||||
return request({
|
return request({
|
||||||
url: "/artist/sublist",
|
url: '/artist/sublist',
|
||||||
method: "get",
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
|
|
@ -122,8 +123,8 @@ export function likedArtists() {
|
||||||
*/
|
*/
|
||||||
export function likedMVs() {
|
export function likedMVs() {
|
||||||
return request({
|
return request({
|
||||||
url: "/mv/sublist",
|
url: '/mv/sublist',
|
||||||
method: "get",
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@
|
||||||
<vue-slider
|
<vue-slider
|
||||||
v-model="player.progress"
|
v-model="player.progress"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="player.currentTrackDuration"
|
:max="player.currentTrackDuration + 1"
|
||||||
:interval="1"
|
:interval="1"
|
||||||
:drag-on-click="true"
|
:drag-on-click="true"
|
||||||
:duration="0"
|
:duration="0"
|
||||||
:dot-size="12"
|
:dot-size="12"
|
||||||
:height="2"
|
:height="2"
|
||||||
:tooltip-formatter="formatTrackTime"
|
:tooltip-formatter="formatTrackTime"
|
||||||
@drag-end="player.seek"
|
:lazy="true"
|
||||||
></vue-slider>
|
></vue-slider>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
|
@ -167,20 +167,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapMutations, mapActions } from "vuex";
|
import { mapState, mapMutations, mapActions } from 'vuex';
|
||||||
import "@/assets/css/slider.css";
|
import '@/assets/css/slider.css';
|
||||||
|
|
||||||
import ButtonIcon from "@/components/ButtonIcon.vue";
|
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||||
import VueSlider from "vue-slider-component";
|
import VueSlider from 'vue-slider-component';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Player",
|
name: 'Player',
|
||||||
components: {
|
components: {
|
||||||
ButtonIcon,
|
ButtonIcon,
|
||||||
VueSlider,
|
VueSlider,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["player", "settings", "data"]),
|
...mapState(['player', 'settings', 'data']),
|
||||||
currentTrack() {
|
currentTrack() {
|
||||||
return this.player.currentTrack;
|
return this.player.currentTrack;
|
||||||
},
|
},
|
||||||
|
|
@ -196,47 +196,47 @@ export default {
|
||||||
return this.player.playing;
|
return this.player.playing;
|
||||||
},
|
},
|
||||||
audioSource() {
|
audioSource() {
|
||||||
return this.player._howler?._src.includes("kuwo.cn")
|
return this.player._howler?._src.includes('kuwo.cn')
|
||||||
? "音源来自酷我音乐"
|
? '音源来自酷我音乐'
|
||||||
: "";
|
: '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(["toggleLyrics"]),
|
...mapMutations(['toggleLyrics']),
|
||||||
...mapActions(["showToast", "likeASong"]),
|
...mapActions(['showToast', 'likeASong']),
|
||||||
goToNextTracksPage() {
|
goToNextTracksPage() {
|
||||||
if (this.player.isPersonalFM) return;
|
if (this.player.isPersonalFM) return;
|
||||||
this.$route.name === "next"
|
this.$route.name === 'next'
|
||||||
? this.$router.go(-1)
|
? this.$router.go(-1)
|
||||||
: this.$router.push({ name: "next" });
|
: this.$router.push({ name: 'next' });
|
||||||
},
|
},
|
||||||
formatTrackTime(value) {
|
formatTrackTime(value) {
|
||||||
if (!value) return "";
|
if (!value) return '';
|
||||||
let min = ~~((value / 60) % 60);
|
let min = ~~((value / 60) % 60);
|
||||||
let sec = (~~(value % 60)).toString().padStart(2, "0");
|
let sec = (~~(value % 60)).toString().padStart(2, '0');
|
||||||
return `${min}:${sec}`;
|
return `${min}:${sec}`;
|
||||||
},
|
},
|
||||||
goToList() {
|
goToList() {
|
||||||
if (this.player.playlistSource.id === this.data.likedSongPlaylistID) {
|
if (this.player.playlistSource.id === this.data.likedSongPlaylistID) {
|
||||||
this.$router.push({ path: "/library/liked-songs" });
|
this.$router.push({ path: '/library/liked-songs' });
|
||||||
} else if (this.player.playlistSource.type === "url") {
|
} else if (this.player.playlistSource.type === 'url') {
|
||||||
this.$router.push({ path: this.player.playlistSource.id });
|
this.$router.push({ path: this.player.playlistSource.id });
|
||||||
} else {
|
} else {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path:
|
path:
|
||||||
"/" +
|
'/' +
|
||||||
this.player.playlistSource.type +
|
this.player.playlistSource.type +
|
||||||
"/" +
|
'/' +
|
||||||
this.player.playlistSource.id,
|
this.player.playlistSource.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goToAlbum() {
|
goToAlbum() {
|
||||||
if (this.player.currentTrack.al.id === 0) return;
|
if (this.player.currentTrack.al.id === 0) return;
|
||||||
this.$router.push({ path: "/album/" + this.player.currentTrack.al.id });
|
this.$router.push({ path: '/album/' + this.player.currentTrack.al.id });
|
||||||
},
|
},
|
||||||
goToArtist(id) {
|
goToArtist(id) {
|
||||||
this.$router.push({ path: "/artist/" + id });
|
this.$router.push({ path: '/artist/' + id });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="item" @click="play">{{ $t("contextMenu.play") }}</div>
|
<div class="item" @click="play">{{ $t('contextMenu.play') }}</div>
|
||||||
<div class="item" @click="playNext">{{ $t("contextMenu.playNext") }}</div>
|
<div class="item" @click="playNext">{{ $t('contextMenu.playNext') }}</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="item" @click="like" v-show="!isRightClickedTrackLiked">
|
<div class="item" @click="like" v-show="!isRightClickedTrackLiked">
|
||||||
{{ $t("contextMenu.saveToMyLikedSongs") }}
|
{{ $t('contextMenu.saveToMyLikedSongs') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="item" @click="like" v-show="isRightClickedTrackLiked">
|
<div class="item" @click="like" v-show="isRightClickedTrackLiked">
|
||||||
{{ $t("contextMenu.removeFromMyLikedSongs") }}
|
{{ $t('contextMenu.removeFromMyLikedSongs') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="extraContextMenuItem.includes('removeTrackFromPlaylist')"
|
v-if="extraContextMenuItem.includes('removeTrackFromPlaylist')"
|
||||||
|
|
@ -40,16 +40,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapActions, mapMutations, mapState } from "vuex";
|
import { mapActions, mapMutations, mapState } from 'vuex';
|
||||||
import { likeATrack } from "@/api/track";
|
import { likeATrack } from '@/api/track';
|
||||||
import { addOrRemoveTrackFromPlaylist } from "@/api/playlist";
|
import { addOrRemoveTrackFromPlaylist } from '@/api/playlist';
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
import { isAccountLoggedIn } from '@/utils/auth';
|
||||||
|
|
||||||
import TrackListItem from "@/components/TrackListItem.vue";
|
import TrackListItem from '@/components/TrackListItem.vue';
|
||||||
import ContextMenu from "@/components/ContextMenu.vue";
|
import ContextMenu from '@/components/ContextMenu.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TrackList",
|
name: 'TrackList',
|
||||||
components: {
|
components: {
|
||||||
TrackListItem,
|
TrackListItem,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
|
@ -60,14 +60,14 @@ export default {
|
||||||
id: Number,
|
id: Number,
|
||||||
dbclickTrackFunc: {
|
dbclickTrackFunc: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "default",
|
default: 'default',
|
||||||
},
|
},
|
||||||
albumObject: {
|
albumObject: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {
|
default: () => {
|
||||||
return {
|
return {
|
||||||
artist: {
|
artist: {
|
||||||
name: "",
|
name: '',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -88,38 +88,38 @@ export default {
|
||||||
},
|
},
|
||||||
itemKey: {
|
itemKey: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "id",
|
default: 'id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
rightClickedTrack: {
|
rightClickedTrack: {
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: '',
|
||||||
ar: [{ name: "" }],
|
ar: [{ name: '' }],
|
||||||
al: { picUrl: "" },
|
al: { picUrl: '' },
|
||||||
},
|
},
|
||||||
listStyles: {},
|
listStyles: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.type === "tracklist") {
|
if (this.type === 'tracklist') {
|
||||||
this.listStyles = {
|
this.listStyles = {
|
||||||
display: "grid",
|
display: 'grid',
|
||||||
gap: "4px",
|
gap: '4px',
|
||||||
gridTemplateColumns: `repeat(${this.columnNumber}, 1fr)`,
|
gridTemplateColumns: `repeat(${this.columnNumber}, 1fr)`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["liked"]),
|
...mapState(['liked']),
|
||||||
isRightClickedTrackLiked() {
|
isRightClickedTrackLiked() {
|
||||||
return this.liked.songs.includes(this.rightClickedTrack?.id);
|
return this.liked.songs.includes(this.rightClickedTrack?.id);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(["updateLikedSongs", "updateModal"]),
|
...mapMutations(['updateLikedSongs', 'updateModal']),
|
||||||
...mapActions(["nextTrack", "showToast"]),
|
...mapActions(['nextTrack', 'showToast']),
|
||||||
openMenu(e, track) {
|
openMenu(e, track) {
|
||||||
this.rightClickedTrack = track;
|
this.rightClickedTrack = track;
|
||||||
this.$refs.menu.openMenu(e);
|
this.$refs.menu.openMenu(e);
|
||||||
|
|
@ -127,49 +127,49 @@ export default {
|
||||||
closeMenu() {
|
closeMenu() {
|
||||||
this.rightClickedTrack = {
|
this.rightClickedTrack = {
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "",
|
name: '',
|
||||||
ar: [{ name: "" }],
|
ar: [{ name: '' }],
|
||||||
al: { picUrl: "" },
|
al: { picUrl: '' },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
playThisList(trackID) {
|
playThisList(trackID) {
|
||||||
if (this.dbclickTrackFunc === "default") {
|
if (this.dbclickTrackFunc === 'default') {
|
||||||
this.playThisListDefault(trackID);
|
this.playThisListDefault(trackID);
|
||||||
} else if (this.dbclickTrackFunc === "none") {
|
} else if (this.dbclickTrackFunc === 'none') {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else if (this.dbclickTrackFunc === "playTrackOnListByID") {
|
} else if (this.dbclickTrackFunc === 'playTrackOnListByID') {
|
||||||
this.$store.state.player.playTrackOnListByID(trackID);
|
this.$store.state.player.playTrackOnListByID(trackID);
|
||||||
} else if (this.dbclickTrackFunc === "playPlaylistByID") {
|
} else if (this.dbclickTrackFunc === 'playPlaylistByID') {
|
||||||
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
||||||
} else if (this.dbclickTrackFunc === "playAList") {
|
} else if (this.dbclickTrackFunc === 'playAList') {
|
||||||
let trackIDs = this.tracks.map((t) => t.id);
|
let trackIDs = this.tracks.map(t => t.id);
|
||||||
this.$store.state.player.replacePlaylist(
|
this.$store.state.player.replacePlaylist(
|
||||||
trackIDs,
|
trackIDs,
|
||||||
this.id,
|
this.id,
|
||||||
"artist",
|
'artist',
|
||||||
trackID
|
trackID
|
||||||
);
|
);
|
||||||
} else if (this.dbclickTrackFunc === "dailyTracks") {
|
} else if (this.dbclickTrackFunc === 'dailyTracks') {
|
||||||
let trackIDs = this.tracks.map((t) => t.id);
|
let trackIDs = this.tracks.map(t => t.id);
|
||||||
this.$store.state.player.replacePlaylist(
|
this.$store.state.player.replacePlaylist(
|
||||||
trackIDs,
|
trackIDs,
|
||||||
"/daily/songs",
|
'/daily/songs',
|
||||||
"url",
|
'url',
|
||||||
trackID
|
trackID
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
playThisListDefault(trackID) {
|
playThisListDefault(trackID) {
|
||||||
if (this.type === "playlist") {
|
if (this.type === 'playlist') {
|
||||||
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
||||||
} else if (this.type === "album") {
|
} else if (this.type === 'album') {
|
||||||
this.$store.state.player.playAlbumByID(this.id, trackID);
|
this.$store.state.player.playAlbumByID(this.id, trackID);
|
||||||
} else if (this.type === "tracklist") {
|
} else if (this.type === 'tracklist') {
|
||||||
let trackIDs = this.tracks.map((t) => t.id);
|
let trackIDs = this.tracks.map(t => t.id);
|
||||||
this.$store.state.player.replacePlaylist(
|
this.$store.state.player.replacePlaylist(
|
||||||
trackIDs,
|
trackIDs,
|
||||||
this.id,
|
this.id,
|
||||||
"artist",
|
'artist',
|
||||||
trackID
|
trackID
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -188,19 +188,19 @@ export default {
|
||||||
},
|
},
|
||||||
likeASong(id) {
|
likeASong(id) {
|
||||||
if (!isAccountLoggedIn()) {
|
if (!isAccountLoggedIn()) {
|
||||||
this.showToast("此操作需要登录网易云账号");
|
this.showToast('此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let like = true;
|
let like = true;
|
||||||
let likedSongs = this.liked.songs;
|
let likedSongs = this.liked.songs;
|
||||||
if (likedSongs.includes(id)) like = false;
|
if (likedSongs.includes(id)) like = false;
|
||||||
likeATrack({ id, like }).then((data) => {
|
likeATrack({ id, like }).then(data => {
|
||||||
if (data.code !== 200) return;
|
if (data.code !== 200) return;
|
||||||
if (like === false) {
|
if (like === false) {
|
||||||
this.showToast(this.$t("toast.removedFromMyLikedSongs"));
|
this.showToast(this.$t('toast.removedFromMyLikedSongs'));
|
||||||
this.updateLikedSongs(likedSongs.filter((d) => d !== id));
|
this.updateLikedSongs(likedSongs.filter(d => d !== id));
|
||||||
} else {
|
} else {
|
||||||
this.showToast(this.$t("toast.savedToMyLikedSongs"));
|
this.showToast(this.$t('toast.savedToMyLikedSongs'));
|
||||||
likedSongs.push(id);
|
likedSongs.push(id);
|
||||||
this.updateLikedSongs(likedSongs);
|
this.updateLikedSongs(likedSongs);
|
||||||
}
|
}
|
||||||
|
|
@ -208,34 +208,34 @@ export default {
|
||||||
},
|
},
|
||||||
addTrackToPlaylist() {
|
addTrackToPlaylist() {
|
||||||
if (!isAccountLoggedIn()) {
|
if (!isAccountLoggedIn()) {
|
||||||
this.showToast("此操作需要登录网易云账号");
|
this.showToast('此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.updateModal({
|
this.updateModal({
|
||||||
modalName: "addTrackToPlaylistModal",
|
modalName: 'addTrackToPlaylistModal',
|
||||||
key: "show",
|
key: 'show',
|
||||||
value: true,
|
value: true,
|
||||||
});
|
});
|
||||||
this.updateModal({
|
this.updateModal({
|
||||||
modalName: "addTrackToPlaylistModal",
|
modalName: 'addTrackToPlaylistModal',
|
||||||
key: "selectedTrackID",
|
key: 'selectedTrackID',
|
||||||
value: this.rightClickedTrack.id,
|
value: this.rightClickedTrack.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
removeTrackFromPlaylist() {
|
removeTrackFromPlaylist() {
|
||||||
if (!isAccountLoggedIn()) {
|
if (!isAccountLoggedIn()) {
|
||||||
this.showToast("此操作需要登录网易云账号");
|
this.showToast('此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (confirm(`确定要从歌单删除 ${this.rightClickedTrack.name}?`)) {
|
if (confirm(`确定要从歌单删除 ${this.rightClickedTrack.name}?`)) {
|
||||||
let trackID = this.rightClickedTrack.id;
|
let trackID = this.rightClickedTrack.id;
|
||||||
addOrRemoveTrackFromPlaylist({
|
addOrRemoveTrackFromPlaylist({
|
||||||
op: "del",
|
op: 'del',
|
||||||
pid: this.id,
|
pid: this.id,
|
||||||
tracks: trackID,
|
tracks: trackID,
|
||||||
}).then((data) => {
|
}).then(data => {
|
||||||
this.showToast(
|
this.showToast(
|
||||||
data.body.code === 200 ? "已从歌单中删除" : data.body.message
|
data.body.code === 200 ? '已从歌单中删除' : data.body.message
|
||||||
);
|
);
|
||||||
this.$parent.removeTrack(trackID);
|
this.$parent.removeTrack(trackID);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,27 @@
|
||||||
// import store, { state, dispatch, commit } from "@/store";
|
// import store, { state, dispatch, commit } from "@/store";
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
import { isAccountLoggedIn, isLooseLoggedIn } from '@/utils/auth';
|
||||||
import { likeATrack } from "@/api/track";
|
import { likeATrack } from '@/api/track';
|
||||||
|
import { getPlaylistDetail } from '@/api/playlist';
|
||||||
|
import { getTrackDetail } from '@/api/track';
|
||||||
|
import {
|
||||||
|
userPlaylist,
|
||||||
|
userLikedSongsIDs,
|
||||||
|
likedAlbums,
|
||||||
|
likedArtists,
|
||||||
|
likedMVs,
|
||||||
|
} from '@/api/user';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
showToast({ state, commit }, text) {
|
showToast({ state, commit }, text) {
|
||||||
if (state.toast.timer !== null) {
|
if (state.toast.timer !== null) {
|
||||||
clearTimeout(state.toast.timer);
|
clearTimeout(state.toast.timer);
|
||||||
commit("updateToast", { show: false, text: "", timer: null });
|
commit('updateToast', { show: false, text: '', timer: null });
|
||||||
}
|
}
|
||||||
commit("updateToast", {
|
commit('updateToast', {
|
||||||
show: true,
|
show: true,
|
||||||
text,
|
text,
|
||||||
timer: setTimeout(() => {
|
timer: setTimeout(() => {
|
||||||
commit("updateToast", {
|
commit('updateToast', {
|
||||||
show: false,
|
show: false,
|
||||||
text: state.toast.text,
|
text: state.toast.text,
|
||||||
timer: null,
|
timer: null,
|
||||||
|
|
@ -20,23 +29,117 @@ export default {
|
||||||
}, 3200),
|
}, 3200),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
likeASong({ state, commit, dispatch }, id) {
|
likeATrack({ state, commit, dispatch }, id) {
|
||||||
if (!isAccountLoggedIn()) {
|
if (!isAccountLoggedIn()) {
|
||||||
dispatch("showToast", "此操作需要登录网易云账号");
|
dispatch('showToast', '此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let like = true;
|
let like = true;
|
||||||
if (state.liked.songs.includes(id)) like = false;
|
if (state.liked.songs.includes(id)) like = false;
|
||||||
likeATrack({ id, like }).then(() => {
|
likeATrack({ id, like }).then(() => {
|
||||||
if (like === false) {
|
if (like === false) {
|
||||||
commit(
|
commit('updateLikedXXX', {
|
||||||
"updateLikedSongs",
|
name: 'songs',
|
||||||
state.liked.songs.filter((d) => d !== id)
|
data: state.liked.songs.filter(d => d !== id),
|
||||||
);
|
});
|
||||||
} else {
|
} else {
|
||||||
let newLikeSongs = state.liked.songs;
|
let newLikeSongs = state.liked.songs;
|
||||||
newLikeSongs.push(id);
|
newLikeSongs.push(id);
|
||||||
commit("updateLikedSongs", newLikeSongs);
|
commit('updateLikedXXX', {
|
||||||
|
name: 'songs',
|
||||||
|
data: newLikeSongs,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dispatch('fetchLikedSongsWithDetails');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchLikedSongs: ({ state, commit }) => {
|
||||||
|
if (!isLooseLoggedIn()) return;
|
||||||
|
console.debug('[debug][actions.js] fetchLikedSongs');
|
||||||
|
if (isAccountLoggedIn()) {
|
||||||
|
return userLikedSongsIDs({ uid: state.data.user.userId }).then(result => {
|
||||||
|
if (result.ids) {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'songs',
|
||||||
|
data: result.ids,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// TODO:搜索ID登录的用户
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchLikedSongsWithDetails: ({ state, commit }) => {
|
||||||
|
console.debug('[debug][actions.js] fetchLikedSongsWithDetails');
|
||||||
|
return getPlaylistDetail(state.data.likedSongPlaylistID, true).then(
|
||||||
|
result => {
|
||||||
|
return getTrackDetail(
|
||||||
|
result.playlist.trackIds
|
||||||
|
.slice(0, 12)
|
||||||
|
.map(t => t.id)
|
||||||
|
.join(',')
|
||||||
|
).then(result => {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'songsWithDetails',
|
||||||
|
data: result.songs,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
fetchLikedPlaylist: ({ state, commit }) => {
|
||||||
|
if (!isLooseLoggedIn()) return;
|
||||||
|
console.debug('[debug][actions.js] fetchLikedPlaylist');
|
||||||
|
if (isAccountLoggedIn()) {
|
||||||
|
return userPlaylist({
|
||||||
|
uid: state.data.user.userId,
|
||||||
|
limit: 2000, // 最多只加载2000个歌单(等有用户反馈问题再修)
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
|
}).then(result => {
|
||||||
|
if (result.playlist) {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'playlists',
|
||||||
|
data: result.playlist,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// TODO:搜索ID登录的用户
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchLikedAlbums: ({ commit }) => {
|
||||||
|
if (!isAccountLoggedIn()) return;
|
||||||
|
console.debug('[debug][actions.js] fetchLikedAlbums');
|
||||||
|
return likedAlbums({ limit: 2000 }).then(result => {
|
||||||
|
if (result.data) {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'albums',
|
||||||
|
data: result.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchLikedArtists: ({ commit }) => {
|
||||||
|
if (!isAccountLoggedIn()) return;
|
||||||
|
console.debug('[debug][actions.js] fetchLikedArtists');
|
||||||
|
return likedArtists().then(result => {
|
||||||
|
if (result.data) {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'artists',
|
||||||
|
data: result.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchLikedMVs: ({ commit }) => {
|
||||||
|
if (!isAccountLoggedIn()) return;
|
||||||
|
console.debug('[debug][actions.js] fetchLikedMVs');
|
||||||
|
return likedMVs().then(result => {
|
||||||
|
if (result.data) {
|
||||||
|
commit('updateLikedXXX', {
|
||||||
|
name: 'mvs',
|
||||||
|
data: result.data,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
export default {
|
export default {
|
||||||
updateLikedSongs(state, trackIDs) {
|
updateLikedXXX(state, { name, data }) {
|
||||||
state.liked.songs = trackIDs;
|
state.liked[name] = data;
|
||||||
state.player.sendSelfToIpcMain();
|
if (name === 'songs') {
|
||||||
|
state.player.sendSelfToIpcMain();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
changeLang(state, lang) {
|
changeLang(state, lang) {
|
||||||
state.settings.lang = lang;
|
state.settings.lang = lang;
|
||||||
|
|
@ -23,11 +25,11 @@ export default {
|
||||||
},
|
},
|
||||||
togglePlaylistCategory(state, name) {
|
togglePlaylistCategory(state, name) {
|
||||||
const index = state.settings.enabledPlaylistCategories.findIndex(
|
const index = state.settings.enabledPlaylistCategories.findIndex(
|
||||||
(c) => c === name
|
c => c === name
|
||||||
);
|
);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
state.settings.enabledPlaylistCategories = state.settings.enabledPlaylistCategories.filter(
|
state.settings.enabledPlaylistCategories = state.settings.enabledPlaylistCategories.filter(
|
||||||
(c) => c !== name
|
c => c !== name
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
state.settings.enabledPlaylistCategories.push(name);
|
state.settings.enabledPlaylistCategories.push(name);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import initLocalStorage from "./initLocalStorage";
|
import initLocalStorage from './initLocalStorage';
|
||||||
import pkg from "../../package.json";
|
import pkg from '../../package.json';
|
||||||
import updateApp from "@/utils/updateApp";
|
import updateApp from '@/utils/updateApp';
|
||||||
|
|
||||||
if (localStorage.getItem("appVersion") === null) {
|
if (localStorage.getItem('appVersion') === null) {
|
||||||
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
localStorage.setItem('settings', JSON.stringify(initLocalStorage.settings));
|
||||||
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
localStorage.setItem('data', JSON.stringify(initLocalStorage.data));
|
||||||
localStorage.setItem("appVersion", pkg.version);
|
localStorage.setItem('appVersion', pkg.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateApp();
|
updateApp();
|
||||||
|
|
@ -14,6 +14,11 @@ export default {
|
||||||
showLyrics: false,
|
showLyrics: false,
|
||||||
liked: {
|
liked: {
|
||||||
songs: [],
|
songs: [],
|
||||||
|
songsWithDetails: [], // 只有前12首
|
||||||
|
playlists: [],
|
||||||
|
albums: [],
|
||||||
|
artists: [],
|
||||||
|
mvs: [],
|
||||||
},
|
},
|
||||||
contextMenu: {
|
contextMenu: {
|
||||||
clickObjectID: 0,
|
clickObjectID: 0,
|
||||||
|
|
@ -21,7 +26,7 @@ export default {
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
show: false,
|
show: false,
|
||||||
text: "",
|
text: '',
|
||||||
timer: null,
|
timer: null,
|
||||||
},
|
},
|
||||||
modals: {
|
modals: {
|
||||||
|
|
@ -35,8 +40,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dailyTracks: [],
|
dailyTracks: [],
|
||||||
lastfm: JSON.parse(localStorage.getItem("lastfm")) || {},
|
lastfm: JSON.parse(localStorage.getItem('lastfm')) || {},
|
||||||
player: JSON.parse(localStorage.getItem("player")),
|
player: JSON.parse(localStorage.getItem('player')),
|
||||||
settings: JSON.parse(localStorage.getItem("settings")),
|
settings: JSON.parse(localStorage.getItem('settings')),
|
||||||
data: JSON.parse(localStorage.getItem("data")),
|
data: JSON.parse(localStorage.getItem('data')),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import { getTrackDetail, scrobble, getMP3 } from "@/api/track";
|
import { getTrackDetail, scrobble, getMP3 } from '@/api/track';
|
||||||
import shuffle from "lodash/shuffle";
|
import shuffle from 'lodash/shuffle';
|
||||||
import { Howler, Howl } from "howler";
|
import { Howler, Howl } from 'howler';
|
||||||
import { cacheTrackSource, getTrackSource } from "@/utils/db";
|
import { cacheTrackSource, getTrackSource } from '@/utils/db';
|
||||||
import { getAlbum } from "@/api/album";
|
import { getAlbum } from '@/api/album';
|
||||||
import { getPlaylistDetail } from "@/api/playlist";
|
import { getPlaylistDetail } from '@/api/playlist';
|
||||||
import { getArtist } from "@/api/artist";
|
import { getArtist } from '@/api/artist';
|
||||||
import { personalFM, fmTrash } from "@/api/others";
|
import { personalFM, fmTrash } from '@/api/others';
|
||||||
import store from "@/store";
|
import store from '@/store';
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
import { isAccountLoggedIn } from '@/utils/auth';
|
||||||
import { trackUpdateNowPlaying, trackScrobble } from "@/api/lastfm";
|
import { trackUpdateNowPlaying, trackScrobble } from '@/api/lastfm';
|
||||||
|
|
||||||
const electron =
|
const electron =
|
||||||
process.env.IS_ELECTRON === true ? window.require("electron") : null;
|
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||||
const ipcRenderer =
|
const ipcRenderer =
|
||||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ export default class {
|
||||||
this._playing = false; // 是否正在播放中
|
this._playing = false; // 是否正在播放中
|
||||||
this._progress = 0; // 当前播放歌曲的进度
|
this._progress = 0; // 当前播放歌曲的进度
|
||||||
this._enabled = false; // 是否启用Player
|
this._enabled = false; // 是否启用Player
|
||||||
this._repeatMode = "off"; // off | on | one
|
this._repeatMode = 'off'; // off | on | one
|
||||||
this._shuffle = false; // true | false
|
this._shuffle = false; // true | false
|
||||||
this._volume = 1; // 0 to 1
|
this._volume = 1; // 0 to 1
|
||||||
this._volumeBeforeMuted = 1; // 用于保存静音前的音量
|
this._volumeBeforeMuted = 1; // 用于保存静音前的音量
|
||||||
|
|
@ -31,7 +31,7 @@ export default class {
|
||||||
this._current = 0; // 当前播放歌曲在播放列表里的index
|
this._current = 0; // 当前播放歌曲在播放列表里的index
|
||||||
this._shuffledList = []; // 被随机打乱的播放列表,随机播放模式下会使用此播放列表
|
this._shuffledList = []; // 被随机打乱的播放列表,随机播放模式下会使用此播放列表
|
||||||
this._shuffledCurrent = 0; // 当前播放歌曲在随机列表里面的index
|
this._shuffledCurrent = 0; // 当前播放歌曲在随机列表里面的index
|
||||||
this._playlistSource = { type: "album", id: 123 }; // 当前播放列表的信息
|
this._playlistSource = { type: 'album', id: 123 }; // 当前播放列表的信息
|
||||||
this._currentTrack = { id: 86827685 }; // 当前播放歌曲的详细信息
|
this._currentTrack = { id: 86827685 }; // 当前播放歌曲的详细信息
|
||||||
this._playNextList = []; // 当这个list不为空时,会优先播放这个list的歌
|
this._playNextList = []; // 当这个list不为空时,会优先播放这个list的歌
|
||||||
this._isPersonalFM = false; // 是否是私人FM模式
|
this._isPersonalFM = false; // 是否是私人FM模式
|
||||||
|
|
@ -40,7 +40,7 @@ export default class {
|
||||||
|
|
||||||
// howler (https://github.com/goldfire/howler.js)
|
// howler (https://github.com/goldfire/howler.js)
|
||||||
this._howler = null;
|
this._howler = null;
|
||||||
Object.defineProperty(this, "_howler", {
|
Object.defineProperty(this, '_howler', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ export default class {
|
||||||
this._init();
|
this._init();
|
||||||
|
|
||||||
// for debug
|
// for debug
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
window.player = this;
|
window.player = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ export default class {
|
||||||
}
|
}
|
||||||
set repeatMode(mode) {
|
set repeatMode(mode) {
|
||||||
if (this._isPersonalFM) return;
|
if (this._isPersonalFM) return;
|
||||||
if (!["off", "on", "one"].includes(mode)) {
|
if (!['off', 'on', 'one'].includes(mode)) {
|
||||||
console.warn("repeatMode: invalid args, must be 'on' | 'off' | 'one'");
|
console.warn("repeatMode: invalid args, must be 'on' | 'off' | 'one'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +70,7 @@ export default class {
|
||||||
set shuffle(shuffle) {
|
set shuffle(shuffle) {
|
||||||
if (this._isPersonalFM) return;
|
if (this._isPersonalFM) return;
|
||||||
if (shuffle !== true && shuffle !== false) {
|
if (shuffle !== true && shuffle !== false) {
|
||||||
console.warn("shuffle: invalid args, must be Boolean");
|
console.warn('shuffle: invalid args, must be Boolean');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._shuffle = shuffle;
|
this._shuffle = shuffle;
|
||||||
|
|
@ -148,11 +148,11 @@ export default class {
|
||||||
if (this._enabled) {
|
if (this._enabled) {
|
||||||
// 恢复当前播放歌曲
|
// 恢复当前播放歌曲
|
||||||
this._replaceCurrentTrack(this._currentTrack.id, false).then(() => {
|
this._replaceCurrentTrack(this._currentTrack.id, false).then(() => {
|
||||||
this._howler?.seek(localStorage.getItem("playerCurrentTrackTime") ?? 0);
|
this._howler?.seek(localStorage.getItem('playerCurrentTrackTime') ?? 0);
|
||||||
setInterval(
|
setInterval(
|
||||||
() =>
|
() =>
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
"playerCurrentTrackTime",
|
'playerCurrentTrackTime',
|
||||||
this._howler?.seek()
|
this._howler?.seek()
|
||||||
),
|
),
|
||||||
1000
|
1000
|
||||||
|
|
@ -164,7 +164,7 @@ export default class {
|
||||||
|
|
||||||
// 初始化私人FM
|
// 初始化私人FM
|
||||||
if (this._personalFMTrack.id === 0 || this._personalFMNextTrack.id === 0) {
|
if (this._personalFMTrack.id === 0 || this._personalFMNextTrack.id === 0) {
|
||||||
personalFM().then((result) => {
|
personalFM().then(result => {
|
||||||
this._personalFMTrack = result.data[0];
|
this._personalFMTrack = result.data[0];
|
||||||
this._personalFMNextTrack = result.data[1];
|
this._personalFMNextTrack = result.data[1];
|
||||||
return this._personalFMTrack;
|
return this._personalFMTrack;
|
||||||
|
|
@ -185,7 +185,7 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当歌曲是列表最后一首 && 循环模式开启
|
// 当歌曲是列表最后一首 && 循环模式开启
|
||||||
if (this.list.length === this.current + 1 && this.repeatMode === "on") {
|
if (this.list.length === this.current + 1 && this.repeatMode === 'on') {
|
||||||
return [this.list[0], 0];
|
return [this.list[0], 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ export default class {
|
||||||
}
|
}
|
||||||
_getPrevTrack() {
|
_getPrevTrack() {
|
||||||
// 当歌曲是列表第一首 && 循环模式开启
|
// 当歌曲是列表第一首 && 循环模式开启
|
||||||
if (this.current === 0 && this.repeatMode === "on") {
|
if (this.current === 0 && this.repeatMode === 'on') {
|
||||||
return [this.list[this.list.length - 1], this.list.length - 1];
|
return [this.list[this.list.length - 1], this.list.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,10 +202,10 @@ export default class {
|
||||||
return [this.list[this.current - 1], this.current - 1];
|
return [this.list[this.current - 1], this.current - 1];
|
||||||
}
|
}
|
||||||
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
|
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
|
||||||
let list = this._list.filter((tid) => tid !== firstTrackID);
|
let list = this._list.filter(tid => tid !== firstTrackID);
|
||||||
if (firstTrackID === "first") list = this._list;
|
if (firstTrackID === 'first') list = this._list;
|
||||||
this._shuffledList = shuffle(list);
|
this._shuffledList = shuffle(list);
|
||||||
if (firstTrackID !== "first") this._shuffledList.unshift(firstTrackID);
|
if (firstTrackID !== 'first') this._shuffledList.unshift(firstTrackID);
|
||||||
}
|
}
|
||||||
async _scrobble(track, time, completed = false) {
|
async _scrobble(track, time, completed = false) {
|
||||||
console.debug(
|
console.debug(
|
||||||
|
|
@ -238,19 +238,19 @@ export default class {
|
||||||
this._howler = new Howl({
|
this._howler = new Howl({
|
||||||
src: [source],
|
src: [source],
|
||||||
html5: true,
|
html5: true,
|
||||||
format: ["mp3", "flac"],
|
format: ['mp3', 'flac'],
|
||||||
});
|
});
|
||||||
if (autoplay) {
|
if (autoplay) {
|
||||||
this.play();
|
this.play();
|
||||||
document.title = `${this._currentTrack.name} · ${this._currentTrack.ar[0].name} - YesPlayMusic`;
|
document.title = `${this._currentTrack.name} · ${this._currentTrack.ar[0].name} - YesPlayMusic`;
|
||||||
}
|
}
|
||||||
this.setOutputDevice();
|
this.setOutputDevice();
|
||||||
this._howler.once("end", () => {
|
this._howler.once('end', () => {
|
||||||
this._nextTrackCallback();
|
this._nextTrackCallback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_getAudioSourceFromCache(id) {
|
_getAudioSourceFromCache(id) {
|
||||||
return getTrackSource(id).then((t) => {
|
return getTrackSource(id).then(t => {
|
||||||
if (!t) return null;
|
if (!t) return null;
|
||||||
const source = URL.createObjectURL(new Blob([t.source]));
|
const source = URL.createObjectURL(new Blob([t.source]));
|
||||||
return source;
|
return source;
|
||||||
|
|
@ -258,18 +258,18 @@ export default class {
|
||||||
}
|
}
|
||||||
_getAudioSourceFromNetease(track) {
|
_getAudioSourceFromNetease(track) {
|
||||||
if (isAccountLoggedIn()) {
|
if (isAccountLoggedIn()) {
|
||||||
return getMP3(track.id).then((result) => {
|
return getMP3(track.id).then(result => {
|
||||||
if (!result.data[0]) return null;
|
if (!result.data[0]) return null;
|
||||||
if (!result.data[0].url) return null;
|
if (!result.data[0].url) return null;
|
||||||
if (result.data[0].freeTrialInfo !== null) return null; // 跳过只能试听的歌曲
|
if (result.data[0].freeTrialInfo !== null) return null; // 跳过只能试听的歌曲
|
||||||
const source = result.data[0].url.replace(/^http:/, "https:");
|
const source = result.data[0].url.replace(/^http:/, 'https:');
|
||||||
if (store.state.settings.automaticallyCacheSongs) {
|
if (store.state.settings.automaticallyCacheSongs) {
|
||||||
cacheTrackSource(track, source, result.data[0].br);
|
cacheTrackSource(track, source, result.data[0].br);
|
||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
resolve(`https://music.163.com/song/media/outer/url?id=${track.id}`);
|
resolve(`https://music.163.com/song/media/outer/url?id=${track.id}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -282,42 +282,42 @@ export default class {
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const source = ipcRenderer.sendSync("unblock-music", track);
|
const source = ipcRenderer.sendSync('unblock-music', track);
|
||||||
if (store.state.settings.automaticallyCacheSongs && source?.url) {
|
if (store.state.settings.automaticallyCacheSongs && source?.url) {
|
||||||
// TODO: 将unblockMusic字样换成真正的来源(比如酷我咪咕等)
|
// TODO: 将unblockMusic字样换成真正的来源(比如酷我咪咕等)
|
||||||
cacheTrackSource(track, source.url, 128000, "unblockMusic");
|
cacheTrackSource(track, source.url, 128000, 'unblockMusic');
|
||||||
}
|
}
|
||||||
return source?.url;
|
return source?.url;
|
||||||
}
|
}
|
||||||
_getAudioSource(track) {
|
_getAudioSource(track) {
|
||||||
return this._getAudioSourceFromCache(String(track.id))
|
return this._getAudioSourceFromCache(String(track.id))
|
||||||
.then((source) => {
|
.then(source => {
|
||||||
return source ?? this._getAudioSourceFromNetease(track);
|
return source ?? this._getAudioSourceFromNetease(track);
|
||||||
})
|
})
|
||||||
.then((source) => {
|
.then(source => {
|
||||||
return source ?? this._getAudioSourceFromUnblockMusic(track);
|
return source ?? this._getAudioSourceFromUnblockMusic(track);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_replaceCurrentTrack(
|
_replaceCurrentTrack(
|
||||||
id,
|
id,
|
||||||
autoplay = true,
|
autoplay = true,
|
||||||
ifUnplayableThen = "playNextTrack"
|
ifUnplayableThen = 'playNextTrack'
|
||||||
) {
|
) {
|
||||||
if (autoplay && this._currentTrack.name) {
|
if (autoplay && this._currentTrack.name) {
|
||||||
this._scrobble(this.currentTrack, this._howler?.seek());
|
this._scrobble(this.currentTrack, this._howler?.seek());
|
||||||
}
|
}
|
||||||
return getTrackDetail(id).then((data) => {
|
return getTrackDetail(id).then(data => {
|
||||||
let track = data.songs[0];
|
let track = data.songs[0];
|
||||||
this._currentTrack = track;
|
this._currentTrack = track;
|
||||||
this._updateMediaSessionMetaData(track);
|
this._updateMediaSessionMetaData(track);
|
||||||
return this._getAudioSource(track).then((source) => {
|
return this._getAudioSource(track).then(source => {
|
||||||
if (source) {
|
if (source) {
|
||||||
this._playAudioSource(source, autoplay);
|
this._playAudioSource(source, autoplay);
|
||||||
this._cacheNextTrack();
|
this._cacheNextTrack();
|
||||||
return source;
|
return source;
|
||||||
} else {
|
} else {
|
||||||
store.dispatch("showToast", `无法播放 ${track.name}`);
|
store.dispatch('showToast', `无法播放 ${track.name}`);
|
||||||
ifUnplayableThen === "playNextTrack"
|
ifUnplayableThen === 'playNextTrack'
|
||||||
? this.playNextTrack()
|
? this.playNextTrack()
|
||||||
: this.playPrevTrack();
|
: this.playPrevTrack();
|
||||||
}
|
}
|
||||||
|
|
@ -329,72 +329,72 @@ export default class {
|
||||||
? this._personalFMNextTrack.id
|
? this._personalFMNextTrack.id
|
||||||
: this._getNextTrack()[0];
|
: this._getNextTrack()[0];
|
||||||
if (!nextTrackID) return;
|
if (!nextTrackID) return;
|
||||||
getTrackDetail(nextTrackID).then((data) => {
|
getTrackDetail(nextTrackID).then(data => {
|
||||||
let track = data.songs[0];
|
let track = data.songs[0];
|
||||||
this._getAudioSource(track);
|
this._getAudioSource(track);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_loadSelfFromLocalStorage() {
|
_loadSelfFromLocalStorage() {
|
||||||
const player = JSON.parse(localStorage.getItem("player"));
|
const player = JSON.parse(localStorage.getItem('player'));
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
for (const [key, value] of Object.entries(player)) {
|
for (const [key, value] of Object.entries(player)) {
|
||||||
this[key] = value;
|
this[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_initMediaSession() {
|
_initMediaSession() {
|
||||||
if ("mediaSession" in navigator) {
|
if ('mediaSession' in navigator) {
|
||||||
navigator.mediaSession.setActionHandler("play", () => {
|
navigator.mediaSession.setActionHandler('play', () => {
|
||||||
this.play();
|
this.play();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("pause", () => {
|
navigator.mediaSession.setActionHandler('pause', () => {
|
||||||
this.pause();
|
this.pause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("previoustrack", () => {
|
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
||||||
this.playPrevTrack();
|
this.playPrevTrack();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("nexttrack", () => {
|
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||||
this.playNextTrack();
|
this.playNextTrack();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("stop", () => {
|
navigator.mediaSession.setActionHandler('stop', () => {
|
||||||
this.pause();
|
this.pause();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("seekto", (event) => {
|
navigator.mediaSession.setActionHandler('seekto', event => {
|
||||||
this.seek(event.seekTime);
|
this.seek(event.seekTime);
|
||||||
this._updateMediaSessionPositionState();
|
this._updateMediaSessionPositionState();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("seekbackward", (event) => {
|
navigator.mediaSession.setActionHandler('seekbackward', event => {
|
||||||
this.seek(this.seek() - (event.seekOffset || 10));
|
this.seek(this.seek() - (event.seekOffset || 10));
|
||||||
this._updateMediaSessionPositionState();
|
this._updateMediaSessionPositionState();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler("seekforward", (event) => {
|
navigator.mediaSession.setActionHandler('seekforward', event => {
|
||||||
this.seek(this.seek() + (event.seekOffset || 10));
|
this.seek(this.seek() + (event.seekOffset || 10));
|
||||||
this._updateMediaSessionPositionState();
|
this._updateMediaSessionPositionState();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_updateMediaSessionMetaData(track) {
|
_updateMediaSessionMetaData(track) {
|
||||||
if ("mediaSession" in navigator === false) {
|
if ('mediaSession' in navigator === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let artists = track.ar.map((a) => a.name);
|
let artists = track.ar.map(a => a.name);
|
||||||
navigator.mediaSession.metadata = new window.MediaMetadata({
|
navigator.mediaSession.metadata = new window.MediaMetadata({
|
||||||
title: track.name,
|
title: track.name,
|
||||||
artist: artists.join(","),
|
artist: artists.join(','),
|
||||||
album: track.al.name,
|
album: track.al.name,
|
||||||
artwork: [
|
artwork: [
|
||||||
{
|
{
|
||||||
src: track.al.picUrl + "?param=512y512",
|
src: track.al.picUrl + '?param=512y512',
|
||||||
type: "image/jpg",
|
type: 'image/jpg',
|
||||||
sizes: "512x512",
|
sizes: '512x512',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_updateMediaSessionPositionState() {
|
_updateMediaSessionPositionState() {
|
||||||
if ("mediaSession" in navigator === false) {
|
if ('mediaSession' in navigator === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ("setPositionState" in navigator.mediaSession) {
|
if ('setPositionState' in navigator.mediaSession) {
|
||||||
navigator.mediaSession.setPositionState({
|
navigator.mediaSession.setPositionState({
|
||||||
duration: ~~(this.currentTrack.dt / 1000),
|
duration: ~~(this.currentTrack.dt / 1000),
|
||||||
playbackRate: 1.0,
|
playbackRate: 1.0,
|
||||||
|
|
@ -404,14 +404,14 @@ export default class {
|
||||||
}
|
}
|
||||||
_nextTrackCallback() {
|
_nextTrackCallback() {
|
||||||
this._scrobble(this._currentTrack, 0, true);
|
this._scrobble(this._currentTrack, 0, true);
|
||||||
if (!this.isPersonalFM && this.repeatMode === "one") {
|
if (!this.isPersonalFM && this.repeatMode === 'one') {
|
||||||
this._replaceCurrentTrack(this._currentTrack.id);
|
this._replaceCurrentTrack(this._currentTrack.id);
|
||||||
} else {
|
} else {
|
||||||
this.playNextTrack();
|
this.playNextTrack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_loadPersonalFMNextTrack() {
|
_loadPersonalFMNextTrack() {
|
||||||
return personalFM().then((result) => {
|
return personalFM().then(result => {
|
||||||
this._personalFMNextTrack = result.data[0];
|
this._personalFMNextTrack = result.data[0];
|
||||||
return this._personalFMNextTrack;
|
return this._personalFMNextTrack;
|
||||||
});
|
});
|
||||||
|
|
@ -425,7 +425,7 @@ export default class {
|
||||||
}
|
}
|
||||||
let copyTrack = { ...track };
|
let copyTrack = { ...track };
|
||||||
copyTrack.dt -= seekTime * 1000;
|
copyTrack.dt -= seekTime * 1000;
|
||||||
ipcRenderer.send("playDiscordPresence", copyTrack);
|
ipcRenderer.send('playDiscordPresence', copyTrack);
|
||||||
}
|
}
|
||||||
_pauseDiscordPresence(track) {
|
_pauseDiscordPresence(track) {
|
||||||
if (
|
if (
|
||||||
|
|
@ -434,7 +434,7 @@ export default class {
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ipcRenderer.send("pauseDiscordPresence", track);
|
ipcRenderer.send('pauseDiscordPresence', track);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTrackID() {
|
currentTrackID() {
|
||||||
|
|
@ -467,23 +467,23 @@ export default class {
|
||||||
const [trackID, index] = this._getPrevTrack();
|
const [trackID, index] = this._getPrevTrack();
|
||||||
if (trackID === undefined) return false;
|
if (trackID === undefined) return false;
|
||||||
this.current = index;
|
this.current = index;
|
||||||
this._replaceCurrentTrack(trackID, true, "playPrevTrack");
|
this._replaceCurrentTrack(trackID, true, 'playPrevTrack');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
saveSelfToLocalStorage() {
|
saveSelfToLocalStorage() {
|
||||||
let player = {};
|
let player = {};
|
||||||
for (let [key, value] of Object.entries(this)) {
|
for (let [key, value] of Object.entries(this)) {
|
||||||
if (key === "_playing") continue;
|
if (key === '_playing') continue;
|
||||||
player[key] = value;
|
player[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("player", JSON.stringify(player));
|
localStorage.setItem('player', JSON.stringify(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
pause() {
|
pause() {
|
||||||
this._howler?.pause();
|
this._howler?.pause();
|
||||||
this._playing = false;
|
this._playing = false;
|
||||||
document.title = "YesPlayMusic";
|
document.title = 'YesPlayMusic';
|
||||||
this._pauseDiscordPresence(this._currentTrack);
|
this._pauseDiscordPresence(this._currentTrack);
|
||||||
}
|
}
|
||||||
play() {
|
play() {
|
||||||
|
|
@ -536,7 +536,7 @@ export default class {
|
||||||
trackIDs,
|
trackIDs,
|
||||||
playlistSourceID,
|
playlistSourceID,
|
||||||
playlistSourceType,
|
playlistSourceType,
|
||||||
autoPlayTrackID = "first"
|
autoPlayTrackID = 'first'
|
||||||
) {
|
) {
|
||||||
this._isPersonalFM = false;
|
this._isPersonalFM = false;
|
||||||
if (!this._enabled) this._enabled = true;
|
if (!this._enabled) this._enabled = true;
|
||||||
|
|
@ -547,37 +547,37 @@ export default class {
|
||||||
id: playlistSourceID,
|
id: playlistSourceID,
|
||||||
};
|
};
|
||||||
if (this.shuffle) this._shuffleTheList(autoPlayTrackID);
|
if (this.shuffle) this._shuffleTheList(autoPlayTrackID);
|
||||||
if (autoPlayTrackID === "first") {
|
if (autoPlayTrackID === 'first') {
|
||||||
this._replaceCurrentTrack(this.list[0]);
|
this._replaceCurrentTrack(this.list[0]);
|
||||||
} else {
|
} else {
|
||||||
this.current = trackIDs.indexOf(autoPlayTrackID);
|
this.current = trackIDs.indexOf(autoPlayTrackID);
|
||||||
this._replaceCurrentTrack(autoPlayTrackID);
|
this._replaceCurrentTrack(autoPlayTrackID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playAlbumByID(id, trackID = "first") {
|
playAlbumByID(id, trackID = 'first') {
|
||||||
getAlbum(id).then((data) => {
|
getAlbum(id).then(data => {
|
||||||
let trackIDs = data.songs.map((t) => t.id);
|
let trackIDs = data.songs.map(t => t.id);
|
||||||
this.replacePlaylist(trackIDs, id, "album", trackID);
|
this.replacePlaylist(trackIDs, id, 'album', trackID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
playPlaylistByID(id, trackID = "first", noCache = false) {
|
playPlaylistByID(id, trackID = 'first', noCache = false) {
|
||||||
console.debug(
|
console.debug(
|
||||||
`[debug][Player.js] playPlaylistByID 👉 id:${id} trackID:${trackID} noCache:${noCache}`
|
`[debug][Player.js] playPlaylistByID 👉 id:${id} trackID:${trackID} noCache:${noCache}`
|
||||||
);
|
);
|
||||||
getPlaylistDetail(id, noCache).then((data) => {
|
getPlaylistDetail(id, noCache).then(data => {
|
||||||
let trackIDs = data.playlist.trackIds.map((t) => t.id);
|
let trackIDs = data.playlist.trackIds.map(t => t.id);
|
||||||
this.replacePlaylist(trackIDs, id, "playlist", trackID);
|
this.replacePlaylist(trackIDs, id, 'playlist', trackID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
playArtistByID(id, trackID = "first") {
|
playArtistByID(id, trackID = 'first') {
|
||||||
getArtist(id).then((data) => {
|
getArtist(id).then(data => {
|
||||||
let trackIDs = data.hotSongs.map((t) => t.id);
|
let trackIDs = data.hotSongs.map(t => t.id);
|
||||||
this.replacePlaylist(trackIDs, id, "artist", trackID);
|
this.replacePlaylist(trackIDs, id, 'artist', trackID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
playTrackOnListByID(id, listName = "default") {
|
playTrackOnListByID(id, listName = 'default') {
|
||||||
if (listName === "default") {
|
if (listName === 'default') {
|
||||||
this._current = this._list.findIndex((t) => t === id);
|
this._current = this._list.findIndex(t => t === id);
|
||||||
}
|
}
|
||||||
this._replaceCurrentTrack(id);
|
this._replaceCurrentTrack(id);
|
||||||
}
|
}
|
||||||
|
|
@ -604,19 +604,19 @@ export default class {
|
||||||
|
|
||||||
sendSelfToIpcMain() {
|
sendSelfToIpcMain() {
|
||||||
if (process.env.IS_ELECTRON !== true) return false;
|
if (process.env.IS_ELECTRON !== true) return false;
|
||||||
ipcRenderer.send("player", {
|
ipcRenderer.send('player', {
|
||||||
playing: this.playing,
|
playing: this.playing,
|
||||||
likedCurrentTrack: store.state.liked.songs.includes(this.currentTrack.id),
|
likedCurrentTrack: store.state.liked.songs.includes(this.currentTrack.id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchRepeatMode() {
|
switchRepeatMode() {
|
||||||
if (this._repeatMode === "on") {
|
if (this._repeatMode === 'on') {
|
||||||
this.repeatMode = "one";
|
this.repeatMode = 'one';
|
||||||
} else if (this._repeatMode === "one") {
|
} else if (this._repeatMode === 'one') {
|
||||||
this.repeatMode = "off";
|
this.repeatMode = 'off';
|
||||||
} else {
|
} else {
|
||||||
this.repeatMode = "on";
|
this.repeatMode = 'on';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switchShuffle() {
|
switchShuffle() {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<h1>
|
<h1>
|
||||||
<img class="avatar" :src="data.user.avatarUrl | resizeImage" />{{
|
<img class="avatar" :src="data.user.avatarUrl | resizeImage" />{{
|
||||||
data.user.nickname
|
data.user.nickname
|
||||||
}}{{ $t("library.sLibrary") }}
|
}}{{ $t('library.sLibrary') }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="section-one">
|
<div class="section-one">
|
||||||
<div class="liked-songs" @click="goToLikedSongsList">
|
<div class="liked-songs" @click="goToLikedSongsList">
|
||||||
|
|
@ -11,17 +11,17 @@
|
||||||
<p>
|
<p>
|
||||||
<span
|
<span
|
||||||
v-for="(line, index) in pickedLyric"
|
v-for="(line, index) in pickedLyric"
|
||||||
:key="`${line}${index}`"
|
|
||||||
v-show="line !== ''"
|
v-show="line !== ''"
|
||||||
|
:key="`${line}${index}`"
|
||||||
>{{ line }}<br
|
>{{ line }}<br
|
||||||
/></span>
|
/></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<div class="titles">
|
<div class="titles">
|
||||||
<div class="title">{{ $t("library.likedSongs") }}</div>
|
<div class="title">{{ $t('library.likedSongs') }}</div>
|
||||||
<div class="sub-title">
|
<div class="sub-title">
|
||||||
{{ likedSongsPlaylist.trackCount }} {{ $t("common.songs") }}
|
{{ liked.songs.length }} {{ $t('common.songs') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button @click.stop="playLikedSongs">
|
<button @click.stop="playLikedSongs">
|
||||||
|
|
@ -31,16 +31,16 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="songs">
|
<div class="songs">
|
||||||
<TrackList
|
<TrackList
|
||||||
:tracks="likedSongs"
|
:id="liked.playlist ? liked.playlist[0].id : 0"
|
||||||
:type="'tracklist'"
|
:tracks="liked.songsWithDetails"
|
||||||
:id="likedSongsPlaylist.id"
|
:column-number="3"
|
||||||
dbclickTrackFunc="playPlaylistByID"
|
type="tracklist"
|
||||||
:columnNumber="3"
|
dbclick-track-func="playPlaylistByID"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-two" id="liked">
|
<div id="liked" class="section-two">
|
||||||
<div class="tabs-row">
|
<div class="tabs-row">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div
|
<div
|
||||||
|
|
@ -48,157 +48,104 @@
|
||||||
:class="{ active: currentTab === 'playlists' }"
|
:class="{ active: currentTab === 'playlists' }"
|
||||||
@click="updateCurrentTab('playlists')"
|
@click="updateCurrentTab('playlists')"
|
||||||
>
|
>
|
||||||
{{ $t("library.playlists") }}
|
{{ $t('library.playlists') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab"
|
class="tab"
|
||||||
:class="{ active: currentTab === 'albums' }"
|
:class="{ active: currentTab === 'albums' }"
|
||||||
@click="updateCurrentTab('albums')"
|
@click="updateCurrentTab('albums')"
|
||||||
>
|
>
|
||||||
{{ $t("library.albums") }}
|
{{ $t('library.albums') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab"
|
class="tab"
|
||||||
:class="{ active: currentTab === 'artists' }"
|
:class="{ active: currentTab === 'artists' }"
|
||||||
@click="updateCurrentTab('artists')"
|
@click="updateCurrentTab('artists')"
|
||||||
>
|
>
|
||||||
{{ $t("library.artists") }}
|
{{ $t('library.artists') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab"
|
class="tab"
|
||||||
:class="{ active: currentTab === 'mvs' }"
|
:class="{ active: currentTab === 'mvs' }"
|
||||||
@click="updateCurrentTab('mvs')"
|
@click="updateCurrentTab('mvs')"
|
||||||
>
|
>
|
||||||
{{ $t("library.mvs") }}
|
{{ $t('library.mvs') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
v-show="currentTab === 'playlists'"
|
||||||
class="add-playlist"
|
class="add-playlist"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
v-show="currentTab === 'playlists'"
|
|
||||||
@click="openAddPlaylistModal"
|
@click="openAddPlaylistModal"
|
||||||
><svg-icon icon-class="plus" />{{ $t("library.newPlayList") }}</button
|
><svg-icon icon-class="plus" />{{ $t('library.newPlayList') }}</button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="currentTab === 'playlists'">
|
<div v-show="currentTab === 'playlists'">
|
||||||
<div v-if="playlists.length > 1">
|
<div v-if="liked.playlists.length > 1">
|
||||||
<CoverRow
|
<CoverRow
|
||||||
:items="playlists.slice(1)"
|
:items="liked.playlists.slice(1)"
|
||||||
type="playlist"
|
type="playlist"
|
||||||
subText="creator"
|
sub-text="creator"
|
||||||
:showPlayButton="true"
|
:show-play-button="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="currentTab === 'albums'">
|
<div v-show="currentTab === 'albums'">
|
||||||
<CoverRow
|
<CoverRow
|
||||||
:items="albums"
|
:items="liked.albums"
|
||||||
type="album"
|
type="album"
|
||||||
subText="artist"
|
sub-text="artist"
|
||||||
:showPlayButton="true"
|
:show-play-button="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="currentTab === 'artists'">
|
<div v-show="currentTab === 'artists'">
|
||||||
<CoverRow :items="artists" type="artist" :showPlayButton="true" />
|
<CoverRow
|
||||||
|
:items="liked.artists"
|
||||||
|
type="artist"
|
||||||
|
:show-play-button="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="currentTab === 'mvs'">
|
<div v-show="currentTab === 'mvs'">
|
||||||
<MvRow :mvs="mvs" />
|
<MvRow :mvs="liked.mvs" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapActions, mapMutations, mapState } from "vuex";
|
import { mapActions, mapMutations, mapState } from 'vuex';
|
||||||
import { getTrackDetail, getLyric } from "@/api/track";
|
import { getLyric } from '@/api/track';
|
||||||
import {
|
import { randomNum, dailyTask } from '@/utils/common';
|
||||||
userDetail,
|
import { isAccountLoggedIn } from '@/utils/auth';
|
||||||
userAccount,
|
import NProgress from 'nprogress';
|
||||||
userPlaylist,
|
|
||||||
likedAlbums,
|
|
||||||
likedArtists,
|
|
||||||
likedMVs,
|
|
||||||
} from "@/api/user";
|
|
||||||
import { randomNum, dailyTask } from "@/utils/common";
|
|
||||||
import { getPlaylistDetail } from "@/api/playlist";
|
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
|
||||||
import NProgress from "nprogress";
|
|
||||||
|
|
||||||
import TrackList from "@/components/TrackList.vue";
|
import TrackList from '@/components/TrackList.vue';
|
||||||
import CoverRow from "@/components/CoverRow.vue";
|
import CoverRow from '@/components/CoverRow.vue';
|
||||||
import SvgIcon from "@/components/SvgIcon.vue";
|
import SvgIcon from '@/components/SvgIcon.vue';
|
||||||
import MvRow from "@/components/MvRow.vue";
|
import MvRow from '@/components/MvRow.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Library",
|
name: 'Library',
|
||||||
components: { SvgIcon, CoverRow, TrackList, MvRow },
|
components: { SvgIcon, CoverRow, TrackList, MvRow },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: false,
|
show: false,
|
||||||
playlists: [],
|
|
||||||
hasMorePlaylists: true,
|
|
||||||
likedSongsPlaylist: {
|
|
||||||
id: 0,
|
|
||||||
trackCount: 0,
|
|
||||||
},
|
|
||||||
likedSongs: [],
|
likedSongs: [],
|
||||||
likedSongIDs: [],
|
|
||||||
lyric: undefined,
|
lyric: undefined,
|
||||||
currentTab: "playlists",
|
currentTab: 'playlists',
|
||||||
albums: [],
|
|
||||||
artists: [],
|
|
||||||
mvs: [],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
NProgress.start();
|
|
||||||
if (isAccountLoggedIn()) {
|
|
||||||
userAccount().then((result) => {
|
|
||||||
this.$store.commit("updateData", {
|
|
||||||
key: "user",
|
|
||||||
value: result.profile,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
userDetail(this.data.user.userId).then((result) => {
|
|
||||||
this.$store.commit("updateData", {
|
|
||||||
key: "user",
|
|
||||||
value: result.profile,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activated() {
|
|
||||||
if (!this.data.likedSongPlaylistID) {
|
|
||||||
userPlaylist({
|
|
||||||
uid: this.data.user.userId,
|
|
||||||
limit: 1,
|
|
||||||
}).then((data) => {
|
|
||||||
this.updateData({
|
|
||||||
key: "likedSongPlaylistID",
|
|
||||||
value: data.playlist[0].id,
|
|
||||||
});
|
|
||||||
this.loadData();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
dailyTask();
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["data"]),
|
...mapState(['data', 'liked']),
|
||||||
likedSongsInState() {
|
|
||||||
return this.$store.state.liked.songs;
|
|
||||||
},
|
|
||||||
pickedLyric() {
|
pickedLyric() {
|
||||||
if (this.lyric === undefined) return "";
|
if (this.lyric === undefined) return '';
|
||||||
let lyric = this.lyric.split("\n");
|
let lyric = this.lyric.split('\n');
|
||||||
lyric = lyric.filter((l) => {
|
lyric = lyric.filter(l => {
|
||||||
if (l.includes("作词") || l.includes("作曲")) {
|
if (l.includes('作词') || l.includes('作曲')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -208,132 +155,76 @@ export default {
|
||||||
lineIndex = randomNum(0, lyric.length - 1);
|
lineIndex = randomNum(0, lyric.length - 1);
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
lyric[lineIndex].split("]")[1],
|
lyric[lineIndex].split(']')[1],
|
||||||
lyric[lineIndex + 1].split("]")[1],
|
lyric[lineIndex + 1].split(']')[1],
|
||||||
lyric[lineIndex + 2].split("]")[1],
|
lyric[lineIndex + 2].split(']')[1],
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
NProgress.start();
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
if (this.liked.songsWithDetails.length > 0) {
|
||||||
|
NProgress.done();
|
||||||
|
this.show = true;
|
||||||
|
this.getRandomLyric();
|
||||||
|
} else {
|
||||||
|
this.$store.dispatch('fetchLikedSongsWithDetails').then(() => {
|
||||||
|
NProgress.done();
|
||||||
|
this.show = true;
|
||||||
|
this.getRandomLyric();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.$store.dispatch('fetchLikedSongs');
|
||||||
|
this.$store.dispatch('fetchLikedPlaylist');
|
||||||
|
this.$store.dispatch('fetchLikedAlbums');
|
||||||
|
this.$store.dispatch('fetchLikedArtists');
|
||||||
|
this.$store.dispatch('fetchLikedMVs');
|
||||||
|
dailyTask();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["showToast"]),
|
...mapActions(['showToast']),
|
||||||
...mapMutations(["updateModal", "updateData"]),
|
...mapMutations(['updateModal', 'updateData']),
|
||||||
playLikedSongs() {
|
playLikedSongs() {
|
||||||
this.$store.state.player.playPlaylistByID(
|
this.$store.state.player.playPlaylistByID(
|
||||||
this.playlists[0].id,
|
this.liked.playlists[0].id,
|
||||||
"first",
|
'first',
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
updateCurrentTab(tab) {
|
updateCurrentTab(tab) {
|
||||||
if (!isAccountLoggedIn() && tab !== "playlists") {
|
if (!isAccountLoggedIn() && tab !== 'playlists') {
|
||||||
this.showToast("此操作需要登录网易云账号");
|
this.showToast('此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentTab = tab;
|
this.currentTab = tab;
|
||||||
document
|
document
|
||||||
.getElementById("liked")
|
.getElementById('liked')
|
||||||
.scrollIntoView({ block: "start", behavior: "smooth" });
|
.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||||
if (tab === "albums") {
|
|
||||||
if (this.albums.length === 0) this.loadLikedAlbums();
|
|
||||||
} else if (tab === "artists") {
|
|
||||||
if (this.artists.length === 0) this.loadLikedArtists();
|
|
||||||
} else if (tab === "mvs") {
|
|
||||||
if (this.mvs.length === 0) this.loadLikedMVs();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
goToLikedSongsList() {
|
goToLikedSongsList() {
|
||||||
this.$router.push({ path: "/library/liked-songs" });
|
this.$router.push({ path: '/library/liked-songs' });
|
||||||
},
|
|
||||||
loadData() {
|
|
||||||
if (this.hasMorePlaylists && this.currentTab === "playlists") {
|
|
||||||
this.getUserPlaylists();
|
|
||||||
}
|
|
||||||
if (this.currentTab === "albums") {
|
|
||||||
this.loadLikedAlbums();
|
|
||||||
} else if (this.currentTab === "artists") {
|
|
||||||
this.loadLikedArtists();
|
|
||||||
} else if (this.currentTab === "mvs") {
|
|
||||||
this.loadLikedMVs();
|
|
||||||
}
|
|
||||||
this.getLikedSongs();
|
|
||||||
},
|
|
||||||
getUserPlaylists(replace = false) {
|
|
||||||
userPlaylist({
|
|
||||||
uid: this.data.user.userId,
|
|
||||||
offset: this.playlists.length === 0 ? 0 : this.playlists.length - 1,
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
}).then((data) => {
|
|
||||||
if (replace) {
|
|
||||||
this.playlists = data.playlist;
|
|
||||||
} else {
|
|
||||||
this.playlists.push(...data.playlist);
|
|
||||||
}
|
|
||||||
this.hasMorePlaylists = data.more;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getLikedSongs(getLyric = true) {
|
|
||||||
getPlaylistDetail(this.data.likedSongPlaylistID, true).then((data) => {
|
|
||||||
this.likedSongsPlaylist = data.playlist;
|
|
||||||
if (data.playlist.trackIds.length === 0) {
|
|
||||||
NProgress.done();
|
|
||||||
this.show = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let TrackIDs = data.playlist.trackIds.slice(0, 12).map((t) => t.id);
|
|
||||||
this.likedSongIDs = TrackIDs;
|
|
||||||
getTrackDetail(this.likedSongIDs.join(",")).then((data) => {
|
|
||||||
this.likedSongs = data.songs;
|
|
||||||
NProgress.done();
|
|
||||||
this.show = true;
|
|
||||||
});
|
|
||||||
if (getLyric) this.getRandomLyric();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
getRandomLyric() {
|
getRandomLyric() {
|
||||||
getLyric(
|
getLyric(
|
||||||
this.likedSongIDs[randomNum(0, this.likedSongIDs.length - 1)]
|
this.liked.songs[randomNum(0, this.liked.songs.length - 1)]
|
||||||
).then((data) => {
|
).then(data => {
|
||||||
if (data.lrc !== undefined) this.lyric = data.lrc.lyric;
|
if (data.lrc !== undefined) this.lyric = data.lrc.lyric;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
loadLikedAlbums() {
|
|
||||||
NProgress.start();
|
|
||||||
likedAlbums().then((data) => {
|
|
||||||
this.albums = data.data;
|
|
||||||
NProgress.done();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadLikedArtists() {
|
|
||||||
NProgress.start();
|
|
||||||
likedArtists().then((data) => {
|
|
||||||
this.artists = data.data;
|
|
||||||
NProgress.done();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadLikedMVs() {
|
|
||||||
NProgress.start();
|
|
||||||
likedMVs().then((data) => {
|
|
||||||
this.mvs = data.data;
|
|
||||||
NProgress.done();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
openAddPlaylistModal() {
|
openAddPlaylistModal() {
|
||||||
if (!isAccountLoggedIn()) {
|
if (!isAccountLoggedIn()) {
|
||||||
this.showToast("此操作需要登录网易云账号");
|
this.showToast('此操作需要登录网易云账号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.updateModal({
|
this.updateModal({
|
||||||
modalName: "newPlaylistModal",
|
modalName: 'newPlaylistModal',
|
||||||
key: "show",
|
key: 'show',
|
||||||
value: true,
|
value: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
likedSongsInState() {
|
|
||||||
this.getLikedSongs(false);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,19 +69,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<span>{{ formatTrackTime(player.progress) || "0:00" }}</span>
|
<span>{{ formatTrackTime(player.progress) || '0:00' }}</span>
|
||||||
<div class="slider">
|
<div class="slider">
|
||||||
<vue-slider
|
<vue-slider
|
||||||
v-model="player.progress"
|
v-model="player.progress"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="player.currentTrackDuration"
|
:max="player.currentTrackDuration + 1"
|
||||||
:interval="1"
|
:interval="1"
|
||||||
:drag-on-click="true"
|
:drag-on-click="true"
|
||||||
:duration="0"
|
:duration="0"
|
||||||
:dot-size="12"
|
:dot-size="12"
|
||||||
:height="2"
|
:height="2"
|
||||||
:tooltip-formatter="formatTrackTime"
|
:tooltip-formatter="formatTrackTime"
|
||||||
@drag-end="player.seek"
|
:lazy="true"
|
||||||
></vue-slider>
|
></vue-slider>
|
||||||
</div>
|
</div>
|
||||||
<span>{{ formatTrackTime(player.currentTrackDuration) }}</span>
|
<span>{{ formatTrackTime(player.currentTrackDuration) }}</span>
|
||||||
|
|
@ -184,15 +184,15 @@
|
||||||
// The lyrics page of Apple Music is so gorgeous, so I copy the design.
|
// The lyrics page of Apple Music is so gorgeous, so I copy the design.
|
||||||
// Some of the codes are from https://github.com/sl1673495/vue-netease-music
|
// Some of the codes are from https://github.com/sl1673495/vue-netease-music
|
||||||
|
|
||||||
import { mapState, mapMutations, mapActions } from "vuex";
|
import { mapState, mapMutations, mapActions } from 'vuex';
|
||||||
import VueSlider from "vue-slider-component";
|
import VueSlider from 'vue-slider-component';
|
||||||
import { formatTrackTime } from "@/utils/common";
|
import { formatTrackTime } from '@/utils/common';
|
||||||
import { getLyric } from "@/api/track";
|
import { getLyric } from '@/api/track';
|
||||||
import { lyricParser } from "@/utils/lyrics";
|
import { lyricParser } from '@/utils/lyrics';
|
||||||
import ButtonIcon from "@/components/ButtonIcon.vue";
|
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Lyrics",
|
name: 'Lyrics',
|
||||||
components: {
|
components: {
|
||||||
VueSlider,
|
VueSlider,
|
||||||
ButtonIcon,
|
ButtonIcon,
|
||||||
|
|
@ -207,12 +207,12 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["player", "settings", "showLyrics"]),
|
...mapState(['player', 'settings', 'showLyrics']),
|
||||||
currentTrack() {
|
currentTrack() {
|
||||||
return this.player.currentTrack;
|
return this.player.currentTrack;
|
||||||
},
|
},
|
||||||
imageUrl() {
|
imageUrl() {
|
||||||
return this.player.currentTrack?.al?.picUrl + "?param=1024y1024";
|
return this.player.currentTrack?.al?.picUrl + '?param=1024y1024';
|
||||||
},
|
},
|
||||||
lyricWithTranslation() {
|
lyricWithTranslation() {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
|
|
@ -222,7 +222,7 @@ export default {
|
||||||
);
|
);
|
||||||
// content统一转换数组形式
|
// content统一转换数组形式
|
||||||
if (lyricFiltered.length) {
|
if (lyricFiltered.length) {
|
||||||
lyricFiltered.forEach((l) => {
|
lyricFiltered.forEach(l => {
|
||||||
const { rawTime, time, content } = l;
|
const { rawTime, time, content } = l;
|
||||||
const lyricItem = { time, content, contents: [content] };
|
const lyricItem = { time, content, contents: [content] };
|
||||||
const sameTimeTLyric = this.tlyric.find(
|
const sameTimeTLyric = this.tlyric.find(
|
||||||
|
|
@ -259,10 +259,10 @@ export default {
|
||||||
artist() {
|
artist() {
|
||||||
return this.currentTrack?.ar
|
return this.currentTrack?.ar
|
||||||
? this.currentTrack.ar[0]
|
? this.currentTrack.ar[0]
|
||||||
: { id: 0, name: "unknown" };
|
: { id: 0, name: 'unknown' };
|
||||||
},
|
},
|
||||||
album() {
|
album() {
|
||||||
return this.currentTrack?.al || { id: 0, name: "unknown" };
|
return this.currentTrack?.al || { id: 0, name: 'unknown' };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -284,11 +284,11 @@ export default {
|
||||||
clearInterval(this.lyricsInterval);
|
clearInterval(this.lyricsInterval);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(["toggleLyrics"]),
|
...mapMutations(['toggleLyrics']),
|
||||||
...mapActions(["likeASong"]),
|
...mapActions(['likeASong']),
|
||||||
getLyric() {
|
getLyric() {
|
||||||
if (!this.currentTrack.id) return;
|
if (!this.currentTrack.id) return;
|
||||||
return getLyric(this.currentTrack.id).then((data) => {
|
return getLyric(this.currentTrack.id).then(data => {
|
||||||
if (!data?.lrc?.lyric) {
|
if (!data?.lrc?.lyric) {
|
||||||
this.lyric = [];
|
this.lyric = [];
|
||||||
this.tlyric = [];
|
this.tlyric = [];
|
||||||
|
|
@ -327,8 +327,8 @@ export default {
|
||||||
const el = document.getElementById(`line${this.highlightLyricIndex}`);
|
const el = document.getElementById(`line${this.highlightLyricIndex}`);
|
||||||
if (el)
|
if (el)
|
||||||
el.scrollIntoView({
|
el.scrollIntoView({
|
||||||
behavior: "smooth",
|
behavior: 'smooth',
|
||||||
block: "center",
|
block: 'center',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
@ -341,7 +341,7 @@ export default {
|
||||||
} else if (line.contents[0] !== undefined) {
|
} else if (line.contents[0] !== undefined) {
|
||||||
return `<span>${line.contents[0]}</span>`;
|
return `<span>${line.contents[0]}</span>`;
|
||||||
}
|
}
|
||||||
return "unknown";
|
return 'unknown';
|
||||||
},
|
},
|
||||||
moveToFMTrash() {
|
moveToFMTrash() {
|
||||||
this.player.moveToFMTrash();
|
this.player.moveToFMTrash();
|
||||||
|
|
@ -367,7 +367,7 @@ export default {
|
||||||
--brightness-dynamic-background: 150%;
|
--brightness-dynamic-background: 150%;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .dynamic-background {
|
[data-theme='dark'] .dynamic-background {
|
||||||
--contrast-dynamic-background: 125%;
|
--contrast-dynamic-background: 125%;
|
||||||
--brightness-dynamic-background: 50%;
|
--brightness-dynamic-background: 50%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue