製作動態菜單的思路:
就是當前用戶登陸後,保存用戶的信息,通過用戶的id,去查找該用戶對象的菜單。後臺獲取的菜單數據,最終傳給前臺形式就是父菜單裏包含了所有的子菜單;並在前臺登錄成功後,把菜單數據取出來,保存在sessionStorage(相當於後端的session)中。這裏由於是用的前後端分離模式,所以先在前端的routes.js路由文件中,存着系統所有的菜單,在Home.vue文件中,通過循環比較來展示該用戶的菜單。
代碼就直接分享核心部分:
service實現層:
這裏我可能獲取菜單有點複雜,僅供參考。
@Override
public List<SystemMenu> findMenus() {
//父菜單容器
List<SystemMenu> parentList = new ArrayList<>();
// //查找得到所有菜單
User user = UserContext.getUser();
List<SystemMenu> menus = systemMenuMapper.findByUserid(user.getId());
boolean falg = true;
for (SystemMenu menu : menus) {
SystemMenu parentMenu = systemMenuMapper.findParentByChild(menu.getId());
if(parentList.size()!=0) {
for (SystemMenu systemMenu : parentList) {
if (systemMenu.getName().equals(parentMenu.getName())) { //同一個父級菜單
systemMenu.getChildren().add(menu); //就向裏面添加
falg = false;
break;
} else {
falg = true;
}
}
}
if(falg){
parentList.add(parentMenu);
falg = false;
}
parentMenu.getChildren().add(menu);
}
return parentList;
}
mapper層
<!--根據用戶id查找所有的子菜單-->
<select id="findByUserid" resultType="SystemMenu">
SELECT DISTINCT m.id ,m.`name`
FROM t_systemmenu m
LEFT JOIN t_permission p ON m.id=p.menu_id
LEFT JOIN t_role_permission rp ON rp.permission_id=p.id
LEFT JOIN t_role r ON r.id=rp.role_id
LEFT JOIN t_user_role ur ON ur.role_id=r.id
LEFT JOIN t_user u ON u.id=ur.user_id
WHERE u.id=#{id}
</select>
<!--根據子菜單id查找父菜單-->
<select id="findParentByChild" resultType="SystemMenu">
SELECT id,name FROM t_systemmenu where id=(SELECT parent_id FROM t_systemmenu WHERE id=#{id})
</select>
前端登錄成功後,執行的函數中保存數據
this.$http.post("/login",loginParams).then(data=>{
this.logining = false;
//NProgress.done();
//解構表達式
let {msg, success,object} = data.data;
// console.debug(object.object.menuList)
//保存當前用戶能看到的所有菜單
sessionStorage.setItem('menus', JSON.stringify(object.object.menuList));
if (!success) { //登錄不成功
this.$message({message: msg, type: 'error'});
} else {
sessionStorage.setItem('user', JSON.stringify(object.object));//存儲當前登錄人的對象
//存儲sessionId
sessionStorage.setItem('sessionId', object.sessionId);
//簡單理解就是跳轉界面
this.$router.push({ path: '/echarts' });
}
});
由於前端用的是基於vue的腳手架和lementUI,所有展示菜單,需要循環遍歷。代碼如下:
<!--導航菜單-摺疊後-->
<ul class="el-menu el-menu-vertical-demo collapsed" v-show="collapsed" ref="menuCollapsed">
<li v-for="(item,index) in $router.options.routes" v-if="!item.hidden" class="el-submenu item">
<template v-if="!item.leaf">
<div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)"><i :class="item.iconCls"></i></div>
<ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
<li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">{{child.name}}</li>
</ul>
</template>
<template v-else>
<li class="el-submenu">
<div class="el-submenu__title el-menu-item" style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"><i :class="item.iconCls"></i></div>
</li>
</template>
</li>
</ul>
data() {
return {
menus:[] //當前登錄用戶所能看到的菜單
}
},
mounted() {
var user = sessionStorage.getItem('user');
if (user) {
user = JSON.parse(user);
this.sysUserName = user.name || '';
// this.sysUserAvatar = user.avatar || ''; avatar//圖片路徑
}
////取出當前用戶能看到的所有菜單,並賦值
let item = sessionStorage.getItem("menus");
this.menus = JSON.parse(item);
}