diff --git a/frontend/src/components/initialization/AutoMode.vue b/frontend/src/components/initialization/AutoMode.vue
index 11fa8d3..23bfa31 100644
--- a/frontend/src/components/initialization/AutoMode.vue
+++ b/frontend/src/components/initialization/AutoMode.vue
@@ -15,8 +15,20 @@
-
重新配置环境
-
强行进入应用
+
+ 重新配置环境
+
+
+ 强行进入应用
+
@@ -41,8 +53,10 @@
import { ref, onMounted } from 'vue'
import { getConfig } from '@/utils/config'
import { getMirrorUrl } from '@/config/mirrors'
+import { mirrorManager } from '@/utils/mirrorManager'
import router from '@/router'
import { connectAfterBackendStart } from '@/composables/useWebSocket'
+import { message } from 'ant-design-vue'
@@ -65,6 +79,11 @@ const aborted = ref(false)
// 状态:控制弹窗显隐
const forceEnterVisible = ref(false)
+// 镜像源重试相关状态
+const currentMirrorIndex = ref(0)
+const availableMirrors = ref([])
+const maxRetries = ref(3)
+
// 点击“强行进入应用”按钮,显示弹窗
function handleForceEnter() {
forceEnterVisible.value = true
@@ -100,12 +119,17 @@ async function startAutoProcess() {
progressText.value = '发现更新,正在更新代码...'
progress.value = 40
- // 使用配置中保存的Git镜像源
- const gitMirrorUrl = getGitMirrorUrl(config.selectedGitMirror)
- const result = await window.electronAPI.updateBackend(gitMirrorUrl)
+ // 尝试更新代码,支持镜像源重试
+ const updateSuccess = await tryUpdateBackendWithRetry(config)
if (aborted.value) return
- if (!result.success) {
- throw new Error(`代码更新失败: ${result.error}`)
+ if (!updateSuccess) {
+ // 所有镜像源都失败了,显示重新配置按钮
+ progressText.value = '代码更新失败,所有镜像源均无法访问'
+ progressStatus.value = 'exception'
+ setTimeout(() => {
+ progressText.value = '请点击下方按钮重新配置环境'
+ }, 2000)
+ return
}
}
@@ -113,23 +137,17 @@ async function startAutoProcess() {
progressText.value = '检查并安装依赖包...'
progress.value = 60
- // 先尝试使用初始化时的镜像源
- let pipMirror = config.selectedPipMirror || 'tsinghua'
- let pipResult = await window.electronAPI.installDependencies(pipMirror)
+ // 尝试安装依赖,支持镜像源重试
+ const dependenciesSuccess = await tryInstallDependenciesWithRetry(config)
if (aborted.value) return
- // 如果初始化时的镜像源不通,让用户重新选择
- if (!pipResult.success) {
- console.warn(`使用镜像源 ${pipMirror} 安装依赖失败,需要重新选择镜像源`)
-
- // 切换到手动模式让用户重新选择镜像源
- progressText.value = '依赖安装失败,需要重新配置镜像源'
+ if (!dependenciesSuccess) {
+ // 所有PIP镜像源都失败了,显示重新配置按钮
+ progressText.value = '依赖安装失败,所有PIP镜像源均无法访问'
progressStatus.value = 'exception'
-
setTimeout(() => {
progressText.value = '请点击下方按钮重新配置环境'
}, 2000)
-
return
}
@@ -180,6 +198,108 @@ function getGitMirrorUrl(mirrorKey: string): string {
return getMirrorUrl('git', mirrorKey)
}
+// 尝试更新后端代码,支持镜像源重试
+async function tryUpdateBackendWithRetry(config: any): Promise {
+ // 获取所有Git镜像源
+ const allGitMirrors = mirrorManager.getMirrors('git')
+
+ // 加载用户的自定义镜像源
+ const customMirrors = config.customGitMirrors || []
+ const combinedMirrors = [...allGitMirrors, ...customMirrors]
+
+ // 优先使用用户选择的镜像源
+ const selectedMirror = combinedMirrors.find(m => m.key === config.selectedGitMirror)
+ let mirrorsToTry = selectedMirror ? [selectedMirror] : []
+
+ // 添加其他镜像源作为备选
+ const otherMirrors = combinedMirrors.filter(m => m.key !== config.selectedGitMirror)
+ mirrorsToTry = [...mirrorsToTry, ...otherMirrors]
+
+ console.log('准备尝试的Git镜像源:', mirrorsToTry.map(m => m.name))
+
+ for (let i = 0; i < mirrorsToTry.length; i++) {
+ if (aborted.value) return false
+
+ const mirror = mirrorsToTry[i]
+ progressText.value = `正在使用 ${mirror.name} 更新代码... (${i + 1}/${mirrorsToTry.length})`
+
+ try {
+ console.log(`尝试使用镜像源: ${mirror.name} (${mirror.url})`)
+ const result = await window.electronAPI.updateBackend(mirror.url)
+
+ if (result.success) {
+ console.log(`使用镜像源 ${mirror.name} 更新成功`)
+ message.success(`使用 ${mirror.name} 更新代码成功`)
+ return true
+ } else {
+ console.warn(`镜像源 ${mirror.name} 更新失败:`, result.error)
+ if (i < mirrorsToTry.length - 1) {
+ progressText.value = `${mirror.name} 失败,尝试下一个镜像源...`
+ await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒
+ }
+ }
+ } catch (error) {
+ console.error(`镜像源 ${mirror.name} 更新异常:`, error)
+ if (i < mirrorsToTry.length - 1) {
+ progressText.value = `${mirror.name} 异常,尝试下一个镜像源...`
+ await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒
+ }
+ }
+ }
+
+ console.error('所有Git镜像源都无法更新代码')
+ return false
+}
+
+// 尝试安装依赖,支持镜像源重试
+async function tryInstallDependenciesWithRetry(config: any): Promise {
+ // 获取所有PIP镜像源
+ const allPipMirrors = mirrorManager.getMirrors('pip')
+
+ // 优先使用用户选择的镜像源
+ const selectedMirror = allPipMirrors.find(m => m.key === config.selectedPipMirror)
+ let mirrorsToTry = selectedMirror ? [selectedMirror] : []
+
+ // 添加其他镜像源作为备选
+ const otherMirrors = allPipMirrors.filter(m => m.key !== config.selectedPipMirror)
+ mirrorsToTry = [...mirrorsToTry, ...otherMirrors]
+
+ console.log('准备尝试的PIP镜像源:', mirrorsToTry.map(m => m.name))
+
+ for (let i = 0; i < mirrorsToTry.length; i++) {
+ if (aborted.value) return false
+
+ const mirror = mirrorsToTry[i]
+ progressText.value = `正在使用 ${mirror.name} 安装依赖... (${i + 1}/${mirrorsToTry.length})`
+
+ try {
+ console.log(`尝试使用PIP镜像源: ${mirror.name} (${mirror.url})`)
+ const result = await window.electronAPI.installDependencies(mirror.key)
+
+ if (result.success) {
+ console.log(`使用PIP镜像源 ${mirror.name} 安装成功`)
+ message.success(`使用 ${mirror.name} 安装依赖成功`)
+ return true
+ } else {
+ console.warn(`PIP镜像源 ${mirror.name} 安装失败:`, result.error)
+ if (i < mirrorsToTry.length - 1) {
+ progressText.value = `${mirror.name} 失败,尝试下一个镜像源...`
+ await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒
+ }
+ }
+ } catch (error) {
+ console.error(`PIP镜像源 ${mirror.name} 安装异常:`, error)
+ if (i < mirrorsToTry.length - 1) {
+ progressText.value = `${mirror.name} 异常,尝试下一个镜像源...`
+ await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒
+ }
+ }
+ }
+
+ console.error('所有PIP镜像源都无法安装依赖')
+ return false
+}
+
// 启动后端服务
async function startBackendService() {
const result = await window.electronAPI.startBackend()
diff --git a/frontend/src/components/initialization/BackendStep.vue b/frontend/src/components/initialization/BackendStep.vue
index f14f910..16562a1 100644
--- a/frontend/src/components/initialization/BackendStep.vue
+++ b/frontend/src/components/initialization/BackendStep.vue
@@ -67,6 +67,67 @@
+
+
+
+
+
+
+
+
+
+
{{ mirror.description }}
+
+
+
+
{{ testingGitSpeed ? '测速中...' : '重新测速' }}
@@ -105,12 +166,26 @@ const sortedMirrorMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(m
const selectedGitMirror = ref('ghproxy_edgeone')
const testingGitSpeed = ref(false)
+// 自定义镜像源相关
+const customMirrorUrl = ref('')
+const customMirrors = ref([])
+const addingCustomMirror = ref(false)
+
// 加载配置中的镜像源选择
async function loadMirrorConfig() {
try {
const config = await getConfig()
- selectedGitMirror.value = config.selectedGitMirror
+ selectedGitMirror.value = config.selectedGitMirror || 'ghproxy_edgeone'
+
+ // 加载自定义镜像源
+ if (config.customGitMirrors && Array.isArray(config.customGitMirrors)) {
+ customMirrors.value = config.customGitMirrors
+ // 将自定义镜像源添加到gitMirrors中
+ gitMirrors.value = [...GIT_MIRRORS, ...customMirrors.value]
+ }
+
console.log('Git镜像源配置已加载:', selectedGitMirror.value)
+ console.log('自定义镜像源已加载:', customMirrors.value.length, '个')
} catch (error) {
console.warn('加载Git镜像源配置失败:', error)
}
@@ -119,8 +194,12 @@ async function loadMirrorConfig() {
// 保存镜像源选择
async function saveMirrorConfig() {
try {
- await saveConfig({ selectedGitMirror: selectedGitMirror.value })
+ await saveConfig({
+ selectedGitMirror: selectedGitMirror.value,
+ customGitMirrors: customMirrors.value
+ })
console.log('Git镜像源配置已保存:', selectedGitMirror.value)
+ console.log('自定义镜像源已保存:', customMirrors.value.length, '个')
} catch (error) {
console.warn('保存Git镜像源配置失败:', error)
}
@@ -176,6 +255,135 @@ function getSpeedClass(speed: number | null) {
return 'speed-slow'
}
+// 处理自定义镜像源URL
+function processCustomMirrorUrl(input: string): string {
+ const trimmedInput = input.trim()
+
+ // 如果已经是完整的Git地址且以.git结尾,直接返回
+ if (trimmedInput.includes('github.com/AUTO-MAS-Project/AUTO-MAS') && trimmedInput.endsWith('.git')) {
+ return trimmedInput
+ }
+
+ // 如果是完整的Git地址但没有.git结尾,添加.git
+ if (trimmedInput.includes('github.com/AUTO-MAS-Project/AUTO-MAS')) {
+ return trimmedInput.endsWith('.git') ? trimmedInput : trimmedInput + '.git'
+ }
+
+ // 如果只是域名,拼接完整地址
+ let domain = trimmedInput
+
+ // 移除协议前缀
+ domain = domain.replace(/^https?:\/\//, '')
+
+ // 移除尾部斜杠
+ domain = domain.replace(/\/$/, '')
+
+ // 拼接完整地址
+ return `https://${domain}/https://github.com/AUTO-MAS-Project/AUTO-MAS.git`
+}
+
+// 添加自定义镜像源
+async function addCustomMirror() {
+ if (!customMirrorUrl.value.trim()) {
+ return
+ }
+
+ addingCustomMirror.value = true
+
+ try {
+ const processedUrl = processCustomMirrorUrl(customMirrorUrl.value)
+
+ // 检查是否已存在
+ const existingMirror = [...gitMirrors.value, ...customMirrors.value].find(
+ m => m.url === processedUrl
+ )
+
+ if (existingMirror) {
+ console.warn('镜像源已存在:', processedUrl)
+ customMirrorUrl.value = ''
+ return
+ }
+
+ // 生成镜像源配置
+ const customKey = `custom_${Date.now()}`
+ const customName = extractDomainName(customMirrorUrl.value)
+
+ const newMirror: MirrorConfig = {
+ key: customKey,
+ name: `${customName} (自定义)`,
+ url: processedUrl,
+ speed: null,
+ type: 'mirror',
+ chinaConnectivity: 'good',
+ description: `用户自定义的镜像源: ${customName}`
+ }
+
+ // 添加到自定义镜像源列表
+ customMirrors.value.push(newMirror)
+
+ // 更新完整的镜像源列表
+ gitMirrors.value = [...GIT_MIRRORS, ...customMirrors.value]
+
+ // 自动选择新添加的镜像源
+ selectedGitMirror.value = customKey
+
+ // 保存配置
+ await saveMirrorConfig()
+
+ // 清空输入框
+ customMirrorUrl.value = ''
+
+ console.log('自定义镜像源添加成功:', newMirror)
+
+ } catch (error) {
+ console.error('添加自定义镜像源失败:', error)
+ } finally {
+ addingCustomMirror.value = false
+ }
+}
+
+// 提取域名作为显示名称
+function extractDomainName(url: string): string {
+ try {
+ // 移除协议前缀
+ let domain = url.replace(/^https?:\/\//, '')
+
+ // 如果包含路径,只取域名部分
+ domain = domain.split('/')[0]
+
+ // 移除端口号
+ domain = domain.split(':')[0]
+
+ return domain || '自定义镜像'
+ } catch {
+ return '自定义镜像'
+ }
+}
+
+// 删除自定义镜像源
+async function removeCustomMirror(key: string) {
+ try {
+ // 从自定义镜像源列表中移除
+ customMirrors.value = customMirrors.value.filter(m => m.key !== key)
+
+ // 更新完整的镜像源列表
+ gitMirrors.value = [...GIT_MIRRORS, ...customMirrors.value]
+
+ // 如果当前选中的是被删除的镜像源,切换到默认镜像源
+ if (selectedGitMirror.value === key) {
+ selectedGitMirror.value = 'ghproxy_edgeone'
+ }
+
+ // 保存配置
+ await saveMirrorConfig()
+
+ console.log('自定义镜像源删除成功:', key)
+
+ } catch (error) {
+ console.error('删除自定义镜像源失败:', error)
+ }
+}
+
defineExpose({
selectedGitMirror,
testGitMirrorSpeed,
@@ -334,4 +542,34 @@ onMounted(async () => {
font-size: 12px;
color: var(--ant-color-text-tertiary);
}
+
+.custom-mirror-input {
+ margin-bottom: 16px;
+}
+
+.custom-mirror-help {
+ margin-top: 8px;
+}
+
+.custom-mirror-help code {
+ background: var(--ant-color-fill-alter);
+ padding: 2px 4px;
+ border-radius: 3px;
+ font-family: 'Courier New', monospace;
+ font-size: 12px;
+}
+
+.mirror-card.custom-mirror {
+ border-color: var(--ant-color-primary-border);
+}
+
+.mirror-card.custom-mirror:hover {
+ border-color: var(--ant-color-primary);
+}
+
+.mirror-actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
\ No newline at end of file