feat(initialization): 优化镜像源选择界面和逻辑,修改后端端口为36163

- 将镜像源按类型分组展示,增加官方源和推荐标签
- 实现按速度和推荐程度排序镜像源的功能
- 添加镜像源描述信息,提高用户体验
- 优化后端服务和 WebSocket 连接端口
This commit is contained in:
2025-08-29 01:25:14 +08:00
parent 9f6c86dbbc
commit 96ef72d300
7 changed files with 538 additions and 134 deletions

View File

@@ -4,24 +4,66 @@
<div class="install-section">
<p>{{ backendExists ? '更新最新的后端代码' : '获取后端源代码' }}</p>
<div class="mirror-grid">
<div
v-for="mirror in gitMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedGitMirror === mirror.key }"
@click="selectedGitMirror = mirror.key"
>
<div class="mirror-header">
<h4>{{ mirror.name }}</h4>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<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 class="mirror-section">
<div class="section-header">
<h4>镜像源</h4>
<a-tag color="green">推荐使用</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedMirrorMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedGitMirror === mirror.key }"
@click="selectedGitMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
<a-tag v-if="mirror.recommended" color="gold" size="small">推荐</a-tag>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<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>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
</div>
<!-- 官方源 -->
<div class="mirror-section">
<div class="section-header">
<h4>官方源</h4>
<a-tag color="orange">中国大陆连通性不佳</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedOfficialMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedGitMirror === mirror.key }"
@click="selectedGitMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<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>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
@@ -36,25 +78,31 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, computed } from 'vue'
import { getConfig, saveConfig } from '@/utils/config'
interface Mirror {
key: string
name: string
url: string
speed: number | null
}
import {
GIT_MIRRORS,
getOfficialMirrors,
getMirrorMirrors,
sortMirrorsBySpeedAndRecommendation,
type MirrorConfig
} from '@/config/mirrors'
defineProps<{
backendExists: boolean
}>()
import { GIT_MIRRORS } from '@/config/mirrors'
const gitMirrors = ref<MirrorConfig[]>(GIT_MIRRORS)
const gitMirrors = ref<Mirror[]>(GIT_MIRRORS)
// 按类型分组的镜像源
const officialMirrors = computed(() => getOfficialMirrors('git'))
const mirrorMirrors = computed(() => getMirrorMirrors('git'))
const selectedGitMirror = ref('github')
// 按速度和推荐排序的镜像源
const sortedOfficialMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(officialMirrors.value))
const sortedMirrorMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(mirrorMirrors.value))
const selectedGitMirror = ref('ghproxy_edgeone')
const testingGitSpeed = ref(false)
// 加载配置中的镜像源选择
@@ -107,9 +155,10 @@ async function testGitMirrorSpeed() {
})
await Promise.all(promises)
gitMirrors.value.sort((a, b) => (a.speed || 9999) - (b.speed || 9999))
const fastest = gitMirrors.value.find(m => m.speed !== 9999)
// 优先选择推荐的且速度最快的镜像源
const sortedMirrors = sortMirrorsBySpeedAndRecommendation(gitMirrors.value)
const fastest = sortedMirrors.find(m => m.speed !== 9999)
if (fastest) {
selectedGitMirror.value = fastest.key
await saveMirrorConfig() // 保存最快的镜像源选择
@@ -204,6 +253,12 @@ onMounted(async () => {
margin-bottom: 8px;
}
.mirror-title {
display: flex;
align-items: center;
gap: 8px;
}
.mirror-header h4 {
margin: 0;
font-size: 16px;
@@ -211,6 +266,8 @@ onMounted(async () => {
color: var(--ant-color-text);
}
.speed-badge {
padding: 4px 8px;
border-radius: 4px;
@@ -238,12 +295,37 @@ onMounted(async () => {
color: var(--ant-color-error);
}
.mirror-description {
font-size: 13px;
color: var(--ant-color-text-secondary);
margin-bottom: 4px;
line-height: 1.4;
}
.mirror-url {
font-size: 12px;
color: var(--ant-color-text-tertiary);
word-break: break-all;
}
.mirror-section {
margin-bottom: 24px;
}
.section-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
}
.section-header h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--ant-color-text);
}
.test-actions {
display: flex;
align-items: center;

View File

@@ -4,24 +4,66 @@
<div class="install-section">
<p>通过 pip 安装项目所需的 Python 依赖包</p>
<div class="mirror-grid">
<div
v-for="mirror in pipMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPipMirror === mirror.key }"
@click="selectedPipMirror = mirror.key"
>
<div class="mirror-header">
<h4>{{ mirror.name }}</h4>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingPipSpeed">未测试</span>
<span v-else-if="testingPipSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
<!-- 镜像源 -->
<div class="mirror-section">
<div class="section-header">
<h4>镜像源</h4>
<a-tag color="green">推荐使用</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedMirrorMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPipMirror === mirror.key }"
@click="selectedPipMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
<a-tag v-if="mirror.recommended" color="gold" size="small">推荐</a-tag>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingPipSpeed">未测试</span>
<span v-else-if="testingPipSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
</div>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
</div>
<!-- 官方源 -->
<div class="mirror-section">
<div class="section-header">
<h4>官方源</h4>
<a-tag color="orange">中国大陆连通性不佳</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedOfficialMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPipMirror === mirror.key }"
@click="selectedPipMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingPipSpeed">未测试</span>
<span v-else-if="testingPipSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
</div>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
@@ -36,21 +78,27 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, computed } from 'vue'
import { getConfig, saveConfig } from '@/utils/config'
import {
PIP_MIRRORS,
getOfficialMirrors,
getMirrorMirrors,
sortMirrorsBySpeedAndRecommendation,
type MirrorConfig
} from '@/config/mirrors'
interface Mirror {
key: string
name: string
url: string
speed: number | null
}
const pipMirrors = ref<MirrorConfig[]>(PIP_MIRRORS)
import { PIP_MIRRORS } from '@/config/mirrors'
// 按类型分组的镜像源
const officialMirrors = computed(() => getOfficialMirrors('pip'))
const mirrorMirrors = computed(() => getMirrorMirrors('pip'))
const pipMirrors = ref<Mirror[]>(PIP_MIRRORS)
// 按速度和推荐排序的镜像源
const sortedOfficialMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(officialMirrors.value))
const sortedMirrorMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(mirrorMirrors.value))
const selectedPipMirror = ref('tsinghua')
const selectedPipMirror = ref('aliyun')
const testingPipSpeed = ref(false)
// 加载配置中的镜像源选择
@@ -103,9 +151,10 @@ async function testPipMirrorSpeed() {
})
await Promise.all(promises)
pipMirrors.value.sort((a, b) => (a.speed || 9999) - (b.speed || 9999))
const fastest = pipMirrors.value.find(m => m.speed !== 9999)
// 优先选择推荐的且速度最快的镜像源
const sortedMirrors = sortMirrorsBySpeedAndRecommendation(pipMirrors.value)
const fastest = sortedMirrors.find(m => m.speed !== 9999)
if (fastest) {
selectedPipMirror.value = fastest.key
await saveMirrorConfig() // 保存最快的镜像源选择
@@ -199,6 +248,12 @@ onMounted(async () => {
margin-bottom: 8px;
}
.mirror-title {
display: flex;
align-items: center;
gap: 8px;
}
.mirror-header h4 {
margin: 0;
font-size: 16px;
@@ -206,6 +261,8 @@ onMounted(async () => {
color: var(--ant-color-text);
}
.speed-badge {
padding: 4px 8px;
border-radius: 4px;
@@ -233,12 +290,37 @@ onMounted(async () => {
color: var(--ant-color-error);
}
.mirror-description {
font-size: 13px;
color: var(--ant-color-text-secondary);
margin-bottom: 4px;
line-height: 1.4;
}
.mirror-url {
font-size: 12px;
color: var(--ant-color-text-tertiary);
word-break: break-all;
}
.mirror-section {
margin-bottom: 24px;
}
.section-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
}
.section-header h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--ant-color-text);
}
.test-actions {
display: flex;
align-items: center;

View File

@@ -4,24 +4,66 @@
<div v-if="!pythonInstalled" class="install-section">
<p>需要安装 Python 3.13.0 运行环境64位嵌入式版本</p>
<div class="mirror-grid">
<div
v-for="mirror in pythonMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPythonMirror === mirror.key }"
@click="selectedPythonMirror = mirror.key"
>
<div class="mirror-header">
<h4>{{ mirror.name }}</h4>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingSpeed">未测试</span>
<span v-else-if="testingSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
<!-- 镜像源 -->
<div class="mirror-section">
<div class="section-header">
<h4>镜像源</h4>
<a-tag color="green">推荐使用</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedMirrorMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPythonMirror === mirror.key }"
@click="selectedPythonMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
<a-tag v-if="mirror.recommended" color="gold" size="small">推荐</a-tag>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingSpeed">未测试</span>
<span v-else-if="testingSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
</div>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
</div>
<!-- 官方源 -->
<div class="mirror-section">
<div class="section-header">
<h4>官方源</h4>
<a-tag color="orange">中国大陆连通性不佳</a-tag>
</div>
<div class="mirror-grid">
<div
v-for="mirror in sortedOfficialMirrors"
:key="mirror.key"
class="mirror-card"
:class="{ active: selectedPythonMirror === mirror.key }"
@click="selectedPythonMirror = mirror.key"
>
<div class="mirror-header">
<div class="mirror-title">
<h4>{{ mirror.name }}</h4>
</div>
<div class="speed-badge" :class="getSpeedClass(mirror.speed)">
<span v-if="mirror.speed === null && !testingSpeed">未测试</span>
<span v-else-if="testingSpeed">测试中...</span>
<span v-else-if="mirror.speed === 9999">超时</span>
<span v-else>{{ mirror.speed }}ms</span>
</div>
</div>
<div class="mirror-description">{{ mirror.description }}</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
<div class="mirror-url">{{ mirror.url }}</div>
</div>
</div>
@@ -45,25 +87,31 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, computed } from 'vue'
import { getConfig, saveConfig } from '@/utils/config'
interface Mirror {
key: string
name: string
url: string
speed: number | null
}
import {
PYTHON_MIRRORS,
getOfficialMirrors,
getMirrorMirrors,
sortMirrorsBySpeedAndRecommendation,
type MirrorConfig
} from '@/config/mirrors'
const props = defineProps<{
pythonInstalled: boolean
}>()
import { PYTHON_MIRRORS } from '@/config/mirrors'
const pythonMirrors = ref<MirrorConfig[]>(PYTHON_MIRRORS)
const pythonMirrors = ref<Mirror[]>(PYTHON_MIRRORS)
// 按类型分组的镜像源
const officialMirrors = computed(() => getOfficialMirrors('python'))
const mirrorMirrors = computed(() => getMirrorMirrors('python'))
const selectedPythonMirror = ref('tsinghua')
// 按速度和推荐排序的镜像源
const sortedOfficialMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(officialMirrors.value))
const sortedMirrorMirrors = computed(() => sortMirrorsBySpeedAndRecommendation(mirrorMirrors.value))
const selectedPythonMirror = ref('aliyun')
const testingSpeed = ref(false)
const reinstalling = ref(false)
@@ -118,9 +166,9 @@ async function testPythonMirrorSpeed() {
await Promise.all(promises)
pythonMirrors.value.sort((a, b) => (a.speed || 9999) - (b.speed || 9999))
const fastest = pythonMirrors.value.find(m => m.speed !== 9999)
// 优先选择推荐的且速度最快的镜像源
const sortedMirrors = sortMirrorsBySpeedAndRecommendation(pythonMirrors.value)
const fastest = sortedMirrors.find(m => m.speed !== 9999)
if (fastest) {
selectedPythonMirror.value = fastest.key
await saveMirrorConfig() // 保存最快的镜像源选择
@@ -245,6 +293,12 @@ onMounted(async () => {
margin-bottom: 8px;
}
.mirror-title {
display: flex;
align-items: center;
gap: 8px;
}
.mirror-header h4 {
margin: 0;
font-size: 16px;
@@ -252,6 +306,8 @@ onMounted(async () => {
color: var(--ant-color-text);
}
.speed-badge {
padding: 4px 8px;
border-radius: 4px;
@@ -284,12 +340,37 @@ onMounted(async () => {
color: var(--ant-color-error);
}
.mirror-description {
font-size: 13px;
color: var(--ant-color-text-secondary);
margin-bottom: 4px;
line-height: 1.4;
}
.mirror-url {
font-size: 12px;
color: var(--ant-color-text-tertiary);
word-break: break-all;
}
.mirror-section {
margin-bottom: 24px;
}
.section-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
}
.section-header h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--ant-color-text);
}
.test-actions {
display: flex;
align-items: center;