mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
feat: add QQ Music API integration, Pinia home cache, and unified search
- Start @sansenjian/qq-music-api server via dynamic import in api-server.ts - Rewrite QQ Music provider to use real API endpoints (getSearchByKey, getMusicPlay, getSongListDetail, getAlbumInfo, getLyric, etc.) - Cache home page data (recommend playlists, daily songs, user playlists) in Pinia store with 5-minute TTL to avoid refetching on every mount - Add unified /api/music/search/all endpoint that queries both Netease and QQ providers in parallel and returns merged results - Remove platform toggle from Search.vue; search both platforms at once - Add platform badge (网易云 / QQ) to SongCard component Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ce6fc92780
commit
94a0df8391
8 files changed
+195
-155
No files matched your search
@@ -16,22 +16,6 @@
|
||||
autofocus
|
||||
/>
|
||||
</div>
|
||||
<div class="platform-toggle">
|
||||
<button
|
||||
class="platform-btn"
|
||||
:class="{ active: platform === 'netease' }"
|
||||
@click="platform = 'netease'; doSearch()"
|
||||
>
|
||||
网易云
|
||||
</button>
|
||||
<button
|
||||
class="platform-btn"
|
||||
:class="{ active: platform === 'qq' }"
|
||||
@click="platform = 'qq'; doSearch()"
|
||||
>
|
||||
QQ音乐
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading">搜索中...</div>
|
||||
@@ -39,7 +23,7 @@
|
||||
<div v-else-if="results.length > 0" class="results">
|
||||
<SongCard
|
||||
v-for="(song, i) in results"
|
||||
:key="song.id"
|
||||
:key="`${song.platform}-${song.id}`"
|
||||
:song="song"
|
||||
:index="i + 1"
|
||||
:active="store.currentSong?.id === song.id"
|
||||
@@ -66,7 +50,6 @@ const store = usePlayerStore();
|
||||
const route = useRoute();
|
||||
|
||||
const query = ref((route.query.q as string) || '');
|
||||
const platform = ref<'netease' | 'qq'>('netease');
|
||||
const results = ref<Array<{ id: string; name: string; artist: string; album: string; duration: number; coverUrl: string; platform: string }>>([]);
|
||||
const loading = ref(false);
|
||||
const searched = ref(false);
|
||||
@@ -76,8 +59,8 @@ async function doSearch() {
|
||||
loading.value = true;
|
||||
searched.value = true;
|
||||
try {
|
||||
const res = await axios.get('/api/music/search', {
|
||||
params: { q: query.value, platform: platform.value },
|
||||
const res = await axios.get('/api/music/search/all', {
|
||||
params: { q: query.value },
|
||||
});
|
||||
results.value = res.data.songs;
|
||||
} catch {
|
||||
@@ -137,27 +120,6 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.platform-toggle {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.platform-btn {
|
||||
padding: 6px 18px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
background: var(--hover-bg);
|
||||
opacity: 0.6;
|
||||
transition: all var(--transition-fast);
|
||||
|
||||
&.active {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
|
||||
Reference in new issue
Block a user