import{ MenuItem, TreeItem, BackPermission } from '@/common/menutypes';importsystem from './menu/system';// 菜单数据const menus: MenuItem[]=[system];// 用于在首页中显示菜单树export function getNavData(): MenuItem[]{return menus;}// 用于“角色管理”模块中显示权限树,获得一个树状结构exportconst getPermissionTree =(tags: string[])=>{
let data =getNavData();
let items: TreeItem[]=[];getTree(data, items, tags);return items;};
function getTree(menus: MenuItem[], items: TreeItem[], tags: string[]){for(let menu of menus){// 如果没有包含对应的tag,则略过当前菜单if(!tags.includes(menu.tag)){continue;}
let item =newTreeItem(menu.tag, menu.name);
items.push(item);if(menu.leaf){if(menu.permissions){for(let option of menu.permissions){// 如果没有包含对应的tag,则略过if(!tags.includes(option.tag)){continue;}
item.addChildren(option.tag, option.name);}}}else{getTree(menu.children, item.children, tags);}}}// 用于”同步权限“功能:// 从前端数据结构中生成权限列表记录exportconst getPermissions =()=>{
let list: BackPermission[]=[];processPermissions(getNavData(), list);return list;};const processPermissions =(menuItems: MenuItem[], list: BackPermission[])=>{for(let menuItem of menuItems){
let backPermission =newBackPermission(menuItem.tag, menuItem.type, menuItem.whiteList);
list.push(backPermission);if(menuItem.leaf && menuItem.permissions){for(let option of menuItem.permissions){
let backPermission =newBackPermission(option.tag, option.type, option.whiteList, option.method, option.pattern);
list.push(backPermission);}}else{processPermissions(menuItem.children, list);}}};
举例展示system菜单
分为index和子菜单文件:比如文件夹为:
-system
-index.ts
-role.ts
-user.ts
-syslog.ts
index.ts:import{ MenuItem } from '@/common/menutypes';importuser from './users';importrole from './roles';importsyslog from './syslogs';import{ i18nt } from '@/utils';// 系统管理// - 用户管理// - 角色管理
let menu =newMenuItem('system',i18nt('menu','系统管理'),'system',false).addChildren(user).addChildren(role).addChildren(syslog);exportdefault menu;
role.ts
import{ i18nt } from '@/utils';import{ MenuItem } from '../../menutypes';
let menu =newMenuItem('system:role',i18nt('menu','角色管理'),'el-icon-fa-users',false,true,'/roles',false,'Roles').addPermission('system:role:select','查询',false,'GET','/api/admin/roles').addPermission('system:role:insert','新增',false,'POST','/api/admin/roles').addPermission('system:role:update','修改',false,'PUT','/api/admin/roles/{roleId}').addPermission('system:role:delete','删除',false,'DELETE','/api/admin/roles/{roleId}').addPermission('system:role:select-permission','查询角色权限',false,'GET','/api/admin/roleperms/{roleId}').addPermission('system:role:assign-permission','分配权限',false,'PUT','/api/admin/roleperms/{roleId}').addPermission('system:role:sync-permission','同步权限',false,'POST','/api/admin/permissions');exportdefault menu;
菜单数据代码为:
async loadAvailButtons(){// 从后台获得当前用户的权限列表
let result;if(this.isIEweb){
result = await Utils.doGet(this, `/api/sessions/permission/tag?${Math.random()}`);}else{
result = await Utils.doGet(this, `/api/sessions/permission/tag`);}
let availableTags =[];if(result.success){
availableTags = result.data;// 获取菜单数据结构(前端定义)
let menus: MenuItem[]= nav.getNavData();// 根据后端的权限列表确定可用的菜单及按钮this.hiddenMenus(menus, availableTags);this.allMenus = menus;}this.$store.commit('setButtons',{
buttons:newSet(availableTags)});}// 根据tags数组,确定菜单项是否隐藏hiddenMenus(menus: MenuItem[], tags: Array<string>){for(let menu of menus){if(menu.whiteList){// 属于白名单,菜单项不需要隐藏
menu.visible =true;}else{// 根据tag是否在列表中判断是否需要隐藏菜单项
menu.visible =!(!this.compareTag(menu.tag, tags)|| menu.hidden);}// 如果有子菜单,则递归检查if(menu.children){this.hiddenMenus(menu.children, tags);}}}
授权的权限树数据
// 授权对话框中加载权限信息
async loadPermsDialogData(){
let result = await Utils.doGet(this,'/api/sessions/permission/tag');if(!result.success){
Utils.showWarning(String(this.t('获取当前用户权限列表失败!原因:'))+ result.message);}
let permissins: any = nav.getPermissionTree(result.data);this.allPermissions = permissins;
var selectedPermissions = await this.loadAllPermsByRoleId(this.permsEditForm.roleId);(this.$refs.tree as any).setCheckedKeys(selectedPermissions);}
关于鉴权
目前逻辑,将permissions数据存储在公共数据管理中(我使用的vuex),自定义指令鉴定该tag是否存在。
vuex:importVue from 'vue';importVuex from 'vuex';import{ i18nt } from '@/utils';
Vue.use(Vuex);
let availButtons =newSet();exportdefaultnew Vuex.Store({
modules:{// 把 store/modules下的文件引入},
state:{
buttons: availButtons,},
mutations:{// 判断按钮是否有权限setButtons(state, payload){
state.buttons = payload.buttons;},
actions:{},
getters:{}});
存储:
定义在上边的loadAvailButtons中
自定义指令:
importVue from 'vue';importstore from '@/store';exportdefault function directive(){
Vue.directive('auth',{
inserted:(el, binding)=>{if(!store.state.buttons.has(binding.value)){
el.remove();}}});}
使用:
<el-button type="primary" @click.native="handleAllConfirm" v-auth="'basic:shift:editDetails'" size="small">{{tt('提交')}}</el-button>