# antd-vue3构建后台管理系统
**Repository Path**: zerobit/antd-vue3-tutorials
## Basic Information
- **Project Name**: antd-vue3构建后台管理系统
- **Description**: 基于 Ant Design 的 Vue 3 组件库,用于快速构建高质量的后台管理系统指南。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-06-22
- **Last Updated**: 2025-06-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# And-Vue3构建后台管理系统指南
1. 采用Vue3前端技术栈应用
2. 详解 ESLint + Prettier 团队编码规范
3. And-Vue 组件库主题定制&布局搭建
4. 动态路由菜单和权限控制
> 视频参考:【黑马前端Vue3技术栈搭建后台管理系统,Antd-Vue构建后台管理系统,参考字节Arco Pro 最佳实践】 https://www.bilibili.com/video/BV1FD421P7XS/?share_source=copy_web&vd_source=e88e1388cc8fa23f4b6d8fdad446478b
## 一、Vue3项目初始化
Vue3官网:https://cn.vuejs.org/
### 1.1 初始化Vue3
- 构建Vue3项目
```bash
// npm
npm create vue@latest
// yarn
# For Yarn (v1+)
yarn create vue
# For Yarn Modern (v2+)
yarn create vue@latest
# For Yarn ^v4.11
yarn dlx create-vue@latest
```

