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

0. 写在前面

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

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

  • element-ui 饿了么出品的vue2.0 pc UI框架
  • axios 一个现在主流并且很好用的请求库 支持Promise
  • js-cookie 一个轻量的JavaScript库来处理cookie
  • normalize.css 格式化css
  • nprogress 轻量的全局进度条控制
  • 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. 迁移过程中遇到问题集锦

  1. “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章。

  1. 启动服务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工程中把代码拷贝移植过来。

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

在这里插入图片描述

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖永威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值