Merge branch 'dev_electron' into dev_i18n

This commit is contained in:
alger
2025-02-13 10:39:25 +08:00
22 changed files with 358 additions and 172 deletions
@@ -106,38 +106,24 @@
</template>
<script setup lang="ts">
import axios from 'axios';
import { computed, onActivated, onMounted, ref } from 'vue';
import type { Donor } from '@/api/donation';
import { getDonationList } from '@/api/donation';
import alipay from '@/assets/alipay.png';
import wechat from '@/assets/wechat.png';
// 默认头像
const defaultAvatar = 'https://avatars.githubusercontent.com/u/0?v=4';
// 捐赠者数据
interface Donor {
id: number;
name: string;
amount: number;
date: string;
message?: string;
avatar?: string;
badge: string;
badgeColor: string;
}
const donors = ref<Donor[]>([]);
const isLoading = ref(false);
const fetchDonors = async () => {
isLoading.value = true;
try {
const response = await axios.get(
'https://www.ghproxy.cn/https://raw.githubusercontent.com/algerkong/data/main/donors.json'
);
donors.value = response.data.map((donor: Donor, index: number) => ({
const data = await getDonationList();
donors.value = data.map((donor, index) => ({
...donor,
avatar: `https://api.dicebear.com/7.x/micah/svg?seed=${index}`
}));
@@ -1,7 +1,7 @@
<template>
<div class="download-drawer-trigger">
<n-badge :value="downloadingCount" :max="99" :show="downloadingCount > 0">
<n-button circle @click="showDrawer = true">
<n-button circle @click="store.commit('setShowDownloadDrawer', true)">
<template #icon>
<i class="iconfont ri-download-cloud-2-line"></i>
</template>
@@ -9,7 +9,12 @@
</n-badge>
</div>
<n-drawer v-model:show="showDrawer" :height="'80%'" placement="bottom">
<n-drawer
v-model:show="showDrawer"
:height="'80%'"
placement="bottom"
@after-leave="handleDrawerClose"
>
<n-drawer-content title="下载管理" closable :native-scrollbar="false">
<div class="drawer-container">
<n-tabs type="line" animated class="h-full">
@@ -85,7 +90,7 @@
</div>
<div v-else class="downloaded-content">
<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-cover">
<n-image
@@ -105,11 +110,11 @@
<div class="downloaded-item-size">{{ formatSize(item.size) }}</div>
</div>
<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>
<i class="iconfont ri-play-circle-line text-xl"></i>
</template>
</n-button>
</n-button> -->
<n-button
text
type="primary"
@@ -162,7 +167,7 @@ import { computed, onMounted, ref } from 'vue';
import { useStore } from 'vuex';
import { getMusicDetail } from '@/api/music';
import { audioService } from '@/services/audioService';
// import { audioService } from '@/services/audioService';
import { getImgUrl } from '@/utils';
interface DownloadItem {
@@ -185,15 +190,26 @@ interface DownloadedItem {
ar: { name: string }[];
}
const store = useStore();
const message = useMessage();
const showDrawer = ref(false);
const store = useStore();
const showDrawer = computed({
get: () => store.state.showDownloadDrawer,
set: (val) => store.commit('setShowDownloadDrawer', val)
});
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 currentMusic = computed(() => store.state.playMusic);
// const play = computed(() => store.state.play as boolean);
// const currentMusic = computed(() => store.state.playMusic);
// 计算下载中的任务数量
const downloadingCount = computed(() => {
@@ -264,8 +280,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 +303,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 +326,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 +393,7 @@ const refreshDownloadedList = async () => {
return acc;
}, {});
downloadedList.value = list.map((item) => {
saveList = list.map((item) => {
const songDetail = songDetails[item.id];
return {
...item,
@@ -379,17 +403,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,
@@ -465,6 +501,10 @@ onMounted(() => {
}
});
});
const handleDrawerClose = () => {
store.commit('setShowDownloadDrawer', false);
};
</script>
<style lang="scss" scoped>
@@ -207,6 +207,11 @@ const dropdownOptions = computed<MenuOption[]>(() => {
type: 'divider',
key: 'd1'
},
{
label: '下载歌曲',
key: 'download',
icon: () => h('i', { class: 'iconfont ri-download-line' })
},
{
label: '添加到歌单',
key: 'addToPlaylist',
@@ -72,7 +72,7 @@ import { marked } from 'marked';
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { useStore } from 'vuex';
import { checkUpdate, UpdateResult } from '@/utils/update';
import { checkUpdate, getProxyNodes, UpdateResult } from '@/utils/update';
import config from '../../../../package.json';
@@ -226,7 +226,13 @@ const handleUpdate = async () => {
try {
downloading.value = true;
downloadStatus.value = '准备下载...';
window.electron.ipcRenderer.send('start-download', downloadUrl);
// 获取代理节点列表
const proxyHosts = await getProxyNodes();
const proxyDownloadUrl = `${proxyHosts[0]}/${downloadUrl}`;
// 发送所有可能的下载地址到主进程
window.electron.ipcRenderer.send('start-download', proxyDownloadUrl);
} catch (error) {
downloading.value = false;
window.$message.error('启动下载失败,请重试或手动下载');