<template> <#if quick_menus??> ${quick_menus} <#else> <div class="app-app-menu<#if ctrl.getPSSysCss?? && ctrl.getPSSysCss()??> ${ctrl.getPSSysCss().getCssName()}</#if>"> <#if ctrl.getAppMenuStyle?? && ctrl.getAppMenuStyle() == "ICONVIEW"> <app-icon-menus :menus = "menus" :ctrlName = "'${ctrl.codeName?lower_case}'" @menuClick="select"></app-icon-menus> <#else> <el-menu class="app-menu" <#if view.getMainMenuAlign()?? && view.getMainMenuAlign()!="TOP">:default-openeds="defaultOpeneds"</#if> :mode="mode" :menu-trigger="trigger" :collapse="isCollapse" @select="select" :default-active="defaultActive"> <template v-if="Object.is(mode,'horizontal')"> <template v-for="item0 in menus"> <template v-if="item0.items && Array.isArray(item0.items) && item0.items.length > 0"> <el-submenu v-show="!item0.hidden" :index="item0.name" :popper-class="popperClass" :key="item0.id" :class="item0.textcls"> <template slot='title'> <template v-if="item0.icon && item0.icon != ''"> <img :src="item0.icon" class='app-menu-icon' /> </template> <template v-else-if="item0.iconcls && item0.iconcls != ''"> <i :class="[item0.iconcls, 'app-menu-icon']"></i> </template> <template v-else> <i class='app-menu-icon'></i> <#-- <i class='fa fa-cogs app-menu-icon'></i> --> </template> <span class='text' :title="$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item0.name)">{{$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item0.name)}}</span> </template> <template v-for="item1 in item0.items"> <template v-if="item1.items && Array.isArray(item1.items) && item1.items.length > 0"> <el-submenu v-show="!item1.hidden" :index="item1.name" :popper-class="popperClass" :key="item1.id" :class="item1.textcls"> <template slot='title'> <template v-if="item1.icon && item1.icon != ''"> <img :src="item1.icon" class='app-menu-icon' /> </template> <template v-else-if="item1.iconcls && item1.iconcls != ''"> <i :class="[item1.iconcls, 'app-menu-icon']"></i> </template> <span class='text' :title="$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item1.name)">{{$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item1.name)}}</span> </template> <template v-for="item2 in item1.items"> <template v-if="item2.type =='MENUITEM'"> <el-menu-item v-show="!item2.hidden" :index="item2.name" :key="item2.id" :class="item2.textcls"> <template v-if="item2.icon && item2.icon != ''"> <img :src="item2.icon" class='app-menu-icon' /> </template> <template v-else-if="item2.iconcls && item2.iconcls != ''"> <i :class="[item2.iconcls, 'app-menu-icon']"></i> </template> <template slot="title"> <span class="text" :title="$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item2.name)">{{$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item2.name)}}</span> <template v-if="counterdata && counterdata[item2.counterid] && counterdata[item2.counterid] > 0"> <span class="pull-right"> <badge :count="counterdata[item2.counterid]" :overflow-count="9999"></badge> </span> </template> </template> </el-menu-item> </template> </template> </el-submenu> </template> <template v-else> <template v-if="item1.type =='MENUITEM'"> <el-menu-item v-show="!item1.hidden" :index="item1.name" :key="item1.id" :class="item1.textcls"> <template v-if="item1.icon && item1.icon != ''"> <img :src="item1.icon" class='app-menu-icon' /> </template> <template v-else-if="item1.iconcls && item1.iconcls != ''"> <i :class="[item1.iconcls, 'app-menu-icon']"></i> </template> <template slot="title"> <span class="text" :title="$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item1.name)">{{$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item1.name)}} </span> <template v-if="counterdata && counterdata[item1.counterid] && counterdata[item1.counterid] > 0"> <span class="pull-right"> <badge :count="counterdata[item1.counterid]" :overflow-count="9999"></badge> </span> </template> </template> </el-menu-item> </template> </template> </template> </el-submenu> </template> <template v-else> <template v-if="item0.type =='MENUITEM'"> <el-menu-item v-show="!item0.hidden" :index="item0.name" :key="item0.id" :class="item0.textcls"> <template v-if="item0.icon && item0.icon != ''"> <img :src="item0.icon" class='app-menu-icon' /> </template> <template v-else-if="item0.iconcls && item0.iconcls != ''"> <i :class="[item0.iconcls, 'app-menu-icon']"></i> </template> <template v-else> <i class='app-menu-icon'></i> <#-- <i class='fa fa-cogs app-menu-icon'></i> --> </template> <template slot="title"> <span class="text" :title="$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item0.name)">{{$t('app.menus.${ctrl.getCodeName()?lower_case}.' + item0.name)}}</span> <template v-if="counterdata && counterdata[item0.counterid] && counterdata[item0.counterid] > 0"> <span class="pull-right"> <badge :count="counterdata[item0.counterid]" :overflow-count="9999"></badge> </span> </template> </template> </el-menu-item> </template> </template> </template> </template> <app-menu-item v-else :isCollapse="isCollapse" :menus="menus" :ctrlName="'${ctrl.getCodeName()?lower_case}'" :isFirst="true" :counterdata="counterdata" :popper-class="popperClass"></app-menu-item> </el-menu> </#if> </div> </#if> </template> <#assign import_block> import ${srfclassname('${ctrl.codeName}')}Model from './${srffilepath2(ctrl.codeName)}-${ctrl.getControlType()?lower_case}-model'; import { Environment } from '@/environments/environment'; import AuthService from '@/authservice/auth-service'; </#assign> <#ibizinclude> ../@MACRO/CONTROL/CONTROL_HEADER-BASE.vue.ftl </#ibizinclude> /** * 获取多项数据 * * @returns {any[]} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public getDatas(): any[] { return []; } /** * 获取单项树 * * @returns {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public getData(): any { return null; } /** * 导航模式(route:面包屑模式、tab:分页导航模式) * * @type {string} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop({default:'tab'}) public navModel?:string; /** * 视图标识 * * @type {string} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop() public viewtag!:string; /** * 菜单模型 * * @public * @type {${srfclassname('${ctrl.codeName}')}Model} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public menuMode: ${srfclassname('${ctrl.codeName}')}Model = new ${srfclassname('${ctrl.codeName}')}Model(); /** * 显示处理提示 * * @type {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop({ default: true }) public showBusyIndicator?: boolean; /** * 菜单数据 * * @public * @type {any[]} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Provide() public menus: any[] = []; /** * 菜单收缩改变 * * @type {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Model() public collapsechange?: boolean; /** * 监听菜单收缩 * * @param {*} newVal * @param {*} oldVal * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Watch('collapsechange') onCollapsechangeChange(newVal: any, oldVal: any) { if (newVal !== this.isCollapse) { this.isCollapse = !this.isCollapse; } } /** * 当前模式,菜单在顶部还是在底部 * * @type {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop() mode: any; /** * 应用起始页面 * * @type {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop({ default: false }) isDefaultPage?: boolean; /** * 空白视图模式 * * @type {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop({ default: false }) isBlankMode?:boolean; /** * 默认打开视图 * * @type {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop() defPSAppView: any; /** * 默认激活的index * * @type {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Provide() defaultActive: any = null; /** * 当前选中主题 * * @type {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Prop() selectTheme: any; /** * 默认打开的index数组 * * @type {any[]} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Provide() public defaultOpeneds: any[] = []; /** * 是否展开 * * @type {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Provide() public isCollapse: boolean = false; /** * 触发方式,默认click * * @type {string} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ @Provide() trigger: string = 'click'; /** * 计数器数据 * * @type {*} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public counterdata: any = {}; /** * 建构权限服务对象 * * @type {AuthService} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public authService:AuthService = new AuthService(); /** * vue 生命周期 * * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public created() { this.afterCreated(); } /** * 执行created后的逻辑 * * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public afterCreated(){ if (Object.is(this.mode, 'horizontal')) { this.trigger = 'hover'; } if (this.viewState) { this.viewStateEvent = this.viewState.subscribe(({ tag, action, data }) => { if (!Object.is(tag, this.name)) { return; } this.load(data); }); } } /** * vue 生命周期 * * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public destroyed() { this.afterDestroy(); } /** * 执行destroyed后的逻辑 * * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public afterDestroy() { if (this.viewStateEvent) { this.viewStateEvent.unsubscribe(); } <#if destroyed_block??> ${destroyed_block} </#if> } <#if view.isDefaultPage?? && view.isDefaultPage()> /** * 处理菜单默认选中项 * * @public * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public doMenuSelect(): void { if (!this.isDefaultPage || this.isBlankMode) { return; } const appFuncs: any[] = this.menuMode.getAppFuncs(); if (this.$route && this.$route.matched && this.$route.matched.length == 2) { // 存在二级路由 const [{ }, matched] = this.$route.matched; const appfunc: any = appFuncs.find((_appfunc: any) => Object.is(_appfunc.routepath, matched.path) && Object.is(_appfunc.appfuncyype, 'APPVIEW')); if (appfunc) { this.computeMenuSelect(this.menus, appfunc.appfunctag); } return; } else if (this.defPSAppView && Object.keys(this.defPSAppView).length > 0) { // 存在默认视图 const appfunc: any = appFuncs.find((_appfunc: any) => Object.is(_appfunc.routepath, this.defPSAppView.routepath) && Object.is(_appfunc.appfuncyype, 'APPVIEW')); if (appfunc) { this.computeMenuSelect(this.menus, appfunc.appfunctag); } const viewparam: any = {}; const path: string = this.$viewTool.buildUpRoutePath(this.$route, {}, this.defPSAppView.deResParameters, this.defPSAppView.parameters, [], viewparam); this.$router.push(path); return; } this.computeMenuSelect(this.menus, ''); let item = this.compute(this.menus, this.defaultActive); if (Object.keys(item).length === 0) { return; } if(!item.hidden){ this.click(item); } } /** * 计算菜单选中项 * * @public * @param {any[]} items * @param {string} appfunctag * @returns {boolean} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public computeMenuSelect(items: any[], appfunctag: string): boolean { const appFuncs: any[] = this.menuMode.getAppFuncs(); return items.some((item: any) => { if (Object.is(appfunctag, '') && !Object.is(item.appfunctag, '') && item.opendefault) { const appfunc = appFuncs.find((_appfunc: any) => Object.is(_appfunc.appfunctag, item.appfunctag)); if (appfunc.routepath) { this.defaultActive = item.name; this.setHideSideBar(item); return true; } } if (Object.is(item.appfunctag, appfunctag) && item.opendefault) { this.setHideSideBar(item); this.defaultActive = item.name; return true; } if (item.items && item.items.length > 0) { const state = this.computeMenuSelect(item.items, appfunctag); if (state) { this.defaultOpeneds.push(item.name); return true; } } return false; }); } </#if> /** * 获取菜单项数据 * * @public * @param {any[]} items * @param {string} name * @returns * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public compute(items: any[], name: string) { const item: any = {}; items.some((_item: any) => { if (name && Object.is(_item.name, name)) { Object.assign(item, _item); this.setHideSideBar(_item); return true; } if (_item.items && Array.isArray(_item.items)) { const subItem = this.compute(_item.items, name); if (Object.keys(subItem).length > 0) { Object.assign(item, subItem); return true; } } return false; }); return item; } /** * 设置是否隐藏菜单栏 * * @public * @param {*} item * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public setHideSideBar(item: any): void { <#if view.isDefaultPage?? && view.isDefaultPage()> if (item.hidesidebar) { this.$emit('collapsechange', true); } </#if> } /** * 菜单项选中处理 * * @param {*} index * @param {any[]} indexs * @returns * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public select(index: any, indexs: any[]) { let item = this.compute(this.menus, index); if (Object.keys(item).length === 0) { return; } this.click(item); } /** * 菜单点击 * * @public * @param {*} item 菜单数据 * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public click(item: any) { if (item) { let navDataService = NavDataService.getInstance(); if(Object.is(this.navModel,"route")){ navDataService.removeNavData(this.viewtag); } switch (item.appfunctag) { <#if ctrl.getPSAppFuncs()??> <#assign appFuncs = ctrl.getPSAppFuncs()> <#list appFuncs as singFuncs> case '${singFuncs.getCodeName()}': this.click${singFuncs.codeName}(item); return; </#list> </#if> default: console.warn('未指定应用功能'); } } } <#if ctrl.getPSAppFuncs()??> <@ibizindent blank=4> <#list ctrl.getPSAppFuncs() as singleFuncs> ${P.getLogicCode(singleFuncs,"LOGIC.vue").code} </#list> </@ibizindent> </#if> /** * 数据加载 * * @param {*} data * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public load(data: any) { this.handleMenusResource(this.menuMode.getAppMenuItems()); } /** * 通过统一资源标识计算菜单 * * @param {*} data * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public handleMenusResource(inputMenus:Array<any>){ if(this.$store.getters['authresource/getEnablePermissionValid']){ this.computedEffectiveMenus(inputMenus); this.computeParentMenus(inputMenus); } this.dataProcess(inputMenus); this.menus = inputMenus; <#if view.isDefaultPage?? && view.isDefaultPage()> this.doMenuSelect(); </#if> } /** * 计算有效菜单项 * * @param {*} inputMenus * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public computedEffectiveMenus(inputMenus:Array<any>){ inputMenus.forEach((_item:any) =>{ if(!this.authService.getMenusPermission(_item)){ _item.hidden = true; if (_item.items && _item.items.length > 0) { this.computedEffectiveMenus(_item.items); } } }) } /** * 计算父项菜单项是否隐藏 * * @param {*} inputMenus * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public computeParentMenus(inputMenus:Array<any>){ if(inputMenus && inputMenus.length >0){ inputMenus.forEach((item:any) =>{ if(item.hidden && item.items && item.items.length >0){ item.items.map((singleItem:any) =>{ if(!singleItem.hidden){ item.hidden = false; }else{ if(singleItem.items && singleItem.items.length >0){ singleItem.items.map((grandsonItem:any) =>{ if(!grandsonItem.hidden){ item.hidden = false; } }) } } if(item.items && item.items.length >0){ this.computeParentMenus(item.items); } }) } }) } } /** * 数据处理 * * @public * @param {any[]} items * @memberof ${srfclassname('${ctrl.codeName}')}Base */ public dataProcess(items: any[]): void { items.forEach((_item: any) => { if (_item.expanded) { this.defaultOpeneds.push(_item.name); } if (_item.items && _item.items.length > 0) { this.dataProcess(_item.items) } }); } /** * 提示框主题样式 * * @readonly * @type {string} * @memberof ${srfclassname('${ctrl.codeName}')}Base */ get popperClass(): string { return 'app-popper-menu ' + this.selectTheme; } <#ibizinclude> ../@MACRO/CONTROL/CONTROL_BOTTOM-BASE.vue.ftl </#ibizinclude> <#ibizinclude> ../@MACRO/CONTROL/CONTROL-BASE.style.ftl </#ibizinclude>