From 5159e7c90ddf0824421722f489e244433ab6da43 Mon Sep 17 00:00:00 2001 From: xie2can <384968446@qq.com> Date: Fri, 15 May 2026 19:31:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8C=E6=9B=B4=E6=96=B0=20AGENTS.md=20?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 66 +++++++++++++++++++++++--------- src/api/auth.ts | 23 +++++++++++ src/mock/auth.ts | 19 ++++++++++ src/mock/index.ts | 3 +- src/pages/login/index.tsx | 80 +++++++++++++++++++++++++++++++++++++++ src/router.tsx | 4 ++ 6 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 src/api/auth.ts create mode 100644 src/mock/auth.ts create mode 100644 src/pages/login/index.tsx diff --git a/AGENTS.md b/AGENTS.md index 01bd66c..ef0348b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,31 +22,61 @@ ``` src/ - index.tsx # 应用入口,将 React 根节点挂载到 #root - App.tsx # 根组件,渲染 ,包含 ConfigProvider / AntdApp 全局配置 - App.css # 全局样式(reset) - router.tsx # createBrowserRouter,由路由树自动生成 - env.d.ts # Rsbuild 环境变量类型声明(ImportMetaEnv) + index.tsx # 应用入口,挂载 React 根节点 + 启动 MSW mock + App.tsx # 根组件,ConfigProvider / AntdApp / RouterProvider + App.css # 全局样式(reset) + router.tsx # createBrowserRouter,登录页独立路由 + 布局子路由 + env.d.ts # Rsbuild 环境变量类型声明(ImportMetaEnv) routes/ - types.ts # RouteItem 类型定义 - index.tsx # 路由树数据(唯一数据源),导出 routes / RouteItem - utils.tsx # toRouteObjects():将路由树转为 React Router RouteObject[] + types.ts # RouteItem 类型定义 + index.tsx # 路由树数据(唯一数据源),导出 routes / RouteItem + utils.tsx # toRouteObjects():将路由树转为 React Router RouteObject[] layouts/ - RootLayout.tsx # 根布局(Header + Sider + Content) + RootLayout.tsx # 根布局(Header + Sider + Content) + SystemLayout.tsx # 系统配置布局(,作为 /system 父路由容器) + api/ + auth.ts # 登录接口 + system/ + user.ts # 部门 / 用户接口 + role.ts # 角色接口 + store/ + index.ts # 统一导出入口 + app.ts # 全局应用状态(侧边栏折叠等) + user.ts # 用户状态(userInfo / token) + mock/ + index.ts # MSW worker 初始化,汇总所有 handlers + auth.ts # 登录 mock + system.ts # 部门 / 用户 / 角色 mock pages/ - Home.tsx # "/" 首页 - About.tsx # "/about" 关于页 - NotFound.tsx # "*" 兜底 404 页 + login/ + index.tsx # "/login" 登录页(不加载布局) + home/ + index.tsx # "/" 首页 + about/ + index.tsx # "/about" 关于页 + not-found/ + index.tsx # "*" 兜底 404 页 + system/ + user/ + index.tsx # "/system/user" 用户管理入口 + DeptTree.tsx # 部门树组件 + DeptModal.tsx # 部门弹窗组件 + UserTable.tsx # 用户表格组件 + UserModal.tsx # 用户弹窗组件 + role/ + index.tsx # "/system/role" 角色管理入口 + RoleTable.tsx # 角色表格组件 + RoleModal.tsx # 角色弹窗组件 types/ - http.d.ts # 全局 API 命名空间(无需 import 直接使用 API.Response) + http.d.ts # 全局 API 命名空间(无需 import 直接使用 API.Response) utils/ - request.ts # axios 实例封装,导出 get / post / put / del -.env # 本地环境变量(已 gitignore,勿提交) -.env.example # 环境变量模板(提交到仓库供参考) + request.ts # axios 实例封装,导出 get / post(自动附加 token) +.env # 本地环境变量(已 gitignore,勿提交) +.env.example # 环境变量模板(提交到仓库供参考) public/ favicon.png -rsbuild.config.ts # 构建配置 -eslint.config.mjs # ESLint 扁平配置(仅作用于 TS/TSX,忽略 dist/) +rsbuild.config.ts # 构建配置 +eslint.config.mjs # ESLint 扁平配置(仅作用于 TS/TSX,忽略 dist/) tsconfig.json ``` diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..ff738bd --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,23 @@ +import { post } from '@/utils/request'; + +/** 登录请求参数(不导出) */ +interface LoginParams { + tenantId: string; + userName: string; + password: string; +} + +/** 登录响应数据(不导出) */ +interface LoginResult { + id: string; + userName: string; + nickName: string; + roles: string[]; + token: string; +} + +/** + * 登录接口 + * @param data 登录参数 + */ +export const login = (data: LoginParams) => post('/api/auth/login', data); diff --git a/src/mock/auth.ts b/src/mock/auth.ts new file mode 100644 index 0000000..5363e40 --- /dev/null +++ b/src/mock/auth.ts @@ -0,0 +1,19 @@ +import { http, HttpResponse } from 'msw'; + +/** 包装为统一响应格式 */ +const ok = (data: unknown) => ({ code: '0', msg: 'ok', data, time: Date.now(), ok: true }); + +export const authHandlers = [ + http.post('/api/auth/login', async ({ request }) => { + const body = await request.json() as { tenantId: string; userName: string; password: string }; + // 模拟登录:任意租户号 + 用户名密码均返回成功 + const result = { + id: '1', + userName: body.userName, + nickName: body.userName === 'admin' ? '管理员' : body.userName, + roles: ['admin'], + token: `mock_token_${Date.now()}`, + }; + return HttpResponse.json(ok(result)); + }), +]; diff --git a/src/mock/index.ts b/src/mock/index.ts index 8571738..3c764dc 100644 --- a/src/mock/index.ts +++ b/src/mock/index.ts @@ -1,7 +1,8 @@ import { setupWorker } from 'msw/browser'; +import { authHandlers } from './auth'; import { systemHandlers } from './system'; /** 汇总所有模块的 mock handlers */ -const worker = setupWorker(...systemHandlers); +const worker = setupWorker(...authHandlers, ...systemHandlers); export default worker; diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx new file mode 100644 index 0000000..10388cb --- /dev/null +++ b/src/pages/login/index.tsx @@ -0,0 +1,80 @@ +import { LockOutlined, UserOutlined } from '@ant-design/icons'; +import { App, Button, Card, Form, Input } from 'antd'; +import { useNavigate } from 'react-router'; +import { login } from '@/api/auth'; +import { useUserStore } from '@/store'; + +/** 登录表单字段 */ +interface LoginFormValues { + tenantId: string; + userName: string; + password: string; +} + +/** 登录页面(不加载布局) */ +const Login = () => { + const navigate = useNavigate(); + const { message } = App.useApp(); + const setUserInfo = useUserStore((s) => s.setUserInfo); + const [form] = Form.useForm(); + + /** 登录提交 */ + const handleLogin = async (values: LoginFormValues) => { + const res = await login(values); + const data = res.data!; + setUserInfo({ + id: data.id, + userName: data.userName, + nickName: data.nickName, + roles: data.roles, + token: data.token, + }); + message.success('登录成功'); + navigate('/'); + }; + + return ( +
+ +
+ + } placeholder="请输入租户号" /> + + + } placeholder="请输入用户名" /> + + + } placeholder="请输入密码" /> + + + + +
+
+
+ ); +}; + +export default Login; diff --git a/src/router.tsx b/src/router.tsx index a90c273..e10aef9 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -1,9 +1,13 @@ import { createBrowserRouter } from 'react-router'; import RootLayout from '@/layouts/RootLayout'; +import Login from '@/pages/login/index'; import { routes } from '@/routes'; import { toRouteObjects } from '@/routes/utils'; const router = createBrowserRouter([ + // 登录页:独立路由,不加载布局 + { path: '/login', element: }, + // 带布局的主应用 { path: '/', element: ,