el-admin框架简单解析
- el-admin 简单了解
- 使用框架的四大步
- 前端文件架构
- el-admin前端部分解析
- 前端Vue目录结构
- Layout 布局
- mixins 混入模式
- router 路由
- idnex.js
- rouer.js
- store 状态管理
- utils 工具包
- 后端 (Gin框架)
- 实战解析
- 前端实战
- 一个页面是如何形成的?
- 新建文件夹
- 新建菜单
- 给角色分配菜单
- 跳转到开发页面
- vue文件构成,如何在el-admin前端的基础上写出我们想要的样子?
- template页面渲染
- 搜索和crud按钮
- 表格
- 分页组件
- script
- import
- defaultForm
- export
- component
- crud
- CRUD.operation.vue
- crud.js
- 各种常用的函数
- 最后想说说casbin
- 后端
- 参考文献:
el-admin 简单了解
一个简单且易上手的 Spring boot 后台管理框架。我们可以通过这个框架快速的构建出一个前端搭载element-ui组件库,带有权限控制的后台管理系统。
前台页面千变万化,需求不同展现出的效果也不同,我们很难去找出一套模板供大家去参考使用,但后台管理系统则与之不同,他们的需求有很多都是存在共性的。
就像最常见的几种管理模式
多级角色进行层级管理
基于权限的新增、删除、修改等操作
基于角色的动态路由展示
岗位管理
部门管理
…
后台管控系统中常见的需求el-admin都可满足详情可以查看官方文档,也可以查看在线预览el-admin的效果预览地址(https://el-admin.xin/),账号密码:admin / 123456
官网:https://el-admin.vip/
前段代码(gitHub):https://github.com/elunez/eladmin-web
后端代码(gitHub):https://github.com/elunez/eladmin
使用框架的四大步
使用一个框架,
- 第一步:明白为何选择这个框架来完成此次项目(框架帮我们做了什么)
- 第二步:框架的技术栈(要提前确认自己是否缺少那一部分,是否会影响到此次项目,影响的话要提前查补缺漏)
- 第三步:根据官方文档、视频、博客敲一点小例子(快速入门),这里更建议去官方文档进行学习
- 第四步:重点再研究一下自己这次项目要接触到的技术点,然后扒一扒源码就可以开始码了。
前端文件架构
【public】:里面存的是el-admin的图片和默认主页,对我们做项目没什么价值。
【src】:里面存储了项目源码
【api】:存储各个模块的api函数,el-admin使用RESTful风格来管理接口,接口就是前端通过给后端发送请求,后端接收到请求之后,进行自己的逻辑处理,最终把数据可以返回给前端,这样前端就收到了数据。
【assets】:原el-admin的静态资源文件夹,存放了一些图片和图标,不过我们的项目并没有用到。
【components】:一些公共组件,比如搜索框,增删改按钮等
【layout】:这个文件里存储了el-admin的侧边栏和主体框架的布局,一般不对这里进行更改。
【mixins】:mixins 混入,这里要先提及一下Vue中的mixin(混入),简单介绍来说,相当于Java中的extends ,继承。
【router】:存放了路由相关的信息,一般也不怎么修改,包括动态路由,静态路由的信息。
【store】:存放了框架中的一些状态信息,算是框架的一些配置信息,比如token的获取,token的过期时间,是否显示某些东西,我们这次做项目没有用到里面的内容,关于权限和token这一块都已经封装好了,我也就没看里面的源码。
【utils】:工具包,里面存放了一些框架的工具方法,比如获取token,设置token,标题,请求,验证等。
el-admin前端部分解析
这里我默认的认为大家都至少已经进行到使用框架的四大步中的第三步,意思就是简单讲官方文档粗略的过了一遍。若没有,现在立刻马上去看官方文档,官方文档中还是有很多的东西,若是能在那里吃透的话,尽量还是看官网的来。
下边我要介绍的是一些我做项目中自己的理解,可以帮助大家更快的去上手这个框架,以及这个框架中我们遇到的一些问题,希望能给大家一些帮助。
前端Vue目录结构
可以看出,其实el-admin的前段Vue目录结构与寻常的Vue项目目录结构并没有太大的差别。其中较为特别的地方我来简单介绍下
Layout 布局
el-admin前段部分有写好的界面,页面部分的布局风格就是通过layout模块进行控制的,这部分控制的就是界面上的侧边栏以及主体部分的布局,一般是不会对其进行更改。
mixins 混入模式
这里要先提及一下Vue中的mixin(混入),简单介绍来说,相当于Java中的extends ,继承。
简单的小例子:
一个Vue组件(组件1)去混入另外一个Vue组件(组件2),相当于这个组件(组件1)继承了被混入组件(组件2)的属性。其中的data域中的不同名属性直接都保留,同名属性取这个组件(组件1)的值,methods域规则同data域,钩子函数则二者的都会被执行,但被混入组件(组件2)的钩子函数会先执行,具体的可以查看Vue.js中mixin的官方介绍.https://cn.vuejs.org/v2/guide/mixins.html
el-admin中的mixins
框架中mixins主要是用于一个重要的组件–CRUD组件的支持,CRUD具体内容我会在components部分介绍
router 路由
idnex.js
我们都知道,el-admin有一个特性就是通过动态路由实现不同页面的访问权限控制。
其中大致功能我都标注在图中了,函数的具体内容逻辑也比较简单,这里就不在给大家赘述了,打击自己拉过代码自己看一下就能明白。
其中有一点要提一下,框架这些界面是都要登录后得到token后才能访问的,但一些页面 如“登录页”的访问是不需要token的 ,这类界面添加到 whiteList 数组中即可(当然要提前在router.js中配置好)
rouer.js
其中配置了一些静态路由, 类似个人信息,首页,登录页等等(不需要进行访问权限控制的)的页面路由。这里也不在赘述。
store 状态管理
只是vuex 很基本一些用法,这里要介绍的框架中的一些配置。
我们这次项目只用到了其中的 user.js 和 permission.js 其中存储这用户用户登录后API端返回给前端的用户基本数据,以及当前登录人的身份(permission),其中包含这用户的登录逻辑,具体的感兴趣的可以自行查看
具体使用,一定会用用到的部分,通过 getter.js可以看出
其中的用户信息,用户身份,是我们开发中经常要用到的属性,例如一些页面内的按钮级的权限管理,就需要我们前端开发者比对这些信息进行特定的处理(v-if)。
utils 工具包
里面有一些框架自带的工具方法,但不一定符合我们的业务需求,大家可以根据需要进行更改,为了考虑到小白下面将utils中的一些常见工具简单讲解一下
auth.js
这里的授权管理,指的是登录时后端生成的token的管理函数,getToken、setToken和removeToken。
clipboard.js
剪切板函数 ,底层实现也是实现了web-api的一个
datetime.js
日期操作的一些常用函数
get-page-title
这个是获取页面标题的方法
index.js
这里面的方法相对来说就比较常用了,我将花费一定的篇幅去给大家讲解下这里面都帮我们写好了那些常用的函数工具。
- parseTime(time, cFormat):将时间解析为字符串,传闯入data和格式,返回相应格式的数据
- formatTime(time, option) :格式化时间,和parseTime是不同的,这个方法可以将时间具体格式成 ‘刚刚’、‘一天前’、‘一小时前’…等等等
- getQueryObject(url):可以获取url路径上的参数列表,封装成一个JS对象返回给你。
byteLength(str):返回字符串的字节长度 - cleanArray(actual):这个还是比较常用的,可以帮助我们将数值中的空值给清除掉
- param(json):这个就更常用了显现是调用了上边的cleanArray,清除jason中的空值,
- param2Obj(url):与getQueryObject的区别在于,这个是返回的一个字符串对象(JSON对象)
- html2Text(val):就像函数名所写的那样,将一个节点转化为 html代码。
- objectMerge(target, source):合并两个对象,相同字段保留source中的值。
- toggleClass(element, className):切换一个类名,类存在则删去,不存在则添上。
- debounce(func, wait, immediate):防抖函数,防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
- deepClone(source):deep深度拷贝,这只是deep copy的一个简单版本,有很多边盒缺陷如果你想使用一个完美的深拷贝,可以使用lodash的.cloneDeep
- uniqueArr:根据传入的数组,生成一个无重复值的数组(内部通过Set集合实现)
- createUniqueString():生成一个唯一码,类似uuid
- hasClass(ele, cls):检查节点是否具有该类。
- addClass(ele, cls):给节点添加该类
- removeClass(ele, cls):删除该类
- regEmail(email):对邮箱进行加密,例:[email protected] =>123****@qq.com
- regMobile(mobile):对手机号进行加密,例:15500001234 => 155****1234
- downloadFile(obj, name, suffix):下载文件,原理帮助我们生成一个不显示的a连接,然后触发点击事件,然后删除a连接。
open-window.js
帮助我们生成一个新的窗口。
permission.js
涉及到了el-admin的权限管理 ,其中只有一个方法**checkPermission(value)**返回值为Boolean
后端 (Gin框架)
【app】:下面存着我们的后端项目文件
【admin或smartcampus】:这两个都是我们项目的文件,下面往往都会有四个文件夹,apis,ctrl层,用来接收请求,接收前端传来的数据。 models,Dao层,用来操作数据库。 router,存放本模块各种路由信息。 service,service层,用来做一个承上启下的过程,apis获取前端传来的参数之后,自己会进行校验,然后调用service层的函数,把接收的参数当做参数传递,此时service层的文件就可以根据自己的逻辑对这些传来的数据进行处理,如果有需要调用数据库的事情,比如增删查改操作,就在service层调用models的函数来获取数据。
【common】:里面写了各个模块的一些公共的方法,比如获取用户的上下文,错误处理,数据库迁移的设置,服务启动,路由设置等,基本上还是原框架所用到的一些方法,内容也不多。
【logs】:存放了各个层级的error
【pkg】:里面存的是第三方库的引用,比如casbin,jwt,file的封装方法。
【settings】:这个里面保存了settings.dev.yml,settings.prod.yml文件,也就是程序各种各样的配置,比如端口,ip,一些全局的配置等。
【utils】:写了各个模块的工具方法,不过我们的项目也用的不多。
剩下的都是git,或者go的包管理,主程序文件了。
实战解析
前端实战
一个页面是如何形成的?
新建文件夹
首先,这个框架一个中规中矩的页面,大概就是这个样子,el-admin是基于element组件的,所以我们在开发el-admin的时候,需要先去了解一下element组件。
需要建立这样一个页面,我们首先需要去【views】中新建一个自己模块的文件夹,假如说就叫model1吧,然后可以在这个文件夹下再新建一个文件夹,比如test1吧,然后可以创建一个index.vue文件。
类似于下面这样,此时我们已经相当于建立了自己的页面文件,但是如何在网页的菜单中点击某个菜单访问index.vue需要我们进行一些设置。
这些名字都无所谓,包括index,都可以改成其它的,只需要配置好就可以了。
新建菜单
我们需要在页面左侧的菜单栏的最下面,出现一个测试管理的下拉菜单,然后里面有一个测试二级菜单,当点击这个测试菜单,就会跳到我们刚才新建的model1/test1/index.vue页面。
我们进入菜单管理,然后点击新建按钮。
- 菜单类型:有目录,菜单,按钮三种类型,所谓的目录,就是左边你所看到的系统管理,学生管理,类别管理,考评管理这些一级标题,这也是我们在写一个新的模块的时候,所最先去做的事情。
- 菜单图标:作为展示的图标
- 外联菜单:我们设置非外联菜单就可以了,外联菜单是指你需要跳转到外部的链接,比如说百度,比如说搜狐等,关于这部分的设置,在el-admin的前端手册中有说明,此处不在赘述。
- 菜单可见:菜单可见是指是否在侧边菜单栏中显示。
- 菜单排序:后端可以通过这个排序数字来对菜单进行一个排序,在有些时候有用,比如你创建了一个model1,model2,model3三个模块,你就是想让他们按照某个顺序展示出来,就可以通过这个排序的数字来控制。
- 路由地址:就是浏览器访问这个菜单的地址,我这里写的是test,那么访问这个顶级类别下的二级类别就应该是http://127.0.0.1:8000/test/xxx。
通过下面的方式,我就创建了一个测试管理模块。
可以看到我们已经创建成功了。 此时常理来讲,你在侧边栏是看不到这个菜单的——即使你新建了,不过不要着急,我们还是一股脑的再建一个二级菜单,一块让它显示出来。
我们刚才建立了一个菜单类型为目录的菜单,现在我们要创建一个菜单类型为菜单的菜单,也就是我们的二级标题,顺带插一嘴,按钮类型的作用不在页面显示上,而是为了控制权限,等我到casbin权限那一块再细细讨论。
我就只解释几个字段:
- 路由地址:就是访问这个菜单的URL地址,我写的是test1,它的上级类目是我们刚刚创建的测试管理,它的路由地址是test,而我们的测试一二级标题的路由地址是test1,那么也就是说访问测试一的url地址应该是http://127.0.0.1:8000/test/test1/xxx。
- 组件路径:是当我们点击测试一这个二级标题,访问http://127.0.0.1:8000/test/test1/的时候,会渲染哪个页面?这个时候就把我们刚才创建的model1/test1/inddex用上了,你可以根据自己的名字来创建。
- 组件名称和菜单缓存是相互的关系,如果不用菜单缓存,组件名称可以不填,其它的字段,我也不是很清楚了,暂时没用上。
这样就可以看到我们已经创建好了测试一。
给角色分配菜单
el-admin的菜单是按照角色来分配的,你可以控制某个角色能看到某些菜单,相应的不让看到某些菜单的话,对应的接口,这个角色也无法访问,这个api的权限控制使用到了casbin,暂且不表。
当我们点击角色管理,因为我登陆的是admin账号,属于超级管理员的角色,所以我就设置超级管理员这个角色的菜单分配了,这个地方有个坑,就是很多人会去点击那个选择框,会发现右边的菜单分配并不会变化,那是因为勾选选择框是代表对这个用户进行操作,并不是菜单分配,只需要点击一下这个用户的空白地方,右边就会显示这个用户的菜单维护情况了,我们看到我们刚才新建的测试管理模块并没有被勾选上。
我们把它勾选上,然后点击保存,保存会等待一下,其实这个时候后台在为这个用户添加该测试模块的一些权限配置。
保存成功之后刷新页面就能看到我们创建的测试管理了。
跳转到开发页面
此时我们点击我们创建的测试一,会发现和我们测试的猜想是一模一样的,我们访问了/test/test1地址,然后访问了我们创建的index.vue文件,这里面是我复制的另一个页面的数据。
如果你要开发一个模块的话,现在就可以点击那个vue文件进行开发了,接下来我会带着你解析一下这个vue文件的构成。
vue文件构成,如何在el-admin前端的基础上写出我们想要的样子?
el-admin的各个页面基本上都是下面的这种结构,大差不差,不过有的时候它可能无法满足我们的要求,我们可能会需要自己去做一些个性化的改善。
刚才我们看到的页面就是下面的代码。
- 【template】:整个页面的内容写在这个标签下
- 【app-container】:这个里面包含了所有的主体内容。
- 【head-container】: 这个div里面建立了input搜索框,日期搜索框,搜索按钮与重置按钮,以及第二排的新增,修改,删除,导出按钮,和右边的三个按钮。
- 【el-dialog】:当点击添加或编辑按钮的时候会弹出这个对话框,是element的组件。
- 【el-table】:展示的主题控件,是element的组件
- 【defaultForm】:里面定义了表单的初始值,以及控件数据源的绑定,也涉及到框架内部对字段的维护,比如点击弹出框的取消按钮,消除所有的内容,就需要把弹出框的变量都写在defaultFrom中。
- 【export default】:这一块定义了核心的内容
- 【name】:这个对标的是我们创建菜单的时候,有个组件名称 字段,用于菜单缓存,不过我们也没用到,所以写不写都行。
- 【components】:这是我们的页面中所用到的组件,我这里引用了六个组件,前五个是比较常用的,udOperation是表格中最右边的编辑和删除按钮,DateRangePicker是日期搜索框需要用到的,rrOperation是搜索框右边的搜索和重置按钮,pagination是分页组件,crudOperation是搜索框下面的四个按钮,IconSelect是我们需要去选择图标的时候用到的组件。
- 【cruds】:这个里面定义了一些进入这个页面的时候,对框架进行一些初始化的内容,比如title,中间table所访问的url地址,api的引入地址,或者一些其它的设置等,总之当你进入到这个页面的时候,会有一大堆的东西可以提前设置一下,有些是必须要设置的,有些可以先不设置。 这个crud常常指代的就是el-admin这个框架的运转。
- 【mixins】:设置混入模式,不过因为我个人对前端并不是很专精,所以这个我不是很清楚,不过我大概知道混入模式的各个模块可以共用属性,至于为什么要用这几个就不太清楚了,参考其它的页面用的是这几个,就照着用了。
- 【data】:设置一些变量,以及rules验证
- 【methods】:这个就不多说了,关于本页面的js操作就在这里写了。
template页面渲染
搜索和crud按钮
接下来我们就专门讨论一下页面渲染这一块,看看各个部分是怎么组成出来的,以及,如何写出我们想要的样子。
我们先看下面的蓝色部分,首先第二句有一个v-if来控制这个div的显示与隐藏,可以看得出来是crud的searchToggle属性来控制的,不过我暂时还没有弄明白它具体有什么用,待日后再填吧。
紧接着是一个el-input,这里面的各个属性大家可以自己去查一查,class也是框架自带的,需要重点关注的有三个属性:
【v-model】:你可以写query.xxx的名字,这个地方的作用是当你写的是query.blurry时,当你点击搜索按钮,搜索框的内容发入后端的参数名就是blurry,同样的,当你写query.name的时候,在输入框中输入内容,然后点击搜索,就会发现参数变成了name,至于点击搜索去访问什么url地址,去哪里设置接口的地址,我后面再讲。
【placeholder】:这个就是当控件没有内容的时候的提示,你要根据你的业务进行填写。
【keyup.enter.native】:这个是当你在这个控件输入内容之后,你按了一下enter键,进行的操作。 crud.toQuery就是搜索的方法,也就是当你在搜索框内输入内容,你可以点击搜索按钮来执行搜索,也可以按enter键来执行搜索。
接下来的是【date-range-picker】组件,这个组件就是我们的时间搜索框,它绑定的query.createTime和搜索的有些不同,这个字段相对固定,因为当你点击搜索的时候,会去获取createTime这个字段的值,然后进行一定的处理,再发出去。 这也是为什么当你选择时间再搜索会发现多了两个参数,一个是startTime,一个是endTime,这都是框架里写好的,不过你要是想改,也可以去改,后面介绍到crud.js的时候,我会和你讨论的。
总之它会接收query.createTime这个参数,然后它是一个数组,里面存了开始日期和结束日期,也就是格式为[start,end]这样的格式,crud会对它进行处理,最终再把他们给两个参数传给后端。
在接下来,你会看到 这一行信息,如果你追踪到这个组件的话,会发现它就是搜索和重置按钮。
紧接着又看到了这一行,这是第二排那四个按钮,以及第二排最右边还有三个不显眼的按钮,permission定义了这些按钮的权限,这个等讲到js代码的时候再说。
这样第一部分我们就讲完了。
点击新增和编辑的弹出框
第二部分是下面的代码,它是一个对话框中套了一个表单控件。
首先说说的属性:
第一行为false是为了控制不能点击对话框外空白的地方关闭对话框。
第二行表示当你点击对话框的右上角叉号的时候,会去调用crud.cancelCU函数,而这个函数会将对话框关掉。
第三行可以看出crud是如何控制对话框的开启和关闭的,是靠crud中status下的cu属性,通过控制它的属性来控制对话框的开启和关闭,至于右边的showInsertDialog属性,那是我自己加的,是我想在crud的基础上,再限制一些条件才能开启。
第四行设置了对话框的标题,它是通过crud.status.title来获取的,而这个属性,在下面script中会有赋值。
剩下的属性自己查吧。
接下来就说说el-form组件
el-form中ref和model属性必须是form(框架内进行维护的就是这个名字,除非你有其它的用处),也就是说只有为form这个名字,它才会被crud检测到,上面那些crud.xxx的属性才能作用到这个对话框上。
接下来的item,你就可以自己去百度查如何写了,或者参考el-admin的其它新增页面,看看是怎么写的,自己做一些修改,这个不是我们的重点,就不赘述了。
唯一一点需要强调的是各个item项下的控件的v-model属性绑定的都是form.xxx,需要写成这样的形式,而item的prop属性一般和xxx相同(参考上图的积分下限即可,prop=lower_limit,v-model=form.lower_limit),然后这些xxx都需要在下面的defaultForm属性中定义下。
当你点击确定,发送表单的时候,prop属性就是你发给后端的参数,比如积分下限,我们输入了-1,点击确定,发送给后端就是lower_limit:-1,v-model.number可以控制发送的数值为数字,如果你发送的无法转为数字,vue会发送原本的字符。
主要需要考虑一个这些输入框和crud的协调问题,既然我们需要crud的帮助,就要遵守crud对我们制定的规则。
表格
这常常是我们对这个页面最关心的部分。
接下来我们来看看这段代码
还是先看看属性,有三个关于crud的:
【v-loading】:这个是控制表格加载的,为true就加载,为false就停止加载,crud有一个loading属性来控制,比如添加后要重新加载一下,编辑要重新加载一下等等。
【data】:这个是表格的数据,等于crud.data,而crud.data属性会获取后端传来的数据,这个我们后面再说。
【selection-change】:这个是当你打勾表格的数据的时候,crud会有一个selections属性来存储对应行的数据,是一个列表。
属性讲完之后,就会表格各个列的名字了,其中会发现有三个地方比较瞩目:
【考评id和积分类别id】:v-if=false就是不显示出来,既然不显示出来,又为什么要在这里呢?是因为在编辑某一条数据的时候,我们往往需要携带这一条数据的id给后端,那么我们就可以通过这个隐藏的列来拿到id。
【创建日期】:这一列我们用parseTime来将后端传过来的时间戳转为日期。
【操作】:也就是最右边的两个按钮,它是调用了组件,这个组件下也有permission,可以控制权限,也就是哪个角色会显示哪个按钮。
另外一个最重要的就是各个列的prop属性不是乱写的,需要根据后端传来的参数来填写,table会自动的填充对应的数据。
比如你想让某一列得到超级管理员这个值,那就把它的prop设置为creator。
分页组件
这个用它默认的就可以了,只要数据返回的符合规范,就没有问题。
script
import
第一部分当然是import,这些都是我们要用到的内容,第一行是我们的api的位置。
可以看到我在api文件夹中创建了我们的模块,里面存放了本模块的api
可以让你看看,大概是这个样子,你需要注意这里的add,del,edit三个函数,因为他们的名字不能更改,讲到下面的URL的时候再说这个事情。
defaultForm
这里就把form中的各个参数写下来就可以了,可以给一些默认值,null就代表空。
export
之前讲过的就不讲了,重点讲一下前面的cruds(),这个是crud内部的方法,用来作初始化。
title属性会控制弹出框的标题,如果你写“考评类别”,crud会存title为“考评类别”,当你点击新增按钮的时候,它会在title的前面加上“新增”,所以最终呈现的就是“新增考评类别”,当点击编辑就变成了“编辑考评类别”,但其实新增和编辑都是用的同一个对话框。
url属性非常的重要,这一个地址影响了很多,它就是我们访问的api地址。
当我们刚进入到这个页面的时候,它就会访问http://localhost:8013/api/appraisal-classification/list这个地址,是一个get请求,返回的数据必须如下图所示,否则框架会找不到对应的数据。
也就是最外层是code,data和message属性,这个message属性就是我们做各种操作的提示信息,data下有current,orders,pages,size和total属性,这五个是有关分页和排序的数据,再加上一个records才是我们查出来数据库的内容。
这些属性少了都会有问题。
当你点击搜索的时候,也会走这个地址,如果搜索的输入框有内容的话,会在原来的参数基础上加上输入框的内容,如果日期搜索有内容的话,也是这样。
所以如果想完成搜索功能,后端需要接收一个input框的内容,然后可以做模糊查询之类的,还需要接收startTime和endTime。
crudMethod存的是我们引入的api中的内容,相当于是让crud这个框架知道这个页面用的是什么api,另外你自己想用某个api的数据,也可以通过引入的名字来调用。它的下面是optShow属性,会发现里面有五个属性为true,这个是控制第二排四个按钮,和重置按钮的显示,比如有的时候我们不需要导出功能,就需要让download属性为false,这个时候你就会发现页面上没有导出按钮了,其它也是同理。
这个时候我们就要聊聊api中的add,del,edit函数了。
这三个函数的名字是固定的,甚至连参数的格式也是固定的。
当点击页面上的添加按钮并提交后,会调用这里的add函数,参数是form表单的数据。
当点击页面上的删除按钮,或勾选了很多进行删除,都会调用del函数,给后端发送一个list(不是json),只是一个list,类似[1,2,3],里面存的是选中行的id。
当点击页面上的修改按钮并提交后,会调用edit函数,参数是form表单的数据外加编辑的那一行table的数据。
这样的话,整个页面我就算是讲完了,剩下的我感觉自己摸索就可以了。
component
components文件夹下有很多的内容,比如面包屑,导航栏,图标,日期搜索框等。
而对我们最重要的,就是Crud这个文件夹内的内容了,所以今天就只讲讲这一块。
crud
这个文件夹下,我就说crud.js和CRUD.operation.vue两个内容,把这两个内容了解一些,其它的内容也可以理解一些了,另外就是其它的内容我研究的也不多,希望各位能多出一些其它的内容来教教我,感激不尽。
CRUD.operation.vue
这就是它的能力范围,我为什么要说这个呢? 因为有的时候,我们不见得就想用它的按钮,比如我们想加个批量修改的按钮,就需要自己在CRUD.operation的基础上进行一个封装才可以。
点开之后是这样一堆的东西,上面写的是四个按钮,可以看到为什么我们在页面中optShow属性中,通过对download属性设置false,可以让导出按钮消失,就是这个v-if设置的,同样的你想让其它button消失,也可以进行设置。
然后你会发现下面有较为复杂的js代码,其实你没必要看懂的,也不太需要。
如果你想在导出的右边再加一个按钮,只需要复制一下导出这个按钮,然后改一下名字,然后把click事件改一下,完成自己想要的功能就可以了。
crud.js
添加按钮的执行过程
我们可以通过CRUD组件来打开crud.js的大门,页面往往有四个按钮,我带你分析一下新增按钮,可以发现click绑定的是crud的toAdd函数。
我们找到这个函数,会发现它的作用是启动添加。
首先是调用了resetForm()函数,清空一下表单,接下来是关于crud钩子的判断,然后比较重要的是设置了一下add的状态,为CRUD.STATUS.PREPARED,这个状态代表现在是启动添加,。
你找一下这个状态,会发现它的值为1
你还记得弹出框有个通过crud.status.cu > 0来控制对话框的显示和关闭吗?而我们通过找到cu,发现它是通过判断按钮的值来返回的,此时cu的值就是1,那么对话框就会弹出来。
也就是当你点击新增按钮的时候,调用了toAdd方法,这个方法设置了crud.add=1,而cu属性会获取这个1,对话框通过cu属性>0来显示。
接下来我们再看看toAdd函数第一行调用的resetForm函数,可以看到第一行它就去找form节点,如果你的对话框的ref不是form的话,就找不到了。
此时用户应该在填写表单,如果它点击了取消,会调用cancelCU函数,如果点击确定会调用submitCU函数。
这个cancelCU里进行了一大堆,其实就是维护状态,把他们的status都变成0,也就是CRUD.STATUS.NORMAL,然后再resetForm,把表单清除一下。
按钮的操作中主要靠这个状态来做操作。
submitCU重要的是下面,它会通过校验是哪个按钮是PREPARED状态,也就是正在写表单的状态,那就说明哪个该提交了,那么它就会走crud.doAdd()。
我们点进去发现它是执行添加函数,可以看到函数内第三行是给add赋值了一个PROCESSING状态
按钮其实就是三个状态:NORMAL、PREPARED、PROCESSING,第一个代表无操作,第二个代表这个按钮被点击了,用户正在写对话框中的数据,属于占用状态,第三个就代表用户已经写好了对话框,点击提交,是提交阶段。
紧接着你就发现它调用了Method.add,也就是我们页面中引入的api文件中的add函数,然后把form表单中的数据存进去。
因为已经开始调用api了,也就说明已经提交上去了,如果提交成功,就把add的状态重新变为NORMAL,也就是0,那么对话框就会消失,如果提交报错,就会走catch,把add的状态重新设置为PREPARED,也就是1,对话框不会消失,此时你可以查看错误重新提交。
添加过程就结束了。
各种常用的函数
接下来就是在crud文件的闲逛了。
这个title返回的数据就是页面中crud.status.title获取到的,如果判断是新增按钮,就加新增两个字,如果判断是编辑按钮,就加编辑两个字。
内部还有一个可以获取query参数的函数,通过传名字就可以获得对应的值。
看一下刷新函数吧,点击重置按钮,或者新增,删除,修改,搜索也都会引起刷新。
之前说后端参数的时候,为什么说返回的格式必须要那样返回,是因为后端在获取参数的时候都是写好的。看我红框的这一条,crud.data就是我们的页面中table的数据,当没有页数的时候,它获取的是res.data,当有页数的时候它获取的是res.data.records,也就是说,当你没有分页的时候,你返回的格式应该是res.data,data下是你的数据列表,当你有分页的时候,就要再加一个records来存你的数据列表。
下面这个是获取查询的参数,input框的就不说了,主要看createTime那里,它会获取这个项为createTime,也就是页面上的query.creatTime是不能改的,获取到了之后,对这个time进行了一些转换,然后通过crud.query的参数来存一下,这个就是发给后端的参数名,可见,也是写死的,不过可以通过修改这里来改变名字。
在这个文件的最下面,会发现有一个CRUD钩子,这个是很好用的。
它就是crud的生命周期,比如你想在crud的Refresh(刷新)函数调用之前,也就是每次重新加载数据之前,想做一些事情,就可以在这里写。
又比如你想在点击编辑按钮之前做一些事情,也可以找到对应的钩子去写语句就可以了。
最后想说说casbin
casbin可以实现对某个角色进行api级的控制,可以让某个角色去访问某些api,或者去禁止某些api。
你下载el-admin,会发现它有一个casbin_rule数据表,里面存的是一些策略,v0下的1代表是sys_role表id=1的角色,v1是api地址,v2是GET,也就是当用户角色id=1的时候,就运行它访问/api/activity请求,类型为GET。
比如说你想限制某些角色的能力,就可以在这里进行控制。
那么我们一个一个的加,肯定不现实,前端有方式去做。
添加菜单的时候,会发现它有一个请求方式和请求路由,这个对标的是我们刚进入这个页面的那个table的查询接口。
当你写上/api/activity GET的时候,当你为某个角色分配这个菜单,它就会在casbin_rule这个表格里添加对应的数据。
那么同样的,每个菜单下还有很多的按钮,每一个按钮都有对应的地址,就可以点击按钮新建了,也有这个请求方式和请求路由,按钮新建之后并不会在页面上显示,它只是一个为casbin权限控制作说明而已。
这样当你对角色1分配这个菜单之后,这个菜单对应的接口对应这个角色会添加到casbin里,然后这个角色调用这些已经被允许的接口才会被通过,否则显示权限不足。
需要注意的是,它同样需要后端的配合,如果后端没有搭建casbin的话,依然没有作用。
后端这一篇内容写了很久,起初是想前后端都写,但是后来想想,后端好像没什么可写的,既然都接触到这个程度了,不至于连接口是什么都不清楚。
我感觉前端摸清楚了之后,后端并不怎么复杂。 就是一个不断的调接口的过程,知识是相对比较固定的,如果你是Java语言,大可以把el-admin的后端下载下来,然后在其基础上进行删改,添加。
如果你是其它语言,可以先找一个框架,然后找一个框架好用的脚手架,在这个脚手架的基础上写接口来返回数据就可以了。
基本上获取的时候,都是这个参数,Current,Size,Orders前端会自动返回给你,Content是搜索框的内容,StartTime和EndTime是时间搜索框的内容。