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:
saopig1andClaude Opus 4.6 committed 2026-03-30 02:31:15 +08:00
1 parent ce6fc92780
commit 94a0df8391
8 files changed
+195 -155

No files matched your search

+27
View File
@@ -32,6 +32,33 @@ export function createMusicRouter(
}
});
router.get("/search/all", async (req, res) => {
try {
const { q, limit } = req.query;
if (!q) {
res.status(400).json({ error: "q (query) is required" });
return;
}
const parsedLimit = parseInt(limit as string) || 20;
const [neteaseResult, qqResult] = await Promise.allSettled([
neteaseProvider.search(q as string, parsedLimit),
qqProvider.search(q as string, parsedLimit),
]);
const songs = [
...(neteaseResult.status === "fulfilled"
? neteaseResult.value.songs
: []),
...(qqResult.status === "fulfilled" ? qqResult.value.songs : []),
];
res.json({ songs });
} catch (err) {
logger.error({ err }, "Unified search failed");
res.status(500).json({ error: (err as Error).message });
}
});
router.get("/song/:id", async (req, res) => {
try {
const provider = getProvider(req.query.platform as string);