fix: 初步修复移动端 UI 错乱

This commit is contained in:
mofeng
2026-01-29 22:43:47 +08:00
parent d9daeb211a
commit 1a0b285fe6
6 changed files with 443 additions and 169 deletions

View File

@@ -1881,104 +1881,161 @@ onUnmounted(() => {
<template>
<div class="h-screen flex flex-col bg-background">
<!-- Header -->
<header class="h-14 shrink-0 border-b border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900">
<div class="h-full px-4 flex items-center justify-between">
<!-- Left: Logo -->
<div class="flex items-center gap-6">
<header class="shrink-0 border-b border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900">
<div class="px-4">
<div class="h-14 flex items-center justify-between">
<!-- Left: Logo -->
<div class="flex items-center gap-6">
<div class="flex items-center gap-2">
<Monitor class="h-6 w-6 text-primary" />
<span class="font-bold text-lg">One-KVM</span>
</div>
</div>
<!-- Right: Status Cards + User Menu -->
<div class="flex items-center gap-2">
<Monitor class="h-6 w-6 text-primary" />
<span class="font-bold text-lg">One-KVM</span>
<div class="hidden md:flex items-center gap-2">
<!-- Video Status -->
<StatusCard
:title="t('statusCard.video')"
type="video"
:status="videoStatus"
:quick-info="videoQuickInfo"
:error-message="videoErrorMessage"
:details="videoDetails"
/>
<!-- Audio Status -->
<StatusCard
v-if="systemStore.audio?.available"
:title="t('statusCard.audio')"
type="audio"
:status="audioStatus"
:quick-info="audioQuickInfo"
:error-message="audioErrorMessage"
:details="audioDetails"
/>
<!-- HID Status -->
<StatusCard
:title="t('statusCard.hid')"
type="hid"
:status="hidStatus"
:quick-info="hidQuickInfo"
:details="hidDetails"
/>
<!-- MSD Status - Hidden when CH9329 backend (no USB gadget support) -->
<StatusCard
v-if="systemStore.msd?.available && systemStore.hid?.backend !== 'ch9329'"
:title="t('statusCard.msd')"
type="msd"
:status="msdStatus"
:quick-info="msdQuickInfo"
:error-message="msdErrorMessage"
:details="msdDetails"
hover-align="end"
/>
</div>
<!-- Separator -->
<div class="h-6 w-px bg-slate-200 dark:bg-slate-700 hidden md:block mx-1" />
<!-- Theme Toggle -->
<Button variant="ghost" size="icon" class="h-8 w-8 hidden md:flex" @click="toggleTheme">
<Sun v-if="isDark" class="h-4 w-4" />
<Moon v-else class="h-4 w-4" />
</Button>
<!-- Language Toggle -->
<Button variant="ghost" size="icon" class="h-8 w-8 hidden md:flex" @click="toggleLanguage">
<Languages class="h-4 w-4" />
</Button>
<!-- User Menu -->
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline" size="sm" class="gap-1.5">
<span class="text-xs max-w-[100px] truncate">{{ authStore.user || 'admin' }}</span>
<ChevronDown class="h-3.5 w-3.5" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem class="md:hidden" @click="toggleTheme">
<Sun v-if="isDark" class="h-4 w-4 mr-2" />
<Moon v-else class="h-4 w-4 mr-2" />
{{ isDark ? t('settings.lightMode') : t('settings.darkMode') }}
</DropdownMenuItem>
<DropdownMenuItem class="md:hidden" @click="toggleLanguage">
<Languages class="h-4 w-4 mr-2" />
{{ locale === 'zh-CN' ? 'English' : '中文' }}
</DropdownMenuItem>
<DropdownMenuSeparator class="md:hidden" />
<DropdownMenuItem @click="changePasswordDialogOpen = true">
<KeyRound class="h-4 w-4 mr-2" />
{{ t('auth.changePassword') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem @click="logout">
<LogOut class="h-4 w-4 mr-2" />
{{ t('auth.logout') }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
<!-- Right: Status Cards + User Menu -->
<div class="flex items-center gap-2">
<!-- Video Status -->
<StatusCard
:title="t('statusCard.video')"
type="video"
:status="videoStatus"
:quick-info="videoQuickInfo"
:error-message="videoErrorMessage"
:details="videoDetails"
/>
<!-- Mobile Status Row -->
<div class="md:hidden pb-2">
<div class="flex items-center gap-2 overflow-x-auto">
<div class="shrink-0">
<StatusCard
:title="t('statusCard.video')"
type="video"
:status="videoStatus"
:quick-info="videoQuickInfo"
:error-message="videoErrorMessage"
:details="videoDetails"
compact
/>
</div>
<!-- Audio Status -->
<StatusCard
v-if="systemStore.audio?.available"
:title="t('statusCard.audio')"
type="audio"
:status="audioStatus"
:quick-info="audioQuickInfo"
:error-message="audioErrorMessage"
:details="audioDetails"
/>
<div v-if="systemStore.audio?.available" class="shrink-0">
<StatusCard
:title="t('statusCard.audio')"
type="audio"
:status="audioStatus"
:quick-info="audioQuickInfo"
:error-message="audioErrorMessage"
:details="audioDetails"
compact
/>
</div>
<!-- HID Status -->
<StatusCard
:title="t('statusCard.hid')"
type="hid"
:status="hidStatus"
:quick-info="hidQuickInfo"
:details="hidDetails"
/>
<div class="shrink-0">
<StatusCard
:title="t('statusCard.hid')"
type="hid"
:status="hidStatus"
:quick-info="hidQuickInfo"
:details="hidDetails"
compact
/>
</div>
<!-- MSD Status - Hidden when CH9329 backend (no USB gadget support) -->
<StatusCard
v-if="systemStore.msd?.available && systemStore.hid?.backend !== 'ch9329'"
:title="t('statusCard.msd')"
type="msd"
:status="msdStatus"
:quick-info="msdQuickInfo"
:error-message="msdErrorMessage"
:details="msdDetails"
hover-align="end"
/>
<!-- Separator -->
<div class="h-6 w-px bg-slate-200 dark:bg-slate-700 hidden md:block mx-1" />
<!-- Theme Toggle -->
<Button variant="ghost" size="icon" class="h-8 w-8 hidden md:flex" @click="toggleTheme">
<Sun v-if="isDark" class="h-4 w-4" />
<Moon v-else class="h-4 w-4" />
</Button>
<!-- Language Toggle -->
<Button variant="ghost" size="icon" class="h-8 w-8 hidden md:flex" @click="toggleLanguage">
<Languages class="h-4 w-4" />
</Button>
<!-- User Menu -->
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline" size="sm" class="gap-1.5">
<span class="text-xs max-w-[100px] truncate">{{ authStore.user || 'admin' }}</span>
<ChevronDown class="h-3.5 w-3.5" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem class="md:hidden" @click="toggleTheme">
<Sun v-if="isDark" class="h-4 w-4 mr-2" />
<Moon v-else class="h-4 w-4 mr-2" />
{{ isDark ? t('settings.lightMode') : t('settings.darkMode') }}
</DropdownMenuItem>
<DropdownMenuItem class="md:hidden" @click="toggleLanguage">
<Languages class="h-4 w-4 mr-2" />
{{ locale === 'zh-CN' ? 'English' : '中文' }}
</DropdownMenuItem>
<DropdownMenuSeparator class="md:hidden" />
<DropdownMenuItem @click="changePasswordDialogOpen = true">
<KeyRound class="h-4 w-4 mr-2" />
{{ t('auth.changePassword') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem @click="logout">
<LogOut class="h-4 w-4 mr-2" />
{{ t('auth.logout') }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<div v-if="systemStore.msd?.available && systemStore.hid?.backend !== 'ch9329'" class="shrink-0">
<StatusCard
:title="t('statusCard.msd')"
type="msd"
:status="msdStatus"
:quick-info="msdQuickInfo"
:error-message="msdErrorMessage"
:details="msdDetails"
hover-align="end"
compact
/>
</div>
</div>
</div>
</div>
</header>