2025-04-07 15:42:09 +08:00
|
|
|
|
import {ReactNode} from 'react'
|
|
|
|
|
|
import Image from 'next/image'
|
|
|
|
|
|
import logo from '@/assets/logo.webp'
|
|
|
|
|
|
import Profile from '@/app/admin/_server/profile'
|
|
|
|
|
|
import {merge} from '@/lib/utils'
|
|
|
|
|
|
import Link from 'next/link'
|
2025-04-08 11:21:58 +08:00
|
|
|
|
import {getProfile} from '@/actions/auth/auth'
|
|
|
|
|
|
import {redirect} from 'next/navigation'
|
2025-04-07 15:42:09 +08:00
|
|
|
|
|
|
|
|
|
|
export type DashboardLayoutProps = {
|
|
|
|
|
|
children: ReactNode
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default async function DashboardLayout(props: DashboardLayoutProps) {
|
2025-04-08 11:21:58 +08:00
|
|
|
|
|
|
|
|
|
|
const profile = await getProfile()
|
|
|
|
|
|
if (!profile) {
|
|
|
|
|
|
return redirect('/login')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-07 15:42:09 +08:00
|
|
|
|
return (
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<div className={`h-screen flex flex-col overflow-hidden min-w-7xl overflow-y-hidden relative`}>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
{/* background */}
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<div className={`-z-10 absolute inset-0 overflow-hidden`}>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
<div className={`absolute w-screen h-screen bg-gray-50`}></div>
|
|
|
|
|
|
<div className={`absolute w-[2000px] h-[2000px] -left-[1000px] -top-[1000px] bg-radial from-blue-50 from-10% to-transparent to-50%`}></div>
|
|
|
|
|
|
<div className={`absolute w-[2000px] h-[2000px] -right-[1000px] -top-[1000px] bg-radial from-blue-50 from-10% to-transparent to-50%`}></div>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<div className={`absolute w-[2000px] h-[2000px] left-[calc(50%-1000px)] -bottom-[1000px] bg-radial from-blue-50 from-10% to-transparent to-50%`}></div>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* content */}
|
|
|
|
|
|
<header className={`flex-none basis-20 flex items-stretch`}>
|
|
|
|
|
|
{/* logo */}
|
|
|
|
|
|
<div className={`flex-none basis-60 flex items-center justify-center`}>
|
|
|
|
|
|
<Image src={logo} alt={`logo`} height={40}/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* title */}
|
|
|
|
|
|
<div className={`flex-auto overflow-hidden flex items-center`}>
|
|
|
|
|
|
欢迎来到,蓝狐代理
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* profile */}
|
|
|
|
|
|
<div className={`flex-none basis-80 flex items-center justify-end`}>
|
|
|
|
|
|
<Profile/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
<div className={`flex-auto overflow-hidden flex items-stretch gap-4`}>
|
|
|
|
|
|
<nav className={merge(
|
|
|
|
|
|
`flex-none basis-60 rounded-tr-xl bg-white p-4`,
|
|
|
|
|
|
`flex flex-col overflow-auto`,
|
|
|
|
|
|
)}>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<NavItem href={'/admin'} icon={`🏠`} label={`账户总览`}/>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
<NavTitle label={`个人信息`}/>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<NavItem href={`/admin`} icon={`📝`} label={`修改信息`}/>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
<NavItem href={`/admin/identify`} icon={`🆔`} label={`实名认证`}/>
|
|
|
|
|
|
<NavItem href={`/admin/whitelist`} icon={`🔒`} label={`白名单`}/>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<NavItem href={`/admin`} icon={`💰`} label={`我的账单`}/>
|
|
|
|
|
|
<NavTitle label={`套餐管理`}/>
|
|
|
|
|
|
<NavItem href={`/admin/purchase`} icon={`🛒`} label={`购买套餐`}/>
|
2025-04-09 17:17:39 +08:00
|
|
|
|
<NavItem href={`/admin/resources`} icon={`📦`} label={`我的套餐`}/>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<NavTitle label={`IP 管理`}/>
|
|
|
|
|
|
<NavItem href={`/admin/extract`} icon={`📤`} label={`IP提取`}/>
|
|
|
|
|
|
<NavItem href={`/admin`} icon={`📜`} label={`IP提取记录`}/>
|
|
|
|
|
|
<NavItem href={`/admin`} icon={`👁️`} label={`查看提取IP`}/>
|
|
|
|
|
|
<NavItem href={`/admin`} icon={`🗂️`} label={`查看使用IP`}/>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
{props.children}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function NavTitle(props: {
|
|
|
|
|
|
label: string
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<p className={`px-4 py-2 text-sm text-gray-500`}>
|
|
|
|
|
|
{props.label}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function NavItem(props: {
|
|
|
|
|
|
href: string
|
|
|
|
|
|
icon?: ReactNode
|
|
|
|
|
|
label: string
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Link className={merge(
|
|
|
|
|
|
`px-4 py-2 flex items-center rounded-md`,
|
|
|
|
|
|
`hover:bg-gray-100`,
|
|
|
|
|
|
)} href={props.href}>
|
2025-04-08 11:21:58 +08:00
|
|
|
|
<span className={`w-6 h-6 flex items-center justify-center`}>{props.icon}</span>
|
2025-04-07 15:42:09 +08:00
|
|
|
|
<span className={`ml-2`}>{props.label}</span>
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|