Vue.js - 后台管理系统模板项目推荐1(Vue Vben Admin,综合天花板、企业级首选)
作者:hangge | 2026-09-14 09:13
在企业级后台管理系统、OA 系统、数据中台、权限管理平台开发中,如果从零搭建项目架构、封装通用组件、配置路由权限、适配样式主题,会耗费开发者大量时间精力。目前开源社区诞生了大量优质的 Vue 后台管理模板,均已封装路由管理、权限控制、动态菜单、Mock 数据、全局样式、常用业务组件等通用能力,支持快速二次开发,大幅提升项目落地效率。本文将为大家推荐一个主流且优质的后台管理系统模板项目:Vue Vben Admin。
(3)安装完毕可以通过 pnpm -v 命令进行验证:
(2)整个项目的目录结构如下:
(3)然后再项目目录下执行如下命令安装依赖:




(2)项目内置 build:docker 脚本,可构建本地 Docker 镜像(需先安装 Docker)。执行命令如下:
(2)其中 authStore.authLogin 方法会调用后端登录接口(如 axios.post('/login',credentials)),并在成功后保存用户信息和权限,然后跳转到首页。
(2)效果如下:
(2)下面是一个使用 useVbenForm 实现的表单样例:
(3)下面是使用 useVbenVxeGrid 实现的表格样例:
一、Vue Vben Admin(企业级首选、综合天花板)
1,基本介绍
(1)vue-vben-admin(简称 Vben Admin)是一个基于 Vue3、Vite、TypeScript 的现代化企业级中后台管理系统前端解决方案,由 vbenjs 团队开发维护,GitHub 星标超 30k+,是 Vue3 生态中架构先进、功能完备、开箱即用的中大型后台开发框架。
- Github 主页地址:https://github.com/vbenjs/vue-vben-admin
- 官方在线文档地址:https://doc.vben.pro/
(2)简单说 vue-vben-admin 不是现成业务系统,而是一个高度工程化的后台开发脚手架,集成了中后台所需的所有核心能力,同时支持多 UI 组件库切换,帮助团队快速搭建高质量、可维护的企业级管理平台。
2,核心技术栈
| 技术项 | 版本 / 选型 | 核心价值 |
| 核心框架 | Vue3(Composition API+setup 语法糖) | 更好的代码组织、逻辑复用、类型推导,性能优化显著 |
| 构建工具 | Vite | 极速冷启动、热更新,开发效率提升 5-10 倍,构建速度更快 |
| 语言 | TypeScript(强制类型校验) | 减少类型错误,提升代码可维护性,大型项目更稳健 |
| UI 组件系统 | 核心使用 Ant Design Vue,同时支持多种可选 UI 库(AntD Next、Element Plus、Naive UI、TDesign 等) | 可自由切换组件库,无需重写业务逻辑,适配不同团队技术偏好 |
| 样式方案 | Tailwind CSS v4 | 原子化 CSS,开发速度快,样式一致性好,体积小 |
| 状态管理 | Pinia(Vue 官方推荐) | 更简洁 API,更好的 TypeScript 支持,无嵌套模块限制 |
| 路由 | Vue Router 4.x | 更好的 Vue3 集成,支持 Composition API,动态路由更灵活 |
| 架构模式 | Monorepo(pnpm workspace) | 代码组织更高效,支持多包管理,方便组件复用和版本控制 |
| 网络请求 | Axios(深度封装) | 完善的请求拦截、错误处理、类型定义、取消请求等功能 |
3,项目优缺点
(1)优点:
- 架构极致解耦,模块化、规范化程度极高,支持大型团队协作开发
- 内置完善的 AI 业务适配能力,完美支持 RAG 知识库、大数据量预览、流式响应场景
- 支持多 UI 框架切换,组件复用性强,自定义拓展成本极低
- 完善的权限体系、细粒度按钮权限、动态路由、菜单缓存功能
- 文档详尽、社区活跃、问题迭代速度快
(2)缺点:
- 功能丰富导致项目体积稍大,新手入门有一定学习成本,小型轻量化项目略显冗余
4,准备工作
(1)首先需求安装 Node.js,并且官方要求 Node.js 22.18.0 及以上版本。我们只需要访问其官网下载安装即可。
- 官网地址:https://nodejs.org/
(2)同时项目只支持使用 pnpm 进行依赖安装,我们还需要执行如下命令安装 pnpm:
npm i -g pnpm
(3)安装完毕可以通过 pnpm -v 命令进行验证:

