内部项目之跨系统登录

107 阅读7分钟

1、前期准备工作(引入assetLogin.js和useAuthentication.js文件)

1-1 assetLogin.js
import request from '@/utils/request';

// const controllerName = '/asset-portal-service';
const controllerName = '';

// 获取用户信息
export function getUserInfo() {
  return request({
    url: controllerName + '/user/auth/getUserInfo',
    method: 'get'
  });
}

// 登出
export function logout() {
  return request({
    url: controllerName + '/sso/auth/logout',
    method: 'get'
  });
}

// 鉴权401时请求
export function login(backUrl) {
  const basePath = process.env.VUE_APP_API_BASE_PATH || '/asset-portal-service/tg-easy-fetch-service/api';
  const currentDomain =
    process.env.VUE_APP_ENV === 'development'
      ? `http://${process.env.CURRENT_IP}/asset-portal-service`
      : process.env.VUE_APP_CURRENTDOMAIN;
  const url = `${basePath}/sso/auth/login?back=${encodeURIComponent(backUrl)}&currentDomain=${encodeURIComponent(
    currentDomain
  )}`;
  window.location.href = url;
}

//获取登录用户的权限列表
export function getUserMenuPermission(data) {
  return request({
    url: controllerName + '/user-api/v1/user/userMenuPermissionV2',
    method: 'get',
    params: {
      appCode: data.appCode || '',
      userId: data.userId || '',
      moduleId: data.moduleId || '',
      belongSystem: data.belongSystem || ''
    }
  });
}

//检测登录用户
export function checkUser(userId) {
  const url = controllerName + '/sso/auth/validateUser';
  return request({
    url,
    method: 'get',
    params: {
      userId: userId
    }
  });
}

//获取系统配置, env选值dev,test,prod
export function getSystemConfig(env) {
  const url = controllerName + '/system/config';
  return request({
    url,
    method: 'get',
    params: {
      env
    }
  });
}

// 获取当前用户租户
export function getCurrModule() {
  return request({
    url: controllerName + '/module/getModule',
    method: 'post'
  });
}

//切换租户
export function switchModule(moduleId) {
  return request({
    url: controllerName + '/module/switch',
    method: 'post',
    data: {
      moduleId
    }
  });
}

export function getZkAssetsPortalModuleName() {
  return request({
    url: controllerName + `/module/getZkAssetsPortalModuleName`,
    method: 'post'
  });
}

// 获取列表
export function getTenantPage(data) {
  return request({
    url: controllerName + '/user-api/v1/user/module/pageList',
    method: 'post',
    data
  });
}

export function getUserModuleList(data) {
  return request({
    url: controllerName + '/user-api/v1/user/userModule/list',
    method: 'post',
    data
  });
}

image.png

1-2 useAuthentication.js

/**
 * 鉴权
 */
import router from '@/router/index';
import { login } from '@/api/assetLogin';
import { MessageBox } from 'element-ui';

export function useAuthentication() {
  /**
   * 获取当前请求接口时路由地址
   * @returns string
   */

  function getCurrRouterUrl() {
    const protocol = window.location.protocol;
    const host = window.location.host;
    const currentRoute = router?.currentRoute;
    const fromPath = currentRoute?.path || '';
    const queryStr = getQuery(currentRoute);
    let url = `${protocol}//${host}`;
    if (!fromPath) {
      const path = currentRoute?.path;
      if (path && path !== '/') url = `${url}${path}`;
    } else {
      if (fromPath !== '/') url = `${url}${fromPath}`;
    }
    if (queryStr) {
      url = `${url}?${queryStr}`;
    }

    return url;
  }

  function getQuery(currentRoute) {
    const query = currentRoute?.query;
    const temp = [];
    for (const i in query) {
      temp.push(`${i}=${query[i]}`);
    }
    const tempStr = temp.join('&') || '';
    return tempStr;
  }

  // 鉴权登录
  function authLogin() {
    const allUrls = process.env.VUE_APP_ALLSTATICSURL;
    const request401Time = sessionStorage.getItem('request401Time') ? sessionStorage.getItem('request401Time') * 1 : 0;
    const backUrl = getCurrRouterUrl();
    window.localStorage.clear();
    window.sessionStorage.clear();

    if (request401Time >= 3) {
      MessageBox.alert('无法检测到资产门户的登录状态,请询问管理是否已经同步数据,请点击确定跳转回工作台', '提示', {
        confirmButtonText: '确定',
        callback: () => {
          window.location.href = allUrls.mainPage;
        }
      });
      return;
    } else {
      sessionStorage.setItem('request401Time', request401Time + 1);
    }

    setTimeout(() => {
      login(backUrl);
    }, 500);
  }
  return {
    authLogin,
    getCurrRouterUrl
  };
}

