前言
这一节我们来学习Vue2项目ElementUI的图标库使用,前面我们已经把权限管理的相关功能都做好了,只是里面的图标处我们还需完善。
使用ElementUI图标库
官方文档见 -> https://element.eleme.cn/#/zh-CN/component/icon
因为我们是使用的vue2项目,这里无需额外引入图标库,参考官方文档的用法,直接在class样式添加相应的值即可,如图

幽络源的代码中已经是绑定了class演示,并且图标值来源于数据中,因此可直接使用,如图

在编辑权限处,将elementui的图标值复制粘贴到编辑框即可,如图可以看到图标信息成功展现



动态菜单动态路由的开发
上面我们引入了Element的图标,权限管理表格的图标成功的展现了,但是左侧的导航菜单却没有变动,是因为幽络源的项目中的菜单现在还是静态的,我们需要将其修改开发为动态菜单,使菜单信息来自于数据库,而不是写死。
通过分析菜单页面可知我们这里需要查询出的数据包括了菜单的 路径、图标值、名称、层级关系,而菜单的排序我们直接在后端处理即可,如图

在权限管理的controller中添加新的接口,名为 查询菜单,代码与图如下
/**
* 菜单查询
* @return
*/
@GetMapping("/selectMenu")
public ResResult<?> selectMenu(@AuthenticationPrincipal UserDetailObject userDetails) {
Long userId = userDetails.getUser().getId();
return permissionService.selectMenu(userId);
}

服务层和持久层如下,和我们查权限是一样的,也是需要递归的,代码与图如下
@Override
public ResResult<?> selectMenu(Long userId) {
//查询用户拥有的所有菜单
ArrayList<Permission> menus=permissionMapper.selectMenuByUserId(userId);
//构建菜单树
List<Permission> menusTree = buildTree(menus, null);
return ResResult.success(menusTree,"菜单查询成功");
}
<!--ArrayList<Permission> selectMenuByUserId(@Param("userId") Long userId);-->
<select id="selectMenuByUserId" resultType="com.tenant.entity.Permission">
select p.id as id,p.`name` as name,p.parent_id as parentId,p.path as path,p.icon as icon,p.sort as sort
from tbs_user u
left join tbs_user_role ur on ur.user_id = u.id
left join tbs_role r on r.id = ur.role_id
left join tbs_role_permission rp on rp.role_id = r.id
left join tbs_permission p on p.id = rp.permission_id
where u.id=#{userId} and type=1
</select>


初次之外,我们还需修改前端的菜单组件为动态获取,在permission.js新增请求封装-获取菜单,如图

然后菜单组件调用请求,修改为动态组件,代码如下
template:
<template>
<aside class="app-sidebar">
<el-menu
:default-active="$route.path"
class="sidebar-menu"
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
router
>
<!-- 首页菜单(固定) -->
<el-menu-item index="/home">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<!-- 动态渲染菜单 -->
<template v-for="menu in menus">
<!-- 有子菜单的情况 -->
<el-submenu
v-if="menu.children && menu.children.length > 0"
:key="menu.id"
:index="menu.path || menu.id.toString()"
>
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.name }}</span>
</template>
<el-menu-item
v-for="child in menu.children"
:key="child.id"
:index="child.path"
>
<i :class="child.icon"></i>
<span>{{ child.name }}</span>
</el-menu-item>
</el-submenu>
<!-- 没有子菜单的情况 -->
<el-menu-item
v-else
:key="menu.id"
:index="menu.path"
>
<i :class="menu.icon"></i>
<span slot="title">{{ menu.name }}</span>
</el-menu-item>
</template>
</el-menu>
</aside>
</template>
script:
<script>
import {selectMenu} from '@/api/tenant/permission'
export default {
name: 'AppSidebar',
data(){
return {
menus:[] //菜单
}
},
methods:{
getAndSetMenus(){
selectMenu().then(res=>{
if (res.code===1){
this.menus=res.data
}
})
}
},
mounted(){
this.getAndSetMenus();
}
}
</script>
然后这里有个注意点!!!
源码中前端的路由除了首页,目前多租户模块的路径是tenant开头的,如下

而我们的数据库中,确实用system开头的,因此幽络源这里将数据库中权限表的菜单权限的路径修改为与前端路由一直,如图

最后启动项目,即可看到我们的菜单不再是写死在前端项目中的了,而是从数据库动态获取的,后续我们完善用户、角色的功能,能够更加的体会到菜单的动态性。
Security登录用户获取
其实,上面我们开发动态菜单时,就已经出现了Security登录用户的获取,也就是在查询菜单的Controller上我们使用如下注解作为参数获取到了 UserDetailObject userDetails
@AuthenticationPrincipal
而这里我们之所以通过这个注解能获取到UserDetail,是因为我们在token过滤器中向Security上下文存放了我们构造的 Authentication,如图

本章源码
https://pan.quark.cn/s/e767691ffecc
结语
如上为幽络源的11、幽络源微服务项目实战:ElementUI图标库的使用+动态菜单动态路由控制+Security登录用户获取教程,如有疑问或对微服务感兴趣可加入我们的QQ群询问与交流:307531422

