🐞 fix: 修复一些下载和登录问题

fix: #49
This commit is contained in:
alger
2025-01-25 23:53:20 +08:00
parent 4fa1295b84
commit c6ca63ee11
12 changed files with 149 additions and 113 deletions
+13 -4
View File
@@ -60,13 +60,22 @@ export function initializeFileManager() {
// 通用的打开目录处理 // 通用的打开目录处理
ipcMain.on('open-directory', (_, filePath) => { ipcMain.on('open-directory', (_, filePath) => {
try { 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 { } else {
shell.showItemInFolder(filePath); shell.showItemInFolder(normalizedPath);
} }
} catch (error) { } catch (error) {
console.error('Error opening path:', error); console.error('打开路径失败:', error);
} }
}); });
+20 -13
View File
@@ -13,20 +13,25 @@ export const getMusicQualityDetail = (id: number) => {
}; };
// 根据音乐Id获取音乐播放URl // 根据音乐Id获取音乐播放URl
export const getMusicUrl = async (id: number) => { export const getMusicUrl = async (id: number, isDownloaded: boolean = false) => {
// 判断是否登录 // 判断是否登录
if (store.state.user) { try {
const res = await request.get('/song/download/url/v1', { if (store.state.user && isDownloaded && store.state.user.vipType !== 0) {
params: { const url = '/song/download/url/v1';
id, const res = await request.get(url, {
level: store.state.setData.musicQuality || 'higher', params: {
cookie: `${localStorage.getItem('token')} os=pc;` id,
} level: store.state.setData.musicQuality || 'higher',
}); cookie: `${localStorage.getItem('token')} os=pc;`
}
});
if (res.data.data.url) { if (res.data.data.url) {
return { data: { data: [{ ...res.data.data }] } }; return { data: { data: [{ ...res.data.data }] } };
}
} }
} catch (error) {
console.error('error', error);
} }
return await request.get('/song/url/v1', { return await request.get('/song/url/v1', {
@@ -84,8 +89,10 @@ export const likeSong = (id: number, like: boolean = true) => {
}; };
// 获取用户喜欢的音乐列表 // 获取用户喜欢的音乐列表
export const getLikedList = () => { export const getLikedList = (uid: number) => {
return request.get('/likelist'); return request.get('/likelist', {
params: { uid }
});
}; };
// 创建歌单 // 创建歌单
@@ -85,7 +85,7 @@
</div> </div>
<div v-else class="downloaded-content"> <div v-else class="downloaded-content">
<div class="downloaded-items"> <div class="downloaded-items">
<div v-for="item in downloadedList" :key="item.path" class="downloaded-item"> <div v-for="item in downList" :key="item.path" class="downloaded-item">
<div class="downloaded-item-content"> <div class="downloaded-item-content">
<div class="downloaded-item-cover"> <div class="downloaded-item-cover">
<n-image <n-image
@@ -105,11 +105,11 @@
<div class="downloaded-item-size">{{ formatSize(item.size) }}</div> <div class="downloaded-item-size">{{ formatSize(item.size) }}</div>
</div> </div>
<div class="downloaded-item-actions"> <div class="downloaded-item-actions">
<n-button text type="primary" size="large" @click="handlePlayMusic(item)"> <!-- <n-button text type="primary" size="large" @click="handlePlayMusic(item)">
<template #icon> <template #icon>
<i class="iconfont ri-play-circle-line text-xl"></i> <i class="iconfont ri-play-circle-line text-xl"></i>
</template> </template>
</n-button> </n-button> -->
<n-button <n-button
text text
type="primary" type="primary"
@@ -159,10 +159,10 @@
import type { ProgressStatus } from 'naive-ui'; import type { ProgressStatus } from 'naive-ui';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useStore } from 'vuex';
// import { useStore } from 'vuex';
import { getMusicDetail } from '@/api/music'; import { getMusicDetail } from '@/api/music';
import { audioService } from '@/services/audioService'; // import { audioService } from '@/services/audioService';
import { getImgUrl } from '@/utils'; import { getImgUrl } from '@/utils';
interface DownloadItem { interface DownloadItem {
@@ -185,15 +185,21 @@ interface DownloadedItem {
ar: { name: string }[]; ar: { name: string }[];
} }
const store = useStore(); // const store = useStore();
const message = useMessage(); const message = useMessage();
const showDrawer = ref(false); const showDrawer = ref(false);
const downloadList = ref<DownloadItem[]>([]); const downloadList = ref<DownloadItem[]>([]);
const downloadedList = ref<DownloadedItem[]>([]); const downloadedList = ref<DownloadedItem[]>(
JSON.parse(localStorage.getItem('downloadedList') || '[]')
);
const downList = computed(() => {
return (downloadedList.value as DownloadedItem[]).reverse();
});
// 获取播放状态 // 获取播放状态
const play = computed(() => store.state.play as boolean); // const play = computed(() => store.state.play as boolean);
const currentMusic = computed(() => store.state.playMusic); // const currentMusic = computed(() => store.state.playMusic);
// 计算下载中的任务数量 // 计算下载中的任务数量
const downloadingCount = computed(() => { const downloadingCount = computed(() => {
@@ -264,8 +270,7 @@ const formatSize = (bytes: number) => {
// 打开目录 // 打开目录
const openDirectory = (path: string) => { const openDirectory = (path: string) => {
const directory = path.substring(0, path.lastIndexOf('/')); window.electron.ipcRenderer.send('open-directory', path);
window.electron.ipcRenderer.send('open-directory', directory);
}; };
// 删除相关 // 删除相关
@@ -288,6 +293,14 @@ const confirmDelete = async () => {
itemToDelete.value.path itemToDelete.value.path
); );
if (success) { if (success) {
localStorage.setItem(
'downloadedList',
JSON.stringify(
downloadedList.value.filter(
(item) => item.id !== (itemToDelete.value as DownloadedItem).id
)
)
);
await refreshDownloadedList(); await refreshDownloadedList();
message.success('删除成功'); message.success('删除成功');
} else { } else {
@@ -303,58 +316,59 @@ const confirmDelete = async () => {
}; };
// 播放音乐 // 播放音乐
const handlePlayMusic = async (item: DownloadedItem) => { // const handlePlayMusic = async (item: DownloadedItem) => {
// 确保路径正确编码 // // 确保路径正确编码
const encodedPath = encodeURIComponent(item.path); // const encodedPath = encodeURIComponent(item.path);
const localUrl = `local://${encodedPath}`; // const localUrl = `local://${encodedPath}`;
const musicInfo = { // const musicInfo = {
name: item.filename, // name: item.filename,
id: item.id, // id: item.id,
url: localUrl, // url: localUrl,
playMusicUrl: localUrl, // playMusicUrl: localUrl,
picUrl: item.picUrl, // picUrl: item.picUrl,
ar: item.ar || [{ name: '本地音乐' }], // ar: item.ar || [{ name: '本地音乐' }],
song: { // song: {
artists: item.ar || [{ name: '本地音乐' }] // artists: item.ar || [{ name: '本地音乐' }]
}, // },
al: { // al: {
picUrl: item.picUrl || '/images/default_cover.png' // picUrl: item.picUrl || '/images/default_cover.png'
} // }
}; // };
// 如果是当前播放的音乐,则切换播放状态 // // 如果是当前播放的音乐,则切换播放状态
if (currentMusic.value?.id === item.id) { // if (currentMusic.value?.id === item.id) {
if (play.value) { // if (play.value) {
audioService.getCurrentSound()?.pause(); // audioService.getCurrentSound()?.pause();
store.commit('setPlayMusic', false); // store.commit('setPlayMusic', false);
} else { // } else {
audioService.getCurrentSound()?.play(); // audioService.getCurrentSound()?.play();
store.commit('setPlayMusic', true); // store.commit('setPlayMusic', true);
} // }
return; // return;
} // }
// 播放新的音乐 // // 播放新的音乐
store.commit('setPlay', musicInfo); // store.commit('setPlay', musicInfo);
store.commit('setPlayMusic', true); // store.commit('setPlayMusic', true);
store.commit('setIsPlay', true); // store.commit('setIsPlay', true);
store.commit( // store.commit(
'setPlayList', // 'setPlayList',
downloadedList.value.map((item) => ({ // downloadedList.value.map((item) => ({
...item, // ...item,
playMusicUrl: `local://${encodeURIComponent(item.path)}` // playMusicUrl: `local://${encodeURIComponent(item.path)}`
})) // }))
); // );
}; // };
// 获取已下载音乐列表 // 获取已下载音乐列表
const refreshDownloadedList = async () => { const refreshDownloadedList = async () => {
try { try {
let saveList: any = [];
const list = await window.electron.ipcRenderer.invoke('get-downloaded-music'); const list = await window.electron.ipcRenderer.invoke('get-downloaded-music');
if (!Array.isArray(list) || list.length === 0) { if (!Array.isArray(list) || list.length === 0) {
downloadedList.value = []; saveList = [];
return; return;
} }
@@ -369,7 +383,7 @@ const refreshDownloadedList = async () => {
return acc; return acc;
}, {}); }, {});
downloadedList.value = list.map((item) => { saveList = list.map((item) => {
const songDetail = songDetails[item.id]; const songDetail = songDetails[item.id];
return { return {
...item, ...item,
@@ -379,17 +393,29 @@ const refreshDownloadedList = async () => {
}); });
} catch (detailError) { } catch (detailError) {
console.error('Failed to get music details:', detailError); console.error('Failed to get music details:', detailError);
downloadedList.value = list; saveList = list;
} }
} else { } else {
downloadedList.value = list; saveList = list;
} }
setLocalDownloadedList(saveList);
} catch (error) { } catch (error) {
console.error('Failed to get downloaded music list:', error); console.error('Failed to get downloaded music list:', error);
downloadedList.value = []; 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( watch(
() => showDrawer.value, () => showDrawer.value,
@@ -207,6 +207,11 @@ const dropdownOptions = computed<MenuOption[]>(() => {
type: 'divider', type: 'divider',
key: 'd1' key: 'd1'
}, },
{
label: '下载歌曲',
key: 'download',
icon: () => h('i', { class: 'iconfont ri-download-line' })
},
{ {
label: '添加到歌单', label: '添加到歌单',
key: 'addToPlaylist', key: 'addToPlaylist',
+1 -1
View File
@@ -13,7 +13,7 @@ const musicHistory = useMusicHistory();
// 获取歌曲url // 获取歌曲url
export const getSongUrl = async (id: number, songData: any, isDownloaded: boolean = false) => { 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 url = '';
let songDetail = null; let songDetail = null;
try { try {
+6 -7
View File
@@ -105,7 +105,7 @@ import { useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { getSearchKeyword } from '@/api/home'; import { getSearchKeyword } from '@/api/home';
import { getUserDetail, logout } from '@/api/login'; import { getUserDetail } from '@/api/login';
import alipay from '@/assets/alipay.png'; import alipay from '@/assets/alipay.png';
import wechat from '@/assets/wechat.png'; import wechat from '@/assets/wechat.png';
import Coffee from '@/components/Coffee.vue'; import Coffee from '@/components/Coffee.vue';
@@ -132,8 +132,10 @@ const loadPage = async () => {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (!token) return; if (!token) return;
const { data } = await getUserDetail(); const { data } = await getUserDetail();
store.state.user = data.profile; console.log('data', data);
localStorage.setItem('user', JSON.stringify(data.profile)); store.state.user =
data.profile || store.state.user || JSON.parse(localStorage.getItem('user') || '{}');
localStorage.setItem('user', JSON.stringify(store.state.user));
}; };
loadPage(); loadPage();
@@ -202,10 +204,7 @@ const selectItem = async (key: string) => {
// switch 判断 // switch 判断
switch (key) { switch (key) {
case 'logout': case 'logout':
logout().then(() => { store.commit('logout');
store.commit('logout');
router.push('/login');
});
break; break;
case 'login': case 'login':
router.push('/login'); router.push('/login');
+8 -5
View File
@@ -1,6 +1,7 @@
import { createStore } from 'vuex'; import { createStore } from 'vuex';
import setData from '@/../main/set.json'; import setData from '@/../main/set.json';
import { logout } from '@/api/login';
import { getLikedList, likeSong } from '@/api/music'; import { getLikedList, likeSong } from '@/api/music';
import { useMusicListHook } from '@/hooks/MusicListHook'; import { useMusicListHook } from '@/hooks/MusicListHook';
import homeRouter from '@/router/home'; import homeRouter from '@/router/home';
@@ -231,9 +232,11 @@ const mutations = {
state.showUpdateModal = value; state.showUpdateModal = value;
}, },
logout(state: State) { logout(state: State) {
state.user = null; logout().then(() => {
localStorage.removeItem('user'); state.user = null;
localStorage.removeItem('token'); localStorage.removeItem('user');
localStorage.removeItem('token');
});
}, },
setShowArtistDrawer(state, show: boolean) { setShowArtistDrawer(state, show: boolean) {
state.showArtistDrawer = show; state.showArtistDrawer = show;
@@ -284,9 +287,9 @@ const actions = {
const localList: number[] = localFavoriteList ? JSON.parse(localFavoriteList) : []; const localList: number[] = localFavoriteList ? JSON.parse(localFavoriteList) : [];
// 如果用户已登录,尝试获取服务器收藏列表并合并 // 如果用户已登录,尝试获取服务器收藏列表并合并
if (state.user && localStorage.getItem('token')) { if (state.user && state.user.userId) {
try { try {
const res = await getLikedList(); const res = await getLikedList(state.user.userId);
if (res.data?.ids) { if (res.data?.ids) {
// 合并本地和服务器的收藏列表,去重 // 合并本地和服务器的收藏列表,去重
const serverList = res.data.ids.reverse(); const serverList = res.data.ids.reverse();
+10 -20
View File
@@ -50,7 +50,7 @@ request.interceptors.request.use(
}; };
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (token) { if (token) {
config.params.cookie = config.params.cookie || token; config.params.cookie = config.params.cookie !== undefined ? config.params.cookie : token;
} }
if (isElectron) { if (isElectron) {
const proxyConfig = setData?.proxyConfig; const proxyConfig = setData?.proxyConfig;
@@ -70,6 +70,8 @@ request.interceptors.request.use(
} }
); );
const NO_RETRY_URLS = ['暂时没有'];
// 响应拦截器 // 响应拦截器
request.interceptors.response.use( request.interceptors.response.use(
(response) => { (response) => {
@@ -88,28 +90,16 @@ request.interceptors.response.use(
if (error.response?.status === 301) { if (error.response?.status === 301) {
// 使用 store mutation 清除用户信息 // 使用 store mutation 清除用户信息
store.commit('logout'); store.commit('logout');
console.log(`301 状态码,清除登录信息后重试第 ${config.retryCount}`);
// 如果还可以重试,则重新发起请求 config.retryCount = 3;
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);
}
} }
// 检查是否还可以重试 // 检查是否还可以重试
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++; config.retryCount++;
console.log(`请求重试第 ${config.retryCount}`); console.log(`请求重试第 ${config.retryCount}`);
+3 -3
View File
@@ -272,9 +272,9 @@ const handleScroll = (e: any) => {
} }
}; };
onMounted(() => { onMounted(async () => {
store.dispatch('initializeFavoriteList'); await store.dispatch('initializeFavoriteList');
getFavoriteSongs(); await getFavoriteSongs();
}); });
// 监听收藏列表变化 // 监听收藏列表变化
+1 -1
View File
@@ -58,7 +58,7 @@ const timerIsQr = (key: string) => {
localStorage.setItem('token', data.cookie); localStorage.setItem('token', data.cookie);
const user = await getUserDetail(); const user = await getUserDetail();
store.state.user = user.data.profile; store.state.user = user.data.profile;
localStorage.setItem('user', JSON.stringify(store.state.user)); localStorage.setItem('user', JSON.stringify(user.data.profile));
message.success('登录成功'); message.success('登录成功');
clearInterval(timer); clearInterval(timer);
-2
View File
@@ -728,8 +728,6 @@ const clearCache = async () => {
localStorage.removeItem('favoriteList'); localStorage.removeItem('favoriteList');
break; break;
case 'user': case 'user':
localStorage.removeItem('user');
localStorage.removeItem('token');
store.commit('logout'); store.commit('logout');
break; break;
case 'settings': case 'settings':
-1
View File
@@ -132,7 +132,6 @@ onBeforeUnmount(() => {
const checkLoginStatus = () => { const checkLoginStatus = () => {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
const userData = localStorage.getItem('user'); const userData = localStorage.getItem('user');
console.log('触发了', token, userData);
if (!token || !userData) { if (!token || !userData) {
router.push('/login'); router.push('/login');