image.png

2、配置路由转发

2-1、vue.config.js

引入方法
function getIpAdress() {
  const interfaces = require('os').networkInterfaces();
  for (const devName in interfaces) {
    const iface = interfaces[devName];
    for (let i = 0; i < iface.length; i++) {
      const alias = iface[i];
      if (
        alias.family === 'IPv4' &&
        alias.address !== '127.0.0.1' &&
        !alias.internal &&
        !/.*(.1)$/.test(alias.address)
      ) {
        return alias.address;
      }
    }
  }
}

function removeNodeModulesCache() {
  const cachePath = resolve('node_modules/.cache');
  if (!existsSync(cachePath)) {
    return;
  }
  const result = rmdirSync(cachePath, { recursive: true, force: true });
  console.log('remove cache dir result: ', result);
}

//更改得地方
devServer: {
  host: getIpAdress(),
  port: port,
  open: true,
  proxy: {
    // detail: https://cli.vuejs.org/config/#devserver-proxy
    ['^' + process.env.VUE_APP_API_BASE_PATH]: {
      target: process.env.VUE_APP_BASE_API,
      changeOrigin: true,
      Connection: 'keep-alive'
      // pathRewrite: {
      //   ['^' + process.env.VUE_APP_BASE_API]: ''
      // }
    }
  },
  disableHostCheck: true
},

config.when(process.env.NODE_ENV === 'development', config => {
  config.plugin('define').tap(args => {
    args[0]['process.env'].CURRENT_IP = JSON.stringify(getIpAdress());
    return args;
  });

  removeNodeModulesCache();
});

config.when(['develop', 'development', 'staging', 'production'].includes(process.env.VUE_APP_ENV), config => {
  let allStaticsUrl = {
    mainPage: 'http://dp.sinohealth.cn/#/home/index'
  };
  if (process.env.VUE_APP_ENV === 'development' || process.env.VUE_APP_ENV === 'develop') {
    allStaticsUrl = {
      mainPage: 'http://192.168.16.91:31130/#/home/index'
    };
  }
  if (process.env.VUE_APP_ENV === 'staging') {
    allStaticsUrl = {
      mainPage: 'http://dp-test.sinohealth.cn/#/home/index'
    };
  }

  config.plugin('define').tap(args => {
    args[0]['process.env'].VUE_APP_ALLSTATICSURL = JSON.stringify(allStaticsUrl);
    return args;
  });
});

2.2完整代码

'use strict';
const { existsSync, rmdirSync } = require('fs');
const path = require('path');
function resolve(dir) {
  return path.join(__dirname, dir);
}

const CompressionPlugin = require('compression-webpack-plugin');

const name = process.env.VUE_APP_TITLE || '中康资产门户'; // 网页标题

const port = process.env.port || process.env.npm_config_port || 80; // 端口

// 获取本机ip
function getIpAdress() {
  const interfaces = require('os').networkInterfaces();
  for (const devName in interfaces) {
    const iface = interfaces[devName];
    for (let i = 0; i < iface.length; i++) {
      const alias = iface[i];
      if (
        alias.family === 'IPv4' &&
        alias.address !== '127.0.0.1' &&
        !alias.internal &&
        !/.*(.1)$/.test(alias.address)
      ) {
        return alias.address;
      }
    }
  }
}

function removeNodeModulesCache() {
  const cachePath = resolve('node_modules/.cache');
  if (!existsSync(cachePath)) {
    return;
  }
  const result = rmdirSync(cachePath, { recursive: true, force: true });
  console.log('remove cache dir result: ', result);
}

