diff --git a/src/renderer/api/bilibili.ts b/src/renderer/api/bilibili.ts index acb963a..b5e0efb 100644 --- a/src/renderer/api/bilibili.ts +++ b/src/renderer/api/bilibili.ts @@ -10,14 +10,50 @@ interface ISearchParams { } /** - * 搜索B站视频 + * 搜索B站视频(带自动重试) + * 最多重试10次,每次间隔100ms * @param params 搜索参数 */ -export const searchBilibili = (params: ISearchParams) => { +export const searchBilibili = async (params: ISearchParams): Promise => { console.log('调用B站搜索API,参数:', params); - return request.get('/bilibili/search', { - params - }); + const maxRetries = 10; + const delayMs = 100; + const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); + + let lastError: unknown = null; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const response = await request.get('/bilibili/search', { params }); + console.log('B站搜索API响应:', response); + const hasTitle = Boolean(response?.data?.data?.result?.length); + if (response?.status === 200 && hasTitle) { + return response; + } + + lastError = new Error( + `搜索结果不符合成功条件(缺少 data.title ) (attempt ${attempt}/${maxRetries})` + ); + console.warn('B站搜索API响应不符合要求,将重试。调试信息:', { + status: response?.status, + hasData: Boolean(response?.data), + hasInnerData: Boolean(response?.data?.data), + title: response?.data?.data?.title + }); + } catch (error) { + lastError = error; + console.warn(`B站搜索API错误[第${attempt}次],将重试:`, error); + } + + if (attempt === maxRetries) { + console.error('B站搜索API重试达到上限,仍然失败'); + if (lastError instanceof Error) throw lastError; + throw new Error('B站搜索失败且达到最大重试次数'); + } + + await delay(delayMs); + } + // 理论上不会到达这里,添加以满足TS控制流分析 + throw new Error('B站搜索在重试后未返回有效结果'); }; interface IBilibiliResponse { @@ -139,7 +175,7 @@ export const getBilibiliAudioUrl = async (bvid: string, cid: number): Promise 0) { - url = playUrlData.dash.audio[0].baseUrl; + url = playUrlData.dash.audio[playUrlData.dash.audio.length - 1].baseUrl; } else if (playUrlData.durl && playUrlData.durl.length > 0) { url = playUrlData.durl[0].url; } else { @@ -158,6 +194,9 @@ export const searchAndGetBilibiliAudioUrl = async (keyword: string): Promise -
@@ -175,7 +174,7 @@ import { getSearchSuggestions } from '@/api/search'; import alipay from '@/assets/alipay.png'; import wechat from '@/assets/wechat.png'; import Coffee from '@/components/Coffee.vue'; -import { SEARCH_TYPES, USER_SET_OPTIONS } from '@/const/bar-const'; +import { SEARCH_TYPE, SEARCH_TYPES, USER_SET_OPTIONS } from '@/const/bar-const'; import { useZoom } from '@/hooks/useZoom'; import { useSearchStore } from '@/store/modules/search'; import { useSettingsStore } from '@/store/modules/settings'; @@ -312,12 +311,13 @@ const selectSearchType = (key: number) => { const rawSearchTypes = ref(SEARCH_TYPES); const searchTypeOptions = computed(() => { - // 引用 locale 以创建响应式依赖 locale.value; - return rawSearchTypes.value.map((type) => ({ - label: t(type.label), - key: type.key - })); + return rawSearchTypes.value + .filter((type) => isElectron || type.key !== SEARCH_TYPE.BILIBILI) + .map((type) => ({ + label: t(type.label), + key: type.key + })); }); const selectItem = async (key: string) => { diff --git a/src/renderer/services/audioService.ts b/src/renderer/services/audioService.ts index f122383..92add84 100644 --- a/src/renderer/services/audioService.ts +++ b/src/renderer/services/audioService.ts @@ -113,23 +113,29 @@ class AudioService { } private updateMediaSessionMetadata(track: SongResult) { - if (!('mediaSession' in navigator)) return; + try { + if (!('mediaSession' in navigator)) return; - const artists = track.ar ? track.ar.map((a) => a.name) : track.song.artists?.map((a) => a.name); - const album = track.al ? track.al.name : track.song.album.name; - const artwork = ['96', '128', '192', '256', '384', '512'].map((size) => ({ - src: `${track.picUrl}?param=${size}y${size}`, - type: 'image/jpg', - sizes: `${size}x${size}` - })); - const metadata = { - title: track.name || '', - artist: artists ? artists.join(',') : '', - album: album || '', - artwork - }; + const artists = track.ar + ? track.ar.map((a) => a.name) + : track.song.artists?.map((a) => a.name); + const album = track.al ? track.al.name : track.song.album.name; + const artwork = ['96', '128', '192', '256', '384', '512'].map((size) => ({ + src: `${track.picUrl}?param=${size}y${size}`, + type: 'image/jpg', + sizes: `${size}x${size}` + })); + const metadata = { + title: track.name || '', + artist: artists ? artists.join(',') : '', + album: album || '', + artwork + }; - navigator.mediaSession.metadata = new window.MediaMetadata(metadata); + navigator.mediaSession.metadata = new window.MediaMetadata(metadata); + } catch (error) { + console.error('更新媒体会话元数据时出错:', error); + } } private updateMediaSessionState(isPlaying: boolean) { @@ -140,14 +146,17 @@ class AudioService { } private updateMediaSessionPositionState() { - if (!this.currentSound || !('mediaSession' in navigator)) return; - - if ('setPositionState' in navigator.mediaSession) { - navigator.mediaSession.setPositionState({ - duration: this.currentSound.duration(), - playbackRate: this.playbackRate, - position: this.currentSound.seek() as number - }); + try { + if (!this.currentSound || !('mediaSession' in navigator)) return; + if ('setPositionState' in navigator.mediaSession) { + navigator.mediaSession.setPositionState({ + duration: this.currentSound.duration(), + playbackRate: this.playbackRate, + position: this.currentSound.seek() as number + }); + } + } catch (error) { + console.error('更新媒体会话位置状态时出错:', error); } }