mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-24 16:27:23 +08:00
✨ feat: 歌曲下载内置封面歌词歌曲信息等,添加无限制下载功能,优化下载管理,支持清空下载记录
This commit is contained in:
@@ -94,6 +94,17 @@
|
||||
<n-empty :description="t('download.empty.noDownloaded')" />
|
||||
</div>
|
||||
<div v-else class="downloaded-content">
|
||||
<div class="downloaded-header">
|
||||
<div class="header-title">
|
||||
{{ t('download.count', { count: downloadedList.length }) }}
|
||||
</div>
|
||||
<n-button secondary size="small" @click="showClearConfirm = true">
|
||||
<template #icon>
|
||||
<i class="iconfont ri-delete-bin-line mr-1"></i>
|
||||
</template>
|
||||
{{ t('download.clearAll') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<div class="downloaded-items">
|
||||
<div v-for="item in downList" :key="item.path" class="downloaded-item">
|
||||
<div class="downloaded-item-content">
|
||||
@@ -172,12 +183,38 @@
|
||||
}}</n-button>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<!-- 清空确认对话框 -->
|
||||
<n-modal
|
||||
v-model:show="showClearConfirm"
|
||||
preset="dialog"
|
||||
type="warning"
|
||||
:title="t('download.clear.title')"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center">
|
||||
<i class="iconfont ri-delete-bin-line mr-2 text-xl"></i>
|
||||
<span>{{ t('download.clear.title') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="delete-confirm-content">
|
||||
{{ t('download.clear.message') }}
|
||||
</div>
|
||||
<template #action>
|
||||
<n-button size="small" @click="showClearConfirm = false">{{
|
||||
t('download.clear.cancel')
|
||||
}}</n-button>
|
||||
<n-button size="small" type="warning" @click="clearDownloadRecords">{{
|
||||
t('download.clear.confirm')
|
||||
}}</n-button>
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { ProgressStatus } from 'naive-ui';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { getMusicDetail } from '@/api/music';
|
||||
@@ -320,29 +357,49 @@ const confirmDelete = async () => {
|
||||
'delete-downloaded-music',
|
||||
itemToDelete.value.path
|
||||
);
|
||||
|
||||
// 无论删除文件是否成功,都从记录中移除
|
||||
localStorage.setItem(
|
||||
'downloadedList',
|
||||
JSON.stringify(
|
||||
downloadedList.value.filter((item) => item.id !== (itemToDelete.value as DownloadedItem).id)
|
||||
)
|
||||
);
|
||||
await refreshDownloadedList();
|
||||
|
||||
if (success) {
|
||||
localStorage.setItem(
|
||||
'downloadedList',
|
||||
JSON.stringify(
|
||||
downloadedList.value.filter(
|
||||
(item) => item.id !== (itemToDelete.value as DownloadedItem).id
|
||||
)
|
||||
)
|
||||
);
|
||||
await refreshDownloadedList();
|
||||
message.success(t('download.delete.success'));
|
||||
} else {
|
||||
message.error(t('download.delete.failed'));
|
||||
message.warning(t('download.delete.fileNotFound'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to delete music:', error);
|
||||
message.error(t('download.delete.failed'));
|
||||
// 即使删除文件出错,也从记录中移除
|
||||
localStorage.setItem(
|
||||
'downloadedList',
|
||||
JSON.stringify(
|
||||
downloadedList.value.filter((item) => item.id !== (itemToDelete.value as DownloadedItem).id)
|
||||
)
|
||||
);
|
||||
await refreshDownloadedList();
|
||||
message.warning(t('download.delete.recordRemoved'));
|
||||
} finally {
|
||||
showDeleteConfirm.value = false;
|
||||
itemToDelete.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 清空下载记录相关
|
||||
const showClearConfirm = ref(false);
|
||||
|
||||
// 清空下载记录
|
||||
const clearDownloadRecords = () => {
|
||||
localStorage.setItem('downloadedList', '[]');
|
||||
downloadedList.value = [];
|
||||
message.success(t('download.clear.success'));
|
||||
showClearConfirm.value = false;
|
||||
};
|
||||
|
||||
// 播放音乐
|
||||
// const handlePlay = async (musicInfo: SongResult) => {
|
||||
// await playerStore.setPlay(musicInfo);
|
||||
@@ -421,6 +478,12 @@ onMounted(() => {
|
||||
// 监听下载进度
|
||||
window.electron.ipcRenderer.on('music-download-progress', (_, data) => {
|
||||
const existingItem = downloadList.value.find((item) => item.filename === data.filename);
|
||||
|
||||
// 如果进度为100%,将状态设置为已完成
|
||||
if (data.progress === 100) {
|
||||
data.status = 'completed';
|
||||
}
|
||||
|
||||
if (existingItem) {
|
||||
Object.assign(existingItem, {
|
||||
...data,
|
||||
@@ -523,9 +586,18 @@ const handleDrawerClose = () => {
|
||||
@apply flex-1 overflow-hidden pb-40;
|
||||
}
|
||||
|
||||
.downloaded-header {
|
||||
@apply flex items-center justify-between p-4 bg-light-100 dark:bg-dark-200 sticky top-0 z-10;
|
||||
@apply border-b border-gray-100 dark:border-gray-800;
|
||||
|
||||
.header-title {
|
||||
@apply text-sm font-medium text-gray-600 dark:text-gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
.download-items,
|
||||
.downloaded-items {
|
||||
@apply space-y-3;
|
||||
@apply space-y-3 p-4;
|
||||
}
|
||||
|
||||
.total-progress {
|
||||
|
||||
@@ -95,6 +95,7 @@ import { getSongUrl } from '@/hooks/MusicListHook';
|
||||
import { useArtist } from '@/hooks/useArtist';
|
||||
import { audioService } from '@/services/audioService';
|
||||
import { usePlayerStore } from '@/store';
|
||||
import { useSettingsStore } from '@/store/modules/settings';
|
||||
import type { SongResult } from '@/type/music';
|
||||
import { getImgUrl, isElectron } from '@/utils';
|
||||
import { getImageBackground } from '@/utils/linearColor';
|
||||
@@ -285,7 +286,14 @@ const downloadMusic = async () => {
|
||||
try {
|
||||
isDownloading.value = true;
|
||||
|
||||
const data = (await getSongUrl(props.item.id as number, cloneDeep(props.item), true)) as any;
|
||||
const settingsStore = useSettingsStore();
|
||||
const { unlimitedDownload } = settingsStore.setData;
|
||||
|
||||
const data = (await getSongUrl(
|
||||
props.item.id as number,
|
||||
cloneDeep(props.item),
|
||||
unlimitedDownload
|
||||
)) as any;
|
||||
if (!data || !data.url) {
|
||||
throw new Error(t('songItem.message.getUrlFailed'));
|
||||
}
|
||||
@@ -293,14 +301,17 @@ const downloadMusic = async () => {
|
||||
// 构建文件名
|
||||
const artistNames = (props.item.ar || props.item.song?.artists)?.map((a) => a.name).join(',');
|
||||
const filename = `${props.item.name} - ${artistNames}`;
|
||||
console.log('props.item', props.item);
|
||||
|
||||
const songData = cloneDeep(props.item);
|
||||
songData.ar = songData.ar || songData.song?.artists;
|
||||
// 发送下载请求
|
||||
window.electron.ipcRenderer.send('download-music', {
|
||||
url: data.url,
|
||||
type: data.type,
|
||||
filename,
|
||||
songInfo: {
|
||||
...cloneDeep(props.item),
|
||||
...songData,
|
||||
downloadTime: Date.now()
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user