feat: 支持自定义镜像源添加、删除及重试机制
This commit is contained in:
@@ -15,8 +15,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auto-actions">
|
<div class="auto-actions">
|
||||||
<a-button @click="handleSwitchToManual" type="primary" size="large">重新配置环境</a-button>
|
<a-button
|
||||||
<a-button @click="handleForceEnter" type="default" size="large">强行进入应用</a-button>
|
@click="handleSwitchToManual"
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
重新配置环境
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
@click="handleForceEnter"
|
||||||
|
type="default"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
强行进入应用
|
||||||
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -41,8 +53,10 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { getConfig } from '@/utils/config'
|
import { getConfig } from '@/utils/config'
|
||||||
import { getMirrorUrl } from '@/config/mirrors'
|
import { getMirrorUrl } from '@/config/mirrors'
|
||||||
|
import { mirrorManager } from '@/utils/mirrorManager'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { connectAfterBackendStart } from '@/composables/useWebSocket'
|
import { connectAfterBackendStart } from '@/composables/useWebSocket'
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +79,11 @@ const aborted = ref(false)
|
|||||||
// 状态:控制弹窗显隐
|
// 状态:控制弹窗显隐
|
||||||
const forceEnterVisible = ref(false)
|
const forceEnterVisible = ref(false)
|
||||||
|
|
||||||
|
// 镜像源重试相关状态
|
||||||
|
const currentMirrorIndex = ref(0)
|
||||||
|
const availableMirrors = ref<any[]>([])
|
||||||
|
const maxRetries = ref(3)
|
||||||
|
|
||||||
// 点击“强行进入应用”按钮,显示弹窗
|
// 点击“强行进入应用”按钮,显示弹窗
|
||||||
function handleForceEnter() {
|
function handleForceEnter() {
|
||||||
forceEnterVisible.value = true
|
forceEnterVisible.value = true
|
||||||
@@ -100,12 +119,17 @@ async function startAutoProcess() {
|
|||||||
progressText.value = '发现更新,正在更新代码...'
|
progressText.value = '发现更新,正在更新代码...'
|
||||||
progress.value = 40
|
progress.value = 40
|
||||||
|
|
||||||
// 使用配置中保存的Git镜像源
|
// 尝试更新代码,支持镜像源重试
|
||||||
const gitMirrorUrl = getGitMirrorUrl(config.selectedGitMirror)
|
const updateSuccess = await tryUpdateBackendWithRetry(config)
|
||||||
const result = await window.electronAPI.updateBackend(gitMirrorUrl)
|
|
||||||
if (aborted.value) return
|
if (aborted.value) return
|
||||||
if (!result.success) {
|
if (!updateSuccess) {
|
||||||
throw new Error(`代码更新失败: ${result.error}`)
|
// 所有镜像源都失败了,显示重新配置按钮
|
||||||
|
progressText.value = '代码更新失败,所有镜像源均无法访问'
|
||||||
|
progressStatus.value = 'exception'
|
||||||
|
setTimeout(() => {
|
||||||
|
progressText.value = '请点击下方按钮重新配置环境'
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,23 +137,17 @@ async function startAutoProcess() {
|
|||||||
progressText.value = '检查并安装依赖包...'
|
progressText.value = '检查并安装依赖包...'
|
||||||
progress.value = 60
|
progress.value = 60
|
||||||
|
|
||||||
// 先尝试使用初始化时的镜像源
|
// 尝试安装依赖,支持镜像源重试
|
||||||
let pipMirror = config.selectedPipMirror || 'tsinghua'
|
const dependenciesSuccess = await tryInstallDependenciesWithRetry(config)
|
||||||
let pipResult = await window.electronAPI.installDependencies(pipMirror)
|
|
||||||
if (aborted.value) return
|
if (aborted.value) return
|
||||||
|
|
||||||
// 如果初始化时的镜像源不通,让用户重新选择
|
if (!dependenciesSuccess) {
|
||||||
if (!pipResult.success) {
|
// 所有PIP镜像源都失败了,显示重新配置按钮
|
||||||
console.warn(`使用镜像源 ${pipMirror} 安装依赖失败,需要重新选择镜像源`)
|
progressText.value = '依赖安装失败,所有PIP镜像源均无法访问'
|
||||||
|
|
||||||
// 切换到手动模式让用户重新选择镜像源
|
|
||||||
progressText.value = '依赖安装失败,需要重新配置镜像源'
|
|
||||||
progressStatus.value = 'exception'
|
progressStatus.value = 'exception'
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
progressText.value = '请点击下方按钮重新配置环境'
|
progressText.value = '请点击下方按钮重新配置环境'
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +198,108 @@ function getGitMirrorUrl(mirrorKey: string): string {
|
|||||||
return getMirrorUrl('git', mirrorKey)
|
return getMirrorUrl('git', mirrorKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 尝试更新后端代码,支持镜像源重试
|
||||||
|
async function tryUpdateBackendWithRetry(config: any): Promise<boolean> {
|
||||||
|
// 获取所有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<boolean> {
|
||||||
|
// 获取所有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() {
|
async function startBackendService() {
|
||||||
const result = await window.electronAPI.startBackend()
|
const result = await window.electronAPI.startBackend()
|
||||||
|
|||||||
@@ -67,6 +67,67 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 自定义镜像源 -->
|
||||||
|
<div class="mirror-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h4>自定义镜像源</h4>
|
||||||
|
<a-tag color="blue">手动添加</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="custom-mirror-input">
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-input
|
||||||
|
v-model:value="customMirrorUrl"
|
||||||
|
placeholder="输入镜像域名或完整Git地址,如:ghproxy.com 或 https://ghproxy.com/https://github.com/AUTO-MAS-Project/AUTO-MAS.git"
|
||||||
|
style="width: calc(100% - 100px)"
|
||||||
|
@pressEnter="addCustomMirror"
|
||||||
|
/>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="addCustomMirror"
|
||||||
|
:loading="addingCustomMirror"
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
添加
|
||||||
|
</a-button>
|
||||||
|
</a-input-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 显示自定义镜像源 -->
|
||||||
|
<div v-if="customMirrors.length > 0" class="mirror-grid" style="margin-top: 16px;">
|
||||||
|
<div
|
||||||
|
v-for="mirror in customMirrors"
|
||||||
|
:key="mirror.key"
|
||||||
|
class="mirror-card custom-mirror"
|
||||||
|
:class="{ active: selectedGitMirror === mirror.key }"
|
||||||
|
@click="selectedGitMirror = mirror.key"
|
||||||
|
>
|
||||||
|
<div class="mirror-header">
|
||||||
|
<div class="mirror-title">
|
||||||
|
<h4>{{ mirror.name }}</h4>
|
||||||
|
<a-tag color="blue" size="small">自定义</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="mirror-actions">
|
||||||
|
<div class="speed-badge" :class="getSpeedClass(mirror.speed ?? null)">
|
||||||
|
<span v-if="mirror.speed === null && !testingGitSpeed">未测试</span>
|
||||||
|
<span v-else-if="testingGitSpeed">测试中...</span>
|
||||||
|
<span v-else-if="mirror.speed === 9999">超时</span>
|
||||||
|
<span v-else>{{ mirror.speed }}ms</span>
|
||||||
|
</div>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
@click.stop="removeCustomMirror(mirror.key)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mirror-description">{{ mirror.description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="test-actions">
|
<div class="test-actions">
|
||||||
<a-button @click="testGitMirrorSpeed" :loading="testingGitSpeed" type="primary">
|
<a-button @click="testGitMirrorSpeed" :loading="testingGitSpeed" type="primary">
|
||||||
{{ testingGitSpeed ? '测速中...' : '重新测速' }}
|
{{ testingGitSpeed ? '测速中...' : '重新测速' }}
|
||||||
@@ -105,12 +166,26 @@ const sortedMirrorMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(m
|
|||||||
const selectedGitMirror = ref('ghproxy_edgeone')
|
const selectedGitMirror = ref('ghproxy_edgeone')
|
||||||
const testingGitSpeed = ref(false)
|
const testingGitSpeed = ref(false)
|
||||||
|
|
||||||
|
// 自定义镜像源相关
|
||||||
|
const customMirrorUrl = ref('')
|
||||||
|
const customMirrors = ref<MirrorConfig[]>([])
|
||||||
|
const addingCustomMirror = ref(false)
|
||||||
|
|
||||||
// 加载配置中的镜像源选择
|
// 加载配置中的镜像源选择
|
||||||
async function loadMirrorConfig() {
|
async function loadMirrorConfig() {
|
||||||
try {
|
try {
|
||||||
const config = await getConfig()
|
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('Git镜像源配置已加载:', selectedGitMirror.value)
|
||||||
|
console.log('自定义镜像源已加载:', customMirrors.value.length, '个')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('加载Git镜像源配置失败:', error)
|
console.warn('加载Git镜像源配置失败:', error)
|
||||||
}
|
}
|
||||||
@@ -119,8 +194,12 @@ async function loadMirrorConfig() {
|
|||||||
// 保存镜像源选择
|
// 保存镜像源选择
|
||||||
async function saveMirrorConfig() {
|
async function saveMirrorConfig() {
|
||||||
try {
|
try {
|
||||||
await saveConfig({ selectedGitMirror: selectedGitMirror.value })
|
await saveConfig({
|
||||||
|
selectedGitMirror: selectedGitMirror.value,
|
||||||
|
customGitMirrors: customMirrors.value
|
||||||
|
})
|
||||||
console.log('Git镜像源配置已保存:', selectedGitMirror.value)
|
console.log('Git镜像源配置已保存:', selectedGitMirror.value)
|
||||||
|
console.log('自定义镜像源已保存:', customMirrors.value.length, '个')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('保存Git镜像源配置失败:', error)
|
console.warn('保存Git镜像源配置失败:', error)
|
||||||
}
|
}
|
||||||
@@ -176,6 +255,135 @@ function getSpeedClass(speed: number | null) {
|
|||||||
return 'speed-slow'
|
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({
|
defineExpose({
|
||||||
selectedGitMirror,
|
selectedGitMirror,
|
||||||
testGitMirrorSpeed,
|
testGitMirrorSpeed,
|
||||||
@@ -334,4 +542,34 @@ onMounted(async () => {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--ant-color-text-tertiary);
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user