+ {/**/}
+
+ {/*');
diff --git a/app/app/(admin)/admin/layout.tsx b/app/app/(admin)/admin/layout.tsx
new file mode 100644
index 000000000..007c748a6
--- /dev/null
+++ b/app/app/(admin)/admin/layout.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import React, { ReactNode, useState } from "react";
+import {
+ MenuFoldOutlined,
+ MenuUnfoldOutlined,
+ UploadOutlined,
+ UserOutlined,
+ VideoCameraOutlined,
+} from "@ant-design/icons";
+import { Layout, Menu, Button, theme, ConfigProvider, ThemeConfig } from "antd";
+import SideBar from "../components/sidebar";
+
+const { Header, Sider, Content } = Layout;
+
+function MainLayout({ children }: { children: ReactNode }) {
+ // const [theme, setTheme] = useState
('dark');
+
+ const [collapsed, setCollapsed] = useState(false);
+ const {
+ token: { colorBgContainer, borderRadiusLG, colorBgLayout },
+ } = theme.useToken();
+
+ return (
+
+
+
+ *
+
+
+
+
+
+ : }
+ onClick={() => setCollapsed(!collapsed)}
+ style={{
+ fontSize: "16px",
+ width: 64,
+ height: 64,
+ }}
+ />
+
+
+ {children}
+
+
+
+
+ );
+}
+
+export default MainLayout;
diff --git a/app/app/(admin)/admin/page.tsx b/app/app/(admin)/admin/page.tsx
index eb6414360..0775d6be9 100644
--- a/app/app/(admin)/admin/page.tsx
+++ b/app/app/(admin)/admin/page.tsx
@@ -1,29 +1,74 @@
-import { Grid, Col } from "@tremor/react";
-import UsageByModel from "./usage-by-model-chart";
-import { getSession } from "@/lib/auth";
-import { isName, ADMIN_LIST } from "@/lib/auth_list";
-import { redirect } from "next/navigation";
+"use client";
-export default async function AdminPage() {
- const session = await getSession();
- if (!(session?.user?.name && ADMIN_LIST.includes(session.user.name))) {
- // Replace '/dashboard' with the desired redirect path
- redirect("/");
- }
+import React, { useState } from "react";
+import {
+ AppstoreOutlined,
+ MailOutlined,
+ SettingOutlined,
+} from "@ant-design/icons";
+import type { MenuProps, MenuTheme } from "antd";
+
+type MenuItem = Required["items"][number];
+
+function getItem(
+ label: React.ReactNode,
+ key?: React.Key | null,
+ icon?: React.ReactNode,
+ children?: MenuItem[],
+ type?: "group",
+): MenuItem {
+ return {
+ key,
+ icon,
+ children,
+ label,
+ type,
+ } as MenuItem;
+}
+
+const items: MenuItem[] = [
+ getItem("Navigation One", "sub1", , [
+ getItem("Option 1", "1"),
+ getItem("Option 2", "2"),
+ getItem("Option 3", "3"),
+ getItem("Option 4", "4"),
+ ]),
+
+ getItem("Navigation Two", "sub2", , [
+ getItem("Option 5", "5"),
+ getItem("Option 6", "6"),
+ getItem("Submenu", "sub3", null, [
+ getItem("Option 7", "7"),
+ getItem("Option 8", "8"),
+ ]),
+ ]),
+
+ getItem("Navigation Three", "sub4", , [
+ getItem("Option 9", "9"),
+ getItem("Option 10", "10"),
+ getItem("Option 11", "11"),
+ getItem("Option 12", "12"),
+ ]),
+];
+
+const App: React.FC = () => {
+ const [theme, setTheme] = useState("dark");
+ const [current, setCurrent] = useState("1");
+
+ const changeTheme = (value: boolean) => {
+ setTheme(value ? "dark" : "light");
+ };
+
+ const onClick: MenuProps["onClick"] = (e) => {
+ console.log("click ", e);
+ setCurrent(e.key);
+ };
return (
<>
-
-
- {/**/}
- {/**/}
- {/**/}
- {/**/}
-
-
-
-
-
+ Admin Page
>
);
-}
+};
+
+export default App;
diff --git a/app/app/(admin)/components/sidebar.tsx b/app/app/(admin)/components/sidebar.tsx
new file mode 100644
index 000000000..195f419bf
--- /dev/null
+++ b/app/app/(admin)/components/sidebar.tsx
@@ -0,0 +1,113 @@
+"use client";
+
+import React, { useEffect, useState } from "react";
+import Link from "next/link";
+import { useRouter, usePathname } from "next/navigation";
+
+import {
+ AppstoreOutlined,
+ MailOutlined,
+ SettingOutlined,
+ DashboardTwoTone,
+} from "@ant-design/icons";
+import type { MenuProps, MenuTheme } from "antd";
+import { Menu, Switch } from "antd";
+
+type MenuItem = Required["items"][number];
+
+function getItem(
+ label: React.ReactNode,
+ key?: React.Key | null,
+ icon?: React.ReactNode,
+ children?: MenuItem[],
+ type?: "group",
+): MenuItem {
+ return {
+ key,
+ icon,
+ children,
+ label,
+ type,
+ } as MenuItem;
+}
+
+const items: MenuItem[] = [
+ getItem("面板", "dashboard", , [
+ getItem("使用分析", "/admin/ana"),
+ ]),
+
+ getItem("Navigation Two", "sub2", , [
+ getItem("Option 5", "5"),
+ getItem("Option 6", "6"),
+ getItem("Submenu", "sub3", null, [
+ getItem("Option 7", "7"),
+ getItem("Option 8", "8"),
+ ]),
+ ]),
+
+ getItem("Navigation Three", "sub4", , [
+ getItem("Option 9", "9"),
+ getItem("Option 10", "10"),
+ getItem("Option 11", "11"),
+ getItem("Option 12", "12"),
+ ]),
+];
+
+const SideBar: React.FC = () => {
+ const [theme, setTheme] = useState("dark");
+ const [current, setCurrent] = useState("/admin/ana");
+ const router = useRouter();
+ const [loading, setLoading] = useState(false);
+ const pathname = usePathname();
+ // const changeTheme = (value: boolean) => {
+ // setTheme(value ? 'dark' : 'light');
+ // };
+
+ const onClick: MenuProps["onClick"] = (e) => {
+ console.log("click ", e);
+ setCurrent(e.key);
+ router.push(e.key);
+ };
+ useEffect(() => {
+ // 如果按钮和路径不相等,那其实应该跳转到按钮的网址
+ if (current != pathname) {
+ router.push(current);
+ }
+ }, []);
+ // useEffect(() => {
+ // const handleStart = () => setLoading(true)
+ // const handleComplete = () => setLoading(false);
+ // router.events.on('routeChangeStart', handleStart);
+ // router.events.on('routeChangeComplete', handleStop);
+ // router.events.on('routeChangeError', handleStop);
+ //
+ // return () => {
+ // router.
+ // }
+ //
+ // }, [router]);
+
+ return (
+ <>
+ {/**/}
+
+
+
+ >
+ );
+};
+
+export default SideBar;
diff --git a/app/app/(admin)/layout.tsx b/app/app/(admin)/layout.tsx
index 240c0e232..e17e6a7b8 100644
--- a/app/app/(admin)/layout.tsx
+++ b/app/app/(admin)/layout.tsx
@@ -1,26 +1,30 @@
import "@/app/app/login.scss";
import { Metadata } from "next";
import { ReactNode } from "react";
+import { AntdRegistry } from "@ant-design/nextjs-registry";
+// import Head from "next/head";
export const metadata: Metadata = {
title: "Admin | 管理页面",
};
-export default async function AdminLayout({
- children,
-}: {
- children: ReactNode;
-}) {
+export default function AdminLayout({ children }: { children: ReactNode }) {
return (
-
-
-
- Admin Page
-
-
- {children}
-
-
-
+ <>
+
+ {children}
+
+ {/**/}
+ {/*
*/}
+ {/*
*/}
+ {/* Admin Page*/}
+ {/*
*/}
+ {/*
*/}
+ {/* {children}*/}
+ {/*
*/}
+ {/*
*/}
+ {/*
*/}
+
+ >
);
}
diff --git a/middleware.ts b/middleware.ts
index baf4bbe96..f26af4795 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -37,7 +37,7 @@ export default async function middleware(req: NextRequest) {
new URL(`/app${path}`, req.url),
);
}
- if (path == "/admin") {
+ if (path.startsWith("/admin")) {
return NextResponse.rewrite(
new URL(`/app${path}`, req.url),
);
diff --git a/package.json b/package.json
index d6f255abc..ac72b8ef4 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev"
},
"dependencies": {
+ "@ant-design/nextjs-registry": "^1.0.0",
"@fortaine/fetch-event-source": "^3.0.6",
"@hello-pangea/dnd": "^16.5.0",
"@next-auth/prisma-adapter": "^1.0.7",
@@ -25,6 +26,7 @@
"@tremor/react": "^3.13.4",
"@vercel/analytics": "^1.1.2",
"@vercel/speed-insights": "^1.0.9",
+ "antd": "^5.15.1",
"echarts": "^5.4.3",
"emoji-picker-react": "^4.7.10",
"fuse.js": "^7.0.0",
@@ -85,4 +87,4 @@
"resolutions": {
"lint-staged/yaml": "^2.2.2"
}
-}
\ No newline at end of file
+}