5,下载项目
(1)在 CMD 终端种执行如下命令克隆代码,然后进入项目:
git clone https://github.com/vbenjs/vue-vben-admin.git cd vue-vben-admin
(2)整个项目的目录结构如下:
. ├── README.md # 项目说明文档 ├── apps # 项目应用目录 │ ├── backend-mock # 后端模拟服务应用 │ ├── web-antd # 基于 Ant Design Vue 的前端应用(功能最全的示例前端) │ ├── web-antdv-next # 基于 Ant Design Vue Next 的前端应用 │ ├── web-ele # 基于 Element Plus 的前端应用 │ ├── web-naive # 基于 Naive UI 的前端应用 │ └── web-tdesign # 基于 TDesign 的前端应用 ├── cspell.json # CSpell 配置文件 ├── docs # 项目文档目录 ├── eslint.config.mjs # ESLint 配置文件 ├── lefthook.yml # Git Hook 配置文件 ├── internal # 内部工具目录 │ ├── lint-configs # 代码检查配置 │ │ ├── commitlint-config # Commitlint 配置 │ │ ├── eslint-config # ESLint 配置 │ │ ├── oxfmt-config # Oxfmt 配置 │ │ ├── oxlint-config # Oxlint 配置 │ │ └── stylelint-config # Stylelint 配置 │ ├── node-utils # Node.js 工具 │ ├── tsconfig # 通用 tsconfig 配置 │ └── vite-config # 通用 Vite 配置 ├── oxfmt.config.ts # Oxfmt 配置入口 ├── oxlint.config.ts # Oxlint 配置文件 ├── package.json # 项目依赖配置 ├── packages # 项目包目录 │ ├── @core # 核心包 │ │ ├── base # 基础包 │ │ │ ├── design # 设计相关 │ │ │ ├── icons # 图标 │ │ │ ├── shared # 共享 │ │ │ └── typings # 类型定义 │ │ ├── composables # 组合式 API │ │ ├── preferences # 偏好设置 │ │ └── ui-kit # UI 组件集合 │ │ ├── layout-ui # 布局 UI │ │ ├── menu-ui # 菜单 UI │ │ ├── shadcn-ui # shadcn UI │ │ └── tabs-ui # 标签页 UI │ ├── constants # 常量 │ ├── effects # 副作用相关包 │ │ ├── access # 访问控制 │ │ ├── plugins # 第三方大型依赖插件 │ │ ├── common-ui # 通用 UI │ │ ├── hooks # 组合式 API │ │ ├── layouts # 布局 │ │ └── request # 请求 │ ├── icons # 图标 │ ├── locales # 国际化 │ ├── preferences # 偏好设置 │ ├── stores # 状态管理 │ ├── styles # 样式 │ ├── types # 类型定义 │ └── utils # 工具 ├── playground # 演示目录 ├── pnpm-lock.yaml # pnpm 锁定文件 ├── pnpm-workspace.yaml # pnpm 工作区配置文件 ├── scripts # 脚本目录 │ ├── deploy # 部署相关脚本 │ ├── turbo-run # Turbo 运行脚本 │ └── vsh # VSH 脚本 ├── stylelint.config.mjs # Stylelint 配置文件 ├── turbo.json # Turbo 配置文件 ├── vben-admin.code-workspace # VS Code 工作区配置文件 └── vitest.config.ts # Vitest 配置文件
(3)然后再项目目录下执行如下命令安装依赖:
pnpm install
6,启动项目
(1)执行如下命令可启动开发服务器。该命令执行后会提示选择运行哪个版本应用(Ant Design Vue、Element Plus、Naive UI、TDesign 等)
pnpm dev

(2)我们也可直接指定启动命令,例如下面命令直接开启 Ant Design Vue 版本。
(3)使用浏览器访问,默认显示登录页:
pnpm dev:antd
(3)使用浏览器访问,默认显示登录页:

(4)登录后内页显示效果如下:

(5)切换成浅色模式效果如下:

7,打包与部署
(1)运行下面命令执行多应用打包。生成结果会输出到各应用的 dist/ 目录。部署时可直接使用打包结果。
pnpm build
(2)项目内置 build:docker 脚本,可构建本地 Docker 镜像(需先安装 Docker)。执行命令如下:
提示:这将启动一个 Nginx 容器托管前端应用。可在仓库中自行编写 Dockerfile 以定制镜像。
pnpm run build:docker docker run -p 80:80 vben-admin:latest
附:项目常用功能与主要代码详解
1,登录/登出
(1)前端登录通常在 src/views/_core/authentication/login.vue 中实现。使用内置的 AuthenticationLogin 组件配合 Pinia 的 authStore 完成表单提交:
<template>
<AuthenticationLogin
:loading="authStore.loginLoading"
@submit="authStore.authLogin"
/>
</template>
<script setup lang="ts">
import { useAuthStore } from '@/store/modules/auth';
const authStore = useAuthStore();
</script>
(2)其中 authStore.authLogin 方法会调用后端登录接口(如 axios.post('/login',credentials)),并在成功后保存用户信息和权限,然后跳转到首页。
(3)登出可调用 authStore.logout() 清除登录状态并跳转到登录页。
(2)登录成功后,会根据后台返回的用户角色列表(如 userInfo.roles = ['admin','user'])过滤路由,将符合条件的路由动态加入到路由表。这样不同角色登录后可见不同的菜单。
2,权限控制 (RBAC)
(1)路由配置中可以通过 meta.authority 指定可访问该路由的角色。例如:
// 示例:只有管理员可访问的路由
{
path: '/admin',
name: 'AdminPage',
component: () => import('@/views/AdminPage.vue'),
meta: { authority: ['admin'] },
}
(2)登录成功后,会根据后台返回的用户角色列表(如 userInfo.roles = ['admin','user'])过滤路由,将符合条件的路由动态加入到路由表。这样不同角色登录后可见不同的菜单。
(3)框架还支持设置 menuVisibleWithForbidden: true 实现“菜单可见但页面禁止访问”跳转 403 页面。
3,动态路由
(1)新增路由时,可在对应应用的 src/router/routes/modules/ 目录下创建模块文件:
import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
meta: {
icon: 'lucide:home',
title: '测试模块',
},
name: 'Test',
path: '/test',
children: [
{
name: 'TestPage1',
path: '/test/page1',
component: () => import('#/views/test/page1/index.vue'),
meta: {
icon: 'lucide:file-text',
title: 'Page 1',
},
},
{
name: 'TestPage2',
path: '/test/page2',
component: () => import('#/views/test/page2/index.vue'),
meta: {
icon: 'lucide:file',
title: 'Page 2',
},
},
],
},
];
export default routes;
(2)效果如下:

