import { markRaw } from '@common/utils/vueTools' import music from '@renderer/utils/musicSdk' import { deduplicationList, toNewMusicInfo } from '@renderer/utils' import { sortInsert, similar } from '@common/utils/common' import { sources, maxPages, listInfos } from './state' interface SearchResult { list: LX.Music.MusicInfo[] allPage: number limit: number total: number source: LX.OnlineSource } /** * 按搜索关键词重新排序列表 * @param list 歌曲列表 * @param keyword 搜索关键词 * @returns 排序后的列表 */ const handleSortList = (list: LX.Music.MusicInfo[], keyword: string) => { let arr: any[] = [] for (const item of list) { sortInsert(arr, { num: similar(keyword, `${item.name} ${item.singer}`), data: item, }) } return arr.map(item => item.data).reverse() } const setLists = (results: SearchResult[], page: number, text: string): LX.Music.MusicInfo[] => { let pages = [] let totals = [] let limit = 0 let list = [] for (const source of results) { maxPages[source.source] = source.allPage limit = Math.max(source.limit, limit) if (source.allPage < page) continue list.push(...source.list) pages.push(source.allPage) totals.push(source.total) } list = deduplicationList(list.map(s => markRaw(toNewMusicInfo(s)))) let listInfo = listInfos.all listInfo.maxPage = Math.max(0, ...pages) const total = Math.max(0, ...totals) if (page == 1 || (total && list.length)) listInfo.total = total else listInfo.total = limit * page // listInfo.limit = limit listInfo.page = page listInfo.list = handleSortList(list, text) if (text && !list.length && page == 1) listInfo.noItemLabel = window.i18n.t('no_item') else listInfo.noItemLabel = '' return listInfo.list } const setList = (datas: SearchResult, page: number, text: string): LX.Music.MusicInfo[] => { // console.log(datas.source, datas.list) let listInfo = listInfos[datas.source]! listInfo.list = deduplicationList(datas.list.map(s => markRaw(toNewMusicInfo(s)))) if (page == 1 || (datas.total && datas.list.length)) listInfo.total = datas.total else listInfo.total = datas.limit * page listInfo.maxPage = datas.allPage listInfo.page = page listInfo.limit = datas.limit if (text && !datas.list.length && page == 1) listInfo.noItemLabel = window.i18n.t('no_item') else listInfo.noItemLabel = '' return listInfo.list } export const resetListInfo = (sourceId: LX.OnlineSource | 'all'): [] => { let listInfo = listInfos[sourceId]! listInfo.list = [] listInfo.page = 0 listInfo.maxPage = 0 listInfo.total = 0 listInfo.noItemLabel = '' return [] } export const search = async(text: string, page: number, sourceId: LX.OnlineSource | 'all'): Promise => { const listInfo = listInfos[sourceId] if (!text) return resetListInfo(sourceId) const key = `${page}__${text}` if (sourceId == 'all') { listInfo!.noItemLabel = window.i18n.t('list__loading') listInfo!.key = key let task = [] for (const source of sources) { if (source == 'all') continue task.push((music[source]?.musicSearch.search(text, page, listInfos.all.limit) ?? Promise.reject(new Error('source not found: ' + source))).catch((error: any) => { console.log(error) return { allPage: 1, limit: 30, list: [], source, total: 0, } })) } return Promise.all(task).then((results: SearchResult[]) => { if (key != listInfo!.key) return [] return setLists(results, page, text) }) } else { if (listInfo?.key == key && listInfo?.list.length) return listInfo?.list listInfo!.noItemLabel = window.i18n.t('list__loading') listInfo!.key = key return music[sourceId].musicSearch.search(text, page, listInfo!.limit).then((data: SearchResult) => { if (key != listInfo!.key) return [] return setList(data, page, text) }).catch((error: any) => { resetListInfo(sourceId) listInfo!.noItemLabel = window.i18n.t('list__load_failed') console.log(error) throw error }) } }