// vue.config.js 配置说明
// 官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档
module.exports = {
  // 部署生产环境和开发环境下的URL。
  // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
  // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
  publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',
  // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
  outputDir: 'dist',
  // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
  assetsDir: 'static',
  // 是否开启eslint保存检测,有效值:ture | false | 'error'
  lintOnSave: process.env.NODE_ENV === 'development',
  // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
  productionSourceMap: false,
  // webpack-dev-server 相关配置
  devServer: {
    host: getIpAdress(),
    port: port,
    open: true,
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      ['^' + process.env.VUE_APP_API_BASE_PATH]: {
        target: process.env.VUE_APP_BASE_API,
        changeOrigin: true,
        Connection: 'keep-alive'
        // pathRewrite: {
        //   ['^' + process.env.VUE_APP_BASE_API]: ''
        // }
      }
    },
    disableHostCheck: true
  },
  css: {
    loaderOptions: {
      sass: {
        sassOptions: { outputStyle: 'expanded' }
      }
    },
    extract: false,
    sourceMap: false
  },
  configureWebpack: {
    name: name,
    resolve: {
      alias: {
        '@': resolve('src')
      }
    },
    plugins: [
      // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
      new CompressionPlugin({
        test: /.(js|css|html)?$/i, // 压缩文件格式
        filename: '[path].gz[query]', // 压缩后的文件名
        algorithm: 'gzip', // 使用gzip压缩
        minRatio: 0.8, // 压缩率小于1才会压缩
        threshold: 10240,
      })
    ],
  },
  chainWebpack(config) {
    config.plugins.delete('preload'); // TODO: need test
    config.plugins.delete('prefetch'); // TODO: need test

    // set svg-sprite-loader
    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/icons'))
      .end();
    config.module
      .rule('icons')
      .test(/.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end();

    config.when(['develop', 'staging', 'production'].includes(process.env.VUE_APP_ENV), config => {
      config
        .plugin('ScriptExtHtmlWebpackPlugin')
        .after('html')
        .use('script-ext-html-webpack-plugin', [
          {
            // `runtime` must same as runtimeChunk name. default is `runtime`
            inline: /runtime..*.js$/
          }
        ])
        .end();
      config.optimization.splitChunks({
        chunks: 'all',
        minSize: 100 * 1024,
        maxSize: 1024 * 1024,
        minChunks: 2,
        maxAsyncRequests: 5,
        maxInitialRequests: 3,
        automaticNameDelimiter: '~',
        name: true,
        cacheGroups: {
          libs: {
            name: 'chunk-libs',
            test: /[\/]node_modules[\/]/,
            minChunks: 2,
            priority: 10,
            chunks: 'initial' // only package third parties that are initially dependent
          },
          elementUI: {
            name: 'chunk-elementUI', // split elementUI into a single package
            priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\/]node_modules[\/]_?element-ui(.*)/ // in order to adapt to cnpm
          },
          commons: {
            name: 'chunk-commons',
            test: resolve('src/components'), // can customize your rules
            minChunks: 3, //  minimum common number
            priority: 5,
            reuseExistingChunk: true
          }
        }
      });
      /* eslint-disable */
      config.optimization.runtimeChunk('single'),
        {
          from: path.resolve(__dirname, './public/robots.txt'), // 防爬虫文件
          to: './' // 到根目录下
        };
    });
    config.when(process.env.NODE_ENV === 'development', config => {
      config.plugin('define').tap(args => {
        args[0]['process.env'].CURRENT_IP = JSON.stringify(getIpAdress());
        return args;
      });

      removeNodeModulesCache();
    });

    config.when(['develop', 'development', 'staging', 'production'].includes(process.env.VUE_APP_ENV), config => {
      let allStaticsUrl = {
        mainPage: 'http://dp.sinohealth.cn/#/home/index'
      };
      if (process.env.VUE_APP_ENV === 'development' || process.env.VUE_APP_ENV === 'develop') {
        allStaticsUrl = {
          mainPage: 'http://192.168.16.91:31130/#/home/index'
        };
      }
      if (process.env.VUE_APP_ENV === 'staging') {
        allStaticsUrl = {
          mainPage: 'http://dp-test.sinohealth.cn/#/home/index'
        };
      }

      config.plugin('define').tap(args => {
        args[0]['process.env'].VUE_APP_ALLSTATICSURL = JSON.stringify(allStaticsUrl);
        return args;
      });
    });
  }
};

