137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect, Suspense } from 'react'
|
|
import { useRouter, useSearchParams } from 'next/navigation'
|
|
import Gatewayinfo from './components/gatewayinfo'
|
|
import GatewayConfig from './components/gatewayConfig'
|
|
import CityNodeStats from './components/cityNodeStats'
|
|
import AllocationStatus from './components/allocationStatus'
|
|
import Settings from './components/settings'
|
|
import Edge from './components/edge'
|
|
import { LogOut } from 'lucide-react'
|
|
|
|
const tabs = [
|
|
{ id: 'gatewayInfo', label: '网关信息' },
|
|
{ id: 'gateway', label: '网关配置' },
|
|
{ id: 'city', label: '城市信息' },
|
|
{ id: 'allocation', label: '分配状态' },
|
|
{ id: 'edge', label: '节点信息' },
|
|
{ id: 'setting', label: '设置' },
|
|
]
|
|
|
|
function DashboardContent() {
|
|
const [activeTab, setActiveTab] = useState('gatewayInfo')
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
const router = useRouter()
|
|
const searchParams = useSearchParams()
|
|
|
|
// 监听URL参数变化
|
|
useEffect(() => {
|
|
const urlTab = searchParams.get('tab')
|
|
if (urlTab && tabs.some(tab => tab.id === urlTab)) {
|
|
setActiveTab(urlTab)
|
|
}
|
|
}, [searchParams])
|
|
|
|
// 退出登录
|
|
const handleLogout = async () => {
|
|
setIsLoading(true)
|
|
try {
|
|
const response = await fetch('/api/auth/logout', {
|
|
method: 'POST',
|
|
})
|
|
|
|
if (response.ok) {
|
|
// 退出成功后跳转到登录页
|
|
router.push('/login')
|
|
router.refresh()
|
|
}
|
|
else {
|
|
console.error('退出失败')
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error('退出错误:', error)
|
|
}
|
|
finally {
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
|
|
const handleTabClick = (tabId: string) => {
|
|
setActiveTab(tabId)
|
|
// 更新 URL 参数
|
|
const params = new URLSearchParams()
|
|
params.set('tab', tabId)
|
|
router.push(`/dashboard?${params.toString()}`)
|
|
}
|
|
|
|
return (
|
|
<div className=" bg-gray-100 w-screen h-screen flex flex-col">
|
|
<nav className="bg-white flex-none h-16 shadow-sm">
|
|
<div className="px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between h-16 items-center">
|
|
<div className="flex items-center">
|
|
<h1 className="text-xl font-bold text-gray-900">网络节点管理系统</h1>
|
|
</div>
|
|
|
|
{/* 简化的退出按钮 */}
|
|
<button
|
|
onClick={handleLogout}
|
|
disabled={isLoading}
|
|
className="flex items-center space-x-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 disabled:opacity-50 transition-colors"
|
|
>
|
|
<LogOut className="h-4 w-4" />
|
|
<span>{isLoading ? '退出中...' : '退出登录'}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div className="flex flex-3 overflow-hidden px-4 sm:px-6 lg:px-8 py-8">
|
|
<div className="border-b border-gray-200 mb-6">
|
|
<nav className="flex flex-col w-64 -mb-px space-x-8">
|
|
{tabs.map(tab => (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => handleTabClick(tab.id)}
|
|
className={`py-2 px-1 h-12 border-b-2 font-medium text-sm ${
|
|
activeTab === tab.id
|
|
? 'border-blue-500 text-blue-600'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
|
}`}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-6 flex-auto">
|
|
{activeTab === 'gatewayInfo' && <Gatewayinfo />}
|
|
{activeTab === 'gateway' && <GatewayConfig />}
|
|
{activeTab === 'city' && <CityNodeStats />}
|
|
{activeTab === 'allocation' && <AllocationStatus detailed />}
|
|
{activeTab === 'edge' && <Edge />}
|
|
{activeTab === 'setting' && <Settings />}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function Dashboard() {
|
|
return (
|
|
<Suspense fallback={(
|
|
<div className=" bg-gray-100 flex items-center justify-center">
|
|
<div className="text-center">
|
|
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto"></div>
|
|
<p className="mt-4 text-gray-600">加载中...</p>
|
|
</div>
|
|
</div>
|
|
)}>
|
|
<DashboardContent />
|
|
</Suspense>
|
|
)
|
|
}
|