项目构建完成,可执行以下命令运行项目:
```bash
npm install
npm run format
npm run dev
```
### 1.2 VS Code 扩展安装
扩展推荐:`.vscode/extensions.json`
输入`@recommended`一键安装推荐拓展
### 1.3 项目基础代码
1. 删除`src`目录下所有文件
2. 在`src`目录下新建`App.vue`和`main.js`
- `App.vue`
```vue
Hello Vue3 👍
```
- `main.js`
```js
import { createApp } from "vue"
import App from "./App.vue"
const app = createApp(App)
app.mount("#app")
```
3. 开启服务器启动时,自动打开浏览器(可选)
`vite.config.js`文件
```js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
+ server: {
+ open: true,
+ },
})
```
### 1.4 团队编码规范
`eslant + prettier`配置参考,可根据项目情况定制
- 允许单文件名组件(可选,**新版本已弃用**)
如新建文件`views/Login/index.vue`,结果文件名报错,需配置允许`index.vue`命名。
修改`.eslintrc.cjs`文件
- 统一添加末尾分号(可选)
修改`.prettierrc.json`文件
```json
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"singleQuote": true,
"printWidth": 100,
+ "trailingComma": "all",
+ "endOfLine": "auto"
}
```
- VS Code工作区设置
修改`.vscode/setting.json`文件(如无可新建),保存时自动运行eslint
```json
{
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"tsconfig.json": "tsconfig.*.json, env.d.ts",
"vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*",
"package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .oxlint*, oxlint*, .prettier*, prettier*, .editorconfig"
},
+ "eslint.enable": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll": "explicit"
+ },
+ "eslint.options": {
+ "extensions": [
+ ".js",
+ ".vue",
+ ".jsx",
+ ".tsx"
+ ]
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
```
## 二、Ant Design Vue组件库
官方文档:https://www.antdv.com/docs/vue/introduce-cn/
### 2.1 安装依赖
```bash
# npm
npm i --save ant-design-vue@4.x
# yarn
yarn add ant-design-vue@4.x
```
- 全局完整注册
```js
import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/reset.css';
const app = createApp(App);
app.use(Antd).mount('#app');
```
- 自动按需引入
如果你使用的是 `Vite` ,推荐使用 `unplugin-vue-components`
```bash
$ npm install unplugin-vue-components -D
```
`vite.config.js`
```js
// vite.config.js
import { defineConfig } from 'vite';
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
plugins: [
// ...
Components({
resolvers: [
AntDesignVueResolver({
importStyle: false, // css in js
}),
],
}),
],
});
```
然后你可以在代码中直接使用 `ant-design-vue` 的组件,插件会自动引入。
### 2.2 antd 图标库
- 安装依赖
```bash
npm install --save @ant-design/icons-vue
```
- 使用图标
```vue
antd 图标演示
按钮图标
ICON插槽
```
- 图标全局注册按需导入
1. 新建`src/components/icon/index.js`文件
```js
// 用于把antd icon注册为全局组件
import { StepBackwardOutlined, StepForwardOutlined } from '@ant-design/icons-vue' // 按需要引入
// 注册全局组件,之后需要什么icon写入即可
const icons = [StepBackwardOutlined, StepForwardOutlined]
export default {
install(app) {
icons.forEach((icon) => {
app.component(icon.displayName, icon)
})
},
}
```
2. 在`main.js`中全局注册
```js
// 全局引入antd图标
import Icons from '@/components/icon'
app.use(Icons)
```
### 2.3 组件库代码提示配置
配置后,使用antd组件库有代码提示
`jsconfig.json`
```json
{
"compilerOptions": {
+ "types": [
+ "ant-design-vue/typings/global.d.ts"
+ ],
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}
```
### 2.4 antd定制主题和国际化
antd默认主题色是蓝色,默认语言为英文
- 国际化:https://www.antdv.com/docs/vue/i18n-cn
- 定制主题:https://www.antdv.com/docs/vue/customize-theme-cn
- `ConfigProvider`全局化配置:https://www.antdv.com/components/config-provider-cn
**使用方法**
可以在`App.vue`中直接配置
```vue
按钮图标
ICON插槽
```
## 三、CSS预处理器和全局样式
### 3.1 安装依赖
考虑到不周的团队习惯,所以把sass和less都安装上,按需使用
```bash
npm install sass less -D
```
### 3.2 样式全局变量
`styles/var.less`
```less
:root {
// CSS3变量
--color-primary: #e15536;
}
```
`styles/main.less`
```less
@import './var.less';
// 全局样式
body {
font-size: 14px;
color: #333;
margin: 0;
}
a {
color: inherit;
text-decoration: none;
&:hover {
color: var(--color-primary);
}
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol {
margin: 0;
padding: 0;
}
// 用于修改nprogress进度条颜色
#nprogress {
.bar {
background: var(--color-primary) !important; // 自定义颜色
}
.peg {
box-shadow:
0 0 10px var(--color-primary),
0 0 5px var(--color-primary) !important;
}
}
```
在`main.js`中引入全局样式
```js
// 全局样式
import '@/styles/main.less'
```
## 四、Ant Design Vue布局和项目路由
### 4.1 antd布局
**src/views/Layout/index.vue**
```vue
侧边栏
页头
内容
页脚
```
### 4.2 项目路由
**src/router/index.js**
```js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/views/Layout/index.vue'),
},
],
})
export default router
```
在`main.js`中引入VueRouter
```js
// Vue Router
import router from '@/router'
app.use(router)
```
### 4.3 在App中使用路由
**App.vue**
```vue
```
### 4.4 加载进度条、动态设置页面标题和使用环境变量
- 页面加载进度条依赖
```bash
npm install nprogress
```
- 在`src/router/index.js`中配置使用进度条插件及配置动态页面标题
```js
import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false })
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/views/Layout/index.vue'),
meta: { title: '首页' },
},
],
})
// 前置路由守卫
router.beforeEach(() => {
// 进度条开始
NProgress.start()
})
// 后置路由守卫
router.afterEach((to) => {
// 进度条结束
NProgress.done()
// 动态设置页面标题
document.title = `${to.meta.title} - ${import.meta.env.VITE_APP_TITLE}`
})
export default router
```
- 使用环境变量
- 项目根目录创建`.env.dev`文件
```
# 开发环境
NODE_ENV='dev'
# 为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。
# js中通过`import.meta.env.VITE_APP_TITLE`取值
VITE_APP_TITLE = 权限管理系统
VITE_APP_PORT = 8080
VITE_APP_BASE_API = '/dev-api'
VITE_APP_BASE_FILE_API = '/dev-api/web/api/system/file/upload'
# 后端服务地址
VITE_APP_SERVICE_API = 'http://127.0.0.1:9090'
```
- 项目根目录创建`.env.prod`文件
```
# 开发环境
NODE_ENV='prod'
# 为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。
# js中通过`import.meta.env.VITE_APP_TITLE`取值
VITE_APP_TITLE = 权限管理系统
VITE_APP_PORT = 8080
VITE_APP_BASE_API = '/prod-api'
VITE_APP_BASE_FILE_API = '/prod-api/web/api/system/file/upload'
# 后端服务地址
VITE_APP_SERVICE_API = 'http://127.0.0.1:9090'
```
- 修改`package.json`文件在项目运行时使用环境变量
```json
"scripts": {
"dev": "vite --mode dev",
"build": "vite build --mode prod",
"prod": "vite --mode prod",
"lint": "eslint . --fix",
"format": "prettier --write src/"
},
```
- 安装依赖用于获取Node.js的全局变量
```bash
npm install vite-plugin-static-copy --save-dev
```
- `vit.config.js`中进行配置环境
```js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import { viteStaticCopy } from 'vite-plugin-static-copy'
// https://vite.dev/config/
export default defineConfig(({ mode }) => {
// 获取`.env`环境配置文件
// eslint-disable-next-line no-undef
const env = loadEnv(mode, process.cwd())
return {
define: {
'process.env': {},
},
plugins: [
vue(),
vueDevTools(),
viteStaticCopy({
targets: [
{
src: '.env*',
dest: '',
},
],
}),
Components({
resolvers: [
AntDesignVueResolver({
importStyle: false, // css in js
}),
],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
open: true,
host: '0.0.0.0',
port: Number(env.VITE_APP_PORT),
proxy: {
[env.VITE_APP_BASE_API]: {
target: env.VITE_APP_SERVICE_API,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), ''),
},
},
},
}
})
```
## 五、Antd Menu组件基于路由生成菜单
### 5.1 使用And Menu组件
**src/components/Layout/AppSiderBar.vue**
```vue
LOGO
机构管理
机构作业范围
机构运费管理
车型管理
车辆列表
回车管理
```
**src/views/Layout/index.vue**
```vue
页头
内容
页脚
```
### 5.2 路由模块化
- 在`router/modules`目录下给每个功能模块建立路由配置,如下所示:
**router/modules/base.js**
```js
export default {
path: '/base',
name: 'Base',
component: () => import('@/views/Layout/index.vue'),
redirect: '/base/department',
meta: { title: '基础管理', icon: 'BarChartOutlined', order: 1 },
children: [
{
path: 'department',
name: '部门管理',
component: () => import('@/views/Base/Department/index.vue'),
meta: { title: '部门管理', parent: 'Base' },
},
{
path: 'role',
name: '角色管理',
component: () => import('@/views/Base/Role/index.vue'),
meta: { title: '角色管理', parent: 'Base' },
},
{
path: 'user',
name: '用户管理',
component: () => import('@/views/Base/User/index.vue'),
meta: { title: '用户管理', parent: 'Base' },
},
],
}
```
- 在`router`目录下新建`asyncRouter.js`文件,用于动态引入所有模块化的路由
```js
// Glob导入: https://cn.vitejs.dev/guide/features#glob-import
const modules = import.meta.glob('./modules/*.js', { eager: true })
// 格式化模块
function formatModules(_modules, result) {
// 遍历模块
Object.keys(_modules).forEach((key) => {
// 获取模块
const defaultModule = _modules[key].default
// 模块存在
if (defaultModule) {
// 把模块放入结果数组
result.push(defaultModule)
}
})
// 返回结果数组, 并且按照模块的order属性排序
return result.sort((a, b) => a.meta?.order - b.meta?.order)
}
// 根据文件生成路由树
export const asyncRoutes = formatModules(modules, [])
```
- 修改`router/index.js`文件动态引入路由
```js
// 引入动态路由
import { asyncRoutes } from './asyncRouter'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/views/Layout/index.vue'),
meta: { title: '首页' },
},
...asyncRoutes,
],
})
```
### 5.3 使Menu组件根据路由动态生成菜单
**src/components/Layout/AppSiderBar.vue**
```vue
```
**src/router/index.js**
```js
import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false })
// 引入动态路由
import { asyncRoutes } from './asyncRouter'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/views/Layout/index.vue'),
meta: { title: '首页', icon: 'HomeOutlined', order: 0 },
},
{
type: 'divider',
meta: { title: '分割线' },
},
...asyncRoutes,
],
})
// 前置路由守卫
router.beforeEach(() => {
// 进度条开始
NProgress.start()
})
// 后置路由守卫
router.afterEach((to) => {
// 进度条结束
NProgress.done()
// 动态设置页面标题
document.title = `${to.meta.title} - ${import.meta.env.VITE_APP_TITLE}`
})
export default router
```
## 六、权限控制
- 通过==指令==的方式进行权限控制(*例如:按钮权限*)
封装`v-permission`指令,可在组件或原生元素上使用,如:
```html
删除
```
- 封装`v-permission`指令步骤
1. 编写权限校验指令:**src/permission/index.js**
```js
// 从pinia中获取用户的权限列表
// import { usePermissionStore } from '@/store/modules/permission'
// 权限校验方法
function checkPermission(el, { value }) {
// 获取用户角色
// const { currentRole } = usePermissionStore()
const currentRole = 'admin' // 示例先写死
// 传入的权限值要求是一个数组
if (Array.isArray(value) && value.length > 0) {
// 判断用户角色是否有权限
const hasPermission = value.includes(currentRole)
// 如果没有权限则删除该元素
if (!hasPermission) el.remove()
} else {
throw new Error(`权限格式错误! 应为 v-permission="['admin','editor']"`)
}
}
export default {
mounted(el, binding) {
checkPermission(el, binding)
},
updated(el, binding) {
checkPermission(el, binding)
},
}
```
2. 在`main.js`文件中全局引入权限指令
```js
// 引入权限指令
import permission from '@/permission'
app.directive('permission', permission)
```