Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { Header } from "@/components/layout/header";
|
||||
import Link from "next/link";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
LayoutDashboard,
|
||||
Building2,
|
||||
UsersRound,
|
||||
Boxes,
|
||||
ScrollText,
|
||||
Cpu,
|
||||
Gauge,
|
||||
ShieldAlert,
|
||||
Menu,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
|
||||
const platformNavItems: { href: string; label: string; icon: LucideIcon }[] = [
|
||||
{ href: "/platform/overview", label: "平台总览", icon: LayoutDashboard },
|
||||
{ href: "/platform/orgs", label: "机构管理", icon: Building2 },
|
||||
{ href: "/platform/users", label: "全局用户", icon: UsersRound },
|
||||
{ href: "/platform/apps", label: "全局应用", icon: Boxes },
|
||||
{ href: "/platform/audit", label: "全局审计", icon: ScrollText },
|
||||
{ href: "/platform/providers", label: "模型提供商", icon: Cpu },
|
||||
{ href: "/platform/quotas", label: "配额管理", icon: Gauge },
|
||||
];
|
||||
|
||||
export default function PlatformLayout({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
||||
const isLoading = useAuthStore((s) => s.isLoading);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && (!isAuthenticated || user?.role !== "super_admin")) {
|
||||
router.replace("/store");
|
||||
}
|
||||
}, [isAuthenticated, isLoading, user, router]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex h-screen items-center justify-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAuthenticated || user?.role !== "super_admin") return null;
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<Header />
|
||||
<div className="flex flex-1 relative">
|
||||
{/* 平台管理区身份标识条 */}
|
||||
<div className="hidden md:block absolute top-0 left-56 right-0 h-1 bg-gradient-to-r from-amber-500 via-orange-500 to-amber-500 z-10" />
|
||||
|
||||
{/* 手机端侧边栏切换按钮 */}
|
||||
<button
|
||||
className="md:hidden fixed bottom-4 right-4 z-50 p-3 rounded-full bg-amber-600 text-white shadow-lg"
|
||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||
>
|
||||
{sidebarOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
|
||||
</button>
|
||||
|
||||
{sidebarOpen && (
|
||||
<div
|
||||
className="fixed inset-0 z-40 bg-black/40 md:hidden"
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<aside
|
||||
className={`fixed inset-y-[3.5rem] left-0 z-50 w-56 border-r bg-background transition-transform duration-200 md:static md:inset-y-0 md:translate-x-0 ${
|
||||
sidebarOpen ? "translate-x-0" : "-translate-x-full"
|
||||
}`}
|
||||
>
|
||||
<div className="px-3 py-3 border-b bg-amber-50/50 dark:bg-amber-950/20">
|
||||
<div className="flex items-center gap-2 text-sm font-medium text-amber-900 dark:text-amber-200">
|
||||
<ShieldAlert className="h-4 w-4" />
|
||||
平台管理控制台
|
||||
</div>
|
||||
<p className="text-[11px] text-amber-700/70 dark:text-amber-300/60 mt-0.5">
|
||||
跨机构最高权限
|
||||
</p>
|
||||
</div>
|
||||
<nav className="p-3 space-y-1">
|
||||
{platformNavItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-3 py-2 rounded-md text-sm transition-colors",
|
||||
pathname === item.href ? "bg-amber-600 text-white" : "hover:bg-muted",
|
||||
)}
|
||||
>
|
||||
<item.icon className="h-4 w-4" />
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
<main className="flex-1 p-3 md:p-6 min-w-0">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user