4,表单与表格
(1)我们除了可以直接使用原生写法来使用 Ant Design Vue 提供的表单和表格组件外,vben-admin 封装了 useVbenForm 和 useVbenVxeGrid 两个强大的 Hook,可以声明式配置表单和表格。
| 传统 Ant Design | 声明式 Vben |
| 手动写 <a-form-item> | 配置 schema 数组 |
| 手动绑定 v-model | 自动处理表单值 |
| 手写分页逻辑 | 内置 proxyConfig 自动请求 |
| 手写 loading 状态 | 自动管理 |
(2)下面是一个使用 useVbenForm 实现的表单样例:
<script lang="ts" setup>
import { ref } from 'vue';
import { Page } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
// 表单 Schema 配置 - 声明式定义表单字段
const formSchema = [
{
component: 'Input',
fieldName: 'username',
label: '用户名',
rules: 'required',
componentProps: {
placeholder: '请输入用户名',
},
},
{
component: 'InputPassword',
fieldName: 'password',
label: '密码',
rules: 'required',
componentProps: {
placeholder: '请输入密码',
},
},
{
component: 'Input',
fieldName: 'email',
label: '邮箱',
rules: 'required',
componentProps: {
placeholder: '请输入邮箱',
},
},
{
component: 'Select',
fieldName: 'role',
label: '角色',
componentProps: {
placeholder: '请选择角色',
options: [
{ label: '管理员', value: 'admin' },
{ label: '普通用户', value: 'user' },
{ label: '访客', value: 'guest' },
],
},
},
{
component: 'RadioGroup',
fieldName: 'status',
label: '状态',
defaultValue: 1,
componentProps: {
optionType: 'button',
buttonStyle: 'solid',
options: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
},
},
{
component: 'RangePicker',
fieldName: 'dateRange',
label: '生效日期',
},
{
component: 'Textarea',
fieldName: 'remark',
label: '备注',
componentProps: {
placeholder: '请输入备注信息',
rows: 4,
},
},
];
// 使用 useVbenForm 创建表单
const [Form, formApi] = useVbenForm({
schema: formSchema,
showDefaultActions: false,
});
// 表单提交
const loading = ref(false);
async function handleSubmit() {
const { valid } = await formApi.validate();
if (!valid) return;
loading.value = true;
const values = await formApi.getValues();
setTimeout(() => {
loading.value = false;
message.success('提交成功!');
console.log('表单数据:', values);
}, 1000);
}
// 重置表单
function handleReset() {
formApi.resetForm();
message.info('表单已重置');
}
</script>
<template>
<Page title="BasicForm 表单演示">
<div class="p-6">
<a-card title="用户信息表单">
<Form />
<div class="mt-4 flex gap-2">
<a-button type="primary" :loading="loading" @click="handleSubmit">
提交
</a-button>
<a-button @click="handleReset">
重置
</a-button>
</div>
</a-card>
</div>
</Page>
</template>
(3)下面是使用 useVbenVxeGrid 实现的表格样例:
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { Page } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
// 表格列配置
const columns = [
{ field: 'id', title: 'ID', width: 80 },
{ field: 'name', title: '姓名', width: 150 },
{ field: 'email', title: '邮箱', minWidth: 200 },
{ field: 'phone', title: '电话', width: 150 },
{
field: 'status',
title: '状态',
width: 100,
cellRender: { name: 'CellTag' },
},
{ field: 'createTime', title: '创建时间', width: 180 },
{
field: 'operation',
title: '操作',
width: 150,
fixed: 'right',
cellRender: {
name: 'CellOperation',
attrs: { onClick: onActionClick },
},
},
];
// 搜索表单配置
const searchFormSchema = [
{
component: 'Input',
fieldName: 'name',
label: '姓名',
componentProps: { placeholder: '请输入姓名' },
},
{
component: 'Select',
fieldName: 'status',
label: '状态',
componentProps: {
placeholder: '请选择状态',
allowClear: true,
options: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
},
},
];
// 模拟数据
const mockData = Array.from({ length: 50 }, (_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
email: `user${i + 1}@example.com`,
phone: `138${String(i).padStart(8, '0')}`,
status: i % 2 === 0 ? 1 : 0,
createTime: new Date(Date.now() - i * 86400000).toLocaleString(),
}));
// 使用 useVbenVxeGrid 创建表格
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: searchFormSchema,
submitOnChange: true,
},
gridOptions: {
columns,
height: 'auto',
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
let filtered = [...mockData];
if (formValues?.name) {
filtered = filtered.filter((item) => item.name.includes(formValues.name));
}
if (formValues?.status !== undefined) {
filtered = filtered.filter((item) => item.status === formValues.status);
}
const start = (page.currentPage - 1) * page.pageSize;
const end = start + page.pageSize;
return {
items: filtered.slice(start, end),
total: filtered.length,
};
},
},
},
rowConfig: { keyField: 'id' },
toolbarConfig: {
custom: true,
export: true,
refresh: true,
search: true,
zoom: true,
},
} as VxeTableGridOptions,
});
// 操作按钮点击事件
function onActionClick(e: { code: string; row: any }) {
if (e.code === 'edit') {
message.info(`编辑: ${e.row.name}`);
} else if (e.code === 'delete') {
message.warning(`删除: ${e.row.name}`);
}
}
</script>
<template>
<Page title="BasicTable 表格演示" auto-content-height>
<Grid table-title="用户列表" class="h-full">
<template #toolbar-tools>
<a-button type="primary" @click="gridApi.query()">
刷新
</a-button>
</template>
</Grid>
</Page>
</template>

全部评论(0)