mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-02-02 02:51:53 +08:00
feat: 引入统一配置 store 并迁移 Console/Settings 配置读写;自动显示当前使用的配置
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
|||||||
} from '@/components/ui/select'
|
} from '@/components/ui/select'
|
||||||
import { Volume2, RefreshCw, Loader2 } from 'lucide-vue-next'
|
import { Volume2, RefreshCw, Loader2 } from 'lucide-vue-next'
|
||||||
import { audioApi, configApi } from '@/api'
|
import { audioApi, configApi } from '@/api'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { useSystemStore } from '@/stores/system'
|
import { useSystemStore } from '@/stores/system'
|
||||||
import { getUnifiedAudio } from '@/composables/useUnifiedAudio'
|
import { getUnifiedAudio } from '@/composables/useUnifiedAudio'
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const configStore = useConfigStore()
|
||||||
const systemStore = useSystemStore()
|
const systemStore = useSystemStore()
|
||||||
const unifiedAudio = getUnifiedAudio()
|
const unifiedAudio = getUnifiedAudio()
|
||||||
|
|
||||||
@@ -87,9 +89,9 @@ async function loadDevices() {
|
|||||||
|
|
||||||
// Initialize from current config
|
// Initialize from current config
|
||||||
function initializeFromCurrent() {
|
function initializeFromCurrent() {
|
||||||
const audio = systemStore.audio
|
const audio = configStore.audio
|
||||||
if (audio) {
|
if (audio) {
|
||||||
audioEnabled.value = audio.available && audio.streaming
|
audioEnabled.value = audio.enabled
|
||||||
selectedDevice.value = audio.device || ''
|
selectedDevice.value = audio.device || ''
|
||||||
selectedQuality.value = (audio.quality as 'voice' | 'balanced' | 'high') || 'balanced'
|
selectedQuality.value = (audio.quality as 'voice' | 'balanced' | 'high') || 'balanced'
|
||||||
}
|
}
|
||||||
@@ -104,12 +106,10 @@ async function applyConfig() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Update config
|
// Update config
|
||||||
await configApi.update({
|
await configStore.updateAudio({
|
||||||
audio: {
|
enabled: audioEnabled.value,
|
||||||
enabled: audioEnabled.value,
|
device: selectedDevice.value,
|
||||||
device: selectedDevice.value,
|
quality: selectedQuality.value,
|
||||||
quality: selectedQuality.value,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// If enabled and device is selected, try to start audio stream
|
// If enabled and device is selected, try to start audio stream
|
||||||
@@ -151,12 +151,19 @@ async function applyConfig() {
|
|||||||
|
|
||||||
// Watch popover open state
|
// Watch popover open state
|
||||||
watch(() => props.open, (isOpen) => {
|
watch(() => props.open, (isOpen) => {
|
||||||
if (isOpen) {
|
if (!isOpen) return
|
||||||
if (devices.value.length === 0) {
|
|
||||||
loadDevices()
|
if (devices.value.length === 0) {
|
||||||
}
|
loadDevices()
|
||||||
initializeFromCurrent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configStore.refreshAudio()
|
||||||
|
.then(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ import {
|
|||||||
import { MousePointer, Move, Loader2, RefreshCw } from 'lucide-vue-next'
|
import { MousePointer, Move, Loader2, RefreshCw } from 'lucide-vue-next'
|
||||||
import HelpTooltip from '@/components/HelpTooltip.vue'
|
import HelpTooltip from '@/components/HelpTooltip.vue'
|
||||||
import { configApi } from '@/api'
|
import { configApi } from '@/api'
|
||||||
import { useSystemStore } from '@/stores/system'
|
import { useConfigStore } from '@/stores/config'
|
||||||
|
import { HidBackend } from '@/types/generated'
|
||||||
|
import type { HidConfigUpdate } from '@/types/generated'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
open: boolean
|
open: boolean
|
||||||
@@ -35,7 +37,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const systemStore = useSystemStore()
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
const DEFAULT_MOUSE_MOVE_SEND_INTERVAL_MS = 16
|
const DEFAULT_MOUSE_MOVE_SEND_INTERVAL_MS = 16
|
||||||
|
|
||||||
@@ -72,7 +74,7 @@ watch(showCursor, (newValue, oldValue) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// HID Device Settings (requires apply)
|
// HID Device Settings (requires apply)
|
||||||
const hidBackend = ref<'otg' | 'ch9329' | 'none'>('none')
|
const hidBackend = ref<HidBackend>(HidBackend.None)
|
||||||
const devicePath = ref<string>('')
|
const devicePath = ref<string>('')
|
||||||
const baudrate = ref<number>(9600)
|
const baudrate = ref<number>(9600)
|
||||||
|
|
||||||
@@ -89,9 +91,9 @@ const buttonText = computed(() => t('actionbar.hidConfig'))
|
|||||||
|
|
||||||
// Available device paths based on backend type
|
// Available device paths based on backend type
|
||||||
const availableDevicePaths = computed(() => {
|
const availableDevicePaths = computed(() => {
|
||||||
if (hidBackend.value === 'ch9329') {
|
if (hidBackend.value === HidBackend.Ch9329) {
|
||||||
return serialDevices.value
|
return serialDevices.value
|
||||||
} else if (hidBackend.value === 'otg') {
|
} else if (hidBackend.value === HidBackend.Otg) {
|
||||||
// For OTG, we show UDC devices
|
// For OTG, we show UDC devices
|
||||||
return udcDevices.value.map(udc => ({
|
return udcDevices.value.map(udc => ({
|
||||||
path: udc.name,
|
path: udc.name,
|
||||||
@@ -124,9 +126,17 @@ function initializeFromCurrent() {
|
|||||||
showCursor.value = storedCursor
|
showCursor.value = storedCursor
|
||||||
|
|
||||||
// Initialize HID device settings from system state
|
// Initialize HID device settings from system state
|
||||||
const hid = systemStore.hid
|
const hid = configStore.hid
|
||||||
if (hid) {
|
if (hid) {
|
||||||
hidBackend.value = (hid.backend as 'otg' | 'ch9329' | 'none') || 'none'
|
hidBackend.value = hid.backend || HidBackend.None
|
||||||
|
if (hidBackend.value === HidBackend.Ch9329) {
|
||||||
|
devicePath.value = hid.ch9329_port || ''
|
||||||
|
baudrate.value = hid.ch9329_baudrate || 9600
|
||||||
|
} else if (hidBackend.value === HidBackend.Otg) {
|
||||||
|
devicePath.value = hid.otg_udc || ''
|
||||||
|
} else {
|
||||||
|
devicePath.value = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +146,8 @@ function toggleMouseMode() {
|
|||||||
emit('update:mouseMode', newMode)
|
emit('update:mouseMode', newMode)
|
||||||
|
|
||||||
// Update backend config
|
// Update backend config
|
||||||
configApi.update({
|
configStore.updateHid({
|
||||||
hid: {
|
mouse_absolute: newMode === 'absolute',
|
||||||
mouse_absolute: newMode === 'absolute',
|
|
||||||
},
|
|
||||||
}).catch(_e => {
|
}).catch(_e => {
|
||||||
console.info('[HidConfig] Failed to update mouse mode')
|
console.info('[HidConfig] Failed to update mouse mode')
|
||||||
toast.error(t('config.updateFailed'))
|
toast.error(t('config.updateFailed'))
|
||||||
@@ -162,7 +170,11 @@ function handleThrottleChange(value: number[] | undefined) {
|
|||||||
// Handle backend change
|
// Handle backend change
|
||||||
function handleBackendChange(backend: unknown) {
|
function handleBackendChange(backend: unknown) {
|
||||||
if (typeof backend !== 'string') return
|
if (typeof backend !== 'string') return
|
||||||
hidBackend.value = backend as 'otg' | 'ch9329' | 'none'
|
if (backend === HidBackend.Otg || backend === HidBackend.Ch9329 || backend === HidBackend.None) {
|
||||||
|
hidBackend.value = backend
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Clear device path when changing backend
|
// Clear device path when changing backend
|
||||||
devicePath.value = ''
|
devicePath.value = ''
|
||||||
@@ -189,18 +201,18 @@ function handleBaudrateChange(rate: unknown) {
|
|||||||
async function applyHidConfig() {
|
async function applyHidConfig() {
|
||||||
applying.value = true
|
applying.value = true
|
||||||
try {
|
try {
|
||||||
const config: Record<string, unknown> = {
|
const config: HidConfigUpdate = {
|
||||||
backend: hidBackend.value,
|
backend: hidBackend.value,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidBackend.value === 'ch9329') {
|
if (hidBackend.value === HidBackend.Ch9329) {
|
||||||
config.ch9329_port = devicePath.value
|
config.ch9329_port = devicePath.value
|
||||||
config.ch9329_baudrate = baudrate.value
|
config.ch9329_baudrate = baudrate.value
|
||||||
} else if (hidBackend.value === 'otg') {
|
} else if (hidBackend.value === HidBackend.Otg) {
|
||||||
config.otg_udc = devicePath.value
|
config.otg_udc = devicePath.value
|
||||||
}
|
}
|
||||||
|
|
||||||
await configApi.update({ hid: config })
|
await configStore.updateHid(config)
|
||||||
|
|
||||||
toast.success(t('config.applied'))
|
toast.success(t('config.applied'))
|
||||||
|
|
||||||
@@ -215,14 +227,20 @@ async function applyHidConfig() {
|
|||||||
|
|
||||||
// Watch open state
|
// Watch open state
|
||||||
watch(() => props.open, (isOpen) => {
|
watch(() => props.open, (isOpen) => {
|
||||||
if (isOpen) {
|
if (!isOpen) return
|
||||||
// Load devices on first open
|
|
||||||
if (serialDevices.value.length === 0) {
|
// Load devices on first open
|
||||||
loadDevices()
|
if (serialDevices.value.length === 0) {
|
||||||
}
|
loadDevices()
|
||||||
// Initialize from current config
|
|
||||||
initializeFromCurrent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configStore.refreshHid()
|
||||||
|
.then(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -331,15 +349,15 @@ watch(() => props.open, (isOpen) => {
|
|||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="otg" class="text-xs">USB OTG</SelectItem>
|
<SelectItem :value="HidBackend.Otg" class="text-xs">USB OTG</SelectItem>
|
||||||
<SelectItem value="ch9329" class="text-xs">CH9329 (Serial)</SelectItem>
|
<SelectItem :value="HidBackend.Ch9329" class="text-xs">CH9329 (Serial)</SelectItem>
|
||||||
<SelectItem value="none" class="text-xs">{{ t('common.disabled') }}</SelectItem>
|
<SelectItem :value="HidBackend.None" class="text-xs">{{ t('common.disabled') }}</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Device Path (OTG or CH9329) -->
|
<!-- Device Path (OTG or CH9329) -->
|
||||||
<div v-if="hidBackend !== 'none'" class="space-y-2">
|
<div v-if="hidBackend !== HidBackend.None" class="space-y-2">
|
||||||
<Label class="text-xs text-muted-foreground">{{ t('actionbar.devicePath') }}</Label>
|
<Label class="text-xs text-muted-foreground">{{ t('actionbar.devicePath') }}</Label>
|
||||||
<Select
|
<Select
|
||||||
:model-value="devicePath"
|
:model-value="devicePath"
|
||||||
@@ -363,7 +381,7 @@ watch(() => props.open, (isOpen) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Baudrate (CH9329 only) -->
|
<!-- Baudrate (CH9329 only) -->
|
||||||
<div v-if="hidBackend === 'ch9329'" class="space-y-2">
|
<div v-if="hidBackend === HidBackend.Ch9329" class="space-y-2">
|
||||||
<Label class="text-xs text-muted-foreground">{{ t('actionbar.baudrate') }}</Label>
|
<Label class="text-xs text-muted-foreground">{{ t('actionbar.baudrate') }}</Label>
|
||||||
<Select
|
<Select
|
||||||
:model-value="String(baudrate)"
|
:model-value="String(baudrate)"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
import { Monitor, RefreshCw, Loader2, Settings, Zap, Scale, Image } from 'lucide-vue-next'
|
import { Monitor, RefreshCw, Loader2, Settings, Zap, Scale, Image } from 'lucide-vue-next'
|
||||||
import HelpTooltip from '@/components/HelpTooltip.vue'
|
import HelpTooltip from '@/components/HelpTooltip.vue'
|
||||||
import { configApi, streamApi, type VideoCodecInfo, type EncoderBackendInfo, type BitratePreset } from '@/api'
|
import { configApi, streamApi, type VideoCodecInfo, type EncoderBackendInfo, type BitratePreset } from '@/api'
|
||||||
import { useSystemStore } from '@/stores/system'
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
export type VideoMode = 'mjpeg' | 'h264' | 'h265' | 'vp8' | 'vp9'
|
export type VideoMode = 'mjpeg' | 'h264' | 'h265' | 'vp8' | 'vp9'
|
||||||
@@ -51,7 +51,7 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const systemStore = useSystemStore()
|
const configStore = useConfigStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// Device list
|
// Device list
|
||||||
@@ -64,7 +64,7 @@ const loadingCodecs = ref(false)
|
|||||||
|
|
||||||
// Backend list
|
// Backend list
|
||||||
const backends = ref<EncoderBackendInfo[]>([])
|
const backends = ref<EncoderBackendInfo[]>([])
|
||||||
const currentEncoderBackend = ref<string>('auto')
|
const currentEncoderBackend = computed(() => configStore.stream?.encoder || 'auto')
|
||||||
|
|
||||||
// Browser supported codecs (WebRTC receive capabilities)
|
// Browser supported codecs (WebRTC receive capabilities)
|
||||||
const browserSupportedCodecs = ref<Set<string>>(new Set())
|
const browserSupportedCodecs = ref<Set<string>>(new Set())
|
||||||
@@ -197,11 +197,11 @@ const applyingBitrate = ref(false)
|
|||||||
|
|
||||||
// Current config from store
|
// Current config from store
|
||||||
const currentConfig = computed(() => ({
|
const currentConfig = computed(() => ({
|
||||||
device: systemStore.stream?.device || '',
|
device: configStore.video?.device || '',
|
||||||
format: systemStore.stream?.format || '',
|
format: configStore.video?.format || '',
|
||||||
width: systemStore.stream?.resolution?.[0] || 1920,
|
width: configStore.video?.width || 1920,
|
||||||
height: systemStore.stream?.resolution?.[1] || 1080,
|
height: configStore.video?.height || 1080,
|
||||||
fps: systemStore.stream?.targetFps || 30,
|
fps: configStore.video?.fps || 30,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Button display text - simplified to just show label
|
// Button display text - simplified to just show label
|
||||||
@@ -303,19 +303,6 @@ async function loadCodecs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load current encoder backend from config
|
|
||||||
async function loadEncoderBackend() {
|
|
||||||
try {
|
|
||||||
const config = await configApi.get()
|
|
||||||
// Access nested stream.encoder
|
|
||||||
const streamConfig = config.stream as { encoder?: string } | undefined
|
|
||||||
currentEncoderBackend.value = streamConfig?.encoder || 'auto'
|
|
||||||
} catch (e) {
|
|
||||||
console.info('[VideoConfig] Failed to load encoder backend config')
|
|
||||||
currentEncoderBackend.value = 'auto'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigate to settings page (video tab)
|
// Navigate to settings page (video tab)
|
||||||
function goToSettings() {
|
function goToSettings() {
|
||||||
router.push('/settings?tab=video')
|
router.push('/settings?tab=video')
|
||||||
@@ -440,14 +427,12 @@ async function applyVideoConfig() {
|
|||||||
|
|
||||||
applying.value = true
|
applying.value = true
|
||||||
try {
|
try {
|
||||||
await configApi.update({
|
await configStore.updateVideo({
|
||||||
video: {
|
device: selectedDevice.value,
|
||||||
device: selectedDevice.value,
|
format: selectedFormat.value,
|
||||||
format: selectedFormat.value,
|
width,
|
||||||
width,
|
height,
|
||||||
height,
|
fps: selectedFps.value,
|
||||||
fps: selectedFps.value,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
toast.success(t('config.applied'))
|
toast.success(t('config.applied'))
|
||||||
@@ -463,26 +448,32 @@ async function applyVideoConfig() {
|
|||||||
|
|
||||||
// Watch open state
|
// Watch open state
|
||||||
watch(() => props.open, (isOpen) => {
|
watch(() => props.open, (isOpen) => {
|
||||||
if (isOpen) {
|
if (!isOpen) {
|
||||||
// Detect browser codec support on first open
|
|
||||||
if (browserSupportedCodecs.value.size === 0) {
|
|
||||||
detectBrowserCodecSupport()
|
|
||||||
}
|
|
||||||
// Load devices on first open
|
|
||||||
if (devices.value.length === 0) {
|
|
||||||
loadDevices()
|
|
||||||
}
|
|
||||||
// Load codecs and backends on first open
|
|
||||||
if (codecs.value.length === 0) {
|
|
||||||
loadCodecs()
|
|
||||||
}
|
|
||||||
// Load encoder backend config
|
|
||||||
loadEncoderBackend()
|
|
||||||
// Initialize from current config
|
|
||||||
initializeFromCurrent()
|
|
||||||
} else {
|
|
||||||
isDirty.value = false
|
isDirty.value = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect browser codec support on first open
|
||||||
|
if (browserSupportedCodecs.value.size === 0) {
|
||||||
|
detectBrowserCodecSupport()
|
||||||
|
}
|
||||||
|
// Load devices on first open
|
||||||
|
if (devices.value.length === 0) {
|
||||||
|
loadDevices()
|
||||||
|
}
|
||||||
|
// Load codecs and backends on first open
|
||||||
|
if (codecs.value.length === 0) {
|
||||||
|
loadCodecs()
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
configStore.refreshVideo(),
|
||||||
|
configStore.refreshStream(),
|
||||||
|
]).then(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
}).catch(() => {
|
||||||
|
initializeFromCurrent()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Sync selected values when backend config changes (e.g., auto format switch on mode change)
|
// Sync selected values when backend config changes (e.g., auto format switch on mode change)
|
||||||
|
|||||||
506
web/src/stores/config.ts
Normal file
506
web/src/stores/config.ts
Normal file
@@ -0,0 +1,506 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import {
|
||||||
|
authConfigApi,
|
||||||
|
atxConfigApi,
|
||||||
|
audioConfigApi,
|
||||||
|
hidConfigApi,
|
||||||
|
msdConfigApi,
|
||||||
|
rustdeskConfigApi,
|
||||||
|
streamConfigApi,
|
||||||
|
videoConfigApi,
|
||||||
|
webConfigApi,
|
||||||
|
} from '@/api'
|
||||||
|
import type {
|
||||||
|
AtxConfig,
|
||||||
|
AtxConfigUpdate,
|
||||||
|
AudioConfig,
|
||||||
|
AudioConfigUpdate,
|
||||||
|
AuthConfig,
|
||||||
|
AuthConfigUpdate,
|
||||||
|
HidConfig,
|
||||||
|
HidConfigUpdate,
|
||||||
|
MsdConfig,
|
||||||
|
MsdConfigUpdate,
|
||||||
|
StreamConfigResponse,
|
||||||
|
StreamConfigUpdate,
|
||||||
|
VideoConfig,
|
||||||
|
VideoConfigUpdate,
|
||||||
|
WebConfig,
|
||||||
|
WebConfigUpdate,
|
||||||
|
} from '@/types/generated'
|
||||||
|
import type {
|
||||||
|
RustDeskConfigResponse as ApiRustDeskConfigResponse,
|
||||||
|
RustDeskConfigUpdate as ApiRustDeskConfigUpdate,
|
||||||
|
RustDeskStatusResponse as ApiRustDeskStatusResponse,
|
||||||
|
RustDeskPasswordResponse as ApiRustDeskPasswordResponse,
|
||||||
|
} from '@/api'
|
||||||
|
|
||||||
|
function normalizeErrorMessage(error: unknown): string {
|
||||||
|
if (error instanceof Error) return error.message
|
||||||
|
if (typeof error === 'string') return error
|
||||||
|
return 'Unknown error'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useConfigStore = defineStore('config', () => {
|
||||||
|
const auth = ref<AuthConfig | null>(null)
|
||||||
|
const video = ref<VideoConfig | null>(null)
|
||||||
|
const audio = ref<AudioConfig | null>(null)
|
||||||
|
const hid = ref<HidConfig | null>(null)
|
||||||
|
const msd = ref<MsdConfig | null>(null)
|
||||||
|
const stream = ref<StreamConfigResponse | null>(null)
|
||||||
|
const web = ref<WebConfig | null>(null)
|
||||||
|
const atx = ref<AtxConfig | null>(null)
|
||||||
|
const rustdeskConfig = ref<ApiRustDeskConfigResponse | null>(null)
|
||||||
|
const rustdeskStatus = ref<ApiRustDeskStatusResponse | null>(null)
|
||||||
|
const rustdeskPassword = ref<ApiRustDeskPasswordResponse | null>(null)
|
||||||
|
|
||||||
|
const authLoading = ref(false)
|
||||||
|
const videoLoading = ref(false)
|
||||||
|
const audioLoading = ref(false)
|
||||||
|
const hidLoading = ref(false)
|
||||||
|
const msdLoading = ref(false)
|
||||||
|
const streamLoading = ref(false)
|
||||||
|
const webLoading = ref(false)
|
||||||
|
const atxLoading = ref(false)
|
||||||
|
const rustdeskLoading = ref(false)
|
||||||
|
|
||||||
|
const authError = ref<string | null>(null)
|
||||||
|
const videoError = ref<string | null>(null)
|
||||||
|
const audioError = ref<string | null>(null)
|
||||||
|
const hidError = ref<string | null>(null)
|
||||||
|
const msdError = ref<string | null>(null)
|
||||||
|
const streamError = ref<string | null>(null)
|
||||||
|
const webError = ref<string | null>(null)
|
||||||
|
const atxError = ref<string | null>(null)
|
||||||
|
const rustdeskError = ref<string | null>(null)
|
||||||
|
|
||||||
|
let authPromise: Promise<AuthConfig> | null = null
|
||||||
|
let videoPromise: Promise<VideoConfig> | null = null
|
||||||
|
let audioPromise: Promise<AudioConfig> | null = null
|
||||||
|
let hidPromise: Promise<HidConfig> | null = null
|
||||||
|
let msdPromise: Promise<MsdConfig> | null = null
|
||||||
|
let streamPromise: Promise<StreamConfigResponse> | null = null
|
||||||
|
let webPromise: Promise<WebConfig> | null = null
|
||||||
|
let atxPromise: Promise<AtxConfig> | null = null
|
||||||
|
let rustdeskPromise: Promise<ApiRustDeskConfigResponse> | null = null
|
||||||
|
let rustdeskStatusPromise: Promise<ApiRustDeskStatusResponse> | null = null
|
||||||
|
let rustdeskPasswordPromise: Promise<ApiRustDeskPasswordResponse> | null = null
|
||||||
|
|
||||||
|
async function refreshAuth() {
|
||||||
|
if (authLoading.value && authPromise) return authPromise
|
||||||
|
authLoading.value = true
|
||||||
|
authError.value = null
|
||||||
|
const request = authConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
auth.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
authError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
authLoading.value = false
|
||||||
|
authPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
authPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshVideo() {
|
||||||
|
if (videoLoading.value && videoPromise) return videoPromise
|
||||||
|
videoLoading.value = true
|
||||||
|
videoError.value = null
|
||||||
|
const request = videoConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
video.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
videoError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
videoLoading.value = false
|
||||||
|
videoPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
videoPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshAudio() {
|
||||||
|
if (audioLoading.value && audioPromise) return audioPromise
|
||||||
|
audioLoading.value = true
|
||||||
|
audioError.value = null
|
||||||
|
const request = audioConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
audio.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
audioError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
audioLoading.value = false
|
||||||
|
audioPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
audioPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshHid() {
|
||||||
|
if (hidLoading.value && hidPromise) return hidPromise
|
||||||
|
hidLoading.value = true
|
||||||
|
hidError.value = null
|
||||||
|
const request = hidConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
hid.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
hidError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
hidLoading.value = false
|
||||||
|
hidPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
hidPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshMsd() {
|
||||||
|
if (msdLoading.value && msdPromise) return msdPromise
|
||||||
|
msdLoading.value = true
|
||||||
|
msdError.value = null
|
||||||
|
const request = msdConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
msd.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
msdError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
msdLoading.value = false
|
||||||
|
msdPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
msdPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshStream() {
|
||||||
|
if (streamLoading.value && streamPromise) return streamPromise
|
||||||
|
streamLoading.value = true
|
||||||
|
streamError.value = null
|
||||||
|
const request = streamConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
stream.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
streamError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
streamLoading.value = false
|
||||||
|
streamPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
streamPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshWeb() {
|
||||||
|
if (webLoading.value && webPromise) return webPromise
|
||||||
|
webLoading.value = true
|
||||||
|
webError.value = null
|
||||||
|
const request = webConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
web.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
webError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
webLoading.value = false
|
||||||
|
webPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
webPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshAtx() {
|
||||||
|
if (atxLoading.value && atxPromise) return atxPromise
|
||||||
|
atxLoading.value = true
|
||||||
|
atxError.value = null
|
||||||
|
const request = atxConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
atx.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
atxError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
atxLoading.value = false
|
||||||
|
atxPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
atxPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshRustdeskConfig() {
|
||||||
|
if (rustdeskLoading.value && rustdeskPromise) return rustdeskPromise
|
||||||
|
rustdeskLoading.value = true
|
||||||
|
rustdeskError.value = null
|
||||||
|
const request = rustdeskConfigApi.get()
|
||||||
|
.then((response) => {
|
||||||
|
rustdeskConfig.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
rustdeskError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
rustdeskLoading.value = false
|
||||||
|
rustdeskPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
rustdeskPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshRustdeskStatus() {
|
||||||
|
if (rustdeskLoading.value && rustdeskStatusPromise) return rustdeskStatusPromise
|
||||||
|
rustdeskLoading.value = true
|
||||||
|
rustdeskError.value = null
|
||||||
|
const request = rustdeskConfigApi.getStatus()
|
||||||
|
.then((response) => {
|
||||||
|
rustdeskStatus.value = response
|
||||||
|
rustdeskConfig.value = response.config
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
rustdeskError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
rustdeskLoading.value = false
|
||||||
|
rustdeskStatusPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
rustdeskStatusPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshRustdeskPassword() {
|
||||||
|
if (rustdeskLoading.value && rustdeskPasswordPromise) return rustdeskPasswordPromise
|
||||||
|
rustdeskLoading.value = true
|
||||||
|
rustdeskError.value = null
|
||||||
|
const request = rustdeskConfigApi.getPassword()
|
||||||
|
.then((response) => {
|
||||||
|
rustdeskPassword.value = response
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
rustdeskError.value = normalizeErrorMessage(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
rustdeskLoading.value = false
|
||||||
|
rustdeskPasswordPromise = null
|
||||||
|
})
|
||||||
|
|
||||||
|
rustdeskPasswordPromise = request
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureAuth() {
|
||||||
|
if (auth.value) return Promise.resolve(auth.value)
|
||||||
|
return refreshAuth()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureVideo() {
|
||||||
|
if (video.value) return Promise.resolve(video.value)
|
||||||
|
return refreshVideo()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureAudio() {
|
||||||
|
if (audio.value) return Promise.resolve(audio.value)
|
||||||
|
return refreshAudio()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureHid() {
|
||||||
|
if (hid.value) return Promise.resolve(hid.value)
|
||||||
|
return refreshHid()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureMsd() {
|
||||||
|
if (msd.value) return Promise.resolve(msd.value)
|
||||||
|
return refreshMsd()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureStream() {
|
||||||
|
if (stream.value) return Promise.resolve(stream.value)
|
||||||
|
return refreshStream()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureWeb() {
|
||||||
|
if (web.value) return Promise.resolve(web.value)
|
||||||
|
return refreshWeb()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureAtx() {
|
||||||
|
if (atx.value) return Promise.resolve(atx.value)
|
||||||
|
return refreshAtx()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRustdeskConfig() {
|
||||||
|
if (rustdeskConfig.value) return Promise.resolve(rustdeskConfig.value)
|
||||||
|
return refreshRustdeskConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateAuth(update: AuthConfigUpdate) {
|
||||||
|
const response = await authConfigApi.update(update)
|
||||||
|
auth.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateVideo(update: VideoConfigUpdate) {
|
||||||
|
const response = await videoConfigApi.update(update)
|
||||||
|
video.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateAudio(update: AudioConfigUpdate) {
|
||||||
|
const response = await audioConfigApi.update(update)
|
||||||
|
audio.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateHid(update: HidConfigUpdate) {
|
||||||
|
const response = await hidConfigApi.update(update)
|
||||||
|
hid.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateMsd(update: MsdConfigUpdate) {
|
||||||
|
const response = await msdConfigApi.update(update)
|
||||||
|
msd.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateStream(update: StreamConfigUpdate) {
|
||||||
|
const response = await streamConfigApi.update(update)
|
||||||
|
stream.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateWeb(update: WebConfigUpdate) {
|
||||||
|
const response = await webConfigApi.update(update)
|
||||||
|
web.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateAtx(update: AtxConfigUpdate) {
|
||||||
|
const response = await atxConfigApi.update(update)
|
||||||
|
atx.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateRustdesk(update: ApiRustDeskConfigUpdate) {
|
||||||
|
const response = await rustdeskConfigApi.update(update)
|
||||||
|
rustdeskConfig.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function regenerateRustdeskId() {
|
||||||
|
const response = await rustdeskConfigApi.regenerateId()
|
||||||
|
rustdeskConfig.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async function regenerateRustdeskPassword() {
|
||||||
|
const response = await rustdeskConfigApi.regeneratePassword()
|
||||||
|
rustdeskConfig.value = response
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
auth,
|
||||||
|
video,
|
||||||
|
audio,
|
||||||
|
hid,
|
||||||
|
msd,
|
||||||
|
stream,
|
||||||
|
web,
|
||||||
|
atx,
|
||||||
|
rustdeskConfig,
|
||||||
|
rustdeskStatus,
|
||||||
|
rustdeskPassword,
|
||||||
|
authLoading,
|
||||||
|
videoLoading,
|
||||||
|
audioLoading,
|
||||||
|
hidLoading,
|
||||||
|
msdLoading,
|
||||||
|
streamLoading,
|
||||||
|
webLoading,
|
||||||
|
atxLoading,
|
||||||
|
rustdeskLoading,
|
||||||
|
authError,
|
||||||
|
videoError,
|
||||||
|
audioError,
|
||||||
|
hidError,
|
||||||
|
msdError,
|
||||||
|
streamError,
|
||||||
|
webError,
|
||||||
|
atxError,
|
||||||
|
rustdeskError,
|
||||||
|
refreshAuth,
|
||||||
|
refreshVideo,
|
||||||
|
refreshAudio,
|
||||||
|
refreshHid,
|
||||||
|
refreshMsd,
|
||||||
|
refreshStream,
|
||||||
|
refreshWeb,
|
||||||
|
refreshAtx,
|
||||||
|
refreshRustdeskConfig,
|
||||||
|
refreshRustdeskStatus,
|
||||||
|
refreshRustdeskPassword,
|
||||||
|
ensureAuth,
|
||||||
|
ensureVideo,
|
||||||
|
ensureAudio,
|
||||||
|
ensureHid,
|
||||||
|
ensureMsd,
|
||||||
|
ensureStream,
|
||||||
|
ensureWeb,
|
||||||
|
ensureAtx,
|
||||||
|
ensureRustdeskConfig,
|
||||||
|
updateAuth,
|
||||||
|
updateVideo,
|
||||||
|
updateAudio,
|
||||||
|
updateHid,
|
||||||
|
updateMsd,
|
||||||
|
updateStream,
|
||||||
|
updateWeb,
|
||||||
|
updateAtx,
|
||||||
|
updateRustdesk,
|
||||||
|
regenerateRustdeskId,
|
||||||
|
regenerateRustdeskPassword,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export { useAuthStore } from './auth'
|
export { useAuthStore } from './auth'
|
||||||
|
export { useConfigStore } from './config'
|
||||||
export { useSystemStore } from './system'
|
export { useSystemStore } from './system'
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ref, onMounted, onUnmounted, computed, watch, nextTick } from 'vue'
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useSystemStore } from '@/stores/system'
|
import { useSystemStore } from '@/stores/system'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { useWebSocket } from '@/composables/useWebSocket'
|
import { useWebSocket } from '@/composables/useWebSocket'
|
||||||
import { useConsoleEvents } from '@/composables/useConsoleEvents'
|
import { useConsoleEvents } from '@/composables/useConsoleEvents'
|
||||||
@@ -59,6 +60,7 @@ import { setLanguage } from '@/i18n'
|
|||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const systemStore = useSystemStore()
|
const systemStore = useSystemStore()
|
||||||
|
const configStore = useConfigStore()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
const { connected: wsConnected, networkError: wsNetworkError } = useWebSocket()
|
const { connected: wsConnected, networkError: wsNetworkError } = useWebSocket()
|
||||||
const hidWs = useHidWebSocket()
|
const hidWs = useHidWebSocket()
|
||||||
@@ -134,6 +136,15 @@ let accumulatedDelta = { x: 0, y: 0 } // For relative mode: accumulate deltas be
|
|||||||
// Cursor visibility (from localStorage, updated via storage event)
|
// Cursor visibility (from localStorage, updated via storage event)
|
||||||
const cursorVisible = ref(localStorage.getItem('hidShowCursor') !== 'false')
|
const cursorVisible = ref(localStorage.getItem('hidShowCursor') !== 'false')
|
||||||
|
|
||||||
|
function syncMouseModeFromConfig() {
|
||||||
|
const mouseAbsolute = configStore.hid?.mouse_absolute
|
||||||
|
if (typeof mouseAbsolute !== 'boolean') return
|
||||||
|
const nextMode: 'absolute' | 'relative' = mouseAbsolute ? 'absolute' : 'relative'
|
||||||
|
if (mouseMode.value !== nextMode) {
|
||||||
|
mouseMode.value = nextMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Virtual keyboard state
|
// Virtual keyboard state
|
||||||
const virtualKeyboardVisible = ref(false)
|
const virtualKeyboardVisible = ref(false)
|
||||||
const virtualKeyboardAttached = ref(true)
|
const virtualKeyboardAttached = ref(true)
|
||||||
@@ -1787,6 +1798,9 @@ onMounted(async () => {
|
|||||||
// 4. 其他初始化
|
// 4. 其他初始化
|
||||||
await systemStore.startStream().catch(() => {})
|
await systemStore.startStream().catch(() => {})
|
||||||
await systemStore.fetchAllStates()
|
await systemStore.fetchAllStates()
|
||||||
|
await configStore.refreshHid().then(() => {
|
||||||
|
syncMouseModeFromConfig()
|
||||||
|
}).catch(() => {})
|
||||||
|
|
||||||
window.addEventListener('keydown', handleKeyDown)
|
window.addEventListener('keydown', handleKeyDown)
|
||||||
window.addEventListener('keyup', handleKeyUp)
|
window.addEventListener('keyup', handleKeyUp)
|
||||||
@@ -1800,6 +1814,10 @@ onMounted(async () => {
|
|||||||
window.addEventListener('hidMouseSendIntervalChanged', handleMouseSendIntervalChange as EventListener)
|
window.addEventListener('hidMouseSendIntervalChanged', handleMouseSendIntervalChange as EventListener)
|
||||||
window.addEventListener('storage', handleMouseSendIntervalStorage)
|
window.addEventListener('storage', handleMouseSendIntervalStorage)
|
||||||
|
|
||||||
|
watch(() => configStore.hid?.mouse_absolute, () => {
|
||||||
|
syncMouseModeFromConfig()
|
||||||
|
})
|
||||||
|
|
||||||
// Pointer Lock event listeners
|
// Pointer Lock event listeners
|
||||||
document.addEventListener('pointerlockchange', handlePointerLockChange)
|
document.addEventListener('pointerlockchange', handlePointerLockChange)
|
||||||
document.addEventListener('pointerlockerror', handlePointerLockError)
|
document.addEventListener('pointerlockerror', handlePointerLockError)
|
||||||
|
|||||||
@@ -2,20 +2,14 @@
|
|||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, onMounted, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useSystemStore } from '@/stores/system'
|
import { useSystemStore } from '@/stores/system'
|
||||||
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import {
|
import {
|
||||||
authApi,
|
authApi,
|
||||||
authConfigApi,
|
|
||||||
configApi,
|
configApi,
|
||||||
streamApi,
|
streamApi,
|
||||||
videoConfigApi,
|
|
||||||
streamConfigApi,
|
|
||||||
hidConfigApi,
|
|
||||||
msdConfigApi,
|
|
||||||
atxConfigApi,
|
atxConfigApi,
|
||||||
extensionsApi,
|
extensionsApi,
|
||||||
rustdeskConfigApi,
|
|
||||||
webConfigApi,
|
|
||||||
systemApi,
|
systemApi,
|
||||||
type EncoderBackendInfo,
|
type EncoderBackendInfo,
|
||||||
type AuthConfig,
|
type AuthConfig,
|
||||||
@@ -80,6 +74,7 @@ import {
|
|||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
const systemStore = useSystemStore()
|
const systemStore = useSystemStore()
|
||||||
|
const configStore = useConfigStore()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
// Settings state
|
// Settings state
|
||||||
@@ -271,7 +266,6 @@ const config = ref({
|
|||||||
} as OtgHidFunctions,
|
} as OtgHidFunctions,
|
||||||
msd_enabled: false,
|
msd_enabled: false,
|
||||||
msd_dir: '',
|
msd_dir: '',
|
||||||
network_port: 8080,
|
|
||||||
encoder_backend: 'auto',
|
encoder_backend: 'auto',
|
||||||
// STUN/TURN settings
|
// STUN/TURN settings
|
||||||
stun_server: '',
|
stun_server: '',
|
||||||
@@ -583,7 +577,7 @@ async function saveConfig() {
|
|||||||
// Video 配置(包括编码器和 WebRTC/STUN/TURN 设置)
|
// Video 配置(包括编码器和 WebRTC/STUN/TURN 设置)
|
||||||
if (activeSection.value === 'video') {
|
if (activeSection.value === 'video') {
|
||||||
savePromises.push(
|
savePromises.push(
|
||||||
videoConfigApi.update({
|
configStore.updateVideo({
|
||||||
device: config.value.video_device || undefined,
|
device: config.value.video_device || undefined,
|
||||||
format: config.value.video_format || undefined,
|
format: config.value.video_format || undefined,
|
||||||
width: config.value.video_width,
|
width: config.value.video_width,
|
||||||
@@ -593,7 +587,7 @@ async function saveConfig() {
|
|||||||
)
|
)
|
||||||
// 同时保存 Stream/Encoder 和 STUN/TURN 配置
|
// 同时保存 Stream/Encoder 和 STUN/TURN 配置
|
||||||
savePromises.push(
|
savePromises.push(
|
||||||
streamConfigApi.update({
|
configStore.updateStream({
|
||||||
encoder: config.value.encoder_backend as any,
|
encoder: config.value.encoder_backend as any,
|
||||||
stun_server: config.value.stun_server || undefined,
|
stun_server: config.value.stun_server || undefined,
|
||||||
turn_server: config.value.turn_server || undefined,
|
turn_server: config.value.turn_server || undefined,
|
||||||
@@ -642,12 +636,12 @@ async function saveConfig() {
|
|||||||
hidUpdate.otg_profile = config.value.hid_otg_profile
|
hidUpdate.otg_profile = config.value.hid_otg_profile
|
||||||
hidUpdate.otg_functions = { ...config.value.hid_otg_functions }
|
hidUpdate.otg_functions = { ...config.value.hid_otg_functions }
|
||||||
}
|
}
|
||||||
savePromises.push(hidConfigApi.update(hidUpdate))
|
savePromises.push(configStore.updateHid(hidUpdate))
|
||||||
if (config.value.msd_enabled !== desiredMsdEnabled) {
|
if (config.value.msd_enabled !== desiredMsdEnabled) {
|
||||||
config.value.msd_enabled = desiredMsdEnabled
|
config.value.msd_enabled = desiredMsdEnabled
|
||||||
}
|
}
|
||||||
savePromises.push(
|
savePromises.push(
|
||||||
msdConfigApi.update({
|
configStore.updateMsd({
|
||||||
enabled: desiredMsdEnabled,
|
enabled: desiredMsdEnabled,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -656,7 +650,7 @@ async function saveConfig() {
|
|||||||
// MSD 配置
|
// MSD 配置
|
||||||
if (activeSection.value === 'msd') {
|
if (activeSection.value === 'msd') {
|
||||||
savePromises.push(
|
savePromises.push(
|
||||||
msdConfigApi.update({
|
configStore.updateMsd({
|
||||||
msd_dir: config.value.msd_dir || undefined,
|
msd_dir: config.value.msd_dir || undefined,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -677,10 +671,10 @@ async function loadConfig() {
|
|||||||
try {
|
try {
|
||||||
// 并行加载所有域配置
|
// 并行加载所有域配置
|
||||||
const [video, stream, hid, msd] = await Promise.all([
|
const [video, stream, hid, msd] = await Promise.all([
|
||||||
videoConfigApi.get(),
|
configStore.refreshVideo(),
|
||||||
streamConfigApi.get(),
|
configStore.refreshStream(),
|
||||||
hidConfigApi.get(),
|
configStore.refreshHid(),
|
||||||
msdConfigApi.get(),
|
configStore.refreshMsd(),
|
||||||
])
|
])
|
||||||
|
|
||||||
config.value = {
|
config.value = {
|
||||||
@@ -702,7 +696,6 @@ async function loadConfig() {
|
|||||||
} as OtgHidFunctions,
|
} as OtgHidFunctions,
|
||||||
msd_enabled: msd.enabled || false,
|
msd_enabled: msd.enabled || false,
|
||||||
msd_dir: msd.msd_dir || '',
|
msd_dir: msd.msd_dir || '',
|
||||||
network_port: 8080, // 从旧 API 加载
|
|
||||||
encoder_backend: stream.encoder || 'auto',
|
encoder_backend: stream.encoder || 'auto',
|
||||||
// STUN/TURN settings
|
// STUN/TURN settings
|
||||||
stun_server: stream.stun_server || '',
|
stun_server: stream.stun_server || '',
|
||||||
@@ -723,14 +716,6 @@ async function loadConfig() {
|
|||||||
otgSerialNumber.value = hid.otg_descriptor.serial_number || ''
|
otgSerialNumber.value = hid.otg_descriptor.serial_number || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载 web config(仍使用旧 API)
|
|
||||||
try {
|
|
||||||
const fullConfig = await configApi.get()
|
|
||||||
const web = fullConfig.web as any || {}
|
|
||||||
config.value.network_port = web.http_port || 8080
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Failed to load web config:', e)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load config:', e)
|
console.error('Failed to load config:', e)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -763,7 +748,7 @@ async function loadBackends() {
|
|||||||
async function loadAuthConfig() {
|
async function loadAuthConfig() {
|
||||||
authConfigLoading.value = true
|
authConfigLoading.value = true
|
||||||
try {
|
try {
|
||||||
authConfig.value = await authConfigApi.get()
|
authConfig.value = await configStore.refreshAuth()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load auth config:', e)
|
console.error('Failed to load auth config:', e)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -774,10 +759,9 @@ async function loadAuthConfig() {
|
|||||||
async function saveAuthConfig() {
|
async function saveAuthConfig() {
|
||||||
authConfigLoading.value = true
|
authConfigLoading.value = true
|
||||||
try {
|
try {
|
||||||
await authConfigApi.update({
|
authConfig.value = await configStore.updateAuth({
|
||||||
single_user_allow_multiple_sessions: authConfig.value.single_user_allow_multiple_sessions,
|
single_user_allow_multiple_sessions: authConfig.value.single_user_allow_multiple_sessions,
|
||||||
})
|
})
|
||||||
await loadAuthConfig()
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to save auth config:', e)
|
console.error('Failed to save auth config:', e)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -912,7 +896,7 @@ function removeEasytierPeer(index: number) {
|
|||||||
// ATX management functions
|
// ATX management functions
|
||||||
async function loadAtxConfig() {
|
async function loadAtxConfig() {
|
||||||
try {
|
try {
|
||||||
const config = await atxConfigApi.get()
|
const config = await configStore.refreshAtx()
|
||||||
atxConfig.value = {
|
atxConfig.value = {
|
||||||
enabled: config.enabled,
|
enabled: config.enabled,
|
||||||
power: { ...config.power },
|
power: { ...config.power },
|
||||||
@@ -937,7 +921,7 @@ async function saveAtxConfig() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
saved.value = false
|
saved.value = false
|
||||||
try {
|
try {
|
||||||
await atxConfigApi.update({
|
await configStore.updateAtx({
|
||||||
enabled: atxConfig.value.enabled,
|
enabled: atxConfig.value.enabled,
|
||||||
power: {
|
power: {
|
||||||
driver: atxConfig.value.power.driver,
|
driver: atxConfig.value.power.driver,
|
||||||
@@ -981,10 +965,8 @@ function getAtxDevicesForDriver(driver: string): string[] {
|
|||||||
async function loadRustdeskConfig() {
|
async function loadRustdeskConfig() {
|
||||||
rustdeskLoading.value = true
|
rustdeskLoading.value = true
|
||||||
try {
|
try {
|
||||||
const [config, status] = await Promise.all([
|
const status = await configStore.refreshRustdeskStatus()
|
||||||
rustdeskConfigApi.get(),
|
const config = status.config
|
||||||
rustdeskConfigApi.getStatus(),
|
|
||||||
])
|
|
||||||
rustdeskConfig.value = config
|
rustdeskConfig.value = config
|
||||||
rustdeskStatus.value = status
|
rustdeskStatus.value = status
|
||||||
rustdeskLocalConfig.value = {
|
rustdeskLocalConfig.value = {
|
||||||
@@ -1002,7 +984,7 @@ async function loadRustdeskConfig() {
|
|||||||
|
|
||||||
async function loadRustdeskPassword() {
|
async function loadRustdeskPassword() {
|
||||||
try {
|
try {
|
||||||
rustdeskPassword.value = await rustdeskConfigApi.getPassword()
|
rustdeskPassword.value = await configStore.refreshRustdeskPassword()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to load RustDesk password:', e)
|
console.error('Failed to load RustDesk password:', e)
|
||||||
}
|
}
|
||||||
@@ -1060,7 +1042,7 @@ function removeBindAddress(index: number) {
|
|||||||
// Web server config functions
|
// Web server config functions
|
||||||
async function loadWebServerConfig() {
|
async function loadWebServerConfig() {
|
||||||
try {
|
try {
|
||||||
const config = await webConfigApi.get()
|
const config = await configStore.refreshWeb()
|
||||||
webServerConfig.value = config
|
webServerConfig.value = config
|
||||||
applyBindStateFromConfig(config)
|
applyBindStateFromConfig(config)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1078,7 +1060,7 @@ async function saveWebServerConfig() {
|
|||||||
https_enabled: webServerConfig.value.https_enabled,
|
https_enabled: webServerConfig.value.https_enabled,
|
||||||
bind_addresses: effectiveBindAddresses.value,
|
bind_addresses: effectiveBindAddresses.value,
|
||||||
}
|
}
|
||||||
const updated = await webConfigApi.update(update)
|
const updated = await configStore.updateWeb(update)
|
||||||
webServerConfig.value = updated
|
webServerConfig.value = updated
|
||||||
applyBindStateFromConfig(updated)
|
applyBindStateFromConfig(updated)
|
||||||
showRestartDialog.value = true
|
showRestartDialog.value = true
|
||||||
@@ -1117,7 +1099,7 @@ async function saveRustdeskConfig() {
|
|||||||
21116,
|
21116,
|
||||||
)
|
)
|
||||||
const relayServer = normalizeRustdeskServer(rustdeskLocalConfig.value.relay_server, 21117)
|
const relayServer = normalizeRustdeskServer(rustdeskLocalConfig.value.relay_server, 21117)
|
||||||
await rustdeskConfigApi.update({
|
await configStore.updateRustdesk({
|
||||||
enabled: rustdeskLocalConfig.value.enabled,
|
enabled: rustdeskLocalConfig.value.enabled,
|
||||||
rendezvous_server: rendezvousServer,
|
rendezvous_server: rendezvousServer,
|
||||||
relay_server: relayServer,
|
relay_server: relayServer,
|
||||||
@@ -1139,7 +1121,7 @@ async function regenerateRustdeskId() {
|
|||||||
if (!confirm(t('extensions.rustdesk.confirmRegenerateId'))) return
|
if (!confirm(t('extensions.rustdesk.confirmRegenerateId'))) return
|
||||||
rustdeskLoading.value = true
|
rustdeskLoading.value = true
|
||||||
try {
|
try {
|
||||||
await rustdeskConfigApi.regenerateId()
|
await configStore.regenerateRustdeskId()
|
||||||
await loadRustdeskConfig()
|
await loadRustdeskConfig()
|
||||||
await loadRustdeskPassword()
|
await loadRustdeskPassword()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1153,7 +1135,7 @@ async function regenerateRustdeskPassword() {
|
|||||||
if (!confirm(t('extensions.rustdesk.confirmRegeneratePassword'))) return
|
if (!confirm(t('extensions.rustdesk.confirmRegeneratePassword'))) return
|
||||||
rustdeskLoading.value = true
|
rustdeskLoading.value = true
|
||||||
try {
|
try {
|
||||||
await rustdeskConfigApi.regeneratePassword()
|
await configStore.regenerateRustdeskPassword()
|
||||||
await loadRustdeskConfig()
|
await loadRustdeskConfig()
|
||||||
await loadRustdeskPassword()
|
await loadRustdeskPassword()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1167,7 +1149,7 @@ async function startRustdesk() {
|
|||||||
rustdeskLoading.value = true
|
rustdeskLoading.value = true
|
||||||
try {
|
try {
|
||||||
// Enable and save config to start the service
|
// Enable and save config to start the service
|
||||||
await rustdeskConfigApi.update({ enabled: true })
|
await configStore.updateRustdesk({ enabled: true })
|
||||||
rustdeskLocalConfig.value.enabled = true
|
rustdeskLocalConfig.value.enabled = true
|
||||||
await loadRustdeskConfig()
|
await loadRustdeskConfig()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1181,7 +1163,7 @@ async function stopRustdesk() {
|
|||||||
rustdeskLoading.value = true
|
rustdeskLoading.value = true
|
||||||
try {
|
try {
|
||||||
// Disable and save config to stop the service
|
// Disable and save config to stop the service
|
||||||
await rustdeskConfigApi.update({ enabled: false })
|
await configStore.updateRustdesk({ enabled: false })
|
||||||
rustdeskLocalConfig.value.enabled = false
|
rustdeskLocalConfig.value.enabled = false
|
||||||
await loadRustdeskConfig()
|
await loadRustdeskConfig()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user