vue-element-admintemplate+tornado(pyrestful)前后端分离框架实践(1)——自定义菜单和仪表盘

it2026-03-01  2

0. 写在前面

vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。[1]

vueAdmin-template 主要是基于vue-cli webpack模板为基础开发的,引入了如下dependencies:

element-ui 饿了么出品的vue2.0 pc UI框架axios 一个现在主流并且很好用的请求库 支持Promisejs-cookie 一个轻量的JavaScript库来处理cookienormalize.css 格式化cssnprogress 轻量的全局进度条控制vuex 官方状态管理vue-router 官方路由

该项目只做了一个管理后台需要极简的功能,封装了axios请求,支持无限层级路由,动态权限和动态侧边栏。

本项目的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为本项目集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。

花裤衩建议

你可以把 vue-element-admin当做工具箱或者集成方案仓库,在 vue-admin-template 的基础上进行二次开发,想要什么功能或者组件就去 vue-element-admin 那里复制过来。

vue-admin-template/src下的目录结构: . ├── App.vue //入口 ├── api // 各种接口 ├── assets // 图片等资源 ├── components // 各种公共组件,非公共组件在各自view下维护 ├── icons //svg icon ├── main.js //入口 ├── permission.js //认证入口 ├── router // 路由表 ├── store // 存储 ├── styles // 各种样式 ├── utils // 公共工具,非公共工具,在各自view下维护 └── views // 各种layout

1. 我们对前端组件、框架的需求——关注点

登录与权限控制

菜单及其动态菜单

图表展现

图标

色彩搭配

中文处理

跨域问题

2. 裁剪前端vue-element-template工程——开始

按花裤衩的建议,使用vue-element-template为基础,进行二次开发。我们避免重复造轮子,尽量少改源代码,尽量抽取移植vue-element-admin工程内容,重新生成属于自己可控的开源框架平台。

根据Vue给定文件目录结构,我们重点选定如下内容:

功能点专业名称使用文件夹/文件说明菜单路由/src/router/index.js菜单与路由控制登录/src/views/login/index.vue登录控制获取权限权限控制/src/permission.js与路由配合控制转向

我们可以这样理解vue-element-template工程(含权限控制版),vue-element-template只是包括菜单、路由、权限、API接口的基础集成,解决最基本的登录、权限、Token、菜单等最基本需求,其他扩展可以参考大而全的案例vue-element-admin,按需移植过来。

避免啰嗦和干扰,直接把/src/router/index.js中不需要的内容删除,结果如下:

export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/newdashboard', children: [{ path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' } }] } ]

3. 关于中文

3.1. 组件中文

如果有人要做国际化可以去element官网国际化看看写的很详细。 修改/src/main.js文件:

import locale from 'element-ui/lib/locale/lang/en' // lang i18n Vue.use(ElementUI, { locale })

替换en为zh-CN

import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n

3.2. 中文菜单

对于中文菜单,直接在路由的文件(/src/router/index.js),修改meta中title的描述为中文即可。

path: '/opeff', component: Layout, redirect: '/opeff/eff', name: 'OpEff', meta: { title: '作业效率分析', icon: 'money' },

4. 新增菜单及页面

4.1. 新增菜单

在当前菜单框架下,直接编辑路由文件(/src/router/index.js),按其树装结构和格式编写即可,效果如下:

export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/newdashboard', children: [{ path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' } }] }, { path: '/opeff', component: Layout, redirect: '/opeff/eff', name: 'OpEff', meta: { title: '作业效率分析', icon: 'money' }, children: [ { path: 'eff', name: 'Eff', component: () => import('@/views/opeff/eff/index'), meta: { title: '效率综合分析', icon: 'eye-open' } }, { path: 'outlet', name: 'Outlet', component: () => import('@/views/opeff/outlet/index'), meta: { title: '发油效率分析', icon: 'link' } } ] } ]

注:对于动态菜单,按权限控制菜单,由于文章逻辑和篇幅有限,先行略过,后续文章再写。

4.2. 新增页面

这里所说的新增页面,是指与新增菜单配套的页面,首先,根据上文菜单,在/src/views目录下形成如下文件夹结构: 在view目录下新增newdashboard目录,内新增index.vue, 作为改页面的入口。 /src/views/newdashboard/index.vue 拷贝vue-element-admin-master/src/views/dashboard/admin/index.vue内容,删减后保留如下内容:

<template> <div class="dashboard-editor-container"> <github-corner class="github-corner" /> <panel-group @handleSetLineChartData="handleSetLineChartData" /> <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> <line-chart :chart-data="lineChartData" /> </el-row> </div> </template> <script> import GithubCorner from '@/components/GithubCorner' import PanelGroup from './components/PanelGroup' import LineChart from './components/LineChart' const lineChartData = { ...... } export default { name: 'DashboardAdmin', components: { GithubCorner, PanelGroup, LineChart }, ...... } </script> <style lang="scss" scoped> ...... </style>

在/src/views/newdashboard下建立components目录,拷贝vue-element-admin/src/views/admin/dashboard下的文件和文件夹: /src/views/dashboard/admin/components/LineChart.vue /src/views/dashboard/admin/components/PanelGroup.vue /src/views/dashboard/admin/components/minxins

4.3. 迁移过程中遇到问题集锦

“npm install”遇到的提示: ...... To install them, you can run: npm install --save echarts echarts/theme/macarons To install it, you can run: npm install --save vue-count-to

