# 菜单管理★
# 1. 概述
菜单管理模块负责目录、菜单信息的维护。(目录:将有类似属性的菜单归类,类似文件夹。菜单:需要打开的页面信息。) 主要功能包含:新增、修改、查询、启用、 删除、数据日志、生命周期、 导入、导出、查看、内联菜单。
【菜单路径:】系统管理–>菜单管理

# 2. 查询菜单
菜单管理页面可以根据菜单编码、菜单名称来查询。

# 3. 新增菜单
勾选目录,再点击新增按钮,打开新增菜单窗口页面中,上级目录默认为勾选的目录。

未勾选目录,点击新增按钮,打开新增资源窗口页面,上级目录为空。

# 菜单各属性介绍
菜单编辑页面信息如下
| 属性名 | 属性说明 |
|---|---|
| 编码 | 菜单编码,唯一不可重复,必填项 |
| 名称 | 菜单名称,必填项 |
| 上级目录 | 上级目录,只能选择目录作为上级 |
| 菜单类型 | 菜单类型,包括:目录、菜单 |
| 目录位置 | 仅在菜单类型为目录,且上级目录为空(即根目录)时显示。目录包含:左侧、右上角。见下文目录位置 |
| 是否外链 | 仅在菜单类型为菜单时显示。开启时,加载类型为iframe,路由配置外部系统的链接地址或static下的静态页面相对路径。 |
| 是否缓存 | 仅在菜单类型为菜单时显示。菜单是否需要前端缓存 |
| 路由 | 仅在菜单类型为菜单时显示。菜单地址,当资源类型为菜单时为必填项,目录也可配置路由用于自定义路由布局.顶级目录如若不配置路由则为页签路由(@components/layouts/TabLayout). 其他目录如若不配置路由则为空路由(@components/layouts/RouteView) |
| 所属模块 | 仅在菜单类型为菜单时显示。菜单不是外链时所选(路由后的下拉),菜单所属的模块.用于程序在哪个模块下查找菜单地址.模块定义详见模块配置 |
| 外链前缀 | 仅在菜单类型为菜单时显示。菜单所关联应用的前端前缀地址,仅适用菜单打开外链开关 |
| 是否免密 | 仅在菜单类型为菜单时显示。菜单是否允许三方系统免密访问 |
| 认证来源编码 | 仅在菜单类型为菜单时显示。菜单开启免密以后,需维护编码,此编码供三方系统调用时传参 |
| 是否第三方资源免密 | 仅在菜单类型为菜单时显示。菜单是否允许免密访问第三方资源,与是否免密选项互斥 |
| 第三方资源秘钥 | 仅在菜单类型为菜单时显示。菜单开启第三方资源免密后输入的SM4秘钥 |
| 是否单点 | 仅在菜单类型为菜单时显示。菜单开启单点开关以后,菜单跳转时会携带token |
| 链接参数 | 仅在菜单类型为菜单时显示。菜单外链地址上携带的参数,包含固定值、动态值(来自动态参数)、自定义(来自数据字典或者手动输入) |
| 链接参数自定义处理地址 | 仅在菜单类型为菜单时显示。与链接参数搭配使用,由业务系统自行处理链接自定义参数并替换,链接地址维护到数据字典中,在菜单中选择即可,字典编码paramsUrlConfig,请求默认为pos请求,body入参格式见下参数详情 |
| 图标 | 菜单图标 |
| 打开方式 | 仅在菜单类型为菜单时显示。菜单打开方式,包括:tab、新窗口、弹窗。详见下文打开方式 |
| 是否启用 | 菜单是否启用 |
| 加载类型 | 仅在菜单类型为菜单且打开方式为tab或新窗口时显示。加载类型,包括:vue组件、iframe。 |
| 是否可见 | 仅在菜单类型为菜单时显示。菜单是否可见,如果为不可见则不会在目录菜单列中展示 |
| 排序 | 菜单排序值,数字。用来控制菜单展示顺序 |
| 页面属性 | 仅在菜单类型为菜单时显示。仅当打开方式为新窗口或弹窗时显示。新窗口支持窗口的样式配置,例如(height:400px);弹窗仅支持弹窗的宽度配置,例如(width:500px 或者 width:40% |
| 扩展参数设置 | 菜单的扩展属性目前包含isVisisble、isRefresh两个属性 |
| 扩展参数设置 | 菜单的扩展属性,需要数据字典中创建,字典编码base-resource-custom-param |
| 菜单个性化处理地址 | 菜单的个性化处理,目前包含visibility、countVisibility、count、color, 个性化地址维护到数据字典中,在菜单中选择即可,字典编码indviUrlConfig,请求默认为pos请求,body入参格式见下参数详情 |
| 高级js | 打开菜单时需要执行的特殊js脚本 |
| js函数 | 打开菜单时执行的前端js方法 |
| 加载类型 | 菜单的打开方式,如果菜单是外链默认为非vue组件 打开菜单时执行的前端js方法 |
# 菜单相关出入参介绍
- 链接参数入参:
需将pageParam存入sessionStorage,字段名为'pageParam', 写法如下所示:
const pageParam = {
code: 'xxx',
name: 'xxx'
}
sessionStorage.setItem('pageParam', JSON.stringify(pageParam))
{
//页面参数集合
"pageParam": JSON.parse(sessionStorage.getItem('pageParam'))
//需要拼接的地址
"url": "http://10.1.23.89/?name=张三",
//菜单的自定义参数
customParams": {
"code": "userCode"//key为链接上的key值,userCode为需要解析的参数值。
}
}
- 链接参数出参:
{
"code": "200",
"data": "http://10.1.23.89/?name=张三&code=001&age=333"
"msg":"操作成功",
"success": true
}
- 个性化配置入参:
在需要重新加载菜单的地方,调用window.parent.postMessage(obj,'*')方法手动触发刷新菜单。 其中obj数据格式为:
{
//必传固定
"type": "refreshMenu",
"data": {
//参数可为空非必传
"categoryId": "",
"categoryLocation": "",
"resourceCode": "",
"pageData":{
//菜单的个性化配置的时候传入的数据;
}
}
}
- 个性化配置出参:
{
"visibility"::true,
"countVisibility": true,
"count": 20,
"color": "red"
}
# 菜单传参
- 动态路由匹配: 很多时候,我们需要将给定匹配模式的路由映射到同一个组件。
例如,我们可能有一个 person-details 组件,它应该对所有用户进行渲染,但用户 ID 不同. 我们可以在编码中使用一个动态字段来实现,我们称之为路径参数。
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。

