diff --git a/components.d.ts b/components.d.ts index cee876bf..a20eff95 100644 --- a/components.d.ts +++ b/components.d.ts @@ -79,7 +79,9 @@ declare module 'vue' { NText: typeof import('naive-ui')['NText'] NThing: typeof import('naive-ui')['NThing'] Pagination: typeof import('./src/components/Global/Pagination.vue')['default'] + PlayCover: typeof import('./src/components/Player/PlayCover.vue')['default'] PlayerControl: typeof import('./src/components/Player/PlayerControl.vue')['default'] + PlayerCover: typeof import('./src/components/Player/PlayerCover.vue')['default'] Playlist: typeof import('./src/components/Global/Playlist.vue')['default'] PlaylistUpdate: typeof import('./src/components/Modal/PlaylistUpdate.vue')['default'] PrivateFm: typeof import('./src/components/Player/PrivateFm.vue')['default'] diff --git a/package.json b/package.json index 7ece3d0d..d60999f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "splayer", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "description": "A minimalist music player", "main": "./out/main/index.js", "author": "imsyy", diff --git a/public/images/pic/pointer.png b/public/images/pic/pointer.png new file mode 100644 index 00000000..8bec5cbe Binary files /dev/null and b/public/images/pic/pointer.png differ diff --git a/src/components/Global/Menu.vue b/src/components/Global/Menu.vue index b911775f..4a452d25 100644 --- a/src/components/Global/Menu.vue +++ b/src/components/Global/Menu.vue @@ -6,7 +6,7 @@ class="main-menu" :root-indent="36" :indent="0" - :collapsed="status.asideMenuCollapsed" + :collapsed="asideMenuCollapsed.value" :defaultExpandedKeys="['user-playlists', 'favorite-playlists']" :collapsed-width="64" :collapsed-icon-size="22" @@ -36,6 +36,7 @@ const router = useRouter(); const data = siteData(); const music = musicData(); const status = siteStatus(); +const { asideMenuCollapsed } = storeToRefs(status); const { userData, userLikeData } = storeToRefs(data); const { playList, playListOld, playIndex, playSongData, playHeartbeatMode, playMode } = storeToRefs(music); @@ -90,7 +91,7 @@ const menuOptions = computed(() => [ label: "在线音乐", key: "online", children: [], - show: !status.asideMenuCollapsed, + show: !asideMenuCollapsed.value, }, { label: () => @@ -143,7 +144,7 @@ const menuOptions = computed(() => [ label: "我的音乐", key: "user", children: [], - show: !status.asideMenuCollapsed, + show: !asideMenuCollapsed.value, }, { label: () => @@ -157,19 +158,33 @@ const menuOptions = computed(() => [ menuid: "like-songs", }, () => [ - h(NText, null, () => ["喜欢的音乐"]), - h(NButton, { - size: "small", - type: "tertiary", - round: true, - strong: true, - secondary: true, - renderIcon: renderIcon("heartbit", "26"), - onclick: (event) => { - event.stopPropagation(); - startHeartRate(); + h( + "div", + { + style: { + width: "100%", + display: "flex", + alignItems: "center", + justifyContent: "space-between", + }, }, - }), + [ + h("span", null, ["喜欢的音乐"]), + h(NButton, { + size: "small", + type: "tertiary", + round: true, + strong: true, + secondary: true, + class: asideMenuCollapsed.value ? "heart-rate-btn collapsed" : "heart-rate-btn", + renderIcon: renderIcon("heartbit", "26"), + onclick: (event) => { + event.stopPropagation(); + startHeartRate(); + }, + }), + ], + ), ], ), key: "like-songs", @@ -222,8 +237,8 @@ const menuOptions = computed(() => [ key: "divider-2", type: "divider", }, - { ...userPlaylists.value, show: !status.asideMenuCollapsed }, - { ...favoritePlaylists.value, show: !status.asideMenuCollapsed }, + { ...userPlaylists.value, show: !asideMenuCollapsed.value }, + { ...favoritePlaylists.value, show: !asideMenuCollapsed.value }, ]); // 更改用户的歌单 @@ -446,3 +461,22 @@ onMounted(() => { } } + + + diff --git a/src/components/List/CommentList.vue b/src/components/List/CommentList.vue index aee23006..7290b01f 100644 --- a/src/components/List/CommentList.vue +++ b/src/components/List/CommentList.vue @@ -293,7 +293,7 @@ const toLikeComment = throttle( width: 100%; padding: 4px 8px; border-radius: 8px; - background-color: var(--n-border-color); + background-color: var(--main-second-color); font-size: 13px; margin-top: 6px; box-sizing: border-box; diff --git a/src/components/Player/FullPlayer.vue b/src/components/Player/FullPlayer.vue index c3b8d099..4e8abd24 100644 --- a/src/components/Player/FullPlayer.vue +++ b/src/components/Player/FullPlayer.vue @@ -68,61 +68,105 @@
+ + -
- - - - - -
-
- -
-
-
- {{ music.getPlaySongData.name || "未知曲目" }} - - -
- 该歌曲暂时无法播放,为您采用其他音源,可能会与原曲存在差别 +
+ {{ music.getPlaySongData.artists || "未知艺术家" }}
- +
+
+ + + + + {{ + typeof music.getPlaySongData.album === "string" + ? music.getPlaySongData.album + : music.getPlaySongData.album.name + }} + + 未知专辑 +
- +
+ +
+
+ +
+
+ {{ music.getPlaySongData.name || "未知曲目" }} + {{ music.getPlaySongData.alia }} +
+
@@ -171,9 +215,9 @@
+ +
- -
@@ -192,7 +236,7 @@ const music = musicData(); const status = siteStatus(); const settings = siteSettings(); const { playList, playSongLyric } = storeToRefs(music); -const { playerBackgroundType, showYrc } = storeToRefs(settings); +const { playerBackgroundType, showYrc, playCoverType } = storeToRefs(settings); const { playerControlShow, controlTimeOut, @@ -202,6 +246,11 @@ const { coverBackground, } = storeToRefs(status); +// 是否有歌词 +const isHasLrc = computed(() => { + return playSongLyric.value.lrc?.[0] && playSongLyric.value.lrc?.length > 4; +}); + // 全屏状态 const screenfullStatus = ref(false); @@ -375,44 +424,6 @@ onUnmounted(() => { &.no-lrc { transform: translateX(50%); } - .cover { - position: relative; - display: flex; - align-items: center; - justify-content: center; - width: 70%; - max-width: 55vh; - height: auto; - aspect-ratio: 1 / 1; - .cover-img { - width: 100%; - height: 100%; - border-radius: 32px; - overflow: hidden; - z-index: 1; - box-shadow: 0 0 10px 6px #00000008; - transition: opacity 0.1s ease-in-out; - :deep(img) { - width: 100%; - height: 100%; - opacity: 0; - transition: opacity 0.3s ease-in-out; - } - } - .cover-shadow { - position: absolute; - top: 12px; - height: 100%; - width: 100%; - filter: blur(20px) opacity(0.6); - transform: scale(0.95); - z-index: 0; - :deep(img) { - width: 100%; - height: 100%; - } - } - } .data { width: 70%; max-width: 55vh; @@ -426,14 +437,14 @@ onUnmounted(() => { display: flex; align-items: center; margin-left: 4px; - .n-text { + .name { font-size: 26px; font-weight: bold; color: var(--cover-main-color); -webkit-line-clamp: 2; } .n-tag { - margin-left: 6px; + margin-left: 12px; cursor: pointer; } } @@ -498,6 +509,88 @@ onUnmounted(() => { } } } + &.record { + margin-top: 60px; + .desc { + align-items: center; + } + } + } + } + .right { + width: 50%; + .data { + padding: 0 24px; + margin-bottom: 40px; + .name { + display: flex; + flex-direction: column; + font-size: 30px; + font-weight: bold; + .name-text { + -webkit-line-clamp: 2; + } + .name-alias { + margin-top: 6px; + font-size: 18px; + font-weight: normal; + opacity: 0.6; + } + } + .other { + display: flex; + flex-direction: column; + margin-top: 8px; + font-size: 16px; + .n-icon { + margin-right: 4px; + color: var(--cover-main-color); + } + .artist { + display: flex; + align-items: center; + margin-right: 12px; + .all-ar { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + word-break: break-all; + .ar { + opacity: 0.7; + display: inline-flex; + transition: opacity 0.3s; + cursor: pointer; + &::after { + content: "/"; + margin: 0 4px; + transition: none; + } + &:last-child { + &::after { + display: none; + } + } + &:hover { + opacity: 1; + } + } + } + } + .album { + display: flex; + align-items: center; + margin-top: 4px; + .al { + opacity: 0.7; + transition: opacity 0.3s; + cursor: pointer; + &:hover { + opacity: 1; + } + } + } + } } } // 全局 @@ -513,7 +606,6 @@ onUnmounted(() => { .title-tip { width: 200px; padding: 12px 20px; - background-color: var(--main-second-color); border-radius: 12px; .n-text { display: initial; diff --git a/src/components/Player/Lyric.vue b/src/components/Player/Lyric.vue index b59aeb54..ac6900ee 100644 --- a/src/components/Player/Lyric.vue +++ b/src/components/Player/Lyric.vue @@ -4,7 +4,7 @@ :style="{ cursor: cursorShow ? 'pointer' : 'none', }" - :class="['lyric', `lyric-${lyricsPosition}`]" + :class="['lyric', `lyric-${lyricsPosition}`, playCoverType]" @mouseenter="lrcMouseStatus = lrcMousePause ? true : false" @mouseleave="lrcAllLeave" > @@ -13,6 +13,8 @@ v-if="playSongLyric.lrc?.[0] && playSongLyric.lrc?.length > 4" :key="playSongLyric.lrc?.[0]" class="lyric-all" + @after-enter="lyricsScroll(playSongLyricIndex)" + @after-leave="lyricsScroll(playSongLyricIndex)" > @@ -154,6 +156,7 @@ const { lyricsBlur, showTransl, showRoma, + playCoverType, } = storeToRefs(settings); // 歌词滚动数据 @@ -188,14 +191,14 @@ const getYrcStyle = (wordData, lyricIndex) => { // 如果当前歌词索引与播放歌曲的歌词索引不匹配 if (playSongLyricIndex.value !== lyricIndex) { return { - transitionDuration: `0ms, 0ms, 0.5s`, + transitionDuration: `0ms, 0ms, 0.35s`, transitionDelay: `0ms`, }; } // 如果播放状态不是加载中,且当前单词的时间加上持续时间减去播放进度大于 0 if (status.playLoading === false && wordData.time + wordData.duration - playSeek.value > 0) { return { - transitionDuration: `0s, 0s, 0.5s`, + transitionDuration: `0s, 0s, 0.35s`, transitionDelay: `0ms`, WebkitMaskPositionX: `${ 100 - Math.max(((playSeek.value - wordData.time) / wordData.duration) * 100, 0) @@ -204,7 +207,7 @@ const getYrcStyle = (wordData, lyricIndex) => { } // 如果以上条件都不满足 return { - transitionDuration: `${wordData.duration}ms, ${wordData.duration * 0.8}ms, 0.5s`, + transitionDuration: `${wordData.duration}ms, ${wordData.duration * 0.8}ms, 0.35s`, transitionDelay: `${wordData.time - playSeek.value}ms, ${ wordData.time - playSeek.value + wordData.duration * 0.5 }ms, 0ms`, @@ -251,7 +254,7 @@ onMounted(() => { diff --git a/src/components/Player/PlayerCover.vue b/src/components/Player/PlayerCover.vue new file mode 100644 index 00000000..a3103c4d --- /dev/null +++ b/src/components/Player/PlayerCover.vue @@ -0,0 +1,212 @@ + + + + + + diff --git a/src/stores/musicData.js b/src/stores/musicData.js index 0fc870d8..6992cb0b 100644 --- a/src/stores/musicData.js +++ b/src/stores/musicData.js @@ -2,7 +2,7 @@ import { defineStore } from "pinia"; import { getPersonalFm, setFmToTrash } from "@/api/recommend"; import { changePlayIndex } from "@/utils/Player"; -// import { isLogin } from "@/utils/auth"; +import { isLogin } from "@/utils/auth"; import formatData from "@/utils/formatData"; const useMusicDataStore = defineStore("musicData", { @@ -197,6 +197,7 @@ const useMusicDataStore = defineStore("musicData", { // 私人FM垃圾桶 async setPersonalFmToTrash(id) { try { + if (!isLogin()) return $message.warning("请登录后使用"); const result = await setFmToTrash(id); if (result.code === 200) { $message.success("已移至垃圾桶"); diff --git a/src/stores/siteSettings.js b/src/stores/siteSettings.js index 533e495e..30d819cb 100644 --- a/src/stores/siteSettings.js +++ b/src/stores/siteSettings.js @@ -18,6 +18,7 @@ const useSiteSettingsStore = defineStore("siteSettings", { themeTypeData: {}, themeAutoCover: true, // 主题色跟随封面 // 播放部分 + playCoverType: "cover", // 播放器样式 songLevel: "exhigh", // 歌曲音质 autoPlay: false, // 程序启动时自动播放 songVolumeFade: true, // 歌曲渐入渐出 diff --git a/src/style/animate.scss b/src/style/animate.scss index a389d47a..05bea710 100644 --- a/src/style/animate.scss +++ b/src/style/animate.scss @@ -83,3 +83,12 @@ transform: rotate(360deg) scale(1) translateX(0); } } + +@keyframes playerCoverRotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/src/utils/formatData.js b/src/utils/formatData.js index 21e40030..b9eedcf9 100644 --- a/src/utils/formatData.js +++ b/src/utils/formatData.js @@ -57,7 +57,7 @@ const formatData = (data, type = "playlist", noTracks = false) => { cover, coverSize, mv: v.mv, - alia: v.alias?.[0] || v.transNames?.[0], + alia: v.alia?.[0] || v.alias?.[0] || v.transNames?.[0], fee: v.fee, pc: v.pc, size: v.size, diff --git a/src/views/Setting/index.vue b/src/views/Setting/index.vue index ab7efac5..469a9942 100644 --- a/src/views/Setting/index.vue +++ b/src/views/Setting/index.vue @@ -169,6 +169,26 @@ + +
+ 播放器样式 + 播放器左侧区域样式 +
+ +
播放背景样式 @@ -470,6 +490,7 @@ const { downloadPath, memorySeek, showGithub, + playCoverType, } = storeToRefs(settings); // 标签页数据