门户V2定制-菜单功能树
场景描述
重新定制企业门户V2首页菜单为双层功能树
实现思路
- 新增“ 门户自定义 ”组件
- 使用“@replace”在重新定义菜单渲染方法“menuRender”
实现步骤
使用租户管理员登录系统,在“应用/服务管理”企业门户V2,开启门户定制(详细操作步骤可参考 门户V2调试)
进入云端开发后,打开市场组件“门户自定义”,并开启组件定制
在“\UI2\comp\portalConfig\components\portalConfig”组件目录下,定制文件“portalConfig.config.js”(文件命名:组件名+“.config.js”,不能随便定义),文件内容如下所示:
import { merge } from "lodash"; import ConfigContextProcessor from 'core/framework/ConfigContextProcessor'; import React from 'react'; import { Menu } from 'antd'; import "./layout.css"; export default { processConfigContext(configContext) { }, async onConfigContextInit(configContextProcessor) { //获取当前页面 let _this = configContextProcessor.page; let portalConfig = { "config": { "/entry": { "/pcxapp": { "/pcx": { "/index.w": { //菜单渲染方法执行后定制 "menuRender": { "@replace": (props, defaultDom) => { let { menus } = props; let mainMenu = []; //一级菜单点击事件 let onMainMenuClick=(e,item)=>{ //删除选择calss document.querySelectorAll(".definedMenu-mainMenu").forEach(item=>{ let classVal= item.getAttribute("class").replace("selected",""); item.setAttribute("class",classVal); }) //新增选择class let _a=e.currentTarget; let className=_a.getAttribute("class")+" selected"; _a.setAttribute("class",className); //设置子菜单数据 _this.setState({childItemMenus:item.children}) } //获取一级菜单信息 menus.forEach(item => { //默认展示第一个一级菜单下子菜单内容 if(!_this.state.childItemMenus){ _this.state.childItemMenus=item.children; } let menu = <a className={`definedMenu-mainMenu`} onClick={(e)=>{onMainMenuClick(e,item)}} title={item.title}> <span className={"icon"}>{item.icon}</span> <span className={"title"}>{item.title}</span> </a> mainMenu.push(menu); }); //设置第一个菜单为选中 let fitsrMenu=mainMenu?.[0]; if(fitsrMenu){ fitsrMenu.props.className+=" selected"; } //转化数据为menu需要的数据格式 let changeMenuData=(menuData)=>{ menuData.map(item=>{ item.label=item.title; //控制菜单是否显示 if(item.hidden!="all"){ delete item.hidden; } }); menuData.forEach(item=>{ if(item.children){ changeMenuData(item.children); } }) } //转换数据为menu组件支持的数据格式 changeMenuData(_this.state.childItemMenus); //二级菜单点击事件 let onChildMenuClick=({ item:{props}})=>{ //调用原菜单单击事件 _this.menuItemClick(props); } //建议在元素上新增key属性,用于判断当前元素是否已存在,需注意key的唯一性 let defineMenu = <div className={"definedMenu"}> <div className={"definedMenu-menuBox"}> <div className={"definedMenu-mainMenuBox"}>{mainMenu}</div> <div className={"definedMenu-subMenuBox"}> <Menu items={_this.state.childItemMenus} mode="inline" onClick={onChildMenuClick} style={{ width: 250}}/> </div> </div> </div>; return defineMenu; } } } } } } } }; merge(_this.configContext, portalConfig); ConfigContextProcessor.enhancePageAdvice(_this); } }
对应的css样式请参考如下代码
.definedMenu { flex: 0 0 330px; position: relative; } .definedMenu * { box-sizing: border-box; } .definedMenu [hidden] { display: none; } .definedMenu-mainMenu { display: flex; align-items: center; flex-direction: column; margin: 5px; padding: 5px 0px; color: #ffffffa6; } .definedMenu-mainMenu:hover { color: #fff; } .definedMenu-mainMenu.selected { border-radius: 5px; color: var(--ant-color-primary); } .definedMenu-mainMenu .icon { padding: 8px 0px; font-size: 16px; } .definedMenu-mainMenu .title { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; width: 100%; text-align: center; padding: 0px 3px; } .definedMenu-menuBox { position: fixed; inset-block-start: 56px; display: flex; height: calc(100% - 56px); } .definedMenu-mainMenuBox { width: 80px; height: 100%; border-right: 1px solid #e5e5e5; background-color: #001529; overflow-y: auto; } .definedMenu-subMenuBox { flex: 1; height: 100%; border-inline-end: 1px solid rgba(5, 5, 5, 0.06); overflow: auto; } .definedMenu-subMenuBox .iconAction { position: absolute; font-size: 22px; z-index: 100; right: -11px; top: 13px; cursor: pointer; }
“门户自定义”组件定制完成之后,重新发布即可