3、环境文件配置

###
# 页面标题
VUE_APP_TITLE = 中康资产门户

# 开发环境配置
ENV = 'development'
VUE_APP_ENV = 'development' //必填
#http://192.168.22.37:8081
#http://192.168.8.110:8084
#http://192.168.16.90:32009 测试环境地址
VUE_APP_BASE_API = 'http://dataassets.dp-test.sinohealth.cn'
# 中康资产门户/开发环境

# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

# websocket配置
VUE_APP_BASE_API_WEBSOCKET='ws://192.168.16.90:30022/ws'

#单点登录事项(开发配置本地ip)
# VUE_APP_CURRENTDOMAIN = 'http://192.168.9.98/asset-portal-service' //开发环境无需填写 生产必填

注意事项 
.env文件需要配置
VUE_APP_API_BASE_PATH='/asset-portal-service/tg-easy-fetch-service/api'

3.1、跳转登录

1、在router.beforeEach中进行拦截,当没有token得时候,则跳转到登录页面
router.beforeEach(async (to, from, next) => {
  if(token){}
  else{
    //鉴权登录
    useAuthentication().authLogin();
  }
})

3.2、退出登录

LogOut({ commit, state }) {
  return new Promise((resolve, reject) => {
    logout(state.token)
      .then(() => {
        sessionStorage.removeItem('userId');
        sessionStorage.removeItem('currModuleId');
        commit('SET_TOKEN', '');
        commit('SET_ROLES', []);
        commit('SET_PERMISSIONS', []);
        removeToken();
        resolve();
      })
      .catch(error => {
        reject(error);
      });
  });
},
//资产门户退出登录接口 成功后 执行 useAuthentication().authLogin()
this.$store.dispatch('LogOut').then(() => {
sessionStorage.setItem('request401Time', 0);
   //鉴权登录
  useAuthentication().authLogin();
});

此时,我们已经完成了整个跨系统得百分之50%

4、对接用户信息租户信息以及权限

// import { login, logout, getInfo, loginByTelephone } from '@/api/login';
import { getInfo } from '@/api/login';
import { getToken, setToken, removeToken } from '@/utils/auth';
// import { newpdata } from '@/router/mock.menudata';

import {
  getUserInfo,
  logout,
  getUserMenuPermission,
  checkUser,
  getCurrModule,
  switchModule,
  getUserModuleList,
  getZkAssetsPortalModuleName
} from '@/api/assetLogin';

