动态权限菜单的实现
原来的usernameAndPassword.
/*
* 处理登录认证
* */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//通过登录名查询用户信息是否存在,如果存在则交给UsernamePasswordFiler 进行密码校验
TUser user = userMapper.selectUserByName(username);
if (ObjectUtils.isEmpty(user)) {
throw new UsernameNotFoundException("该用户名不存在");
}
List<TRole> tRoles= roleMapper.selectByUid(user.getId());
List<String> roleList=new ArrayList<>();
List<String> permissionList=new ArrayList<>();
tRoles.forEach(role->{
roleList.add(role.getRole());
List<TPermission> tPermissions= permissionMapper.selectByRid(role.getId());
tPermissions.forEach(permission->{
if (StringUtils.hasText(permission.getCode())){
permissionList.add(permission.getCode());
}
});
});
//将角色和权限信息放入user
user.setRoleList(roleList);
user.setPermissionList(permissionList);
user.setLastLoginTime(new Date());
return user;
}
由于需要实现动态菜单,需要查询每个用户权限下的菜单列表,将菜单列表信息交给认证成功的用户。
但是有一个问题是菜单可能是多级菜单,那么多级菜单的情况下如何处理代码逻辑实现动态菜单。还有一个问题菜单都有标签,那么动态标签如何实现呢?怎么判断是一级菜单呢?怎么判断是二级菜单呢?
头好痛啊啊啊~
要长脑子了捏。
请看数据库表结构
好耶,想明白了__.将菜单信息存入权限类,icon信息存入权限类在,则二级菜单和相应的菜单图标不就有吗?那一级菜单怎么办捏?哦豁哦豁,在权限类当中设置一个子类权限的集合的成员变量。一级菜单不就是这个类实体对象本身吗?二级菜单就存在这个类集合成员变量当中。
后端处理请求
@GetMapping("/api/loadMenuList")
public R getMenuList(){
TUser user = (TUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return R.OK(user.getMenuList());
}
业务逻辑层:
/*
* 处理登录认证
* */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//通过登录名查询用户信息是否存在,如果存在则交给UsernamePasswordFiler 进行密码校验
TUser user = userMapper.selectUserByName(username);
if (ObjectUtils.isEmpty(user)) {
throw new UsernameNotFoundException("该用户名不存在");
}
List<TRole> tRoles= roleMapper.selectByUid(user.getId());
List<String> roleList=new ArrayList<>();
List<String> permissionList=new ArrayList<>();
List<TPermission> menuList = new ArrayList<>();
tRoles.forEach(role->{
roleList.add(role.getRole());
List<TPermission> tPermissions= permissionMapper.selectByRid(role.getId());
tPermissions.forEach(permission->{
if (StringUtils.hasText(permission.getCode())){
permissionList.add(permission.getCode());
}
});
//处理一级菜单信息
List<TPermission> parentMenuList=permissionMapper.selectMenuByParentId(role.getId(),0);
parentMenuList.forEach(tPermission -> {
// 3. 查询一级菜单对应的子菜单
List<TPermission> sonMenuList = permissionMapper.selectMenuByParentId(role.getId(), tPermission.getId());
// 4. 将子菜单保存到对应的一级菜单对象中
tPermission.setSonMenuList(sonMenuList);
// 5. 将一级菜单对象保存到集合中
menuList.add(tPermission);
});
});
//将角色和权限信息放入user
user.setRoleList(roleList);
user.setPermissionList(permissionList);
user.setMenuList(menuList);//保存菜单列表
user.setLastLoginTime(new Date());
return user;
}
TUser类:添加内容
List<String> roleList;//角色信息
List<String> permissionList;//权限信息,用来认证
List<TPermission> menuList;//菜单信息,标签信息,用来实现前端的动态菜单
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities=new ArrayList<>();
if (!ObjectUtils.isEmpty(roleList)){
roleList.forEach(roleCode->{
authorities.add(new SimpleGrantedAuthority("ROLE_"+roleCode));
});
}
if (!ObjectUtils.isEmpty(permissionList)){
permissionList.forEach(code->{
if (StringUtils.hasText(code)){
authorities.add(new SimpleGrantedAuthority(code));
}
});
}
return authorities;
}
TPermssion权限类添加内容:
private List<TPermission> sonMenuList;
后端拿捏__.
前端处理菜单展示
data() {
return {
isShow: false,
username: "",
menuList: [{}],
defaultActive: "", //菜单默认展开
};
},
loadMenuList() {
doGet("/api/loadMenuList", {}).then((resp) => {
// console.log(resp);
if (resp.data.code === 200) {
this.menuList = resp.data.data;
}
});
},
mounted() {
// 钩子函数 页面渲染时执行该函数 created早于页面渲染
this.loadUsername();
this.loadMenuList();
this.loadMenuDefauleActive();//处理菜单默认展开
},
loadMenuDefauleActive() {
//拿到最近访问的路由路径
let path = this.$route.path;
let arr = path.split("/");
if (arr.length > 3) {
// /dashboard/activity
this.defaultActive = "/" + arr[1] + "/" + arr[2];
} else {
this.defaultActive = path;
}
this.$router.push(this.defaultActive);
},
页面展示:主要是用v-for指令展开菜单和子菜单。
<el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="2"
text-color="#fff" :unique-opened="true" :defaultActive="defaultActive" :collapse="isShow"
:collapse-transition="false" :router="true">
<el-sub-menu :index="index+' '" v-for="(parantMenu,index) in menuList" :key="parantMenu.id">
<template #title>
<!-- <el-icon>
<Notification />
</el-icon> -->
<el-icon>
<component :is="parantMenu.icon"></component>
</el-icon>
<span>{{parantMenu.name}}</span>
</template>
<el-menu-item :index="sonMenu.url" v-for="(sonMenu) in parantMenu.sonMenuList" :key="sonMenu.id"><el-icon>
<!-- <Odometer /> -->
<el-icon>
<component :is="sonMenu.icon"></component>
</el-icon>
</el-icon>{{sonMenu.name}}</el-menu-item>
</el-sub-menu>
</el-menu>
:defaultActiv动态绑定一个默认路由选择。即这个就是子菜单默认选项。
圆满仅此简单记录,!_!_.