feat(music): refine source browsing and subscriptions

This commit is contained in:
jxxghp
2026-08-12 12:56:40 +08:00
parent a423a2ce04
commit d7534ecba4
52 changed files with 513 additions and 414 deletions
+12 -12
View File
@@ -12,37 +12,37 @@ import { describe, expect, it } from 'vitest'
describe('music utils', () => {
it('routes a recording to the music detail page', () => {
expect(buildMusicDetailRoute({ source: 'musicbrainz', media_id: 'recording-1', title: '晴天' })).toEqual({
expect(buildMusicDetailRoute({ media_source: 'musicbrainz', media_id: 'recording-1', title: '晴天' })).toEqual({
path: '/music/detail',
query: { source: 'musicbrainz', mediaid: 'recording-1', title: '晴天' },
query: { media_source: 'musicbrainz', mediaid: 'recording-1', title: '晴天' },
})
})
it('routes an album entity to the album page', () => {
expect(
buildMusicDetailRoute({
source: 'musicbrainz',
media_source: 'musicbrainz',
media_id: 'release-group-1',
music_type: 'album',
title: '叶惠美',
}),
).toEqual({
path: '/music/album',
query: { source: 'musicbrainz', mediaid: 'release-group-1', title: '叶惠美' },
query: { media_source: 'musicbrainz', mediaid: 'release-group-1', title: '叶惠美' },
})
})
it('routes an artist entity to the artist page', () => {
expect(
buildMusicDetailRoute({
source: 'musicbrainz',
media_source: 'musicbrainz',
media_id: 'artist-1',
music_type: 'artist',
name: 'Queen',
}),
).toEqual({
path: '/music/artist',
query: { source: 'musicbrainz', mediaid: 'artist-1', title: 'Queen' },
query: { media_source: 'musicbrainz', mediaid: 'artist-1', title: 'Queen' },
})
})
@@ -56,11 +56,11 @@ describe('music utils', () => {
it('builds album and artist routes with the default source', () => {
expect(buildMusicAlbumRoute('release-group-1', '叶惠美')).toEqual({
path: '/music/album',
query: { source: 'musicbrainz', mediaid: 'release-group-1', title: '叶惠美' },
query: { media_source: 'musicbrainz', mediaid: 'release-group-1', title: '叶惠美' },
})
expect(buildMusicArtistRoute('artist-1', 'Queen')).toEqual({
path: '/music/artist',
query: { source: 'musicbrainz', mediaid: 'artist-1', title: 'Queen' },
query: { media_source: 'musicbrainz', mediaid: 'artist-1', title: 'Queen' },
})
})
@@ -68,7 +68,7 @@ describe('music utils', () => {
expect(
buildMusicResourceRoute(
{
source: 'musicbrainz',
media_source: 'musicbrainz',
media_id: 'recording-1',
title: '晴天',
year: '2003',
@@ -89,7 +89,7 @@ describe('music utils', () => {
it('does not build a resource route for an artist browsing entity', () => {
expect(
buildMusicResourceRoute({
source: 'musicbrainz',
media_source: 'musicbrainz',
media_id: 'artist-1',
music_type: 'artist',
title: 'Queen',
@@ -98,8 +98,8 @@ describe('music utils', () => {
})
it('keeps the entity type inside the list key so albums and tracks never collide', () => {
const track = getMusicKey({ source: 'musicbrainz', media_id: 'same-id' })
const album = getMusicKey({ source: 'musicbrainz', media_id: 'same-id', music_type: 'album' })
const track = getMusicKey({ media_source: 'musicbrainz', media_id: 'same-id' })
const album = getMusicKey({ media_source: 'musicbrainz', media_id: 'same-id', music_type: 'album' })
expect(track).not.toEqual(album)
})
+2 -7
View File
@@ -34,7 +34,7 @@ describe('recommendSources', () => {
it('creates the complete built-in source contract', () => {
const sources = createBuiltInRecommendSources(translate)
expect(sources).toHaveLength(19)
expect(sources).toHaveLength(17)
expect(sources[0]).toEqual({
apipath: 'recommend/tmdb_trending',
linkurl: '/browse/recommend/tmdb_trending?title=translated:recommend.trendingNow',
@@ -68,12 +68,7 @@ describe('recommendSources', () => {
})
expect(
sources.filter(source => source.type === 'translated:recommend.categoryMusic').map(source => source.apipath),
).toEqual([
'recommend/music_weekly',
'recommend/music_theaudiodb_albums',
'recommend/music_theaudiodb_tracks',
'recommend/music_douban',
])
).toEqual(['recommend/music_weekly', 'recommend/music_douban'])
expect(
sources.filter(source => source.type === 'translated:recommend.categoryAnime').map(source => source.apipath),
).toEqual([
+6 -7
View File
@@ -2,7 +2,6 @@ import type { MediaInfo, MusicAlbumInfo, MusicArtistInfo, MusicEntityType } from
import type { RouteLocationRaw } from 'vue-router'
export interface MusicRouteTarget {
source?: string
media_source?: string
media_id?: string | number
music_type?: MusicEntityType
@@ -59,7 +58,7 @@ export function formatMusicAudioSpecs(item?: MusicAudioInfo): string {
/** 返回音乐对象可用于路由和订阅的统一来源。 */
export function getMusicSource(item: MusicRouteTarget): string | undefined {
return item.source || item.media_source
return item.media_source
}
/** 返回内置音乐元数据源的用户可见名称。 */
@@ -80,13 +79,13 @@ export function getMusicKey(item: MusicRouteTarget): string {
}
/** 构造专辑详情路由。 */
export function buildMusicAlbumRoute(albumId: string, title?: string, source = 'musicbrainz'): RouteLocationRaw {
return { path: '/music/album', query: { source, mediaid: albumId, title } }
export function buildMusicAlbumRoute(albumId: string, title?: string, mediaSource = 'musicbrainz'): RouteLocationRaw {
return { path: '/music/album', query: { media_source: mediaSource, mediaid: albumId, title } }
}
/** 构造艺术家详情路由。 */
export function buildMusicArtistRoute(artistId: string, name?: string, source = 'musicbrainz'): RouteLocationRaw {
return { path: '/music/artist', query: { source, mediaid: artistId, title: name } }
export function buildMusicArtistRoute(artistId: string, name?: string, mediaSource = 'musicbrainz'): RouteLocationRaw {
return { path: '/music/artist', query: { media_source: mediaSource, mediaid: artistId, title: name } }
}
/** 按音乐实体类型构造详情路由,缺少标准身份时回退到音乐搜索页。 */
@@ -101,7 +100,7 @@ export function buildMusicDetailRoute(item: MusicRouteTarget): RouteLocationRaw
return {
path: '/music/detail',
query: {
source,
media_source: source,
mediaid: mediaId,
title: item.title || item.name,
},
-12
View File
@@ -48,18 +48,6 @@ export function createBuiltInRecommendSources(t: Translate): RecommendViewSource
title: t('recommend.listenBrainzWeekly'),
type: t('recommend.categoryMusic'),
},
{
apipath: 'recommend/music_theaudiodb_albums',
linkurl: '/browse/recommend/music_theaudiodb_albums?title=' + t('recommend.theAudioDbAlbums'),
title: t('recommend.theAudioDbAlbums'),
type: t('recommend.categoryMusic'),
},
{
apipath: 'recommend/music_theaudiodb_tracks',
linkurl: '/browse/recommend/music_theaudiodb_tracks?title=' + t('recommend.theAudioDbTracks'),
title: t('recommend.theAudioDbTracks'),
type: t('recommend.categoryMusic'),
},
{
apipath: 'recommend/music_douban',
linkurl: '/browse/recommend/music_douban?title=' + t('recommend.doubanMusic'),