Skip to content

微应用的菜单权限

前言:主应用和微应用都使用cpvf框架时,可使用如下两种方式。框架中的菜单是通过路由生成的,文中描述的下发路由,就能实现控制菜单的作用。

方案一:微应用的菜单由微应用本身控制

  • 主应用和微应用使用不同的后端服务,并且已经实现token互认。
  • 在主应用中配置微应用菜单时,应考虑到,当前用户在微应用有访问对应路由的权限,没有则需要在微应用中授权。
  • 注意修改微应用缓存名,见最后。
  • 如果主应用和微应用使用同一个后端服务,则无需任何修改。

方案二:微应用的菜单由主应用控制,由主应用下发路由到微应用

  • 在微应用的main.ts中,发送需要路由事件(needRouter)
src\main.ts

if (window.__POWERED_BY_WUJIE__) {
  createEvent();
  // ElementPlus = window.ElementPlus;
  window.__WUJIE_MOUNT = () => {
    window.$wujie.bus.$emit('onMicroMessage', { type: 'needRouter' });
    bootstrap();
    window.$wujie.bus.$emit('onMicroMessage', '子应用路由创建完成');
  };
  window.__WUJIE_UNMOUNT = () => {
    console.log('__WUJIE_UNMOUNT');
    app.unmount();
  };
  window.__WUJIE.mount();
} else {
  bootstrap();
}
  • 在微应用中把接收到的路由列表保存,修改messageEvent,判断routerList
src\views\micro\libs\messageEvent.ts

import router from '../../../router';
import { usemicroStateWithOut } from './microStore';
let firstRouter = true;
const createEvent = () => {
  const userStore = usemicroStateWithOut();
  window.$wujie?.bus.$on('sendMicroMessage', function (data) {
    console.log('子应用接收到的数据', data, data.message.path);
    if (data.type == 'routerList') {
      userStore.setmicroState(data);
    }
    if (data.type == 'router' && data.message.path) {
      if (!firstRouter) {
        router.push(data.message.path as string);
        userStore.setNextPath('');
      } else {
        firstRouter = false;
        userStore.setNextPath(data.message.path);
      }
    }
  });
};
export default createEvent;
  • 在微应用获取路由时添加判断
src\stores\modules\permission.ts

import { usemicroStateWithOut } from '/@/views/micro/libs/microStore';

172行
const microStore = usemicroStateWithOut();
// 只要是微前端,就从主应用获取菜单
const backMenus = !window.__POWERED_BY_WUJIE__
? ((await getMenus(params)) as any)
: microStore.getMessage.routerList;

或者
const microStore = usemicroStateWithOut();
const routerList = microStore.getMessage?.routerList || '';
// 只要主应用传递,就用主应用的菜单
const backMenus = !routerList ? ((await getMenus(params)) as any) : routerList;
  • 注意修改微应用的缓存名,见最后。
  • 主应用的修改:在主应用的 src\views\micro\pages\vite.vue 文件中,修改findMicroRouter方法。
36行
const findMicroRouter = (list: Menu[] = []) => {
  list.map((item: Menu) => {
    if (item.type === '2' && item?.meta?.microName == appInfo.value.name) {
      // 替换路由和类型,type:1是菜单。主应用的microPath才是真正的微应用路径。
      microRouter.push({ ...item, ...{ path: item.meta.microPath, type: '1' } });
    }
    if (item.children && item.children.length > 0) {
      findMicroRouter(item.children);
    }
  });
};

注意:主应用和微应用缓存同名的问题

可在微应用的src\settings\config\projectConfig.ts中,修改storageName,完全区分主应用和微应用缓存的前缀,但会导致微应用没办法直接获取主应用的token,需要手动传递来实现免密登录。

可在微应用的src\enums\cacheEnum.ts中,修改如下代码:区分菜单和选中菜单即可。

// menu key
export const MENU_KEY = 'MICRO_MENU__LIST__';

// current menu
export const CUR_MENU_KEY = 'MICRO_CUR__MENU__';