diff --git a/src/renderer/components/common/UpdateModal.vue b/src/renderer/components/common/UpdateModal.vue index 8163d4b..3730834 100644 --- a/src/renderer/components/common/UpdateModal.vue +++ b/src/renderer/components/common/UpdateModal.vue @@ -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('启动下载失败,请重试或手动下载'); diff --git a/src/renderer/utils/update.ts b/src/renderer/utils/update.ts index ab41b66..71cb8dd 100644 --- a/src/renderer/utils/update.ts +++ b/src/renderer/utils/update.ts @@ -15,6 +15,23 @@ interface GithubReleaseInfo { }>; } +interface ProxyNode { + url: string; + server: string; + ip: string; + location: string; + latency: number; + speed: number; +} + +interface ProxyResponse { + code: number; + msg: string; + data: ProxyNode[]; + total: number; + update_time: string; +} + export interface UpdateResult { hasUpdate: boolean; latestVersion: string; @@ -30,6 +47,81 @@ export interface UpdateResult { } | null; } +// 缓存相关配置 +const CACHE_KEY = 'github_proxy_nodes'; +const CACHE_EXPIRE_TIME = 1000 * 60 * 10; // 10分钟过期 + +// 请求配置 +const REQUEST_TIMEOUT = 2000; // 2秒超时 + +/** + * 从缓存获取代理节点 + */ +const getCachedProxyNodes = (): { nodes: string[]; timestamp: number } | null => { + const cached = localStorage.getItem(CACHE_KEY); + if (cached) { + const { nodes, timestamp } = JSON.parse(cached); + if (Date.now() - timestamp < CACHE_EXPIRE_TIME) { + return { nodes, timestamp }; + } + } + return null; +}; + +/** + * 缓存代理节点 + */ +const cacheProxyNodes = (nodes: string[]) => { + localStorage.setItem( + CACHE_KEY, + JSON.stringify({ + nodes, + timestamp: Date.now() + }) + ); +}; + +/** + * 获取代理节点列表 + */ +export const getProxyNodes = async (): Promise => { + // 尝试从缓存获取 + const cached = getCachedProxyNodes(); + if (cached) { + return cached.nodes; + } + + try { + // 获取最新代理节点 + const { data } = await axios.get('https://api.akams.cn/github', { + timeout: REQUEST_TIMEOUT + }); + if (data.code === 200) { + // 按速度排序并获取前10个节点 + const nodes = data.data + .sort((a, b) => b.speed - a.speed) + .slice(0, 10) + .map((node) => node.url); + + // 缓存节点 + cacheProxyNodes(nodes); + return nodes; + } + } catch (error) { + console.error('获取代理节点失败:', error); + } + + // 使用备用节点 + return [ + 'https://gh.lk.cc', + 'https://ghproxy.cn', + 'https://ghproxy.net', + 'https://gitproxy.click', + 'https://github.tbedu.top', + 'https://github.moeyy.xyz' + ]; +}; + /** * 获取 GitHub 最新发布版本信息 */ @@ -38,22 +130,15 @@ export const getLatestReleaseInfo = async (): Promise const token = import.meta.env.VITE_GITHUB_TOKEN; const headers = {}; - // GitHub API 代理地址列表 - const proxyHosts = [ - 'https://gh.lk.cc', - 'https://ghproxy.cn', - 'https://ghproxy.net', - 'https://gitproxy.click', - 'https://github.tbedu.top', - 'https://github.moeyy.xyz' - ]; + // 获取代理节点列表 + const proxyHosts = await getProxyNodes(); // 构建 API URL 列表 const apiUrls = [ // 原始地址 'https://api.github.com/repos/algerkong/AlgerMusicPlayer/releases/latest', - // 使用各种代理 + // 使用代理节点 ...proxyHosts.map( (host) => `${host}/https://raw.githubusercontent.com/algerkong/AlgerMusicPlayer/dev_electron/package.json` @@ -66,12 +151,17 @@ export const getLatestReleaseInfo = async (): Promise for (const url of apiUrls) { try { - const response = await axios.get(url, { headers }); + const response = await axios.get(url, { + headers, + timeout: REQUEST_TIMEOUT + }); if (url.includes('package.json')) { // 如果是 package.json,获取对应的 CHANGELOG const changelogUrl = url.replace('package.json', 'CHANGELOG.md'); - const changelogResponse = await axios.get(changelogUrl); + const changelogResponse = await axios.get(changelogUrl, { + timeout: REQUEST_TIMEOUT + }); return { tag_name: response.data.version,