const user = {
  state: {
    token: getToken(),
    name: '',
    avatar: '',
    roles: [],
    realName: '',
    id: '', //旧易数阁的用户id
    userId: '', //数智平台的用户id
    permissions: [],
    easyUserInfo: {},
    userInfo: {},
    userInfoType: '',
    redirect: '',
    usreItemList: [],
    currentModule: {},
    tenantCode: '',
    appCode: '',
    moduleId: '',
    belongSystem: '',
    menuPermission: {
      menuPermissionTree: [],
      menus: [],
      permissions: []
    }
    // orgUserInfo:{},
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token;
    },
    SET_ID: (state, id) => {
      state.id = id;
    },
    SET_USER_ID: (state, id) => {
      sessionStorage.setItem('userId', id);
      state.userId = id;
    },
    SET_NAME: (state, name) => {
      state.name = name;
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar;
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles;
    },
    SET_PERMISSIONS: (state, permissions) => {
      state.permissions = permissions;
    },
    SET_REALNAME: (state, realName) => {
      state.realName = realName;
    },
    SET_ROLETYPE: (state, userInfoType) => {
      state.userInfoType = userInfoType;
    },
    SET_REDIRECT: (state, redirect) => {
      state.redirect = redirect;
    },
    // SET_ORGUSERNAME:(state,orgUserInfo)=>{
    //   state.orgUserInfo = orgUserInfo
    // },
    SET_USERINFO: (state, userInfo) => {
      state.userInfo = userInfo;
    },
    SET_EASYUSERINFO: (state, easyUserInfo) => {
      state.easyUserInfo = easyUserInfo;
    },
    SET_PHONENUMBER: (state, phonenumber) => {
      state.userInfo.phonenumber = phonenumber;
    },
    SET_USERITEMLIST: (state, usreItemList) => {
      state.usreItemList = usreItemList;
    },
    SET_CURRENTMODULE: (state, currentModule) => {
      sessionStorage.setItem('currModuleId', currentModule.id);
      state.currentModule = currentModule;
    },
    SET_TENANTCODE: (state, tenantCode) => {
      state.tenantCode = tenantCode;
    },
    SET_APPCODE: (state, appCode) => {
      state.appCode = appCode;
    },
    SET_MODULEID: (state, moduleId) => {
      state.moduleId = moduleId;
    },

    SET_BELONGSYSTEM: (state, belongSystem) => {
      state.belongSystem = belongSystem;
    },
    SET_MENUPERMISSION: (state, menuPermission) => {
      state.menuPermission = menuPermission;
      const permissions = menuPermission.permissions || [];
      state.permissions = permissions.map(item => {
        return item.path.replace('system:assetportal:', '');
      });
    }
  },

  actions: {
    // 登录
    Login({ commit }, userInfo) {
      const username = userInfo.username.trim();
      const password = userInfo.password;
      const telephone = userInfo.telephone;
      const code = userInfo.code;
      const uuid = userInfo.uuid;

      return new Promise((resolve, reject) => {
        login(username, password, telephone, code, uuid)
          .then(res => {
            setToken(res.token);
            commit('SET_TOKEN', res.token);
            // this.dispatch('GetInfo').then(r=>{
            //   resolve(r.user)
            // })
            resolve();
          })
          .catch(error => {
            reject(error);
          });
      });
    },

    // 登录
    phoneLogin({ commit }, userInfo) {
      const username = userInfo.username.trim();
      const password = userInfo.password;
      const telephone = userInfo.telephone;
      const code = userInfo.code;
      const uuid = userInfo.uuid;

      return new Promise((resolve, reject) => {
        loginByTelephone(username, password, telephone, code, uuid)
          .then(res => {
            setToken(res.token);
            commit('SET_TOKEN', res.token);
            // this.dispatch('GetInfo').then(r=>{
            //   resolve(r.user)
            // })
            resolve();
          })
          .catch(error => {
            reject(error);
          });
      });
    },

    switchModuleFn({}, { moduleId }) {
      return new Promise(yes => {
        switchModule(moduleId)
          .then(res => {
            if (res.code === 200) {
              return yes(true);
            } else {
              return yes(false);
            }
          })
          .catch(() => {
            return yes(false);
          });
      });
    },

    getFirstModule({ commit, state }) {
      const userId = state.userId;
      const currModuleId = sessionStorage.getItem('currModuleId');

      return new Promise(yes => {
        getUserModuleList({
          userId
        })
          .then(res => {
            if (res.code === '0') {
              let first = null;

              commit('SET_USERITEMLIST', res.result);
              if (res.result.length > 0) {
                if (!currModuleId) {
                  first = res.result[0];
                } else {
                  first = res.result.find(r => r.id === currModuleId);
                }
              }

              return yes(first);
            } else {
              return yes(false);
            }
          })
          .catch(() => {
            return yes(false);
          });
      });
    },
    getCurrModuleFn({ commit }) {
      return new Promise(yes => {
        getCurrModule()
          .then(res => {
            if (res.code === 200) {
              commit('SET_CURRENTMODULE', res.data);
              commit('SET_TENANTCODE', res.data.tenantCode);
              commit('SET_APPCODE', res.data.appCode);
              commit('SET_MODULEID', res.data.id);
              return yes(true);
            } else {
              return yes(false);
            }
          })
          .catch(() => {
            return yes(false);
          });
      });
    },
    getCurrentTgszModuleName({ commit }) {
      // getZkAssetsPortalModuleName
      return new Promise(yes => {
        getZkAssetsPortalModuleName()
          .then(res => {
            if (res.code === 0) {
              commit('SET_BELONGSYSTEM', res.data);
              return yes(true);
            } else {
              return yes(false);
            }
          })
          .catch(() => {
            return yes(false);
          });
      });
    },
    doGetUserInfoFn({ commit }) {
      return new Promise((resolve, reject) => {
        getUserInfo()
          .then(res => {
            const user = res.data;
            const avatar =
              user.avatarPath == '' || user.avatarPath == null
                ? require('@/assets/images/profile.jpg')
                : user.avatarPath;
            // if (res.roles && res.roles.length > 0) {
            //   // 验证返回的roles是否是一个非空数组
            //   commit('SET_ROLES', res.roles);
            //   res.permissions.includes('*:*:*')
            //     ? commit('SET_PERMISSIONS', res.permissions)
            //     : commit('SET_PERMISSIONS', newpdata);
            // } else {
            //   commit('SET_ROLES', ['ROLE_DEFAULT']);
            // }
            commit('SET_ROLES', ['ROLE_DEFAULT']);
            commit('SET_NAME', user.account);
            commit('SET_REALNAME', user.realName);
            commit('SET_AVATAR', avatar);
            commit('SET_USER_ID', user.id);
            // userInfoType, 2 == 内部用户, 3 == 外部用户, 默认为内部用户
            commit('SET_ROLETYPE', 2);
            commit('SET_USERINFO', user);
            resolve(res);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    doGetEasyGoInfoFn({ commit, state }) {
      return new Promise((resolve, reject) => {
        getInfo()
          .then(res => {
            const userInfo = state.userInfo;
            const user = res.user;
            commit('SET_ID', user.userId);
            commit('SET_USERINFO', Object.assign({}, user, userInfo));
            commit('SET_EASYUSERINFO', {
              user,
              id: user.userId
            });
            resolve(res);
          })
          .catch(error => {
            reject(error);
          });
      });
    },

    // 获取用户信息
    GetInfo({ dispatch }) {
      return new Promise(async resolve => {
        // 获取用户信息
        await dispatch('doGetUserInfoFn');
        //获取旧易数阁用户数据
        await dispatch('doGetEasyGoInfoFn');
        // 获取第一个租户信息
        const firstModule = await dispatch('getFirstModule');
        if (firstModule) {
          // 切换租户
          await dispatch('switchModuleFn', { moduleId: firstModule?.id });
          // 获取当前租户信息
          await dispatch('getCurrModuleFn');
          //  获取当前租户的所属系统
          await dispatch('getCurrentTgszModuleName');
          //获取权限
          await dispatch('getUserMenuPermissionFn');
        }
        return resolve(true);
      });
    },

    checkUserFn({ commit }, { userId }) {
      return new Promise(yes => {
        checkUser(userId)
          .then(res => {
            return yes(res.data);
          })
          .catch(() => {
            return yes(3);
          });
      });
    },
    getUserMenuPermissionFn({ commit, state }) {
      return new Promise(yes => {
        if (state.userId) {
          getUserMenuPermission({
            appCode: state.appCode,
            userId: state.userId,
            moduleId: state.moduleId,
            belongSystem: state.belongSystem
          })
            .then(res => {
              if (res.code === '0') {
                const { menuPermissionTree } = res.result;
                let temp = [];
                menuPermissionTree.forEach(item => {
                  if (item.type === 'ROOT' && item.status === 1) {
                    if (item.subMenus && item.subMenus.length > 0) {
                      temp = temp.concat(item.subMenus);
                    }
                  } else {
                    temp = temp.concat(item);
                  }
                });
                commit('SET_MENUPERMISSION', {
                  ...res.result,
                  menuPermissionTree: temp
                });
              } else {
                // handleAdminRoute([]);
                commit('SET_MENUPERMISSION', {
                  menuPermissionTree: [],
                  menus: [],
                  permissions: []
                });
                router.replace({ path: '/401' });
              }
            })
            .catch(() => {
              // handleAdminRoute([]);
              commit('SET_MENUPERMISSION', {
                menuPermissionTree: [],
                menus: [],
                permissions: []
              });
            })
            .finally(() => {
              yes(true);
            });
        }
      });
    },

    // 退出系统
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token)
          .then(() => {
            sessionStorage.removeItem('userId');
            sessionStorage.removeItem('currModuleId');
            commit('SET_TOKEN', '');
            commit('SET_ROLES', []);
            commit('SET_PERMISSIONS', []);
            removeToken();
            resolve();
          })
          .catch(error => {
            reject(error);
          });
      });
    },

    // 前端 登出
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '');
        removeToken();
        resolve();
      });
    },

    //绑定手机号
    mobilePhone({ commit }, phonenumber) {
      commit('SET_PHONENUMBER', phonenumber);
    }
  }
};

