From 9d18af22f10deb093b06b279da4d105c48ec1933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Thu, 17 Jul 2025 22:19:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B=20store?= =?UTF-8?q?=20=E5=92=8C=20router=20=E5=B0=81=E8=A3=85=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/package.json | 3 ++- nkebao/src/App.tsx | 13 ++++------ nkebao/src/api/request.ts | 24 +++++++++++++++---- nkebao/src/router/index.tsx | 34 +++++++++++++++++++++++++++ nkebao/src/router/module/about.tsx | 10 ++++++++ nkebao/src/router/module/home.tsx | 17 ++++++++++++++ nkebao/src/router/permissionRoute.tsx | 28 ++++++++++++++++++++++ nkebao/src/store/index.ts | 2 ++ nkebao/src/store/module/user.ts | 20 ++++++++++++++++ 9 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 nkebao/src/router/index.tsx create mode 100644 nkebao/src/router/module/about.tsx create mode 100644 nkebao/src/router/module/home.tsx create mode 100644 nkebao/src/router/permissionRoute.tsx create mode 100644 nkebao/src/store/index.ts create mode 100644 nkebao/src/store/module/user.ts 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