import { defineStore } from 'pinia'; import { http } from '/nerv-lib/util/http'; import { stringUtil } from '/nerv-lib/util/string-util'; import { cloneDeep } from 'lodash-es'; import { toRaw } from 'vue'; import { log } from '/nerv-lib/util/log'; export const authorizationService = defineStore({ id: 'authorizationService', /** * token 测试用 * userinfo 用户信息 * itemMap 权限树 * @returns */ state(): { token: boolean; userInfo: any; itemMap: any; defaultRegion: { value: string; label: string; isDefault: any }; currentRegion: { value: string; label: string; isDefault: any }; regionArray: Array; ModulesRes: Array; permissionMap: Recordable; switches: Recordable; } { return { token: false, userInfo: {}, itemMap: {}, defaultRegion: { label: '', value: '', isDefault: '' }, currentRegion: { label: '', value: '', isDefault: '' }, regionArray: [], ModulesRes: [], permissionMap: {}, switches: {}, }; }, actions: { login() {}, logout() { window.location.href = '/login'; }, loadAuthorization() { return http.post('/api/passport/passport/objs/Authorization/CheckAuthorization'); }, loadModules() { return http.get('/api/webui/webui/objs/GetModules'); }, loadRegion() { return http.get('/api/passport/objs/GetRegionsInfo'); }, loadSwitch() { return http.get('/api/webui/webui/objs/GetSwitchs'); }, getAuthMap() { const requestArr = [ this.loadAuthorization(), this.loadModules(), this.loadRegion(), this.loadSwitch(), ]; return Promise.all(requestArr).then((result) => { if (result && result.length >= 2) { log.info('权限加载完成'); const authResponse = result[0]; const menusResponse = result[1]; this.ModulesRes = cloneDeep(result[1]); result[2] ? this.setRegionInfo(result[2]) : ''; this.itemMap = this.convertResponse2ItemMap(authResponse, menusResponse); this.permissionMap = this.getPermissionMap(authResponse, menusResponse); this.switches = result[3]?.switchs; log.info('生成权限树', toRaw(this.permissionMap)); } }); }, /** * 是否有权限 * * @param moduleName 模块名 * * @param subModuleName 子模块名 * * @param operationName 操作名 * * @returns {boolean} true: 有权限, false: 没有权限 */ exists(moduleName: string, subModuleName?: string, operationName?: string): boolean { /**(1)访问主模块*/ let key = moduleName; if (subModuleName) { /**(2)访问子模块*/ key = key + '_' + subModuleName; } /**(3)某个具体操作*/ if (operationName) { key = key + '_' + operationName; } // this.checkAuthMap() return this.itemMap[key] != null || this.isAdmin(); }, // 递归遍历权限树方法 traverseMenus(menusItem: any, subMenus: any, itemMap: any, module: any) { if (menusItem['submenus'] && menusItem['submenus'].length > 0) { menusItem['submenus'].forEach((subMenu: any) => { if (subMenu['isGlobalDisplay']) { if (!subMenu['isOperation']) { // 如果是自定义资源且是操作,就不用按照菜单权限写入 if (subMenu['operation'] && subMenu['operation']['resource']) { const subMenusName = subMenu['operation']['resource']; subMenus.push(subMenusName); itemMap[module['name'] + '_' + subMenusName] = true; if (subMenu['operations'] && subMenu['operations'].length) { subMenu['operations'].forEach((op: any) => { itemMap[module['name'] + '_' + subMenusName + '__' + op['name']] = true; itemMap[ module['name'] + '_' + subMenusName + stringUtil.firstToUpper(op['name']) ] = true; //操作对应的页面权限 }); } } } else { // 如果是自定义资源且是操作,如【管理】按钮,将它写入父节点的操作里 const opName = subMenu?.operation.resource; itemMap[module['name'] + '_' + menusItem['name'] + '__' + opName] = true; // xxApp_xxMenus__xxOpName itemMap[module['name'] + '_' + menusItem['name'] + stringUtil.firstToUpper(opName)] = true; //操作对应的页面权限,如:xxApp_xxMenusXxOpName } this.traverseMenus(subMenu, subMenus, itemMap, module); } }); } else { return; } }, //处理权限树 convertResponse2ItemMap(authResponse: any, menusResponse: any) { const itemMap: any = {}; /** 如果是具有admin权限用户*/ if (authResponse['accountname'] == 'admin' || authResponse['isAdmin']) { itemMap['*'] = ''; return itemMap; } /***默认显示的模块或者菜单 如:监控下面的指标监控 * 先处理默认显示的模块权限,再处理授权的权限,注意顺序 */ if (menusResponse instanceof Array) { menusResponse.forEach((module) => { if (module['isGlobalDisplay']) { let menus: Array = []; if (itemMap[module['name']] == null) { itemMap[module['name']] = ''; //保留上个项目中该模块的菜单信息 } itemMap[module['name']] = ''; if (module['menus'] && module['menus'].length > 0) { module['menus'].forEach((menusItem: any) => { if (menusItem['isGlobalDisplay']) { if (menusItem['isGlobal']) { // 1. 全局开放模块又是独立模块 itemMap[menusItem['name']] = ''; const globalMenus: Array = []; if (menusItem['submenus'] && menusItem['submenus'].length > 0) { menusItem['submenus'].forEach((subMenu: any) => { if (subMenu['isGlobalDisplay']) { if (subMenu['operation'] && subMenu['operation']['resource']) { const globalMenuName = subMenu['operation']['resource']; globalMenus.push(globalMenuName); itemMap[menusItem['name'] + '_' + globalMenuName] = ''; if (subMenu['operations'] && subMenu['operations'].length) { subMenu['operations'].forEach((op: any) => { itemMap[ menusItem['name'] + '_' + globalMenuName + '_' + op['name'] ] = ''; }); } } if (menusItem['isDir']) { itemMap[module['name'] + '_' + subMenu['name']] = true; } } }); itemMap[menusItem['name']] = globalMenus; } } else if (menusItem['isDir']) { // 2. 文件夹下的模块 const subMenus: Array = []; this.traverseMenus(menusItem, subMenus, itemMap, module); menus = [...menus, ...subMenus]; } else { //3. 普通全局开放模块 menus.push(menusItem['name']); itemMap[module['name'] + '_' + menusItem['name']] = ''; if (menusItem.operations && menusItem.operations.length) { menusItem.operations.forEach((op: any) => { itemMap[module['name'] + '_' + menusItem['name'] + '_' + op['name']] = ''; }); } // 处理下层菜单 const subMenus: Array = []; this.traverseMenus(menusItem, subMenus, itemMap, module); menus = [...menus, ...subMenus]; } } }); } itemMap[module['name']] = menus; } }); } if (!authResponse) { return itemMap; } const projects = authResponse['projects']; if (!projects.length) { return itemMap; } projects.forEach((project: any) => { // if (project['projectname'] == 'systemProject') { const modules = project['modules']; if (!modules.length) { return; } modules.forEach((module: any) => { let menus = []; if (itemMap[module['name']] == null) { itemMap[module['name']] = ''; //保留上个项目中该模块的菜单信息 } if (!module['resources'].length) { return; } module['resources'].forEach((subModule: any) => { menus.push(subModule['name']); itemMap[module['name'] + '_' + subModule['name']] = ''; //当该资源在系统项目下,即受角色管理 itemMap[module['name'] + '_' + subModule['name'] + '_' + project['projectname']] = ''; if (!subModule['operations'].length) { return; } const ops: Array = []; subModule['operations'].forEach((op: any) => { /**权限合并修改: * 1.后端注册权限将查看(detail)和列表(list)权限合并为查看(list)权限后, * 2.前端:用户勾选查看(list),即表示有查看列表和详情权限。 */ if (op['name'] == subModule['name'] + '_list') { op['name'] = subModule['name'] + '_detail'; } itemMap[module['name'] + '_' + subModule['name'] + '_' + op['name']] = ''; itemMap[ module['name'] + '_' + subModule['name'] + '_' + project['projectname'] + '_' + op['name'] ] = ''; ops.push(op['name']); }); itemMap[module['name'] + '_' + subModule['name'] + '_' + project['projectname']] = ops.join(','); }); if (itemMap[module['name']] && itemMap[module['name']] instanceof Array) { //如果上个项目在该模块有菜单 menus.push(...itemMap[module['name']]); //合并 menus = Array.from(new Set(menus)); //去重 } itemMap[module['name']] = menus; }); // } }); return itemMap; }, //判断是否在当前项目内 isCurrentApp(app: string) { const url = window.location.href; const reg = /[http|https]+:\/\/.+?\/([^/]+)/gi; let currentApp; const result = reg.exec(url); if (result != null) { currentApp = result[1]; } return currentApp === app; }, getValidFirstMenuName(moduleName: string | number) { if (!this.itemMap) { return []; } // let menuName = null; const menus: any[] = this.itemMap[moduleName]; // if(!menus||menus.length==0)return; // menuName = menus[0]; return menus; }, isAdmin() { return this.itemMap['*'] != null; }, //设置region信息 setRegionInfo(response: any) { if (response) { const item: { label: any; value: any; isDefault: any }[] = []; const regions = response['regions']; regions.forEach((region: { isDefault: any; name: any; label: any }) => { region.isDefault ? (this.defaultRegion = { label: region.label, value: region.name, isDefault: region.isDefault, }) : ''; item.push({ label: region.label, value: region.name, isDefault: region.isDefault, }); }); this.regionArray = item; } }, setCurrentRegion(currentRegion: { value: string; label: string; isDefault: any }) { this.currentRegion = currentRegion; }, getApp() { return ((import.meta.env.VITE_PUBLIC_PATH || '') as string).replace(/\//g, ''); }, getPermissionMap(authResponse: any, menusResponse: any) { const itemMap: any = {}; // itemMap['*'] = true; // return itemMap; /** 如果是具有admin权限用户*/ if (authResponse['accountname'] == 'admin' || authResponse['isAdmin']) { itemMap['*'] = true; return itemMap; } /***默认显示的模块或者菜单 如:监控下面的指标监控 * 先处理默认显示的模块权限,再处理授权的权限,注意顺序 */ if (menusResponse instanceof Array) { menusResponse.forEach((module) => { if (module['isGlobalDisplay']) { let menus: Array = []; if (itemMap[module['name']] == null) { itemMap[module['name']] = ''; //保留上个项目中该模块的菜单信息 } itemMap[module['name']] = ''; if (module['menus'] && module['menus'].length > 0) { module['menus'].forEach((menusItem: any) => { if (menusItem['isGlobalDisplay']) { if (menusItem['isGlobal']) { //全局开放模块又是独立模块 itemMap[menusItem['name']] = ''; const globalMenus: Array = []; if (menusItem['submenus'] && menusItem['submenus'].length > 0) { menusItem['submenus'].forEach((subMenu: any) => { if (subMenu['isGlobalDisplay']) { if (subMenu['operation'] && subMenu['operation']['resource']) { const globalMenuName = subMenu['operation']['resource']; globalMenus.push(globalMenuName); itemMap[menusItem['name'] + '_' + globalMenuName] = true; if (subMenu['operations'] && subMenu['operations'].length) { subMenu['operations'].forEach((op: any) => { itemMap[ menusItem['name'] + '_' + globalMenuName + '__' + op['name'] ] = true; itemMap[ menusItem['name'] + '_' + globalMenuName + stringUtil.firstToUpper(op['name']) ] = true; //权限对应页面 }); } } } }); itemMap[menusItem['name']] = globalMenus; } } else if (menusItem['isDir']) { // 2. 文件夹下的模块 const subMenus: Array = []; this.traverseMenus(menusItem, subMenus, itemMap, module); menus = [...menus, ...subMenus]; } else { //3. 普通全局开放模块 menus.push(menusItem['name']); itemMap[module['name'] + '_' + menusItem['name']] = true; if (menusItem.operations && menusItem.operations.length) { menusItem.operations.forEach((op: any) => { itemMap[module['name'] + '_' + menusItem['name'] + '__' + op['name']] = true; itemMap[ module['name'] + '_' + menusItem['name'] + stringUtil.firstToUpper(op['name']) ] = true; //权限对应页面 }); } // 处理下层菜单 const subMenus: Array = []; this.traverseMenus(menusItem, subMenus, itemMap, module); menus = [...menus, ...subMenus]; } } }); } itemMap[module['name']] = menus; } }); } if (!authResponse) { return itemMap; } const projects = authResponse['projects']; if (!projects.length) { return itemMap; } projects.forEach((project: any) => { const modules = project['modules']; if (!modules.length) { return; } modules.forEach((module: any) => { let menus = []; if (itemMap[module['name']] == null) { itemMap[module['name']] = ''; //保留上个项目中该模块的菜单信息 } if (!module['resources'].length) { return; } module['resources'].forEach((subModule: any) => { menus.push(subModule['name']); if (project['projectname'] === 'systemProject') { itemMap[module['name'] + '_' + subModule['name']] = 'systemProject'; //当该资源在系统项目下,即受角色管理 } else { itemMap[module['name'] + '_' + subModule['name']] = true; //当该资源在系统项目下,即受角色管理 itemMap[module['name'] + '_' + subModule['name'] + '_' + project['projectname']] = true; } if (!subModule['operations'].length) { return; } const ops: Array = []; subModule['operations'].forEach((op: any) => { /**权限合并修改: * 1.后端注册权限将查看(detail)和列表(list)权限合并为查看(list)权限后, * 2.前端:用户勾选查看(list),即表示有查看列表和详情权限。 */ if (op['name'] == 'list') { op['name'] = 'detail'; } itemMap[module['name'] + '_' + subModule['name'] + '__' + op['name']] = true; itemMap[ module['name'] + '_' + subModule['name'] + stringUtil.firstToUpper(op['name']) ] = true; //权限对应页面 if (project['projectname'] !== 'systemProject') { itemMap[ module['name'] + '_' + subModule['name'] + '_' + project['projectname'] + '__' + op['name'] ] = true; } ops.push(op['name']); }); if (project['projectname'] !== 'systemProject') { itemMap[module['name'] + '_' + subModule['name'] + '_' + project['projectname']] = ops.join(','); } }); if (itemMap[module['name']] && itemMap[module['name']] instanceof Array) { //如果上个项目在该模块有菜单 menus.push(...itemMap[module['name']]); //合并 menus = Array.from(new Set(menus)); //去重 } itemMap[module['name']] = menus; }); // } }); return itemMap; }, async checkAuthMap() { if (this.ModulesRes.length === 0) { await this.getAuthMap(); } }, checkPermission( moduleName: string, subModuleName?: string | undefined, operationName?: string | undefined, projectName?: string | undefined, ): boolean { if (this.permissionMap['*']) { return true; } let key = moduleName; if (!subModuleName) { // console.log(1, key); return !!this.permissionMap[key]; } key = `${key}_${subModuleName}`; if (!projectName) { if (operationName) { key = `${key}__${operationName}`; } return !!this.permissionMap[key]; } if (this.permissionMap[key] === 'systemProject') { if (operationName) { key = `${key}__${operationName}`; } // console.log(3, key, operationName); return !!this.permissionMap[key]; } else { key = `${key}_${projectName}`; if (operationName) { key = `${key}__${operationName}`; } return !!this.permissionMap[key]; } }, }, });