export default user;

4.1 主要方法

// 获取用户信息
GetInfo({ dispatch }) {
  return new Promise(async resolve => {
    // 获取用户信息
    await dispatch('doGetUserInfoFn');
    //获取旧易数阁用户数据
    await dispatch('doGetEasyGoInfoFn');
    // 获取第一个租户信息
    const firstModule = await dispatch('getFirstModule');
    if (firstModule) {
      // 切换租户
      await dispatch('switchModuleFn', { moduleId: firstModule?.id });
      // 获取当前租户信息
      await dispatch('getCurrModuleFn');
      //  获取当前租户的所属系统
      await dispatch('getCurrentTgszModuleName');
      //获取权限
      await dispatch('getUserMenuPermissionFn');
    }
    return resolve(true);
  });
},

5.路由拦截

import router from './router';
import store from './store';
import { Message } from 'element-ui';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { getToken } from '@/utils/auth';
import { isRelogin } from '@/utils/request';
import { toggleTagsView } from '@/utils/assetPortal';
import { useAuthentication } from '@/utils/useAuthentication';
import GlobalLoading from '@/utils/loading';

NProgress.configure({ showSpinner: false });

const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
router.beforeEach(async (to, from, next) => {
  var reg = /([^/]*/[^/]*)/.*/;
  NProgress.start();

  const token = getToken();

  if (!window.existLoading) {
    GlobalLoading.show();
    window.existLoading = true;
  }

  if (token) {
    if (to.matched.length === 0 && store.state.permission.addRoutes.length > 0) {
      next('/401');
    }
    to.meta.title && store.dispatch('settings/setTitle', to.meta.title);
    /* has token*/
    // 切换tabs显隐
    toggleTagsView(from, to);
    isRelogin.show = true;
    // 判断当前用户是否已拉取完user_info信息

    const userId = sessionStorage.getItem('userId');
    if (userId) {
      const checkUserStatus = sessionStorage.getItem('checkUserStatus') || false;

      if (checkUserStatus === false || checkUserStatus === 'false') {
        let checkUser = await store.dispatch('checkUserFn', { userId });
        sessionStorage.setItem('checkUserStatus', true);
        if (checkUser === 2) {
          sessionStorage.removeItem('userId');
          sessionStorage.removeItem('currModuleId');
          return window.location.reload();
        }
        if (checkUser === 3) {
          store.dispatch('GetInfo');
          return;
        }
      }
    }

    if (store.state.permission.addRoutes.length === 0) {
      store
        .dispatch('GetInfo')
        .then(() => {
          isRelogin.show = false;
          store.dispatch('GenerateRoutes').then(accessRoutes => {
            //accessRoutes最少会有一个401
            if (accessRoutes.length === 1) {
              next({ path: '/401', replace: true });
            } else {
              router.addRoutes(accessRoutes); // 动态添加可访问路由表
              next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
            }
          });
        })
        .catch(err => {
          store.dispatch('LogOut').then(() => {
            Message.error(err);
            useAuthentication().authLogin();
          });
        });
    } else {
      next();
    }
  } else {
    useAuthentication().authLogin();
    next();
  }
});

router.beforeResolve((to, from, next) => {
  // 处理当前页面是否有权限
  const { name } = to;
  const { menuPermission } = store.state.user;
  const menus = menuPermission.menus || [];
  const hasMenu = menus.find(menu => menu.code.replace('system:assetportal:', '') === name) || {};
  if (!hasMenu) {
    return next({ path: '/401', replace: true });
  }
  // 处理当前页面是否有权限结束
  //处理公共页面刷新左边栏数据问题开始
  const toPath = to.path;
  const fromPath = from.path;

  if (toPath.includes('CommonPageRouterPath') && fromPath !== '/') {
    if (!fromPath.includes('CommonPageRouterPath')) {
      sessionStorage.setItem('CommonPageParentRouterPath', fromPath);
    }
  }
  //处理公共页面刷新左边栏数据问题结束
  next();
});

router.afterEach(() => {
  if (window.existLoading) {
    setTimeout(() => {
      GlobalLoading.hide();
    }, 500);
  }
  NProgress.done();
});