3. 员工分页查询
3.1 需求分析
系统中的员工很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。而在我们的分页查询页面中, 除了分页条件以外,还有一个查询条件 "员工姓名"。
- 请求参数
- 搜索条件: 员工姓名(模糊查询)
- 分页条件: 每页展示条数 , 页码
- 响应数据
- 总记录数
- 结果列表
3.2 程序执行流程
3.2.1 页面流程分析
在开发代码之前,需要梳理一下整个程序的执行过程。
A. 点击菜单,打开员工管理页面时,执行查询:
B. 搜索栏输入员工姓名,回车,执行查询:
1). 页面发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端
2). 服务端Controller接收页面提交的数据, 并组装条件调用Service查询数据
3). Service调用Mapper操作数据库,查询分页数据
4). Controller将查询到的分页数据, 响应给前端页面
5). 页面接收到分页数据, 并通过ElementUI的Table组件展示到页面上
3.2.2 前端代码介绍
1). 访问员工列表页面/member/list.html时, 会触发Vuejs中的钩子方法, 在页面初始化时调用created方法
从上述的前端代码中我们可以看到, 执行完分页查询, 我们需要给前端返回的信息中需要包含两项 : records 中封装结果列表, total中封装总记录数 。
而在组装请求参数时 , page、pageSize 都是前端分页插件渲染时的参数;
2). 在getMemberList方法中, 通过axios发起异步请求
axios发起的异步请求会被声明在 request.js 中的request拦截器拦截, 在其中对get请求进行进一步的封装处理
最终发送给服务端的请求为 : GET请求 , 请求链接 /employee/page?page=1&pageSize=10&name=xxx
3.3 代码实现
3.3.1 分页插件配置
当前我们要实现的分页查询功能,而在MybatisPlus要实现分页功能,就需要用到MybatisPlus中提供的分页插件,要使用分页插件,就要在配置类中声明分页插件的bean对象。
所属包: com.itheima.reggie.config
1.<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">extension</span>.<span style="color:#000000">plugins</span>.<span style="color:#000000">MybatisPlusInterceptor</span>; <span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">extension</span>.<span style="color:#000000">plugins</span>.<span style="color:#000000">inner</span>.<span style="color:#000000">PaginationInnerInterceptor</span>; <span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">context</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">Bean</span>; <span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">context</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">Configuration</span>; <span style="color:#aa5500">/**</span> <span style="color:#aa5500">* 配置MP的分页插件</span> <span style="color:#aa5500">*/</span> <span style="color:#555555">@Configuration</span> <span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">MybatisPlusConfig</span> { <span style="color:#555555">@Bean</span> <span style="color:#770088">public</span> <span style="color:#000000">MybatisPlusInterceptor</span> <span style="color:#000000">mybatisPlusInterceptor</span>(){ <span style="color:#000000">MybatisPlusInterceptor</span> <span style="color:#000000">mybatisPlusInterceptor</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">MybatisPlusInterceptor</span>(); <span style="color:#000000">mybatisPlusInterceptor</span>.<span style="color:#000000">addInnerInterceptor</span>(<span style="color:#770088">new</span> <span style="color:#000000">PaginationInnerInterceptor</span>()); <span style="color:#770088">return</span> <span style="color:#000000">mybatisPlusInterceptor</span>; } }</span></span>
3.3.2 分页查询实现
在上面我们已经分析了,页面在进行分页查询时, 具体的请求信息如下:
请求 | 说明 |
请求方式 | GET |
请求路径 | /employee/page |
请求参数 | page , pageSize , name |
那么查询完毕后我们需要给前端返回什么样的结果呢?
在上述我们也分析了, 查询返回的结果数据data中应该封装两项信息, 分别为: records 封装分页列表数据, total 中封装符合条件的总记录数。 那么这个时候, 在定义controller方法的返回值类型R时, 我们可以直接将 MybatisPlus 分页查询的结果 Page 直接封装返回, 因为Page中的属性如下:
那么接下来就依据于这些已知的需求和条件完成分页查询的代码实现。 具体的逻辑如下:
A. 构造分页条件
B. 构建搜索条件 - name进行模糊匹配
C. 构建排序条件 - 更新时间倒序排序
D. 执行查询
E. 组装结果并返回
具体的代码实现如下:
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">/**</span> <span style="color:#aa5500">* 员工信息分页查询</span> <span style="color:#aa5500">* @param page 当前查询页码</span> <span style="color:#aa5500">* @param pageSize 每页展示记录数</span> <span style="color:#aa5500">* @param name 员工姓名 - 可选参数</span> <span style="color:#aa5500">* @return</span> <span style="color:#aa5500">*/</span> <span style="color:#555555">@GetMapping</span>(<span style="color:#aa1111">"/page"</span>) <span style="color:#770088">public</span> <span style="color:#000000">R</span><span style="color:#981a1a"><</span><span style="color:#000000">Page</span><span style="color:#981a1a">></span> <span style="color:#0000ff">page</span>(<span style="color:#008855">int</span> <span style="color:#000000">page</span>,<span style="color:#008855">int</span> <span style="color:#000000">pageSize</span>,<span style="color:#008855">String</span> <span style="color:#000000">name</span>){ <span style="color:#000000">log</span>.<span style="color:#000000">info</span>(<span style="color:#aa1111">"page = {},pageSize = {},name = {}"</span> ,<span style="color:#000000">page</span>,<span style="color:#000000">pageSize</span>,<span style="color:#000000">name</span>); <span style="color:#aa5500">//构造分页构造器</span> <span style="color:#000000">Page</span> <span style="color:#000000">pageInfo</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">Page</span>(<span style="color:#000000">page</span>,<span style="color:#000000">pageSize</span>); <span style="color:#aa5500">//构造条件构造器</span> <span style="color:#000000">LambdaQueryWrapper</span><span style="color:#981a1a"><</span><span style="color:#000000">Employee</span><span style="color:#981a1a">></span> <span style="color:#000000">queryWrapper</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">LambdaQueryWrapper</span>(); <span style="color:#aa5500">//添加过滤条件</span> <span style="color:#000000">queryWrapper</span>.<span style="color:#000000">like</span>(<span style="color:#000000">StringUtils</span>.<span style="color:#000000">isNotEmpty</span>(<span style="color:#000000">name</span>),<span style="color:#000000">Employee</span>::<span style="color:#000000">getName</span>,<span style="color:#000000">name</span>); <span style="color:#aa5500">//添加排序条件</span> <span style="color:#000000">queryWrapper</span>.<span style="color:#000000">orderByDesc</span>(<span style="color:#000000">Employee</span>::<span style="color:#000000">getUpdateTime</span>); <span style="color:#aa5500">//执行查询</span> <span style="color:#000000">employeeService</span>.<span style="color:#000000">page</span>(<span style="color:#000000">pageInfo</span>,<span style="color:#000000">queryWrapper</span>); <span style="color:#770088">return</span> <span style="color:#000000">R</span>.<span style="color:#000000">success</span>(<span style="color:#000000">pageInfo</span>); }</span></span>
3.4 功能测试
代码编写完毕之后,我们需要将工程重启, 完毕之后直接访问管理系统首页, 默认就会打开员工管理的列表页面, 我们可以查看列表数据是否可以正常展示, 也可以通过分页插件来测试分页功能, 及员工姓名的模糊查询功能。
在进行测试时,可以使用浏览器的监控工具查看页面和服务端的数据交互细节。 并借助于debug的形式, 根据服务端参数接收及逻辑执行情况。
测试过程中可以发现,对于员工状态字段(status)服务端返回的是状态码(1或者0),但是页面上显示的则是“正常”或者“已禁用”,这是因为页面中在展示数据时进行了处理。
4. 启用/禁用员工账号
4.1 需求分析
在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统,启用后的员工可以正常登录。如果某个员工账号状态为正常,则按钮显示为 "禁用",如果员工账号状态为已禁用,则按钮显示为"启用"。
==需要注意,只有管理员(admin用户)可以对其他普通用户进行启用、禁用操作,所以普通用户登录系统后启用、禁用按钮不显示。==
A. admin 管理员登录
B. 普通用户登录
4.2 程序执行流程
4.2.1 页面按钮动态展示
在上述的需求中,我们提到需要实现的效果是 : 只有管理员(admin用户)可以对其他普通用户进行启用、禁用操作,所以普通用户登录系统后启用、禁用按钮不显示 , 页面中是怎么做到只有管理员admin能够看到启用、禁用按钮的?
1). 在列表页面(list.html)加载时, 触发钩子函数created, 在钩子函数中, 会从localStorage中获取到用户登录信息, 然后获取到用户名
2). 在页面中, 通过Vue指令v-if进行判断,如果登录用户为admin将展示 启用/禁用 按钮, 否则不展示
4.2.2 执行流程分析
1). 当管理员admin点击 "启用" 或 "禁用" 按钮时, 调用方法statusHandle
2). statusHandle方法中进行二次确认, 然后发起ajax请求, 传递id、status参数
最终发起异步请求, 请求服务端, 请求信息如下:
请求 | 说明 |
请求方式 | PUT |
请求路径 | /employee |
请求参数 | {"id":xxx,"status":xxx} |
{...params} : 三点是ES6中出现的扩展运算符。作用是遍历当前使用的对象能够访问到的所有属性,并将属性放入当前对象中。