feat: 增加 OpenWrt 系统管理入口

- 通过 ONE_KVM_OPENWRT=1 控制入口显示和跳转;
- 读取 uhttpd 当前监听配置,并跳转到 LuCI 地址。
This commit is contained in:
mofeng-git
2026-10-12 23:02:12 +08:00
parent 92f4203bc2
commit 2ebad622f0
9 changed files with 199 additions and 1 deletions

View File

@@ -138,6 +138,7 @@ export const systemApi = {
request<{
version: string
initialized: boolean
openwrt_system: boolean
platform: PlatformCapabilities
capabilities: {
video: { available: boolean; backend?: string; reason?: string }

View File

@@ -142,6 +142,7 @@ export default {
networkErrorDesc: 'Unable to connect to server. Please check your connection.',
},
nav: {
openwrtSystemManagement: 'OpenWRT System Management',
logout: 'Logout',
},
auth: {

View File

@@ -142,6 +142,7 @@ export default {
networkErrorDesc: '无法连接到服务器,请检查网络连接。',
},
nav: {
openwrtSystemManagement: 'OpenWRT 系统管理',
logout: '退出登录',
},
auth: {

View File

@@ -161,6 +161,7 @@ export interface DeviceInfoEvent {
export const useSystemStore = defineStore('system', () => {
const version = ref<string>('')
const openwrtSystem = ref(false)
const platform = ref<PlatformCapabilities | null>(null)
const capabilities = ref<SystemCapabilities | null>(null)
const diskSpace = ref<DiskSpaceInfo | null>(null)
@@ -183,6 +184,7 @@ export const useSystemStore = defineStore('system', () => {
try {
const info = await systemApi.info()
version.value = info.version
openwrtSystem.value = info.openwrt_system === true
platform.value = info.platform
capabilities.value = info.capabilities
diskSpace.value = info.disk_space ?? null
@@ -442,6 +444,7 @@ export const useSystemStore = defineStore('system', () => {
return {
version,
openwrtSystem,
platform,
capabilities,
diskSpace,

View File

@@ -196,6 +196,7 @@ const SETTINGS_SECTION_ID_SET = new Set<string>(SETTINGS_SECTION_IDS)
const navGroups = computed(() => [
{
id: 'software',
title: t('settings.software'),
items: [
{ id: 'appearance', label: t('settings.appearance'), icon: Sun },
@@ -205,6 +206,7 @@ const navGroups = computed(() => [
]
},
{
id: 'system',
title: t('settings.system'),
items: [
{ id: 'video', label: t('settings.video'), icon: Monitor },
@@ -215,6 +217,7 @@ const navGroups = computed(() => [
]
},
{
id: 'extensions',
title: t('settings.extensions'),
items: [
{ id: 'ext-ttyd', label: t('extensions.ttyd.title'), icon: Terminal },
@@ -2764,7 +2767,7 @@ watch(isWindows, () => {
<h1 class="text-xl font-semibold">{{ t('settings.title') }}</h1>
</SidebarHeader>
<SidebarContent class="px-3 pb-6 md:pb-10">
<SidebarGroup v-for="group in navGroups" :key="group.title" class="px-0 py-1">
<SidebarGroup v-for="group in navGroups" :key="group.id" class="px-0 py-1">
<SidebarGroupLabel class="uppercase">{{ group.title }}</SidebarGroupLabel>
<SidebarMenu>
<SidebarMenuItem v-for="item in group.items" :key="item.id">
@@ -2778,6 +2781,15 @@ watch(isWindows, () => {
<span>{{ item.label }}</span>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem v-if="systemStore.openwrtSystem && group.id === 'extensions'">
<SidebarMenuButton as-child :tooltip="t('nav.openwrtSystemManagement')" class="h-8 px-3 text-foreground">
<a href="/api/system/openwrt" target="_blank" rel="noopener noreferrer" :title="t('nav.openwrtSystemManagement')">
<Server aria-hidden="true" />
<span class="min-w-0 flex-1 truncate">{{ t('nav.openwrtSystemManagement') }}</span>
<ExternalLink class="!size-3.5 shrink-0 text-muted-foreground" aria-hidden="true" />
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroup>
</SidebarContent>