【ABP】 动态菜单修改过程asp.netcore+vue
程序员文章站
2023-11-14 09:25:04
无论用什么框架,第一件事情就是实现动态菜单,从数据库中读取菜单配置项输出前台,网上翻了一大堆翻译文档,也看了官方英文文档,关键点在于如何实现 和在前端调用 。 后台处理 1、建表UiMenu 2、实现MyNavigationProvider 在Core项目里新建文件夹 ,新建类 ,需继承 。 如下实 ......
无论用什么框架,第一件事情就是实现动态菜单,从数据库中读取菜单配置项输出前台,网上翻了一大堆翻译文档,也看了官方英文文档,关键点在于如何实现navigationprovider
和在前端调用abp.nav.menus.mainmenu
。
后台处理
1、建表uimenu
public class uimenu : fullauditedentity<int>, imusthavetenant { public int pid { get; set; } [required] [stringlength(50)] public string name { get; set; } [required] [stringlength(50)] public string displayname { get; set; } [required] [stringlength(50)] public string menutype { get; set; } [stringlength(200)] public string path { get; set; } [stringlength(500)] public string customdata { get; set; } [stringlength(200)] public string remark { get; set; } public string icon { get; set; } public string action { get; set; } public int order { get; set; } public int tenantid { get; set; } }
2、实现mynavigationprovider
在core项目里新建文件夹navigations
,新建类mynavigationprovider
,需继承navigationprovider
。
如下实现uimneu的仓储操作对象
private readonly irepository<uimenu> _repository; public mynavigationprovider(irepository<uimenu> repository) { _repository = repository; }
然后重写setnavigation
。
var allmenus = _repository.getalllist(); foreach (var item in allmenus) { if (item.pid>0) { //子项 context.manager.mainmenu.getitembyname(allmenus.find(p => p.id == item.pid).name).additem( new menuitemdefinition( item.name, new localizablestring(item.displayname, myconsts.localizationsourcename), url: item.path, icon: item.icon, isvisible: item.isdeleted, requiredpermissionname: "" ) ); } else { //父级菜单 context.manager.mainmenu.additem(new menuitemdefinition( item.name, new localizablestring(item.displayname, myconsts.localizationsourcename), url: item.path, icon: item.icon, isvisible:item.isdeleted, requiredpermissionname:""//配置权限,可在uimenu表中新加字段配置 )); } }
至于如何对菜单表进行增删改查维护,不是本篇主题,故略过。
前端实现
前端实现的主要是依靠官方提供的方法abp.nav.menus.mainmenu
1、创建router帮助方法 router-util.ts
import main from '../views/main.vue' //import parentview from '@/components/parent-view' // 加载路由菜单,从localstorage拿到路由,在创建路由时使用 // @函数: 引入组件 export const lazyloadingcop = file => require('../views' + file + '.vue').default class routerhelper { dynamicrouteradd(): array<router> { let dynamicrouter = [] window.abp.nav.menus.mainmenu.items.foreach(el => { let obj = { path: '/' + el.name, name: el.name, icon: el.icon, permission: undefined, meta: { title: el.displayname }, component: 'main', children: [], } if (el.items.length > 0) { el.items.foreach(child => { obj.children.push({ path: child.name, name: child.name, icon: child.icon, permission: undefined, meta: { title: child.displayname }, component: child.url, children: null, }) }) dynamicrouter.push(obj) } else { dynamicrouter.push({ path: '/' + el.items[0].name, name: el.items[0].name, icon: el.items[0].icon, permission: undefined, meta: { title: el.items[0].displayname }, component: el.items[0].url, children: [], }) } }); dynamicrouter = this.filterasyncrouter(dynamicrouter) return dynamicrouter } // @函数: 遍历后台传来的路由字符串,转换为组件对象 filterasyncrouter(asyncroutermap) { const accessedrouters = asyncroutermap.filter(route => { if (route.component) { if (route.component === 'main' || route.component.name === 'main') { // main组件特殊处理 route.component = main } // else if (route.component === 'parentview') { // parentview组件特殊处理 // route.component = parentview // } else { route.component = lazyloadingcop(route.component) } } if (route.children && route.children.length) { route.children = this.filterasyncrouter(route.children) } return true }) return accessedrouters } } const routerhelper = new routerhelper(); export default routerhelper;
parentview
为多级菜单,如果有需求可以使用,该组件摘自iview admin 2.0
解释:
循环abp.nav.menus.mainmenu.items
,将其格式转换为router
。方便菜单调用。
2、修改router/index.ts
找到router/index.ts,
在beforeeach
方法里添加如下代码
let dyrouters = routerhelper.dynamicrouteradd() dyrouters.foreach(element => { approuters.push(element); }); router.addroutes(approuters)
注意引用 import routerhelper from '../lib/router-util'
总结
一开始没有丝毫头绪,后台参照使用iview admin时构建的方法进行尝试,加之刚刚接触typescript,用起来不是特别顺手,问题的关键在于router/router.ts
->approuters处无法获得abp.nav.menus.mainmenu.items
在store/modules/app里虽然可以获取,但是router中不存在,无法正常点击跳转,taglist同样也无从获取。
最终想到这种不是很完美的方法,前端仍然需要进行循环转换model。但终归是实现了动态菜单,可以进行下一步操作了。