feat: support cloud disk

This commit is contained in:
qier222 2021-06-05 21:14:06 +08:00
parent 996904f056
commit 571d0d71f8
No known key found for this signature in database
GPG key ID: 9C85007ED905F14D
10 changed files with 250 additions and 35 deletions

View file

@ -240,6 +240,8 @@ export default {
this.$router.push({ path: '/library/liked-songs' });
} else if (this.player.playlistSource.type === 'url') {
this.$router.push({ path: this.player.playlistSource.id });
} else if (this.player.playlistSource.type === 'cloudDisk') {
this.$router.push({ path: '/library' });
} else {
this.$router.push({
path:

View file

@ -1,14 +1,14 @@
<template>
<div class="track-list">
<ContextMenu ref="menu">
<div class="item-info">
<img :src="rightClickedTrack.al.picUrl | resizeImage(224)" />
<div v-show="type !== 'cloudDisk'" class="item-info">
<img :src="rightClickedTrackComputed.al.picUrl | resizeImage(224)" />
<div class="info">
<div class="title">{{ rightClickedTrack.name }}</div>
<div class="subtitle">{{ rightClickedTrack.ar[0].name }}</div>
<div class="title">{{ rightClickedTrackComputed.name }}</div>
<div class="subtitle">{{ rightClickedTrackComputed.ar[0].name }}</div>
</div>
</div>
<hr />
<hr v-show="type !== 'cloudDisk'" />
<div class="item" @click="play">{{ $t('contextMenu.play') }}</div>
<div class="item" @click="addToQueue">{{
$t('contextMenu.addToQueue')
@ -19,11 +19,19 @@
@click="removeTrackFromQueue"
>从队列删除</div
>
<hr />
<div v-show="!isRightClickedTrackLiked" class="item" @click="like">
<hr v-show="type !== 'cloudDisk'" />
<div
v-show="!isRightClickedTrackLiked && type !== 'cloudDisk'"
class="item"
@click="like"
>
{{ $t('contextMenu.saveToMyLikedSongs') }}
</div>
<div v-show="isRightClickedTrackLiked" class="item" @click="like">
<div
v-show="isRightClickedTrackLiked && type !== 'cloudDisk'"
class="item"
@click="like"
>
{{ $t('contextMenu.removeFromMyLikedSongs') }}
</div>
<div
@ -32,17 +40,27 @@
@click="removeTrackFromPlaylist"
>从歌单中删除</div
>
<div class="item" @click="addTrackToPlaylist">{{
$t('contextMenu.addToPlaylist')
}}</div>
<div
v-show="type !== 'cloudDisk'"
class="item"
@click="addTrackToPlaylist"
>{{ $t('contextMenu.addToPlaylist') }}</div
>
<div
v-if="extraContextMenuItem.includes('removeTrackFromCloudDisk')"
class="item"
@click="removeTrackFromCloudDisk"
>从云盘中删除</div
>
</ContextMenu>
<div :style="listStyles">
<TrackListItem
v-for="(track, index) in tracks"
:key="itemKey === 'id' ? track.id : `${track.id}${index}`"
:track="track"
:track-prop="track"
:highlight-playing-track="highlightPlayingTrack"
@dblclick.native="playThisList(track.id)"
@dblclick.native="playThisList(track.id || track.songId)"
@click.right.native="openMenu($event, track, index)"
/>
</div>
@ -52,6 +70,7 @@
<script>
import { mapActions, mapMutations, mapState } from 'vuex';
import { addOrRemoveTrackFromPlaylist } from '@/api/playlist';
import { cloudDiskTrackDelete } from '@/api/user';
import { isAccountLoggedIn } from '@/utils/auth';
import TrackListItem from '@/components/TrackListItem.vue';
@ -65,9 +84,20 @@ export default {
ContextMenu,
},
props: {
tracks: Array,
type: String,
id: Number,
tracks: {
type: Array,
default: () => {
return [];
},
},
type: {
type: String,
default: 'tracklist',
}, // tracklist | album | playlist | cloudDisk
id: {
type: Number,
default: 0,
},
dbclickTrackFunc: {
type: String,
default: 'default',
@ -88,6 +118,7 @@ export default {
return [
// 'removeTrackFromPlaylist'
// 'removeTrackFromQueue'
// 'removeTrackFromCloudDisk'
];
},
},
@ -121,6 +152,16 @@ export default {
isRightClickedTrackLiked() {
return this.liked.songs.includes(this.rightClickedTrack?.id);
},
rightClickedTrackComputed() {
return this.type === 'cloudDisk'
? {
id: 0,
name: '',
ar: [{ name: '' }],
al: { picUrl: '' },
}
: this.rightClickedTrack;
},
},
created() {
if (this.type === 'tracklist') {
@ -158,11 +199,14 @@ export default {
} else if (this.dbclickTrackFunc === 'playPlaylistByID') {
this.player.playPlaylistByID(this.id, trackID);
} else if (this.dbclickTrackFunc === 'playAList') {
let trackIDs = this.tracks.map(t => t.id);
let trackIDs = this.tracks.map(t => t.id || t.songId);
this.player.replacePlaylist(trackIDs, this.id, 'artist', trackID);
} else if (this.dbclickTrackFunc === 'dailyTracks') {
let trackIDs = this.tracks.map(t => t.id);
this.player.replacePlaylist(trackIDs, '/daily/songs', 'url', trackID);
} else if (this.dbclickTrackFunc === 'playCloudDisk') {
let trackIDs = this.tracks.map(t => t.id || t.songId);
this.player.replacePlaylist(trackIDs, this.id, 'cloudDisk', trackID);
}
},
playThisListDefault(trackID) {
@ -226,6 +270,23 @@ export default {
this.rightClickedTrackIndex
);
},
removeTrackFromCloudDisk() {
if (confirm(`确定要从云盘删除 ${this.rightClickedTrack.songName}`)) {
let trackID = this.rightClickedTrack.songId;
cloudDiskTrackDelete(trackID).then(data => {
this.showToast(
data.code === 200 ? '已将此歌曲从云盘删除' : data.message
);
let newCloudDisk = this.liked.cloudDisk.filter(
t => t.songId !== trackID
);
this.$store.commit('updateLikedXXX', {
name: 'cloudDisk',
data: newCloudDisk,
});
});
}
},
},
};
</script>

View file

@ -13,7 +13,7 @@
:class="{ hover: focus }"
@click="goToAlbum"
/>
<div v-if="isAlbum" class="no">
<div v-if="showOrderNumber" class="no">
<button v-show="focus && track.playable && !isPlaying" @click="playTrack">
<svg-icon
icon-class="play"
@ -37,7 +37,7 @@
<span v-if="isAlbum" class="featured">
<ArtistsInLine
:artists="track.ar"
:exclude="this.$parent.albumObject.artist.name"
:exclude="$parent.albumObject.artist.name"
prefix="-"
/></span>
<span v-if="isAlbum && track.mark === 1318912" class="explicit-symbol"
@ -58,11 +58,13 @@
</div>
<div></div>
</div>
<div v-if="!isTracklist && !isAlbum" class="album">
<div v-if="showAlbumName" class="album">
<router-link :to="`/album/${album.id}`">{{ album.name }}</router-link>
<div></div>
</div>
<div v-if="!isTracklist" class="actions">
<div v-if="showLikeButton" class="actions">
<button @click="likeThisSong">
<svg-icon
icon-class="heart"
@ -73,7 +75,7 @@
<svg-icon v-show="isLiked" icon-class="heart-solid"></svg-icon>
</button>
</div>
<div v-if="!isTracklist" class="time">
<div v-if="showTrackTime" class="time">
{{ track.dt | formatTime }}
</div>
</div>
@ -87,18 +89,26 @@ import { mapState } from 'vuex';
export default {
name: 'TrackListItem',
components: { ArtistsInLine, ExplicitSymbol },
props: {
track: Object,
trackProp: Object,
highlightPlayingTrack: {
type: Boolean,
default: true,
},
},
data() {
return { hover: false, trackStyle: {} };
},
computed: {
...mapState(['settings']),
track() {
return this.type === 'cloudDisk'
? this.trackProp.simpleSong
: this.trackProp;
},
imgUrl() {
let image =
this.track?.al?.picUrl ??
@ -112,7 +122,7 @@ export default {
return [];
},
album() {
return this.track.album || this.track.al;
return this.track.album || this.track.al || this.track?.simpleSong?.al;
},
translate() {
let t;
@ -134,17 +144,14 @@ export default {
this.track.alia?.length > 0
);
},
isTracklist() {
return this.type === 'tracklist';
},
isPlaylist() {
return this.type === 'playlist';
},
isLiked() {
return this.$parent.liked.songs.includes(this.track.id);
return this.$parent.liked.songs.includes(this.track?.id);
},
isPlaying() {
return this.$store.state.player.currentTrack.id === this.track.id;
return this.$store.state.player.currentTrack.id === this.track?.id;
},
trackClass() {
let trackClass = [this.type];
@ -169,7 +176,20 @@ export default {
? !this.$store.state.settings.enableUnblockNeteaseMusic
: true;
},
showLikeButton() {
return this.type !== 'tracklist' && this.type !== 'cloudDisk';
},
showOrderNumber() {
return this.type === 'album';
},
showAlbumName() {
return this.type !== 'album' && this.type !== 'tracklist';
},
showTrackTime() {
return this.type !== 'tracklist';
},
},
methods: {
goToAlbum() {
this.$router.push({ path: '/album/' + this.track.al.id });