Adds artist support for the NetEase and QQ providers plus the matching UI.
Backend:
- SearchResult gains `artists`; new optional MusicProvider methods
getArtistDetail / getArtistSongs / getArtistAlbums / getArtistAllSongs.
- NetEase: /cloudsearch type=100 for artist search, /artists, /artist/songs,
/artist/album and /artist/desc for the artist page.
- QQ: singer search rides along in the existing musicu.fcg batch
(search_type=1); singer detail via music.web_singer_info_svr. QQ exposes no
working singer-song paging endpoint, so the full catalogue is built from the
hot 50 plus every album of the singer (album search filtered by singerMID,
songs fetched per album, de-duplicated, cached for 10 minutes). A failed
album sweep is never cached and degrades to the hot list.
- API: GET /api/music/artist/:id and POST /api/player/:botId/play-artist
(player.control capability, guest flag playCollection); /search/all now
aggregates artists too.
Frontend:
- Search history in localStorage (max 10, per platform, never shared between
users), shown as a dropdown under the search box and as 最近搜索 chips.
- Artist row in the search results; new /artist/:id page (portrait, aliases,
stats, description, top songs, album shelf) with 播放 / 随机播放, which queue
the singer's whole catalogue.
- playArtist store action.
Tests cover the provider mappers, the new routes, the play-artist collector
(paging, de-duplication, 500-track cap), permission gating and the new views.