refactor: 前端界面微调

This commit is contained in:
mofeng-git
2026-06-15 23:36:17 +08:00
parent e2c19d550c
commit f1e362a820
14 changed files with 141 additions and 95 deletions

View File

@@ -11,6 +11,7 @@ import { useHidWebSocket } from '@/composables/useHidWebSocket'
import { useWebRTC } from '@/composables/useWebRTC'
import { useVideoSession } from '@/composables/useVideoSession'
import { useComputerUseSocket, type ComputerUseServerMessage } from '@/composables/useComputerUseSocket'
import { useFeatureVisibility } from '@/composables/useFeatureVisibility'
import { getUnifiedAudio } from '@/composables/useUnifiedAudio'
import { streamApi, hidApi, atxApi, atxConfigApi, authApi, computerUseApi } from '@/api'
import type { ComputerUseScreenshot, ComputerUseSession } from '@/api'
@@ -185,7 +186,10 @@ const changingPassword = ref(false)
const ttydStatus = ref<{ available: boolean; running: boolean } | null>(null)
const showTerminalDialog = ref(false)
const showTerminal = computed(() => ttydStatus.value?.available !== false)
const featureVisibility = useFeatureVisibility()
const terminalAvailable = computed(() => ttydStatus.value?.available !== false)
const showTerminal = computed(() => terminalAvailable.value && featureVisibility.value.webTerminal)
const showComputerUse = computed(() => featureVisibility.value.computerUse)
const isDark = ref(document.documentElement.classList.contains('dark'))
@@ -772,6 +776,7 @@ function clearComputerUseTimeline() {
}
async function openComputerUse() {
if (!showComputerUse.value) return
computerUseOpen.value = true
await computerUseSocket.connect().catch(() => {})
computerUseSession.value = await computerUseApi.session().catch(() => computerUseSession.value)
@@ -1818,6 +1823,14 @@ watch(() => webrtc.videoTrack.value, async (track) => {
}
})
watch(showTerminal, (visible) => {
if (!visible) showTerminalDialog.value = false
})
watch(showComputerUse, (visible) => {
if (!visible) computerUseOpen.value = false
})
watch(() => webrtc.audioTrack.value, async (track) => {
videoDebugLog('WebRTC audio track ref changed', {
hasTrack: Boolean(track),
@@ -2820,6 +2833,7 @@ onUnmounted(() => {
:video-mode="videoMode"
:ttyd-running="ttydStatus?.running"
:show-terminal="showTerminal"
:show-computer-use="showComputerUse"
@toggle-fullscreen="toggleFullscreen"
@toggle-stats="statsSheetOpen = true"
@toggle-virtual-keyboard="handleToggleVirtualKeyboard"
@@ -3037,6 +3051,7 @@ onUnmounted(() => {
</div>
</div>
<ComputerUseSheet
v-if="showComputerUse"
v-model:open="computerUseOpen"
:connected="computerUseSocket.connected.value"
:ws-error="computerUseSocket.error.value"
@@ -3120,6 +3135,7 @@ onUnmounted(() => {
id="currentPassword"
v-model="currentPassword"
type="password"
autocomplete="current-password"
:placeholder="t('auth.currentPasswordPlaceholder')"
/>
</div>
@@ -3129,6 +3145,7 @@ onUnmounted(() => {
id="newPassword"
v-model="newPassword"
type="password"
autocomplete="new-password"
:placeholder="t('auth.newPasswordPlaceholder')"
/>
</div>
@@ -3138,6 +3155,7 @@ onUnmounted(() => {
id="confirmPassword"
v-model="confirmPassword"
type="password"
autocomplete="new-password"
:placeholder="t('auth.confirmPasswordPlaceholder')"
/>
</div>

View File

@@ -82,6 +82,7 @@ async function handleLogin() {
id="username"
v-model="username"
type="text"
autocomplete="username"
:placeholder="t('auth.username')"
class="pl-10"
/>
@@ -96,6 +97,7 @@ async function handleLogin() {
id="password"
v-model="password"
:type="showPassword ? 'text' : 'password'"
autocomplete="current-password"
:placeholder="t('auth.password')"
class="pl-10 pr-10"
/>

View File

@@ -51,6 +51,7 @@ import type {
import { FrpProxyType, FrpcConfigMode } from '@/types/generated'
import { formatFpsLabel, toConfigFps } from '@/lib/fps'
import { useClipboard } from '@/composables/useClipboard'
import { useFeatureVisibility } from '@/composables/useFeatureVisibility'
import { getVideoFormatState } from '@/lib/video-format-support'
import { formatVideoDeviceLabel } from '@/lib/video-device-label'
import AppLayout from '@/components/AppLayout.vue'
@@ -111,6 +112,7 @@ import {
Globe,
Loader2,
AlertTriangle,
Bot,
} from 'lucide-vue-next'
const { t, te } = useI18n()
@@ -119,6 +121,7 @@ const router = useRouter()
const systemStore = useSystemStore()
const configStore = useConfigStore()
const authStore = useAuthStore()
const featureVisibility = useFeatureVisibility()
const isWindows = computed(() => systemStore.platform?.mode === 'windows')
const isAndroid = computed(() => systemStore.platform?.mode === 'android_amlogic')
@@ -2762,6 +2765,29 @@ watch(isWindows, () => {
<LanguageToggleButton variant="outline" size="sm" label-mode="current" />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>{{ t('settings.featureVisibility') }}</CardTitle>
<CardDescription>{{ t('settings.featureVisibilityDesc') }}</CardDescription>
</CardHeader>
<CardContent class="space-y-1">
<div class="flex items-center justify-between gap-4 px-3 py-3">
<Label for="feature-web-terminal" class="flex min-w-0 items-center gap-2 font-normal">
<Terminal class="h-4 w-4 shrink-0 text-muted-foreground" />
<span class="truncate">{{ t('actionbar.webTerminal') }}</span>
</Label>
<Switch id="feature-web-terminal" v-model="featureVisibility.webTerminal" />
</div>
<div class="flex items-center justify-between gap-4 px-3 py-3">
<Label for="feature-computer-use" class="flex min-w-0 items-center gap-2 font-normal">
<Bot class="h-4 w-4 shrink-0 text-muted-foreground" />
<span class="truncate">{{ t('settings.computerUseAgent') }}</span>
</Label>
<Switch id="feature-computer-use" v-model="featureVisibility.computerUse" />
</div>
</CardContent>
</Card>
</div>
<!-- Account Section -->
@@ -2968,6 +2994,7 @@ watch(isWindows, () => {
id="turn-password"
v-model="config.turn_password"
:type="showPasswords ? 'text' : 'password'"
autocomplete="off"
:disabled="!config.stun_server && !config.turn_server"
/>
<button
@@ -4320,7 +4347,7 @@ watch(isWindows, () => {
<div class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.gostc.key') }}</Label>
<div class="sm:col-span-3 space-y-1">
<Input v-model="extConfig.gostc.key" type="password" :disabled="isExtRunning(extensions?.gostc?.status)" />
<Input v-model="extConfig.gostc.key" type="password" autocomplete="off" :disabled="isExtRunning(extensions?.gostc?.status)" />
<p v-if="extConfig.gostc.enabled && !extConfig.gostc.key" class="text-xs text-destructive">{{ t('extensions.gostc.keyRequired') }}</p>
</div>
</div>
@@ -4416,7 +4443,7 @@ watch(isWindows, () => {
</div>
<div class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.easytier.networkSecret') }}</Label>
<Input v-model="extConfig.easytier.network_secret" type="password" class="sm:col-span-3" :disabled="isExtRunning(extensions?.easytier?.status)" />
<Input v-model="extConfig.easytier.network_secret" type="password" autocomplete="off" class="sm:col-span-3" :disabled="isExtRunning(extensions?.easytier?.status)" />
</div>
<div class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.easytier.peers') }}</Label>
@@ -4572,7 +4599,7 @@ watch(isWindows, () => {
<div class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.frpc.token') }}</Label>
<div class="sm:col-span-3 space-y-1">
<Input v-model="extConfig.frpc.token" type="password" :disabled="isExtRunning(extensions?.frpc?.status)" />
<Input v-model="extConfig.frpc.token" type="password" autocomplete="off" :disabled="isExtRunning(extensions?.frpc?.status)" />
<p v-if="extConfig.frpc.enabled && !extConfig.frpc.token" class="text-xs text-destructive">{{ t('extensions.frpc.tokenRequired') }}</p>
</div>
</div>
@@ -4600,7 +4627,7 @@ watch(isWindows, () => {
</div>
<div v-if="showFrpcSecretKey" class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.frpc.secretKey') }}</Label>
<Input v-model="extConfig.frpc.secret_key" class="sm:col-span-3" type="password" :disabled="isExtRunning(extensions?.frpc?.status)" />
<Input v-model="extConfig.frpc.secret_key" class="sm:col-span-3" type="password" autocomplete="off" :disabled="isExtRunning(extensions?.frpc?.status)" />
</div>
<div class="grid gap-2 sm:grid-cols-4 sm:items-center">
<Label class="sm:text-right">{{ t('extensions.frpc.tls') }}</Label>

View File

@@ -646,6 +646,7 @@ const stepIcons = [User, Video, Keyboard, Puzzle]
id="username"
v-model="username"
type="text"
autocomplete="username"
:placeholder="t('setup.usernameHint')"
class="pl-10"
:class="{ 'border-destructive focus-visible:ring-destructive': usernameError }"
@@ -665,6 +666,7 @@ const stepIcons = [User, Video, Keyboard, Puzzle]
id="password"
v-model="password"
:type="showPassword ? 'text' : 'password'"
autocomplete="new-password"
:placeholder="t('setup.passwordHint')"
class="pr-10"
:class="{ 'border-destructive focus-visible:ring-destructive': passwordError }"
@@ -707,6 +709,7 @@ const stepIcons = [User, Video, Keyboard, Puzzle]
id="confirmPassword"
v-model="confirmPassword"
:type="showPassword ? 'text' : 'password'"
autocomplete="new-password"
:placeholder="t('setup.confirmPassword')"
:class="{ 'border-destructive focus-visible:ring-destructive': confirmPasswordError }"
@blur="validateConfirmPassword"