diff --git a/.env b/.env
index 359f825..0738ae8 100644
--- a/.env
+++ b/.env
@@ -1,3 +1,3 @@
VITE_APP_BASE_URL="/"
VITE_APP_API_URL="//127.0.0.1:5050/api"
-VITE_APP_TITLE="XX系统"
+VITE_APP_TITLE_SUFFIX ="XX系统"
diff --git a/package-lock.json b/package-lock.json
index 71613a6..68f97bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,7 +21,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
- "react-router-dom": "^6.28.0",
+ "react-router-dom": "6.26.2",
"tailwind-merge": "^2.5.4",
"zustand": "^5.0.1"
},
@@ -35,6 +35,7 @@
"@vitejs/plugin-react-swc": "^3.7.1",
"autoprefixer": "^10.4.20",
"eslint": "^9.14.0",
+ "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
@@ -1382,9 +1383,9 @@
}
},
"node_modules/@remix-run/router": {
- "version": "1.21.0",
- "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.21.0.tgz",
- "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==",
+ "version": "1.19.2",
+ "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.19.2.tgz",
+ "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
@@ -3520,6 +3521,19 @@
}
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
"node_modules/eslint-plugin-prettier": {
"version": "5.2.1",
"resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
@@ -5915,12 +5929,12 @@
"license": "MIT"
},
"node_modules/react-router": {
- "version": "6.28.0",
- "resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.28.0.tgz",
- "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==",
+ "version": "6.26.2",
+ "resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.26.2.tgz",
+ "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==",
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.21.0"
+ "@remix-run/router": "1.19.2"
},
"engines": {
"node": ">=14.0.0"
@@ -5930,13 +5944,13 @@
}
},
"node_modules/react-router-dom": {
- "version": "6.28.0",
- "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.28.0.tgz",
- "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==",
+ "version": "6.26.2",
+ "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.26.2.tgz",
+ "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==",
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.21.0",
- "react-router": "6.28.0"
+ "@remix-run/router": "1.19.2",
+ "react-router": "6.26.2"
},
"engines": {
"node": ">=14.0.0"
diff --git a/package.json b/package.json
index 5011daf..195566a 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
- "react-router-dom": "^6.28.0",
+ "react-router-dom": "6.26.2",
"tailwind-merge": "^2.5.4",
"zustand": "^5.0.1"
},
@@ -40,6 +40,7 @@
"@vitejs/plugin-react-swc": "^3.7.1",
"autoprefixer": "^10.4.20",
"eslint": "^9.14.0",
+ "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
@@ -61,4 +62,4 @@
"npm run lint:fix"
]
}
-}
\ No newline at end of file
+}
diff --git a/src/components/helmet/index.tsx b/src/components/helmet/index.tsx
new file mode 100644
index 0000000..fcf88c9
--- /dev/null
+++ b/src/components/helmet/index.tsx
@@ -0,0 +1,15 @@
+import { Helmet } from "react-helmet-async";
+import { useMatches } from "react-router-dom";
+import { at } from "@/utils";
+
+export function AppHelmet() {
+ const matches = useMatches();
+ const currRouter = at(matches, -1);
+ return (
+
+
+ {(currRouter?.handle as any)?.title || "React"} | {import.meta.env.VITE_APP_TITLE_SUFFIX}
+
+
+ );
+}
diff --git a/src/layouts/components/Breadcrumb.tsx b/src/layouts/components/bread-crumb.tsx
similarity index 100%
rename from src/layouts/components/Breadcrumb.tsx
rename to src/layouts/components/bread-crumb.tsx
diff --git a/src/layouts/components/Content.tsx b/src/layouts/components/main-content.tsx
similarity index 82%
rename from src/layouts/components/Content.tsx
rename to src/layouts/components/main-content.tsx
index a57b1b9..1477663 100644
--- a/src/layouts/components/Content.tsx
+++ b/src/layouts/components/main-content.tsx
@@ -6,7 +6,7 @@ export default function Content() {
const matches = useMatches();
const currRouter = matches.at(-1);
return (
-
+
diff --git a/src/layouts/components/Sider.tsx b/src/layouts/components/sider-bar.tsx
similarity index 92%
rename from src/layouts/components/Sider.tsx
rename to src/layouts/components/sider-bar.tsx
index 26201c2..f1a12b3 100644
--- a/src/layouts/components/Sider.tsx
+++ b/src/layouts/components/sider-bar.tsx
@@ -45,15 +45,15 @@ const items: MenuProps["items"] = [
{
icon: ,
label: "一级菜单",
- key: "/nav",
+ key: "/nest-menu",
children: [
{
- key: "/nav/sub-1",
- label: 二级菜单-1,
+ key: "/nest-menu/sub-menu-1",
+ label: 二级菜单-1,
},
{
- key: "/nav/sub-2",
- label: 二级菜单-2,
+ key: "/nest-menu/sub-menu-2",
+ label: 二级菜单-2,
},
],
},
@@ -64,7 +64,7 @@ const items: MenuProps["items"] = [
},
];
-export default function Sider() {
+export default function SiderBar() {
const location = useLocation();
const firstRenderRef = useRef(true);
diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx
index cf3ab71..b364203 100644
--- a/src/layouts/index.tsx
+++ b/src/layouts/index.tsx
@@ -1,36 +1,63 @@
+import { useEffect } from "react";
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { Button, Flex, Layout } from "antd";
+import { AppHelmet } from "@/components/helmet";
import { ThemeSwitch } from "@/components/theme-switch";
-import Breadcrumb from "./components/breadcrumb";
-import Content from "./components/content";
+import Breadcrumb from "./components/bread-crumb";
import CustomSkin from "./components/custom-skin";
-import Sider from "./components/sider";
+import Content from "./components/main-content";
+import SiderBar from "./components/sider-bar";
import UserAvatar from "./components/user-avatar";
import { setCollapsed, useSelector, useSettingsStore } from "@/stores";
export default function MainLayout() {
const { collapsed } = useSettingsStore(useSelector(["collapsed"]));
+ // 设置header阴影
+ useEffect(() => {
+ const handleScroll = () => {
+ const scrollTop = document.scrollingElement?.scrollTop || document.body.scrollTop;
+ const className = "shadow-[0_6px_10px_-10px_rgba(0,0,0,0.3)]";
+ if (scrollTop > 0) {
+ document.getElementById("app-header-bar")?.classList.add(className);
+ } else {
+ document.getElementById("app-header-bar")?.classList.remove(className);
+ }
+ };
+ window.addEventListener("scroll", handleScroll);
+ return () => {
+ window.removeEventListener("scroll", handleScroll);
+ };
+ }, []);
+
+ console.log("out 👉: ");
+
return (
-
-
+ <>
+
-
- : }
- onClick={() => setCollapsed(!collapsed)}
- className="mr-2"
- />
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+ >
);
}
diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx
index db137ef..df983b6 100644
--- a/src/pages/landing/index.tsx
+++ b/src/pages/landing/index.tsx
@@ -1,4 +1,3 @@
-import { Helmet } from "react-helmet-async";
import { Button, DatePicker, Flex, Typography } from "antd";
import { Test1 } from "./components/test-1";
import { Test2 } from "./components/test-2";
@@ -8,9 +7,6 @@ const { RangePicker } = DatePicker;
export default function LandingPage() {
return (
<>
-
- 首页 | {import.meta.env.VITE_APP_TITLE}
-
首页
diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx
index 959a91b..82fd0c2 100644
--- a/src/pages/login/index.tsx
+++ b/src/pages/login/index.tsx
@@ -10,7 +10,7 @@ export default function Login() {
return (
<>
- 登录页 | {import.meta.env.VITE_APP_TITLE}
+ 登录页 | {import.meta.env.VITE_APP_TITLE_SUFFIX}
diff --git a/src/pages/nav/index.tsx b/src/pages/nav/index.tsx
deleted file mode 100644
index 26f2264..0000000
--- a/src/pages/nav/index.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Helmet } from "react-helmet-async";
-import { Outlet } from "react-router-dom";
-
-export default function NavLayout() {
- return (
- <>
-
- 导航页 | {import.meta.env.VITE_APP_TITLE}
-
-
- Nav Layout
-
-
- >
- );
-}
diff --git a/src/pages/nest-menu/index.tsx b/src/pages/nest-menu/index.tsx
new file mode 100644
index 0000000..e9fdabb
--- /dev/null
+++ b/src/pages/nest-menu/index.tsx
@@ -0,0 +1,10 @@
+import { Outlet } from "react-router-dom";
+
+export default function NavLayout() {
+ return (
+
+ Nav Layout
+
+
+ );
+}
diff --git a/src/pages/nav/sub-nav-1/index.tsx b/src/pages/nest-menu/sub-menu-1/index.tsx
similarity index 100%
rename from src/pages/nav/sub-nav-1/index.tsx
rename to src/pages/nest-menu/sub-menu-1/index.tsx
diff --git a/src/pages/nav/sub-nav-2/index.tsx b/src/pages/nest-menu/sub-menu-2/index.tsx
similarity index 100%
rename from src/pages/nav/sub-nav-2/index.tsx
rename to src/pages/nest-menu/sub-menu-2/index.tsx
diff --git a/src/pages/not-found/index.tsx b/src/pages/not-found/index.tsx
index a83290a..b76a0db 100644
--- a/src/pages/not-found/index.tsx
+++ b/src/pages/not-found/index.tsx
@@ -7,7 +7,7 @@ export default function NotFound() {
return (
<>
- 404 | {import.meta.env.VITE_APP_TITLE}
+ 404 | {import.meta.env.VITE_APP_TITLE_SUFFIX}
["columns"] = [
export default function UserManagement() {
const { data, isFetching } = useUserList();
- return (
- <>
-
- 用户管理 | {import.meta.env.VITE_APP_TITLE}
-
-
- >
- );
+ return ;
}
diff --git a/src/router/index.tsx b/src/router/index.tsx
index 5140d34..18d97f1 100644
--- a/src/router/index.tsx
+++ b/src/router/index.tsx
@@ -1,7 +1,7 @@
import { createBrowserRouter, Navigate, type RouteObject } from "react-router-dom";
import { echartsDemoRoute } from "./modules/echarts-demo";
import { landingRoute } from "./modules/landing";
-import { navRoute } from "./modules/nav";
+import { nestMenuRoute } from "./modules/nest-menu";
import { userManagerRoute } from "./modules/user-management";
const routes: RouteObject[] = [
@@ -23,7 +23,7 @@ const routes: RouteObject[] = [
},
landingRoute,
userManagerRoute,
- navRoute,
+ nestMenuRoute,
echartsDemoRoute,
],
},
diff --git a/src/router/modules/echarts-demo.tsx b/src/router/modules/echarts-demo.tsx
index 5969b55..ca53e4a 100644
--- a/src/router/modules/echarts-demo.tsx
+++ b/src/router/modules/echarts-demo.tsx
@@ -6,6 +6,7 @@ export const echartsDemoRoute: RouteObject = {
Component: (await import("@/pages/echarts-demo/layout")).default,
}),
handle: {
+ title: "Echarts Demo",
crumb: () => Echarts Demo,
},
};
diff --git a/src/router/modules/landing.tsx b/src/router/modules/landing.tsx
index c81039e..b163f08 100644
--- a/src/router/modules/landing.tsx
+++ b/src/router/modules/landing.tsx
@@ -5,4 +5,7 @@ export const landingRoute: RouteObject = {
lazy: async () => ({
Component: (await import("@/pages/landing")).default,
}),
+ handle: {
+ title: "首页",
+ },
};
diff --git a/src/router/modules/nav.tsx b/src/router/modules/nav.tsx
deleted file mode 100644
index 501589f..0000000
--- a/src/router/modules/nav.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Link, type RouteObject } from "react-router-dom";
-
-export const navRoute: RouteObject = {
- path: "nav",
- lazy: async () => ({
- Component: (await import("@/pages/nav")).default,
- }),
- handle: {
- crumb: () => "一级菜单",
- },
- children: [
- {
- path: "sub-1",
- lazy: async () => ({
- Component: (await import("@/pages/nav/sub-nav-1")).default,
- }),
- handle: {
- crumb: () => 二级菜单-1,
- },
- },
- {
- path: "sub-2",
- lazy: async () => ({
- Component: (await import("@/pages/nav/sub-nav-2")).default,
- }),
- handle: {
- crumb: () => 二级菜单-2,
- },
- },
- ],
-};
diff --git a/src/router/modules/nest-menu.tsx b/src/router/modules/nest-menu.tsx
new file mode 100644
index 0000000..1af17cd
--- /dev/null
+++ b/src/router/modules/nest-menu.tsx
@@ -0,0 +1,34 @@
+import { Link, type RouteObject } from "react-router-dom";
+
+export const nestMenuRoute: RouteObject = {
+ path: "nest-menu",
+ lazy: async () => ({
+ Component: (await import("@/pages/nest-menu")).default,
+ }),
+ handle: {
+ title: "嵌套菜单",
+ crumb: () => "嵌套菜单",
+ },
+ children: [
+ {
+ path: "sub-menu-1",
+ lazy: async () => ({
+ Component: (await import("@/pages/nest-menu/sub-menu-1")).default,
+ }),
+ handle: {
+ title: "二级菜单-1",
+ crumb: () => 二级菜单-1,
+ },
+ },
+ {
+ path: "sub-menu-2",
+ lazy: async () => ({
+ Component: (await import("@/pages/nest-menu/sub-menu-2")).default,
+ }),
+ handle: {
+ title: "二级菜单-2",
+ crumb: () => 二级菜单-2,
+ },
+ },
+ ],
+};
diff --git a/src/router/modules/user-management.tsx b/src/router/modules/user-management.tsx
index 8cc7601..6d9829a 100644
--- a/src/router/modules/user-management.tsx
+++ b/src/router/modules/user-management.tsx
@@ -6,6 +6,7 @@ export const userManagerRoute: RouteObject = {
Component: (await import("@/pages/user-management")).default,
}),
handle: {
+ title: "用户管理",
crumb: () => 用户管理,
},
};
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index 31cbe09..d784963 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -4,7 +4,7 @@
interface ImportMetaEnv {
readonly VITE_APP_BASE_URL: string;
readonly VITE_APP_API_URL: string;
- readonly VITE_APP_TITLE: string;
+ readonly VITE_APP_TITLE_SUFFIX: string;
}
interface ImportMeta {