✨ feat: implement web overview, connections, and settings pages
- Add Overview page with realtime metrics, SRv6 SID display, and TUN alert - Add Connections page with card/table views and action menus - Add Settings page with 4 tabs, dynamic item lists, and auto-connect toggle - Implement HashRouter navigation and SSE live event stream integration - Integrate Base UI-based shadcn components and Toaster notifications - Support enableTUN flag and refactor connection table naming conventions
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import type { KLALBControllerConfig } from '@/types/api'
|
||||
|
||||
interface UseKlalbConfigResult {
|
||||
config: KLALBControllerConfig | null
|
||||
isLoading: boolean
|
||||
isSaving: boolean
|
||||
error: string | null
|
||||
saveSuccess: boolean
|
||||
fetchConfig: () => Promise<void>
|
||||
saveConfig: (newConfig: KLALBControllerConfig) => Promise<{ success: boolean; message?: string }>
|
||||
}
|
||||
|
||||
export function useKlalbConfig(): UseKlalbConfigResult {
|
||||
const [config, setConfig] = useState<KLALBControllerConfig | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [isSaving, setIsSaving] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [saveSuccess, setSaveSuccess] = useState(false)
|
||||
|
||||
const fetchConfig = useCallback(async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const res = await fetch('/api/config')
|
||||
if (res.ok) {
|
||||
const data = (await res.json()) as KLALBControllerConfig
|
||||
setConfig(data)
|
||||
setError(null)
|
||||
} else {
|
||||
setError('获取配置失败: 服务器返回异常状态')
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
const msg = err instanceof Error ? err.message : String(err)
|
||||
setError(`无法连接到配置接口: ${msg}`)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const saveConfig = useCallback(
|
||||
async (newConfig: KLALBControllerConfig): Promise<{ success: boolean; message?: string }> => {
|
||||
setIsSaving(true)
|
||||
setSaveSuccess(false)
|
||||
setError(null)
|
||||
try {
|
||||
const res = await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(newConfig),
|
||||
})
|
||||
const data = await res.json()
|
||||
if (res.ok && (data.success || data.success === undefined)) {
|
||||
setConfig(newConfig)
|
||||
setSaveSuccess(true)
|
||||
setTimeout(() => setSaveSuccess(false), 3000)
|
||||
return { success: true }
|
||||
}
|
||||
const errMsg = data.error || data.message || '保存配置失败'
|
||||
setError(errMsg)
|
||||
return { success: false, message: errMsg }
|
||||
} catch (err: unknown) {
|
||||
const msg = err instanceof Error ? err.message : String(err)
|
||||
setError(msg)
|
||||
return { success: false, message: msg }
|
||||
} finally {
|
||||
setIsSaving(false)
|
||||
}
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
fetchConfig()
|
||||
}, [fetchConfig])
|
||||
|
||||
return {
|
||||
config,
|
||||
isLoading,
|
||||
isSaving,
|
||||
error,
|
||||
saveSuccess,
|
||||
fetchConfig,
|
||||
saveConfig,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user