# much-admin **Repository Path**: chenhang0612/much-admin ## Basic Information - **Project Name**: much-admin - **Description**: 基于 Vue 3 + TypeScript + Vite 的后台管理前端,对接网关下的 认证(/auth)、系统(/system)、会员(/member) 等接口 - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-01 - **Last Updated**: 2026-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Much Admin 基于 **Vue 3 + TypeScript + Vite** 的后台管理前端,对接网关下的 **认证(`/auth`)**、**系统(`/system`)** 等服务。菜单与路由由后端权限树动态生成,配套布局 Tab、可折叠侧栏、主题切换与 Element Plus 图标选择等能力。 默认配套后端:**much-system-service**(经网关,如 `http://localhost:8080`)。 --- ## 技术栈 | 类别 | 技术 | |------|------| | 框架 | Vue 3、Vue Router 4、Vuex 4 | | UI | Element Plus、`@element-plus/icons-vue` | | 构建 | Vite 6、Sass(全局注入 `variables.scss`) | | HTTP | Axios(`src/utils/request.ts`) | | 其它 | NProgress、TypeScript、ESLint、Prettier | --- ## 功能概览 - **SSO 登录**:`/auth/sso/login`,Token 写入本地并在请求头携带 `token` - **动态路由 / 侧栏**:`getUserPermissionList` 拉取权限树 → 适配为路由 → 注册到 Layout 子路由 - **权限码**:`collectPermissionCodes` 收集按钮权限,供 `v-perm` 指令使用 - **布局 Tab**:访问页面自动开 Tab,可关闭;数量上限由 `VITE_LAYOUT_TAB_MAX` 控制(硬顶 8) - **侧栏折叠**:展开时仅在侧栏 Logo 行显示收起;折叠后侧栏完全隐藏,顶栏显示 **Expand** 展开按钮 - **菜单管理**:类型 **1-项目 / 2-菜单 / 9-按钮**;Element Plus 官方图标选择器;表格预览图标 - **系统模块页面**:用户、角色、菜单、部门、字典、日志、设置、工作台等(见下方页面列表) --- ## 环境要求 - **Node.js**:建议 18+ / LTS(与 Vite 6、当前依赖兼容) - **后端网关**:开发环境默认代理到 `http://localhost:8080`(见 `vite.config.ts`) --- ## 快速开始 ```bash # 安装依赖 npm install # 开发 npm run dev # 生产构建 npm run build # 预览构建产物 npm run preview # 构建并复制到 monorepo 发布目录(见 release.sh) npm run build:release # 代码检查 / 格式化 npm run lint npm run prettier ``` 浏览器访问开发地址(以终端输出为准,常见为 `http://localhost:5173`)。 --- ## 环境变量 文件:`.env.development`、`.env.production`。 | 变量 | 说明 | |------|------| | `VITE_APP_BASE_URL` | 接口根路径。开发建议 **`/api`**,由 Vite 代理到网关;生产填网关完整地址(如 `http://localhost:8080`)。 | | `VITE_PERMISSION_ROOT_ID` | `getUserPermissionList` 请求体中的菜单树根节点 **id**,默认 `1`。 | | `VITE_LAYOUT_TAB_MAX` | 布局 Tab 最大数量,默认 `8`(代码硬顶 8)。 | --- ## 开发代理 `vite.config.ts` 将 **`/api`** 转发到网关,并去掉前缀: ```text 浏览器请求 /api/system/user/list ↓ 网关收到 /system/user/list ``` 这样前端路由(如 `/system/user`)刷新时不会被误代理到后端。修改网关地址请改 `server.proxy['/api'].target`。 --- ## 鉴权与请求 - **Token**:登录成功后缓存;Axios 拦截器在请求头附加 **`token`** - **响应约定**:兼容 `code` / `message`(或 `msg`)/ `data` 等常见 `Result` 结构;未登录等场景可触发 `redirect` 跳转登录 - **登录接口**:`POST /auth/sso/login`(`src/api/user.ts`) - **用户信息**:`GET /auth/sso/getUserInfo` - **权限树**:`POST /system/permission/getUserPermissionList`(body:`userId`、`id` 树根) --- ## 路由与菜单 ### 静态路由(`src/router/index.ts`) | 路径 | 说明 | |------|------| | `/` | Layout,默认重定向 `/workbench` | | `/workbench` | 工作台 | | `/login` | 登录页 | | `/500` | 服务异常页 | | `/:pathMatch(.*)*` | 404(挂在 Layout 子级,避免抢动态路由) | ### 动态路由流程 1. `src/permission.ts` 路由守卫:有 Token 时拉取用户信息与权限树 2. `permissionAdapter.ts`:后端 **PermissionDto**(`sonList`)→ 前端菜单行结构 3. `filterAsyncRoutes` + `createRouteRecord`(`src/core/lib/router.ts`)生成 `RouteRecordRaw` 4. `addDynamicRoutes` 挂到主 Layout(`indexName`)下 ### 菜单类型(与后端 `Permission.type` 对齐) | type | 含义 | 侧栏 | 路由 | |------|------|------|------| | `1` | 项目(目录) | 展示 | `RouterView` 容器 | | `2` | 菜单(页面) | 展示 | 按 `component` 加载 `src/views/**/*.vue` | | `9` | 按钮 | **不展示** | 仅权限码,供 `v-perm` | | `0` | 历史目录 | 按项目兼容 | 适配层映射为项目 | 侧栏另过滤 `type` 为 `12`、`99` 等非导航节点(见 `PERM_TYPES_HIDDEN_IN_SIDEBAR`)。 ### 页面组件解析 - 菜单字段 **`component`** 应对应 `src/views` 下路径,如 `system/user/index` → `src/views/system/user/index.vue` - `import.meta.glob('../../views/**/*.vue')` 动态匹配;未命中时使用 **`src/views/system/common/dynamic-placeholder.vue`** --- ## 内置页面(`src/views`) | 路径 | 页面 | |------|------| | `workbench/index.vue` | 工作台 | | `account/login.vue` | 登录 | | `system/user/index.vue` | 用户管理 | | `system/role/index.vue` | 角色管理 | | `system/menu/index.vue` | 菜单管理 | | `system/dept/index.vue` | 部门管理 | | `system/dict/index.vue` | 字典管理 | | `system/log/index.vue` | 日志 | | `system/setting/index.vue` | 系统设置 | | `system/common/dynamic-placeholder.vue` | 动态路由占位 | | `error/404.vue`、`error/500.vue` | 错误页 | 实际可见菜单以后台配置为准。 --- ## 主要接口模块(`src/api`) | 文件 | 职责 | |------|------| | `user.ts` | 登录、登出、用户信息、权限树 | | `auth.ts` | 用户/角色/菜单 CRUD、角色授权、菜单树 | | `organize.ts` | 部门树、分页、增删改查 | | `dict.ts` | 字典类型与字典数据 | | `log.ts` | 登录日志、操作日志 | ### 部分接口约定(与 much-system 对齐) - 用户列表:`POST /system/user/list` - 用户注册:`POST /system/user/register` - 用户更新:`POST /system/user/update` - 用户删除:`POST /system/user/delete?id=`(Query 参数) - 权限树:`POST /system/permission/getPermissionTree` - 菜单创建/更新:`POST /system/permission/create`、`/update` --- ## 目录结构 ```text much-admin/ ├── public/ # 静态资源(favicon 等) ├── src/ │ ├── api/ # 接口封装 │ ├── assets/ # 图片、iconfont │ ├── components/ # 通用组件(admin-page、pagination、icon-picker、menu-icon…) │ ├── config/ # 应用配置、权限树根、主题、布局 Tab 上限 │ ├── core/ │ │ ├── directives/ # 自定义指令(v-perm、v-copy) │ │ ├── hooks/ # useAdmin、分页 hooks │ │ └── lib/ # 路由生成、权限适配、Tab、菜单图标 │ ├── layout/ # 布局、侧栏、顶栏、Tab 栏、主内容区 │ ├── plugins/ # Element Plus 注册 │ ├── router/ # 静态路由、动态路由注册 │ ├── store/ # Vuex(user、permission、app、tabs) │ ├── styles/ # 全局样式、SCSS 变量 │ ├── utils/ # 请求、缓存、主题、校验 │ ├── views/ # 业务页面 │ ├── App.vue │ ├── main.ts │ └── permission.ts # 全局路由守卫 ├── .env.development ├── .env.production ├── vite.config.ts ├── tsconfig.json └── release.sh # 构建产物复制到 ../frontend/public/admin ``` --- ## 布局与主题 - **布局**:左侧菜单 + 顶栏(面包屑、主题、用户)+ Tab 栏 + 主内容 - **侧栏折叠**:状态存 `localStorage`(`much_admin_sidebar_collapse`) - **主题**:顶栏切换多套主色,写入 CSS 变量与 `localStorage`(`much-admin-theme`),启动时 `initTheme()` 恢复 布局相关变量见 `src/styles/variables.scss`(侧栏宽 200px,收起为 0)。 --- ## 自定义指令 ```html 编辑 ``` `getUserPermissionList`:**仅 type=9 为按钮权限**,出现在接口结果树中即表示用户具备该权限,写入 `store.getters.permission`;未出现的 `Perm.*` 对应按钮不展示。支持通配符(如 `system:dict:type:*`)。`userType === 1` 超级管理员默认放行。 --- ## 生产部署 ```bash npm run build ``` 产物在 `dist/`。若需并入 monorepo 前端静态目录: ```bash npm run build:release # 默认复制到 ../frontend/public/admin ``` 生产环境请将 `VITE_APP_BASE_URL` 设为网关对外地址,或由 Nginx 将 `/api` 反代到网关(与开发代理策略一致即可)。 --- ## 与后端对齐检查清单 - [ ] 网关地址与 `vite.config.ts` 代理、`VITE_APP_BASE_URL` 一致 - [ ] `VITE_PERMISSION_ROOT_ID` 与库中菜单树根 **id** 一致 - [ ] 菜单 **path / component** 与 `src/views` 文件路径一致 - [ ] 菜单 **type** 使用 `1 / 2 / 9`,按钮不进侧栏 - [ ] 用户删除接口为 **POST + Query `id`**,勿用 JSON Body - [ ] 登录响应包含 **token** 字段 --- ## 常见问题 **登录成功但白屏或 404** - 检查动态路由是否注册成功,URL 是否与菜单 **path** 一致 - 检查 **component** 能否解析到 `src/views` 下对应 `.vue` **接口跨域** - 开发环境使用 `VITE_APP_BASE_URL=/api` + Vite 代理 - 若直连网关,需在网关配置 CORS **侧栏无菜单** - 确认 `getUserPermissionList` 返回非空 `sonList` - 确认节点未被标为按钮(`type=9`)或隐藏类型 **菜单管理类型显示不对** - 列表展示以后端 **type** 为准(1/2/9),见 `permissionAdapter.normalizeBackendMenuType` **动态页显示「功能页面待接入」** - 表示 `component` 路径未匹配到视图文件,请补全 `src/views` 或修正后台配置 --- ## 许可证 以项目仓库或组织约定为准;若需开源协议请补充根目录 `LICENSE` 文件。