refactor(app): 移除 naive-ui 依赖并优化配置结构
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 31s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m30s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m39s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m19s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m43s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m18s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m38s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m50s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 2m6s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m18s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m57s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m25s

- 从 App.vue 中移除 naive-ui 组件及其主题配置
- 从组件声明中移除 NIcon 和 NTag 组件引用
- 将 JSPluginConfig 从 ServerConfig 中分离
- 在 ServerSettings 中整合 PluginStore 配置
- 更新配置 DTO 结构以支持 PluginStore 配置
- 移除 JS 插件加载和签名验证相关代码
- 从 main.ts 中移除 naive-ui 的引入和使用
- 从 package.json 中移除 naive-ui 和相关自动导入插件依赖
- 在设置页面添加插件商店 URL 配置字段
- 更新 StoreHandler 中插件商店 URL 的获取方式
- 移除 Vite 配置中的自动导入和组件解析插件
This commit is contained in:
Flik
2026-01-22 20:37:11 +08:00
parent d1058f9e89
commit 7cddb7b3e7
13 changed files with 352 additions and 958 deletions

View File

@@ -1,10 +1,6 @@
<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue'
import { RouterView, useRouter, useRoute } from 'vue-router'
import {
NConfigProvider, NMessageProvider, NDialogProvider, NGlobalStyle,
type GlobalThemeOverrides
} from 'naive-ui'
import {
HomeOutline, DesktopOutline, SettingsOutline,
PersonCircleOutline, LogOutOutline, LogoGithub, ServerOutline, CheckmarkCircleOutline, ArrowUpCircleOutline
@@ -88,95 +84,72 @@ const logout = () => {
const toggleUserMenu = () => {
showUserMenu.value = !showUserMenu.value
}
// 紫色渐变主题
const themeOverrides: GlobalThemeOverrides = {
common: {
primaryColor: '#6366f1',
primaryColorHover: '#818cf8',
primaryColorPressed: '#4f46e5',
},
Layout: {
headerColor: '#ffffff'
},
Tabs: {
tabTextColorActiveLine: '#6366f1',
barColor: '#6366f1'
}
}
</script>
<template>
<n-config-provider :theme-overrides="themeOverrides">
<n-global-style />
<n-dialog-provider>
<n-message-provider>
<div v-if="!isLoginPage" class="app-layout">
<!-- Header -->
<header class="app-header">
<div class="header-left">
<span class="logo">GoTunnel</span>
</div>
<nav class="header-nav">
<router-link
v-for="item in navItems"
:key="item.key"
:to="item.path"
class="nav-item"
:class="{ active: activeNav === item.key }"
>
<component :is="item.icon" class="nav-icon" />
<span>{{ item.label }}</span>
</router-link>
</nav>
<div class="header-right">
<div class="user-menu" @click="toggleUserMenu">
<PersonCircleOutline class="user-icon" />
<div v-if="showUserMenu" class="user-dropdown" @click.stop>
<button class="dropdown-item" @click="logout">
<LogOutOutline class="dropdown-icon" />
<span>退出登录</span>
</button>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<RouterView />
</main>
<!-- Footer -->
<footer class="app-footer">
<div class="footer-left">
<span class="brand">GoTunnel</span>
<div v-if="version" class="version-info">
<ServerOutline class="version-icon" />
<span class="version">v{{ version }}</span>
<span v-if="updateInfo" class="update-status" :class="{ latest: !updateInfo.available, 'has-update': updateInfo.available }">
<template v-if="updateInfo.available">
<ArrowUpCircleOutline class="status-icon" />
<span>新版本 ({{ updateInfo.latest }})</span>
</template>
<template v-else>
<CheckmarkCircleOutline class="status-icon" />
<span>最新版本</span>
</template>
</span>
</div>
</div>
<a href="https://github.com/user/gotunnel" target="_blank" class="footer-link">
<LogoGithub class="footer-icon" />
<span>GitHub</span>
</a>
<span class="copyright">© 2024 Flik. MIT License</span>
</footer>
<div v-if="!isLoginPage" class="app-layout">
<!-- Header -->
<header class="app-header">
<div class="header-left">
<span class="logo">GoTunnel</span>
</div>
<nav class="header-nav">
<router-link
v-for="item in navItems"
:key="item.key"
:to="item.path"
class="nav-item"
:class="{ active: activeNav === item.key }"
>
<component :is="item.icon" class="nav-icon" />
<span>{{ item.label }}</span>
</router-link>
</nav>
<div class="header-right">
<div class="user-menu" @click="toggleUserMenu">
<PersonCircleOutline class="user-icon" />
<div v-if="showUserMenu" class="user-dropdown" @click.stop>
<button class="dropdown-item" @click="logout">
<LogOutOutline class="dropdown-icon" />
<span>退出登录</span>
</button>
</div>
</div>
<RouterView v-else />
</n-message-provider>
</n-dialog-provider>
</n-config-provider>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<RouterView />
</main>
<!-- Footer -->
<footer class="app-footer">
<div class="footer-left">
<span class="brand">GoTunnel</span>
<div v-if="version" class="version-info">
<ServerOutline class="version-icon" />
<span class="version">v{{ version }}</span>
<span v-if="updateInfo" class="update-status" :class="{ latest: !updateInfo.available, 'has-update': updateInfo.available }">
<template v-if="updateInfo.available">
<ArrowUpCircleOutline class="status-icon" />
<span>新版本 ({{ updateInfo.latest }})</span>
</template>
<template v-else>
<CheckmarkCircleOutline class="status-icon" />
<span>最新版本</span>
</template>
</span>
</div>
</div>
<a href="https://github.com/user/gotunnel" target="_blank" class="footer-link">
<LogoGithub class="footer-icon" />
<span>GitHub</span>
</a>
<span class="copyright">© 2024 Flik. MIT License</span>
</footer>
</div>
<RouterView v-else />
</template>
<style scoped>

View File

@@ -212,14 +212,20 @@ export interface WebConfigInfo {
password: string
}
export interface PluginStoreConfigInfo {
url: string
}
export interface ServerConfigResponse {
server: ServerConfigInfo
web: WebConfigInfo
plugin_store: PluginStoreConfigInfo
}
export interface UpdateServerConfigRequest {
server?: Partial<ServerConfigInfo>
web?: Partial<WebConfigInfo>
plugin_store?: Partial<PluginStoreConfigInfo>
}
export const getServerConfig = () => get<ServerConfigResponse>('/config')

View File

@@ -1,10 +1,8 @@
import { createApp } from 'vue'
import naive from 'naive-ui'
import './style.css'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.use(naive)
app.mount('#app')

View File

@@ -30,7 +30,8 @@ const configForm = ref({
heartbeat_sec: 30,
heartbeat_timeout: 90,
web_username: '',
web_password: ''
web_password: '',
plugin_store_url: ''
})
const loadVersionInfo = async () => {
@@ -55,7 +56,8 @@ const loadServerConfig = async () => {
heartbeat_sec: data.server.heartbeat_sec,
heartbeat_timeout: data.server.heartbeat_timeout,
web_username: data.web.username,
web_password: ''
web_password: '',
plugin_store_url: data.plugin_store.url
}
} catch (e) {
console.error('Failed to load server config', e)
@@ -75,6 +77,9 @@ const handleSaveConfig = async () => {
},
web: {
username: configForm.value.web_username
},
plugin_store: {
url: configForm.value.plugin_store_url
}
}
// 只有填写了密码才更新
@@ -269,6 +274,19 @@ onMounted(() => {
</div>
</div>
<div class="form-divider"></div>
<div class="form-group">
<label class="form-label">插件商店地址</label>
<input
v-model="configForm.plugin_store_url"
type="text"
class="glass-input"
placeholder="https://example.com/plugins"
/>
<span class="form-hint">插件商店的 API 地址</span>
</div>
<div class="form-actions">
<button
class="glass-btn primary"