From c6ca63ee1156ca0eaf5db83f7934a8f4d6d70625 Mon Sep 17 00:00:00 2001 From: alger Date: Sat, 25 Jan 2025 23:53:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E4=B8=8B=E8=BD=BD=E5=92=8C=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: #49 --- src/main/modules/fileManager.ts | 17 ++- src/renderer/api/music.ts | 33 +++-- .../components/common/DownloadDrawer.vue | 138 +++++++++++------- src/renderer/components/common/SongItem.vue | 5 + src/renderer/hooks/MusicListHook.ts | 2 +- src/renderer/layout/components/SearchBar.vue | 13 +- src/renderer/store/index.ts | 13 +- src/renderer/utils/request.ts | 30 ++-- src/renderer/views/favorite/index.vue | 6 +- src/renderer/views/login/index.vue | 2 +- src/renderer/views/set/index.vue | 2 - src/renderer/views/user/index.vue | 1 - 12 files changed, 149 insertions(+), 113 deletions(-) diff --git a/src/main/modules/fileManager.ts b/src/main/modules/fileManager.ts index ae3cb93..be46448 100644 --- a/src/main/modules/fileManager.ts +++ b/src/main/modules/fileManager.ts @@ -60,13 +60,22 @@ export function initializeFileManager() { // 通用的打开目录处理 ipcMain.on('open-directory', (_, filePath) => { try { - if (fs.statSync(filePath).isDirectory()) { - shell.openPath(filePath); + // 验证文件路径 + if (!filePath) { + console.error('无效的文件路径: 路径为空'); + return; + } + + // 统一处理路径分隔符 + const normalizedPath = path.normalize(filePath); + + if (fs.statSync(normalizedPath).isDirectory()) { + shell.openPath(normalizedPath); } else { - shell.showItemInFolder(filePath); + shell.showItemInFolder(normalizedPath); } } catch (error) { - console.error('Error opening path:', error); + console.error('打开路径失败:', error); } }); diff --git a/src/renderer/api/music.ts b/src/renderer/api/music.ts index d7c97ed..236f892 100644 --- a/src/renderer/api/music.ts +++ b/src/renderer/api/music.ts @@ -13,20 +13,25 @@ export const getMusicQualityDetail = (id: number) => { }; // 根据音乐Id获取音乐播放URl -export const getMusicUrl = async (id: number) => { +export const getMusicUrl = async (id: number, isDownloaded: boolean = false) => { // 判断是否登录 - if (store.state.user) { - const res = await request.get('/song/download/url/v1', { - params: { - id, - level: store.state.setData.musicQuality || 'higher', - cookie: `${localStorage.getItem('token')} os=pc;` - } - }); + try { + if (store.state.user && isDownloaded && store.state.user.vipType !== 0) { + const url = '/song/download/url/v1'; + const res = await request.get(url, { + params: { + id, + level: store.state.setData.musicQuality || 'higher', + cookie: `${localStorage.getItem('token')} os=pc;` + } + }); - if (res.data.data.url) { - return { data: { data: [{ ...res.data.data }] } }; + if (res.data.data.url) { + return { data: { data: [{ ...res.data.data }] } }; + } } + } catch (error) { + console.error('error', error); } return await request.get('/song/url/v1', { @@ -84,8 +89,10 @@ export const likeSong = (id: number, like: boolean = true) => { }; // 获取用户喜欢的音乐列表 -export const getLikedList = () => { - return request.get('/likelist'); +export const getLikedList = (uid: number) => { + return request.get('/likelist', { + params: { uid } + }); }; // 创建歌单 diff --git a/src/renderer/components/common/DownloadDrawer.vue b/src/renderer/components/common/DownloadDrawer.vue index 3d91206..56dd0bb 100644 --- a/src/renderer/components/common/DownloadDrawer.vue +++ b/src/renderer/components/common/DownloadDrawer.vue @@ -85,7 +85,7 @@
-
+
{{ formatSize(item.size) }}
- + ([]); -const downloadedList = ref([]); +const downloadedList = ref( + JSON.parse(localStorage.getItem('downloadedList') || '[]') +); + +const downList = computed(() => { + return (downloadedList.value as DownloadedItem[]).reverse(); +}); // 获取播放状态 -const play = computed(() => store.state.play as boolean); -const currentMusic = computed(() => store.state.playMusic); +// const play = computed(() => store.state.play as boolean); +// const currentMusic = computed(() => store.state.playMusic); // 计算下载中的任务数量 const downloadingCount = computed(() => { @@ -264,8 +270,7 @@ const formatSize = (bytes: number) => { // 打开目录 const openDirectory = (path: string) => { - const directory = path.substring(0, path.lastIndexOf('/')); - window.electron.ipcRenderer.send('open-directory', directory); + window.electron.ipcRenderer.send('open-directory', path); }; // 删除相关 @@ -288,6 +293,14 @@ const confirmDelete = async () => { itemToDelete.value.path ); if (success) { + localStorage.setItem( + 'downloadedList', + JSON.stringify( + downloadedList.value.filter( + (item) => item.id !== (itemToDelete.value as DownloadedItem).id + ) + ) + ); await refreshDownloadedList(); message.success('删除成功'); } else { @@ -303,58 +316,59 @@ const confirmDelete = async () => { }; // 播放音乐 -const handlePlayMusic = async (item: DownloadedItem) => { - // 确保路径正确编码 - const encodedPath = encodeURIComponent(item.path); - const localUrl = `local://${encodedPath}`; +// const handlePlayMusic = async (item: DownloadedItem) => { +// // 确保路径正确编码 +// const encodedPath = encodeURIComponent(item.path); +// const localUrl = `local://${encodedPath}`; - const musicInfo = { - name: item.filename, - id: item.id, - url: localUrl, - playMusicUrl: localUrl, - picUrl: item.picUrl, - ar: item.ar || [{ name: '本地音乐' }], - song: { - artists: item.ar || [{ name: '本地音乐' }] - }, - al: { - picUrl: item.picUrl || '/images/default_cover.png' - } - }; +// const musicInfo = { +// name: item.filename, +// id: item.id, +// url: localUrl, +// playMusicUrl: localUrl, +// picUrl: item.picUrl, +// ar: item.ar || [{ name: '本地音乐' }], +// song: { +// artists: item.ar || [{ name: '本地音乐' }] +// }, +// al: { +// picUrl: item.picUrl || '/images/default_cover.png' +// } +// }; - // 如果是当前播放的音乐,则切换播放状态 - if (currentMusic.value?.id === item.id) { - if (play.value) { - audioService.getCurrentSound()?.pause(); - store.commit('setPlayMusic', false); - } else { - audioService.getCurrentSound()?.play(); - store.commit('setPlayMusic', true); - } - return; - } +// // 如果是当前播放的音乐,则切换播放状态 +// if (currentMusic.value?.id === item.id) { +// if (play.value) { +// audioService.getCurrentSound()?.pause(); +// store.commit('setPlayMusic', false); +// } else { +// audioService.getCurrentSound()?.play(); +// store.commit('setPlayMusic', true); +// } +// return; +// } - // 播放新的音乐 - store.commit('setPlay', musicInfo); - store.commit('setPlayMusic', true); - store.commit('setIsPlay', true); +// // 播放新的音乐 +// store.commit('setPlay', musicInfo); +// store.commit('setPlayMusic', true); +// store.commit('setIsPlay', true); - store.commit( - 'setPlayList', - downloadedList.value.map((item) => ({ - ...item, - playMusicUrl: `local://${encodeURIComponent(item.path)}` - })) - ); -}; +// store.commit( +// 'setPlayList', +// downloadedList.value.map((item) => ({ +// ...item, +// playMusicUrl: `local://${encodeURIComponent(item.path)}` +// })) +// ); +// }; // 获取已下载音乐列表 const refreshDownloadedList = async () => { try { + let saveList: any = []; const list = await window.electron.ipcRenderer.invoke('get-downloaded-music'); if (!Array.isArray(list) || list.length === 0) { - downloadedList.value = []; + saveList = []; return; } @@ -369,7 +383,7 @@ const refreshDownloadedList = async () => { return acc; }, {}); - downloadedList.value = list.map((item) => { + saveList = list.map((item) => { const songDetail = songDetails[item.id]; return { ...item, @@ -379,17 +393,29 @@ const refreshDownloadedList = async () => { }); } catch (detailError) { console.error('Failed to get music details:', detailError); - downloadedList.value = list; + saveList = list; } } else { - downloadedList.value = list; + saveList = list; } + setLocalDownloadedList(saveList); } catch (error) { console.error('Failed to get downloaded music list:', error); downloadedList.value = []; } }; +const setLocalDownloadedList = (list: DownloadedItem[]) => { + const localList = localStorage.getItem('downloadedList'); + // 合并 去重 + const saveList = [...(localList ? JSON.parse(localList) : []), ...list]; + const uniqueList = saveList.filter( + (item, index, self) => index === self.findIndex((t) => t.id === item.id) + ); + localStorage.setItem('downloadedList', JSON.stringify(uniqueList)); + downloadedList.value = uniqueList; +}; + // 监听抽屉显示状态 watch( () => showDrawer.value, diff --git a/src/renderer/components/common/SongItem.vue b/src/renderer/components/common/SongItem.vue index 5cbc3c7..ffa3517 100644 --- a/src/renderer/components/common/SongItem.vue +++ b/src/renderer/components/common/SongItem.vue @@ -207,6 +207,11 @@ const dropdownOptions = computed(() => { type: 'divider', key: 'd1' }, + { + label: '下载歌曲', + key: 'download', + icon: () => h('i', { class: 'iconfont ri-download-line' }) + }, { label: '添加到歌单', key: 'addToPlaylist', diff --git a/src/renderer/hooks/MusicListHook.ts b/src/renderer/hooks/MusicListHook.ts index 1539a9a..e5ae3d6 100644 --- a/src/renderer/hooks/MusicListHook.ts +++ b/src/renderer/hooks/MusicListHook.ts @@ -13,7 +13,7 @@ const musicHistory = useMusicHistory(); // 获取歌曲url export const getSongUrl = async (id: number, songData: any, isDownloaded: boolean = false) => { - const { data } = await getMusicUrl(id); + const { data } = await getMusicUrl(id, isDownloaded); let url = ''; let songDetail = null; try { diff --git a/src/renderer/layout/components/SearchBar.vue b/src/renderer/layout/components/SearchBar.vue index 68d3955..8785a47 100644 --- a/src/renderer/layout/components/SearchBar.vue +++ b/src/renderer/layout/components/SearchBar.vue @@ -105,7 +105,7 @@ import { useRouter } from 'vue-router'; import { useStore } from 'vuex'; import { getSearchKeyword } from '@/api/home'; -import { getUserDetail, logout } from '@/api/login'; +import { getUserDetail } from '@/api/login'; import alipay from '@/assets/alipay.png'; import wechat from '@/assets/wechat.png'; import Coffee from '@/components/Coffee.vue'; @@ -132,8 +132,10 @@ const loadPage = async () => { const token = localStorage.getItem('token'); if (!token) return; const { data } = await getUserDetail(); - store.state.user = data.profile; - localStorage.setItem('user', JSON.stringify(data.profile)); + console.log('data', data); + store.state.user = + data.profile || store.state.user || JSON.parse(localStorage.getItem('user') || '{}'); + localStorage.setItem('user', JSON.stringify(store.state.user)); }; loadPage(); @@ -202,10 +204,7 @@ const selectItem = async (key: string) => { // switch 判断 switch (key) { case 'logout': - logout().then(() => { - store.commit('logout'); - router.push('/login'); - }); + store.commit('logout'); break; case 'login': router.push('/login'); diff --git a/src/renderer/store/index.ts b/src/renderer/store/index.ts index ad33b0d..18847f0 100644 --- a/src/renderer/store/index.ts +++ b/src/renderer/store/index.ts @@ -1,6 +1,7 @@ import { createStore } from 'vuex'; import setData from '@/../main/set.json'; +import { logout } from '@/api/login'; import { getLikedList, likeSong } from '@/api/music'; import { useMusicListHook } from '@/hooks/MusicListHook'; import homeRouter from '@/router/home'; @@ -231,9 +232,11 @@ const mutations = { state.showUpdateModal = value; }, logout(state: State) { - state.user = null; - localStorage.removeItem('user'); - localStorage.removeItem('token'); + logout().then(() => { + state.user = null; + localStorage.removeItem('user'); + localStorage.removeItem('token'); + }); }, setShowArtistDrawer(state, show: boolean) { state.showArtistDrawer = show; @@ -284,9 +287,9 @@ const actions = { const localList: number[] = localFavoriteList ? JSON.parse(localFavoriteList) : []; // 如果用户已登录,尝试获取服务器收藏列表并合并 - if (state.user && localStorage.getItem('token')) { + if (state.user && state.user.userId) { try { - const res = await getLikedList(); + const res = await getLikedList(state.user.userId); if (res.data?.ids) { // 合并本地和服务器的收藏列表,去重 const serverList = res.data.ids.reverse(); diff --git a/src/renderer/utils/request.ts b/src/renderer/utils/request.ts index f4b0036..a8d3a02 100644 --- a/src/renderer/utils/request.ts +++ b/src/renderer/utils/request.ts @@ -50,7 +50,7 @@ request.interceptors.request.use( }; const token = localStorage.getItem('token'); if (token) { - config.params.cookie = config.params.cookie || token; + config.params.cookie = config.params.cookie !== undefined ? config.params.cookie : token; } if (isElectron) { const proxyConfig = setData?.proxyConfig; @@ -70,6 +70,8 @@ request.interceptors.request.use( } ); +const NO_RETRY_URLS = ['暂时没有']; + // 响应拦截器 request.interceptors.response.use( (response) => { @@ -88,28 +90,16 @@ request.interceptors.response.use( if (error.response?.status === 301) { // 使用 store mutation 清除用户信息 store.commit('logout'); - - // 如果还可以重试,则重新发起请求 - if (config.retryCount === undefined || config.retryCount < MAX_RETRIES) { - config.retryCount = (config.retryCount || 1) + 1; - console.log(`301 状态码,清除登录信息后重试第 ${config.retryCount} 次`); - notification.error({ - content: '登录状态失效,请重新登录', - meta: '请重新登录', - duration: 2500, - keepAliveOnHover: true - }); - - // 延迟重试 - await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); - - // 重新发起请求 - return request(config); - } + console.log(`301 状态码,清除登录信息后重试第 ${config.retryCount} 次`); + config.retryCount = 3; } // 检查是否还可以重试 - if (config.retryCount !== undefined && config.retryCount < MAX_RETRIES) { + if ( + config.retryCount !== undefined && + config.retryCount < MAX_RETRIES && + !NO_RETRY_URLS.includes(config.url as string) + ) { config.retryCount++; console.log(`请求重试第 ${config.retryCount} 次`); diff --git a/src/renderer/views/favorite/index.vue b/src/renderer/views/favorite/index.vue index ed0fea8..733e098 100644 --- a/src/renderer/views/favorite/index.vue +++ b/src/renderer/views/favorite/index.vue @@ -272,9 +272,9 @@ const handleScroll = (e: any) => { } }; -onMounted(() => { - store.dispatch('initializeFavoriteList'); - getFavoriteSongs(); +onMounted(async () => { + await store.dispatch('initializeFavoriteList'); + await getFavoriteSongs(); }); // 监听收藏列表变化 diff --git a/src/renderer/views/login/index.vue b/src/renderer/views/login/index.vue index f1bc6bb..4b05194 100644 --- a/src/renderer/views/login/index.vue +++ b/src/renderer/views/login/index.vue @@ -58,7 +58,7 @@ const timerIsQr = (key: string) => { localStorage.setItem('token', data.cookie); const user = await getUserDetail(); store.state.user = user.data.profile; - localStorage.setItem('user', JSON.stringify(store.state.user)); + localStorage.setItem('user', JSON.stringify(user.data.profile)); message.success('登录成功'); clearInterval(timer); diff --git a/src/renderer/views/set/index.vue b/src/renderer/views/set/index.vue index 77994f9..b382a3f 100644 --- a/src/renderer/views/set/index.vue +++ b/src/renderer/views/set/index.vue @@ -728,8 +728,6 @@ const clearCache = async () => { localStorage.removeItem('favoriteList'); break; case 'user': - localStorage.removeItem('user'); - localStorage.removeItem('token'); store.commit('logout'); break; case 'settings': diff --git a/src/renderer/views/user/index.vue b/src/renderer/views/user/index.vue index c9e6523..ed0c762 100644 --- a/src/renderer/views/user/index.vue +++ b/src/renderer/views/user/index.vue @@ -132,7 +132,6 @@ onBeforeUnmount(() => { const checkLoginStatus = () => { const token = localStorage.getItem('token'); const userData = localStorage.getItem('user'); - console.log('触发了', token, userData); if (!token || !userData) { router.push('/login');