携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
设计思路:
这一节比较简单,因为来源于,系统应用层,主要整体控制一二级菜单的展示,所有提供的API较少
1、提供响应扩展能力,获取菜单类别等
设计动机:
针对ToB类的系统,大多类似于后台管理类系统。菜单的设计,都是产品大脑的歪歪想出来的。正常点的还好。不正常的,没法说。我们属于后者,仔细看完你就知道了。
ToB类系统:
单页签方式
多页签方式
上面2中的区别,比较明显,正常使用上我觉得都差不多,相对来说,简单一些,我更倾向于第一种单页签方式,如果你产于讨论时,会发现会冒出很多想法
- 多页签,用户可以功能操作未完成时,去其他功能,完了还可以回来继续做
- 功能关联性,功能B依赖先完成功能A
我感觉上面都是伪需求,都是大佬和产品的臆想,真实的情况,上述2个看着都没问题,但是一般不会发生,而且必要性不强。
原因:管理类系统,功能都是相对独立,依赖性不强,所以第二项不成立。
对于管理类系统,很多时候都是给领导做的,够大体够炫就可以了。
完成功能在回来做,这个你自己平常工作方式,你推荐吗?你自己都不会这么搞,还想着别人可能这么去干而且多页签的使用情况,看着人畜无害,所以有则好,没有也不影响。
无页签方式
单页签的一种变种布局吧,多应用于网站之类
而且这种布局模式,单一使用有点蹩脚,可能会带个Banner,做宣传
上面这些,都是一级菜单相关,如果有二三级,相关页面怎么办呢?产品的大脑开始震荡....
无敌了吧。看着没问题。就是有点复杂。不画了,在画,我就是产品了。
我们继续看代码吧...
设计实践:
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