注:解决方案见第5章。

启动服务webpack提示: [Vue warn]: Error in mounted hook: “TypeError: Object(…) is not a function” /src/views/newdashboard/components/LineChart.vue文件中 <script> import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize'

"./mixins/resize"指向/src/views/newdashboard/components/mixins/resize.js文件,文件中:

import { debounce } from '@/utils'

“@/utils”指向/src/utils/index.js文件,发现文件中没有“debounce”函数,需要从vue-element-admin工程中把代码拷贝移植过来。

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components 出现这个错误的原因 检查一下你引入的组件里面是否在components里面写入子组件。

/src/views/opeff/outlet/components/TransactionTable.vue?vue&type=script&lang=js&) Module not found: Error: Can’t resolve ‘@/api/remote-search’ in ‘D:\VueApp\vue-admin-template-permission-control\src\views\opeff\outlet\components’ 把/src/api/remote-search.js文件移植拷贝到工程中。

5. 增加图表组件ECharts

当在代码中引用ECharts、数字滚动等新增插件,需要在/package.json中注册插件,如下所示:

"dependencies": { "axios": "0.18.1", "core-js": "3.6.5", "echarts": "4.2.1", //新增 "element-ui": "2.13.2", "js-cookie": "2.2.0", "normalize.css": "7.0.0", "nprogress": "0.2.0", "path-to-regexp": "2.4.0", "vue": "2.6.10", "vue-count-to": "1.0.13", //新增 "vue-router": "3.0.6", "vuex": "3.1.0" },

或者,手动安装echarts,npm install echarts --save。

注:在HBuilder X开发工具下,需要先删除目录/node_modules,并删除package-lock.json,修改package.json文件,增加“echarts”配置,重新npm install。

6. 图标处理

6.1. 菜单上的图标

路由文件(/src/router/index.js)中的icom的描述与图标对应。

path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' }

运行vue-element-admin项目,“Icons”菜单下能看到已经集成到的图标,按名称引用和拷贝。

6.2. 页面上的图标

例如/src/views/newdashboard/components/PanelGroup.vue文件需要图标,如下图所示,需要把图标peoples.svg拷贝到/src/icons/svg目录下。

7. 目录权限

做后台项目区别于做其它的项目,权限验证与安全性是非常重要的,可以说是一个后台项目一开始就必须考虑和搭建的基础核心功能。我们所要做到的是:不同的权限对应着不同的路由,同时侧边栏也需根据不同的权限,异步生成。这里先简单说一下,我实现登录和权限验证的思路。[2]

登录:当用户填写完账号和密码后向服务端验证是否正确,验证通过之后,服务端会返回一个token,拿到token之后(我会将这个token存贮到cookie中,保证刷新页面后能记住用户登录状态),前端会根据token再去拉取一个 user_info 的接口来获取用户的详细信息(如用户权限,用户名等等信息)。权限验证:通过token获取用户对应的 role,动态根据用户的 role 算出其对应有权限的路由,通过 router.addRoutes 动态挂载这些路由。

7.1. 路由表定义菜单及权限

大多数系统都有根据用户权限,或者说角色,展示相应菜单/页面的需求,目录权限直接体现在/src/router/index中。

结合框架来实现目录的控制,如果是传统项目,一般是把目录结构整个存在后台数据库里,然后前端循环展示出来,但是这个在这里不需要这么麻烦,只需要把每个页面对应的权限保存起来就行了

/src/router/index表示目录为两个部分: constantRouterMap 与 asyncRouterMap

constantRouterMap:主要是通用部分,每个用户都有的页面asyncRouterMap:需要进行权限过滤的页面

7.2. 根据角色选定菜单(权限)

通过“/src/permission.js ”代码,按角色控制选择菜单。

通过参考/mock/user.js,可以明确知道系统角色定义为admin和editor,参考如下:

const tokens = { admin: { token: 'admin-token' }, editor: { token: 'editor-token' } } const users = { 'admin-token': { roles: ['admin'], introduction: 'I am a super administrator', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', name: 'Super Admin' }, 'editor-token': { roles: ['editor'], introduction: 'I am an editor', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', name: 'Normal Editor' } }

8. 效果

本实践后台采用Python开发,使用基于Tornado的pyrestful插件开发rest服务。后续详见《vue-element-admin/template+tornado(pyrestful)前后端分离框架实践(2)——登录过程与后端python服务》。

由于笔者水平有限,时间仓促,欢迎讨论交流。

参考:

[1]《vue-element-admin》 [2]《手摸手,带你用vue撸后台 系列二(登录权限篇)》 掘金 , 花裤衩 ,2017年5月 [3]《vue-element-admin登录流程》 博客 , 兔子零84 , 2019年09月 [4]《Vue 新手学习笔记:vue-element-admin 之登陆及目录权限控制》 博客 ,乐之终曲 ,2019年05月 [5]《Access-Control-Allow- 设置 跨域资源共享 CORS 详解》 博客 ,Normal Developer , 2017年12月 [6]《Cross-Origin Resource Sharing (CORS》) MDN web docs [7]《使用vueAdmin开发后台管理系统(登录篇)》 博客 ,zw沐知 , 2020年7月 [8]《Nginx+Vue.js+Tornado前后端分离架构环境实践(2)》 博客 , 肖永威 2020年10月

最新回复(0)