业务侧-菜单管理器-MenuLoader

254 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

设计思路:

这一节比较简单,因为来源于,系统应用层,主要整体控制一二级菜单的展示,所有提供的API较少

1、提供响应扩展能力,获取菜单类别等

设计动机:

针对ToB类的系统,大多类似于后台管理类系统。菜单的设计,都是产品大脑的歪歪想出来的。正常点的还好。不正常的,没法说。我们属于后者,仔细看完你就知道了。

ToB类系统:

单页签方式

image.png

多页签方式 image.png

上面2中的区别,比较明显,正常使用上我觉得都差不多,相对来说,简单一些,我更倾向于第一种单页签方式,如果你产于讨论时,会发现会冒出很多想法

  • 多页签,用户可以功能操作未完成时,去其他功能,完了还可以回来继续做
  • 功能关联性,功能B依赖先完成功能A

我感觉上面都是伪需求,都是大佬和产品的臆想,真实的情况,上述2个看着都没问题,但是一般不会发生,而且必要性不强。

原因:

管理类系统,功能都是相对独立,依赖性不强,所以第二项不成立。

对于管理类系统,很多时候都是给领导做的,够大体够炫就可以了。

完成功能在回来做,这个你自己平常工作方式,你推荐吗?你自己都不会这么搞,还想着别人可能这么去干而且多页签的使用情况,看着人畜无害,所以有则好,没有也不影响。

无页签方式
单页签的一种变种布局吧,多应用于网站之类

image.png

而且这种布局模式,单一使用有点蹩脚,可能会带个Banner,做宣传

image.png

上面这些,都是一级菜单相关,如果有二三级,相关页面怎么办呢?产品的大脑开始震荡....

image.png

image.png

无敌了吧。看着没问题。就是有点复杂。不画了,在画,我就是产品了。

我们继续看代码吧...

设计实践:

API

名称内容
getEntryRouter根据当前路由地址获取入口菜单的信息
isEntryMenu判断当前地址是否是入口页面
isFlowMenu判断当前地址是否进入流式布局
findAuthUnit查找路由地址所对应的详细信息
getFirstEntry获取第一个菜单
getSidebarMenu左侧菜单获取
import { BaseStore } from "@basic-library";

/**
 * 左侧导航-加载器
 * @param {*} routerUrl 
 * @returns  1/2/3...级菜单 pageType=1
 */
const getSidebarMenu = (routerUrl) => {
  const item = BaseStore.auth.getInfoByRoute(routerUrl)
  if (!item) {
    console.warn(`进入非入口页面,当前访问模块${routerUrl}未授权,请联系管理员进行授权!`)
    return
  }
  let pageId = ''
  if (item.parentId == '-1') {
    pageId = item.pageId
  } else {
    pageId = item.parentIds.split(',')[1]
  }
  console.debug('查询pageId=' + pageId + "下的页面")
  return BaseStore.auth.getInfoByNotEntryTree(pageId)
}

/**
 * 根据地址获取入口菜单信息
 * @param {*} routerUrl 
 */
 const getEntryRouter = (routerUrl) => {
  const item = BaseStore.auth.getInfoByRoute(routerUrl)
  if (!item) return
  let pageId = ''
  if (item.parentId == '-1') {
    pageId = item.pageId
  } else {
    pageId = item.parentIds.split(',')[1]
   }
  return BaseStore.auth.getInfoByCode(pageId)
}

/**
 * 左侧导航-加载器---全部
 * @param {*}  
 * @returns  1/2/3...级菜单 pageType=1
 */
const getAllMenu = () => {
  return BaseStore.auth.userTreeMenuList
}
/**
 * 判断当前地址是否是入口页面-一级菜单
 * @param {*} routerUrl 当前路由地址
 * @returns 
 */
const isEntryMenu = (routerUrl) => {
  const authArr = BaseStore.auth.userEntryMenuList
  return authArr.find((v) => v.path === routerUrl)
}

/**
 * 判断当前地址是否进入流式页面(无左侧菜单、无banner)
 * @param {*} routerUrl 当前路由地址
 * @returns 
 */
 const isFlowMenu = (routerUrl) => {
  const authArr = BaseStore.auth.userEntryMenuList
  const portalArr = BaseStore.auth.getMenuListByType('portal')
  if(routerUrl == '/dashBoard') return true
  if(authArr.find((v) => v.path === routerUrl)) return true
  if(portalArr.find((v) => v.path === routerUrl)) return true
  
  return
}
/**
 * 根据当前路由地址,查找功能对应的菜单信息
 * @param {*} routerUrl  当前路由地址
 * @returns 
 */
const findAuthUnit = (routerUrl) => {
  const item = BaseStore.auth.getInfoByRoute(routerUrl)
  if (!item) return routerUrl
  // 开始查找追溯
  if (item.pageType == 'entry') {
    return routerUrl
  } else {
    return BaseStore.auth.getInfoByCode(item.parentId)?.path
  }
}

/**
 * 获取第一个菜单
 * @param {*}  
 * @returns
 */
 const getFirstEntry = () => {
  let path = '/dashBoard'
  if(isAdmin()) return path
  const authArr = BaseStore.auth.userEntryMenuList
  // Config.BSConfig.homePath
  if(authArr.length && authArr[0]?.path) path = authArr[0].path
  return path
}

export default {
  getEntryRouter,
  isEntryMenu,
  getSidebarMenu,
  isFlowMenu,
  getAllMenu,
  findAuthUnit,
  getFirstEntry,
};

核心代码解读:

使用比较多的是 BaseStore.auth这个是框架层的,里面提供的东西比较多,主要是对菜单信息进行解析,提供相关服务

getInfoByRoute 根据路由地址,获取路由详细信息
getInfoByCode 根据页面id,获取路由详细信
getInfoByNotEntryTree 根据页面ID,获取当前菜单下所有的子菜单,转换成树形结构数据
userEntryMenuList 所有入口页面菜单的集合
getMenuListByType 根据类型,获取相应类型下的菜单集合
userTreeMenuList 所有菜单的集合,转换成树形结构数据输出

关于 BaseStore.auth,后面专门章节讲解,敬请关注。

后记:

这章写完,Loader层设计暂时结束,后期会根据云平台的发展,进行能力积累发展微应用、低代码平台发展。做这些之前,要做一些能力上的积累。下面我们会写写

1、框架层的相关设计和积累
2、业务层浅谈类实践经验
3、纯技术类,组件和工程构建方面

但是现在团队人员较少,业务吃紧,管理不善,自己都没多大的信心,被拉去四处救火,架构相关都是在尽力驱动。

针对Loader管理器的一系列,请看下方:

业务侧-Loader设计构思
业务侧-系统应用加载器-AppLoader
业务侧-登录管理器-LoginLoader
业务侧-异常拦截管理器-ErrorLoader
业务侧-路由管理器-RouterLoader
业务侧-消息管理器-IMLoader