From 744fd53fb12124bcca865e06284746e1a77999f7 Mon Sep 17 00:00:00 2001 From: alger Date: Sun, 12 Jan 2025 20:59:36 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=B7=BB=E5=8A=A0=E6=AD=8C?= =?UTF-8?q?=E8=AF=8D=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.cjs | 1 + src/main/index.ts | 2 + src/main/modules/cache.ts | 89 +++++++++++++++++++++++++++++ src/preload/index.d.ts | 1 + src/preload/index.ts | 10 +++- src/renderer/api/music.ts | 23 +++++++- src/renderer/hooks/MusicListHook.ts | 3 - src/renderer/views/set/index.vue | 6 +- 8 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 src/main/modules/cache.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index fbb90aa..daf70aa 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -103,6 +103,7 @@ module.exports = { { files: ['*.ts', '*.tsx'], rules: { + 'max-classes-per-file': 'off', 'no-await-in-loop': 'off', 'dot-notation': 'off', 'constructor-super': 'off', diff --git a/src/main/index.ts b/src/main/index.ts index 229bee0..4cedd15 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,6 +3,7 @@ import { app, globalShortcut, ipcMain, nativeImage } from 'electron'; import { join } from 'path'; import { loadLyricWindow } from './lyric'; +import { initializeCacheManager } from './modules/cache'; import { initializeConfig } from './modules/config'; import { initializeFileManager } from './modules/fileManager'; import { initializeTray } from './modules/tray'; @@ -26,6 +27,7 @@ function initialize() { // 初始化各个模块 initializeConfig(); initializeFileManager(); + initializeCacheManager(); // 创建主窗口 mainWindow = createMainWindow(icon); diff --git a/src/main/modules/cache.ts b/src/main/modules/cache.ts new file mode 100644 index 0000000..89a3f7b --- /dev/null +++ b/src/main/modules/cache.ts @@ -0,0 +1,89 @@ +import { ipcMain } from 'electron'; +import Store from 'electron-store'; + +interface LyricData { + id: number; + data: any; + timestamp: number; +} + +interface StoreSchema { + lyrics: Record; +} + +class CacheManager { + private store: Store; + + constructor() { + this.store = new Store({ + name: 'lyrics', + defaults: { + lyrics: {} + } + }); + } + + async cacheLyric(id: number, data: any) { + try { + const lyrics = this.store.get('lyrics'); + lyrics[id] = { + id, + data, + timestamp: Date.now() + }; + this.store.set('lyrics', lyrics); + return true; + } catch (error) { + console.error('Error caching lyric:', error); + return false; + } + } + + async getCachedLyric(id: number) { + try { + const lyrics = this.store.get('lyrics'); + const result = lyrics[id]; + + if (!result) return undefined; + + // 检查缓存是否过期(24小时) + if (Date.now() - result.timestamp > 24 * 60 * 60 * 1000) { + delete lyrics[id]; + this.store.set('lyrics', lyrics); + return undefined; + } + + return result.data; + } catch (error) { + console.error('Error getting cached lyric:', error); + return undefined; + } + } + + async clearLyricCache() { + try { + this.store.set('lyrics', {}); + return true; + } catch (error) { + console.error('Error clearing lyric cache:', error); + return false; + } + } +} + +export const cacheManager = new CacheManager(); + +export function initializeCacheManager() { + // 添加歌词缓存相关的 IPC 处理 + ipcMain.handle('cache-lyric', async (_, id: number, lyricData: any) => { + return await cacheManager.cacheLyric(id, lyricData); + }); + + ipcMain.handle('get-cached-lyric', async (_, id: number) => { + return await cacheManager.getCachedLyric(id); + }); + + ipcMain.handle('clear-lyric-cache', async () => { + return await cacheManager.clearLyricCache(); + }); +} diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index c48875f..a52e117 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -13,6 +13,7 @@ declare global { miniTray: () => void; restart: () => void; unblockMusic: (id: number, data: any) => Promise; + invoke: (channel: string, ...args: any[]) => Promise; }; $message: any; } diff --git a/src/preload/index.ts b/src/preload/index.ts index efa9cf6..20809d2 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -11,7 +11,15 @@ const api = { restart: () => ipcRenderer.send('restart'), openLyric: () => ipcRenderer.send('open-lyric'), sendLyric: (data) => ipcRenderer.send('send-lyric', data), - unblockMusic: (id) => ipcRenderer.invoke('unblock-music', id) + unblockMusic: (id) => ipcRenderer.invoke('unblock-music', id), + // 歌词缓存相关 + invoke: (channel: string, ...args: any[]) => { + const validChannels = ['get-cached-lyric', 'cache-lyric', 'clear-lyric-cache']; + if (validChannels.includes(channel)) { + return ipcRenderer.invoke(channel, ...args); + } + return Promise.reject(new Error(`Invalid channel: ${channel}`)); + } }; // Use `contextBridge` APIs to expose Electron APIs to diff --git a/src/renderer/api/music.ts b/src/renderer/api/music.ts index 43e3d50..28bdfe7 100644 --- a/src/renderer/api/music.ts +++ b/src/renderer/api/music.ts @@ -1,5 +1,5 @@ import store from '@/store'; -import { ILyric } from '@/type/lyric'; +import type { ILyric } from '@/type/lyric'; import { isElectron } from '@/utils'; import request from '@/utils/request'; import requestMusic from '@/utils/request_music'; @@ -36,8 +36,25 @@ export const getMusicDetail = (ids: Array) => { }; // 根据音乐Id获取音乐歌词 -export const getMusicLrc = (id: number) => { - return request.get('/lyric', { params: { id } }); +export const getMusicLrc = async (id: number) => { + if (isElectron) { + // 先尝试从缓存获取 + const cachedLyric = await window.api.invoke('get-cached-lyric', id); + console.log('cachedLyric', cachedLyric); + if (cachedLyric) { + return { data: cachedLyric }; + } + } + + // 如果缓存中没有,则从服务器获取 + const res = await request.get('/lyric', { params: { id } }); + + // 缓存完整的响应数据 + if (isElectron && res) { + await window.api.invoke('cache-lyric', id, res.data); + } + + return res; }; export const getParsingMusicUrl = (id: number, data: any) => { diff --git a/src/renderer/hooks/MusicListHook.ts b/src/renderer/hooks/MusicListHook.ts index 104beb5..0b9efe9 100644 --- a/src/renderer/hooks/MusicListHook.ts +++ b/src/renderer/hooks/MusicListHook.ts @@ -13,13 +13,11 @@ const musicHistory = useMusicHistory(); // 获取歌曲url export const getSongUrl = async (id: number, songData: any, isDownloaded: boolean = false) => { const { data } = await getMusicUrl(id); - console.log('data', data); let url = ''; let songDetail = null; try { if (data.data[0].freeTrialInfo || !data.data[0].url) { const res = await getParsingMusicUrl(id, songData); - console.log('res', res); url = res.data.data.url; songDetail = res.data.data; } else { @@ -52,7 +50,6 @@ const getSongDetail = async (playMusic: SongResult) => { export const useMusicListHook = () => { const handlePlayMusic = async (state: any, playMusic: SongResult) => { const updatedPlayMusic = await getSongDetail(playMusic); - console.log('updatedPlayMusic', updatedPlayMusic); state.playMusic = updatedPlayMusic; state.playMusicUrl = updatedPlayMusic.playMusicUrl; state.play = true; diff --git a/src/renderer/views/set/index.vue b/src/renderer/views/set/index.vue index 8dc830f..4240337 100644 --- a/src/renderer/views/set/index.vue +++ b/src/renderer/views/set/index.vue @@ -552,7 +552,8 @@ const clearCacheOptions = ref([ { label: '用户数据', key: 'user', description: '清除登录信息和用户相关数据' }, { label: '应用设置', key: 'settings', description: '清除应用的所有自定义设置' }, { label: '下载记录', key: 'downloads', description: '清除下载历史记录(不会删除已下载的文件)' }, - { label: '音乐资源', key: 'resources', description: '清除已加载的音乐文件、歌词等资源缓存' } + { label: '音乐资源', key: 'resources', description: '清除已加载的音乐文件、歌词等资源缓存' }, + { label: '歌词资源', key: 'lyrics', description: '清除已加载的歌词资源缓存' } ]); const selectedCacheTypes = ref([]); @@ -609,6 +610,9 @@ const clearCache = async () => { } } break; + case 'lyrics': + window.api.invoke('clear-lyrics-cache'); + break; default: break; }