diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index d39c87b..422baa5 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -59,7 +59,7 @@ const navItems = [ { path: "/", label: "歌单", icon: "home" }, { path: "/ranking", label: "排行榜", icon: "trophy" }, { path: "/library", label: "我的音乐", icon: "music" }, - { path: "/demo", label: "演示", icon: "play" }, + // { path: "/demo", label: "演示", icon: "play" }, ] as const function isActive(path: string) { diff --git a/src/views/SearchView.vue b/src/views/SearchView.vue index f7fced4..e1292e6 100644 --- a/src/views/SearchView.vue +++ b/src/views/SearchView.vue @@ -17,6 +17,19 @@ +
+ + + + + +
+
@@ -73,6 +86,17 @@
+ +
+ + +
+
@@ -84,11 +108,15 @@ import { NEmpty, NInput, NSpin, NTabPane, NTabs, NTag, useDialog, useMessage } f import AppIcon from "@/components/AppIcon.vue" import MusicCard from "@/components/MusicCard.vue" import SongTable from "@/components/SongTable.vue" -import MusicApi, { type MusicSearchPlaylist, type MusicSearchSong } from "@/api/music" +import MusicApi, { + type MusicSearchAlbum, + type MusicSearchPlaylist, + type MusicSearchSong, +} from "@/api/music" import type { PlayListSummary } from "@/api/playlist" import { hotKeywords, type Song } from "@/mocks/music" import { usePlayerStore } from "@/stores/player" -import { useSettingsStore } from "@/stores/settings" +import { ALL_SOURCES, SOURCE_LABELS, useSettingsStore } from "@/stores/settings" import { displayCover } from "@/utils/cover" import Source from "@/types/global" import { useSearchHistoryStore } from "@/stores/searchHistory" @@ -100,12 +128,15 @@ const settingsStore = useSettingsStore() const searchHistoryStore = useSearchHistoryStore() const keyword = ref("") const activeTab = ref("song") +const allSources = ALL_SOURCES +const selectedSource = ref(settingsStore.defaultSource) const normalized = computed(() => keyword.value.trim().toLowerCase()) const loading = ref(false) const songResults = ref([]) const playlistResults = ref([]) +const albumResults = ref([]) let searchTimer: number | undefined let requestSeq = 0 @@ -119,6 +150,7 @@ watch(normalized, (q) => { requestSeq += 1 songResults.value = [] playlistResults.value = [] + albumResults.value = [] loading.value = false return } @@ -130,9 +162,11 @@ watch(normalized, (q) => { async function doSearch(q: string) { const seq = ++requestSeq loading.value = true - const [songRes, playlistRes] = await Promise.allSettled([ - MusicApi.search(q, "song", settingsStore.enabledSources), - MusicApi.search(q, "playlist", settingsStore.enabledSources), + const sources = [selectedSource.value] + const [songRes, playlistRes, albumRes] = await Promise.allSettled([ + MusicApi.search(q, "song", sources), + MusicApi.search(q, "playlist", sources), + MusicApi.search(q, "album", sources), ]) if (seq !== requestSeq) return if (songRes.status === "fulfilled") { @@ -145,6 +179,11 @@ async function doSearch(q: string) { } else { playlistResults.value = [] } + if (albumRes.status === "fulfilled") { + albumResults.value = (albumRes.value.data.albums ?? []).map(toPlaylist) + } else { + albumResults.value = [] + } loading.value = false } @@ -160,7 +199,7 @@ function toSong(item: MusicSearchSong): Song { } } -function toPlaylist(item: MusicSearchPlaylist): PlayListSummary { +function toPlaylist(item: MusicSearchPlaylist | MusicSearchAlbum): PlayListSummary { return { id: item.id, name: item.name, @@ -174,6 +213,18 @@ function toPlaylist(item: MusicSearchPlaylist): PlayListSummary { } } +function onSourceChange(source: Source) { + settingsStore.setDefaultSource(source) + const q = normalized.value + if (q) { + if (searchTimer !== undefined) { + window.clearTimeout(searchTimer) + searchTimer = undefined + } + void doSearch(q) + } +} + async function playSearchSong(song: Song) { const source = (song.source ?? settingsStore.defaultSource) as Source try { @@ -182,6 +233,10 @@ async function playSearchSong(song: Song) { const res = await MusicApi.url(String(song.id), source) const url = res.data.url console.log("url: ", url) + if (!res) { + message.error(`获取直链失败:${song.title}`) + return + } playerStore.playSong(song, songResults.value, url) } catch { // 拿不到直链时仍切歌,后续可尝试 MusicApi.stream 代理播放 @@ -246,6 +301,14 @@ onBeforeUnmount(() => { max-width: min(560px, 100%); } +.source-bar { + margin-top: 18px; +} + +.source-scrollbar { + padding-bottom: 8px; +} + .search-icon { color: var(--app-text-muted); }