diff --git a/nkebao/package.json b/nkebao/package.json
index cfa0f01b..f9f4ac6e 100644
--- a/nkebao/package.json
+++ b/nkebao/package.json
@@ -8,7 +8,8 @@
"axios": "^1.6.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-router-dom": "^6.20.0"
+ "react-router-dom": "^6.20.0",
+ "zustand": "^5.0.6"
},
"devDependencies": {
"@types/node": "^24.0.14",
diff --git a/nkebao/src/App.tsx b/nkebao/src/App.tsx
index bb423eff..4437b140 100644
--- a/nkebao/src/App.tsx
+++ b/nkebao/src/App.tsx
@@ -1,22 +1,17 @@
import React from "react";
-import { BrowserRouter, Routes, Route } from "react-router-dom";
+import AppRouter from "@/router";
import { Button } from "antd";
import { Button as MobileButton } from "antd-mobile";
-import Home from "./pages/Home";
-import About from "./pages/About";
function App() {
return (
-
-
- } />
- } />
-
+ <>
+
Antd-Mobile 按钮
-
+ >
);
}
diff --git a/nkebao/src/api/request.ts b/nkebao/src/api/request.ts
index aaa2dca1..bd7a086a 100644
--- a/nkebao/src/api/request.ts
+++ b/nkebao/src/api/request.ts
@@ -1,4 +1,5 @@
import axios, { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse } from 'axios';
+import { Toast } from 'antd-mobile';
const DEBOUNCE_GAP = 1000;
const debounceMap = new Map();
@@ -22,14 +23,28 @@ instance.interceptors.request.use(config => {
instance.interceptors.response.use(
(res: AxiosResponse) => {
- if (res.data && (res.data.code === 200 || res.data.success)) {
+ const { code, success, msg } = res.data || {};
+ if (code === 200 || success) {
return res.data.data ?? res.data;
}
- window?.alert?.(res.data?.msg || '接口错误');
- return Promise.reject(res.data?.msg || '接口错误');
+ // 业务错误统一提示
+ Toast.show({ content: msg || '接口错误', position: 'top' });
+ // 分类处理
+ if (code === 401) {
+ // 未登录或登录失效
+ // 可跳转登录页或清除 token
+ localStorage.removeItem('token');
+ } else if (code === 403) {
+ // 无权限
+ // 可做特殊处理
+ } else if (code === 500) {
+ // 服务端异常
+ }
+ return Promise.reject(msg || '接口错误');
},
err => {
- window?.alert?.(err.message || '网络异常');
+ // 网络错误、超时等
+ Toast.show({ content: err.message || '网络异常', position: 'top' });
return Promise.reject(err);
}
);
@@ -44,6 +59,7 @@ export function request(
const now = Date.now();
const last = debounceMap.get(key) || 0;
if (now - last < DEBOUNCE_GAP) {
+ Toast.show({ content: '请求过于频繁,请稍后再试', position: 'top' });
return Promise.reject('请求过于频繁,请稍后再试');
}
debounceMap.set(key, now);
diff --git a/nkebao/src/router/index.tsx b/nkebao/src/router/index.tsx
new file mode 100644
index 00000000..0c58db7e
--- /dev/null
+++ b/nkebao/src/router/index.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+import { BrowserRouter, useRoutes } from "react-router-dom";
+import homeRoutes from "./module/home";
+import aboutRoutes from "./module/about";
+import PermissionRoute from "./permissionRoute";
+
+function wrapWithPermission(route) {
+ if (route.auth) {
+ return {
+ ...route,
+ element: (
+
+ {route.element}
+
+ ),
+ };
+ }
+ return route;
+}
+
+const routes = [
+ ...homeRoutes.map(wrapWithPermission),
+ ...aboutRoutes.map(wrapWithPermission),
+];
+
+const AppRoutes = () => useRoutes(routes);
+
+const AppRouter: React.FC = () => (
+
+
+
+);
+
+export default AppRouter;
diff --git a/nkebao/src/router/module/about.tsx b/nkebao/src/router/module/about.tsx
new file mode 100644
index 00000000..d76d7e08
--- /dev/null
+++ b/nkebao/src/router/module/about.tsx
@@ -0,0 +1,10 @@
+import About from "@/pages/About";
+
+const aboutRoutes = [
+ {
+ path: "/about",
+ element: ,
+ },
+];
+
+export default aboutRoutes;
diff --git a/nkebao/src/router/module/home.tsx b/nkebao/src/router/module/home.tsx
new file mode 100644
index 00000000..a4c5247a
--- /dev/null
+++ b/nkebao/src/router/module/home.tsx
@@ -0,0 +1,17 @@
+import Home from "@/pages/Home";
+
+const homeRoutes = [
+ {
+ path: "/",
+ element: ,
+ auth: false, // 不需要权限
+ },
+ {
+ path: "/dashboard",
+ element: ,
+ auth: true, // 需要登录
+ requiredRole: "admin", // 需要 admin 角色
+ },
+];
+
+export default homeRoutes;
diff --git a/nkebao/src/router/permissionRoute.tsx b/nkebao/src/router/permissionRoute.tsx
new file mode 100644
index 00000000..66b0b3dc
--- /dev/null
+++ b/nkebao/src/router/permissionRoute.tsx
@@ -0,0 +1,28 @@
+import React from "react";
+import { Navigate, useLocation } from "react-router-dom";
+import { useUserStore } from "@/store/module/user"; // 假设你用 zustand 管理用户状态
+
+interface Props {
+ children: React.ReactNode;
+ requiredRole?: string; // 可选:需要的角色
+}
+
+const PermissionRoute: React.FC = ({ children, requiredRole }) => {
+ const user = useUserStore((state) => state.user);
+ const location = useLocation();
+
+ // 未登录
+ if (!user) {
+ return ;
+ }
+
+ // 有角色要求但不满足
+ if (requiredRole && user.role !== requiredRole) {
+ return ;
+ }
+
+ // 通过
+ return <>{children}>;
+};
+
+export default PermissionRoute;
diff --git a/nkebao/src/store/index.ts b/nkebao/src/store/index.ts
new file mode 100644
index 00000000..8edf9c6e
--- /dev/null
+++ b/nkebao/src/store/index.ts
@@ -0,0 +1,2 @@
+export * from './module/user';
+// 未来可继续合并其他模块
\ No newline at end of file
diff --git a/nkebao/src/store/module/user.ts b/nkebao/src/store/module/user.ts
new file mode 100644
index 00000000..63202e04
--- /dev/null
+++ b/nkebao/src/store/module/user.ts
@@ -0,0 +1,20 @@
+// src/store/user.ts
+import { create } from 'zustand';
+
+export interface User {
+ name: string;
+ role: string;
+ token: string;
+}
+
+interface UserState {
+ user: User | null;
+ setUser: (user: User) => void;
+ clearUser: () => void;
+}
+
+export const useUserStore = create((set) => ({
+ user: null,
+ setUser: (user) => set({ user }),
+ clearUser: () => set({ user: null }),
+}));
\ No newline at end of file