import { IAppMenuStore } from '@/core/interface/widgets/store'; import { CtrlController } from './ctrl-controller'; import { AppMenuActionType, IAppFunc, IAppMenuAbility, IAppMenuController, IAppMenuControllerParams, IAppMenuModel, ICtrlActionResult, IParam, } from '../../interface'; import { deepCopy } from '@/core'; import { router } from '@/router'; import { useAppStoreWithOut } from '@/store'; /** * 菜单部件控制器 (todo:视图/部件交互方式存在问题) * * @export * @class MenuController * @extends {CtrlController} * @implements {IMenuController} * @template T */ export class AppMenuController extends CtrlController implements IAppMenuController { /** * @description 是否应用起始页 * @protected * @type {boolean} * @memberof AppMenuController */ protected isDefaultPage!: boolean; /** * @description 空白首页模式 * @protected * @type {boolean} * @memberof AppMenuController */ protected isBlankMode!: boolean; /** * @description 默认视图 * @protected * @type {string} * @memberof AppMenuController */ protected defPSAppView?: string; /** * @description 菜单模式 * @protected * @type {string} * @memberof AppMenuController */ protected mode!: string; /** * @description 菜单模式 * @protected * @type {string} * @memberof AppMenuController */ protected cacheMenu!: IParam[]; /** * Creates an instance of AppMenuController. * @param {IAppMenuControllerParams} params * @memberof AppMenuController */ public constructor( params: IAppMenuControllerParams ) { super(params); this.ctrlInit(params); } /** * 处理部件初始化 * * @protected * @param {IAppMenuControllerParams} params * @memberof AppMenuController */ protected processCtrlInit( params: IAppMenuControllerParams ) { super.processCtrlInit(params); this.isDefaultPage = params.isDefaultPage === true; this.isBlankMode = params.isBlankMode === true; this.defPSAppView = params.defPSAppView; this.mode = params.mode; const model = this.getModel(); Object.assign(this.store, { defaultExpands: model.defaultExpands, menus: deepCopy(model.menus), selections: [], }); } /** * 获取数据 * * @return {*} {IParam[]} * @memberof AppMenuController */ public getData(): IParam[] { const data: Array = this.store.menus; return data; } /** * @description 获取能力 * @return {*} {IAppMenuAbility} * @memberof AppMenuController */ public getAbility(): IAppMenuAbility { return { ...super.getAbility(), load: this.load.bind(this), }; } /** * @description 加载数据 * @memberof AppMenuController */ public load(): Promise { const menus: IParam[] = deepCopy(this.model.menus) as IParam[]; if (App.getEnableAppPermission()) { this.computedMenusResource(this.store.menus); } else { this.store.menus = menus } this.computeMenusIcon(); this.computeDefaultView(); this.emit('loaded', this.store.menus); this.cacheMenu = this.getData(); return Promise.resolve({ ok: false, data: this.getData(), rowData: menus }); } /** * @description 设置选中数据 * @param {IParam} menu * @memberof AppMenuController */ public setSelection(menu: IParam) { this.store.selections = [menu.name]; this.store.defaultExpands.push(menu.name); } /** * @description 计算菜单权限 * @memberof AppMenuController */ protected computedMenusResource(menus: IParam[]) { if (menus.length > 0) { const appName = App.getAppConfig().appName; const sysName = App.getAppConfig().sysName; const menuPermissionMode = App.getProjectSetting().menuSetting.menuPermissionMode; menus.forEach((menu: IParam) => { const tag: string = Object.is(menuPermissionMode, 'RT') ? `${appName}-${this.model.codeName}-${menu.name}` : menu.resourceTag ? menu.resourceTag : `${sysName}-${appName}-${this.model.codeName}-${menu.name}`; if (tag && !App.getAppMenuAuth(tag)) { menu.hidden = true; } else if (menu.menuItems && menu.menuItems.length > 0) { this.computedMenusResource(menu.menuItems); } }); } } /** * @description 计算第一级菜单图标 * @memberof AppMenuController */ public computeMenusIcon() { this.store.menus.forEach((menu: IParam) => { if (!menu.iconClass && !menu.imgPath && !menu.imgPathX) { menu.iconClass = 'fa fa-cogs'; } }) } /** * @description 设置默认视图 * @param {IParam[]} menus * @return {*} * @memberof AppMenuController */ public setDefaultView(menus: IParam[]) { const appFuncConfig = App.getAppFuncConfig(); const result = menus.some((menu: any) => { if (menu.funcTag && menu.openDefault && !menu.hidden ) { const appFunc = appFuncConfig?.find((_appFunc: any) => Object.is(_appFunc.funcTag, menu.funcTag) ); if (appFunc && appFunc.openViewCodeName) { const { setDefaultViewCodeName, unshiftBreadcrumbs, getBreadcrumbs, addBreadcrumbs } = useAppStoreWithOut(); setDefaultViewCodeName(appFunc.openViewCodeName); const appViewConfig = App.getAppViewConfig(); const view = appViewConfig[appFunc.openViewCodeName]; if (view) { if (getBreadcrumbs.length === 1 && !Object.is(getBreadcrumbs[0].tag, appFunc.openViewCodeName)) { const context = deepCopy(this.store.context); Object.assign(view, { isRoute: true, context }) unshiftBreadcrumbs(view); const currentRoute = unref(router.currentRoute); if ( currentRoute.meta && !currentRoute.meta.ignoreAddPage && currentRoute.meta.tag !== 'AppWFRedirectView' ) { const pageMeta: any = {...currentRoute.meta, fullPath: currentRoute.fullPath }; addBreadcrumbs(pageMeta); } } } return true; } } if (menu.menuItems && menu.menuItems.length > 0) { return this.setDefaultView(menu.menuItems); } return false; }); return result; } /** * @description 计算默认视图 * @memberof AppMenuController */ public computeDefaultView() { if (!this.isDefaultPage || this.isBlankMode) { return; } const appFuncConfig = App.getAppFuncConfig(); const currentRoute = unref(router.currentRoute); if ( currentRoute && currentRoute.matched && currentRoute.matched.length == 2 ) { // 存在二级路由 const [{ }, matched] = currentRoute.matched; const appFunc: any = appFuncConfig.find( (_appFunc: any) => Object.is(_appFunc.openViewCodeName, matched.meta.tag) && Object.is(_appFunc.appFuncType, 'APPVIEW') ); if (appFunc) { this.computeMenuSelect(this.store.menus, appFunc.funcTag); } this.setDefaultView(this.store.menus); return; } else if (this.defPSAppView) { // 存在默认视图 const appFunc: any = appFuncConfig.find( (_appFunc: any) => Object.is(_appFunc.openViewCodeName, this.defPSAppView) && Object.is(_appFunc.appFuncType, 'APPVIEW') ); if (appFunc) { this.computeMenuSelect(this.store.menus, appFunc.funcTag); } this.openDefaultView(this.defPSAppView); return; } this.computeMenuSelect(this.store.menus, ''); } /** * @description 计算菜单选中 * @param {IParam[]} menus * @param {string} appFuncTag * @return {*} {boolean} * @memberof AppMenuController */ public computeMenuSelect(menus: IParam[], appFuncTag: string): boolean { const appFuncConfig = App.getAppFuncConfig(); const result = menus.some((menu: any) => { if ( Object.is(appFuncTag, '') && menu.funcTag && menu.openDefault && !menu.hidden ) { const appFunc = appFuncConfig?.find((_appFunc: any) => Object.is(_appFunc.funcTag, menu.funcTag) ); if (appFunc && appFunc.openViewCodeName) { this.setSelection(menu); this.openDefaultView(appFunc.openViewCodeName,appFunc.navigateParam?appFunc.navigateParam:{}); return true; } } if (menu.funcTag && Object.is(menu.funcTag, appFuncTag) && !menu.hidden) { this.setSelection(menu); return true; } if (menu.menuItems && menu.menuItems.length > 0) { return this.computeMenuSelect(menu.menuItems, appFuncTag); } return false; }); return result; } /** * @description 打开默认视图 * @param {string} codeName * @memberof AppMenuController */ public openDefaultView(codeName: string,viewParam?:IParam) { const appViewConfig = App.getAppViewConfig(); const view = appViewConfig[codeName]; let localViewParam = {}; if(viewParam){ localViewParam = Object.assign(localViewParam,viewParam); } if (view) { const { setDefaultViewCodeName } = useAppStoreWithOut(); setDefaultViewCodeName(view.codeName); const context = deepCopy(this.store.context); App.getOpenViewHelper().openPage(view, context, localViewParam); } else { console.warn(App.ts("widget.common.nofindview", "未找到相关视图")); } } /** * @description 处理菜单点击 * @param {number} index * @memberof AppMenuController */ public handleMenuClick(name: string) { const item = this.computeItem(this.model.menus, name); if (!item || !item.name) { return; } if (item.funcTag) { const { removeBreadcrumbsFirst } = useAppStoreWithOut(); removeBreadcrumbsFirst(); if ( Object.is(this.mode, 'TABEXP_LEFT') || Object.is(this.mode, 'TABEXP_TOP') || Object.is(this.mode, 'TABEXP_RIGHT') || Object.is(this.mode, 'TABEXP_BOTTOM') || Object.is(this.mode, 'TREEEXP') ) { const appFuncConfig = App.getAppFuncConfig(); if (appFuncConfig && appFuncConfig.length > 0) { const appFunc = appFuncConfig.find((appFunc: IAppFunc) => Object.is(appFunc.funcTag, item.funcTag) ); if (appFunc && appFunc.openViewCodeName) { this.store.openViewCodeName = appFunc.openViewCodeName; } } } else { App.getAppFuncHelper().execute( item.funcTag, this.store.context, this.store.viewParams ); } } else { console.warn(App.ts("widget.menu.noconfigmenu")); } } /** * @description 计算当前菜单项 * @param {any[]} items * @param {string} name * @return {*} * @memberof AppMenuController */ public computeItem(items: any[], name: string) { let item: any = null; if (items && items.length > 0) { items.some((_item: any) => { if (_item.name === name) { item = _item; return true; } const child = this.computeItem(_item.menuItems, name); if (child) { item = child; return true; } return false; }); } return item; } /** * 刷新 * * @param {(IParam | undefined)} [args] * @return {*} {Promise} * @memberof CtrlController */ public refresh(args?: IParam | undefined): Promise { if (!args?.value) { this.store.menus = this.cacheMenu; return Promise.resolve(true);; } const { value } = args; const items = this.store.menus; const calcIndexOf = (filter: any[]): any => { let searchMenus: any[] = []; if (filter) { const filterMenus = (menus: any[], childrenArr: any[]) => { if (!menus.length) return; for (let menu of menus) { let children: any[] = []; if (menu.menuItems && menu.menuItems.length > 0) { filterMenus(menu.menuItems, children); } if (children.length > 0) { const filterMenu = Object.assign(deepCopy(menu), { menuItems: children, }) childrenArr.push(filterMenu); } else if (menu.caption && menu.caption.search(filter) != -1) { const filterMenu = Object.assign(deepCopy(menu), { menuItems: [], }) childrenArr.push(filterMenu); } } } filterMenus(this.cacheMenu, searchMenus); } else { searchMenus = this.cacheMenu; } return searchMenus; } const _items = calcIndexOf(value); this.store.menus = _items; return Promise.resolve(true); } }