不管用什麼框架,第一件事情就是實現動態菜單,從數據庫中讀取菜單配置項輸出前臺,網上翻了一大堆翻譯文檔,也看了官方英文文檔,關鍵點在於如何實現NavigationProvider
和在前端調用abp.nav.menus.MainMenu
。前端
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; } }
在Core項目裏新建文件夾Navigations
,新建類MyNavigationProvider
,需繼承NavigationProvider
。vue
以下實現UiMneu的倉儲操做對象typescript
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表中新加字段配置 )); } }
至於如何對菜單表進行增刪改查維護,不是本篇主題,故略過。c#
前端實現的主要是依靠官方提供的方法abp.nav.menus.MainMenu
app
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框架
解釋:iview
循環abp.nav.menus.MainMenu.items
,將其格式轉換爲Router
。方便菜單調用。async
找到router/index.ts,
在beforeEach
方法裏添加以下代碼ide
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。但終歸是實現了動態菜單,能夠進行下一步操做了。