diff --git a/frontend/.yarn/install-state.gz b/frontend/.yarn/install-state.gz
deleted file mode 100644
index 2f3047b..0000000
Binary files a/frontend/.yarn/install-state.gz and /dev/null differ
diff --git a/frontend/package.json b/frontend/package.json
index 1476357..03550ed 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
- "version": "1.0.1",
+ "version": "1.0.2",
"main": "dist-electron/main.js",
"scripts": {
"dev": "concurrently \"vite\" \"yarn watch:main\" \"yarn electron-dev\"",
diff --git a/frontend/src/components/initialization/AutoMode.vue b/frontend/src/components/initialization/AutoMode.vue
index a7ffb90..0f61829 100644
--- a/frontend/src/components/initialization/AutoMode.vue
+++ b/frontend/src/components/initialization/AutoMode.vue
@@ -15,8 +15,20 @@
-
重新配置环境
-
强行进入应用
+
+ 重新配置环境
+
+
+ 强行进入应用
+
@@ -41,9 +53,11 @@
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 { useUpdateChecker } from '@/composables/useUpdateChecker'
import { connectAfterBackendStart } from '@/composables/useWebSocket'
+import { message } from 'ant-design-vue'
@@ -69,6 +83,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
@@ -104,12 +123,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
}
}
@@ -117,23 +141,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
}
@@ -184,6 +202,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
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index 78adbce..a7bd096 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -12,6 +12,9 @@ import 'dayjs/locale/zh-cn'
// 导入日志系统
import { logger } from '@/utils/logger'
+// 导入镜像管理器
+import { mirrorManager } from '@/utils/mirrorManager'
+
// 配置dayjs中文本地化
dayjs.locale('zh-cn')
@@ -24,6 +27,13 @@ OpenAPI.BASE = API_ENDPOINTS.local
logger.info('前端应用开始初始化')
logger.info(`API基础URL: ${OpenAPI.BASE}`)
+// 初始化镜像管理器(异步)
+mirrorManager.initialize().then(() => {
+ logger.info('镜像管理器初始化完成')
+}).catch((error) => {
+ logger.error('镜像管理器初始化失败:', error)
+})
+
// 创建应用实例
const app = createApp(App)
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index a316355..16badf9 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -94,6 +94,12 @@ const routes: RouteRecordRaw[] = [
component: () => import('../views/Logs.vue'),
meta: { title: '日志查看' },
},
+ {
+ path: '/mirror-test',
+ name: 'MirrorTest',
+ component: () => import('../views/MirrorTest.vue'),
+ meta: { title: '镜像配置测试' },
+ },
]
const router = createRouter({
diff --git a/frontend/src/utils/cloudConfigManager.ts b/frontend/src/utils/cloudConfigManager.ts
new file mode 100644
index 0000000..27684c0
--- /dev/null
+++ b/frontend/src/utils/cloudConfigManager.ts
@@ -0,0 +1,187 @@
+/**
+ * 云端配置管理器
+ * 负责从云端拉取最新的镜像站配置,如果失败则使用本地兜底配置
+ */
+
+import type { MirrorCategory, MirrorConfig } from '@/config/mirrors'
+
+export interface CloudMirrorConfig {
+ version: string
+ lastUpdated: string
+ mirrors: MirrorCategory
+ apiEndpoints: Record
+ downloadLinks: Record
+}
+
+export class CloudConfigManager {
+ private static instance: CloudConfigManager
+ private cloudConfigUrl = 'https://download.auto-mas.top/d/AUTO_MAS/Server/mirrors.json'
+ private fallbackConfig: CloudMirrorConfig | null = null
+ private currentConfig: CloudMirrorConfig | null = null
+ private fetchTimeout = 3000 // 3秒超时
+
+ private constructor() {}
+
+ static getInstance(): CloudConfigManager {
+ if (!CloudConfigManager.instance) {
+ CloudConfigManager.instance = new CloudConfigManager()
+ }
+ return CloudConfigManager.instance
+ }
+
+ /**
+ * 设置兜底配置(本地配置)
+ */
+ setFallbackConfig(config: CloudMirrorConfig): void {
+ this.fallbackConfig = config
+ }
+
+ /**
+ * 从云端拉取最新配置
+ */
+ async fetchCloudConfig(): Promise {
+ try {
+ console.log('正在从云端拉取镜像站配置...')
+
+ const controller = new AbortController()
+ const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeout)
+
+ const response = await fetch(this.cloudConfigUrl, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json',
+ 'Cache-Control': 'no-cache'
+ },
+ signal: controller.signal
+ })
+
+ clearTimeout(timeoutId)
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`)
+ }
+
+ const config: CloudMirrorConfig = await response.json()
+
+ // 验证配置格式
+ if (!this.validateConfig(config)) {
+ throw new Error('云端配置格式不正确')
+ }
+
+ this.currentConfig = config
+ console.log('云端配置拉取成功:', config.version)
+ return config
+
+ } catch (error) {
+ console.warn('云端配置拉取失败:', error)
+ return null
+ }
+ }
+
+ /**
+ * 验证配置格式是否正确
+ */
+ private validateConfig(config: any): config is CloudMirrorConfig {
+ if (!config || typeof config !== 'object') {
+ return false
+ }
+
+ // 检查必需字段
+ if (!config.version || !config.mirrors || !config.apiEndpoints || !config.downloadLinks) {
+ return false
+ }
+
+ // 检查mirrors结构
+ if (typeof config.mirrors !== 'object') {
+ return false
+ }
+
+ // 检查每个镜像类型的配置
+ for (const [type, mirrors] of Object.entries(config.mirrors)) {
+ if (!Array.isArray(mirrors)) {
+ return false
+ }
+
+ // 检查每个镜像配置
+ for (const mirror of mirrors as any[]) {
+ if (!mirror.key || !mirror.name || !mirror.url || !mirror.type) {
+ return false
+ }
+ }
+ }
+
+ return true
+ }
+
+ /**
+ * 获取当前有效配置(优先云端,兜底本地)
+ */
+ getCurrentConfig(): CloudMirrorConfig | null {
+ return this.currentConfig || this.fallbackConfig
+ }
+
+ /**
+ * 初始化配置(启动时调用)
+ */
+ async initializeConfig(fallbackConfig: CloudMirrorConfig): Promise {
+ this.setFallbackConfig(fallbackConfig)
+
+ // 尝试拉取云端配置
+ const cloudConfig = await this.fetchCloudConfig()
+
+ if (cloudConfig) {
+ console.log('使用云端配置')
+ return cloudConfig
+ } else {
+ console.log('使用本地兜底配置')
+ return fallbackConfig
+ }
+ }
+
+ /**
+ * 手动刷新配置
+ */
+ async refreshConfig(): Promise<{ success: boolean; config?: CloudMirrorConfig; error?: string }> {
+ try {
+ const cloudConfig = await this.fetchCloudConfig()
+
+ if (cloudConfig) {
+ return { success: true, config: cloudConfig }
+ } else {
+ return {
+ success: false,
+ error: '无法获取云端配置,继续使用当前配置',
+ config: this.getCurrentConfig() || undefined
+ }
+ }
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : '未知错误',
+ config: this.getCurrentConfig() || undefined
+ }
+ }
+ }
+
+ /**
+ * 获取配置状态信息
+ */
+ getConfigStatus(): {
+ isUsingCloudConfig: boolean
+ version?: string
+ lastUpdated?: string
+ source: 'cloud' | 'fallback'
+ } {
+ const config = this.getCurrentConfig()
+
+ return {
+ isUsingCloudConfig: this.currentConfig !== null,
+ version: config?.version,
+ lastUpdated: config?.lastUpdated,
+ source: this.currentConfig ? 'cloud' : 'fallback'
+ }
+ }
+}
+
+// 导出单例实例
+export const cloudConfigManager = CloudConfigManager.getInstance()
\ No newline at end of file
diff --git a/frontend/src/utils/mirrorManager.ts b/frontend/src/utils/mirrorManager.ts
index 1b06003..fe8bf80 100644
--- a/frontend/src/utils/mirrorManager.ts
+++ b/frontend/src/utils/mirrorManager.ts
@@ -14,6 +14,7 @@ import {
sortMirrorsBySpeed,
getFastestMirror,
} from '@/config/mirrors'
+import { cloudConfigManager, type CloudMirrorConfig } from './cloudConfigManager'
/**
* 镜像源管理器类
@@ -23,6 +24,7 @@ export class MirrorManager {
private mirrorConfigs: MirrorCategory = { ...ALL_MIRRORS }
private apiEndpoints = { ...API_ENDPOINTS }
private downloadLinks = { ...DOWNLOAD_LINKS }
+ private isInitialized = false
private constructor() {}
@@ -36,6 +38,73 @@ export class MirrorManager {
return MirrorManager.instance
}
+ /**
+ * 初始化镜像管理器(从云端拉取配置)
+ */
+ async initialize(): Promise {
+ if (this.isInitialized) {
+ return
+ }
+
+ try {
+ // 准备兜底配置
+ const fallbackConfig: CloudMirrorConfig = {
+ version: '1.0.0-local',
+ lastUpdated: new Date().toISOString(),
+ mirrors: { ...ALL_MIRRORS },
+ apiEndpoints: { ...API_ENDPOINTS },
+ downloadLinks: { ...DOWNLOAD_LINKS }
+ }
+
+ // 从云端初始化配置
+ const config = await cloudConfigManager.initializeConfig(fallbackConfig)
+
+ // 更新本地配置
+ this.mirrorConfigs = config.mirrors
+ this.apiEndpoints = config.apiEndpoints
+ this.downloadLinks = config.downloadLinks
+
+ this.isInitialized = true
+ console.log('镜像管理器初始化完成')
+ } catch (error) {
+ console.error('镜像管理器初始化失败:', error)
+ // 使用默认配置
+ this.isInitialized = true
+ }
+ }
+
+ /**
+ * 手动刷新云端配置
+ */
+ async refreshCloudConfig(): Promise<{ success: boolean; error?: string }> {
+ try {
+ const result = await cloudConfigManager.refreshConfig()
+
+ if (result.success && result.config) {
+ // 更新本地配置
+ this.mirrorConfigs = result.config.mirrors
+ this.apiEndpoints = result.config.apiEndpoints
+ this.downloadLinks = result.config.downloadLinks
+
+ return { success: true }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : '刷新配置失败'
+ }
+ }
+ }
+
+ /**
+ * 获取配置状态
+ */
+ getConfigStatus() {
+ return cloudConfigManager.getConfigStatus()
+ }
+
/**
* 获取指定类型的镜像源列表
*/
diff --git a/frontend/src/views/Initialization.vue b/frontend/src/views/Initialization.vue
index d3da8ca..025c2b7 100644
--- a/frontend/src/views/Initialization.vue
+++ b/frontend/src/views/Initialization.vue
@@ -34,6 +34,7 @@ import AdminCheck from '@/components/initialization/AdminCheck.vue'
import AutoMode from '@/components/initialization/AutoMode.vue'
import ManualMode from '@/components/initialization/ManualMode.vue'
import type { DownloadProgress } from '@/types/initialization'
+import { mirrorManager } from '@/utils/mirrorManager'
const router = useRouter()
@@ -48,6 +49,12 @@ const backendExists = ref(false)
const dependenciesInstalled = ref(false)
const serviceStarted = ref(false)
+// 镜像配置状态
+const mirrorConfigStatus = ref({
+ source: 'fallback' as 'cloud' | 'fallback',
+ version: ''
+})
+
// 组件引用
const manualModeRef = ref()
@@ -230,6 +237,14 @@ function handleProgressUpdate(progress: DownloadProgress) {
onMounted(async () => {
console.log('初始化页面 onMounted 开始')
+ // 更新镜像配置状态
+ const status = mirrorManager.getConfigStatus()
+ mirrorConfigStatus.value = {
+ source: status.source,
+ version: status.version || ''
+ }
+ console.log('镜像配置状态:', mirrorConfigStatus.value)
+
// 测试配置系统
try {
console.log('测试配置系统...')
diff --git a/frontend/src/views/MirrorTest.vue b/frontend/src/views/MirrorTest.vue
new file mode 100644
index 0000000..66e954e
--- /dev/null
+++ b/frontend/src/views/MirrorTest.vue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+ {{ configStatus.source === 'cloud' ? '云端配置' : '本地兜底配置' }}
+
+
+
+ {{ configStatus.version }}
+
+
+ {{ new Date(configStatus.lastUpdated).toLocaleString() }}
+
+
+
+
+
+
+
+ 刷新云端配置
+
+
+ 更新状态
+
+
+ 测试云端URL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ log.time }}
+ {{ log.message }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue
index 987d8a1..5bea5e2 100644
--- a/frontend/src/views/Settings.vue
+++ b/frontend/src/views/Settings.vue
@@ -16,6 +16,7 @@ import type { SelectValue } from 'ant-design-vue/es/select'
import type { SettingsData } from '../types/settings'
import { Service, type VersionOut } from '@/api'
import UpdateModal from '@/components/UpdateModal.vue'
+import { mirrorManager } from '@/utils/mirrorManager'
const updateData = ref>({})
@@ -32,6 +33,15 @@ const activeKey = ref('basic')
const backendUpdateInfo = ref(null)
+// 镜像配置相关状态
+const mirrorConfigStatus = ref({
+ isUsingCloudConfig: false,
+ version: '',
+ lastUpdated: '',
+ source: 'fallback' as 'cloud' | 'fallback'
+})
+const refreshingConfig = ref(false)
+
const settings = reactive({
UI: {
IfShowTray: false,
@@ -257,6 +267,34 @@ const checkUpdate = async () => {
}
}
+// 镜像配置相关方法
+const updateMirrorConfigStatus = () => {
+ const status = mirrorManager.getConfigStatus()
+ mirrorConfigStatus.value = status
+}
+
+const refreshMirrorConfig = async () => {
+ refreshingConfig.value = true
+ try {
+ const result = await mirrorManager.refreshCloudConfig()
+ if (result.success) {
+ message.success('镜像配置刷新成功')
+ updateMirrorConfigStatus()
+ } else {
+ message.warning(result.error || '刷新失败,继续使用当前配置')
+ }
+ } catch (error) {
+ console.error('刷新镜像配置失败:', error)
+ message.error('刷新镜像配置失败')
+ } finally {
+ refreshingConfig.value = false
+ }
+}
+
+const goToMirrorTest = () => {
+ router.push('/mirror-test')
+}
+
// 确认回调
const onUpdateConfirmed = () => {
updateVisible.value = false
@@ -265,6 +303,7 @@ const onUpdateConfirmed = () => {
onMounted(() => {
loadSettings()
getBackendVersion()
+ updateMirrorConfigStatus()
})
@@ -1186,6 +1225,97 @@ onMounted(() => {
+
+
+
+
+