From 888136fd723679a170d54ffb35de8ca1ed462a67 Mon Sep 17 00:00:00 2001 From: Link Date: Wed, 10 Feb 2021 20:44:17 +0800 Subject: [PATCH] feat: support search all songs --- src/api/search.ts | 53 +++ .../secondary-bar/index.tsx | 17 +- src/components-business/table/index.less | 8 +- src/components-business/table/index.tsx | 66 +++- src/interface/app.ts | 6 + src/interface/index.ts | 1 + src/interface/service/songs.ts | 3 + src/pages/header/api/search.ts | 25 -- src/pages/header/component/search.less | 12 +- src/pages/header/component/search.tsx | 28 +- src/pages/header/interface.ts | 16 +- src/pages/header/sage.ts | 2 +- src/pages/index.ts | 2 +- .../news/children/song-list/api/index.ts | 4 +- src/pages/news/children/song-list/sage.ts | 4 +- src/pages/news/interface.ts | 5 +- src/pages/search/children/album.tsx | 8 + src/pages/search/children/artist.tsx | 8 + src/pages/search/children/lyrice.tsx | 8 + src/pages/search/children/song-list.tsx | 8 + src/pages/search/children/song.tsx | 57 ++++ src/pages/search/index.ts | 7 + src/pages/search/interface.ts | 37 +++ src/pages/search/logic/index.ts | 14 + src/pages/search/view/search.less | 6 + src/pages/search/view/search.tsx | 26 ++ src/router/base.ts | 22 ++ src/router/content.ts | 201 ++++++++++++ src/router/index.ts | 309 +----------------- src/router/nav.tsx | 200 ++++++++++++ src/utils/effect.ts | 5 + src/utils/http.ts | 6 +- 32 files changed, 798 insertions(+), 376 deletions(-) create mode 100644 src/api/search.ts delete mode 100644 src/pages/header/api/search.ts create mode 100644 src/pages/search/children/album.tsx create mode 100644 src/pages/search/children/artist.tsx create mode 100644 src/pages/search/children/lyrice.tsx create mode 100644 src/pages/search/children/song-list.tsx create mode 100644 src/pages/search/children/song.tsx create mode 100644 src/pages/search/index.ts create mode 100644 src/pages/search/interface.ts create mode 100644 src/pages/search/logic/index.ts create mode 100644 src/pages/search/view/search.less create mode 100644 src/pages/search/view/search.tsx create mode 100644 src/router/base.ts create mode 100644 src/router/content.ts create mode 100644 src/router/nav.tsx create mode 100644 src/utils/effect.ts diff --git a/src/api/search.ts b/src/api/search.ts new file mode 100644 index 00000000..b751d998 --- /dev/null +++ b/src/api/search.ts @@ -0,0 +1,53 @@ +import { get } from '@/utils/http' +import { SearchSuggest, SearchType, Pagination } from '@/interface' + +interface SearchApiResult { + [SearchType.SONG]: { + songs: SearchSuggest['songs'] + songCount: number + } + [SearchType.SONG_LIST]: { + playlists: SearchSuggest['playlists'] + playlistCount: number + } + [SearchType.ALBUM]: { + albums: SearchSuggest['albums'] + albumCount: number + } + [SearchType.ARTIST]: { + artists: SearchSuggest['artists'] + artistCount: number + } + [SearchType.LYRICE]: { + songs: SearchSuggest['lyrice'] + songCount: number + } +} + +export const search = async ( + key: string, + type: T, + pagination: Pagination +): Promise => { + const songs = await get<{ + result: SearchApiResult[T] + }>('/api/search', { + keywords: key, + type: type, + ...pagination + }) + + return songs.result +} + +export const searchSuggest = async (key: string): Promise => { + const data = await get<{ result: SearchSuggest }>('/api/search/suggest', { + keywords: key + }) + const songs = await search(key, SearchType.SONG, { + limit: 30, + offset: 0 + }) + data.result.songs = songs.songs + return data.result +} diff --git a/src/components-business/secondary-bar/index.tsx b/src/components-business/secondary-bar/index.tsx index 427322c6..4d5a4313 100644 --- a/src/components-business/secondary-bar/index.tsx +++ b/src/components-business/secondary-bar/index.tsx @@ -1,5 +1,5 @@ -import { defineComponent, toRefs, PropType } from 'vue' -import { RouterLink, RouteRecordRaw } from 'vue-router' +import { defineComponent, toRefs, PropType, toRaw } from 'vue' +import { RouterLink, RouteRecordRaw, useRoute } from 'vue-router' import './index.less' const prefix = 'secondary' @@ -26,6 +26,17 @@ export const SecondaryBar = defineComponent({ }, setup(props) { const { nav, size } = toRefs(props) + const route = useRoute() + + const renderPath = (url: string) => { + if (typeof url === 'string') { + return { + path: url, + query: toRaw(route.query) + } + } + return url + } return () => (
@@ -34,7 +45,7 @@ export const SecondaryBar = defineComponent({ {link.meta?.name} diff --git a/src/components-business/table/index.less b/src/components-business/table/index.less index ed0d294c..7021e419 100644 --- a/src/components-business/table/index.less +++ b/src/components-business/table/index.less @@ -1,13 +1,19 @@ @prefix: ~'table'; .@{prefix} { - display: block; + height: 100%; + overflow: auto; &-body { .ant-table-tbody > tr > td, .ant-table-thead > tr > th { padding: 12px 16px; } } + &-pagination { + display: flex; + justify-content: center; + padding: 10px 0; + } .row-music { cursor: pointer; } diff --git a/src/components-business/table/index.tsx b/src/components-business/table/index.tsx index 3f2613c0..2caef98e 100644 --- a/src/components-business/table/index.tsx +++ b/src/components-business/table/index.tsx @@ -1,10 +1,11 @@ -import { defineComponent, PropType, toRefs, ref, computed } from 'vue' -import { Table as ATable } from 'ant-design-vue' +import { defineComponent, PropType, toRefs, ref, computed, watch } from 'vue' +import { Table as ATable, Pagination as APagination } from 'ant-design-vue' import { noop, formatTime, formatTimeToStandard, - formatSize + formatSize, + scrollAnmation } from '@/utils/index' import { SongsDetail, @@ -12,16 +13,19 @@ import { FooterMutations, DownloadActions, SongListColumnsType, - DownloadMutations + DownloadMutations, + Pagination } from '@/interface/index' import { useDownloadModule, useFooterModule } from '@/modules/index' import { useSubscribe } from '@/shared/subscribe' import { getMusicUrl } from '@/shared/music-shared' import { instance } from '@/components-business/fly/index' +import { TweenMap } from '@/utils/tween' import './index.less' const prefix = 'table' +const tween = TweenMap['Quad-easeOut'] const columns = [ { width: 40, @@ -194,20 +198,31 @@ export const Table = defineComponent({ type: Boolean as PropType, default: true }, + pagination: { + type: Object as PropType, + default: () => ({}) + }, onDblclick: { // eslint-disable-next-line @typescript-eslint/no-explicit-any type: Function as PropType<(item: any) => void>, default: noop }, + onChange: { + type: Function as PropType<(page: number, size: number) => void>, + default: noop + }, rowClassName: { // eslint-disable-next-line @typescript-eslint/no-explicit-any type: Function as PropType<(item: any) => void>, default: () => 'row-music' } }, - emits: ['dblclick'], + emits: ['dblclick', 'change'], setup(props, { emit }) { - const { list, columnsTypes, showHeader, rowClassName } = toRefs(props) + const contanier = ref() + const { list, columnsTypes, showHeader, rowClassName, pagination } = toRefs( + props + ) const renderColumns = computed(() => { const col: unknown[] = [] @@ -220,8 +235,26 @@ export const Table = defineComponent({ return col }) + const paginationChange = (page: number, size: number) => { + emit('change', page, size) + } + + watch(list, () => { + if (contanier.value) { + const scrollContanier = contanier.value + const from = scrollContanier.scrollTop + scrollAnmation(from, 0, { + tween: tween, + duration: 200, + cb: n => { + contanier.value && (scrollContanier.scrollTop = n) + } + }) + } + }) + return () => ( -
+
{/*
*/}
- {/*
- -
*/} + {pagination.value.limit && ( +
+ +
+ )}
) } diff --git a/src/interface/app.ts b/src/interface/app.ts index 601c812f..aa1bd1ca 100644 --- a/src/interface/app.ts +++ b/src/interface/app.ts @@ -12,6 +12,12 @@ export interface GlobalBase { name: string } +export interface Pagination { + offset: number + limit: number + total?: number +} + export interface ElectronWindowEventMap extends WindowEventMap { maximize: Event unmaximize: Event diff --git a/src/interface/index.ts b/src/interface/index.ts index 75e088da..8304686e 100644 --- a/src/interface/index.ts +++ b/src/interface/index.ts @@ -1,5 +1,6 @@ export * from './http' export * from './app' +export * from './utils' export * from './service/albums' export * from './service/artists' export * from './service/songs' diff --git a/src/interface/service/songs.ts b/src/interface/service/songs.ts index ab84cd2c..4f965f98 100644 --- a/src/interface/service/songs.ts +++ b/src/interface/service/songs.ts @@ -1,8 +1,11 @@ import { Artists } from './artists' import { GlobalBase } from '../app' +import { Albums } from './albums' export interface Songs extends GlobalBase { artists: Artists[] + duration?: number + album?: Albums } export interface Song extends Songs { diff --git a/src/pages/header/api/search.ts b/src/pages/header/api/search.ts deleted file mode 100644 index 20bb2ab0..00000000 --- a/src/pages/header/api/search.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { get } from '@/utils/http' -import { SearchSuggest } from '@/interface' - -interface QQ { - id: { song: number; file: number } - name: string - duration: number - album: { id: string; name: string } - artists: { id: number; name: string; alias: unknown[]; img1v1Url: string }[] -} - -export const searchSuggest = async (key: string): Promise => { - const data = await get<{ result: SearchSuggest }>('/api/search/suggest', { - keywords: key - }) - const songs = await get<{ - result: { - songs: SearchSuggest['songs'] - } - }>('/api/search', { - keywords: key - }) - data.result.songs = songs.result.songs - return data.result -} diff --git a/src/pages/header/component/search.less b/src/pages/header/component/search.less index 1005b233..f925bc54 100644 --- a/src/pages/header/component/search.less +++ b/src/pages/header/component/search.less @@ -12,6 +12,14 @@ li.qq-song { &-popper { height: 240px; font-size: 13px; + .keyword { + font-weight: normal; + color: var(--primary-theme-text); + } + &-more { + padding: 10px 20px; + cursor: pointer; + } &-title { padding: 4px 10px; background-color: #e7e7e7; @@ -29,10 +37,6 @@ li.qq-song { &:hover { background-color: #eaeaea; } - .keyword { - font-weight: normal; - color: var(--primary-theme-text); - } } } &-last { diff --git a/src/pages/header/component/search.tsx b/src/pages/header/component/search.tsx index 37e6f391..51c804f6 100644 --- a/src/pages/header/component/search.tsx +++ b/src/pages/header/component/search.tsx @@ -6,6 +6,13 @@ import { playMusic } from '@/shared/music-shared' import debounce from 'lodash/debounce' import './search.less' +const enum SearchType { + SONGS = 'SONGS', + ARTISTS = 'ARTISTS', + ALBUMS = 'ALBUMS', + PLAYLISTS = 'PLAYLISTS' +} + const Option = defineComponent({ name: 'Option', props: { @@ -92,7 +99,7 @@ const Group = defineComponent({ }) export const Search = defineComponent({ - name: 'Search', + name: 'SearchInput', components: { Option, Group @@ -118,13 +125,6 @@ export const Search = defineComponent({ } }, 200) - const enum SearchType { - SONGS = 'SONGS', - ARTISTS = 'ARTISTS', - ALBUMS = 'ALBUMS', - PLAYLISTS = 'PLAYLISTS' - } - const handleSelect = async (type: SearchType, id: unknown) => { switch (type) { case SearchType.SONGS: @@ -147,10 +147,22 @@ export const Search = defineComponent({ } } + const handleSearchMore = () => { + router.push({ + path: '/search/song', + query: { + words: words.value + } + }) + } + const Slot = { prefix: () => , popper: () => (
+
+ 搜"{words.value}"相关的结果 +
单曲
diff --git a/src/pages/header/interface.ts b/src/pages/header/interface.ts index 1fdd1601..9dceb97c 100644 --- a/src/pages/header/interface.ts +++ b/src/pages/header/interface.ts @@ -1,15 +1,15 @@ -import { Albums, Songs, Artists, PlayLists } from '@/interface/index' +import { SearchSuggest } from '@/interface' -export interface SearchSuggest { - albums?: Albums[] - artists?: Artists[] - songs?: Songs[] - order?: string[] - playlists?: PlayLists[] +export interface QQ { + id: { song: number; file: number } + name: string + duration: number + album: { id: string; name: string } + artists: { id: number; name: string; alias: unknown[]; img1v1Url: string }[] } export interface HeaderState { - searchSuggest: SearchSuggest + searchSuggest: Partial themeColor: string } diff --git a/src/pages/header/sage.ts b/src/pages/header/sage.ts index b7b7d459..e8bb8a73 100644 --- a/src/pages/header/sage.ts +++ b/src/pages/header/sage.ts @@ -1,5 +1,5 @@ import { ActionTree, MutationTree } from 'vuex' -import { searchSuggest } from './api/search' +import { searchSuggest } from '@/api/search' import { HeaderState, SearchSuggest, diff --git a/src/pages/index.ts b/src/pages/index.ts index 2bf4e543..5a128502 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line prettier/prettier export * from './list/interface' export * from './news/interface' export * from './header/interface' @@ -8,3 +7,4 @@ export * from './footer/interface' export * from './download/interface' export * from './music/interface' export * from './setting/interface' +export * from './search/interface' diff --git a/src/pages/news/children/song-list/api/index.ts b/src/pages/news/children/song-list/api/index.ts index d8501b0a..afd97efd 100644 --- a/src/pages/news/children/song-list/api/index.ts +++ b/src/pages/news/children/song-list/api/index.ts @@ -1,8 +1,8 @@ import { get } from '@/utils/http' -import { Song, Pagination, Catlists, Tags } from '@/interface/index' +import { Song, PaginationHighquality, Catlists, Tags } from '@/interface/index' export const getHighqualityPl = async ( - pagination: Pagination + pagination: PaginationHighquality ): Promise => { const data = await get<{ playlists: Song[] }>( '/api/top/playlist/highquality', diff --git a/src/pages/news/children/song-list/sage.ts b/src/pages/news/children/song-list/sage.ts index 68e2cec0..26243890 100644 --- a/src/pages/news/children/song-list/sage.ts +++ b/src/pages/news/children/song-list/sage.ts @@ -4,7 +4,7 @@ import { Song, SongListActions, SongListMutations, - Pagination, + PaginationHighquality, SongListState, Tags } from '@/interface/index' @@ -13,7 +13,7 @@ import { getHighqualityPl, getHighqualityTags, getHotTags } from './api/index' export const actions: ActionTree = { async [SongListActions.SET_ACTION_SONG_LIST]( { commit }, - pagination: Pagination + pagination: PaginationHighquality ) { const result = await getHighqualityPl(pagination) commit(SongListMutations.SET_SONG_LIST, result) diff --git a/src/pages/news/interface.ts b/src/pages/news/interface.ts index fbfe6aa7..e0b0a617 100644 --- a/src/pages/news/interface.ts +++ b/src/pages/news/interface.ts @@ -1,4 +1,4 @@ -import { Song } from '@/interface/index' +import { Pagination, Song } from '@/interface/index' import { Artist } from '@/interface/index' import { GlobalBase } from '@/interface/index' @@ -27,8 +27,7 @@ export interface ArtistsState { completed: boolean } -export interface Pagination { - limit: number +export interface PaginationHighquality extends Pagination { before: number cat: string } diff --git a/src/pages/search/children/album.tsx b/src/pages/search/children/album.tsx new file mode 100644 index 00000000..6a644d5c --- /dev/null +++ b/src/pages/search/children/album.tsx @@ -0,0 +1,8 @@ +import { defineComponent } from 'vue' + +export const SearchAlbum = defineComponent({ + name: 'SearchAlbum', + setup() { + return () =>
+ } +}) diff --git a/src/pages/search/children/artist.tsx b/src/pages/search/children/artist.tsx new file mode 100644 index 00000000..570182ee --- /dev/null +++ b/src/pages/search/children/artist.tsx @@ -0,0 +1,8 @@ +import { defineComponent } from 'vue' + +export const SearchArtist = defineComponent({ + name: 'SearchArtist', + setup() { + return () =>
+ } +}) diff --git a/src/pages/search/children/lyrice.tsx b/src/pages/search/children/lyrice.tsx new file mode 100644 index 00000000..470007bf --- /dev/null +++ b/src/pages/search/children/lyrice.tsx @@ -0,0 +1,8 @@ +import { defineComponent } from 'vue' + +export const SearchLyrice = defineComponent({ + name: 'SearchLyrice', + setup() { + return () =>
+ } +}) diff --git a/src/pages/search/children/song-list.tsx b/src/pages/search/children/song-list.tsx new file mode 100644 index 00000000..dec4e01c --- /dev/null +++ b/src/pages/search/children/song-list.tsx @@ -0,0 +1,8 @@ +import { defineComponent } from 'vue' + +export const SearchSongList = defineComponent({ + name: 'SearchSongList', + setup() { + return () =>
+ } +}) diff --git a/src/pages/search/children/song.tsx b/src/pages/search/children/song.tsx new file mode 100644 index 00000000..a3f51ee1 --- /dev/null +++ b/src/pages/search/children/song.tsx @@ -0,0 +1,57 @@ +import { defineComponent, reactive, ref } from 'vue' +import { Table } from '@/components-business/table/index' +import { effectWords } from '../logic/index' +import { search } from '@/api/search' +import { playMusic } from '@/shared/music-shared' +import { Pagination, SearchType, SearchSuggest, ArrayItem } from '@/interface' + +type Songs = SearchSuggest['songs'] + +export const SearchSong = defineComponent({ + name: 'SearchSong', + setup() { + const list = ref([]) + const pagination = reactive({ + limit: 30, + offset: 1, + total: 0 + }) + + const updateList = async (words: string) => { + if (words) { + const result = await search(words, SearchType.SONG, pagination) + list.value = result.songs.map(song => { + return { + ...song, + dt: song.duration, + al: song.album, + ar: song.artists + } + }) + pagination.total = result.songCount + } + } + + const handleChange = (page: number) => { + pagination.offset = page + } + + const handlePlaySingle = (song: ArrayItem) => { + playMusic(song.id) + } + + effectWords(updateList, [pagination]) + + return () => ( +
+ + + ) + } +}) diff --git a/src/pages/search/index.ts b/src/pages/search/index.ts new file mode 100644 index 00000000..3b968e8f --- /dev/null +++ b/src/pages/search/index.ts @@ -0,0 +1,7 @@ +/* eslint-disable prettier/prettier */ +export { Search } from './view/search' +export { SearchSong } from './children/song' +export { SearchSongList } from './children/song-list' +export { SearchAlbum } from './children/album' +export { SearchArtist } from './children/artist' +export { SearchLyrice } from './children/lyrice' diff --git a/src/pages/search/interface.ts b/src/pages/search/interface.ts new file mode 100644 index 00000000..ad6c3476 --- /dev/null +++ b/src/pages/search/interface.ts @@ -0,0 +1,37 @@ +import { + SongsDetail, + Albums, + Songs, + Artists, + PlayLists, + Merage +} from '@/interface/index' + +export interface SearchSuggest { + albums: Albums[] + artists: Artists[] + songs: Merage<{ album: Albums }, Songs>[] + order: string[] + playlists: PlayLists[] + lyrice: Merage< + { + txt: string + }, + Songs + >[] +} + +export const enum SearchType { + SONG = 1, + ALBUM = 10, + ARTIST = 100, + SONG_LIST = 1000, + LYRICE = 1006 +} + +export interface SearchState { + songs: SongsDetail +} + +export const enum SearchActions {} +export const enum SearchMutations {} diff --git a/src/pages/search/logic/index.ts b/src/pages/search/logic/index.ts new file mode 100644 index 00000000..cd1a14f2 --- /dev/null +++ b/src/pages/search/logic/index.ts @@ -0,0 +1,14 @@ +import { watch } from 'vue' +import { useRoute } from '@/hooks/index' + +export const effectWords = ( + cb: (word: string, deps?: unknown[]) => void, + deps: unknown[] +) => { + const route = useRoute() + + cb(route.query.words as string) + watch([() => route.query.words, ...deps], ([words, deps]) => { + cb((words as unknown) as string, deps as unknown[]) + }) +} diff --git a/src/pages/search/view/search.less b/src/pages/search/view/search.less new file mode 100644 index 00000000..58c61335 --- /dev/null +++ b/src/pages/search/view/search.less @@ -0,0 +1,6 @@ +.search { + &-song { + height: 100%; + overflow: hidden; + } +} diff --git a/src/pages/search/view/search.tsx b/src/pages/search/view/search.tsx new file mode 100644 index 00000000..755b9daa --- /dev/null +++ b/src/pages/search/view/search.tsx @@ -0,0 +1,26 @@ +import { defineComponent } from 'vue' +import { MusicLayout } from '@/layout/music/music' +import { contentRouter } from '@/router/index' +import { RouterView } from 'vue-router' +import { + SecondaryBar, + renderNavList +} from '@/components-business/secondary-bar/index' +import './search.less' + +export const Search = defineComponent({ + name: 'Search', + setup() { + const nav = renderNavList(contentRouter, Search.name) + + return () => ( +
找到 {} 首歌曲
, + head: () => , + body: () => + }} + /> + ) + } +}) diff --git a/src/router/base.ts b/src/router/base.ts new file mode 100644 index 00000000..b6f091a7 --- /dev/null +++ b/src/router/base.ts @@ -0,0 +1,22 @@ +import { RouteRecordRaw } from 'vue-router' +import { $404 } from '@/pages/404/view/index' + +// Internationalization is not currently supported +export const baseRouter: RouteRecordRaw[] = [ + { + path: '/:pathMatch(.*)', // https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes + name: $404.name, + meta: { + full: true, + canBeCollect: false // Can be collected by a custom controller + }, + component: $404 + }, + { + path: '/', + redirect: '/music', + meta: { + canBeCollect: false + } + } +] diff --git a/src/router/content.ts b/src/router/content.ts new file mode 100644 index 00000000..b0e6637e --- /dev/null +++ b/src/router/content.ts @@ -0,0 +1,201 @@ +import { RouteRecordRaw } from 'vue-router' + +const List = () => import('@/pages/list/view/index') + +const Artist = () => + import(/* webpackChunkName: "artist" */ '@/pages/artist/view/index') + +const ArtistAlbume = () => + import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( + component => component.Albume + ) + +const ArtistMv = () => + import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( + component => component.Mv + ) + +const ArtistDesc = () => + import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( + component => component.Desc + ) + +const ArtistSimilar = () => + import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( + component => component.Similar + ) + +const Setting = () => + import(/* webpackChunkName: "setting" */ '@/pages/setting/index').then( + component => component.Setting + ) + +const Search = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.Search + ) + +const SearchSong = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.SearchSong + ) + +const SearchArtist = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.SearchArtist + ) + +const SearchAlbum = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.SearchAlbum + ) + +const SearchSongList = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.SearchSongList + ) + +const SearchLyrice = () => + import(/* webpackChunkName: "search" */ '@/pages/search/index').then( + component => component.SearchLyrice + ) + +export const contentBaseRouter: RouteRecordRaw[] = [ + { + path: '/list/:type/:playlist', + component: List, + meta: { + canBeCollect: true, + browser: true, + electron: true + } + }, + { + path: '/artist/:id', + component: Artist, + name: 'Artist', + meta: { + canBeCollect: true, + browser: true, + electron: true + }, + beforeEnter: (to, from, next) => { + if (to.params.id) { + next() + } else { + next({ + path: '/' + }) + } + }, + children: [ + { + path: 'album', + component: ArtistAlbume, + name: 'ArtistAlbume', + meta: { + name: '专辑', + canBeCollect: true + } + }, + { + path: 'mv', + component: ArtistMv, + name: 'ArtistMv', + meta: { + name: 'MV', + canBeCollect: true + } + }, + { + path: 'detail', + component: ArtistDesc, + name: 'ArtistDesc', + meta: { + name: '歌手详情', + canBeCollect: true + } + }, + { + path: 'similar', + component: ArtistSimilar, + name: 'ArtistSimilar', + meta: { + name: '相似歌手', + canBeCollect: true + } + } + ] + }, + { + path: '/setting/:location', + component: Setting, + name: 'Setting', + meta: { + canBeCollect: true, + browser: true, + electron: true + } + }, + { + path: '/search', + name: 'Search', + component: Search, + meta: { + canBeCollect: true, + browser: true, + electron: true + }, + children: [ + { + path: '', + redirect: '/search/song' + }, + { + path: 'song', + component: SearchSong, + name: 'SearchSong', + meta: { + name: '歌曲', + path: 'song' + } + }, + { + path: 'artist', + component: SearchArtist, + name: 'SearchArtist', + meta: { + name: '歌手', + path: 'artist' + } + }, + { + path: 'album', + component: SearchAlbum, + name: 'SearchAlbum', + meta: { + name: '专辑', + path: 'album' + } + }, + { + path: 'songlist', + component: SearchSongList, + name: 'SearchSongList', + meta: { + name: '歌单', + path: 'songlist' + } + }, + { + path: 'lyrice', + component: SearchLyrice, + name: 'SearchLyrice', + meta: { + name: '歌词', + path: 'lyrice' + } + } + ] + } +] diff --git a/src/router/index.ts b/src/router/index.ts index 38d095e7..6dc8cf0d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -6,17 +6,10 @@ import { } from 'vue-router' import { ComponentPublicInstance } from 'vue' import { hook } from './hook' -import { $404 } from '@/pages/404/view/index' -import { News, Recommend, SongList, TopList, Artists } from '@/pages/news/index' -// Use this method when you need to load dynamically -// const video = () => import(/* webpackChunkName: "video" */ '@/pages/video/index') -import { Video, Mv } from '@/pages/video/index' -import { Profile } from '@/pages/auth/views/profile' -import { Moments } from '@/pages/moments/index' -import { LocalMusic, LocalMusicSong, LocalMusicDir } from '@/pages/music/index' -import { Download, DownloadSong, DownloadMv } from '@/pages/download/index' -import { Cloud } from '@/pages/cloud/index' -import { Setting } from '@/pages/setting/index' +import { baseRouter } from './base' +import { contentBaseRouter } from './content' +import { baseNavRouter } from './nav' + import { isBrowser, isElectron } from '@/utils' export interface Meta { @@ -32,106 +25,7 @@ export interface RouterChildren { export const LYRICE_PATH = '/electron-lyrice-float' -// Internationalization is not currently supported -const baseRouter: RouteRecordRaw[] = [ - { - path: '/:pathMatch(.*)', // https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes - name: $404.name, - meta: { - full: true, - canBeCollect: false - }, - component: $404 - }, - { - path: '/', - redirect: '/music', - meta: { - canBeCollect: false - } - }, - { - path: '/setting/:location', - name: Setting.name, - component: Setting, - meta: { - canBeCollect: true - } - } -] - -export const contentRouter: RouteRecordRaw[] = [ - { - path: '/list/:type/:playlist', - component: () => import('@/pages/list/view/index'), - meta: { - canBeCollect: true - } - }, - { - path: '/artist/:id', - component: () => - import(/* webpackChunkName: "artist" */ '@/pages/artist/view/index'), - name: 'Artist', - beforeEnter: (to, from, next) => { - if (to.params.id) { - next() - } else { - next({ - path: '/' - }) - } - }, - children: [ - { - path: 'album', - component: () => - import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( - component => component.Albume - ), - meta: { - name: '专辑', - canBeCollect: true - } - }, - { - path: 'mv', - component: () => - import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( - component => component.Mv - ), - meta: { - name: 'MV', - canBeCollect: true - } - }, - { - path: 'detail', - component: () => - import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( - component => component.Desc - ), - meta: { - name: '歌手详情', - canBeCollect: true - } - }, - { - path: 'similar', - component: () => - import(/* webpackChunkName: "artist" */ '@/pages/artist/index').then( - component => component.Similar - ), - meta: { - name: '相似歌手', - canBeCollect: true - } - } - ] - } -] - -const renderSidebar = (nav: RouteRecordRaw[]) => { +const renderRouter = (nav: RouteRecordRaw[]) => { return nav.filter(n => { if (isBrowser()) { return n?.meta?.browser @@ -143,197 +37,8 @@ const renderSidebar = (nav: RouteRecordRaw[]) => { }) } -export const baseNavRouter: RouteRecordRaw[] = [ - { - path: '/profile', - component: Profile, - name: Profile.name, - meta: { - auth: true, - nonav: true, - browser: true, - electron: true, - canBeCollect: true - } - }, - { - path: '/music', - component: News, - name: News.name, - meta: { - name: '发现音乐', - browser: true, - electron: true - }, - children: [ - { - path: '', - redirect: '/music/recommend' - }, - { - path: 'recommend', - component: Recommend, - name: 'recommend', - meta: { - name: '个性推荐', - path: 'recommend', - canBeCollect: true - } - }, - { - path: 'songlist', - component: SongList, - name: 'songlist', - meta: { - name: '精品歌单', - path: { - name: 'songlist', - query: { - tag: 'all' - } - }, - canBeCollect: true - } - }, - { - path: 'toplist', - component: TopList, - name: 'toplist', - meta: { - name: '排行榜', - path: 'toplist', - canBeCollect: true - } - }, - { - path: 'artists', - component: Artists, - name: 'artists', - meta: { - name: '歌手', - path: 'artists', - canBeCollect: true - } - } - ] - }, - { - path: '/video', - component: Video, - meta: { - name: '视频', - browser: true, - electron: true - }, - children: [ - { - path: '', - redirect: '/video/mv' - }, - { - path: '/video/mv', - component: Mv, - meta: { - name: 'MV', - canBeCollect: true - } - } - ] - }, - { - path: '/moments', - component: Moments, - meta: { - name: '朋友', - browser: false, - electron: false, - canBeCollect: true - } - }, - { - path: '/download', - component: Download, - name: Download.name, - meta: { - name: '下载管理', - beforeHeader: '我的音乐', - browser: true, - electron: true - }, - children: [ - { - path: '', - redirect: '/download/song' - }, - { - path: 'song', - component: DownloadSong, - meta: { - name: '已下载单曲', - path: 'song', - canBeCollect: true - } - }, - { - path: 'mv', - component: DownloadMv, - meta: { - name: '已下载MV', - path: 'mv', - canBeCollect: true - } - } - ] - }, - { - path: '/local-music', - component: LocalMusic, - name: LocalMusic.name, - meta: { - name: '本地音乐', - browser: false, - electron: true - }, - children: [ - { - path: '', - redirect: '/local-music/song' - }, - { - path: 'song', - component: LocalMusicSong, - meta: { - name: '歌曲', - path: 'song', - canBeCollect: true - } - }, - { - path: 'dir', - component: LocalMusicDir, - meta: { - name: '文件夹', - path: 'dir', - canBeCollect: true - } - } - ] - }, - { - path: '/cloud', - component: Cloud, - name: Cloud.name, - meta: { - name: '我的音乐云盘', - auth: true, - browser: true, - electron: true, - canBeCollect: true - } - } -] - -export const navRouter = renderSidebar(baseNavRouter) +export const navRouter = renderRouter(baseNavRouter) +export const contentRouter = renderRouter(contentBaseRouter) const router = createRouter({ // history: diff --git a/src/router/nav.tsx b/src/router/nav.tsx new file mode 100644 index 00000000..b166269d --- /dev/null +++ b/src/router/nav.tsx @@ -0,0 +1,200 @@ +import { RouteRecordRaw } from 'vue-router' +import { News, Recommend, SongList, TopList, Artists } from '@/pages/news/index' +// Use this method when you need to load dynamically +// const video = () => import(/* webpackChunkName: "video" */ '@/pages/video/index') +import { Video, Mv } from '@/pages/video/index' +import { Profile } from '@/pages/auth/views/profile' +import { Moments } from '@/pages/moments/index' +import { LocalMusic, LocalMusicSong, LocalMusicDir } from '@/pages/music/index' +import { Download, DownloadSong, DownloadMv } from '@/pages/download/index' +import { Cloud } from '@/pages/cloud/index' + +export const baseNavRouter: RouteRecordRaw[] = [ + { + path: '/profile', + component: Profile, + name: Profile.name, + meta: { + auth: true, + nonav: true, + browser: true, + electron: true, + canBeCollect: true + } + }, + { + path: '/music', + component: News, + name: News.name, + meta: { + name: '发现音乐', + browser: true, + electron: true + }, + children: [ + { + path: '', + redirect: '/music/recommend' + }, + { + path: 'recommend', + component: Recommend, + name: 'recommend', + meta: { + name: '个性推荐', + path: 'recommend', + canBeCollect: true + } + }, + { + path: 'songlist', + component: SongList, + name: 'songlist', + meta: { + name: '精品歌单', + path: { + name: 'songlist', + query: { + tag: 'all' + } + }, + canBeCollect: true + } + }, + { + path: 'toplist', + component: TopList, + name: 'toplist', + meta: { + name: '排行榜', + path: 'toplist', + canBeCollect: true + } + }, + { + path: 'artists', + component: Artists, + name: 'artists', + meta: { + name: '歌手', + path: 'artists', + canBeCollect: true + } + } + ] + }, + { + path: '/video', + component: Video, + meta: { + name: '视频', + browser: true, + electron: true + }, + children: [ + { + path: '', + redirect: '/video/mv' + }, + { + path: '/video/mv', + component: Mv, + meta: { + name: 'MV', + canBeCollect: true + } + } + ] + }, + { + path: '/moments', + component: Moments, + meta: { + name: '朋友', + browser: false, + electron: false, + canBeCollect: true + } + }, + { + path: '/download', + component: Download, + name: Download.name, + meta: { + name: '下载管理', + beforeHeader: '我的音乐', + browser: true, + electron: true + }, + children: [ + { + path: '', + redirect: '/download/song' + }, + { + path: 'song', + component: DownloadSong, + meta: { + name: '已下载单曲', + path: 'song', + canBeCollect: true + } + }, + { + path: 'mv', + component: DownloadMv, + meta: { + name: '已下载MV', + path: 'mv', + canBeCollect: true + } + } + ] + }, + { + path: '/local-music', + component: LocalMusic, + name: LocalMusic.name, + meta: { + name: '本地音乐', + browser: false, + electron: true + }, + children: [ + { + path: '', + redirect: '/local-music/song' + }, + { + path: 'song', + component: LocalMusicSong, + meta: { + name: '歌曲', + path: 'song', + canBeCollect: true + } + }, + { + path: 'dir', + component: LocalMusicDir, + meta: { + name: '文件夹', + path: 'dir', + canBeCollect: true + } + } + ] + }, + { + path: '/cloud', + component: Cloud, + name: Cloud.name, + meta: { + name: '我的音乐云盘', + auth: true, + browser: true, + electron: true, + canBeCollect: true + } + } +] diff --git a/src/utils/effect.ts b/src/utils/effect.ts new file mode 100644 index 00000000..ae0da080 --- /dev/null +++ b/src/utils/effect.ts @@ -0,0 +1,5 @@ +import { watchEffect } from 'vue' + +export const useCallback = (fn: (...args: any[]) => void, deps: any[]) => { + return fn +} diff --git a/src/utils/http.ts b/src/utils/http.ts index f44289cf..c936f941 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -27,7 +27,7 @@ http.defaults.params = {} http.interceptors.request.use( config => { - config.params[Date.now()] = 'no-cache' + config.params.timestampAxios = Date.now() return config }, error => { @@ -43,9 +43,9 @@ http.interceptors.response.use( return response }, error => { - const config = error.response.config as HttpConfig + const config = error.response?.config as HttpConfig if (error.response) { - if (error.response.status === 301 && config.auths) { + if (error.response.status === 301 && config?.auths) { store.commit('Auth/SHOW_VIEW') return syncToAsync(resolve => { on(