v2.0.0
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
|
||||
import { throttle } from '@common/utils/common'
|
||||
import { toRaw } from '@common/utils/vueTools'
|
||||
import {
|
||||
getSearchHistoryList,
|
||||
saveSearchHistoryList,
|
||||
} from '@renderer/utils/ipc'
|
||||
import { appSetting } from '../setting'
|
||||
import { searchText, historyList } from './state'
|
||||
|
||||
|
||||
export const setSearchText = (text: string) => {
|
||||
searchText.value = text
|
||||
}
|
||||
|
||||
let isInitedSearchHistory = false
|
||||
const saveSearchHistoryListThrottle = throttle((list: LX.List.SearchHistoryList) => {
|
||||
saveSearchHistoryList(list)
|
||||
}, 500)
|
||||
|
||||
|
||||
export const getHistoryList = async() => {
|
||||
if (isInitedSearchHistory) return
|
||||
historyList.push(...(await getSearchHistoryList() ?? []))
|
||||
isInitedSearchHistory = true
|
||||
}
|
||||
export const addHistoryWord = async(word: string) => {
|
||||
if (!appSetting['search.isShowHistorySearch']) return
|
||||
if (!isInitedSearchHistory) await getHistoryList()
|
||||
let index = historyList.indexOf(word)
|
||||
if (index > -1) historyList.splice(index, 1)
|
||||
if (historyList.length >= 15) historyList.splice(14, historyList.length - 14)
|
||||
historyList.unshift(word)
|
||||
saveSearchHistoryListThrottle(toRaw(historyList))
|
||||
}
|
||||
export const removeHistoryWord = (index: number) => {
|
||||
historyList.splice(index, 1)
|
||||
saveSearchHistoryListThrottle(toRaw(historyList))
|
||||
}
|
||||
export const clearHistoryList = (id: string) => {
|
||||
historyList.splice(0, historyList.length)
|
||||
saveSearchHistoryList([])
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
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, ListInfo } 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 total = 0
|
||||
// let limit = 0
|
||||
let list = []
|
||||
for (const source of results) {
|
||||
maxPages[source.source] = source.allPage
|
||||
if (source.allPage < page) continue
|
||||
list.push(...source.list)
|
||||
pages.push(source.allPage)
|
||||
total += source.total
|
||||
// limit = Math.max(source.limit, limit)
|
||||
}
|
||||
list = deduplicationList(list.map(s => markRaw(toNewMusicInfo(s))))
|
||||
let listInfo = listInfos.all
|
||||
listInfo.maxPage = Math.max(...pages)
|
||||
listInfo.total = total
|
||||
// listInfo.limit = limit
|
||||
listInfo.page = page
|
||||
listInfo.list = handleSortList(list, text)
|
||||
if (text && !list.length) 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] as ListInfo
|
||||
listInfo.list = deduplicationList(datas.list.map(s => markRaw(toNewMusicInfo(s))))
|
||||
listInfo.total = datas.total
|
||||
listInfo.maxPage = datas.allPage
|
||||
listInfo.page = page
|
||||
listInfo.limit = datas.limit
|
||||
if (text && !datas.list.length) listInfo.noItemLabel = window.i18n.t('no_item')
|
||||
else listInfo.noItemLabel = ''
|
||||
return listInfo.list
|
||||
}
|
||||
|
||||
export const resetListInfo = (sourceId: LX.OnlineSource | 'all'): [] => {
|
||||
let listInfo = listInfos[sourceId] as ListInfo
|
||||
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<LX.Music.MusicInfo[]> => {
|
||||
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).catch((error: any) => {
|
||||
console.log(error)
|
||||
return {
|
||||
allPage: 1,
|
||||
limit: 30,
|
||||
list: [],
|
||||
source,
|
||||
total: 0,
|
||||
}
|
||||
}))
|
||||
}
|
||||
return await 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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
export * from './action'
|
||||
export * from './state'
|
||||
@@ -0,0 +1,48 @@
|
||||
import { reactive, markRaw } from '@common/utils/vueTools'
|
||||
import music from '@renderer/utils/musicSdk'
|
||||
|
||||
// import { deduplicationList } from '@common/utils/renderer'
|
||||
|
||||
export declare interface ListInfo {
|
||||
list: LX.Music.MusicInfo[]
|
||||
total: number
|
||||
page: number
|
||||
maxPage: number
|
||||
limit: number
|
||||
key: string | null
|
||||
noItemLabel: string
|
||||
}
|
||||
|
||||
interface ListInfos extends Partial<Record<LX.OnlineSource, ListInfo>> {
|
||||
'all': ListInfo
|
||||
}
|
||||
|
||||
export const sources: Array<LX.OnlineSource | 'all'> = markRaw([])
|
||||
|
||||
export const listInfos: ListInfos = markRaw({
|
||||
all: reactive<ListInfo>({
|
||||
page: 1,
|
||||
maxPage: 0,
|
||||
limit: 30,
|
||||
total: 0,
|
||||
list: [],
|
||||
key: null,
|
||||
noItemLabel: '',
|
||||
}),
|
||||
})
|
||||
export const maxPages: Partial<Record<LX.OnlineSource, number>> = {}
|
||||
for (const source of music.sources) {
|
||||
if (!music[source.id as LX.OnlineSource].musicSearch) continue
|
||||
sources.push(source.id as LX.OnlineSource)
|
||||
listInfos[source.id as LX.OnlineSource] = reactive<ListInfo>({
|
||||
page: 1,
|
||||
maxPage: 0,
|
||||
limit: 30,
|
||||
total: 0,
|
||||
list: [],
|
||||
key: '',
|
||||
noItemLabel: '',
|
||||
})
|
||||
maxPages[source.id as LX.OnlineSource] = 0
|
||||
}
|
||||
sources.push('all')
|
||||
@@ -0,0 +1,123 @@
|
||||
import { markRawList } from '@common/utils/vueTools'
|
||||
import music from '@renderer/utils/musicSdk'
|
||||
import { sortInsert, similar } from '@common/utils/common'
|
||||
|
||||
import { sources, maxPages, listInfos, ListInfoItem, SearchListInfo } from './state'
|
||||
|
||||
interface SearchResult {
|
||||
list: ListInfoItem[]
|
||||
limit: number
|
||||
total: number
|
||||
source: LX.OnlineSource
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 按搜索关键词重新排序列表
|
||||
* @param list 歌曲列表
|
||||
* @param keyword 搜索关键词
|
||||
* @returns 排序后的列表
|
||||
*/
|
||||
const handleSortList = (list: ListInfoItem[], keyword: string) => {
|
||||
let arr: any[] = []
|
||||
for (const item of list) {
|
||||
sortInsert(arr, {
|
||||
num: similar(keyword, item.name),
|
||||
data: item,
|
||||
})
|
||||
}
|
||||
return arr.map(item => item.data).reverse()
|
||||
}
|
||||
|
||||
|
||||
let maxTotals: Partial<Record<LX.OnlineSource, number>> = {
|
||||
|
||||
}
|
||||
const setLists = (results: SearchResult[], page: number, text: string): ListInfoItem[] => {
|
||||
let totals = []
|
||||
// let limit = 0
|
||||
let list = []
|
||||
for (const source of results) {
|
||||
list.push(...source.list)
|
||||
totals.push(source.total)
|
||||
maxTotals[source.source] = source.total
|
||||
maxPages[source.source] = Math.ceil(source.total / source.limit)
|
||||
// limit = Math.max(source.limit, limit)
|
||||
}
|
||||
markRawList(list)
|
||||
|
||||
let listInfo = listInfos.all
|
||||
listInfo.total = Math.max(...totals)
|
||||
listInfo.page = page
|
||||
listInfo.list = handleSortList(list, text)
|
||||
if (text && !list.length) listInfo.noItemLabel = window.i18n.t('no_item')
|
||||
else listInfo.noItemLabel = ''
|
||||
return listInfo.list
|
||||
}
|
||||
|
||||
const setList = (datas: SearchResult, page: number, text: string): ListInfoItem[] => {
|
||||
// console.log(datas.source, datas.list)
|
||||
let listInfo = listInfos[datas.source] as SearchListInfo
|
||||
listInfo.list = markRawList(datas.list)
|
||||
listInfo.total = datas.total
|
||||
listInfo.page = page
|
||||
listInfo.limit = datas.limit
|
||||
if (text && !datas.list.length) listInfo.noItemLabel = window.i18n.t('no_item')
|
||||
else listInfo.noItemLabel = ''
|
||||
return listInfo.list
|
||||
}
|
||||
|
||||
export const resetListInfo = (sourceId: LX.OnlineSource | 'all'): [] => {
|
||||
let listInfo = listInfos[sourceId] as SearchListInfo
|
||||
listInfo.page = 1
|
||||
listInfo.limit = 20
|
||||
listInfo.total = 0
|
||||
listInfo.list = []
|
||||
listInfo.key = null
|
||||
listInfo.noItemLabel = ''
|
||||
listInfo.tagId = ''
|
||||
listInfo.sortId = ''
|
||||
return []
|
||||
}
|
||||
|
||||
export const search = async(text: string, page: number, sourceId: LX.OnlineSource | 'all'): Promise<ListInfoItem[]> => {
|
||||
const listInfo = listInfos[sourceId] as SearchListInfo
|
||||
if (!text) return resetListInfo(sourceId)
|
||||
const key = `${page}__${sourceId}__${text}`
|
||||
if (listInfo.key == key && listInfo.list.length) return listInfo.list
|
||||
if (sourceId == 'all') {
|
||||
listInfo.noItemLabel = window.i18n.t('list__loading')
|
||||
listInfo.key = key
|
||||
let task = []
|
||||
for (const source of sources) {
|
||||
if (source == 'all' || (page > 1 && page > (maxPages[source] as number))) continue
|
||||
task.push(music[source].songList.search(text, page, listInfos.all.limit).catch((error: any) => {
|
||||
console.log(error)
|
||||
return {
|
||||
list: [],
|
||||
total: 0,
|
||||
limit: listInfos.all.limit,
|
||||
source,
|
||||
}
|
||||
}))
|
||||
}
|
||||
return await 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].songList.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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
export * from './action'
|
||||
export * from './state'
|
||||
@@ -0,0 +1,48 @@
|
||||
import { reactive, markRaw } from '@common/utils/vueTools'
|
||||
import music from '@renderer/utils/musicSdk'
|
||||
|
||||
// import { deduplicationList } from '@common/utils/renderer'
|
||||
|
||||
import { ListInfo } from '@renderer/store/songList/state'
|
||||
|
||||
export { ListInfoItem } from '@renderer/store/songList/state'
|
||||
|
||||
export const sources: Array<LX.OnlineSource | 'all'> = markRaw([])
|
||||
|
||||
export type SearchListInfo = Omit<ListInfo, 'source'>
|
||||
|
||||
|
||||
interface ListInfos extends Partial<Record<LX.OnlineSource, SearchListInfo>> {
|
||||
'all': SearchListInfo
|
||||
}
|
||||
|
||||
|
||||
export const listInfos: ListInfos = markRaw({
|
||||
all: reactive<SearchListInfo>({
|
||||
page: 1,
|
||||
limit: 15,
|
||||
total: 0,
|
||||
list: [],
|
||||
key: null,
|
||||
noItemLabel: '',
|
||||
tagId: '',
|
||||
sortId: '',
|
||||
}),
|
||||
})
|
||||
export const maxPages: Partial<Record<LX.OnlineSource, number>> = {}
|
||||
for (const source of music.sources) {
|
||||
if (!music[source.id as LX.OnlineSource].songList?.search) continue
|
||||
sources.push(source.id as LX.OnlineSource)
|
||||
listInfos[source.id as LX.OnlineSource] = reactive<SearchListInfo>({
|
||||
page: 1,
|
||||
limit: 18,
|
||||
total: 0,
|
||||
list: [],
|
||||
key: null,
|
||||
noItemLabel: '',
|
||||
tagId: '',
|
||||
sortId: '',
|
||||
})
|
||||
maxPages[source.id as LX.OnlineSource] = 0
|
||||
}
|
||||
sources.push('all')
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ref, shallowReactive } from '@common/utils/vueTools'
|
||||
|
||||
|
||||
export const searchText = ref('')
|
||||
|
||||
export declare type onlineSource = LX.OnlineSource
|
||||
|
||||
|
||||
export const historyList = shallowReactive<string[]>([])
|
||||
Reference in New Issue
Block a user