路由跳转使用:

- 传递固定参数给路由组件,组件可通过props接收路由参数.

- 如果是要传不固定的参数,比如token,又不想将参数暴露在路由上,可使用高级js进行脚本编辑。

# 打开方式
打开方式为tab时,页面以页签方式打开,路由必须为系统内部vue页面路径,如下:


打开方式为弹窗时,页面窗口形式打开,如下:

打开方式为新窗口时,会打开新页面,如下:
# static 菜单配置方式

# 目录位置
目录位置为左侧时,目录显示在页面最左侧。入下图:

目录位置为右上角时,目录显示在页面最右上角。入下图:

# 4. 修改菜单
点击菜单表格行操作列编辑按钮,即可打开菜单详情页面进行编辑操作。

页面编辑信息详见上文新增菜单
# 5. 停启用菜单
对停用状态的菜单进行启用操作,点击是否启用列switch按钮,将菜单状态置为启用状态即可。

# 6. 删除菜单
菜单删除包含两种操作场景:单独删除和批量删除。
单独删除。点击菜单表格行操作列删除按钮,即可对菜单进行删除。

批量删除。勾选菜单后,点击表头上方删除按钮,即可对菜单进行批量删除。

注意:目录下如果有子级数据,则不可删除。
# 7. 菜单数据日志
菜单管理提供数据日志的查询功能,点击数据日志按钮即可进入菜单管理模块的数据日志列表页面,详情参考数据日志。
# 8. 菜单生命周期
菜单管理提供生命周期的查询功能,勾选表格行选中框,点击生命周期即可查看该条数据的生命周期信息,详情参考生命周期。
# 9. 菜单导入
菜单管理提供数据的导入功能,详情参考导入导出-导入流程。
# 10. 菜单导出
菜单管理提供数据的导出功能,详情参考导入导出-导出流程。
# 11. 菜单详情查看
菜单管理提供数据的详情查看功能,选择某一个记录,点击【查看】按钮,即可查看该条数据的详细信息。
# 12. 内联菜单维护
点击菜单类型行内的【内联菜单】按钮可打开内联菜单维护界面,如下

