feat(ui): 重构应用布局和添加客户端更新功能
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 41s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m31s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m38s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m27s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 2m0s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m13s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 2m10s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m12s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m51s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m29s
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 41s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m31s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m38s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m27s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 2m0s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m13s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 2m10s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m12s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m51s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m29s
- 将侧边栏菜单改为顶部标签页导航设计 - 添加客户端操作系统和架构信息显示 - 实现客户端自动更新检查和应用功能 - 添加底部页脚显示版本和GitHub链接 - 更新主题颜色为紫色渐变风格 - 优化首页和插件页面的UI布局结构 - 修改路由配置将更新页面重命名为设置页面 - 在认证协议中添加客户端平台信息字段 - 重构App.vue中的导航和状态管理逻辑
This commit is contained in:
@@ -10,12 +10,13 @@ import {
|
||||
import {
|
||||
ArrowBackOutline, CreateOutline, TrashOutline,
|
||||
PushOutline, AddOutline, StorefrontOutline, DocumentTextOutline,
|
||||
ExtensionPuzzleOutline, SettingsOutline, OpenOutline
|
||||
ExtensionPuzzleOutline, SettingsOutline, OpenOutline, CloudDownloadOutline, RefreshOutline
|
||||
} from '@vicons/ionicons5'
|
||||
import {
|
||||
getClient, updateClient, deleteClient, pushConfigToClient, disconnectClient, restartClient,
|
||||
getClientPluginConfig, updateClientPluginConfig,
|
||||
getStorePlugins, installStorePlugin, getRuleSchemas, startClientPlugin, restartClientPlugin, stopClientPlugin, deleteClientPlugin
|
||||
getStorePlugins, installStorePlugin, getRuleSchemas, startClientPlugin, restartClientPlugin, stopClientPlugin, deleteClientPlugin,
|
||||
checkClientUpdate, applyClientUpdate, type UpdateInfo
|
||||
} from '../api'
|
||||
import type { ProxyRule, ClientPlugin, ConfigField, StorePluginInfo, RuleSchemasMap } from '../types'
|
||||
import LogViewer from '../components/LogViewer.vue'
|
||||
@@ -34,6 +35,13 @@ const nickname = ref('')
|
||||
const rules = ref<ProxyRule[]>([])
|
||||
const clientPlugins = ref<ClientPlugin[]>([])
|
||||
const loading = ref(false)
|
||||
const clientOs = ref('')
|
||||
const clientArch = ref('')
|
||||
|
||||
// 客户端更新相关
|
||||
const clientUpdate = ref<UpdateInfo | null>(null)
|
||||
const checkingUpdate = ref(false)
|
||||
const updatingClient = ref(false)
|
||||
|
||||
// Rule Schemas
|
||||
const pluginRuleSchemas = ref<RuleSchemasMap>({})
|
||||
@@ -125,6 +133,8 @@ const loadClient = async () => {
|
||||
nickname.value = data.nickname || ''
|
||||
rules.value = data.rules || []
|
||||
clientPlugins.value = data.plugins || []
|
||||
clientOs.value = data.os || ''
|
||||
clientArch.value = data.arch || ''
|
||||
} catch (e) {
|
||||
message.error('加载客户端信息失败')
|
||||
console.error(e)
|
||||
@@ -133,6 +143,57 @@ const loadClient = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 客户端更新
|
||||
const handleCheckClientUpdate = async () => {
|
||||
if (!online.value) {
|
||||
message.warning('客户端离线,无法检查更新')
|
||||
return
|
||||
}
|
||||
if (!clientOs.value || !clientArch.value) {
|
||||
message.warning('无法获取客户端平台信息')
|
||||
return
|
||||
}
|
||||
checkingUpdate.value = true
|
||||
try {
|
||||
const { data } = await checkClientUpdate(clientOs.value, clientArch.value)
|
||||
clientUpdate.value = data
|
||||
if (data.download_url) {
|
||||
message.success('找到客户端更新: ' + data.latest)
|
||||
} else {
|
||||
message.info('已是最新版本或未找到对应平台的更新包')
|
||||
}
|
||||
} catch (e: any) {
|
||||
message.error(e.response?.data || '检查更新失败')
|
||||
} finally {
|
||||
checkingUpdate.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleApplyClientUpdate = () => {
|
||||
if (!clientUpdate.value?.download_url) {
|
||||
message.error('没有可用的下载链接')
|
||||
return
|
||||
}
|
||||
dialog.warning({
|
||||
title: '确认更新客户端',
|
||||
content: `即将更新客户端到 ${clientUpdate.value.latest},更新后客户端将自动重启。确定要继续吗?`,
|
||||
positiveText: '更新',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
updatingClient.value = true
|
||||
try {
|
||||
await applyClientUpdate(clientId, clientUpdate.value!.download_url)
|
||||
message.success('更新命令已发送,客户端将自动重启')
|
||||
clientUpdate.value = null
|
||||
} catch (e: any) {
|
||||
message.error(e.response?.data || '更新失败')
|
||||
} finally {
|
||||
updatingClient.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Client Rename
|
||||
const showRenameModal = ref(false)
|
||||
const renameValue = ref('')
|
||||
@@ -479,6 +540,32 @@ const handleDeletePlugin = (plugin: ClientPlugin) => {
|
||||
<n-statistic label="插件数" :value="clientPlugins.length" />
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<!-- 客户端更新 -->
|
||||
<n-card title="客户端更新" bordered size="small">
|
||||
<template #header-extra>
|
||||
<n-button size="tiny" :loading="checkingUpdate" @click="handleCheckClientUpdate" :disabled="!online">
|
||||
<template #icon><n-icon><RefreshOutline /></n-icon></template>
|
||||
检查
|
||||
</n-button>
|
||||
</template>
|
||||
<div v-if="clientOs && clientArch" style="margin-bottom: 8px; font-size: 12px; color: #666;">
|
||||
平台: {{ clientOs }}/{{ clientArch }}
|
||||
</div>
|
||||
<n-empty v-if="!clientUpdate" description="点击检查更新" size="small" />
|
||||
<template v-else>
|
||||
<div v-if="clientUpdate.download_url" style="font-size: 13px;">
|
||||
<p style="margin: 0 0 8px 0; color: #10b981;">发现新版本 {{ clientUpdate.latest }}</p>
|
||||
<n-button size="small" type="primary" :loading="updatingClient" @click="handleApplyClientUpdate">
|
||||
<template #icon><n-icon><CloudDownloadOutline /></n-icon></template>
|
||||
更新
|
||||
</n-button>
|
||||
</div>
|
||||
<div v-else style="font-size: 13px; color: #666;">
|
||||
已是最新版本
|
||||
</div>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-grid-item>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user