mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 09:41:49 +08:00
fix: conflict
This commit is contained in:
commit
720d0b3116
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -27,3 +27,6 @@ pnpm-debug.log*
|
|||
|
||||
#Electron-builder output
|
||||
/dist_electron
|
||||
|
||||
NeteaseCloudMusicApi-master
|
||||
NeteaseCloudMusicApi-master.zip
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
build
|
||||
coverage
|
||||
dist
|
||||
NeteaseCloudMusicApi-master
|
||||
NeteaseCloudMusicApi-master.zip
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "yes-play-music",
|
||||
"version": "0.1.0",
|
||||
"name": "YesPlayMusic",
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
|
|
|
@ -37,3 +37,34 @@ export function newAlbums(params) {
|
|||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 专辑动态信息
|
||||
* 说明 : 调用此接口 , 传入专辑 id, 可获得专辑动态信息,如是否收藏,收藏数,评论数,分享数
|
||||
* - id - 专辑id
|
||||
* @param {number} id
|
||||
*/
|
||||
export function albumDynamicDetail(id) {
|
||||
return request({
|
||||
url: "/album/detail/dynamic",
|
||||
method: "get",
|
||||
params: { id, timestamp: new Date().getTime() },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏/取消收藏专辑
|
||||
* 说明 : 调用此接口,可收藏/取消收藏专辑
|
||||
* - id - 返专辑 id
|
||||
* - t - 1 为收藏,其他为取消收藏
|
||||
* @param {Object} params
|
||||
* @param {number} params.id
|
||||
* @param {number} params.t
|
||||
*/
|
||||
export function likeAAlbum(params) {
|
||||
return request({
|
||||
url: "/album/sub",
|
||||
method: "post",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ export function getArtist(id) {
|
|||
method: "get",
|
||||
params: {
|
||||
id,
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
}).then((data) => {
|
||||
data.hotSongs = mapTrackPlayableStatus(data.hotSongs);
|
||||
|
@ -71,3 +72,20 @@ export function artistMv(id) {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏歌手
|
||||
* 说明 : 调用此接口 , 传入歌手 id, 可收藏歌手
|
||||
* - id: 歌手 id
|
||||
* - t: 操作,1 为收藏,其他为取消收藏
|
||||
* @param {Object} params
|
||||
* @param {number} params.id
|
||||
* @param {number} params.t
|
||||
*/
|
||||
export function followAArtist(params) {
|
||||
return request({
|
||||
url: "/artist/sub",
|
||||
method: "post",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ export function userPlaylist(params) {
|
|||
}
|
||||
|
||||
/**
|
||||
* 喜欢音乐列表
|
||||
* 喜欢音乐列表(需要登录)
|
||||
* 说明 : 调用此接口 , 传入用户 id, 可获取已喜欢音乐id列表(id数组)
|
||||
* - uid: 用户 id
|
||||
* @param {number} uid
|
||||
|
@ -52,8 +52,13 @@ export function userLikedSongsIDs(uid) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 每日签到
|
||||
* 说明 : 调用此接口可签到获取积分
|
||||
* - type: 签到类型 , 默认 0, 其中 0 为安卓端签到 ,1 为 web/PC 签到
|
||||
* @param {number} type
|
||||
*/
|
||||
export function dailySignin(type = 0) {
|
||||
//可选参数 : type: 签到类型 , 默认 0, 其中 0 为安卓端签到 ,1 为 web/PC 签到
|
||||
return request({
|
||||
url: "/daily_signin",
|
||||
method: "post",
|
||||
|
@ -62,3 +67,50 @@ export function dailySignin(type = 0) {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏的专辑(需要登录)
|
||||
* 说明 : 调用此接口可获取到用户收藏的专辑
|
||||
* - limit : 返回数量 , 默认为 30
|
||||
* - offset : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0
|
||||
* @param {Object} params
|
||||
* @param {number} params.limit
|
||||
* @param {number=} params.offset
|
||||
*/
|
||||
export function likedAlbums() {
|
||||
return request({
|
||||
url: "/album/sublist",
|
||||
method: "get",
|
||||
params: {
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏的歌手(需要登录)
|
||||
* 说明 : 调用此接口可获取到用户收藏的歌手
|
||||
*/
|
||||
export function likedArtists() {
|
||||
return request({
|
||||
url: "/artist/sublist",
|
||||
method: "get",
|
||||
params: {
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏的MV(需要登录)
|
||||
* 说明 : 调用此接口可获取到用户收藏的MV
|
||||
*/
|
||||
export function likedMVs() {
|
||||
return request({
|
||||
url: "/mv/sublist",
|
||||
method: "get",
|
||||
params: {
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -49,10 +49,13 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
button {
|
||||
height: 40px;
|
||||
min-width: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
line-height: 18px;
|
||||
font-weight: 600;
|
||||
background-color: var(--color-primary-bg);
|
||||
color: var(--color-primary);
|
||||
|
|
|
@ -76,8 +76,9 @@ export default {
|
|||
created() {
|
||||
this.shadowStyle = {
|
||||
height: `${this.size}px`,
|
||||
width: `${this.size}px`,
|
||||
width: `${~~(this.size * 0.96)}px`,
|
||||
top: `${this.shadowMargin}px`,
|
||||
right: `${~~(this.size * 0.02)}px`,
|
||||
borderRadius: `${this.radius}px`,
|
||||
};
|
||||
this.playButtonStyle = {
|
||||
|
@ -165,6 +166,13 @@ export default {
|
|||
height: 208px;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
[data-theme="dark"] {
|
||||
.shadow {
|
||||
filter: blur(16px) brightness(68%);
|
||||
transform: scale(0.96);
|
||||
}
|
||||
}
|
||||
|
||||
.play-button {
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
|
|
|
@ -95,8 +95,12 @@ export default {
|
|||
if (this.subText === "creator") return "by " + item.creator.nickname;
|
||||
if (this.subText === "releaseYear")
|
||||
return new Date(item.publishTime).getFullYear();
|
||||
if (this.subText === "artist")
|
||||
return `<a href="/#/artist/${item.artist.id}">${item.artist.name}</a>`;
|
||||
if (this.subText === "artist") {
|
||||
if (item.artist !== undefined)
|
||||
return `<a href="/#/artist/${item.artist.id}">${item.artist.name}</a>`;
|
||||
if (item.artists !== undefined)
|
||||
return `<a href="/#/artist/${item.artists[0].id}">${item.artists[0].name}</a>`;
|
||||
}
|
||||
if (this.subText === "albumType+releaseYear") {
|
||||
let albumType = item.type;
|
||||
if (item.type === "EP/Single") {
|
||||
|
|
|
@ -1,34 +1,27 @@
|
|||
<template>
|
||||
<div class="mv-row">
|
||||
<div class="mv" v-for="mv in mvs" :key="mv.id">
|
||||
<div class="mv" v-for="mv in mvs" :key="getID(mv)">
|
||||
<div class="cover-container">
|
||||
<img
|
||||
class="cover"
|
||||
:src="getUrl(mv)"
|
||||
@mouseover="hoverVideoID = mv.id"
|
||||
@mouseover="hoverVideoID = getID(mv)"
|
||||
@mouseleave="hoverVideoID = 0"
|
||||
@click="goToMv(mv.id)"
|
||||
@click="goToMv(getID(mv))"
|
||||
/>
|
||||
<transition name="fade">
|
||||
<img
|
||||
class="shadow"
|
||||
v-show="hoverVideoID === mv.id"
|
||||
v-show="hoverVideoID === getID(mv)"
|
||||
:src="getUrl(mv)"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title">
|
||||
<router-link :to="'/mv/' + mv.id">{{ mv.name }}</router-link>
|
||||
</div>
|
||||
<div class="artist">
|
||||
<router-link
|
||||
v-if="subtitle === 'artist'"
|
||||
:to="'/artist/' + mv.artistId"
|
||||
>{{ mv.artistName }}</router-link
|
||||
>
|
||||
<span v-if="subtitle === 'publishTime'">{{ mv.publishTime }}</span>
|
||||
<router-link :to="'/mv/' + getID(mv)">{{ getTitle(mv) }}</router-link>
|
||||
</div>
|
||||
<div class="artist" v-html="getSubtitle(mv)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -62,6 +55,30 @@ export default {
|
|||
if (mv.imgurl16v9 !== undefined) return mv.imgurl16v9;
|
||||
if (mv.coverUrl !== undefined) return mv.coverUrl;
|
||||
},
|
||||
getID(mv) {
|
||||
if (mv.id !== undefined) return mv.id;
|
||||
if (mv.vid !== undefined) return mv.vid;
|
||||
},
|
||||
getTitle(mv) {
|
||||
if (mv.name !== undefined) return mv.name;
|
||||
if (mv.title !== undefined) return mv.title;
|
||||
},
|
||||
getSubtitle(mv) {
|
||||
if (this.subtitle === "artist") {
|
||||
let artistName = "null";
|
||||
let artistID = 0;
|
||||
if (mv.artistName !== undefined) {
|
||||
artistName = mv.artistName;
|
||||
artistID = mv.artistId;
|
||||
} else if (mv.creator !== undefined) {
|
||||
artistName = mv.creator[0].userName;
|
||||
artistID = mv.creator[0].userId;
|
||||
}
|
||||
return `<a href="/artist/${artistID}">${artistName}</a>`;
|
||||
} else if (this.subtitle === "publishTime") {
|
||||
return mv.publishTime;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -137,8 +137,7 @@ nav {
|
|||
left: 12px;
|
||||
}
|
||||
&:hover {
|
||||
background: var(--color-primary-bg);
|
||||
color: var(--color-primary);
|
||||
background: var(--color-secondary-bg);
|
||||
}
|
||||
&:active {
|
||||
transform: scale(0.92);
|
||||
|
|
|
@ -146,13 +146,13 @@ export default {
|
|||
this.progress = ~~this.howler.seek();
|
||||
}, 1000);
|
||||
if (isAccountLoggedIn()) {
|
||||
userLikedSongsIDs(this.settings.user.userId).then((data) => {
|
||||
userLikedSongsIDs(this.data.user.userId).then((data) => {
|
||||
this.updateLikedSongs(data.ids);
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["player", "howler", "settings", "liked", "accountLogin"]),
|
||||
...mapState(["player", "howler", "settings", "liked", "data"]),
|
||||
currentTrack() {
|
||||
return this.player.currentTrack;
|
||||
},
|
||||
|
@ -175,6 +175,9 @@ export default {
|
|||
let max = ~~(this.currentTrack.dt / 1000);
|
||||
return max > 1 ? max - 1 : max;
|
||||
},
|
||||
accountLogin() {
|
||||
return isAccountLoggedIn();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
|
@ -266,7 +269,7 @@ export default {
|
|||
});
|
||||
},
|
||||
goToList() {
|
||||
if (this.player.listInfo.id === this.settings.user.likedSongPlaylistID)
|
||||
if (this.player.listInfo.id === this.data.likedSongPlaylistID)
|
||||
this.$router.push({ path: "/library/liked-songs" });
|
||||
else
|
||||
this.$router.push({
|
||||
|
|
|
@ -3,10 +3,18 @@
|
|||
<ContextMenu ref="menu">
|
||||
<div class="item" @click="play">Play</div>
|
||||
<div class="item" @click="playNext">Play Next</div>
|
||||
<div class="item" @click="like" v-show="!isRightClickedTrackLiked">
|
||||
<div
|
||||
class="item"
|
||||
@click="like"
|
||||
v-show="!isRightClickedTrackLiked && accountLogin"
|
||||
>
|
||||
Save to my Liked Songs
|
||||
</div>
|
||||
<div class="item" @click="like" v-show="isRightClickedTrackLiked">
|
||||
<div
|
||||
class="item"
|
||||
@click="like"
|
||||
v-show="isRightClickedTrackLiked && accountLogin"
|
||||
>
|
||||
Remove from my Liked Songs
|
||||
</div>
|
||||
</ContextMenu>
|
||||
|
@ -29,6 +37,7 @@ import {
|
|||
playAList,
|
||||
appendTrackToPlayerList,
|
||||
} from "@/utils/play";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
import TrackListItem from "@/components/TrackListItem.vue";
|
||||
import ContextMenu from "@/components/ContextMenu.vue";
|
||||
|
@ -67,6 +76,9 @@ export default {
|
|||
isRightClickedTrackLiked() {
|
||||
return this.liked.songs.includes(this.rightClickedTrack?.id);
|
||||
},
|
||||
accountLogin() {
|
||||
return isAccountLoggedIn();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(["updateLikedSongs"]),
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
import ArtistsInLine from "@/components/ArtistsInLine.vue";
|
||||
import ExplicitSymbol from "@/components/ExplicitSymbol.vue";
|
||||
|
@ -93,7 +93,6 @@ export default {
|
|||
return { focus: false, trackStyle: {} };
|
||||
},
|
||||
computed: {
|
||||
...mapState(["accountLogin"]),
|
||||
imgUrl() {
|
||||
if (this.track.al !== undefined) return this.track.al.picUrl;
|
||||
if (this.track.album !== undefined) return this.track.album.picUrl;
|
||||
|
@ -128,6 +127,9 @@ export default {
|
|||
if (this.isPlaying) trackClass.push("playing");
|
||||
return trackClass;
|
||||
},
|
||||
accountLogin() {
|
||||
return isAccountLoggedIn();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
goToAlbum() {
|
||||
|
|
|
@ -118,7 +118,7 @@ const router = new VueRouter({
|
|||
router.beforeEach((to, from, next) => {
|
||||
// 需要登录的逻辑
|
||||
if (to.meta.requireLogin) {
|
||||
if (store.state.settings.user.nickname === undefined) {
|
||||
if (store.state.data.user.nickname === undefined) {
|
||||
next({ path: "/login" });
|
||||
}
|
||||
if (isLooseLoggedIn()) {
|
||||
|
|
|
@ -3,22 +3,28 @@ import Vuex from "vuex";
|
|||
import state from "./state";
|
||||
import mutations from "./mutations";
|
||||
import actions from "./actions";
|
||||
import initState from "./initState";
|
||||
import initLocalStorage from "./initLocalStorage";
|
||||
import { Howl, Howler } from "howler";
|
||||
import { changeAppearance } from "@/utils/common";
|
||||
import updateApp from "@/utils/updateApp";
|
||||
import pack from "../../package.json";
|
||||
|
||||
if (localStorage.getItem("appVersion") === null) {
|
||||
localStorage.setItem("player", JSON.stringify(initState.player));
|
||||
localStorage.setItem("settings", JSON.stringify(initState.settings));
|
||||
localStorage.setItem("appVersion", "0.1");
|
||||
localStorage.setItem("player", JSON.stringify(initLocalStorage.player));
|
||||
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
||||
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
||||
localStorage.setItem("appVersion", pack.version);
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
updateApp();
|
||||
|
||||
const saveToLocalStorage = (store) => {
|
||||
store.subscribe((mutation, state) => {
|
||||
// console.log(mutation);
|
||||
localStorage.setItem("player", JSON.stringify(state.player));
|
||||
localStorage.setItem("settings", JSON.stringify(state.settings));
|
||||
localStorage.setItem("data", JSON.stringify(state.data));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
const initState = {
|
||||
howler: null,
|
||||
accountLogin: false,
|
||||
usernameLogin: false,
|
||||
liked: {
|
||||
songs: [],
|
||||
},
|
||||
contextMenu: {
|
||||
clickObjectID: 0,
|
||||
showMenu: false,
|
||||
},
|
||||
export default {
|
||||
player: {
|
||||
enable: false,
|
||||
show: true,
|
||||
|
@ -83,16 +73,16 @@ const initState = {
|
|||
enable: true,
|
||||
},
|
||||
],
|
||||
user: {
|
||||
id: 0,
|
||||
},
|
||||
lang: null,
|
||||
appearance: "auto",
|
||||
musicQuality: 320000,
|
||||
showGithubIcon: true,
|
||||
showPlaylistsByAppleMusic: true,
|
||||
},
|
||||
data: {
|
||||
user: {},
|
||||
likedSongPlaylistID: 0,
|
||||
lastRefreshCookieDate: 0,
|
||||
loginMode: null,
|
||||
},
|
||||
};
|
||||
|
||||
export default initState;
|
|
@ -81,22 +81,6 @@ export default {
|
|||
return track;
|
||||
});
|
||||
},
|
||||
updateAccountLogin(state, status) {
|
||||
state.accountLogin = status;
|
||||
},
|
||||
updateUsernameLogin(state, status) {
|
||||
state.usernameLogin = status;
|
||||
},
|
||||
updateLogout() {
|
||||
this.commit("updateAccountLogin", false);
|
||||
this.commit("updateUsernameLogin", false);
|
||||
},
|
||||
updateUser(state, user) {
|
||||
state.settings.user = user;
|
||||
},
|
||||
updateUserInfo(state, { key, value }) {
|
||||
state.settings.user[key] = value;
|
||||
},
|
||||
updateLikedSongs(state, trackIDs) {
|
||||
state.liked.songs = trackIDs;
|
||||
},
|
||||
|
@ -119,4 +103,7 @@ export default {
|
|||
updateSettings(state, { key, value }) {
|
||||
state.settings[key] = value;
|
||||
},
|
||||
updateData(state, { key, value }) {
|
||||
state.data[key] = value;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
export default {
|
||||
howler: null,
|
||||
accountLogin: false,
|
||||
usernameLogin: false,
|
||||
liked: {
|
||||
songs: [],
|
||||
},
|
||||
|
@ -11,4 +9,5 @@ export default {
|
|||
},
|
||||
player: JSON.parse(localStorage.getItem("player")),
|
||||
settings: JSON.parse(localStorage.getItem("settings")),
|
||||
data: JSON.parse(localStorage.getItem("data")),
|
||||
};
|
||||
|
|
|
@ -4,14 +4,12 @@ import store from "@/store";
|
|||
|
||||
export function doLogout() {
|
||||
logout();
|
||||
// 移除前端本地用来认证登录的字段
|
||||
Cookies.remove("loginMode");
|
||||
// 网易云的接口会自动移除该 cookies
|
||||
// Cookies.remove("MUSIC_U");
|
||||
// 更新状态仓库中的用户信息
|
||||
store.commit("updateUser", { id: 0 });
|
||||
store.commit("updateData", { key: "user", value: {} });
|
||||
// 更新状态仓库中的登录状态
|
||||
store.commit("updateLogout");
|
||||
store.commit("updateData", { key: "loginMode", value: null });
|
||||
}
|
||||
|
||||
// MUSIC_U 只有在账户登录的情况下才有
|
||||
|
@ -23,16 +21,13 @@ export function isLoggedIn() {
|
|||
export function isAccountLoggedIn() {
|
||||
return (
|
||||
Cookies.get("MUSIC_U") !== undefined &&
|
||||
Cookies.get("loginMode") === "account"
|
||||
store.state.data.loginMode === "account"
|
||||
);
|
||||
}
|
||||
|
||||
// 用户名搜索(用户数据为只读)
|
||||
export function isUsernameLoggedIn() {
|
||||
return (
|
||||
Cookies.get("MUSIC_U") === undefined &&
|
||||
Cookies.get("loginMode") === "username"
|
||||
);
|
||||
return store.state.data.loginMode === "username";
|
||||
}
|
||||
|
||||
// 账户登录或者用户名搜索都判断为登录,宽松检查
|
||||
|
|
|
@ -10,7 +10,7 @@ export function isTrackPlayable(track) {
|
|||
reason: "",
|
||||
};
|
||||
if (track.fee === 1 || track.privilege?.fee === 1) {
|
||||
if (isAccountLoggedIn() && store.state.settings.user.vipType === 11) {
|
||||
if (isAccountLoggedIn() && store.state.data.user.vipType === 11) {
|
||||
result.playable = true;
|
||||
} else {
|
||||
result.playable = false;
|
||||
|
@ -80,13 +80,13 @@ export function updateHttps(url) {
|
|||
}
|
||||
|
||||
export function dailyTask() {
|
||||
let lastDate = store.state.settings.lastRefreshCookieDate;
|
||||
let lastDate = store.state.data.lastRefreshCookieDate;
|
||||
if (
|
||||
isAccountLoggedIn() &&
|
||||
(lastDate === undefined || lastDate !== dayjs().date())
|
||||
) {
|
||||
console.log("execute dailyTask");
|
||||
store.commit("updateSettings", {
|
||||
store.commit("updateData", {
|
||||
key: "lastRefreshCookieDate",
|
||||
value: dayjs().date(),
|
||||
});
|
||||
|
|
28
src/utils/updateApp.js
Normal file
28
src/utils/updateApp.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import pack from "../../package.json";
|
||||
|
||||
function updateTo_0_2_0() {
|
||||
// 0.1 to 0.2.0
|
||||
// 移动 settings 内的 user 数据到 data
|
||||
let settings = JSON.parse(localStorage.getItem("settings"));
|
||||
let data = {
|
||||
likedSongPlaylistID: settings.user.likedSongPlaylistID,
|
||||
lastRefreshCookieDate: settings.lastRefreshCookieDate,
|
||||
};
|
||||
delete settings.user.likedSongPlaylistID;
|
||||
delete settings.lastRefreshCookieDate;
|
||||
data.user = settings.user;
|
||||
delete settings.user;
|
||||
localStorage.setItem("settings", JSON.stringify(settings));
|
||||
localStorage.setItem("data", JSON.stringify(data));
|
||||
localStorage.setItem("appVersion", "0.2.0");
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
export default function () {
|
||||
while (localStorage.getItem("appVersion") !== pack.version) {
|
||||
let currentVersion = localStorage.getItem("appVersion");
|
||||
if (currentVersion === "0.1") {
|
||||
updateTo_0_2_0();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,15 @@
|
|||
>
|
||||
{{ $t("play") }}
|
||||
</ButtonTwoTone>
|
||||
<ButtonTwoTone
|
||||
v-if="accountLogin"
|
||||
shape="round"
|
||||
:iconClass="dynamicDetail.isSub ? 'heart-solid' : 'heart'"
|
||||
:iconButton="true"
|
||||
:horizontalPadding="0"
|
||||
@click.native="likeAlbum"
|
||||
>
|
||||
</ButtonTwoTone>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -93,8 +102,9 @@ import { mapMutations, mapActions, mapState } from "vuex";
|
|||
import { getArtistAlbum } from "@/api/artist";
|
||||
import { getTrackDetail } from "@/api/track";
|
||||
import { playAlbumByID } from "@/utils/play";
|
||||
import { getAlbum } from "@/api/album";
|
||||
import { getAlbum, albumDynamicDetail, likeAAlbum } from "@/api/album";
|
||||
import NProgress from "nprogress";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
import ExplicitSymbol from "@/components/ExplicitSymbol.vue";
|
||||
import ButtonTwoTone from "@/components/ButtonTwoTone.vue";
|
||||
|
@ -124,18 +134,22 @@ export default {
|
|||
showFullDescription: false,
|
||||
show: false,
|
||||
moreAlbums: [],
|
||||
dynamicDetail: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.loadData(this.$route.params.id);
|
||||
},
|
||||
computed: {
|
||||
...mapState(["player"]),
|
||||
...mapState(["player", "data"]),
|
||||
albumTime() {
|
||||
let time = 0;
|
||||
this.tracks.map((t) => (time = time + t.dt));
|
||||
return time;
|
||||
},
|
||||
accountLogin() {
|
||||
return isAccountLoggedIn();
|
||||
},
|
||||
filteredMoreAlbums() {
|
||||
let moreAlbums = this.moreAlbums.filter((a) => a.id !== this.album.id);
|
||||
let realAlbums = moreAlbums.filter((a) => a.type === "专辑");
|
||||
|
@ -159,6 +173,15 @@ export default {
|
|||
}
|
||||
playAlbumByID(id, trackID);
|
||||
},
|
||||
likeAlbum() {
|
||||
likeAAlbum({
|
||||
id: this.album.id,
|
||||
t: this.dynamicDetail.isSub ? 0 : 1,
|
||||
}).then((data) => {
|
||||
if (data.code === 200)
|
||||
this.dynamicDetail.isSub = !this.dynamicDetail.isSub;
|
||||
});
|
||||
},
|
||||
loadData(id) {
|
||||
getAlbum(id).then((data) => {
|
||||
this.album = data.album;
|
||||
|
@ -179,6 +202,9 @@ export default {
|
|||
}
|
||||
);
|
||||
});
|
||||
albumDynamicDetail(id).then((data) => {
|
||||
this.dynamicDetail = data;
|
||||
});
|
||||
},
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
|
@ -235,6 +261,13 @@ export default {
|
|||
opacity: 0.88;
|
||||
}
|
||||
}
|
||||
.buttons {
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
button {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
<ButtonTwoTone @click.native="playPopularSongs()" :iconClass="`play`">
|
||||
{{ $t("play") }}
|
||||
</ButtonTwoTone>
|
||||
<ButtonTwoTone @click.native="followArtist" color="grey">
|
||||
<span v-if="artist.followed">Following</span>
|
||||
<span v-else>Follow</span>
|
||||
</ButtonTwoTone>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,7 +98,12 @@
|
|||
|
||||
<script>
|
||||
import { mapMutations, mapActions, mapState } from "vuex";
|
||||
import { getArtist, getArtistAlbum, artistMv } from "@/api/artist";
|
||||
import {
|
||||
getArtist,
|
||||
getArtistAlbum,
|
||||
artistMv,
|
||||
followAArtist,
|
||||
} from "@/api/artist";
|
||||
import { playAList } from "@/utils/play";
|
||||
import NProgress from "nprogress";
|
||||
|
||||
|
@ -168,6 +177,14 @@ export default {
|
|||
let trackIDs = this.popularTracks.map((t) => t.id);
|
||||
playAList(trackIDs, this.artist.id, "artist", trackID);
|
||||
},
|
||||
followArtist() {
|
||||
followAArtist({
|
||||
id: this.artist.id,
|
||||
t: this.artist.followed ? 0 : 1,
|
||||
}).then((data) => {
|
||||
if (data.code === 200) this.artist.followed = !this.artist.followed;
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.loadData(this.$route.params.id);
|
||||
|
|
|
@ -40,16 +40,65 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="playlists" v-if="playlists.length > 1">
|
||||
<div class="title">{{ $t("playlist.playlist") }}</div>
|
||||
<div>
|
||||
<div class="section-two" id="liked">
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab"
|
||||
:class="{ active: currentTab === 'playlists' }"
|
||||
@click="updateCurrentTab('playlists')"
|
||||
>
|
||||
Playlists
|
||||
</div>
|
||||
<div
|
||||
class="tab"
|
||||
:class="{ active: currentTab === 'albums' }"
|
||||
@click="updateCurrentTab('albums')"
|
||||
>
|
||||
Albums
|
||||
</div>
|
||||
<div
|
||||
class="tab"
|
||||
:class="{ active: currentTab === 'artists' }"
|
||||
@click="updateCurrentTab('artists')"
|
||||
>
|
||||
Artists
|
||||
</div>
|
||||
<div
|
||||
class="tab"
|
||||
:class="{ active: currentTab === 'mvs' }"
|
||||
@click="updateCurrentTab('mvs')"
|
||||
>
|
||||
MVs
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="currentTab === 'playlists'">
|
||||
<div v-if="playlists.length > 1">
|
||||
<CoverRow
|
||||
:items="playlists.slice(1)"
|
||||
type="playlist"
|
||||
subText="creator"
|
||||
:showPlayButton="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="currentTab === 'albums'">
|
||||
<CoverRow
|
||||
:items="playlists.slice(1)"
|
||||
type="playlist"
|
||||
subText="creator"
|
||||
:items="albums"
|
||||
type="album"
|
||||
subText="artist"
|
||||
:showPlayButton="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-show="currentTab === 'artists'">
|
||||
<CoverRow :items="artists" type="artist" :showPlayButton="true" />
|
||||
</div>
|
||||
|
||||
<div v-show="currentTab === 'mvs'">
|
||||
<MvRow :mvs="mvs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -57,7 +106,13 @@
|
|||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import { getTrackDetail, getLyric } from "@/api/track";
|
||||
import { userDetail, userPlaylist } from "@/api/user";
|
||||
import {
|
||||
userDetail,
|
||||
userPlaylist,
|
||||
likedAlbums,
|
||||
likedArtists,
|
||||
likedMVs,
|
||||
} from "@/api/user";
|
||||
import { randomNum, dailyTask } from "@/utils/common";
|
||||
import { getPlaylistDetail } from "@/api/playlist";
|
||||
import { playPlaylistByID } from "@/utils/play";
|
||||
|
@ -65,11 +120,12 @@ import NProgress from "nprogress";
|
|||
|
||||
import TrackList from "@/components/TrackList.vue";
|
||||
import CoverRow from "@/components/CoverRow.vue";
|
||||
import MvRow from "@/components/MvRow.vue";
|
||||
import SvgIcon from "@/components/SvgIcon.vue";
|
||||
|
||||
export default {
|
||||
name: "Library",
|
||||
components: { SvgIcon, CoverRow, TrackList },
|
||||
components: { SvgIcon, CoverRow, TrackList, MvRow },
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
|
@ -88,11 +144,15 @@ export default {
|
|||
likedSongs: [],
|
||||
likedSongIDs: [],
|
||||
lyric: undefined,
|
||||
currentTab: "playlists",
|
||||
albums: [],
|
||||
artists: [],
|
||||
mvs: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
NProgress.start();
|
||||
userDetail(this.settings.user.userId).then((data) => {
|
||||
userDetail(this.data.user.userId).then((data) => {
|
||||
this.user = data;
|
||||
});
|
||||
},
|
||||
|
@ -101,7 +161,7 @@ export default {
|
|||
dailyTask();
|
||||
},
|
||||
computed: {
|
||||
...mapState(["settings"]),
|
||||
...mapState(["data"]),
|
||||
likedSongsInState() {
|
||||
return this.$store.state.liked.songs;
|
||||
},
|
||||
|
@ -129,18 +189,38 @@ export default {
|
|||
playLikedSongs() {
|
||||
playPlaylistByID(this.playlists[0].id, "first", true);
|
||||
},
|
||||
updateCurrentTab(tab) {
|
||||
this.currentTab = tab;
|
||||
document
|
||||
.getElementById("liked")
|
||||
.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() {
|
||||
this.$router.push({ path: "/library/liked-songs" });
|
||||
},
|
||||
loadData() {
|
||||
if (this.hasMorePlaylists) {
|
||||
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.settings.user.userId,
|
||||
uid: this.data.user.userId,
|
||||
offset: this.playlists.length === 0 ? 0 : this.playlists.length - 1,
|
||||
timestamp: new Date().getTime(),
|
||||
}).then((data) => {
|
||||
|
@ -153,19 +233,17 @@ export default {
|
|||
});
|
||||
},
|
||||
getLikedSongs(getLyric = true) {
|
||||
getPlaylistDetail(this.settings.user.likedSongPlaylistID, true).then(
|
||||
(data) => {
|
||||
this.likedSongsPlaylist = data.playlist;
|
||||
let TrackIDs = data.playlist.trackIds.slice(0, 20).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();
|
||||
}
|
||||
);
|
||||
getPlaylistDetail(this.data.likedSongPlaylistID, true).then((data) => {
|
||||
this.likedSongsPlaylist = data.playlist;
|
||||
let TrackIDs = data.playlist.trackIds.slice(0, 20).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() {
|
||||
getLyric(
|
||||
|
@ -174,6 +252,21 @@ export default {
|
|||
if (data.lrc !== undefined) this.lyric = data.lrc.lyric;
|
||||
});
|
||||
},
|
||||
loadLikedAlbums() {
|
||||
likedAlbums().then((data) => {
|
||||
this.albums = data.data;
|
||||
});
|
||||
},
|
||||
loadLikedArtists() {
|
||||
likedArtists().then((data) => {
|
||||
this.artists = data.data;
|
||||
});
|
||||
},
|
||||
loadLikedMVs() {
|
||||
likedMVs().then((data) => {
|
||||
this.mvs = data.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
likedSongsInState() {
|
||||
|
@ -280,14 +373,37 @@ h1 {
|
|||
}
|
||||
}
|
||||
|
||||
.playlists {
|
||||
.section-two {
|
||||
// margin-top: 42px;
|
||||
// padding-top: 14px;
|
||||
// border-top: 1px solid rgba(128, 128, 128, 0.18);
|
||||
margin-top: 54px;
|
||||
.title {
|
||||
color: var(--color-text);
|
||||
opacity: 0.88;
|
||||
margin-bottom: 8px;
|
||||
font-size: 24px;
|
||||
min-height: calc(100vh - 182px);
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 18px;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 6px;
|
||||
.tab {
|
||||
font-weight: 600;
|
||||
padding: 8px 14px;
|
||||
margin: 10px 14px 6px 0;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: 0.2s;
|
||||
opacity: 0.68;
|
||||
&:hover {
|
||||
opacity: 0.88;
|
||||
background-color: var(--color-secondary-bg);
|
||||
}
|
||||
}
|
||||
.tab.active {
|
||||
opacity: 0.88;
|
||||
background-color: var(--color-secondary-bg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -89,7 +89,6 @@ import { loginWithPhone, loginWithEmail } from "@/api/auth";
|
|||
import md5 from "crypto-js/md5";
|
||||
import { mapMutations } from "vuex";
|
||||
import { userPlaylist } from "@/api/user";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
|
@ -112,15 +111,14 @@ export default {
|
|||
NProgress.done();
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(["updateUser", "updateUserInfo", "updateAccountLogin"]),
|
||||
...mapMutations(["updateData"]),
|
||||
afterLogin() {
|
||||
this.updateAccountLogin(true);
|
||||
Cookies.set("loginMode", "account", { expires: 3650 });
|
||||
this.updateData({ key: "loginMode", value: "account" });
|
||||
userPlaylist({
|
||||
uid: this.$store.state.settings.user.userId,
|
||||
uid: this.$store.state.data.user.userId,
|
||||
limit: 1,
|
||||
}).then((data) => {
|
||||
this.updateUserInfo({
|
||||
this.updateData({
|
||||
key: "likedSongPlaylistID",
|
||||
value: data.playlist[0].id,
|
||||
});
|
||||
|
@ -163,7 +161,7 @@ export default {
|
|||
})
|
||||
.then((data) => {
|
||||
if (data.code !== 502) {
|
||||
this.updateUser(data.profile);
|
||||
this.updateData({ key: "user", value: data.profile });
|
||||
this.afterLogin();
|
||||
}
|
||||
})
|
||||
|
@ -180,7 +178,7 @@ export default {
|
|||
})
|
||||
.then((data) => {
|
||||
if (data.code !== 502) {
|
||||
this.updateUser(data.profile);
|
||||
this.updateData({ key: "user", value: data.profile });
|
||||
this.afterLogin();
|
||||
}
|
||||
})
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
import { mapMutations } from "vuex";
|
||||
import NProgress from "nprogress";
|
||||
import { search } from "@/api/others";
|
||||
import Cookies from "js-cookie";
|
||||
import { userPlaylist } from "@/api/user";
|
||||
import { throttle } from "@/utils/common";
|
||||
|
||||
|
@ -74,7 +73,7 @@ export default {
|
|||
NProgress.done();
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(["updateUser", "updateUserInfo", "updateUsernameLogin"]),
|
||||
...mapMutations(["updateData"]),
|
||||
search() {
|
||||
if (!this.keyword) return;
|
||||
search({ keywords: this.keyword, limit: 9, type: 1002 }).then((data) => {
|
||||
|
@ -83,14 +82,13 @@ export default {
|
|||
});
|
||||
},
|
||||
confirm() {
|
||||
this.updateUser(this.activeUser);
|
||||
this.updateUsernameLogin(true);
|
||||
Cookies.set("loginMode", "username", { expires: 3650 });
|
||||
this.updateData({ key: "user", value: this.activeUser });
|
||||
this.updateData({ key: "loginMode", value: "username" });
|
||||
userPlaylist({
|
||||
uid: this.activeUser.userId,
|
||||
limit: 1,
|
||||
}).then((data) => {
|
||||
this.updateUserInfo({
|
||||
this.updateData({
|
||||
key: "likedSongPlaylistID",
|
||||
value: data.playlist[0].id,
|
||||
});
|
||||
|
|
|
@ -45,9 +45,7 @@
|
|||
{{ $t("play") }}
|
||||
</ButtonTwoTone>
|
||||
<ButtonTwoTone
|
||||
v-if="
|
||||
accountLogin && playlist.creator.userId !== settings.user.userId
|
||||
"
|
||||
v-if="accountLogin && playlist.creator.userId !== data.user.userId"
|
||||
shape="round"
|
||||
:iconClass="playlist.subscribed ? 'heart-solid' : 'heart'"
|
||||
:iconButton="true"
|
||||
|
@ -61,8 +59,8 @@
|
|||
|
||||
<div class="user-info" v-else>
|
||||
<h1>
|
||||
<img class="avatar" :src="settings.user.avatarUrl | resizeImage" />{{
|
||||
settings.user.nickname
|
||||
<img class="avatar" :src="data.user.avatarUrl | resizeImage" />{{
|
||||
data.user.nickname
|
||||
}}{{ $t("library.sLikedSongs") }}
|
||||
</h1>
|
||||
</div>
|
||||
|
@ -92,6 +90,7 @@ import NProgress from "nprogress";
|
|||
import { getPlaylistDetail, subscribePlaylist } from "@/api/playlist";
|
||||
import { playAList } from "@/utils/play";
|
||||
import { getTrackDetail } from "@/api/track";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
import ButtonTwoTone from "@/components/ButtonTwoTone.vue";
|
||||
import TrackList from "@/components/TrackList.vue";
|
||||
|
@ -122,7 +121,7 @@ export default {
|
|||
},
|
||||
created() {
|
||||
if (this.$route.name === "likedSongs") {
|
||||
this.loadData(this.settings.user.likedSongPlaylistID);
|
||||
this.loadData(this.data.user.likedSongPlaylistID);
|
||||
} else {
|
||||
this.loadData(this.$route.params.id);
|
||||
}
|
||||
|
@ -131,10 +130,13 @@ export default {
|
|||
window.removeEventListener("scroll", this.handleScroll, true);
|
||||
},
|
||||
computed: {
|
||||
...mapState(["player", "settings", "accountLogin"]),
|
||||
...mapState(["player", "data"]),
|
||||
isLikeSongsPage() {
|
||||
return this.$route.name === "likedSongs";
|
||||
},
|
||||
accountLogin() {
|
||||
return isAccountLoggedIn();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(["appendTrackToPlayerList"]),
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user