⚡ 简介
v3-admin 是一个中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element-Plus 和 Vue-Cli 4.5
1️⃣ 功能
- 用户管理
- 登录
- 注销
- 权限验证
- 页面权限
- 指令权限
- 多环境
- dev
- stage
- prod
- 全局功能
- svg
- 国际化多语言
- 多种动态换肤
- 动态侧边栏(支持多级路由嵌套)
- 动态面包屑
- 快捷导航(标签页)
- Screenfull 全屏
- 自适应收缩侧边栏
- 错误页面
- 401
- 404
- Dashboard
- admin
- editor
2️⃣ 目录
# v3-admin
├─ .env.dev # 开发环境
├─ .env.prod # 生产环境
├─ .env.stage # 预发布环境
├─ .eslintrc.js # eslint
├─ public # 静态资源
│ ├─ favicon.ico # favicon 图标
│ ├─ index.html # html模板
├─ src # 源码
│ ├─ @types # ts 声明
│ ├─ api-inject # 接口(全局注入的方式)
│ ├─ api-import # 接口(import/export 的方式)
│ ├─ assets # 主题、字体、svg等静态资源
│ ├─ components # 全局公用组件
│ ├─ config # 全局配置
│ ├─ constant # 常量/枚举
│ ├─ directives # 全局指令
│ ├─ layout # 全局 layout
│ ├─ locales # 国际化
│ ├─ model # 全局 model
│ ├─ plugins # 插件
│ ├─ router # 路由
│ ├─ store # 全局 store 管理
│ ├─ styles # 全局样式
│ ├─ utils # 全局公共方法
│ └─ views # 所有页面
├─ tsconfig.json # ts 编译配置
└─ vue.config.js # vue-cli 配置
3️⃣ 安装
# 克隆项目
git clone https://github.com/v3-projects/v3-admin
# 进入项目目录
cd v3-admin
# 安装依赖
yarn
# 启动项目
yarn dev
? 基础
1️⃣ 路由
配置项
// 默认false,设置 true 的时候该路由不会在侧边栏出现
hidden: true
// 设置 noRedirect 的时候该路由在面包屑导航中不可被点击
redirect: 'noRedirect'
// 设定路由的名字,一定要填写不然重置路由可能会出问题
name: 'router-name'
meta: {
// 设置该路由进入的权限,支持多个权限叠加
roles: ['admin', 'editor']
// 设置该路由在侧边栏和面包屑中展示的名字
title: 'title'
// 设置该路由的图标,记得将 svg 导入 @/assets/svg-icons/icons
icon: 'svg-name'
// 默认true,如果设置为false,则不会在面包屑中显示
breadcrumb: false
// 默认false,如果设置为true,它则会固定在 tags-view 中
affix: true
// 当一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式
// 只有一个时,会将那个子路由当做根路由显示在侧边栏
// 若想不管路由下面的 children 声明的个数都显示你的根路由
// 可以设置alwaysShow: true,这样就会忽略之前定义的规则,一直显示根路由
alwaysShow: true
// 当设置了该属性,进入路由时,则会高亮 activeMenu 属性对应的侧边栏
activeMenu: '/dashboard'
}
动态路由
constantRoutes
把不需要判断权限的路由放置在常驻路由里面,如 /login
、/dashboard
。
asyncRoutes
放置需求动态判断权限并通过 addRoute
动态添加的路由。
添加动态路由方法:
案例:在 @/router/asyncModules
下面创建例如 permission.ts
文件
import { RouteRecordRaw } from 'vue-router'
import Layout from '@/layout/index.vue'
const permissionRouter: Array<RouteRecordRaw> = [
{
path: '/permission',
component: Layout,
name: 'Permission',
redirect: '/permission/directive',
meta: {
title: 'permission',
icon: 'lock',
roles: ['admin', 'editor'], // 可以在根路由中设置角色
alwaysShow: true // 将始终显示根菜单
},
children: [
{
path: 'page',
component: () => import(/* webpackChunkName: "permission-page" */ '@/views/permission/page.vue'),
name: 'PagePermission',
meta: {
title: 'pagePermission',
roles: ['admin'] // 或者在子导航中设置角色
}
},
{
path: 'directive',
component: () => import(/* webpackChunkName: "permission-directive" */ '@/views/permission/directive.vue'),
name: 'DirectivePermission',
meta: {
title: 'directivePermission' // 如果未设置角色,则表示:该页面不需要权限,但会继承根路由的角色
}
}
]
}
]
export default permissionRouter
2️⃣ 发送HTTP请求
大致的流程如下:
graph LR
页面/交互 --> 统一管理的API --> 封装的service.ts --> 服务器
统一管理的 API
import 形式
@/api-import/login.ts
/**
* api-import
* 实现:采用 import/export 的方式
* 优点:拥有 TypeScript 类型提示
* 缺点:使用时需要 "import { accountLogin } from '@/api-import/login'" 来导入指导的api
* @see:暂无
*/
import { request } from '@/utils/service'
interface UserRequestData {
username: string
password: string
}
export function accountLogin(data: UserRequestData) {
return request({
url: 'user/login',
method: 'post',
data
})
}
inject 形式
@/api-inject/index.ts
/**
* api-inject
* 实现:采用全局注入的方式
* 优点:使用时只需 "import $api from '@/api-inject'" 或者 const $api = inject('$api') 即可方便的通过 $api 调用所有api
* 缺点:丢失了 TypeScript 类型提示
* @see:'@/store/modules/user/actions.ts'
* @see:'@/views/login/index.vue'
*/
import { assign, map } from 'lodash'
import { request } from '@/utils/service'
const files = require.context('./modules', true, /\.ts$/)
const generators = files.keys().map(key => files(key).default)
export default assign({}, ...map(generators, generator => generator(request)))
@/api-inject/modules/sys.api.login.ts
import { AxiosAdapter } from 'axios'
interface UserRequestData {
username: string
password: string
}
export default (request: AxiosAdapter) => {
return {
accountLogin(data: UserRequestData) {
return request({
url: 'user/login',
method: 'post',
data
})
}
}
}
封装的 service.ts
@/utils/service.ts
是基于 axios 的封装,封装了全局 request拦截器、response拦截器、统一的错误处理、统一做了超时处理、baseURL设置等。
3️⃣ 多环境
构建
项目开发完成,打包代码时,内置两种环境:
# 打包预发布环境
npm run build:stage
# 打包正式环境
npm run build:prod
变量
在 .env.prod
等 .env.xxx
文件中,配置了该环境对应的变量:
# 当前运行的环境
NODE_ENV=production
# 当前环境对应接口的 baseURL
VUE_APP_BASE_API = 'https://www.xxx.com'
获取方式:
console.log(process.env.NODE_ENV)
console.log(process.env.VUE_APP_BASE_API)
4️⃣ 跨域
@/config
文件夹下存放了内置的一些配置项,比如 white-list
路由白名单,vue.custom.config
vue.config 文件配置等。
其中的 vue.custom.config
里就有 proxy
进行反向代理。
与之对应的生产环境,则可以使用 nginx
来做反向代理。
反向代理
const vueDefaultConfig = {
publicPath: './',
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: false,
transpileDependencies: ['vue-echarts', 'resize-detector'],
// webpack 配置的项目名称
title: 'v3-admin',
titleSeparator: ' - ',
titleReverse: false,
abbreviation: 'vt2at',
providePlugin: {},
build7z: false,
startMessage:'欢迎使用 v3-admin',
devServer: {
publicPath: '/',
hot: true,
port: '9999',
open: true,
noInfo: false,
overlay: {
warnings: true,
errors: true,
},
// 反向代理
proxy: {
'/api/': {
target: 'http://xxxxxx/api/',
ws: true,
pathRewrite: {
'^/api/': ''
},
changeOrigin: true,
secure: false
}
}
}
}
module.exports = vueDefaultConfig
CORS
这种方案对于前端来说没有什么工作量,和正常发送请求写法上没有任何区别,工作量基本都在后端这里。
实现 CORS 之后,不管是开发环境还是生产环境,都能方便的调用接口。
✈️ 进阶
规范代码很重要!
1️⃣ ESLint
- 配置项:在
.eslintrc.js
文件中 - 取消自动校验:
@/config/vue.custom.config.ts
中将lintOnSave
设置为false
- 推荐 VSCode 的 ESlint 插件,它可在写代码时,将不符合规范的代码标红,并且在你保存代码是自动修复一些简单的标红的代码(VSCode 配置 ESlint 教程可自行 Google)
- 手动校验:
yarn lint
(提交代码前执行该命令,特别是在你 lintOnSave 为 false 的情况下)
2️⃣ Git Hooks
package.json
中配置了 gitHooks,每次 commit 时都将检测代码
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"vue-cli-service lint",
"git add"
]
}
❓ 常见问题
1️⃣ 所有的报错
Google 一下可以解决 99% 的报错!
剩下 1% 可以加群问我,然后我偷偷去 Google!
2️⃣ 依赖失败
- 不要使用 cnpm
- 尝试删除 node_modules 后再次依赖
- Google 一下
3️⃣ 路由模式切换为 browserHistory 后,刷新出现空白页面
将 @/config/vue.custom.config.ts
文件中 publicPath
的值从 ./
修改为 /
☕ 其他
1️⃣ 站在巨人的肩膀上
- vue-element-admin
- vue3-composition-admin
- d2-admin
- vue-vben-admin
2️⃣ 交流(吹水)群
无人问津的交流(吹水)群:1014374415