From d5ac9e551bb30932b11e2cac1904ef0ad255b451 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Mon, 10 Jul 2023 18:35:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=8F=9C=E5=8D=95=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E5=99=A8=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/app-menu/app-menu.controller.ts | 37 ++++++- src/control/app-menu/app-menu.scss | 13 +++ src/control/app-menu/app-menu.tsx | 111 ++++++++++++++------ src/control/chart/chart.controller.ts | 2 +- 4 files changed, 129 insertions(+), 34 deletions(-) diff --git a/src/control/app-menu/app-menu.controller.ts b/src/control/app-menu/app-menu.controller.ts index 3444d7d1..98b834a4 100644 --- a/src/control/app-menu/app-menu.controller.ts +++ b/src/control/app-menu/app-menu.controller.ts @@ -10,6 +10,7 @@ import { IAppMenuEvent, Application, IAppMenuState, + AppCounter, } from '@ibiz-template/runtime'; import { IAppMenu, IAppMenuItem } from '@ibiz/model-core'; @@ -63,7 +64,7 @@ export class AppMenuController * @param {string} id * @return {*} {Promise} */ - async onClickMenuItem(id: string, event: MouseEvent): Promise { + async onClickMenuItem(id: string, event?: MouseEvent): Promise { const menuItem = findRecursiveChild(this.model, id, { compareField: 'id', childrenFields: ['appMenuItems'], @@ -128,4 +129,38 @@ export class AppMenuController permitted: true, }; } + + /** + * 所有项平铺 + * @return {*} + * @author: zhujiamin + * @Date: 2022-09-09 16:48:21 + */ + getAllItems() { + const result: IAppMenuItem[] = []; + const flattenMenus = (menuItems: IAppMenuItem[]) => { + menuItems.forEach(item => { + result.push(item); + if (item.appMenuItems && item.appMenuItems.length > 0) { + flattenMenus(item.appMenuItems); + } + }); + }; + flattenMenus(this.model.appMenuItems!); + return result; + } + + /** + * 根据id去视图控制器里取得计数器对象 + * @return {*} + * @author: zhujiamin + * @Date: 2023-07-10 15:14:21 + */ + getCounter(id: string): AppCounter | null { + const counters = this.ctx.view.counters; + if (counters[id]) { + return counters[id]; + } + return null; + } } diff --git a/src/control/app-menu/app-menu.scss b/src/control/app-menu/app-menu.scss index 443bcb1f..e3686863 100644 --- a/src/control/app-menu/app-menu.scss +++ b/src/control/app-menu/app-menu.scss @@ -179,6 +179,19 @@ $control-appmenu-item: ( calc(getCssVar('control-appmenu', 'item-padding') * 2.5); } } + + .#{bem('control-appmenu', 'counter')} { + position: absolute; + top: 50%; + right: 5px; + height: 20px; + padding: 0 6px; + line-height: initial; + color: #fff; + background-color: #f56c6c; + border-radius: 10px; + transform: translateY(-50%); + } } // 收缩时菜单项样式 diff --git a/src/control/app-menu/app-menu.tsx b/src/control/app-menu/app-menu.tsx index b88bdff0..865ac257 100644 --- a/src/control/app-menu/app-menu.tsx +++ b/src/control/app-menu/app-menu.tsx @@ -6,16 +6,19 @@ import { defineComponent, getCurrentInstance, onMounted, + onUnmounted, PropType, Ref, ref, } from 'vue'; import { createUUID } from 'qx-util'; import './app-menu.scss'; +import { AppCounter } from '@ibiz-template/runtime'; +import { useRoute } from 'vue-router'; import { AppMenuController } from './app-menu.controller'; /** - * 递归生成菜单数据,递给 antd 的 Menu 组件 + * 递归生成菜单数据,递给 element 的 Menu 组件 * * @author chitanda * @date 2022-07-25 10:07:28 @@ -28,6 +31,9 @@ function getMenus(items: IAppMenuItem[]): IData[] { key: item.id, label: item.caption, image: item.sysImage?.imagePath, + counterId: item.counterId, + disabled: !item.appFuncId, + tooltip: item.tooltip, }; if (item.appMenuItems?.length) { data.children = getMenus(item.appMenuItems); @@ -49,14 +55,23 @@ function renderMenuItem( collapse: boolean, ns: Namespace, c: AppMenuController, + counterData: IData, ) { if (!c.state.menuItemsState[menu.key].visible) { return; } return !(isFirst && collapse) ? ( - + {menu.label} + {typeof counterData[menu.counterId] === 'number' ? ( +
{counterData[menu.counterId]}
+ ) : null}
) : ( - + {!menu.image ? menu.label.slice(0, 1) : null} @@ -86,6 +105,7 @@ function renderSubmenu( collapse: boolean, ns: Namespace, c: AppMenuController, + counterData: IData, ) { if (!c.state.menuItemsState[subMenu.key].visible) { return; @@ -96,9 +116,9 @@ function renderSubmenu( default: () => subMenu.children.map((item: IData) => { if (item.children) { - return renderSubmenu(false, item, collapse, ns, c); + return renderSubmenu(false, item, collapse, ns, c, counterData); } - return renderMenuItem(false, item, collapse, ns, c); + return renderMenuItem(false, item, collapse, ns, c, counterData); }), title: () => [ , @@ -133,9 +153,12 @@ export const AppMenuControl = defineComponent({ // 默认展开菜单项数组 const defaultOpens: Ref = ref([]); // 路由对象 - // const route = useRoute(); + const route = useRoute(); + // 计数器数据 + let counter: AppCounter | null = null; + const counterData = ref({}); - const onClick = async (key: string, event: MouseEvent) => { + const onClick = async (key: string, event?: MouseEvent) => { await c.onClickMenuItem(key, event); }; @@ -204,31 +227,46 @@ export const AppMenuControl = defineComponent({ // }, // ); - onMounted(() => { - // // 默认激活的菜单项 - // const defaultActiveMenuItem = c.model.allItems.find(item => { - // return item.source.openDefault && !item.source.hidden; - // }); - // if ( - // defaultActiveMenuItem && - // !route.params.view2 && - // !route.fullPath.includes('404') - // ) { - // defaultActive.value = defaultActiveMenuItem.id; - // onClick(defaultActive.value); - // } - // // 默认展开的菜单项数组 - // const defaultOpensArr = c.model.allItems.filter(item => { - // return item.source.expanded && !item.source.hidden; - // }); - // if (defaultOpensArr.length > 0) { - // if (props.mode === 'LEFT') { - // defaultOpensArr.forEach(item => { - // defaultOpens.value.push(item.id); - // }); - // } - // } + onMounted(async () => { + const allItems = c.getAllItems(); + // 默认激活的菜单项 + const defaultActiveMenuItem = allItems.find(item => { + return item.openDefault && !item.hidden; + }); + if ( + defaultActiveMenuItem && + !route.params.view2 && + !route.fullPath.includes('404') + ) { + defaultActive.value = defaultActiveMenuItem.id!; + onClick(defaultActive.value); + } + // 默认展开的菜单项数组 + const defaultOpensArr = allItems.filter(item => { + return item.expanded && !item.hidden; + }); + if (defaultOpensArr.length > 0) { + if (props.mode === 'LEFT') { + defaultOpensArr.forEach(item => { + defaultOpens.value.push(item.id!); + }); + } + } updateMenu(); + // 计数器相关 + const counterRefId = c.model.appCounterRefId; + if (counterRefId) { + counter = c.getCounter(counterRefId); + if (counter) { + counter.onChange((data: IData) => { + counterData.value = data; + }); + } + } + }); + + onUnmounted(() => { + counter?.destroy(); }); const MenuMode = computed(() => { @@ -255,6 +293,7 @@ export const AppMenuControl = defineComponent({ defaultActive, defaultOpens, MenuMode, + counterData, }; }, render() { @@ -284,9 +323,17 @@ export const AppMenuControl = defineComponent({ this.collapse, this.ns, this.c, + this.counterData, ); } - return renderMenuItem(true, item, this.collapse, this.ns, this.c); + return renderMenuItem( + true, + item, + this.collapse, + this.ns, + this.c, + this.counterData, + ); })} )} diff --git a/src/control/chart/chart.controller.ts b/src/control/chart/chart.controller.ts index e69014ad..d201883c 100644 --- a/src/control/chart/chart.controller.ts +++ b/src/control/chart/chart.controller.ts @@ -111,7 +111,7 @@ export class ChartController protected async onDestroyed(): Promise { window.removeEventListener('resize', this.resizeChart); - await super.destroyed(); + await super.onDestroyed(); this.chart?.dispose(); } } -- Gitee