微应用的菜单权限
前言:主应用和微应用都使用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__';