From 2237dba3c5b12dc0cfec0100178c05ec76f5914d Mon Sep 17 00:00:00 2001 From: AoXuan Date: Wed, 13 Aug 2025 21:02:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(config):=20=E9=87=8D=E6=9E=84=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E6=BA=90=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/electron/services/pythonService.ts | 2 +- frontend/src/api/mirrors.ts | 100 ++++++++ .../components/initialization/AutoMode.vue | 22 +- .../components/initialization/BackendStep.vue | 11 +- .../initialization/DependenciesStep.vue | 9 +- .../src/components/initialization/GitStep.vue | 12 +- .../components/initialization/ManualMode.vue | 48 ++-- .../src/components/initialization/PipStep.vue | 12 +- .../components/initialization/PythonStep.vue | 22 +- frontend/src/config/mirrors.ts | 216 ++++++++++++++++++ frontend/src/main.ts | 4 +- frontend/src/utils/mirrorManager.ts | 187 +++++++++++++++ 12 files changed, 575 insertions(+), 70 deletions(-) create mode 100644 frontend/src/api/mirrors.ts create mode 100644 frontend/src/config/mirrors.ts create mode 100644 frontend/src/utils/mirrorManager.ts diff --git a/frontend/electron/services/pythonService.ts b/frontend/electron/services/pythonService.ts index e0e3454..4591ba5 100644 --- a/frontend/electron/services/pythonService.ts +++ b/frontend/electron/services/pythonService.ts @@ -203,7 +203,7 @@ export async function downloadPython(appRoot: string, mirror = 'ustc'): Promise< // Python 3.12.0嵌入式版本应该大约30MB,如果小于5MB可能是无效文件 if (stats.size < 5 * 1024 * 1024) { // 5MB fs.unlinkSync(zipPath) // 删除无效文件 - throw new Error(`Python下载文件大小异常: ${stats.size} bytes (${(stats.size / 1024).toFixed(2)} KB),可能是镜像站返回的错误页面或无效文件`) + throw new Error(`Python下载文件大小异常: ${stats.size} bytes (${(stats.size / 1024).toFixed(2)} KB),可能是镜像站返回的错误页面或无效文件。请选择一个其他可用镜像源进行下载!`) } if (mainWindow) { diff --git a/frontend/src/api/mirrors.ts b/frontend/src/api/mirrors.ts new file mode 100644 index 0000000..a33e65b --- /dev/null +++ b/frontend/src/api/mirrors.ts @@ -0,0 +1,100 @@ +/** + * 镜像源 API 接口 + * 用于从后端获取最新的镜像源配置 + */ + +import { OpenAPI } from '@/api' +import type { MirrorConfig } from '@/config/mirrors' + +export interface MirrorApiResponse { + git?: MirrorConfig[] + python?: MirrorConfig[] + pip?: MirrorConfig[] + apiEndpoints?: { + local?: string + production?: string + proxy?: string + } + downloadLinks?: { + [category: string]: { + [key: string]: string + } + } +} + +/** + * 获取镜像源配置 + */ +export async function fetchMirrorConfig(): Promise { + try { + const response = await fetch(`${OpenAPI.BASE}/api/mirrors`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + return await response.json() + } catch (error) { + console.warn('获取镜像源配置失败,使用默认配置:', error) + throw error + } +} + +/** + * 测试镜像源连通性 + */ +export async function testMirrorConnectivity(url: string, timeout: number = 5000): Promise<{ + success: boolean + speed: number + error?: string +}> { + try { + const startTime = Date.now() + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), timeout) + + const response = await fetch(url, { + method: 'HEAD', + signal: controller.signal, + cache: 'no-cache', + mode: 'no-cors' // 避免 CORS 问题 + }) + + clearTimeout(timeoutId) + const speed = Date.now() - startTime + + return { + success: true, + speed + } + } catch (error) { + return { + success: false, + speed: 9999, + error: error instanceof Error ? error.message : String(error) + } + } +} + +/** + * 批量测试镜像源 + */ +export async function batchTestMirrors(mirrors: MirrorConfig[]): Promise { + const promises = mirrors.map(async (mirror) => { + const result = await testMirrorConnectivity(mirror.url) + return { + ...mirror, + speed: result.speed + } + }) + + const results = await Promise.all(promises) + + // 按速度排序 + return results.sort((a, b) => (a.speed || 9999) - (b.speed || 9999)) +} diff --git a/frontend/src/components/initialization/AutoMode.vue b/frontend/src/components/initialization/AutoMode.vue index 1f9a667..0c1a701 100644 --- a/frontend/src/components/initialization/AutoMode.vue +++ b/frontend/src/components/initialization/AutoMode.vue @@ -41,6 +41,7 @@ import { ref, onMounted } from 'vue' import { createComponentLogger } from '@/utils/logger' import { getConfig } from '@/utils/config' +import { getMirrorUrl } from '@/config/mirrors' import router from '@/router' const logger = createComponentLogger('AutoMode') @@ -58,6 +59,9 @@ const progress = ref(0) const progressText = ref('') const progressStatus = ref<'normal' | 'exception' | 'success'>('normal') +// 状态:控制是否取消自动启动 +const aborted = ref(false) + // 状态:控制弹窗显隐 const forceEnterVisible = ref(false) @@ -74,6 +78,7 @@ function handleForceEnterConfirm() { // 事件处理 function handleSwitchToManual() { + aborted.value = true // 设置中断 props.onSwitchToManual() } @@ -82,12 +87,14 @@ async function startAutoProcess() { try { // 获取配置中保存的镜像源设置 const config = await getConfig() + if (aborted.value) return progressText.value = '检查Git仓库更新...' progress.value = 20 // 检查Git仓库是否有更新 const hasUpdate = await checkGitUpdate() + if (aborted.value) return if (hasUpdate) { progressText.value = '发现更新,正在更新代码...' @@ -96,6 +103,7 @@ async function startAutoProcess() { // 使用配置中保存的Git镜像源 const gitMirrorUrl = getGitMirrorUrl(config.selectedGitMirror) const result = await window.electronAPI.updateBackend(gitMirrorUrl) + if (aborted.value) return if (!result.success) { throw new Error(`代码更新失败: ${result.error}`) } @@ -108,6 +116,7 @@ async function startAutoProcess() { // 先尝试使用初始化时的镜像源 let pipMirror = config.selectedPipMirror || 'tsinghua' let pipResult = await window.electronAPI.installDependencies(pipMirror) + if (aborted.value) return // 如果初始化时的镜像源不通,让用户重新选择 if (!pipResult.success) { @@ -127,6 +136,7 @@ async function startAutoProcess() { progressText.value = '启动后端服务...' progress.value = 80 await startBackendService() + if (aborted.value) return progressText.value = '启动完成!' progress.value = 100 @@ -167,16 +177,7 @@ async function checkGitUpdate(): Promise { // 根据镜像源key获取对应的URL function getGitMirrorUrl(mirrorKey: string): string { - const mirrors = { - github: 'https://github.com/DLmaster361/AUTO_MAA.git', - ghfast: 'https://ghfast.top/https://github.com/DLmaster361/AUTO_MAA.git', - ghproxy_cloudflare: 'https://gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', - ghproxy_hongkong: 'https://hk.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', - ghproxy_fastly: 'https://cdn.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', - ghproxy_edgeone: 'https://edgeone.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git' - } - - return mirrors[mirrorKey as keyof typeof mirrors] || mirrors.github + return getMirrorUrl('git', mirrorKey) } // 启动后端服务 @@ -189,6 +190,7 @@ async function startBackendService() { // 组件挂载时开始自动流程 onMounted(() => { + aborted.value = false startAutoProcess() }) diff --git a/frontend/src/components/initialization/BackendStep.vue b/frontend/src/components/initialization/BackendStep.vue index 7bafc3c..54656d2 100644 --- a/frontend/src/components/initialization/BackendStep.vue +++ b/frontend/src/components/initialization/BackendStep.vue @@ -50,14 +50,9 @@ defineProps<{ backendExists: boolean }>() -const gitMirrors = ref([ - { key: 'github', name: 'GitHub 官方', url: 'https://github.com/DLmaster361/AUTO_MAA.git', speed: null }, - { key: 'ghfast', name: 'ghfast 镜像', url: 'https://ghfast.top/https://github.com/DLmaster361/AUTO_MAA.git', speed: null }, - { key: 'ghproxy_cloudflare', name: 'gh-proxy Cloudflare 全球加速', url: 'https://gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', speed: null }, - { key: 'ghproxy_hongkong', name: 'gh-proxy 香港节点(大陆优化)', url: 'https://hk.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', speed: null }, - { key: 'ghproxy_fastly', name: 'gh-proxy Fastly CDN', url: 'https://cdn.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', speed: null }, - { key: 'ghproxy_edgeone', name: 'gh-proxy EdgeOne 全球加速', url: 'https://edgeone.gh-proxy.com/https://github.com/DLmaster361/AUTO_MAA.git.git', speed: null } -]) +import { GIT_MIRRORS } from '@/config/mirrors' + +const gitMirrors = ref(GIT_MIRRORS) const selectedGitMirror = ref('github') diff --git a/frontend/src/components/initialization/DependenciesStep.vue b/frontend/src/components/initialization/DependenciesStep.vue index f0853bb..123e418 100644 --- a/frontend/src/components/initialization/DependenciesStep.vue +++ b/frontend/src/components/initialization/DependenciesStep.vue @@ -46,12 +46,9 @@ interface Mirror { speed: number | null } -const pipMirrors = ref([ - { key: 'official', name: 'PyPI 官方', url: 'https://pypi.org/simple/', speed: null }, - { key: 'tsinghua', name: '清华大学', url: 'https://pypi.tuna.tsinghua.edu.cn/simple/', speed: null }, - { key: 'aliyun', name: '阿里云', url: 'https://mirrors.aliyun.com/pypi/simple/', speed: null }, - { key: 'ustc', name: '中科大', url: 'https://pypi.mirrors.ustc.edu.cn/simple/', speed: null }, -]) +import { PIP_MIRRORS } from '@/config/mirrors' + +const pipMirrors = ref(PIP_MIRRORS) const selectedPipMirror = ref('tsinghua') const testingPipSpeed = ref(false) diff --git a/frontend/src/components/initialization/GitStep.vue b/frontend/src/components/initialization/GitStep.vue index 9e05dd8..ec2b7b5 100644 --- a/frontend/src/components/initialization/GitStep.vue +++ b/frontend/src/components/initialization/GitStep.vue @@ -14,12 +14,12 @@
-
- - {{ reinstalling ? '正在重新安装...' : '强制重新安装' }} - -

点击此按钮将删除现有Git环境并重新安装

-
+ + + + + +
diff --git a/frontend/src/components/initialization/ManualMode.vue b/frontend/src/components/initialization/ManualMode.vue index 8503c27..4f9e2b2 100644 --- a/frontend/src/components/initialization/ManualMode.vue +++ b/frontend/src/components/initialization/ManualMode.vue @@ -28,15 +28,15 @@ - -
- -
{{ progressText }}
-
+ + + + + + + + +
@@ -94,20 +94,21 @@
-
- -
+ + + + + + + + +