内联菜单页面操作请到内联菜单维护
# 13. 菜单切换
使用postMessage发送消息,通过此消息(Object)中的type:消息类型(String)及data:菜单编码(String),进行相应的逻辑处理. 注: 消息中的type有多种,不同场景有相应的type字段.发送消息时的type字段必须按文档采用固定写法. 具体示例代码如下:
const message = {
type: 'isNeedSwitch' // type不同场景有相应内容,为固定写法.
data: 'menuCode' // 要前往的菜单编码
}
window.postMessage(message, '*')
# 菜单切换确认
进行菜单页签切换时,首先框架会使用postMessage发送一条消息,确认是否需要进行菜单页签切换确认.消息中的data字段为要前往菜单的编码.
此时对type: 'isNeedSwitch'进行监听.在接收到此类型消息后,若需要进行跳转确认,需立即使用 postMessage 返回一条消息.
在进行自定义的逻辑处理后,使用postMessage发送一条消息type: 'tabSwitch',表示逻辑已处理完毕,根据处理结果判断是否允许切换.
菜单切换确认对应的type为: 'isNeedSwitch', 'needSwitch', 'tabSwitch'.
示例代码如下:
// 可在此处定义需进行切换确认的菜单列表(内容为菜单编码)
const menuList = ['route1', 'route2']
// 进行message事件监听
// 若在子iframe里,则此处需要使用window.top.addEventListener
window.addEventListener('message', (e) => {
const { type, data } = e.data
if (type === 'isNeedSwitch') {
// 判断要前往的菜单是否在定义的列表里(此处仅做示例)
if (menuList.includes(data)) {
// 若不需要跳转确认,则什么都不做或返回{ type: 'needSwitch', data: false }
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'needSwitch', data: true })
// ...... (一些自定义逻辑处理)
// 在进行自定义逻辑处理完毕后,根据结果决定是否进行跳转
// data为true表示跳转,为false表示不跳转
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'tabSwitch', data: true })
}
}
})
# 退出登录确认
退出登录逻辑基本同上.退出登录时,框架在postMessage发送消息时,data字段固定为'login'.
退出登录对应的type为: 'isNeedLogout', 'needLogout', 'confirmLogout'.
示例代码如下:
// 进行message事件监听
// 若在子iframe里,则此处需要使用window.top.addEventListener
window.addEventListener('message', (e) => {
const { type, data } = e.data
if (type === 'isNeedLogout') {
// 若不需要退出登录确认,则什么都不做或返回{ type: 'needLogout', data: false }
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'needLogout', data: true })
// ...... (一些自定义逻辑处理)
// 在进行自定义逻辑处理完毕后,根据结果决定是否进行跳转
// data为true表示退出,为false表示不退出
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'confirmLogout', data: true })
}
})
# 关闭 Tab 页签确认
关闭Tab页签确认逻辑基本同上.关闭页签时,框架在postMessage发送消息时,data字段为要关闭的页签的菜单编码.
退出登录对应的type为: 'isNeedRemove', 'needRemove', 'confirmRemove'.
示例代码如下:
// 可在此处定义需进行切换确认的菜单列表(内容为菜单编码)
const menuList = ['route1', 'route2']
// 进行message事件监听
// 若在子iframe里,则此处需要使用window.top.addEventListener
window.addEventListener('message', (e) => {
const { type, data } = e.data
if (type === 'isNeedRemove') {
// 判断要关闭的页签对应的菜单编码是否在定义的列表里(此处仅做示例)
if (menuList.includes(data)) {
// 若不需要关闭页签确认,则什么都不做或返回{ type: 'needRemove', data: false }
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'needRemove', data: true })
// ...... (一些自定义逻辑处理)
// 在进行自定义逻辑处理完毕后,根据结果决定是否进行关闭页签
// data为true表示关闭,为false表示不关闭
// 若在子iframe里,则此处需要使用window.top.postMessage
window.postMessage({ type: 'confirmRemove', data: true })
}
}
})