refactor(left-menu): 重构左侧菜单组件状态管理
- 添加 useState 和 useEffect 钩子管理菜单状态 - 将菜单展开状态和激活菜单项改为状态变量 - 实现动态子菜单列表管理功能 - 修复菜单项点击事件类型转换问题 - 优化菜单展开状态更新逻辑 - 删除过时的付款编码字段定义
This commit is contained in:
parent
f36678fe6c
commit
f68b148319
@ -1,14 +1,14 @@
|
||||
import {MenuDataItem} from '@ant-design/pro-components';
|
||||
import {getMatchMenu} from '@umijs/route-utils';
|
||||
import {Layout, Menu} from 'antd';
|
||||
import {MenuItemType} from 'antd/es/menu/interface';
|
||||
import React from 'react';
|
||||
import { MenuDataItem } from '@ant-design/pro-components';
|
||||
import { getMatchMenu } from '@umijs/route-utils';
|
||||
import { Layout, Menu } from 'antd';
|
||||
import { MenuItemType } from 'antd/es/menu/interface';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import useButtonStyle from './style.style';
|
||||
|
||||
interface ILeftMenuProps {
|
||||
menuData: MenuDataItem[];
|
||||
pathname: string;
|
||||
onClick: (item: MenuItemType) => void;
|
||||
menuData: MenuDataItem[];
|
||||
pathname: string;
|
||||
onClick: (item: MenuItemType) => void;
|
||||
}
|
||||
|
||||
// 递归 menuData tree 树状结构 增加 label 参数
|
||||
@ -18,116 +18,122 @@ const notNullArray = (value: any[]) => Array.isArray(value) && value.length > 0;
|
||||
* 删除 hideInMenu 和 item.name 不存在的
|
||||
*/
|
||||
const defaultFilterMenuData = (menuData: MenuDataItem[] = []): MenuItemType[] =>
|
||||
menuData
|
||||
.filter(
|
||||
(item) =>
|
||||
item &&
|
||||
(item.name || notNullArray(item.children as MenuItemType[])) &&
|
||||
!item.hideInMenu,
|
||||
)
|
||||
.map((item) => {
|
||||
const newItem = { ...item };
|
||||
const routerChildren = newItem.children || [];
|
||||
delete newItem.children;
|
||||
menuData
|
||||
.filter(
|
||||
(item) =>
|
||||
item &&
|
||||
(item.name || notNullArray(item.children as MenuItemType[])) &&
|
||||
!item.hideInMenu,
|
||||
)
|
||||
.map((item) => {
|
||||
const newItem = { ...item };
|
||||
const routerChildren = newItem.children || [];
|
||||
delete newItem.children;
|
||||
|
||||
if (
|
||||
notNullArray(routerChildren) &&
|
||||
!newItem.hideInMenu &&
|
||||
routerChildren.some((child) => child && !!child.name)
|
||||
) {
|
||||
const newChildren = defaultFilterMenuData(routerChildren);
|
||||
if (newChildren.length)
|
||||
return {
|
||||
key: item.key,
|
||||
label: item.name,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
children: newChildren,
|
||||
// type: 'group',
|
||||
} as unknown as MenuItemType;
|
||||
}
|
||||
return {
|
||||
key: newItem.key,
|
||||
label: newItem.name,
|
||||
name: item.name,
|
||||
path: newItem.path,
|
||||
} as MenuItemType;
|
||||
})
|
||||
.filter((item) => item);
|
||||
if (
|
||||
notNullArray(routerChildren) &&
|
||||
!newItem.hideInMenu &&
|
||||
routerChildren.some((child) => child && !!child.name)
|
||||
) {
|
||||
const newChildren = defaultFilterMenuData(routerChildren);
|
||||
if (newChildren.length)
|
||||
return {
|
||||
key: item.key,
|
||||
label: item.name,
|
||||
name: item.name,
|
||||
path: item.path,
|
||||
children: newChildren,
|
||||
// type: 'group',
|
||||
} as unknown as MenuItemType;
|
||||
}
|
||||
return {
|
||||
key: newItem.key,
|
||||
label: newItem.name,
|
||||
name: item.name,
|
||||
path: newItem.path,
|
||||
} as MenuItemType;
|
||||
})
|
||||
.filter((item) => item);
|
||||
|
||||
const LeftMenu: React.FC<ILeftMenuProps> = (props) => {
|
||||
const { styles } = useButtonStyle();
|
||||
const { pathname, menuData, onClick } = props;
|
||||
const { styles } = useButtonStyle();
|
||||
const { pathname, menuData, onClick } = props;
|
||||
|
||||
if (!menuData) {
|
||||
return null;
|
||||
}
|
||||
// 根据提供的 menuData 提供的 tree 结构,获取第一层等级菜单
|
||||
// moduleMenu
|
||||
const moduleMenu = menuData.map((item: MenuDataItem) => {
|
||||
return {
|
||||
key: item.key,
|
||||
label: item.name,
|
||||
path: item.path,
|
||||
} as MenuItemType;
|
||||
});
|
||||
|
||||
// 根据提供的 menuData 提供的 tree 结构,获取第一层等级菜单
|
||||
// moduleMenu
|
||||
const moduleMenu = menuData.map((item: MenuDataItem) => {
|
||||
return {
|
||||
key: item.key,
|
||||
label: item.name,
|
||||
path: item.path,
|
||||
} as MenuItemType;
|
||||
});
|
||||
const [openKeys, setOpenKeys] = useState<string[]>([]);
|
||||
const [activeMenuKey, setActiveMenuKey] = useState<string[]>();
|
||||
const [subMenuList, setSubMenuList] = useState<MenuItemType[]>([]);
|
||||
|
||||
// 通过循环 moduleMenu 判断 history.location.pathname 是否包含 key
|
||||
const activeMenu = getMatchMenu(pathname, menuData, true);
|
||||
// pluck activeMenu key
|
||||
const activeMenuKey = activeMenu.map(
|
||||
(item: MenuDataItem) => item.key as string,
|
||||
);
|
||||
const openKeys = activeMenu.flatMap((item: MenuDataItem) => item.children).map(
|
||||
(item: any) => item?.key as string,
|
||||
);
|
||||
useEffect(() => {
|
||||
// 通过循环 moduleMenu 判断 history.location.pathname 是否包含 key
|
||||
const activeMenu = getMatchMenu(pathname, menuData, true);
|
||||
const activeMenuKey = activeMenu.map(
|
||||
(item: MenuDataItem) => item.key as string,
|
||||
);
|
||||
|
||||
let subMenu: MenuItemType[] = [];
|
||||
if (activeMenu[0]?.children) {
|
||||
subMenu = defaultFilterMenuData(activeMenu[0]?.children);
|
||||
}
|
||||
setSubMenuList(
|
||||
activeMenu[0]?.children
|
||||
? defaultFilterMenuData(activeMenu[0]?.children)
|
||||
: [],
|
||||
);
|
||||
setActiveMenuKey(activeMenuKey);
|
||||
setOpenKeys([...openKeys, ...activeMenuKey]);
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={styles.box}
|
||||
style={{
|
||||
// @ts-ignore
|
||||
'--box-with': subMenu.length > 0 ? '248px' : '100px',
|
||||
}}
|
||||
></div>
|
||||
<Layout.Sider
|
||||
className={styles.sider}
|
||||
style={{ position: 'fixed' }}
|
||||
width={'auto'}
|
||||
theme={'light'}
|
||||
>
|
||||
<Menu
|
||||
items={moduleMenu}
|
||||
className={styles.moduleMenu}
|
||||
selectedKeys={activeMenuKey}
|
||||
theme={'dark'}
|
||||
onClick={(item) => {
|
||||
onClick(item);
|
||||
}}
|
||||
/>
|
||||
{subMenu.length > 0 && (
|
||||
<Menu
|
||||
items={subMenu}
|
||||
className={styles.subMenu}
|
||||
selectedKeys={activeMenuKey}
|
||||
openKeys={openKeys}
|
||||
mode="inline"
|
||||
inlineIndent={12}
|
||||
onClick={(item) => {
|
||||
onClick(item);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Layout.Sider>
|
||||
</>
|
||||
);
|
||||
if (!menuData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={styles.box}
|
||||
style={{
|
||||
// @ts-ignore
|
||||
'--box-with': subMenuList.length > 0 ? '248px' : '100px',
|
||||
}}
|
||||
></div>
|
||||
<Layout.Sider
|
||||
className={styles.sider}
|
||||
style={{ position: 'fixed' }}
|
||||
width={'auto'}
|
||||
theme={'light'}
|
||||
>
|
||||
<Menu
|
||||
items={moduleMenu}
|
||||
className={styles.moduleMenu}
|
||||
selectedKeys={activeMenuKey}
|
||||
theme={'dark'}
|
||||
onClick={(item) => {
|
||||
onClick(item as any);
|
||||
}}
|
||||
/>
|
||||
{subMenuList.length > 0 && (
|
||||
<Menu
|
||||
items={subMenuList}
|
||||
className={styles.subMenu}
|
||||
selectedKeys={activeMenuKey}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={(keys) => setOpenKeys(keys)}
|
||||
mode="inline"
|
||||
inlineIndent={12}
|
||||
onClick={(item) => {
|
||||
onClick(item as any);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Layout.Sider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LeftMenu;
|
||||
|
||||
@ -4908,8 +4908,6 @@ declare namespace BusinessAPI {
|
||||
taskName: string;
|
||||
/** 任务类型:1-瓜农付款任务 */
|
||||
taskType: 'MELON_FARMER';
|
||||
/** 付款编码 */
|
||||
paymentTaskSn: string;
|
||||
/** 付款任务对象ID */
|
||||
targetId: string;
|
||||
/** 付款总金额 */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user